#include "desk.h" /****************************************************************************** * 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 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; }