Geoff Chappell - Software Analyst
This function loads the string resource that is indicated indirectly by a given registry value.
HRESULT SHLoadRegUIString ( HKEY hKey, LPCTSTR pszValue, LPTSTR pszOutBuf, UINT cchOutBuf);
The function exists in ANSI and Unicode forms.
The hKey argument provides a handle to an open key.
The pszValue argument provides the address of a null-terminated string that names the value to query within the key, or is NULL to query the key’s default value.
The pszOutBuf and cchOutBuf arguments describe a buffer, by address and capacity (in characters) respectively, which is to receive the loaded string resource.
The function returns zero for success, else an error code.
If cchOutBuf is not zero, the function initialises the output buffer with a null character.
If hKey is -1 or NULL, or if pszOutBuf is NULL, the function fails (returning E_INVALIDARG). Note that if pszOutBuf is NULL, the function will have already faulted unless cchOutBuf is also zero.
The function queries the specified registry value (using SHQueryValueEx, without insisting on any particular type of data) for as much data as fits the output buffer. If this fails for any reason other than there being too much data to fit the buffer, the function fails (returning E_FAIL). If there is too much data to fit the buffer, the function seeks temporary memory for the data, and queries again. If the function cannot obtain this temporary memory, it fails (returning E_OUTOFMEMORY). If this second query into supposedly enough memory fails for any reason, so does the function (returning E_FAIL).
The registry value’s data is anticipated to have the form of an indirect string, in a particular format that specifies a resource library and the ID of a string resource in that library. Interpretation is done by the SHLoadIndirectString function. If this fails, then so does the function. A quick summary follows. If the data fits the anticipated format, then what is produced in the output buffer is the indirectly indicated string resource, else the function fails. If the data does not conform to the format of an indirect string, the output buffer contains as much of the registry value’s data as fits, and the function succeeds.
Initialisation of the output buffer begins with the build of version 5.00 from Windows 2000.
An additional parameter check was dropped for version 6.00: the pszValue argument must be not NULL, else the function fails (returning E_INVALIDARG).
Versions before 6.00 differ significantly in the interpretation of the registry value’s data, the work being not yet settled into a separately exported function. A significant difference is that the function does not fail if the registry value’s data is an indirect string but the indicated resource string fails to load. Instead, the function proceeds as if the data was not an indirect string, and succeeds.
There are also differences in the anticipated format of an indirect string. In builds of version 5.00 from before Windows 2000, the indirect string is simply what is documented:
The build from Windows 2000 introduces an elaboration of the anticipated format so that the resource string can be cached in the registry value from which it is indirectly loaded. The full format of an indirect string in these versions is:
Characters between the resource ID and the @ sign are ignored, as are characters between the language ID and the comma. If the continuation is present and the language ID matches the current MUI language (from the MLGetUILanguage function), then the function accepts the cached resource string without having to load the library. In cases where the resource string is loaded, the function constructs the full indirect string and sets it as new REG_SZ data for the registry value.
The function has always been natively Unicode. The ANSI form converts to and from Unicode around a call to the Unicode form.
The SHLoadRegUIString function is exported from SHLWAPI.DLL as ordinals 438 and 439 (for ANSI and Unicode forms respectively) in version 5.00 and higher.
Though this function dates from as long ago as 1999, it was still not documented by Microsoft as late as the January 2007 edition of the Windows Vista Software Development Kit (SDK).
Although this function remains undocumented, the notion of indirection for registry strings is taken into Windows itself for Windows Vista and Microsoft seems more than merely pleased to write about it as a new feature, e.g., in Using Registry String Redirection. Of course, it is a new feature at that level of Windows. It’s so new that the distribution of documentation among pages seems still to be uncertain, having changed at least twice since the January 2007 edition of the Windows Vista SDK. Yet the work of the new ADVAPI32 function RegLoadMUIString has been available from the shell through the SHLoadRegUIString function for most of a decade, during which time it was used heavily by Internet Explorer.