rsaenh: Fix the accepted RC2 key length, based on a test case by Dan Kegel.
[wine] / dlls / advapi32 / tests / registry.c
1 /*
2  * Unit tests for registry functions
3  *
4  * Copyright (c) 2002 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include "wine/test.h"
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winreg.h"
28 #include "winsvc.h"
29 #include "winerror.h"
30
31 static HKEY hkey_main;
32 static DWORD GLE;
33
34 static const char * sTestpath1 = "%LONGSYSTEMVAR%\\subdir1";
35 static const char * sTestpath2 = "%FOO%\\subdir1";
36
37 static HMODULE hadvapi32;
38 static DWORD (WINAPI *pRegGetValueA)(HKEY,LPCSTR,LPCSTR,DWORD,LPDWORD,PVOID,LPDWORD);
39 static DWORD (WINAPI *pRegDeleteTreeA)(HKEY,LPCSTR);
40
41
42
43 /* Debugging functions from wine/libs/wine/debug.c */
44
45 /* allocate some tmp string space */
46 /* FIXME: this is not 100% thread-safe */
47 static char *get_temp_buffer( int size )
48 {
49     static char *list[32];
50     static UINT pos;
51     char *ret;
52     UINT idx;
53
54     idx = ++pos % (sizeof(list)/sizeof(list[0]));
55     if (list[idx])
56         ret = HeapReAlloc( GetProcessHeap(), 0, list[idx], size );
57     else
58         ret = HeapAlloc( GetProcessHeap(), 0, size );
59     if (ret) list[idx] = ret;
60     return ret;
61 }
62
63 static const char *wine_debugstr_an( const char *str, int n )
64 {
65     static const char hex[16] = "0123456789abcdef";
66     char *dst, *res;
67     size_t size;
68
69     if (!((ULONG_PTR)str >> 16))
70     {
71         if (!str) return "(null)";
72         res = get_temp_buffer( 6 );
73         sprintf( res, "#%04x", LOWORD(str) );
74         return res;
75     }
76     if (n == -1) n = strlen(str);
77     if (n < 0) n = 0;
78     size = 10 + min( 300, n * 4 );
79     dst = res = get_temp_buffer( size );
80     *dst++ = '"';
81     while (n-- > 0 && dst <= res + size - 9)
82     {
83         unsigned char c = *str++;
84         switch (c)
85         {
86         case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
87         case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
88         case '\t': *dst++ = '\\'; *dst++ = 't'; break;
89         case '"':  *dst++ = '\\'; *dst++ = '"'; break;
90         case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
91         default:
92             if (c >= ' ' && c <= 126)
93                 *dst++ = c;
94             else
95             {
96                 *dst++ = '\\';
97                 *dst++ = 'x';
98                 *dst++ = hex[(c >> 4) & 0x0f];
99                 *dst++ = hex[c & 0x0f];
100             }
101         }
102     }
103     *dst++ = '"';
104     if (n > 0)
105     {
106         *dst++ = '.';
107         *dst++ = '.';
108         *dst++ = '.';
109     }
110     *dst++ = 0;
111     return res;
112 }
113
114 #define ADVAPI32_GET_PROC(func) \
115     p ## func = (void*)GetProcAddress(hadvapi32, #func);
116
117
118 static void InitFunctionPtrs(void)
119 {
120     hadvapi32 = GetModuleHandleA("advapi32.dll");
121
122     /* This function was introduced with Windows 2003 SP1 */
123     ADVAPI32_GET_PROC(RegGetValueA)
124     ADVAPI32_GET_PROC(RegDeleteTreeA)
125 }
126
127 /* delete key and all its subkeys */
128 static DWORD delete_key( HKEY hkey )
129 {
130     char name[MAX_PATH];
131     DWORD ret;
132
133     while (!(ret = RegEnumKeyA(hkey, 0, name, sizeof(name))))
134     {
135         HKEY tmp;
136         if (!(ret = RegOpenKeyExA( hkey, name, 0, KEY_ENUMERATE_SUB_KEYS, &tmp )))
137         {
138             ret = delete_key( tmp );
139             RegCloseKey( tmp );
140         }
141         if (ret) break;
142     }
143     if (ret != ERROR_NO_MORE_ITEMS) return ret;
144     RegDeleteKeyA( hkey, "" );
145     return 0;
146 }
147
148 static void setup_main_key(void)
149 {
150     if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main )) delete_key( hkey_main );
151
152     assert (!RegCreateKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main ));
153 }
154
155 #define lok ok_(__FILE__, line)
156 #define test_hkey_main_Value_A(name, string, full_byte_len) _test_hkey_main_Value_A(__LINE__, name, string, full_byte_len)
157 static void _test_hkey_main_Value_A(int line, LPCSTR name, LPCSTR string,
158                                    DWORD full_byte_len)
159 {
160     DWORD ret, type, cbData;
161     DWORD str_byte_len;
162     BYTE* value;
163
164     type=0xdeadbeef;
165     cbData=0xdeadbeef;
166     /* When successful RegQueryValueExA() leaves GLE as is,
167      * so we must reset it to detect unimplemented functions.
168      */
169     SetLastError(0xdeadbeef);
170     ret = RegQueryValueExA(hkey_main, name, NULL, &type, NULL, &cbData);
171     GLE = GetLastError();
172     lok(ret == ERROR_SUCCESS, "RegQueryValueExA/1 failed: %d, GLE=%d\n", ret, GLE);
173     /* It is wrong for the Ansi version to not be implemented */
174     ok(GLE == 0xdeadbeef, "RegQueryValueExA set GLE = %u\n", GLE);
175     if(GLE == ERROR_CALL_NOT_IMPLEMENTED) return;
176
177     str_byte_len = (string ? lstrlenA(string) : 0) + 1;
178     lok(type == REG_SZ, "RegQueryValueExA/1 returned type %d\n", type);
179     lok(cbData == full_byte_len || cbData == str_byte_len /* Win9x */,
180         "cbData=%d instead of %d or %d\n", cbData, full_byte_len, str_byte_len);
181
182     value = HeapAlloc(GetProcessHeap(), 0, cbData+1);
183     memset(value, 0xbd, cbData+1);
184     type=0xdeadbeef;
185     ret = RegQueryValueExA(hkey_main, name, NULL, &type, value, &cbData);
186     GLE = GetLastError();
187     lok(ret == ERROR_SUCCESS, "RegQueryValueExA/2 failed: %d, GLE=%d\n", ret, GLE);
188     if (!string)
189     {
190         /* When cbData == 0, RegQueryValueExA() should not modify the buffer */
191         lok(*value == 0xbd || (cbData == 1 && *value == '\0') /* Win9x */,
192            "RegQueryValueExA overflowed: cbData=%u *value=%02x\n", cbData, *value);
193     }
194     else
195     {
196         lok(memcmp(value, string, cbData) == 0, "RegQueryValueExA/2 failed: %s/%d != %s/%d\n",
197            wine_debugstr_an((char*)value, cbData), cbData,
198            wine_debugstr_an(string, full_byte_len), full_byte_len);
199         lok(*(value+cbData) == 0xbd, "RegQueryValueExA/2 overflowed at offset %u: %02x != bd\n", cbData, *(value+cbData));
200     }
201     HeapFree(GetProcessHeap(), 0, value);
202 }
203
204 #define test_hkey_main_Value_W(name, string, full_byte_len) _test_hkey_main_Value_W(__LINE__, name, string, full_byte_len)
205 static void _test_hkey_main_Value_W(int line, LPCWSTR name, LPCWSTR string,
206                                    DWORD full_byte_len)
207 {
208     DWORD ret, type, cbData;
209     BYTE* value;
210
211     type=0xdeadbeef;
212     cbData=0xdeadbeef;
213     /* When successful RegQueryValueExW() leaves GLE as is,
214      * so we must reset it to detect unimplemented functions.
215      */
216     SetLastError(0xdeadbeef);
217     ret = RegQueryValueExW(hkey_main, name, NULL, &type, NULL, &cbData);
218     GLE = GetLastError();
219     lok(ret == ERROR_SUCCESS, "RegQueryValueExW/1 failed: %d, GLE=%d\n", ret, GLE);
220     if(GLE == ERROR_CALL_NOT_IMPLEMENTED)
221     {
222         win_skip("RegQueryValueExW() is not implemented\n");
223         return;
224     }
225
226     lok(type == REG_SZ, "RegQueryValueExW/1 returned type %d\n", type);
227     lok(cbData == full_byte_len,
228         "cbData=%d instead of %d\n", cbData, full_byte_len);
229
230     /* Give enough space to overflow by one WCHAR */
231     value = HeapAlloc(GetProcessHeap(), 0, cbData+2);
232     memset(value, 0xbd, cbData+2);
233     type=0xdeadbeef;
234     ret = RegQueryValueExW(hkey_main, name, NULL, &type, value, &cbData);
235     GLE = GetLastError();
236     lok(ret == ERROR_SUCCESS, "RegQueryValueExW/2 failed: %d, GLE=%d\n", ret, GLE);
237     if (string)
238     {
239         lok(memcmp(value, string, cbData) == 0, "RegQueryValueExW failed: %s/%d != %s/%d\n",
240            wine_dbgstr_wn((WCHAR*)value, cbData / sizeof(WCHAR)), cbData,
241            wine_dbgstr_wn(string, full_byte_len / sizeof(WCHAR)), full_byte_len);
242     }
243     /* This implies that when cbData == 0, RegQueryValueExW() should not modify the buffer */
244     lok(*(value+cbData) == 0xbd, "RegQueryValueExW/2 overflowed at %u: %02x != bd\n", cbData, *(value+cbData));
245     lok(*(value+cbData+1) == 0xbd, "RegQueryValueExW/2 overflowed at %u+1: %02x != bd\n", cbData, *(value+cbData+1));
246     HeapFree(GetProcessHeap(), 0, value);
247 }
248
249 static void test_set_value(void)
250 {
251     DWORD ret;
252
253     static const WCHAR name1W[] =   {'C','l','e','a','n','S','i','n','g','l','e','S','t','r','i','n','g', 0};
254     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};
255     static const WCHAR emptyW[] = {0};
256     static const WCHAR string1W[] = {'T','h','i','s','N','e','v','e','r','B','r','e','a','k','s', 0};
257     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};
258     static const WCHAR substring2W[] = {'T','h','i','s',0};
259
260     static const char name1A[] =   "CleanSingleString";
261     static const char name2A[] =   "SomeIntraZeroedString";
262     static const char emptyA[] = "";
263     static const char string1A[] = "ThisNeverBreaks";
264     static const char string2A[] = "This\0Breaks\0\0A\0\0\0Lot\0\0\0\0";
265     static const char substring2A[] = "This";
266
267     if (0)
268     {
269         /* Crashes on NT4, Windows 2000 and XP SP1 */
270         ret = RegSetValueA(hkey_main, NULL, REG_SZ, NULL, 0);
271         ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueA should have failed with ERROR_INVALID_PARAMETER instead of %d\n", ret);
272     }
273
274     ret = RegSetValueA(hkey_main, NULL, REG_SZ, string1A, sizeof(string1A));
275     ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %d, GLE=%d\n", ret, GetLastError());
276     test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
277     test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
278
279     /* RegSetValueA ignores the size passed in */
280     ret = RegSetValueA(hkey_main, NULL, REG_SZ, string1A, 4);
281     ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %d, GLE=%d\n", ret, GetLastError());
282     test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
283     test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
284
285     /* stops at first null */
286     ret = RegSetValueA(hkey_main, NULL, REG_SZ, string2A, sizeof(string2A));
287     ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %d, GLE=%d\n", ret, GetLastError());
288     test_hkey_main_Value_A(NULL, substring2A, sizeof(substring2A));
289     test_hkey_main_Value_W(NULL, substring2W, sizeof(substring2W));
290
291     /* only REG_SZ is supported on NT*/
292     ret = RegSetValueA(hkey_main, NULL, REG_BINARY, string2A, sizeof(string2A));
293     /* NT: ERROR_INVALID_PARAMETER, 9x: ERROR_SUCCESS */
294     ok(ret == ERROR_INVALID_PARAMETER || broken(ret == ERROR_SUCCESS),
295         "got %d (expected ERROR_INVALID_PARAMETER or ERROR_SUCCESS)\n", ret);
296
297     ret = RegSetValueA(hkey_main, NULL, REG_EXPAND_SZ, string2A, sizeof(string2A));
298     /* NT: ERROR_INVALID_PARAMETER, 9x: ERROR_SUCCESS */
299     ok(ret == ERROR_INVALID_PARAMETER || broken(ret == ERROR_SUCCESS),
300         "got %d (expected ERROR_INVALID_PARAMETER or ERROR_SUCCESS)\n", ret);
301
302     ret = RegSetValueA(hkey_main, NULL, REG_MULTI_SZ, string2A, sizeof(string2A));
303     /* NT: ERROR_INVALID_PARAMETER, 9x: ERROR_SUCCESS */
304     ok(ret == ERROR_INVALID_PARAMETER || broken(ret == ERROR_SUCCESS),
305         "got %d (expected ERROR_INVALID_PARAMETER or ERROR_SUCCESS)\n", ret);
306
307     /* Test RegSetValueExA with a 'zero-byte' string (as Office 2003 does).
308      * Surprisingly enough we're supposed to get zero bytes out of it.
309      */
310     ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)emptyA, 0);
311     ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
312     test_hkey_main_Value_A(name1A, NULL, 0);
313     test_hkey_main_Value_W(name1W, NULL, 0);
314
315     /* test RegSetValueExA with an empty string */
316     ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)emptyA, sizeof(emptyA));
317     ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
318     test_hkey_main_Value_A(name1A, emptyA, sizeof(emptyA));
319     test_hkey_main_Value_W(name1W, emptyW, sizeof(emptyW));
320
321     /* test RegSetValueExA with off-by-one size */
322     ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)string1A, sizeof(string1A)-sizeof(string1A[0]));
323     ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
324     test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
325     test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
326
327     /* test RegSetValueExA with normal string */
328     ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)string1A, sizeof(string1A));
329     ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
330     test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
331     test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
332
333     /* test RegSetValueExA with intrazeroed string */
334     ret = RegSetValueExA(hkey_main, name2A, 0, REG_SZ, (const BYTE *)string2A, sizeof(string2A));
335     ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
336     test_hkey_main_Value_A(name2A, string2A, sizeof(string2A));
337     test_hkey_main_Value_W(name2W, string2W, sizeof(string2W));
338
339     /* 9x doesn't support W-calls, so don't test them then */
340     if(GLE == ERROR_CALL_NOT_IMPLEMENTED) return; 
341
342     if (0)
343     {
344         /* Crashes on NT4, Windows 2000 and XP SP1 */
345         ret = RegSetValueW(hkey_main, NULL, REG_SZ, NULL, 0);
346         ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have failed with ERROR_INVALID_PARAMETER instead of %d\n", ret);
347     }
348
349     ret = RegSetValueW(hkey_main, NULL, REG_SZ, string1W, sizeof(string1W));
350     ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError());
351     test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
352     test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
353
354     /* RegSetValueA ignores the size passed in */
355     ret = RegSetValueW(hkey_main, NULL, REG_SZ, string1W, 4 * sizeof(string1W[0]));
356     ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError());
357     test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
358     test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
359
360     /* stops at first null */
361     ret = RegSetValueW(hkey_main, NULL, REG_SZ, string2W, sizeof(string2W));
362     ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError());
363     test_hkey_main_Value_A(NULL, substring2A, sizeof(substring2A));
364     test_hkey_main_Value_W(NULL, substring2W, sizeof(substring2W));
365
366     /* only REG_SZ is supported */
367     ret = RegSetValueW(hkey_main, NULL, REG_BINARY, string2W, sizeof(string2W));
368     ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
369     ret = RegSetValueW(hkey_main, NULL, REG_EXPAND_SZ, string2W, sizeof(string2W));
370     ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
371     ret = RegSetValueW(hkey_main, NULL, REG_MULTI_SZ, string2W, sizeof(string2W));
372     ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret);
373
374     /* test RegSetValueExW with off-by-one size */
375     ret = RegSetValueExW(hkey_main, name1W, 0, REG_SZ, (const BYTE *)string1W, sizeof(string1W)-sizeof(string1W[0]));
376     ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %d, GLE=%d\n", ret, GetLastError());
377     test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
378     test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
379
380     /* test RegSetValueExW with normal string */
381     ret = RegSetValueExW(hkey_main, name1W, 0, REG_SZ, (const BYTE *)string1W, sizeof(string1W));
382     ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %d, GLE=%d\n", ret, GetLastError());
383     test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
384     test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
385
386     /* test RegSetValueExW with intrazeroed string */
387     ret = RegSetValueExW(hkey_main, name2W, 0, REG_SZ, (const BYTE *)string2W, sizeof(string2W));
388     ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %d, GLE=%d\n", ret, GetLastError());
389     test_hkey_main_Value_A(name2A, string2A, sizeof(string2A));
390     test_hkey_main_Value_W(name2W, string2W, sizeof(string2W));
391 }
392
393 static void create_test_entries(void)
394 {
395     static const DWORD qw[2] = { 0x12345678, 0x87654321 };
396
397     SetEnvironmentVariableA("LONGSYSTEMVAR", "bar");
398     SetEnvironmentVariableA("FOO", "ImARatherLongButIndeedNeededString");
399
400     ok(!RegSetValueExA(hkey_main,"TP1_EXP_SZ",0,REG_EXPAND_SZ, (const BYTE *)sTestpath1, strlen(sTestpath1)+1), 
401         "RegSetValueExA failed\n");
402     ok(!RegSetValueExA(hkey_main,"TP1_SZ",0,REG_SZ, (const BYTE *)sTestpath1, strlen(sTestpath1)+1), 
403         "RegSetValueExA failed\n");
404     ok(!RegSetValueExA(hkey_main,"TP1_ZB_SZ",0,REG_SZ, (const BYTE *)"", 0),
405        "RegSetValueExA failed\n");
406     ok(!RegSetValueExA(hkey_main,"TP2_EXP_SZ",0,REG_EXPAND_SZ, (const BYTE *)sTestpath2, strlen(sTestpath2)+1), 
407         "RegSetValueExA failed\n");
408     ok(!RegSetValueExA(hkey_main,"DWORD",0,REG_DWORD, (const BYTE *)qw, 4),
409         "RegSetValueExA failed\n");
410     ok(!RegSetValueExA(hkey_main,"BIN32",0,REG_BINARY, (const BYTE *)qw, 4),
411         "RegSetValueExA failed\n");
412     ok(!RegSetValueExA(hkey_main,"BIN64",0,REG_BINARY, (const BYTE *)qw, 8),
413         "RegSetValueExA failed\n");
414 }
415         
416 static void test_enum_value(void)
417 {
418     DWORD res;
419     HKEY test_key;
420     char value[20], data[20];
421     WCHAR valueW[20], dataW[20];
422     DWORD val_count, data_count, type;
423     static const WCHAR foobarW[] = {'f','o','o','b','a','r',0};
424     static const WCHAR testW[] = {'T','e','s','t',0};
425     static const WCHAR xxxW[] = {'x','x','x','x','x','x','x','x',0};
426
427     /* create the working key for new 'Test' value */
428     res = RegCreateKeyA( hkey_main, "TestKey", &test_key );
429     ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res);
430
431     /* check NULL data with zero length */
432     res = RegSetValueExA( test_key, "Test", 0, REG_SZ, NULL, 0 );
433     if (GetVersion() & 0x80000000)
434         ok( res == ERROR_INVALID_PARAMETER, "RegSetValueExA returned %d\n", res );
435     else
436         ok( !res, "RegSetValueExA returned %d\n", res );
437     res = RegSetValueExA( test_key, "Test", 0, REG_EXPAND_SZ, NULL, 0 );
438     ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %d\n", res );
439     res = RegSetValueExA( test_key, "Test", 0, REG_BINARY, NULL, 0 );
440     ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %d\n", res );
441
442     res = RegSetValueExA( test_key, "Test", 0, REG_SZ, (const BYTE *)"foobar", 7 );
443     ok( res == 0, "RegSetValueExA failed error %d\n", res );
444
445     /* overflow both name and data */
446     val_count = 2;
447     data_count = 2;
448     type = 1234;
449     strcpy( value, "xxxxxxxxxx" );
450     strcpy( data, "xxxxxxxxxx" );
451     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
452     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
453     ok( val_count == 2, "val_count set to %d\n", val_count );
454     ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
455     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
456     ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
457     ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data );
458
459     /* overflow name */
460     val_count = 3;
461     data_count = 20;
462     type = 1234;
463     strcpy( value, "xxxxxxxxxx" );
464     strcpy( data, "xxxxxxxxxx" );
465     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
466     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
467     /* Win9x returns 2 as specified by MSDN but NT returns 3... */
468     ok( val_count == 2 || val_count == 3, "val_count set to %d\n", val_count );
469     ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
470     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
471     /* v5.1.2600.0 (XP Home and Professional) does not touch value or data in this case */
472     ok( !strcmp( value, "Te" ) || !strcmp( value, "xxxxxxxxxx" ), 
473         "value set to '%s' instead of 'Te' or 'xxxxxxxxxx'\n", value );
474     ok( !strcmp( data, "foobar" ) || !strcmp( data, "xxxxxxx" ), 
475         "data set to '%s' instead of 'foobar' or 'xxxxxxx'\n", data );
476
477     /* overflow empty name */
478     val_count = 0;
479     data_count = 20;
480     type = 1234;
481     strcpy( value, "xxxxxxxxxx" );
482     strcpy( data, "xxxxxxxxxx" );
483     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
484     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
485     ok( val_count == 0, "val_count set to %d\n", val_count );
486     ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
487     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
488     ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
489     /* v5.1.2600.0 (XP Home and Professional) does not touch data in this case */
490     ok( !strcmp( data, "foobar" ) || !strcmp( data, "xxxxxxx" ), 
491         "data set to '%s' instead of 'foobar' or 'xxxxxxx'\n", data );
492
493     /* overflow data */
494     val_count = 20;
495     data_count = 2;
496     type = 1234;
497     strcpy( value, "xxxxxxxxxx" );
498     strcpy( data, "xxxxxxxxxx" );
499     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
500     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
501     ok( val_count == 20, "val_count set to %d\n", val_count );
502     ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
503     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
504     ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
505     ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data );
506
507     /* no overflow */
508     val_count = 20;
509     data_count = 20;
510     type = 1234;
511     strcpy( value, "xxxxxxxxxx" );
512     strcpy( data, "xxxxxxxxxx" );
513     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
514     ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res );
515     ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
516     ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
517     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
518     ok( !strcmp( value, "Test" ), "value is '%s' instead of Test\n", value );
519     ok( !strcmp( data, "foobar" ), "data is '%s' instead of foobar\n", data );
520
521     /* Unicode tests */
522
523     SetLastError(0xdeadbeef);
524     res = RegSetValueExW( test_key, testW, 0, REG_SZ, (const BYTE *)foobarW, 7*sizeof(WCHAR) );
525     if (res==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
526     {
527         win_skip("RegSetValueExW is not implemented\n");
528         goto cleanup;
529     }
530     ok( res == 0, "RegSetValueExW failed error %d\n", res );
531
532     /* overflow both name and data */
533     val_count = 2;
534     data_count = 2;
535     type = 1234;
536     memcpy( valueW, xxxW, sizeof(xxxW) );
537     memcpy( dataW, xxxW, sizeof(xxxW) );
538     res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
539     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
540     ok( val_count == 2, "val_count set to %d\n", val_count );
541     ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
542     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
543     ok( !memcmp( valueW, xxxW, sizeof(xxxW) ), "value modified\n" );
544     ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
545
546     /* overflow name */
547     val_count = 3;
548     data_count = 20;
549     type = 1234;
550     memcpy( valueW, xxxW, sizeof(xxxW) );
551     memcpy( dataW, xxxW, sizeof(xxxW) );
552     res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
553     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
554     ok( val_count == 3, "val_count set to %d\n", val_count );
555     ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
556     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
557     ok( !memcmp( valueW, xxxW, sizeof(xxxW) ), "value modified\n" );
558     ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
559
560     /* overflow data */
561     val_count = 20;
562     data_count = 2;
563     type = 1234;
564     memcpy( valueW, xxxW, sizeof(xxxW) );
565     memcpy( dataW, xxxW, sizeof(xxxW) );
566     res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
567     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
568     ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
569     ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
570     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
571     ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" );
572     ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
573
574     /* no overflow */
575     val_count = 20;
576     data_count = 20;
577     type = 1234;
578     memcpy( valueW, xxxW, sizeof(xxxW) );
579     memcpy( dataW, xxxW, sizeof(xxxW) );
580     res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
581     ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res );
582     ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
583     ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
584     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
585     ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" );
586     ok( !memcmp( dataW, foobarW, sizeof(foobarW) ), "data is not 'foobar'\n" );
587
588 cleanup:
589     RegDeleteKeyA(test_key, "");
590     RegCloseKey(test_key);
591 }
592
593 static void test_query_value_ex(void)
594 {
595     DWORD ret;
596     DWORD size;
597     DWORD type;
598     BYTE buffer[10];
599     
600     ret = RegQueryValueExA(hkey_main, "TP1_SZ", NULL, &type, NULL, &size);
601     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
602     ok(size == strlen(sTestpath1) + 1, "(%d,%d)\n", (DWORD)strlen(sTestpath1) + 1, size);
603     ok(type == REG_SZ, "type %d is not REG_SZ\n", type);
604
605     type = 0xdeadbeef;
606     size = 0xdeadbeef;
607     ret = RegQueryValueExA(HKEY_CLASSES_ROOT, "Nonexistent Value", NULL, &type, NULL, &size);
608     ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
609     /* the type parameter is cleared on Win9x, but is set to a random value on
610      * NT, so don't do that test there. The size parameter is left untouched on Win9x
611      * but cleared on NT+, this can be tested on all platforms.
612      */
613     if (GetVersion() & 0x80000000)
614     {
615         ok(type == 0, "type should have been set to 0 instead of 0x%x\n", type);
616         ok(size == 0xdeadbeef, "size should have been left untouched (0xdeadbeef)\n");
617     }
618     else
619     {
620         trace("test_query_value_ex: type set to: 0x%08x\n", type);
621         ok(size == 0, "size should have been set to 0 instead of %d\n", size);
622     }
623
624     size = sizeof(buffer);
625     ret = RegQueryValueExA(HKEY_CLASSES_ROOT, "Nonexistent Value", NULL, &type, buffer, &size);
626     ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
627     ok(size == sizeof(buffer), "size shouldn't have been changed to %d\n", size);
628
629     size = 4;
630     ret = RegQueryValueExA(hkey_main, "BIN32", NULL, &size, buffer, &size);
631     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
632 }
633
634 static void test_get_value(void)
635 {
636     DWORD ret;
637     DWORD size;
638     DWORD type;
639     DWORD dw, qw[2];
640     CHAR buf[80];
641     CHAR expanded[] = "bar\\subdir1";
642     CHAR expanded2[] = "ImARatherLongButIndeedNeededString\\subdir1";
643    
644     if(!pRegGetValueA)
645     {
646         win_skip("RegGetValue not available on this platform\n");
647         return;
648     }
649
650     /* Invalid parameter */
651     ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_DWORD, &type, &dw, NULL);
652     ok(ret == ERROR_INVALID_PARAMETER, "ret=%d\n", ret);
653
654     /* Query REG_DWORD using RRF_RT_REG_DWORD (ok) */
655     size = type = dw = 0xdeadbeef;
656     ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_DWORD, &type, &dw, &size);
657     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
658     ok(size == 4, "size=%d\n", size);
659     ok(type == REG_DWORD, "type=%d\n", type);
660     ok(dw == 0x12345678, "dw=%d\n", dw);
661
662     /* Query by subkey-name */
663     ret = pRegGetValueA(HKEY_CURRENT_USER, "Software\\Wine\\Test", "DWORD", RRF_RT_REG_DWORD, NULL, NULL, NULL);
664     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
665
666     /* Query REG_DWORD using RRF_RT_REG_BINARY (restricted) */
667     size = type = dw = 0xdeadbeef;
668     ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_BINARY, &type, &dw, &size);
669     ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
670     /* Although the function failed all values are retrieved */
671     ok(size == 4, "size=%d\n", size);
672     ok(type == REG_DWORD, "type=%d\n", type);
673     ok(dw == 0x12345678, "dw=%d\n", dw);
674
675     /* Test RRF_ZEROONFAILURE */
676     type = dw = 0xdeadbeef; size = 4;
677     ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_SZ|RRF_ZEROONFAILURE, &type, &dw, &size);
678     ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
679     /* Again all values are retrieved ... */
680     ok(size == 4, "size=%d\n", size);
681     ok(type == REG_DWORD, "type=%d\n", type);
682     /* ... except the buffer, which is zeroed out */
683     ok(dw == 0, "dw=%d\n", dw);
684
685     /* Test RRF_ZEROONFAILURE with a NULL buffer... */
686     type = size = 0xbadbeef;
687     ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_SZ|RRF_ZEROONFAILURE, &type, NULL, &size);
688     ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
689     ok(size == 4, "size=%d\n", size);
690     ok(type == REG_DWORD, "type=%d\n", type);
691
692     /* Query REG_DWORD using RRF_RT_DWORD (ok) */
693     size = type = dw = 0xdeadbeef;
694     ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_DWORD, &type, &dw, &size);
695     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
696     ok(size == 4, "size=%d\n", size);
697     ok(type == REG_DWORD, "type=%d\n", type);
698     ok(dw == 0x12345678, "dw=%d\n", dw);
699
700     /* Query 32-bit REG_BINARY using RRF_RT_DWORD (ok) */
701     size = type = dw = 0xdeadbeef;
702     ret = pRegGetValueA(hkey_main, NULL, "BIN32", RRF_RT_DWORD, &type, &dw, &size);
703     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
704     ok(size == 4, "size=%d\n", size);
705     ok(type == REG_BINARY, "type=%d\n", type);
706     ok(dw == 0x12345678, "dw=%d\n", dw);
707     
708     /* Query 64-bit REG_BINARY using RRF_RT_DWORD (type mismatch) */
709     qw[0] = qw[1] = size = type = 0xdeadbeef;
710     ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_DWORD, &type, qw, &size);
711     ok(ret == ERROR_DATATYPE_MISMATCH, "ret=%d\n", ret);
712     ok(size == 8, "size=%d\n", size);
713     ok(type == REG_BINARY, "type=%d\n", type);
714     ok(qw[0] == 0x12345678 && 
715        qw[1] == 0x87654321, "qw={%d,%d}\n", qw[0], qw[1]);
716     
717     /* Query 64-bit REG_BINARY using 32-bit buffer (buffer too small) */
718     type = dw = 0xdeadbeef; size = 4;
719     ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_REG_BINARY, &type, &dw, &size);
720     ok(ret == ERROR_MORE_DATA, "ret=%d\n", ret);
721     ok(dw == 0xdeadbeef, "dw=%d\n", dw);
722     ok(size == 8, "size=%d\n", size);
723
724     /* Query 64-bit REG_BINARY using RRF_RT_QWORD (ok) */
725     qw[0] = qw[1] = size = type = 0xdeadbeef;
726     ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_QWORD, &type, qw, &size);
727     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
728     ok(size == 8, "size=%d\n", size);
729     ok(type == REG_BINARY, "type=%d\n", type);
730     ok(qw[0] == 0x12345678 &&
731        qw[1] == 0x87654321, "qw={%d,%d}\n", qw[0], qw[1]);
732
733     /* Query REG_SZ using RRF_RT_REG_SZ (ok) */
734     buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
735     ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ, &type, buf, &size);
736     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
737     ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
738     ok(type == REG_SZ, "type=%d\n", type);
739     ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
740
741     /* Query REG_SZ using RRF_RT_REG_SZ and no buffer (ok) */
742     type = 0xdeadbeef; size = 0;
743     ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ, &type, NULL, &size);
744     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
745     /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
746     ok(size == strlen(sTestpath1)+1 || broken(size == strlen(sTestpath1)+2),
747        "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
748     ok(type == REG_SZ, "type=%d\n", type);
749
750     /* Query REG_SZ using RRF_RT_REG_SZ on a zero-byte value (ok) */
751     strcpy(buf, sTestpath1);
752     type = 0xdeadbeef;
753     size = sizeof(buf);
754     ret = pRegGetValueA(hkey_main, NULL, "TP1_ZB_SZ", RRF_RT_REG_SZ, &type, buf, &size);
755     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
756     /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
757     ok(size == 0 ||
758        size == 1, /* win2k3 */
759        "size=%d\n", size);
760     ok(type == REG_SZ, "type=%d\n", type);
761     ok(!strcmp(sTestpath1, buf) ||
762        !strcmp(buf, ""),
763        "Expected \"%s\" or \"\", got \"%s\"\n", sTestpath1, buf);
764
765     /* Query REG_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (ok) */
766     buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
767     ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ|RRF_NOEXPAND, &type, buf, &size);
768     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
769     ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
770     ok(type == REG_SZ, "type=%d\n", type);
771     ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
772
773     /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ and no buffer (ok, expands) */
774     size = 0;
775     ret = pRegGetValueA(hkey_main, NULL, "TP2_EXP_SZ", RRF_RT_REG_SZ, NULL, NULL, &size);
776     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
777     ok((size == strlen(expanded2)+1) || /* win2k3 SP1 */
778        (size == strlen(expanded2)+2) || /* win2k3 SP2 */
779        (size == strlen(sTestpath2)+1),
780         "strlen(expanded2)=%d, strlen(sTestpath2)=%d, size=%d\n", lstrlenA(expanded2), lstrlenA(sTestpath2), size);
781
782     /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ (ok, expands) */
783     buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
784     ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_SZ, &type, buf, &size);
785     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
786     /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath1 length + 1 here. */
787     ok(size == strlen(expanded)+1 || broken(size == strlen(sTestpath1)+1),
788         "strlen(expanded)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded), lstrlenA(sTestpath1), size);
789     ok(type == REG_SZ, "type=%d\n", type);
790     ok(!strcmp(expanded, buf), "expanded=\"%s\" buf=\"%s\"\n", expanded, buf);
791
792     /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ (ok, expands a lot) */
793     buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
794     ret = pRegGetValueA(hkey_main, NULL, "TP2_EXP_SZ", RRF_RT_REG_SZ, &type, buf, &size);
795     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
796     /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath2 length + 1 here. */
797     ok(size == strlen(expanded2)+1 || broken(size == strlen(sTestpath2)+1),
798         "strlen(expanded2)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded2), lstrlenA(sTestpath2), size);
799     ok(type == REG_SZ, "type=%d\n", type);
800     ok(!strcmp(expanded2, buf), "expanded2=\"%s\" buf=\"%s\"\n", expanded2, buf);
801
802     /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND (ok, doesn't expand) */
803     buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
804     ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND, &type, buf, &size);
805     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
806     ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
807     ok(type == REG_EXPAND_SZ, "type=%d\n", type);
808     ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
809
810     /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND and no buffer (ok, doesn't expand) */
811     size = 0xbadbeef;
812     ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND, NULL, NULL, &size);
813     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
814     /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
815     ok(size == strlen(sTestpath1)+1 || broken(size == strlen(sTestpath1)+2),
816        "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
817
818     /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (type mismatch) */
819     ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_SZ|RRF_NOEXPAND, NULL, NULL, NULL);
820     ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
821
822     /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ (not allowed without RRF_NOEXPAND) */
823     ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ, NULL, NULL, NULL);
824     ok(ret == ERROR_INVALID_PARAMETER, "ret=%d\n", ret);
825
826     /* Query REG_EXPAND_SZ using RRF_RT_ANY */
827     buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
828     ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_ANY, &type, buf, &size);
829     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
830     /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath1 length + 1 here. */
831     ok(size == strlen(expanded)+1 || broken(size == strlen(sTestpath1)+1),
832         "strlen(expanded)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded), lstrlenA(sTestpath1), size);
833     ok(type == REG_SZ, "type=%d\n", type);
834     ok(!strcmp(expanded, buf), "expanded=\"%s\" buf=\"%s\"\n", expanded, buf);
835
836
837 static void test_reg_open_key(void)
838 {
839     DWORD ret = 0;
840     HKEY hkResult = NULL;
841     HKEY hkPreserve = NULL;
842
843     /* successful open */
844     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult);
845     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
846     ok(hkResult != NULL, "expected hkResult != NULL\n");
847     hkPreserve = hkResult;
848
849     /* these tests fail on Win9x, but we want to be compatible with NT, so
850      * run them if we can */
851     if (!(GetVersion() & 0x80000000))
852     {
853         /* open same key twice */
854         ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult);
855         ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
856         ok(hkResult != hkPreserve, "epxected hkResult != hkPreserve\n");
857         ok(hkResult != NULL, "hkResult != NULL\n");
858         RegCloseKey(hkResult);
859     
860         /* open nonexistent key
861         * check that hkResult is set to NULL
862         */
863         hkResult = hkPreserve;
864         ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
865         ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
866         ok(hkResult == NULL, "expected hkResult == NULL\n");
867     
868         /* open the same nonexistent key again to make sure the key wasn't created */
869         hkResult = hkPreserve;
870         ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
871         ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
872         ok(hkResult == NULL, "expected hkResult == NULL\n");
873     
874         /* send in NULL lpSubKey
875         * check that hkResult receives the value of hKey
876         */
877         hkResult = hkPreserve;
878         ret = RegOpenKeyA(HKEY_CURRENT_USER, NULL, &hkResult);
879         ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
880         ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
881     
882         /* send empty-string in lpSubKey */
883         hkResult = hkPreserve;
884         ret = RegOpenKeyA(HKEY_CURRENT_USER, "", &hkResult);
885         ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
886         ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
887     
888         /* send in NULL lpSubKey and NULL hKey
889         * hkResult is set to NULL
890         */
891         hkResult = hkPreserve;
892         ret = RegOpenKeyA(NULL, NULL, &hkResult);
893         ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
894         ok(hkResult == NULL, "expected hkResult == NULL\n");
895     }
896
897     /* only send NULL hKey
898      * the value of hkResult remains unchanged
899      */
900     hkResult = hkPreserve;
901     ret = RegOpenKeyA(NULL, "Software\\Wine\\Test", &hkResult);
902     ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */
903        "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
904     ok(hkResult == hkPreserve, "expected hkResult == hkPreserve\n");
905     RegCloseKey(hkResult);
906
907     /* send in NULL hkResult */
908     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", NULL);
909     ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", ret);
910
911     ret = RegOpenKeyA(HKEY_CURRENT_USER, NULL, NULL);
912     ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", ret);
913
914     ret = RegOpenKeyA(NULL, NULL, NULL);
915     ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", ret);
916
917     /*  beginning backslash character */
918     ret = RegOpenKeyA(HKEY_CURRENT_USER, "\\Software\\Wine\\Test", &hkResult);
919        ok(ret == ERROR_BAD_PATHNAME || /* NT/2k/XP */
920            ret == ERROR_FILE_NOT_FOUND /* Win9x,ME */
921            , "expected ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %d\n", ret);
922
923     hkResult = NULL;
924     ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, "\\clsid", 0, KEY_QUERY_VALUE, &hkResult);
925     ok(ret == ERROR_SUCCESS || /* 2k/XP */
926        ret == ERROR_BAD_PATHNAME || /* NT */
927        ret == ERROR_FILE_NOT_FOUND /* Win9x,ME */
928        , "expected ERROR_SUCCESS, ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %d\n", ret);
929     RegCloseKey(hkResult);
930
931     /* WOW64 flags */
932     hkResult = NULL;
933     ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WOW64_32KEY, &hkResult);
934     ok((ret == ERROR_SUCCESS && hkResult != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */),
935         "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret);
936     RegCloseKey(hkResult);
937
938     hkResult = NULL;
939     ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WOW64_64KEY, &hkResult);
940     ok((ret == ERROR_SUCCESS && hkResult != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */),
941         "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret);
942     RegCloseKey(hkResult);
943 }
944
945 static void test_reg_create_key(void)
946 {
947     LONG ret;
948     HKEY hkey1, hkey2;
949     ret = RegCreateKeyExA(hkey_main, "Subkey1", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL);
950     ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
951     /* should succeed: all versions of Windows ignore the access rights
952      * to the parent handle */
953     ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey2, NULL);
954     ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
955
956     /* clean up */
957     RegDeleteKey(hkey2, "");
958     RegDeleteKey(hkey1, "");
959
960     /*  beginning backslash character */
961     ret = RegCreateKeyExA(hkey_main, "\\Subkey3", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL);
962     if (!(GetVersion() & 0x80000000))
963         ok(ret == ERROR_BAD_PATHNAME, "expected ERROR_BAD_PATHNAME, got %d\n", ret);
964     else {
965         ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
966         RegDeleteKey(hkey1, NULL);
967     }
968
969     /* WOW64 flags - open an existing key */
970     hkey1 = NULL;
971     ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0, KEY_READ|KEY_WOW64_32KEY, NULL, &hkey1, NULL);
972     ok((ret == ERROR_SUCCESS && hkey1 != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */),
973         "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret);
974     RegCloseKey(hkey1);
975
976     hkey1 = NULL;
977     ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0, KEY_READ|KEY_WOW64_64KEY, NULL, &hkey1, NULL);
978     ok((ret == ERROR_SUCCESS && hkey1 != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */),
979         "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret);
980     RegCloseKey(hkey1);
981 }
982
983 static void test_reg_close_key(void)
984 {
985     DWORD ret = 0;
986     HKEY hkHandle;
987
988     /* successfully close key
989      * hkHandle remains changed after call to RegCloseKey
990      */
991     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkHandle);
992     ret = RegCloseKey(hkHandle);
993     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
994
995     /* try to close the key twice */
996     ret = RegCloseKey(hkHandle); /* Windows 95 doesn't mind. */
997     ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_SUCCESS,
998        "expected ERROR_INVALID_HANDLE or ERROR_SUCCESS, got %d\n", ret);
999     
1000     /* try to close a NULL handle */
1001     ret = RegCloseKey(NULL);
1002     ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */
1003        "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
1004
1005     /* Check to see if we didn't potentially close our main handle, which could happen on win98 as
1006      * win98 doesn't give a new handle when the same key is opened.
1007      * Not re-opening will make some next tests fail.
1008      */
1009     if (hkey_main == hkHandle)
1010     {
1011         trace("The main handle is most likely closed, so re-opening\n");
1012         RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main );
1013     }
1014 }
1015
1016 static void test_reg_delete_key(void)
1017 {
1018     DWORD ret;
1019
1020     ret = RegDeleteKey(hkey_main, NULL);
1021
1022     /* There is a bug in NT4 and W2K that doesn't check if the subkey is NULL. If
1023      * there are also no subkeys available it will delete the key pointed to by hkey_main.
1024      * Not re-creating will make some next tests fail.
1025      */
1026     if (ret == ERROR_SUCCESS)
1027     {
1028         trace("We are probably running on NT4 or W2K as the main key is deleted,"
1029             " re-creating the main key\n");
1030         setup_main_key();
1031     }
1032     else
1033         ok(ret == ERROR_INVALID_PARAMETER ||
1034            ret == ERROR_ACCESS_DENIED ||
1035            ret == ERROR_BADKEY, /* Win95 */
1036            "ret=%d\n", ret);
1037 }
1038
1039 static void test_reg_save_key(void)
1040 {
1041     DWORD ret;
1042
1043     ret = RegSaveKey(hkey_main, "saved_key", NULL);
1044     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1045 }
1046
1047 static void test_reg_load_key(void)
1048 {
1049     DWORD ret;
1050     HKEY hkHandle;
1051
1052     ret = RegLoadKey(HKEY_LOCAL_MACHINE, "Test", "saved_key");
1053     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1054
1055     ret = RegOpenKey(HKEY_LOCAL_MACHINE, "Test", &hkHandle);
1056     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1057
1058     RegCloseKey(hkHandle);
1059 }
1060
1061 static void test_reg_unload_key(void)
1062 {
1063     DWORD ret;
1064
1065     ret = RegUnLoadKey(HKEY_LOCAL_MACHINE, "Test");
1066     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1067
1068     DeleteFile("saved_key");
1069     DeleteFile("saved_key.LOG");
1070 }
1071
1072 static BOOL set_privileges(LPCSTR privilege, BOOL set)
1073 {
1074     TOKEN_PRIVILEGES tp;
1075     HANDLE hToken;
1076     LUID luid;
1077
1078     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
1079         return FALSE;
1080
1081     if(!LookupPrivilegeValue(NULL, privilege, &luid))
1082     {
1083         CloseHandle(hToken);
1084         return FALSE;
1085     }
1086
1087     tp.PrivilegeCount = 1;
1088     tp.Privileges[0].Luid = luid;
1089     
1090     if (set)
1091         tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1092     else
1093         tp.Privileges[0].Attributes = 0;
1094
1095     AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
1096     if (GetLastError() != ERROR_SUCCESS)
1097     {
1098         CloseHandle(hToken);
1099         return FALSE;
1100     }
1101
1102     CloseHandle(hToken);
1103     return TRUE;
1104 }
1105
1106 /* tests that show that RegConnectRegistry and 
1107    OpenSCManager accept computer names without the
1108    \\ prefix (what MSDN says).   */
1109 static void test_regconnectregistry( void)
1110 {
1111     CHAR compName[MAX_COMPUTERNAME_LENGTH + 1];
1112     CHAR netwName[MAX_COMPUTERNAME_LENGTH + 3]; /* 2 chars for double backslash */
1113     DWORD len = sizeof(compName) ;
1114     BOOL ret;
1115     LONG retl;
1116     HKEY hkey;
1117     SC_HANDLE schnd;
1118
1119     SetLastError(0xdeadbeef);
1120     ret = GetComputerNameA(compName, &len);
1121     ok( ret, "GetComputerName failed err = %d\n", GetLastError());
1122     if( !ret) return;
1123
1124     lstrcpyA(netwName, "\\\\");
1125     lstrcpynA(netwName+2, compName, MAX_COMPUTERNAME_LENGTH + 1);
1126
1127     retl = RegConnectRegistryA( compName, HKEY_LOCAL_MACHINE, &hkey);
1128     ok( !retl ||
1129         retl == ERROR_DLL_INIT_FAILED ||
1130         retl == ERROR_BAD_NETPATH, /* some win2k */
1131         "RegConnectRegistryA failed err = %d\n", retl);
1132     if( !retl) RegCloseKey( hkey);
1133
1134     retl = RegConnectRegistryA( netwName, HKEY_LOCAL_MACHINE, &hkey);
1135     ok( !retl ||
1136         retl == ERROR_DLL_INIT_FAILED ||
1137         retl == ERROR_BAD_NETPATH, /* some win2k */
1138         "RegConnectRegistryA failed err = %d\n", retl);
1139     if( !retl) RegCloseKey( hkey);
1140
1141     SetLastError(0xdeadbeef);
1142     schnd = OpenSCManagerA( compName, NULL, GENERIC_READ); 
1143     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1144     {
1145         win_skip("OpenSCManagerA is not implemented\n");
1146         return;
1147     }
1148
1149     ok( schnd != NULL, "OpenSCManagerA failed err = %d\n", GetLastError());
1150     CloseServiceHandle( schnd);
1151
1152     SetLastError(0xdeadbeef);
1153     schnd = OpenSCManagerA( netwName, NULL, GENERIC_READ); 
1154     ok( schnd != NULL, "OpenSCManagerA failed err = %d\n", GetLastError());
1155     CloseServiceHandle( schnd);
1156
1157 }
1158
1159 static void test_reg_query_value(void)
1160 {
1161     HKEY subkey;
1162     CHAR val[MAX_PATH];
1163     WCHAR valW[5];
1164     LONG size, ret;
1165
1166     static const WCHAR expected[] = {'d','a','t','a',0};
1167
1168     ret = RegCreateKeyA(hkey_main, "subkey", &subkey);
1169     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1170
1171     ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4);
1172     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1173
1174     /* try an invalid hkey */
1175     SetLastError(0xdeadbeef);
1176     size = MAX_PATH;
1177     ret = RegQueryValueA((HKEY)0xcafebabe, "subkey", val, &size);
1178     ok(ret == ERROR_INVALID_HANDLE ||
1179        ret == ERROR_BADKEY || /* Windows 98 returns BADKEY */
1180        ret == ERROR_ACCESS_DENIED, /* non-admin winxp */
1181        "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
1182     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1183
1184     /* try a NULL hkey */
1185     SetLastError(0xdeadbeef);
1186     size = MAX_PATH;
1187     ret = RegQueryValueA(NULL, "subkey", val, &size);
1188     ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 98 returns BADKEY */
1189        "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
1190     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1191
1192     /* try a NULL value */
1193     size = MAX_PATH;
1194     ret = RegQueryValueA(hkey_main, "subkey", NULL, &size);
1195     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1196     ok(size == 5, "Expected 5, got %d\n", size);
1197
1198     /* try a NULL size */
1199     SetLastError(0xdeadbeef);
1200     val[0] = '\0';
1201     ret = RegQueryValueA(hkey_main, "subkey", val, NULL);
1202     ok(ret == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", ret);
1203     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1204     ok(lstrlenA(val) == 0, "Expected val to be untouched, got %s\n", val);
1205
1206     /* try a NULL value and size */
1207     ret = RegQueryValueA(hkey_main, "subkey", NULL, NULL);
1208     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1209
1210     /* try a size too small */
1211     SetLastError(0xdeadbeef);
1212     val[0] = '\0';
1213     size = 1;
1214     ret = RegQueryValueA(hkey_main, "subkey", val, &size);
1215     ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret);
1216     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1217     ok(lstrlenA(val) == 0, "Expected val to be untouched, got %s\n", val);
1218     ok(size == 5, "Expected 5, got %d\n", size);
1219
1220     /* successfully read the value using 'subkey' */
1221     size = MAX_PATH;
1222     ret = RegQueryValueA(hkey_main, "subkey", val, &size);
1223     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1224     ok(!lstrcmpA(val, "data"), "Expected 'data', got '%s'\n", val);
1225     ok(size == 5, "Expected 5, got %d\n", size);
1226
1227     /* successfully read the value using the subkey key */
1228     size = MAX_PATH;
1229     ret = RegQueryValueA(subkey, NULL, val, &size);
1230     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1231     ok(!lstrcmpA(val, "data"), "Expected 'data', got '%s'\n", val);
1232     ok(size == 5, "Expected 5, got %d\n", size);
1233
1234     /* unicode - try size too small */
1235     SetLastError(0xdeadbeef);
1236     valW[0] = '\0';
1237     size = 0;
1238     ret = RegQueryValueW(subkey, NULL, valW, &size);
1239     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1240     {
1241         win_skip("RegQueryValueW is not implemented\n");
1242         goto cleanup;
1243     }
1244     ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret);
1245     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1246     ok(lstrlenW(valW) == 0, "Expected valW to be untouched\n");
1247     ok(size == sizeof(expected), "Got wrong size: %d\n", size);
1248
1249     /* unicode - try size in WCHARS */
1250     SetLastError(0xdeadbeef);
1251     size = sizeof(valW) / sizeof(WCHAR);
1252     ret = RegQueryValueW(subkey, NULL, valW, &size);
1253     ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret);
1254     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
1255     ok(lstrlenW(valW) == 0, "Expected valW to be untouched\n");
1256     ok(size == sizeof(expected), "Got wrong size: %d\n", size);
1257
1258     /* unicode - successfully read the value */
1259     size = sizeof(valW);
1260     ret = RegQueryValueW(subkey, NULL, valW, &size);
1261     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1262     ok(!lstrcmpW(valW, expected), "Got wrong value\n");
1263     ok(size == sizeof(expected), "Got wrong size: %d\n", size);
1264
1265     /* unicode - set the value without a NULL terminator */
1266     ret = RegSetValueW(subkey, NULL, REG_SZ, expected, sizeof(expected)-sizeof(WCHAR));
1267     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1268
1269     /* unicode - read the unterminated value, value is terminated for us */
1270     memset(valW, 'a', sizeof(valW));
1271     size = sizeof(valW);
1272     ret = RegQueryValueW(subkey, NULL, valW, &size);
1273     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1274     ok(!lstrcmpW(valW, expected), "Got wrong value\n");
1275     ok(size == sizeof(expected), "Got wrong size: %d\n", size);
1276
1277 cleanup:
1278     RegDeleteKeyA(subkey, "");
1279     RegCloseKey(subkey);
1280 }
1281
1282 static void test_string_termination(void)
1283 {
1284     HKEY subkey;
1285     LSTATUS ret;
1286     static const char string[] = "FullString";
1287     char name[11];
1288     BYTE buffer[11];
1289     DWORD insize, outsize, nsize;
1290
1291     ret = RegCreateKeyA(hkey_main, "string_termination", &subkey);
1292     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1293
1294     /* Off-by-one RegSetValueExA -> adds a trailing '\0'! */
1295     insize=sizeof(string)-1;
1296     ret = RegSetValueExA(subkey, "stringtest", 0, REG_SZ, (BYTE*)string, insize);
1297     ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", ret);
1298     outsize=insize;
1299     ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize);
1300     ok(ret == ERROR_MORE_DATA, "RegQueryValueExA returned: %d\n", ret);
1301
1302     /* Off-by-two RegSetValueExA -> no trailing '\0', except on Win9x */
1303     insize=sizeof(string)-2;
1304     ret = RegSetValueExA(subkey, "stringtest", 0, REG_SZ, (BYTE*)string, insize);
1305     ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", ret);
1306     outsize=0;
1307     ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, NULL, &outsize);
1308     ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", ret);
1309     ok(outsize == insize || broken(outsize == sizeof(string)) /* Win9x */,
1310        "wrong size %u != %u\n", outsize, insize);
1311
1312     if (outsize == insize)
1313     {
1314         /* RegQueryValueExA may return a string with no trailing '\0' */
1315         outsize=insize;
1316         memset(buffer, 0xbd, sizeof(buffer));
1317         ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize);
1318         ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", ret);
1319         ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize);
1320         ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n",
1321            wine_debugstr_an((char*)buffer, outsize), outsize, string);
1322         ok(buffer[insize] == 0xbd, "buffer overflow at %u %02x\n", insize, buffer[insize]);
1323
1324         /* RegQueryValueExA adds a trailing '\0' if there is room */
1325         outsize=insize+1;
1326         memset(buffer, 0xbd, sizeof(buffer));
1327         ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize);
1328         ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", ret);
1329         ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize);
1330         ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n",
1331            wine_debugstr_an((char*)buffer, outsize), outsize, string);
1332         ok(buffer[insize] == 0, "buffer overflow at %u %02x\n", insize, buffer[insize]);
1333
1334         /* RegEnumValueA may return a string with no trailing '\0' */
1335         outsize=insize;
1336         memset(buffer, 0xbd, sizeof(buffer));
1337         nsize=sizeof(name);
1338         ret = RegEnumValueA(subkey, 0, name, &nsize, NULL, NULL, buffer, &outsize);
1339         ok(ret == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", ret);
1340         ok(strcmp(name, "stringtest") == 0, "wrong name: %s\n", name);
1341         ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize);
1342         ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n",
1343            wine_debugstr_an((char*)buffer, outsize), outsize, string);
1344         ok(buffer[insize] == 0xbd, "buffer overflow at %u %02x\n", insize, buffer[insize]);
1345
1346         /* RegEnumValueA adds a trailing '\0' if there is room */
1347         outsize=insize+1;
1348         memset(buffer, 0xbd, sizeof(buffer));
1349         nsize=sizeof(name);
1350         ret = RegEnumValueA(subkey, 0, name, &nsize, NULL, NULL, buffer, &outsize);
1351         ok(ret == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", ret);
1352         ok(strcmp(name, "stringtest") == 0, "wrong name: %s\n", name);
1353         ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize);
1354         ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n",
1355            wine_debugstr_an((char*)buffer, outsize), outsize, string);
1356         ok(buffer[insize] == 0, "buffer overflow at %u %02x\n", insize, buffer[insize]);
1357     }
1358
1359     RegDeleteKeyA(subkey, "");
1360     RegCloseKey(subkey);
1361 }
1362
1363 static void test_reg_delete_tree(void)
1364 {
1365     CHAR buffer[MAX_PATH];
1366     HKEY subkey, subkey2;
1367     LONG size, ret;
1368
1369     if(!pRegDeleteTreeA) {
1370         win_skip("Skipping RegDeleteTreeA tests, function not present\n");
1371         return;
1372     }
1373
1374     ret = RegCreateKeyA(hkey_main, "subkey", &subkey);
1375     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1376     ret = RegCreateKeyA(subkey, "subkey2", &subkey2);
1377     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1378     ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4);
1379     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1380     ret = RegSetValueA(subkey2, NULL, REG_SZ, "data2", 5);
1381     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1382     ret = RegCloseKey(subkey2);
1383     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1384
1385     ret = pRegDeleteTreeA(subkey, "subkey2");
1386     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1387     ok(RegOpenKeyA(subkey, "subkey2", &subkey2),
1388         "subkey2 was not deleted\n");
1389     size = MAX_PATH;
1390     ok(!RegQueryValueA(subkey, NULL, buffer, &size),
1391         "Default value of subkey not longer present\n");
1392
1393     ret = RegCreateKeyA(subkey, "subkey2", &subkey2);
1394     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1395     ret = RegCloseKey(subkey2);
1396     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1397     ret = pRegDeleteTreeA(hkey_main, "subkey\\subkey2");
1398     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1399     ok(RegOpenKeyA(subkey, "subkey2", &subkey2),
1400         "subkey2 was not deleted\n");
1401     ok(!RegQueryValueA(subkey, NULL, buffer, &size),
1402         "Default value of subkey not longer present\n");
1403
1404     ret = RegCreateKeyA(subkey, "subkey2", &subkey2);
1405     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1406     ret = RegCloseKey(subkey2);
1407     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1408     ret = RegCreateKeyA(subkey, "subkey3", &subkey2);
1409     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1410     ret = RegCloseKey(subkey2);
1411     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1412     ret = RegSetValueA(subkey, "value", REG_SZ, "data2", 5);
1413     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1414     ret = pRegDeleteTreeA(subkey, NULL);
1415     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
1416     ok(!RegOpenKeyA(hkey_main, "subkey", &subkey),
1417         "subkey was deleted\n");
1418     ok(RegOpenKeyA(subkey, "subkey2", &subkey2),
1419         "subkey2 was not deleted\n");
1420     ok(RegOpenKeyA(subkey, "subkey3", &subkey2),
1421         "subkey3 was not deleted\n");
1422     size = MAX_PATH;
1423     ret = RegQueryValueA(subkey, NULL, buffer, &size);
1424     ok(ret == ERROR_SUCCESS,
1425         "Default value of subkey is not present\n");
1426     ok(!lstrlenA(buffer),
1427         "Expected length 0 got length %u(%s)\n", lstrlenA(buffer), buffer);
1428     size = MAX_PATH;
1429     ok(RegQueryValueA(subkey, "value", buffer, &size),
1430         "Value is still present\n");
1431
1432     ret = pRegDeleteTreeA(hkey_main, "not-here");
1433     ok(ret == ERROR_FILE_NOT_FOUND,
1434         "Expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
1435 }
1436
1437 static void test_rw_order(void)
1438 {
1439     HKEY hKey;
1440     DWORD dw = 0;
1441     static char keyname[] = "test_rw_order";
1442     char value_buf[2];
1443     DWORD values, value_len, value_name_max_len;
1444     LSTATUS ret;
1445
1446     RegDeleteKeyA(HKEY_CURRENT_USER, keyname);
1447     ret = RegCreateKeyA(HKEY_CURRENT_USER, keyname, &hKey);
1448     if(ret != ERROR_SUCCESS) {
1449         skip("Couldn't create key. Skipping.\n");
1450         return;
1451     }
1452
1453     ok(!RegSetValueExA(hKey, "A", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)),
1454        "RegSetValueExA for value \"A\" failed\n");
1455     ok(!RegSetValueExA(hKey, "C", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)),
1456        "RegSetValueExA for value \"C\" failed\n");
1457     ok(!RegSetValueExA(hKey, "D", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)),
1458        "RegSetValueExA for value \"D\" failed\n");
1459     ok(!RegSetValueExA(hKey, "B", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)),
1460        "RegSetValueExA for value \"B\" failed\n");
1461
1462     ok(!RegQueryInfoKeyA(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &values,
1463        &value_name_max_len, NULL, NULL, NULL), "RegQueryInfoKeyA failed\n");
1464     ok(values == 4, "Expected 4 values, got %u\n", values);
1465
1466     /* Value enumeration preserves RegSetValueEx call order */
1467     value_len = 2;
1468     ok(!RegEnumValueA(hKey, 0, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n");
1469     ok(strcmp(value_buf, "A") == 0, "Expected name \"A\", got %s\n", value_buf);
1470     value_len = 2;
1471     ok(!RegEnumValueA(hKey, 1, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n");
1472     todo_wine ok(strcmp(value_buf, "C") == 0, "Expected name \"C\", got %s\n", value_buf);
1473     value_len = 2;
1474     ok(!RegEnumValueA(hKey, 2, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n");
1475     todo_wine ok(strcmp(value_buf, "D") == 0, "Expected name \"D\", got %s\n", value_buf);
1476     value_len = 2;
1477     ok(!RegEnumValueA(hKey, 3, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n");
1478     todo_wine ok(strcmp(value_buf, "B") == 0, "Expected name \"B\", got %s\n", value_buf);
1479
1480     ok(!RegDeleteKey(HKEY_CURRENT_USER, keyname), "Failed to delete key\n");
1481 }
1482
1483 START_TEST(registry)
1484 {
1485     /* Load pointers for functions that are not available in all Windows versions */
1486     InitFunctionPtrs();
1487
1488     setup_main_key();
1489     test_set_value();
1490     create_test_entries();
1491     test_enum_value();
1492     test_query_value_ex();
1493     test_get_value();
1494     test_reg_open_key();
1495     test_reg_create_key();
1496     test_reg_close_key();
1497     test_reg_delete_key();
1498     test_reg_query_value();
1499     test_string_termination();
1500
1501     /* SaveKey/LoadKey require the SE_BACKUP_NAME privilege to be set */
1502     if (set_privileges(SE_BACKUP_NAME, TRUE) &&
1503         set_privileges(SE_RESTORE_NAME, TRUE))
1504     {
1505         test_reg_save_key();
1506         test_reg_load_key();
1507         test_reg_unload_key();
1508
1509         set_privileges(SE_BACKUP_NAME, FALSE);
1510         set_privileges(SE_RESTORE_NAME, FALSE);
1511     }
1512
1513     test_reg_delete_tree();
1514     test_rw_order();
1515
1516     /* cleanup */
1517     delete_key( hkey_main );
1518     
1519     test_regconnectregistry();
1520 }