SHGetShellKey

This function opens or creates a subkey of a shell key.

Declaration

HKEY
SHGetShellKey (
    SHELLKEY nShellKey,
    LPCWSTR pszSubKey,
    BOOL bCreate);

Parameters

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.

Return Value

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.

Behaviour

Starting with the SHLWAPI version 6.00 from Windows Vista, this function is implemented as a call to SHGetShellKeyEx, asking for MAXIMUM_ALLOWED access rights.

Earlier Builds

The original implementation interprets the nShellKey argument through three bit masks to extract a root, key and subkey, whose concatenation is the shell key.

If the root is HKEY_CURRENT_USER and the calling thread has an impersonation token, then the root of the shell key is instead to be the target user’s branch of HKEY_USERS. To open this root key, the function needs to be running on Windows 2000 or higher, for the RegOpenCurrentUser function. If the function cannot open this root key, with MAXIMUM_ALLOWED access rights, it fails (setting ERROR_ACCESS_DENIED as the last error).

To open or create the shell key, the function first gets a handle to the key that is represented by the concatenation of root and key. If the key mask produces an unsupported value, the function fails (setting E_INVALIDARG as the last error).

The function caches handles to all the possible combinations of root and key. If the indicated combination is already cached, then provided that the root has not been redirected for impersonation, the function proceeds with the cached handle. Otherwise, the function opens or creates (according to the bCreate argument) the key relative to the root, asking for the MAXIMUM_ALLOWED access rights. Failure at this is failure for the function. If the key is Software\Microsoft\Windows\ShellNoRoam, some initialisation is performed (discussed below). Whatever the key, except if the root is redirected for impersonation, the function caches the new handle. If a handle for the same combination of root and key has got cached meanwhile, the function discards its new handle and proceeds with the cached handle.

If the subkey mask produces either 0 or an unsupported value, the combination of root and key is the shell key. Otherwise, the function must yet open or create the subkey relative to the key. The function caches handles to all the possible combinations of root and subkey. If the indicated combination is already cached, then provided that the root has not been redirected for impersonation, the function proceeds with the cached handle. Otherwise, the function opens or creates (according to the bCreate argument) the subkey relative to the key, asking for the MAXIMUM_ALLOWED access rights. If the subkey is Volatile, the REG_OPTION_VOLATILE option is specified. Failure to open or create is failure for the function. If the subkey is MUICache, some initialisation is performed (discussed below). Whatever the subkey, except if the root is redirected for impersonation, the function caches the new handle. If a handle for the same combination of root and subkey has got cached meanwhile, the function discards its new handle and proceeds with the cached handle.

Having (finally) got a handle to the shell key, the function opens or creates the subkey named by the pszSubkey argument, again asking for MAXIMUM_ALLOWED access rights. 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.

Coding Error

The caching of handles provides for all combinations of root and key, but each subkey is cached only for each root. If the function is called to open a shell key selected by root, key1 and subkey, and is then called to open a shell key selected by root, key2 and subkey, it will use on the second call whatever handle was cached for the first call’s different specification of shell key.

ShellNoRoam Initialisation

As noted above, the Software\Microsoft\Windows\ShellNoRoam key, in any root, must be initialised before its first use. If data for the default value does not match the case-insensitive computer name, then the key is cleared of all subkeys and values, and the default value is set afresh to have the computer name as its REG_SZ data.

MUICache Initialisation

Also noted above is that an MUICache key must be initialised before its first use. The particular concern is for the LangID value in the key, i.e.,

Key: root\key\MUICache
Value: LangID

If the LangID value is not present with two bytes of data equal to the user-interface language, then the key is cleared of all subkeys and values, and a fresh LangID value is set to have the user-interface language as its two bytes of REG_BINARY data. For this purpose, the user-interface language is the result from the MLGetUILanguage function if running on Windows 2000 or higher, else 0xFFFF.

Availability

The SHGetShellKey function is exported from SHLWAPI.DLL as ordinal 491 in version 6.00 and higher.

Though this function dates from 2001, it was still not documented by Microsoft as late as the January 2007 edition of the Windows Vista Software Development Kit (SDK).