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 #include "precomp.h"
23 
24 #include <assert.h>
25 #include <winperf.h>
26 
27 #define IS_HKCR(hk) ((UINT_PTR)hk > 0 && ((UINT_PTR)hk & 3) == 2)
28 
29 static HKEY hkey_main;
30 static DWORD GLE;
31 
32 static const char * sTestpath1 = "%LONGSYSTEMVAR%\\subdir1";
33 static const char * sTestpath2 = "%FOO%\\subdir1";
34 static const DWORD ptr_size = 8 * sizeof(void*);
35 
36 static DWORD (WINAPI *pRegGetValueA)(HKEY,LPCSTR,LPCSTR,DWORD,LPDWORD,PVOID,LPDWORD);
37 static LONG (WINAPI *pRegCopyTreeA)(HKEY,const char *,HKEY);
38 static LONG (WINAPI *pRegDeleteTreeA)(HKEY,const char *);
39 static DWORD (WINAPI *pRegDeleteKeyExA)(HKEY,LPCSTR,REGSAM,DWORD);
40 static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
41 static NTSTATUS (WINAPI * pNtDeleteKey)(HANDLE);
42 static NTSTATUS (WINAPI * pRtlFormatCurrentUserKeyPath)(UNICODE_STRING*);
43 static NTSTATUS (WINAPI * pRtlFreeUnicodeString)(PUNICODE_STRING);
44 static LONG (WINAPI *pRegDeleteKeyValueA)(HKEY,LPCSTR,LPCSTR);
45 static LONG (WINAPI *pRegSetKeyValueW)(HKEY,LPCWSTR,LPCWSTR,DWORD,const void*,DWORD);
46 
47 static BOOL limited_user;
48 
49 
50 /* Debugging functions from wine/libs/wine/debug.c */
51 
52 /* allocate some tmp string space */
53 /* FIXME: this is not 100% thread-safe */
54 static char *get_temp_buffer( int size )
55 {
56     static char *list[32];
57     static UINT pos;
58     char *ret;
59     UINT idx;
60 
61     idx = ++pos % (sizeof(list)/sizeof(list[0]));
62     if (list[idx])
63         ret = HeapReAlloc( GetProcessHeap(), 0, list[idx], size );
64     else
65         ret = HeapAlloc( GetProcessHeap(), 0, size );
66     if (ret) list[idx] = ret;
67     return ret;
68 }
69 
70 static const char *wine_debugstr_an( const char *str, int n )
71 {
72     static const char hex[16] = "0123456789abcdef";
73     char *dst, *res;
74     size_t size;
75 
76     if (!((ULONG_PTR)str >> 16))
77     {
78         if (!str) return "(null)";
79         res = get_temp_buffer( 6 );
80         sprintf( res, "#%04x", LOWORD(str) );
81         return res;
82     }
83     if (n == -1) n = strlen(str);
84     if (n < 0) n = 0;
85     size = 10 + min( 300, n * 4 );
86     dst = res = get_temp_buffer( size );
87     *dst++ = '"';
88     while (n-- > 0 && dst <= res + size - 9)
89     {
90         unsigned char c = *str++;
91         switch (c)
92         {
93         case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
94         case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
95         case '\t': *dst++ = '\\'; *dst++ = 't'; break;
96         case '"':  *dst++ = '\\'; *dst++ = '"'; break;
97         case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
98         default:
99             if (c >= ' ' && c <= 126)
100                 *dst++ = c;
101             else
102             {
103                 *dst++ = '\\';
104                 *dst++ = 'x';
105                 *dst++ = hex[(c >> 4) & 0x0f];
106                 *dst++ = hex[c & 0x0f];
107             }
108         }
109     }
110     *dst++ = '"';
111     if (n > 0)
112     {
113         *dst++ = '.';
114         *dst++ = '.';
115         *dst++ = '.';
116     }
117     *dst++ = 0;
118     return res;
119 }
120 
121 #define ADVAPI32_GET_PROC(func) \
122     p ## func = (void*)GetProcAddress(hadvapi32, #func)
123 
124 static void InitFunctionPtrs(void)
125 {
126     HMODULE hntdll = GetModuleHandleA("ntdll.dll");
127     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
128     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
129 
130     /* This function was introduced with Windows 2003 SP1 */
131     ADVAPI32_GET_PROC(RegGetValueA);
132     ADVAPI32_GET_PROC(RegCopyTreeA);
133     ADVAPI32_GET_PROC(RegDeleteTreeA);
134     ADVAPI32_GET_PROC(RegDeleteKeyExA);
135     ADVAPI32_GET_PROC(RegDeleteKeyValueA);
136     ADVAPI32_GET_PROC(RegSetKeyValueW);
137 
138     pIsWow64Process = (void *)GetProcAddress( hkernel32, "IsWow64Process" );
139     pRtlFormatCurrentUserKeyPath = (void *)GetProcAddress( hntdll, "RtlFormatCurrentUserKeyPath" );
140     pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
141     pNtDeleteKey = (void *)GetProcAddress( hntdll, "NtDeleteKey" );
142 }
143 
144 /* delete key and all its subkeys */
145 static DWORD delete_key( HKEY hkey )
146 {
147     char name[MAX_PATH];
148     DWORD ret;
149 
150     if ((ret = RegOpenKeyExA( hkey, "", 0, KEY_ENUMERATE_SUB_KEYS, &hkey ))) return ret;
151     while (!(ret = RegEnumKeyA(hkey, 0, name, sizeof(name))))
152     {
153         HKEY tmp;
154         if (!(ret = RegOpenKeyExA( hkey, name, 0, KEY_ENUMERATE_SUB_KEYS, &tmp )))
155         {
156             ret = delete_key( tmp );
157             RegCloseKey( tmp );
158         }
159         if (ret) break;
160     }
161     if (ret != ERROR_NO_MORE_ITEMS) return ret;
162     RegDeleteKeyA( hkey, "" );
163     RegCloseKey(hkey);
164     return 0;
165 }
166 
167 static void setup_main_key(void)
168 {
169     if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main )) delete_key( hkey_main );
170 
171     assert (!RegCreateKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main ));
172 }
173 
174 static void check_user_privs(void)
175 {
176     DWORD ret;
177     HKEY hkey = (HKEY)0xdeadbeef;
178 
179     ret = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WRITE, &hkey);
180     ok(ret == ERROR_SUCCESS || ret == ERROR_ACCESS_DENIED, "expected success or access denied, got %i\n", ret);
181     if (ret == ERROR_SUCCESS)
182     {
183         ok(hkey != NULL, "RegOpenKeyExA succeeded but returned NULL hkey\n");
184         RegCloseKey(hkey);
185     }
186     else
187     {
188         ok(hkey == NULL, "RegOpenKeyExA failed but returned hkey %p\n", hkey);
189         limited_user = TRUE;
190         trace("running as limited user\n");
191     }
192 }
193 
194 #define lok ok_(__FILE__, line)
195 #define test_hkey_main_Value_A(name, string, full_byte_len) _test_hkey_main_Value_A(__LINE__, name, string, full_byte_len)
196 static void _test_hkey_main_Value_A(int line, LPCSTR name, LPCSTR string,
197                                    DWORD full_byte_len)
198 {
199     DWORD ret, type, cbData;
200     DWORD str_byte_len;
201     BYTE* value;
202 
203     type=0xdeadbeef;
204     cbData=0xdeadbeef;
205     /* When successful RegQueryValueExA() leaves GLE as is,
206      * so we must reset it to detect unimplemented functions.
207      */
208     SetLastError(0xdeadbeef);
209     ret = RegQueryValueExA(hkey_main, name, NULL, &type, NULL, &cbData);
210     GLE = GetLastError();
211     lok(ret == ERROR_SUCCESS, "RegQueryValueExA/1 failed: %d, GLE=%d\n", ret, GLE);
212     /* It is wrong for the Ansi version to not be implemented */
213     ok(GLE == 0xdeadbeef, "RegQueryValueExA set GLE = %u\n", GLE);
214     if(GLE == ERROR_CALL_NOT_IMPLEMENTED) return;
215 
216     str_byte_len = (string ? lstrlenA(string) : 0) + 1;
217     lok(type == REG_SZ, "RegQueryValueExA/1 returned type %d\n", type);
218     lok(cbData == full_byte_len, "cbData=%d instead of %d or %d\n", cbData, full_byte_len, str_byte_len);
219 
220     value = HeapAlloc(GetProcessHeap(), 0, cbData+1);
221     memset(value, 0xbd, cbData+1);
222     type=0xdeadbeef;
223     ret = RegQueryValueExA(hkey_main, name, NULL, &type, value, &cbData);
224     GLE = GetLastError();
225     lok(ret == ERROR_SUCCESS, "RegQueryValueExA/2 failed: %d, GLE=%d\n", ret, GLE);
226     if (!string)
227     {
228         /* When cbData == 0, RegQueryValueExA() should not modify the buffer */
229         lok(*value == 0xbd, "RegQueryValueExA overflowed: cbData=%u *value=%02x\n", cbData, *value);
230     }
231     else
232     {
233         lok(memcmp(value, string, cbData) == 0, "RegQueryValueExA/2 failed: %s/%d != %s/%d\n",
234            wine_debugstr_an((char*)value, cbData), cbData,
235            wine_debugstr_an(string, full_byte_len), full_byte_len);
236         lok(*(value+cbData) == 0xbd, "RegQueryValueExA/2 overflowed at offset %u: %02x != bd\n", cbData, *(value+cbData));
237     }
238     HeapFree(GetProcessHeap(), 0, value);
239 }
240 
241 #define test_hkey_main_Value_W(name, string, full_byte_len) _test_hkey_main_Value_W(__LINE__, name, string, full_byte_len)
242 static void _test_hkey_main_Value_W(int line, LPCWSTR name, LPCWSTR string,
243                                    DWORD full_byte_len)
244 {
245     DWORD ret, type, cbData;
246     BYTE* value;
247 
248     type=0xdeadbeef;
249     cbData=0xdeadbeef;
250     /* When successful RegQueryValueExW() leaves GLE as is,
251      * so we must reset it to detect unimplemented functions.
252      */
253     SetLastError(0xdeadbeef);
254     ret = RegQueryValueExW(hkey_main, name, NULL, &type, NULL, &cbData);
255     GLE = GetLastError();
256     lok(ret == ERROR_SUCCESS, "RegQueryValueExW/1 failed: %d, GLE=%d\n", ret, GLE);
257     if(GLE == ERROR_CALL_NOT_IMPLEMENTED)
258     {
259         win_skip("RegQueryValueExW() is not implemented\n");
260         return;
261     }
262 
263     lok(type == REG_SZ, "RegQueryValueExW/1 returned type %d\n", type);
264     lok(cbData == full_byte_len,
265         "cbData=%d instead of %d\n", cbData, full_byte_len);
266 
267     /* Give enough space to overflow by one WCHAR */
268     value = HeapAlloc(GetProcessHeap(), 0, cbData+2);
269     memset(value, 0xbd, cbData+2);
270     type=0xdeadbeef;
271     ret = RegQueryValueExW(hkey_main, name, NULL, &type, value, &cbData);
272     GLE = GetLastError();
273     lok(ret == ERROR_SUCCESS, "RegQueryValueExW/2 failed: %d, GLE=%d\n", ret, GLE);
274     if (string)
275     {
276         lok(memcmp(value, string, cbData) == 0, "RegQueryValueExW failed: %s/%d != %s/%d\n",
277            wine_dbgstr_wn((WCHAR*)value, cbData / sizeof(WCHAR)), cbData,
278            wine_dbgstr_wn(string, full_byte_len / sizeof(WCHAR)), full_byte_len);
279     }
280     /* This implies that when cbData == 0, RegQueryValueExW() should not modify the buffer */
281     lok(*(value+cbData) == 0xbd, "RegQueryValueExW/2 overflowed at %u: %02x != bd\n", cbData, *(value+cbData));
282     lok(*(value+cbData+1) == 0xbd, "RegQueryValueExW/2 overflowed at %u+1: %02x != bd\n", cbData, *(value+cbData+1));
283     HeapFree(GetProcessHeap(), 0, value);
284 }
285 
286 static void test_set_value(void)
287 {
288     DWORD ret;
289 
290     static const WCHAR name1W[] =   {'C','l','e','a','n','S','i','n','g','l','e','S','t','r','i','n','g', 0};
291     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};
292     static const WCHAR emptyW[] = {0};
293     static const WCHAR string1W[] = {'T','h','i','s','N','e','v','e','r','B','r','e','a','k','s', 0};
294     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};
295     static const WCHAR substring2W[] = {'T','h','i','s',0};
296 
297     static const char name1A[] =   "CleanSingleString";
298     static const char name2A[] =   "SomeIntraZeroedString";
299     static const char emptyA[] = "";
300     static const char string1A[] = "ThisNeverBreaks";
301     static const char string2A[] = "This\0Breaks\0\0A\0\0\0Lot\0\0\0\0";
302     static const char substring2A[] = "This";
303 
304     if (0)
305     {
306         /* Crashes on NT4, Windows 2000 and XP SP1 */
307         ret = RegSetValueA(hkey_main, NULL, REG_SZ, NULL, 0);
308         ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueA should have failed with ERROR_INVALID_PARAMETER instead of %d\n", ret);
309     }
310 
311     ret = RegSetValueA(hkey_main, NULL, REG_SZ, string1A, sizeof(string1A));
312     ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %d, GLE=%d\n", ret, GetLastError());
313     test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
314     test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
315 
316     /* RegSetValueA ignores the size passed in */
317     ret = RegSetValueA(hkey_main, NULL, REG_SZ, string1A, 4);
318     ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %d, GLE=%d\n", ret, GetLastError());
319     test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
320     test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
321 
322     /* stops at first null */
323     ret = RegSetValueA(hkey_main, NULL, REG_SZ, string2A, sizeof(string2A));
324     ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %d, GLE=%d\n", ret, GetLastError());
325     test_hkey_main_Value_A(NULL, substring2A, sizeof(substring2A));
326     test_hkey_main_Value_W(NULL, substring2W, sizeof(substring2W));
327 
328     /* only REG_SZ is supported on NT*/
329     ret = RegSetValueA(hkey_main, NULL, REG_BINARY, string2A, sizeof(string2A));
330     ok(ret == ERROR_INVALID_PARAMETER, "got %d (expected ERROR_INVALID_PARAMETER)\n", ret);
331 
332     ret = RegSetValueA(hkey_main, NULL, REG_EXPAND_SZ, string2A, sizeof(string2A));
333     ok(ret == ERROR_INVALID_PARAMETER, "got %d (expected ERROR_INVALID_PARAMETER)\n", ret);
334 
335     ret = RegSetValueA(hkey_main, NULL, REG_MULTI_SZ, string2A, sizeof(string2A));
336     ok(ret == ERROR_INVALID_PARAMETER, "got %d (expected ERROR_INVALID_PARAMETER)\n", ret);
337 
338     /* Test RegSetValueExA with a 'zero-byte' string (as Office 2003 does).
339      * Surprisingly enough we're supposed to get zero bytes out of it.
340      */
341     ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)emptyA, 0);
342     ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
343     test_hkey_main_Value_A(name1A, NULL, 0);
344     test_hkey_main_Value_W(name1W, NULL, 0);
345 
346     /* test RegSetValueExA with an empty string */
347     ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)emptyA, sizeof(emptyA));
348     ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
349     test_hkey_main_Value_A(name1A, emptyA, sizeof(emptyA));
350     test_hkey_main_Value_W(name1W, emptyW, sizeof(emptyW));
351 
352     /* test RegSetValueExA with off-by-one size */
353     ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)string1A, sizeof(string1A)-sizeof(string1A[0]));
354     ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
355     test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
356     test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
357 
358     /* test RegSetValueExA with normal string */
359     ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)string1A, sizeof(string1A));
360     ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
361     test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
362     test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
363 
364     /* test RegSetValueExA with intrazeroed string */
365     ret = RegSetValueExA(hkey_main, name2A, 0, REG_SZ, (const BYTE *)string2A, sizeof(string2A));
366     ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
367     test_hkey_main_Value_A(name2A, string2A, sizeof(string2A));
368     test_hkey_main_Value_W(name2W, string2W, sizeof(string2W));
369 
370     if (0)
371     {
372         /* Crashes on NT4, Windows 2000 and XP SP1 */
373         ret = RegSetValueW(hkey_main, NULL, REG_SZ, NULL, 0);
374         ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have failed with ERROR_INVALID_PARAMETER instead of %d\n", ret);
375 
376         RegSetValueExA(hkey_main, name2A, 0, REG_SZ, (const BYTE *)1, 1);
377         RegSetValueExA(hkey_main, name2A, 0, REG_DWORD, (const BYTE *)1, 1);
378     }
379 
380     ret = RegSetValueW(hkey_main, NULL, REG_SZ, string1W, sizeof(string1W));
381     ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError());
382     test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
383     test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
384 
385     ret = RegSetValueW(hkey_main, name1W, REG_SZ, string1W, sizeof(string1W));
386     ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError());
387     test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
388     test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
389 
390     /* RegSetValueW ignores the size passed in */
391     ret = RegSetValueW(hkey_main, NULL, REG_SZ, string1W, 4 * sizeof(string1W[0]));
392     ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError());
393     test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
394     test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
395 
396     /* stops at first null */
397     ret = RegSetValueW(hkey_main, NULL, REG_SZ, string2W, sizeof(string2W));
398     ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError());
399     test_hkey_main_Value_A(NULL, substring2A, sizeof(substring2A));
400     test_hkey_main_Value_W(NULL, substring2W, sizeof(substring2W));
401 
402     /* only REG_SZ is supported */
403     ret = RegSetValueW(hkey_main, NULL, REG_BINARY, string2W, sizeof(string2W));
404     ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
405     ret = RegSetValueW(hkey_main, NULL, REG_EXPAND_SZ, string2W, sizeof(string2W));
406     ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
407     ret = RegSetValueW(hkey_main, NULL, REG_MULTI_SZ, string2W, sizeof(string2W));
408     ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
409 
410     /* test RegSetValueExW with off-by-one size */
411     ret = RegSetValueExW(hkey_main, name1W, 0, REG_SZ, (const BYTE *)string1W, sizeof(string1W)-sizeof(string1W[0]));
412     ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %d, GLE=%d\n", ret, GetLastError());
413     test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
414     test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
415 
416     /* test RegSetValueExW with normal string */
417     ret = RegSetValueExW(hkey_main, name1W, 0, REG_SZ, (const BYTE *)string1W, sizeof(string1W));
418     ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %d, GLE=%d\n", ret, GetLastError());
419     test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
420     test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
421 
422     /* test RegSetValueExW with intrazeroed string */
423     ret = RegSetValueExW(hkey_main, name2W, 0, REG_SZ, (const BYTE *)string2W, sizeof(string2W));
424     ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %d, GLE=%d\n", ret, GetLastError());
425     test_hkey_main_Value_A(name2A, string2A, sizeof(string2A));
426     test_hkey_main_Value_W(name2W, string2W, sizeof(string2W));
427 
428     /* test RegSetValueExW with data = 1 */
429     ret = RegSetValueExW(hkey_main, name2W, 0, REG_SZ, (const BYTE *)1, 1);
430     ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %d, GLE=%d\n", ret, GetLastError());
431     ret = RegSetValueExW(hkey_main, name2W, 0, REG_DWORD, (const BYTE *)1, 1);
432     ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %d, GLE=%d\n", ret, GetLastError());
433 
434     if (pRegGetValueA) /* avoid a crash on Windows 2000 */
435     {
436         ret = RegSetValueExW(hkey_main, NULL, 0, REG_SZ, NULL, 4);
437         ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %d, GLE=%d\n", ret, GetLastError());
438 
439         ret = RegSetValueExW(hkey_main, NULL, 0, REG_SZ, NULL, 0);
440         ok(ret == ERROR_SUCCESS, "got %d\n", ret);
441 
442         ret = RegSetValueExW(hkey_main, NULL, 0, REG_DWORD, NULL, 4);
443         ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %d, GLE=%d\n", ret, GetLastError());
444 
445         ret = RegSetValueExW(hkey_main, NULL, 0, REG_DWORD, NULL, 0);
446         ok(ret == ERROR_SUCCESS, "got %d\n", ret);
447     }
448 
449     /* RegSetKeyValue */
450     if (!pRegSetKeyValueW)
451         win_skip("RegSetKeyValue() is not supported.\n");
452     else
453     {
454         static const WCHAR subkeyW[] = {'s','u','b','k','e','y',0};
455         DWORD len, type;
456         HKEY subkey;
457 
458         ret = pRegSetKeyValueW(hkey_main, NULL, name1W, REG_SZ, (const BYTE*)string2W, sizeof(string2W));
459         ok(ret == ERROR_SUCCESS, "got %d\n", ret);
460         test_hkey_main_Value_A(name1A, string2A, sizeof(string2A));
461         test_hkey_main_Value_W(name1W, string2W, sizeof(string2W));
462 
463         ret = pRegSetKeyValueW(hkey_main, subkeyW, name1W, REG_SZ, string1W, sizeof(string1W));
464         ok(ret == ERROR_SUCCESS, "got %d\n", ret);
465 
466         ret = RegOpenKeyExW(hkey_main, subkeyW, 0, KEY_QUERY_VALUE, &subkey);
467         ok(ret == ERROR_SUCCESS, "got %d\n", ret);
468         type = len = 0;
469         ret = RegQueryValueExW(subkey, name1W, 0, &type, NULL, &len);
470         ok(ret == ERROR_SUCCESS, "got %d\n", ret);
471         ok(len == sizeof(string1W), "got %d\n", len);
472         ok(type == REG_SZ, "got type %d\n", type);
473 
474         ret = pRegSetKeyValueW(hkey_main, subkeyW, name1W, REG_SZ, NULL, 0);
475         ok(ret == ERROR_SUCCESS, "got %d\n", ret);
476 
477         ret = pRegSetKeyValueW(hkey_main, subkeyW, name1W, REG_SZ, NULL, 4);
478         ok(ret == ERROR_NOACCESS, "got %d\n", ret);
479 
480         ret = pRegSetKeyValueW(hkey_main, subkeyW, name1W, REG_DWORD, NULL, 4);
481         ok(ret == ERROR_NOACCESS, "got %d\n", ret);
482 
483         RegCloseKey(subkey);
484     }
485 }
486 
487 static void create_test_entries(void)
488 {
489     static const DWORD qw[2] = { 0x12345678, 0x87654321 };
490 
491     SetEnvironmentVariableA("LONGSYSTEMVAR", "bar");
492     SetEnvironmentVariableA("FOO", "ImARatherLongButIndeedNeededString");
493 
494     ok(!RegSetValueExA(hkey_main,"TP1_EXP_SZ",0,REG_EXPAND_SZ, (const BYTE *)sTestpath1, strlen(sTestpath1)+1),
495         "RegSetValueExA failed\n");
496     ok(!RegSetValueExA(hkey_main,"TP1_SZ",0,REG_SZ, (const BYTE *)sTestpath1, strlen(sTestpath1)+1),
497         "RegSetValueExA failed\n");
498     ok(!RegSetValueExA(hkey_main,"TP1_ZB_SZ",0,REG_SZ, (const BYTE *)"", 0),
499        "RegSetValueExA failed\n");
500     ok(!RegSetValueExA(hkey_main,"TP2_EXP_SZ",0,REG_EXPAND_SZ, (const BYTE *)sTestpath2, strlen(sTestpath2)+1),
501         "RegSetValueExA failed\n");
502     ok(!RegSetValueExA(hkey_main,"DWORD",0,REG_DWORD, (const BYTE *)qw, 4),
503         "RegSetValueExA failed\n");
504     ok(!RegSetValueExA(hkey_main,"BIN32",0,REG_BINARY, (const BYTE *)qw, 4),
505         "RegSetValueExA failed\n");
506     ok(!RegSetValueExA(hkey_main,"BIN64",0,REG_BINARY, (const BYTE *)qw, 8),
507         "RegSetValueExA failed\n");
508 }
509 
510 static void test_enum_value(void)
511 {
512     DWORD res;
513     HKEY test_key;
514     char value[20], data[20];
515     WCHAR valueW[20], dataW[20];
516     DWORD val_count, data_count, type;
517     static const WCHAR foobarW[] = {'f','o','o','b','a','r',0};
518     static const WCHAR testW[] = {'T','e','s','t',0};
519     static const WCHAR xxxW[] = {'x','x','x','x','x','x','x','x',0};
520 
521     /* create the working key for new 'Test' value */
522     res = RegCreateKeyA( hkey_main, "TestKey", &test_key );
523     ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res);
524 
525     /* check NULL data with zero length */
526     res = RegSetValueExA( test_key, "Test", 0, REG_SZ, NULL, 0 );
527     if (GetVersion() & 0x80000000)
528         ok( res == ERROR_INVALID_PARAMETER, "RegSetValueExA returned %d\n", res );
529     else
530         ok( !res, "RegSetValueExA returned %d\n", res );
531     res = RegSetValueExA( test_key, "Test", 0, REG_EXPAND_SZ, NULL, 0 );
532     ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %d\n", res );
533     res = RegSetValueExA( test_key, "Test", 0, REG_BINARY, NULL, 0 );
534     ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %d\n", res );
535 
536     /* test reading the value and data without setting them */
537     val_count = 20;
538     data_count = 20;
539     type = 1234;
540     strcpy( value, "xxxxxxxxxx" );
541     strcpy( data, "xxxxxxxxxx" );
542     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
543     ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res );
544     ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
545     ok( data_count == 0, "data_count set to %d instead of 0\n", data_count );
546     ok( type == REG_BINARY, "type %d is not REG_BINARY\n", type );
547     ok( !strcmp( value, "Test" ), "value is '%s' instead of Test\n", value );
548     ok( !strcmp( data, "xxxxxxxxxx" ), "data is '%s' instead of xxxxxxxxxx\n", data );
549 
550     val_count = 20;
551     data_count = 20;
552     type = 1234;
553     memcpy( valueW, xxxW, sizeof(xxxW) );
554     memcpy( dataW, xxxW, sizeof(xxxW) );
555     res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
556     ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res );
557     ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
558     ok( data_count == 0, "data_count set to %d instead of 0\n", data_count );
559     ok( type == REG_BINARY, "type %d is not REG_BINARY\n", type );
560     ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" );
561     ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data is not 'xxxxxxxxxx'\n" );
562 
563     res = RegSetValueExA( test_key, "Test", 0, REG_SZ, (const BYTE *)"foobar", 7 );
564     ok( res == 0, "RegSetValueExA failed error %d\n", res );
565 
566     /* overflow both name and data */
567     val_count = 2;
568     data_count = 2;
569     type = 1234;
570     strcpy( value, "xxxxxxxxxx" );
571     strcpy( data, "xxxxxxxxxx" );
572     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
573     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
574     ok( val_count == 2, "val_count set to %d\n", val_count );
575     ok( data_count == 7 || broken( data_count == 8 ), "data_count set to %d instead of 7\n", data_count );
576     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
577     ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
578     ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data );
579 
580     /* overflow name */
581     val_count = 3;
582     data_count = 20;
583     type = 1234;
584     strcpy( value, "xxxxxxxxxx" );
585     strcpy( data, "xxxxxxxxxx" );
586     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
587     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
588     ok( val_count == 3, "val_count set to %d\n", val_count );
589     ok( data_count == 7 || broken( data_count == 8 ), "data_count set to %d instead of 7\n", data_count );
590     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
591     /* v5.1.2600.0 (XP Home and Professional) does not touch value or data in this case */
592     ok( !strcmp( value, "Te" ) || !strcmp( value, "xxxxxxxxxx" ),
593         "value set to '%s' instead of 'Te' or 'xxxxxxxxxx'\n", value );
594     ok( !strcmp( data, "foobar" ) || !strcmp( data, "xxxxxxx" ) || broken( !strcmp( data, "xxxxxxxx" ) && data_count == 8 ),
595         "data set to '%s' instead of 'foobar' or 'xxxxxxx'\n", data );
596 
597     /* overflow empty name */
598     val_count = 0;
599     data_count = 20;
600     type = 1234;
601     strcpy( value, "xxxxxxxxxx" );
602     strcpy( data, "xxxxxxxxxx" );
603     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
604     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
605     ok( val_count == 0, "val_count set to %d\n", val_count );
606     ok( data_count == 7 || broken( data_count == 8 ), "data_count set to %d instead of 7\n", data_count );
607     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
608     ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
609     /* v5.1.2600.0 (XP Home and Professional) does not touch data in this case */
610     ok( !strcmp( data, "foobar" ) || !strcmp( data, "xxxxxxx" ) || broken( !strcmp( data, "xxxxxxxx" ) && data_count == 8 ),
611         "data set to '%s' instead of 'foobar' or 'xxxxxxx'\n", data );
612 
613     /* overflow data */
614     val_count = 20;
615     data_count = 2;
616     type = 1234;
617     strcpy( value, "xxxxxxxxxx" );
618     strcpy( data, "xxxxxxxxxx" );
619     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
620     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
621     ok( val_count == 20, "val_count set to %d\n", val_count );
622     ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
623     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
624     ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
625     ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data );
626 
627     /* no overflow */
628     val_count = 20;
629     data_count = 20;
630     type = 1234;
631     strcpy( value, "xxxxxxxxxx" );
632     strcpy( data, "xxxxxxxxxx" );
633     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
634     ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res );
635     ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
636     ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
637     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
638     ok( !strcmp( value, "Test" ), "value is '%s' instead of Test\n", value );
639     ok( !strcmp( data, "foobar" ), "data is '%s' instead of foobar\n", data );
640 
641     if (pRegGetValueA) /* avoid a crash on Windows 2000 */
642     {
643         /* no value and no val_count parameter */
644         data_count = 20;
645         type = 1234;
646         strcpy( data, "xxxxxxxxxx" );
647         res = RegEnumValueA( test_key, 0, NULL, NULL, NULL, &type, (BYTE*)data, &data_count );
648         ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res );
649 
650         /* no value parameter */
651         val_count = 20;
652         data_count = 20;
653         type = 1234;
654         strcpy( data, "xxxxxxxxxx" );
655         res = RegEnumValueA( test_key, 0, NULL, &val_count, NULL, &type, (BYTE*)data, &data_count );
656         ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res );
657 
658         /* no val_count parameter */
659         data_count = 20;
660         type = 1234;
661         strcpy( value, "xxxxxxxxxx" );
662         strcpy( data, "xxxxxxxxxx" );
663         res = RegEnumValueA( test_key, 0, value, NULL, NULL, &type, (BYTE*)data, &data_count );
664         ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res );
665     }
666 
667     /* Unicode tests */
668 
669     SetLastError(0xdeadbeef);
670     res = RegSetValueExW( test_key, testW, 0, REG_SZ, (const BYTE *)foobarW, 7*sizeof(WCHAR) );
671     if (res==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
672     {
673         win_skip("RegSetValueExW is not implemented\n");
674         goto cleanup;
675     }
676     ok( res == 0, "RegSetValueExW failed error %d\n", res );
677 
678     /* overflow both name and data */
679     val_count = 2;
680     data_count = 2;
681     type = 1234;
682     memcpy( valueW, xxxW, sizeof(xxxW) );
683     memcpy( dataW, xxxW, sizeof(xxxW) );
684     res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
685     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
686     ok( val_count == 2, "val_count set to %d\n", val_count );
687     ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
688     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
689     ok( !memcmp( valueW, xxxW, sizeof(xxxW) ), "value modified\n" );
690     ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
691 
692     /* overflow name */
693     val_count = 3;
694     data_count = 20;
695     type = 1234;
696     memcpy( valueW, xxxW, sizeof(xxxW) );
697     memcpy( dataW, xxxW, sizeof(xxxW) );
698     res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
699     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
700     ok( val_count == 3, "val_count set to %d\n", val_count );
701     ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
702     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
703     ok( !memcmp( valueW, xxxW, sizeof(xxxW) ), "value modified\n" );
704     ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
705 
706     /* overflow data */
707     val_count = 20;
708     data_count = 2;
709     type = 1234;
710     memcpy( valueW, xxxW, sizeof(xxxW) );
711     memcpy( dataW, xxxW, sizeof(xxxW) );
712     res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
713     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
714     ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
715     ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
716     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
717     ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" );
718     ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
719 
720     /* no overflow */
721     val_count = 20;
722     data_count = 20;
723     type = 1234;
724     memcpy( valueW, xxxW, sizeof(xxxW) );
725     memcpy( dataW, xxxW, sizeof(xxxW) );
726     res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
727     ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res );
728     ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
729     ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
730     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
731     ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" );
732     ok( !memcmp( dataW, foobarW, sizeof(foobarW) ), "data is not 'foobar'\n" );
733 
734     if (pRegGetValueA) /* avoid a crash on Windows 2000 */
735     {
736         /* no valueW and no val_count parameter */
737         data_count = 20;
738         type = 1234;
739         memcpy( dataW, xxxW, sizeof(xxxW) );
740         res = RegEnumValueW( test_key, 0, NULL, NULL, NULL, &type, (BYTE*)dataW, &data_count );
741         ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res );
742 
743         /* no valueW parameter */
744         val_count = 20;
745         data_count = 20;
746         type = 1234;
747         memcpy( dataW, xxxW, sizeof(xxxW) );
748         res = RegEnumValueW( test_key, 0, NULL, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
749         ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res );
750 
751         /* no val_count parameter */
752         data_count = 20;
753         type = 1234;
754         memcpy( valueW, xxxW, sizeof(xxxW) );
755         memcpy( dataW, xxxW, sizeof(xxxW) );
756         res = RegEnumValueW( test_key, 0, valueW, NULL, NULL, &type, (BYTE*)dataW, &data_count );
757         ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res );
758     }
759 
760 cleanup:
761     RegDeleteKeyA(test_key, "");
762     RegCloseKey(test_key);
763 }
764 
765 static void test_query_value_ex(void)
766 {
767     DWORD ret, size, type;
768     BYTE buffer[10];
769 
770     size = sizeof(buffer);
771     ret = RegQueryValueExA(hkey_main, "TP1_SZ", NULL, &type, NULL, &size);
772     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
773     ok(size == strlen(sTestpath1) + 1, "(%d,%d)\n", (DWORD)strlen(sTestpath1) + 1, size);
774     ok(type == REG_SZ, "type %d is not REG_SZ\n", type);
775 
776     type = 0xdeadbeef;
777     size = 0xdeadbeef;
778     ret = RegQueryValueExA(HKEY_CLASSES_ROOT, "Nonexistent Value", NULL, &type, NULL, &size);
779     ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
780     ok(size == 0, "size should have been set to 0 instead of %d\n", size);
781 
782     size = sizeof(buffer);
783     ret = RegQueryValueExA(HKEY_CLASSES_ROOT, "Nonexistent Value", NULL, &type, buffer, &size);
784     ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
785     ok(size == sizeof(buffer), "size shouldn't have been changed to %d\n", size);
786 
787     size = 4;
788     ret = RegQueryValueExA(hkey_main, "BIN32", NULL, &size, buffer, &size);
789     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
790 }
791 
792 static void test_get_value(void)
793 {
794     DWORD ret;
795     DWORD size;
796     DWORD type;
797     DWORD dw, qw[2];
798     CHAR buf[80];
799     CHAR expanded[] = "bar\\subdir1";
800     CHAR expanded2[] = "ImARatherLongButIndeedNeededString\\subdir1";
801 
802     if(!pRegGetValueA)
803     {
804         win_skip("RegGetValue not available on this platform\n");
805         return;
806     }
807 
808     /* Invalid parameter */
809     ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_DWORD, &type, &dw, NULL);
810     ok(ret == ERROR_INVALID_PARAMETER, "ret=%d\n", ret);
811 
812     /* Query REG_DWORD using RRF_RT_REG_DWORD (ok) */
813     size = type = dw = 0xdeadbeef;
814     ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_DWORD, &type, &dw, &size);
815     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
816     ok(size == 4, "size=%d\n", size);
817     ok(type == REG_DWORD, "type=%d\n", type);
818     ok(dw == 0x12345678, "dw=%d\n", dw);
819 
820     /* Query by subkey-name */
821     ret = pRegGetValueA(HKEY_CURRENT_USER, "Software\\Wine\\Test", "DWORD", RRF_RT_REG_DWORD, NULL, NULL, NULL);
822     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
823 
824     /* Query REG_DWORD using RRF_RT_REG_BINARY (restricted) */
825     size = type = dw = 0xdeadbeef;
826     ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_BINARY, &type, &dw, &size);
827     ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
828     /* Although the function failed all values are retrieved */
829     ok(size == 4, "size=%d\n", size);
830     ok(type == REG_DWORD, "type=%d\n", type);
831     ok(dw == 0x12345678, "dw=%d\n", dw);
832 
833     /* Test RRF_ZEROONFAILURE */
834     type = dw = 0xdeadbeef; size = 4;
835     ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_SZ|RRF_ZEROONFAILURE, &type, &dw, &size);
836     ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
837     /* Again all values are retrieved ... */
838     ok(size == 4, "size=%d\n", size);
839     ok(type == REG_DWORD, "type=%d\n", type);
840     /* ... except the buffer, which is zeroed out */
841     ok(dw == 0, "dw=%d\n", dw);
842 
843     /* Test RRF_ZEROONFAILURE with a NULL buffer... */
844     type = size = 0xbadbeef;
845     ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_SZ|RRF_ZEROONFAILURE, &type, NULL, &size);
846     ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
847     ok(size == 4, "size=%d\n", size);
848     ok(type == REG_DWORD, "type=%d\n", type);
849 
850     /* Query REG_DWORD using RRF_RT_DWORD (ok) */
851     size = type = dw = 0xdeadbeef;
852     ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_DWORD, &type, &dw, &size);
853     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
854     ok(size == 4, "size=%d\n", size);
855     ok(type == REG_DWORD, "type=%d\n", type);
856     ok(dw == 0x12345678, "dw=%d\n", dw);
857 
858     /* Query 32-bit REG_BINARY using RRF_RT_DWORD (ok) */
859     size = type = dw = 0xdeadbeef;
860     ret = pRegGetValueA(hkey_main, NULL, "BIN32", RRF_RT_DWORD, &type, &dw, &size);
861     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
862     ok(size == 4, "size=%d\n", size);
863     ok(type == REG_BINARY, "type=%d\n", type);
864     ok(dw == 0x12345678, "dw=%d\n", dw);
865 
866     /* Query 64-bit REG_BINARY using RRF_RT_DWORD (type mismatch) */
867     qw[0] = qw[1] = size = type = 0xdeadbeef;
868     ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_DWORD, &type, qw, &size);
869     ok(ret == ERROR_DATATYPE_MISMATCH, "ret=%d\n", ret);
870     ok(size == 8, "size=%d\n", size);
871     ok(type == REG_BINARY, "type=%d\n", type);
872     ok(qw[0] == 0x12345678 &&
873        qw[1] == 0x87654321, "qw={%d,%d}\n", qw[0], qw[1]);
874 
875     /* Query 64-bit REG_BINARY using 32-bit buffer (buffer too small) */
876     type = dw = 0xdeadbeef; size = 4;
877     ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_REG_BINARY, &type, &dw, &size);
878     ok(ret == ERROR_MORE_DATA, "ret=%d\n", ret);
879     ok(dw == 0xdeadbeef, "dw=%d\n", dw);
880     ok(size == 8, "size=%d\n", size);
881 
882     /* Query 64-bit REG_BINARY using RRF_RT_QWORD (ok) */
883     qw[0] = qw[1] = size = type = 0xdeadbeef;
884     ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_QWORD, &type, qw, &size);
885     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
886     ok(size == 8, "size=%d\n", size);
887     ok(type == REG_BINARY, "type=%d\n", type);
888     ok(qw[0] == 0x12345678 &&
889        qw[1] == 0x87654321, "qw={%d,%d}\n", qw[0], qw[1]);
890 
891     /* Query REG_SZ using RRF_RT_REG_SZ (ok) */
892     buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
893     ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ, &type, buf, &size);
894     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
895     ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
896     ok(type == REG_SZ, "type=%d\n", type);
897     ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
898 
899     /* Query REG_SZ using RRF_RT_REG_SZ and no buffer (ok) */
900     type = 0xdeadbeef; size = 0;
901     ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ, &type, NULL, &size);
902     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
903     /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
904     ok(size == strlen(sTestpath1)+1 || broken(size == strlen(sTestpath1)+2),
905        "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
906     ok(type == REG_SZ, "type=%d\n", type);
907 
908     /* Query REG_SZ using RRF_RT_REG_SZ on a zero-byte value (ok) */
909     strcpy(buf, sTestpath1);
910     type = 0xdeadbeef;
911     size = sizeof(buf);
912     ret = pRegGetValueA(hkey_main, NULL, "TP1_ZB_SZ", RRF_RT_REG_SZ, &type, buf, &size);
913     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
914     /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
915     ok(size == 0 ||
916        size == 1, /* win2k3 */
917        "size=%d\n", size);
918     ok(type == REG_SZ, "type=%d\n", type);
919     ok(!strcmp(sTestpath1, buf) ||
920        !strcmp(buf, ""),
921        "Expected \"%s\" or \"\", got \"%s\"\n", sTestpath1, buf);
922 
923     /* Query REG_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (ok) */
924     buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
925     ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ|RRF_NOEXPAND, &type, buf, &size);
926     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
927     ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
928     ok(type == REG_SZ, "type=%d\n", type);
929     ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
930 
931     /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ and no buffer (ok, expands) */
932     size = 0;
933     ret = pRegGetValueA(hkey_main, NULL, "TP2_EXP_SZ", RRF_RT_REG_SZ, NULL, NULL, &size);
934     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
935     ok((size == strlen(expanded2)+1) || /* win2k3 SP1 */
936        (size == strlen(expanded2)+2) || /* win2k3 SP2 */
937        (size == strlen(sTestpath2)+1),
938         "strlen(expanded2)=%d, strlen(sTestpath2)=%d, size=%d\n", lstrlenA(expanded2), lstrlenA(sTestpath2), size);
939 
940     /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ (ok, expands) */
941     buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
942     ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_SZ, &type, buf, &size);
943     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
944     /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath1 length + 1 here. */
945     ok(size == strlen(expanded)+1 || broken(size == strlen(sTestpath1)+1),
946         "strlen(expanded)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded), lstrlenA(sTestpath1), size);
947     ok(type == REG_SZ, "type=%d\n", type);
948     ok(!strcmp(expanded, buf), "expanded=\"%s\" buf=\"%s\"\n", expanded, buf);
949 
950     /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ (ok, expands a lot) */
951     buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
952     ret = pRegGetValueA(hkey_main, NULL, "TP2_EXP_SZ", RRF_RT_REG_SZ, &type, buf, &size);
953     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
954     /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath2 length + 1 here. */
955     ok(size == strlen(expanded2)+1 || broken(size == strlen(sTestpath2)+1),
956         "strlen(expanded2)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded2), lstrlenA(sTestpath2), size);
957     ok(type == REG_SZ, "type=%d\n", type);
958     ok(!strcmp(expanded2, buf), "expanded2=\"%s\" buf=\"%s\"\n", expanded2, buf);
959 
960     /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND (ok, doesn't expand) */
961     buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
962     ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND, &type, buf, &size);
963     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
964     ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
965     ok(type == REG_EXPAND_SZ, "type=%d\n", type);
966     ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
967 
968     /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND and no buffer (ok, doesn't expand) */
969     size = 0xbadbeef;
970     ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND, NULL, NULL, &size);
971     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
972     /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
973     ok(size == strlen(sTestpath1)+1 || broken(size == strlen(sTestpath1)+2),
974        "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
975 
976     /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (type mismatch) */
977     ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_SZ|RRF_NOEXPAND, NULL, NULL, NULL);
978     ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
979 
980     /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ (not allowed without RRF_NOEXPAND) */
981     ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ, NULL, NULL, NULL);
982     /* before win8: ERROR_INVALID_PARAMETER, win8: ERROR_UNSUPPORTED_TYPE */
983     ok(ret == ERROR_INVALID_PARAMETER || ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
984 
985     /* Query REG_EXPAND_SZ using RRF_RT_ANY */
986     buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
987     ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_ANY, &type, buf, &size);
988     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
989     /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath1 length + 1 here. */
990     ok(size == strlen(expanded)+1 || broken(size == strlen(sTestpath1)+1),
991         "strlen(expanded)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded), lstrlenA(sTestpath1), size);
992     ok(type == REG_SZ, "type=%d\n", type);
993     ok(!strcmp(expanded, buf), "expanded=\"%s\" buf=\"%s\"\n", expanded, buf);
994 }
995 
996 static void test_reg_open_key(void)
997 {
998     DWORD ret = 0;
999     HKEY hkResult = NULL;
1000     HKEY hkPreserve = NULL;
1001     HKEY hkRoot64 = NULL;
1002     HKEY hkRoot32 = NULL;
1003     BOOL bRet;
1004     SID_IDENTIFIER_AUTHORITY sid_authority = {SECURITY_WORLD_SID_AUTHORITY};
1005     PSID world_sid;
1006     EXPLICIT_ACCESSA access;
1007     PACL key_acl;
1008     SECURITY_DESCRIPTOR *sd;
1009 
1010     /* successful open */
1011     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult);
1012     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1013     ok(hkResult != NULL, "expected hkResult != NULL\n");
1014     hkPreserve = hkResult;
1015 
1016     /* open same key twice */
1017     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult);
1018     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1019     ok(hkResult != hkPreserve, "expected hkResult != hkPreserve\n");
1020     ok(hkResult != NULL, "hkResult != NULL\n");
1021     RegCloseKey(hkResult);
1022 
1023     /* trailing slashes */
1024     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test\\\\", &hkResult);
1025     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1026     RegCloseKey(hkResult);
1027 
1028     /* open nonexistent key
1029     * check that hkResult is set to NULL
1030     */
1031     hkResult = hkPreserve;
1032     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
1033     ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
1034     ok(hkResult == NULL, "expected hkResult == NULL\n");
1035 
1036     /* open the same nonexistent key again to make sure the key wasn't created */
1037     hkResult = hkPreserve;
1038     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
1039     ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
1040     ok(hkResult == NULL, "expected hkResult == NULL\n");
1041 
1042     /* send in NULL lpSubKey
1043     * check that hkResult receives the value of hKey
1044     */
1045     hkResult = hkPreserve;
1046     ret = RegOpenKeyA(HKEY_CURRENT_USER, NULL, &hkResult);
1047     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1048     ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
1049 
1050     /* send empty-string in lpSubKey */
1051     hkResult = hkPreserve;
1052     ret = RegOpenKeyA(HKEY_CURRENT_USER, "", &hkResult);
1053     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1054     ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
1055 
1056     /* send in NULL lpSubKey and NULL hKey
1057     * hkResult is set to NULL
1058     */
1059     hkResult = hkPreserve;
1060     ret = RegOpenKeyA(NULL, NULL, &hkResult);
1061     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1062     ok(hkResult == NULL, "expected hkResult == NULL\n");
1063 
1064     /* only send NULL hKey
1065      * the value of hkResult remains unchanged
1066      */
1067     hkResult = hkPreserve;
1068     ret = RegOpenKeyA(NULL, "Software\\Wine\\Test", &hkResult);
1069     ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */
1070        "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
1071     ok(hkResult == hkPreserve, "expected hkResult == hkPreserve\n");
1072 
1073     /* send in NULL hkResult */
1074     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", NULL);
1075     ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", ret);
1076 
1077     ret = RegOpenKeyA(HKEY_CURRENT_USER, NULL, NULL);
1078     ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", ret);
1079 
1080     ret = RegOpenKeyA(NULL, NULL, NULL);
1081     ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", ret);
1082 
1083     /*  beginning backslash character */
1084     ret = RegOpenKeyA(HKEY_CURRENT_USER, "\\Software\\Wine\\Test", &hkResult);
1085     ok(ret == ERROR_BAD_PATHNAME || /* NT/2k/XP */
1086        broken(ret == ERROR_SUCCESS),  /* wow64 */
1087        "expected ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %d\n", ret);
1088     if (!ret) RegCloseKey(hkResult);
1089 
1090     hkResult = NULL;
1091     ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, "\\clsid", 0, KEY_QUERY_VALUE, &hkResult);
1092     ok(ret == ERROR_SUCCESS || /* 2k/XP */
1093        ret == ERROR_BAD_PATHNAME, /* NT */
1094        "expected ERROR_SUCCESS, ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %d\n", ret);
1095     RegCloseKey(hkResult);
1096 
1097     /* NULL or empty subkey of special root */
1098     hkResult = NULL;
1099     ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, NULL, 0, KEY_QUERY_VALUE, &hkResult);
1100     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1101     ok(hkResult == HKEY_CLASSES_ROOT, "expected hkResult == HKEY_CLASSES_ROOT\n");
1102 
1103     hkResult = NULL;
1104     ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, "", 0, KEY_QUERY_VALUE, &hkResult);
1105     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1106     ok(hkResult == HKEY_CLASSES_ROOT, "expected hkResult == HKEY_CLASSES_ROOT\n");
1107 
1108     hkResult = NULL;
1109     ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, "\\", 0, KEY_QUERY_VALUE, &hkResult);
1110     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1111     ok(hkResult != HKEY_CLASSES_ROOT, "expected hkResult to be a new key\n");
1112     ok(!RegCloseKey(hkResult), "got invalid hkey\n");
1113 
1114     /* empty subkey of existing handle */
1115     hkResult = hkPreserve;
1116     ret = RegOpenKeyExA(hkPreserve, "", 0, KEY_QUERY_VALUE, &hkResult);
1117     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1118     ok(hkResult != hkPreserve, "expected hkResult != hkPreserve\n");
1119     ok(!RegCloseKey(hkResult), "got invalid hkey\n");
1120 
1121     /* NULL subkey of existing handle */
1122     hkResult = hkPreserve;
1123     ret = RegOpenKeyExA(hkPreserve, NULL, 0, KEY_QUERY_VALUE, &hkResult);
1124     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1125     ok(hkResult != hkPreserve, "expected hkResult != hkPreserve\n");
1126     ok(!RegCloseKey(hkResult), "got invalid hkey\n");
1127 
1128     /* empty subkey of NULL */
1129     hkResult = hkPreserve;
1130     ret = RegOpenKeyExA(NULL, "", 0, KEY_QUERY_VALUE, &hkResult);
1131     ok(ret == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", ret);
1132     ok(hkResult == hkPreserve, "expected hkResult == hkPreserve\n");
1133 
1134     RegCloseKey(hkPreserve);
1135 
1136     /* WOW64 flags */
1137     hkResult = NULL;
1138     ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WOW64_32KEY, &hkResult);
1139     ok((ret == ERROR_SUCCESS && hkResult != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */),
1140         "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret);
1141     RegCloseKey(hkResult);
1142 
1143     hkResult = NULL;
1144     ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WOW64_64KEY, &hkResult);
1145     ok((ret == ERROR_SUCCESS && hkResult != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */),
1146         "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret);
1147     RegCloseKey(hkResult);
1148 
1149     /* check special HKEYs on 64bit
1150      * only the lower 4 bytes of the supplied key are used
1151      */
1152     if (ptr_size == 64)
1153     {
1154         /* HKEY_CURRENT_USER */
1155         ret = RegOpenKeyA(UlongToHandle(HandleToUlong(HKEY_CURRENT_USER)), "Software", &hkResult);
1156         ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1157         ok(hkResult != NULL, "expected hkResult != NULL\n");
1158         RegCloseKey(hkResult);
1159 
1160         ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_CURRENT_USER) | (ULONG64)1 << 32), "Software", &hkResult);
1161         ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1162         ok(hkResult != NULL, "expected hkResult != NULL\n");
1163         RegCloseKey(hkResult);
1164 
1165         ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_CURRENT_USER) | (ULONG64)0xdeadbeef << 32), "Software", &hkResult);
1166         ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1167         ok(hkResult != NULL, "expected hkResult != NULL\n");
1168         RegCloseKey(hkResult);
1169 
1170         ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_CURRENT_USER) | (ULONG64)0xffffffff << 32), "Software", &hkResult);
1171         ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1172         ok(hkResult != NULL, "expected hkResult != NULL\n");
1173         RegCloseKey(hkResult);
1174 
1175         /* HKEY_LOCAL_MACHINE */
1176         ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_LOCAL_MACHINE) | (ULONG64)0xdeadbeef << 32), "Software", &hkResult);
1177         ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1178         ok(hkResult != NULL, "expected hkResult != NULL\n");
1179         RegCloseKey(hkResult);
1180     }
1181 
1182     /* Try using WOW64 flags when opening a key with a DACL set to verify that
1183      * the registry access check is performed correctly. Redirection isn't
1184      * being tested, so the tests don't care about whether the process is
1185      * running under WOW64. */
1186     if (!pIsWow64Process)
1187     {
1188         win_skip("WOW64 flags are not recognized\n");
1189         return;
1190     }
1191 
1192     ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1193                           KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &hkRoot32, NULL);
1194     if (limited_user)
1195         ok(ret == ERROR_ACCESS_DENIED && hkRoot32 == NULL,
1196            "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret);
1197     else
1198         ok(ret == ERROR_SUCCESS && hkRoot32 != NULL,
1199            "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret);
1200 
1201     ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1202                           KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &hkRoot64, NULL);
1203     if (limited_user)
1204         ok(ret == ERROR_ACCESS_DENIED && hkRoot64 == NULL,
1205            "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret);
1206     else
1207         ok(ret == ERROR_SUCCESS && hkRoot64 != NULL,
1208            "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret);
1209 
1210     bRet = AllocateAndInitializeSid(&sid_authority, 1, SECURITY_WORLD_RID,
1211                                     0, 0, 0, 0, 0, 0, 0, &world_sid);
1212     ok(bRet == TRUE,
1213        "Expected AllocateAndInitializeSid to return TRUE, got %d, last error %u\n", bRet, GetLastError());
1214 
1215     access.grfAccessPermissions = GENERIC_ALL | STANDARD_RIGHTS_ALL;
1216     access.grfAccessMode = SET_ACCESS;
1217     access.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
1218     access.Trustee.pMultipleTrustee = NULL;
1219     access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1220     access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
1221     access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
1222     access.Trustee.ptstrName = (char *)world_sid;
1223 
1224     ret = SetEntriesInAclA(1, &access, NULL, &key_acl);
1225     ok(ret == ERROR_SUCCESS,
1226        "Expected SetEntriesInAclA to return ERROR_SUCCESS, got %u, last error %u\n", ret, GetLastError());
1227 
1228     sd = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
1229     bRet = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
1230     ok(bRet == TRUE,
1231        "Expected InitializeSecurityDescriptor to return TRUE, got %d, last error %u\n", bRet, GetLastError());
1232 
1233     bRet = SetSecurityDescriptorDacl(sd, TRUE, key_acl, FALSE);
1234     ok(bRet == TRUE,
1235        "Expected SetSecurityDescriptorDacl to return TRUE, got %d, last error %u\n", bRet, GetLastError());
1236 
1237     if (limited_user)
1238     {
1239         skip("not enough privileges to modify HKLM\n");
1240     }
1241     else
1242     {
1243         LONG error;
1244 
1245         error = RegSetKeySecurity(hkRoot64, DACL_SECURITY_INFORMATION, sd);
1246         ok(error == ERROR_SUCCESS,
1247            "Expected RegSetKeySecurity to return success, got error %u\n", error);
1248 
1249         error = RegSetKeySecurity(hkRoot32, DACL_SECURITY_INFORMATION, sd);
1250         ok(error == ERROR_SUCCESS,
1251            "Expected RegSetKeySecurity to return success, got error %u\n", error);
1252 
1253         hkResult = NULL;
1254         ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, KEY_WOW64_64KEY | KEY_READ, &hkResult);
1255         ok(ret == ERROR_SUCCESS && hkResult != NULL,
1256            "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret);
1257         RegCloseKey(hkResult);
1258 
1259         hkResult = NULL;
1260         ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, KEY_WOW64_32KEY | KEY_READ, &hkResult);
1261         ok(ret == ERROR_SUCCESS && hkResult != NULL,
1262            "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret);
1263         RegCloseKey(hkResult);
1264     }
1265 
1266     HeapFree(GetProcessHeap(), 0, sd);
1267     LocalFree(key_acl);
1268     FreeSid(world_sid);
1269     RegDeleteKeyA(hkRoot64, "");
1270     RegCloseKey(hkRoot64);
1271     RegDeleteKeyA(hkRoot32, "");
1272     RegCloseKey(hkRoot32);
1273 }
1274 
1275 static void test_reg_create_key(void)
1276 {
1277     LONG ret;
1278     HKEY hkey1, hkey2;
1279     HKEY hkRoot64 = NULL;
1280     HKEY hkRoot32 = NULL;
1281     DWORD dwRet;
1282     BOOL bRet;
1283     SID_IDENTIFIER_AUTHORITY sid_authority = {SECURITY_WORLD_SID_AUTHORITY};
1284     PSID world_sid;
1285     EXPLICIT_ACCESSA access;
1286     PACL key_acl;
1287     SECURITY_DESCRIPTOR *sd;
1288 
1289     ret = RegCreateKeyExA(hkey_main, "Subkey1", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL);
1290     ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
1291     /* should succeed: all versions of Windows ignore the access rights
1292      * to the parent handle */
1293     ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey2, NULL);
1294     ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
1295 
1296     /* clean up */
1297     RegDeleteKeyA(hkey2, "");
1298     RegDeleteKeyA(hkey1, "");
1299     RegCloseKey(hkey2);
1300     RegCloseKey(hkey1);
1301 
1302     /* test creation of volatile keys */
1303     ret = RegCreateKeyExA(hkey_main, "Volatile", 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey1, NULL);
1304     ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
1305     ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey2, NULL);
1306     ok(ret == ERROR_CHILD_MUST_BE_VOLATILE, "RegCreateKeyExA failed with error %d\n", ret);
1307     if (!ret) RegCloseKey( hkey2 );
1308     ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey2, NULL);
1309     ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
1310     RegCloseKey(hkey2);
1311     /* should succeed if the key already exists */
1312     ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey2, NULL);
1313     ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
1314 
1315     /* clean up */
1316     RegDeleteKeyA(hkey2, "");
1317     RegDeleteKeyA(hkey1, "");
1318     RegCloseKey(hkey2);
1319     RegCloseKey(hkey1);
1320 
1321     /*  beginning backslash character */
1322     ret = RegCreateKeyExA(hkey_main, "\\Subkey3", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL);
1323     if (!(GetVersion() & 0x80000000))
1324         ok(ret == ERROR_BAD_PATHNAME, "expected ERROR_BAD_PATHNAME, got %d\n", ret);
1325     else {
1326         ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
1327         RegDeleteKeyA(hkey1, "");
1328         RegCloseKey(hkey1);
1329     }
1330 
1331     /* trailing backslash characters */
1332     ret = RegCreateKeyExA(hkey_main, "Subkey4\\\\", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL);
1333     ok(ret == ERROR_SUCCESS, "RegCreateKeyExA failed with error %d\n", ret);
1334     RegDeleteKeyA(hkey1, "");
1335     RegCloseKey(hkey1);
1336 
1337     /* System\CurrentControlSet\Control\Video should be non-volatile */
1338     ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\Video\\Wine",
1339                           0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL);
1340     ok(ret == ERROR_SUCCESS, "RegCreateKeyExA failed with error %d\n", ret);
1341     RegDeleteKeyA(hkey1, "");
1342     RegCloseKey(hkey1);
1343 
1344     /* WOW64 flags - open an existing key */
1345     hkey1 = NULL;
1346     ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0, KEY_READ|KEY_WOW64_32KEY, NULL, &hkey1, NULL);
1347     ok((ret == ERROR_SUCCESS && hkey1 != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */),
1348         "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret);
1349     RegCloseKey(hkey1);
1350 
1351     hkey1 = NULL;
1352     ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0, KEY_READ|KEY_WOW64_64KEY, NULL, &hkey1, NULL);
1353     ok((ret == ERROR_SUCCESS && hkey1 != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */),
1354         "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret);
1355     RegCloseKey(hkey1);
1356 
1357     /* Try using WOW64 flags when opening a key with a DACL set to verify that
1358      * the registry access check is performed correctly. Redirection isn't
1359      * being tested, so the tests don't care about whether the process is
1360      * running under WOW64. */
1361     if (!pIsWow64Process)
1362     {
1363         win_skip("WOW64 flags are not recognized\n");
1364         return;
1365     }
1366 
1367     ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1368                           KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &hkRoot32, NULL);
1369     if (limited_user)
1370         ok(ret == ERROR_ACCESS_DENIED && hkRoot32 == NULL,
1371            "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%d)\n", ret);
1372     else
1373         ok(ret == ERROR_SUCCESS && hkRoot32 != NULL,
1374            "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%d)\n", ret);
1375 
1376     ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1377                           KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &hkRoot64, NULL);
1378     if (limited_user)
1379         ok(ret == ERROR_ACCESS_DENIED && hkRoot64 == NULL,
1380            "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%d)\n", ret);
1381     else
1382         ok(ret == ERROR_SUCCESS && hkRoot64 != NULL,
1383            "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%d)\n", ret);
1384 
1385     bRet = AllocateAndInitializeSid(&sid_authority, 1, SECURITY_WORLD_RID,
1386                                     0, 0, 0, 0, 0, 0, 0, &world_sid);
1387     ok(bRet == TRUE,
1388        "Expected AllocateAndInitializeSid to return TRUE, got %d, last error %u\n", bRet, GetLastError());
1389 
1390     access.grfAccessPermissions = GENERIC_ALL | STANDARD_RIGHTS_ALL;
1391     access.grfAccessMode = SET_ACCESS;
1392     access.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
1393     access.Trustee.pMultipleTrustee = NULL;
1394     access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1395     access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
1396     access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
1397     access.Trustee.ptstrName = (char *)world_sid;
1398 
1399     dwRet = SetEntriesInAclA(1, &access, NULL, &key_acl);
1400     ok(dwRet == ERROR_SUCCESS,
1401        "Expected SetEntriesInAclA to return ERROR_SUCCESS, got %u, last error %u\n", dwRet, GetLastError());
1402 
1403     sd = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
1404     bRet = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
1405     ok(bRet == TRUE,
1406        "Expected InitializeSecurityDescriptor to return TRUE, got %d, last error %u\n", bRet, GetLastError());
1407 
1408     bRet = SetSecurityDescriptorDacl(sd, TRUE, key_acl, FALSE);
1409     ok(bRet == TRUE,
1410        "Expected SetSecurityDescriptorDacl to return TRUE, got %d, last error %u\n", bRet, GetLastError());
1411 
1412     if (limited_user)
1413     {
1414         skip("not enough privileges to modify HKLM\n");
1415     }
1416     else
1417     {
1418         ret = RegSetKeySecurity(hkRoot64, DACL_SECURITY_INFORMATION, sd);
1419         ok(ret == ERROR_SUCCESS,
1420            "Expected RegSetKeySecurity to return success, got error %u\n", ret);
1421 
1422         ret = RegSetKeySecurity(hkRoot32, DACL_SECURITY_INFORMATION, sd);
1423         ok(ret == ERROR_SUCCESS,
1424            "Expected RegSetKeySecurity to return success, got error %u\n", ret);
1425 
1426         hkey1 = NULL;
1427         ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1428                               KEY_WOW64_64KEY | KEY_READ, NULL, &hkey1, NULL);
1429         ok(ret == ERROR_SUCCESS && hkey1 != NULL,
1430            "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret);
1431         RegCloseKey(hkey1);
1432 
1433         hkey1 = NULL;
1434         ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1435                               KEY_WOW64_32KEY | KEY_READ, NULL, &hkey1, NULL);
1436         ok(ret == ERROR_SUCCESS && hkey1 != NULL,
1437            "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret);
1438         RegCloseKey(hkey1);
1439     }
1440 
1441     HeapFree(GetProcessHeap(), 0, sd);
1442     LocalFree(key_acl);
1443     FreeSid(world_sid);
1444     RegDeleteKeyA(hkRoot64, "");
1445     RegCloseKey(hkRoot64);
1446     RegDeleteKeyA(hkRoot32, "");
1447     RegCloseKey(hkRoot32);
1448 }
1449 
1450 static void test_reg_close_key(void)
1451 {
1452     DWORD ret = 0;
1453     HKEY hkHandle;
1454 
1455     /* successfully close key
1456      * hkHandle remains changed after call to RegCloseKey
1457      */
1458     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkHandle);
1459     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1460     ret = RegCloseKey(hkHandle);
1461     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1462 
1463     /* try to close the key twice */
1464     ret = RegCloseKey(hkHandle); /* Windows 95 doesn't mind. */
1465     ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_SUCCESS,
1466        "expected ERROR_INVALID_HANDLE or ERROR_SUCCESS, got %d\n", ret);
1467 
1468     /* try to close a NULL handle */
1469     ret = RegCloseKey(NULL);
1470     ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */
1471        "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
1472 
1473     /* Check to see if we didn't potentially close our main handle, which could happen on win98 as
1474      * win98 doesn't give a new handle when the same key is opened.
1475      * Not re-opening will make some next tests fail.
1476      */
1477     if (hkey_main == hkHandle)
1478     {
1479         trace("The main handle is most likely closed, so re-opening\n");
1480         RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main );
1481     }
1482 }
1483 
1484 static void test_reg_delete_key(void)
1485 {
1486     DWORD ret;
1487     HKEY key;
1488 
1489     ret = RegDeleteKeyA(hkey_main, NULL);
1490 
1491     /* There is a bug in NT4 and W2K that doesn't check if the subkey is NULL. If
1492      * there are also no subkeys available it will delete the key pointed to by hkey_main.
1493      * Not re-creating will make some next tests fail.
1494      */
1495     if (ret == ERROR_SUCCESS)
1496     {
1497         trace("We are probably running on NT4 or W2K as the main key is deleted,"
1498             " re-creating the main key\n");
1499         setup_main_key();
1500     }
1501     else
1502         ok(ret == ERROR_INVALID_PARAMETER ||
1503            ret == ERROR_ACCESS_DENIED ||
1504            ret == ERROR_BADKEY, /* Win95 */
1505            "ret=%d\n", ret);
1506 
1507     ret = RegCreateKeyA(hkey_main, "deleteme", &key);
1508     ok(ret == ERROR_SUCCESS, "Could not create key, got %d\n", ret);
1509     ret = RegDeleteKeyA(key, "");
1510     ok(ret == ERROR_SUCCESS, "RegDeleteKeyA failed, got %d\n", ret);
1511     RegCloseKey(key);
1512     ret = RegOpenKeyA(hkey_main, "deleteme", &key);
1513     ok(ret == ERROR_FILE_NOT_FOUND, "Key was not deleted, got %d\n", ret);
1514     RegCloseKey(key);
1515 }
1516 
1517 static BOOL set_privileges(LPCSTR privilege, BOOL set)
1518 {
1519     TOKEN_PRIVILEGES tp;
1520     HANDLE hToken;
1521     LUID luid;
1522 
1523     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
1524         return FALSE;
1525 
1526     if(!LookupPrivilegeValueA(NULL, privilege, &luid))
1527     {
1528         CloseHandle(hToken);
1529         return FALSE;
1530     }
1531 
1532     tp.PrivilegeCount = 1;
1533     tp.Privileges[0].Luid = luid;
1534 
1535     if (set)
1536         tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1537     else
1538         tp.Privileges[0].Attributes = 0;
1539 
1540     AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
1541     if (GetLastError() != ERROR_SUCCESS)
1542     {
1543         CloseHandle(hToken);
1544         return FALSE;
1545     }
1546 
1547     CloseHandle(hToken);
1548     return TRUE;
1549 }
1550 
1551 static void test_reg_save_key(void)
1552 {
1553     DWORD ret;
1554 
1555     if (!set_privileges(SE_BACKUP_NAME, TRUE) ||
1556         !set_privileges(SE_RESTORE_NAME, FALSE))
1557     {
1558         win_skip("Failed to set SE_BACKUP_NAME privileges, skipping tests\n");
1559         return;
1560     }
1561 
1562     ret = RegSaveKeyA(hkey_main, "saved_key", NULL);
1563     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1564 
1565     set_privileges(SE_BACKUP_NAME, FALSE);
1566 }
1567 
1568 static void test_reg_load_key(void)
1569 {
1570     DWORD ret;
1571     HKEY hkHandle;
1572 
1573     if (!set_privileges(SE_RESTORE_NAME, TRUE) ||
1574         !set_privileges(SE_BACKUP_NAME, FALSE))
1575     {
1576         win_skip("Failed to set SE_RESTORE_NAME privileges, skipping tests\n");
1577         return;
1578     }
1579 
1580     ret = RegLoadKeyA(HKEY_LOCAL_MACHINE, "Test", "saved_key");
1581     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1582 
1583     set_privileges(SE_RESTORE_NAME, FALSE);
1584 
1585     ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, "Test", &hkHandle);
1586     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1587 
1588     RegCloseKey(hkHandle);
1589 }
1590 
1591 static void test_reg_unload_key(void)
1592 {
1593     DWORD ret;
1594 
1595     if (!set_privileges(SE_RESTORE_NAME, TRUE) ||
1596         !set_privileges(SE_BACKUP_NAME, FALSE))
1597     {
1598         win_skip("Failed to set SE_RESTORE_NAME privileges, skipping tests\n");
1599         return;
1600     }
1601 
1602     ret = RegUnLoadKeyA(HKEY_LOCAL_MACHINE, "Test");
1603     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1604 
1605     set_privileges(SE_RESTORE_NAME, FALSE);
1606 
1607     DeleteFileA("saved_key");
1608     DeleteFileA("saved_key.LOG");
1609 }
1610 
1611 /* tests that show that RegConnectRegistry and
1612    OpenSCManager accept computer names without the
1613    \\ prefix (what MSDN says).   */
1614 static void test_regconnectregistry( void)
1615 {
1616     CHAR compName[MAX_COMPUTERNAME_LENGTH + 1];
1617     CHAR netwName[MAX_COMPUTERNAME_LENGTH + 3]; /* 2 chars for double backslash */
1618     DWORD len = sizeof(compName) ;
1619     BOOL ret;
1620     LONG retl;
1621     HKEY hkey;
1622     SC_HANDLE schnd;
1623 
1624     SetLastError(0xdeadbeef);
1625     ret = GetComputerNameA(compName, &len);
1626     ok( ret, "GetComputerName failed err = %d\n", GetLastError());
1627     if( !ret) return;
1628 
1629     lstrcpyA(netwName, "\\\\");
1630     lstrcpynA(netwName+2, compName, MAX_COMPUTERNAME_LENGTH + 1);
1631 
1632     retl = RegConnectRegistryA( compName, HKEY_LOCAL_MACHINE, &hkey);
1633     ok( !retl ||
1634         retl == ERROR_DLL_INIT_FAILED ||
1635         retl == ERROR_BAD_NETPATH, /* some win2k */
1636         "RegConnectRegistryA failed err = %d\n", retl);
1637     if( !retl) RegCloseKey( hkey);
1638 
1639     retl = RegConnectRegistryA( netwName, HKEY_LOCAL_MACHINE, &hkey);
1640     ok( !retl ||
1641         retl == ERROR_DLL_INIT_FAILED ||
1642         retl == ERROR_BAD_NETPATH, /* some win2k */
1643         "RegConnectRegistryA failed err = %d\n", retl);
1644     if( !retl) RegCloseKey( hkey);
1645 
1646     SetLastError(0xdeadbeef);
1647     schnd = OpenSCManagerA( compName, NULL, GENERIC_READ);
1648     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1649     {
1650         win_skip("OpenSCManagerA is not implemented\n");
1651         return;
1652     }
1653 
1654     ok( schnd != NULL, "OpenSCManagerA failed err = %d\n", GetLastError());
1655     CloseServiceHandle( schnd);
1656 
1657     SetLastError(0xdeadbeef);
1658     schnd = OpenSCManagerA( netwName, NULL, GENERIC_READ);
1659     ok( schnd != NULL, "OpenSCManagerA failed err = %d\n", GetLastError());
1660     CloseServiceHandle( schnd);
1661 
1662 }
1663 
1664 static void test_reg_query_value(void)
1665 {
1666     HKEY subkey;
1667     CHAR val[MAX_PATH];
1668     WCHAR valW[5];
1669     LONG size, ret;
1670 
1671     static const WCHAR expected[] = {'d','a','t','a',0};
1672 
1673     ret = RegCreateKeyA(hkey_main, "subkey", &subkey);
1674     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1675 
1676     ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4);
1677     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1678 
1679     /* try an invalid hkey */
1680     SetLastError(0xdeadbeef);
1681     size = MAX_PATH;
1682     ret = RegQueryValueA((HKEY)0xcafebabe, "subkey", val, &size);
1683     ok(ret == ERROR_INVALID_HANDLE ||
1684        ret == ERROR_BADKEY || /* Windows 98 returns BADKEY */
1685        ret == ERROR_ACCESS_DENIED, /* non-admin winxp */
1686        "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
1687     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1688 
1689     /* try a NULL hkey */
1690     SetLastError(0xdeadbeef);
1691     size = MAX_PATH;
1692     ret = RegQueryValueA(NULL, "subkey", val, &size);
1693     ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 98 returns BADKEY */
1694        "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
1695     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1696 
1697     /* try a NULL value */
1698     size = MAX_PATH;
1699     ret = RegQueryValueA(hkey_main, "subkey", NULL, &size);
1700     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1701     ok(size == 5, "Expected 5, got %d\n", size);
1702 
1703     /* try a NULL size */
1704     SetLastError(0xdeadbeef);
1705     val[0] = '\0';
1706     ret = RegQueryValueA(hkey_main, "subkey", val, NULL);
1707     ok(ret == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", ret);
1708     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1709     ok(!val[0], "Expected val to be untouched, got %s\n", val);
1710 
1711     /* try a NULL value and size */
1712     ret = RegQueryValueA(hkey_main, "subkey", NULL, NULL);
1713     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1714 
1715     /* try a size too small */
1716     SetLastError(0xdeadbeef);
1717     val[0] = '\0';
1718     size = 1;
1719     ret = RegQueryValueA(hkey_main, "subkey", val, &size);
1720     ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret);
1721     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1722     ok(!val[0], "Expected val to be untouched, got %s\n", val);
1723     ok(size == 5, "Expected 5, got %d\n", size);
1724 
1725     /* successfully read the value using 'subkey' */
1726     size = MAX_PATH;
1727     ret = RegQueryValueA(hkey_main, "subkey", val, &size);
1728     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1729     ok(!lstrcmpA(val, "data"), "Expected 'data', got '%s'\n", val);
1730     ok(size == 5, "Expected 5, got %d\n", size);
1731 
1732     /* successfully read the value using the subkey key */
1733     size = MAX_PATH;
1734     ret = RegQueryValueA(subkey, NULL, val, &size);
1735     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1736     ok(!lstrcmpA(val, "data"), "Expected 'data', got '%s'\n", val);
1737     ok(size == 5, "Expected 5, got %d\n", size);
1738 
1739     /* unicode - try size too small */
1740     SetLastError(0xdeadbeef);
1741     valW[0] = '\0';
1742     size = 0;
1743     ret = RegQueryValueW(subkey, NULL, valW, &size);
1744     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1745     {
1746         win_skip("RegQueryValueW is not implemented\n");
1747         goto cleanup;
1748     }
1749     ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret);
1750     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1751     ok(!valW[0], "Expected valW to be untouched\n");
1752     ok(size == sizeof(expected), "Got wrong size: %d\n", size);
1753 
1754     /* unicode - try size in WCHARS */
1755     SetLastError(0xdeadbeef);
1756     size = sizeof(valW) / sizeof(WCHAR);
1757     ret = RegQueryValueW(subkey, NULL, valW, &size);
1758     ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret);
1759     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1760     ok(!valW[0], "Expected valW to be untouched\n");
1761     ok(size == sizeof(expected), "Got wrong size: %d\n", size);
1762 
1763     /* unicode - successfully read the value */
1764     size = sizeof(valW);
1765     ret = RegQueryValueW(subkey, NULL, valW, &size);
1766     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1767     ok(!lstrcmpW(valW, expected), "Got wrong value\n");
1768     ok(size == sizeof(expected), "Got wrong size: %d\n", size);
1769 
1770     /* unicode - set the value without a NULL terminator */
1771     ret = RegSetValueW(subkey, NULL, REG_SZ, expected, sizeof(expected)-sizeof(WCHAR));
1772     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1773 
1774     /* unicode - read the unterminated value, value is terminated for us */
1775     memset(valW, 'a', sizeof(valW));
1776     size = sizeof(valW);
1777     ret = RegQueryValueW(subkey, NULL, valW, &size);
1778     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1779     ok(!lstrcmpW(valW, expected), "Got wrong value\n");
1780     ok(size == sizeof(expected), "Got wrong size: %d\n", size);
1781 
1782 cleanup:
1783     RegDeleteKeyA(subkey, "");
1784     RegCloseKey(subkey);
1785 }
1786 
1787 static void test_reg_query_info(void)
1788 {
1789     HKEY subkey;
1790     HKEY subsubkey;
1791     LONG ret;
1792     char classbuffer[32];
1793     WCHAR classbufferW[32];
1794     char expectbuffer[32];
1795     WCHAR expectbufferW[32];
1796     char subkey_class[] = "subkey class";
1797     WCHAR subkey_classW[] = {'s','u','b','k','e','y',' ','c','l','a','s','s',0};
1798     char subsubkey_class[] = "subsubkey class";
1799     DWORD classlen;
1800     DWORD subkeys, maxsubkeylen, maxclasslen;
1801     DWORD values, maxvaluenamelen, maxvaluelen;
1802     DWORD sdlen;
1803     FILETIME lastwrite;
1804 
1805     ret = RegCreateKeyExA(hkey_main, "subkey", 0, subkey_class, 0, KEY_ALL_ACCESS, NULL, &subkey, NULL);
1806     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1807 
1808     /* all parameters NULL */
1809     ret = RegQueryInfoKeyA(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1810     ok(ret == ERROR_INVALID_HANDLE, "ret = %d\n", ret);
1811 
1812     ret = RegQueryInfoKeyW(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1813     ok(ret == ERROR_INVALID_HANDLE, "ret = %d\n", ret);
1814 
1815     /* not requesting any information */
1816     ret = RegQueryInfoKeyA(subkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1817     ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1818 
1819     ret = RegQueryInfoKeyW(subkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1820     ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1821 
1822     /* class without length is invalid */
1823     memset(classbuffer, 0x55, sizeof(classbuffer));
1824     ret = RegQueryInfoKeyA(subkey, classbuffer, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1825     ok(ret == ERROR_INVALID_PARAMETER, "ret = %d\n", ret);
1826     ok(classbuffer[0] == 0x55, "classbuffer[0] = 0x%x\n", classbuffer[0]);
1827 
1828     memset(classbufferW, 0x55, sizeof(classbufferW));
1829     ret = RegQueryInfoKeyW(subkey, classbufferW, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1830     ok(ret == ERROR_INVALID_PARAMETER, "ret = %d\n", ret);
1831     ok(classbufferW[0] == 0x5555, "classbufferW[0] = 0x%x\n", classbufferW[0]);
1832 
1833     /* empty key */
1834     sdlen = classlen =0;
1835     ret = RegQueryInfoKeyA(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite);
1836     ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1837     ok(classlen == strlen(subkey_class), "classlen = %u\n", classlen);
1838     ok(subkeys == 0, "subkeys = %u\n", subkeys);
1839     ok(maxsubkeylen == 0, "maxsubkeylen = %u\n", maxsubkeylen);
1840     ok(maxclasslen == 0, "maxclasslen = %u\n", maxclasslen);
1841     ok(values == 0, "values = %u\n", values);
1842     ok(maxvaluenamelen == 0, "maxvaluenamelen = %u\n", maxvaluenamelen);
1843     ok(maxvaluelen == 0, "maxvaluelen = %u\n", maxvaluelen);
1844     todo_wine ok(sdlen != 0, "sdlen = %u\n", sdlen);
1845     ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %u\n", lastwrite.dwLowDateTime);
1846     ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %u\n", lastwrite.dwHighDateTime);
1847 
1848     sdlen = classlen = 0;
1849     ret = RegQueryInfoKeyW(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite);
1850     ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1851     ok(classlen == strlen(subkey_class), "classlen = %u\n", classlen);
1852     ok(subkeys == 0, "subkeys = %u\n", subkeys);
1853     ok(maxsubkeylen == 0, "maxsubkeylen = %u\n", maxsubkeylen);
1854     ok(maxclasslen == 0, "maxclasslen = %u\n", maxclasslen);
1855     ok(values == 0, "values = %u\n", values);
1856     ok(maxvaluenamelen == 0, "maxvaluenamelen = %u\n", maxvaluenamelen);
1857     ok(maxvaluelen == 0, "maxvaluelen = %u\n", maxvaluelen);
1858     todo_wine ok(sdlen != 0, "sdlen = %u\n", sdlen);
1859     ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %u\n", lastwrite.dwLowDateTime);
1860     ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %u\n", lastwrite.dwHighDateTime);
1861 
1862     ret = RegCreateKeyExA(subkey, "subsubkey", 0, subsubkey_class, 0, KEY_ALL_ACCESS, NULL, &subsubkey, NULL);
1863     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1864 
1865     ret = RegSetValueExA(subkey, NULL, 0, REG_SZ, (const BYTE*)"data", 5);
1866     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1867 
1868     /* with subkey & default value */
1869     sdlen = classlen = 0;
1870     ret = RegQueryInfoKeyA(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite);
1871     ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1872     ok(classlen == strlen(subkey_class), "classlen = %u\n", classlen);
1873     ok(subkeys == 1, "subkeys = %u\n", subkeys);
1874     ok(maxsubkeylen == strlen("subsubkey"), "maxsubkeylen = %u\n", maxsubkeylen);
1875     ok(maxclasslen == strlen(subsubkey_class), "maxclasslen = %u\n", maxclasslen);
1876     ok(values == 1, "values = %u\n", values);
1877     ok(maxvaluenamelen == 0, "maxvaluenamelen = %u\n", maxvaluenamelen);
1878     ok(maxvaluelen == sizeof("data") * sizeof(WCHAR), "maxvaluelen = %u\n", maxvaluelen);
1879     todo_wine ok(sdlen != 0, "sdlen = %u\n", sdlen);
1880     ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %u\n", lastwrite.dwLowDateTime);
1881     ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %u\n", lastwrite.dwHighDateTime);
1882 
1883     sdlen = classlen = 0;
1884     ret = RegQueryInfoKeyW(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite);
1885     ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1886     ok(classlen == strlen(subkey_class), "classlen = %u\n", classlen);
1887     ok(subkeys == 1, "subkeys = %u\n", subkeys);
1888     ok(maxsubkeylen == strlen("subsubkey"), "maxsubkeylen = %u\n", maxsubkeylen);
1889     ok(maxclasslen == strlen(subsubkey_class), "maxclasslen = %u\n", maxclasslen);
1890     ok(values == 1, "values = %u\n", values);
1891     ok(maxvaluenamelen == 0, "maxvaluenamelen = %u\n", maxvaluenamelen);
1892     ok(maxvaluelen == sizeof("data") * sizeof(WCHAR), "maxvaluelen = %u\n", maxvaluelen);
1893     todo_wine ok(sdlen != 0, "sdlen = %u\n", sdlen);
1894     ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %u\n", lastwrite.dwLowDateTime);
1895     ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %u\n", lastwrite.dwHighDateTime);
1896 
1897     ret = RegSetValueExA(subkey, "value one", 0, REG_SZ, (const BYTE*)"first value data", 17);
1898     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1899 
1900     ret = RegSetValueExA(subkey, "value 2", 0, REG_SZ, (const BYTE*)"second value data", 18);
1901     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1902 
1903     /* with named value */
1904     classlen = 0;
1905     ret = RegQueryInfoKeyA(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite);
1906     ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
1907     ok(values == 3, "values = %u\n", values);
1908     ok(maxvaluenamelen == strlen("value one"), "maxvaluenamelen = %u\n", maxvaluenamelen);
1909     ok(maxvaluelen == sizeof("second value data") * sizeof(WCHAR), "maxvaluelen = %u\n", maxvaluelen);
1910 
1911     classlen = 0;
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(classbuffer, 0x55, sizeof(classbuffer));
1992     classlen = 0xdeadbeef;
1993     ret = RegQueryInfoKeyA(subkey, classbuffer, &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(expectbuffer, 0x55, sizeof(expectbuffer));
1997     strcpy(expectbuffer, subkey_class);
1998     ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)),
1999        "classbuffer = \"%.*s\", expected %s\n",
2000        (int)sizeof(classbuffer), classbuffer, expectbuffer);
2001 
2002     memset(classbufferW, 0x55, sizeof(classbufferW));
2003     classlen = sizeof(subkey_class);
2004     ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2005     ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
2006     ok(classlen == sizeof(subkey_class) - 1, "classlen = %u\n", classlen);
2007     memset(expectbufferW, 0x55, sizeof(expectbufferW));
2008     lstrcpyW(expectbufferW, subkey_classW);
2009     ok(!memcmp(classbufferW, expectbufferW, sizeof(classbufferW)),
2010        "classbufferW = %s, expected %s\n",
2011        wine_dbgstr_wn(classbufferW, sizeof(classbufferW) / sizeof(WCHAR)), wine_dbgstr_w(expectbufferW));
2012 
2013     memset(classbufferW, 0x55, sizeof(classbufferW));
2014     classlen = 0xdeadbeef;
2015     ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2016     ok(ret == ERROR_SUCCESS, "ret = %d\n", ret);
2017     ok(classlen == sizeof(subkey_class) - 1, "classlen = %u\n", classlen);
2018     memset(expectbufferW, 0x55, sizeof(expectbufferW));
2019     lstrcpyW(expectbufferW, subkey_classW);
2020     ok(!memcmp(classbufferW, expectbufferW, sizeof(classbufferW)),
2021        "classbufferW = %s, expected %s\n",
2022        wine_dbgstr_wn(classbufferW, sizeof(classbufferW) / sizeof(WCHAR)), wine_dbgstr_w(expectbufferW));
2023 
2024     RegDeleteKeyA(subsubkey, "");
2025     RegCloseKey(subsubkey);
2026     RegDeleteKeyA(subkey, "");
2027     RegCloseKey(subkey);
2028 }
2029 
2030 static void test_string_termination(void)
2031 {
2032     HKEY subkey;
2033     LSTATUS ret;
2034     static const char string[] = "FullString";
2035     char name[11];
2036     BYTE buffer[11];
2037     DWORD insize, outsize, nsize;
2038 
2039     ret = RegCreateKeyA(hkey_main, "string_termination", &subkey);
2040     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2041 
2042     /* Off-by-one RegSetValueExA -> adds a trailing '\0'! */
2043     insize=sizeof(string)-1;
2044     ret = RegSetValueExA(subkey, "stringtest", 0, REG_SZ, (BYTE*)string, insize);
2045     ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", ret);
2046     outsize=insize;
2047     ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize);
2048     ok(ret == ERROR_MORE_DATA, "RegQueryValueExA returned: %d\n", ret);
2049 
2050     /* Off-by-two RegSetValueExA -> no trailing '\0' */
2051     insize=sizeof(string)-2;
2052     ret = RegSetValueExA(subkey, "stringtest", 0, REG_SZ, (BYTE*)string, insize);
2053     ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", ret);
2054     outsize=0;
2055     ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, NULL, &outsize);
2056     ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", ret);
2057     ok(outsize == insize, "wrong size %u != %u\n", outsize, insize);
2058 
2059     /* RegQueryValueExA may return a string with no trailing '\0' */
2060     outsize=insize;
2061     memset(buffer, 0xbd, sizeof(buffer));
2062     ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize);
2063     ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", ret);
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     /* RegQueryValueExA adds a trailing '\0' if there is room */
2070     outsize=insize+1;
2071     memset(buffer, 0xbd, sizeof(buffer));
2072     ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize);
2073     ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", ret);
2074     ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize);
2075     ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n",
2076        wine_debugstr_an((char*)buffer, outsize), outsize, string);
2077     ok(buffer[insize] == 0, "buffer overflow at %u %02x\n", insize, buffer[insize]);
2078 
2079     /* RegEnumValueA may return a string with no trailing '\0' */
2080     outsize=insize;
2081     memset(buffer, 0xbd, sizeof(buffer));
2082     nsize=sizeof(name);
2083     ret = RegEnumValueA(subkey, 0, name, &nsize, NULL, NULL, buffer, &outsize);
2084     ok(ret == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", ret);
2085     ok(strcmp(name, "stringtest") == 0, "wrong name: %s\n", name);
2086     ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize);
2087     ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n",
2088        wine_debugstr_an((char*)buffer, outsize), outsize, string);
2089     ok(buffer[insize] == 0xbd, "buffer overflow at %u %02x\n", insize, buffer[insize]);
2090 
2091     /* RegEnumValueA adds a trailing '\0' if there is room */
2092     outsize=insize+1;
2093     memset(buffer, 0xbd, sizeof(buffer));
2094     nsize=sizeof(name);
2095     ret = RegEnumValueA(subkey, 0, name, &nsize, NULL, NULL, buffer, &outsize);
2096     ok(ret == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", ret);
2097     ok(strcmp(name, "stringtest") == 0, "wrong name: %s\n", name);
2098     ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize);
2099     ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n",
2100        wine_debugstr_an((char*)buffer, outsize), outsize, string);
2101     ok(buffer[insize] == 0, "buffer overflow at %u %02x\n", insize, buffer[insize]);
2102 
2103     RegDeleteKeyA(subkey, "");
2104     RegCloseKey(subkey);
2105 }
2106 
2107 static void test_reg_copy_tree(void)
2108 {
2109     HKEY src, dst, subkey;
2110     CHAR buffer[MAX_PATH];
2111     DWORD dwsize, type;
2112     LONG size, ret;
2113 
2114     if (!pRegCopyTreeA)
2115     {
2116         win_skip("Skipping RegCopyTreeA tests, function not present\n");
2117         return;
2118     }
2119 
2120     ret = RegCreateKeyA(hkey_main, "src", &src);
2121     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2122     ret = RegCreateKeyA(hkey_main, "dst", &dst);
2123     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2124 
2125     /* Copy nonexistent subkey */
2126     ret = pRegCopyTreeA(src, "nonexistent_subkey", dst);
2127     ok(ret == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
2128 
2129     /*  Create test keys and values */
2130     ret = RegSetValueA(src, NULL, REG_SZ, "data", 4);
2131     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2132     ret = RegSetValueExA(src, "value", 0, REG_SZ, (const BYTE *)"data2", 5);
2133     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2134 
2135     ret = RegCreateKeyA(src, "subkey2", &subkey);
2136     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2137     ret = RegSetValueA(subkey, NULL, REG_SZ, "data3", 5);
2138     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2139     ret = RegSetValueExA(subkey, "value", 0, REG_SZ, (const BYTE *)"data4", 5);
2140     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2141     ret = RegCloseKey(subkey);
2142     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2143 
2144     ret = RegCreateKeyA(src, "subkey3", &subkey);
2145     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2146     ret = RegCloseKey(subkey);
2147     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2148 
2149     /* Copy subkey */
2150     ret = pRegCopyTreeA(src, "subkey2", dst);
2151     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2152 
2153     size = MAX_PATH;
2154     ret = RegQueryValueA(dst, NULL, buffer, &size);
2155     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2156     ok(!strcmp(buffer, "data3"), "Expected 'data3', got '%s'\n", buffer);
2157 
2158     dwsize = MAX_PATH;
2159     ret = RegQueryValueExA(dst, "value", NULL, &type, (BYTE *)buffer, &dwsize);
2160     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2161     ok(type == REG_SZ, "Expected REG_SZ, got %u\n", type);
2162     ok(!strcmp(buffer, "data4"), "Expected 'data4', got '%s'\n", buffer);
2163 
2164     /* Copy full tree */
2165     ret = pRegCopyTreeA(src, NULL, dst);
2166     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2167 
2168     size = MAX_PATH;
2169     ret = RegQueryValueA(dst, NULL, buffer, &size);
2170     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2171     ok(!strcmp(buffer, "data"), "Expected 'data', got '%s'\n", buffer);
2172 
2173     dwsize = MAX_PATH;
2174     ret = RegQueryValueExA(dst, "value", NULL, &type, (BYTE *)buffer, &dwsize);
2175     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2176     ok(type == REG_SZ, "Expected REG_SZ, got %u\n", type);
2177     ok(!strcmp(buffer, "data2"), "Expected 'data2', got '%s'\n", buffer);
2178 
2179     ret = RegOpenKeyA(dst, "subkey2", &subkey);
2180     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2181     size = MAX_PATH;
2182     ret = RegQueryValueA(subkey, NULL, buffer, &size);
2183     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2184     ok(!strcmp(buffer, "data3"), "Expected 'data3', got '%s'\n", buffer);
2185     dwsize = MAX_PATH;
2186     ret = RegQueryValueExA(subkey, "value", NULL, &type, (BYTE *)buffer, &dwsize);
2187     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2188     ok(type == REG_SZ, "Expected REG_SZ, got %u\n", type);
2189     ok(!strcmp(buffer, "data4"), "Expected 'data4', got '%s'\n", buffer);
2190     ret = RegCloseKey(subkey);
2191     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2192 
2193     ret = RegOpenKeyA(dst, "subkey3", &subkey);
2194     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2195     ret = RegCloseKey(subkey);
2196     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2197 
2198     delete_key(src);
2199     delete_key(dst);
2200 }
2201 
2202 static void test_reg_delete_tree(void)
2203 {
2204     CHAR buffer[MAX_PATH];
2205     HKEY subkey, subkey2;
2206     DWORD dwsize, type;
2207     LONG size, ret;
2208 
2209     if(!pRegDeleteTreeA) {
2210         win_skip("Skipping RegDeleteTreeA tests, function not present\n");
2211         return;
2212     }
2213 
2214     ret = RegCreateKeyA(hkey_main, "subkey", &subkey);
2215     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2216     ret = RegCreateKeyA(subkey, "subkey2", &subkey2);
2217     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2218     ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4);
2219     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2220     ret = RegSetValueA(subkey2, NULL, REG_SZ, "data2", 5);
2221     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2222     ret = RegCloseKey(subkey2);
2223     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2224 
2225     ret = pRegDeleteTreeA(subkey, "subkey2");
2226     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2227     ok(RegOpenKeyA(subkey, "subkey2", &subkey2),
2228         "subkey2 was not deleted\n");
2229     size = MAX_PATH;
2230     ok(!RegQueryValueA(subkey, NULL, buffer, &size),
2231         "Default value of subkey no longer present\n");
2232 
2233     ret = RegCreateKeyA(subkey, "subkey2", &subkey2);
2234     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2235     ret = RegCloseKey(subkey2);
2236     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2237     ret = pRegDeleteTreeA(hkey_main, "subkey\\subkey2");
2238     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2239     ok(RegOpenKeyA(subkey, "subkey2", &subkey2),
2240         "subkey2 was not deleted\n");
2241     ok(!RegQueryValueA(subkey, NULL, buffer, &size),
2242         "Default value of subkey no longer present\n");
2243 
2244     ret = RegCreateKeyA(subkey, "subkey2", &subkey2);
2245     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2246     ret = RegCloseKey(subkey2);
2247     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2248     ret = RegCreateKeyA(subkey, "subkey3", &subkey2);
2249     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2250     ret = RegCloseKey(subkey2);
2251     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2252     ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4);
2253     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2254     ret = RegSetValueExA(subkey, "value", 0, REG_SZ, (const BYTE *)"data2", 5);
2255     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2256     ret = pRegDeleteTreeA(subkey, NULL);
2257     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2258     ok(!RegOpenKeyA(hkey_main, "subkey", &subkey),
2259         "subkey was deleted\n");
2260     ok(RegOpenKeyA(subkey, "subkey2", &subkey2),
2261         "subkey2 was not deleted\n");
2262     ok(RegOpenKeyA(subkey, "subkey3", &subkey2),
2263         "subkey3 was not deleted\n");
2264     size = MAX_PATH;
2265     ret = RegQueryValueA(subkey, NULL, buffer, &size);
2266     ok(ret == ERROR_SUCCESS,
2267         "Default value of subkey is not present\n");
2268     ok(!buffer[0], "Expected length 0 got length %u(%s)\n", lstrlenA(buffer), buffer);
2269     dwsize = MAX_PATH;
2270     ok(RegQueryValueExA(subkey, "value", NULL, &type, (BYTE *)buffer, &dwsize),
2271         "Value is still present\n");
2272     ret = RegCloseKey(subkey);
2273     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2274 
2275     ret = RegOpenKeyA(hkey_main, "subkey", &subkey);
2276     ok(ret == ERROR_SUCCESS, "subkey was deleted\n");
2277     ret = pRegDeleteTreeA(subkey, "");
2278     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2279     ret = RegCloseKey(subkey);
2280     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2281 
2282     ret = RegOpenKeyA(hkey_main, "subkey", &subkey);
2283     ok(ret == ERROR_SUCCESS, "subkey was deleted\n");
2284     ret = RegCloseKey(subkey);
2285     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
2286 
2287     ret = pRegDeleteTreeA(hkey_main, "not-here");
2288     ok(ret == ERROR_FILE_NOT_FOUND,
2289         "Expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
2290 }
2291 
2292 static void test_rw_order(void)
2293 {
2294     HKEY hKey;
2295     DWORD dw = 0;
2296     static const char keyname[] = "test_rw_order";
2297     char value_buf[2];
2298     DWORD values, value_len, value_name_max_len;
2299     LSTATUS ret;
2300 
2301     RegDeleteKeyA(HKEY_CURRENT_USER, keyname);
2302     ret = RegCreateKeyA(HKEY_CURRENT_USER, keyname, &hKey);
2303     if(ret != ERROR_SUCCESS) {
2304         skip("Couldn't create key. Skipping.\n");
2305         return;
2306     }
2307 
2308     ok(!RegSetValueExA(hKey, "A", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)),
2309        "RegSetValueExA for value \"A\" failed\n");
2310     ok(!RegSetValueExA(hKey, "C", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)),
2311        "RegSetValueExA for value \"C\" failed\n");
2312     ok(!RegSetValueExA(hKey, "D", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)),
2313        "RegSetValueExA for value \"D\" failed\n");
2314     ok(!RegSetValueExA(hKey, "B", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)),
2315        "RegSetValueExA for value \"B\" failed\n");
2316 
2317     ok(!RegQueryInfoKeyA(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &values,
2318        &value_name_max_len, NULL, NULL, NULL), "RegQueryInfoKeyA failed\n");
2319     ok(values == 4, "Expected 4 values, got %u\n", values);
2320 
2321     /* Value enumeration preserves RegSetValueEx call order */
2322     value_len = 2;
2323     ok(!RegEnumValueA(hKey, 0, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n");
2324     ok(strcmp(value_buf, "A") == 0, "Expected name \"A\", got %s\n", value_buf);
2325     value_len = 2;
2326     ok(!RegEnumValueA(hKey, 1, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n");
2327     todo_wine ok(strcmp(value_buf, "C") == 0, "Expected name \"C\", got %s\n", value_buf);
2328     value_len = 2;
2329     ok(!RegEnumValueA(hKey, 2, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n");
2330     todo_wine ok(strcmp(value_buf, "D") == 0, "Expected name \"D\", got %s\n", value_buf);
2331     value_len = 2;
2332     ok(!RegEnumValueA(hKey, 3, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n");
2333     todo_wine ok(strcmp(value_buf, "B") == 0, "Expected name \"B\", got %s\n", value_buf);
2334 
2335     ok(!RegDeleteKeyA(HKEY_CURRENT_USER, keyname), "Failed to delete key\n");
2336 }
2337 
2338 static void test_symlinks(void)
2339 {
2340     static const WCHAR targetW[] = {'\\','S','o','f','t','w','a','r','e','\\','W','i','n','e',
2341                                     '\\','T','e','s','t','\\','t','a','r','g','e','t',0};
2342     BYTE buffer[1024];
2343     UNICODE_STRING target_str;
2344     WCHAR *target;
2345     HKEY key, link;
2346     NTSTATUS status;
2347     DWORD target_len, type, len, dw, err;
2348 
2349     if (!pRtlFormatCurrentUserKeyPath || !pNtDeleteKey)
2350     {
2351         win_skip( "Can't perform symlink tests\n" );
2352         return;
2353     }
2354 
2355     pRtlFormatCurrentUserKeyPath( &target_str );
2356 
2357     target_len = target_str.Length + sizeof(targetW);
2358     target = HeapAlloc( GetProcessHeap(), 0, target_len );
2359     memcpy( target, target_str.Buffer, target_str.Length );
2360     memcpy( target + target_str.Length/sizeof(WCHAR), targetW, sizeof(targetW) );
2361 
2362     err = RegCreateKeyExA( hkey_main, "link", 0, NULL, REG_OPTION_CREATE_LINK,
2363                            KEY_ALL_ACCESS, NULL, &link, NULL );
2364     ok( err == ERROR_SUCCESS, "RegCreateKeyEx failed: %u\n", err );
2365 
2366     /* REG_SZ is not allowed */
2367     err = RegSetValueExA( link, "SymbolicLinkValue", 0, REG_SZ, (BYTE *)"foobar", sizeof("foobar") );
2368     ok( err == ERROR_ACCESS_DENIED, "RegSetValueEx wrong error %u\n", err );
2369     err = RegSetValueExA( link, "SymbolicLinkValue", 0, REG_LINK,
2370                           (BYTE *)target, target_len - sizeof(WCHAR) );
2371     ok( err == ERROR_SUCCESS, "RegSetValueEx failed error %u\n", err );
2372     /* other values are not allowed */
2373     err = RegSetValueExA( link, "link", 0, REG_LINK, (BYTE *)target, target_len - sizeof(WCHAR) );
2374     ok( err == ERROR_ACCESS_DENIED, "RegSetValueEx wrong error %u\n", err );
2375 
2376     /* try opening the target through the link */
2377 
2378     err = RegOpenKeyA( hkey_main, "link", &key );
2379     ok( err == ERROR_FILE_NOT_FOUND, "RegOpenKey wrong error %u\n", err );
2380 
2381     err = RegCreateKeyExA( hkey_main, "target", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL );
2382     ok( err == ERROR_SUCCESS, "RegCreateKeyEx failed error %u\n", err );
2383 
2384     dw = 0xbeef;
2385     err = RegSetValueExA( key, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) );
2386     ok( err == ERROR_SUCCESS, "RegSetValueEx failed error %u\n", err );
2387     RegCloseKey( key );
2388 
2389     err = RegOpenKeyA( hkey_main, "link", &key );
2390     ok( err == ERROR_SUCCESS, "RegOpenKey failed error %u\n", err );
2391 
2392     len = sizeof(buffer);
2393     err = RegQueryValueExA( key, "value", NULL, &type, buffer, &len );
2394     ok( err == ERROR_SUCCESS, "RegOpenKey failed error %u\n", err );
2395     ok( len == sizeof(DWORD), "wrong len %u\n", len );
2396 
2397     len = sizeof(buffer);
2398     err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len );
2399     ok( err == ERROR_FILE_NOT_FOUND, "RegQueryValueEx wrong error %u\n", err );
2400 
2401     /* REG_LINK can be created in non-link keys */
2402     err = RegSetValueExA( key, "SymbolicLinkValue", 0, REG_LINK,
2403                           (BYTE *)target, target_len - sizeof(WCHAR) );
2404     ok( err == ERROR_SUCCESS, "RegSetValueEx failed error %u\n", err );
2405     len = sizeof(buffer);
2406     err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len );
2407     ok( err == ERROR_SUCCESS, "RegQueryValueEx failed error %u\n", err );
2408     ok( len == target_len - sizeof(WCHAR), "wrong len %u\n", len );
2409     err = RegDeleteValueA( key, "SymbolicLinkValue" );
2410     ok( err == ERROR_SUCCESS, "RegDeleteValue failed error %u\n", err );
2411 
2412     RegCloseKey( key );
2413 
2414     err = RegCreateKeyExA( hkey_main, "link", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL );
2415     ok( err == ERROR_SUCCESS, "RegCreateKeyEx failed error %u\n", err );
2416 
2417     len = sizeof(buffer);
2418     err = RegQueryValueExA( key, "value", NULL, &type, buffer, &len );
2419     ok( err == ERROR_SUCCESS, "RegQueryValueEx failed error %u\n", err );
2420     ok( len == sizeof(DWORD), "wrong len %u\n", len );
2421 
2422     err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len );
2423     ok( err == ERROR_FILE_NOT_FOUND, "RegQueryValueEx wrong error %u\n", err );
2424     RegCloseKey( key );
2425 
2426     /* now open the symlink itself */
2427 
2428     err = RegOpenKeyExA( hkey_main, "link", REG_OPTION_OPEN_LINK, KEY_ALL_ACCESS, &key );
2429     ok( err == ERROR_SUCCESS, "RegOpenKeyEx failed error %u\n", err );
2430     len = sizeof(buffer);
2431     err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len );
2432     ok( err == ERROR_SUCCESS, "RegQueryValueEx failed error %u\n", err );
2433     ok( len == target_len - sizeof(WCHAR), "wrong len %u\n", len );
2434     RegCloseKey( key );
2435 
2436     err = RegCreateKeyExA( hkey_main, "link", 0, NULL, REG_OPTION_OPEN_LINK,
2437                            KEY_ALL_ACCESS, NULL, &key, NULL );
2438     ok( err == ERROR_SUCCESS, "RegCreateKeyEx failed error %u\n", err );
2439     len = sizeof(buffer);
2440     err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len );
2441     ok( err == ERROR_SUCCESS, "RegQueryValueEx failed error %u\n", err );
2442     ok( len == target_len - sizeof(WCHAR), "wrong len %u\n", len );
2443     RegCloseKey( key );
2444 
2445     err = RegCreateKeyExA( hkey_main, "link", 0, NULL, REG_OPTION_CREATE_LINK,
2446                            KEY_ALL_ACCESS, NULL, &key, NULL );
2447     ok( err == ERROR_ALREADY_EXISTS, "RegCreateKeyEx wrong error %u\n", err );
2448 
2449     err = RegCreateKeyExA( hkey_main, "link", 0, NULL, REG_OPTION_CREATE_LINK | REG_OPTION_OPEN_LINK,
2450                            KEY_ALL_ACCESS, NULL, &key, NULL );
2451     ok( err == ERROR_ALREADY_EXISTS, "RegCreateKeyEx wrong error %u\n", err );
2452 
2453     err = RegDeleteKeyA( hkey_main, "target" );
2454     ok( err == ERROR_SUCCESS, "RegDeleteKey failed error %u\n", err );
2455 
2456     err = RegDeleteKeyA( hkey_main, "link" );
2457     ok( err == ERROR_FILE_NOT_FOUND, "RegDeleteKey wrong error %u\n", err );
2458 
2459     status = pNtDeleteKey( link );
2460     ok( !status, "NtDeleteKey failed: 0x%08x\n", status );
2461     RegCloseKey( link );
2462 
2463     HeapFree( GetProcessHeap(), 0, target );
2464     pRtlFreeUnicodeString( &target_str );
2465 }
2466 
2467 static DWORD get_key_value( HKEY root, const char *name, DWORD flags )
2468 {
2469     HKEY key;
2470     DWORD err, type, dw, len = sizeof(dw);
2471 
2472     err = RegCreateKeyExA( root, name, 0, NULL, 0, flags | KEY_ALL_ACCESS, NULL, &key, NULL );
2473     if (err == ERROR_FILE_NOT_FOUND) return 0;
2474     ok( err == ERROR_SUCCESS, "%08x: RegCreateKeyEx failed: %u\n", flags, err );
2475 
2476     err = RegQueryValueExA( key, "value", NULL, &type, (BYTE *)&dw, &len );
2477     if (err == ERROR_FILE_NOT_FOUND)
2478         dw = 0;
2479     else
2480         ok( err == ERROR_SUCCESS, "%08x: RegQueryValueEx failed: %u\n", flags, err );
2481     RegCloseKey( key );
2482     return dw;
2483 }
2484 
2485 static void _check_key_value( int line, HANDLE root, const char *name, DWORD flags, DWORD expect )
2486 {
2487     DWORD dw = get_key_value( root, name, flags );
2488     ok_(__FILE__,line)( dw == expect, "%08x: wrong value %u/%u\n", flags, dw, expect );
2489 }
2490 #define check_key_value(root,name,flags,expect) _check_key_value( __LINE__, root, name, flags, expect )
2491 
2492 static void test_redirection(void)
2493 {
2494     DWORD err, type, dw, len;
2495     HKEY key, root32, root64, key32, key64, native, op_key;
2496     BOOL is_vista = FALSE;
2497     REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
2498 
2499     if (ptr_size != 64)
2500     {
2501         BOOL is_wow64;
2502         if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 ) || !is_wow64)
2503         {
2504             skip( "Not on Wow64, no redirection\n" );
2505             return;
2506         }
2507     }
2508 
2509     err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
2510                            KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &root64, NULL );
2511     ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2512 
2513     err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
2514                            KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &root32, NULL );
2515     ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2516 
2517     err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", 0, NULL, 0,
2518                            KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &key64, NULL );
2519     ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2520 
2521     err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", 0, NULL, 0,
2522                            KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key32, NULL );
2523     ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2524 
2525     dw = 64;
2526     err = RegSetValueExA( key64, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) );
2527     ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %u\n", err );
2528 
2529     dw = 32;
2530     err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) );
2531     ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %u\n", err );
2532 
2533     dw = 0;
2534     len = sizeof(dw);
2535     err = RegQueryValueExA( key32, "value", NULL, &type, (BYTE *)&dw, &len );
2536     ok( err == ERROR_SUCCESS, "RegQueryValueExA failed: %u\n", err );
2537     ok( dw == 32, "wrong value %u\n", dw );
2538 
2539     dw = 0;
2540     len = sizeof(dw);
2541     err = RegQueryValueExA( key64, "value", NULL, &type, (BYTE *)&dw, &len );
2542     ok( err == ERROR_SUCCESS, "RegQueryValueExA failed: %u\n", err );
2543     ok( dw == 64, "wrong value %u\n", dw );
2544 
2545     err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0,
2546                            KEY_ALL_ACCESS, NULL, &key, NULL );
2547     ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2548 
2549     if (ptr_size == 32)
2550     {
2551         /* the Vista mechanism allows opening Wow6432Node from a 32-bit key too */
2552         /* the new (and simpler) Win7 mechanism doesn't */
2553         if (get_key_value( key, "Wow6432Node\\Wine\\Winetest", 0 ) == 32)
2554         {
2555             trace( "using Vista-style Wow6432Node handling\n" );
2556             is_vista = TRUE;
2557         }
2558         check_key_value( key, "Wine\\Winetest", 0, 32 );
2559         check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
2560         check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2561         check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, is_vista ? 32 : 0 );
2562         check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 0 );
2563         check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, is_vista ? 32 : 0 );
2564     }
2565     else
2566     {
2567         if (get_key_value( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY ) == 64)
2568         {
2569             trace( "using Vista-style Wow6432Node handling\n" );
2570             is_vista = TRUE;
2571         }
2572         check_key_value( key, "Wine\\Winetest", 0, 64 );
2573         check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, 32 );
2574     }
2575     RegCloseKey( key );
2576 
2577     if (ptr_size == 32)
2578     {
2579         err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0,
2580                                KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &key, NULL );
2581         ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2582         dw = get_key_value( key, "Wine\\Winetest", 0 );
2583         ok( dw == 64 || broken(dw == 32) /* xp64 */, "wrong value %u\n", dw );
2584         check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, 64 );
2585         check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2586         check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, 32 );
2587         dw = get_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY );
2588         ok( dw == 32 || broken(dw == 64) /* xp64 */, "wrong value %u\n", dw );
2589         check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2590         RegCloseKey( key );
2591 
2592         err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0,
2593                                KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key, NULL );
2594         ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2595         check_key_value( key, "Wine\\Winetest", 0, 32 );
2596         check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
2597         check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2598         check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, is_vista ? 32 : 0 );
2599         check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 0 );
2600         check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, is_vista ? 32 : 0 );
2601         RegCloseKey( key );
2602     }
2603     else
2604     {
2605         err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0,
2606                                KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &key, NULL );
2607         ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2608         check_key_value( key, "Wine\\Winetest", 0, 64 );
2609         check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, 64 );
2610         dw = get_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY );
2611         todo_wine ok( dw == 32, "wrong value %u\n", dw );
2612         check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, 32 );
2613         RegCloseKey( key );
2614 
2615         err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0,
2616                                KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key, NULL );
2617         ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2618         check_key_value( key, "Wine\\Winetest", 0, 32 );
2619         dw = get_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY );
2620         ok( dw == 32 || broken(dw == 64) /* vista */, "wrong value %u\n", dw );
2621         check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2622         RegCloseKey( key );
2623     }
2624 
2625     check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", 0, ptr_size );
2626     check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine\\Winetest", 0, 32 );
2627     if (ptr_size == 64)
2628     {
2629         /* KEY_WOW64 flags have no effect on 64-bit */
2630         check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", KEY_WOW64_64KEY, 64 );
2631         check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2632         check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
2633         check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2634     }
2635     else
2636     {
2637         check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", KEY_WOW64_64KEY, 64 );
2638         check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2639         check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
2640         check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2641     }
2642 
2643     err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node", 0, NULL, 0,
2644                            KEY_ALL_ACCESS, NULL, &key, NULL );
2645     ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2646     check_key_value( key, "Wine\\Winetest", 0, 32 );
2647     check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
2648     check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2649     RegCloseKey( key );
2650 
2651     if (ptr_size == 32)
2652     {
2653         err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node", 0, NULL, 0,
2654                                KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &key, NULL );
2655         ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2656         dw = get_key_value( key, "Wine\\Winetest", 0 );
2657         ok( dw == (is_vista ? 64 : 32) || broken(dw == 32) /* xp64 */, "wrong value %u\n", dw );
2658         check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
2659         check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2660         RegCloseKey( key );
2661 
2662         err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node", 0, NULL, 0,
2663                                KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key, NULL );
2664         ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2665         check_key_value( key, "Wine\\Winetest", 0, 32 );
2666         check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
2667         check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2668         RegCloseKey( key );
2669     }
2670 
2671     err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine", 0, NULL, 0,
2672                            KEY_ALL_ACCESS, NULL, &key, NULL );
2673     ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2674     check_key_value( key, "Winetest", 0, 32 );
2675     check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
2676     check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
2677     RegCloseKey( key );
2678 
2679     if (ptr_size == 32)
2680     {
2681         err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine", 0, NULL, 0,
2682                                KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &key, NULL );
2683         ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2684         dw = get_key_value( key, "Winetest", 0 );
2685         ok( dw == 32 || (is_vista && dw == 64), "wrong value %u\n", dw );
2686         check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
2687         check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
2688         RegCloseKey( key );
2689 
2690         err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine", 0, NULL, 0,
2691                                KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key, NULL );
2692         ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2693         check_key_value( key, "Winetest", 0, 32 );
2694         check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
2695         check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
2696         RegCloseKey( key );
2697     }
2698 
2699     err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
2700                            KEY_ALL_ACCESS, NULL, &key, NULL );
2701     ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2702     check_key_value( key, "Winetest", 0, ptr_size );
2703     check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : ptr_size );
2704     dw = get_key_value( key, "Winetest", KEY_WOW64_32KEY );
2705     todo_wine_if (ptr_size != 32)
2706         ok( dw == 32, "wrong value %u\n", dw );
2707     RegCloseKey( key );
2708 
2709     if (ptr_size == 32)
2710     {
2711         err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
2712                                KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &key, NULL );
2713         ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2714         dw = get_key_value( key, "Winetest", 0 );
2715         ok( dw == 64 || broken(dw == 32) /* xp64 */, "wrong value %u\n", dw );
2716         check_key_value( key, "Winetest", KEY_WOW64_64KEY, 64 );
2717         dw = get_key_value( key, "Winetest", KEY_WOW64_32KEY );
2718         todo_wine ok( dw == 32, "wrong value %u\n", dw );
2719         RegCloseKey( key );
2720 
2721         err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
2722                                KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key, NULL );
2723         ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err );
2724         check_key_value( key, "Winetest", 0, 32 );
2725         check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
2726         check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
2727         RegCloseKey( key );
2728     }
2729 
2730     if (pRegDeleteKeyExA)
2731     {
2732         err = pRegDeleteKeyExA( key32, "", KEY_WOW64_32KEY, 0 );
2733         ok( err == ERROR_SUCCESS, "RegDeleteKey failed: %u\n", err );
2734         err = pRegDeleteKeyExA( key64, "", KEY_WOW64_64KEY, 0 );
2735         ok( err == ERROR_SUCCESS, "RegDeleteKey failed: %u\n", err );
2736         pRegDeleteKeyExA( key64, "", KEY_WOW64_64KEY, 0 );
2737         pRegDeleteKeyExA( root64, "", KEY_WOW64_64KEY, 0 );
2738     }
2739     else
2740     {
2741         err = RegDeleteKeyA( key32, "" );
2742         ok( err == ERROR_SUCCESS, "RegDeleteKey failed: %u\n", err );
2743         err = RegDeleteKeyA( key64, "" );
2744         ok( err == ERROR_SUCCESS, "RegDeleteKey failed: %u\n", err );
2745         RegDeleteKeyA( key64, "" );
2746         RegDeleteKeyA( root64, "" );
2747     }
2748     RegCloseKey( key32 );
2749     RegCloseKey( key64 );
2750     RegCloseKey( root32 );
2751     RegCloseKey( root64 );
2752 
2753     /* open key in native bit mode */
2754     err = RegOpenKeyExA(HKEY_CLASSES_ROOT, "Interface", 0, KEY_ALL_ACCESS, &native);
2755     ok(err == ERROR_SUCCESS, "got %i\n", err);
2756 
2757     pRegDeleteKeyExA(native, "AWineTest", 0, 0);
2758 
2759     /* write subkey in opposite bit mode */
2760     err = RegOpenKeyExA(HKEY_CLASSES_ROOT, "Interface", 0, KEY_ALL_ACCESS | opposite, &op_key);
2761     ok(err == ERROR_SUCCESS, "got %i\n", err);
2762 
2763     err = RegCreateKeyExA(op_key, "AWineTest", 0, NULL, 0, KEY_ALL_ACCESS | opposite,
2764             NULL, &key, NULL);
2765     ok(err == ERROR_SUCCESS || err == ERROR_ACCESS_DENIED, "got %i\n", err);
2766     if(err != ERROR_SUCCESS){
2767         win_skip("Can't write to registry\n");
2768         RegCloseKey(op_key);
2769         RegCloseKey(native);
2770         return;
2771     }
2772     RegCloseKey(key);
2773 
2774     /* verify subkey is not present in native mode */
2775     err = RegOpenKeyExA(native, "AWineTest", 0, KEY_ALL_ACCESS, &key);
2776     ok(err == ERROR_FILE_NOT_FOUND ||
2777             broken(err == ERROR_SUCCESS), /* before Win7, HKCR is reflected instead of redirected */
2778             "got %i\n", err);
2779 
2780     err = pRegDeleteKeyExA(op_key, "AWineTest", opposite, 0);
2781     ok(err == ERROR_SUCCESS, "got %i\n", err);
2782 
2783     RegCloseKey(op_key);
2784     RegCloseKey(native);
2785 }
2786 
2787 static void test_classesroot(void)
2788 {
2789     HKEY hkey, hklm, hkcr, hkeysub1, hklmsub1, hkcrsub1, hklmsub2, hkcrsub2;
2790     DWORD size = 8;
2791     DWORD type = REG_SZ;
2792     static CHAR buffer[8];
2793     LONG res;
2794 
2795     /* create a key in the user's classes */
2796     if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", &hkey ))
2797     {
2798         delete_key( hkey );
2799         RegCloseKey( hkey );
2800     }
2801     res = RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", 0, NULL, 0,
2802                            KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hkey, NULL );
2803     if (res == ERROR_ACCESS_DENIED)
2804     {
2805         skip("not enough privileges to add a user class\n");
2806         return;
2807     }
2808     ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey);
2809 
2810     /* try to open that key in hkcr */
2811     res = RegOpenKeyExA( HKEY_CLASSES_ROOT, "WineTestCls", 0,
2812                          KEY_QUERY_VALUE|KEY_SET_VALUE, &hkcr );
2813     todo_wine ok(res == ERROR_SUCCESS ||
2814                  broken(res == ERROR_FILE_NOT_FOUND /* WinNT */),
2815                  "test key not found in hkcr: %d\n", res);
2816     if (res)
2817     {
2818         skip("HKCR key merging not supported\n");
2819         delete_key( hkey );
2820         RegCloseKey( hkey );
2821         return;
2822     }
2823 
2824     todo_wine ok(IS_HKCR(hkcr), "hkcr mask not set in %p\n", hkcr);
2825 
2826     /* set a value in user's classes */
2827     res = RegSetValueExA(hkey, "val1", 0, REG_SZ, (const BYTE *)"user", sizeof("user"));
2828     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError());
2829 
2830     /* try to find the value in hkcr */
2831     res = RegQueryValueExA(hkcr, "val1", NULL, &type, (LPBYTE)buffer, &size);
2832     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res);
2833     ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer );
2834 
2835     /* modify the value in hkcr */
2836     res = RegSetValueExA(hkcr, "val1", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr"));
2837     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError());
2838 
2839     /* check if the value is also modified in user's classes */
2840     res = RegQueryValueExA(hkey, "val1", NULL, &type, (LPBYTE)buffer, &size);
2841     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError());
2842     ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer );
2843 
2844     /* set a value in hkcr */
2845     res = RegSetValueExA(hkcr, "val0", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr"));
2846     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError());
2847 
2848     /* try to find the value in user's classes */
2849     res = RegQueryValueExA(hkey, "val0", NULL, &type, (LPBYTE)buffer, &size);
2850     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res);
2851     ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer );
2852 
2853     /* modify the value in user's classes */
2854     res = RegSetValueExA(hkey, "val0", 0, REG_SZ, (const BYTE *)"user", sizeof("user"));
2855     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError());
2856 
2857     /* check if the value is also modified in hkcr */
2858     res = RegQueryValueExA(hkcr, "val0", NULL, &type, (LPBYTE)buffer, &size);
2859     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError());
2860     ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer );
2861 
2862     /* cleanup */
2863     delete_key( hkey );
2864     delete_key( hkcr );
2865     RegCloseKey( hkey );
2866     RegCloseKey( hkcr );
2867 
2868     /* create a key in the hklm classes */
2869     if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Classes\\WineTestCls", &hklm ))
2870     {
2871         delete_key( hklm );
2872         RegCloseKey( hklm );
2873     }
2874     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\WineTestCls", 0, NULL, REG_OPTION_NON_VOLATILE,
2875                            KEY_ALL_ACCESS, NULL, &hklm, NULL );
2876     if (res == ERROR_ACCESS_DENIED)
2877     {
2878         skip("not enough privileges to add a system class\n");
2879         return;
2880     }
2881     ok(!IS_HKCR(hklm), "hkcr mask set in %p\n", hklm);
2882 
2883     /* try to open that key in hkcr */
2884     res = RegOpenKeyExA( HKEY_CLASSES_ROOT, "WineTestCls", 0,
2885                          KEY_QUERY_VALUE|KEY_SET_VALUE, &hkcr );
2886     ok(res == ERROR_SUCCESS,
2887        "test key not found in hkcr: %d\n", res);
2888     ok(IS_HKCR(hkcr), "hkcr mask not set in %p\n", hkcr);
2889     if (res)
2890     {
2891         delete_key( hklm );
2892         RegCloseKey( hklm );
2893         return;
2894     }
2895 
2896     /* set a value in hklm classes */
2897     res = RegSetValueExA(hklm, "val2", 0, REG_SZ, (const BYTE *)"hklm", sizeof("hklm"));
2898     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError());
2899 
2900     /* try to find the value in hkcr */
2901     res = RegQueryValueExA(hkcr, "val2", NULL, &type, (LPBYTE)buffer, &size);
2902     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res);
2903     ok(!strcmp( buffer, "hklm" ), "value set to '%s'\n", buffer );
2904 
2905     /* modify the value in hkcr */
2906     res = RegSetValueExA(hkcr, "val2", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr"));
2907     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError());
2908 
2909     /* check that the value is modified in hklm classes */
2910     res = RegQueryValueExA(hklm, "val2", NULL, &type, (LPBYTE)buffer, &size);
2911     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError());
2912     ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer );
2913 
2914     if (RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", 0, NULL, 0,
2915                          KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hkey, NULL )) return;
2916     ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey);
2917 
2918     /* try to open that key in hkcr */
2919     res = RegOpenKeyExA( HKEY_CLASSES_ROOT, "WineTestCls", 0,
2920                          KEY_QUERY_VALUE|KEY_SET_VALUE, &hkcr );
2921     ok(res == ERROR_SUCCESS,
2922        "test key not found in hkcr: %d\n", res);
2923     ok(IS_HKCR(hkcr), "hkcr mask not set in %p\n", hkcr);
2924 
2925     /* set a value in user's classes */
2926     res = RegSetValueExA(hkey, "val2", 0, REG_SZ, (const BYTE *)"user", sizeof("user"));
2927     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError());
2928 
2929     /* try to find the value in hkcr */
2930     res = RegQueryValueExA(hkcr, "val2", NULL, &type, (LPBYTE)buffer, &size);
2931     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res);
2932     ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer );
2933 
2934     /* modify the value in hklm */
2935     res = RegSetValueExA(hklm, "val2", 0, REG_SZ, (const BYTE *)"hklm", sizeof("hklm"));
2936     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError());
2937 
2938     /* check that the value is not overwritten in hkcr or user's classes */
2939     res = RegQueryValueExA(hkcr, "val2", NULL, &type, (LPBYTE)buffer, &size);
2940     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res);
2941     ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer );
2942     res = RegQueryValueExA(hkey, "val2", NULL, &type, (LPBYTE)buffer, &size);
2943     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError());
2944     ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer );
2945 
2946     /* modify the value in hkcr */
2947     res = RegSetValueExA(hkcr, "val2", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr"));
2948     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError());
2949 
2950     /* check that the value is overwritten in hklm and user's classes */
2951     res = RegQueryValueExA(hkcr, "val2", NULL, &type, (LPBYTE)buffer, &size);
2952     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res);
2953     ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer );
2954     res = RegQueryValueExA(hkey, "val2", NULL, &type, (LPBYTE)buffer, &size);
2955     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError());
2956     ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer );
2957 
2958     /* create a subkey in hklm */
2959     if (RegCreateKeyExA( hklm, "subkey1", 0, NULL, 0,
2960                          KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hklmsub1, NULL )) return;
2961     ok(!IS_HKCR(hklmsub1), "hkcr mask set in %p\n", hklmsub1);
2962     /* try to open that subkey in hkcr */
2963     res = RegOpenKeyExA( hkcr, "subkey1", 0, KEY_QUERY_VALUE|KEY_SET_VALUE, &hkcrsub1 );
2964     ok(res == ERROR_SUCCESS, "test key not found in hkcr: %d\n", res);
2965     ok(IS_HKCR(hkcrsub1), "hkcr mask not set in %p\n", hkcrsub1);
2966 
2967     /* set a value in hklm classes */
2968     res = RegSetValueExA(hklmsub1, "subval1", 0, REG_SZ, (const BYTE *)"hklm", sizeof("hklm"));
2969     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError());
2970 
2971     /* try to find the value in hkcr */
2972     res = RegQueryValueExA(hkcrsub1, "subval1", NULL, &type, (LPBYTE)buffer, &size);
2973     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res);
2974     ok(!strcmp( buffer, "hklm" ), "value set to '%s'\n", buffer );
2975 
2976     /* modify the value in hkcr */
2977     res = RegSetValueExA(hkcrsub1, "subval1", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr"));
2978     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError());
2979 
2980     /* check that the value is modified in hklm classes */
2981     res = RegQueryValueExA(hklmsub1, "subval1", NULL, &type, (LPBYTE)buffer, &size);
2982     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError());
2983     ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer );
2984 
2985     /* create a subkey in user's classes */
2986     if (RegCreateKeyExA( hkey, "subkey1", 0, NULL, 0,
2987                          KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hkeysub1, NULL )) return;
2988     ok(!IS_HKCR(hkeysub1), "hkcr mask set in %p\n", hkeysub1);
2989 
2990     /* set a value in user's classes */
2991     res = RegSetValueExA(hkeysub1, "subval1", 0, REG_SZ, (const BYTE *)"user", sizeof("user"));
2992     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError());
2993 
2994     /* try to find the value in hkcr */
2995     res = RegQueryValueExA(hkcrsub1, "subval1", NULL, &type, (LPBYTE)buffer, &size);
2996     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res);
2997     ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer );
2998 
2999     /* modify the value in hklm */
3000     res = RegSetValueExA(hklmsub1, "subval1", 0, REG_SZ, (const BYTE *)"hklm", sizeof("hklm"));
3001     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError());
3002 
3003     /* check that the value is not overwritten in hkcr or user's classes */
3004     res = RegQueryValueExA(hkcrsub1, "subval1", NULL, &type, (LPBYTE)buffer, &size);
3005     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res);
3006     ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer );
3007     res = RegQueryValueExA(hkeysub1, "subval1", NULL, &type, (LPBYTE)buffer, &size);
3008     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError());
3009     ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer );
3010 
3011     /* modify the value in hkcr */
3012     res = RegSetValueExA(hkcrsub1, "subval1", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr"));
3013     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError());
3014 
3015     /* check that the value is not overwritten in hklm, but in user's classes */
3016     res = RegQueryValueExA(hklmsub1, "subval1", NULL, &type, (LPBYTE)buffer, &size);
3017     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res);
3018     ok(!strcmp( buffer, "hklm" ), "value set to '%s'\n", buffer );
3019     res = RegQueryValueExA(hkeysub1, "subval1", NULL, &type, (LPBYTE)buffer, &size);
3020     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError());
3021     ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer );
3022 
3023     /* new subkey in hkcr */
3024     if (RegCreateKeyExA( hkcr, "subkey2", 0, NULL, 0,
3025                          KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hkcrsub2, NULL )) return;
3026     ok(IS_HKCR(hkcrsub2), "hkcr mask not set in %p\n", hkcrsub2);
3027     res = RegSetValueExA(hkcrsub2, "subval1", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr"));
3028     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError());
3029 
3030     /* try to open that new subkey in user's classes and hklm */
3031     res = RegOpenKeyExA( hkey, "subkey2", 0, KEY_QUERY_VALUE|KEY_SET_VALUE, &hklmsub2 );
3032     ok(res != ERROR_SUCCESS, "test key found in user's classes: %d\n", res);
3033     hklmsub2 = 0;
3034     res = RegOpenKeyExA( hklm, "subkey2", 0, KEY_QUERY_VALUE|KEY_SET_VALUE, &hklmsub2 );
3035     ok(res == ERROR_SUCCESS, "test key not found in hklm: %d\n", res);
3036     ok(!IS_HKCR(hklmsub2), "hkcr mask set in %p\n", hklmsub2);
3037 
3038     /* check that the value is present in hklm */
3039     res = RegQueryValueExA(hklmsub2, "subval1", NULL, &type, (LPBYTE)buffer, &size);
3040     ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res);
3041     ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer );
3042 
3043     /* cleanup */
3044     RegCloseKey( hkeysub1 );
3045     RegCloseKey( hklmsub1 );
3046 
3047     /* delete subkey1 from hkcr (should point at user's classes) */
3048     res = RegDeleteKeyA(hkcr, "subkey1");
3049     ok(res == ERROR_SUCCESS, "RegDeleteKey failed: %d\n", res);
3050 
3051     /* confirm key was removed in hkey but not hklm */
3052     res = RegOpenKeyExA(hkey, "subkey1", 0, KEY_READ, &hkeysub1);
3053     ok(res == ERROR_FILE_NOT_FOUND, "test key found in user's classes: %d\n", res);
3054     res = RegOpenKeyExA(hklm, "subkey1", 0, KEY_READ, &hklmsub1);
3055     ok(res == ERROR_SUCCESS, "test key not found in hklm: %d\n", res);
3056     ok(!IS_HKCR(hklmsub1), "hkcr mask set in %p\n", hklmsub1);
3057 
3058     /* delete subkey1 from hkcr again (which should now point at hklm) */
3059     res = RegDeleteKeyA(hkcr, "subkey1");
3060     ok(res == ERROR_SUCCESS, "RegDeleteKey failed: %d\n", res);
3061 
3062     /* confirm hkey was removed in hklm */
3063     RegCloseKey( hklmsub1 );
3064     res = RegOpenKeyExA(hklm, "subkey1", 0, KEY_READ, &hklmsub1);
3065     ok(res == ERROR_FILE_NOT_FOUND, "test key found in hklm: %d\n", res);
3066 
3067     /* final cleanup */
3068     delete_key( hkey );
3069     delete_key( hklm );
3070     delete_key( hkcr );
3071     delete_key( hkeysub1 );
3072     delete_key( hklmsub1 );
3073     delete_key( hkcrsub1 );
3074     delete_key( hklmsub2 );
3075     delete_key( hkcrsub2 );
3076     RegCloseKey( hkey );
3077     RegCloseKey( hklm );
3078     RegCloseKey( hkcr );
3079     RegCloseKey( hkeysub1 );
3080     RegCloseKey( hklmsub1 );
3081     RegCloseKey( hkcrsub1 );
3082     RegCloseKey( hklmsub2 );
3083     RegCloseKey( hkcrsub2 );
3084 }
3085 
3086 static void test_classesroot_enum(void)
3087 {
3088     HKEY hkcu=0, hklm=0, hkcr=0, hkcusub[2]={0}, hklmsub[2]={0};
3089     DWORD size;
3090     static CHAR buffer[2];
3091     LONG res;
3092 
3093     /* prepare initial testing env in HKCU */
3094     if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", &hkcu ))
3095     {
3096         delete_key( hkcu );
3097         RegCloseKey( hkcu );
3098     }
3099     res = RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", 0, NULL, 0,
3100                             KEY_SET_VALUE|KEY_ENUMERATE_SUB_KEYS, NULL, &hkcu, NULL );
3101 
3102     if (res != ERROR_SUCCESS)
3103     {
3104         skip("failed to add a user class\n");
3105         return;
3106     }
3107 
3108     res = RegOpenKeyA( HKEY_CLASSES_ROOT, "WineTestCls", &hkcr );
3109     todo_wine ok(res == ERROR_SUCCESS ||
3110                  broken(res == ERROR_FILE_NOT_FOUND /* WinNT */),
3111                  "test key not found in hkcr: %d\n", res);
3112     if (res)
3113     {
3114         skip("HKCR key merging not supported\n");
3115         delete_key( hkcu );
3116         RegCloseKey( hkcu );
3117         return;
3118     }
3119 
3120     res = RegSetValueExA( hkcu, "X", 0, REG_SZ, (const BYTE *) "AA", 3 );
3121     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", res);
3122     res = RegSetValueExA( hkcu, "Y", 0, REG_SZ, (const BYTE *) "B", 2 );
3123     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", res);
3124     res = RegCreateKeyA( hkcu, "A", &hkcusub[0] );
3125     ok(res == ERROR_SUCCESS, "RegCreateKeyA failed: %d\n", res);
3126     res = RegCreateKeyA( hkcu, "B", &hkcusub[1] );
3127     ok(res == ERROR_SUCCESS, "RegCreateKeyA failed: %d\n", res);
3128 
3129     /* test on values in HKCU */
3130     size = sizeof(buffer);
3131     res = RegEnumValueA( hkcr, 0, buffer, &size, NULL, NULL, NULL, NULL );
3132     ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res );
3133     ok(!strcmp( buffer, "X" ), "expected 'X', got '%s'\n", buffer);
3134     size = sizeof(buffer);
3135     res = RegEnumValueA( hkcr, 1, buffer, &size, NULL, NULL, NULL, NULL );
3136     ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res );
3137     ok(!strcmp( buffer, "Y" ), "expected 'Y', got '%s'\n", buffer);
3138     size = sizeof(buffer);
3139     res = RegEnumValueA( hkcr, 2, buffer, &size, NULL, NULL, NULL, NULL );
3140     ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res );
3141 
3142     res = RegEnumKeyA( hkcr, 0, buffer, size );
3143     ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res );
3144     ok(!strcmp( buffer, "A" ), "expected 'A', got '%s'\n", buffer);
3145     res = RegEnumKeyA( hkcr, 1, buffer, size );
3146     ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res );
3147     ok(!strcmp( buffer, "B" ), "expected 'B', got '%s'\n", buffer);
3148     res = RegEnumKeyA( hkcr, 2, buffer, size );
3149     ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res );
3150 
3151     /* prepare test env in HKLM */
3152     if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Classes\\WineTestCls", &hklm ))
3153     {
3154         delete_key( hklm );
3155         RegCloseKey( hklm );
3156     }
3157 
3158     res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\WineTestCls", 0, NULL, 0,
3159                             KEY_SET_VALUE|KEY_ENUMERATE_SUB_KEYS, NULL, &hklm, NULL );
3160 
3161     if (res == ERROR_ACCESS_DENIED)
3162     {
3163         RegCloseKey( hkcusub[0] );
3164         RegCloseKey( hkcusub[1] );
3165         delete_key( hkcu );
3166         RegCloseKey( hkcu );
3167         RegCloseKey( hkcr );
3168         skip("not enough privileges to add a system class\n");
3169         return;
3170     }
3171 
3172     res = RegSetValueExA( hklm, "X", 0, REG_SZ, (const BYTE *) "AB", 3 );
3173     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", res);
3174     res = RegSetValueExA( hklm, "Z", 0, REG_SZ, (const BYTE *) "C", 2 );
3175     ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", res);
3176     res = RegCreateKeyA( hklm, "A", &hklmsub[0] );
3177     ok(res == ERROR_SUCCESS, "RegCreateKeyA failed: %d\n", res);
3178     res = RegCreateKeyA( hklm, "C", &hklmsub[1] );
3179     ok(res == ERROR_SUCCESS, "RegCreateKeyA failed: %d\n", res);
3180 
3181     /* test on values/keys in both HKCU and HKLM */
3182     size = sizeof(buffer);
3183     res = RegEnumValueA( hkcr, 0, buffer, &size, NULL, NULL, NULL, NULL );
3184     ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res );
3185     ok(!strcmp( buffer, "X" ), "expected 'X', got '%s'\n", buffer);
3186     size = sizeof(buffer);
3187     res = RegEnumValueA( hkcr, 1, buffer, &size, NULL, NULL, NULL, NULL );
3188     ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res );
3189     ok(!strcmp( buffer, "Y" ), "expected 'Y', got '%s'\n", buffer);
3190     size = sizeof(buffer);
3191     res = RegEnumValueA( hkcr, 2, buffer, &size, NULL, NULL, NULL, NULL );
3192     ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res );
3193     ok(!strcmp( buffer, "Z" ), "expected 'Z', got '%s'\n", buffer);
3194     size = sizeof(buffer);
3195     res = RegEnumValueA( hkcr, 3, buffer, &size, NULL, NULL, NULL, NULL );
3196     ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res );
3197 
3198     res = RegEnumKeyA( hkcr, 0, buffer, size );
3199     ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res );
3200     ok(!strcmp( buffer, "A" ), "expected 'A', got '%s'\n", buffer);
3201     res = RegEnumKeyA( hkcr, 1, buffer, size );
3202     ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res );
3203     ok(!strcmp( buffer, "B" ), "expected 'B', got '%s'\n", buffer);
3204     res = RegEnumKeyA( hkcr, 2, buffer, size );
3205     ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res );
3206     ok(!strcmp( buffer, "C" ), "expected 'C', got '%s'\n", buffer);
3207     res = RegEnumKeyA( hkcr, 3, buffer, size );
3208     ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res );
3209 
3210     /* delete values/keys from HKCU to test only on HKLM */
3211     RegCloseKey( hkcusub[0] );
3212     RegCloseKey( hkcusub[1] );
3213     delete_key( hkcu );
3214     RegCloseKey( hkcu );
3215 
3216     size = sizeof(buffer);
3217     res = RegEnumValueA( hkcr, 0, buffer, &size, NULL, NULL, NULL, NULL );
3218     ok(res == ERROR_KEY_DELETED ||
3219        res == ERROR_NO_SYSTEM_RESOURCES, /* Windows XP */
3220        "expected ERROR_KEY_DELETED, got %d\n", res);
3221     size = sizeof(buffer);
3222     res = RegEnumKeyA( hkcr, 0, buffer, size );
3223     ok(res == ERROR_KEY_DELETED ||
3224        res == ERROR_NO_SYSTEM_RESOURCES, /* Windows XP */
3225        "expected ERROR_KEY_DELETED, got %d\n", res);
3226 
3227     /* reopen HKCR handle */
3228     RegCloseKey( hkcr );
3229     res = RegOpenKeyA( HKEY_CLASSES_ROOT, "WineTestCls", &hkcr );
3230     ok(res == ERROR_SUCCESS, "test key not found in hkcr: %d\n", res);
3231     if (res) goto cleanup;
3232 
3233     /* test on values/keys in HKLM */
3234     size = sizeof(buffer);
3235     res = RegEnumValueA( hkcr, 0, buffer, &size, NULL, NULL, NULL, NULL );
3236     ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res );
3237     ok(!strcmp( buffer, "X" ), "expected 'X', got '%s'\n", buffer);
3238     size = sizeof(buffer);
3239     res = RegEnumValueA( hkcr, 1, buffer, &size, NULL, NULL, NULL, NULL );
3240     ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res );
3241     ok(!strcmp( buffer, "Z" ), "expected 'Z', got '%s'\n", buffer);
3242     size = sizeof(buffer);
3243     res = RegEnumValueA( hkcr, 2, buffer, &size, NULL, NULL, NULL, NULL );
3244     ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res );
3245 
3246     res = RegEnumKeyA( hkcr, 0, buffer, size );
3247     ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res );
3248     ok(!strcmp( buffer, "A" ), "expected 'A', got '%s'\n", buffer);
3249     res = RegEnumKeyA( hkcr, 1, buffer, size );
3250     ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res );
3251     ok(!strcmp( buffer, "C" ), "expected 'C', got '%s'\n", buffer);
3252     res = RegEnumKeyA( hkcr, 2, buffer, size );
3253     ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res );
3254 
3255 cleanup:
3256     RegCloseKey( hklmsub[0] );
3257     RegCloseKey( hklmsub[1] );
3258     delete_key( hklm );
3259     RegCloseKey( hklm );
3260     RegCloseKey( hkcr );
3261 }
3262 
3263 static void test_classesroot_mask(void)
3264 {
3265     HKEY hkey;
3266     LSTATUS res;
3267 
3268     res = RegOpenKeyA( HKEY_CLASSES_ROOT, "CLSID", &hkey );
3269     ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %d\n", res);
3270     todo_wine ok(IS_HKCR(hkey) || broken(!IS_HKCR(hkey)) /* WinNT */,
3271                  "hkcr mask not set in %p\n", hkey);
3272     RegCloseKey( hkey );
3273 
3274     res = RegOpenKeyA( HKEY_CURRENT_USER, "Software", &hkey );
3275     ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %d\n", res);
3276     ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey);
3277     RegCloseKey( hkey );
3278 
3279     res = RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software", &hkey );
3280     ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %d\n", res);
3281     ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey);
3282     RegCloseKey( hkey );
3283 
3284     res = RegOpenKeyA( HKEY_USERS, ".Default", &hkey );
3285     ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %d\n", res);
3286     ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey);
3287     RegCloseKey( hkey );
3288 
3289     res = RegOpenKeyA( HKEY_CURRENT_CONFIG, "Software", &hkey );
3290     ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %d\n", res);
3291     ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey);
3292     RegCloseKey( hkey );
3293 }
3294 
3295 static void test_perflib_key(void)
3296 {
3297     DWORD size;
3298     LONG ret;
3299     HKEY key;
3300 
3301     ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\009", &key);
3302     ok(ret == ERROR_SUCCESS, "RegOpenKeyA failed with error %u\n", ret);
3303 
3304     ret = RegQueryValueExA(key, "Counter", NULL, NULL, NULL, &size);
3305     if (ret != ERROR_SUCCESS)
3306     {
3307         skip("Perflib\\009\\Counter does not exist, skipping perflib test\n");
3308         goto done;
3309     }
3310     ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed with error %u\n", ret);
3311 
3312     /* Windows only compares the first few characters of the value name.
3313      * On Windows XP / 2003, it is sufficient to use "Cou", newer versions
3314      * require a longer substring. */
3315 
3316     ret = RegQueryValueExA(key, "Counters", NULL, NULL, NULL, &size);
3317     ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed with error %u\n", ret);
3318     ret = RegQueryValueExA(key, "Counter2", NULL, NULL, NULL, &size);
3319     todo_wine ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed with error %u\n", ret);
3320     ret = RegQueryValueExA(key, "CounterWine", NULL, NULL, NULL, &size);
3321     todo_wine ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed with error %u\n", ret);
3322 
3323 done:
3324     RegCloseKey(key);
3325 }
3326 
3327 static void test_deleted_key(void)
3328 {
3329     HKEY hkey, hkey2;
3330     char value[20];
3331     DWORD val_count, type;
3332     LONG res;
3333 
3334     /* Open the test key, then delete it while it's open */
3335     RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey );
3336 
3337     delete_key( hkey_main );
3338 
3339     val_count = sizeof(value);
3340     type = 0;
3341     res = RegEnumValueA( hkey, 0, value, &val_count, NULL, &type, 0, 0 );
3342     ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %i\n", res);
3343 
3344     res = RegEnumKeyA( hkey, 0, value, sizeof(value) );
3345     ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %i\n", res);
3346 
3347     val_count = sizeof(value);
3348     type = 0;
3349     res = RegQueryValueExA( hkey, "test", NULL, &type, (BYTE *)value, &val_count );
3350     ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %i\n", res);
3351 
3352     res = RegSetValueExA( hkey, "test", 0, REG_SZ, (const BYTE*)"value", 6);
3353     ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %i\n", res);
3354 
3355     res = RegOpenKeyA( hkey, "test", &hkey2 );
3356     ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %i\n", res);
3357     if (res == 0)
3358         RegCloseKey( hkey2 );
3359 
3360     res = RegCreateKeyA( hkey, "test", &hkey2 );
3361     ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %i\n", res);
3362     if (res == 0)
3363         RegCloseKey( hkey2 );
3364 
3365     res = RegFlushKey( hkey );
3366     ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %i\n", res);
3367 
3368     RegCloseKey( hkey );
3369 
3370     setup_main_key();
3371 }
3372 
3373 static void test_delete_value(void)
3374 {
3375     LONG res;
3376     char longname[401];
3377 
3378     res = RegSetValueExA( hkey_main, "test", 0, REG_SZ, (const BYTE*)"value", 6 );
3379     ok(res == ERROR_SUCCESS, "expect ERROR_SUCCESS, got %i\n", res);
3380 
3381     res = RegQueryValueExA( hkey_main, "test", NULL, NULL, NULL, NULL);
3382     ok(res == ERROR_SUCCESS, "expect ERROR_SUCCESS, got %i\n", res);
3383 
3384     res = RegDeleteValueA( hkey_main, "test" );
3385     ok(res == ERROR_SUCCESS, "expect ERROR_SUCCESS, got %i\n", res);
3386 
3387     res = RegQueryValueExA( hkey_main, "test", NULL, NULL, NULL, NULL);
3388     ok(res == ERROR_FILE_NOT_FOUND, "expect ERROR_FILE_NOT_FOUND, got %i\n", res);
3389 
3390     res = RegDeleteValueA( hkey_main, "test" );
3391     ok(res == ERROR_FILE_NOT_FOUND, "expect ERROR_FILE_NOT_FOUND, got %i\n", res);
3392 
3393     memset(longname, 'a', 400);
3394     longname[400] = 0;
3395     res = RegDeleteValueA( hkey_main, longname );
3396     ok(res == ERROR_FILE_NOT_FOUND || broken(res == ERROR_MORE_DATA), /* nt4, win2k */
3397        "expect ERROR_FILE_NOT_FOUND, got %i\n", res);
3398 
3399     /* Default registry value */
3400     res = RegSetValueExA(hkey_main, "", 0, REG_SZ, (const BYTE *)"value", 6);
3401     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res);
3402 
3403     res = RegQueryValueExA(hkey_main, "", NULL, NULL, NULL, NULL);
3404     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res);
3405 
3406     res = RegDeleteValueA(hkey_main, "" );
3407     ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res);
3408 
3409     res = RegQueryValueExA(hkey_main, "", NULL, NULL, NULL, NULL);
3410     ok(res == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3411 }
3412 
3413 static void test_delete_key_value(void)
3414 {
3415     HKEY subkey;
3416     LONG ret;
3417 
3418     if (!pRegDeleteKeyValueA)
3419     {
3420         win_skip("RegDeleteKeyValue is not available.\n");
3421         return;
3422     }
3423 
3424     ret = pRegDeleteKeyValueA(NULL, NULL, NULL);
3425     ok(ret == ERROR_INVALID_HANDLE, "got %d\n", ret);
3426 
3427     ret = pRegDeleteKeyValueA(hkey_main, NULL, NULL);
3428     ok(ret == ERROR_FILE_NOT_FOUND, "got %d\n", ret);
3429 
3430     ret = RegSetValueExA(hkey_main, "test", 0, REG_SZ, (const BYTE*)"value", 6);
3431     ok(ret == ERROR_SUCCESS, "got %d\n", ret);
3432 
3433     ret = RegQueryValueExA(hkey_main, "test", NULL, NULL, NULL, NULL);
3434     ok(ret == ERROR_SUCCESS, "got %d\n", ret);
3435 
3436     /* NULL subkey name means delete from open key */
3437     ret = pRegDeleteKeyValueA(hkey_main, NULL, "test");
3438     ok(ret == ERROR_SUCCESS, "got %d\n", ret);
3439 
3440     ret = RegQueryValueExA(hkey_main, "test", NULL, NULL, NULL, NULL);
3441     ok(ret == ERROR_FILE_NOT_FOUND, "got %d\n", ret);
3442 
3443     /* now with real subkey */
3444     ret = RegCreateKeyExA(hkey_main, "Subkey1", 0, NULL, 0, KEY_WRITE|KEY_READ, NULL, &subkey, NULL);
3445     ok(!ret, "failed with error %d\n", ret);
3446 
3447     ret = RegSetValueExA(subkey, "test", 0, REG_SZ, (const BYTE*)"value", 6);
3448     ok(ret == ERROR_SUCCESS, "got %d\n", ret);
3449 
3450     ret = RegQueryValueExA(subkey, "test", NULL, NULL, NULL, NULL);
3451     ok(ret == ERROR_SUCCESS, "got %d\n", ret);
3452 
3453     ret = pRegDeleteKeyValueA(hkey_main, "Subkey1", "test");
3454     ok(ret == ERROR_SUCCESS, "got %d\n", ret);
3455 
3456     ret = RegQueryValueExA(subkey, "test", NULL, NULL, NULL, NULL);
3457     ok(ret == ERROR_FILE_NOT_FOUND, "got %d\n", ret);
3458 
3459     /* Default registry value */
3460     ret = RegSetValueExA(subkey, "", 0, REG_SZ, (const BYTE *)"value", 6);
3461     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
3462 
3463     ret = RegQueryValueExA(subkey, "", NULL, NULL, NULL, NULL);
3464     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
3465 
3466     ret = pRegDeleteKeyValueA(hkey_main, "Subkey1", "" );
3467     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
3468 
3469     ret = RegQueryValueExA(subkey, "", NULL, NULL, NULL, NULL);
3470     ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
3471 
3472     RegDeleteKeyA(subkey, "");
3473     RegCloseKey(subkey);
3474 }
3475 
3476 static void test_RegOpenCurrentUser(void)
3477 {
3478     HKEY key;
3479     LONG ret;
3480 
3481     key = HKEY_CURRENT_USER;
3482     ret = RegOpenCurrentUser(KEY_READ, &key);
3483     ok(!ret, "got %d, error %d\n", ret, GetLastError());
3484     ok(key != HKEY_CURRENT_USER, "got %p\n", key);
3485     RegCloseKey(key);
3486 }
3487 
3488 static void test_RegNotifyChangeKeyValue(void)
3489 {
3490     HKEY key, subkey;
3491     HANDLE event;
3492     DWORD dwret;
3493     LONG ret;
3494 
3495     event = CreateEventW(NULL, FALSE, TRUE, NULL);
3496     ok(event != NULL, "CreateEvent failed, error %u\n", GetLastError());
3497     ret = RegCreateKeyA(hkey_main, "TestKey", &key);
3498     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
3499 
3500     ret = RegNotifyChangeKeyValue(key, TRUE, REG_NOTIFY_CHANGE_NAME, event, TRUE);
3501     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
3502     dwret = WaitForSingleObject(event, 0);
3503     ok(dwret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", dwret);
3504 
3505     ret = RegCreateKeyA(key, "SubKey", &subkey);
3506     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
3507     dwret = WaitForSingleObject(event, 0);
3508     ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", dwret);
3509 
3510     RegDeleteKeyA(key, "");
3511     RegCloseKey(key);
3512     CloseHandle(event);
3513 }
3514 
3515 static const char *dbgstr_longlong(ULONGLONG ll)
3516 {
3517     static char buf[16][64];
3518     static int idx;
3519 
3520     idx &= 0x0f;
3521 
3522     if (sizeof(ll) > sizeof(unsigned long) && ll >> 32)
3523         sprintf(buf[idx], "0x%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll);
3524     else
3525         sprintf(buf[idx], "0x%08lx", (unsigned long)ll);
3526 
3527     return buf[idx++];
3528 }
3529 
3530 #define cmp_li(a, b, c) cmp_li_real(a, b, c, __LINE__)
3531 static void cmp_li_real(LARGE_INTEGER *l1, LARGE_INTEGER *l2, LONGLONG slack, int line)
3532 {
3533     LONGLONG diff = l2->QuadPart - l1->QuadPart;
3534     if (diff < 0) diff = -diff;
3535     ok_(__FILE__, line)(diff <= slack, "values don't match: %s/%s\n",
3536         dbgstr_longlong(l1->QuadPart), dbgstr_longlong(l2->QuadPart));
3537 }
3538 
3539 static void test_RegQueryValueExPerformanceData(void)
3540 {
3541     static const WCHAR globalW[] = { 'G','l','o','b','a','l',0 };
3542     static const WCHAR dummyW[5] = { 'd','u','m','m','y' };
3543     static const char * const names[] = { NULL, "", "Global", "2" "invalid counter name" };
3544     DWORD cbData, len, i, type;
3545     BYTE *value;
3546     DWORD dwret;
3547     LONG limit = 6;
3548     PERF_DATA_BLOCK *pdb;
3549     HKEY hkey;
3550     BYTE buf[256 + sizeof(PERF_DATA_BLOCK)];
3551 
3552     /* Test with data == NULL */
3553     dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, NULL, &cbData );
3554     ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret );
3555 
3556     dwret = RegQueryValueExW( HKEY_PERFORMANCE_DATA, globalW, NULL, NULL, NULL, &cbData );
3557     ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret );
3558 
3559     /* Test ERROR_MORE_DATA, start with small buffer */
3560     len = 10;
3561     value = HeapAlloc(GetProcessHeap(), 0, len);
3562     cbData = len;
3563     type = 0xdeadbeef;
3564     dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, &type, value, &cbData );
3565     ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret );
3566     ok(type == REG_BINARY, "got %u\n", type);
3567     while( dwret == ERROR_MORE_DATA && limit)
3568     {
3569         len = len * 10;
3570         value = HeapReAlloc( GetProcessHeap(), 0, value, len );
3571         cbData = len;
3572         type = 0xdeadbeef;
3573         dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, &type, value, &cbData );
3574         limit--;
3575     }
3576     ok(limit > 0, "too many times ERROR_MORE_DATA returned\n");
3577 
3578     ok(dwret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", dwret);
3579     ok(type == REG_BINARY, "got %u\n", type);
3580 
3581     /* Check returned data */
3582     if (dwret == ERROR_SUCCESS)
3583     {
3584         ok(len >= sizeof(PERF_DATA_BLOCK), "got size %d\n", len);
3585         if (len >= sizeof(PERF_DATA_BLOCK)) {
3586             pdb = (PERF_DATA_BLOCK*) value;
3587             ok(pdb->Signature[0] == 'P', "expected Signature[0] = 'P', got 0x%x\n", pdb->Signature[0]);
3588             ok(pdb->Signature[1] == 'E', "expected Signature[1] = 'E', got 0x%x\n", pdb->Signature[1]);
3589             ok(pdb->Signature[2] == 'R', "expected Signature[2] = 'R', got 0x%x\n", pdb->Signature[2]);
3590             ok(pdb->Signature[3] == 'F', "expected Signature[3] = 'F', got 0x%x\n", pdb->Signature[3]);
3591             /* TODO: check other field */
3592         }
3593     }
3594 
3595     HeapFree(GetProcessHeap(), 0, value);
3596 
3597     for (i = 0; i < sizeof(names)/sizeof(names[0]); i++)
3598     {
3599         cbData = 0xdeadbeef;
3600         dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, names[i], NULL, NULL, NULL, &cbData);
3601         ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
3602         ok(cbData == 0, "got %u\n", cbData);
3603 
3604         cbData = 0;
3605         dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, names[i], NULL, NULL, NULL, &cbData);
3606         ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
3607         ok(cbData == 0, "got %u\n", cbData);
3608 
3609         cbData = 0xdeadbeef;
3610         dwret = RegQueryValueExA(HKEY_PERFORMANCE_TEXT, names[i], NULL, NULL, NULL, &cbData);
3611 todo_wine
3612         ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
3613         ok(cbData == 0, "got %u\n", cbData);
3614 
3615         cbData = 0;
3616         dwret = RegQueryValueExA(HKEY_PERFORMANCE_TEXT, names[i], NULL, NULL, NULL, &cbData);
3617 todo_wine
3618         ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
3619         ok(cbData == 0, "got %u\n", cbData);
3620 
3621         cbData = 0xdeadbeef;
3622         dwret = RegQueryValueExA(HKEY_PERFORMANCE_NLSTEXT, names[i], NULL, NULL, NULL, &cbData);
3623 todo_wine
3624         ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
3625         ok(cbData == 0, "got %u\n", cbData);
3626 
3627         cbData = 0;
3628         dwret = RegQueryValueExA(HKEY_PERFORMANCE_NLSTEXT, names[i], NULL, NULL, NULL, &cbData);
3629 todo_wine
3630         ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
3631         ok(cbData == 0, "got %u\n", cbData);
3632     }
3633 
3634     memset(buf, 0x77, sizeof(buf));
3635     type = 0xdeadbeef;
3636     cbData = sizeof(buf);
3637     dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "invalid counter name", NULL, &type, buf, &cbData);
3638     ok(dwret == ERROR_SUCCESS, "got %u\n", dwret);
3639     ok(type == REG_BINARY, "got %u\n", type);
3640     if (dwret == ERROR_SUCCESS)
3641     {
3642         SYSTEMTIME st;
3643         WCHAR sysname[MAX_COMPUTERNAME_LENGTH + 1];
3644         DWORD sysname_len;
3645         LARGE_INTEGER counter, freq, ftime;
3646 
3647         GetSystemTime(&st);
3648         GetSystemTimeAsFileTime((FILETIME *)&ftime);
3649         QueryPerformanceCounter(&counter);
3650         QueryPerformanceFrequency(&freq);
3651 
3652         sysname_len = MAX_COMPUTERNAME_LENGTH + 1;
3653         GetComputerNameW(sysname, &sysname_len);
3654 
3655         pdb = (PERF_DATA_BLOCK *)buf;
3656         ok(pdb->Signature[0] == 'P', "got '%c'\n", pdb->Signature[0]);
3657         ok(pdb->Signature[1] == 'E', "got '%c'\n", pdb->Signature[1]);
3658         ok(pdb->Signature[2] == 'R', "got '%c'\n", pdb->Signature[2]);
3659         ok(pdb->Signature[3] == 'F', "got '%c'\n", pdb->Signature[3]);
3660 
3661         ok(pdb->LittleEndian == 1, "got %u\n", pdb->LittleEndian);
3662         ok(pdb->Version == 1, "got %u\n", pdb->Version);
3663         ok(pdb->Revision == 1, "got %u\n", pdb->Revision);
3664         len = (sizeof(*pdb) + pdb->SystemNameLength + 7) & ~7;
3665         ok(pdb->TotalByteLength == len, "got %u vs %u\n", pdb->TotalByteLength, len);
3666         ok(pdb->HeaderLength == pdb->TotalByteLength, "got %u\n", pdb->HeaderLength);
3667         ok(pdb->NumObjectTypes == 0, "got %u\n", pdb->NumObjectTypes);
3668 todo_wine
3669         ok(pdb->DefaultObject != 0, "got %u\n", pdb->DefaultObject);
3670         ok(pdb->SystemTime.wYear == st.wYear, "got %u\n", pdb->SystemTime.wYear);
3671         ok(pdb->SystemTime.wMonth == st.wMonth, "got %u\n", pdb->SystemTime.wMonth);
3672         ok(pdb->SystemTime.wDayOfWeek == st.wDayOfWeek, "got %u\n", pdb->SystemTime.wDayOfWeek);
3673         ok(pdb->SystemTime.wDay == st.wDay, "got %u\n", pdb->SystemTime.wDay);
3674         if (U(pdb->PerfTime).LowPart != 0x77777777) /* TestBot is broken */
3675             cmp_li(&pdb->PerfTime, &counter, freq.QuadPart);
3676         if (U(pdb->PerfFreq).LowPart != 0x77777777) /* TestBot is broken */
3677             cmp_li(&pdb->PerfFreq, &freq, 0);
3678         cmp_li(&pdb->PerfTime100nSec, &ftime, 200000); /* TestBot needs huge slack value */
3679         ok(pdb->SystemNameLength == (sysname_len + 1) * sizeof(WCHAR), "expected %u, got %u\n",
3680            (sysname_len + 1) * sizeof(WCHAR), pdb->SystemNameLength);
3681         ok(pdb->SystemNameOffset == sizeof(*pdb), "got %u\n", pdb->SystemNameOffset);
3682         ok(!lstrcmpW(sysname, (LPCWSTR)(pdb + 1)), "%s != %s\n",
3683            wine_dbgstr_w(sysname), wine_dbgstr_w((LPCWSTR)(pdb + 1)));
3684 
3685         len = pdb->TotalByteLength - (sizeof(*pdb) + pdb->SystemNameLength);
3686         if (len)
3687         {
3688             BYTE remainder[8], *p;
3689 
3690             memset(remainder, 0x77, sizeof(remainder));
3691             p = buf + sizeof(*pdb) + pdb->SystemNameLength;
3692             ok(!memcmp(p, remainder, len), "remainder: %02x,%02x...\n", p[0], p[1]);
3693         }
3694     }
3695 
3696     dwret = RegOpenKeyA(HKEY_PERFORMANCE_DATA, NULL, &hkey);
3697 todo_wine
3698     ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
3699 
3700     dwret = RegOpenKeyA(HKEY_PERFORMANCE_DATA, "Global", &hkey);
3701 todo_wine
3702     ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
3703 
3704     dwret = RegOpenKeyExA(HKEY_PERFORMANCE_DATA, "Global", 0, KEY_READ, &hkey);
3705 todo_wine
3706     ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
3707 
3708     dwret = RegQueryValueA(HKEY_PERFORMANCE_DATA, "Global", NULL, (LONG *)&cbData);
3709 todo_wine
3710     ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
3711 
3712     dwret = RegSetValueA(HKEY_PERFORMANCE_DATA, "Global", REG_SZ, "dummy", 4);
3713 todo_wine
3714     ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
3715 
3716     dwret = RegSetValueExA(HKEY_PERFORMANCE_DATA, "Global", 0, REG_SZ, (const BYTE *)"dummy", 40);
3717 todo_wine
3718     ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
3719 
3720     cbData = sizeof(buf);
3721     dwret = RegEnumKeyA(HKEY_PERFORMANCE_DATA, 0, (LPSTR)buf, cbData);
3722 todo_wine
3723     ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
3724 
3725     cbData = sizeof(buf);
3726     dwret = RegEnumValueA(HKEY_PERFORMANCE_DATA, 0, (LPSTR)buf, &cbData, NULL, NULL, NULL, NULL);
3727 todo_wine
3728     ok(dwret == ERROR_MORE_DATA, "got %u\n", dwret);
3729 todo_wine
3730     ok(cbData == sizeof(buf), "got %u\n", cbData);
3731 
3732     dwret = RegEnumValueA(HKEY_PERFORMANCE_DATA, 0, NULL, &cbData, NULL, NULL, NULL, NULL);
3733     ok(dwret == ERROR_INVALID_PARAMETER, "got %u\n", dwret);
3734 
3735     if (pRegSetKeyValueW)
3736     {
3737         dwret = pRegSetKeyValueW(HKEY_PERFORMANCE_DATA, NULL, globalW, REG_SZ, dummyW, sizeof(dummyW));
3738 todo_wine
3739         ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
3740     }
3741 
3742     dwret = RegCloseKey(HKEY_PERFORMANCE_DATA);
3743     ok(dwret == ERROR_SUCCESS, "got %u\n", dwret);
3744 }
3745 
3746 START_TEST(registry)
3747 {
3748     /* Load pointers for functions that are not available in all Windows versions */
3749     InitFunctionPtrs();
3750 
3751     setup_main_key();
3752     check_user_privs();
3753     test_set_value();
3754     create_test_entries();
3755     test_enum_value();
3756     test_query_value_ex();
3757     test_get_value();
3758     test_reg_open_key();
3759     test_reg_create_key();
3760     test_reg_close_key();
3761     test_reg_delete_key();
3762     test_reg_query_value();
3763     test_reg_query_info();
3764     test_string_termination();
3765     test_symlinks();
3766     test_redirection();
3767     test_classesroot();
3768     test_classesroot_enum();
3769     test_classesroot_mask();
3770     test_perflib_key();
3771     test_reg_save_key();
3772     test_reg_load_key();
3773     test_reg_unload_key();
3774     test_reg_copy_tree();
3775     test_reg_delete_tree();
3776     test_rw_order();
3777     test_deleted_key();
3778     test_delete_value();
3779     test_delete_key_value();
3780     test_RegOpenCurrentUser();
3781     test_RegNotifyChangeKeyValue();
3782     test_RegQueryValueExPerformanceData();
3783 
3784     /* cleanup */
3785     delete_key( hkey_main );
3786 
3787     test_regconnectregistry();
3788 }
3789