Stub implementation od IPersist, IPersistMoniker, IPersistFile,
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 "winerror.h"
28
29 static HKEY hkey_main;
30
31 static const char * sTestpath1 = "%LONGSYSTEMVAR%\\subdir1";
32 static const char * sTestpath2 = "%FOO%\\subdir1";
33
34 /* delete key and all its subkeys */
35 static DWORD delete_key( HKEY hkey )
36 {
37     char name[MAX_PATH];
38     DWORD ret;
39
40     while (!(ret = RegEnumKeyA(hkey, 0, name, sizeof(name))))
41     {
42         HKEY tmp;
43         if (!(ret = RegOpenKeyExA( hkey, name, 0, KEY_ENUMERATE_SUB_KEYS, &tmp )))
44         {
45             ret = delete_key( tmp );
46             RegCloseKey( tmp );
47         }
48         if (ret) break;
49     }
50     if (ret != ERROR_NO_MORE_ITEMS) return ret;
51     RegDeleteKeyA( hkey, NULL );
52     return 0;
53 }
54
55 static void setup_main_key(void)
56 {
57     if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main )) delete_key( hkey_main );
58
59     assert (!RegCreateKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main ));
60 }
61
62 static void create_test_entries(void)
63 {
64     SetEnvironmentVariableA("LONGSYSTEMVAR", "bar");
65     SetEnvironmentVariableA("FOO", "ImARatherLongButIndeedNeededString");
66
67     ok(!RegSetValueExA(hkey_main,"Test1",0,REG_EXPAND_SZ, sTestpath1, strlen(sTestpath1)+1), 
68         "RegSetValueExA failed\n");
69     ok(!RegSetValueExA(hkey_main,"Test2",0,REG_SZ, sTestpath1, strlen(sTestpath1)+1), 
70         "RegSetValueExA failed\n");
71     ok(!RegSetValueExA(hkey_main,"Test3",0,REG_EXPAND_SZ, sTestpath2, strlen(sTestpath2)+1), 
72         "RegSetValueExA failed\n");
73 }
74         
75 static void test_enum_value(void)
76 {
77     DWORD res;
78     HKEY test_key;
79     char value[20], data[20];
80     WCHAR valueW[20], dataW[20];
81     DWORD val_count, data_count, type;
82     static const WCHAR foobarW[] = {'f','o','o','b','a','r',0};
83     static const WCHAR testW[] = {'T','e','s','t',0};
84     static const WCHAR xxxW[] = {'x','x','x','x','x','x','x','x',0};
85
86     /* create the working key for new 'Test' value */
87     res = RegCreateKeyA( hkey_main, "TestKey", &test_key );
88     ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res);
89
90     /* check NULL data with zero length */
91     res = RegSetValueExA( test_key, "Test", 0, REG_SZ, NULL, 0 );
92     if (GetVersion() & 0x80000000)
93         ok( res == ERROR_INVALID_PARAMETER, "RegSetValueExA returned %ld\n", res );
94     else
95         ok( !res, "RegSetValueExA returned %ld\n", res );
96     res = RegSetValueExA( test_key, "Test", 0, REG_EXPAND_SZ, NULL, 0 );
97     ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %ld\n", res );
98     if (ERROR_INVALID_PARAMETER == res)
99         trace ("RegSetValueExA() returned ERROR_INVALID_PARAMETER\n");
100     res = RegSetValueExA( test_key, "Test", 0, REG_BINARY, NULL, 0 );
101     ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %ld\n", res );
102     if (ERROR_INVALID_PARAMETER == res)
103         trace ("RegSetValueExA() returned ERROR_INVALID_PARAMETER\n");
104
105     res = RegSetValueExA( test_key, "Test", 0, REG_SZ, (BYTE *)"foobar", 7 );
106     ok( res == 0, "RegSetValueExA failed error %ld\n", res );
107
108     /* overflow both name and data */
109     val_count = 2;
110     data_count = 2;
111     type = 1234;
112     strcpy( value, "xxxxxxxxxx" );
113     strcpy( data, "xxxxxxxxxx" );
114     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, data, &data_count );
115     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
116     ok( val_count == 2, "val_count set to %ld\n", val_count );
117     ok( data_count == 7, "data_count set to %ld instead of 7\n", data_count );
118     ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
119     ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
120     ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data );
121
122     /* overflow name */
123     val_count = 3;
124     data_count = 20;
125     type = 1234;
126     strcpy( value, "xxxxxxxxxx" );
127     strcpy( data, "xxxxxxxxxx" );
128     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, data, &data_count );
129     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
130     /* Win9x returns 2 as specified by MSDN but NT returns 3... */
131     ok( val_count == 2 || val_count == 3, "val_count set to %ld\n", val_count );
132     ok( data_count == 7, "data_count set to %ld instead of 7\n", data_count );
133     ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
134 #if 0
135     /* v5.1.2600.0 (XP Home) does not touch value or data in this case */
136     ok( !strcmp( value, "Te" ), "value set to '%s' instead of 'Te'\n", value );
137     ok( !strcmp( data, "foobar" ), "data set to '%s' instead of 'foobar'\n", data );
138 #endif
139
140     /* overflow empty name */
141     val_count = 0;
142     data_count = 20;
143     type = 1234;
144     strcpy( value, "xxxxxxxxxx" );
145     strcpy( data, "xxxxxxxxxx" );
146     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, data, &data_count );
147     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
148     ok( val_count == 0, "val_count set to %ld\n", val_count );
149     ok( data_count == 7, "data_count set to %ld instead of 7\n", data_count );
150     ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
151     ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
152 #if 0
153     /* v5.1.2600.0 (XP Home) does not touch data in this case */
154     ok( !strcmp( data, "foobar" ), "data set to '%s' instead of 'foobar'\n", data );
155 #endif
156
157     /* overflow data */
158     val_count = 20;
159     data_count = 2;
160     type = 1234;
161     strcpy( value, "xxxxxxxxxx" );
162     strcpy( data, "xxxxxxxxxx" );
163     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, data, &data_count );
164     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
165     ok( val_count == 20, "val_count set to %ld\n", val_count );
166     ok( data_count == 7, "data_count set to %ld instead of 7\n", data_count );
167     ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
168     ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
169     ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data );
170
171     /* no overflow */
172     val_count = 20;
173     data_count = 20;
174     type = 1234;
175     strcpy( value, "xxxxxxxxxx" );
176     strcpy( data, "xxxxxxxxxx" );
177     res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, data, &data_count );
178     ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res );
179     ok( val_count == 4, "val_count set to %ld instead of 4\n", val_count );
180     ok( data_count == 7, "data_count set to %ld instead of 7\n", data_count );
181     ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
182     ok( !strcmp( value, "Test" ), "value is '%s' instead of Test\n", value );
183     ok( !strcmp( data, "foobar" ), "data is '%s' instead of foobar\n", data );
184
185     /* Unicode tests */
186
187     SetLastError(0);
188     res = RegSetValueExW( test_key, testW, 0, REG_SZ, (const BYTE *)foobarW, 7*sizeof(WCHAR) );
189     if (res==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
190         return;
191     ok( res == 0, "RegSetValueExW failed error %ld\n", res );
192
193     /* overflow both name and data */
194     val_count = 2;
195     data_count = 2;
196     type = 1234;
197     memcpy( valueW, xxxW, sizeof(xxxW) );
198     memcpy( dataW, xxxW, sizeof(xxxW) );
199     res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
200     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
201     ok( val_count == 2, "val_count set to %ld\n", val_count );
202     ok( data_count == 7*sizeof(WCHAR), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count );
203     ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
204     ok( !memcmp( valueW, xxxW, sizeof(xxxW) ), "value modified\n" );
205     ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
206
207     /* overflow name */
208     val_count = 3;
209     data_count = 20;
210     type = 1234;
211     memcpy( valueW, xxxW, sizeof(xxxW) );
212     memcpy( dataW, xxxW, sizeof(xxxW) );
213     res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
214     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
215     ok( val_count == 3, "val_count set to %ld\n", val_count );
216     ok( data_count == 7*sizeof(WCHAR), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count );
217     ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
218     ok( !memcmp( valueW, xxxW, sizeof(xxxW) ), "value modified\n" );
219     ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
220
221     /* overflow data */
222     val_count = 20;
223     data_count = 2;
224     type = 1234;
225     memcpy( valueW, xxxW, sizeof(xxxW) );
226     memcpy( dataW, xxxW, sizeof(xxxW) );
227     res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
228     ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
229     ok( val_count == 4, "val_count set to %ld instead of 4\n", val_count );
230     ok( data_count == 7*sizeof(WCHAR), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count );
231     ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
232     ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" );
233     ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" );
234
235     /* no overflow */
236     val_count = 20;
237     data_count = 20;
238     type = 1234;
239     memcpy( valueW, xxxW, sizeof(xxxW) );
240     memcpy( dataW, xxxW, sizeof(xxxW) );
241     res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
242     ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res );
243     ok( val_count == 4, "val_count set to %ld instead of 4\n", val_count );
244     ok( data_count == 7*sizeof(WCHAR), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count );
245     ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
246     ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" );
247     ok( !memcmp( dataW, foobarW, sizeof(foobarW) ), "data is not 'foobar'\n" );
248 }
249
250 static void test_query_value_ex()
251 {
252     DWORD ret;
253     DWORD size;
254     DWORD type;
255     
256     ret = RegQueryValueExA(hkey_main, "Test2", NULL, &type, NULL, &size);
257     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
258     ok(size == strlen(sTestpath1) + 1, "(%ld,%ld)\n", (DWORD)strlen(sTestpath1) + 1, size);
259     ok(type == REG_SZ, "type %ld is not REG_SZ\n", type);
260 }
261
262 static void test_reg_open_key()
263 {
264     DWORD ret = 0;
265     HKEY hkResult = NULL;
266     HKEY hkPreserve = NULL;
267
268     /* successful open */
269     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult);
270     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
271     ok(hkResult != NULL, "expected hkResult != NULL\n");
272     hkPreserve = hkResult;
273
274     /* open same key twice */
275     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult);
276     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
277     ok(hkResult != hkPreserve && hkResult != NULL, 
278                 "expected hkResult != hkPreserve and hkResult != NULL\n");
279     RegCloseKey(hkResult);
280
281     /* open nonexistent key
282      * check that hkResult is set to NULL
283      */
284     hkResult = hkPreserve;
285     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
286     ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret);
287     ok(hkResult == NULL, "expected hkResult == NULL\n");
288
289     /* open the same nonexistent key again to make sure the key wasn't created */
290     hkResult = hkPreserve;
291     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
292     ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret);
293     ok(hkResult == NULL, "expected hkResult == NULL\n");
294
295     /* send in NULL lpSubKey
296      * check that hkResult receives the value of hKey
297      */
298     hkResult = hkPreserve;
299     ret = RegOpenKeyA(HKEY_CURRENT_USER, NULL, &hkResult);
300     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
301     ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
302
303     /* send empty-string in lpSubKey */
304     hkResult = hkPreserve;
305     ret = RegOpenKeyA(HKEY_CURRENT_USER, "", &hkResult);
306     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
307     ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
308
309     /* send in NULL lpSubKey and NULL hKey
310      * hkResult is set to NULL
311      */
312     hkResult = hkPreserve;
313     ret = RegOpenKeyA(NULL, NULL, &hkResult);
314     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
315     ok(hkResult == NULL, "expected hkResult == NULL\n");
316
317     /* only send NULL hKey
318      * the value of hkResult remains unchanged
319      */
320     hkResult = hkPreserve;
321     ret = RegOpenKeyA(NULL, "Software\\Wine\\Test", &hkResult);
322     ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */
323        "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %ld\n", ret);
324     ok(hkResult == hkPreserve, "expected hkResult == hkPreserve\n");
325     RegCloseKey(hkResult);
326
327     /* send in NULL hkResult */
328     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", NULL);
329     ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", ret);
330 }
331
332 static void test_reg_close_key()
333 {
334     DWORD ret = 0;
335     HKEY hkHandle;
336
337     /* successfully close key
338      * hkHandle remains changed after call to RegCloseKey
339      */
340     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkHandle);
341     ret = RegCloseKey(hkHandle);
342     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
343
344     /* try to close the key twice */
345     ret = RegCloseKey(hkHandle); /* Windows 95 doesn't mind. */
346     ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_SUCCESS,
347        "expected ERROR_INVALID_HANDLE or ERROR_SUCCESS, got %ld\n", ret);
348     
349     /* try to close a NULL handle */
350     ret = RegCloseKey(NULL);
351     ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */
352        "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %ld\n", ret);
353 }
354
355 static void test_reg_save_key()
356 {
357     DWORD ret;
358
359     ret = RegSaveKey(hkey_main, "saved_key", NULL);
360     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
361 }
362
363 static void test_reg_load_key()
364 {
365     DWORD ret;
366     HKEY hkHandle;
367
368     ret = RegLoadKey(HKEY_LOCAL_MACHINE, "Test", "saved_key");
369     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
370
371     ret = RegOpenKey(HKEY_LOCAL_MACHINE, "Test", &hkHandle);
372     ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
373
374     delete_key(hkHandle);
375     DeleteFile("saved_key");
376 }
377
378 START_TEST(registry)
379 {
380     setup_main_key();
381     create_test_entries();
382     test_enum_value();
383     test_query_value_ex();
384     test_reg_open_key();
385     test_reg_close_key();
386     test_reg_save_key();
387     test_reg_load_key();
388
389     /* cleanup */
390     delete_key( hkey_main );
391 }