advapi32/tests: Add check to see if SetEntriesInAclW is implemented.
[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 "wine/test.h"
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winreg.h"
27 #include "winsvc.h"
28 #include "winerror.h"
29
30 static HKEY hkey_main;
31 static DWORD GLE;
32
33 static const char * sTestpath1 = "%LONGSYSTEMVAR%\\subdir1";
34 static const char * sTestpath2 = "%FOO%\\subdir1";
35
36 static HMODULE hadvapi32;
37 static DWORD (WINAPI *pRegGetValueA)(HKEY,LPCSTR,LPCSTR,DWORD,LPDWORD,PVOID,LPDWORD);
38
39 #define ADVAPI32_GET_PROC(func) \
40     p ## func = (void*)GetProcAddress(hadvapi32, #func); \
41     if(!p ## func) \
42       trace("GetProcAddress(%s) failed\n", #func);
43
44 static void InitFunctionPtrs(void)
45 {
46     hadvapi32 = GetModuleHandleA("advapi32.dll");
47
48     /* This function was introduced with Windows 2003 SP1 */
49     ADVAPI32_GET_PROC(RegGetValueA)
50 }
51
52 /* delete key and all its subkeys */
53 static DWORD delete_key( HKEY hkey )
54 {
55     char name[MAX_PATH];
56     DWORD ret;
57
58     while (!(ret = RegEnumKeyA(hkey, 0, name, sizeof(name))))
59     {
60         HKEY tmp;
61         if (!(ret = RegOpenKeyExA( hkey, name, 0, KEY_ENUMERATE_SUB_KEYS, &tmp )))
62         {
63             ret = delete_key( tmp );
64             RegCloseKey( tmp );
65         }
66         if (ret) break;
67     }
68     if (ret != ERROR_NO_MORE_ITEMS) return ret;
69     RegDeleteKeyA( hkey, "" );
70     return 0;
71 }
72
73 static void setup_main_key(void)
74 {
75     if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main )) delete_key( hkey_main );
76
77     assert (!RegCreateKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main ));
78 }
79
80 static void test_hkey_main_Value_A(LPCSTR name, LPCSTR string)
81 {
82     DWORD ret, type, cbData;
83     DWORD str_byte_len, full_byte_len;
84
85     ret = RegQueryValueExA(hkey_main, name, NULL, &type, NULL, &cbData);
86     GLE = GetLastError();
87     ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%d\n", ret, GLE);
88     if(GLE == ERROR_CALL_NOT_IMPLEMENTED) return;
89
90     str_byte_len = lstrlenA(string) + 1;
91     full_byte_len = sizeof(string);
92     ok(type == REG_SZ, "RegQueryValueExA returned type %d\n", type);
93     ok(cbData == full_byte_len || cbData == str_byte_len,
94         "cbData=%d instead of %d or %d\n", cbData, full_byte_len, str_byte_len);
95 }
96
97 static void test_hkey_main_Value_W(LPCWSTR name, LPCWSTR string)
98 {
99     DWORD ret, type, cbData;
100     DWORD str_byte_len, full_byte_len;
101
102     ret = RegQueryValueExW(hkey_main, name, NULL, &type, NULL, &cbData);
103     GLE = GetLastError();
104     ok(ret == ERROR_SUCCESS, "RegQueryValueExW failed: %d, GLE=%d\n", ret, GLE);
105     if(GLE == ERROR_CALL_NOT_IMPLEMENTED) return;
106
107     str_byte_len = (lstrlenW(string) + 1) * sizeof(WCHAR);
108     full_byte_len = sizeof(string);
109     ok(type == REG_SZ, "RegQueryValueExW returned type %d\n", type);
110     ok(cbData == full_byte_len || cbData == str_byte_len,
111         "cbData=%d instead of %d or %d\n", cbData, full_byte_len, str_byte_len);
112 }
113
114 static void test_set_value(void)
115 {
116     DWORD ret;
117
118     static const WCHAR name1W[] =   {'C','l','e','a','n','S','i','n','g','l','e','S','t','r','i','n','g', 0};
119     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};
120     static const WCHAR string1W[] = {'T','h','i','s','N','e','v','e','r','B','r','e','a','k','s', 0};
121     static const WCHAR string2W[] = {'T','h','i','s', 0 ,'B','r','e','a','k','s', 0 , 0 ,'A', 0 , 0 , 0 , 0 ,'L','o','t', 0 , 0 , 0 , 0};
122
123     static const char name1A[] =   "CleanSingleString";
124     static const char name2A[] =   "SomeIntraZeroedString";
125     static const char string1A[] = "ThisNeverBreaks";
126     static const char string2A[] = "This\0Breaks\0\0A\0\0\0Lot\0\0\0\0";
127
128     /* test RegSetValueExA with normal string */
129     ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)string1A, sizeof(string1A));
130     ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
131     test_hkey_main_Value_A(name1A, string1A);
132     test_hkey_main_Value_W(name1W, string1W);
133
134     /* test RegSetValueExA with intrazeroed string */
135     ret = RegSetValueExA(hkey_main, name2A, 0, REG_SZ, (const BYTE *)string2A, sizeof(string2A));
136     ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError());
137     test_hkey_main_Value_A(name1A, string1A);
138     test_hkey_main_Value_W(name1W, string1W);
139
140     /* 9x doesn't support W-calls, so don't test them then */
141     if(GLE == ERROR_CALL_NOT_IMPLEMENTED) return; 
142
143     /* test RegSetValueExW with normal string */
144     ret = RegSetValueExW(hkey_main, name1W, 0, REG_SZ, (const BYTE *)string1W, sizeof(string1W));
145     ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %d, GLE=%d\n", ret, GetLastError());
146     test_hkey_main_Value_A(name1A, string1A);
147     test_hkey_main_Value_W(name1W, string1W);
148
149     /* test RegSetValueExW with intrazeroed string */
150     ret = RegSetValueExW(hkey_main, name2W, 0, REG_SZ, (const BYTE *)string2W, sizeof(string2W));
151     ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %d, GLE=%d\n", ret, GetLastError());
152     test_hkey_main_Value_A(name1A, string1A);
153     test_hkey_main_Value_W(name1W, string1W);
154 }
155
156 static void create_test_entries(void)
157 {
158     static const DWORD qw[2] = { 0x12345678, 0x87654321 };
159
160     SetEnvironmentVariableA("LONGSYSTEMVAR", "bar");
161     SetEnvironmentVariableA("FOO", "ImARatherLongButIndeedNeededString");
162
163     ok(!RegSetValueExA(hkey_main,"TP1_EXP_SZ",0,REG_EXPAND_SZ, (const BYTE *)sTestpath1, strlen(sTestpath1)+1), 
164         "RegSetValueExA failed\n");
165     ok(!RegSetValueExA(hkey_main,"TP1_SZ",0,REG_SZ, (const BYTE *)sTestpath1, strlen(sTestpath1)+1), 
166         "RegSetValueExA failed\n");
167     ok(!RegSetValueExA(hkey_main,"TP2_EXP_SZ",0,REG_EXPAND_SZ, (const BYTE *)sTestpath2, strlen(sTestpath2)+1), 
168         "RegSetValueExA failed\n");
169     ok(!RegSetValueExA(hkey_main,"DWORD",0,REG_DWORD, (const BYTE *)qw, 4),
170         "RegSetValueExA failed\n");
171     ok(!RegSetValueExA(hkey_main,"BIN32",0,REG_BINARY, (const BYTE *)qw, 4),
172         "RegSetValueExA failed\n");
173     ok(!RegSetValueExA(hkey_main,"BIN64",0,REG_BINARY, (const BYTE *)qw, 8),
174         "RegSetValueExA failed\n");
175 }
176         
177 static void test_enum_value(void)
178 {
179     DWORD res;
180     HKEY test_key;
181     char value[20], data[20];
182     WCHAR valueW[20], dataW[20];
183     DWORD val_count, data_count, type;
184     static const WCHAR foobarW[] = {'f','o','o','b','a','r',0};
185     static const WCHAR testW[] = {'T','e','s','t',0};
186     static const WCHAR xxxW[] = {'x','x','x','x','x','x','x','x',0};
187
188     /* create the working key for new 'Test' value */
189     res = RegCreateKeyA( hkey_main, "TestKey", &test_key );
190     ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res);
191
192     /* check NULL data with zero length */
193     res = RegSetValueExA( test_key, "Test", 0, REG_SZ, NULL, 0 );
194     if (GetVersion() & 0x80000000)
195         ok( res == ERROR_INVALID_PARAMETER, "RegSetValueExA returned %d\n", res );
196     else
197         ok( !res, "RegSetValueExA returned %d\n", res );
198     res = RegSetValueExA( test_key, "Test", 0, REG_EXPAND_SZ, NULL, 0 );
199     ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %d\n", res );
200     res = RegSetValueExA( test_key, "Test", 0, REG_BINARY, NULL, 0 );
201     ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %d\n", res );
202
203     res = RegSetValueExA( test_key, "Test", 0, REG_SZ, (const BYTE *)"foobar", 7 );
204     ok( res == 0, "RegSetValueExA failed error %d\n", res );
205
206     /* overflow both name and data */
207     val_count = 2;
208     data_count = 2;
209     type = 1234;
210     strcpy( value, "xxxxxxxxxx" );
211     strcpy( data, "xxxxxxxxxx" );
212     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
213     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
214     ok( val_count == 2, "val_count set to %d\n", val_count );
215     ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
216     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
217     ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
218     ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data );
219
220     /* overflow name */
221     val_count = 3;
222     data_count = 20;
223     type = 1234;
224     strcpy( value, "xxxxxxxxxx" );
225     strcpy( data, "xxxxxxxxxx" );
226     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
227     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
228     /* Win9x returns 2 as specified by MSDN but NT returns 3... */
229     ok( val_count == 2 || val_count == 3, "val_count set to %d\n", val_count );
230     ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
231     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
232     /* v5.1.2600.0 (XP Home and Proffesional) does not touch value or data in this case */
233     ok( !strcmp( value, "Te" ) || !strcmp( value, "xxxxxxxxxx" ), 
234         "value set to '%s' instead of 'Te' or 'xxxxxxxxxx'\n", value );
235     ok( !strcmp( data, "foobar" ) || !strcmp( data, "xxxxxxx" ), 
236         "data set to '%s' instead of 'foobar' or 'xxxxxxx'\n", data );
237
238     /* overflow empty name */
239     val_count = 0;
240     data_count = 20;
241     type = 1234;
242     strcpy( value, "xxxxxxxxxx" );
243     strcpy( data, "xxxxxxxxxx" );
244     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
245     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
246     ok( val_count == 0, "val_count set to %d\n", val_count );
247     ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
248     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
249     ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
250     /* v5.1.2600.0 (XP Home and Professional) does not touch data in this case */
251     ok( !strcmp( data, "foobar" ) || !strcmp( data, "xxxxxxx" ), 
252         "data set to '%s' instead of 'foobar' or 'xxxxxxx'\n", data );
253
254     /* overflow data */
255     val_count = 20;
256     data_count = 2;
257     type = 1234;
258     strcpy( value, "xxxxxxxxxx" );
259     strcpy( data, "xxxxxxxxxx" );
260     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
261     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
262     ok( val_count == 20, "val_count set to %d\n", val_count );
263     ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
264     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
265     ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
266     ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data );
267
268     /* no overflow */
269     val_count = 20;
270     data_count = 20;
271     type = 1234;
272     strcpy( value, "xxxxxxxxxx" );
273     strcpy( data, "xxxxxxxxxx" );
274     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
275     ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res );
276     ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
277     ok( data_count == 7, "data_count set to %d instead of 7\n", data_count );
278     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
279     ok( !strcmp( value, "Test" ), "value is '%s' instead of Test\n", value );
280     ok( !strcmp( data, "foobar" ), "data is '%s' instead of foobar\n", data );
281
282     /* Unicode tests */
283
284     SetLastError(0);
285     res = RegSetValueExW( test_key, testW, 0, REG_SZ, (const BYTE *)foobarW, 7*sizeof(WCHAR) );
286     if (res==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
287         return;
288     ok( res == 0, "RegSetValueExW failed error %d\n", res );
289
290     /* overflow both name and data */
291     val_count = 2;
292     data_count = 2;
293     type = 1234;
294     memcpy( valueW, xxxW, sizeof(xxxW) );
295     memcpy( dataW, xxxW, sizeof(xxxW) );
296     res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
297     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
298     ok( val_count == 2, "val_count set to %d\n", val_count );
299     ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
300     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
301     ok( !memcmp( valueW, xxxW, sizeof(xxxW) ), "value modified\n" );
302     ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
303
304     /* overflow name */
305     val_count = 3;
306     data_count = 20;
307     type = 1234;
308     memcpy( valueW, xxxW, sizeof(xxxW) );
309     memcpy( dataW, xxxW, sizeof(xxxW) );
310     res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
311     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
312     ok( val_count == 3, "val_count set to %d\n", val_count );
313     ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
314     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
315     ok( !memcmp( valueW, xxxW, sizeof(xxxW) ), "value modified\n" );
316     ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
317
318     /* overflow data */
319     val_count = 20;
320     data_count = 2;
321     type = 1234;
322     memcpy( valueW, xxxW, sizeof(xxxW) );
323     memcpy( dataW, xxxW, sizeof(xxxW) );
324     res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
325     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res );
326     ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
327     ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
328     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
329     ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" );
330     ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
331
332     /* no overflow */
333     val_count = 20;
334     data_count = 20;
335     type = 1234;
336     memcpy( valueW, xxxW, sizeof(xxxW) );
337     memcpy( dataW, xxxW, sizeof(xxxW) );
338     res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
339     ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res );
340     ok( val_count == 4, "val_count set to %d instead of 4\n", val_count );
341     ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count );
342     ok( type == REG_SZ, "type %d is not REG_SZ\n", type );
343     ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" );
344     ok( !memcmp( dataW, foobarW, sizeof(foobarW) ), "data is not 'foobar'\n" );
345 }
346
347 static void test_query_value_ex(void)
348 {
349     DWORD ret;
350     DWORD size;
351     DWORD type;
352     BYTE buffer[10];
353     
354     ret = RegQueryValueExA(hkey_main, "TP1_SZ", NULL, &type, NULL, &size);
355     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
356     ok(size == strlen(sTestpath1) + 1, "(%d,%d)\n", (DWORD)strlen(sTestpath1) + 1, size);
357     ok(type == REG_SZ, "type %d is not REG_SZ\n", type);
358
359     type = 0xdeadbeef;
360     size = 0xdeadbeef;
361     ret = RegQueryValueExA(HKEY_CLASSES_ROOT, "Nonexistent Value", NULL, &type, NULL, &size);
362     ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
363     ok(size == 0, "size should have been set to 0 instead of %d\n", size);
364     /* the type parameter is cleared on Win9x, but is set to a random value on
365      * NT, so don't do this test there */
366     if (GetVersion() & 0x80000000)
367         ok(type == 0, "type should have been set to 0 instead of 0x%x\n", type);
368     else
369         trace("test_query_value_ex: type set to: 0x%08x\n", type);
370
371     size = sizeof(buffer);
372     ret = RegQueryValueExA(HKEY_CLASSES_ROOT, "Nonexistent Value", NULL, &type, buffer, &size);
373     ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
374     ok(size == sizeof(buffer), "size shouldn't have been changed to %d\n", size);
375 }
376
377 static void test_get_value(void)
378 {
379     DWORD ret;
380     DWORD size;
381     DWORD type;
382     DWORD dw, qw[2];
383     CHAR buf[80];
384     CHAR expanded[] = "bar\\subdir1";
385    
386     if(!pRegGetValueA)
387     {
388         skip("RegGetValue not available on this platform\n");
389         return;
390     }
391
392     /* Query REG_DWORD using RRF_RT_REG_DWORD (ok) */
393     size = type = dw = 0xdeadbeef;
394     ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_DWORD, &type, &dw, &size);
395     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
396     ok(size == 4, "size=%d\n", size);
397     ok(type == REG_DWORD, "type=%d\n", type);
398     ok(dw == 0x12345678, "dw=%d\n", dw);
399
400     /* Query by subkey-name */
401     ret = pRegGetValueA(HKEY_CURRENT_USER, "Software\\Wine\\Test", "DWORD", RRF_RT_REG_DWORD, NULL, NULL, NULL);
402     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
403
404     /* Query REG_DWORD using RRF_RT_REG_BINARY (restricted) */
405     size = type = dw = 0xdeadbeef;
406     ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_BINARY, &type, &dw, &size);
407     ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
408     /* Although the function failed all values are retrieved */
409     ok(size == 4, "size=%d\n", size);
410     ok(type == REG_DWORD, "type=%d\n", type);
411     ok(dw == 0x12345678, "dw=%d\n", dw);
412
413     /* Test RRF_ZEROONFAILURE */
414     type = dw = 0xdeadbeef; size = 4;
415     ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_SZ|RRF_ZEROONFAILURE, &type, &dw, &size);
416     ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
417     /* Again all values are retrieved ... */
418     ok(size == 4, "size=%d\n", size);
419     ok(type == REG_DWORD, "type=%d\n", type);
420     /* ... except the buffer, which is zeroed out */
421     ok(dw == 0, "dw=%d\n", dw);
422
423     /* Query REG_DWORD using RRF_RT_DWORD (ok) */
424     size = type = dw = 0xdeadbeef;
425     ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_DWORD, &type, &dw, &size);
426     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
427     ok(size == 4, "size=%d\n", size);
428     ok(type == REG_DWORD, "type=%d\n", type);
429     ok(dw == 0x12345678, "dw=%d\n", dw);
430
431     /* Query 32-bit REG_BINARY using RRF_RT_DWORD (ok) */
432     size = type = dw = 0xdeadbeef;
433     ret = pRegGetValueA(hkey_main, NULL, "BIN32", RRF_RT_DWORD, &type, &dw, &size);
434     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
435     ok(size == 4, "size=%d\n", size);
436     ok(type == REG_BINARY, "type=%d\n", type);
437     ok(dw == 0x12345678, "dw=%d\n", dw);
438     
439     /* Query 64-bit REG_BINARY using RRF_RT_DWORD (type mismatch) */
440     qw[0] = qw[1] = size = type = 0xdeadbeef;
441     ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_DWORD, &type, qw, &size);
442     ok(ret == ERROR_DATATYPE_MISMATCH, "ret=%d\n", ret);
443     ok(size == 8, "size=%d\n", size);
444     ok(type == REG_BINARY, "type=%d\n", type);
445     ok(qw[0] == 0x12345678 && 
446        qw[1] == 0x87654321, "qw={%d,%d}\n", qw[0], qw[1]);
447     
448     /* Query 64-bit REG_BINARY using 32-bit buffer (buffer too small) */
449     type = dw = 0xdeadbeef; size = 4;
450     ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_REG_BINARY, &type, &dw, &size);
451     ok(ret == ERROR_MORE_DATA, "ret=%d\n", ret);
452     ok(dw == 0xdeadbeef, "dw=%d\n", dw);
453     ok(size == 8, "size=%d\n", size);
454
455     /* Query 64-bit REG_BINARY using RRF_RT_QWORD (ok) */
456     qw[0] = qw[1] = size = type = 0xdeadbeef;
457     ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_QWORD, &type, qw, &size);
458     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
459     ok(size == 8, "size=%d\n", size);
460     ok(type == REG_BINARY, "type=%d\n", type);
461     ok(qw[0] == 0x12345678 &&
462        qw[1] == 0x87654321, "qw={%d,%d}\n", qw[0], qw[1]);
463
464     /* Query REG_SZ using RRF_RT_REG_SZ (ok) */
465     buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
466     ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ, &type, buf, &size);
467     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
468     ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
469     ok(type == REG_SZ, "type=%d\n", type);
470     ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
471
472     /* Query REG_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (ok) */
473     buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
474     ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ|RRF_NOEXPAND, &type, buf, &size);
475     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
476     ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
477     ok(type == REG_SZ, "type=%d\n", type);
478     ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
479
480     /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ (ok, expands) */
481     buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
482     ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_SZ, &type, buf, &size);
483     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
484     /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath1 length + 1 here. */
485     ok((size == strlen(expanded)+1) || (size == strlen(sTestpath1)+1), 
486         "strlen(expanded)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded), lstrlenA(sTestpath1), size);
487     ok(type == REG_SZ, "type=%d\n", type);
488     ok(!strcmp(expanded, buf), "expanded=\"%s\" buf=\"%s\"\n", expanded, buf);
489     
490     /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND (ok, doesn't expand) */
491     buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
492     ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND, &type, buf, &size);
493     ok(ret == ERROR_SUCCESS, "ret=%d\n", ret);
494     ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size);
495     ok(type == REG_EXPAND_SZ, "type=%d\n", type);
496     ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
497     
498     /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (type mismatch) */
499     ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_SZ|RRF_NOEXPAND, NULL, NULL, NULL);
500     ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret);
501
502     /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ (not allowed without RRF_NOEXPAND) */
503     ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ, NULL, NULL, NULL);
504     ok(ret == ERROR_INVALID_PARAMETER, "ret=%d\n", ret);
505
506
507 static void test_reg_open_key(void)
508 {
509     DWORD ret = 0;
510     HKEY hkResult = NULL;
511     HKEY hkPreserve = NULL;
512
513     /* successful open */
514     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult);
515     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
516     ok(hkResult != NULL, "expected hkResult != NULL\n");
517     hkPreserve = hkResult;
518
519     /* these tests fail on Win9x, but we want to be compatible with NT, so
520      * run them if we can */
521     if (!(GetVersion() & 0x80000000))
522     {
523         /* open same key twice */
524         ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult);
525         ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
526         ok(hkResult != hkPreserve, "epxected hkResult != hkPreserve\n");
527         ok(hkResult != NULL, "hkResult != NULL\n");
528         RegCloseKey(hkResult);
529     
530         /* open nonexistent key
531         * check that hkResult is set to NULL
532         */
533         hkResult = hkPreserve;
534         ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
535         ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
536         ok(hkResult == NULL, "expected hkResult == NULL\n");
537     
538         /* open the same nonexistent key again to make sure the key wasn't created */
539         hkResult = hkPreserve;
540         ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
541         ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
542         ok(hkResult == NULL, "expected hkResult == NULL\n");
543     
544         /* send in NULL lpSubKey
545         * check that hkResult receives the value of hKey
546         */
547         hkResult = hkPreserve;
548         ret = RegOpenKeyA(HKEY_CURRENT_USER, NULL, &hkResult);
549         ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
550         ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
551     
552         /* send empty-string in lpSubKey */
553         hkResult = hkPreserve;
554         ret = RegOpenKeyA(HKEY_CURRENT_USER, "", &hkResult);
555         ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
556         ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
557     
558         /* send in NULL lpSubKey and NULL hKey
559         * hkResult is set to NULL
560         */
561         hkResult = hkPreserve;
562         ret = RegOpenKeyA(NULL, NULL, &hkResult);
563         ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
564         ok(hkResult == NULL, "expected hkResult == NULL\n");
565     }
566
567     /* only send NULL hKey
568      * the value of hkResult remains unchanged
569      */
570     hkResult = hkPreserve;
571     ret = RegOpenKeyA(NULL, "Software\\Wine\\Test", &hkResult);
572     ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */
573        "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
574     ok(hkResult == hkPreserve, "expected hkResult == hkPreserve\n");
575     RegCloseKey(hkResult);
576
577     /* send in NULL hkResult */
578     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", NULL);
579     ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", ret);
580
581     /*  beginning backslash character */
582     ret = RegOpenKeyA(HKEY_CURRENT_USER, "\\Software\\Wine\\Test", &hkResult);
583        ok(ret == ERROR_BAD_PATHNAME || /* NT/2k/XP */
584            ret == ERROR_FILE_NOT_FOUND /* Win9x,ME */
585            , "expected ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %d\n", ret);
586 }
587
588 static void test_reg_create_key(void)
589 {
590     LONG ret;
591     HKEY hkey1, hkey2;
592     ret = RegCreateKeyExA(hkey_main, "Subkey1", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL);
593     ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
594     /* should succeed: all versions of Windows ignore the access rights
595      * to the parent handle */
596     ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey2, NULL);
597     ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
598
599     /* clean up */
600     RegDeleteKey(hkey2, "");
601     RegDeleteKey(hkey1, "");
602
603     /*  beginning backslash character */
604     ret = RegCreateKeyExA(hkey_main, "\\Subkey3", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL);
605     if (!(GetVersion() & 0x80000000))
606         ok(ret == ERROR_BAD_PATHNAME, "expected ERROR_BAD_PATHNAME, got %d\n", ret);
607     else {
608         ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
609         RegDeleteKey(hkey1, NULL);
610     }
611 }
612
613 static void test_reg_close_key(void)
614 {
615     DWORD ret = 0;
616     HKEY hkHandle;
617
618     /* successfully close key
619      * hkHandle remains changed after call to RegCloseKey
620      */
621     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkHandle);
622     ret = RegCloseKey(hkHandle);
623     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
624
625     /* try to close the key twice */
626     ret = RegCloseKey(hkHandle); /* Windows 95 doesn't mind. */
627     ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_SUCCESS,
628        "expected ERROR_INVALID_HANDLE or ERROR_SUCCESS, got %d\n", ret);
629     
630     /* try to close a NULL handle */
631     ret = RegCloseKey(NULL);
632     ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */
633        "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret);
634 }
635
636 static void test_reg_delete_key(void)
637 {
638     DWORD ret;
639
640     ret = RegDeleteKey(hkey_main, NULL);
641     ok(ret == ERROR_INVALID_PARAMETER ||
642        ret == ERROR_ACCESS_DENIED ||
643        ret == ERROR_BADKEY, /* Win95 */
644        "ret=%d\n", ret);
645 }
646
647 static void test_reg_save_key(void)
648 {
649     DWORD ret;
650
651     ret = RegSaveKey(hkey_main, "saved_key", NULL);
652     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
653 }
654
655 static void test_reg_load_key(void)
656 {
657     DWORD ret;
658     HKEY hkHandle;
659
660     ret = RegLoadKey(HKEY_LOCAL_MACHINE, "Test", "saved_key");
661     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
662
663     ret = RegOpenKey(HKEY_LOCAL_MACHINE, "Test", &hkHandle);
664     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
665
666     RegCloseKey(hkHandle);
667 }
668
669 static void test_reg_unload_key(void)
670 {
671     DWORD ret;
672
673     ret = RegUnLoadKey(HKEY_LOCAL_MACHINE, "Test");
674     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
675
676     DeleteFile("saved_key");
677     DeleteFile("saved_key.LOG");
678 }
679
680 static BOOL set_privileges(LPCSTR privilege, BOOL set)
681 {
682     TOKEN_PRIVILEGES tp;
683     HANDLE hToken;
684     LUID luid;
685
686     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
687         return FALSE;
688
689     if(!LookupPrivilegeValue(NULL, privilege, &luid))
690     {
691         CloseHandle(hToken);
692         return FALSE;
693     }
694
695     tp.PrivilegeCount = 1;
696     tp.Privileges[0].Luid = luid;
697     
698     if (set)
699         tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
700     else
701         tp.Privileges[0].Attributes = 0;
702
703     AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
704     if (GetLastError() != ERROR_SUCCESS)
705     {
706         CloseHandle(hToken);
707         return FALSE;
708     }
709
710     CloseHandle(hToken);
711     return TRUE;
712 }
713
714 /* tests that show that RegConnectRegistry and 
715    OpenSCManager accept computer names without the
716    \\ prefix (what MSDN says).   */
717 static void test_regconnectregistry( void)
718 {
719     CHAR compName[MAX_COMPUTERNAME_LENGTH + 1];
720     CHAR netwName[MAX_COMPUTERNAME_LENGTH + 3]; /* 2 chars for double backslash */
721     DWORD len = sizeof(compName) ;
722     BOOL ret;
723     LONG retl;
724     HKEY hkey;
725     SC_HANDLE schnd;
726     DWORD GLE;
727
728     ret = GetComputerNameA(compName, &len);
729     ok( ret, "GetComputerName failed err = %d\n", GetLastError());
730     if( !ret) return;
731
732     lstrcpyA(netwName, "\\\\");
733     lstrcpynA(netwName+2, compName, MAX_COMPUTERNAME_LENGTH + 1);
734
735     retl = RegConnectRegistryA( compName, HKEY_LOCAL_MACHINE, &hkey);
736     ok( !retl || retl == ERROR_DLL_INIT_FAILED, "RegConnectRegistryA failed err = %d\n", retl);
737     if( !retl) RegCloseKey( hkey);
738
739     retl = RegConnectRegistryA( netwName, HKEY_LOCAL_MACHINE, &hkey);
740     ok( !retl || retl == ERROR_DLL_INIT_FAILED, "RegConnectRegistryA failed err = %d\n", retl);
741     if( !retl) RegCloseKey( hkey);
742
743     schnd = OpenSCManagerA( compName, NULL, GENERIC_READ); 
744     GLE = GetLastError();
745     ok( schnd != NULL || GLE==ERROR_CALL_NOT_IMPLEMENTED, 
746         "OpenSCManagerA failed err = %d\n", GLE);
747     CloseServiceHandle( schnd);
748
749     schnd = OpenSCManagerA( netwName, NULL, GENERIC_READ); 
750     GLE = GetLastError();
751     ok( schnd != NULL || GLE==ERROR_CALL_NOT_IMPLEMENTED, 
752         "OpenSCManagerA failed err = %d\n", GLE);
753     CloseServiceHandle( schnd);
754
755 }
756
757 static void test_reg_query_value(void)
758 {
759     HKEY subkey;
760     CHAR val[MAX_PATH];
761     WCHAR valW[5];
762     LONG size, ret;
763
764     static const WCHAR expected[] = {'d','a','t','a',0};
765
766     ret = RegCreateKeyA(hkey_main, "subkey", &subkey);
767     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
768
769     ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4);
770     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
771
772     /* try an invalid hkey */
773     SetLastError(0xdeadbeef);
774     size = MAX_PATH;
775     ret = RegQueryValueA((HKEY)0xcafebabe, "subkey", val, &size);
776     ok(ret == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", ret);
777     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
778
779     /* try a NULL hkey */
780     SetLastError(0xdeadbeef);
781     size = MAX_PATH;
782     ret = RegQueryValueA(NULL, "subkey", val, &size);
783     ok(ret == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", ret);
784     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
785
786     /* try a NULL value */
787     size = MAX_PATH;
788     ret = RegQueryValueA(hkey_main, "subkey", NULL, &size);
789     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
790     ok(size == 5, "Expected 5, got %d\n", size);
791
792     /* try a NULL size */
793     SetLastError(0xdeadbeef);
794     val[0] = '\0';
795     ret = RegQueryValueA(hkey_main, "subkey", val, NULL);
796     ok(ret == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", ret);
797     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
798     ok(lstrlenA(val) == 0, "Expected val to be untouched, got %s\n", val);
799
800     /* try a NULL value and size */
801     ret = RegQueryValueA(hkey_main, "subkey", NULL, NULL);
802     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
803
804     /* try a size too small */
805     SetLastError(0xdeadbeef);
806     val[0] = '\0';
807     size = 1;
808     ret = RegQueryValueA(hkey_main, "subkey", val, &size);
809     ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret);
810     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
811     ok(lstrlenA(val) == 0, "Expected val to be untouched, got %s\n", val);
812     ok(size == 5, "Expected 5, got %d\n", size);
813
814     /* successfully read the value using 'subkey' */
815     size = MAX_PATH;
816     ret = RegQueryValueA(hkey_main, "subkey", val, &size);
817     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
818     ok(!lstrcmpA(val, "data"), "Expected 'data', got '%s'\n", val);
819     ok(size == 5, "Expected 5, got %d\n", size);
820
821     /* successfully read the value using the subkey key */
822     size = MAX_PATH;
823     ret = RegQueryValueA(subkey, NULL, val, &size);
824     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
825     ok(!lstrcmpA(val, "data"), "Expected 'data', got '%s'\n", val);
826     ok(size == 5, "Expected 5, got %d\n", size);
827
828     /* unicode - try size too small */
829     SetLastError(0xdeadbeef);
830     valW[0] = '\0';
831     size = 0;
832     ret = RegQueryValueW(subkey, NULL, valW, &size);
833     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
834     {
835         skip("RegQueryValueW is not implemented\n");
836         goto cleanup;
837     }
838     ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret);
839     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
840     ok(lstrlenW(valW) == 0, "Expected valW to be untouched\n");
841     ok(size == sizeof(expected), "Got wrong size: %d\n", size);
842
843     /* unicode - try size in WCHARS */
844     SetLastError(0xdeadbeef);
845     size = sizeof(valW) / sizeof(WCHAR);
846     ret = RegQueryValueW(subkey, NULL, valW, &size);
847     ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret);
848     ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
849     ok(lstrlenW(valW) == 0, "Expected valW to be untouched\n");
850     ok(size == sizeof(expected), "Got wrong size: %d\n", size);
851
852     /* unicode - successfully read the value */
853     size = sizeof(valW);
854     ret = RegQueryValueW(subkey, NULL, valW, &size);
855     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
856     ok(!lstrcmpW(valW, expected), "Got wrong value\n");
857     ok(size == sizeof(expected), "Got wrong size: %d\n", size);
858
859     /* unicode - set the value without a NULL terminator */
860     ret = RegSetValueW(subkey, NULL, REG_SZ, expected, sizeof(expected)-sizeof(WCHAR));
861     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
862
863     /* unicode - read the unterminated value, value is terminated for us */
864     memset(valW, 'a', sizeof(valW));
865     size = sizeof(valW);
866     ret = RegQueryValueW(subkey, NULL, valW, &size);
867     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
868     ok(!lstrcmpW(valW, expected), "Got wrong value\n");
869     ok(size == sizeof(expected), "Got wrong size: %d\n", size);
870
871 cleanup:
872     RegDeleteKeyA(subkey, "");
873 }
874
875 START_TEST(registry)
876 {
877     /* Load pointers for functions that are not available in all Windows versions */
878     InitFunctionPtrs();
879
880     setup_main_key();
881     test_set_value();
882     create_test_entries();
883     test_enum_value();
884     test_query_value_ex();
885     test_get_value();
886     test_reg_open_key();
887     test_reg_create_key();
888     test_reg_close_key();
889     test_reg_delete_key();
890     test_reg_query_value();
891
892     /* SaveKey/LoadKey require the SE_BACKUP_NAME privilege to be set */
893     if (set_privileges(SE_BACKUP_NAME, TRUE) &&
894         set_privileges(SE_RESTORE_NAME, TRUE))
895     {
896         test_reg_save_key();
897         test_reg_load_key();
898         test_reg_unload_key();
899
900         set_privileges(SE_BACKUP_NAME, FALSE);
901         set_privileges(SE_RESTORE_NAME, FALSE);
902     }
903
904     /* cleanup */
905     delete_key( hkey_main );
906     
907     test_regconnectregistry();
908 }