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