Geoff Chappell - Software Analyst
This function opens or creates a subkey of a shell key and specifies the desired access rights.
HKEY SHGetShellKeyEx ( SHELLKEY nShellKey, LPCWSTR pszSubKey, BOOL bCreate REGSAM samDesired);
The nShellKey argument specifies the shell key as a constant from the SHELLKEY enumeration.
The pszSubKey argument provides the address of a null-terminated string that names the subkey, or is NULL to open the shell key itself.
The bCreate argument is non-zero to permit the function to create the subkey, or is FALSE if the function may only open the subkey.
The samDesired argument specifies access rights that are desired to the subkey.
The function returns a handle to the opened subkey, if successful. It returns NULL for failure, in which case an error code is meant to be retrievable through GetLastError.
If the nShellKey argument is not valid as selecting a shell key, the function fails. No last error is set.
If the shell key has HKEY_CURRENT_USER_LOCAL_SETTINGS as its root, the function checks whether this pre-defined handle (0x80000007) is valid. If the handle can be opened for read access, it is valid and the function remembers so that the handle need not be reopened on later executions. If it cannot be opened for read access and the error is ERROR_INVALID_HANDLE, the function remembers this too, and falls back to using HKEY_CURRENT_USER as the root.
If the shell key has HKEY_CURRENT_USER as its root (including because of the fall-back just noted) and the calling thread has an impersonation token, then the root key is instead to be the target user’s branch of HKEY_USERS. If the function cannot open this root key for read access, plus KEY_CREATE_SUB_KEY if bCreate is non-zero, it fails (setting ERROR_ACCESS_DENIED as the last error).
The function caches handles to shell keys. If the selected shell key is not redirected to another user’s registry branch because of impersonation, then the function accepts whatever handle it retains from an earlier execution. Otherwise, the function opens or creates the shell key, according to whether bCreate is zero, asking for the access rights given by samDesired. Failure at this is failure for the function. If nShellKey is 0x5021, some initialisation is performed (discussed below). For all shell keys, except if redirected because of impersonation, the function caches the new handle. If a handle for the same shell key has got cached meanwhile, the cache is not disturbed and the function continues with the new handle.
Having got a handle to the shell key, the function opens or creates the subkey named by pszSubKey, again asking for the access rights given by samDesired. In the special case where pszSubKey is NULL, the function opens a new handle to the shell key itself, relative to the handle it already has, and ignores bCreate.
The caching of handles to shell keys does not accommodate the possibility that different calls to the function for the same shell key may ask for different access rights. For example, suppose your first call to the function is to open a subkey of some shell key, and you ask just for read access, intending just to inspect values that are already there. Provided that the shell key’s root is not redirected by impersonation, the newly opened handle to this shell key gets cached and you are returned a handle to the subkey. Suppose that you later call the function to open the same or another subkey of the same shell key, but now you ask for read and write access. This call will fail because the subkey is opened relative to the cached handle for the shell key, and this cached handle has only read access. For reliable use of the function, if only until this problem is fixed, the first call for each shell key must obtain all the access rights that may be sought on any later calls to the same shell key.
As noted above, the shell key that is represented by 0x5021 in the SHELLKEY enumeration must be initialised before its first use. The particular concern is for the LangID value in the key, i.e.,
Key: | HKEY_CURRENT_USER_LOCAL_SETTINGS\Software\Microsoft\Windows\Shell\MuiCache |
Value: | LangID |
If the newly opened handle can be duplicated for read-write access but the LangID value is not present with two bytes of data equal to the user default UI language, then the key is cleared of all subkeys and values, and a fresh LangID value is set to have the user default UI language as its two bytes of REG_BINARY data.
The SHGetShellKeyEx function is exported as ordinal 635 by the SHLWAPI.DLL version 6.00 from Windows Vista, and higher.
Though new for Windows Vista, this function is not documented by Microsoft in the January 2007 edition of the Software Development Kit (SDK) for Windows Vista.