Sync with trunk r63935.
[reactos.git] / dll / cpl / desk / muireg.c
1 #include "desk.h"
2
3 /******************************************************************************
4 * load_string [Internal]
5 *
6 * This is basically a copy of user32/resource.c's LoadStringW. Necessary to
7 * avoid importing user32, which is higher level than advapi32. Helper for
8 * RegLoadMUIString.
9 */
10 static int load_string(HINSTANCE hModule, UINT resId, LPWSTR pwszBuffer, INT cMaxChars)
11 {
12 HGLOBAL hMemory;
13 HRSRC hResource;
14 WCHAR *pString;
15 int idxString;
16
17 /* Negative values have to be inverted. */
18 if (HIWORD(resId) == 0xffff)
19 resId = (UINT)(-((INT)resId));
20
21 /* Load the resource into memory and get a pointer to it. */
22 hResource = FindResourceW(hModule, MAKEINTRESOURCEW(LOWORD(resId >> 4) + 1), (LPWSTR)RT_STRING);
23 if (!hResource) return 0;
24 hMemory = LoadResource(hModule, hResource);
25 if (!hMemory) return 0;
26 pString = LockResource(hMemory);
27
28 /* Strings are length-prefixed. Lowest nibble of resId is an index. */
29 idxString = resId & 0xf;
30 while (idxString--) pString += *pString + 1;
31
32 /* If no buffer is given, return length of the string. */
33 if (!pwszBuffer) return *pString;
34
35 /* Else copy over the string, respecting the buffer size. */
36 cMaxChars = (*pString < cMaxChars) ? *pString : (cMaxChars - 1);
37 if (cMaxChars >= 0)
38 {
39 memcpy(pwszBuffer, pString+1, cMaxChars * sizeof(WCHAR));
40 pwszBuffer[cMaxChars] = L'\0';
41 }
42
43 return cMaxChars;
44 }
45
46
47 /************************************************************************
48 * RegLoadMUIStringW
49 *
50 * @implemented
51 */
52 LONG
53 RegLoadMUIStringW(IN HKEY hKey,
54 IN LPCWSTR pszValue OPTIONAL,
55 OUT LPWSTR pszOutBuf,
56 IN DWORD cbOutBuf,
57 OUT LPDWORD pcbData OPTIONAL,
58 IN DWORD Flags,
59 IN LPCWSTR pszDirectory OPTIONAL)
60 {
61 DWORD dwValueType, cbData;
62 LPWSTR pwszTempBuffer = NULL, pwszExpandedBuffer = NULL;
63 LONG result;
64
65 /* Parameter sanity checks. */
66 if (!hKey || !pszOutBuf)
67 return ERROR_INVALID_PARAMETER;
68
69 if (pszDirectory && *pszDirectory)
70 {
71 //FIXME("BaseDir parameter not yet supported!\n");
72 return ERROR_INVALID_PARAMETER;
73 }
74
75 /* Check for value existence and correctness of it's type, allocate a buffer and load it. */
76 result = RegQueryValueExW(hKey, pszValue, NULL, &dwValueType, NULL, &cbData);
77 if (result != ERROR_SUCCESS) goto cleanup;
78 if (!(dwValueType == REG_SZ || dwValueType == REG_EXPAND_SZ) || !cbData)
79 {
80 result = ERROR_FILE_NOT_FOUND;
81 goto cleanup;
82 }
83 pwszTempBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
84 if (!pwszTempBuffer)
85 {
86 result = ERROR_NOT_ENOUGH_MEMORY;
87 goto cleanup;
88 }
89 result = RegQueryValueExW(hKey, pszValue, NULL, &dwValueType, (LPBYTE)pwszTempBuffer, &cbData);
90 if (result != ERROR_SUCCESS) goto cleanup;
91
92 /* Expand environment variables, if appropriate, or copy the original string over. */
93 if (dwValueType == REG_EXPAND_SZ)
94 {
95 cbData = ExpandEnvironmentStringsW(pwszTempBuffer, NULL, 0) * sizeof(WCHAR);
96 if (!cbData) goto cleanup;
97 pwszExpandedBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
98 if (!pwszExpandedBuffer)
99 {
100 result = ERROR_NOT_ENOUGH_MEMORY;
101 goto cleanup;
102 }
103 ExpandEnvironmentStringsW(pwszTempBuffer, pwszExpandedBuffer, cbData);
104 }
105 else
106 {
107 pwszExpandedBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
108 memcpy(pwszExpandedBuffer, pwszTempBuffer, cbData);
109 }
110
111 /* If the value references a resource based string, parse the value and load the string.
112 * Else just copy over the original value. */
113 result = ERROR_SUCCESS;
114 if (*pwszExpandedBuffer != L'@') /* '@' is the prefix for resource based string entries. */
115 {
116 lstrcpynW(pszOutBuf, pwszExpandedBuffer, cbOutBuf / sizeof(WCHAR));
117 }
118 else
119 {
120 WCHAR *pComma = wcsrchr(pwszExpandedBuffer, L',');
121 UINT uiStringId;
122 HMODULE hModule;
123
124 /* Format of the expanded value is 'path_to_dll,-resId' */
125 if (!pComma || pComma[1] != L'-')
126 {
127 result = ERROR_BADKEY;
128 goto cleanup;
129 }
130
131 uiStringId = _wtoi(pComma+2);
132 *pComma = L'\0';
133
134 hModule = LoadLibraryExW(pwszExpandedBuffer + 1, NULL, LOAD_LIBRARY_AS_DATAFILE);
135 if (!hModule || !load_string(hModule, uiStringId, pszOutBuf, cbOutBuf / sizeof(WCHAR)))
136 result = ERROR_BADKEY;
137 FreeLibrary(hModule);
138 }
139
140 cleanup:
141 HeapFree(GetProcessHeap(), 0, pwszTempBuffer);
142 HeapFree(GetProcessHeap(), 0, pwszExpandedBuffer);
143 return result;
144 }