Renaming in my NSE does not work in Content View - winapi

NSE meaning namesapce extension
(https://msdn.microsoft.com/en-us/library/windows/desktop/cc144095%28v=vs.85%29.aspx)
I have a namespace extension developed using the DefView.
I am handling FMTID_PropList+PID_PropList_ContentViewModeForBrowse and returning the correct proplist-string.
When I browse my nse in "Content View" in Windows Explorer, renaming does not work.
Additionally, I notice that Windows Explorer prefixes the value of my first column (which is the item name) with "Name:
- it does not do this for items in the filesystem.
How can I solve both the above issues?
I copied the question from:
https://social.msdn.microsoft.com/Forums/en-US/a88ca56d-542e-46a8-81b4-7c37431ea26a/renaming-in-my-nse-does-not-work-in-content-view?forum=windowsuidevelopment
I'm having the exact same issue and could not find any help on the web.

You are using obsolete format of proplist string. It was actual in Windows XP era. Starting from Windows Vista it is necessary to use new format. Instead of GUID and PID you must use canonical name of property key. That why Windows does not allow user to rename your object in content view mode.
{b725f130-47ef-101a-a5f1-02608c9eebac} 10 is equal to PKEY_ItemNameDisplay with canonical name System.ItemNameDisplay.
"~" char before canonical name has a special meaning. If it does not present shell shows label before value. In case of System.ItemNameDisplay label is "Name".

Related

Explorer ignores ParseDisplayName in Shell Namespace Extension

I am writing a Shell Namespace Extension.
How may I force explorer to access (and open) items that are not enumerated with IShellFolder::EnumObjects by typing their parsing name in the address bar?
I have seen SFGAO_NONENUMERATED flag which I believe is used to mark such items (so in theory it should be possible, otherwise why do one need this flag?). I don't want to use SFGAO_HIDDEN or SFGAO_SYSTEM because such items could be seen nevertheless.
I am expecting explorer to call IShellFolder::ParseDisplayName with absolute or at least relative path to the item requested. But instead it is calling IShellFolder::ParseDisplayName only for the first segment of the parsing name (basically the first folder's parsing name). After this explorer queries content of each sub folder via IShellFolder::EnumObjects and calls IShellFolder::GetDisplayNameOf to get both display and parsing name of each item enumerated.
Based on this comment from Raymond Chen I understood that it is normal for explorer to rely on both display and parsing names to retrieve the item requested in the address bar. But the biggest issue here is that my items (that I want to obtain) are not enumerated. So explorer does not know about their existence.

For the use of the LocalizedResourceName property

I wish to customize my own folder style, I tried to make the folder get remarks by modifying the LocalizedResourceName property in desktop.ini.
I try to set LocalizedResourceName to a Chinese string. But it is displayed as garbled characters when it is actually displayed.
I noticed the following code in the desktop.ini of the system folder:
LocalizedResourceName=#%SystemRoot%\system32\shell32.dll,-21798
So I try to write a .dll file by myself, encapsulate the icon and string, and use it.
I already know how to make a resource-only dll file, but I don't know how to get a certain resource in the file. (ie, get the number -21798 in the above example code)
How should I do ?
By convention, a positive resource number is an index (0 is the first resource etc.) and negative numbers are resource ids. In this specific case, it is the string resource with the id of abs(-21798) that Windows would pass to LoadString.
If you want to create your own .dll, add a string with an id of 2 for example (any number between 2 and 0xffff) and in your .ini you would use #c:\path\mydll.dll,-2.
Before you go to all this trouble, just try saving the .ini as UTF-16 LE (Unicode in Notepad) and use Chinese strings directly without the #.

Delphi TOpenDialog/TSaveDialog last used path

Referring my question to this answer: https://stackoverflow.com/a/4016075/698266, in particular step 3 says "Otherwise, if the application has used an Open or Save As dialog box in the past, the path most recently used is selected as the initial directory."
Where does Windows save this information?
Note: by experimenting, it seems to be linked to the application file name without its path - i.e. the same executable copied in different directories "sees" the same last path information, while changing the exe file name makes the dialogs point to the user's Documents directory.
My actual interest is for testing purposes. I need to "reset" this information in order to test my application in conditions similar to a first run.
Windows XP uses HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedMRU and the format of each item seems to be ExeFilename+Path with both strings zero terminated and in UTF-16LE format. The MRU list is stored as a string named MRUList.
Newer versions of Windows uses HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRU and HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRULegacy and the format seems to be ExeFilename+ItemIdList (ExeFilename in UTF-16LE and zero terminated). The MRU list seems to be a list of DWORDs in a binary value named MRUListEx and the list is terminated by 0xffffffff.
I would assume that the change happened in Vista because that is when the new IFileDialog was added. LastVisitedPidlMRULegacy is probably used when GetOpen/SaveFileName is called with a custom template and/or hook function.
I finally found the answer myself.
For Windows 10 (this may be different in different versions of Windows, as David pointed up) there's a list of values in the registry that keep track of the executable name and its associated last "visited" path.
The list can be found in this key:
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRU
In order to reset the default open/save path for a particular program, you have to find the value whose data string (UNICODE) starts with your executable name and delete it. If you watch at the data string, you'll notice that the last used path is there, after the executable name.

Registry does not like long filename for shell commands or verbs

(if not applicable to SO, please refer to another appropriate place, thanks).
When using the registry to associate file extensions and application, I put in the full filename of my application, but that does not work well, only if I use the 8.3 filename.
for example ( taken from the registry) this works:
[HKEY_CLASSES_ROOT\Toto.Document\shell\myVerb\command]
#="C:\\my\\path\\bin\\Debug\\bin\\myexe_~1.EXE /dde"
[HKEY_CLASSES_ROOT\Toto.Document\shell\myVerb\ddeexec]
#="[myVerb(\"%1\")]"
but this does not work :
[HKEY_CLASSES_ROOT\Toto.Document\shell\myVerb\command]
#="C:\\my\\path\\bin\\Debug\\bin\\myexecutable.EXE /dde"
[HKEY_CLASSES_ROOT\Toto.Document\shell\myVerb\ddeexec]
#="[myVerb(\"%1\")]"
The action is called by right-clicking on the file in Explorer, I get the error :
"Windows cannot find 'c:\users\me\desktop\tata.toto'. Make sure you typed the name correctly, and then try again".
I'm creating the keys programatically with CRegKey and using GetModuleFileName to get the application path.
2 questions :
- I'm probably missing something in my registry entry ? (i've tried quoting the paths, but does not work)
- Can I get the "short" filename ? (searching a little bit seems that GetShortPath should work, but not always!)
Thanks.
Max.
(edit 22/03/2011)
I tried using quotes but it did not work (with /dde)
I decided to use normal parameters instead of /dde and it seems to work nicely with the normal path (not shortened like stated above).
I'm still not certain why when creating a simple MFC SDI project it will write out registry values with the old short name instead of the long name.
Thanks again.
Max.
Try creating the key with another couple of double-quotes (note between .EXE and /dde:
#="C:\\my\\path\\bin\\Debug\\bin\\myexecutable.EXE" "/dde"

read known file extensions / types from the registry

I want to present the user with a list of known file extensions for him to pick. I know that these are stored in the Registry under HKEY_CLASSES_ROOT usually like this:
.txt -> (default)="txtfile"
where txtfile then contains the information about associated programs etc.
Unfortunately that place in the registry also stores lots of other keys, like the file types (e.g. txtfile) and entries like
CAPICOM.Certificates (whatever that is)
How do I determine which of the entries are file extensions? Or is there a different way to get these extensions like an API function?
(I don't think it matters, but I am using Delphi for the program.)
There is no guarantee that every keys preceded by a dot in HKEY_CLASSES_ROOT is intended for file association, but every file association requires creation of a key preceded by a dot. See MSDN on File Types topic.
AFAIK, the method I describe here conforms with how the Windows Set File Associations feature works to get a list of all known file types. It was based on my former observation when I delved into this subject.
To achieve that, you'll need to do intricate steps as follows:
Enumerating every keys preceded by a dot . , you can use RegQueryInfoKey() and RegEnumKeyEx() for this purpose.
In every keys preceded by a dot, look at the default value data:
a. If the default value is not empty, this is enough indication that the "preceding dot key" is intended for file association in all Windows NT version, then try to open the key name as mentioned by the value data, just says TheKeyNameMentioned.
a1) If there is subkeys shell\open\command under TheKeyNameMentioned, then test the existence of the path pointed by the default value of this key; if the path exists, there is a default application associated with the extension; if the path doesn't exists, the default application is unknown. To get the file extension description, look at the default value of TheKeyNameMentioned. To get the program description, first, test whether the following key contain a value-name equal to the EXE file path, that is HKCR\Local Settings\Software\Microsoft\Windows\Shell\MuiCache. If it is there, then look at the value data to get the file description; if it is not there, use GetFileVersionInfo() directly to get the file description.
a2) If there is no subkeys shell\open\command under TheKeyNameMentioned, then the default application is unknown. To get the file extension description, look at the default value of TheKeyNameMentioned.
b. On Windows Vista and later, when the point [a] fails, you need additional check. If the default value is empty, test whether the key has a subkey named OpenWithProgIDs.
If OpenWithProgIDs subkey exists, use RegEnumValue() to find the first encountered value name that meets the criteria, that is, the name of the value name must point to an existing key (just says TheKeyNameMentioned.) with the same name as the value name. If TheKeyNameMentioned exists, this is enough indication that the "preceding dot key" is intended for file association. Read point a1 and a2 for the next steps.
If OpenWithProgIDs subkey doesn't exist, the default application is unknown. To get the file extension description, look at the default value of TheKeyNameMentioned.
Hope that helps. :-)
For a command-line alternative, the assoc command-line program included in Windows shows registered file extensions.
c:\> assoc
.3g2=VLC.3g2
.3gp=VLC.3gp
.3gp2=VLC.3gp2
.3gpp=VLC.3gpp
...
I'm not sure which verb this looks for. Open perhaps? I'm also not sure which extensions will appear in this list. Perhaps the extensions of files that can open from the command line.
To then find out which executable is mapped to each file type, the ftype command will tell:
c:\> ftype VLC.3g2
VLC.3g2="c:\vlc.exe" --started-from-file "%1"
IMHO - all those registry subkeys starting with the dot (.) - are for file extensions.
For instance in your case .txt stands for the "txt" extension, whereas txtfile doesn't start with the dot.
I don't know the details, but it seems you could use the IQueryAssociations interface.

Resources