2 * Unit tests for registry functions
4 * Copyright (c) 2002 Alexandre Julliard
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.
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.
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
23 #include "wine/test.h"
29 static HKEY hkey_main
;
31 static const char * sTestpath1
= "%LONGSYSTEMVAR%\\subdir1";
32 static const char * sTestpath2
= "%FOO%\\subdir1";
34 /* delete key and all its subkeys */
35 static DWORD
delete_key( HKEY hkey
)
40 while (!(ret
= RegEnumKeyA(hkey
, 0, name
, sizeof(name
))))
43 if (!(ret
= RegOpenKeyExA( hkey
, name
, 0, KEY_ENUMERATE_SUB_KEYS
, &tmp
)))
45 ret
= delete_key( tmp
);
50 if (ret
!= ERROR_NO_MORE_ITEMS
) return ret
;
51 RegDeleteKeyA( hkey
, "" );
55 static void setup_main_key(void)
57 if (RegOpenKeyA( HKEY_CURRENT_USER
, "Software\\Wine\\Test", &hkey_main
)) delete_key( hkey_main
);
59 assert (!RegCreateKeyA( HKEY_CURRENT_USER
, "Software\\Wine\\Test", &hkey_main
));
62 static void create_test_entries(void)
64 SetEnvironmentVariableA("LONGSYSTEMVAR", "bar");
65 SetEnvironmentVariableA("FOO", "ImARatherLongButIndeedNeededString");
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");
75 static void test_enum_value(void)
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};
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
);
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
);
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 res
= RegSetValueExA( test_key
, "Test", 0, REG_BINARY
, NULL
, 0 );
99 ok( ERROR_SUCCESS
== res
|| ERROR_INVALID_PARAMETER
== res
, "RegSetValueExA returned %ld\n", res
);
101 res
= RegSetValueExA( test_key
, "Test", 0, REG_SZ
, (BYTE
*)"foobar", 7 );
102 ok( res
== 0, "RegSetValueExA failed error %ld\n", res
);
104 /* overflow both name and data */
108 strcpy( value
, "xxxxxxxxxx" );
109 strcpy( data
, "xxxxxxxxxx" );
110 res
= RegEnumValueA( test_key
, 0, value
, &val_count
, NULL
, &type
, data
, &data_count
);
111 ok( res
== ERROR_MORE_DATA
, "expected ERROR_MORE_DATA, got %ld\n", res
);
112 ok( val_count
== 2, "val_count set to %ld\n", val_count
);
113 ok( data_count
== 7, "data_count set to %ld instead of 7\n", data_count
);
114 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
115 ok( !strcmp( value
, "xxxxxxxxxx" ), "value set to '%s'\n", value
);
116 ok( !strcmp( data
, "xxxxxxxxxx" ), "data set to '%s'\n", data
);
122 strcpy( value
, "xxxxxxxxxx" );
123 strcpy( data
, "xxxxxxxxxx" );
124 res
= RegEnumValueA( test_key
, 0, value
, &val_count
, NULL
, &type
, data
, &data_count
);
125 ok( res
== ERROR_MORE_DATA
, "expected ERROR_MORE_DATA, got %ld\n", res
);
126 /* Win9x returns 2 as specified by MSDN but NT returns 3... */
127 ok( val_count
== 2 || val_count
== 3, "val_count set to %ld\n", val_count
);
128 ok( data_count
== 7, "data_count set to %ld instead of 7\n", data_count
);
129 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
131 /* v5.1.2600.0 (XP Home) does not touch value or data in this case */
132 ok( !strcmp( value
, "Te" ), "value set to '%s' instead of 'Te'\n", value
);
133 ok( !strcmp( data
, "foobar" ), "data set to '%s' instead of 'foobar'\n", data
);
136 /* overflow empty name */
140 strcpy( value
, "xxxxxxxxxx" );
141 strcpy( data
, "xxxxxxxxxx" );
142 res
= RegEnumValueA( test_key
, 0, value
, &val_count
, NULL
, &type
, data
, &data_count
);
143 ok( res
== ERROR_MORE_DATA
, "expected ERROR_MORE_DATA, got %ld\n", res
);
144 ok( val_count
== 0, "val_count set to %ld\n", val_count
);
145 ok( data_count
== 7, "data_count set to %ld instead of 7\n", data_count
);
146 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
147 ok( !strcmp( value
, "xxxxxxxxxx" ), "value set to '%s'\n", value
);
149 /* v5.1.2600.0 (XP Home) does not touch data in this case */
150 ok( !strcmp( data
, "foobar" ), "data set to '%s' instead of 'foobar'\n", data
);
157 strcpy( value
, "xxxxxxxxxx" );
158 strcpy( data
, "xxxxxxxxxx" );
159 res
= RegEnumValueA( test_key
, 0, value
, &val_count
, NULL
, &type
, data
, &data_count
);
160 ok( res
== ERROR_MORE_DATA
, "expected ERROR_MORE_DATA, got %ld\n", res
);
161 ok( val_count
== 20, "val_count set to %ld\n", val_count
);
162 ok( data_count
== 7, "data_count set to %ld instead of 7\n", data_count
);
163 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
164 ok( !strcmp( value
, "xxxxxxxxxx" ), "value set to '%s'\n", value
);
165 ok( !strcmp( data
, "xxxxxxxxxx" ), "data set to '%s'\n", data
);
171 strcpy( value
, "xxxxxxxxxx" );
172 strcpy( data
, "xxxxxxxxxx" );
173 res
= RegEnumValueA( test_key
, 0, value
, &val_count
, NULL
, &type
, data
, &data_count
);
174 ok( res
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", res
);
175 ok( val_count
== 4, "val_count set to %ld instead of 4\n", val_count
);
176 ok( data_count
== 7, "data_count set to %ld instead of 7\n", data_count
);
177 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
178 ok( !strcmp( value
, "Test" ), "value is '%s' instead of Test\n", value
);
179 ok( !strcmp( data
, "foobar" ), "data is '%s' instead of foobar\n", data
);
184 res
= RegSetValueExW( test_key
, testW
, 0, REG_SZ
, (const BYTE
*)foobarW
, 7*sizeof(WCHAR
) );
185 if (res
==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED
)
187 ok( res
== 0, "RegSetValueExW failed error %ld\n", res
);
189 /* overflow both name and data */
193 memcpy( valueW
, xxxW
, sizeof(xxxW
) );
194 memcpy( dataW
, xxxW
, sizeof(xxxW
) );
195 res
= RegEnumValueW( test_key
, 0, valueW
, &val_count
, NULL
, &type
, (BYTE
*)dataW
, &data_count
);
196 ok( res
== ERROR_MORE_DATA
, "expected ERROR_MORE_DATA, got %ld\n", res
);
197 ok( val_count
== 2, "val_count set to %ld\n", val_count
);
198 ok( data_count
== 7*sizeof(WCHAR
), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count
);
199 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
200 ok( !memcmp( valueW
, xxxW
, sizeof(xxxW
) ), "value modified\n" );
201 ok( !memcmp( dataW
, xxxW
, sizeof(xxxW
) ), "data modified\n" );
207 memcpy( valueW
, xxxW
, sizeof(xxxW
) );
208 memcpy( dataW
, xxxW
, sizeof(xxxW
) );
209 res
= RegEnumValueW( test_key
, 0, valueW
, &val_count
, NULL
, &type
, (BYTE
*)dataW
, &data_count
);
210 ok( res
== ERROR_MORE_DATA
, "expected ERROR_MORE_DATA, got %ld\n", res
);
211 ok( val_count
== 3, "val_count set to %ld\n", val_count
);
212 ok( data_count
== 7*sizeof(WCHAR
), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count
);
213 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
214 ok( !memcmp( valueW
, xxxW
, sizeof(xxxW
) ), "value modified\n" );
215 ok( !memcmp( dataW
, xxxW
, sizeof(xxxW
) ), "data modified\n" );
221 memcpy( valueW
, xxxW
, sizeof(xxxW
) );
222 memcpy( dataW
, xxxW
, sizeof(xxxW
) );
223 res
= RegEnumValueW( test_key
, 0, valueW
, &val_count
, NULL
, &type
, (BYTE
*)dataW
, &data_count
);
224 ok( res
== ERROR_MORE_DATA
, "expected ERROR_MORE_DATA, got %ld\n", res
);
225 ok( val_count
== 4, "val_count set to %ld instead of 4\n", val_count
);
226 ok( data_count
== 7*sizeof(WCHAR
), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count
);
227 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
228 ok( !memcmp( valueW
, testW
, sizeof(testW
) ), "value is not 'Test'\n" );
229 ok( !memcmp( dataW
, xxxW
, sizeof(xxxW
) ), "data modified\n" );
235 memcpy( valueW
, xxxW
, sizeof(xxxW
) );
236 memcpy( dataW
, xxxW
, sizeof(xxxW
) );
237 res
= RegEnumValueW( test_key
, 0, valueW
, &val_count
, NULL
, &type
, (BYTE
*)dataW
, &data_count
);
238 ok( res
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", res
);
239 ok( val_count
== 4, "val_count set to %ld instead of 4\n", val_count
);
240 ok( data_count
== 7*sizeof(WCHAR
), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count
);
241 ok( type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
242 ok( !memcmp( valueW
, testW
, sizeof(testW
) ), "value is not 'Test'\n" );
243 ok( !memcmp( dataW
, foobarW
, sizeof(foobarW
) ), "data is not 'foobar'\n" );
246 static void test_query_value_ex()
252 ret
= RegQueryValueExA(hkey_main
, "Test2", NULL
, &type
, NULL
, &size
);
253 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
254 ok(size
== strlen(sTestpath1
) + 1, "(%ld,%ld)\n", (DWORD
)strlen(sTestpath1
) + 1, size
);
255 ok(type
== REG_SZ
, "type %ld is not REG_SZ\n", type
);
258 static void test_reg_open_key()
261 HKEY hkResult
= NULL
;
262 HKEY hkPreserve
= NULL
;
264 /* successful open */
265 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Test", &hkResult
);
266 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
267 ok(hkResult
!= NULL
, "expected hkResult != NULL\n");
268 hkPreserve
= hkResult
;
270 /* open same key twice */
271 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Test", &hkResult
);
272 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
273 ok(hkResult
!= hkPreserve
, "epxected hkResult != hkPreserve\n");
274 ok(hkResult
!= NULL
, "hkResult != NULL\n");
275 RegCloseKey(hkResult
);
277 /* open nonexistent key
278 * check that hkResult is set to NULL
280 hkResult
= hkPreserve
;
281 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Nonexistent", &hkResult
);
282 ok(ret
== ERROR_FILE_NOT_FOUND
, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret
);
283 ok(hkResult
== NULL
, "expected hkResult == NULL\n");
285 /* open the same nonexistent key again to make sure the key wasn't created */
286 hkResult
= hkPreserve
;
287 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Nonexistent", &hkResult
);
288 ok(ret
== ERROR_FILE_NOT_FOUND
, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret
);
289 ok(hkResult
== NULL
, "expected hkResult == NULL\n");
291 /* send in NULL lpSubKey
292 * check that hkResult receives the value of hKey
294 hkResult
= hkPreserve
;
295 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, NULL
, &hkResult
);
296 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
297 ok(hkResult
== HKEY_CURRENT_USER
, "expected hkResult == HKEY_CURRENT_USER\n");
299 /* send empty-string in lpSubKey */
300 hkResult
= hkPreserve
;
301 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, "", &hkResult
);
302 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
303 ok(hkResult
== HKEY_CURRENT_USER
, "expected hkResult == HKEY_CURRENT_USER\n");
305 /* send in NULL lpSubKey and NULL hKey
306 * hkResult is set to NULL
308 hkResult
= hkPreserve
;
309 ret
= RegOpenKeyA(NULL
, NULL
, &hkResult
);
310 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
311 ok(hkResult
== NULL
, "expected hkResult == NULL\n");
313 /* only send NULL hKey
314 * the value of hkResult remains unchanged
316 hkResult
= hkPreserve
;
317 ret
= RegOpenKeyA(NULL
, "Software\\Wine\\Test", &hkResult
);
318 ok(ret
== ERROR_INVALID_HANDLE
|| ret
== ERROR_BADKEY
, /* Windows 95 returns BADKEY */
319 "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %ld\n", ret
);
320 ok(hkResult
== hkPreserve
, "expected hkResult == hkPreserve\n");
321 RegCloseKey(hkResult
);
323 /* send in NULL hkResult */
324 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Test", NULL
);
325 ok(ret
== ERROR_INVALID_PARAMETER
, "expected ERROR_INVALID_PARAMETER, got %ld\n", ret
);
328 static void test_reg_close_key()
333 /* successfully close key
334 * hkHandle remains changed after call to RegCloseKey
336 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Test", &hkHandle
);
337 ret
= RegCloseKey(hkHandle
);
338 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
340 /* try to close the key twice */
341 ret
= RegCloseKey(hkHandle
); /* Windows 95 doesn't mind. */
342 ok(ret
== ERROR_INVALID_HANDLE
|| ret
== ERROR_SUCCESS
,
343 "expected ERROR_INVALID_HANDLE or ERROR_SUCCESS, got %ld\n", ret
);
345 /* try to close a NULL handle */
346 ret
= RegCloseKey(NULL
);
347 ok(ret
== ERROR_INVALID_HANDLE
|| ret
== ERROR_BADKEY
, /* Windows 95 returns BADKEY */
348 "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %ld\n", ret
);
351 static void test_reg_delete_key()
355 ret
= RegDeleteKey(hkey_main
, NULL
);
356 ok(ret
== ERROR_INVALID_PARAMETER
|| ret
== ERROR_ACCESS_DENIED
,
357 "expected ERROR_INVALID_PARAMETER or ERROR_ACCESS_DENIED, got %ld\n", ret
);
360 static void test_reg_save_key()
364 ret
= RegSaveKey(hkey_main
, "saved_key", NULL
);
365 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
368 static void test_reg_load_key()
373 ret
= RegLoadKey(HKEY_LOCAL_MACHINE
, "Test", "saved_key");
374 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
376 ret
= RegOpenKey(HKEY_LOCAL_MACHINE
, "Test", &hkHandle
);
377 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
379 RegCloseKey(hkHandle
);
382 static void test_reg_unload_key()
386 ret
= RegUnLoadKey(HKEY_LOCAL_MACHINE
, "Test");
387 ok(ret
== ERROR_SUCCESS
, "expected ERROR_SUCCESS, got %ld\n", ret
);
389 DeleteFile("saved_key");
392 static BOOL
set_privileges(LPCSTR privilege
, BOOL set
)
398 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
, &hToken
))
401 if(!LookupPrivilegeValue(NULL
, privilege
, &luid
))
407 tp
.PrivilegeCount
= 1;
408 tp
.Privileges
[0].Luid
= luid
;
411 tp
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
413 tp
.Privileges
[0].Attributes
= 0;
415 AdjustTokenPrivileges(hToken
, FALSE
, &tp
, sizeof(TOKEN_PRIVILEGES
), NULL
, NULL
);
416 if (GetLastError() != ERROR_SUCCESS
)
429 create_test_entries();
431 test_query_value_ex();
433 test_reg_close_key();
434 test_reg_delete_key();
436 /* SaveKey/LoadKey require the SE_BACKUP_NAME privilege to be set */
437 if (set_privileges(SE_BACKUP_NAME
, TRUE
) &&
438 set_privileges(SE_RESTORE_NAME
, TRUE
))
442 test_reg_unload_key();
444 set_privileges(SE_BACKUP_NAME
, FALSE
);
445 set_privileges(SE_RESTORE_NAME
, FALSE
);
449 delete_key( hkey_main
);