2 LONG WINAPI
RegCopyTreeX(HKEY
, LPCWSTR
, HKEY
)
8 static int load_string(HINSTANCE hModule
, UINT resId
, LPWSTR pwszBuffer
, INT cMaxChars
)
15 /* Negative values have to be inverted. */
16 if (HIWORD(resId
) == 0xffff)
17 resId
= (UINT
)(-((INT
)resId
));
19 /* Load the resource into memory and get a pointer to it. */
20 hResource
= FindResourceW(hModule
, MAKEINTRESOURCEW(LOWORD(resId
>> 4) + 1), (LPWSTR
)RT_STRING
);
21 if (!hResource
) return 0;
22 hMemory
= LoadResource(hModule
, hResource
);
23 if (!hMemory
) return 0;
24 pString
= (WCHAR
*)LockResource(hMemory
);
26 /* Strings are length-prefixed. Lowest nibble of resId is an index. */
27 idxString
= resId
& 0xf;
28 while (idxString
--) pString
+= *pString
+ 1;
30 /* If no buffer is given, return length of the string. */
31 if (!pwszBuffer
) return *pString
;
33 /* Else copy over the string, respecting the buffer size. */
34 cMaxChars
= (*pString
< cMaxChars
) ? *pString
: (cMaxChars
- 1);
37 memcpy(pwszBuffer
, pString
+1, cMaxChars
* sizeof(WCHAR
));
38 pwszBuffer
[cMaxChars
] = L
'\0';
45 RegLoadMUIStringWX(IN HKEY hKey
,
46 IN LPCWSTR pszValue OPTIONAL
,
49 OUT LPDWORD pcbData OPTIONAL
,
51 IN LPCWSTR pszDirectory OPTIONAL
)
53 DWORD dwValueType
, cbData
;
54 LPWSTR pwszTempBuffer
= NULL
, pwszExpandedBuffer
= NULL
;
57 /* Parameter sanity checks. */
58 if (!hKey
|| !pszOutBuf
)
59 return ERROR_INVALID_PARAMETER
;
61 if (pszDirectory
&& *pszDirectory
)
63 return ERROR_INVALID_PARAMETER
;
66 /* Check for value existence and correctness of it's type, allocate a buffer and load it. */
67 result
= RegQueryValueExW(hKey
, pszValue
, NULL
, &dwValueType
, NULL
, &cbData
);
68 if (result
!= ERROR_SUCCESS
) goto cleanup
;
69 if (!(dwValueType
== REG_SZ
|| dwValueType
== REG_EXPAND_SZ
) || !cbData
)
71 result
= ERROR_FILE_NOT_FOUND
;
74 pwszTempBuffer
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, cbData
);
77 result
= ERROR_NOT_ENOUGH_MEMORY
;
80 result
= RegQueryValueExW(hKey
, pszValue
, NULL
, &dwValueType
, (LPBYTE
)pwszTempBuffer
, &cbData
);
81 if (result
!= ERROR_SUCCESS
) goto cleanup
;
83 /* Expand environment variables, if appropriate, or copy the original string over. */
84 if (dwValueType
== REG_EXPAND_SZ
)
86 cbData
= ExpandEnvironmentStringsW(pwszTempBuffer
, NULL
, 0) * sizeof(WCHAR
);
87 if (!cbData
) goto cleanup
;
88 pwszExpandedBuffer
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, cbData
);
89 if (!pwszExpandedBuffer
)
91 result
= ERROR_NOT_ENOUGH_MEMORY
;
94 ExpandEnvironmentStringsW(pwszTempBuffer
, pwszExpandedBuffer
, cbData
);
98 pwszExpandedBuffer
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, cbData
);
99 memcpy(pwszExpandedBuffer
, pwszTempBuffer
, cbData
);
102 /* If the value references a resource based string, parse the value and load the string.
103 * Else just copy over the original value. */
104 result
= ERROR_SUCCESS
;
105 if (*pwszExpandedBuffer
!= L
'@') /* '@' is the prefix for resource based string entries. */
107 lstrcpynW(pszOutBuf
, pwszExpandedBuffer
, cbOutBuf
/ sizeof(WCHAR
));
111 WCHAR
*pComma
= wcsrchr(pwszExpandedBuffer
, L
',');
115 /* Format of the expanded value is 'path_to_dll,-resId' */
116 if (!pComma
|| pComma
[1] != L
'-')
118 result
= ERROR_BADKEY
;
122 uiStringId
= _wtoi(pComma
+2);
125 hModule
= LoadLibraryExW(pwszExpandedBuffer
+ 1, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
126 if (!hModule
|| !load_string(hModule
, uiStringId
, pszOutBuf
, cbOutBuf
/ sizeof(WCHAR
)))
127 result
= ERROR_BADKEY
;
128 FreeLibrary(hModule
);
132 HeapFree(GetProcessHeap(), 0, pwszTempBuffer
);
133 HeapFree(GetProcessHeap(), 0, pwszExpandedBuffer
);
138 VOID WINAPI
RtlFreeUnicodeString(PUNICODE_STRING UnicodeString
);
140 typedef VOID (WINAPI
*PRtlFreeUnicodeString
)(PUNICODE_STRING UnicodeString
);
142 RtlFreeUnicodeStringx(PUNICODE_STRING UnicodeString
)
144 static PRtlFreeUnicodeString Func
= NULL
;
149 hShlwapi
= LoadLibrary(TEXT("ntdll.DLL"));
150 if (hShlwapi
!= NULL
)
152 Func
= (PRtlFreeUnicodeString
)GetProcAddress(hShlwapi
, "RtlFreeUnicodeString");
162 MessageBox(NULL
, TEXT("RtlFreeUnicodeString not available"), NULL
, 0);
167 RegLoadMUIStringAX(IN HKEY hKey
,
168 IN LPCSTR pszValue OPTIONAL
,
171 OUT LPDWORD pcbData OPTIONAL
,
173 IN LPCSTR pszDirectory OPTIONAL
)
175 UNICODE_STRING valueW
, baseDirW
;
177 DWORD cbData
= cbOutBuf
* sizeof(WCHAR
);
180 valueW
.Buffer
= baseDirW
.Buffer
= pwszBuffer
= NULL
;
181 if (!RtlCreateUnicodeStringFromAsciiz(&valueW
, pszValue
) ||
182 !RtlCreateUnicodeStringFromAsciiz(&baseDirW
, pszDirectory
) ||
183 !(pwszBuffer
= (WCHAR
*)HeapAlloc(GetProcessHeap(), 0, cbData
)))
185 result
= ERROR_NOT_ENOUGH_MEMORY
;
189 result
= RegLoadMUIStringWX(hKey
, valueW
.Buffer
, pwszBuffer
, cbData
, NULL
, Flags
,
192 if (result
== ERROR_SUCCESS
)
194 cbData
= WideCharToMultiByte(CP_ACP
, 0, pwszBuffer
, -1, pszOutBuf
, cbOutBuf
, NULL
, NULL
);
200 HeapFree(GetProcessHeap(), 0, pwszBuffer
);
201 RtlFreeUnicodeStringx(&baseDirW
);
202 RtlFreeUnicodeStringx(&valueW
);
208 RegpApplyRestrictions(DWORD dwFlags
,
213 /* Check if the type is restricted by the passed flags */
214 if (*ret
== ERROR_SUCCESS
|| *ret
== ERROR_MORE_DATA
)
220 case REG_NONE
: dwMask
= RRF_RT_REG_NONE
; break;
221 case REG_SZ
: dwMask
= RRF_RT_REG_SZ
; break;
222 case REG_EXPAND_SZ
: dwMask
= RRF_RT_REG_EXPAND_SZ
; break;
223 case REG_MULTI_SZ
: dwMask
= RRF_RT_REG_MULTI_SZ
; break;
224 case REG_BINARY
: dwMask
= RRF_RT_REG_BINARY
; break;
225 case REG_DWORD
: dwMask
= RRF_RT_REG_DWORD
; break;
226 case REG_QWORD
: dwMask
= RRF_RT_REG_QWORD
; break;
229 if (dwFlags
& dwMask
)
231 /* Type is not restricted, check for size mismatch */
232 if (dwType
== REG_BINARY
)
236 if ((dwFlags
& RRF_RT_DWORD
) == RRF_RT_DWORD
)
238 else if ((dwFlags
& RRF_RT_QWORD
) == RRF_RT_QWORD
)
241 if (cbExpect
&& cbData
!= cbExpect
)
242 *ret
= ERROR_DATATYPE_MISMATCH
;
245 else *ret
= ERROR_UNSUPPORTED_TYPE
;
249 LONG WINAPI
RegGetValueX(HKEY hKey
, LPCWSTR pszSubKey
, LPCWSTR pszValue
, DWORD dwFlags
, LPDWORD pdwType
, PVOID pvData
, LPDWORD pcbData
)
251 DWORD dwType
, cbData
= pcbData
? *pcbData
: 0;
255 if (pvData
&& !pcbData
)
256 return ERROR_INVALID_PARAMETER
;
257 if ((dwFlags
& RRF_RT_REG_EXPAND_SZ
) && !(dwFlags
& RRF_NOEXPAND
) &&
258 ((dwFlags
& RRF_RT_ANY
) != RRF_RT_ANY
))
259 return ERROR_INVALID_PARAMETER
;
261 if (pszSubKey
&& pszSubKey
[0])
263 ret
= RegOpenKeyExW(hKey
, pszSubKey
, 0, KEY_QUERY_VALUE
, &hKey
);
264 if (ret
!= ERROR_SUCCESS
) return ret
;
267 ret
= RegQueryValueExW(hKey
, pszValue
, NULL
, &dwType
, (LPBYTE
)pvData
, &cbData
);
269 /* If we are going to expand we need to read in the whole the value even
270 * if the passed buffer was too small as the expanded string might be
271 * smaller than the unexpanded one and could fit into cbData bytes. */
272 if ((ret
== ERROR_SUCCESS
|| ret
== ERROR_MORE_DATA
) &&
273 dwType
== REG_EXPAND_SZ
&& !(dwFlags
& RRF_NOEXPAND
))
277 HeapFree(GetProcessHeap(), 0, pvBuf
);
279 pvBuf
= HeapAlloc(GetProcessHeap(), 0, cbData
);
282 ret
= ERROR_NOT_ENOUGH_MEMORY
;
286 if (ret
== ERROR_MORE_DATA
|| !pvData
)
287 ret
= RegQueryValueExW(hKey
, pszValue
, NULL
,
288 &dwType
, (LPBYTE
)pvBuf
, &cbData
);
291 /* Even if cbData was large enough we have to copy the
292 * string since ExpandEnvironmentStrings can't handle
293 * overlapping buffers. */
294 CopyMemory(pvBuf
, pvData
, cbData
);
297 /* Both the type or the value itself could have been modified in
298 * between so we have to keep retrying until the buffer is large
299 * enough or we no longer have to expand the value. */
301 while (dwType
== REG_EXPAND_SZ
&& ret
== ERROR_MORE_DATA
);
303 if (ret
== ERROR_SUCCESS
)
305 /* Recheck dwType in case it changed since the first call */
306 if (dwType
== REG_EXPAND_SZ
)
308 cbData
= ExpandEnvironmentStringsW((LPCWSTR
)pvBuf
, (LPWSTR
)pvData
,
309 pcbData
? *pcbData
: 0) * sizeof(WCHAR
);
311 if (pvData
&& pcbData
&& cbData
> *pcbData
)
312 ret
= ERROR_MORE_DATA
;
315 CopyMemory(pvData
, pvBuf
, *pcbData
);
318 HeapFree(GetProcessHeap(), 0, pvBuf
);
321 if (pszSubKey
&& pszSubKey
[0])
324 RegpApplyRestrictions(dwFlags
, dwType
, cbData
, &ret
);
326 if (pvData
&& ret
!= ERROR_SUCCESS
&& (dwFlags
& RRF_ZEROONFAILURE
))
327 ZeroMemory(pvData
, *pcbData
);