2 * Unit tests for registry functions
4 * Copyright (c) 2002 Alexandre Julliard
5 * Copyright (c) 2010 André Hentschel
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #define WIN32_NO_STATUS
27 #include "wine/test.h"
37 #define IS_HKCR(hk) ((UINT_PTR)hk > 0 && ((UINT_PTR)hk & 3) == 2)
39 static HKEY hkey_main
;
42 static const char * sTestpath1
= "%LONGSYSTEMVAR%\\subdir1";
43 static const char * sTestpath2
= "%FOO%\\subdir1";
44 static const DWORD ptr_size
= 8 * sizeof(void*);
46 static DWORD (WINAPI
*pRegGetValueA
)(HKEY
,LPCSTR
,LPCSTR
,DWORD
,LPDWORD
,PVOID
,LPDWORD
);
47 static DWORD (WINAPI
*pRegGetValueW
)(HKEY
,LPCWSTR
,LPCWSTR
,DWORD
,LPDWORD
,PVOID
,LPDWORD
);
48 static LONG (WINAPI
*pRegCopyTreeA
)(HKEY
,const char *,HKEY
);
49 static LONG (WINAPI
*pRegDeleteTreeA
)(HKEY
,const char *);
50 static DWORD (WINAPI
*pRegDeleteKeyExA
)(HKEY
,LPCSTR
,REGSAM
,DWORD
);
51 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
,PBOOL
);
52 static NTSTATUS (WINAPI
* pNtDeleteKey
)(HANDLE
);
53 static NTSTATUS (WINAPI
* pNtUnloadKey
)(POBJECT_ATTRIBUTES
);
54 static NTSTATUS (WINAPI
* pRtlFormatCurrentUserKeyPath
)(UNICODE_STRING
*);
55 static NTSTATUS (WINAPI
* pRtlFreeUnicodeString
)(PUNICODE_STRING
);
56 static NTSTATUS (WINAPI
* pRtlInitUnicodeString
)(PUNICODE_STRING
,PCWSTR
);
57 static LONG (WINAPI
*pRegDeleteKeyValueA
)(HKEY
,LPCSTR
,LPCSTR
);
58 static LONG (WINAPI
*pRegSetKeyValueW
)(HKEY
,LPCWSTR
,LPCWSTR
,DWORD
,const void*,DWORD
);
59 static LONG (WINAPI
*pRegLoadMUIStringA
)(HKEY
,LPCSTR
,LPSTR
,DWORD
,LPDWORD
,DWORD
,LPCSTR
);
60 static LONG (WINAPI
*pRegLoadMUIStringW
)(HKEY
,LPCWSTR
,LPWSTR
,DWORD
,LPDWORD
,DWORD
,LPCWSTR
);
61 static DWORD (WINAPI
*pEnumDynamicTimeZoneInformation
)(const DWORD
,
62 DYNAMIC_TIME_ZONE_INFORMATION
*);
64 static BOOL limited_user
;
66 static const char *dbgstr_SYSTEMTIME(const SYSTEMTIME
*st
)
68 return wine_dbg_sprintf("%02d-%02d-%04d %02d:%02d:%02d.%03d",
69 st
->wMonth
, st
->wDay
, st
->wYear
,
70 st
->wHour
, st
->wMinute
, st
->wSecond
, st
->wMilliseconds
);
73 #define ADVAPI32_GET_PROC(func) \
74 p ## func = (void*)GetProcAddress(hadvapi32, #func)
76 static void InitFunctionPtrs(void)
78 HMODULE hntdll
= GetModuleHandleA("ntdll.dll");
79 HMODULE hkernel32
= GetModuleHandleA("kernel32.dll");
80 HMODULE hadvapi32
= GetModuleHandleA("advapi32.dll");
82 /* This function was introduced with Windows 2003 SP1 */
83 ADVAPI32_GET_PROC(RegGetValueA
);
84 ADVAPI32_GET_PROC(RegGetValueW
);
85 ADVAPI32_GET_PROC(RegCopyTreeA
);
86 ADVAPI32_GET_PROC(RegDeleteTreeA
);
87 ADVAPI32_GET_PROC(RegDeleteKeyExA
);
88 ADVAPI32_GET_PROC(RegDeleteKeyValueA
);
89 ADVAPI32_GET_PROC(RegSetKeyValueW
);
90 ADVAPI32_GET_PROC(RegLoadMUIStringA
);
91 ADVAPI32_GET_PROC(RegLoadMUIStringW
);
92 ADVAPI32_GET_PROC(EnumDynamicTimeZoneInformation
);
94 pIsWow64Process
= (void *)GetProcAddress( hkernel32
, "IsWow64Process" );
95 pRtlFormatCurrentUserKeyPath
= (void *)GetProcAddress( hntdll
, "RtlFormatCurrentUserKeyPath" );
96 pRtlFreeUnicodeString
= (void *)GetProcAddress(hntdll
, "RtlFreeUnicodeString");
97 pRtlInitUnicodeString
= (void *)GetProcAddress(hntdll
, "RtlInitUnicodeString");
98 pNtDeleteKey
= (void *)GetProcAddress( hntdll
, "NtDeleteKey" );
99 pNtUnloadKey
= (void *)GetProcAddress( hntdll
, "NtUnloadKey" );
102 static BOOL
is_special_key(HKEY key
)
104 return !!((ULONG_PTR
)key
& 0x80000000);
107 /* delete key and all its subkeys */
108 static DWORD
delete_key( HKEY hkey
)
113 if ((ret
= RegOpenKeyExA( hkey
, "", 0, KEY_ENUMERATE_SUB_KEYS
, &hkey
))) return ret
;
114 while (!(ret
= RegEnumKeyA(hkey
, 0, name
, sizeof(name
))))
117 if (!(ret
= RegOpenKeyExA( hkey
, name
, 0, KEY_ENUMERATE_SUB_KEYS
, &tmp
)))
119 ret
= delete_key( tmp
);
124 if (ret
!= ERROR_NO_MORE_ITEMS
) return ret
;
125 RegDeleteKeyA( hkey
, "" );
130 static void setup_main_key(void)
134 if (!RegOpenKeyA( HKEY_CURRENT_USER
, "Software\\Wine\\Test", &hkey_main
)) delete_key( hkey_main
);
136 ret
= RegCreateKeyA( HKEY_CURRENT_USER
, "Software\\Wine\\Test", &hkey_main
);
137 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
140 static void check_user_privs(void)
143 HKEY hkey
= (HKEY
)0xdeadbeef;
145 ret
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software", 0, KEY_READ
|KEY_WRITE
, &hkey
);
146 ok(ret
== ERROR_SUCCESS
|| ret
== ERROR_ACCESS_DENIED
, "expected success or access denied, got %li\n", ret
);
147 if (ret
== ERROR_SUCCESS
)
149 ok(hkey
!= NULL
, "RegOpenKeyExA succeeded but returned NULL hkey\n");
154 ok(hkey
== NULL
, "RegOpenKeyExA failed but returned hkey %p\n", hkey
);
156 trace("running as limited user\n");
160 #define lok ok_(__FILE__, line)
161 #define test_hkey_main_Value_A(name, string, full_byte_len) _test_hkey_main_Value_A(__LINE__, name, string, full_byte_len)
162 static void _test_hkey_main_Value_A(int line
, LPCSTR name
, LPCSTR string
,
165 DWORD ret
, type
, cbData
;
171 /* When successful RegQueryValueExA() leaves GLE as is,
172 * so we must reset it to detect unimplemented functions.
174 SetLastError(0xdeadbeef);
175 ret
= RegQueryValueExA(hkey_main
, name
, NULL
, &type
, NULL
, &cbData
);
176 GLE
= GetLastError();
177 lok(ret
== ERROR_SUCCESS
, "RegQueryValueExA/1 failed: %ld, GLE=%ld\n", ret
, GLE
);
178 /* It is wrong for the Ansi version to not be implemented */
179 ok(GLE
== 0xdeadbeef, "RegQueryValueExA set GLE = %lu\n", GLE
);
180 if(GLE
== ERROR_CALL_NOT_IMPLEMENTED
) return;
182 str_byte_len
= (string
? lstrlenA(string
) : 0) + 1;
183 lok(type
== REG_SZ
, "RegQueryValueExA/1 returned type %ld\n", type
);
184 lok(cbData
== full_byte_len
, "cbData=%ld instead of %ld or %ld\n", cbData
, full_byte_len
, str_byte_len
);
186 value
= HeapAlloc(GetProcessHeap(), 0, cbData
+1);
187 memset(value
, 0xbd, cbData
+1);
189 ret
= RegQueryValueExA(hkey_main
, name
, NULL
, &type
, value
, &cbData
);
190 GLE
= GetLastError();
191 lok(ret
== ERROR_SUCCESS
, "RegQueryValueExA/2 failed: %ld, GLE=%ld\n", ret
, GLE
);
194 /* When cbData == 0, RegQueryValueExA() should not modify the buffer */
195 lok(*value
== 0xbd, "RegQueryValueExA overflowed: cbData=%lu *value=%02x\n", cbData
, *value
);
199 lok(memcmp(value
, string
, cbData
) == 0, "RegQueryValueExA/2 failed: %s/%ld != %s/%ld\n",
200 debugstr_an((char*)value
, cbData
), cbData
,
201 debugstr_an(string
, full_byte_len
), full_byte_len
);
202 lok(*(value
+cbData
) == 0xbd, "RegQueryValueExA/2 overflowed at offset %lu: %02x != bd\n", cbData
, *(value
+cbData
));
204 HeapFree(GetProcessHeap(), 0, value
);
207 #define test_hkey_main_Value_W(name, string, full_byte_len) _test_hkey_main_Value_W(__LINE__, name, string, full_byte_len)
208 static void _test_hkey_main_Value_W(int line
, LPCWSTR name
, LPCWSTR string
,
211 DWORD ret
, type
, cbData
;
216 /* When successful RegQueryValueExW() leaves GLE as is,
217 * so we must reset it to detect unimplemented functions.
219 SetLastError(0xdeadbeef);
220 ret
= RegQueryValueExW(hkey_main
, name
, NULL
, &type
, NULL
, &cbData
);
221 GLE
= GetLastError();
222 lok(ret
== ERROR_SUCCESS
, "RegQueryValueExW/1 failed: %ld, GLE=%ld\n", ret
, GLE
);
223 if(GLE
== ERROR_CALL_NOT_IMPLEMENTED
)
225 win_skip("RegQueryValueExW() is not implemented\n");
229 lok(type
== REG_SZ
, "RegQueryValueExW/1 returned type %ld\n", type
);
230 lok(cbData
== full_byte_len
,
231 "cbData=%ld instead of %ld\n", cbData
, full_byte_len
);
233 /* Give enough space to overflow by one WCHAR */
234 value
= HeapAlloc(GetProcessHeap(), 0, cbData
+2);
235 memset(value
, 0xbd, cbData
+2);
237 ret
= RegQueryValueExW(hkey_main
, name
, NULL
, &type
, value
, &cbData
);
238 GLE
= GetLastError();
239 lok(ret
== ERROR_SUCCESS
, "RegQueryValueExW/2 failed: %ld, GLE=%ld\n", ret
, GLE
);
242 lok(memcmp(value
, string
, cbData
) == 0, "RegQueryValueExW failed: %s/%ld != %s/%ld\n",
243 wine_dbgstr_wn((WCHAR
*)value
, cbData
/ sizeof(WCHAR
)), cbData
,
244 wine_dbgstr_wn(string
, full_byte_len
/ sizeof(WCHAR
)), full_byte_len
);
246 /* This implies that when cbData == 0, RegQueryValueExW() should not modify the buffer */
247 lok(*(value
+cbData
) == 0xbd, "RegQueryValueExW/2 overflowed at %lu: %02x != bd\n", cbData
, *(value
+cbData
));
248 lok(*(value
+cbData
+1) == 0xbd, "RegQueryValueExW/2 overflowed at %lu+1: %02x != bd\n", cbData
, *(value
+cbData
+1));
249 HeapFree(GetProcessHeap(), 0, value
);
252 static void test_set_value(void)
256 static const WCHAR name1W
[] = L
"CleanSingleString";
257 static const WCHAR name2W
[] = L
"SomeIntraZeroedString";
258 static const WCHAR emptyW
[] = L
"";
259 static const WCHAR string1W
[] = L
"ThisNeverBreaks";
260 static const WCHAR string2W
[] = L
"This\0Breaks\0\0A\0\0\0Lot\0\0\0\0";
261 static const WCHAR substring2W
[] = L
"This";
263 static const char name1A
[] = "CleanSingleString";
264 static const char name2A
[] = "SomeIntraZeroedString";
265 static const char emptyA
[] = "";
266 static const char string1A
[] = "ThisNeverBreaks";
267 static const char string2A
[] = "This\0Breaks\0\0A\0\0\0Lot\0\0\0\0";
268 static const char substring2A
[] = "This";
272 /* Crashes on NT4, Windows 2000 and XP SP1 */
273 ret
= RegSetValueA(hkey_main
, NULL
, REG_SZ
, NULL
, 0);
274 ok(ret
== ERROR_INVALID_PARAMETER
, "RegSetValueA should have failed with ERROR_INVALID_PARAMETER instead of %ld\n", ret
);
277 ret
= RegSetValueA(hkey_main
, NULL
, REG_SZ
, string1A
, sizeof(string1A
));
278 ok(ret
== ERROR_SUCCESS
, "RegSetValueA failed: %ld, GLE=%ld\n", ret
, GetLastError());
279 test_hkey_main_Value_A(NULL
, string1A
, sizeof(string1A
));
280 test_hkey_main_Value_W(NULL
, string1W
, sizeof(string1W
));
282 /* RegSetValueA ignores the size passed in */
283 ret
= RegSetValueA(hkey_main
, NULL
, REG_SZ
, string1A
, 4);
284 ok(ret
== ERROR_SUCCESS
, "RegSetValueA failed: %ld, GLE=%ld\n", ret
, GetLastError());
285 test_hkey_main_Value_A(NULL
, string1A
, sizeof(string1A
));
286 test_hkey_main_Value_W(NULL
, string1W
, sizeof(string1W
));
288 /* stops at first null */
289 ret
= RegSetValueA(hkey_main
, NULL
, REG_SZ
, string2A
, sizeof(string2A
));
290 ok(ret
== ERROR_SUCCESS
, "RegSetValueA failed: %ld, GLE=%ld\n", ret
, GetLastError());
291 test_hkey_main_Value_A(NULL
, substring2A
, sizeof(substring2A
));
292 test_hkey_main_Value_W(NULL
, substring2W
, sizeof(substring2W
));
294 /* only REG_SZ is supported on NT*/
295 ret
= RegSetValueA(hkey_main
, NULL
, REG_BINARY
, string2A
, sizeof(string2A
));
296 ok(ret
== ERROR_INVALID_PARAMETER
, "got %ld (expected ERROR_INVALID_PARAMETER)\n", ret
);
298 ret
= RegSetValueA(hkey_main
, NULL
, REG_EXPAND_SZ
, string2A
, sizeof(string2A
));
299 ok(ret
== ERROR_INVALID_PARAMETER
, "got %ld (expected ERROR_INVALID_PARAMETER)\n", ret
);
301 ret
= RegSetValueA(hkey_main
, NULL
, REG_MULTI_SZ
, string2A
, sizeof(string2A
));
302 ok(ret
== ERROR_INVALID_PARAMETER
, "got %ld (expected ERROR_INVALID_PARAMETER)\n", ret
);
304 /* Test RegSetValueExA with a 'zero-byte' string (as Office 2003 does).
305 * Surprisingly enough we're supposed to get zero bytes out of it.
307 ret
= RegSetValueExA(hkey_main
, name1A
, 0, REG_SZ
, (const BYTE
*)emptyA
, 0);
308 ok(ret
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%ld\n", ret
, GetLastError());
309 test_hkey_main_Value_A(name1A
, NULL
, 0);
310 test_hkey_main_Value_W(name1W
, NULL
, 0);
312 /* test RegSetValueExA with an empty string */
313 ret
= RegSetValueExA(hkey_main
, name1A
, 0, REG_SZ
, (const BYTE
*)emptyA
, sizeof(emptyA
));
314 ok(ret
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%ld\n", ret
, GetLastError());
315 test_hkey_main_Value_A(name1A
, emptyA
, sizeof(emptyA
));
316 test_hkey_main_Value_W(name1W
, emptyW
, sizeof(emptyW
));
318 /* test RegSetValueExA with off-by-one size */
319 ret
= RegSetValueExA(hkey_main
, name1A
, 0, REG_SZ
, (const BYTE
*)string1A
, sizeof(string1A
)-sizeof(string1A
[0]));
320 ok(ret
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%ld\n", ret
, GetLastError());
321 test_hkey_main_Value_A(name1A
, string1A
, sizeof(string1A
));
322 test_hkey_main_Value_W(name1W
, string1W
, sizeof(string1W
));
324 /* test RegSetValueExA with normal string */
325 ret
= RegSetValueExA(hkey_main
, name1A
, 0, REG_SZ
, (const BYTE
*)string1A
, sizeof(string1A
));
326 ok(ret
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%ld\n", ret
, GetLastError());
327 test_hkey_main_Value_A(name1A
, string1A
, sizeof(string1A
));
328 test_hkey_main_Value_W(name1W
, string1W
, sizeof(string1W
));
330 /* test RegSetValueExA with intrazeroed string */
331 ret
= RegSetValueExA(hkey_main
, name2A
, 0, REG_SZ
, (const BYTE
*)string2A
, sizeof(string2A
));
332 ok(ret
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%ld\n", ret
, GetLastError());
333 test_hkey_main_Value_A(name2A
, string2A
, sizeof(string2A
));
334 test_hkey_main_Value_W(name2W
, string2W
, sizeof(string2W
));
338 /* Crashes on NT4, Windows 2000 and XP SP1 */
339 ret
= RegSetValueW(hkey_main
, NULL
, REG_SZ
, NULL
, 0);
340 ok(ret
== ERROR_INVALID_PARAMETER
, "RegSetValueW should have failed with ERROR_INVALID_PARAMETER instead of %ld\n", ret
);
342 RegSetValueExA(hkey_main
, name2A
, 0, REG_SZ
, (const BYTE
*)1, 1);
343 RegSetValueExA(hkey_main
, name2A
, 0, REG_DWORD
, (const BYTE
*)1, 1);
346 ret
= RegSetValueW(hkey_main
, NULL
, REG_SZ
, string1W
, sizeof(string1W
));
347 ok(ret
== ERROR_SUCCESS
, "RegSetValueW failed: %ld, GLE=%ld\n", ret
, GetLastError());
348 test_hkey_main_Value_A(NULL
, string1A
, sizeof(string1A
));
349 test_hkey_main_Value_W(NULL
, string1W
, sizeof(string1W
));
351 ret
= RegSetValueW(hkey_main
, name1W
, REG_SZ
, string1W
, sizeof(string1W
));
352 ok(ret
== ERROR_SUCCESS
, "RegSetValueW failed: %ld, GLE=%ld\n", ret
, GetLastError());
353 test_hkey_main_Value_A(name1A
, string1A
, sizeof(string1A
));
354 test_hkey_main_Value_W(name1W
, string1W
, sizeof(string1W
));
356 /* RegSetValueW ignores the size passed in */
357 ret
= RegSetValueW(hkey_main
, NULL
, REG_SZ
, string1W
, 4 * sizeof(string1W
[0]));
358 ok(ret
== ERROR_SUCCESS
, "RegSetValueW failed: %ld, GLE=%ld\n", ret
, GetLastError());
359 test_hkey_main_Value_A(NULL
, string1A
, sizeof(string1A
));
360 test_hkey_main_Value_W(NULL
, string1W
, sizeof(string1W
));
362 /* stops at first null */
363 ret
= RegSetValueW(hkey_main
, NULL
, REG_SZ
, string2W
, sizeof(string2W
));
364 ok(ret
== ERROR_SUCCESS
, "RegSetValueW failed: %ld, GLE=%ld\n", ret
, GetLastError());
365 test_hkey_main_Value_A(NULL
, substring2A
, sizeof(substring2A
));
366 test_hkey_main_Value_W(NULL
, substring2W
, sizeof(substring2W
));
368 /* only REG_SZ is supported */
369 ret
= RegSetValueW(hkey_main
, NULL
, REG_BINARY
, string2W
, sizeof(string2W
));
370 ok(ret
== ERROR_INVALID_PARAMETER
, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %ld\n", ret
);
371 ret
= RegSetValueW(hkey_main
, NULL
, REG_EXPAND_SZ
, string2W
, sizeof(string2W
));
372 ok(ret
== ERROR_INVALID_PARAMETER
, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %ld\n", ret
);
373 ret
= RegSetValueW(hkey_main
, NULL
, REG_MULTI_SZ
, string2W
, sizeof(string2W
));
374 ok(ret
== ERROR_INVALID_PARAMETER
, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %ld\n", ret
);
376 /* test RegSetValueExW with off-by-one size */
377 ret
= RegSetValueExW(hkey_main
, name1W
, 0, REG_SZ
, (const BYTE
*)string1W
, sizeof(string1W
)-sizeof(string1W
[0]));
378 ok(ret
== ERROR_SUCCESS
, "RegSetValueExW failed: %ld, GLE=%ld\n", ret
, GetLastError());
379 test_hkey_main_Value_A(name1A
, string1A
, sizeof(string1A
));
380 test_hkey_main_Value_W(name1W
, string1W
, sizeof(string1W
));
382 /* test RegSetValueExW with normal string */
383 ret
= RegSetValueExW(hkey_main
, name1W
, 0, REG_SZ
, (const BYTE
*)string1W
, sizeof(string1W
));
384 ok(ret
== ERROR_SUCCESS
, "RegSetValueExW failed: %ld, GLE=%ld\n", ret
, GetLastError());
385 test_hkey_main_Value_A(name1A
, string1A
, sizeof(string1A
));
386 test_hkey_main_Value_W(name1W
, string1W
, sizeof(string1W
));
388 /* test RegSetValueExW with intrazeroed string */
389 ret
= RegSetValueExW(hkey_main
, name2W
, 0, REG_SZ
, (const BYTE
*)string2W
, sizeof(string2W
));
390 ok(ret
== ERROR_SUCCESS
, "RegSetValueExW failed: %ld, GLE=%ld\n", ret
, GetLastError());
391 test_hkey_main_Value_A(name2A
, string2A
, sizeof(string2A
));
392 test_hkey_main_Value_W(name2W
, string2W
, sizeof(string2W
));
394 /* test RegSetValueExW with data = 1 */
395 ret
= RegSetValueExW(hkey_main
, name2W
, 0, REG_SZ
, (const BYTE
*)1, 1);
396 ok(ret
== ERROR_NOACCESS
, "RegSetValueExW should have failed with ERROR_NOACCESS: %ld, GLE=%ld\n", ret
, GetLastError());
397 ret
= RegSetValueExW(hkey_main
, name2W
, 0, REG_DWORD
, (const BYTE
*)1, 1);
398 ok(ret
== ERROR_NOACCESS
, "RegSetValueExW should have failed with ERROR_NOACCESS: %ld, GLE=%ld\n", ret
, GetLastError());
400 if (pRegGetValueA
) /* avoid a crash on Windows 2000 */
402 ret
= RegSetValueExW(hkey_main
, NULL
, 0, REG_SZ
, NULL
, 4);
403 ok(ret
== ERROR_NOACCESS
, "RegSetValueExW should have failed with ERROR_NOACCESS: %ld, GLE=%ld\n", ret
, GetLastError());
405 ret
= RegSetValueExW(hkey_main
, NULL
, 0, REG_SZ
, NULL
, 0);
406 ok(ret
== ERROR_SUCCESS
, "got %ld\n", ret
);
408 ret
= RegSetValueExW(hkey_main
, NULL
, 0, REG_DWORD
, NULL
, 4);
409 ok(ret
== ERROR_NOACCESS
, "RegSetValueExW should have failed with ERROR_NOACCESS: %ld, GLE=%ld\n", ret
, GetLastError());
411 ret
= RegSetValueExW(hkey_main
, NULL
, 0, REG_DWORD
, NULL
, 0);
412 ok(ret
== ERROR_SUCCESS
, "got %ld\n", ret
);
416 if (!pRegSetKeyValueW
)
417 win_skip("RegSetKeyValue() is not supported.\n");
423 ret
= pRegSetKeyValueW(hkey_main
, NULL
, name1W
, REG_SZ
, (const BYTE
*)string2W
, sizeof(string2W
));
424 ok(ret
== ERROR_SUCCESS
, "got %ld\n", ret
);
425 test_hkey_main_Value_A(name1A
, string2A
, sizeof(string2A
));
426 test_hkey_main_Value_W(name1W
, string2W
, sizeof(string2W
));
428 ret
= pRegSetKeyValueW(hkey_main
, L
"subkey", name1W
, REG_SZ
, string1W
, sizeof(string1W
));
429 ok(ret
== ERROR_SUCCESS
, "got %ld\n", ret
);
431 ret
= RegOpenKeyExW(hkey_main
, L
"subkey", 0, KEY_QUERY_VALUE
, &subkey
);
432 ok(ret
== ERROR_SUCCESS
, "got %ld\n", ret
);
434 ret
= RegQueryValueExW(subkey
, name1W
, 0, &type
, NULL
, &len
);
435 ok(ret
== ERROR_SUCCESS
, "got %ld\n", ret
);
436 ok(len
== sizeof(string1W
), "got %ld\n", len
);
437 ok(type
== REG_SZ
, "got type %ld\n", type
);
439 ret
= pRegSetKeyValueW(hkey_main
, L
"subkey", name1W
, REG_SZ
, NULL
, 0);
440 ok(ret
== ERROR_SUCCESS
, "got %ld\n", ret
);
442 ret
= pRegSetKeyValueW(hkey_main
, L
"subkey", name1W
, REG_SZ
, NULL
, 4);
443 ok(ret
== ERROR_NOACCESS
, "got %ld\n", ret
);
445 ret
= pRegSetKeyValueW(hkey_main
, L
"subkey", name1W
, REG_DWORD
, NULL
, 4);
446 ok(ret
== ERROR_NOACCESS
, "got %ld\n", ret
);
452 static void create_test_entries(void)
454 static const DWORD qw
[2] = { 0x12345678, 0x87654321 };
456 SetEnvironmentVariableA("LONGSYSTEMVAR", "bar");
457 SetEnvironmentVariableA("FOO", "ImARatherLongButIndeedNeededString");
459 ok(!RegSetValueExA(hkey_main
,"TP1_EXP_SZ",0,REG_EXPAND_SZ
, (const BYTE
*)sTestpath1
, strlen(sTestpath1
)+1),
460 "RegSetValueExA failed\n");
461 ok(!RegSetValueExA(hkey_main
,"TP1_SZ",0,REG_SZ
, (const BYTE
*)sTestpath1
, strlen(sTestpath1
)+1),
462 "RegSetValueExA failed\n");
463 ok(!RegSetValueExA(hkey_main
,"TP1_ZB_SZ",0,REG_SZ
, (const BYTE
*)"", 0),
464 "RegSetValueExA failed\n");
465 ok(!RegSetValueExA(hkey_main
,"TP2_EXP_SZ",0,REG_EXPAND_SZ
, (const BYTE
*)sTestpath2
, strlen(sTestpath2
)+1),
466 "RegSetValueExA failed\n");
467 ok(!RegSetValueExA(hkey_main
,"DWORD",0,REG_DWORD
, (const BYTE
*)qw
, 4),
468 "RegSetValueExA failed\n");
469 ok(!RegSetValueExA(hkey_main
,"BIN32",0,REG_BINARY
, (const BYTE
*)qw
, 4),
470 "RegSetValueExA failed\n");
471 ok(!RegSetValueExA(hkey_main
,"BIN64",0,REG_BINARY
, (const BYTE
*)qw
, 8),
472 "RegSetValueExA failed\n");
475 static void test_enum_value(void)
479 char value
[20], data
[30];
480 WCHAR valueW
[20], dataW
[20];
481 DWORD val_count
, data_count
, type
;
483 /* create the working key for new 'Test' value */
484 res
= RegCreateKeyA( hkey_main
, "TestKey", &test_key
);
485 ok( res
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", res
);
487 /* check NULL data with zero length */
488 res
= RegSetValueExA( test_key
, "Test", 0, REG_SZ
, NULL
, 0 );
489 if (GetVersion() & 0x80000000)
490 ok( res
== ERROR_INVALID_PARAMETER
, "RegSetValueExA returned %ld\n", res
);
492 ok( !res
, "RegSetValueExA returned %ld\n", res
);
493 res
= RegSetValueExA( test_key
, "Test", 0, REG_EXPAND_SZ
, NULL
, 0 );
494 ok( ERROR_SUCCESS
== res
, "RegSetValueExA returned %ld\n", res
);
495 res
= RegSetValueExA( test_key
, "Test", 0, REG_BINARY
, NULL
, 0 );
496 ok( ERROR_SUCCESS
== res
, "RegSetValueExA returned %ld\n", res
);
498 /* test reading the value and data without setting them */
502 strcpy( value
, "xxxxxxxxxx" );
503 strcpy( data
, "xxxxxxxxxx" );
504 res
= RegEnumValueA( test_key
, 0, value
, &val_count
, NULL
, &type
, (LPBYTE
)data
, &data_count
);
505 ok( res
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", res
);
506 ok( val_count
== 4, "val_count set to %ld instead of 4\n", val_count
);
507 ok( data_count
== 0, "data_count set to %ld instead of 0\n", data_count
);
508 ok( type
== REG_BINARY
, "type %ld is not REG_BINARY\n", type
);
509 ok( !strcmp( value
, "Test" ), "value is '%s' instead of Test\n", value
);
510 ok( !strcmp( data
, "xxxxxxxxxx" ), "data is '%s' instead of xxxxxxxxxx\n", data
);
515 wcscpy( valueW
, L
"xxxxxxxx" );
516 wcscpy( dataW
, L
"xxxxxxxx" );
517 res
= RegEnumValueW( test_key
, 0, valueW
, &val_count
, NULL
, &type
, (BYTE
*)dataW
, &data_count
);
518 ok( res
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", res
);
519 ok( val_count
== 4, "val_count set to %ld instead of 4\n", val_count
);
520 ok( data_count
== 0, "data_count set to %ld instead of 0\n", data_count
);
521 ok( type
== REG_BINARY
, "type %ld is not REG_BINARY\n", type
);
522 ok( !wcscmp( valueW
, L
"Test" ), "value is not 'Test'\n" );
523 ok( !wcscmp( dataW
, L
"xxxxxxxx" ), "data is not 'xxxxxxxx'\n" );
525 res
= RegSetValueExA( test_key
, "Test", 0, REG_SZ
, (const BYTE
*)"foobar", 7 );
526 ok( res
== 0, "RegSetValueExA failed error %ld\n", res
);
528 /* overflow both name and data */
532 strcpy( value
, "xxxxxxxxxx" );
533 strcpy( data
, "xxxxxxxxxx" );
534 res
= RegEnumValueA( test_key
, 0, value
, &val_count
, NULL
, &type
, (LPBYTE
)data
, &data_count
);
535 ok( res
== ERROR_MORE_DATA
, "expected ERROR_MORE_DATA, got %ld\n", res
);
536 ok( val_count
== 2, "val_count set to %ld\n", val_count
);
537 /* Chinese, Japanese, and Korean editions of Windows 10 sometimes set data_count to a higher value */
538 ok( data_count
== 7 || broken( data_count
> 7 ), "data_count set to %ld instead of 7\n", data_count
);
539 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
540 ok( !strcmp( value
, "xxxxxxxxxx" ), "value set to '%s'\n", value
);
541 ok( !strcmp( data
, "xxxxxxxxxx" ), "data set to '%s'\n", data
);
547 strcpy( value
, "xxxxxxxxxx" );
548 memset( data
, 'x', sizeof(data
) );
549 data
[sizeof(data
)-1] = '\0';
550 res
= RegEnumValueA( test_key
, 0, value
, &val_count
, NULL
, &type
, (LPBYTE
)data
, &data_count
);
551 ok( res
== ERROR_MORE_DATA
, "expected ERROR_MORE_DATA, got %ld\n", res
);
552 ok( val_count
== 3, "val_count set to %ld\n", val_count
);
553 /* In double-byte and UTF-8 locales Windows 10 may set data_count > 7,
554 * potentially even more than the declared buffer size, in which case the
555 * buffer is not NUL-terminated.
557 ok( data_count
== 7 || broken( data_count
> 7 ), "data_count set to %ld instead of 7\n", data_count
);
558 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
559 /* v5.1.2600.0 (XP Home and Professional) does not touch value or data in
560 * this case. Neither does Windows 10 21H1 in UTF-8 locales.
562 ok( !strcmp( value
, "Te" ) || !strcmp( value
, "xxxxxxxxxx" ),
563 "value set to '%s' instead of 'Te' or 'xxxxxxxxxx'\n", value
);
564 ok( !strcmp( data
, "foobar" ) || !strcmp( data
, "xxxxxxx" ) ||
565 broken( data_count
> 7 && data_count
< 16 &&
566 strspn( data
, "x" ) == data_count
&& data
[data_count
] == 0 ) ||
567 broken( data_count
>= 16 && strspn( data
, "x" ) == sizeof(data
) - 1 ),
568 "data set to '%s' instead of 'foobar' or x's, data_count=%lu\n", data
, data_count
);
570 /* overflow empty name */
574 strcpy( value
, "xxxxxxxxxx" );
575 memset( data
, 'x', sizeof(data
) );
576 data
[sizeof(data
)-1] = '\0';
577 res
= RegEnumValueA( test_key
, 0, value
, &val_count
, NULL
, &type
, (LPBYTE
)data
, &data_count
);
578 ok( res
== ERROR_MORE_DATA
, "expected ERROR_MORE_DATA, got %ld\n", res
);
579 ok( val_count
== 0, "val_count set to %ld\n", val_count
);
580 /* See comment in 'overflow name' section */
581 ok( data_count
== 7 || broken( data_count
> 7 ), "data_count set to %ld instead of 7\n", data_count
);
582 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
583 ok( !strcmp( value
, "xxxxxxxxxx" ), "value set to '%s'\n", value
);
584 /* See comment in 'overflow name' section */
585 ok( !strcmp( data
, "foobar" ) || !strcmp( data
, "xxxxxxx" ) ||
586 broken( data_count
> 7 && data_count
< 16 &&
587 strspn( data
, "x" ) == data_count
&& data
[data_count
] == 0 ) ||
588 broken( data_count
>= 16 && strspn( data
, "x" ) == sizeof(data
) - 1 ),
589 "data set to '%s' instead of 'foobar' or x's, data_count=%lu\n", data
, data_count
);
595 strcpy( value
, "xxxxxxxxxx" );
596 strcpy( data
, "xxxxxxxxxx" );
597 res
= RegEnumValueA( test_key
, 0, value
, &val_count
, NULL
, &type
, (LPBYTE
)data
, &data_count
);
598 ok( res
== ERROR_MORE_DATA
, "expected ERROR_MORE_DATA, got %ld\n", res
);
599 ok( val_count
== 20, "val_count set to %ld\n", val_count
);
600 ok( data_count
== 7, "data_count set to %ld instead of 7\n", data_count
);
601 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
602 ok( !strcmp( value
, "xxxxxxxxxx" ), "value set to '%s'\n", value
);
603 ok( !strcmp( data
, "xxxxxxxxxx" ), "data set to '%s'\n", data
);
609 strcpy( value
, "xxxxxxxxxx" );
610 strcpy( data
, "xxxxxxxxxx" );
611 res
= RegEnumValueA( test_key
, 0, value
, &val_count
, NULL
, &type
, (LPBYTE
)data
, &data_count
);
612 ok( res
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", res
);
613 ok( val_count
== 4, "val_count set to %ld instead of 4\n", val_count
);
614 ok( data_count
== 7, "data_count set to %ld instead of 7\n", data_count
);
615 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
616 ok( !strcmp( value
, "Test" ), "value is '%s' instead of Test\n", value
);
617 ok( !strcmp( data
, "foobar" ), "data is '%s' instead of foobar\n", data
);
619 if (pRegGetValueA
) /* avoid a crash on Windows 2000 */
621 /* no value and no val_count parameter */
624 strcpy( data
, "xxxxxxxxxx" );
625 res
= RegEnumValueA( test_key
, 0, NULL
, NULL
, NULL
, &type
, (BYTE
*)data
, &data_count
);
626 ok( res
== ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %ld\n", res
);
628 /* no value parameter */
632 strcpy( data
, "xxxxxxxxxx" );
633 res
= RegEnumValueA( test_key
, 0, NULL
, &val_count
, NULL
, &type
, (BYTE
*)data
, &data_count
);
634 ok( res
== ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %ld\n", res
);
636 /* no val_count parameter */
639 strcpy( value
, "xxxxxxxxxx" );
640 strcpy( data
, "xxxxxxxxxx" );
641 res
= RegEnumValueA( test_key
, 0, value
, NULL
, NULL
, &type
, (BYTE
*)data
, &data_count
);
642 ok( res
== ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %ld\n", res
);
647 SetLastError(0xdeadbeef);
648 res
= RegSetValueExW( test_key
, L
"Test", 0, REG_SZ
, (const BYTE
*)L
"foobar", 7*sizeof(WCHAR
) );
649 if (res
==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED
)
651 win_skip("RegSetValueExW is not implemented\n");
654 ok( res
== 0, "RegSetValueExW failed error %ld\n", res
);
656 /* overflow both name and data */
660 wcscpy( valueW
, L
"xxxxxxxx" );
661 wcscpy( dataW
, L
"xxxxxxxx" );
662 res
= RegEnumValueW( test_key
, 0, valueW
, &val_count
, NULL
, &type
, (BYTE
*)dataW
, &data_count
);
663 ok( res
== ERROR_MORE_DATA
, "expected ERROR_MORE_DATA, got %ld\n", res
);
664 ok( val_count
== 2, "val_count set to %ld\n", val_count
);
665 ok( data_count
== 7*sizeof(WCHAR
), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count
);
666 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
667 ok( !wcscmp( valueW
, L
"xxxxxxxx" ), "value modified\n" );
668 ok( !wcscmp( dataW
, L
"xxxxxxxx" ), "data modified\n" );
674 wcscpy( valueW
, L
"xxxxxxxx" );
675 wcscpy( dataW
, L
"xxxxxxxx" );
676 res
= RegEnumValueW( test_key
, 0, valueW
, &val_count
, NULL
, &type
, (BYTE
*)dataW
, &data_count
);
677 ok( res
== ERROR_MORE_DATA
, "expected ERROR_MORE_DATA, got %ld\n", res
);
678 ok( val_count
== 3, "val_count set to %ld\n", val_count
);
679 ok( data_count
== 7*sizeof(WCHAR
), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count
);
680 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
681 ok( !wcscmp( valueW
, L
"xxxxxxxx" ), "value modified\n" );
682 ok( !wcscmp( dataW
, L
"xxxxxxxx" ), "data modified\n" );
688 wcscpy( valueW
, L
"xxxxxxxx" );
689 wcscpy( dataW
, L
"xxxxxxxx" );
690 res
= RegEnumValueW( test_key
, 0, valueW
, &val_count
, NULL
, &type
, (BYTE
*)dataW
, &data_count
);
691 ok( res
== ERROR_MORE_DATA
, "expected ERROR_MORE_DATA, got %ld\n", res
);
692 ok( val_count
== 4, "val_count set to %ld instead of 4\n", val_count
);
693 ok( data_count
== 7*sizeof(WCHAR
), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count
);
694 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
695 ok( !wcscmp( valueW
, L
"Test" ), "value is not 'Test'\n" );
696 ok( !wcscmp( dataW
, L
"xxxxxxxx" ), "data modified\n" );
702 wcscpy( valueW
, L
"xxxxxxxx" );
703 wcscpy( dataW
, L
"xxxxxxxx" );
704 res
= RegEnumValueW( test_key
, 0, valueW
, &val_count
, NULL
, &type
, (BYTE
*)dataW
, &data_count
);
705 ok( res
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", res
);
706 ok( val_count
== 4, "val_count set to %ld instead of 4\n", val_count
);
707 ok( data_count
== 7*sizeof(WCHAR
), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count
);
708 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
709 ok( !wcscmp( valueW
, L
"Test" ), "value is not 'Test'\n" );
710 ok( !wcscmp( dataW
, L
"foobar" ), "data is not 'foobar'\n" );
712 if (pRegGetValueA
) /* avoid a crash on Windows 2000 */
714 /* no valueW and no val_count parameter */
717 wcscpy( dataW
, L
"xxxxxxxx" );
718 res
= RegEnumValueW( test_key
, 0, NULL
, NULL
, NULL
, &type
, (BYTE
*)dataW
, &data_count
);
719 ok( res
== ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %ld\n", res
);
721 /* no valueW parameter */
725 wcscpy( dataW
, L
"xxxxxxxx" );
726 res
= RegEnumValueW( test_key
, 0, NULL
, &val_count
, NULL
, &type
, (BYTE
*)dataW
, &data_count
);
727 ok( res
== ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %ld\n", res
);
729 /* no val_count parameter */
732 wcscpy( valueW
, L
"xxxxxxxx" );
733 wcscpy( dataW
, L
"xxxxxxxx" );
734 res
= RegEnumValueW( test_key
, 0, valueW
, NULL
, NULL
, &type
, (BYTE
*)dataW
, &data_count
);
735 ok( res
== ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %ld\n", res
);
739 RegDeleteKeyA(test_key
, "");
740 RegCloseKey(test_key
);
743 static void test_query_value_ex(void)
745 DWORD ret
, size
, type
;
748 size
= sizeof(buffer
);
749 ret
= RegQueryValueExA(hkey_main
, "TP1_SZ", NULL
, &type
, NULL
, &size
);
750 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
751 ok(size
== strlen(sTestpath1
) + 1, "(%ld,%ld)\n", (DWORD
)strlen(sTestpath1
) + 1, size
);
752 ok(type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
756 ret
= RegQueryValueExA(HKEY_CLASSES_ROOT
, "Nonexistent Value", NULL
, &type
, NULL
, &size
);
757 ok(ret
== ERROR_FILE_NOT_FOUND
, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret
);
758 ok(size
== 0, "size should have been set to 0 instead of %ld\n", size
);
760 size
= sizeof(buffer
);
761 ret
= RegQueryValueExA(HKEY_CLASSES_ROOT
, "Nonexistent Value", NULL
, &type
, buffer
, &size
);
762 ok(ret
== ERROR_FILE_NOT_FOUND
, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret
);
763 ok(size
== sizeof(buffer
), "size shouldn't have been changed to %ld\n", size
);
766 ret
= RegQueryValueExA(hkey_main
, "BIN32", NULL
, &size
, buffer
, &size
);
767 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
770 static void test_get_value(void)
777 CHAR expanded
[] = "bar\\subdir1";
778 CHAR expanded2
[] = "ImARatherLongButIndeedNeededString\\subdir1";
782 win_skip("RegGetValue not available on this platform\n");
786 /* Invalid parameter */
787 ret
= pRegGetValueA(hkey_main
, NULL
, "DWORD", RRF_RT_REG_DWORD
, &type
, &dw
, NULL
);
788 ok(ret
== ERROR_INVALID_PARAMETER
, "ret=%ld\n", ret
);
790 /* Query REG_DWORD using RRF_RT_REG_DWORD (ok) */
791 size
= type
= dw
= 0xdeadbeef;
792 ret
= pRegGetValueA(hkey_main
, NULL
, "DWORD", RRF_RT_REG_DWORD
, &type
, &dw
, &size
);
793 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
794 ok(size
== 4, "size=%ld\n", size
);
795 ok(type
== REG_DWORD
, "type=%ld\n", type
);
796 ok(dw
== 0x12345678, "dw=%ld\n", dw
);
798 /* Check RRF_SUBKEY_WOW64*KEY validation on a case without a subkey */
799 ret
= pRegGetValueA(hkey_main
, NULL
, "DWORD", RRF_RT_REG_DWORD
| RRF_SUBKEY_WOW6464KEY
| RRF_SUBKEY_WOW6432KEY
, NULL
, NULL
, NULL
);
800 ok(ret
== ERROR_INVALID_PARAMETER
|| broken(ret
== ERROR_SUCCESS
), /* Before Win10 */
802 ret
= pRegGetValueA(hkey_main
, NULL
, "DWORD", RRF_RT_REG_DWORD
| RRF_SUBKEY_WOW6464KEY
, NULL
, NULL
, NULL
);
803 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
804 ret
= pRegGetValueA(hkey_main
, NULL
, "DWORD", RRF_RT_REG_DWORD
| RRF_SUBKEY_WOW6432KEY
, NULL
, NULL
, NULL
);
805 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
807 /* Query by subkey-name */
808 ret
= pRegGetValueA(HKEY_CURRENT_USER
, "Software\\Wine\\Test", "DWORD", RRF_RT_REG_DWORD
, NULL
, NULL
, NULL
);
809 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
811 /* Check RRF_SUBKEY_WOW64*KEY validation on a case with a subkey */
812 ret
= pRegGetValueA(HKEY_CURRENT_USER
, "Software\\Wine\\Test", "DWORD", RRF_RT_REG_DWORD
| RRF_SUBKEY_WOW6464KEY
| RRF_SUBKEY_WOW6432KEY
, NULL
, NULL
, NULL
);
813 ok(ret
== ERROR_INVALID_PARAMETER
|| broken(ret
== ERROR_SUCCESS
), /* Before Win10 */
815 ret
= pRegGetValueA(HKEY_CURRENT_USER
, "Software\\Wine\\Test", "DWORD", RRF_RT_REG_DWORD
| RRF_SUBKEY_WOW6464KEY
, NULL
, NULL
, NULL
);
816 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
817 ret
= pRegGetValueA(HKEY_CURRENT_USER
, "Software\\Wine\\Test", "DWORD", RRF_RT_REG_DWORD
| RRF_SUBKEY_WOW6432KEY
, NULL
, NULL
, NULL
);
818 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
820 /* Query REG_DWORD using RRF_RT_REG_BINARY (restricted) */
821 size
= type
= dw
= 0xdeadbeef;
822 ret
= pRegGetValueA(hkey_main
, NULL
, "DWORD", RRF_RT_REG_BINARY
, &type
, &dw
, &size
);
823 ok(ret
== ERROR_UNSUPPORTED_TYPE
, "ret=%ld\n", ret
);
824 /* Although the function failed all values are retrieved */
825 ok(size
== 4, "size=%ld\n", size
);
826 ok(type
== REG_DWORD
, "type=%ld\n", type
);
827 ok(dw
== 0x12345678, "dw=%ld\n", dw
);
829 /* Test RRF_ZEROONFAILURE */
830 type
= dw
= 0xdeadbeef; size
= 4;
831 ret
= pRegGetValueA(hkey_main
, NULL
, "DWORD", RRF_RT_REG_SZ
|RRF_ZEROONFAILURE
, &type
, &dw
, &size
);
832 ok(ret
== ERROR_UNSUPPORTED_TYPE
, "ret=%ld\n", ret
);
833 /* Again all values are retrieved ... */
834 ok(size
== 4, "size=%ld\n", size
);
835 ok(type
== REG_DWORD
, "type=%ld\n", type
);
836 /* ... except the buffer, which is zeroed out */
837 ok(dw
== 0, "dw=%ld\n", dw
);
839 /* Test RRF_ZEROONFAILURE with a NULL buffer... */
840 type
= size
= 0xbadbeef;
841 ret
= pRegGetValueA(hkey_main
, NULL
, "DWORD", RRF_RT_REG_SZ
|RRF_ZEROONFAILURE
, &type
, NULL
, &size
);
842 ok(ret
== ERROR_UNSUPPORTED_TYPE
, "ret=%ld\n", ret
);
843 ok(size
== 4, "size=%ld\n", size
);
844 ok(type
== REG_DWORD
, "type=%ld\n", type
);
846 /* Query REG_DWORD using RRF_RT_DWORD (ok) */
847 size
= type
= dw
= 0xdeadbeef;
848 ret
= pRegGetValueA(hkey_main
, NULL
, "DWORD", RRF_RT_DWORD
, &type
, &dw
, &size
);
849 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
850 ok(size
== 4, "size=%ld\n", size
);
851 ok(type
== REG_DWORD
, "type=%ld\n", type
);
852 ok(dw
== 0x12345678, "dw=%ld\n", dw
);
854 /* Query 32-bit REG_BINARY using RRF_RT_DWORD (ok) */
855 size
= type
= dw
= 0xdeadbeef;
856 ret
= pRegGetValueA(hkey_main
, NULL
, "BIN32", RRF_RT_DWORD
, &type
, &dw
, &size
);
857 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
858 ok(size
== 4, "size=%ld\n", size
);
859 ok(type
== REG_BINARY
, "type=%ld\n", type
);
860 ok(dw
== 0x12345678, "dw=%ld\n", dw
);
862 /* Query 64-bit REG_BINARY using RRF_RT_DWORD (type mismatch) */
863 qw
[0] = qw
[1] = size
= type
= 0xdeadbeef;
864 ret
= pRegGetValueA(hkey_main
, NULL
, "BIN64", RRF_RT_DWORD
, &type
, qw
, &size
);
865 ok(ret
== ERROR_DATATYPE_MISMATCH
, "ret=%ld\n", ret
);
866 ok(size
== 8, "size=%ld\n", size
);
867 ok(type
== REG_BINARY
, "type=%ld\n", type
);
868 ok(qw
[0] == 0x12345678 &&
869 qw
[1] == 0x87654321, "qw={%ld,%ld}\n", qw
[0], qw
[1]);
871 /* Query 64-bit REG_BINARY using 32-bit buffer (buffer too small) */
872 type
= dw
= 0xdeadbeef; size
= 4;
873 ret
= pRegGetValueA(hkey_main
, NULL
, "BIN64", RRF_RT_REG_BINARY
, &type
, &dw
, &size
);
874 ok(ret
== ERROR_MORE_DATA
, "ret=%ld\n", ret
);
875 ok(dw
== 0xdeadbeef, "dw=%ld\n", dw
);
876 ok(size
== 8, "size=%ld\n", size
);
878 /* Query 64-bit REG_BINARY using RRF_RT_QWORD (ok) */
879 qw
[0] = qw
[1] = size
= type
= 0xdeadbeef;
880 ret
= pRegGetValueA(hkey_main
, NULL
, "BIN64", RRF_RT_QWORD
, &type
, qw
, &size
);
881 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
882 ok(size
== 8, "size=%ld\n", size
);
883 ok(type
== REG_BINARY
, "type=%ld\n", type
);
884 ok(qw
[0] == 0x12345678 &&
885 qw
[1] == 0x87654321, "qw={%ld,%ld}\n", qw
[0], qw
[1]);
887 /* Query REG_SZ using RRF_RT_REG_SZ (ok) */
888 buf
[0] = 0; type
= 0xdeadbeef; size
= sizeof(buf
);
889 ret
= pRegGetValueA(hkey_main
, NULL
, "TP1_SZ", RRF_RT_REG_SZ
, &type
, buf
, &size
);
890 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
891 ok(size
== strlen(sTestpath1
)+1, "strlen(sTestpath1)=%d size=%ld\n", lstrlenA(sTestpath1
), size
);
892 ok(type
== REG_SZ
, "type=%ld\n", type
);
893 ok(!strcmp(sTestpath1
, buf
), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1
, buf
);
895 /* Query REG_SZ using RRF_RT_REG_SZ and no buffer (ok) */
896 type
= 0xdeadbeef; size
= 0;
897 ret
= pRegGetValueA(hkey_main
, NULL
, "TP1_SZ", RRF_RT_REG_SZ
, &type
, NULL
, &size
);
898 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
899 /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
900 ok(size
== strlen(sTestpath1
)+1 || broken(size
== strlen(sTestpath1
)+2),
901 "strlen(sTestpath1)=%d size=%ld\n", lstrlenA(sTestpath1
), size
);
902 ok(type
== REG_SZ
, "type=%ld\n", type
);
904 /* Query REG_SZ using RRF_RT_REG_SZ on a zero-byte value (ok) */
905 strcpy(buf
, sTestpath1
);
908 ret
= pRegGetValueA(hkey_main
, NULL
, "TP1_ZB_SZ", RRF_RT_REG_SZ
, &type
, buf
, &size
);
909 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
910 /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
912 size
== 1, /* win2k3 */
914 ok(type
== REG_SZ
, "type=%ld\n", type
);
915 ok(!strcmp(sTestpath1
, buf
) ||
917 "Expected \"%s\" or \"\", got \"%s\"\n", sTestpath1
, buf
);
919 /* Query REG_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (ok) */
920 buf
[0] = 0; type
= 0xdeadbeef; size
= sizeof(buf
);
921 ret
= pRegGetValueA(hkey_main
, NULL
, "TP1_SZ", RRF_RT_REG_SZ
|RRF_NOEXPAND
, &type
, buf
, &size
);
922 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
923 ok(size
== strlen(sTestpath1
)+1, "strlen(sTestpath1)=%d size=%ld\n", lstrlenA(sTestpath1
), size
);
924 ok(type
== REG_SZ
, "type=%ld\n", type
);
925 ok(!strcmp(sTestpath1
, buf
), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1
, buf
);
927 /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ and no buffer (ok, expands) */
929 ret
= pRegGetValueA(hkey_main
, NULL
, "TP2_EXP_SZ", RRF_RT_REG_SZ
, NULL
, NULL
, &size
);
930 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
931 ok((size
== strlen(expanded2
)+1) || /* win2k3 SP1 */
932 (size
== strlen(expanded2
)+2) || /* win2k3 SP2 */
933 (size
== strlen(sTestpath2
)+1),
934 "strlen(expanded2)=%d, strlen(sTestpath2)=%d, size=%ld\n", lstrlenA(expanded2
), lstrlenA(sTestpath2
), size
);
936 /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ (ok, expands) */
937 buf
[0] = 0; type
= 0xdeadbeef; size
= sizeof(buf
);
938 ret
= pRegGetValueA(hkey_main
, NULL
, "TP1_EXP_SZ", RRF_RT_REG_SZ
, &type
, buf
, &size
);
939 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
940 /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath1 length + 1 here. */
941 ok(size
== strlen(expanded
)+1 || broken(size
== strlen(sTestpath1
)+1),
942 "strlen(expanded)=%d, strlen(sTestpath1)=%d, size=%ld\n", lstrlenA(expanded
), lstrlenA(sTestpath1
), size
);
943 ok(type
== REG_SZ
, "type=%ld\n", type
);
944 ok(!strcmp(expanded
, buf
), "expanded=\"%s\" buf=\"%s\"\n", expanded
, buf
);
946 /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ (ok, expands a lot) */
947 buf
[0] = 0; type
= 0xdeadbeef; size
= sizeof(buf
);
948 ret
= pRegGetValueA(hkey_main
, NULL
, "TP2_EXP_SZ", RRF_RT_REG_SZ
, &type
, buf
, &size
);
949 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
950 /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath2 length + 1 here. */
951 ok(size
== strlen(expanded2
)+1 || broken(size
== strlen(sTestpath2
)+1),
952 "strlen(expanded2)=%d, strlen(sTestpath1)=%d, size=%ld\n", lstrlenA(expanded2
), lstrlenA(sTestpath2
), size
);
953 ok(type
== REG_SZ
, "type=%ld\n", type
);
954 ok(!strcmp(expanded2
, buf
), "expanded2=\"%s\" buf=\"%s\"\n", expanded2
, buf
);
956 /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND (ok, doesn't expand) */
957 buf
[0] = 0; type
= 0xdeadbeef; size
= sizeof(buf
);
958 ret
= pRegGetValueA(hkey_main
, NULL
, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ
|RRF_NOEXPAND
, &type
, buf
, &size
);
959 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
960 ok(size
== strlen(sTestpath1
)+1, "strlen(sTestpath1)=%d size=%ld\n", lstrlenA(sTestpath1
), size
);
961 ok(type
== REG_EXPAND_SZ
, "type=%ld\n", type
);
962 ok(!strcmp(sTestpath1
, buf
), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1
, buf
);
964 /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND and no buffer (ok, doesn't expand) */
966 ret
= pRegGetValueA(hkey_main
, NULL
, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ
|RRF_NOEXPAND
, NULL
, NULL
, &size
);
967 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
968 /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
969 ok(size
== strlen(sTestpath1
)+1 || broken(size
== strlen(sTestpath1
)+2),
970 "strlen(sTestpath1)=%d size=%ld\n", lstrlenA(sTestpath1
), size
);
972 /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (type mismatch) */
973 ret
= pRegGetValueA(hkey_main
, NULL
, "TP1_EXP_SZ", RRF_RT_REG_SZ
|RRF_NOEXPAND
, NULL
, NULL
, NULL
);
974 ok(ret
== ERROR_UNSUPPORTED_TYPE
, "ret=%ld\n", ret
);
976 /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ (not allowed without RRF_NOEXPAND) */
977 ret
= pRegGetValueA(hkey_main
, NULL
, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ
, NULL
, NULL
, NULL
);
978 /* before win8: ERROR_INVALID_PARAMETER, win8: ERROR_UNSUPPORTED_TYPE */
979 ok(ret
== ERROR_INVALID_PARAMETER
|| ret
== ERROR_UNSUPPORTED_TYPE
, "ret=%ld\n", ret
);
981 /* Query REG_EXPAND_SZ using RRF_RT_ANY */
982 buf
[0] = 0; type
= 0xdeadbeef; size
= sizeof(buf
);
983 ret
= pRegGetValueA(hkey_main
, NULL
, "TP1_EXP_SZ", RRF_RT_ANY
, &type
, buf
, &size
);
984 ok(ret
== ERROR_SUCCESS
, "ret=%ld\n", ret
);
985 /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath1 length + 1 here. */
986 ok(size
== strlen(expanded
)+1 || broken(size
== strlen(sTestpath1
)+1),
987 "strlen(expanded)=%d, strlen(sTestpath1)=%d, size=%ld\n", lstrlenA(expanded
), lstrlenA(sTestpath1
), size
);
988 ok(type
== REG_SZ
, "type=%ld\n", type
);
989 ok(!strcmp(expanded
, buf
), "expanded=\"%s\" buf=\"%s\"\n", expanded
, buf
);
992 static void test_reg_open_key(void)
995 HKEY hkResult
= NULL
;
996 HKEY hkPreserve
= NULL
;
997 HKEY hkRoot64
= NULL
;
998 HKEY hkRoot32
= NULL
;
1000 SID_IDENTIFIER_AUTHORITY sid_authority
= {SECURITY_WORLD_SID_AUTHORITY
};
1002 EXPLICIT_ACCESSA access
;
1004 SECURITY_DESCRIPTOR
*sd
;
1006 /* successful open */
1007 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Test", &hkResult
);
1008 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1009 ok(hkResult
!= NULL
, "expected hkResult != NULL\n");
1010 hkPreserve
= hkResult
;
1012 /* open same key twice */
1013 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Test", &hkResult
);
1014 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1015 ok(hkResult
!= hkPreserve
, "expected hkResult != hkPreserve\n");
1016 ok(hkResult
!= NULL
, "hkResult != NULL\n");
1017 RegCloseKey(hkResult
);
1019 /* trailing slashes */
1020 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Test\\\\", &hkResult
);
1021 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1022 RegCloseKey(hkResult
);
1024 /* open nonexistent key
1025 * check that hkResult is set to NULL
1027 hkResult
= hkPreserve
;
1028 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Nonexistent", &hkResult
);
1029 ok(ret
== ERROR_FILE_NOT_FOUND
, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret
);
1030 ok(hkResult
== NULL
, "expected hkResult == NULL\n");
1032 /* open the same nonexistent key again to make sure the key wasn't created */
1033 hkResult
= hkPreserve
;
1034 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Nonexistent", &hkResult
);
1035 ok(ret
== ERROR_FILE_NOT_FOUND
, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret
);
1036 ok(hkResult
== NULL
, "expected hkResult == NULL\n");
1038 /* send in NULL lpSubKey
1039 * check that hkResult receives the value of hKey
1041 hkResult
= hkPreserve
;
1042 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, NULL
, &hkResult
);
1043 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1044 ok(hkResult
== HKEY_CURRENT_USER
, "expected hkResult == HKEY_CURRENT_USER\n");
1046 /* send empty-string in lpSubKey */
1047 hkResult
= hkPreserve
;
1048 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, "", &hkResult
);
1049 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1050 ok(hkResult
== HKEY_CURRENT_USER
, "expected hkResult == HKEY_CURRENT_USER\n");
1052 /* send in NULL lpSubKey and NULL hKey
1053 * hkResult is set to NULL
1055 hkResult
= hkPreserve
;
1056 ret
= RegOpenKeyA(NULL
, NULL
, &hkResult
);
1057 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1058 ok(hkResult
== NULL
, "expected hkResult == NULL\n");
1060 /* only send NULL hKey
1061 * the value of hkResult remains unchanged
1063 hkResult
= hkPreserve
;
1064 ret
= RegOpenKeyA(NULL
, "Software\\Wine\\Test", &hkResult
);
1065 ok(ret
== ERROR_INVALID_HANDLE
|| ret
== ERROR_BADKEY
, /* Windows 95 returns BADKEY */
1066 "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %ld\n", ret
);
1067 ok(hkResult
== hkPreserve
, "expected hkResult == hkPreserve\n");
1069 /* send in NULL hkResult */
1070 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Test", NULL
);
1071 ok(ret
== ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %ld\n", ret
);
1073 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, NULL
, NULL
);
1074 ok(ret
== ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %ld\n", ret
);
1076 ret
= RegOpenKeyA(NULL
, NULL
, NULL
);
1077 ok(ret
== ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %ld\n", ret
);
1079 /* beginning backslash character */
1080 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, "\\Software\\Wine\\Test", &hkResult
);
1081 ok(ret
== ERROR_BAD_PATHNAME
|| /* NT/2k/XP */
1082 broken(ret
== ERROR_SUCCESS
), /* wow64 */
1083 "expected ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %ld\n", ret
);
1084 if (!ret
) RegCloseKey(hkResult
);
1087 ret
= RegOpenKeyExA(HKEY_CLASSES_ROOT
, "\\clsid", 0, KEY_QUERY_VALUE
, &hkResult
);
1088 ok(ret
== ERROR_SUCCESS
|| /* 2k/XP */
1089 ret
== ERROR_BAD_PATHNAME
, /* NT */
1090 "expected ERROR_SUCCESS, ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %ld\n", ret
);
1091 RegCloseKey(hkResult
);
1093 /* NULL or empty subkey of special root */
1095 ret
= RegOpenKeyExA(HKEY_CLASSES_ROOT
, NULL
, 0, KEY_QUERY_VALUE
, &hkResult
);
1096 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1097 ok(hkResult
== HKEY_CLASSES_ROOT
, "expected hkResult == HKEY_CLASSES_ROOT\n");
1100 ret
= RegOpenKeyExA(HKEY_CLASSES_ROOT
, "", 0, KEY_QUERY_VALUE
, &hkResult
);
1101 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1102 ok(hkResult
== HKEY_CLASSES_ROOT
, "expected hkResult == HKEY_CLASSES_ROOT\n");
1105 ret
= RegOpenKeyExA(HKEY_CLASSES_ROOT
, "\\", 0, KEY_QUERY_VALUE
, &hkResult
);
1106 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1107 ok(hkResult
!= HKEY_CLASSES_ROOT
, "expected hkResult to be a new key\n");
1108 ok(!RegCloseKey(hkResult
), "got invalid hkey\n");
1110 /* empty subkey of existing handle */
1111 hkResult
= hkPreserve
;
1112 ret
= RegOpenKeyExA(hkPreserve
, "", 0, KEY_QUERY_VALUE
, &hkResult
);
1113 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1114 ok(hkResult
!= hkPreserve
, "expected hkResult != hkPreserve\n");
1115 ok(!RegCloseKey(hkResult
), "got invalid hkey\n");
1117 /* NULL subkey of existing handle */
1118 hkResult
= hkPreserve
;
1119 ret
= RegOpenKeyExA(hkPreserve
, NULL
, 0, KEY_QUERY_VALUE
, &hkResult
);
1120 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1121 ok(hkResult
!= hkPreserve
, "expected hkResult != hkPreserve\n");
1122 ok(!RegCloseKey(hkResult
), "got invalid hkey\n");
1124 /* empty subkey of NULL */
1125 hkResult
= hkPreserve
;
1126 ret
= RegOpenKeyExW(NULL
, L
"", 0, KEY_QUERY_VALUE
, &hkResult
);
1127 ok(ret
== ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %ld\n", ret
);
1128 ok(hkResult
== NULL
|| broken(hkResult
== hkPreserve
/* Windows XP */), "expected hkResult == NULL\n");
1130 hkResult
= hkPreserve
;
1131 ret
= RegOpenKeyExA(NULL
, "", 0, KEY_QUERY_VALUE
, &hkResult
);
1132 ok(ret
== ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %ld\n", ret
);
1133 ok(hkResult
== hkPreserve
, "expected hkResult == hkPreserve\n");
1135 RegCloseKey(hkPreserve
);
1139 ret
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
, "Software", 0, KEY_READ
|KEY_WOW64_32KEY
, &hkResult
);
1140 ok((ret
== ERROR_SUCCESS
&& hkResult
!= NULL
) || broken(ret
== ERROR_ACCESS_DENIED
/* NT4, win2k */),
1141 "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%lu)\n", ret
);
1142 RegCloseKey(hkResult
);
1145 ret
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
, "Software", 0, KEY_READ
|KEY_WOW64_64KEY
, &hkResult
);
1146 ok((ret
== ERROR_SUCCESS
&& hkResult
!= NULL
) || broken(ret
== ERROR_ACCESS_DENIED
/* NT4, win2k */),
1147 "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%lu)\n", ret
);
1148 RegCloseKey(hkResult
);
1150 /* check special HKEYs on 64bit
1151 * only the lower 4 bytes of the supplied key are used
1155 /* HKEY_CURRENT_USER */
1156 ret
= RegOpenKeyA(UlongToHandle(HandleToUlong(HKEY_CURRENT_USER
)), "Software", &hkResult
);
1157 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1158 ok(hkResult
!= NULL
, "expected hkResult != NULL\n");
1159 RegCloseKey(hkResult
);
1161 ret
= RegOpenKeyA((HKEY
)(HandleToUlong(HKEY_CURRENT_USER
) | (ULONG64
)1 << 32), "Software", &hkResult
);
1162 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1163 ok(hkResult
!= NULL
, "expected hkResult != NULL\n");
1164 RegCloseKey(hkResult
);
1166 ret
= RegOpenKeyA((HKEY
)(HandleToUlong(HKEY_CURRENT_USER
) | (ULONG64
)0xdeadbeef << 32), "Software", &hkResult
);
1167 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1168 ok(hkResult
!= NULL
, "expected hkResult != NULL\n");
1169 RegCloseKey(hkResult
);
1171 ret
= RegOpenKeyA((HKEY
)(HandleToUlong(HKEY_CURRENT_USER
) | (ULONG64
)0xffffffff << 32), "Software", &hkResult
);
1172 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1173 ok(hkResult
!= NULL
, "expected hkResult != NULL\n");
1174 RegCloseKey(hkResult
);
1176 /* HKEY_LOCAL_MACHINE */
1177 ret
= RegOpenKeyA((HKEY
)(HandleToUlong(HKEY_LOCAL_MACHINE
) | (ULONG64
)0xdeadbeef << 32), "Software", &hkResult
);
1178 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1179 ok(hkResult
!= NULL
, "expected hkResult != NULL\n");
1180 RegCloseKey(hkResult
);
1183 /* Try using WOW64 flags when opening a key with a DACL set to verify that
1184 * the registry access check is performed correctly. Redirection isn't
1185 * being tested, so the tests don't care about whether the process is
1186 * running under WOW64. */
1187 if (!pIsWow64Process
)
1189 win_skip("WOW64 flags are not recognized\n");
1193 ret
= RegCreateKeyExA(HKEY_LOCAL_MACHINE
, "Software\\Wine", 0, NULL
, 0,
1194 KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, NULL
, &hkRoot32
, NULL
);
1196 ok(ret
== ERROR_ACCESS_DENIED
&& hkRoot32
== NULL
,
1197 "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%lu)\n", ret
);
1199 ok(ret
== ERROR_SUCCESS
&& hkRoot32
!= NULL
,
1200 "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%lu)\n", ret
);
1202 ret
= RegCreateKeyExA(HKEY_LOCAL_MACHINE
, "Software\\Wine", 0, NULL
, 0,
1203 KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, NULL
, &hkRoot64
, NULL
);
1205 ok(ret
== ERROR_ACCESS_DENIED
&& hkRoot64
== NULL
,
1206 "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%lu)\n", ret
);
1208 ok(ret
== ERROR_SUCCESS
&& hkRoot64
!= NULL
,
1209 "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%lu)\n", ret
);
1211 bRet
= AllocateAndInitializeSid(&sid_authority
, 1, SECURITY_WORLD_RID
,
1212 0, 0, 0, 0, 0, 0, 0, &world_sid
);
1214 "Expected AllocateAndInitializeSid to return TRUE, got %d, last error %lu\n", bRet
, GetLastError());
1216 access
.grfAccessPermissions
= GENERIC_ALL
| STANDARD_RIGHTS_ALL
;
1217 access
.grfAccessMode
= SET_ACCESS
;
1218 access
.grfInheritance
= SUB_CONTAINERS_AND_OBJECTS_INHERIT
;
1219 access
.Trustee
.pMultipleTrustee
= NULL
;
1220 access
.Trustee
.MultipleTrusteeOperation
= NO_MULTIPLE_TRUSTEE
;
1221 access
.Trustee
.TrusteeForm
= TRUSTEE_IS_SID
;
1222 access
.Trustee
.TrusteeType
= TRUSTEE_IS_WELL_KNOWN_GROUP
;
1223 access
.Trustee
.ptstrName
= (char *)world_sid
;
1225 ret
= SetEntriesInAclA(1, &access
, NULL
, &key_acl
);
1226 ok(ret
== ERROR_SUCCESS
,
1227 "Expected SetEntriesInAclA to return ERROR_SUCCESS, got %lu, last error %lu\n", ret
, GetLastError());
1229 sd
= HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH
);
1230 bRet
= InitializeSecurityDescriptor(sd
, SECURITY_DESCRIPTOR_REVISION
);
1232 "Expected InitializeSecurityDescriptor to return TRUE, got %d, last error %lu\n", bRet
, GetLastError());
1234 bRet
= SetSecurityDescriptorDacl(sd
, TRUE
, key_acl
, FALSE
);
1236 "Expected SetSecurityDescriptorDacl to return TRUE, got %d, last error %lu\n", bRet
, GetLastError());
1240 skip("not enough privileges to modify HKLM\n");
1246 error
= RegSetKeySecurity(hkRoot64
, DACL_SECURITY_INFORMATION
, sd
);
1247 ok(error
== ERROR_SUCCESS
,
1248 "Expected RegSetKeySecurity to return success, got error %lu\n", error
);
1250 error
= RegSetKeySecurity(hkRoot32
, DACL_SECURITY_INFORMATION
, sd
);
1251 ok(error
== ERROR_SUCCESS
,
1252 "Expected RegSetKeySecurity to return success, got error %lu\n", error
);
1255 ret
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
, "Software\\Wine", 0, KEY_WOW64_64KEY
| KEY_READ
, &hkResult
);
1256 ok(ret
== ERROR_SUCCESS
&& hkResult
!= NULL
,
1257 "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%lu)\n", ret
);
1258 RegCloseKey(hkResult
);
1261 ret
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
, "Software\\Wine", 0, KEY_WOW64_32KEY
| KEY_READ
, &hkResult
);
1262 ok(ret
== ERROR_SUCCESS
&& hkResult
!= NULL
,
1263 "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%lu)\n", ret
);
1264 RegCloseKey(hkResult
);
1267 HeapFree(GetProcessHeap(), 0, sd
);
1270 RegDeleteKeyA(hkRoot64
, "");
1271 RegCloseKey(hkRoot64
);
1272 RegDeleteKeyA(hkRoot32
, "");
1273 RegCloseKey(hkRoot32
);
1276 static void test_reg_create_key(void)
1280 HKEY hkRoot64
= NULL
;
1281 HKEY hkRoot32
= NULL
;
1284 SID_IDENTIFIER_AUTHORITY sid_authority
= {SECURITY_WORLD_SID_AUTHORITY
};
1286 EXPLICIT_ACCESSA access
;
1288 SECURITY_DESCRIPTOR
*sd
;
1290 ret
= RegCreateKeyExA(hkey_main
, "Subkey1", 0, NULL
, 0, KEY_NOTIFY
, NULL
, &hkey1
, NULL
);
1291 ok(!ret
, "RegCreateKeyExA failed with error %ld\n", ret
);
1292 /* should succeed: all versions of Windows ignore the access rights
1293 * to the parent handle */
1294 ret
= RegCreateKeyExA(hkey1
, "Subkey2", 0, NULL
, 0, KEY_SET_VALUE
, NULL
, &hkey2
, NULL
);
1295 ok(!ret
, "RegCreateKeyExA failed with error %ld\n", ret
);
1298 RegDeleteKeyA(hkey2
, "");
1299 RegDeleteKeyA(hkey1
, "");
1303 /* test creation of volatile keys */
1304 ret
= RegCreateKeyExA(hkey_main
, "Volatile", 0, NULL
, REG_OPTION_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hkey1
, NULL
);
1305 ok(!ret
, "RegCreateKeyExA failed with error %ld\n", ret
);
1306 ret
= RegCreateKeyExA(hkey1
, "Subkey2", 0, NULL
, 0, KEY_ALL_ACCESS
, NULL
, &hkey2
, NULL
);
1307 ok(ret
== ERROR_CHILD_MUST_BE_VOLATILE
, "RegCreateKeyExA failed with error %ld\n", ret
);
1308 if (!ret
) RegCloseKey( hkey2
);
1309 ret
= RegCreateKeyExA(hkey1
, "Subkey2", 0, NULL
, REG_OPTION_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hkey2
, NULL
);
1310 ok(!ret
, "RegCreateKeyExA failed with error %ld\n", ret
);
1312 /* should succeed if the key already exists */
1313 ret
= RegCreateKeyExA(hkey1
, "Subkey2", 0, NULL
, 0, KEY_ALL_ACCESS
, NULL
, &hkey2
, NULL
);
1314 ok(!ret
, "RegCreateKeyExA failed with error %ld\n", ret
);
1317 RegDeleteKeyA(hkey2
, "");
1318 RegDeleteKeyA(hkey1
, "");
1322 /* beginning backslash character */
1323 ret
= RegCreateKeyExA(hkey_main
, "\\Subkey3", 0, NULL
, 0, KEY_NOTIFY
, NULL
, &hkey1
, NULL
);
1324 ok(ret
== ERROR_BAD_PATHNAME
, "expected ERROR_BAD_PATHNAME, got %ld\n", ret
);
1326 /* trailing backslash characters */
1327 ret
= RegCreateKeyExA(hkey_main
, "Subkey4\\\\", 0, NULL
, 0, KEY_NOTIFY
, NULL
, &hkey1
, NULL
);
1328 ok(ret
== ERROR_SUCCESS
, "RegCreateKeyExA failed with error %ld\n", ret
);
1329 RegDeleteKeyA(hkey1
, "");
1332 /* WOW64 flags - open an existing key */
1334 ret
= RegCreateKeyExA(HKEY_LOCAL_MACHINE
, "Software", 0, NULL
, 0, KEY_READ
|KEY_WOW64_32KEY
, NULL
, &hkey1
, NULL
);
1335 ok(ret
== ERROR_SUCCESS
&& hkey1
!= NULL
,
1336 "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%lu)\n", ret
);
1340 ret
= RegCreateKeyExA(HKEY_LOCAL_MACHINE
, "Software", 0, NULL
, 0, KEY_READ
|KEY_WOW64_64KEY
, NULL
, &hkey1
, NULL
);
1341 ok(ret
== ERROR_SUCCESS
&& hkey1
!= NULL
,
1342 "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%lu)\n", ret
);
1345 /* Try using WOW64 flags when opening a key with a DACL set to verify that
1346 * the registry access check is performed correctly. Redirection isn't
1347 * being tested, so the tests don't care about whether the process is
1348 * running under WOW64. */
1349 if (!pIsWow64Process
)
1351 win_skip("WOW64 flags are not recognized\n");
1355 ret
= RegCreateKeyExA(HKEY_LOCAL_MACHINE
, "Software\\Wine", 0, NULL
, 0,
1356 KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, NULL
, &hkRoot32
, NULL
);
1358 ok(ret
== ERROR_ACCESS_DENIED
&& hkRoot32
== NULL
,
1359 "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%ld)\n", ret
);
1361 ok(ret
== ERROR_SUCCESS
&& hkRoot32
!= NULL
,
1362 "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%ld)\n", ret
);
1364 ret
= RegCreateKeyExA(HKEY_LOCAL_MACHINE
, "Software\\Wine", 0, NULL
, 0,
1365 KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, NULL
, &hkRoot64
, NULL
);
1367 ok(ret
== ERROR_ACCESS_DENIED
&& hkRoot64
== NULL
,
1368 "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%ld)\n", ret
);
1370 ok(ret
== ERROR_SUCCESS
&& hkRoot64
!= NULL
,
1371 "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%ld)\n", ret
);
1373 bRet
= AllocateAndInitializeSid(&sid_authority
, 1, SECURITY_WORLD_RID
,
1374 0, 0, 0, 0, 0, 0, 0, &world_sid
);
1376 "Expected AllocateAndInitializeSid to return TRUE, got %d, last error %lu\n", bRet
, GetLastError());
1378 access
.grfAccessPermissions
= GENERIC_ALL
| STANDARD_RIGHTS_ALL
;
1379 access
.grfAccessMode
= SET_ACCESS
;
1380 access
.grfInheritance
= SUB_CONTAINERS_AND_OBJECTS_INHERIT
;
1381 access
.Trustee
.pMultipleTrustee
= NULL
;
1382 access
.Trustee
.MultipleTrusteeOperation
= NO_MULTIPLE_TRUSTEE
;
1383 access
.Trustee
.TrusteeForm
= TRUSTEE_IS_SID
;
1384 access
.Trustee
.TrusteeType
= TRUSTEE_IS_WELL_KNOWN_GROUP
;
1385 access
.Trustee
.ptstrName
= (char *)world_sid
;
1387 dwRet
= SetEntriesInAclA(1, &access
, NULL
, &key_acl
);
1388 ok(dwRet
== ERROR_SUCCESS
,
1389 "Expected SetEntriesInAclA to return ERROR_SUCCESS, got %lu, last error %lu\n", dwRet
, GetLastError());
1391 sd
= HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH
);
1392 bRet
= InitializeSecurityDescriptor(sd
, SECURITY_DESCRIPTOR_REVISION
);
1394 "Expected InitializeSecurityDescriptor to return TRUE, got %d, last error %lu\n", bRet
, GetLastError());
1396 bRet
= SetSecurityDescriptorDacl(sd
, TRUE
, key_acl
, FALSE
);
1398 "Expected SetSecurityDescriptorDacl to return TRUE, got %d, last error %lu\n", bRet
, GetLastError());
1402 skip("not enough privileges to modify HKLM\n");
1406 ret
= RegSetKeySecurity(hkRoot64
, DACL_SECURITY_INFORMATION
, sd
);
1407 ok(ret
== ERROR_SUCCESS
,
1408 "Expected RegSetKeySecurity to return success, got error %lu\n", ret
);
1410 ret
= RegSetKeySecurity(hkRoot32
, DACL_SECURITY_INFORMATION
, sd
);
1411 ok(ret
== ERROR_SUCCESS
,
1412 "Expected RegSetKeySecurity to return success, got error %lu\n", ret
);
1415 ret
= RegCreateKeyExA(HKEY_LOCAL_MACHINE
, "Software\\Wine", 0, NULL
, 0,
1416 KEY_WOW64_64KEY
| KEY_READ
, NULL
, &hkey1
, NULL
);
1417 ok(ret
== ERROR_SUCCESS
&& hkey1
!= NULL
,
1418 "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%lu)\n", ret
);
1422 ret
= RegCreateKeyExA(HKEY_LOCAL_MACHINE
, "Software\\Wine", 0, NULL
, 0,
1423 KEY_WOW64_32KEY
| KEY_READ
, NULL
, &hkey1
, NULL
);
1424 ok(ret
== ERROR_SUCCESS
&& hkey1
!= NULL
,
1425 "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%lu)\n", ret
);
1429 HeapFree(GetProcessHeap(), 0, sd
);
1432 RegDeleteKeyA(hkRoot64
, "");
1433 RegCloseKey(hkRoot64
);
1434 RegDeleteKeyA(hkRoot32
, "");
1435 RegCloseKey(hkRoot32
);
1438 static void test_reg_close_key(void)
1443 /* successfully close key
1444 * hkHandle remains changed after call to RegCloseKey
1446 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Test", &hkHandle
);
1447 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1448 ret
= RegCloseKey(hkHandle
);
1449 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1451 /* try to close the key twice */
1452 ret
= RegCloseKey(hkHandle
); /* Windows 95 doesn't mind. */
1453 ok(ret
== ERROR_INVALID_HANDLE
|| ret
== ERROR_SUCCESS
,
1454 "expected ERROR_INVALID_HANDLE or ERROR_SUCCESS, got %ld\n", ret
);
1456 /* try to close a NULL handle */
1457 ret
= RegCloseKey(NULL
);
1458 ok(ret
== ERROR_INVALID_HANDLE
|| ret
== ERROR_BADKEY
, /* Windows 95 returns BADKEY */
1459 "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %ld\n", ret
);
1461 /* Check to see if we didn't potentially close our main handle, which could happen on win98 as
1462 * win98 doesn't give a new handle when the same key is opened.
1463 * Not re-opening will make some next tests fail.
1465 if (hkey_main
== hkHandle
)
1467 trace("The main handle is most likely closed, so re-opening\n");
1468 RegOpenKeyA( HKEY_CURRENT_USER
, "Software\\Wine\\Test", &hkey_main
);
1472 static void test_reg_delete_key(void)
1477 ret
= RegDeleteKeyA(hkey_main
, NULL
);
1479 /* There is a bug in NT4 and W2K that doesn't check if the subkey is NULL. If
1480 * there are also no subkeys available it will delete the key pointed to by hkey_main.
1481 * Not re-creating will make some next tests fail.
1483 if (ret
== ERROR_SUCCESS
)
1485 trace("We are probably running on NT4 or W2K as the main key is deleted,"
1486 " re-creating the main key\n");
1490 ok(ret
== ERROR_INVALID_PARAMETER
||
1491 ret
== ERROR_ACCESS_DENIED
||
1492 ret
== ERROR_BADKEY
, /* Win95 */
1495 ret
= RegCreateKeyA(hkey_main
, "deleteme", &key
);
1496 ok(ret
== ERROR_SUCCESS
, "Could not create key, got %ld\n", ret
);
1497 ret
= RegDeleteKeyA(key
, "");
1498 ok(ret
== ERROR_SUCCESS
, "RegDeleteKeyA failed, got %ld\n", ret
);
1500 ret
= RegOpenKeyA(hkey_main
, "deleteme", &key
);
1501 ok(ret
== ERROR_FILE_NOT_FOUND
, "Key was not deleted, got %ld\n", ret
);
1504 /* Test deleting 32-bit keys */
1505 ret
= RegCreateKeyExA(hkey_main
, "deleteme", 0, NULL
, 0, KEY_ALL_ACCESS
| KEY_WOW64_32KEY
, NULL
, &key
, NULL
);
1506 ok(ret
== ERROR_SUCCESS
, "Could not create key, got %ld\n", ret
);
1509 ret
= RegOpenKeyExA(hkey_main
, "deleteme", 0, KEY_READ
| KEY_WOW64_32KEY
, &key
);
1510 ok(ret
== ERROR_SUCCESS
, "Could not open key, got %ld\n", ret
);
1512 ret
= RegDeleteKeyExA(key
, "", KEY_WOW64_32KEY
, 0);
1513 ok(ret
== ERROR_SUCCESS
, "RegDeleteKeyExA failed, got %ld\n", ret
);
1516 ret
= RegOpenKeyExA(hkey_main
, "deleteme", 0, KEY_READ
| KEY_WOW64_32KEY
, &key
);
1517 ok(ret
== ERROR_FILE_NOT_FOUND
, "Key was not deleted, got %ld\n", ret
);
1521 static BOOL
set_privileges(LPCSTR privilege
, BOOL set
)
1523 TOKEN_PRIVILEGES tp
;
1527 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
, &hToken
))
1530 if(!LookupPrivilegeValueA(NULL
, privilege
, &luid
))
1532 CloseHandle(hToken
);
1536 tp
.PrivilegeCount
= 1;
1537 tp
.Privileges
[0].Luid
= luid
;
1540 tp
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
1542 tp
.Privileges
[0].Attributes
= 0;
1544 AdjustTokenPrivileges(hToken
, FALSE
, &tp
, sizeof(TOKEN_PRIVILEGES
), NULL
, NULL
);
1545 if (GetLastError() != ERROR_SUCCESS
)
1547 CloseHandle(hToken
);
1551 CloseHandle(hToken
);
1555 static void test_reg_save_key(void)
1559 if (!set_privileges(SE_BACKUP_NAME
, TRUE
) ||
1560 !set_privileges(SE_RESTORE_NAME
, FALSE
))
1562 win_skip("Failed to set SE_BACKUP_NAME privileges, skipping tests\n");
1566 ret
= RegSaveKeyA(hkey_main
, "saved_key", NULL
);
1567 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1569 set_privileges(SE_BACKUP_NAME
, FALSE
);
1572 static void test_reg_load_key(void)
1577 if (!set_privileges(SE_RESTORE_NAME
, TRUE
) ||
1578 !set_privileges(SE_BACKUP_NAME
, FALSE
))
1580 win_skip("Failed to set SE_RESTORE_NAME privileges, skipping tests\n");
1584 ret
= RegLoadKeyA(HKEY_LOCAL_MACHINE
, "Test", "saved_key");
1585 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1587 set_privileges(SE_RESTORE_NAME
, FALSE
);
1589 ret
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, "Test", &hkHandle
);
1590 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1592 RegCloseKey(hkHandle
);
1595 static void test_reg_unload_key(void)
1597 UNICODE_STRING key_name
;
1598 OBJECT_ATTRIBUTES attr
;
1603 if (!set_privileges(SE_RESTORE_NAME
, TRUE
) ||
1604 !set_privileges(SE_BACKUP_NAME
, FALSE
))
1606 win_skip("Failed to set SE_RESTORE_NAME privileges, skipping tests\n");
1610 ret
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
, "Test", 0, KEY_READ
, &key
);
1611 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1613 /* try to unload though the key handle is live */
1614 pRtlInitUnicodeString(&key_name
, L
"\\REGISTRY\\Machine\\Test");
1615 InitializeObjectAttributes(&attr
, &key_name
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
1616 status
= pNtUnloadKey(&attr
);
1617 ok(status
== STATUS_CANNOT_DELETE
, "expected STATUS_CANNOT_DELETE, got %08lx\n", status
);
1621 ret
= RegUnLoadKeyA(HKEY_LOCAL_MACHINE
, "Test");
1622 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1624 set_privileges(SE_RESTORE_NAME
, FALSE
);
1626 DeleteFileA("saved_key");
1627 DeleteFileA("saved_key.LOG");
1630 /* Helper function to wait for a file blocked by the registry to be available */
1631 static void wait_file_available(char *path
)
1636 while (((file
= CreateFileA(path
, GENERIC_READ
, 0, NULL
,
1637 OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
)) == INVALID_HANDLE_VALUE
)
1642 ok(file
!= INVALID_HANDLE_VALUE
, "couldn't open file %s after 10 attempts error %ld.\n", path
, GetLastError());
1646 static void test_reg_load_app_key(void)
1649 char temppath
[MAX_PATH
], hivefilepath
[MAX_PATH
];
1650 const BYTE test_data
[] = "Hello World";
1651 BYTE output
[sizeof(test_data
)];
1654 GetTempPathA(sizeof(temppath
), temppath
);
1655 GetTempFileNameA(temppath
, "key", 0, hivefilepath
);
1656 DeleteFileA(hivefilepath
);
1658 if (!set_privileges(SE_BACKUP_NAME
, TRUE
) ||
1659 !set_privileges(SE_RESTORE_NAME
, FALSE
))
1661 win_skip("Failed to set SE_BACKUP_NAME privileges, skipping tests\n");
1665 ret
= RegSaveKeyA(hkey_main
, hivefilepath
, NULL
);
1666 if (ret
!= ERROR_SUCCESS
)
1668 win_skip("Failed to save test key 0x%lx\n", ret
);
1672 set_privileges(SE_BACKUP_NAME
, FALSE
);
1673 set_privileges(SE_RESTORE_NAME
, FALSE
);
1675 /* Test simple key load */
1676 /* Check if the changes are saved */
1677 ret
= RegLoadAppKeyA(hivefilepath
, &appkey
, KEY_READ
| KEY_WRITE
, 0, 0);
1678 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1679 ok(appkey
!= NULL
, "got a null key\n");
1681 ret
= RegSetValueExA(appkey
, "testkey", 0, REG_BINARY
, test_data
, sizeof(test_data
));
1682 todo_wine
ok(ret
== ERROR_SUCCESS
, "couldn't set key value %lx\n", ret
);
1683 RegCloseKey(appkey
);
1685 wait_file_available(hivefilepath
);
1688 ret
= RegLoadAppKeyA(hivefilepath
, &appkey
, KEY_READ
, 0, 0);
1689 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1690 ok(appkey
!= NULL
, "got a null key\n");
1692 size
= sizeof(test_data
);
1693 memset(output
, 0xff, sizeof(output
));
1694 ret
= RegGetValueA(appkey
, NULL
, "testkey", RRF_RT_REG_BINARY
, NULL
, output
, &size
);
1695 todo_wine
ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
1696 ok(size
== sizeof(test_data
), "size doesn't match %ld != %ld\n", size
, (DWORD
)sizeof(test_data
));
1697 todo_wine
ok(!memcmp(test_data
, output
, sizeof(test_data
)), "output is not what expected\n");
1699 RegCloseKey(appkey
);
1701 wait_file_available(hivefilepath
);
1702 ret
= DeleteFileA(hivefilepath
);
1703 ok(ret
, "couldn't delete hive file %ld\n", GetLastError());
1706 /* tests that show that RegConnectRegistry and
1707 OpenSCManager accept computer names without the
1708 \\ prefix (what MSDN says). */
1709 static void test_regconnectregistry( void)
1711 CHAR compName
[MAX_COMPUTERNAME_LENGTH
+ 1];
1712 CHAR netwName
[MAX_COMPUTERNAME_LENGTH
+ 3]; /* 2 chars for double backslash */
1713 DWORD len
= sizeof(compName
) ;
1719 SetLastError(0xdeadbeef);
1720 ret
= GetComputerNameA(compName
, &len
);
1721 ok( ret
, "GetComputerName failed err = %ld\n", GetLastError());
1724 lstrcpyA(netwName
, "\\\\");
1725 lstrcpynA(netwName
+2, compName
, MAX_COMPUTERNAME_LENGTH
+ 1);
1727 retl
= RegConnectRegistryA( compName
, HKEY_LOCAL_MACHINE
, &hkey
);
1729 retl
== ERROR_DLL_INIT_FAILED
||
1730 retl
== ERROR_BAD_NETPATH
, /* some win2k */
1731 "RegConnectRegistryA failed err = %ld\n", retl
);
1732 if( !retl
) RegCloseKey( hkey
);
1734 retl
= RegConnectRegistryA( netwName
, HKEY_LOCAL_MACHINE
, &hkey
);
1736 retl
== ERROR_DLL_INIT_FAILED
||
1737 retl
== ERROR_BAD_NETPATH
, /* some win2k */
1738 "RegConnectRegistryA failed err = %ld\n", retl
);
1739 if( !retl
) RegCloseKey( hkey
);
1741 SetLastError(0xdeadbeef);
1742 schnd
= OpenSCManagerA( compName
, NULL
, GENERIC_READ
);
1743 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1745 win_skip("OpenSCManagerA is not implemented\n");
1749 ok( schnd
!= NULL
, "OpenSCManagerA failed err = %ld\n", GetLastError());
1750 CloseServiceHandle( schnd
);
1752 SetLastError(0xdeadbeef);
1753 schnd
= OpenSCManagerA( netwName
, NULL
, GENERIC_READ
);
1754 ok( schnd
!= NULL
, "OpenSCManagerA failed err = %ld\n", GetLastError());
1755 CloseServiceHandle( schnd
);
1759 static void test_reg_query_value(void)
1766 ret
= RegCreateKeyA(hkey_main
, "subkey", &subkey
);
1767 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
1769 ret
= RegSetValueA(subkey
, NULL
, REG_SZ
, "data", 4);
1770 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
1772 /* try an invalid hkey */
1773 SetLastError(0xdeadbeef);
1775 ret
= RegQueryValueA((HKEY
)0xcafebabe, "subkey", val
, &size
);
1776 ok(ret
== ERROR_INVALID_HANDLE
||
1777 ret
== ERROR_BADKEY
|| /* Windows 98 returns BADKEY */
1778 ret
== ERROR_ACCESS_DENIED
, /* non-admin winxp */
1779 "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %ld\n", ret
);
1780 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1782 /* try a NULL hkey */
1783 SetLastError(0xdeadbeef);
1785 ret
= RegQueryValueA(NULL
, "subkey", val
, &size
);
1786 ok(ret
== ERROR_INVALID_HANDLE
|| ret
== ERROR_BADKEY
, /* Windows 98 returns BADKEY */
1787 "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %ld\n", ret
);
1788 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1790 /* try a NULL value */
1792 ret
= RegQueryValueA(hkey_main
, "subkey", NULL
, &size
);
1793 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
1794 ok(size
== 5, "Expected 5, got %ld\n", size
);
1796 /* try a NULL size */
1797 SetLastError(0xdeadbeef);
1799 ret
= RegQueryValueA(hkey_main
, "subkey", val
, NULL
);
1800 ok(ret
== ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %ld\n", ret
);
1801 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1802 ok(!val
[0], "Expected val to be untouched, got %s\n", val
);
1804 /* try a NULL value and size */
1805 ret
= RegQueryValueA(hkey_main
, "subkey", NULL
, NULL
);
1806 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
1808 /* try a size too small */
1809 SetLastError(0xdeadbeef);
1812 ret
= RegQueryValueA(hkey_main
, "subkey", val
, &size
);
1813 ok(ret
== ERROR_MORE_DATA
, "Expected ERROR_MORE_DATA, got %ld\n", ret
);
1814 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1815 ok(!val
[0], "Expected val to be untouched, got %s\n", val
);
1816 ok(size
== 5, "Expected 5, got %ld\n", size
);
1818 /* successfully read the value using 'subkey' */
1820 ret
= RegQueryValueA(hkey_main
, "subkey", val
, &size
);
1821 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
1822 ok(!lstrcmpA(val
, "data"), "Expected 'data', got '%s'\n", val
);
1823 ok(size
== 5, "Expected 5, got %ld\n", size
);
1825 /* successfully read the value using the subkey key */
1827 ret
= RegQueryValueA(subkey
, NULL
, val
, &size
);
1828 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
1829 ok(!lstrcmpA(val
, "data"), "Expected 'data', got '%s'\n", val
);
1830 ok(size
== 5, "Expected 5, got %ld\n", size
);
1832 /* unicode - try size too small */
1833 SetLastError(0xdeadbeef);
1836 ret
= RegQueryValueW(subkey
, NULL
, valW
, &size
);
1837 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1839 win_skip("RegQueryValueW is not implemented\n");
1842 ok(ret
== ERROR_MORE_DATA
, "Expected ERROR_MORE_DATA, got %ld\n", ret
);
1843 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1844 ok(!valW
[0], "Expected valW to be untouched\n");
1845 ok(size
== 10, "Got wrong size: %ld\n", size
);
1847 /* unicode - try size in WCHARS */
1848 SetLastError(0xdeadbeef);
1849 size
= ARRAY_SIZE(valW
);
1850 ret
= RegQueryValueW(subkey
, NULL
, valW
, &size
);
1851 ok(ret
== ERROR_MORE_DATA
, "Expected ERROR_MORE_DATA, got %ld\n", ret
);
1852 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1853 ok(!valW
[0], "Expected valW to be untouched\n");
1854 ok(size
== 10, "Got wrong size: %ld\n", size
);
1856 /* unicode - successfully read the value */
1857 size
= sizeof(valW
);
1858 ret
= RegQueryValueW(subkey
, NULL
, valW
, &size
);
1859 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
1860 ok(!lstrcmpW(valW
, L
"data"), "Got wrong value\n");
1861 ok(size
== 10, "Got wrong size: %ld\n", size
);
1863 /* unicode - set the value without a NULL terminator */
1864 ret
= RegSetValueW(subkey
, NULL
, REG_SZ
, L
"data", 8);
1865 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
1867 /* unicode - read the unterminated value, value is terminated for us */
1868 memset(valW
, 'a', sizeof(valW
));
1869 size
= sizeof(valW
);
1870 ret
= RegQueryValueW(subkey
, NULL
, valW
, &size
);
1871 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
1872 ok(!lstrcmpW(valW
, L
"data"), "Got wrong value\n");
1873 ok(size
== 10, "Got wrong size: %ld\n", size
);
1876 RegDeleteKeyA(subkey
, "");
1877 RegCloseKey(subkey
);
1880 static void test_reg_query_info(void)
1885 char classbuffer
[32];
1886 WCHAR classbufferW
[32];
1887 char expectbuffer
[32];
1888 WCHAR expectbufferW
[32];
1889 char subkey_class
[] = "subkey class";
1890 WCHAR subkey_classW
[] = L
"subkey class";
1891 char subsubkey_class
[] = "subsubkey class";
1893 DWORD subkeys
, maxsubkeylen
, maxclasslen
;
1894 DWORD values
, maxvaluenamelen
, maxvaluelen
;
1898 ret
= RegCreateKeyExA(hkey_main
, "subkey", 0, subkey_class
, 0, KEY_ALL_ACCESS
, NULL
, &subkey
, NULL
);
1899 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
1901 /* all parameters NULL */
1902 ret
= RegQueryInfoKeyA(NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1903 ok(ret
== ERROR_INVALID_HANDLE
, "ret = %ld\n", ret
);
1905 ret
= RegQueryInfoKeyW(NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1906 ok(ret
== ERROR_INVALID_HANDLE
, "ret = %ld\n", ret
);
1908 /* not requesting any information */
1909 ret
= RegQueryInfoKeyA(subkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1910 ok(ret
== ERROR_SUCCESS
, "ret = %ld\n", ret
);
1912 ret
= RegQueryInfoKeyW(subkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1913 ok(ret
== ERROR_SUCCESS
, "ret = %ld\n", ret
);
1915 /* class without length is invalid */
1916 memset(classbuffer
, 0x55, sizeof(classbuffer
));
1917 ret
= RegQueryInfoKeyA(subkey
, classbuffer
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1918 ok(ret
== ERROR_INVALID_PARAMETER
, "ret = %ld\n", ret
);
1919 ok(classbuffer
[0] == 0x55, "classbuffer[0] = 0x%x\n", classbuffer
[0]);
1921 memset(classbufferW
, 0x55, sizeof(classbufferW
));
1922 ret
= RegQueryInfoKeyW(subkey
, classbufferW
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1923 ok(ret
== ERROR_INVALID_PARAMETER
, "ret = %ld\n", ret
);
1924 ok(classbufferW
[0] == 0x5555, "classbufferW[0] = 0x%x\n", classbufferW
[0]);
1927 sdlen
= classlen
=0;
1928 ret
= RegQueryInfoKeyA(subkey
, NULL
, &classlen
, NULL
, &subkeys
, &maxsubkeylen
, &maxclasslen
, &values
, &maxvaluenamelen
, &maxvaluelen
, &sdlen
, &lastwrite
);
1929 ok(ret
== ERROR_SUCCESS
, "ret = %ld\n", ret
);
1930 ok(classlen
== strlen(subkey_class
), "classlen = %lu\n", classlen
);
1931 ok(subkeys
== 0, "subkeys = %lu\n", subkeys
);
1932 ok(maxsubkeylen
== 0, "maxsubkeylen = %lu\n", maxsubkeylen
);
1933 ok(maxclasslen
== 0, "maxclasslen = %lu\n", maxclasslen
);
1934 ok(values
== 0, "values = %lu\n", values
);
1935 ok(maxvaluenamelen
== 0, "maxvaluenamelen = %lu\n", maxvaluenamelen
);
1936 ok(maxvaluelen
== 0, "maxvaluelen = %lu\n", maxvaluelen
);
1937 todo_wine
ok(sdlen
!= 0, "sdlen = %lu\n", sdlen
);
1938 ok(lastwrite
.dwLowDateTime
!= 0, "lastwrite.dwLowDateTime = %lu\n", lastwrite
.dwLowDateTime
);
1939 ok(lastwrite
.dwHighDateTime
!= 0, "lastwrite.dwHighDateTime = %lu\n", lastwrite
.dwHighDateTime
);
1941 sdlen
= classlen
= 0;
1942 ret
= RegQueryInfoKeyW(subkey
, NULL
, &classlen
, NULL
, &subkeys
, &maxsubkeylen
, &maxclasslen
, &values
, &maxvaluenamelen
, &maxvaluelen
, &sdlen
, &lastwrite
);
1943 ok(ret
== ERROR_SUCCESS
, "ret = %ld\n", ret
);
1944 ok(classlen
== strlen(subkey_class
), "classlen = %lu\n", classlen
);
1945 ok(subkeys
== 0, "subkeys = %lu\n", subkeys
);
1946 ok(maxsubkeylen
== 0, "maxsubkeylen = %lu\n", maxsubkeylen
);
1947 ok(maxclasslen
== 0, "maxclasslen = %lu\n", maxclasslen
);
1948 ok(values
== 0, "values = %lu\n", values
);
1949 ok(maxvaluenamelen
== 0, "maxvaluenamelen = %lu\n", maxvaluenamelen
);
1950 ok(maxvaluelen
== 0, "maxvaluelen = %lu\n", maxvaluelen
);
1951 todo_wine
ok(sdlen
!= 0, "sdlen = %lu\n", sdlen
);
1952 ok(lastwrite
.dwLowDateTime
!= 0, "lastwrite.dwLowDateTime = %lu\n", lastwrite
.dwLowDateTime
);
1953 ok(lastwrite
.dwHighDateTime
!= 0, "lastwrite.dwHighDateTime = %lu\n", lastwrite
.dwHighDateTime
);
1955 ret
= RegCreateKeyExA(subkey
, "subsubkey", 0, subsubkey_class
, 0, KEY_ALL_ACCESS
, NULL
, &subsubkey
, NULL
);
1956 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
1958 ret
= RegSetValueExA(subkey
, NULL
, 0, REG_SZ
, (const BYTE
*)"data", 5);
1959 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
1961 /* with subkey & default value */
1962 sdlen
= classlen
= 0;
1963 ret
= RegQueryInfoKeyA(subkey
, NULL
, &classlen
, NULL
, &subkeys
, &maxsubkeylen
, &maxclasslen
, &values
, &maxvaluenamelen
, &maxvaluelen
, &sdlen
, &lastwrite
);
1964 ok(ret
== ERROR_SUCCESS
, "ret = %ld\n", ret
);
1965 ok(classlen
== strlen(subkey_class
), "classlen = %lu\n", classlen
);
1966 ok(subkeys
== 1, "subkeys = %lu\n", subkeys
);
1967 ok(maxsubkeylen
== strlen("subsubkey"), "maxsubkeylen = %lu\n", maxsubkeylen
);
1968 ok(maxclasslen
== strlen(subsubkey_class
), "maxclasslen = %lu\n", maxclasslen
);
1969 ok(values
== 1, "values = %lu\n", values
);
1970 ok(maxvaluenamelen
== 0, "maxvaluenamelen = %lu\n", maxvaluenamelen
);
1971 ok(maxvaluelen
== sizeof("data") * sizeof(WCHAR
), "maxvaluelen = %lu\n", maxvaluelen
);
1972 todo_wine
ok(sdlen
!= 0, "sdlen = %lu\n", sdlen
);
1973 ok(lastwrite
.dwLowDateTime
!= 0, "lastwrite.dwLowDateTime = %lu\n", lastwrite
.dwLowDateTime
);
1974 ok(lastwrite
.dwHighDateTime
!= 0, "lastwrite.dwHighDateTime = %lu\n", lastwrite
.dwHighDateTime
);
1976 sdlen
= classlen
= 0;
1977 ret
= RegQueryInfoKeyW(subkey
, NULL
, &classlen
, NULL
, &subkeys
, &maxsubkeylen
, &maxclasslen
, &values
, &maxvaluenamelen
, &maxvaluelen
, &sdlen
, &lastwrite
);
1978 ok(ret
== ERROR_SUCCESS
, "ret = %ld\n", ret
);
1979 ok(classlen
== strlen(subkey_class
), "classlen = %lu\n", classlen
);
1980 ok(subkeys
== 1, "subkeys = %lu\n", subkeys
);
1981 ok(maxsubkeylen
== strlen("subsubkey"), "maxsubkeylen = %lu\n", maxsubkeylen
);
1982 ok(maxclasslen
== strlen(subsubkey_class
), "maxclasslen = %lu\n", maxclasslen
);
1983 ok(values
== 1, "values = %lu\n", values
);
1984 ok(maxvaluenamelen
== 0, "maxvaluenamelen = %lu\n", maxvaluenamelen
);
1985 ok(maxvaluelen
== sizeof("data") * sizeof(WCHAR
), "maxvaluelen = %lu\n", maxvaluelen
);
1986 todo_wine
ok(sdlen
!= 0, "sdlen = %lu\n", sdlen
);
1987 ok(lastwrite
.dwLowDateTime
!= 0, "lastwrite.dwLowDateTime = %lu\n", lastwrite
.dwLowDateTime
);
1988 ok(lastwrite
.dwHighDateTime
!= 0, "lastwrite.dwHighDateTime = %lu\n", lastwrite
.dwHighDateTime
);
1990 ret
= RegSetValueExA(subkey
, "value one", 0, REG_SZ
, (const BYTE
*)"first value data", 17);
1991 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
1993 ret
= RegSetValueExA(subkey
, "value 2", 0, REG_SZ
, (const BYTE
*)"second value data", 18);
1994 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
1996 /* with named value */
1998 ret
= RegQueryInfoKeyA(subkey
, NULL
, &classlen
, NULL
, &subkeys
, &maxsubkeylen
, &maxclasslen
, &values
, &maxvaluenamelen
, &maxvaluelen
, &sdlen
, &lastwrite
);
1999 ok(ret
== ERROR_SUCCESS
, "ret = %ld\n", ret
);
2000 ok(values
== 3, "values = %lu\n", values
);
2001 ok(maxvaluenamelen
== strlen("value one"), "maxvaluenamelen = %lu\n", maxvaluenamelen
);
2002 ok(maxvaluelen
== sizeof("second value data") * sizeof(WCHAR
), "maxvaluelen = %lu\n", maxvaluelen
);
2005 ret
= RegQueryInfoKeyW(subkey
, NULL
, &classlen
, NULL
, &subkeys
, &maxsubkeylen
, &maxclasslen
, &values
, &maxvaluenamelen
, &maxvaluelen
, &sdlen
, &lastwrite
);
2006 ok(ret
== ERROR_SUCCESS
, "ret = %ld\n", ret
);
2007 ok(values
== 3, "values = %lu\n", values
);
2008 ok(maxvaluenamelen
== strlen("value one"), "maxvaluenamelen = %lu\n", maxvaluenamelen
);
2009 ok(maxvaluelen
== sizeof("second value data") * sizeof(WCHAR
), "maxvaluelen = %lu\n", maxvaluelen
);
2011 /* class name with zero size buffer */
2012 memset(classbuffer
, 0x55, sizeof(classbuffer
));
2014 ret
= RegQueryInfoKeyA(subkey
, classbuffer
, &classlen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2015 ok(ret
== ERROR_SUCCESS
, "ret = %ld\n", ret
);
2016 ok(classlen
== strlen(subkey_class
) /* win2k */ ||
2017 classlen
== 0, "classlen = %lu\n", classlen
);
2018 memset(expectbuffer
, 0x55, sizeof(expectbuffer
));
2019 ok(!memcmp(classbuffer
, expectbuffer
, sizeof(classbuffer
)), "classbuffer was modified\n");
2021 memset(classbufferW
, 0x55, sizeof(classbufferW
));
2023 ret
= RegQueryInfoKeyW(subkey
, classbufferW
, &classlen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2024 ok(ret
== ERROR_SUCCESS
, "ret = %ld\n", ret
);
2025 ok(classlen
== strlen(subkey_class
) /* win2k */ ||
2026 classlen
== 0, "classlen = %lu\n", classlen
);
2027 memset(expectbufferW
, 0x55, sizeof(expectbufferW
));
2028 ok(!memcmp(classbufferW
, expectbufferW
, sizeof(classbufferW
)), "classbufferW was modified\n");
2030 /* class name with one char buffer */
2031 memset(classbuffer
, 0x55, sizeof(classbuffer
));
2033 ret
= RegQueryInfoKeyA(subkey
, classbuffer
, &classlen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2034 ok(ret
== ERROR_MORE_DATA
, "ret = %ld\n", ret
);
2035 ok(classlen
== 0, "classlen = %lu\n", classlen
);
2036 memset(expectbuffer
, 0x55, sizeof(expectbuffer
));
2037 expectbuffer
[0] = 0;
2038 ok(!memcmp(classbuffer
, expectbuffer
, sizeof(classbuffer
)), "classbuffer was modified\n");
2040 memset(classbufferW
, 0x55, sizeof(classbufferW
));
2042 ret
= RegQueryInfoKeyW(subkey
, classbufferW
, &classlen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2043 /* failure-code changed to ERROR_MORE_DATA in recent win10 */
2044 ok((ret
== ERROR_INSUFFICIENT_BUFFER
) || (ret
== ERROR_MORE_DATA
), "ret = %ld\n", ret
);
2045 ok(classlen
== 0 /* win8 */ ||
2046 classlen
== strlen(subkey_class
), "classlen = %lu\n", classlen
);
2047 memset(expectbufferW
, 0x55, sizeof(expectbufferW
));
2048 ok(!memcmp(classbufferW
, expectbufferW
, sizeof(classbufferW
)), "classbufferW was modified\n");
2050 /* class name with buffer one char too small */
2051 memset(classbuffer
, 0x55, sizeof(classbuffer
));
2052 classlen
= sizeof(subkey_class
) - 1;
2053 ret
= RegQueryInfoKeyA(subkey
, classbuffer
, &classlen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2054 ok(ret
== ERROR_MORE_DATA
, "ret = %ld\n", ret
);
2055 ok(classlen
== sizeof(subkey_class
) - 2, "classlen = %lu\n", classlen
);
2056 memset(expectbuffer
, 0x55, sizeof(expectbuffer
));
2057 strcpy(expectbuffer
, subkey_class
);
2058 expectbuffer
[sizeof(subkey_class
) - 2] = 0;
2059 expectbuffer
[sizeof(subkey_class
) - 1] = 0x55;
2060 ok(!memcmp(classbuffer
, expectbuffer
, sizeof(classbuffer
)),
2061 "classbuffer = %.*s, expected %s\n",
2062 (int)sizeof(classbuffer
), classbuffer
, expectbuffer
);
2064 memset(classbufferW
, 0x55, sizeof(classbufferW
));
2065 classlen
= sizeof(subkey_class
) - 1;
2066 ret
= RegQueryInfoKeyW(subkey
, classbufferW
, &classlen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2067 ok(ret
== ERROR_INSUFFICIENT_BUFFER
, "ret = %ld\n", ret
);
2068 ok(classlen
== sizeof(subkey_class
) - 2 /* win8 */ ||
2069 classlen
== strlen(subkey_class
), "classlen = %lu\n", classlen
);
2070 memset(expectbufferW
, 0x55, sizeof(expectbufferW
));
2071 ok(!memcmp(classbufferW
, expectbufferW
, sizeof(classbufferW
)), "classbufferW was modified\n");
2073 /* class name with large enough buffer */
2074 memset(classbuffer
, 0x55, sizeof(classbuffer
));
2075 classlen
= sizeof(subkey_class
);
2076 ret
= RegQueryInfoKeyA(subkey
, classbuffer
, &classlen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2077 ok(ret
== ERROR_SUCCESS
, "ret = %ld\n", ret
);
2078 ok(classlen
== sizeof(subkey_class
) - 1, "classlen = %lu\n", classlen
);
2079 memset(expectbuffer
, 0x55, sizeof(expectbuffer
));
2080 strcpy(expectbuffer
, subkey_class
);
2081 ok(!memcmp(classbuffer
, expectbuffer
, sizeof(classbuffer
)),
2082 "classbuffer = \"%.*s\", expected %s\n",
2083 (int)sizeof(classbuffer
), classbuffer
, expectbuffer
);
2085 memset(classbuffer
, 0x55, sizeof(classbuffer
));
2086 classlen
= 0xdeadbeef;
2087 ret
= RegQueryInfoKeyA(subkey
, classbuffer
, &classlen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2088 ok(ret
== ERROR_SUCCESS
, "ret = %ld\n", ret
);
2089 ok(classlen
== sizeof(subkey_class
) - 1, "classlen = %lu\n", classlen
);
2090 memset(expectbuffer
, 0x55, sizeof(expectbuffer
));
2091 strcpy(expectbuffer
, subkey_class
);
2092 ok(!memcmp(classbuffer
, expectbuffer
, sizeof(classbuffer
)),
2093 "classbuffer = \"%.*s\", expected %s\n",
2094 (int)sizeof(classbuffer
), classbuffer
, expectbuffer
);
2096 memset(classbufferW
, 0x55, sizeof(classbufferW
));
2097 classlen
= sizeof(subkey_class
);
2098 ret
= RegQueryInfoKeyW(subkey
, classbufferW
, &classlen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2099 ok(ret
== ERROR_SUCCESS
, "ret = %ld\n", ret
);
2100 ok(classlen
== sizeof(subkey_class
) - 1, "classlen = %lu\n", classlen
);
2101 memset(expectbufferW
, 0x55, sizeof(expectbufferW
));
2102 lstrcpyW(expectbufferW
, subkey_classW
);
2103 ok(!memcmp(classbufferW
, expectbufferW
, sizeof(classbufferW
)),
2104 "classbufferW = %s, expected %s\n",
2105 wine_dbgstr_wn(classbufferW
, ARRAY_SIZE(classbufferW
)), wine_dbgstr_w(expectbufferW
));
2107 memset(classbufferW
, 0x55, sizeof(classbufferW
));
2108 classlen
= 0xdeadbeef;
2109 ret
= RegQueryInfoKeyW(subkey
, classbufferW
, &classlen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2110 ok(ret
== ERROR_SUCCESS
, "ret = %ld\n", ret
);
2111 ok(classlen
== sizeof(subkey_class
) - 1, "classlen = %lu\n", classlen
);
2112 memset(expectbufferW
, 0x55, sizeof(expectbufferW
));
2113 lstrcpyW(expectbufferW
, subkey_classW
);
2114 ok(!memcmp(classbufferW
, expectbufferW
, sizeof(classbufferW
)),
2115 "classbufferW = %s, expected %s\n",
2116 wine_dbgstr_wn(classbufferW
, ARRAY_SIZE(classbufferW
)), wine_dbgstr_w(expectbufferW
));
2118 RegDeleteKeyA(subsubkey
, "");
2119 RegCloseKey(subsubkey
);
2120 RegDeleteKeyA(subkey
, "");
2121 RegCloseKey(subkey
);
2124 static void test_string_termination(void)
2128 static const char string
[] = "FullString";
2131 DWORD insize
, outsize
, nsize
;
2133 ret
= RegCreateKeyA(hkey_main
, "string_termination", &subkey
);
2134 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2136 /* Off-by-one RegSetValueExA -> adds a trailing '\0'! */
2137 insize
=sizeof(string
)-1;
2138 ret
= RegSetValueExA(subkey
, "stringtest", 0, REG_SZ
, (BYTE
*)string
, insize
);
2139 ok(ret
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld\n", ret
);
2141 ret
= RegQueryValueExA(subkey
, "stringtest", NULL
, NULL
, buffer
, &outsize
);
2142 ok(ret
== ERROR_MORE_DATA
, "RegQueryValueExA returned: %ld\n", ret
);
2144 /* Off-by-two RegSetValueExA -> no trailing '\0' */
2145 insize
=sizeof(string
)-2;
2146 ret
= RegSetValueExA(subkey
, "stringtest", 0, REG_SZ
, (BYTE
*)string
, insize
);
2147 ok(ret
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld\n", ret
);
2149 ret
= RegQueryValueExA(subkey
, "stringtest", NULL
, NULL
, NULL
, &outsize
);
2150 ok(ret
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld\n", ret
);
2151 ok(outsize
== insize
, "wrong size %lu != %lu\n", outsize
, insize
);
2153 /* RegQueryValueExA may return a string with no trailing '\0' */
2155 memset(buffer
, 0xbd, sizeof(buffer
));
2156 ret
= RegQueryValueExA(subkey
, "stringtest", NULL
, NULL
, buffer
, &outsize
);
2157 ok(ret
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld\n", ret
);
2158 ok(outsize
== insize
, "wrong size: %lu != %lu\n", outsize
, insize
);
2159 ok(memcmp(buffer
, string
, outsize
) == 0, "bad string: %s/%lu != %s\n",
2160 debugstr_an((char*)buffer
, outsize
), outsize
, string
);
2161 ok(buffer
[insize
] == 0xbd, "buffer overflow at %lu %02x\n", insize
, buffer
[insize
]);
2163 /* RegQueryValueExA adds a trailing '\0' if there is room */
2165 memset(buffer
, 0xbd, sizeof(buffer
));
2166 ret
= RegQueryValueExA(subkey
, "stringtest", NULL
, NULL
, buffer
, &outsize
);
2167 ok(ret
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld\n", ret
);
2168 ok(outsize
== insize
, "wrong size: %lu != %lu\n", outsize
, insize
);
2169 ok(memcmp(buffer
, string
, outsize
) == 0, "bad string: %s/%lu != %s\n",
2170 debugstr_an((char*)buffer
, outsize
), outsize
, string
);
2171 ok(buffer
[insize
] == 0, "buffer overflow at %lu %02x\n", insize
, buffer
[insize
]);
2173 /* RegEnumValueA may return a string with no trailing '\0' */
2175 memset(buffer
, 0xbd, sizeof(buffer
));
2177 ret
= RegEnumValueA(subkey
, 0, name
, &nsize
, NULL
, NULL
, buffer
, &outsize
);
2178 ok(ret
== ERROR_SUCCESS
, "RegEnumValueA failed: %ld\n", ret
);
2179 ok(strcmp(name
, "stringtest") == 0, "wrong name: %s\n", name
);
2180 ok(outsize
== insize
, "wrong size: %lu != %lu\n", outsize
, insize
);
2181 ok(memcmp(buffer
, string
, outsize
) == 0, "bad string: %s/%lu != %s\n",
2182 debugstr_an((char*)buffer
, outsize
), outsize
, string
);
2183 ok(buffer
[insize
] == 0xbd, "buffer overflow at %lu %02x\n", insize
, buffer
[insize
]);
2185 /* RegEnumValueA adds a trailing '\0' if there is room */
2187 memset(buffer
, 0xbd, sizeof(buffer
));
2189 ret
= RegEnumValueA(subkey
, 0, name
, &nsize
, NULL
, NULL
, buffer
, &outsize
);
2190 ok(ret
== ERROR_SUCCESS
, "RegEnumValueA failed: %ld\n", ret
);
2191 ok(strcmp(name
, "stringtest") == 0, "wrong name: %s\n", name
);
2192 ok(outsize
== insize
, "wrong size: %lu != %lu\n", outsize
, insize
);
2193 ok(memcmp(buffer
, string
, outsize
) == 0, "bad string: %s/%lu != %s\n",
2194 debugstr_an((char*)buffer
, outsize
), outsize
, string
);
2195 ok(buffer
[insize
] == 0, "buffer overflow at %lu %02x\n", insize
, buffer
[insize
]);
2197 RegDeleteKeyA(subkey
, "");
2198 RegCloseKey(subkey
);
2201 static void test_reg_copy_tree(void)
2203 HKEY src
, dst
, subkey
;
2204 CHAR buffer
[MAX_PATH
];
2210 win_skip("Skipping RegCopyTreeA tests, function not present\n");
2214 ret
= RegCreateKeyA(hkey_main
, "src", &src
);
2215 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2216 ret
= RegCreateKeyA(hkey_main
, "dst", &dst
);
2217 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2219 /* Copy nonexistent subkey */
2220 ret
= pRegCopyTreeA(src
, "nonexistent_subkey", dst
);
2221 ok(ret
== ERROR_FILE_NOT_FOUND
, "Expected ERROR_FILE_NOT_FOUND, got %ld\n", ret
);
2223 /* Create test keys and values */
2224 ret
= RegSetValueA(src
, NULL
, REG_SZ
, "data", 4);
2225 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2226 ret
= RegSetValueExA(src
, "value", 0, REG_SZ
, (const BYTE
*)"data2", 5);
2227 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2229 ret
= RegCreateKeyA(src
, "subkey2", &subkey
);
2230 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2231 ret
= RegSetValueA(subkey
, NULL
, REG_SZ
, "data3", 5);
2232 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2233 ret
= RegSetValueExA(subkey
, "value", 0, REG_SZ
, (const BYTE
*)"data4", 5);
2234 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2235 ret
= RegCloseKey(subkey
);
2236 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2238 ret
= RegCreateKeyA(src
, "subkey3", &subkey
);
2239 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2240 ret
= RegCloseKey(subkey
);
2241 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2244 ret
= pRegCopyTreeA(src
, "subkey2", dst
);
2245 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2248 ret
= RegQueryValueA(dst
, NULL
, buffer
, &size
);
2249 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2250 ok(!strcmp(buffer
, "data3"), "Expected 'data3', got '%s'\n", buffer
);
2253 ret
= RegQueryValueExA(dst
, "value", NULL
, &type
, (BYTE
*)buffer
, &dwsize
);
2254 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2255 ok(type
== REG_SZ
, "Expected REG_SZ, got %lu\n", type
);
2256 ok(!strcmp(buffer
, "data4"), "Expected 'data4', got '%s'\n", buffer
);
2258 /* Copy full tree */
2259 ret
= pRegCopyTreeA(src
, NULL
, dst
);
2260 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2263 ret
= RegQueryValueA(dst
, NULL
, buffer
, &size
);
2264 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2265 ok(!strcmp(buffer
, "data"), "Expected 'data', got '%s'\n", buffer
);
2268 ret
= RegQueryValueExA(dst
, "value", NULL
, &type
, (BYTE
*)buffer
, &dwsize
);
2269 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2270 ok(type
== REG_SZ
, "Expected REG_SZ, got %lu\n", type
);
2271 ok(!strcmp(buffer
, "data2"), "Expected 'data2', got '%s'\n", buffer
);
2273 ret
= RegOpenKeyA(dst
, "subkey2", &subkey
);
2274 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2276 ret
= RegQueryValueA(subkey
, NULL
, buffer
, &size
);
2277 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2278 ok(!strcmp(buffer
, "data3"), "Expected 'data3', got '%s'\n", buffer
);
2280 ret
= RegQueryValueExA(subkey
, "value", NULL
, &type
, (BYTE
*)buffer
, &dwsize
);
2281 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2282 ok(type
== REG_SZ
, "Expected REG_SZ, got %lu\n", type
);
2283 ok(!strcmp(buffer
, "data4"), "Expected 'data4', got '%s'\n", buffer
);
2284 ret
= RegCloseKey(subkey
);
2285 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2287 ret
= RegOpenKeyA(dst
, "subkey3", &subkey
);
2288 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2289 ret
= RegCloseKey(subkey
);
2290 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2296 static void test_reg_delete_tree(void)
2298 CHAR buffer
[MAX_PATH
];
2299 HKEY subkey
, subkey2
;
2303 if(!pRegDeleteTreeA
) {
2304 win_skip("Skipping RegDeleteTreeA tests, function not present\n");
2308 ret
= RegCreateKeyA(hkey_main
, "subkey", &subkey
);
2309 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2310 ret
= RegCreateKeyA(subkey
, "subkey2", &subkey2
);
2311 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2312 ret
= RegSetValueA(subkey
, NULL
, REG_SZ
, "data", 4);
2313 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2314 ret
= RegSetValueA(subkey2
, NULL
, REG_SZ
, "data2", 5);
2315 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2316 ret
= RegCloseKey(subkey2
);
2317 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2319 ret
= pRegDeleteTreeA(subkey
, "subkey2");
2320 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2321 ok(RegOpenKeyA(subkey
, "subkey2", &subkey2
),
2322 "subkey2 was not deleted\n");
2324 ok(!RegQueryValueA(subkey
, NULL
, buffer
, &size
),
2325 "Default value of subkey no longer present\n");
2327 ret
= RegCreateKeyA(subkey
, "subkey2", &subkey2
);
2328 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2329 ret
= RegCloseKey(subkey2
);
2330 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2331 ret
= pRegDeleteTreeA(hkey_main
, "subkey\\subkey2");
2332 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2333 ok(RegOpenKeyA(subkey
, "subkey2", &subkey2
),
2334 "subkey2 was not deleted\n");
2335 ok(!RegQueryValueA(subkey
, NULL
, buffer
, &size
),
2336 "Default value of subkey no longer present\n");
2338 ret
= RegCreateKeyA(subkey
, "subkey2", &subkey2
);
2339 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2340 ret
= RegCloseKey(subkey2
);
2341 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2342 ret
= RegCreateKeyA(subkey
, "subkey3", &subkey2
);
2343 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2344 ret
= RegCloseKey(subkey2
);
2345 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2346 ret
= RegSetValueA(subkey
, NULL
, REG_SZ
, "data", 4);
2347 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2348 ret
= RegSetValueExA(subkey
, "value", 0, REG_SZ
, (const BYTE
*)"data2", 5);
2349 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2350 ret
= pRegDeleteTreeA(subkey
, NULL
);
2351 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2352 ok(!RegOpenKeyA(hkey_main
, "subkey", &subkey
),
2353 "subkey was deleted\n");
2354 ok(RegOpenKeyA(subkey
, "subkey2", &subkey2
),
2355 "subkey2 was not deleted\n");
2356 ok(RegOpenKeyA(subkey
, "subkey3", &subkey2
),
2357 "subkey3 was not deleted\n");
2359 ret
= RegQueryValueA(subkey
, NULL
, buffer
, &size
);
2360 ok(ret
== ERROR_SUCCESS
,
2361 "Default value of subkey is not present\n");
2362 ok(!buffer
[0], "Expected length 0 got length %u(%s)\n", lstrlenA(buffer
), buffer
);
2364 ok(RegQueryValueExA(subkey
, "value", NULL
, &type
, (BYTE
*)buffer
, &dwsize
),
2365 "Value is still present\n");
2366 ret
= RegCloseKey(subkey
);
2367 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2369 ret
= RegOpenKeyA(hkey_main
, "subkey", &subkey
);
2370 ok(ret
== ERROR_SUCCESS
, "subkey was deleted\n");
2371 ret
= pRegDeleteTreeA(subkey
, "");
2372 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2373 ret
= RegCloseKey(subkey
);
2374 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2376 ret
= RegOpenKeyA(hkey_main
, "subkey", &subkey
);
2377 ok(ret
== ERROR_SUCCESS
, "subkey was deleted\n");
2378 ret
= RegCloseKey(subkey
);
2379 ok(ret
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %ld\n", ret
);
2381 ret
= pRegDeleteTreeA(hkey_main
, "not-here");
2382 ok(ret
== ERROR_FILE_NOT_FOUND
,
2383 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", ret
);
2386 static void test_rw_order(void)
2390 static const char keyname
[] = "test_rw_order";
2392 DWORD values
, value_len
, value_name_max_len
;
2395 RegDeleteKeyA(HKEY_CURRENT_USER
, keyname
);
2396 ret
= RegCreateKeyA(HKEY_CURRENT_USER
, keyname
, &hKey
);
2397 if(ret
!= ERROR_SUCCESS
) {
2398 skip("Couldn't create key. Skipping.\n");
2402 ok(!RegSetValueExA(hKey
, "A", 0, REG_DWORD
, (LPBYTE
)&dw
, sizeof(dw
)),
2403 "RegSetValueExA for value \"A\" failed\n");
2404 ok(!RegSetValueExA(hKey
, "C", 0, REG_DWORD
, (LPBYTE
)&dw
, sizeof(dw
)),
2405 "RegSetValueExA for value \"C\" failed\n");
2406 ok(!RegSetValueExA(hKey
, "D", 0, REG_DWORD
, (LPBYTE
)&dw
, sizeof(dw
)),
2407 "RegSetValueExA for value \"D\" failed\n");
2408 ok(!RegSetValueExA(hKey
, "B", 0, REG_DWORD
, (LPBYTE
)&dw
, sizeof(dw
)),
2409 "RegSetValueExA for value \"B\" failed\n");
2411 ok(!RegQueryInfoKeyA(hKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &values
,
2412 &value_name_max_len
, NULL
, NULL
, NULL
), "RegQueryInfoKeyA failed\n");
2413 ok(values
== 4, "Expected 4 values, got %lu\n", values
);
2415 /* Value enumeration preserves RegSetValueEx call order */
2417 ok(!RegEnumValueA(hKey
, 0, value_buf
, &value_len
, NULL
, NULL
, NULL
, NULL
), "RegEnumValueA failed\n");
2418 ok(strcmp(value_buf
, "A") == 0, "Expected name \"A\", got %s\n", value_buf
);
2420 ok(!RegEnumValueA(hKey
, 1, value_buf
, &value_len
, NULL
, NULL
, NULL
, NULL
), "RegEnumValueA failed\n");
2421 todo_wine
ok(strcmp(value_buf
, "C") == 0, "Expected name \"C\", got %s\n", value_buf
);
2423 ok(!RegEnumValueA(hKey
, 2, value_buf
, &value_len
, NULL
, NULL
, NULL
, NULL
), "RegEnumValueA failed\n");
2424 todo_wine
ok(strcmp(value_buf
, "D") == 0, "Expected name \"D\", got %s\n", value_buf
);
2426 ok(!RegEnumValueA(hKey
, 3, value_buf
, &value_len
, NULL
, NULL
, NULL
, NULL
), "RegEnumValueA failed\n");
2427 todo_wine
ok(strcmp(value_buf
, "B") == 0, "Expected name \"B\", got %s\n", value_buf
);
2429 ok(!RegDeleteKeyA(HKEY_CURRENT_USER
, keyname
), "Failed to delete key\n");
2432 static void test_symlinks(void)
2434 static const WCHAR targetW
[] = L
"\\Software\\Wine\\Test\\target";
2436 UNICODE_STRING target_str
;
2440 DWORD target_len
, type
, len
, dw
, err
;
2442 if (!pRtlFormatCurrentUserKeyPath
|| !pNtDeleteKey
)
2444 win_skip( "Can't perform symlink tests\n" );
2448 pRtlFormatCurrentUserKeyPath( &target_str
);
2450 target_len
= target_str
.Length
+ sizeof(targetW
);
2451 target
= HeapAlloc( GetProcessHeap(), 0, target_len
);
2452 memcpy( target
, target_str
.Buffer
, target_str
.Length
);
2453 memcpy( target
+ target_str
.Length
/sizeof(WCHAR
), targetW
, sizeof(targetW
) );
2455 err
= RegCreateKeyExA( hkey_main
, "link", 0, NULL
, REG_OPTION_CREATE_LINK
,
2456 KEY_ALL_ACCESS
, NULL
, &link
, NULL
);
2457 ok( err
== ERROR_SUCCESS
, "RegCreateKeyEx failed: %lu\n", err
);
2459 /* REG_SZ is not allowed */
2460 err
= RegSetValueExA( link
, "SymbolicLinkValue", 0, REG_SZ
, (BYTE
*)"foobar", sizeof("foobar") );
2461 ok( err
== ERROR_ACCESS_DENIED
, "RegSetValueEx wrong error %lu\n", err
);
2462 err
= RegSetValueExA( link
, "SymbolicLinkValue", 0, REG_LINK
,
2463 (BYTE
*)target
, target_len
- sizeof(WCHAR
) );
2464 ok( err
== ERROR_SUCCESS
, "RegSetValueEx failed error %lu\n", err
);
2465 /* other values are not allowed */
2466 err
= RegSetValueExA( link
, "link", 0, REG_LINK
, (BYTE
*)target
, target_len
- sizeof(WCHAR
) );
2467 ok( err
== ERROR_ACCESS_DENIED
, "RegSetValueEx wrong error %lu\n", err
);
2469 /* try opening the target through the link */
2471 err
= RegOpenKeyA( hkey_main
, "link", &key
);
2472 ok( err
== ERROR_FILE_NOT_FOUND
, "RegOpenKey wrong error %lu\n", err
);
2474 err
= RegCreateKeyExA( hkey_main
, "target", 0, NULL
, 0, KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2475 ok( err
== ERROR_SUCCESS
, "RegCreateKeyEx failed error %lu\n", err
);
2478 err
= RegSetValueExA( key
, "value", 0, REG_DWORD
, (BYTE
*)&dw
, sizeof(dw
) );
2479 ok( err
== ERROR_SUCCESS
, "RegSetValueEx failed error %lu\n", err
);
2482 err
= RegOpenKeyA( hkey_main
, "link", &key
);
2483 ok( err
== ERROR_SUCCESS
, "RegOpenKey failed error %lu\n", err
);
2485 len
= sizeof(buffer
);
2486 err
= RegQueryValueExA( key
, "value", NULL
, &type
, buffer
, &len
);
2487 ok( err
== ERROR_SUCCESS
, "RegOpenKey failed error %lu\n", err
);
2488 ok( len
== sizeof(DWORD
), "wrong len %lu\n", len
);
2490 len
= sizeof(buffer
);
2491 err
= RegQueryValueExA( key
, "SymbolicLinkValue", NULL
, &type
, buffer
, &len
);
2492 ok( err
== ERROR_FILE_NOT_FOUND
, "RegQueryValueEx wrong error %lu\n", err
);
2494 /* REG_LINK can be created in non-link keys */
2495 err
= RegSetValueExA( key
, "SymbolicLinkValue", 0, REG_LINK
,
2496 (BYTE
*)target
, target_len
- sizeof(WCHAR
) );
2497 ok( err
== ERROR_SUCCESS
, "RegSetValueEx failed error %lu\n", err
);
2498 len
= sizeof(buffer
);
2499 err
= RegQueryValueExA( key
, "SymbolicLinkValue", NULL
, &type
, buffer
, &len
);
2500 ok( err
== ERROR_SUCCESS
, "RegQueryValueEx failed error %lu\n", err
);
2501 ok( len
== target_len
- sizeof(WCHAR
), "wrong len %lu\n", len
);
2502 err
= RegDeleteValueA( key
, "SymbolicLinkValue" );
2503 ok( err
== ERROR_SUCCESS
, "RegDeleteValue failed error %lu\n", err
);
2507 err
= RegCreateKeyExA( hkey_main
, "link", 0, NULL
, 0, KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2508 ok( err
== ERROR_SUCCESS
, "RegCreateKeyEx failed error %lu\n", err
);
2510 len
= sizeof(buffer
);
2511 err
= RegQueryValueExA( key
, "value", NULL
, &type
, buffer
, &len
);
2512 ok( err
== ERROR_SUCCESS
, "RegQueryValueEx failed error %lu\n", err
);
2513 ok( len
== sizeof(DWORD
), "wrong len %lu\n", len
);
2515 err
= RegQueryValueExA( key
, "SymbolicLinkValue", NULL
, &type
, buffer
, &len
);
2516 ok( err
== ERROR_FILE_NOT_FOUND
, "RegQueryValueEx wrong error %lu\n", err
);
2519 /* now open the symlink itself */
2521 err
= RegOpenKeyExA( hkey_main
, "link", REG_OPTION_OPEN_LINK
, KEY_ALL_ACCESS
, &key
);
2522 ok( err
== ERROR_SUCCESS
, "RegOpenKeyEx failed error %lu\n", err
);
2523 len
= sizeof(buffer
);
2524 err
= RegQueryValueExA( key
, "SymbolicLinkValue", NULL
, &type
, buffer
, &len
);
2525 ok( err
== ERROR_SUCCESS
, "RegQueryValueEx failed error %lu\n", err
);
2526 ok( len
== target_len
- sizeof(WCHAR
), "wrong len %lu\n", len
);
2529 err
= RegCreateKeyExA( hkey_main
, "link", 0, NULL
, REG_OPTION_OPEN_LINK
,
2530 KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2531 ok( err
== ERROR_SUCCESS
, "RegCreateKeyEx failed error %lu\n", err
);
2532 len
= sizeof(buffer
);
2533 err
= RegQueryValueExA( key
, "SymbolicLinkValue", NULL
, &type
, buffer
, &len
);
2534 ok( err
== ERROR_SUCCESS
, "RegQueryValueEx failed error %lu\n", err
);
2535 ok( len
== target_len
- sizeof(WCHAR
), "wrong len %lu\n", len
);
2538 err
= RegCreateKeyExA( hkey_main
, "link", 0, NULL
, REG_OPTION_CREATE_LINK
,
2539 KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2540 ok( err
== ERROR_ALREADY_EXISTS
, "RegCreateKeyEx wrong error %lu\n", err
);
2542 err
= RegCreateKeyExA( hkey_main
, "link", 0, NULL
, REG_OPTION_CREATE_LINK
| REG_OPTION_OPEN_LINK
,
2543 KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2544 ok( err
== ERROR_ALREADY_EXISTS
, "RegCreateKeyEx wrong error %lu\n", err
);
2546 err
= RegDeleteKeyA( hkey_main
, "target" );
2547 ok( err
== ERROR_SUCCESS
, "RegDeleteKey failed error %lu\n", err
);
2549 err
= RegDeleteKeyA( hkey_main
, "link" );
2550 ok( err
== ERROR_FILE_NOT_FOUND
, "RegDeleteKey wrong error %lu\n", err
);
2552 status
= pNtDeleteKey( link
);
2553 ok( !status
, "NtDeleteKey failed: 0x%08lx\n", status
);
2554 RegCloseKey( link
);
2556 HeapFree( GetProcessHeap(), 0, target
);
2557 pRtlFreeUnicodeString( &target_str
);
2560 static DWORD
get_key_value( HKEY root
, const char *name
, DWORD flags
)
2563 DWORD err
, type
, dw
= 1, len
= sizeof(dw
);
2565 err
= RegOpenKeyExA( root
, name
, 0, flags
| KEY_ALL_ACCESS
, &key
);
2566 if (err
== ERROR_FILE_NOT_FOUND
) return 0;
2567 ok( err
== ERROR_SUCCESS
, "%08lx: RegOpenKeyEx failed: %lu\n", flags
, err
);
2569 err
= RegQueryValueExA( key
, "value", NULL
, &type
, (BYTE
*)&dw
, &len
);
2570 if (err
== ERROR_FILE_NOT_FOUND
)
2573 ok( err
== ERROR_SUCCESS
, "%08lx: RegQueryValueEx failed: %lu\n", flags
, err
);
2578 static void _check_key_value( int line
, HANDLE root
, const char *name
, DWORD flags
, DWORD expect
)
2580 DWORD dw
= get_key_value( root
, name
, flags
);
2581 ok_(__FILE__
,line
)( dw
== expect
, "%08lx: wrong value %lu/%lu\n", flags
, dw
, expect
);
2583 #define check_key_value(root,name,flags,expect) _check_key_value( __LINE__, root, name, flags, expect )
2585 static void _check_enum_value( int line
, const char *name
, DWORD flags
, DWORD subkeys_in
, BOOL found_in
)
2588 DWORD err
, i
, subkeys
;
2592 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, name
, 0, flags
, &key
);
2593 ok_( __FILE__
, line
)( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
2595 err
= RegQueryInfoKeyA( key
, NULL
, NULL
, NULL
, &subkeys
,
2596 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2597 ok_( __FILE__
, line
)( err
== ERROR_SUCCESS
, "RegQueryInfoKeyA failed: %lu\n", err
);
2598 ok_( __FILE__
, line
)( subkeys
== subkeys_in
, "wrong number of subkeys: %lu\n", subkeys
);
2601 for (i
= 0; i
< subkeys
; i
++)
2603 err
= RegEnumKeyA( key
, i
, buffer
, sizeof(buffer
) );
2604 ok_( __FILE__
, line
)( err
== ERROR_SUCCESS
, "RegEnumKeyA failed: %lu\n", err
);
2606 if (!strcmp(buffer
, "Wine"))
2609 ok_( __FILE__
, line
)( found
== found_in
, "found equals %d\n", found
);
2612 #define check_enum_value(name, flags, subkeys, found) _check_enum_value( __LINE__, name, flags, subkeys, found )
2614 static void test_redirection(void)
2616 DWORD err
, type
, dw
, len
;
2617 HKEY key
, key32
, key64
, root
, root32
, root64
;
2618 DWORD subkeys
, subkeys32
, subkeys64
;
2623 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
) || !is_wow64
)
2625 skip( "Not on Wow64, no redirection\n" );
2632 skip("not enough privileges to modify HKLM\n");
2636 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wine", 0, NULL
, 0,
2637 KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, NULL
, &root64
, NULL
);
2638 ok( err
== ERROR_SUCCESS
, "RegCreateKeyExA failed: %lu\n", err
);
2640 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wine", 0, NULL
, 0,
2641 KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, NULL
, &root32
, NULL
);
2642 ok( err
== ERROR_SUCCESS
, "RegCreateKeyExA failed: %lu\n", err
);
2644 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wine\\Winetest", 0, NULL
, 0,
2645 KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, NULL
, &key64
, NULL
);
2646 ok( err
== ERROR_SUCCESS
, "RegCreateKeyExA failed: %lu\n", err
);
2648 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wine\\Winetest", 0, NULL
, 0,
2649 KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, NULL
, &key32
, NULL
);
2650 ok( err
== ERROR_SUCCESS
, "RegCreateKeyExA failed: %lu\n", err
);
2653 err
= RegSetValueExA( key64
, "value", 0, REG_DWORD
, (BYTE
*)&dw
, sizeof(dw
) );
2654 ok( err
== ERROR_SUCCESS
, "RegSetValueExA failed: %lu\n", err
);
2657 err
= RegSetValueExA( key32
, "value", 0, REG_DWORD
, (BYTE
*)&dw
, sizeof(dw
) );
2658 ok( err
== ERROR_SUCCESS
, "RegSetValueExA failed: %lu\n", err
);
2662 err
= RegQueryValueExA( key32
, "value", NULL
, &type
, (BYTE
*)&dw
, &len
);
2663 ok( err
== ERROR_SUCCESS
, "RegQueryValueExA failed: %lu\n", err
);
2664 ok( dw
== 32, "wrong value %lu\n", dw
);
2668 err
= RegQueryValueExA( key64
, "value", NULL
, &type
, (BYTE
*)&dw
, &len
);
2669 ok( err
== ERROR_SUCCESS
, "RegQueryValueExA failed: %lu\n", err
);
2670 ok( dw
== 64, "wrong value %lu\n", dw
);
2672 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software", 0, NULL
, 0,
2673 KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2674 ok( err
== ERROR_SUCCESS
, "RegCreateKeyExA failed: %lu\n", err
);
2675 check_key_value( key
, "Wine\\Winetest", 0, ptr_size
);
2676 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, ptr_size
);
2677 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
2678 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", 0, ptr_size
== 32 ? 0 : 32 );
2679 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY
, ptr_size
== 32 ? 0 : 32 );
2680 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY
, ptr_size
== 32 ? 0 : 32 );
2683 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software", 0, NULL
, 0,
2684 KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2685 ok( err
== ERROR_SUCCESS
, "RegCreateKeyExA failed: %lu\n", err
);
2686 dw
= get_key_value( key
, "Wine\\Winetest", 0 );
2687 ok( dw
== 64 || broken(dw
== 32) /* win7 */, "wrong value %lu\n", dw
);
2688 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, 64 );
2689 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
2690 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", 0, 32 );
2691 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY
, 32 );
2692 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
2695 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software", 0, NULL
, 0,
2696 KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2697 ok( err
== ERROR_SUCCESS
, "RegCreateKeyExA failed: %lu\n", err
);
2698 check_key_value( key
, "Wine\\Winetest", 0, 32 );
2699 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, 32 );
2700 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
2701 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", 0, 0 );
2702 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY
, 0 );
2703 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY
, 0 );
2706 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Wine\\Winetest", 0, ptr_size
);
2707 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Wow6432Node\\Wine\\Winetest", 0, 32 );
2708 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Wine\\Winetest", KEY_WOW64_64KEY
, 64 );
2709 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
2710 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY
, 32 );
2711 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
2713 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wow6432Node", 0, NULL
, 0,
2714 KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2715 ok( err
== ERROR_SUCCESS
, "RegCreateKeyExA failed: %lu\n", err
);
2716 check_key_value( key
, "Wine\\Winetest", 0, 32 );
2717 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, 32 );
2718 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
2721 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wow6432Node", 0, NULL
, 0,
2722 KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2723 ok( err
== ERROR_SUCCESS
, "RegCreateKeyExA failed: %lu\n", err
);
2724 check_key_value( key
, "Wine\\Winetest", 0, 32 );
2725 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, 32 );
2726 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
2729 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wow6432Node", 0, NULL
, 0,
2730 KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2731 ok( err
== ERROR_SUCCESS
, "RegCreateKeyExA failed: %lu\n", err
);
2732 check_key_value( key
, "Wine\\Winetest", 0, 32 );
2733 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, 32 );
2734 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
2737 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wow6432Node\\Wine", 0, NULL
, 0,
2738 KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2739 ok( err
== ERROR_SUCCESS
, "RegCreateKeyExA failed: %lu\n", err
);
2740 check_key_value( key
, "Winetest", 0, 32 );
2741 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, 32 );
2742 check_key_value( key
, "Winetest", KEY_WOW64_32KEY
, 32 );
2745 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wow6432Node\\Wine", 0, NULL
, 0,
2746 KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2747 ok( err
== ERROR_SUCCESS
, "RegCreateKeyExA failed: %lu\n", err
);
2748 check_key_value( key
, "Winetest", 0, 32 );
2749 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, 32 );
2750 check_key_value( key
, "Winetest", KEY_WOW64_32KEY
, 32 );
2753 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wow6432Node\\Wine", 0, NULL
, 0,
2754 KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2755 ok( err
== ERROR_SUCCESS
, "RegCreateKeyExA failed: %lu\n", err
);
2756 check_key_value( key
, "Winetest", 0, 32 );
2757 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, 32 );
2758 check_key_value( key
, "Winetest", KEY_WOW64_32KEY
, 32 );
2761 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wine", 0, NULL
, 0,
2762 KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2763 ok( err
== ERROR_SUCCESS
, "RegCreateKeyExA failed: %lu\n", err
);
2764 check_key_value( key
, "Winetest", 0, ptr_size
);
2765 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, ptr_size
);
2766 check_key_value( key
, "Winetest", KEY_WOW64_32KEY
, 32 );
2769 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wine", 0, NULL
, 0,
2770 KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2771 ok( err
== ERROR_SUCCESS
, "RegCreateKeyExA failed: %lu\n", err
);
2772 check_key_value( key
, "Winetest", 0, 64 );
2773 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, 64 );
2774 check_key_value( key
, "Winetest", KEY_WOW64_32KEY
, 32 );
2777 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wine", 0, NULL
, 0,
2778 KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2779 ok( err
== ERROR_SUCCESS
, "RegCreateKeyExA failed: %lu\n", err
);
2780 check_key_value( key
, "Winetest", 0, 32 );
2781 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, 32 );
2782 check_key_value( key
, "Winetest", KEY_WOW64_32KEY
, 32 );
2785 if (pRegDeleteKeyExA
)
2787 err
= pRegDeleteKeyExA( key32
, "", KEY_WOW64_32KEY
, 0 );
2788 ok( err
== ERROR_SUCCESS
, "RegDeleteKey failed: %lu\n", err
);
2789 err
= pRegDeleteKeyExA( key64
, "", KEY_WOW64_64KEY
, 0 );
2790 ok( err
== ERROR_SUCCESS
, "RegDeleteKey failed: %lu\n", err
);
2791 pRegDeleteKeyExA( key64
, "", KEY_WOW64_64KEY
, 0 );
2792 pRegDeleteKeyExA( root64
, "", KEY_WOW64_64KEY
, 0 );
2796 err
= RegDeleteKeyA( key32
, "" );
2797 ok( err
== ERROR_SUCCESS
, "RegDeleteKey failed: %lu\n", err
);
2798 err
= RegDeleteKeyA( key64
, "" );
2799 ok( err
== ERROR_SUCCESS
, "RegDeleteKey failed: %lu\n", err
);
2800 RegDeleteKeyA( key64
, "" );
2801 RegDeleteKeyA( root64
, "" );
2803 RegCloseKey( key32
);
2804 RegCloseKey( key64
);
2805 RegCloseKey( root32
);
2806 RegCloseKey( root64
);
2808 /* Software\Classes is shared/reflected so behavior is different */
2810 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wine",
2811 0, NULL
, 0, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, NULL
, &key64
, NULL
);
2812 if (err
== ERROR_ACCESS_DENIED
)
2814 skip("Not authorized to modify the Classes key\n");
2817 ok( err
== ERROR_SUCCESS
, "RegCreateKeyA failed: %lu\n", err
);
2819 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wow6432Node\\Wine",
2820 0, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &key
);
2821 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
2824 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wow6432Node\\Wine",
2825 0, KEY_ALL_ACCESS
, &key
);
2826 ok( err
== (ptr_size
== 64 ? ERROR_FILE_NOT_FOUND
: ERROR_SUCCESS
),
2827 "RegOpenKeyExA failed: %lu\n", err
);
2828 if (!err
) RegCloseKey( key
);
2830 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wow6432Node\\Wine",
2831 0, NULL
, 0, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, NULL
, &key32
, NULL
);
2832 ok( err
== ERROR_SUCCESS
, "RegCreateKeyA failed: %lu\n", err
);
2835 err
= RegSetValueExA( key32
, "value", 0, REG_DWORD
, (BYTE
*)&dw
, sizeof(dw
) );
2836 ok( err
== ERROR_SUCCESS
, "RegSetValueExA failed: %lu\n", err
);
2839 err
= RegSetValueExA( key64
, "value", 0, REG_DWORD
, (BYTE
*)&dw
, sizeof(dw
) );
2840 ok( err
== ERROR_SUCCESS
, "RegSetValueExA failed: %lu\n", err
);
2842 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wine", 0, 64 );
2843 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wine", KEY_WOW64_64KEY
, 64 );
2844 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wine", KEY_WOW64_32KEY
, 64 );
2845 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wow6432Node\\Wine", 0, ptr_size
== 64 ? 0 : 64 );
2846 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wow6432Node\\Wine", KEY_WOW64_64KEY
, 0 );
2847 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wow6432Node\\Wine", KEY_WOW64_32KEY
, 64 );
2849 RegDeleteKeyA( key32
, "" );
2850 RegCloseKey( key32
);
2852 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wine", 0, 0 );
2853 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wine", KEY_WOW64_64KEY
, 0 );
2854 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wine", KEY_WOW64_32KEY
, 0 );
2855 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wow6432Node\\Wine", 0, 0 );
2856 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wow6432Node\\Wine", KEY_WOW64_64KEY
, 0 );
2857 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wow6432Node\\Wine", KEY_WOW64_32KEY
, 0 );
2859 RegDeleteKeyA( key64
, "" );
2860 RegCloseKey( key64
);
2862 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes", 0, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &root64
);
2863 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
2865 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes", 0, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &root32
);
2866 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
2868 err
= RegCreateKeyExA( root64
, "Wine", 0, NULL
, 0,
2869 KEY_ALL_ACCESS
, NULL
, &key64
, NULL
);
2870 ok( err
== ERROR_SUCCESS
, "RegCreateKeyA failed: %lu\n", err
);
2872 err
= RegCreateKeyExA( key64
, "Wine", 0, NULL
, 0,
2873 KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
2874 ok( err
== ERROR_SUCCESS
, "RegCreateKeyA failed: %lu\n", err
);
2875 RegDeleteKeyA( key
, "" );
2878 err
= RegOpenKeyExA( root32
, "Wine", 0, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &key
);
2879 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
2882 err
= RegOpenKeyExA( root32
, "Wine", 0, KEY_ALL_ACCESS
, &key
);
2883 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
2886 err
= RegCreateKeyExA( root32
, "Wine", 0, NULL
, 0,
2887 KEY_ALL_ACCESS
, NULL
, &key32
, NULL
);
2888 ok( err
== ERROR_SUCCESS
, "RegCreateKeyA failed: %lu\n", err
);
2891 err
= RegSetValueExA( key32
, "value", 0, REG_DWORD
, (BYTE
*)&dw
, sizeof(dw
) );
2892 ok( err
== ERROR_SUCCESS
, "RegSetValueExA failed: %lu\n", err
);
2895 err
= RegSetValueExA( key64
, "value", 0, REG_DWORD
, (BYTE
*)&dw
, sizeof(dw
) );
2896 ok( err
== ERROR_SUCCESS
, "RegSetValueExA failed: %lu\n", err
);
2898 check_key_value( root64
, "Wine", 0, 64 );
2899 check_key_value( root64
, "Wine", KEY_WOW64_64KEY
, 64 );
2900 check_key_value( root64
, "Wine", KEY_WOW64_32KEY
, 64 );
2901 check_key_value( root32
, "Wine", 0, 64 );
2902 check_key_value( root32
, "Wine", KEY_WOW64_64KEY
, 64 );
2903 check_key_value( root32
, "Wine", KEY_WOW64_32KEY
, 64 );
2905 RegDeleteKeyA( key32
, "" );
2906 RegCloseKey( key32
);
2908 check_key_value( root64
, "Wine", 0, 0 );
2909 check_key_value( root64
, "Wine", KEY_WOW64_64KEY
, 0 );
2910 check_key_value( root64
, "Wine", KEY_WOW64_32KEY
, 0 );
2911 check_key_value( root32
, "Wine", 0, 0 );
2912 check_key_value( root32
, "Wine", KEY_WOW64_64KEY
, 0 );
2913 check_key_value( root32
, "Wine", KEY_WOW64_32KEY
, 0 );
2915 RegDeleteKeyA( key64
, "" );
2916 RegCloseKey( key64
);
2918 err
= RegCreateKeyExA( root32
, "Wine", 0, NULL
, 0,
2919 KEY_ALL_ACCESS
, NULL
, &key32
, NULL
);
2920 ok( err
== ERROR_SUCCESS
, "RegCreateKeyA failed: %lu\n", err
);
2923 err
= RegSetValueExA( key32
, "value", 0, REG_DWORD
, (BYTE
*)&dw
, sizeof(dw
) );
2924 ok( err
== ERROR_SUCCESS
, "RegSetValueExA failed: %lu\n", err
);
2926 check_key_value( root64
, "Wine", 0, 32 );
2927 check_key_value( root64
, "Wine", KEY_WOW64_64KEY
, 32 );
2928 check_key_value( root64
, "Wine", KEY_WOW64_32KEY
, 32 );
2929 check_key_value( root32
, "Wine", 0, 32 );
2930 check_key_value( root32
, "Wine", KEY_WOW64_64KEY
, 32 );
2931 check_key_value( root32
, "Wine", KEY_WOW64_32KEY
, 32 );
2933 RegDeleteKeyA( key32
, "" );
2934 RegCloseKey( key32
);
2936 RegCloseKey( root64
);
2937 RegCloseKey( root32
);
2939 err
= RegOpenKeyExA( HKEY_CLASSES_ROOT
, "Interface",
2940 0, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &root64
);
2941 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
2943 err
= RegOpenKeyExA( HKEY_CLASSES_ROOT
, "Interface",
2944 0, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &root32
);
2945 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
2947 err
= RegOpenKeyExA( HKEY_CLASSES_ROOT
, "Interface",
2948 0, KEY_ALL_ACCESS
, &root
);
2949 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
2951 err
= RegCreateKeyExA( root32
, "Wine", 0, NULL
, 0,
2952 KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, NULL
, &key32
, NULL
);
2953 ok( err
== ERROR_SUCCESS
, "RegCreateKeyA failed: %lu\n", err
);
2955 err
= RegOpenKeyExA( root
, "Wine", 0, KEY_ALL_ACCESS
, &key
);
2956 ok( err
== (ptr_size
== 64 ? ERROR_FILE_NOT_FOUND
: ERROR_SUCCESS
),
2957 "RegOpenKeyExA failed: %lu\n", err
);
2958 if (!err
) RegCloseKey( key
);
2960 RegDeleteKeyA( key32
, "" );
2961 RegCloseKey( key32
);
2963 err
= RegCreateKeyExA( root64
, "Wine", 0, NULL
, 0,
2964 KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, NULL
, &key64
, NULL
);
2965 ok( err
== ERROR_SUCCESS
, "RegCreateKeyA failed: %lu\n", err
);
2967 err
= RegOpenKeyExA( root
, "Wine", 0, KEY_ALL_ACCESS
, &key
);
2968 ok( err
== (ptr_size
== 32 ? ERROR_FILE_NOT_FOUND
: ERROR_SUCCESS
),
2969 "RegOpenKeyExA failed: %lu\n", err
);
2970 if (!err
) RegCloseKey( key
);
2972 RegDeleteKeyA( key64
, "" );
2973 RegCloseKey( key64
);
2975 RegDeleteKeyA( root64
, "" );
2976 RegDeleteKeyA( root32
, "" );
2977 RegDeleteKeyA( root
, "" );
2979 RegCloseKey( root64
);
2980 RegCloseKey( root32
);
2981 RegCloseKey( root
);
2983 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes",
2984 0, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &root64
);
2985 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
2987 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes",
2988 0, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &root32
);
2989 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
2991 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes",
2992 0, KEY_ALL_ACCESS
, &root
);
2993 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
2995 err
= RegOpenKeyExA( root64
, "Interface",
2996 0, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &key64
);
2997 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
2999 err
= RegOpenKeyExA( root32
, "Interface",
3000 0, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &key32
);
3001 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
3003 err
= RegOpenKeyExA( root
, "Interface",
3004 0, KEY_ALL_ACCESS
, &key
);
3005 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
3007 RegCloseKey( root64
);
3008 RegCloseKey( root32
);
3009 RegCloseKey( root
);
3015 err
= RegCreateKeyExA( root32
, "Wine", 0, NULL
, 0,
3016 KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, NULL
, &key32
, NULL
);
3017 ok( err
== ERROR_SUCCESS
, "RegCreateKeyA failed: %lu\n", err
);
3019 err
= RegOpenKeyExA( root
, "Wine", 0, KEY_ALL_ACCESS
, &key
);
3020 ok( err
== (ptr_size
== 64 ? ERROR_FILE_NOT_FOUND
: ERROR_SUCCESS
),
3021 "RegOpenKeyExA failed: %lu\n", err
);
3022 if (!err
) RegCloseKey( key
);
3024 RegDeleteKeyA( key32
, "" );
3025 RegCloseKey( key32
);
3027 err
= RegCreateKeyExA( root64
, "Wine", 0, NULL
, 0,
3028 KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, NULL
, &key64
, NULL
);
3029 ok( err
== ERROR_SUCCESS
, "RegCreateKeyA failed: %lu\n", err
);
3031 err
= RegOpenKeyExA( root
, "Wine", 0, KEY_ALL_ACCESS
, &key
);
3032 ok( err
== (ptr_size
== 32 ? ERROR_FILE_NOT_FOUND
: ERROR_SUCCESS
),
3033 "RegOpenKeyExA failed: %lu\n", err
);
3034 if (!err
) RegCloseKey( key
);
3036 RegDeleteKeyA( key64
, "" );
3037 RegCloseKey( key64
);
3039 RegDeleteKeyA( root
, "" );
3040 RegCloseKey( root
);
3042 err
= RegCreateKeyExA( root64
, "Wine", 0, NULL
, 0,
3043 KEY_ALL_ACCESS
, NULL
, &key64
, NULL
);
3044 ok( err
== ERROR_SUCCESS
, "RegCreateKeyA failed: %lu\n", err
);
3046 err
= RegOpenKeyExA( root32
, "Wine", 0, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &key
);
3047 ok( err
== ERROR_FILE_NOT_FOUND
, "RegOpenKeyExA failed: %lu\n", err
);
3049 err
= RegOpenKeyExA( root32
, "Wine", 0, KEY_ALL_ACCESS
, &key
);
3050 ok( err
== ERROR_FILE_NOT_FOUND
, "RegOpenKeyExA failed: %lu\n", err
);
3052 err
= RegCreateKeyExA( root32
, "Wine", 0, NULL
, 0,
3053 KEY_ALL_ACCESS
, NULL
, &key32
, NULL
);
3054 ok( err
== ERROR_SUCCESS
, "RegCreateKeyA failed: %lu\n", err
);
3057 err
= RegSetValueExA( key32
, "value", 0, REG_DWORD
, (BYTE
*)&dw
, sizeof(dw
) );
3058 ok( err
== ERROR_SUCCESS
, "RegSetValueExA failed: %lu\n", err
);
3061 err
= RegSetValueExA( key64
, "value", 0, REG_DWORD
, (BYTE
*)&dw
, sizeof(dw
) );
3062 ok( err
== ERROR_SUCCESS
, "RegSetValueExA failed: %lu\n", err
);
3064 check_key_value( root64
, "Wine", 0, 64 );
3065 check_key_value( root64
, "Wine", KEY_WOW64_64KEY
, 64 );
3066 check_key_value( root64
, "Wine", KEY_WOW64_32KEY
, 32 );
3067 check_key_value( root32
, "Wine", 0, 32 );
3068 check_key_value( root32
, "Wine", KEY_WOW64_64KEY
, 32 );
3069 check_key_value( root32
, "Wine", KEY_WOW64_32KEY
, 32 );
3071 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Interface",
3072 0, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &key
);
3073 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
3074 check_key_value( key
, "Wine", 0, 64 );
3075 check_key_value( key
, "Wine", KEY_WOW64_64KEY
, 64 );
3076 check_key_value( key
, "Wine", KEY_WOW64_32KEY
, 32 );
3079 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Interface",
3080 0, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &key
);
3081 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
3082 check_key_value( key
, "Wine", 0, 32 );
3083 check_key_value( key
, "Wine", KEY_WOW64_64KEY
, 32 );
3084 check_key_value( key
, "Wine", KEY_WOW64_32KEY
, 32 );
3087 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Interface\\Wine", 0, ptr_size
);
3088 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Interface\\Wine", KEY_WOW64_64KEY
, 64 );
3089 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Interface\\Wine", KEY_WOW64_32KEY
, 32 );
3091 RegDeleteKeyA( key32
, "" );
3092 RegCloseKey( key32
);
3094 check_key_value( root64
, "Wine", 0, 64 );
3095 check_key_value( root64
, "Wine", KEY_WOW64_64KEY
, 64 );
3096 check_key_value( root64
, "Wine", KEY_WOW64_32KEY
, 0 );
3097 check_key_value( root32
, "Wine", 0, 0 );
3098 check_key_value( root32
, "Wine", KEY_WOW64_64KEY
, 0 );
3099 check_key_value( root32
, "Wine", KEY_WOW64_32KEY
, 0 );
3101 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Interface\\Wine", 0, ptr_size
== 64 ? 64 : 0 );
3102 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Interface\\Wine", KEY_WOW64_64KEY
, 64 );
3103 check_key_value( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Interface\\Wine", KEY_WOW64_32KEY
, 0 );
3105 RegDeleteKeyA( key64
, "" );
3106 RegCloseKey( key64
);
3108 err
= RegCreateKeyExA( root32
, "Wine", 0, NULL
, 0,
3109 KEY_ALL_ACCESS
, NULL
, &key32
, NULL
);
3110 ok( err
== ERROR_SUCCESS
, "RegCreateKeyA failed: %lu\n", err
);
3113 err
= RegSetValueExA( key32
, "value", 0, REG_DWORD
, (BYTE
*)&dw
, sizeof(dw
) );
3114 ok( err
== ERROR_SUCCESS
, "RegSetValueExA failed: %lu\n", err
);
3116 check_key_value( root64
, "Wine", 0, 0 );
3117 check_key_value( root64
, "Wine", KEY_WOW64_64KEY
, 0 );
3118 check_key_value( root64
, "Wine", KEY_WOW64_32KEY
, 32 );
3119 check_key_value( root32
, "Wine", 0, 32 );
3120 check_key_value( root32
, "Wine", KEY_WOW64_64KEY
, 32 );
3121 check_key_value( root32
, "Wine", KEY_WOW64_32KEY
, 32 );
3123 RegDeleteKeyA( key32
, "" );
3124 RegCloseKey( key32
);
3126 RegCloseKey( root64
);
3127 RegCloseKey( root32
);
3129 err
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wow6432Node\\Wine",
3130 0, NULL
, 0, KEY_ALL_ACCESS
, NULL
, &key32
, NULL
);
3131 ok( err
== ERROR_SUCCESS
, "RegCreateKeyA failed: %lu\n", err
);
3133 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wow6432Node\\Wine",
3134 0, KEY_ALL_ACCESS
, &key
);
3135 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
3138 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wow6432Node\\Wine",
3139 0, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &key
);
3140 todo_wine_if(ptr_size
== 64) ok( err
== (ptr_size
== 64 ? ERROR_FILE_NOT_FOUND
: ERROR_SUCCESS
),
3141 "RegOpenKeyExA failed: %lu\n", err
);
3142 if (!err
) RegCloseKey( key
);
3144 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wow6432Node\\Wine",
3145 0, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &key
);
3146 ok( err
== (ptr_size
== 32 ? ERROR_FILE_NOT_FOUND
: ERROR_SUCCESS
),
3147 "RegOpenKeyExA failed: %lu\n", err
);
3148 if (!err
) RegCloseKey( key
);
3150 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wine",
3151 0, KEY_ALL_ACCESS
, &key
);
3152 ok( err
== (ptr_size
== 64 ? ERROR_FILE_NOT_FOUND
: ERROR_SUCCESS
),
3153 "RegOpenKeyExA failed: %lu\n", err
);
3154 if (!err
) RegCloseKey( key
);
3156 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wine",
3157 0, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &key
);
3158 todo_wine_if(ptr_size
== 64) ok( err
== (ptr_size
== 64 ? ERROR_FILE_NOT_FOUND
: ERROR_SUCCESS
),
3159 "RegOpenKeyExA failed: %lu\n", err
);
3160 if (!err
) RegCloseKey( key
);
3162 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wine",
3163 0, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &key
);
3164 ok( err
== (ptr_size
== 64 ? ERROR_FILE_NOT_FOUND
: ERROR_SUCCESS
),
3165 "RegOpenKeyExA failed: %lu\n", err
);
3166 if (!err
) RegCloseKey( key
);
3168 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\Wow6432Node",
3169 0, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &root32
);
3170 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
3172 err
= RegQueryInfoKeyA(root32
, NULL
, NULL
, NULL
, &subkeys
,
3173 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
3174 ok( err
== ERROR_SUCCESS
, "RegQueryInfoKeyA failed: %lu\n", err
);
3175 ok( subkeys
> 0, "wrong number of subkeys: %lu\n", subkeys
);
3176 subkeys32
= subkeys
;
3177 RegCloseKey( root32
);
3179 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes",
3180 0, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &root64
);
3181 ok( err
== ERROR_SUCCESS
, "RegOpenKeyExA failed: %lu\n", err
);
3183 err
= RegQueryInfoKeyA(root64
, NULL
, NULL
, NULL
, &subkeys
,
3184 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
3185 ok( err
== ERROR_SUCCESS
, "RegQueryInfoKeyA failed: %lu\n", err
);
3186 ok( subkeys
> subkeys32
, "wrong number of subkeys: %lu\n", subkeys
);
3187 subkeys64
= subkeys
;
3188 RegCloseKey( root64
);
3190 check_enum_value( "Software\\Classes",
3191 KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, subkeys64
, ptr_size
== 32 );
3192 check_enum_value( "Software\\Classes",
3193 KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, subkeys64
, ptr_size
== 32 );
3194 check_enum_value( "Software\\Classes",
3195 KEY_ALL_ACCESS
, subkeys64
, ptr_size
== 32 );
3196 check_enum_value( "Software\\Classes\\Wow6432Node",
3197 KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, subkeys32
, ptr_size
== 64 );
3198 check_enum_value( "Software\\Classes\\Wow6432Node",
3199 KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, subkeys32
, ptr_size
== 64 );
3200 check_enum_value( "Software\\Classes\\Wow6432Node",
3201 KEY_ALL_ACCESS
, subkeys32
, ptr_size
== 64 );
3202 check_enum_value( "Software\\Wow6432Node\\Classes",
3203 KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, subkeys64
, ptr_size
== 32 );
3204 check_enum_value( "Software\\Wow6432Node\\Classes",
3205 KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, subkeys32
, ptr_size
== 64 );
3206 check_enum_value( "Software\\Wow6432Node\\Classes",
3207 KEY_ALL_ACCESS
, ptr_size
== 32 ? subkeys64
: subkeys32
, TRUE
);
3209 RegDeleteKeyA( key32
, "" );
3210 RegCloseKey( key32
);
3213 static void test_classesroot(void)
3215 HKEY hkey
, hklm
, hkcr
, hkeysub1
, hklmsub1
, hkcrsub1
, hklmsub2
, hkcrsub2
;
3217 DWORD type
= REG_SZ
;
3218 static CHAR buffer
[8];
3221 /* create a key in the user's classes */
3222 if (!RegOpenKeyA( HKEY_CURRENT_USER
, "Software\\Classes\\WineTestCls", &hkey
))
3225 RegCloseKey( hkey
);
3227 res
= RegCreateKeyExA( HKEY_CURRENT_USER
, "Software\\Classes\\WineTestCls", 0, NULL
, 0,
3228 KEY_QUERY_VALUE
|KEY_SET_VALUE
, NULL
, &hkey
, NULL
);
3229 if (res
== ERROR_ACCESS_DENIED
)
3231 skip("not enough privileges to add a user class\n");
3234 ok(!IS_HKCR(hkey
), "hkcr mask set in %p\n", hkey
);
3236 /* try to open that key in hkcr */
3237 res
= RegOpenKeyExA( HKEY_CLASSES_ROOT
, "WineTestCls", 0,
3238 KEY_QUERY_VALUE
|KEY_SET_VALUE
, &hkcr
);
3239 todo_wine
ok(res
== ERROR_SUCCESS
||
3240 broken(res
== ERROR_FILE_NOT_FOUND
/* WinNT */),
3241 "test key not found in hkcr: %ld\n", res
);
3244 skip("HKCR key merging not supported\n");
3246 RegCloseKey( hkey
);
3250 todo_wine
ok(IS_HKCR(hkcr
), "hkcr mask not set in %p\n", hkcr
);
3252 /* set a value in user's classes */
3253 res
= RegSetValueExA(hkey
, "val1", 0, REG_SZ
, (const BYTE
*)"user", sizeof("user"));
3254 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3256 /* try to find the value in hkcr */
3257 res
= RegQueryValueExA(hkcr
, "val1", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3258 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld\n", res
);
3259 ok(!strcmp( buffer
, "user" ), "value set to '%s'\n", buffer
);
3261 /* modify the value in hkcr */
3262 res
= RegSetValueExA(hkcr
, "val1", 0, REG_SZ
, (const BYTE
*)"hkcr", sizeof("hkcr"));
3263 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3265 /* check if the value is also modified in user's classes */
3266 res
= RegQueryValueExA(hkey
, "val1", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3267 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3268 ok(!strcmp( buffer
, "hkcr" ), "value set to '%s'\n", buffer
);
3270 /* set a value in hkcr */
3271 res
= RegSetValueExA(hkcr
, "val0", 0, REG_SZ
, (const BYTE
*)"hkcr", sizeof("hkcr"));
3272 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3274 /* try to find the value in user's classes */
3275 res
= RegQueryValueExA(hkey
, "val0", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3276 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld\n", res
);
3277 ok(!strcmp( buffer
, "hkcr" ), "value set to '%s'\n", buffer
);
3279 /* modify the value in user's classes */
3280 res
= RegSetValueExA(hkey
, "val0", 0, REG_SZ
, (const BYTE
*)"user", sizeof("user"));
3281 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3283 /* check if the value is also modified in hkcr */
3284 res
= RegQueryValueExA(hkcr
, "val0", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3285 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3286 ok(!strcmp( buffer
, "user" ), "value set to '%s'\n", buffer
);
3291 RegCloseKey( hkey
);
3292 RegCloseKey( hkcr
);
3294 /* create a key in the hklm classes */
3295 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\WineTestCls", &hklm
))
3298 RegCloseKey( hklm
);
3300 res
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\WineTestCls", 0, NULL
, REG_OPTION_NON_VOLATILE
,
3301 KEY_ALL_ACCESS
, NULL
, &hklm
, NULL
);
3302 if (res
== ERROR_ACCESS_DENIED
)
3304 skip("not enough privileges to add a system class\n");
3307 ok(!IS_HKCR(hklm
), "hkcr mask set in %p\n", hklm
);
3309 /* try to open that key in hkcr */
3310 res
= RegOpenKeyExA( HKEY_CLASSES_ROOT
, "WineTestCls", 0,
3311 KEY_QUERY_VALUE
|KEY_SET_VALUE
, &hkcr
);
3312 ok(res
== ERROR_SUCCESS
,
3313 "test key not found in hkcr: %ld\n", res
);
3314 ok(IS_HKCR(hkcr
), "hkcr mask not set in %p\n", hkcr
);
3318 RegCloseKey( hklm
);
3322 /* set a value in hklm classes */
3323 res
= RegSetValueExA(hklm
, "val2", 0, REG_SZ
, (const BYTE
*)"hklm", sizeof("hklm"));
3324 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3326 /* try to find the value in hkcr */
3327 res
= RegQueryValueExA(hkcr
, "val2", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3328 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld\n", res
);
3329 ok(!strcmp( buffer
, "hklm" ), "value set to '%s'\n", buffer
);
3331 /* modify the value in hkcr */
3332 res
= RegSetValueExA(hkcr
, "val2", 0, REG_SZ
, (const BYTE
*)"hkcr", sizeof("hkcr"));
3333 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3335 /* check that the value is modified in hklm classes */
3336 res
= RegQueryValueExA(hklm
, "val2", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3337 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3338 ok(!strcmp( buffer
, "hkcr" ), "value set to '%s'\n", buffer
);
3340 if (RegCreateKeyExA( HKEY_CURRENT_USER
, "Software\\Classes\\WineTestCls", 0, NULL
, 0,
3341 KEY_QUERY_VALUE
|KEY_SET_VALUE
, NULL
, &hkey
, NULL
)) return;
3342 ok(!IS_HKCR(hkey
), "hkcr mask set in %p\n", hkey
);
3344 /* try to open that key in hkcr */
3345 res
= RegOpenKeyExA( HKEY_CLASSES_ROOT
, "WineTestCls", 0,
3346 KEY_QUERY_VALUE
|KEY_SET_VALUE
, &hkcr
);
3347 ok(res
== ERROR_SUCCESS
,
3348 "test key not found in hkcr: %ld\n", res
);
3349 ok(IS_HKCR(hkcr
), "hkcr mask not set in %p\n", hkcr
);
3351 /* set a value in user's classes */
3352 res
= RegSetValueExA(hkey
, "val2", 0, REG_SZ
, (const BYTE
*)"user", sizeof("user"));
3353 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3355 /* try to find the value in hkcr */
3356 res
= RegQueryValueExA(hkcr
, "val2", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3357 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld\n", res
);
3358 ok(!strcmp( buffer
, "user" ), "value set to '%s'\n", buffer
);
3360 /* modify the value in hklm */
3361 res
= RegSetValueExA(hklm
, "val2", 0, REG_SZ
, (const BYTE
*)"hklm", sizeof("hklm"));
3362 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3364 /* check that the value is not overwritten in hkcr or user's classes */
3365 res
= RegQueryValueExA(hkcr
, "val2", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3366 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld\n", res
);
3367 ok(!strcmp( buffer
, "user" ), "value set to '%s'\n", buffer
);
3368 res
= RegQueryValueExA(hkey
, "val2", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3369 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3370 ok(!strcmp( buffer
, "user" ), "value set to '%s'\n", buffer
);
3372 /* modify the value in hkcr */
3373 res
= RegSetValueExA(hkcr
, "val2", 0, REG_SZ
, (const BYTE
*)"hkcr", sizeof("hkcr"));
3374 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3376 /* check that the value is overwritten in hklm and user's classes */
3377 res
= RegQueryValueExA(hkcr
, "val2", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3378 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld\n", res
);
3379 ok(!strcmp( buffer
, "hkcr" ), "value set to '%s'\n", buffer
);
3380 res
= RegQueryValueExA(hkey
, "val2", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3381 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3382 ok(!strcmp( buffer
, "hkcr" ), "value set to '%s'\n", buffer
);
3384 /* create a subkey in hklm */
3385 if (RegCreateKeyExA( hklm
, "subkey1", 0, NULL
, 0,
3386 KEY_QUERY_VALUE
|KEY_SET_VALUE
, NULL
, &hklmsub1
, NULL
)) return;
3387 ok(!IS_HKCR(hklmsub1
), "hkcr mask set in %p\n", hklmsub1
);
3388 /* try to open that subkey in hkcr */
3389 res
= RegOpenKeyExA( hkcr
, "subkey1", 0, KEY_QUERY_VALUE
|KEY_SET_VALUE
, &hkcrsub1
);
3390 ok(res
== ERROR_SUCCESS
, "test key not found in hkcr: %ld\n", res
);
3391 ok(IS_HKCR(hkcrsub1
), "hkcr mask not set in %p\n", hkcrsub1
);
3393 /* set a value in hklm classes */
3394 res
= RegSetValueExA(hklmsub1
, "subval1", 0, REG_SZ
, (const BYTE
*)"hklm", sizeof("hklm"));
3395 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3397 /* try to find the value in hkcr */
3398 res
= RegQueryValueExA(hkcrsub1
, "subval1", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3399 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld\n", res
);
3400 ok(!strcmp( buffer
, "hklm" ), "value set to '%s'\n", buffer
);
3402 /* modify the value in hkcr */
3403 res
= RegSetValueExA(hkcrsub1
, "subval1", 0, REG_SZ
, (const BYTE
*)"hkcr", sizeof("hkcr"));
3404 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3406 /* check that the value is modified in hklm classes */
3407 res
= RegQueryValueExA(hklmsub1
, "subval1", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3408 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3409 ok(!strcmp( buffer
, "hkcr" ), "value set to '%s'\n", buffer
);
3411 /* create a subkey in user's classes */
3412 if (RegCreateKeyExA( hkey
, "subkey1", 0, NULL
, 0,
3413 KEY_QUERY_VALUE
|KEY_SET_VALUE
, NULL
, &hkeysub1
, NULL
)) return;
3414 ok(!IS_HKCR(hkeysub1
), "hkcr mask set in %p\n", hkeysub1
);
3416 /* set a value in user's classes */
3417 res
= RegSetValueExA(hkeysub1
, "subval1", 0, REG_SZ
, (const BYTE
*)"user", sizeof("user"));
3418 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3420 /* try to find the value in hkcr */
3421 res
= RegQueryValueExA(hkcrsub1
, "subval1", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3422 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld\n", res
);
3423 ok(!strcmp( buffer
, "user" ), "value set to '%s'\n", buffer
);
3425 /* modify the value in hklm */
3426 res
= RegSetValueExA(hklmsub1
, "subval1", 0, REG_SZ
, (const BYTE
*)"hklm", sizeof("hklm"));
3427 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3429 /* check that the value is not overwritten in hkcr or user's classes */
3430 res
= RegQueryValueExA(hkcrsub1
, "subval1", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3431 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld\n", res
);
3432 ok(!strcmp( buffer
, "user" ), "value set to '%s'\n", buffer
);
3433 res
= RegQueryValueExA(hkeysub1
, "subval1", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3434 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3435 ok(!strcmp( buffer
, "user" ), "value set to '%s'\n", buffer
);
3437 /* modify the value in hkcr */
3438 res
= RegSetValueExA(hkcrsub1
, "subval1", 0, REG_SZ
, (const BYTE
*)"hkcr", sizeof("hkcr"));
3439 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3441 /* check that the value is not overwritten in hklm, but in user's classes */
3442 res
= RegQueryValueExA(hklmsub1
, "subval1", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3443 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld\n", res
);
3444 ok(!strcmp( buffer
, "hklm" ), "value set to '%s'\n", buffer
);
3445 res
= RegQueryValueExA(hkeysub1
, "subval1", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3446 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3447 ok(!strcmp( buffer
, "hkcr" ), "value set to '%s'\n", buffer
);
3449 /* new subkey in hkcr */
3450 if (RegCreateKeyExA( hkcr
, "subkey2", 0, NULL
, 0,
3451 KEY_QUERY_VALUE
|KEY_SET_VALUE
, NULL
, &hkcrsub2
, NULL
)) return;
3452 ok(IS_HKCR(hkcrsub2
), "hkcr mask not set in %p\n", hkcrsub2
);
3453 res
= RegSetValueExA(hkcrsub2
, "subval1", 0, REG_SZ
, (const BYTE
*)"hkcr", sizeof("hkcr"));
3454 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld, GLE=%lx\n", res
, GetLastError());
3456 /* try to open that new subkey in user's classes and hklm */
3457 res
= RegOpenKeyExA( hkey
, "subkey2", 0, KEY_QUERY_VALUE
|KEY_SET_VALUE
, &hklmsub2
);
3458 ok(res
!= ERROR_SUCCESS
, "test key found in user's classes: %ld\n", res
);
3460 res
= RegOpenKeyExA( hklm
, "subkey2", 0, KEY_QUERY_VALUE
|KEY_SET_VALUE
, &hklmsub2
);
3461 ok(res
== ERROR_SUCCESS
, "test key not found in hklm: %ld\n", res
);
3462 ok(!IS_HKCR(hklmsub2
), "hkcr mask set in %p\n", hklmsub2
);
3464 /* check that the value is present in hklm */
3465 res
= RegQueryValueExA(hklmsub2
, "subval1", NULL
, &type
, (LPBYTE
)buffer
, &size
);
3466 ok(res
== ERROR_SUCCESS
, "RegQueryValueExA failed: %ld\n", res
);
3467 ok(!strcmp( buffer
, "hkcr" ), "value set to '%s'\n", buffer
);
3470 RegCloseKey( hkeysub1
);
3471 RegCloseKey( hklmsub1
);
3473 /* delete subkey1 from hkcr (should point at user's classes) */
3474 res
= RegDeleteKeyA(hkcr
, "subkey1");
3475 ok(res
== ERROR_SUCCESS
, "RegDeleteKey failed: %ld\n", res
);
3477 /* confirm key was removed in hkey but not hklm */
3478 res
= RegOpenKeyExA(hkey
, "subkey1", 0, KEY_READ
, &hkeysub1
);
3479 ok(res
== ERROR_FILE_NOT_FOUND
, "test key found in user's classes: %ld\n", res
);
3480 res
= RegOpenKeyExA(hklm
, "subkey1", 0, KEY_READ
, &hklmsub1
);
3481 ok(res
== ERROR_SUCCESS
, "test key not found in hklm: %ld\n", res
);
3482 ok(!IS_HKCR(hklmsub1
), "hkcr mask set in %p\n", hklmsub1
);
3484 /* delete subkey1 from hkcr again (which should now point at hklm) */
3485 res
= RegDeleteKeyA(hkcr
, "subkey1");
3486 ok(res
== ERROR_SUCCESS
, "RegDeleteKey failed: %ld\n", res
);
3488 /* confirm hkey was removed in hklm */
3489 RegCloseKey( hklmsub1
);
3490 res
= RegOpenKeyExA(hklm
, "subkey1", 0, KEY_READ
, &hklmsub1
);
3491 ok(res
== ERROR_FILE_NOT_FOUND
, "test key found in hklm: %ld\n", res
);
3497 delete_key( hkeysub1
);
3498 delete_key( hklmsub1
);
3499 delete_key( hkcrsub1
);
3500 delete_key( hklmsub2
);
3501 delete_key( hkcrsub2
);
3502 RegCloseKey( hkey
);
3503 RegCloseKey( hklm
);
3504 RegCloseKey( hkcr
);
3505 RegCloseKey( hkeysub1
);
3506 RegCloseKey( hklmsub1
);
3507 RegCloseKey( hkcrsub1
);
3508 RegCloseKey( hklmsub2
);
3509 RegCloseKey( hkcrsub2
);
3512 static void test_classesroot_enum(void)
3514 HKEY hkcu
=0, hklm
=0, hkcr
=0, hkcusub
[2]={0}, hklmsub
[2]={0};
3516 static CHAR buffer
[2];
3519 /* prepare initial testing env in HKCU */
3520 if (!RegOpenKeyA( HKEY_CURRENT_USER
, "Software\\Classes\\WineTestCls", &hkcu
))
3523 RegCloseKey( hkcu
);
3525 res
= RegCreateKeyExA( HKEY_CURRENT_USER
, "Software\\Classes\\WineTestCls", 0, NULL
, 0,
3526 KEY_SET_VALUE
|KEY_ENUMERATE_SUB_KEYS
, NULL
, &hkcu
, NULL
);
3528 if (res
!= ERROR_SUCCESS
)
3530 skip("failed to add a user class\n");
3534 res
= RegOpenKeyA( HKEY_CLASSES_ROOT
, "WineTestCls", &hkcr
);
3535 todo_wine
ok(res
== ERROR_SUCCESS
||
3536 broken(res
== ERROR_FILE_NOT_FOUND
/* WinNT */),
3537 "test key not found in hkcr: %ld\n", res
);
3540 skip("HKCR key merging not supported\n");
3542 RegCloseKey( hkcu
);
3546 res
= RegSetValueExA( hkcu
, "X", 0, REG_SZ
, (const BYTE
*) "AA", 3 );
3547 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld\n", res
);
3548 res
= RegSetValueExA( hkcu
, "Y", 0, REG_SZ
, (const BYTE
*) "B", 2 );
3549 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld\n", res
);
3550 res
= RegCreateKeyA( hkcu
, "A", &hkcusub
[0] );
3551 ok(res
== ERROR_SUCCESS
, "RegCreateKeyA failed: %ld\n", res
);
3552 res
= RegCreateKeyA( hkcu
, "B", &hkcusub
[1] );
3553 ok(res
== ERROR_SUCCESS
, "RegCreateKeyA failed: %ld\n", res
);
3555 /* test on values in HKCU */
3556 size
= sizeof(buffer
);
3557 res
= RegEnumValueA( hkcr
, 0, buffer
, &size
, NULL
, NULL
, NULL
, NULL
);
3558 ok(res
== ERROR_SUCCESS
, "RegEnumValueA failed: %ld\n", res
);
3559 ok(!strcmp( buffer
, "X" ), "expected 'X', got '%s'\n", buffer
);
3560 size
= sizeof(buffer
);
3561 res
= RegEnumValueA( hkcr
, 1, buffer
, &size
, NULL
, NULL
, NULL
, NULL
);
3562 ok(res
== ERROR_SUCCESS
, "RegEnumValueA failed: %ld\n", res
);
3563 ok(!strcmp( buffer
, "Y" ), "expected 'Y', got '%s'\n", buffer
);
3564 size
= sizeof(buffer
);
3565 res
= RegEnumValueA( hkcr
, 2, buffer
, &size
, NULL
, NULL
, NULL
, NULL
);
3566 ok(res
== ERROR_NO_MORE_ITEMS
, "expected ERROR_NO_MORE_ITEMS, got %ld\n", res
);
3568 res
= RegEnumKeyA( hkcr
, 0, buffer
, size
);
3569 ok(res
== ERROR_SUCCESS
, "RegEnumKey failed: %ld\n", res
);
3570 ok(!strcmp( buffer
, "A" ), "expected 'A', got '%s'\n", buffer
);
3571 res
= RegEnumKeyA( hkcr
, 1, buffer
, size
);
3572 ok(res
== ERROR_SUCCESS
, "RegEnumKey failed: %ld\n", res
);
3573 ok(!strcmp( buffer
, "B" ), "expected 'B', got '%s'\n", buffer
);
3574 res
= RegEnumKeyA( hkcr
, 2, buffer
, size
);
3575 ok(res
== ERROR_NO_MORE_ITEMS
, "expected ERROR_NO_MORE_ITEMS, got %ld\n", res
);
3577 /* prepare test env in HKLM */
3578 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\WineTestCls", &hklm
))
3581 RegCloseKey( hklm
);
3584 res
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Classes\\WineTestCls", 0, NULL
, 0,
3585 KEY_SET_VALUE
|KEY_ENUMERATE_SUB_KEYS
, NULL
, &hklm
, NULL
);
3587 if (res
== ERROR_ACCESS_DENIED
)
3589 RegCloseKey( hkcusub
[0] );
3590 RegCloseKey( hkcusub
[1] );
3592 RegCloseKey( hkcu
);
3593 RegCloseKey( hkcr
);
3594 skip("not enough privileges to add a system class\n");
3598 res
= RegSetValueExA( hklm
, "X", 0, REG_SZ
, (const BYTE
*) "AB", 3 );
3599 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld\n", res
);
3600 res
= RegSetValueExA( hklm
, "Z", 0, REG_SZ
, (const BYTE
*) "C", 2 );
3601 ok(res
== ERROR_SUCCESS
, "RegSetValueExA failed: %ld\n", res
);
3602 res
= RegCreateKeyA( hklm
, "A", &hklmsub
[0] );
3603 ok(res
== ERROR_SUCCESS
, "RegCreateKeyA failed: %ld\n", res
);
3604 res
= RegCreateKeyA( hklm
, "C", &hklmsub
[1] );
3605 ok(res
== ERROR_SUCCESS
, "RegCreateKeyA failed: %ld\n", res
);
3607 /* test on values/keys in both HKCU and HKLM */
3608 size
= sizeof(buffer
);
3609 res
= RegEnumValueA( hkcr
, 0, buffer
, &size
, NULL
, NULL
, NULL
, NULL
);
3610 ok(res
== ERROR_SUCCESS
, "RegEnumValueA failed: %ld\n", res
);
3611 ok(!strcmp( buffer
, "X" ), "expected 'X', got '%s'\n", buffer
);
3612 size
= sizeof(buffer
);
3613 res
= RegEnumValueA( hkcr
, 1, buffer
, &size
, NULL
, NULL
, NULL
, NULL
);
3614 ok(res
== ERROR_SUCCESS
, "RegEnumValueA failed: %ld\n", res
);
3615 ok(!strcmp( buffer
, "Y" ), "expected 'Y', got '%s'\n", buffer
);
3616 size
= sizeof(buffer
);
3617 res
= RegEnumValueA( hkcr
, 2, buffer
, &size
, NULL
, NULL
, NULL
, NULL
);
3618 ok(res
== ERROR_SUCCESS
, "RegEnumValueA failed: %ld\n", res
);
3619 ok(!strcmp( buffer
, "Z" ), "expected 'Z', got '%s'\n", buffer
);
3620 size
= sizeof(buffer
);
3621 res
= RegEnumValueA( hkcr
, 3, buffer
, &size
, NULL
, NULL
, NULL
, NULL
);
3622 ok(res
== ERROR_NO_MORE_ITEMS
, "expected ERROR_NO_MORE_ITEMS, got %ld\n", res
);
3624 res
= RegEnumKeyA( hkcr
, 0, buffer
, size
);
3625 ok(res
== ERROR_SUCCESS
, "RegEnumKey failed: %ld\n", res
);
3626 ok(!strcmp( buffer
, "A" ), "expected 'A', got '%s'\n", buffer
);
3627 res
= RegEnumKeyA( hkcr
, 1, buffer
, size
);
3628 ok(res
== ERROR_SUCCESS
, "RegEnumKey failed: %ld\n", res
);
3629 ok(!strcmp( buffer
, "B" ), "expected 'B', got '%s'\n", buffer
);
3630 res
= RegEnumKeyA( hkcr
, 2, buffer
, size
);
3631 ok(res
== ERROR_SUCCESS
, "RegEnumKey failed: %ld\n", res
);
3632 ok(!strcmp( buffer
, "C" ), "expected 'C', got '%s'\n", buffer
);
3633 res
= RegEnumKeyA( hkcr
, 3, buffer
, size
);
3634 ok(res
== ERROR_NO_MORE_ITEMS
, "expected ERROR_NO_MORE_ITEMS, got %ld\n", res
);
3636 /* delete values/keys from HKCU to test only on HKLM */
3637 RegCloseKey( hkcusub
[0] );
3638 RegCloseKey( hkcusub
[1] );
3640 RegCloseKey( hkcu
);
3642 size
= sizeof(buffer
);
3643 res
= RegEnumValueA( hkcr
, 0, buffer
, &size
, NULL
, NULL
, NULL
, NULL
);
3644 ok(res
== ERROR_KEY_DELETED
||
3645 res
== ERROR_NO_SYSTEM_RESOURCES
, /* Windows XP */
3646 "expected ERROR_KEY_DELETED, got %ld\n", res
);
3647 size
= sizeof(buffer
);
3648 res
= RegEnumKeyA( hkcr
, 0, buffer
, size
);
3649 ok(res
== ERROR_KEY_DELETED
||
3650 res
== ERROR_NO_SYSTEM_RESOURCES
, /* Windows XP */
3651 "expected ERROR_KEY_DELETED, got %ld\n", res
);
3653 /* reopen HKCR handle */
3654 RegCloseKey( hkcr
);
3655 res
= RegOpenKeyA( HKEY_CLASSES_ROOT
, "WineTestCls", &hkcr
);
3656 ok(res
== ERROR_SUCCESS
, "test key not found in hkcr: %ld\n", res
);
3657 if (res
) goto cleanup
;
3659 /* test on values/keys in HKLM */
3660 size
= sizeof(buffer
);
3661 res
= RegEnumValueA( hkcr
, 0, buffer
, &size
, NULL
, NULL
, NULL
, NULL
);
3662 ok(res
== ERROR_SUCCESS
, "RegEnumValueA failed: %ld\n", res
);
3663 ok(!strcmp( buffer
, "X" ), "expected 'X', got '%s'\n", buffer
);
3664 size
= sizeof(buffer
);
3665 res
= RegEnumValueA( hkcr
, 1, buffer
, &size
, NULL
, NULL
, NULL
, NULL
);
3666 ok(res
== ERROR_SUCCESS
, "RegEnumValueA failed: %ld\n", res
);
3667 ok(!strcmp( buffer
, "Z" ), "expected 'Z', got '%s'\n", buffer
);
3668 size
= sizeof(buffer
);
3669 res
= RegEnumValueA( hkcr
, 2, buffer
, &size
, NULL
, NULL
, NULL
, NULL
);
3670 ok(res
== ERROR_NO_MORE_ITEMS
, "expected ERROR_NO_MORE_ITEMS, got %ld\n", res
);
3672 res
= RegEnumKeyA( hkcr
, 0, buffer
, size
);
3673 ok(res
== ERROR_SUCCESS
, "RegEnumKey failed: %ld\n", res
);
3674 ok(!strcmp( buffer
, "A" ), "expected 'A', got '%s'\n", buffer
);
3675 res
= RegEnumKeyA( hkcr
, 1, buffer
, size
);
3676 ok(res
== ERROR_SUCCESS
, "RegEnumKey failed: %ld\n", res
);
3677 ok(!strcmp( buffer
, "C" ), "expected 'C', got '%s'\n", buffer
);
3678 res
= RegEnumKeyA( hkcr
, 2, buffer
, size
);
3679 ok(res
== ERROR_NO_MORE_ITEMS
, "expected ERROR_NO_MORE_ITEMS, got %ld\n", res
);
3682 RegCloseKey( hklmsub
[0] );
3683 RegCloseKey( hklmsub
[1] );
3685 RegCloseKey( hklm
);
3686 RegCloseKey( hkcr
);
3689 static void test_classesroot_mask(void)
3694 res
= RegOpenKeyA( HKEY_CLASSES_ROOT
, "CLSID", &hkey
);
3695 ok(res
== ERROR_SUCCESS
, "RegOpenKeyA failed: %ld\n", res
);
3696 todo_wine
ok(IS_HKCR(hkey
) || broken(!IS_HKCR(hkey
)) /* WinNT */,
3697 "hkcr mask not set in %p\n", hkey
);
3698 RegCloseKey( hkey
);
3700 res
= RegOpenKeyA( HKEY_CURRENT_USER
, "Software", &hkey
);
3701 ok(res
== ERROR_SUCCESS
, "RegOpenKeyA failed: %ld\n", res
);
3702 ok(!IS_HKCR(hkey
), "hkcr mask set in %p\n", hkey
);
3703 RegCloseKey( hkey
);
3705 res
= RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software", &hkey
);
3706 ok(res
== ERROR_SUCCESS
, "RegOpenKeyA failed: %ld\n", res
);
3707 ok(!IS_HKCR(hkey
), "hkcr mask set in %p\n", hkey
);
3708 RegCloseKey( hkey
);
3710 res
= RegOpenKeyA( HKEY_USERS
, ".Default", &hkey
);
3711 ok(res
== ERROR_SUCCESS
, "RegOpenKeyA failed: %ld\n", res
);
3712 ok(!IS_HKCR(hkey
), "hkcr mask set in %p\n", hkey
);
3713 RegCloseKey( hkey
);
3715 res
= RegOpenKeyA( HKEY_CURRENT_CONFIG
, "Software", &hkey
);
3716 ok(res
== ERROR_SUCCESS
, "RegOpenKeyA failed: %ld\n", res
);
3717 ok(!IS_HKCR(hkey
), "hkcr mask set in %p\n", hkey
);
3718 RegCloseKey( hkey
);
3721 static void test_deleted_key(void)
3725 DWORD val_count
, type
;
3728 /* Open the test key, then delete it while it's open */
3729 RegOpenKeyA( HKEY_CURRENT_USER
, "Software\\Wine\\Test", &hkey
);
3731 delete_key( hkey_main
);
3733 val_count
= sizeof(value
);
3735 res
= RegEnumValueA( hkey
, 0, value
, &val_count
, NULL
, &type
, 0, 0 );
3736 ok(res
== ERROR_KEY_DELETED
, "expect ERROR_KEY_DELETED, got %li\n", res
);
3738 res
= RegEnumKeyA( hkey
, 0, value
, sizeof(value
) );
3739 ok(res
== ERROR_KEY_DELETED
, "expect ERROR_KEY_DELETED, got %li\n", res
);
3741 val_count
= sizeof(value
);
3743 res
= RegQueryValueExA( hkey
, "test", NULL
, &type
, (BYTE
*)value
, &val_count
);
3744 ok(res
== ERROR_KEY_DELETED
, "expect ERROR_KEY_DELETED, got %li\n", res
);
3746 res
= RegSetValueExA( hkey
, "test", 0, REG_SZ
, (const BYTE
*)"value", 6);
3747 ok(res
== ERROR_KEY_DELETED
, "expect ERROR_KEY_DELETED, got %li\n", res
);
3749 res
= RegOpenKeyA( hkey
, "test", &hkey2
);
3750 ok(res
== ERROR_KEY_DELETED
, "expect ERROR_KEY_DELETED, got %li\n", res
);
3752 RegCloseKey( hkey2
);
3754 res
= RegCreateKeyA( hkey
, "test", &hkey2
);
3755 ok(res
== ERROR_KEY_DELETED
, "expect ERROR_KEY_DELETED, got %li\n", res
);
3757 RegCloseKey( hkey2
);
3759 res
= RegFlushKey( hkey
);
3760 ok(res
== ERROR_KEY_DELETED
, "expect ERROR_KEY_DELETED, got %li\n", res
);
3762 RegCloseKey( hkey
);
3767 static void test_delete_value(void)
3772 res
= RegSetValueExA( hkey_main
, "test", 0, REG_SZ
, (const BYTE
*)"value", 6 );
3773 ok(res
== ERROR_SUCCESS
, "expect ERROR_SUCCESS, got %li\n", res
);
3775 res
= RegQueryValueExA( hkey_main
, "test", NULL
, NULL
, NULL
, NULL
);
3776 ok(res
== ERROR_SUCCESS
, "expect ERROR_SUCCESS, got %li\n", res
);
3778 res
= RegDeleteValueA( hkey_main
, "test" );
3779 ok(res
== ERROR_SUCCESS
, "expect ERROR_SUCCESS, got %li\n", res
);
3781 res
= RegQueryValueExA( hkey_main
, "test", NULL
, NULL
, NULL
, NULL
);
3782 ok(res
== ERROR_FILE_NOT_FOUND
, "expect ERROR_FILE_NOT_FOUND, got %li\n", res
);
3784 res
= RegDeleteValueA( hkey_main
, "test" );
3785 ok(res
== ERROR_FILE_NOT_FOUND
, "expect ERROR_FILE_NOT_FOUND, got %li\n", res
);
3787 memset(longname
, 'a', 400);
3789 res
= RegDeleteValueA( hkey_main
, longname
);
3790 ok(res
== ERROR_FILE_NOT_FOUND
|| broken(res
== ERROR_MORE_DATA
), /* nt4, win2k */
3791 "expect ERROR_FILE_NOT_FOUND, got %li\n", res
);
3793 /* Default registry value */
3794 res
= RegSetValueExA(hkey_main
, "", 0, REG_SZ
, (const BYTE
*)"value", 6);
3795 ok(res
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", res
);
3797 res
= RegQueryValueExA(hkey_main
, "", NULL
, NULL
, NULL
, NULL
);
3798 ok(res
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", res
);
3800 res
= RegDeleteValueA(hkey_main
, "" );
3801 ok(res
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", res
);
3803 res
= RegQueryValueExA(hkey_main
, "", NULL
, NULL
, NULL
, NULL
);
3804 ok(res
== ERROR_FILE_NOT_FOUND
, "expected ERROR_FILE_NOT_FOUND, got %ld\n", res
);
3807 static void test_delete_key_value(void)
3812 if (!pRegDeleteKeyValueA
)
3814 win_skip("RegDeleteKeyValue is not available.\n");
3818 ret
= pRegDeleteKeyValueA(NULL
, NULL
, NULL
);
3819 ok(ret
== ERROR_INVALID_HANDLE
, "got %ld\n", ret
);
3821 ret
= pRegDeleteKeyValueA(hkey_main
, NULL
, NULL
);
3822 ok(ret
== ERROR_FILE_NOT_FOUND
, "got %ld\n", ret
);
3824 ret
= RegSetValueExA(hkey_main
, "test", 0, REG_SZ
, (const BYTE
*)"value", 6);
3825 ok(ret
== ERROR_SUCCESS
, "got %ld\n", ret
);
3827 ret
= RegQueryValueExA(hkey_main
, "test", NULL
, NULL
, NULL
, NULL
);
3828 ok(ret
== ERROR_SUCCESS
, "got %ld\n", ret
);
3830 /* NULL subkey name means delete from open key */
3831 ret
= pRegDeleteKeyValueA(hkey_main
, NULL
, "test");
3832 ok(ret
== ERROR_SUCCESS
, "got %ld\n", ret
);
3834 ret
= RegQueryValueExA(hkey_main
, "test", NULL
, NULL
, NULL
, NULL
);
3835 ok(ret
== ERROR_FILE_NOT_FOUND
, "got %ld\n", ret
);
3837 /* now with real subkey */
3838 ret
= RegCreateKeyExA(hkey_main
, "Subkey1", 0, NULL
, 0, KEY_WRITE
|KEY_READ
, NULL
, &subkey
, NULL
);
3839 ok(!ret
, "failed with error %ld\n", ret
);
3841 ret
= RegSetValueExA(subkey
, "test", 0, REG_SZ
, (const BYTE
*)"value", 6);
3842 ok(ret
== ERROR_SUCCESS
, "got %ld\n", ret
);
3844 ret
= RegQueryValueExA(subkey
, "test", NULL
, NULL
, NULL
, NULL
);
3845 ok(ret
== ERROR_SUCCESS
, "got %ld\n", ret
);
3847 ret
= pRegDeleteKeyValueA(hkey_main
, "Subkey1", "test");
3848 ok(ret
== ERROR_SUCCESS
, "got %ld\n", ret
);
3850 ret
= RegQueryValueExA(subkey
, "test", NULL
, NULL
, NULL
, NULL
);
3851 ok(ret
== ERROR_FILE_NOT_FOUND
, "got %ld\n", ret
);
3853 /* Default registry value */
3854 ret
= RegSetValueExA(subkey
, "", 0, REG_SZ
, (const BYTE
*)"value", 6);
3855 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
3857 ret
= RegQueryValueExA(subkey
, "", NULL
, NULL
, NULL
, NULL
);
3858 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
3860 ret
= pRegDeleteKeyValueA(hkey_main
, "Subkey1", "" );
3861 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
3863 ret
= RegQueryValueExA(subkey
, "", NULL
, NULL
, NULL
, NULL
);
3864 ok(ret
== ERROR_FILE_NOT_FOUND
, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret
);
3866 RegDeleteKeyA(subkey
, "");
3867 RegCloseKey(subkey
);
3870 static void test_RegOpenCurrentUser(void)
3875 key
= HKEY_CURRENT_USER
;
3876 ret
= RegOpenCurrentUser(KEY_READ
, &key
);
3877 ok(!ret
, "got %ld, error %ld\n", ret
, GetLastError());
3878 ok(key
!= HKEY_CURRENT_USER
, "got %p\n", key
);
3882 struct notify_data
{
3888 static DWORD WINAPI
notify_change_thread(void *arg
)
3890 struct notify_data
*data
= arg
;
3893 ret
= RegNotifyChangeKeyValue(data
->key
, TRUE
,
3894 REG_NOTIFY_CHANGE_NAME
|data
->flags
, data
->event
, TRUE
);
3895 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
3899 static void test_RegNotifyChangeKeyValue(void)
3901 struct notify_data data
;
3902 HKEY key
, subkey
, subsubkey
;
3908 event
= CreateEventW(NULL
, FALSE
, TRUE
, NULL
);
3909 ok(event
!= NULL
, "CreateEvent failed, error %lu\n", GetLastError());
3910 ret
= RegCreateKeyA(hkey_main
, "TestKey", &key
);
3911 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
3913 ret
= RegNotifyChangeKeyValue(key
, TRUE
, REG_NOTIFY_CHANGE_NAME
|REG_NOTIFY_CHANGE_LAST_SET
, event
, TRUE
);
3914 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
3915 dwret
= WaitForSingleObject(event
, 0);
3916 ok(dwret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %lu\n", dwret
);
3918 ret
= RegCreateKeyA(key
, "SubKey", &subkey
);
3919 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
3920 dwret
= WaitForSingleObject(event
, 0);
3921 ok(dwret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %lu\n", dwret
);
3923 /* watching deeper keys */
3924 ret
= RegNotifyChangeKeyValue(key
, TRUE
, REG_NOTIFY_CHANGE_NAME
|REG_NOTIFY_CHANGE_LAST_SET
, event
, TRUE
);
3925 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
3926 dwret
= WaitForSingleObject(event
, 0);
3927 ok(dwret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %lu\n", dwret
);
3929 ret
= RegCreateKeyA(subkey
, "SubKey", &subsubkey
);
3930 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
3931 dwret
= WaitForSingleObject(event
, 0);
3932 ok(dwret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %lu\n", dwret
);
3934 /* watching deeper values */
3935 ret
= RegNotifyChangeKeyValue(key
, TRUE
, REG_NOTIFY_CHANGE_NAME
|REG_NOTIFY_CHANGE_LAST_SET
, event
, TRUE
);
3936 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
3937 dwret
= WaitForSingleObject(event
, 0);
3938 ok(dwret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %lu\n", dwret
);
3940 ret
= RegSetValueA(subsubkey
, NULL
, REG_SZ
, "SubSubKeyValue", 0);
3941 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
3942 dwret
= WaitForSingleObject(event
, 0);
3943 ok(dwret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %lu\n", dwret
);
3945 /* don't watch deeper values */
3947 ret
= RegOpenKeyA(hkey_main
, "TestKey", &key
);
3948 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
3950 ret
= RegNotifyChangeKeyValue(key
, FALSE
, REG_NOTIFY_CHANGE_NAME
|REG_NOTIFY_CHANGE_LAST_SET
, event
, TRUE
);
3951 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
3952 dwret
= WaitForSingleObject(event
, 0);
3953 ok(dwret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %lu\n", dwret
);
3955 ret
= RegSetValueA(subsubkey
, NULL
, REG_SZ
, "SubSubKeyValueNEW", 0);
3956 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
3957 dwret
= WaitForSingleObject(event
, 0);
3958 ok(dwret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %lu\n", dwret
);
3960 RegDeleteKeyA(subkey
, "SubKey");
3961 RegDeleteKeyA(key
, "SubKey");
3962 RegCloseKey(subsubkey
);
3963 RegCloseKey(subkey
);
3966 /* test same thread with REG_NOTIFY_THREAD_AGNOSTIC */
3967 ret
= RegOpenKeyA(hkey_main
, "TestKey", &key
);
3968 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
3969 ret
= RegNotifyChangeKeyValue(key
, TRUE
, REG_NOTIFY_CHANGE_NAME
|REG_NOTIFY_THREAD_AGNOSTIC
,
3971 if (ret
== ERROR_INVALID_PARAMETER
)
3973 win_skip("REG_NOTIFY_THREAD_AGNOSTIC is not supported\n");
3979 ret
= RegCreateKeyA(key
, "SubKey", &subkey
);
3980 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
3981 dwret
= WaitForSingleObject(event
, 0);
3982 ok(dwret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %lu\n", dwret
);
3984 RegDeleteKeyA(key
, "SubKey");
3985 RegCloseKey(subkey
);
3988 /* test different thread without REG_NOTIFY_THREAD_AGNOSTIC */
3989 ret
= RegOpenKeyA(hkey_main
, "TestKey", &key
);
3990 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
3995 thread
= CreateThread(NULL
, 0, notify_change_thread
, &data
, 0, NULL
);
3996 WaitForSingleObject(thread
, INFINITE
);
3997 CloseHandle(thread
);
3999 /* the thread exiting causes event to signal on Windows
4000 this is worked around on Windows using REG_NOTIFY_THREAD_AGNOSTIC
4001 Wine already behaves as if the flag is set */
4002 dwret
= WaitForSingleObject(event
, 0);
4004 ok(dwret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %lu\n", dwret
);
4007 /* test different thread with REG_NOTIFY_THREAD_AGNOSTIC */
4008 ret
= RegOpenKeyA(hkey_main
, "TestKey", &key
);
4009 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
4011 data
.flags
= REG_NOTIFY_THREAD_AGNOSTIC
;
4012 thread
= CreateThread(NULL
, 0, notify_change_thread
, &data
, 0, NULL
);
4013 WaitForSingleObject(thread
, INFINITE
);
4014 CloseHandle(thread
);
4016 dwret
= WaitForSingleObject(event
, 0);
4017 ok(dwret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %lu\n", dwret
);
4019 ret
= RegCreateKeyA(key
, "SubKey", &subkey
);
4020 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
4022 dwret
= WaitForSingleObject(event
, 0);
4023 ok(dwret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %lu\n", dwret
);
4025 RegDeleteKeyA(key
, "SubKey");
4026 RegDeleteKeyA(key
, "");
4027 RegCloseKey(subkey
);
4032 static const char *find_counter_value(const char *text
, const char *index
)
4034 const char *p
= text
;
4038 if (!strcmp(p
, index
))
4039 return p
+ strlen(p
) + 1;
4048 static void test_counter_values(const char *text
, HKEY key
)
4050 const char *p
= text
;
4053 ok(!strcmp(p
, "1"), "got first index %s\n", debugstr_a(p
));
4055 ok(!strcmp(p
, "1847"), "got first name %s\n", debugstr_a(p
));
4060 unsigned int index
= atoi(p
);
4062 ok(index
> 0, "expected nonzero index\n");
4065 ok(*p
, "name missing for %u\n", index
);
4069 name
= find_counter_value(text
, "1846");
4070 ok(name
!= NULL
, "did not find name\n");
4071 if (key
!= HKEY_PERFORMANCE_NLSTEXT
)
4072 ok(!strcmp(name
, "End Marker"), "got name %s\n", debugstr_a(name
));
4075 static void test_help_values(const char *text
, HKEY key
)
4077 const char *p
= text
;
4082 unsigned int index
= atoi(p
);
4084 ok(index
> 0, "expected nonzero index\n");
4090 name
= find_counter_value(text
, "1847");
4091 ok(name
!= NULL
, "did not find name\n");
4092 if (key
!= HKEY_PERFORMANCE_NLSTEXT
)
4093 ok(!strcmp(name
, "End Marker"), "got name %s\n", debugstr_a(name
));
4096 static void test_performance_keys(void)
4098 static const HKEY keys
[] = {HKEY_PERFORMANCE_DATA
, HKEY_PERFORMANCE_TEXT
, HKEY_PERFORMANCE_NLSTEXT
};
4099 static const char *const names
[] = {NULL
, "", "Global", "2", "invalid counter name", "System"};
4100 DWORD size
, type
, sysname_len
, expect_size
, key_count
, value_count
;
4101 LARGE_INTEGER perftime1
, perftime2
, systime1
, systime2
, freq
;
4102 WCHAR sysname
[MAX_COMPUTERNAME_LENGTH
+ 1];
4103 unsigned int buffer_size
= 1024 * 1024;
4104 void *buffer
, *bufferW
;
4105 PERF_DATA_BLOCK
*data
;
4115 buffer
= malloc(buffer_size
);
4117 sysname_len
= ARRAY_SIZE(sysname
);
4118 GetComputerNameW(sysname
, &sysname_len
);
4120 for (i
= 0; i
< ARRAY_SIZE(keys
); ++i
)
4122 winetest_push_context("key %p", keys
[i
]);
4124 for (j
= 0; j
< ARRAY_SIZE(names
); ++j
)
4126 winetest_push_context("value %s", debugstr_a(names
[j
]));
4128 QueryPerformanceFrequency(&freq
);
4131 ret
= RegQueryValueExA(keys
[i
], names
[j
], NULL
, NULL
, NULL
, &size
);
4132 ok(ret
== ERROR_MORE_DATA
, "got %lu\n", ret
);
4133 ok(!size
, "got size %lu\n", size
);
4136 ret
= RegQueryValueExA(keys
[i
], names
[j
], NULL
, NULL
, buffer
, &size
);
4137 ok(ret
== ERROR_MORE_DATA
, "got %lu\n", ret
);
4139 ok(size
== 10, "got size %lu\n", size
);
4142 ret
= RegQueryValueExA(keys
[i
], names
[j
], NULL
, NULL
, NULL
, &size
);
4143 ok(ret
== ERROR_MORE_DATA
, "got %lu\n", ret
);
4145 QueryPerformanceCounter(&perftime1
);
4146 NtQuerySystemTime(&systime1
);
4150 ret
= RegQueryValueExA(keys
[i
], names
[j
], NULL
, &type
, buffer
, &size
);
4151 ok(!ret
, "got %lu\n", ret
);
4152 ok(type
== REG_BINARY
, "got type %lu\n", type
);
4153 ok(size
>= sizeof(PERF_DATA_BLOCK
) && size
< buffer_size
, "got size %lu\n", size
);
4155 QueryPerformanceCounter(&perftime2
);
4156 NtQuerySystemTime(&systime2
);
4159 ok(!wcsncmp(data
->Signature
, L
"PERF", 4), "got signature %s\n",
4160 debugstr_wn(data
->Signature
, 4));
4161 ok(data
->LittleEndian
== 1, "got endianness %lu\n", data
->LittleEndian
);
4162 ok(data
->Version
== 1, "got version %lu\n", data
->Version
);
4163 ok(data
->Revision
== 1, "got version %lu\n", data
->Revision
);
4164 ok(data
->TotalByteLength
== size
, "expected size %lu, got %lu\n",
4165 size
, data
->TotalByteLength
);
4167 expect_size
= sizeof(PERF_DATA_BLOCK
) + data
->SystemNameLength
;
4168 expect_size
= (expect_size
+ 7) & ~7;
4170 ok(data
->HeaderLength
== expect_size
, "expected header size %lu, got %lu\n",
4171 expect_size
, data
->HeaderLength
);
4172 /* todo: test objects... */
4173 todo_wine
ok(data
->DefaultObject
== 238, "got default object %lu\n", data
->DefaultObject
);
4175 ok(data
->PerfTime
.QuadPart
>= perftime1
.QuadPart
4176 && data
->PerfTime
.QuadPart
<= perftime2
.QuadPart
,
4177 "got times %I64d, %I64d, %I64d\n",
4178 perftime1
.QuadPart
, data
->PerfTime
.QuadPart
, perftime2
.QuadPart
);
4179 ok(data
->PerfFreq
.QuadPart
== freq
.QuadPart
, "expected frequency %I64d, got %I64d\n",
4180 freq
.QuadPart
, data
->PerfFreq
.QuadPart
);
4181 ok(data
->PerfTime100nSec
.QuadPart
>= systime1
.QuadPart
4182 && data
->PerfTime100nSec
.QuadPart
<= systime2
.QuadPart
,
4183 "got times %I64d, %I64d, %I64d\n",
4184 systime1
.QuadPart
, data
->PerfTime100nSec
.QuadPart
, systime2
.QuadPart
);
4185 SystemTimeToFileTime(&data
->SystemTime
, &file_time
.f
);
4186 /* SYSTEMTIME has a granularity of 1 ms */
4187 ok(file_time
.l
>= systime1
.QuadPart
- 10000 && file_time
.l
<= systime2
.QuadPart
,
4188 "got times %I64d, %I64d, %I64d\n", systime1
.QuadPart
, file_time
.l
, systime2
.QuadPart
);
4190 ok(data
->SystemNameLength
== (sysname_len
+ 1) * sizeof(WCHAR
),
4191 "expected name len %Iu, got %lu\n",
4192 (sysname_len
+ 1) * sizeof(WCHAR
), data
->SystemNameLength
);
4193 ok(data
->SystemNameOffset
== sizeof(PERF_DATA_BLOCK
),
4194 "got name offset %lu\n", data
->SystemNameOffset
);
4195 ok(!wcscmp(sysname
, (const WCHAR
*)(data
+ 1)), "expected name %s, got %s\n",
4196 debugstr_w(sysname
), debugstr_w((const WCHAR
*)(data
+ 1)));
4198 winetest_pop_context();
4201 /* test the "Counter" value */
4204 ret
= RegQueryValueExA(keys
[i
], "cOuNtEr", NULL
, NULL
, NULL
, &size
);
4205 ok(!ret
, "got %lu\n", ret
);
4206 ok(size
> 0 && size
< 0xdeadbeef, "got size %lu\n", size
);
4210 ret
= RegQueryValueExA(keys
[i
], "cOuNtEr", NULL
, &type
, buffer
, &size
);
4211 ok(ret
== ERROR_MORE_DATA
, "got %lu\n", ret
);
4212 ok(size
> 0, "got size %lu\n", size
);
4216 ret
= RegQueryValueExA(keys
[i
], "cOuNtEr", NULL
, &type
, buffer
, &size
);
4217 ok(!ret
, "got %lu\n", ret
);
4218 ok(type
== REG_MULTI_SZ
, "got type %lu\n", type
);
4219 test_counter_values(buffer
, keys
[i
]);
4223 ret
= RegQueryValueExA(keys
[i
], "cOuNtErwine", NULL
, &type
, buffer
, &size
);
4224 ok(!ret
, "got %lu\n", ret
);
4225 ok(type
== REG_MULTI_SZ
, "got type %lu\n", type
);
4226 test_counter_values(buffer
, keys
[i
]);
4229 ret
= RegQueryValueExW(keys
[i
], L
"cOuNtEr", NULL
, NULL
, NULL
, &size
);
4230 ok(!ret
, "got %lu\n", ret
);
4231 ok(size
> 0, "got size %lu\n", size
);
4233 bufferW
= malloc(size
);
4236 ret
= RegQueryValueExW(keys
[i
], L
"cOuNtEr", NULL
, &type
, bufferW
, &size
);
4237 ok(!ret
, "got %lu\n", ret
);
4238 ok(type
== REG_MULTI_SZ
, "got type %lu\n", type
);
4239 WideCharToMultiByte(CP_ACP
, 0, bufferW
, size
/ sizeof(WCHAR
), buffer
, buffer_size
, NULL
, NULL
);
4240 test_counter_values(buffer
, keys
[i
]);
4242 /* test the "Help" value */
4245 ret
= RegQueryValueExA(keys
[i
], "hElP", NULL
, NULL
, NULL
, &size
);
4246 ok(!ret
, "got %lu\n", ret
);
4247 ok(size
> 0 && size
< 0xdeadbeef, "got size %lu\n", size
);
4251 ret
= RegQueryValueExA(keys
[i
], "hElP", NULL
, &type
, buffer
, &size
);
4252 ok(ret
== ERROR_MORE_DATA
, "got %lu\n", ret
);
4253 ok(size
> 0, "got size %lu\n", size
);
4257 ret
= RegQueryValueExA(keys
[i
], "hElP", NULL
, &type
, buffer
, &size
);
4258 test_help_values(buffer
, keys
[i
]);
4262 ret
= RegQueryValueExA(keys
[i
], "hElPwine", NULL
, &type
, buffer
, &size
);
4263 ok(!ret
, "got %lu\n", ret
);
4264 ok(type
== REG_MULTI_SZ
, "got type %lu\n", type
);
4265 test_help_values(buffer
, keys
[i
]);
4268 ret
= RegQueryValueExW(keys
[i
], L
"hElP", NULL
, NULL
, NULL
, &size
);
4269 ok(!ret
, "got %lu\n", ret
);
4270 ok(size
> 0, "got size %lu\n", size
);
4272 bufferW
= malloc(size
);
4275 ret
= RegQueryValueExW(keys
[i
], L
"hElP", NULL
, &type
, bufferW
, &size
);
4276 ok(!ret
, "got %lu\n", ret
);
4277 ok(type
== REG_MULTI_SZ
, "got type %lu\n", type
);
4278 WideCharToMultiByte(CP_ACP
, 0, bufferW
, size
/ sizeof(WCHAR
), buffer
, buffer_size
, NULL
, NULL
);
4279 test_help_values(buffer
, keys
[i
]);
4281 /* test other registry APIs */
4283 ret
= RegOpenKeyA(keys
[i
], NULL
, &key
);
4284 todo_wine
ok(ret
== ERROR_INVALID_HANDLE
, "got %lu\n", ret
);
4286 ret
= RegOpenKeyA(keys
[i
], "Global", &key
);
4287 ok(ret
== ERROR_INVALID_HANDLE
, "got %lu\n", ret
);
4289 ret
= RegOpenKeyExA(keys
[i
], "Global", 0, KEY_READ
, &key
);
4290 ok(ret
== ERROR_INVALID_HANDLE
, "got %lu\n", ret
);
4293 ret
= RegQueryValueA(keys
[i
], "Global", NULL
, (LONG
*)&size
);
4294 ok(ret
== ERROR_INVALID_HANDLE
, "got %lu\n", ret
);
4296 ret
= RegSetValueA(keys
[i
], "Global", REG_SZ
, "dummy", 5);
4297 ok(ret
== ERROR_INVALID_HANDLE
, "got %lu\n", ret
);
4299 key_count
= 0x900ddeed;
4300 ret
= RegQueryInfoKeyA(keys
[i
], NULL
, NULL
, NULL
, &key_count
, NULL
,
4301 NULL
, &value_count
, NULL
, NULL
, NULL
, NULL
);
4302 todo_wine
ok(!ret
, "got %lu\n", ret
);
4303 todo_wine
ok(!key_count
, "got %lu subkeys\n", key_count
);
4304 todo_wine
ok(value_count
== 2, "got %lu values\n", value_count
);
4307 ret
= RegEnumValueA(keys
[i
], 0, buffer
, &size
, NULL
, NULL
, NULL
, NULL
);
4308 todo_wine
ok(ret
== ERROR_MORE_DATA
, "got %lu\n", ret
);
4309 ok(size
== buffer_size
, "got size %lu\n", size
);
4311 ret
= RegCloseKey(keys
[i
]);
4312 ok(!ret
, "got %lu\n", ret
);
4314 ret
= RegCloseKey(keys
[i
]);
4315 ok(!ret
, "got %lu\n", ret
);
4317 winetest_pop_context();
4320 ret
= RegSetValueExA(HKEY_PERFORMANCE_DATA
, "Global", 0, REG_SZ
, (const BYTE
*)"dummy", 5);
4321 ok(ret
== ERROR_INVALID_HANDLE
, "got %lu\n", ret
);
4323 ret
= RegSetValueExA(HKEY_PERFORMANCE_TEXT
, "Global", 0, REG_SZ
, (const BYTE
*)"dummy", 5);
4324 todo_wine
ok(ret
== ERROR_BADKEY
, "got %lu\n", ret
);
4326 ret
= RegSetValueExA(HKEY_PERFORMANCE_NLSTEXT
, "Global", 0, REG_SZ
, (const BYTE
*)"dummy", 5);
4327 todo_wine
ok(ret
== ERROR_BADKEY
, "got %lu\n", ret
);
4329 if (pRegSetKeyValueW
)
4331 ret
= pRegSetKeyValueW(HKEY_PERFORMANCE_DATA
, NULL
, L
"Global", REG_SZ
, L
"dummy", 10);
4332 ok(ret
== ERROR_INVALID_HANDLE
, "got %lu\n", ret
);
4334 ret
= pRegSetKeyValueW(HKEY_PERFORMANCE_TEXT
, NULL
, L
"Global", REG_SZ
, L
"dummy", 10);
4335 todo_wine
ok(ret
== ERROR_BADKEY
, "got %lu\n", ret
);
4337 ret
= pRegSetKeyValueW(HKEY_PERFORMANCE_NLSTEXT
, NULL
, L
"Global", REG_SZ
, L
"dummy", 10);
4338 todo_wine
ok(ret
== ERROR_BADKEY
, "got %lu\n", ret
);
4341 ret
= RegEnumKeyA(HKEY_PERFORMANCE_DATA
, 0, buffer
, buffer_size
);
4342 ok(ret
== ERROR_INVALID_HANDLE
, "got %lu\n", ret
);
4344 ret
= RegEnumKeyA(HKEY_PERFORMANCE_TEXT
, 0, buffer
, buffer_size
);
4345 todo_wine
ok(ret
== ERROR_NO_MORE_ITEMS
, "got %lu\n", ret
);
4347 ret
= RegEnumKeyA(HKEY_PERFORMANCE_NLSTEXT
, 0, buffer
, buffer_size
);
4348 todo_wine
ok(ret
== ERROR_NO_MORE_ITEMS
, "got %lu\n", ret
);
4353 static void test_perflib_key(void)
4355 unsigned int primary_lang
= PRIMARYLANGID(GetUserDefaultLangID());
4356 unsigned int buffer_size
= 1024 * 1024;
4357 OBJECT_NAME_INFORMATION
*name_info
;
4358 HKEY perflib_key
, key
, key2
;
4359 OBJECT_ATTRIBUTES attr
;
4360 UNICODE_STRING string
;
4362 const char *knames
[2] = {"009", "CurrentLanguage"};
4367 ret
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
,
4368 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Perflib", 0, KEY_READ
, &perflib_key
);
4369 ok(!ret
, "got %lu\n", ret
);
4371 ret
= RegOpenKeyExA(perflib_key
, "009", 0, KEY_READ
, &key
);
4372 ok(!ret
, "got %lu\n", ret
);
4373 /* English always returns TEXT; most other languages return NLSTEXT, but
4374 * some (e.g. Hindi) return TEXT */
4375 ok(key
== HKEY_PERFORMANCE_TEXT
|| key
== HKEY_PERFORMANCE_NLSTEXT
, "got key %p\n", key
);
4377 ret
= RegCloseKey(key
);
4378 ok(!ret
, "got %lu\n", ret
);
4380 RtlInitUnicodeString(&string
, L
"009");
4381 InitializeObjectAttributes(&attr
, &string
, OBJ_CASE_INSENSITIVE
, perflib_key
, NULL
);
4382 ret
= NtOpenKey((HANDLE
*)&key
, KEY_ALL_ACCESS
, &attr
);
4383 ok(ret
== STATUS_PREDEFINED_HANDLE
|| ret
== STATUS_ACCESS_DENIED
4384 || ret
== STATUS_SUCCESS
/* Win < 7 */, "got %#lx\n", ret
);
4385 if (ret
== STATUS_PREDEFINED_HANDLE
)
4386 ok(!is_special_key(key
), "expected a normal handle, got %p\n", key
);
4387 else if (ret
== STATUS_SUCCESS
)
4388 ok(key
== HKEY_PERFORMANCE_TEXT
, "got key %p\n", key
);
4391 skip("Not enough permissions to test the perflib key.\n");
4392 RegCloseKey(perflib_key
);
4396 buffer
= malloc(buffer_size
);
4398 ret
= NtQueryKey(key
, KeyFullInformation
, buffer
, buffer_size
, &size
);
4399 ok(ret
== STATUS_INVALID_HANDLE
, "got %#lx\n", ret
);
4401 ret
= NtEnumerateKey(key
, 0, KeyFullInformation
, buffer
, buffer_size
, &size
);
4402 ok(ret
== STATUS_INVALID_HANDLE
, "got %#lx\n", ret
);
4404 RtlInitUnicodeString(&string
, L
"counter");
4405 ret
= NtQueryValueKey(key
, &string
, KeyValuePartialInformation
, buffer
, buffer_size
, &size
);
4406 ok(ret
== STATUS_INVALID_HANDLE
, "got %#lx\n", ret
);
4408 ret
= NtEnumerateValueKey(key
, 0, KeyValuePartialInformation
, buffer
, buffer_size
, &size
);
4409 ok(ret
== STATUS_INVALID_HANDLE
, "got %#lx\n", ret
);
4411 ret
= NtSetValueKey(key
, &string
, 0, REG_SZ
, "test", 5);
4412 ok(ret
== STATUS_INVALID_HANDLE
, "got %#lx\n", ret
);
4414 ret
= NtDeleteValueKey(key
, &string
);
4415 ok(ret
== STATUS_INVALID_HANDLE
, "got %#lx\n", ret
);
4417 ret
= NtDeleteKey(key
);
4418 ok(ret
== STATUS_INVALID_HANDLE
, "got %#lx\n", ret
);
4420 RtlInitUnicodeString(&string
, L
"subkey");
4421 InitializeObjectAttributes(&attr
, &string
, OBJ_CASE_INSENSITIVE
, key
, NULL
);
4422 ret
= NtOpenKey((HANDLE
*)&key2
, KEY_READ
, &attr
);
4423 if (is_special_key(key
))
4424 ok(ret
== STATUS_INVALID_HANDLE
, "got %#lx\n", ret
);
4426 ok(ret
== STATUS_OBJECT_NAME_NOT_FOUND
4427 || broken(ret
== STATUS_INVALID_HANDLE
) /* WoW64 */, "got %#lx\n", ret
);
4429 ret
= NtCreateKey((HANDLE
*)&key2
, KEY_ALL_ACCESS
, &attr
, 0, NULL
, 0, NULL
);
4430 if (is_special_key(key
))
4431 ok(ret
== STATUS_INVALID_HANDLE
, "got %#lx\n", ret
);
4433 ok(!ret
|| broken(ret
== STATUS_ACCESS_DENIED
) /* w8adm */
4434 || broken(ret
== STATUS_INVALID_HANDLE
) /* WoW64 */, "got %#lx\n", ret
);
4441 /* it's a real handle, though */
4442 ret
= NtQueryObject(key
, ObjectNameInformation
, buffer
, buffer_size
, &size
);
4443 if (is_special_key(key
))
4444 ok(ret
== STATUS_INVALID_HANDLE
, "got %#lx\n", ret
);
4446 ok(!ret
, "got %#lx\n", ret
);
4449 name_info
= (OBJECT_NAME_INFORMATION
*)buffer
;
4450 ok(!wcsicmp(name_info
->Name
.Buffer
, L
"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows NT"
4451 "\\CurrentVersion\\Perflib\\009"), "got name %s\n", debugstr_w(name_info
->Name
.Buffer
));
4455 if (is_special_key(key
))
4456 ok(ret
== STATUS_INVALID_HANDLE
, "got %#lx\n", ret
);
4458 ok(!ret
, "got %#lx\n", ret
);
4460 for (l
= 0; l
< ARRAY_SIZE(knames
); l
++)
4462 winetest_push_context("%ld", l
);
4463 todo_wine_if(l
== 1) {
4464 ret
= RegOpenKeyExA(perflib_key
, knames
[l
], 0, KEY_READ
, &key
);
4465 ok(!ret
, "got %lu\n", ret
);
4466 if (is_special_key(key
))
4469 ret
= RegQueryValueExA(key
, "counter", NULL
, NULL
, (BYTE
*)buffer
, &size
);
4470 ok(!ret
, "got %lu\n", ret
);
4475 for (str
= buffer
; *str
; str
+= strlen(str
) + 1)
4477 /* Note that the two keys may not have the same number of
4478 * entries if they are in different languages.
4480 ok(c
>= 2 && (c
% 2) == 0, "%d is not a valid number of entries in %s\n", c
, knames
[l
]);
4481 trace("%s has %d entries\n", knames
[l
], c
);
4486 /* Windows 7 does not always return a special key for 009
4487 * when running without elevated privileges.
4489 ok(broken(l
== 0), "expected a special handle, got %p\n", key
);
4492 ret
= RegCloseKey(key
);
4493 ok(!ret
, "got %lu\n", ret
);
4495 winetest_pop_context();
4498 /* multilingual support was not really completely thought through */
4499 switch (primary_lang
)
4501 case LANG_PORTUGUESE
:
4503 sprintf(lang_name
, "%04x", GetUserDefaultLangID());
4506 sprintf(lang_name
, "%03x", primary_lang
);
4509 if (primary_lang
!= LANG_ENGLISH
&&
4510 !RegOpenKeyExA(perflib_key
, lang_name
, 0, KEY_READ
, &key
))
4512 ok(!is_special_key(key
), "expected a normal handle, got %p\n", key
);
4515 ret
= RegQueryValueExA(key
, "counter", NULL
, NULL
, (BYTE
*)buffer
, &size
);
4516 todo_wine
ok(ret
== ERROR_FILE_NOT_FOUND
, "got %lu\n", ret
);
4518 ret
= RegCloseKey(key
);
4519 todo_wine
ok(!ret
, "got %lu\n", ret
);
4521 /* else some languages don't have their own key. The keys are not really
4522 * usable anyway so assume it does not really matter.
4525 ret
= RegCloseKey(perflib_key
);
4526 ok(!ret
, "got %lu\n", ret
);
4528 RtlInitUnicodeString(&string
, L
"\\Registry\\PerfData");
4529 InitializeObjectAttributes(&attr
, &string
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
4530 ret
= NtOpenKey((HANDLE
*)&key
, KEY_READ
, &attr
);
4531 ok(ret
== STATUS_OBJECT_NAME_NOT_FOUND
, "got %#lx\n", ret
);
4536 static void test_RegLoadMUIString(void)
4538 HMODULE hUser32
, hResDll
, hFile
;
4539 int (WINAPI
*pLoadStringW
)(HMODULE
, UINT
, WCHAR
*, int);
4542 DWORD type
, size
, text_size
;
4544 char buf
[64], *p
, sysdir
[MAX_PATH
];
4545 char with_env_var
[128], filename
[MAX_PATH
], tmp_path
[MAX_PATH
];
4546 WCHAR textW
[64], bufW
[64];
4547 WCHAR curdirW
[MAX_PATH
], sysdirW
[MAX_PATH
];
4548 const static char tz_value
[] = "MUI_Std";
4549 const static WCHAR tz_valueW
[] = L
"MUI_Std";
4558 { "", REG_SZ
, FALSE
, ERROR_INVALID_DATA
},
4559 { "not a MUI string", REG_SZ
, FALSE
, ERROR_INVALID_DATA
},
4560 { "@unknown.dll", REG_SZ
, TRUE
, ERROR_INVALID_DATA
},
4561 { "@unknown.dll,-10", REG_SZ
, TRUE
, ERROR_FILE_NOT_FOUND
},
4563 { with_env_var
, REG_SZ
, FALSE
, ERROR_SUCCESS
},
4564 { with_env_var
, REG_EXPAND_SZ
, FALSE
, ERROR_SUCCESS
},
4565 { "%WineMuiTest1%", REG_EXPAND_SZ
, TRUE
, ERROR_INVALID_DATA
},
4566 { "@%WineMuiTest2%", REG_EXPAND_SZ
, TRUE
, ERROR_SUCCESS
},
4568 { "@%WineMuiExe%,a", REG_SZ
, FALSE
, ERROR_INVALID_DATA
},
4569 { "@%WineMuiExe%,-4", REG_SZ
, FALSE
, ERROR_NOT_FOUND
, ERROR_FILE_NOT_FOUND
},
4570 { "@%WineMuiExe%,-39", REG_SZ
, FALSE
, ERROR_RESOURCE_NAME_NOT_FOUND
},
4571 { "@%WineMuiDat%,-16", REG_EXPAND_SZ
, FALSE
, ERROR_BAD_EXE_FORMAT
, ERROR_FILE_NOT_FOUND
},
4574 if (!pRegLoadMUIStringA
|| !pRegLoadMUIStringW
)
4576 win_skip("RegLoadMUIString is not available\n");
4580 hUser32
= LoadLibraryA("user32.dll");
4581 ok(hUser32
!= NULL
, "cannot load user32.dll\n");
4582 pLoadStringW
= (void *)GetProcAddress(hUser32
, "LoadStringW");
4583 ok(pLoadStringW
!= NULL
, "failed to get LoadStringW address\n");
4585 ret
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
,
4586 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\UTC", 0,
4588 ok(ret
== ERROR_SUCCESS
, "got %ld\n", ret
);
4590 size
= ARRAY_SIZE(buf
);
4591 ret
= RegQueryValueExA(hkey
, tz_value
, NULL
, &type
, (BYTE
*)buf
, &size
);
4592 ok(ret
== ERROR_SUCCESS
, "got %ld\n", ret
);
4593 ok(buf
[0] == '@', "got %s\n", buf
);
4595 /* setup MUI string for tests */
4596 strcpy(with_env_var
, "@%windir%\\system32\\");
4597 strcat(with_env_var
, &buf
[1]);
4598 SetEnvironmentVariableA("WineMuiTest1", buf
);
4599 SetEnvironmentVariableA("WineMuiTest2", &buf
[1]);
4601 /* load expecting text */
4602 p
= strrchr(buf
, ',');
4604 i
= atoi(p
+ 2); /* skip ',-' */
4605 hResDll
= LoadLibraryExA(&buf
[1], NULL
, LOAD_LIBRARY_AS_DATAFILE
| LOAD_LIBRARY_AS_IMAGE_RESOURCE
);
4606 memset(textW
, 0xaa, sizeof(textW
));
4607 ret
= pLoadStringW(hResDll
, i
, textW
, ARRAY_SIZE(textW
));
4608 ok(ret
> 0, "failed to load string resource\n");
4609 text_size
= (ret
+ 1) * sizeof(WCHAR
);
4610 FreeLibrary(hResDll
);
4611 FreeLibrary(hUser32
);
4613 ret
= GetSystemDirectoryW(sysdirW
, ARRAY_SIZE(sysdirW
));
4614 ok(ret
> 0, "GetSystemDirectoryW failed\n");
4615 ret
= GetSystemDirectoryA(sysdir
, ARRAY_SIZE(sysdir
));
4616 ok(ret
> 0, "GetSystemDirectoryA failed\n");
4618 /* change the current directory to system32 */
4619 GetCurrentDirectoryW(ARRAY_SIZE(curdirW
), curdirW
);
4620 SetCurrentDirectoryW(sysdirW
);
4623 ret
= pRegLoadMUIStringW(hkey
, tz_valueW
, NULL
, 0, &size
, 0, NULL
);
4624 ok(ret
== ERROR_MORE_DATA
, "got %ld, expected ERROR_MORE_DATA\n", ret
);
4625 ok(size
== text_size
, "got %lu, expected %lu\n", size
, text_size
);
4627 memset(bufW
, 0xff, sizeof(bufW
));
4628 ret
= pRegLoadMUIStringW(hkey
, tz_valueW
, bufW
, sizeof(WCHAR
)+1, &size
, 0, NULL
);
4629 ok(ret
== ERROR_INVALID_PARAMETER
, "got %ld, expected ERROR_INVALID_PARAMETER\n", ret
);
4630 ok(bufW
[0] == 0xffff, "got 0x%04x, expected 0xffff\n", bufW
[0]);
4633 memset(bufW
, 0xff, sizeof(bufW
));
4634 ret
= pRegLoadMUIStringW(hkey
, tz_valueW
, bufW
, sizeof(WCHAR
)*2, &size
, 0, NULL
);
4635 ok(ret
== ERROR_MORE_DATA
, "got %ld, expected ERROR_MORE_DATA\n", ret
);
4636 ok(size
== text_size
|| broken(size
== text_size
+ sizeof(WCHAR
) /* vista */),
4637 "got %lu, expected %lu\n", size
, text_size
);
4638 ok(bufW
[0] == 0xffff, "got 0x%04x, expected 0xffff\n", bufW
[0]);
4640 memset(bufW
, 0xff, sizeof(bufW
));
4641 ret
= pRegLoadMUIStringW(hkey
, tz_valueW
, bufW
, sizeof(WCHAR
)*2, &size
, REG_MUI_STRING_TRUNCATE
, NULL
);
4642 ok(ret
== ERROR_INVALID_PARAMETER
, "got %ld, expected ERROR_INVALID_PARAMETER\n", ret
);
4643 ok(bufW
[0] == 0xffff, "got 0x%04x, expected 0xffff\n", bufW
[0]);
4645 memset(bufW
, 0xff, sizeof(bufW
));
4646 ret
= pRegLoadMUIStringW(hkey
, tz_valueW
, bufW
, sizeof(WCHAR
)*2, NULL
, 0xdeadbeef, NULL
);
4647 ok(ret
== ERROR_INVALID_PARAMETER
, "got %ld, expected ERROR_INVALID_PARAMETER\n", ret
);
4648 ok(bufW
[0] == 0xffff, "got 0x%04x, expected 0xffff\n", bufW
[0]);
4650 memset(bufW
, 0xff, sizeof(bufW
));
4651 ret
= pRegLoadMUIStringW(hkey
, tz_valueW
, bufW
, sizeof(WCHAR
)*2, NULL
, REG_MUI_STRING_TRUNCATE
, NULL
);
4652 ok(ret
== ERROR_SUCCESS
, "got %ld, expected ERROR_SUCCESS\n", ret
);
4653 ok(bufW
[0] == textW
[0], "got 0x%04x, expected 0x%04x\n", bufW
[0], textW
[0]);
4654 ok(bufW
[1] == 0, "got 0x%04x, expected nul\n", bufW
[1]);
4657 memset(bufW
, 0xff, sizeof(bufW
));
4658 ret
= pRegLoadMUIStringW(hkey
, tz_valueW
, bufW
, ARRAY_SIZE(bufW
), &size
, 0, NULL
);
4659 ok(ret
== ERROR_SUCCESS
, "got %ld, expected ERROR_SUCCESS\n", ret
);
4660 ok(size
== text_size
, "got %lu, expected %lu\n", size
, text_size
);
4661 ok(!memcmp(textW
, bufW
, size
), "got %s, expected %s\n",
4662 wine_dbgstr_wn(bufW
, size
/ sizeof(WCHAR
)), wine_dbgstr_wn(textW
, text_size
/ sizeof(WCHAR
)));
4664 ret
= pRegLoadMUIStringA(hkey
, tz_value
, buf
, ARRAY_SIZE(buf
), &size
, 0, NULL
);
4665 ok(ret
== ERROR_CALL_NOT_IMPLEMENTED
, "got %ld, expected ERROR_CALL_NOT_IMPLEMENTED\n", ret
);
4667 /* change the current directory to other than system32 directory */
4668 SetCurrentDirectoryA("\\");
4671 memset(bufW
, 0xff, sizeof(bufW
));
4672 ret
= pRegLoadMUIStringW(hkey
, tz_valueW
, bufW
, ARRAY_SIZE(bufW
), &size
, 0, sysdirW
);
4673 ok(ret
== ERROR_SUCCESS
, "got %ld, expected ERROR_SUCCESS\n", ret
);
4674 ok(size
== text_size
, "got %lu, expected %lu\n", size
, text_size
);
4675 ok(!memcmp(textW
, bufW
, size
), "got %s, expected %s\n",
4676 wine_dbgstr_wn(bufW
, size
/ sizeof(WCHAR
)), wine_dbgstr_wn(textW
, text_size
/ sizeof(WCHAR
)));
4678 ret
= pRegLoadMUIStringA(hkey
, tz_value
, buf
, ARRAY_SIZE(buf
), &size
, 0, sysdir
);
4679 ok(ret
== ERROR_CALL_NOT_IMPLEMENTED
, "got %ld, expected ERROR_CALL_NOT_IMPLEMENTED\n", ret
);
4681 ret
= pRegLoadMUIStringW(hkey
, tz_valueW
, bufW
, ARRAY_SIZE(bufW
), &size
, 0, NULL
);
4682 ok(ret
== ERROR_FILE_NOT_FOUND
, "got %ld, expected ERROR_FILE_NOT_FOUND\n", ret
);
4684 ret
= pRegLoadMUIStringA(hkey
, tz_value
, buf
, ARRAY_SIZE(buf
), &size
, 0, NULL
);
4685 ok(ret
== ERROR_CALL_NOT_IMPLEMENTED
, "got %ld, expected ERROR_CALL_NOT_IMPLEMENTED\n", ret
);
4689 GetModuleFileNameA(NULL
, filename
, ARRAY_SIZE(filename
));
4690 SetEnvironmentVariableA("WineMuiExe", filename
);
4692 GetTempPathA(ARRAY_SIZE(tmp_path
), tmp_path
);
4693 GetTempFileNameA(tmp_path
, "mui", 0, filename
);
4694 SetEnvironmentVariableA("WineMuiDat", filename
);
4696 /* write dummy data to the file, i.e. it's not a PE file. */
4697 hFile
= CreateFileA(filename
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
4698 ok(hFile
!= INVALID_HANDLE_VALUE
, "can't open %s\n", filename
);
4699 WriteFile(hFile
, filename
, strlen(filename
), &size
, NULL
);
4702 for (i
= 0; i
< ARRAY_SIZE(test_case
); i
++)
4704 size
= test_case
[i
].value
? strlen(test_case
[i
].value
) + 1 : 0;
4705 ret
= RegSetValueExA(hkey_main
, tz_value
, 0, test_case
[i
].type
,
4706 (const BYTE
*)test_case
[i
].value
, size
);
4707 ok(ret
== ERROR_SUCCESS
, "[%2u] got %ld\n", i
, ret
);
4710 memset(bufW
, 0xff, sizeof(bufW
));
4711 ret
= pRegLoadMUIStringW(hkey_main
, tz_valueW
, bufW
, ARRAY_SIZE(bufW
),
4713 test_case
[i
].use_sysdir
? sysdirW
: NULL
);
4714 ok(ret
== test_case
[i
].expected
||
4715 broken(test_case
[i
].value
[0] == '%' && ret
== ERROR_SUCCESS
/* vista */) ||
4716 broken(test_case
[i
].broken_ret
&& ret
== test_case
[i
].broken_ret
/* vista */),
4717 "[%2u] expected %ld, got %ld\n", i
, test_case
[i
].expected
, ret
);
4718 if (ret
== ERROR_SUCCESS
&& test_case
[i
].expected
== ERROR_SUCCESS
)
4720 ok(size
== text_size
, "[%2u] got %lu, expected %lu\n", i
, size
, text_size
);
4721 ok(!memcmp(bufW
, textW
, size
), "[%2u] got %s, expected %s\n", i
,
4722 wine_dbgstr_wn(bufW
, size
/sizeof(WCHAR
)),
4723 wine_dbgstr_wn(textW
, text_size
/sizeof(WCHAR
)));
4727 SetCurrentDirectoryW(curdirW
);
4728 DeleteFileA(filename
);
4729 SetEnvironmentVariableA("WineMuiTest1", NULL
);
4730 SetEnvironmentVariableA("WineMuiTest2", NULL
);
4731 SetEnvironmentVariableA("WineMuiExe", NULL
);
4732 SetEnvironmentVariableA("WineMuiDat", NULL
);
4735 static void test_EnumDynamicTimeZoneInformation(void)
4741 WCHAR sysdir
[MAX_PATH
];
4742 DWORD index
, ret
, gle
, size
;
4743 DYNAMIC_TIME_ZONE_INFORMATION bogus_dtzi
, dtzi
;
4749 SYSTEMTIME std_date
;
4750 SYSTEMTIME dlt_date
;
4753 if (!pEnumDynamicTimeZoneInformation
)
4755 win_skip("EnumDynamicTimeZoneInformation is not supported.\n");
4759 if (pRegLoadMUIStringW
)
4760 GetSystemDirectoryW(sysdir
, ARRAY_SIZE(sysdir
));
4762 SetLastError(0xdeadbeef);
4763 ret
= pEnumDynamicTimeZoneInformation(0, NULL
);
4764 gle
= GetLastError();
4765 ok(gle
== 0xdeadbeef, "got 0x%lx\n", gle
);
4766 ok(ret
== ERROR_INVALID_PARAMETER
, "got %ld\n", ret
);
4768 memset(&bogus_dtzi
, 0xcc, sizeof(bogus_dtzi
));
4769 memset(&dtzi
, 0xcc, sizeof(dtzi
));
4770 SetLastError(0xdeadbeef);
4771 ret
= pEnumDynamicTimeZoneInformation(-1, &dtzi
);
4772 gle
= GetLastError();
4773 ok(gle
== 0xdeadbeef, "got 0x%lx\n", gle
);
4774 ok(ret
== ERROR_NO_MORE_ITEMS
, "got %ld\n", ret
);
4775 ok(!memcmp(&dtzi
, &bogus_dtzi
, sizeof(dtzi
)), "mismatch\n");
4777 status
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
,
4778 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones", 0,
4779 KEY_ENUMERATE_SUB_KEYS
|KEY_QUERY_VALUE
, &key
);
4780 ok(status
== ERROR_SUCCESS
, "got %ld\n", status
);
4782 while (!(status
= RegEnumKeyW(key
, index
, keyname
, ARRAY_SIZE(keyname
))))
4784 winetest_push_context("%s" , wine_dbgstr_w(keyname
));
4786 status
= RegOpenKeyExW(key
, keyname
, 0, KEY_QUERY_VALUE
, &subkey
);
4787 ok(status
== ERROR_SUCCESS
, "got %ld\n", status
);
4789 memset(&dtzi
, 0xcc, sizeof(dtzi
));
4790 SetLastError(0xdeadbeef);
4791 ret
= pEnumDynamicTimeZoneInformation(index
, &dtzi
);
4792 gle
= GetLastError();
4793 /* recently added time zones may not have MUI strings */
4794 ok(gle
== ERROR_SUCCESS
||
4795 gle
== ERROR_RESOURCE_TYPE_NOT_FOUND
/* Win10 1809 32-bit */ ||
4796 gle
== ERROR_MUI_FILE_NOT_FOUND
/* Win10 1809 64-bit */,
4797 "got 0x%lx\n", gle
);
4798 ok(ret
== ERROR_SUCCESS
, "got %ld\n", ret
);
4799 ok(!lstrcmpW(dtzi
.TimeZoneKeyName
, keyname
), "expected %s, got %s\n",
4800 wine_dbgstr_w(keyname
), wine_dbgstr_w(dtzi
.TimeZoneKeyName
));
4802 if (gle
== ERROR_SUCCESS
)
4804 size
= sizeof(name
);
4805 memset(name
, 0, sizeof(name
));
4806 status
= pRegGetValueW(subkey
, NULL
, L
"Std", RRF_RT_REG_SZ
, NULL
, name
, &size
);
4807 ok(status
== ERROR_SUCCESS
, "status %ld Std %s\n", status
,
4808 wine_dbgstr_w(name
));
4809 ok(*name
, "Std name is empty\n");
4810 if (pRegLoadMUIStringW
)
4812 size
= sizeof(name
);
4813 memset(name
, 0, sizeof(name
));
4814 status
= pRegLoadMUIStringW(subkey
, L
"MUI_Std", name
, size
, &size
, 0, sysdir
);
4815 ok(status
== ERROR_SUCCESS
, "status %ld MUI_Std %s\n",
4816 status
, wine_dbgstr_w(name
));
4817 ok(*name
, "MUI_Std name is empty\n");
4819 ok(!memcmp(&dtzi
.StandardName
, name
, size
), "expected %s, got %s\n",
4820 wine_dbgstr_w(name
), wine_dbgstr_w(dtzi
.StandardName
));
4822 size
= sizeof(name
);
4823 memset(name
, 0, sizeof(name
));
4824 status
= pRegGetValueW(subkey
, NULL
, L
"Dlt", RRF_RT_REG_SZ
, NULL
, name
, &size
);
4825 ok(status
== ERROR_SUCCESS
, "status %ld %s Dlt %s\n",
4826 status
, wine_dbgstr_w(keyname
), wine_dbgstr_w(name
));
4827 ok(*name
, "Dlt name is empty\n");
4828 if (pRegLoadMUIStringW
)
4830 size
= sizeof(name
);
4831 memset(name
, 0, sizeof(name
));
4832 status
= pRegLoadMUIStringW(subkey
, L
"MUI_Dlt", name
, size
, &size
, 0, sysdir
);
4833 ok(status
== ERROR_SUCCESS
, "status %ld %s MUI_Dlt %s\n",
4834 status
, wine_dbgstr_w(keyname
), wine_dbgstr_w(name
));
4835 ok(*name
, "MUI_Dlt name is empty\n");
4837 ok(!memcmp(&dtzi
.DaylightName
, name
, size
), "expected %s, got %s\n",
4838 wine_dbgstr_w(name
), wine_dbgstr_w(dtzi
.DaylightName
));
4840 size
= sizeof(name
);
4841 memset(name
, 0, sizeof(name
));
4842 status
= pRegGetValueW(subkey
, NULL
, L
"Display", RRF_RT_REG_SZ
, NULL
, name
, &size
);
4843 ok(status
== ERROR_SUCCESS
, "status %ld %s Display %s\n",
4844 status
, wine_dbgstr_w(keyname
), wine_dbgstr_w(name
));
4845 ok(*name
, "Display name is empty\n");
4846 if (pRegLoadMUIStringW
)
4848 size
= sizeof(name
);
4849 memset(name
, 0, sizeof(name
));
4850 status
= pRegLoadMUIStringW(subkey
, L
"MUI_Display", name
, size
, &size
, 0, sysdir
);
4851 /* recently added time zones may not have MUI strings */
4852 ok((status
== ERROR_SUCCESS
&& *name
) ||
4853 broken(status
== ERROR_RESOURCE_TYPE_NOT_FOUND
) /* Win10 1809 32-bit */ ||
4854 broken(status
== ERROR_MUI_FILE_NOT_FOUND
) /* Win10 1809 64-bit */,
4855 "status %ld MUI_Display %s\n", status
, wine_dbgstr_w(name
));
4860 ok(!dtzi
.StandardName
[0], "expected empty StandardName\n");
4861 ok(!dtzi
.DaylightName
[0], "expected empty DaylightName\n");
4864 ok(!dtzi
.DynamicDaylightTimeDisabled
, "got %d\n", dtzi
.DynamicDaylightTimeDisabled
);
4866 size
= sizeof(tz_data
);
4867 status
= pRegGetValueW(key
, keyname
, L
"TZI", RRF_RT_REG_BINARY
, NULL
, &tz_data
, &size
);
4868 ok(status
== ERROR_SUCCESS
, "got %ld\n", status
);
4870 ok(dtzi
.Bias
== tz_data
.bias
, "expected %ld, got %ld\n",
4871 tz_data
.bias
, dtzi
.Bias
);
4872 ok(dtzi
.StandardBias
== tz_data
.std_bias
, "expected %ld, got %ld\n",
4873 tz_data
.std_bias
, dtzi
.StandardBias
);
4874 ok(dtzi
.DaylightBias
== tz_data
.dlt_bias
, "expected %ld, got %ld\n",
4875 tz_data
.dlt_bias
, dtzi
.DaylightBias
);
4877 ok(!memcmp(&dtzi
.StandardDate
, &tz_data
.std_date
, sizeof(dtzi
.StandardDate
)),
4878 "expected %s, got %s\n",
4879 dbgstr_SYSTEMTIME(&tz_data
.std_date
), dbgstr_SYSTEMTIME(&dtzi
.StandardDate
));
4881 ok(!memcmp(&dtzi
.DaylightDate
, &tz_data
.dlt_date
, sizeof(dtzi
.DaylightDate
)),
4882 "expected %s, got %s\n",
4883 dbgstr_SYSTEMTIME(&tz_data
.dlt_date
), dbgstr_SYSTEMTIME(&dtzi
.DaylightDate
));
4885 winetest_pop_context();
4886 RegCloseKey(subkey
);
4889 ok(status
== ERROR_NO_MORE_ITEMS
, "got %ld\n", status
);
4891 memset(&dtzi
, 0xcc, sizeof(dtzi
));
4892 SetLastError(0xdeadbeef);
4893 ret
= pEnumDynamicTimeZoneInformation(index
, &dtzi
);
4894 gle
= GetLastError();
4895 ok(gle
== 0xdeadbeef, "got 0x%lx\n", gle
);
4896 ok(ret
== ERROR_NO_MORE_ITEMS
, "got %ld\n", ret
);
4897 ok(!memcmp(&dtzi
, &bogus_dtzi
, sizeof(dtzi
)), "mismatch\n");
4902 static void test_RegRenameKey(void)
4907 ret
= RegRenameKey(NULL
, NULL
, NULL
);
4908 ok(ret
== ERROR_INVALID_PARAMETER
, "Unexpected return value %ld.\n", ret
);
4909 ret
= RegRenameKey(NULL
, NULL
, L
"newname");
4910 ok(ret
== ERROR_INVALID_HANDLE
, "Unexpected return value %ld.\n", ret
);
4911 ret
= RegRenameKey(NULL
, L
"oldname", NULL
);
4912 ok(ret
== ERROR_INVALID_HANDLE
, "Unexpected return value %ld.\n", ret
);
4913 ret
= RegRenameKey(NULL
, L
"oldname", L
"newname");
4914 ok(ret
== ERROR_INVALID_HANDLE
, "Unexpected return value %ld.\n", ret
);
4916 ret
= RegCreateKeyExA(hkey_main
, "TestRenameKey", 0, NULL
, 0, KEY_READ
, NULL
, &key
, NULL
);
4917 ok(!ret
, "Unexpected return value %ld.\n", ret
);
4918 ret
= RegRenameKey(key
, NULL
, L
"TestNewRenameKey");
4919 ok(ret
== ERROR_ACCESS_DENIED
, "Unexpected return value %ld.\n", ret
);
4922 /* Rename itself. */
4923 ret
= RegCreateKeyExA(hkey_main
, "TestRenameKey", 0, NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
);
4924 ok(!ret
, "Unexpected return value %ld.\n", ret
);
4925 ret
= RegRenameKey(key
, NULL
, NULL
);
4926 ok(ret
== ERROR_INVALID_PARAMETER
, "Unexpected return value %ld.\n", ret
);
4927 ret
= RegRenameKey(key
, NULL
, L
"TestNewRenameKey");
4928 ok(!ret
, "Unexpected return value %ld.\n", ret
);
4931 ret
= RegDeleteKeyA(hkey_main
, "TestNewRenameKey");
4932 ok(!ret
, "Unexpected return value %ld.\n", ret
);
4933 ret
= RegDeleteKeyA(hkey_main
, "TestRenameKey");
4934 ok(ret
, "Unexpected return value %ld.\n", ret
);
4936 /* Subkey does not exist. */
4937 ret
= RegCreateKeyExA(hkey_main
, "TestRenameKey", 0, NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
);
4938 ok(!ret
, "Unexpected return value %ld.\n", ret
);
4939 ret
= RegRenameKey(key
, L
"unknown_subkey", NULL
);
4940 ok(ret
== ERROR_FILE_NOT_FOUND
, "Unexpected return value %ld.\n", ret
);
4941 ret
= RegRenameKey(key
, L
"unknown_subkey", L
"known_subkey");
4942 ok(ret
== ERROR_FILE_NOT_FOUND
, "Unexpected return value %ld.\n", ret
);
4944 /* Rename existing subkey. */
4945 ret
= RegCreateKeyExA(key
, "known_subkey", 0, NULL
, 0, KEY_WRITE
, NULL
, &key2
, NULL
);
4946 ok(!ret
, "Unexpected return value %ld.\n", ret
);
4949 ret
= RegRenameKey(key
, L
"known_subkey", L
"renamed_subkey");
4950 ok(!ret
, "Unexpected return value %ld.\n", ret
);
4952 ret
= RegDeleteKeyA(key
, "renamed_subkey");
4953 ok(!ret
, "Unexpected return value %ld.\n", ret
);
4954 ret
= RegDeleteKeyA(key
, "known_subkey");
4955 ok(ret
, "Unexpected return value %ld.\n", ret
);
4960 START_TEST(registry
)
4962 /* Load pointers for functions that are not available in all Windows versions */
4968 create_test_entries();
4970 test_query_value_ex();
4972 test_reg_open_key();
4973 test_reg_create_key();
4974 test_reg_close_key();
4975 test_reg_delete_key();
4976 test_reg_query_value();
4977 test_reg_query_info();
4978 test_string_termination();
4982 test_classesroot_enum();
4983 test_classesroot_mask();
4984 test_reg_save_key();
4985 test_reg_load_key();
4986 test_reg_unload_key();
4987 test_reg_load_app_key();
4988 test_reg_copy_tree();
4989 test_reg_delete_tree();
4992 test_delete_value();
4993 test_delete_key_value();
4994 test_RegOpenCurrentUser();
4995 test_RegNotifyChangeKeyValue();
4996 test_performance_keys();
4997 test_RegLoadMUIString();
4998 test_EnumDynamicTimeZoneInformation();
5000 test_RegRenameKey();
5003 delete_key( hkey_main
);
5005 test_regconnectregistry();