[ADVAPI32_WINETEST] Sync with Wine Staging 1.7.55. CORE-10536
[reactos.git] / rostests / winetests / advapi32 / registry.c
1 /*
2 * Unit tests for registry functions
3 *
4 * Copyright (c) 2002 Alexandre Julliard
5 * Copyright (c) 2010 André Hentschel
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #define WIN32_NO_STATUS
23 #define WIN32_LEAN_AND_MEAN
24
25 #include <assert.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include "wine/test.h"
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wine/winternl.h"
32 #include "winreg.h"
33 #include "winsvc.h"
34 #include "winerror.h"
35 #include "aclapi.h"
36
37 #define IS_HKCR(hk) ((UINT_PTR)hk > 0 && ((UINT_PTR)hk & 3) == 2)
38
39 static HKEY hkey_main;
40 static DWORD GLE;
41
42 static const char * sTestpath1 = "%LONGSYSTEMVAR%\\subdir1";
43 static const char * sTestpath2 = "%FOO%\\subdir1";
44 static const DWORD ptr_size = 8 * sizeof(void*);
45
46 static DWORD (WINAPI *pRegGetValueA)(HKEY,LPCSTR,LPCSTR,DWORD,LPDWORD,PVOID,LPDWORD);
47 static DWORD (WINAPI *pRegDeleteTreeA)(HKEY,LPCSTR);
48 static DWORD (WINAPI *pRegDeleteKeyExA)(HKEY,LPCSTR,REGSAM,DWORD);
49 static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
50 static NTSTATUS (WINAPI * pNtDeleteKey)(HANDLE);
51 static NTSTATUS (WINAPI * pRtlFormatCurrentUserKeyPath)(UNICODE_STRING*);
52 static NTSTATUS (WINAPI * pRtlFreeUnicodeString)(PUNICODE_STRING);
53 static LONG (WINAPI *pRegDeleteKeyValueA)(HKEY,LPCSTR,LPCSTR);
54 static LONG (WINAPI *pRegSetKeyValueW)(HKEY,LPCWSTR,LPCWSTR,DWORD,const void*,DWORD);
55
56 static BOOL limited_user;
57
58
59 /* Debugging functions from wine/libs/wine/debug.c */
60
61 /* allocate some tmp string space */
62 /* FIXME: this is not 100% thread-safe */
63 static char *get_temp_buffer( int size )
64 {
65 static char *list[32];
66 static UINT pos;
67 char *ret;
68 UINT idx;
69
70 idx = ++pos % (sizeof(list)/sizeof(list[0]));
71 if (list[idx])
72 ret = HeapReAlloc( GetProcessHeap(), 0, list[idx], size );
73 else
74 ret = HeapAlloc( GetProcessHeap(), 0, size );
75 if (ret) list[idx] = ret;
76 return ret;
77 }
78
79 static const char *wine_debugstr_an( const char *str, int n )
80 {
81 static const char hex[16] = "0123456789abcdef";
82 char *dst, *res;
83 size_t size;
84
85 if (!((ULONG_PTR)str >> 16))
86 {
87 if (!str) return "(null)";
88 res = get_temp_buffer( 6 );
89 sprintf( res, "#%04x", LOWORD(str) );
90 return res;
91 }
92 if (n == -1) n = strlen(str);
93 if (n < 0) n = 0;
94 size = 10 + min( 300, n * 4 );
95 dst = res = get_temp_buffer( size );
96 *dst++ = '"';
97 while (n-- > 0 && dst <= res + size - 9)
98 {
99 unsigned char c = *str++;
100 switch (c)
101 {
102 case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
103 case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
104 case '\t': *dst++ = '\\'; *dst++ = 't'; break;
105 case '"': *dst++ = '\\'; *dst++ = '"'; break;
106 case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
107 default:
108 if (c >= ' ' && c <= 126)
109 *dst++ = c;
110 else
111 {
112 *dst++ = '\\';
113 *dst++ = 'x';
114 *dst++ = hex[(c >> 4) & 0x0f];
115 *dst++ = hex[c & 0x0f];
116 }
117 }
118 }
119 *dst++ = '"';
120 if (n > 0)
121 {
122 *dst++ = '.';
123 *dst++ = '.';
124 *dst++ = '.';
125 }
126 *dst++ = 0;
127 return res;
128 }
129
130 #define ADVAPI32_GET_PROC(func) \
131 p ## func = (void*)GetProcAddress(hadvapi32, #func)
132
133 static void InitFunctionPtrs(void)
134 {
135 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
136 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
137 HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
138
139 /* This function was introduced with Windows 2003 SP1 */
140 ADVAPI32_GET_PROC(RegGetValueA);
141 ADVAPI32_GET_PROC(RegDeleteTreeA);
142 ADVAPI32_GET_PROC(RegDeleteKeyExA);
143 ADVAPI32_GET_PROC(RegDeleteKeyValueA);
144 ADVAPI32_GET_PROC(RegSetKeyValueW);
145
146 pIsWow64Process = (void *)GetProcAddress( hkernel32, "IsWow64Process" );
147 pRtlFormatCurrentUserKeyPath = (void *)GetProcAddress( hntdll, "RtlFormatCurrentUserKeyPath" );
148 pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
149 pNtDeleteKey = (void *)GetProcAddress( hntdll, "NtDeleteKey" );
150 }
151
152 /* delete key and all its subkeys */
153 static DWORD delete_key( HKEY hkey )
154 {
155 char name[MAX_PATH];
156 DWORD ret;
157
158 if ((ret = RegOpenKeyExA( hkey, "", 0, KEY_ENUMERATE_SUB_KEYS, &hkey ))) return ret;
159 while (!(ret = RegEnumKeyA(hkey, 0, name, sizeof(name))))
160 {
161 HKEY tmp;
162 if (!(ret = RegOpenKeyExA( hkey, name, 0, KEY_ENUMERATE_SUB_KEYS, &tmp )))
163 {
164 ret = delete_key( tmp );
165 RegCloseKey( tmp );
166 }
167 if (ret) break;
168 }
169 if (ret != ERROR_NO_MORE_ITEMS) return ret;
170 RegDeleteKeyA( hkey, "" );
171 RegCloseKey(hkey);
172 return 0;
173 }
174
175 static void setup_main_key(void)
176 {
177 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main )) delete_key( hkey_main );
178
179 assert (!RegCreateKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main ));
180 }
181
182 static void check_user_privs(void)
183 {
184 DWORD ret;
185 HKEY hkey = (HKEY)0xdeadbeef;
186
187 ret = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WRITE, &hkey);
188 ok(ret == ERROR_SUCCESS || ret == ERROR_ACCESS_DENIED, "expected success or access denied, got %i\n", ret);
189 if (ret == ERROR_SUCCESS)
190 {
191 ok(hkey != NULL, "RegOpenKeyExA succeeded but returned NULL hkey\n");
192 RegCloseKey(hkey);
193 }
194 else
195 {
196 ok(hkey == NULL, "RegOpenKeyExA failed but returned hkey %p\n", hkey);
197 limited_user = TRUE;
198 trace("running as limited user\n");
199 }
200 }
201
202 #define lok ok_(__FILE__, line)
203 #define test_hkey_main_Value_A(name, string, full_byte_len) _test_hkey_main_Value_A(__LINE__, name, string, full_byte_len)
204 static void _test_hkey_main_Value_A(int line, LPCSTR name, LPCSTR string,
205 DWORD full_byte_len)
206 {
207 DWORD ret, type, cbData;
208 DWORD str_byte_len;
209 BYTE* value;
210
211 type=0xdeadbeef;
212 cbData=0xdeadbeef;
213 /* When successful RegQueryValueExA() leaves GLE as is,
214 * so we must reset it to detect unimplemented functions.
215 */
216 SetLastError(0xdeadbeef);
217 ret = RegQueryValueExA(hkey_main, name, NULL, &type, NULL, &cbData);
218 GLE = GetLastError();
219 lok(ret == ERROR_SUCCESS, "RegQueryValueExA/1 failed: %d, GLE=%d\n", ret, GLE);
220 /* It is wrong for the Ansi version to not be implemented */
221 ok(GLE == 0xdeadbeef, "RegQueryValueExA set GLE = %u\n", GLE);
222 if(GLE == ERROR_CALL_NOT_IMPLEMENTED) return;
223
224 str_byte_len = (string ? lstrlenA(string) : 0) + 1;
225 lok(type == REG_SZ, "RegQueryValueExA/1 returned type %d\n", type);
226 lok(cbData == full_byte_len, "cbData=%d instead of %d or %d\n", cbData, full_byte_len, str_byte_len);
227
228 value = HeapAlloc(GetProcessHeap(), 0, cbData+1);
229 memset(value, 0xbd, cbData+1);
230 type=0xdeadbeef;
231 ret = RegQueryValueExA(hkey_main, name, NULL, &type, value, &cbData);
232 GLE = GetLastError();
233 lok(ret == ERROR_SUCCESS, "RegQueryValueExA/2 failed: %d, GLE=%d\n", ret, GLE);
234 if (!string)
235 {
236 /* When cbData == 0, RegQueryValueExA() should not modify the buffer */
237 lok(*value == 0xbd, "RegQueryValueExA overflowed: cbData=%u *value=%02x\n", cbData, *value);
238 }
239 else
240 {
241 lok(memcmp(value, string, cbData) == 0, "RegQueryValueExA/2 failed: %s/%d != %s/%d\n",
242 wine_debugstr_an((char*)value, cbData), cbData,
243 wine_debugstr_an(string, full_byte_len), full_byte_len);
244 lok(*(value+cbData) == 0xbd, "RegQueryValueExA/2 overflowed at offset %u: %02x != bd\n", cbData, *(value+cbData));
245 }
246 HeapFree(GetProcessHeap(), 0, value);
247 }
248
249 #define test_hkey_main_Value_W(name, string, full_byte_len) _test_hkey_main_Value_W(__LINE__, name, string, full_byte_len)
250 static void _test_hkey_main_Value_W(int line, LPCWSTR name, LPCWSTR string,
251 DWORD full_byte_len)
252 {
253 DWORD ret, type, cbData;
254 BYTE* value;
255
256 type=0xdeadbeef;
257 cbData=0xdeadbeef;
258 /* When successful RegQueryValueExW() leaves GLE as is,
259 * so we must reset it to detect unimplemented functions.
260 */
261 SetLastError(0xdeadbeef);
262 ret = RegQueryValueExW(hkey_main, name, NULL, &type, NULL, &cbData);
263 GLE = GetLastError();
264 lok(ret == ERROR_SUCCESS, "RegQueryValueExW/1 failed: %d, GLE=%d\n", ret, GLE);
265 if(GLE == ERROR_CALL_NOT_IMPLEMENTED)
266 {
267 win_skip("RegQueryValueExW() is not implemented\n");
268 return;
269 }
270
271 lok(type == REG_SZ, "RegQueryValueExW/1 returned type %d\n", type);
272 lok(cbData == full_byte_len,
273 "cbData=%d instead of %d\n", cbData, full_byte_len);
274
275 /* Give enough space to overflow by one WCHAR */
276 value = HeapAlloc(GetProcessHeap(), 0, cbData+2);
277 memset(value, 0xbd, cbData+2);
278 type=0xdeadbeef;
279 ret = RegQueryValueExW(hkey_main, name, NULL, &type, value, &cbData);
280 GLE = GetLastError();
281 lok(ret == ERROR_SUCCESS, "RegQueryValueExW/2 failed: %d, GLE=%d\n", ret, GLE);
282 if (string)
283 {
284 lok(memcmp(value, string, cbData) == 0, "RegQueryValueExW failed: %s/%d != %s/%d\n",
285 wine_dbgstr_wn((WCHAR*)value, cbData / sizeof(WCHAR)), cbData,
286 wine_dbgstr_wn(string, full_byte_len / sizeof(WCHAR)), full_byte_len);
287 }
288 /* This implies that when cbData == 0, RegQueryValueExW() should not modify the buffer */
289 lok(*(value+cbData) == 0xbd, "RegQueryValueExW/2 overflowed at %u: %02x != bd\n", cbData, *(value+cbData));
290 lok(*(value+cbData+1) == 0xbd, "RegQueryValueExW/2 overflowed at %u+1: %02x != bd\n", cbData, *(value+cbData+1));
291 HeapFree(GetProcessHeap(), 0, value);
292 }
293
294 static void test_set_value(void)
295 {
296 DWORD ret;
297
298 static const WCHAR name1W[] = {'C','l','e','a','n','S','i','n','g','l','e','S','t','r','i','n','g', 0};
299 static const WCHAR name2W[] = {'S','o','m','e','I','n','t','r','a','Z','e','r','o','e','d','S','t','r','i','n','g', 0};
300 static const WCHAR emptyW[] = {0};
301 static const WCHAR string1W[] = {'T','h','i','s','N','e','v','e','r','B','r','e','a','k','s', 0};
302 static const WCHAR string2W[] = {'T','h','i','s', 0 ,'B','r','e','a','k','s', 0 , 0 ,'A', 0 , 0 , 0 , 'L','o','t', 0 , 0 , 0 , 0, 0};
303 static const WCHAR substring2W[] = {'T','h','i','s',0};
304
305 static const char name1A[] = "CleanSingleString";
306 static const char name2A[] = "SomeIntraZeroedString";
307 static const char emptyA[] = "";
308 static const char string1A[] = "ThisNeverBreaks";
309 static const char string2A[] = "This\0Breaks\0\0A\0\0\0Lot\0\0\0\0";
310 static const char substring2A[] = "This";
311
312 if (0)
313 {
314 /* Crashes on NT4, Windows 2000 and XP SP1 */
315 ret = RegSetValueA(hkey_main, NULL, REG_SZ, NULL, 0);
316 ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueA should have failed with ERROR_INVALID_PARAMETER instead of %d\n", ret);
317 }
318
319 ret = RegSetValueA(hkey_main, NULL, REG_SZ, string1A, sizeof(string1A));
320 ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %d, GLE=%d\n", ret, GetLastError());
321 test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
322 test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
323
324 /* RegSetValueA ignores the size passed in */
325 ret = RegSetValueA(hkey_main, NULL, REG_SZ, string1A, 4);
326 ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %d, GLE=%d\n", ret, GetLastError());
327 test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
328 test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
329
330 /* stops at first null */
331 ret = RegSetValueA(hkey_main, NULL, REG_SZ, string2A, sizeof(string2A));
332 ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %d, GLE=%d\n", ret, GetLastError());
333 test_hkey_main_Value_A(NULL, substring2A, sizeof(substring2A));
334 test_hkey_main_Value_W(NULL, substring2W, sizeof(substring2W));
335
336 /* only REG_SZ is supported on NT*/
337 ret = RegSetValueA(hkey_main, NULL, REG_BINARY, string2A, sizeof(string2A));
338 ok(ret == ERROR_INVALID_PARAMETER, "got %d (expected ERROR_INVALID_PARAMETER)\n", ret);
339
340 ret = RegSetValueA(hkey_main, NULL, REG_EXPAND_SZ, string2A, sizeof(string2A));
341 ok(ret == ERROR_INVALID_PARAMETER, "got %d (expected ERROR_INVALID_PARAMETER)\n", ret);
342
343 ret = RegSetValueA(hkey_main, NULL, REG_MULTI_SZ, string2A, sizeof(string2A));
344 ok(ret == ERROR_INVALID_PARAMETER, "got %d (expected ERROR_INVALID_PARAMETER)\n", ret);
345
346 /* Test RegSetValueExA with a 'zero-byte' string (as Office 2003 does).
347 * Surprisingly enough we're supposed to get zero bytes out of it.
348 */
349 ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)emptyA, 0);
350 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
351 test_hkey_main_Value_A(name1A, NULL, 0);
352 test_hkey_main_Value_W(name1W, NULL, 0);
353
354 /* test RegSetValueExA with an empty string */
355 ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)emptyA, sizeof(emptyA));
356 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
357 test_hkey_main_Value_A(name1A, emptyA, sizeof(emptyA));
358 test_hkey_main_Value_W(name1W, emptyW, sizeof(emptyW));
359
360 /* test RegSetValueExA with off-by-one size */
361 ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)string1A, sizeof(string1A)-sizeof(string1A[0]));
362 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
363 test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
364 test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
365
366 /* test RegSetValueExA with normal string */
367 ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)string1A, sizeof(string1A));
368 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
369 test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
370 test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
371
372 /* test RegSetValueExA with intrazeroed string */
373 ret = RegSetValueExA(hkey_main, name2A, 0, REG_SZ, (const BYTE *)string2A, sizeof(string2A));
374 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
375 test_hkey_main_Value_A(name2A, string2A, sizeof(string2A));
376 test_hkey_main_Value_W(name2W, string2W, sizeof(string2W));
377
378 if (0)
379 {
380 /* Crashes on NT4, Windows 2000 and XP SP1 */
381 ret = RegSetValueW(hkey_main, NULL, REG_SZ, NULL, 0);
382 ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have failed with ERROR_INVALID_PARAMETER instead of %d\n", ret);
383
384 RegSetValueExA(hkey_main, name2A, 0, REG_SZ, (const BYTE *)1, 1);
385 RegSetValueExA(hkey_main, name2A, 0, REG_DWORD, (const BYTE *)1, 1);
386 }
387
388 ret = RegSetValueW(hkey_main, NULL, REG_SZ, string1W, sizeof(string1W));
389 ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError());
390 test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
391 test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
392
393 ret = RegSetValueW(hkey_main, name1W, REG_SZ, string1W, sizeof(string1W));
394 ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError());
395 test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
396 test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
397
398 /* RegSetValueW ignores the size passed in */
399 ret = RegSetValueW(hkey_main, NULL, REG_SZ, string1W, 4 * sizeof(string1W[0]));
400 ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError());
401 test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
402 test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
403
404 /* stops at first null */
405 ret = RegSetValueW(hkey_main, NULL, REG_SZ, string2W, sizeof(string2W));
406 ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError());
407 test_hkey_main_Value_A(NULL, substring2A, sizeof(substring2A));
408 test_hkey_main_Value_W(NULL, substring2W, sizeof(substring2W));
409
410 /* only REG_SZ is supported */
411 ret = RegSetValueW(hkey_main, NULL, REG_BINARY, string2W, sizeof(string2W));
412 ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
413 ret = RegSetValueW(hkey_main, NULL, REG_EXPAND_SZ, string2W, sizeof(string2W));
414 ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
415 ret = RegSetValueW(hkey_main, NULL, REG_MULTI_SZ, string2W, sizeof(string2W));
416 ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
417
418 /* test RegSetValueExW with off-by-one size */
419 ret = RegSetValueExW(hkey_main, name1W, 0, REG_SZ, (const BYTE *)string1W, sizeof(string1W)-sizeof(string1W[0]));
420 ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %d, GLE=%d\n", ret, GetLastError());
421 test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
422 test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
423
424 /* test RegSetValueExW with normal string */
425 ret = RegSetValueExW(hkey_main, name1W, 0, REG_SZ, (const BYTE *)string1W, sizeof(string1W));
426 ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %d, GLE=%d\n", ret, GetLastError());
427 test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
428 test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
429
430 /* test RegSetValueExW with intrazeroed string */
431 ret = RegSetValueExW(hkey_main, name2W, 0, REG_SZ, (const BYTE *)string2W, sizeof(string2W));
432 ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %d, GLE=%d\n", ret, GetLastError());
433 test_hkey_main_Value_A(name2A, string2A, sizeof(string2A));
434 test_hkey_main_Value_W(name2W, string2W, sizeof(string2W));
435
436 /* test RegSetValueExW with data = 1 */
437 ret = RegSetValueExW(hkey_main, name2W, 0, REG_SZ, (const BYTE *)1, 1);
438 ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %d, GLE=%d\n", ret, GetLastError());
439 ret = RegSetValueExW(hkey_main, name2W, 0, REG_DWORD, (const BYTE *)1, 1);
440 ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %d, GLE=%d\n", ret, GetLastError());
441
442 if (pRegGetValueA) /* avoid a crash on Windows 2000 */
443 {
444 ret = RegSetValueExW(hkey_main, NULL, 0, REG_SZ, NULL, 4);
445 ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %d, GLE=%d\n", ret, GetLastError());
446
447 ret = RegSetValueExW(hkey_main, NULL, 0, REG_SZ, NULL, 0);
448 ok(ret == ERROR_SUCCESS, "got %d\n", ret);
449
450 ret = RegSetValueExW(hkey_main, NULL, 0, REG_DWORD, NULL, 4);
451 ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %d, GLE=%d\n", ret, GetLastError());
452
453 ret = RegSetValueExW(hkey_main, NULL, 0, REG_DWORD, NULL, 0);
454 ok(ret == ERROR_SUCCESS, "got %d\n", ret);
455 }
456
457 /* RegSetKeyValue */
458 if (!pRegSetKeyValueW)
459 win_skip("RegSetKeyValue() is not supported.\n");
460 else
461 {
462 static const WCHAR subkeyW[] = {'s','u','b','k','e','y',0};
463 DWORD len, type;
464 HKEY subkey;
465
466 ret = pRegSetKeyValueW(hkey_main, NULL, name1W, REG_SZ, (const BYTE*)string2W, sizeof(string2W));
467 ok(ret == ERROR_SUCCESS, "got %d\n", ret);
468 test_hkey_main_Value_A(name1A, string2A, sizeof(string2A));
469 test_hkey_main_Value_W(name1W, string2W, sizeof(string2W));
470
471 ret = pRegSetKeyValueW(hkey_main, subkeyW, name1W, REG_SZ, string1W, sizeof(string1W));
472 ok(ret == ERROR_SUCCESS, "got %d\n", ret);
473
474 ret = RegOpenKeyExW(hkey_main, subkeyW, 0, KEY_QUERY_VALUE, &subkey);
475 ok(ret == ERROR_SUCCESS, "got %d\n", ret);
476 type = len = 0;
477 ret = RegQueryValueExW(subkey, name1W, 0, &type, NULL, &len);
478 ok(ret == ERROR_SUCCESS, "got %d\n", ret);
479 ok(len == sizeof(string1W), "got %d\n", len);
480 ok(type == REG_SZ, "got type %d\n", type);
481
482 ret = pRegSetKeyValueW(hkey_main, subkeyW, name1W, REG_SZ, NULL, 0);
483 ok(ret == ERROR_SUCCESS, "got %d\n", ret);
484
485 ret = pRegSetKeyValueW(hkey_main, subkeyW, name1W, REG_SZ, NULL, 4);
486 ok(ret == ERROR_NOACCESS, "got %d\n", ret);
487
488 ret = pRegSetKeyValueW(hkey_main, subkeyW, name1W, REG_DWORD, NULL, 4);
489 ok(ret == ERROR_NOACCESS, "got %d\n", ret);
490
491 RegCloseKey(subkey);
492 }
493 }
494
495 static void create_test_entries(void)
496 {
497 static const DWORD qw[2] = { 0x12345678, 0x87654321 };
498
499 SetEnvironmentVariableA("LONGSYSTEMVAR", "bar");
500 SetEnvironmentVariableA("FOO", "ImARatherLongButIndeedNeededString");
501
502 ok(!RegSetValueExA(hkey_main,"TP1_EXP_SZ",0,REG_EXPAND_SZ, (const BYTE *)sTestpath1, strlen(sTestpath1)+1),
503 "RegSetValueExA failed\n");
504 ok(!RegSetValueExA(hkey_main,"TP1_SZ",0,REG_SZ, (const BYTE *)sTestpath1, strlen(sTestpath1)+1),
505 "RegSetValueExA failed\n");
506 ok(!RegSetValueExA(hkey_main,"TP1_ZB_SZ",0,REG_SZ, (const BYTE *)"", 0),
507 "RegSetValueExA failed\n");
508 ok(!RegSetValueExA(hkey_main,"TP2_EXP_SZ",0,REG_EXPAND_SZ, (const BYTE *)sTestpath2, strlen(sTestpath2)+1),
509 "RegSetValueExA failed\n");
510 ok(!RegSetValueExA(hkey_main,"DWORD",0,REG_DWORD, (const BYTE *)qw, 4),
511 "RegSetValueExA failed\n");
512 ok(!RegSetValueExA(hkey_main,"BIN32",0,REG_BINARY, (const BYTE *)qw, 4),
513 "RegSetValueExA failed\n");
514 ok(!RegSetValueExA(hkey_main,"BIN64",0,REG_BINARY, (const BYTE *)qw, 8),
515 "RegSetValueExA failed\n");
516 }
517
518 static void test_enum_value(void)
519 {
520 DWORD res;
521 HKEY test_key;
522 char value[20], data[20];
523 WCHAR valueW[20], dataW[20];
524 DWORD val_count, data_count, type;
525 static const WCHAR foobarW[] = {'f','o','o','b','a','r',0};
526 static const WCHAR testW[] = {'T','e','s','t',0};
527 static const WCHAR xxxW[] = {'x','x','x','x','x','x','x','x',0};
528
529 /* create the working key for new 'Test' value */
530 res = RegCreateKeyA( hkey_main, "TestKey", &test_key );
531 ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res);
532
533 /* check NULL data with zero length */
534 res = RegSetValueExA( test_key, "Test", 0, REG_SZ, NULL, 0 );
535 if (GetVersion() & 0x80000000)
536 ok( res == ERROR_INVALID_PARAMETER, "RegSetValueExA returned %d\n", res );
537 else
538 ok( !res, "RegSetValueExA returned %d\n", res );
539 res = RegSetValueExA( test_key, "Test", 0, REG_EXPAND_SZ, NULL, 0 );
540 ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %d\n", res );
541 res = RegSetValueExA( test_key, "Test", 0, REG_BINARY, NULL, 0 );
542 ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %d\n", res );
543
544 /* test reading the value and data without setting them */
545 val_count = 20;
546 data_count = 20;
547 type = 1234;
548 strcpy( value, "xxxxxxxxxx" );
549 strcpy( data, "xxxxxxxxxx" );
550 res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
551 ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res );
552 ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
553 ok( data_count == 0, "data_count set to %d instead of 0\n", data_count );
554 ok( type == REG_BINARY, "type %d is not REG_BINARY\n", type );
555 ok( !strcmp( value, "Test" ), "value is '%s' instead of Test\n", value );
556 ok( !strcmp( data, "xxxxxxxxxx" ), "data is '%s' instead of xxxxxxxxxx\n", data );
557
558 val_count = 20;
559 data_count = 20;
560 type = 1234;
561 memcpy( valueW, xxxW, sizeof(xxxW) );
562 memcpy( dataW, xxxW, sizeof(xxxW) );
563 res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
564 ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res );
565 ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
566 ok( data_count == 0, "data_count set to %d instead of 0\n", data_count );
567 ok( type == REG_BINARY, "type %d is not REG_BINARY\n", type );
568 ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" );
569 ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data is not 'xxxxxxxxxx'\n" );
570
571 res = RegSetValueExA( test_key, "Test", 0, REG_SZ, (const BYTE *)"foobar", 7 );
572 ok( res == 0, "RegSetValueExA failed error %d\n", res );
573
574 /* overflow both name and data */
575 val_count = 2;
576 data_count = 2;
577 type = 1234;
578 strcpy( value, "xxxxxxxxxx" );
579 strcpy( data, "xxxxxxxxxx" );
580 res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
581 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
582 ok( val_count == 2, "val_count set to %d\n", val_count );
583 ok( data_count == 7 || broken( data_count == 8 ), "data_count set to %d instead of 7\n", data_count );
584 ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
585 ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
586 ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data );
587
588 /* overflow name */
589 val_count = 3;
590 data_count = 20;
591 type = 1234;
592 strcpy( value, "xxxxxxxxxx" );
593 strcpy( data, "xxxxxxxxxx" );
594 res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
595 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
596 ok( val_count == 3, "val_count set to %d\n", val_count );
597 ok( data_count == 7 || broken( data_count == 8 ), "data_count set to %d instead of 7\n", data_count );
598 ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
599 /* v5.1.2600.0 (XP Home and Professional) does not touch value or data in this case */
600 ok( !strcmp( value, "Te" ) || !strcmp( value, "xxxxxxxxxx" ),
601 "value set to '%s' instead of 'Te' or 'xxxxxxxxxx'\n", value );
602 ok( !strcmp( data, "foobar" ) || !strcmp( data, "xxxxxxx" ) || broken( !strcmp( data, "xxxxxxxx" ) && data_count == 8 ),
603 "data set to '%s' instead of 'foobar' or 'xxxxxxx'\n", data );
604
605 /* overflow empty name */
606 val_count = 0;
607 data_count = 20;
608 type = 1234;
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_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
613 ok( val_count == 0, "val_count set to %d\n", val_count );
614 ok( data_count == 7 || broken( data_count == 8 ), "data_count set to %d instead of 7\n", data_count );
615 ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
616 ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
617 /* v5.1.2600.0 (XP Home and Professional) does not touch data in this case */
618 ok( !strcmp( data, "foobar" ) || !strcmp( data, "xxxxxxx" ) || broken( !strcmp( data, "xxxxxxxx" ) && data_count == 8 ),
619 "data set to '%s' instead of 'foobar' or 'xxxxxxx'\n", data );
620
621 /* overflow data */
622 val_count = 20;
623 data_count = 2;
624 type = 1234;
625 strcpy( value, "xxxxxxxxxx" );
626 strcpy( data, "xxxxxxxxxx" );
627 res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
628 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
629 ok( val_count == 20, "val_count set to %d\n", val_count );
630 ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
631 ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
632 ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
633 ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data );
634
635 /* no overflow */
636 val_count = 20;
637 data_count = 20;
638 type = 1234;
639 strcpy( value, "xxxxxxxxxx" );
640 strcpy( data, "xxxxxxxxxx" );
641 res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
642 ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res );
643 ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
644 ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
645 ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
646 ok( !strcmp( value, "Test" ), "value is '%s' instead of Test\n", value );
647 ok( !strcmp( data, "foobar" ), "data is '%s' instead of foobar\n", data );
648
649 if (pRegGetValueA) /* avoid a crash on Windows 2000 */
650 {
651 /* no value and no val_count parameter */
652 data_count = 20;
653 type = 1234;
654 strcpy( data, "xxxxxxxxxx" );
655 res = RegEnumValueA( test_key, 0, NULL, NULL, NULL, &type, (BYTE*)data, &data_count );
656 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res );
657
658 /* no value parameter */
659 val_count = 20;
660 data_count = 20;
661 type = 1234;
662 strcpy( data, "xxxxxxxxxx" );
663 res = RegEnumValueA( test_key, 0, NULL, &val_count, NULL, &type, (BYTE*)data, &data_count );
664 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res );
665
666 /* no val_count parameter */
667 data_count = 20;
668 type = 1234;
669 strcpy( value, "xxxxxxxxxx" );
670 strcpy( data, "xxxxxxxxxx" );
671 res = RegEnumValueA( test_key, 0, value, NULL, NULL, &type, (BYTE*)data, &data_count );
672 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res );
673 }
674
675 /* Unicode tests */
676
677 SetLastError(0xdeadbeef);
678 res = RegSetValueExW( test_key, testW, 0, REG_SZ, (const BYTE *)foobarW, 7*sizeof(WCHAR) );
679 if (res==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
680 {
681 win_skip("RegSetValueExW is not implemented\n");
682 goto cleanup;
683 }
684 ok( res == 0, "RegSetValueExW failed error %d\n", res );
685
686 /* overflow both name and data */
687 val_count = 2;
688 data_count = 2;
689 type = 1234;
690 memcpy( valueW, xxxW, sizeof(xxxW) );
691 memcpy( dataW, xxxW, sizeof(xxxW) );
692 res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
693 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
694 ok( val_count == 2, "val_count set to %d\n", val_count );
695 ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
696 ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
697 ok( !memcmp( valueW, xxxW, sizeof(xxxW) ), "value modified\n" );
698 ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
699
700 /* overflow name */
701 val_count = 3;
702 data_count = 20;
703 type = 1234;
704 memcpy( valueW, xxxW, sizeof(xxxW) );
705 memcpy( dataW, xxxW, sizeof(xxxW) );
706 res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
707 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
708 ok( val_count == 3, "val_count set to %d\n", val_count );
709 ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
710 ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
711 ok( !memcmp( valueW, xxxW, sizeof(xxxW) ), "value modified\n" );
712 ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
713
714 /* overflow data */
715 val_count = 20;
716 data_count = 2;
717 type = 1234;
718 memcpy( valueW, xxxW, sizeof(xxxW) );
719 memcpy( dataW, xxxW, sizeof(xxxW) );
720 res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
721 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
722 ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
723 ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
724 ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
725 ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" );
726 ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
727
728 /* no overflow */
729 val_count = 20;
730 data_count = 20;
731 type = 1234;
732 memcpy( valueW, xxxW, sizeof(xxxW) );
733 memcpy( dataW, xxxW, sizeof(xxxW) );
734 res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
735 ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res );
736 ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
737 ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
738 ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
739 ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" );
740 ok( !memcmp( dataW, foobarW, sizeof(foobarW) ), "data is not 'foobar'\n" );
741
742 if (pRegGetValueA) /* avoid a crash on Windows 2000 */
743 {
744 /* no valueW and no val_count parameter */
745 data_count = 20;
746 type = 1234;
747 memcpy( dataW, xxxW, sizeof(xxxW) );
748 res = RegEnumValueW( test_key, 0, NULL, NULL, NULL, &type, (BYTE*)dataW, &data_count );
749 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res );
750
751 /* no valueW parameter */
752 val_count = 20;
753 data_count = 20;
754 type = 1234;
755 memcpy( dataW, xxxW, sizeof(xxxW) );
756 res = RegEnumValueW( test_key, 0, NULL, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
757 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res );
758
759 /* no val_count parameter */
760 data_count = 20;
761 type = 1234;
762 memcpy( valueW, xxxW, sizeof(xxxW) );
763 memcpy( dataW, xxxW, sizeof(xxxW) );
764 res = RegEnumValueW( test_key, 0, valueW, NULL, NULL, &type, (BYTE*)dataW, &data_count );
765 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res );
766 }
767
768 cleanup:
769 RegDeleteKeyA(test_key, "");
770 RegCloseKey(test_key);
771 }
772
773 static void test_query_value_ex(void)
774 {
775 DWORD ret;
776 DWORD size;
777 DWORD type;
778 BYTE buffer[10];
779
780 ret = RegQueryValueExA(hkey_main, "TP1_SZ", NULL, &type, NULL, &size);
781 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
782 ok(size == strlen(sTestpath1) + 1, "(%d,%d)\n", (DWORD)strlen(sTestpath1) + 1, size);
783 ok(type == REG_SZ, "type %d is not REG_SZ\n", type);
784
785 type = 0xdeadbeef;
786 size = 0xdeadbeef;
787 ret = RegQueryValueExA(HKEY_CLASSES_ROOT, "Nonexistent Value", NULL, &type, NULL, &size);
788 ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
789 ok(size == 0, "size should have been set to 0 instead of %d\n", size);
790
791 size = sizeof(buffer);
792 ret = RegQueryValueExA(HKEY_CLASSES_ROOT, "Nonexistent Value", NULL, &type, buffer, &size);
793 ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
794 ok(size == sizeof(buffer), "size shouldn't have been changed to %d\n", size);
795
796 size = 4;
797 ret = RegQueryValueExA(hkey_main, "BIN32", NULL, &size, buffer, &size);
798 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
799 }
800
801 static void test_get_value(void)
802 {
803 DWORD ret;
804 DWORD size;
805 DWORD type;
806 DWORD dw, qw[2];
807 CHAR buf[80];
808 CHAR expanded[] = "bar\\subdir1";
809 CHAR expanded2[] = "ImARatherLongButIndeedNeededString\\subdir1";
810
811 if(!pRegGetValueA)
812 {
813 win_skip("RegGetValue not available on this platform\n");
814 return;
815 }
816
817 /* Invalid parameter */
818 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_DWORD, &type, &dw, NULL);
819 ok(ret == ERROR_INVALID_PARAMETER, "ret=%d\n", ret);
820
821 /* Query REG_DWORD using RRF_RT_REG_DWORD (ok) */
822 size = type = dw = 0xdeadbeef;
823 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_DWORD, &type, &dw, &size);
824 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
825 ok(size == 4, "size=%d\n", size);
826 ok(type == REG_DWORD, "type=%d\n", type);
827 ok(dw == 0x12345678, "dw=%d\n", dw);
828
829 /* Query by subkey-name */
830 ret = pRegGetValueA(HKEY_CURRENT_USER, "Software\\Wine\\Test", "DWORD", RRF_RT_REG_DWORD, NULL, NULL, NULL);
831 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
832
833 /* Query REG_DWORD using RRF_RT_REG_BINARY (restricted) */
834 size = type = dw = 0xdeadbeef;
835 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_BINARY, &type, &dw, &size);
836 ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
837 /* Although the function failed all values are retrieved */
838 ok(size == 4, "size=%d\n", size);
839 ok(type == REG_DWORD, "type=%d\n", type);
840 ok(dw == 0x12345678, "dw=%d\n", dw);
841
842 /* Test RRF_ZEROONFAILURE */
843 type = dw = 0xdeadbeef; size = 4;
844 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_SZ|RRF_ZEROONFAILURE, &type, &dw, &size);
845 ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
846 /* Again all values are retrieved ... */
847 ok(size == 4, "size=%d\n", size);
848 ok(type == REG_DWORD, "type=%d\n", type);
849 /* ... except the buffer, which is zeroed out */
850 ok(dw == 0, "dw=%d\n", dw);
851
852 /* Test RRF_ZEROONFAILURE with a NULL buffer... */
853 type = size = 0xbadbeef;
854 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_SZ|RRF_ZEROONFAILURE, &type, NULL, &size);
855 ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
856 ok(size == 4, "size=%d\n", size);
857 ok(type == REG_DWORD, "type=%d\n", type);
858
859 /* Query REG_DWORD using RRF_RT_DWORD (ok) */
860 size = type = dw = 0xdeadbeef;
861 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_DWORD, &type, &dw, &size);
862 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
863 ok(size == 4, "size=%d\n", size);
864 ok(type == REG_DWORD, "type=%d\n", type);
865 ok(dw == 0x12345678, "dw=%d\n", dw);
866
867 /* Query 32-bit REG_BINARY using RRF_RT_DWORD (ok) */
868 size = type = dw = 0xdeadbeef;
869 ret = pRegGetValueA(hkey_main, NULL, "BIN32", RRF_RT_DWORD, &type, &dw, &size);
870 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
871 ok(size == 4, "size=%d\n", size);
872 ok(type == REG_BINARY, "type=%d\n", type);
873 ok(dw == 0x12345678, "dw=%d\n", dw);
874
875 /* Query 64-bit REG_BINARY using RRF_RT_DWORD (type mismatch) */
876 qw[0] = qw[1] = size = type = 0xdeadbeef;
877 ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_DWORD, &type, qw, &size);
878 ok(ret == ERROR_DATATYPE_MISMATCH, "ret=%d\n", ret);
879 ok(size == 8, "size=%d\n", size);
880 ok(type == REG_BINARY, "type=%d\n", type);
881 ok(qw[0] == 0x12345678 &&
882 qw[1] == 0x87654321, "qw={%d,%d}\n", qw[0], qw[1]);
883
884 /* Query 64-bit REG_BINARY using 32-bit buffer (buffer too small) */
885 type = dw = 0xdeadbeef; size = 4;
886 ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_REG_BINARY, &type, &dw, &size);
887 ok(ret == ERROR_MORE_DATA, "ret=%d\n", ret);
888 ok(dw == 0xdeadbeef, "dw=%d\n", dw);
889 ok(size == 8, "size=%d\n", size);
890
891 /* Query 64-bit REG_BINARY using RRF_RT_QWORD (ok) */
892 qw[0] = qw[1] = size = type = 0xdeadbeef;
893 ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_QWORD, &type, qw, &size);
894 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
895 ok(size == 8, "size=%d\n", size);
896 ok(type == REG_BINARY, "type=%d\n", type);
897 ok(qw[0] == 0x12345678 &&
898 qw[1] == 0x87654321, "qw={%d,%d}\n", qw[0], qw[1]);
899
900 /* Query REG_SZ using RRF_RT_REG_SZ (ok) */
901 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
902 ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ, &type, buf, &size);
903 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
904 ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
905 ok(type == REG_SZ, "type=%d\n", type);
906 ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
907
908 /* Query REG_SZ using RRF_RT_REG_SZ and no buffer (ok) */
909 type = 0xdeadbeef; size = 0;
910 ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ, &type, NULL, &size);
911 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
912 /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
913 ok(size == strlen(sTestpath1)+1 || broken(size == strlen(sTestpath1)+2),
914 "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
915 ok(type == REG_SZ, "type=%d\n", type);
916
917 /* Query REG_SZ using RRF_RT_REG_SZ on a zero-byte value (ok) */
918 strcpy(buf, sTestpath1);
919 type = 0xdeadbeef;
920 size = sizeof(buf);
921 ret = pRegGetValueA(hkey_main, NULL, "TP1_ZB_SZ", RRF_RT_REG_SZ, &type, buf, &size);
922 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
923 /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
924 ok(size == 0 ||
925 size == 1, /* win2k3 */
926 "size=%d\n", size);
927 ok(type == REG_SZ, "type=%d\n", type);
928 ok(!strcmp(sTestpath1, buf) ||
929 !strcmp(buf, ""),
930 "Expected \"%s\" or \"\", got \"%s\"\n", sTestpath1, buf);
931
932 /* Query REG_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (ok) */
933 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
934 ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ|RRF_NOEXPAND, &type, buf, &size);
935 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
936 ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
937 ok(type == REG_SZ, "type=%d\n", type);
938 ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
939
940 /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ and no buffer (ok, expands) */
941 size = 0;
942 ret = pRegGetValueA(hkey_main, NULL, "TP2_EXP_SZ", RRF_RT_REG_SZ, NULL, NULL, &size);
943 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
944 ok((size == strlen(expanded2)+1) || /* win2k3 SP1 */
945 (size == strlen(expanded2)+2) || /* win2k3 SP2 */
946 (size == strlen(sTestpath2)+1),
947 "strlen(expanded2)=%d, strlen(sTestpath2)=%d, size=%d\n", lstrlenA(expanded2), lstrlenA(sTestpath2), size);
948
949 /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ (ok, expands) */
950 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
951 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_SZ, &type, buf, &size);
952 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
953 /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath1 length + 1 here. */
954 ok(size == strlen(expanded)+1 || broken(size == strlen(sTestpath1)+1),
955 "strlen(expanded)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded), lstrlenA(sTestpath1), size);
956 ok(type == REG_SZ, "type=%d\n", type);
957 ok(!strcmp(expanded, buf), "expanded=\"%s\" buf=\"%s\"\n", expanded, buf);
958
959 /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ (ok, expands a lot) */
960 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
961 ret = pRegGetValueA(hkey_main, NULL, "TP2_EXP_SZ", RRF_RT_REG_SZ, &type, buf, &size);
962 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
963 /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath2 length + 1 here. */
964 ok(size == strlen(expanded2)+1 || broken(size == strlen(sTestpath2)+1),
965 "strlen(expanded2)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded2), lstrlenA(sTestpath2), size);
966 ok(type == REG_SZ, "type=%d\n", type);
967 ok(!strcmp(expanded2, buf), "expanded2=\"%s\" buf=\"%s\"\n", expanded2, buf);
968
969 /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND (ok, doesn't expand) */
970 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
971 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND, &type, buf, &size);
972 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
973 ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
974 ok(type == REG_EXPAND_SZ, "type=%d\n", type);
975 ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
976
977 /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND and no buffer (ok, doesn't expand) */
978 size = 0xbadbeef;
979 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND, NULL, NULL, &size);
980 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
981 /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
982 ok(size == strlen(sTestpath1)+1 || broken(size == strlen(sTestpath1)+2),
983 "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
984
985 /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (type mismatch) */
986 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_SZ|RRF_NOEXPAND, NULL, NULL, NULL);
987 ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
988
989 /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ (not allowed without RRF_NOEXPAND) */
990 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ, NULL, NULL, NULL);
991 /* before win8: ERROR_INVALID_PARAMETER, win8: ERROR_UNSUPPORTED_TYPE */
992 ok(ret == ERROR_INVALID_PARAMETER || ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
993
994 /* Query REG_EXPAND_SZ using RRF_RT_ANY */
995 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
996 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_ANY, &type, buf, &size);
997 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
998 /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath1 length + 1 here. */
999 ok(size == strlen(expanded)+1 || broken(size == strlen(sTestpath1)+1),
1000 "strlen(expanded)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded), lstrlenA(sTestpath1), size);
1001 ok(type == REG_SZ, "type=%d\n", type);
1002 ok(!strcmp(expanded, buf), "expanded=\"%s\" buf=\"%s\"\n", expanded, buf);
1003 }
1004
1005 static void test_reg_open_key(void)
1006 {
1007 DWORD ret = 0;
1008 HKEY hkResult = NULL;
1009 HKEY hkPreserve = NULL;
1010 HKEY hkRoot64 = NULL;
1011 HKEY hkRoot32 = NULL;
1012 BOOL bRet;
1013 SID_IDENTIFIER_AUTHORITY sid_authority = {SECURITY_WORLD_SID_AUTHORITY};
1014 PSID world_sid;
1015 EXPLICIT_ACCESSA access;
1016 PACL key_acl;
1017 SECURITY_DESCRIPTOR *sd;
1018
1019 /* successful open */
1020 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult);
1021 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1022 ok(hkResult != NULL, "expected hkResult != NULL\n");
1023 hkPreserve = hkResult;
1024
1025 /* open same key twice */
1026 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult);
1027 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1028 ok(hkResult != hkPreserve, "expected hkResult != hkPreserve\n");
1029 ok(hkResult != NULL, "hkResult != NULL\n");
1030 RegCloseKey(hkResult);
1031
1032 /* trailing slashes */
1033 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test\\\\", &hkResult);
1034 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1035 RegCloseKey(hkResult);
1036
1037 /* open nonexistent key
1038 * check that hkResult is set to NULL
1039 */
1040 hkResult = hkPreserve;
1041 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
1042 ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
1043 ok(hkResult == NULL, "expected hkResult == NULL\n");
1044
1045 /* open the same nonexistent key again to make sure the key wasn't created */
1046 hkResult = hkPreserve;
1047 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
1048 ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
1049 ok(hkResult == NULL, "expected hkResult == NULL\n");
1050
1051 /* send in NULL lpSubKey
1052 * check that hkResult receives the value of hKey
1053 */
1054 hkResult = hkPreserve;
1055 ret = RegOpenKeyA(HKEY_CURRENT_USER, NULL, &hkResult);
1056 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1057 ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
1058
1059 /* send empty-string in lpSubKey */
1060 hkResult = hkPreserve;
1061 ret = RegOpenKeyA(HKEY_CURRENT_USER, "", &hkResult);
1062 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1063 ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
1064
1065 /* send in NULL lpSubKey and NULL hKey
1066 * hkResult is set to NULL
1067 */
1068 hkResult = hkPreserve;
1069 ret = RegOpenKeyA(NULL, NULL, &hkResult);
1070 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1071 ok(hkResult == NULL, "expected hkResult == NULL\n");
1072
1073 /* only send NULL hKey
1074 * the value of hkResult remains unchanged
1075 */
1076 hkResult = hkPreserve;
1077 ret = RegOpenKeyA(NULL, "Software\\Wine\\Test", &hkResult);
1078 ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */
1079 "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
1080 ok(hkResult == hkPreserve, "expected hkResult == hkPreserve\n");
1081
1082 /* send in NULL hkResult */
1083 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", NULL);
1084 ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", ret);
1085
1086 ret = RegOpenKeyA(HKEY_CURRENT_USER, NULL, NULL);
1087 ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", ret);
1088
1089 ret = RegOpenKeyA(NULL, NULL, NULL);
1090 ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", ret);
1091
1092 /* beginning backslash character */
1093 ret = RegOpenKeyA(HKEY_CURRENT_USER, "\\Software\\Wine\\Test", &hkResult);
1094 ok(ret == ERROR_BAD_PATHNAME || /* NT/2k/XP */
1095 broken(ret == ERROR_SUCCESS), /* wow64 */
1096 "expected ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %d\n", ret);
1097 if (!ret) RegCloseKey(hkResult);
1098
1099 hkResult = NULL;
1100 ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, "\\clsid", 0, KEY_QUERY_VALUE, &hkResult);
1101 ok(ret == ERROR_SUCCESS || /* 2k/XP */
1102 ret == ERROR_BAD_PATHNAME, /* NT */
1103 "expected ERROR_SUCCESS, ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %d\n", ret);
1104 RegCloseKey(hkResult);
1105
1106 /* NULL or empty subkey of special root */
1107 hkResult = NULL;
1108 ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, NULL, 0, KEY_QUERY_VALUE, &hkResult);
1109 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1110 ok(hkResult == HKEY_CLASSES_ROOT, "expected hkResult == HKEY_CLASSES_ROOT\n");
1111
1112 hkResult = NULL;
1113 ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, "", 0, KEY_QUERY_VALUE, &hkResult);
1114 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1115 ok(hkResult == HKEY_CLASSES_ROOT, "expected hkResult == HKEY_CLASSES_ROOT\n");
1116
1117 hkResult = NULL;
1118 ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, "\\", 0, KEY_QUERY_VALUE, &hkResult);
1119 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1120 ok(hkResult != HKEY_CLASSES_ROOT, "expected hkResult to be a new key\n");
1121 ok(!RegCloseKey(hkResult), "got invalid hkey\n");
1122
1123 /* empty subkey of existing handle */
1124 hkResult = hkPreserve;
1125 ret = RegOpenKeyExA(hkPreserve, "", 0, KEY_QUERY_VALUE, &hkResult);
1126 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1127 ok(hkResult != hkPreserve, "expected hkResult != hkPreserve\n");
1128 ok(!RegCloseKey(hkResult), "got invalid hkey\n");
1129
1130 /* NULL subkey of existing handle */
1131 hkResult = hkPreserve;
1132 ret = RegOpenKeyExA(hkPreserve, NULL, 0, KEY_QUERY_VALUE, &hkResult);
1133 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1134 ok(hkResult != hkPreserve, "expected hkResult != hkPreserve\n");
1135 ok(!RegCloseKey(hkResult), "got invalid hkey\n");
1136
1137 /* empty subkey of NULL */
1138 hkResult = hkPreserve;
1139 ret = RegOpenKeyExA(NULL, "", 0, KEY_QUERY_VALUE, &hkResult);
1140 ok(ret == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", ret);
1141 ok(hkResult == hkPreserve, "expected hkResult == hkPreserve\n");
1142
1143 RegCloseKey(hkPreserve);
1144
1145 /* WOW64 flags */
1146 hkResult = NULL;
1147 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WOW64_32KEY, &hkResult);
1148 ok((ret == ERROR_SUCCESS && hkResult != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */),
1149 "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret);
1150 RegCloseKey(hkResult);
1151
1152 hkResult = NULL;
1153 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WOW64_64KEY, &hkResult);
1154 ok((ret == ERROR_SUCCESS && hkResult != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */),
1155 "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret);
1156 RegCloseKey(hkResult);
1157
1158 /* check special HKEYs on 64bit
1159 * only the lower 4 bytes of the supplied key are used
1160 */
1161 if (ptr_size == 64)
1162 {
1163 /* HKEY_CURRENT_USER */
1164 ret = RegOpenKeyA(UlongToHandle(HandleToUlong(HKEY_CURRENT_USER)), "Software", &hkResult);
1165 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1166 ok(hkResult != NULL, "expected hkResult != NULL\n");
1167 RegCloseKey(hkResult);
1168
1169 ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_CURRENT_USER) | (ULONG64)1 << 32), "Software", &hkResult);
1170 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1171 ok(hkResult != NULL, "expected hkResult != NULL\n");
1172 RegCloseKey(hkResult);
1173
1174 ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_CURRENT_USER) | (ULONG64)0xdeadbeef << 32), "Software", &hkResult);
1175 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1176 ok(hkResult != NULL, "expected hkResult != NULL\n");
1177 RegCloseKey(hkResult);
1178
1179 ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_CURRENT_USER) | (ULONG64)0xffffffff << 32), "Software", &hkResult);
1180 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1181 ok(hkResult != NULL, "expected hkResult != NULL\n");
1182 RegCloseKey(hkResult);
1183
1184 /* HKEY_LOCAL_MACHINE */
1185 ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_LOCAL_MACHINE) | (ULONG64)0xdeadbeef << 32), "Software", &hkResult);
1186 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1187 ok(hkResult != NULL, "expected hkResult != NULL\n");
1188 RegCloseKey(hkResult);
1189 }
1190
1191 /* Try using WOW64 flags when opening a key with a DACL set to verify that
1192 * the registry access check is performed correctly. Redirection isn't
1193 * being tested, so the tests don't care about whether the process is
1194 * running under WOW64. */
1195 if (!pIsWow64Process)
1196 {
1197 win_skip("WOW64 flags are not recognized\n");
1198 return;
1199 }
1200
1201 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1202 KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &hkRoot32, NULL);
1203 if (limited_user)
1204 ok(ret == ERROR_ACCESS_DENIED && hkRoot32 == NULL,
1205 "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret);
1206 else
1207 ok(ret == ERROR_SUCCESS && hkRoot32 != NULL,
1208 "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret);
1209
1210 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1211 KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &hkRoot64, NULL);
1212 if (limited_user)
1213 ok(ret == ERROR_ACCESS_DENIED && hkRoot64 == NULL,
1214 "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret);
1215 else
1216 ok(ret == ERROR_SUCCESS && hkRoot64 != NULL,
1217 "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret);
1218
1219 bRet = AllocateAndInitializeSid(&sid_authority, 1, SECURITY_WORLD_RID,
1220 0, 0, 0, 0, 0, 0, 0, &world_sid);
1221 ok(bRet == TRUE,
1222 "Expected AllocateAndInitializeSid to return TRUE, got %d, last error %u\n", bRet, GetLastError());
1223
1224 access.grfAccessPermissions = GENERIC_ALL | STANDARD_RIGHTS_ALL;
1225 access.grfAccessMode = SET_ACCESS;
1226 access.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
1227 access.Trustee.pMultipleTrustee = NULL;
1228 access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1229 access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
1230 access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
1231 access.Trustee.ptstrName = (char *)world_sid;
1232
1233 ret = SetEntriesInAclA(1, &access, NULL, &key_acl);
1234 ok(ret == ERROR_SUCCESS,
1235 "Expected SetEntriesInAclA to return ERROR_SUCCESS, got %u, last error %u\n", ret, GetLastError());
1236
1237 sd = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
1238 bRet = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
1239 ok(bRet == TRUE,
1240 "Expected InitializeSecurityDescriptor to return TRUE, got %d, last error %u\n", bRet, GetLastError());
1241
1242 bRet = SetSecurityDescriptorDacl(sd, TRUE, key_acl, FALSE);
1243 ok(bRet == TRUE,
1244 "Expected SetSecurityDescriptorDacl to return TRUE, got %d, last error %u\n", bRet, GetLastError());
1245
1246 if (limited_user)
1247 {
1248 skip("not enough privileges to modify HKLM\n");
1249 }
1250 else
1251 {
1252 LONG error;
1253
1254 error = RegSetKeySecurity(hkRoot64, DACL_SECURITY_INFORMATION, sd);
1255 ok(error == ERROR_SUCCESS,
1256 "Expected RegSetKeySecurity to return success, got error %u\n", error);
1257
1258 error = RegSetKeySecurity(hkRoot32, DACL_SECURITY_INFORMATION, sd);
1259 ok(error == ERROR_SUCCESS,
1260 "Expected RegSetKeySecurity to return success, got error %u\n", error);
1261
1262 hkResult = NULL;
1263 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, KEY_WOW64_64KEY | KEY_READ, &hkResult);
1264 ok(ret == ERROR_SUCCESS && hkResult != NULL,
1265 "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret);
1266 RegCloseKey(hkResult);
1267
1268 hkResult = NULL;
1269 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, KEY_WOW64_32KEY | KEY_READ, &hkResult);
1270 ok(ret == ERROR_SUCCESS && hkResult != NULL,
1271 "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret);
1272 RegCloseKey(hkResult);
1273 }
1274
1275 HeapFree(GetProcessHeap(), 0, sd);
1276 LocalFree(key_acl);
1277 FreeSid(world_sid);
1278 RegDeleteKeyA(hkRoot64, "");
1279 RegCloseKey(hkRoot64);
1280 RegDeleteKeyA(hkRoot32, "");
1281 RegCloseKey(hkRoot32);
1282 }
1283
1284 static void test_reg_create_key(void)
1285 {
1286 LONG ret;
1287 HKEY hkey1, hkey2;
1288 HKEY hkRoot64 = NULL;
1289 HKEY hkRoot32 = NULL;
1290 DWORD dwRet;
1291 BOOL bRet;
1292 SID_IDENTIFIER_AUTHORITY sid_authority = {SECURITY_WORLD_SID_AUTHORITY};
1293 PSID world_sid;
1294 EXPLICIT_ACCESSA access;
1295 PACL key_acl;
1296 SECURITY_DESCRIPTOR *sd;
1297
1298 ret = RegCreateKeyExA(hkey_main, "Subkey1", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL);
1299 ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
1300 /* should succeed: all versions of Windows ignore the access rights
1301 * to the parent handle */
1302 ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey2, NULL);
1303 ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
1304
1305 /* clean up */
1306 RegDeleteKeyA(hkey2, "");
1307 RegDeleteKeyA(hkey1, "");
1308 RegCloseKey(hkey2);
1309 RegCloseKey(hkey1);
1310
1311 /* test creation of volatile keys */
1312 ret = RegCreateKeyExA(hkey_main, "Volatile", 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey1, NULL);
1313 ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
1314 ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey2, NULL);
1315 ok(ret == ERROR_CHILD_MUST_BE_VOLATILE, "RegCreateKeyExA failed with error %d\n", ret);
1316 if (!ret) RegCloseKey( hkey2 );
1317 ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey2, NULL);
1318 ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
1319 RegCloseKey(hkey2);
1320 /* should succeed if the key already exists */
1321 ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey2, NULL);
1322 ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
1323
1324 /* clean up */
1325 RegDeleteKeyA(hkey2, "");
1326 RegDeleteKeyA(hkey1, "");
1327 RegCloseKey(hkey2);
1328 RegCloseKey(hkey1);
1329
1330 /* beginning backslash character */
1331 ret = RegCreateKeyExA(hkey_main, "\\Subkey3", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL);
1332 if (!(GetVersion() & 0x80000000))
1333 ok(ret == ERROR_BAD_PATHNAME, "expected ERROR_BAD_PATHNAME, got %d\n", ret);
1334 else {
1335 ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
1336 RegDeleteKeyA(hkey1, "");
1337 RegCloseKey(hkey1);
1338 }
1339
1340 /* trailing backslash characters */
1341 ret = RegCreateKeyExA(hkey_main, "Subkey4\\\\", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL);
1342 ok(ret == ERROR_SUCCESS, "RegCreateKeyExA failed with error %d\n", ret);
1343 RegDeleteKeyA(hkey1, "");
1344 RegCloseKey(hkey1);
1345
1346 /* WOW64 flags - open an existing key */
1347 hkey1 = NULL;
1348 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0, KEY_READ|KEY_WOW64_32KEY, NULL, &hkey1, NULL);
1349 ok((ret == ERROR_SUCCESS && hkey1 != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */),
1350 "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret);
1351 RegCloseKey(hkey1);
1352
1353 hkey1 = NULL;
1354 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0, KEY_READ|KEY_WOW64_64KEY, NULL, &hkey1, NULL);
1355 ok((ret == ERROR_SUCCESS && hkey1 != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */),
1356 "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret);
1357 RegCloseKey(hkey1);
1358
1359 /* Try using WOW64 flags when opening a key with a DACL set to verify that
1360 * the registry access check is performed correctly. Redirection isn't
1361 * being tested, so the tests don't care about whether the process is
1362 * running under WOW64. */
1363 if (!pIsWow64Process)
1364 {
1365 win_skip("WOW64 flags are not recognized\n");
1366 return;
1367 }
1368
1369 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1370 KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &hkRoot32, NULL);
1371 if (limited_user)
1372 ok(ret == ERROR_ACCESS_DENIED && hkRoot32 == NULL,
1373 "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%d)\n", ret);
1374 else
1375 ok(ret == ERROR_SUCCESS && hkRoot32 != NULL,
1376 "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%d)\n", ret);
1377
1378 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1379 KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &hkRoot64, NULL);
1380 if (limited_user)
1381 ok(ret == ERROR_ACCESS_DENIED && hkRoot64 == NULL,
1382 "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%d)\n", ret);
1383 else
1384 ok(ret == ERROR_SUCCESS && hkRoot64 != NULL,
1385 "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%d)\n", ret);
1386
1387 bRet = AllocateAndInitializeSid(&sid_authority, 1, SECURITY_WORLD_RID,
1388 0, 0, 0, 0, 0, 0, 0, &world_sid);
1389 ok(bRet == TRUE,
1390 "Expected AllocateAndInitializeSid to return TRUE, got %d, last error %u\n", bRet, GetLastError());
1391
1392 access.grfAccessPermissions = GENERIC_ALL | STANDARD_RIGHTS_ALL;
1393 access.grfAccessMode = SET_ACCESS;
1394 access.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
1395 access.Trustee.pMultipleTrustee = NULL;
1396 access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1397 access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
1398 access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
1399 access.Trustee.ptstrName = (char *)world_sid;
1400
1401 dwRet = SetEntriesInAclA(1, &access, NULL, &key_acl);
1402 ok(dwRet == ERROR_SUCCESS,
1403 "Expected SetEntriesInAclA to return ERROR_SUCCESS, got %u, last error %u\n", dwRet, GetLastError());
1404
1405 sd = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
1406 bRet = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
1407 ok(bRet == TRUE,
1408 "Expected InitializeSecurityDescriptor to return TRUE, got %d, last error %u\n", bRet, GetLastError());
1409
1410 bRet = SetSecurityDescriptorDacl(sd, TRUE, key_acl, FALSE);
1411 ok(bRet == TRUE,
1412 "Expected SetSecurityDescriptorDacl to return TRUE, got %d, last error %u\n", bRet, GetLastError());
1413
1414 if (limited_user)
1415 {
1416 skip("not enough privileges to modify HKLM\n");
1417 }
1418 else
1419 {
1420 ret = RegSetKeySecurity(hkRoot64, DACL_SECURITY_INFORMATION, sd);
1421 ok(ret == ERROR_SUCCESS,
1422 "Expected RegSetKeySecurity to return success, got error %u\n", ret);
1423
1424 ret = RegSetKeySecurity(hkRoot32, DACL_SECURITY_INFORMATION, sd);
1425 ok(ret == ERROR_SUCCESS,
1426 "Expected RegSetKeySecurity to return success, got error %u\n", ret);
1427
1428 hkey1 = NULL;
1429 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1430 KEY_WOW64_64KEY | KEY_READ, NULL, &hkey1, NULL);
1431 ok(ret == ERROR_SUCCESS && hkey1 != NULL,
1432 "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret);
1433 RegCloseKey(hkey1);
1434
1435 hkey1 = NULL;
1436 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1437 KEY_WOW64_32KEY | KEY_READ, NULL, &hkey1, NULL);
1438 ok(ret == ERROR_SUCCESS && hkey1 != NULL,
1439 "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret);
1440 RegCloseKey(hkey1);
1441 }
1442
1443 HeapFree(GetProcessHeap(), 0, sd);
1444 LocalFree(key_acl);
1445 FreeSid(world_sid);
1446 RegDeleteKeyA(hkRoot64, "");
1447 RegCloseKey(hkRoot64);
1448 RegDeleteKeyA(hkRoot32, "");
1449 RegCloseKey(hkRoot32);
1450 }
1451
1452 static void test_reg_close_key(void)
1453 {
1454 DWORD ret = 0;
1455 HKEY hkHandle;
1456
1457 /* successfully close key
1458 * hkHandle remains changed after call to RegCloseKey
1459 */
1460 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkHandle);
1461 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1462 ret = RegCloseKey(hkHandle);
1463 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1464
1465 /* try to close the key twice */
1466 ret = RegCloseKey(hkHandle); /* Windows 95 doesn't mind. */
1467 ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_SUCCESS,
1468 "expected ERROR_INVALID_HANDLE or ERROR_SUCCESS, got %d\n", ret);
1469
1470 /* try to close a NULL handle */
1471 ret = RegCloseKey(NULL);
1472 ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */
1473 "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
1474
1475 /* Check to see if we didn't potentially close our main handle, which could happen on win98 as
1476 * win98 doesn't give a new handle when the same key is opened.
1477 * Not re-opening will make some next tests fail.
1478 */
1479 if (hkey_main == hkHandle)
1480 {
1481 trace("The main handle is most likely closed, so re-opening\n");
1482 RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main );
1483 }
1484 }
1485
1486 static void test_reg_delete_key(void)
1487 {
1488 DWORD ret;
1489 HKEY key;
1490
1491 ret = RegDeleteKeyA(hkey_main, NULL);
1492
1493 /* There is a bug in NT4 and W2K that doesn't check if the subkey is NULL. If
1494 * there are also no subkeys available it will delete the key pointed to by hkey_main.
1495 * Not re-creating will make some next tests fail.
1496 */
1497 if (ret == ERROR_SUCCESS)
1498 {
1499 trace("We are probably running on NT4 or W2K as the main key is deleted,"
1500 " re-creating the main key\n");
1501 setup_main_key();
1502 }
1503 else
1504 ok(ret == ERROR_INVALID_PARAMETER ||
1505 ret == ERROR_ACCESS_DENIED ||
1506 ret == ERROR_BADKEY, /* Win95 */
1507 "ret=%d\n", ret);
1508
1509 ret = RegCreateKeyA(hkey_main, "deleteme", &key);
1510 ok(ret == ERROR_SUCCESS, "Could not create key, got %d\n", ret);
1511 ret = RegDeleteKeyA(key, "");
1512 ok(ret == ERROR_SUCCESS, "RegDeleteKeyA failed, got %d\n", ret);
1513 RegCloseKey(key);
1514 ret = RegOpenKeyA(hkey_main, "deleteme", &key);
1515 ok(ret == ERROR_FILE_NOT_FOUND, "Key was not deleted, got %d\n", ret);
1516 RegCloseKey(key);
1517 }
1518
1519 static BOOL set_privileges(LPCSTR privilege, BOOL set)
1520 {
1521 TOKEN_PRIVILEGES tp;
1522 HANDLE hToken;
1523 LUID luid;
1524
1525 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
1526 return FALSE;
1527
1528 if(!LookupPrivilegeValueA(NULL, privilege, &luid))
1529 {
1530 CloseHandle(hToken);
1531 return FALSE;
1532 }
1533
1534 tp.PrivilegeCount = 1;
1535 tp.Privileges[0].Luid = luid;
1536
1537 if (set)
1538 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1539 else
1540 tp.Privileges[0].Attributes = 0;
1541
1542 AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
1543 if (GetLastError() != ERROR_SUCCESS)
1544 {
1545 CloseHandle(hToken);
1546 return FALSE;
1547 }
1548
1549 CloseHandle(hToken);
1550 return TRUE;
1551 }
1552
1553 static void test_reg_save_key(void)
1554 {
1555 DWORD ret;
1556
1557 if (!set_privileges(SE_BACKUP_NAME, TRUE) ||
1558 !set_privileges(SE_RESTORE_NAME, FALSE))
1559 {
1560 win_skip("Failed to set SE_BACKUP_NAME privileges, skipping tests\n");
1561 return;
1562 }
1563
1564 ret = RegSaveKeyA(hkey_main, "saved_key", NULL);
1565 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1566
1567 set_privileges(SE_BACKUP_NAME, FALSE);
1568 }
1569
1570 static void test_reg_load_key(void)
1571 {
1572 DWORD ret;
1573 HKEY hkHandle;
1574
1575 if (!set_privileges(SE_RESTORE_NAME, TRUE) ||
1576 !set_privileges(SE_BACKUP_NAME, FALSE))
1577 {
1578 win_skip("Failed to set SE_RESTORE_NAME privileges, skipping tests\n");
1579 return;
1580 }
1581
1582 ret = RegLoadKeyA(HKEY_LOCAL_MACHINE, "Test", "saved_key");
1583 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1584
1585 set_privileges(SE_RESTORE_NAME, FALSE);
1586
1587 ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, "Test", &hkHandle);
1588 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1589
1590 RegCloseKey(hkHandle);
1591 }
1592
1593 static void test_reg_unload_key(void)
1594 {
1595 DWORD ret;
1596
1597 if (!set_privileges(SE_RESTORE_NAME, TRUE) ||
1598 !set_privileges(SE_BACKUP_NAME, FALSE))
1599 {
1600 win_skip("Failed to set SE_RESTORE_NAME privileges, skipping tests\n");
1601 return;
1602 }
1603
1604 ret = RegUnLoadKeyA(HKEY_LOCAL_MACHINE, "Test");
1605 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1606
1607 set_privileges(SE_RESTORE_NAME, FALSE);
1608
1609 DeleteFileA("saved_key");
1610 DeleteFileA("saved_key.LOG");
1611 }
1612
1613 /* tests that show that RegConnectRegistry and
1614 OpenSCManager accept computer names without the
1615 \\ prefix (what MSDN says). */
1616 static void test_regconnectregistry( void)
1617 {
1618 CHAR compName[MAX_COMPUTERNAME_LENGTH + 1];
1619 CHAR netwName[MAX_COMPUTERNAME_LENGTH + 3]; /* 2 chars for double backslash */
1620 DWORD len = sizeof(compName) ;
1621 BOOL ret;
1622 LONG retl;
1623 HKEY hkey;
1624 SC_HANDLE schnd;
1625
1626 SetLastError(0xdeadbeef);
1627 ret = GetComputerNameA(compName, &len);
1628 ok( ret, "GetComputerName failed err = %d\n", GetLastError());
1629 if( !ret) return;
1630
1631 lstrcpyA(netwName, "\\\\");
1632 lstrcpynA(netwName+2, compName, MAX_COMPUTERNAME_LENGTH + 1);
1633
1634 retl = RegConnectRegistryA( compName, HKEY_LOCAL_MACHINE, &hkey);
1635 ok( !retl ||
1636 retl == ERROR_DLL_INIT_FAILED ||
1637 retl == ERROR_BAD_NETPATH, /* some win2k */
1638 "RegConnectRegistryA failed err = %d\n", retl);
1639 if( !retl) RegCloseKey( hkey);
1640
1641 retl = RegConnectRegistryA( netwName, HKEY_LOCAL_MACHINE, &hkey);
1642 ok( !retl ||
1643 retl == ERROR_DLL_INIT_FAILED ||
1644 retl == ERROR_BAD_NETPATH, /* some win2k */
1645 "RegConnectRegistryA failed err = %d\n", retl);
1646 if( !retl) RegCloseKey( hkey);
1647
1648 SetLastError(0xdeadbeef);
1649 schnd = OpenSCManagerA( compName, NULL, GENERIC_READ);
1650 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1651 {
1652 win_skip("OpenSCManagerA is not implemented\n");
1653 return;
1654 }
1655
1656 ok( schnd != NULL, "OpenSCManagerA failed err = %d\n", GetLastError());
1657 CloseServiceHandle( schnd);
1658
1659 SetLastError(0xdeadbeef);
1660 schnd = OpenSCManagerA( netwName, NULL, GENERIC_READ);
1661 ok( schnd != NULL, "OpenSCManagerA failed err = %d\n", GetLastError());
1662 CloseServiceHandle( schnd);
1663
1664 }
1665
1666 static void test_reg_query_value(void)
1667 {
1668 HKEY subkey;
1669 CHAR val[MAX_PATH];
1670 WCHAR valW[5];
1671 LONG size, ret;
1672
1673 static const WCHAR expected[] = {'d','a','t','a',0};
1674
1675 ret = RegCreateKeyA(hkey_main, "subkey", &subkey);
1676 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1677
1678 ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4);
1679 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1680
1681 /* try an invalid hkey */
1682 SetLastError(0xdeadbeef);
1683 size = MAX_PATH;
1684 ret = RegQueryValueA((HKEY)0xcafebabe, "subkey", val, &size);
1685 ok(ret == ERROR_INVALID_HANDLE ||
1686 ret == ERROR_BADKEY || /* Windows 98 returns BADKEY */
1687 ret == ERROR_ACCESS_DENIED, /* non-admin winxp */
1688 "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
1689 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1690
1691 /* try a NULL hkey */
1692 SetLastError(0xdeadbeef);
1693 size = MAX_PATH;
1694 ret = RegQueryValueA(NULL, "subkey", val, &size);
1695 ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 98 returns BADKEY */
1696 "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
1697 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1698
1699 /* try a NULL value */
1700 size = MAX_PATH;
1701 ret = RegQueryValueA(hkey_main, "subkey", NULL, &size);
1702 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1703 ok(size == 5, "Expected 5, got %d\n", size);
1704
1705 /* try a NULL size */
1706 SetLastError(0xdeadbeef);
1707 val[0] = '\0';
1708 ret = RegQueryValueA(hkey_main, "subkey", val, NULL);
1709 ok(ret == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", ret);
1710 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1711 ok(!val[0], "Expected val to be untouched, got %s\n", val);
1712
1713 /* try a NULL value and size */
1714 ret = RegQueryValueA(hkey_main, "subkey", NULL, NULL);
1715 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1716
1717 /* try a size too small */
1718 SetLastError(0xdeadbeef);
1719 val[0] = '\0';
1720 size = 1;
1721 ret = RegQueryValueA(hkey_main, "subkey", val, &size);
1722 ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret);
1723 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1724 ok(!val[0], "Expected val to be untouched, got %s\n", val);
1725 ok(size == 5, "Expected 5, got %d\n", size);
1726
1727 /* successfully read the value using 'subkey' */
1728 size = MAX_PATH;
1729 ret = RegQueryValueA(hkey_main, "subkey", val, &size);
1730 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1731 ok(!lstrcmpA(val, "data"), "Expected 'data', got '%s'\n", val);
1732 ok(size == 5, "Expected 5, got %d\n", size);
1733
1734 /* successfully read the value using the subkey key */
1735 size = MAX_PATH;
1736 ret = RegQueryValueA(subkey, NULL, val, &size);
1737 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1738 ok(!lstrcmpA(val, "data"), "Expected 'data', got '%s'\n", val);
1739 ok(size == 5, "Expected 5, got %d\n", size);
1740
1741 /* unicode - try size too small */
1742 SetLastError(0xdeadbeef);
1743 valW[0] = '\0';
1744 size = 0;
1745 ret = RegQueryValueW(subkey, NULL, valW, &size);
1746 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1747 {
1748 win_skip("RegQueryValueW is not implemented\n");
1749 goto cleanup;
1750 }
1751 ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret);
1752 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1753 ok(!valW[0], "Expected valW to be untouched\n");
1754 ok(size == sizeof(expected), "Got wrong size: %d\n", size);
1755
1756 /* unicode - try size in WCHARS */
1757 SetLastError(0xdeadbeef);
1758 size = sizeof(valW) / sizeof(WCHAR);
1759 ret = RegQueryValueW(subkey, NULL, valW, &size);
1760 ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret);
1761 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1762 ok(!valW[0], "Expected valW to be untouched\n");
1763 ok(size == sizeof(expected), "Got wrong size: %d\n", size);
1764
1765 /* unicode - successfully read the value */
1766 size = sizeof(valW);
1767 ret = RegQueryValueW(subkey, NULL, valW, &size);
1768 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1769 ok(!lstrcmpW(valW, expected), "Got wrong value\n");
1770 ok(size == sizeof(expected), "Got wrong size: %d\n", size);
1771
1772 /* unicode - set the value without a NULL terminator */
1773 ret = RegSetValueW(subkey, NULL, REG_SZ, expected, sizeof(expected)-sizeof(WCHAR));
1774 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1775
1776 /* unicode - read the unterminated value, value is terminated for us */
1777 memset(valW, 'a', sizeof(valW));
1778 size = sizeof(valW);
1779 ret = RegQueryValueW(subkey, NULL, valW, &size);
1780 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1781 ok(!lstrcmpW(valW, expected), "Got wrong value\n");
1782 ok(size == sizeof(expected), "Got wrong size: %d\n", size);
1783
1784 cleanup:
1785 RegDeleteKeyA(subkey, "");
1786 RegCloseKey(subkey);
1787 }
1788
1789 static void test_reg_query_info(void)
1790 {
1791 HKEY subkey;
1792 HKEY subsubkey;
1793 LONG ret;
1794 char classbuffer[32];
1795 WCHAR classbufferW[32];
1796 char expectbuffer[32];
1797 WCHAR expectbufferW[32];
1798 char subkey_class[] = "subkey class";
1799 WCHAR subkey_classW[] = {'s','u','b','k','e','y',' ','c','l','a','s','s',0};
1800 char subsubkey_class[] = "subsubkey class";
1801 DWORD classlen;
1802 DWORD subkeys, maxsubkeylen, maxclasslen;
1803 DWORD values, maxvaluenamelen, maxvaluelen;
1804 DWORD sdlen;
1805 FILETIME lastwrite;
1806
1807 ret = RegCreateKeyExA(hkey_main, "subkey", 0, subkey_class, 0, KEY_ALL_ACCESS, NULL, &subkey, NULL);
1808 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1809
1810 /* all parameters NULL */
1811 ret = RegQueryInfoKeyA(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1812 ok(ret == ERROR_INVALID_HANDLE, "ret = %d\n", ret);
1813
1814 ret = RegQueryInfoKeyW(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1815 ok(ret == ERROR_INVALID_HANDLE, "ret = %d\n", ret);
1816
1817 /* not requesting any information */
1818 ret = RegQueryInfoKeyA(subkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1819 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1820
1821 ret = RegQueryInfoKeyW(subkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1822 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1823
1824 /* class without length is invalid */
1825 memset(classbuffer, 0x55, sizeof(classbuffer));
1826 ret = RegQueryInfoKeyA(subkey, classbuffer, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1827 ok(ret == ERROR_INVALID_PARAMETER, "ret = %d\n", ret);
1828 ok(classbuffer[0] == 0x55, "classbuffer[0] = 0x%x\n", classbuffer[0]);
1829
1830 memset(classbufferW, 0x55, sizeof(classbufferW));
1831 ret = RegQueryInfoKeyW(subkey, classbufferW, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1832 ok(ret == ERROR_INVALID_PARAMETER, "ret = %d\n", ret);
1833 ok(classbufferW[0] == 0x5555, "classbufferW[0] = 0x%x\n", classbufferW[0]);
1834
1835 /* empty key */
1836 sdlen = 0;
1837 ret = RegQueryInfoKeyA(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite);
1838 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1839 ok(classlen == strlen(subkey_class), "classlen = %u\n", classlen);
1840 ok(subkeys == 0, "subkeys = %u\n", subkeys);
1841 ok(maxsubkeylen == 0, "maxsubkeylen = %u\n", maxsubkeylen);
1842 ok(maxclasslen == 0, "maxclasslen = %u\n", maxclasslen);
1843 ok(values == 0, "values = %u\n", values);
1844 ok(maxvaluenamelen == 0, "maxvaluenamelen = %u\n", maxvaluenamelen);
1845 ok(maxvaluelen == 0, "maxvaluelen = %u\n", maxvaluelen);
1846 todo_wine ok(sdlen != 0, "sdlen = %u\n", sdlen);
1847 ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %u\n", lastwrite.dwLowDateTime);
1848 ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %u\n", lastwrite.dwHighDateTime);
1849
1850 sdlen = 0;
1851 ret = RegQueryInfoKeyW(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite);
1852 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1853 ok(classlen == strlen(subkey_class), "classlen = %u\n", classlen);
1854 ok(subkeys == 0, "subkeys = %u\n", subkeys);
1855 ok(maxsubkeylen == 0, "maxsubkeylen = %u\n", maxsubkeylen);
1856 ok(maxclasslen == 0, "maxclasslen = %u\n", maxclasslen);
1857 ok(values == 0, "values = %u\n", values);
1858 ok(maxvaluenamelen == 0, "maxvaluenamelen = %u\n", maxvaluenamelen);
1859 ok(maxvaluelen == 0, "maxvaluelen = %u\n", maxvaluelen);
1860 todo_wine ok(sdlen != 0, "sdlen = %u\n", sdlen);
1861 ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %u\n", lastwrite.dwLowDateTime);
1862 ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %u\n", lastwrite.dwHighDateTime);
1863
1864 ret = RegCreateKeyExA(subkey, "subsubkey", 0, subsubkey_class, 0, KEY_ALL_ACCESS, NULL, &subsubkey, NULL);
1865 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1866
1867 ret = RegSetValueExA(subkey, NULL, 0, REG_SZ, (const BYTE*)"data", 5);
1868 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1869
1870 /* with subkey & default value */
1871 sdlen = 0;
1872 ret = RegQueryInfoKeyA(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite);
1873 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1874 ok(classlen == strlen(subkey_class), "classlen = %u\n", classlen);
1875 ok(subkeys == 1, "subkeys = %u\n", subkeys);
1876 ok(maxsubkeylen == strlen("subsubkey"), "maxsubkeylen = %u\n", maxsubkeylen);
1877 ok(maxclasslen == strlen(subsubkey_class), "maxclasslen = %u\n", maxclasslen);
1878 ok(values == 1, "values = %u\n", values);
1879 ok(maxvaluenamelen == 0, "maxvaluenamelen = %u\n", maxvaluenamelen);
1880 ok(maxvaluelen == sizeof("data") * sizeof(WCHAR), "maxvaluelen = %u\n", maxvaluelen);
1881 todo_wine ok(sdlen != 0, "sdlen = %u\n", sdlen);
1882 ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %u\n", lastwrite.dwLowDateTime);
1883 ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %u\n", lastwrite.dwHighDateTime);
1884
1885 sdlen = 0;
1886 ret = RegQueryInfoKeyW(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite);
1887 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1888 ok(classlen == strlen(subkey_class), "classlen = %u\n", classlen);
1889 ok(subkeys == 1, "subkeys = %u\n", subkeys);
1890 ok(maxsubkeylen == strlen("subsubkey"), "maxsubkeylen = %u\n", maxsubkeylen);
1891 ok(maxclasslen == strlen(subsubkey_class), "maxclasslen = %u\n", maxclasslen);
1892 ok(values == 1, "values = %u\n", values);
1893 ok(maxvaluenamelen == 0, "maxvaluenamelen = %u\n", maxvaluenamelen);
1894 ok(maxvaluelen == sizeof("data") * sizeof(WCHAR), "maxvaluelen = %u\n", maxvaluelen);
1895 todo_wine ok(sdlen != 0, "sdlen = %u\n", sdlen);
1896 ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %u\n", lastwrite.dwLowDateTime);
1897 ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %u\n", lastwrite.dwHighDateTime);
1898
1899 ret = RegSetValueExA(subkey, "value one", 0, REG_SZ, (const BYTE*)"first value data", 17);
1900 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1901
1902 ret = RegSetValueExA(subkey, "value 2", 0, REG_SZ, (const BYTE*)"second value data", 18);
1903 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1904
1905 /* with named value */
1906 ret = RegQueryInfoKeyA(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite);
1907 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1908 ok(values == 3, "values = %u\n", values);
1909 ok(maxvaluenamelen == strlen("value one"), "maxvaluenamelen = %u\n", maxvaluenamelen);
1910 ok(maxvaluelen == sizeof("second value data") * sizeof(WCHAR), "maxvaluelen = %u\n", maxvaluelen);
1911
1912 ret = RegQueryInfoKeyW(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite);
1913 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1914 ok(values == 3, "values = %u\n", values);
1915 ok(maxvaluenamelen == strlen("value one"), "maxvaluenamelen = %u\n", maxvaluenamelen);
1916 ok(maxvaluelen == sizeof("second value data") * sizeof(WCHAR), "maxvaluelen = %u\n", maxvaluelen);
1917
1918 /* class name with zero size buffer */
1919 memset(classbuffer, 0x55, sizeof(classbuffer));
1920 classlen = 0;
1921 ret = RegQueryInfoKeyA(subkey, classbuffer, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1922 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1923 ok(classlen == strlen(subkey_class) /* win2k */ ||
1924 classlen == 0, "classlen = %u\n", classlen);
1925 memset(expectbuffer, 0x55, sizeof(expectbuffer));
1926 ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)), "classbuffer was modified\n");
1927
1928 memset(classbufferW, 0x55, sizeof(classbufferW));
1929 classlen = 0;
1930 ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1931 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1932 ok(classlen == strlen(subkey_class) /* win2k */ ||
1933 classlen == 0, "classlen = %u\n", classlen);
1934 memset(expectbufferW, 0x55, sizeof(expectbufferW));
1935 ok(!memcmp(classbufferW, expectbufferW, sizeof(classbufferW)), "classbufferW was modified\n");
1936
1937 /* class name with one char buffer */
1938 memset(classbuffer, 0x55, sizeof(classbuffer));
1939 classlen = 1;
1940 ret = RegQueryInfoKeyA(subkey, classbuffer, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1941 ok(ret == ERROR_MORE_DATA, "ret = %d\n", ret);
1942 ok(classlen == 0, "classlen = %u\n", classlen);
1943 memset(expectbuffer, 0x55, sizeof(expectbuffer));
1944 expectbuffer[0] = 0;
1945 ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)), "classbuffer was modified\n");
1946
1947 memset(classbufferW, 0x55, sizeof(classbufferW));
1948 classlen = 1;
1949 ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1950 ok(ret == ERROR_INSUFFICIENT_BUFFER, "ret = %d\n", ret);
1951 ok(classlen == 0 /* win8 */ ||
1952 classlen == strlen(subkey_class), "classlen = %u\n", classlen);
1953 memset(expectbufferW, 0x55, sizeof(expectbufferW));
1954 ok(!memcmp(classbufferW, expectbufferW, sizeof(classbufferW)), "classbufferW was modified\n");
1955
1956 /* class name with buffer one char too small */
1957 memset(classbuffer, 0x55, sizeof(classbuffer));
1958 classlen = sizeof(subkey_class) - 1;
1959 ret = RegQueryInfoKeyA(subkey, classbuffer, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1960 ok(ret == ERROR_MORE_DATA, "ret = %d\n", ret);
1961 ok(classlen == sizeof(subkey_class) - 2, "classlen = %u\n", classlen);
1962 memset(expectbuffer, 0x55, sizeof(expectbuffer));
1963 strcpy(expectbuffer, subkey_class);
1964 expectbuffer[sizeof(subkey_class) - 2] = 0;
1965 expectbuffer[sizeof(subkey_class) - 1] = 0x55;
1966 ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)),
1967 "classbuffer = %.*s, expected %s\n",
1968 (int)sizeof(classbuffer), classbuffer, expectbuffer);
1969
1970 memset(classbufferW, 0x55, sizeof(classbufferW));
1971 classlen = sizeof(subkey_class) - 1;
1972 ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1973 ok(ret == ERROR_INSUFFICIENT_BUFFER, "ret = %d\n", ret);
1974 ok(classlen == sizeof(subkey_class) - 2 /* win8 */ ||
1975 classlen == strlen(subkey_class), "classlen = %u\n", classlen);
1976 memset(expectbufferW, 0x55, sizeof(expectbufferW));
1977 ok(!memcmp(classbufferW, expectbufferW, sizeof(classbufferW)), "classbufferW was modified\n");
1978
1979 /* class name with large enough buffer */
1980 memset(classbuffer, 0x55, sizeof(classbuffer));
1981 classlen = sizeof(subkey_class);
1982 ret = RegQueryInfoKeyA(subkey, classbuffer, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1983 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1984 ok(classlen == sizeof(subkey_class) - 1, "classlen = %u\n", classlen);
1985 memset(expectbuffer, 0x55, sizeof(expectbuffer));
1986 strcpy(expectbuffer, subkey_class);
1987 ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)),
1988 "classbuffer = \"%.*s\", expected %s\n",
1989 (int)sizeof(classbuffer), classbuffer, expectbuffer);
1990
1991 memset(classbufferW, 0x55, sizeof(classbufferW));
1992 classlen = sizeof(subkey_class);
1993 ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1994 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1995 ok(classlen == sizeof(subkey_class) - 1, "classlen = %u\n", classlen);
1996 memset(expectbufferW, 0x55, sizeof(expectbufferW));
1997 lstrcpyW(expectbufferW, subkey_classW);
1998 ok(!memcmp(classbufferW, expectbufferW, sizeof(classbufferW)),
1999 "classbufferW = %s, expected %s\n",
2000 wine_dbgstr_wn(classbufferW, sizeof(classbufferW) / sizeof(WCHAR)), wine_dbgstr_w(expectbufferW));
2001
2002 RegDeleteKeyA(subsubkey, "");
2003 RegCloseKey(subsubkey);
2004 RegDeleteKeyA(subkey, "");
2005 RegCloseKey(subkey);
2006 }
2007
2008 static void test_string_termination(void)
2009 {
2010 HKEY subkey;
2011 LSTATUS ret;
2012 static const char string[] = "FullString";
2013 char name[11];
2014 BYTE buffer[11];
2015 DWORD insize, outsize, nsize;
2016
2017 ret = RegCreateKeyA(hkey_main, "string_termination", &subkey);
2018 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2019
2020 /* Off-by-one RegSetValueExA -> adds a trailing '\0'! */
2021 insize=sizeof(string)-1;
2022 ret = RegSetValueExA(subkey, "stringtest", 0, REG_SZ, (BYTE*)string, insize);
2023 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", ret);
2024 outsize=insize;
2025 ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize);
2026 ok(ret == ERROR_MORE_DATA, "RegQueryValueExA returned: %d\n", ret);
2027
2028 /* Off-by-two RegSetValueExA -> no trailing '\0' */
2029 insize=sizeof(string)-2;
2030 ret = RegSetValueExA(subkey, "stringtest", 0, REG_SZ, (BYTE*)string, insize);
2031 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", ret);
2032 outsize=0;
2033 ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, NULL, &outsize);
2034 ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", ret);
2035 ok(outsize == insize, "wrong size %u != %u\n", outsize, insize);
2036
2037 /* RegQueryValueExA may return a string with no trailing '\0' */
2038 outsize=insize;
2039 memset(buffer, 0xbd, sizeof(buffer));
2040 ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize);
2041 ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", ret);
2042 ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize);
2043 ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n",
2044 wine_debugstr_an((char*)buffer, outsize), outsize, string);
2045 ok(buffer[insize] == 0xbd, "buffer overflow at %u %02x\n", insize, buffer[insize]);
2046
2047 /* RegQueryValueExA adds a trailing '\0' if there is room */
2048 outsize=insize+1;
2049 memset(buffer, 0xbd, sizeof(buffer));
2050 ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize);
2051 ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", ret);
2052 ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize);
2053 ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n",
2054 wine_debugstr_an((char*)buffer, outsize), outsize, string);
2055 ok(buffer[insize] == 0, "buffer overflow at %u %02x\n", insize, buffer[insize]);
2056
2057 /* RegEnumValueA may return a string with no trailing '\0' */
2058 outsize=insize;
2059 memset(buffer, 0xbd, sizeof(buffer));
2060 nsize=sizeof(name);
2061 ret = RegEnumValueA(subkey, 0, name, &nsize, NULL, NULL, buffer, &outsize);
2062 ok(ret == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", ret);
2063 ok(strcmp(name, "stringtest") == 0, "wrong name: %s\n", name);
2064 ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize);
2065 ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n",
2066 wine_debugstr_an((char*)buffer, outsize), outsize, string);
2067 ok(buffer[insize] == 0xbd, "buffer overflow at %u %02x\n", insize, buffer[insize]);
2068
2069 /* RegEnumValueA adds a trailing '\0' if there is room */
2070 outsize=insize+1;
2071 memset(buffer, 0xbd, sizeof(buffer));
2072 nsize=sizeof(name);
2073 ret = RegEnumValueA(subkey, 0, name, &nsize, NULL, NULL, buffer, &outsize);
2074 ok(ret == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", ret);
2075 ok(strcmp(name, "stringtest") == 0, "wrong name: %s\n", name);
2076 ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize);
2077 ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n",
2078 wine_debugstr_an((char*)buffer, outsize), outsize, string);
2079 ok(buffer[insize] == 0, "buffer overflow at %u %02x\n", insize, buffer[insize]);
2080
2081 RegDeleteKeyA(subkey, "");
2082 RegCloseKey(subkey);
2083 }
2084
2085 static void test_reg_delete_tree(void)
2086 {
2087 CHAR buffer[MAX_PATH];
2088 HKEY subkey, subkey2;
2089 LONG size, ret;
2090
2091 if(!pRegDeleteTreeA) {
2092 win_skip("Skipping RegDeleteTreeA tests, function not present\n");
2093 return;
2094 }
2095
2096 ret = RegCreateKeyA(hkey_main, "subkey", &subkey);
2097 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2098 ret = RegCreateKeyA(subkey, "subkey2", &subkey2);
2099 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2100 ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4);
2101 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2102 ret = RegSetValueA(subkey2, NULL, REG_SZ, "data2", 5);
2103 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2104 ret = RegCloseKey(subkey2);
2105 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2106
2107 ret = pRegDeleteTreeA(subkey, "subkey2");
2108 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2109 ok(RegOpenKeyA(subkey, "subkey2", &subkey2),
2110 "subkey2 was not deleted\n");
2111 size = MAX_PATH;
2112 ok(!RegQueryValueA(subkey, NULL, buffer, &size),
2113 "Default value of subkey not longer present\n");
2114
2115 ret = RegCreateKeyA(subkey, "subkey2", &subkey2);
2116 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2117 ret = RegCloseKey(subkey2);
2118 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2119 ret = pRegDeleteTreeA(hkey_main, "subkey\\subkey2");
2120 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2121 ok(RegOpenKeyA(subkey, "subkey2", &subkey2),
2122 "subkey2 was not deleted\n");
2123 ok(!RegQueryValueA(subkey, NULL, buffer, &size),
2124 "Default value of subkey not longer present\n");
2125
2126 ret = RegCreateKeyA(subkey, "subkey2", &subkey2);
2127 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2128 ret = RegCloseKey(subkey2);
2129 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2130 ret = RegCreateKeyA(subkey, "subkey3", &subkey2);
2131 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2132 ret = RegCloseKey(subkey2);
2133 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2134 ret = RegSetValueA(subkey, "value", REG_SZ, "data2", 5);
2135 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2136 ret = pRegDeleteTreeA(subkey, NULL);
2137 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2138 ok(!RegOpenKeyA(hkey_main, "subkey", &subkey),
2139 "subkey was deleted\n");
2140 ok(RegOpenKeyA(subkey, "subkey2", &subkey2),
2141 "subkey2 was not deleted\n");
2142 ok(RegOpenKeyA(subkey, "subkey3", &subkey2),
2143 "subkey3 was not deleted\n");
2144 size = MAX_PATH;
2145 ret = RegQueryValueA(subkey, NULL, buffer, &size);
2146 ok(ret == ERROR_SUCCESS,
2147 "Default value of subkey is not present\n");
2148 ok(!buffer[0], "Expected length 0 got length %u(%s)\n", lstrlenA(buffer), buffer);
2149 size = MAX_PATH;
2150 ok(RegQueryValueA(subkey, "value", buffer, &size),
2151 "Value is still present\n");
2152
2153 ret = pRegDeleteTreeA(hkey_main, "not-here");
2154 ok(ret == ERROR_FILE_NOT_FOUND,
2155 "Expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
2156 }
2157
2158 static void test_rw_order(void)
2159 {
2160 HKEY hKey;
2161 DWORD dw = 0;
2162 static const char keyname[] = "test_rw_order";
2163 char value_buf[2];
2164 DWORD values, value_len, value_name_max_len;
2165 LSTATUS ret;
2166
2167 RegDeleteKeyA(HKEY_CURRENT_USER, keyname);
2168 ret = RegCreateKeyA(HKEY_CURRENT_USER, keyname, &hKey);
2169 if(ret != ERROR_SUCCESS) {
2170 skip("Couldn't create key. Skipping.\n");
2171 return;
2172 }
2173
2174 ok(!RegSetValueExA(hKey, "A", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)),
2175 "RegSetValueExA for value \"A\" failed\n");
2176 ok(!RegSetValueExA(hKey, "C", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)),
2177 "RegSetValueExA for value \"C\" failed\n");
2178 ok(!RegSetValueExA(hKey, "D", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)),
2179 "RegSetValueExA for value \"D\" failed\n");
2180 ok(!RegSetValueExA(hKey, "B", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)),
2181 "RegSetValueExA for value \"B\" failed\n");
2182
2183 ok(!RegQueryInfoKeyA(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &values,
2184 &value_name_max_len, NULL, NULL, NULL), "RegQueryInfoKeyA failed\n");
2185 ok(values == 4, "Expected 4 values, got %u\n", values);
2186
2187 /* Value enumeration preserves RegSetValueEx call order */
2188 value_len = 2;
2189 ok(!RegEnumValueA(hKey, 0, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n");
2190 ok(strcmp(value_buf, "A") == 0, "Expected name \"A\", got %s\n", value_buf);
2191 value_len = 2;
2192 ok(!RegEnumValueA(hKey, 1, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n");
2193 todo_wine ok(strcmp(value_buf, "C") == 0, "Expected name \"C\", got %s\n", value_buf);
2194 value_len = 2;
2195 ok(!RegEnumValueA(hKey, 2, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n");
2196 todo_wine ok(strcmp(value_buf, "D") == 0, "Expected name \"D\", got %s\n", value_buf);
2197 value_len = 2;
2198 ok(!RegEnumValueA(hKey, 3, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n");
2199 todo_wine ok(strcmp(value_buf, "B") == 0, "Expected name \"B\", got %s\n", value_buf);
2200
2201 ok(!RegDeleteKeyA(HKEY_CURRENT_USER, keyname), "Failed to delete key\n");
2202 }
2203
2204 static void test_symlinks(void)
2205 {
2206 static const WCHAR targetW[] = {'\\','S','o','f','t','w','a','r','e','\\','W','i','n','e',
2207 '\\','T','e','s','t','\\','t','a','r','g','e','t',0};
2208 BYTE buffer[1024];
2209 UNICODE_STRING target_str;
2210 WCHAR *target;
2211 HKEY key, link;
2212 NTSTATUS status;
2213 DWORD target_len, type, len, dw, err;
2214
2215 if (!pRtlFormatCurrentUserKeyPath || !pNtDeleteKey)
2216 {
2217 win_skip( "Can't perform symlink tests\n" );
2218 return;
2219 }
2220
2221 pRtlFormatCurrentUserKeyPath( &target_str );
2222
2223 target_len = target_str.Length + sizeof(targetW);
2224 target = HeapAlloc( GetProcessHeap(), 0, target_len );
2225 memcpy( target, target_str.Buffer, target_str.Length );
2226 memcpy( target + target_str.Length/sizeof(WCHAR), targetW, sizeof(targetW) );
2227
2228 err = RegCreateKeyExA( hkey_main, "link", 0, NULL, REG_OPTION_CREATE_LINK,
2229 KEY_ALL_ACCESS, NULL, &link, NULL );
2230 ok( err == ERROR_SUCCESS, "RegCreateKeyEx failed: %u\n", err );
2231
2232 /* REG_SZ is not allowed */
2233 err = RegSetValueExA( link, "SymbolicLinkValue", 0, REG_SZ, (BYTE *)"foobar", sizeof("foobar") );
2234 ok( err == ERROR_ACCESS_DENIED, "RegSetValueEx wrong error %u\n", err );
2235 err = RegSetValueExA( link, "SymbolicLinkValue", 0, REG_LINK,
2236 (BYTE *)target, target_len - sizeof(WCHAR) );
2237 ok( err == ERROR_SUCCESS, "RegSetValueEx failed error %u\n", err );
2238 /* other values are not allowed */
2239 err = RegSetValueExA( link, "link", 0, REG_LINK, (BYTE *)target, target_len - sizeof(WCHAR) );
2240 ok( err == ERROR_ACCESS_DENIED, "RegSetValueEx wrong error %u\n", err );
2241
2242 /* try opening the target through the link */
2243
2244 err = RegOpenKeyA( hkey_main, "link", &key );
2245 ok( err == ERROR_FILE_NOT_FOUND, "RegOpenKey wrong error %u\n", err );
2246
2247 err = RegCreateKeyExA( hkey_main, "target", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL );
2248 ok( err == ERROR_SUCCESS, "RegCreateKeyEx failed error %u\n", err );
2249
2250 dw = 0xbeef;
2251 err = RegSetValueExA( key, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) );
2252 ok( err == ERROR_SUCCESS, "RegSetValueEx failed error %u\n", err );
2253 RegCloseKey( key );
2254
2255 err = RegOpenKeyA( hkey_main, "link", &key );
2256 ok( err == ERROR_SUCCESS, "RegOpenKey failed error %u\n", err );
2257
2258 len = sizeof(buffer);
2259 err = RegQueryValueExA( key, "value", NULL, &type, buffer, &len );
2260 ok( err == ERROR_SUCCESS, "RegOpenKey failed error %u\n", err );
2261 ok( len == sizeof(DWORD), "wrong len %u\n", len );
2262
2263 len = sizeof(buffer);
2264 err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len );
2265 ok( err == ERROR_FILE_NOT_FOUND, "RegQueryValueEx wrong error %u\n", err );
2266
2267 /* REG_LINK can be created in non-link keys */
2268 err = RegSetValueExA( key, "SymbolicLinkValue", 0, REG_LINK,
2269 (BYTE *)target, target_len - sizeof(WCHAR) );
2270 ok( err == ERROR_SUCCESS, "RegSetValueEx failed error %u\n", err );
2271 len = sizeof(buffer);
2272 err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len );
2273 ok( err == ERROR_SUCCESS, "RegQueryValueEx failed error %u\n", err );
2274 ok( len == target_len - sizeof(WCHAR), "wrong len %u\n", len );
2275 err = RegDeleteValueA( key, "SymbolicLinkValue" );
2276 ok( err == ERROR_SUCCESS, "RegDeleteValue failed error %u\n", err );
2277
2278 RegCloseKey( key );
2279
2280 err = RegCreateKeyExA( hkey_main, "link", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL );
2281 ok( err == ERROR_SUCCESS, "RegCreateKeyEx failed error %u\n", err );
2282
2283 len = sizeof(buffer);
2284 err = RegQueryValueExA( key, "value", NULL, &type, buffer, &len );
2285 ok( err == ERROR_SUCCESS, "RegQueryValueEx failed error %u\n", err );
2286 ok( len == sizeof(DWORD), "wrong len %u\n", len );
2287
2288 err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len );
2289 ok( err == ERROR_FILE_NOT_FOUND, "RegQueryValueEx wrong error %u\n", err );
2290 RegCloseKey( key );
2291
2292 /* now open the symlink itself */
2293
2294 err = RegOpenKeyExA( hkey_main, "link", REG_OPTION_OPEN_LINK, KEY_ALL_ACCESS, &key );
2295 ok( err == ERROR_SUCCESS, "RegOpenKeyEx failed error %u\n", err );
2296 len = sizeof(buffer);
2297 err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len );
2298 ok( err == ERROR_SUCCESS, "RegQueryValueEx failed error %u\n", err );
2299 ok( len == target_len - sizeof(WCHAR), "wrong len %u\n", len );
2300 RegCloseKey( key );
2301
2302 err = RegCreateKeyExA( hkey_main, "link", 0, NULL, REG_OPTION_OPEN_LINK,
2303 KEY_ALL_ACCESS, NULL, &key, NULL );
2304 ok( err == ERROR_SUCCESS, "RegCreateKeyEx failed error %u\n", err );
2305 len = sizeof(buffer);
2306 err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len );
2307 ok( err == ERROR_SUCCESS, "RegQueryValueEx failed error %u\n", err );
2308 ok( len == target_len - sizeof(WCHAR), "wrong len %u\n", len );
2309 RegCloseKey( key );
2310
2311 err = RegCreateKeyExA( hkey_main, "link", 0, NULL, REG_OPTION_CREATE_LINK,
2312 KEY_ALL_ACCESS, NULL, &key, NULL );
2313 ok( err == ERROR_ALREADY_EXISTS, "RegCreateKeyEx wrong error %u\n", err );
2314
2315 err = RegCreateKeyExA( hkey_main, "link", 0, NULL, REG_OPTION_CREATE_LINK | REG_OPTION_OPEN_LINK,
2316 KEY_ALL_ACCESS, NULL, &key, NULL );
2317 ok( err == ERROR_ALREADY_EXISTS, "RegCreateKeyEx wrong error %u\n", err );
2318
2319 err = RegDeleteKeyA( hkey_main, "target" );
2320 ok( err == ERROR_SUCCESS, "RegDeleteKey failed error %u\n", err );
2321
2322 err = RegDeleteKeyA( hkey_main, "link" );
2323 ok( err == ERROR_FILE_NOT_FOUND, "RegDeleteKey wrong error %u\n", err );
2324
2325 status = pNtDeleteKey( link );
2326 ok( !status, "NtDeleteKey failed: 0x%08x\n", status );
2327 RegCloseKey( link );
2328
2329 HeapFree( GetProcessHeap(), 0, target );
2330 pRtlFreeUnicodeString( &target_str );
2331 }
2332
2333 static DWORD get_key_value( HKEY root, const char *name, DWORD flags )
2334 {
2335 HKEY key;
2336 DWORD err, type, dw, len = sizeof(dw);
2337
2338 err = RegCreateKeyExA( root, name, 0, NULL, 0, flags | KEY_ALL_ACCESS, NULL, &key, NULL );
2339 if (err == ERROR_FILE_NOT_FOUND) return 0;
2340 ok( err == ERROR_SUCCESS, "%08x: RegCreateKeyEx failed: %u\n", flags, err );
2341
2342 err = RegQueryValueExA( key, "value", NULL, &type, (BYTE *)&dw, &len );
2343 if (err == ERROR_FILE_NOT_FOUND)
2344 dw = 0;
2345 else
2346 ok( err == ERROR_SUCCESS, "%08x: RegQueryValueEx failed: %u\n", flags, err );
2347 RegCloseKey( key );
2348 return dw;
2349 }
2350
2351 static void _check_key_value( int line, HANDLE root, const char *name, DWORD flags, DWORD expect )
2352 {
2353 DWORD dw = get_key_value( root, name, flags );
2354 ok_(__FILE__,line)( dw == expect, "%08x: wrong value %u/%u\n", flags, dw, expect );
2355 }
2356 #define check_key_value(root,name,flags,expect) _check_key_value( __LINE__, root, name, flags, expect )
2357
2358 static void test_redirection(void)
2359 {
2360 DWORD err, type, dw, len;
2361 HKEY key, root32, root64, key32, key64, native, op_key;
2362 BOOL is_vista = FALSE;
2363 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
2364
2365 if (ptr_size != 64)
2366 {
2367 BOOL is_wow64;
2368 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 ) || !is_wow64)
2369 {
2370 skip( "Not on Wow64, no redirection\n" );
2371 return;
2372 }
2373 }
2374
2375 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
2376 KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &root64, NULL );
2377 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2378
2379 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
2380 KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &root32, NULL );
2381 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2382
2383 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", 0, NULL, 0,
2384 KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &key64, NULL );
2385 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2386
2387 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", 0, NULL, 0,
2388 KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key32, NULL );
2389 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2390
2391 dw = 64;
2392 err = RegSetValueExA( key64, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) );
2393 ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %u\n", err );
2394
2395 dw = 32;
2396 err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) );
2397 ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %u\n", err );
2398
2399 dw = 0;
2400 len = sizeof(dw);
2401 err = RegQueryValueExA( key32, "value", NULL, &type, (BYTE *)&dw, &len );
2402 ok( err == ERROR_SUCCESS, "RegQueryValueExA failed: %u\n", err );
2403 ok( dw == 32, "wrong value %u\n", dw );
2404
2405 dw = 0;
2406 len = sizeof(dw);
2407 err = RegQueryValueExA( key64, "value", NULL, &type, (BYTE *)&dw, &len );
2408 ok( err == ERROR_SUCCESS, "RegQueryValueExA failed: %u\n", err );
2409 ok( dw == 64, "wrong value %u\n", dw );
2410
2411 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0,
2412 KEY_ALL_ACCESS, NULL, &key, NULL );
2413 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2414
2415 if (ptr_size == 32)
2416 {
2417 /* the Vista mechanism allows opening Wow6432Node from a 32-bit key too */
2418 /* the new (and simpler) Win7 mechanism doesn't */
2419 if (get_key_value( key, "Wow6432Node\\Wine\\Winetest", 0 ) == 32)
2420 {
2421 trace( "using Vista-style Wow6432Node handling\n" );
2422 is_vista = TRUE;
2423 }
2424 check_key_value( key, "Wine\\Winetest", 0, 32 );
2425 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
2426 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2427 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, is_vista ? 32 : 0 );
2428 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 0 );
2429 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, is_vista ? 32 : 0 );
2430 }
2431 else
2432 {
2433 if (get_key_value( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY ) == 64)
2434 {
2435 trace( "using Vista-style Wow6432Node handling\n" );
2436 is_vista = TRUE;
2437 }
2438 check_key_value( key, "Wine\\Winetest", 0, 64 );
2439 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, 32 );
2440 }
2441 RegCloseKey( key );