-
-/******************************************************************************
- * load_string [Internal]
- *
- * This is basically a copy of user32/resource.c's LoadStringW. Necessary to
- * avoid importing user32, which is higher level than advapi32. Helper for
- * RegLoadMUIString.
- */
-static int load_string(HINSTANCE hModule, UINT resId, LPWSTR pwszBuffer, INT cMaxChars)
-{
- HGLOBAL hMemory;
- HRSRC hResource;
- WCHAR *pString;
- int idxString;
-
- /* Negative values have to be inverted. */
- if (HIWORD(resId) == 0xffff)
- resId = (UINT)(-((INT)resId));
-
- /* Load the resource into memory and get a pointer to it. */
- hResource = FindResourceW(hModule, MAKEINTRESOURCEW(LOWORD(resId >> 4) + 1), (LPWSTR)RT_STRING);
- if (!hResource) return 0;
- hMemory = LoadResource(hModule, hResource);
- if (!hMemory) return 0;
- pString = LockResource(hMemory);
-
- /* Strings are length-prefixed. Lowest nibble of resId is an index. */
- idxString = resId & 0xf;
- while (idxString--) pString += *pString + 1;
-
- /* If no buffer is given, return length of the string. */
- if (!pwszBuffer) return *pString;
-
- /* Else copy over the string, respecting the buffer size. */
- cMaxChars = (*pString < cMaxChars) ? *pString : (cMaxChars - 1);
- if (cMaxChars >= 0)
- {
- memcpy(pwszBuffer, pString+1, cMaxChars * sizeof(WCHAR));
- pwszBuffer[cMaxChars] = L'\0';
- }
-
- return cMaxChars;
-}
-
-
-/************************************************************************
- * RegLoadMUIStringW
- *
- * @implemented
- */
-LONG WINAPI
-RegLoadMUIStringW(IN HKEY hKey,
- IN LPCWSTR pszValue OPTIONAL,
- OUT LPWSTR pszOutBuf,
- IN DWORD cbOutBuf,
- OUT LPDWORD pcbData OPTIONAL,
- IN DWORD Flags,
- IN LPCWSTR pszDirectory OPTIONAL)
-{
- DWORD dwValueType, cbData;
- LPWSTR pwszTempBuffer = NULL, pwszExpandedBuffer = NULL;
- LONG result;
-
- /* Parameter sanity checks. */
- if (!hKey || !pszOutBuf)
- return ERROR_INVALID_PARAMETER;
-
- if (pszDirectory && *pszDirectory)
- {
- FIXME("BaseDir parameter not yet supported!\n");
- return ERROR_INVALID_PARAMETER;
- }
-
- /* Check for value existence and correctness of it's type, allocate a buffer and load it. */
- result = RegQueryValueExW(hKey, pszValue, NULL, &dwValueType, NULL, &cbData);
- if (result != ERROR_SUCCESS) goto cleanup;
- if (!(dwValueType == REG_SZ || dwValueType == REG_EXPAND_SZ) || !cbData)
- {
- result = ERROR_FILE_NOT_FOUND;
- goto cleanup;
- }
- pwszTempBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
- if (!pwszTempBuffer)
- {
- result = ERROR_NOT_ENOUGH_MEMORY;
- goto cleanup;
- }
- result = RegQueryValueExW(hKey, pszValue, NULL, &dwValueType, (LPBYTE)pwszTempBuffer, &cbData);
- if (result != ERROR_SUCCESS) goto cleanup;
-
- /* Expand environment variables, if appropriate, or copy the original string over. */
- if (dwValueType == REG_EXPAND_SZ)
- {
- cbData = ExpandEnvironmentStringsW(pwszTempBuffer, NULL, 0) * sizeof(WCHAR);
- if (!cbData) goto cleanup;
- pwszExpandedBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
- if (!pwszExpandedBuffer)
- {
- result = ERROR_NOT_ENOUGH_MEMORY;
- goto cleanup;
- }
- ExpandEnvironmentStringsW(pwszTempBuffer, pwszExpandedBuffer, cbData);
- }
- else
- {
- pwszExpandedBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
- memcpy(pwszExpandedBuffer, pwszTempBuffer, cbData);
- }
-
- /* If the value references a resource based string, parse the value and load the string.
- * Else just copy over the original value. */
- result = ERROR_SUCCESS;
- if (*pwszExpandedBuffer != L'@') /* '@' is the prefix for resource based string entries. */
- {
- lstrcpynW(pszOutBuf, pwszExpandedBuffer, cbOutBuf / sizeof(WCHAR));
- }
- else
- {
- WCHAR *pComma = wcsrchr(pwszExpandedBuffer, L',');
- UINT uiStringId;
- HMODULE hModule;
-
- /* Format of the expanded value is 'path_to_dll,-resId' */
- if (!pComma || pComma[1] != L'-')
- {
- result = ERROR_BADKEY;
- goto cleanup;
- }
-
- uiStringId = _wtoi(pComma+2);
- *pComma = L'\0';
-
- hModule = LoadLibraryExW(pwszExpandedBuffer + 1, NULL, LOAD_LIBRARY_AS_DATAFILE);
- if (!hModule || !load_string(hModule, uiStringId, pszOutBuf, cbOutBuf / sizeof(WCHAR)))
- result = ERROR_BADKEY;
- FreeLibrary(hModule);
- }
-
-cleanup:
- HeapFree(GetProcessHeap(), 0, pwszTempBuffer);
- HeapFree(GetProcessHeap(), 0, pwszExpandedBuffer);
- return result;
-}
-
-
-/************************************************************************
- * RegLoadMUIStringA
- *
- * @implemented
- */
-LONG WINAPI
-RegLoadMUIStringA(IN HKEY hKey,
- IN LPCSTR pszValue OPTIONAL,
- OUT LPSTR pszOutBuf,
- IN DWORD cbOutBuf,
- OUT LPDWORD pcbData OPTIONAL,
- IN DWORD Flags,
- IN LPCSTR pszDirectory OPTIONAL)
-{
- UNICODE_STRING valueW, baseDirW;
- WCHAR *pwszBuffer;
- DWORD cbData = cbOutBuf * sizeof(WCHAR);
- LONG result;
-
- valueW.Buffer = baseDirW.Buffer = pwszBuffer = NULL;
- if (!RtlCreateUnicodeStringFromAsciiz(&valueW, pszValue) ||
- !RtlCreateUnicodeStringFromAsciiz(&baseDirW, pszDirectory) ||
- !(pwszBuffer = HeapAlloc(GetProcessHeap(), 0, cbData)))
- {
- result = ERROR_NOT_ENOUGH_MEMORY;
- goto cleanup;
- }
-
- result = RegLoadMUIStringW(hKey, valueW.Buffer, pwszBuffer, cbData, NULL, Flags,
- baseDirW.Buffer);
-
- if (result == ERROR_SUCCESS)
- {
- cbData = WideCharToMultiByte(CP_ACP, 0, pwszBuffer, -1, pszOutBuf, cbOutBuf, NULL, NULL);
- if (pcbData)
- *pcbData = cbData;
- }
-
-cleanup:
- HeapFree(GetProcessHeap(), 0, pwszBuffer);
- RtlFreeUnicodeString(&baseDirW);
- RtlFreeUnicodeString(&valueW);
-
- return result;
-}
-