ReactOS 0.4.16-dev-2332-g4cba65d
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 "ntstatus.h"
26#define WIN32_NO_STATUS
27#include "wine/test.h"
28#include "windef.h"
29#include "winbase.h"
30#include "winternl.h"
31#include "winreg.h"
32#include "winperf.h"
33#include "winsvc.h"
34#include "winerror.h"
35#include "aclapi.h"
36#ifdef __REACTOS__
37/* FIXME: Removing this hack requires fixing our incompatible wine/test.h and wine/debug.h. */
38#ifndef wine_dbg_sprintf
39static inline const char* wine_dbg_sprintf(const char* format, ...)
40{
41 static char buffer[256];
44 vsnprintf(buffer, sizeof(buffer), format, args);
45 va_end(args);
46 return buffer;
47}
48#endif
49#endif
50
51#define IS_HKCR(hk) ((UINT_PTR)hk > 0 && ((UINT_PTR)hk & 3) == 2)
52
54static DWORD GLE;
55
56static const char * sTestpath1 = "%LONGSYSTEMVAR%\\subdir1";
57static const char * sTestpath2 = "%FOO%\\subdir1";
58static const DWORD ptr_size = 8 * sizeof(void*);
59
62static LONG (WINAPI *pRegCopyTreeA)(HKEY,const char *,HKEY);
63static LONG (WINAPI *pRegDeleteTreeA)(HKEY,const char *);
64static DWORD (WINAPI *pRegDeleteKeyExA)(HKEY,LPCSTR,REGSAM,DWORD);
65static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
66static NTSTATUS (WINAPI * pNtDeleteKey)(HANDLE);
67static NTSTATUS (WINAPI * pNtUnloadKey)(POBJECT_ATTRIBUTES);
68static NTSTATUS (WINAPI * pRtlFormatCurrentUserKeyPath)(UNICODE_STRING*);
69static NTSTATUS (WINAPI * pRtlFreeUnicodeString)(PUNICODE_STRING);
70static NTSTATUS (WINAPI * pRtlInitUnicodeString)(PUNICODE_STRING,PCWSTR);
71static LONG (WINAPI *pRegDeleteKeyValueA)(HKEY,LPCSTR,LPCSTR);
72static LONG (WINAPI *pRegSetKeyValueW)(HKEY,LPCWSTR,LPCWSTR,DWORD,const void*,DWORD);
73static LONG (WINAPI *pRegLoadMUIStringA)(HKEY,LPCSTR,LPSTR,DWORD,LPDWORD,DWORD,LPCSTR);
74static LONG (WINAPI *pRegLoadMUIStringW)(HKEY,LPCWSTR,LPWSTR,DWORD,LPDWORD,DWORD,LPCWSTR);
75static DWORD (WINAPI *pEnumDynamicTimeZoneInformation)(const DWORD,
77
79static const BOOL is_64bit = sizeof(void *) > sizeof(int);
80
81static BOOL has_wow64(void)
82{
83 if (!is_64bit)
84 {
86 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 ) || !is_wow64)
87 return FALSE;
88 }
89 return TRUE;
90}
91
92static const char *dbgstr_SYSTEMTIME(const SYSTEMTIME *st)
93{
94 return wine_dbg_sprintf("%02d-%02d-%04d %02d:%02d:%02d.%03d",
95 st->wMonth, st->wDay, st->wYear,
96 st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
97}
98
99#define ADVAPI32_GET_PROC(func) \
100 p ## func = (void*)GetProcAddress(hadvapi32, #func)
101
102static void InitFunctionPtrs(void)
103{
104 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
105 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
106 HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
107
108 /* This function was introduced with Windows 2003 SP1 */
119
120 pIsWow64Process = (void *)GetProcAddress( hkernel32, "IsWow64Process" );
121 pRtlFormatCurrentUserKeyPath = (void *)GetProcAddress( hntdll, "RtlFormatCurrentUserKeyPath" );
122 pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
123 pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
124 pNtDeleteKey = (void *)GetProcAddress( hntdll, "NtDeleteKey" );
125 pNtUnloadKey = (void *)GetProcAddress( hntdll, "NtUnloadKey" );
126}
127
129{
130 return !!((ULONG_PTR)key & 0x80000000);
131}
132
133/* delete key and all its subkeys */
134static DWORD delete_key( HKEY hkey )
135{
136 char name[MAX_PATH];
137 DWORD ret;
138
139 if ((ret = RegOpenKeyExA( hkey, "", 0, KEY_ENUMERATE_SUB_KEYS, &hkey ))) return ret;
140 while (!(ret = RegEnumKeyA(hkey, 0, name, sizeof(name))))
141 {
142 HKEY tmp;
143 if (!(ret = RegOpenKeyExA( hkey, name, 0, KEY_ENUMERATE_SUB_KEYS, &tmp )))
144 {
145 ret = delete_key( tmp );
146 RegCloseKey( tmp );
147 }
148 if (ret) break;
149 }
150 if (ret != ERROR_NO_MORE_ITEMS) return ret;
151 RegDeleteKeyA( hkey, "" );
152 RegCloseKey(hkey);
153 return 0;
154}
155
156static void setup_main_key(void)
157{
158 DWORD ret;
159
160 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main )) delete_key( hkey_main );
161
162 ret = RegCreateKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main );
163 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
164}
165
166static void check_user_privs(void)
167{
168 DWORD ret;
169 HKEY hkey = (HKEY)0xdeadbeef;
170
171 ret = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WRITE, &hkey);
172 ok(ret == ERROR_SUCCESS || ret == ERROR_ACCESS_DENIED, "expected success or access denied, got %li\n", ret);
173 if (ret == ERROR_SUCCESS)
174 {
175 ok(hkey != NULL, "RegOpenKeyExA succeeded but returned NULL hkey\n");
176 RegCloseKey(hkey);
177 }
178 else
179 {
180 ok(hkey == NULL, "RegOpenKeyExA failed but returned hkey %p\n", hkey);
182 trace("running as limited user\n");
183 }
184}
185
186#define lok ok_(__FILE__, line)
187#define test_hkey_main_Value_A(name, string, full_byte_len) _test_hkey_main_Value_A(__LINE__, name, string, full_byte_len)
189 DWORD full_byte_len)
190{
192 DWORD str_byte_len;
193 BYTE* value;
194
195 type=0xdeadbeef;
196 cbData=0xdeadbeef;
197 /* When successful RegQueryValueExA() leaves GLE as is,
198 * so we must reset it to detect unimplemented functions.
199 */
200 SetLastError(0xdeadbeef);
202 GLE = GetLastError();
203 lok(ret == ERROR_SUCCESS, "RegQueryValueExA/1 failed: %ld, GLE=%ld\n", ret, GLE);
204 /* It is wrong for the Ansi version to not be implemented */
205 ok(GLE == 0xdeadbeef, "RegQueryValueExA set GLE = %lu\n", GLE);
206 if(GLE == ERROR_CALL_NOT_IMPLEMENTED) return;
207
208 str_byte_len = (string ? lstrlenA(string) : 0) + 1;
209 lok(type == REG_SZ, "RegQueryValueExA/1 returned type %ld\n", type);
210 lok(cbData == full_byte_len, "cbData=%ld instead of %ld or %ld\n", cbData, full_byte_len, str_byte_len);
211
212 value = malloc(cbData+1);
213 memset(value, 0xbd, cbData+1);
214 type=0xdeadbeef;
216 GLE = GetLastError();
217 lok(ret == ERROR_SUCCESS, "RegQueryValueExA/2 failed: %ld, GLE=%ld\n", ret, GLE);
218 if (!string)
219 {
220 /* When cbData == 0, RegQueryValueExA() should not modify the buffer */
221 lok(*value == 0xbd, "RegQueryValueExA overflowed: cbData=%lu *value=%02x\n", cbData, *value);
222 }
223 else
224 {
225 lok(memcmp(value, string, cbData) == 0, "RegQueryValueExA/2 failed: %s/%ld != %s/%ld\n",
226 debugstr_an((char*)value, cbData), cbData,
227 debugstr_an(string, full_byte_len), full_byte_len);
228 lok(*(value+cbData) == 0xbd, "RegQueryValueExA/2 overflowed at offset %lu: %02x != bd\n", cbData, *(value+cbData));
229 }
230 free(value);
231}
232
233#define test_hkey_main_Value_W(name, string, full_byte_len) _test_hkey_main_Value_W(__LINE__, name, string, full_byte_len)
235 DWORD full_byte_len)
236{
238 BYTE* value;
239
240 type=0xdeadbeef;
241 cbData=0xdeadbeef;
242 /* When successful RegQueryValueExW() leaves GLE as is,
243 * so we must reset it to detect unimplemented functions.
244 */
245 SetLastError(0xdeadbeef);
247 GLE = GetLastError();
248 lok(ret == ERROR_SUCCESS, "RegQueryValueExW/1 failed: %ld, GLE=%ld\n", ret, GLE);
250 {
251 win_skip("RegQueryValueExW() is not implemented\n");
252 return;
253 }
254
255 lok(type == REG_SZ, "RegQueryValueExW/1 returned type %ld\n", type);
256 lok(cbData == full_byte_len,
257 "cbData=%ld instead of %ld\n", cbData, full_byte_len);
258
259 /* Give enough space to overflow by one WCHAR */
260 value = malloc(cbData+2);
261 memset(value, 0xbd, cbData+2);
262 type=0xdeadbeef;
264 GLE = GetLastError();
265 lok(ret == ERROR_SUCCESS, "RegQueryValueExW/2 failed: %ld, GLE=%ld\n", ret, GLE);
266 if (string)
267 {
268 lok(memcmp(value, string, cbData) == 0, "RegQueryValueExW failed: %s/%ld != %s/%ld\n",
270 wine_dbgstr_wn(string, full_byte_len / sizeof(WCHAR)), full_byte_len);
271 }
272 /* This implies that when cbData == 0, RegQueryValueExW() should not modify the buffer */
273 lok(*(value+cbData) == 0xbd, "RegQueryValueExW/2 overflowed at %lu: %02x != bd\n", cbData, *(value+cbData));
274 lok(*(value+cbData+1) == 0xbd, "RegQueryValueExW/2 overflowed at %lu+1: %02x != bd\n", cbData, *(value+cbData+1));
275 free(value);
276}
277
278static void test_set_value(void)
279{
280 DWORD ret;
281
282 static const WCHAR name1W[] = L"CleanSingleString";
283 static const WCHAR name2W[] = L"SomeIntraZeroedString";
284 static const WCHAR emptyW[] = L"";
285 static const WCHAR string1W[] = L"ThisNeverBreaks";
286 static const WCHAR string2W[] = L"This\0Breaks\0\0A\0\0\0Lot\0\0\0\0";
287 static const WCHAR substring2W[] = L"This";
288
289 static const char name1A[] = "CleanSingleString";
290 static const char name2A[] = "SomeIntraZeroedString";
291 static const char emptyA[] = "";
292 static const char string1A[] = "ThisNeverBreaks";
293 static const char string2A[] = "This\0Breaks\0\0A\0\0\0Lot\0\0\0\0";
294 static const char substring2A[] = "This";
295
297 ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueA should have failed with ERROR_INVALID_PARAMETER instead of %ld\n", ret);
298
299 ret = RegSetValueA(hkey_main, NULL, REG_SZ, string1A, sizeof(string1A));
300 ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %ld, GLE=%ld\n", ret, GetLastError());
301 test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
302 test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
303
304 /* RegSetValueA ignores the size passed in */
305 ret = RegSetValueA(hkey_main, NULL, REG_SZ, string1A, 4);
306 ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %ld, GLE=%ld\n", ret, GetLastError());
307 test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
308 test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
309
310 /* stops at first null */
311 ret = RegSetValueA(hkey_main, NULL, REG_SZ, string2A, sizeof(string2A));
312 ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %ld, GLE=%ld\n", ret, GetLastError());
313 test_hkey_main_Value_A(NULL, substring2A, sizeof(substring2A));
314 test_hkey_main_Value_W(NULL, substring2W, sizeof(substring2W));
315
316 /* only REG_SZ is supported on NT*/
317 ret = RegSetValueA(hkey_main, NULL, REG_BINARY, string2A, sizeof(string2A));
318 ok(ret == ERROR_INVALID_PARAMETER, "got %ld (expected ERROR_INVALID_PARAMETER)\n", ret);
319
320 ret = RegSetValueA(hkey_main, NULL, REG_EXPAND_SZ, string2A, sizeof(string2A));
321 ok(ret == ERROR_INVALID_PARAMETER, "got %ld (expected ERROR_INVALID_PARAMETER)\n", ret);
322
323 ret = RegSetValueA(hkey_main, NULL, REG_MULTI_SZ, string2A, sizeof(string2A));
324 ok(ret == ERROR_INVALID_PARAMETER, "got %ld (expected ERROR_INVALID_PARAMETER)\n", ret);
325
326 /* Test RegSetValueExA with a 'zero-byte' string (as Office 2003 does).
327 * Surprisingly enough we're supposed to get zero bytes out of it.
328 */
329 ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)emptyA, 0);
330 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%ld\n", ret, GetLastError());
331 test_hkey_main_Value_A(name1A, NULL, 0);
332 test_hkey_main_Value_W(name1W, NULL, 0);
333
334 /* test RegSetValueExA with an empty string */
335 ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)emptyA, sizeof(emptyA));
336 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%ld\n", ret, GetLastError());
337 test_hkey_main_Value_A(name1A, emptyA, sizeof(emptyA));
338 test_hkey_main_Value_W(name1W, emptyW, sizeof(emptyW));
339
340 /* test RegSetValueExA with off-by-one size */
341 ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)string1A, sizeof(string1A)-sizeof(string1A[0]));
342 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%ld\n", ret, GetLastError());
343 test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
344 test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
345
346 /* test RegSetValueExA with normal string */
347 ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)string1A, sizeof(string1A));
348 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%ld\n", ret, GetLastError());
349 test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
350 test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
351
352 /* test RegSetValueExA with intrazeroed string */
353 ret = RegSetValueExA(hkey_main, name2A, 0, REG_SZ, (const BYTE *)string2A, sizeof(string2A));
354 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%ld\n", ret, GetLastError());
355 test_hkey_main_Value_A(name2A, string2A, sizeof(string2A));
356 test_hkey_main_Value_W(name2W, string2W, sizeof(string2W));
357
358 if (0)
359 {
361 ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have failed with ERROR_INVALID_PARAMETER instead of %ld\n", ret);
362
363 RegSetValueExA(hkey_main, name2A, 0, REG_SZ, (const BYTE *)1, 1);
364 RegSetValueExA(hkey_main, name2A, 0, REG_DWORD, (const BYTE *)1, 1);
365 }
366
367 ret = RegSetValueW(hkey_main, NULL, REG_SZ, string1W, sizeof(string1W));
368 ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %ld, GLE=%ld\n", ret, GetLastError());
369 test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
370 test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
371
372 ret = RegSetValueW(hkey_main, name1W, REG_SZ, string1W, sizeof(string1W));
373 ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %ld, GLE=%ld\n", ret, GetLastError());
374 test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
375 test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
376
377 /* RegSetValueW ignores the size passed in */
378 ret = RegSetValueW(hkey_main, NULL, REG_SZ, string1W, 4 * sizeof(string1W[0]));
379 ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %ld, GLE=%ld\n", ret, GetLastError());
380 test_hkey_main_Value_A(NULL, string1A, sizeof(string1A));
381 test_hkey_main_Value_W(NULL, string1W, sizeof(string1W));
382
383 /* stops at first null */
384 ret = RegSetValueW(hkey_main, NULL, REG_SZ, string2W, sizeof(string2W));
385 ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %ld, GLE=%ld\n", ret, GetLastError());
386 test_hkey_main_Value_A(NULL, substring2A, sizeof(substring2A));
387 test_hkey_main_Value_W(NULL, substring2W, sizeof(substring2W));
388
389 /* only REG_SZ is supported */
390 ret = RegSetValueW(hkey_main, NULL, REG_BINARY, string2W, sizeof(string2W));
391 ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %ld\n", ret);
392 ret = RegSetValueW(hkey_main, NULL, REG_EXPAND_SZ, string2W, sizeof(string2W));
393 ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %ld\n", ret);
394 ret = RegSetValueW(hkey_main, NULL, REG_MULTI_SZ, string2W, sizeof(string2W));
395 ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %ld\n", ret);
396
397 /* test RegSetValueExW with off-by-one size */
398 ret = RegSetValueExW(hkey_main, name1W, 0, REG_SZ, (const BYTE *)string1W, sizeof(string1W)-sizeof(string1W[0]));
399 ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %ld, GLE=%ld\n", ret, GetLastError());
400 test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
401 test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
402
403 /* test RegSetValueExW with normal string */
404 ret = RegSetValueExW(hkey_main, name1W, 0, REG_SZ, (const BYTE *)string1W, sizeof(string1W));
405 ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %ld, GLE=%ld\n", ret, GetLastError());
406 test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
407 test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));
408
409 /* test RegSetValueExW with intrazeroed string */
410 ret = RegSetValueExW(hkey_main, name2W, 0, REG_SZ, (const BYTE *)string2W, sizeof(string2W));
411 ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %ld, GLE=%ld\n", ret, GetLastError());
412 test_hkey_main_Value_A(name2A, string2A, sizeof(string2A));
413 test_hkey_main_Value_W(name2W, string2W, sizeof(string2W));
414
415 /* test RegSetValueExW with data = 1 */
416 ret = RegSetValueExW(hkey_main, name2W, 0, REG_SZ, (const BYTE *)1, 1);
417 ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %ld, GLE=%ld\n", ret, GetLastError());
418 ret = RegSetValueExW(hkey_main, name2W, 0, REG_DWORD, (const BYTE *)1, 1);
419 ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %ld, GLE=%ld\n", ret, GetLastError());
420
421 if (pRegGetValueA) /* avoid a crash on Windows 2000 */
422 {
424 ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %ld, GLE=%ld\n", ret, GetLastError());
425
427 ok(ret == ERROR_SUCCESS, "got %ld\n", ret);
428
430 ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %ld, GLE=%ld\n", ret, GetLastError());
431
433 ok(ret == ERROR_SUCCESS, "got %ld\n", ret);
434 }
435
436 /* RegSetKeyValue */
437 if (!pRegSetKeyValueW)
438 win_skip("RegSetKeyValue() is not supported.\n");
439 else
440 {
441 DWORD len, type;
442 HKEY subkey;
443
444 ret = pRegSetKeyValueW(hkey_main, NULL, name1W, REG_SZ, (const BYTE*)string2W, sizeof(string2W));
445 ok(ret == ERROR_SUCCESS, "got %ld\n", ret);
446 test_hkey_main_Value_A(name1A, string2A, sizeof(string2A));
447 test_hkey_main_Value_W(name1W, string2W, sizeof(string2W));
448
449 ret = pRegSetKeyValueW(hkey_main, L"subkey", name1W, REG_SZ, string1W, sizeof(string1W));
450 ok(ret == ERROR_SUCCESS, "got %ld\n", ret);
451
452 ret = RegOpenKeyExW(hkey_main, L"subkey", 0, KEY_QUERY_VALUE, &subkey);
453 ok(ret == ERROR_SUCCESS, "got %ld\n", ret);
454 type = len = 0;
455 ret = RegQueryValueExW(subkey, name1W, 0, &type, NULL, &len);
456 ok(ret == ERROR_SUCCESS, "got %ld\n", ret);
457 ok(len == sizeof(string1W), "got %ld\n", len);
458 ok(type == REG_SZ, "got type %ld\n", type);
459
460 ret = pRegSetKeyValueW(hkey_main, L"subkey", name1W, REG_SZ, NULL, 0);
461 ok(ret == ERROR_SUCCESS, "got %ld\n", ret);
462
463 ret = pRegSetKeyValueW(hkey_main, L"subkey", name1W, REG_SZ, NULL, 4);
464 ok(ret == ERROR_NOACCESS, "got %ld\n", ret);
465
466 ret = pRegSetKeyValueW(hkey_main, L"subkey", name1W, REG_DWORD, NULL, 4);
467 ok(ret == ERROR_NOACCESS, "got %ld\n", ret);
468
469 RegCloseKey(subkey);
470 }
471}
472
473static void create_test_entries(void)
474{
475 static const DWORD qw[2] = { 0x12345678, 0x87654321 };
476
477 SetEnvironmentVariableA("LONGSYSTEMVAR", "bar");
478 SetEnvironmentVariableA("FOO", "ImARatherLongButIndeedNeededString");
479
481 "RegSetValueExA failed\n");
482 ok(!RegSetValueExA(hkey_main,"TP1_SZ",0,REG_SZ, (const BYTE *)sTestpath1, strlen(sTestpath1)+1),
483 "RegSetValueExA failed\n");
484 ok(!RegSetValueExA(hkey_main,"TP1_ZB_SZ",0,REG_SZ, (const BYTE *)"", 0),
485 "RegSetValueExA failed\n");
487 "RegSetValueExA failed\n");
488 ok(!RegSetValueExA(hkey_main,"DWORD",0,REG_DWORD, (const BYTE *)qw, 4),
489 "RegSetValueExA failed\n");
490 ok(!RegSetValueExA(hkey_main,"BIN32",0,REG_BINARY, (const BYTE *)qw, 4),
491 "RegSetValueExA failed\n");
492 ok(!RegSetValueExA(hkey_main,"BIN64",0,REG_BINARY, (const BYTE *)qw, 8),
493 "RegSetValueExA failed\n");
494}
495
496static void test_enum_value(void)
497{
498 DWORD res;
499 HKEY test_key;
500 char value[20], data[30];
501 WCHAR valueW[20], dataW[20];
502 DWORD val_count, data_count, type;
503
504 /* create the working key for new 'Test' value */
505 res = RegCreateKeyA( hkey_main, "TestKey", &test_key );
506 ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res);
507
508 /* check NULL data with zero length */
509 res = RegSetValueExA( test_key, "Test", 0, REG_SZ, NULL, 0 );
510 if (GetVersion() & 0x80000000)
511 ok( res == ERROR_INVALID_PARAMETER, "RegSetValueExA returned %ld\n", res );
512 else
513 ok( !res, "RegSetValueExA returned %ld\n", res );
514 res = RegSetValueExA( test_key, "Test", 0, REG_EXPAND_SZ, NULL, 0 );
515 ok( ERROR_SUCCESS == res, "RegSetValueExA returned %ld\n", res );
516 res = RegSetValueExA( test_key, "Test", 0, REG_BINARY, NULL, 0 );
517 ok( ERROR_SUCCESS == res, "RegSetValueExA returned %ld\n", res );
518
519 /* test reading the value and data without setting them */
520 val_count = 20;
521 data_count = 20;
522 type = 1234;
523 strcpy( value, "xxxxxxxxxx" );
524 strcpy( data, "xxxxxxxxxx" );
525 res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
526 ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res );
527 ok( val_count == 4, "val_count set to %ld instead of 4\n", val_count );
528 ok( data_count == 0, "data_count set to %ld instead of 0\n", data_count );
529 ok( type == REG_BINARY, "type %ld is not REG_BINARY\n", type );
530 ok( !strcmp( value, "Test" ), "value is '%s' instead of Test\n", value );
531 ok( !strcmp( data, "xxxxxxxxxx" ), "data is '%s' instead of xxxxxxxxxx\n", data );
532
533 val_count = 20;
534 data_count = 20;
535 type = 1234;
536 wcscpy( valueW, L"xxxxxxxx" );
537 wcscpy( dataW, L"xxxxxxxx" );
538 res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
539 ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res );
540 ok( val_count == 4, "val_count set to %ld instead of 4\n", val_count );
541 ok( data_count == 0, "data_count set to %ld instead of 0\n", data_count );
542 ok( type == REG_BINARY, "type %ld is not REG_BINARY\n", type );
543 ok( !wcscmp( valueW, L"Test" ), "value is not 'Test'\n" );
544 ok( !wcscmp( dataW, L"xxxxxxxx" ), "data is not 'xxxxxxxx'\n" );
545
546 res = RegSetValueExA( test_key, "Test", 0, REG_SZ, (const BYTE *)"foobar", 7 );
547 ok( res == 0, "RegSetValueExA failed error %ld\n", res );
548
549 /* overflow both name and data */
550 val_count = 2;
551 data_count = 2;
552 type = 1234;
553 strcpy( value, "xxxxxxxxxx" );
554 strcpy( data, "xxxxxxxxxx" );
555 res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
556 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
557 ok( val_count == 2, "val_count set to %ld\n", val_count );
558 /* Chinese, Japanese, and Korean editions of Windows 10 sometimes set data_count to a higher value */
559 ok( data_count == 7 || broken( data_count > 7 ), "data_count set to %ld instead of 7\n", data_count );
560 ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
561 ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
562 ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data );
563
564 /* overflow name */
565 val_count = 3;
566 data_count = 16;
567 type = 1234;
568 strcpy( value, "xxxxxxxxxx" );
569 memset( data, 'x', sizeof(data) );
570 data[sizeof(data)-1] = '\0';
571 res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
572 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
573 ok( val_count == 3, "val_count set to %ld\n", val_count );
574 /* In double-byte and UTF-8 locales Windows 10 may set data_count > 7,
575 * potentially even more than the declared buffer size, in which case the
576 * buffer is not NUL-terminated.
577 */
578 ok( data_count == 7 || broken( data_count > 7 ), "data_count set to %ld instead of 7\n", data_count );
579 ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
580 /* v5.1.2600.0 (XP Home and Professional) does not touch value or data in
581 * this case. Neither does Windows 10 21H1 in UTF-8 locales.
582 */
583 ok( !strcmp( value, "Te" ) || !strcmp( value, "xxxxxxxxxx" ),
584 "value set to '%s' instead of 'Te' or 'xxxxxxxxxx'\n", value );
585 ok( !strcmp( data, "foobar" ) || !strcmp( data, "xxxxxxx" ) ||
586 broken( data_count > 7 && data_count < 16 &&
587 strspn( data, "x" ) == data_count && data[data_count] == 0 ) ||
588 broken( data_count >= 16 && strspn( data, "x" ) == sizeof(data) - 1 ),
589 "data set to '%s' instead of 'foobar' or x's, data_count=%lu\n", data, data_count );
590
591 /* overflow empty name */
592 val_count = 0;
593 data_count = 16;
594 type = 1234;
595 strcpy( value, "xxxxxxxxxx" );
596 memset( data, 'x', sizeof(data) );
597 data[sizeof(data)-1] = '\0';
598 res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
599 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
600 ok( val_count == 0, "val_count set to %ld\n", val_count );
601 /* See comment in 'overflow name' section */
602 ok( data_count == 7 || broken( data_count > 7 ), "data_count set to %ld instead of 7\n", data_count );
603 ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
604 ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
605 /* See comment in 'overflow name' section */
606 ok( !strcmp( data, "foobar" ) || !strcmp( data, "xxxxxxx" ) ||
607 broken( data_count > 7 && data_count < 16 &&
608 strspn( data, "x" ) == data_count && data[data_count] == 0 ) ||
609 broken( data_count >= 16 && strspn( data, "x" ) == sizeof(data) - 1 ),
610 "data set to '%s' instead of 'foobar' or x's, data_count=%lu\n", data, data_count );
611
612 /* overflow data */
613 val_count = 20;
614 data_count = 2;
615 type = 1234;
616 strcpy( value, "xxxxxxxxxx" );
617 strcpy( data, "xxxxxxxxxx" );
618 res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
619 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
620 ok( val_count == 20, "val_count set to %ld\n", val_count );
621 ok( data_count == 7, "data_count set to %ld instead of 7\n", data_count );
622 ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
623 ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value );
624 ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data );
625
626 /* no overflow */
627 val_count = 20;
628 data_count = 20;
629 type = 1234;
630 strcpy( value, "xxxxxxxxxx" );
631 strcpy( data, "xxxxxxxxxx" );
632 res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count );
633 ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res );
634 ok( val_count == 4, "val_count set to %ld instead of 4\n", val_count );
635 ok( data_count == 7, "data_count set to %ld instead of 7\n", data_count );
636 ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
637 ok( !strcmp( value, "Test" ), "value is '%s' instead of Test\n", value );
638 ok( !strcmp( data, "foobar" ), "data is '%s' instead of foobar\n", data );
639
640 if (pRegGetValueA) /* avoid a crash on Windows 2000 */
641 {
642 /* no value and no val_count parameter */
643 data_count = 20;
644 type = 1234;
645 strcpy( data, "xxxxxxxxxx" );
646 res = RegEnumValueA( test_key, 0, NULL, NULL, NULL, &type, (BYTE*)data, &data_count );
647 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", res );
648
649 /* no value parameter */
650 val_count = 20;
651 data_count = 20;
652 type = 1234;
653 strcpy( data, "xxxxxxxxxx" );
654 res = RegEnumValueA( test_key, 0, NULL, &val_count, NULL, &type, (BYTE*)data, &data_count );
655 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", res );
656
657 /* no val_count parameter */
658 data_count = 20;
659 type = 1234;
660 strcpy( value, "xxxxxxxxxx" );
661 strcpy( data, "xxxxxxxxxx" );
662 res = RegEnumValueA( test_key, 0, value, NULL, NULL, &type, (BYTE*)data, &data_count );
663 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", res );
664 }
665
666 /* Unicode tests */
667
668 SetLastError(0xdeadbeef);
669 res = RegSetValueExW( test_key, L"Test", 0, REG_SZ, (const BYTE *)L"foobar", 7*sizeof(WCHAR) );
671 {
672 win_skip("RegSetValueExW is not implemented\n");
673 goto cleanup;
674 }
675 ok( res == 0, "RegSetValueExW failed error %ld\n", res );
676
677 /* overflow both name and data */
678 val_count = 2;
679 data_count = 2;
680 type = 1234;
681 wcscpy( valueW, L"xxxxxxxx" );
682 wcscpy( dataW, L"xxxxxxxx" );
683 res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
684 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
685 ok( val_count == 2, "val_count set to %ld\n", val_count );
686 ok( data_count == 7*sizeof(WCHAR), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count );
687 ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
688 ok( !wcscmp( valueW, L"xxxxxxxx" ), "value modified\n" );
689 ok( !wcscmp( dataW, L"xxxxxxxx" ), "data modified\n" );
690
691 /* overflow name */
692 val_count = 3;
693 data_count = 20;
694 type = 1234;
695 wcscpy( valueW, L"xxxxxxxx" );
696 wcscpy( dataW, L"xxxxxxxx" );
697 res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
698 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
699 ok( val_count == 3, "val_count set to %ld\n", val_count );
700 ok( data_count == 7*sizeof(WCHAR), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count );
701 ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
702 ok( !wcscmp( valueW, L"xxxxxxxx" ), "value modified\n" );
703 ok( !wcscmp( dataW, L"xxxxxxxx" ), "data modified\n" );
704
705 /* overflow data */
706 val_count = 20;
707 data_count = 2;
708 type = 1234;
709 wcscpy( valueW, L"xxxxxxxx" );
710 wcscpy( dataW, L"xxxxxxxx" );
711 res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
712 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %ld\n", res );
713 ok( val_count == 4, "val_count set to %ld instead of 4\n", val_count );
714 ok( data_count == 7*sizeof(WCHAR), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count );
715 ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
716 ok( !wcscmp( valueW, L"Test" ), "value is not 'Test'\n" );
717 ok( !wcscmp( dataW, L"xxxxxxxx" ), "data modified\n" );
718
719 /* no overflow */
720 val_count = 20;
721 data_count = 20;
722 type = 1234;
723 wcscpy( valueW, L"xxxxxxxx" );
724 wcscpy( dataW, L"xxxxxxxx" );
725 res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
726 ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res );
727 ok( val_count == 4, "val_count set to %ld instead of 4\n", val_count );
728 ok( data_count == 7*sizeof(WCHAR), "data_count set to %ld instead of 7*sizeof(WCHAR)\n", data_count );
729 ok( type == REG_SZ, "type %ld is not REG_SZ\n", type );
730 ok( !wcscmp( valueW, L"Test" ), "value is not 'Test'\n" );
731 ok( !wcscmp( dataW, L"foobar" ), "data is not 'foobar'\n" );
732
733 if (pRegGetValueA) /* avoid a crash on Windows 2000 */
734 {
735 /* no valueW and no val_count parameter */
736 data_count = 20;
737 type = 1234;
738 wcscpy( dataW, L"xxxxxxxx" );
739 res = RegEnumValueW( test_key, 0, NULL, NULL, NULL, &type, (BYTE*)dataW, &data_count );
740 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", res );
741
742 /* no valueW parameter */
743 val_count = 20;
744 data_count = 20;
745 type = 1234;
746 wcscpy( dataW, L"xxxxxxxx" );
747 res = RegEnumValueW( test_key, 0, NULL, &val_count, NULL, &type, (BYTE*)dataW, &data_count );
748 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", res );
749
750 /* no val_count parameter */
751 data_count = 20;
752 type = 1234;
753 wcscpy( valueW, L"xxxxxxxx" );
754 wcscpy( dataW, L"xxxxxxxx" );
755 res = RegEnumValueW( test_key, 0, valueW, NULL, NULL, &type, (BYTE*)dataW, &data_count );
756 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", res );
757 }
758
759cleanup:
760 RegDeleteKeyA(test_key, "");
761 RegCloseKey(test_key);
762}
763
764static void test_query_value_ex(void)
765{
766 DWORD ret, size, type;
767 BYTE buffer[10];
768
769 size = sizeof(buffer);
770 ret = RegQueryValueExA(hkey_main, "TP1_SZ", NULL, &type, NULL, &size);
771 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
772 ok(size == strlen(sTestpath1) + 1, "(%ld,%ld)\n", (DWORD)strlen(sTestpath1) + 1, size);
773 ok(type == REG_SZ, "type %ld is not REG_SZ\n", type);
774
775 type = 0xdeadbeef;
776 size = 0xdeadbeef;
777 ret = RegQueryValueExA(HKEY_CLASSES_ROOT, "Nonexistent Value", NULL, &type, NULL, &size);
778 ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret);
779 ok(size == 0, "size should have been set to 0 instead of %ld\n", size);
780
781 size = sizeof(buffer);
782 ret = RegQueryValueExA(HKEY_CLASSES_ROOT, "Nonexistent Value", NULL, &type, buffer, &size);
783 ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret);
784 ok(size == sizeof(buffer), "size shouldn't have been changed to %ld\n", size);
785
786 size = 4;
788 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
789}
790
791static void test_get_value(void)
792{
793 DWORD ret;
794 DWORD size;
795 DWORD type;
796 DWORD dw, qw[2];
797 CHAR buf[80];
798 CHAR expanded[] = "bar\\subdir1";
799 CHAR expanded2[] = "ImARatherLongButIndeedNeededString\\subdir1";
800
801 if(!pRegGetValueA)
802 {
803 win_skip("RegGetValue not available on this platform\n");
804 return;
805 }
806
807 /* Invalid parameter */
808 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_DWORD, &type, &dw, NULL);
809 ok(ret == ERROR_INVALID_PARAMETER, "ret=%ld\n", ret);
810
811 /* Query REG_DWORD using RRF_RT_REG_DWORD (ok) */
812 size = type = dw = 0xdeadbeef;
813 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_DWORD, &type, &dw, &size);
814 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
815 ok(size == 4, "size=%ld\n", size);
816 ok(type == REG_DWORD, "type=%ld\n", type);
817 ok(dw == 0x12345678, "dw=%ld\n", dw);
818
819 /* Check RRF_SUBKEY_WOW64*KEY validation on a case without a subkey */
821 ok(ret == ERROR_INVALID_PARAMETER || broken(ret == ERROR_SUCCESS), /* Before Win10 */
822 "ret=%ld\n", ret);
823 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_DWORD | RRF_SUBKEY_WOW6464KEY, NULL, NULL, NULL);
824 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
825 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_DWORD | RRF_SUBKEY_WOW6432KEY, NULL, NULL, NULL);
826 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
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=%ld\n", ret);
831
832 /* Check RRF_SUBKEY_WOW64*KEY validation on a case with a subkey */
833 ret = pRegGetValueA(HKEY_CURRENT_USER, "Software\\Wine\\Test", "DWORD", RRF_RT_REG_DWORD | RRF_SUBKEY_WOW6464KEY | RRF_SUBKEY_WOW6432KEY, NULL, NULL, NULL);
834 ok(ret == ERROR_INVALID_PARAMETER || broken(ret == ERROR_SUCCESS), /* Before Win10 */
835 "ret=%ld\n", ret);
836 ret = pRegGetValueA(HKEY_CURRENT_USER, "Software\\Wine\\Test", "DWORD", RRF_RT_REG_DWORD | RRF_SUBKEY_WOW6464KEY, NULL, NULL, NULL);
837 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
838 ret = pRegGetValueA(HKEY_CURRENT_USER, "Software\\Wine\\Test", "DWORD", RRF_RT_REG_DWORD | RRF_SUBKEY_WOW6432KEY, NULL, NULL, NULL);
839 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
840
841 /* Query REG_DWORD using RRF_RT_REG_BINARY (restricted) */
842 size = type = dw = 0xdeadbeef;
843 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_BINARY, &type, &dw, &size);
844 ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%ld\n", ret);
845 /* Although the function failed all values are retrieved */
846 ok(size == 4, "size=%ld\n", size);
847 ok(type == REG_DWORD, "type=%ld\n", type);
848 ok(dw == 0x12345678, "dw=%ld\n", dw);
849
850 /* Test RRF_ZEROONFAILURE */
851 type = dw = 0xdeadbeef; size = 4;
852 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_SZ|RRF_ZEROONFAILURE, &type, &dw, &size);
853 ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%ld\n", ret);
854 /* Again all values are retrieved ... */
855 ok(size == 4, "size=%ld\n", size);
856 ok(type == REG_DWORD, "type=%ld\n", type);
857 /* ... except the buffer, which is zeroed out */
858 ok(dw == 0, "dw=%ld\n", dw);
859
860 /* Test RRF_ZEROONFAILURE with a NULL buffer... */
861 type = size = 0xbadbeef;
862 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_SZ|RRF_ZEROONFAILURE, &type, NULL, &size);
863 ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%ld\n", ret);
864 ok(size == 4, "size=%ld\n", size);
865 ok(type == REG_DWORD, "type=%ld\n", type);
866
867 /* Query REG_DWORD using RRF_RT_DWORD (ok) */
868 size = type = dw = 0xdeadbeef;
869 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_DWORD, &type, &dw, &size);
870 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
871 ok(size == 4, "size=%ld\n", size);
872 ok(type == REG_DWORD, "type=%ld\n", type);
873 ok(dw == 0x12345678, "dw=%ld\n", dw);
874
875 /* Query 32-bit REG_BINARY using RRF_RT_DWORD (ok) */
876 size = type = dw = 0xdeadbeef;
877 ret = pRegGetValueA(hkey_main, NULL, "BIN32", RRF_RT_DWORD, &type, &dw, &size);
878 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
879 ok(size == 4, "size=%ld\n", size);
880 ok(type == REG_BINARY, "type=%ld\n", type);
881 ok(dw == 0x12345678, "dw=%ld\n", dw);
882
883 /* Query 64-bit REG_BINARY using RRF_RT_DWORD (type mismatch) */
884 qw[0] = qw[1] = size = type = 0xdeadbeef;
885 ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_DWORD, &type, qw, &size);
886 ok(ret == ERROR_DATATYPE_MISMATCH, "ret=%ld\n", ret);
887 ok(size == 8, "size=%ld\n", size);
888 ok(type == REG_BINARY, "type=%ld\n", type);
889 ok(qw[0] == 0x12345678 &&
890 qw[1] == 0x87654321, "qw={%ld,%ld}\n", qw[0], qw[1]);
891
892 /* Query 64-bit REG_BINARY using 32-bit buffer (buffer too small) */
893 type = dw = 0xdeadbeef; size = 4;
894 ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_REG_BINARY, &type, &dw, &size);
895 ok(ret == ERROR_MORE_DATA, "ret=%ld\n", ret);
896 ok(dw == 0xdeadbeef, "dw=%ld\n", dw);
897 ok(size == 8, "size=%ld\n", size);
898
899 /* Query 64-bit REG_BINARY using RRF_RT_QWORD (ok) */
900 qw[0] = qw[1] = size = type = 0xdeadbeef;
901 ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_QWORD, &type, qw, &size);
902 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
903 ok(size == 8, "size=%ld\n", size);
904 ok(type == REG_BINARY, "type=%ld\n", type);
905 ok(qw[0] == 0x12345678 &&
906 qw[1] == 0x87654321, "qw={%ld,%ld}\n", qw[0], qw[1]);
907
908 /* Query REG_SZ using RRF_RT_REG_SZ (ok) */
909 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
910 ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ, &type, buf, &size);
911 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
912 ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%ld\n", lstrlenA(sTestpath1), size);
913 ok(type == REG_SZ, "type=%ld\n", type);
914 ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
915
916 /* Query REG_SZ using RRF_RT_REG_SZ and no buffer (ok) */
917 type = 0xdeadbeef; size = 0;
918 ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ, &type, NULL, &size);
919 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
920 /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */
922 "strlen(sTestpath1)=%d size=%ld\n", lstrlenA(sTestpath1), size);
923 ok(type == REG_SZ, "type=%ld\n", type);
924
925 /* Query REG_SZ using RRF_RT_REG_SZ on a zero-byte value (ok) */
927 type = 0xdeadbeef;
928 size = 0;
929 ret = pRegGetValueA(hkey_main, NULL, "TP1_ZB_SZ", RRF_RT_REG_SZ, &type, NULL, &size);
930 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
931 ok(size == 1, "size=%ld\n", size);
932 ok(type == REG_SZ, "type=%ld\n", type);
933 ret = pRegGetValueA(hkey_main, NULL, "TP1_ZB_SZ", RRF_RT_REG_SZ, &type, buf, &size);
934 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
935 ok(size == 1, "size=%ld\n", size);
936 ok(type == REG_SZ, "type=%ld\n", type);
937 ok(!strcmp(buf, ""), "Expected \"\", got \"%s\"\n", buf);
938
939 /* Query REG_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (ok) */
940 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
941 ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ|RRF_NOEXPAND, &type, buf, &size);
942 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
943 ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%ld\n", lstrlenA(sTestpath1), size);
944 ok(type == REG_SZ, "type=%ld\n", type);
945 ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
946
947 /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ and no buffer (ok, expands) */
948 size = 0;
949 ret = pRegGetValueA(hkey_main, NULL, "TP2_EXP_SZ", RRF_RT_REG_SZ, NULL, NULL, &size);
950 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
951 ok(size == strlen(expanded2)+2,
952 "strlen(expanded2)=%d, strlen(sTestpath2)=%d, size=%ld\n", lstrlenA(expanded2), lstrlenA(sTestpath2), size);
953
954 /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ (ok, expands) */
955 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
956 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_SZ, &type, buf, &size);
957 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
959 "strlen(expanded)=%d, strlen(sTestpath1)=%d, size=%ld\n", lstrlenA(expanded), lstrlenA(sTestpath1), size);
960 ok(type == REG_SZ, "type=%ld\n", type);
961 ok(!strcmp(expanded, buf), "expanded=\"%s\" buf=\"%s\"\n", expanded, buf);
962
963 /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ (ok, expands a lot) */
964 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
965 ret = pRegGetValueA(hkey_main, NULL, "TP2_EXP_SZ", RRF_RT_REG_SZ, &type, buf, &size);
966 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
967 ok(size == strlen(expanded2)+1,
968 "strlen(expanded2)=%d, strlen(sTestpath1)=%d, size=%ld\n", lstrlenA(expanded2), lstrlenA(sTestpath2), size);
969 ok(type == REG_SZ, "type=%ld\n", type);
970 ok(!strcmp(expanded2, buf), "expanded2=\"%s\" buf=\"%s\"\n", expanded2, buf);
971
972 /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND (ok, doesn't expand) */
973 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
974 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND, &type, buf, &size);
975 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
976 ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%ld\n", lstrlenA(sTestpath1), size);
977 ok(type == REG_EXPAND_SZ, "type=%ld\n", type);
978 ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
979
980 /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND and no buffer (ok, doesn't expand) */
981 size = 0xbadbeef;
982 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND, NULL, NULL, &size);
983 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
984 todo_wine ok(size == strlen(sTestpath1)+2, "strlen(sTestpath1)=%d size=%ld\n", lstrlenA(sTestpath1), size);
985
986 /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (type mismatch) */
987 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_SZ|RRF_NOEXPAND, NULL, NULL, NULL);
988 ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%ld\n", ret);
989
990 /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ (not allowed without RRF_NOEXPAND) */
991 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ, NULL, NULL, NULL);
992 /* before win8: ERROR_INVALID_PARAMETER, win8: ERROR_UNSUPPORTED_TYPE */
994
995 /* Query REG_EXPAND_SZ using RRF_RT_ANY */
996 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
997 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_ANY, &type, buf, &size);
998 ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
1000 "strlen(expanded)=%d, strlen(sTestpath1)=%d, size=%ld\n", lstrlenA(expanded), lstrlenA(sTestpath1), size);
1001 ok(type == REG_SZ, "type=%ld\n", type);
1002 ok(!strcmp(expanded, buf), "expanded=\"%s\" buf=\"%s\"\n", expanded, buf);
1003}
1004
1005static void test_reg_open_key(void)
1006{
1007 DWORD ret = 0;
1008 HKEY hkResult = NULL;
1009 HKEY hkPreserve = NULL;
1010 HKEY hkRoot64 = NULL;
1011 HKEY hkRoot32 = NULL;
1012 BOOL bRet;
1014 PSID world_sid;
1016 PACL key_acl;
1018
1019 /* successful open */
1020 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult);
1021 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1022 ok(hkResult != NULL, "expected hkResult != NULL\n");
1023 hkPreserve = hkResult;
1024
1025 /* open same key twice */
1026 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult);
1027 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1028 ok(hkResult != hkPreserve, "expected hkResult != hkPreserve\n");
1029 ok(hkResult != NULL, "hkResult != NULL\n");
1030 RegCloseKey(hkResult);
1031
1032 /* trailing slashes */
1033 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test\\\\", &hkResult);
1034 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1035 RegCloseKey(hkResult);
1036
1037 /* open nonexistent key
1038 * check that hkResult is set to NULL
1039 */
1040 hkResult = hkPreserve;
1041 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
1042 ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret);
1043 ok(hkResult == NULL, "expected hkResult == NULL\n");
1044
1045 /* open the same nonexistent key again to make sure the key wasn't created */
1046 hkResult = hkPreserve;
1047 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult);
1048 ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret);
1049 ok(hkResult == NULL, "expected hkResult == NULL\n");
1050
1051 /* send in NULL lpSubKey
1052 * check that hkResult receives the value of hKey
1053 */
1054 hkResult = hkPreserve;
1055 ret = RegOpenKeyA(HKEY_CURRENT_USER, NULL, &hkResult);
1056 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1057 ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
1058
1059 /* send empty-string in lpSubKey */
1060 hkResult = hkPreserve;
1061 ret = RegOpenKeyA(HKEY_CURRENT_USER, "", &hkResult);
1062 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1063 ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n");
1064
1065 /* send in NULL lpSubKey and NULL hKey
1066 * hkResult is set to NULL
1067 */
1068 hkResult = hkPreserve;
1069 ret = RegOpenKeyA(NULL, NULL, &hkResult);
1070 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1071 ok(hkResult == NULL, "expected hkResult == NULL\n");
1072
1073 /* only send NULL hKey
1074 * the value of hkResult remains unchanged
1075 */
1076 hkResult = hkPreserve;
1077 ret = RegOpenKeyA(NULL, "Software\\Wine\\Test", &hkResult);
1078 ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */
1079 "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %ld\n", ret);
1080 ok(hkResult == hkPreserve, "expected hkResult == hkPreserve\n");
1081
1082 /* send in NULL hkResult */
1083 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", NULL);
1084 ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", ret);
1085
1087 ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", ret);
1088
1090 ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", ret);
1091
1092 /* beginning backslash character */
1093 ret = RegOpenKeyA(HKEY_CURRENT_USER, "\\Software\\Wine\\Test", &hkResult);
1094 ok(ret == ERROR_BAD_PATHNAME || broken(ret == ERROR_SUCCESS), /* wow64 */
1095 "expected ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %ld\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,
1101 "expected ERROR_SUCCESS, ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %ld\n", ret);
1102 RegCloseKey(hkResult);
1103
1104 /* NULL or empty subkey of special root */
1105 hkResult = NULL;
1107 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1108 ok(hkResult == HKEY_CLASSES_ROOT, "expected hkResult == HKEY_CLASSES_ROOT\n");
1109
1110 hkResult = NULL;
1111 ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, "", 0, KEY_QUERY_VALUE, &hkResult);
1112 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1113 ok(hkResult == HKEY_CLASSES_ROOT, "expected hkResult == HKEY_CLASSES_ROOT\n");
1114
1115 hkResult = NULL;
1116 ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, "\\", 0, KEY_QUERY_VALUE, &hkResult);
1117 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1118 ok(hkResult != HKEY_CLASSES_ROOT, "expected hkResult to be a new key\n");
1119 ok(!RegCloseKey(hkResult), "got invalid hkey\n");
1120
1121 /* empty subkey of existing handle */
1122 hkResult = hkPreserve;
1123 ret = RegOpenKeyExA(hkPreserve, "", 0, KEY_QUERY_VALUE, &hkResult);
1124 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1125 ok(hkResult != hkPreserve, "expected hkResult != hkPreserve\n");
1126 ok(!RegCloseKey(hkResult), "got invalid hkey\n");
1127
1128 /* NULL subkey of existing handle */
1129 hkResult = hkPreserve;
1130 ret = RegOpenKeyExA(hkPreserve, NULL, 0, KEY_QUERY_VALUE, &hkResult);
1131 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1132 ok(hkResult != hkPreserve, "expected hkResult != hkPreserve\n");
1133 ok(!RegCloseKey(hkResult), "got invalid hkey\n");
1134
1135 /* empty subkey of NULL */
1136 hkResult = hkPreserve;
1137 ret = RegOpenKeyExW(NULL, L"", 0, KEY_QUERY_VALUE, &hkResult);
1138 ok(ret == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", ret);
1139#ifdef __REACTOS__
1140 ok(hkResult == NULL || broken(GetNTVersion() <= _WIN32_WINNT_WS03), "expected hkResult == NULL\n");
1141#else
1142 ok(hkResult == NULL, "expected hkResult == NULL\n");
1143#endif
1144
1145 hkResult = hkPreserve;
1146 ret = RegOpenKeyExA(NULL, "", 0, KEY_QUERY_VALUE, &hkResult);
1147 ok(ret == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", ret);
1148 ok(hkResult == hkPreserve, "expected hkResult == hkPreserve\n");
1149
1150 RegCloseKey(hkPreserve);
1151
1152 /* WOW64 flags */
1153 hkResult = NULL;
1154 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WOW64_32KEY, &hkResult);
1155 ok(ret == ERROR_SUCCESS && hkResult, "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%lu)\n", ret);
1156 RegCloseKey(hkResult);
1157
1158 hkResult = NULL;
1159 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WOW64_64KEY, &hkResult);
1160 ok(ret == ERROR_SUCCESS && hkResult, "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%lu)\n", ret);
1161 RegCloseKey(hkResult);
1162
1163 /* check special HKEYs on 64bit
1164 * only the lower 4 bytes of the supplied key are used
1165 */
1166 if (ptr_size == 64)
1167 {
1168 /* HKEY_CURRENT_USER */
1169 ret = RegOpenKeyA(UlongToHandle(HandleToUlong(HKEY_CURRENT_USER)), "Software", &hkResult);
1170 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1171 ok(hkResult != NULL, "expected hkResult != NULL\n");
1172 RegCloseKey(hkResult);
1173
1174 ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_CURRENT_USER) | (ULONG64)1 << 32), "Software", &hkResult);
1175 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1176 ok(hkResult != NULL, "expected hkResult != NULL\n");
1177 RegCloseKey(hkResult);
1178
1179 ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_CURRENT_USER) | (ULONG64)0xdeadbeef << 32), "Software", &hkResult);
1180 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1181 ok(hkResult != NULL, "expected hkResult != NULL\n");
1182 RegCloseKey(hkResult);
1183
1184 ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_CURRENT_USER) | (ULONG64)0xffffffff << 32), "Software", &hkResult);
1185 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1186 ok(hkResult != NULL, "expected hkResult != NULL\n");
1187 RegCloseKey(hkResult);
1188
1189 /* HKEY_LOCAL_MACHINE */
1190 ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_LOCAL_MACHINE) | (ULONG64)0xdeadbeef << 32), "Software", &hkResult);
1191 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1192 ok(hkResult != NULL, "expected hkResult != NULL\n");
1193 RegCloseKey(hkResult);
1194 }
1195
1196 /* Try using WOW64 flags when opening a key with a DACL set to verify that
1197 * the registry access check is performed correctly. Redirection isn't
1198 * being tested, so the tests don't care about whether the process is
1199 * running under WOW64. */
1200 if (!is_64bit)
1201 {
1202 skip("Not running WoW64 tests on 32-bit\n");
1203 return;
1204 }
1205
1206 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1207 KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &hkRoot32, NULL);
1209 "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%lu)\n", ret);
1210 if (ret == ERROR_ACCESS_DENIED) return;
1211 ok(hkRoot32 != NULL, "hkRoot32 was set\n");
1212
1213 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1214 KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &hkRoot64, NULL);
1216 "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%lu)\n", ret);
1217 if (ret == ERROR_ACCESS_DENIED)
1218 {
1219 RegDeleteKeyA(hkRoot32, "");
1220 RegCloseKey(hkRoot32);
1221 return;
1222 }
1223 ok(hkRoot64 != NULL, "hkRoot64 was set\n");
1224
1225 bRet = AllocateAndInitializeSid(&sid_authority, 1, SECURITY_WORLD_RID,
1226 0, 0, 0, 0, 0, 0, 0, &world_sid);
1227 ok(bRet == TRUE,
1228 "Expected AllocateAndInitializeSid to return TRUE, got %d, last error %lu\n", bRet, GetLastError());
1229
1230 access.grfAccessPermissions = GENERIC_ALL | STANDARD_RIGHTS_ALL;
1231 access.grfAccessMode = SET_ACCESS;
1233 access.Trustee.pMultipleTrustee = NULL;
1234 access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1235 access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
1236 access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
1237 access.Trustee.ptstrName = (char *)world_sid;
1238
1239 ret = SetEntriesInAclA(1, &access, NULL, &key_acl);
1240 ok(ret == ERROR_SUCCESS,
1241 "Expected SetEntriesInAclA to return ERROR_SUCCESS, got %lu, last error %lu\n", ret, GetLastError());
1242
1245 ok(bRet == TRUE,
1246 "Expected InitializeSecurityDescriptor to return TRUE, got %d, last error %lu\n", bRet, GetLastError());
1247
1248 bRet = SetSecurityDescriptorDacl(sd, TRUE, key_acl, FALSE);
1249 ok(bRet == TRUE,
1250 "Expected SetSecurityDescriptorDacl to return TRUE, got %d, last error %lu\n", bRet, GetLastError());
1251
1252 if (limited_user)
1253 {
1254 skip("not enough privileges to modify HKLM\n");
1255 }
1256 else
1257 {
1258 LONG error;
1259
1262 "Expected RegSetKeySecurity to return success, got error %lu\n", error);
1263
1266 "Expected RegSetKeySecurity to return success, got error %lu\n", error);
1267
1268 hkResult = NULL;
1269 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, KEY_WOW64_64KEY | KEY_READ, &hkResult);
1270 ok(ret == ERROR_SUCCESS, "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%lu)\n", ret);
1271 ok(hkResult != NULL, "hkResult wasn't set\n");
1272 RegCloseKey(hkResult);
1273
1274 hkResult = NULL;
1275 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, KEY_WOW64_32KEY | KEY_READ, &hkResult);
1276 ok(ret == ERROR_SUCCESS, "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%lu)\n", ret);
1277 ok(hkResult != NULL, "hkResult wasn't set\n");
1278 RegCloseKey(hkResult);
1279 }
1280
1281 free(sd);
1282 LocalFree(key_acl);
1283 FreeSid(world_sid);
1284 RegDeleteKeyA(hkRoot64, "");
1285 RegCloseKey(hkRoot64);
1286 RegDeleteKeyA(hkRoot32, "");
1287 RegCloseKey(hkRoot32);
1288}
1289
1290static void test_reg_create_key(void)
1291{
1292 LONG ret;
1293 HKEY hkey1, hkey2;
1294 HKEY hkRoot64 = NULL;
1295 HKEY hkRoot32 = NULL;
1296 DWORD dwRet;
1297 BOOL bRet;
1299 PSID world_sid;
1301 PACL key_acl;
1303
1304 /* NULL return key check */
1305 ret = RegCreateKeyA(hkey_main, "Subkey1", NULL);
1306 ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %ld.\n", ret);
1307
1308 ret = RegCreateKeyW(hkey_main, L"Subkey1", NULL);
1309#ifdef __REACTOS__
1310 ok(ret == ERROR_INVALID_PARAMETER || broken(ERROR_BADKEY) /* WS03 */, "Got unexpected ret %ld.\n", ret);
1311#else
1312 ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %ld.\n", ret);
1313#endif
1314
1315 ret = RegCreateKeyExA(hkey_main, "Subkey1", 0, NULL, 0, KEY_NOTIFY, NULL, NULL, NULL);
1316 ok(ret == ERROR_BADKEY, "Got unexpected ret %ld.\n", ret);
1317
1318 ret = RegCreateKeyExW(hkey_main, L"Subkey1", 0, NULL, 0, KEY_NOTIFY, NULL, NULL, NULL);
1319 ok(ret == ERROR_BADKEY, "Got unexpected ret %ld.\n", ret);
1320
1321 ret = RegCreateKeyExA(hkey_main, "Subkey1", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL);
1322 ok(!ret, "RegCreateKeyExA failed with error %ld\n", ret);
1323 /* should succeed: all versions of Windows ignore the access rights
1324 * to the parent handle */
1325 ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey2, NULL);
1326 ok(!ret, "RegCreateKeyExA failed with error %ld\n", ret);
1327
1328 /* clean up */
1329 RegDeleteKeyA(hkey2, "");
1330 RegDeleteKeyA(hkey1, "");
1331 RegCloseKey(hkey2);
1332 RegCloseKey(hkey1);
1333
1334 /* test creation of volatile keys */
1336 ok(!ret, "RegCreateKeyExA failed with error %ld\n", ret);
1337 ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey2, NULL);
1338 ok(ret == ERROR_CHILD_MUST_BE_VOLATILE, "RegCreateKeyExA failed with error %ld\n", ret);
1339 if (!ret) RegCloseKey( hkey2 );
1340 ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey2, NULL);
1341 ok(!ret, "RegCreateKeyExA failed with error %ld\n", ret);
1342 RegCloseKey(hkey2);
1343 /* should succeed if the key already exists */
1344 ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey2, NULL);
1345 ok(!ret, "RegCreateKeyExA failed with error %ld\n", ret);
1346
1347 /* clean up */
1348 RegDeleteKeyA(hkey2, "");
1349 RegDeleteKeyA(hkey1, "");
1350 RegCloseKey(hkey2);
1351 RegCloseKey(hkey1);
1352
1353 /* beginning backslash character */
1354 ret = RegCreateKeyExA(hkey_main, "\\Subkey3", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL);
1355 ok(ret == ERROR_BAD_PATHNAME, "expected ERROR_BAD_PATHNAME, got %ld\n", ret);
1356
1357 /* trailing backslash characters */
1358 ret = RegCreateKeyExA(hkey_main, "Subkey4\\\\", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL);
1359 ok(ret == ERROR_SUCCESS, "RegCreateKeyExA failed with error %ld\n", ret);
1360 RegDeleteKeyA(hkey1, "");
1361 RegCloseKey(hkey1);
1362
1363 /* WOW64 flags - open an existing key */
1364 hkey1 = NULL;
1366 ok(ret == ERROR_SUCCESS && hkey1 != NULL,
1367 "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%lu)\n", ret);
1368 RegCloseKey(hkey1);
1369
1370 hkey1 = NULL;
1372 ok(ret == ERROR_SUCCESS && hkey1 != NULL,
1373 "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%lu)\n", ret);
1374 RegCloseKey(hkey1);
1375
1376 /* Try using WOW64 flags when opening a key with a DACL set to verify that
1377 * the registry access check is performed correctly. Redirection isn't
1378 * being tested, so the tests don't care about whether the process is
1379 * running under WOW64. */
1380 if (!has_wow64())
1381 {
1382 skip("WOW64 flags are not recognized\n");
1383 return;
1384 }
1385
1386 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1387 KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &hkRoot32, NULL);
1388 if (limited_user)
1389 ok(ret == ERROR_ACCESS_DENIED && hkRoot32 == NULL,
1390 "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%ld)\n", ret);
1391 else
1392 ok(ret == ERROR_SUCCESS && hkRoot32 != NULL,
1393 "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%ld)\n", ret);
1394
1395 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1396 KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &hkRoot64, NULL);
1397 if (limited_user)
1398 ok(ret == ERROR_ACCESS_DENIED && hkRoot64 == NULL,
1399 "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%ld)\n", ret);
1400 else
1401 ok(ret == ERROR_SUCCESS && hkRoot64 != NULL,
1402 "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%ld)\n", ret);
1403
1404 bRet = AllocateAndInitializeSid(&sid_authority, 1, SECURITY_WORLD_RID,
1405 0, 0, 0, 0, 0, 0, 0, &world_sid);
1406 ok(bRet == TRUE,
1407 "Expected AllocateAndInitializeSid to return TRUE, got %d, last error %lu\n", bRet, GetLastError());
1408
1409 access.grfAccessPermissions = GENERIC_ALL | STANDARD_RIGHTS_ALL;
1410 access.grfAccessMode = SET_ACCESS;
1412 access.Trustee.pMultipleTrustee = NULL;
1413 access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1414 access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
1415 access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
1416 access.Trustee.ptstrName = (char *)world_sid;
1417
1418 dwRet = SetEntriesInAclA(1, &access, NULL, &key_acl);
1419 ok(dwRet == ERROR_SUCCESS,
1420 "Expected SetEntriesInAclA to return ERROR_SUCCESS, got %lu, last error %lu\n", dwRet, GetLastError());
1421
1424 ok(bRet == TRUE,
1425 "Expected InitializeSecurityDescriptor to return TRUE, got %d, last error %lu\n", bRet, GetLastError());
1426
1427 bRet = SetSecurityDescriptorDacl(sd, TRUE, key_acl, FALSE);
1428 ok(bRet == TRUE,
1429 "Expected SetSecurityDescriptorDacl to return TRUE, got %d, last error %lu\n", bRet, GetLastError());
1430
1431 if (limited_user)
1432 {
1433 skip("not enough privileges to modify HKLM\n");
1434 }
1435 else
1436 {
1438 ok(ret == ERROR_SUCCESS,
1439 "Expected RegSetKeySecurity to return success, got error %lu\n", ret);
1440
1442 ok(ret == ERROR_SUCCESS,
1443 "Expected RegSetKeySecurity to return success, got error %lu\n", ret);
1444
1445 hkey1 = NULL;
1446 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1447 KEY_WOW64_64KEY | KEY_READ, NULL, &hkey1, NULL);
1448 ok(ret == ERROR_SUCCESS && hkey1 != NULL,
1449 "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%lu)\n", ret);
1450 RegCloseKey(hkey1);
1451
1452 hkey1 = NULL;
1453 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
1454 KEY_WOW64_32KEY | KEY_READ, NULL, &hkey1, NULL);
1455 ok(ret == ERROR_SUCCESS && hkey1 != NULL,
1456 "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%lu)\n", ret);
1457 RegCloseKey(hkey1);
1458 }
1459
1460 free(sd);
1461 LocalFree(key_acl);
1462 FreeSid(world_sid);
1463 RegDeleteKeyA(hkRoot64, "");
1464 RegCloseKey(hkRoot64);
1465 RegDeleteKeyA(hkRoot32, "");
1466 RegCloseKey(hkRoot32);
1467}
1468
1469static void test_reg_close_key(void)
1470{
1471 DWORD ret = 0;
1472 HKEY hkHandle;
1473
1474 /* successfully close key
1475 * hkHandle remains changed after call to RegCloseKey
1476 */
1477 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkHandle);
1478 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1479 ret = RegCloseKey(hkHandle);
1480 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1481
1482 /* try to close the key twice */
1483 ret = RegCloseKey(hkHandle); /* Windows 95 doesn't mind. */
1485 "expected ERROR_INVALID_HANDLE or ERROR_SUCCESS, got %ld\n", ret);
1486
1487 /* try to close a NULL handle */
1488 ret = RegCloseKey(NULL);
1489 ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */
1490 "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %ld\n", ret);
1491
1492 /* Check to see if we didn't potentially close our main handle, which could happen on win98 as
1493 * win98 doesn't give a new handle when the same key is opened.
1494 * Not re-opening will make some next tests fail.
1495 */
1496 if (hkey_main == hkHandle)
1497 {
1498 trace("The main handle is most likely closed, so re-opening\n");
1499 RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main );
1500 }
1501}
1502
1503static void test_reg_delete_key(void)
1504{
1505 DWORD ret;
1506 HKEY key;
1507
1509 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
1510
1511 ret = RegCreateKeyA(hkey_main, "deleteme", &key);
1512 ok(ret == ERROR_SUCCESS, "Could not create key, got %ld\n", ret);
1513 ret = RegDeleteKeyA(key, "");
1514 ok(ret == ERROR_SUCCESS, "RegDeleteKeyA failed, got %ld\n", ret);
1516 ret = RegOpenKeyA(hkey_main, "deleteme", &key);
1517 ok(ret == ERROR_FILE_NOT_FOUND, "Key was not deleted, got %ld\n", ret);
1519
1520 /* Test deleting 32-bit keys */
1522 ok(ret == ERROR_SUCCESS, "Could not create key, got %ld\n", ret);
1524
1525 ret = RegOpenKeyExA(hkey_main, "deleteme", 0, KEY_READ | KEY_WOW64_32KEY, &key);
1526 ok(ret == ERROR_SUCCESS, "Could not open key, got %ld\n", ret);
1527
1529 ok(ret == ERROR_SUCCESS, "RegDeleteKeyExA failed, got %ld\n", ret);
1531
1532 ret = RegOpenKeyExA(hkey_main, "deleteme", 0, KEY_READ | KEY_WOW64_32KEY, &key);
1533 ok(ret == ERROR_FILE_NOT_FOUND, "Key was not deleted, got %ld\n", ret);
1535}
1536
1538{
1540 HANDLE hToken;
1541 LUID luid;
1542
1544 return FALSE;
1545
1546 if(!LookupPrivilegeValueA(NULL, privilege, &luid))
1547 {
1548 CloseHandle(hToken);
1549 return FALSE;
1550 }
1551
1552 tp.PrivilegeCount = 1;
1553 tp.Privileges[0].Luid = luid;
1554
1555 if (set)
1556 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1557 else
1558 tp.Privileges[0].Attributes = 0;
1559
1561 if (GetLastError() != ERROR_SUCCESS)
1562 {
1563 CloseHandle(hToken);
1564 return FALSE;
1565 }
1566
1567 CloseHandle(hToken);
1568 return TRUE;
1569}
1570
1571static void delete_dir(const char *path)
1572{
1573 char file[2 * MAX_PATH], *p;
1575 HANDLE hfind;
1576 BOOL r;
1577
1578 strcpy(file, path);
1579 p = file + strlen(file);
1580 p[0] = '\\';
1581 p[1] = '*';
1582 p[2] = 0;
1583 hfind = FindFirstFileA(file, &fd);
1584 if (hfind != INVALID_HANDLE_VALUE)
1585 {
1586 do
1587 {
1588 if (!strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, ".."))
1589 continue;
1590
1591 strcpy(p + 1, fd.cFileName);
1592 r = DeleteFileA(file);
1593 ok(r, "DeleteFile failed on %s: %ld\n", debugstr_a(file), GetLastError());
1594 } while(FindNextFileA(hfind, &fd));
1595 FindClose(hfind);
1596 }
1597
1599 ok(r, "RemoveDirectory failed: %ld\n", GetLastError());
1600}
1601
1602static void test_reg_load_key(void)
1603{
1604 char saved_key[2 * MAX_PATH], buf[16], *p;
1608 DWORD ret, size;
1609 HKEY key;
1610
1613 {
1614 win_skip("Failed to set SE_RESTORE_NAME privileges, skipping tests\n");
1615 return;
1616 }
1617
1618 GetTempPathA(MAX_PATH, saved_key);
1619 strcat(saved_key, "\\wine_reg_test");
1620 CreateDirectoryA(saved_key, NULL);
1621 strcat(saved_key, "\\saved_key");
1622
1623 ret = RegSaveKeyA(hkey_main, saved_key, NULL);
1624 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1625
1626 ret = RegLoadKeyA(HKEY_LOCAL_MACHINE, "Test", saved_key);
1627 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1628
1630 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1631
1632 ret = RegSetValueExA(key, "test", 0, REG_SZ, (BYTE *)"value", 6);
1633 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1634
1635 /* try to unload though the key handle is live */
1636 pRtlInitUnicodeString(&key_name, L"\\REGISTRY\\Machine\\Test");
1638 status = pNtUnloadKey(&attr);
1639 ok(status == STATUS_CANNOT_DELETE, "expected STATUS_CANNOT_DELETE, got %08lx\n", status);
1640
1642
1644 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1645
1646 ret = RegLoadKeyA(HKEY_LOCAL_MACHINE, "Test", "");
1647 ok(ret == ERROR_INVALID_PARAMETER, "expected INVALID_PARAMETER, got %ld\n", ret);
1648
1649 /* check if modifications are saved */
1650 ret = RegLoadKeyA(HKEY_LOCAL_MACHINE, "Test", saved_key);
1651 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1652
1654 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1655
1656 size = sizeof(buf);
1657 ret = RegGetValueA(key, NULL, "test", RRF_RT_REG_SZ, NULL, buf, &size);
1658 todo_wine ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1659 if (ret == ERROR_SUCCESS)
1660 {
1661 ok(size == 6, "size = %ld\n", size);
1662 ok(!strcmp(buf, "value"), "buf = %s\n", buf);
1663 }
1664
1666
1668 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1669
1670 pRtlInitUnicodeString(&key_name, L"\\REGISTRY\\User\\.Default");
1672 status = pNtUnloadKey(&attr);
1673#ifdef __REACTOS__
1674 ok(status == STATUS_ACCESS_DENIED || broken(status == STATUS_CANNOT_DELETE) /* WS03 */, "expected STATUS_ACCESS_DENIED, got %08lx\n", status);
1675#else
1676 ok(status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %08lx\n", status);
1677#endif
1678
1679 ret = RegUnLoadKeyA(HKEY_USERS, ".Default");
1680 ok(ret == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", ret);
1681
1684
1685 p = strrchr(saved_key, '\\');
1686 *p = 0;
1687 delete_dir(saved_key);
1688}
1689
1690/* Helper function to wait for a file blocked by the registry to be available */
1691static void wait_file_available(char *path)
1692{
1693 int attempts = 0;
1694 HANDLE file = NULL;
1695
1696 while (((file = CreateFileA(path, GENERIC_READ, 0, NULL,
1698 && attempts++ < 10)
1699 {
1700 Sleep(200);
1701 }
1702 ok(file != INVALID_HANDLE_VALUE, "couldn't open file %s after 10 attempts error %ld.\n", path, GetLastError());
1704}
1705
1706static void test_reg_load_app_key(void)
1707{
1708#if defined(__REACTOS__) && DLL_EXPORT_VERSION < 0x600
1709 skip("test_reg_load_app_key() can't be built unless DLL_EXPORT_VERSION >= 0x600\n");
1710#else
1711 DWORD ret, size;
1712 char hivefilepath[2 * MAX_PATH], *p;
1713 const BYTE test_data[] = "Hello World";
1714 BYTE output[sizeof(test_data)];
1715 HKEY appkey = NULL;
1716
1718 {
1719 win_skip("Failed to set SE_BACKUP_NAME privileges, skipping tests\n");
1720 return;
1721 }
1722
1723 GetTempPathA(MAX_PATH, hivefilepath);
1724 strcat(hivefilepath, "\\wine_reg_test");
1725 CreateDirectoryA(hivefilepath, NULL);
1726 strcat(hivefilepath, "\\saved_key");
1727
1728 ret = RegSaveKeyA(hkey_main, hivefilepath, NULL);
1729 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1730
1732
1733 /* Test simple key load */
1734 /* Check if the changes are saved */
1735 ret = RegLoadAppKeyA(hivefilepath, &appkey, KEY_READ | KEY_WRITE, 0, 0);
1736 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1737 ok(appkey != NULL, "got a null key\n");
1738
1739 ret = RegSetValueExA(appkey, "testkey", 0, REG_BINARY, test_data, sizeof(test_data));
1740 todo_wine ok(ret == ERROR_SUCCESS, "couldn't set key value %lx\n", ret);
1741 RegCloseKey(appkey);
1742
1743 wait_file_available(hivefilepath);
1744
1745 appkey = NULL;
1746 ret = RegLoadAppKeyA(hivefilepath, &appkey, KEY_READ, 0, 0);
1747 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1748 ok(appkey != NULL, "got a null key\n");
1749
1750 size = sizeof(test_data);
1751 memset(output, 0xff, sizeof(output));
1752 ret = RegGetValueA(appkey, NULL, "testkey", RRF_RT_REG_BINARY, NULL, output, &size);
1753 todo_wine ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
1754 ok(size == sizeof(test_data), "size doesn't match %ld != %ld\n", size, (DWORD)sizeof(test_data));
1755 todo_wine ok(!memcmp(test_data, output, sizeof(test_data)), "output is not what expected\n");
1756
1757 RegCloseKey(appkey);
1758
1759 wait_file_available(hivefilepath);
1760
1761 p = strrchr(hivefilepath, '\\');
1762 *p = 0;
1763 delete_dir(hivefilepath);
1764#endif
1765}
1766
1767/* tests that show that RegConnectRegistry and
1768 OpenSCManager accept computer names without the
1769 \\ prefix (what MSDN says). */
1770static void test_regconnectregistry( void)
1771{
1772 CHAR compName[MAX_COMPUTERNAME_LENGTH + 1];
1773 CHAR netwName[MAX_COMPUTERNAME_LENGTH + 3]; /* 2 chars for double backslash */
1774 DWORD len = sizeof(compName) ;
1775 BOOL ret;
1776 LONG retl;
1777 HKEY hkey;
1778 SC_HANDLE schnd;
1779
1780 SetLastError(0xdeadbeef);
1781 ret = GetComputerNameA(compName, &len);
1782 ok( ret, "GetComputerName failed err = %ld\n", GetLastError());
1783 if( !ret) return;
1784
1785 lstrcpyA(netwName, "\\\\");
1786 lstrcpynA(netwName+2, compName, MAX_COMPUTERNAME_LENGTH + 1);
1787
1788 retl = RegConnectRegistryA( compName, HKEY_LOCAL_MACHINE, &hkey);
1789 ok( !retl, "RegConnectRegistryA failed err = %ld\n", retl);
1790 if( !retl) RegCloseKey( hkey);
1791
1792 retl = RegConnectRegistryA( netwName, HKEY_LOCAL_MACHINE, &hkey);
1793 ok( !retl, "RegConnectRegistryA failed err = %ld\n", retl);
1794 if( !retl) RegCloseKey( hkey);
1795
1796 SetLastError(0xdeadbeef);
1797 schnd = OpenSCManagerA( compName, NULL, GENERIC_READ);
1799 {
1800 win_skip("OpenSCManagerA is not implemented\n");
1801 return;
1802 }
1803
1804 ok( schnd != NULL, "OpenSCManagerA failed err = %ld\n", GetLastError());
1805 CloseServiceHandle( schnd);
1806
1807 SetLastError(0xdeadbeef);
1808 schnd = OpenSCManagerA( netwName, NULL, GENERIC_READ);
1809 ok( schnd != NULL, "OpenSCManagerA failed err = %ld\n", GetLastError());
1810 CloseServiceHandle( schnd);
1811
1812}
1813
1814static void test_reg_query_value(void)
1815{
1816 HKEY subkey;
1817 CHAR val[MAX_PATH];
1818 WCHAR valW[5];
1819 LONG size, ret;
1820
1821 ret = RegCreateKeyA(hkey_main, "subkey", &subkey);
1822 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
1823
1824 ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4);
1825 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
1826
1827 /* try an invalid hkey */
1828 SetLastError(0xdeadbeef);
1829 size = MAX_PATH;
1830 ret = RegQueryValueA((HKEY)0xcafebabe, "subkey", val, &size);
1832 ret == ERROR_BADKEY || /* Windows 98 returns BADKEY */
1833 ret == ERROR_ACCESS_DENIED, /* non-admin winxp */
1834 "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %ld\n", ret);
1835 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1836
1837 /* try a NULL hkey */
1838 SetLastError(0xdeadbeef);
1839 size = MAX_PATH;
1840 ret = RegQueryValueA(NULL, "subkey", val, &size);
1841 ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 98 returns BADKEY */
1842 "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %ld\n", ret);
1843 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1844
1845 /* try a NULL value */
1846 size = MAX_PATH;
1847 ret = RegQueryValueA(hkey_main, "subkey", NULL, &size);
1848 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
1849 ok(size == 5, "Expected 5, got %ld\n", size);
1850
1851 /* try a NULL size */
1852 SetLastError(0xdeadbeef);
1853 val[0] = '\0';
1854 ret = RegQueryValueA(hkey_main, "subkey", val, NULL);
1855 ok(ret == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %ld\n", ret);
1856 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1857 ok(!val[0], "Expected val to be untouched, got %s\n", val);
1858
1859 /* try a NULL value and size */
1860 ret = RegQueryValueA(hkey_main, "subkey", NULL, NULL);
1861 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
1862
1863 /* try a size too small */
1864 SetLastError(0xdeadbeef);
1865 val[0] = '\0';
1866 size = 1;
1867 ret = RegQueryValueA(hkey_main, "subkey", val, &size);
1868 ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %ld\n", ret);
1869 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1870 ok(!val[0], "Expected val to be untouched, got %s\n", val);
1871 ok(size == 5, "Expected 5, got %ld\n", size);
1872
1873 /* successfully read the value using 'subkey' */
1874 size = MAX_PATH;
1875 ret = RegQueryValueA(hkey_main, "subkey", val, &size);
1876 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
1877 ok(!lstrcmpA(val, "data"), "Expected 'data', got '%s'\n", val);
1878 ok(size == 5, "Expected 5, got %ld\n", size);
1879
1880 /* successfully read the value using the subkey key */
1881 size = MAX_PATH;
1882 ret = RegQueryValueA(subkey, NULL, val, &size);
1883 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
1884 ok(!lstrcmpA(val, "data"), "Expected 'data', got '%s'\n", val);
1885 ok(size == 5, "Expected 5, got %ld\n", size);
1886
1887 /* unicode - try size too small */
1888 SetLastError(0xdeadbeef);
1889 valW[0] = '\0';
1890 size = 0;
1891 ret = RegQueryValueW(subkey, NULL, valW, &size);
1893 {
1894 win_skip("RegQueryValueW is not implemented\n");
1895 goto cleanup;
1896 }
1897 ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %ld\n", ret);
1898 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1899 ok(!valW[0], "Expected valW to be untouched\n");
1900 ok(size == 10, "Got wrong size: %ld\n", size);
1901
1902 /* unicode - try size in WCHARS */
1903 SetLastError(0xdeadbeef);
1904 size = ARRAY_SIZE(valW);
1905 ret = RegQueryValueW(subkey, NULL, valW, &size);
1906 ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %ld\n", ret);
1907 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", GetLastError());
1908 ok(!valW[0], "Expected valW to be untouched\n");
1909 ok(size == 10, "Got wrong size: %ld\n", size);
1910
1911 /* unicode - successfully read the value */
1912 size = sizeof(valW);
1913 ret = RegQueryValueW(subkey, NULL, valW, &size);
1914 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
1915 ok(!lstrcmpW(valW, L"data"), "Got wrong value\n");
1916 ok(size == 10, "Got wrong size: %ld\n", size);
1917
1918 /* unicode - set the value without a NULL terminator */
1919 ret = RegSetValueW(subkey, NULL, REG_SZ, L"data", 8);
1920 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
1921
1922 /* unicode - read the unterminated value, value is terminated for us */
1923 memset(valW, 'a', sizeof(valW));
1924 size = sizeof(valW);
1925 ret = RegQueryValueW(subkey, NULL, valW, &size);
1926 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
1927 ok(!lstrcmpW(valW, L"data"), "Got wrong value\n");
1928 ok(size == 10, "Got wrong size: %ld\n", size);
1929
1930cleanup:
1931 RegDeleteKeyA(subkey, "");
1932 RegCloseKey(subkey);
1933}
1934
1935static void test_reg_query_info(void)
1936{
1937 HKEY subkey;
1938 HKEY subsubkey;
1939 LONG ret;
1940 char classbuffer[32];
1941 WCHAR classbufferW[32];
1942 char expectbuffer[32];
1943 WCHAR expectbufferW[32];
1944 char subkey_class[] = "subkey class";
1945 WCHAR subkey_classW[] = L"subkey class";
1946 char subsubkey_class[] = "subsubkey class";
1947 DWORD classlen;
1948 DWORD subkeys, maxsubkeylen, maxclasslen;
1949 DWORD values, maxvaluenamelen, maxvaluelen;
1950 DWORD sdlen;
1951 FILETIME lastwrite;
1952
1953 ret = RegCreateKeyExA(hkey_main, "subkey", 0, subkey_class, 0, KEY_ALL_ACCESS, NULL, &subkey, NULL);
1954 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
1955
1956 /* all parameters NULL */
1958 ok(ret == ERROR_INVALID_HANDLE, "ret = %ld\n", ret);
1959
1961 ok(ret == ERROR_INVALID_HANDLE, "ret = %ld\n", ret);
1962
1963 /* not requesting any information */
1965 ok(ret == ERROR_SUCCESS, "ret = %ld\n", ret);
1966
1968 ok(ret == ERROR_SUCCESS, "ret = %ld\n", ret);
1969
1970 /* class without length is invalid */
1971 memset(classbuffer, 0x55, sizeof(classbuffer));
1972 ret = RegQueryInfoKeyA(subkey, classbuffer, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1973 ok(ret == ERROR_INVALID_PARAMETER, "ret = %ld\n", ret);
1974 ok(classbuffer[0] == 0x55, "classbuffer[0] = 0x%x\n", classbuffer[0]);
1975
1976 memset(classbufferW, 0x55, sizeof(classbufferW));
1977 ret = RegQueryInfoKeyW(subkey, classbufferW, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1978 ok(ret == ERROR_INVALID_PARAMETER, "ret = %ld\n", ret);
1979 ok(classbufferW[0] == 0x5555, "classbufferW[0] = 0x%x\n", classbufferW[0]);
1980
1981 /* empty key */
1982 sdlen = classlen =0;
1983 ret = RegQueryInfoKeyA(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite);
1984 ok(ret == ERROR_SUCCESS, "ret = %ld\n", ret);
1985 ok(classlen == strlen(subkey_class), "classlen = %lu\n", classlen);
1986 ok(subkeys == 0, "subkeys = %lu\n", subkeys);
1987 ok(maxsubkeylen == 0, "maxsubkeylen = %lu\n", maxsubkeylen);
1988 ok(maxclasslen == 0, "maxclasslen = %lu\n", maxclasslen);
1989 ok(values == 0, "values = %lu\n", values);
1990 ok(maxvaluenamelen == 0, "maxvaluenamelen = %lu\n", maxvaluenamelen);
1991 ok(maxvaluelen == 0, "maxvaluelen = %lu\n", maxvaluelen);
1992 todo_wine ok(sdlen != 0, "sdlen = %lu\n", sdlen);
1993 ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %lu\n", lastwrite.dwLowDateTime);
1994 ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %lu\n", lastwrite.dwHighDateTime);
1995
1996 sdlen = classlen = 0;
1997 ret = RegQueryInfoKeyW(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite);
1998 ok(ret == ERROR_SUCCESS, "ret = %ld\n", ret);
1999 ok(classlen == strlen(subkey_class), "classlen = %lu\n", classlen);
2000 ok(subkeys == 0, "subkeys = %lu\n", subkeys);
2001 ok(maxsubkeylen == 0, "maxsubkeylen = %lu\n", maxsubkeylen);
2002 ok(maxclasslen == 0, "maxclasslen = %lu\n", maxclasslen);
2003 ok(values == 0, "values = %lu\n", values);
2004 ok(maxvaluenamelen == 0, "maxvaluenamelen = %lu\n", maxvaluenamelen);
2005 ok(maxvaluelen == 0, "maxvaluelen = %lu\n", maxvaluelen);
2006 todo_wine ok(sdlen != 0, "sdlen = %lu\n", sdlen);
2007 ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %lu\n", lastwrite.dwLowDateTime);
2008 ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %lu\n", lastwrite.dwHighDateTime);
2009
2010 ret = RegCreateKeyExA(subkey, "subsubkey", 0, subsubkey_class, 0, KEY_ALL_ACCESS, NULL, &subsubkey, NULL);
2011 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2012
2013 ret = RegSetValueExA(subkey, NULL, 0, REG_SZ, (const BYTE*)"data", 5);
2014 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2015
2016 /* with subkey & default value */
2017 sdlen = classlen = 0;
2018 ret = RegQueryInfoKeyA(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite);
2019 ok(ret == ERROR_SUCCESS, "ret = %ld\n", ret);
2020 ok(classlen == strlen(subkey_class), "classlen = %lu\n", classlen);
2021 ok(subkeys == 1, "subkeys = %lu\n", subkeys);
2022 ok(maxsubkeylen == strlen("subsubkey"), "maxsubkeylen = %lu\n", maxsubkeylen);
2023 ok(maxclasslen == strlen(subsubkey_class), "maxclasslen = %lu\n", maxclasslen);
2024 ok(values == 1, "values = %lu\n", values);
2025 ok(maxvaluenamelen == 0, "maxvaluenamelen = %lu\n", maxvaluenamelen);
2026 ok(maxvaluelen == sizeof("data") * sizeof(WCHAR), "maxvaluelen = %lu\n", maxvaluelen);
2027 todo_wine ok(sdlen != 0, "sdlen = %lu\n", sdlen);
2028 ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %lu\n", lastwrite.dwLowDateTime);
2029 ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %lu\n", lastwrite.dwHighDateTime);
2030
2031 sdlen = classlen = 0;
2032 ret = RegQueryInfoKeyW(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite);
2033 ok(ret == ERROR_SUCCESS, "ret = %ld\n", ret);
2034 ok(classlen == strlen(subkey_class), "classlen = %lu\n", classlen);
2035 ok(subkeys == 1, "subkeys = %lu\n", subkeys);
2036 ok(maxsubkeylen == strlen("subsubkey"), "maxsubkeylen = %lu\n", maxsubkeylen);
2037 ok(maxclasslen == strlen(subsubkey_class), "maxclasslen = %lu\n", maxclasslen);
2038 ok(values == 1, "values = %lu\n", values);
2039 ok(maxvaluenamelen == 0, "maxvaluenamelen = %lu\n", maxvaluenamelen);
2040 ok(maxvaluelen == sizeof("data") * sizeof(WCHAR), "maxvaluelen = %lu\n", maxvaluelen);
2041 todo_wine ok(sdlen != 0, "sdlen = %lu\n", sdlen);
2042 ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %lu\n", lastwrite.dwLowDateTime);
2043 ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %lu\n", lastwrite.dwHighDateTime);
2044
2045 ret = RegSetValueExA(subkey, "value one", 0, REG_SZ, (const BYTE*)"first value data", 17);
2046 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2047
2048 ret = RegSetValueExA(subkey, "value 2", 0, REG_SZ, (const BYTE*)"second value data", 18);
2049 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2050
2051 /* with named value */
2052 classlen = 0;
2053 ret = RegQueryInfoKeyA(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite);
2054 ok(ret == ERROR_SUCCESS, "ret = %ld\n", ret);
2055 ok(values == 3, "values = %lu\n", values);
2056 ok(maxvaluenamelen == strlen("value one"), "maxvaluenamelen = %lu\n", maxvaluenamelen);
2057 ok(maxvaluelen == sizeof("second value data") * sizeof(WCHAR), "maxvaluelen = %lu\n", maxvaluelen);
2058
2059 classlen = 0;
2060 ret = RegQueryInfoKeyW(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite);
2061 ok(ret == ERROR_SUCCESS, "ret = %ld\n", ret);
2062 ok(values == 3, "values = %lu\n", values);
2063 ok(maxvaluenamelen == strlen("value one"), "maxvaluenamelen = %lu\n", maxvaluenamelen);
2064 ok(maxvaluelen == sizeof("second value data") * sizeof(WCHAR), "maxvaluelen = %lu\n", maxvaluelen);
2065
2066 /* class name with zero size buffer */
2067 memset(classbuffer, 0x55, sizeof(classbuffer));
2068 classlen = 0;
2069 ret = RegQueryInfoKeyA(subkey, classbuffer, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2070 ok(ret == ERROR_SUCCESS, "ret = %ld\n", ret);
2071 todo_wine ok(classlen == 0, "classlen = %lu\n", classlen);
2072 memset(expectbuffer, 0x55, sizeof(expectbuffer));
2073 ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)), "classbuffer was modified\n");
2074
2075 memset(classbufferW, 0x55, sizeof(classbufferW));
2076 classlen = 0;
2077 ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2078 ok(ret == ERROR_SUCCESS, "ret = %ld\n", ret);
2079 todo_wine ok(classlen == 0, "classlen = %lu\n", classlen);
2080 memset(expectbufferW, 0x55, sizeof(expectbufferW));
2081 ok(!memcmp(classbufferW, expectbufferW, sizeof(classbufferW)), "classbufferW was modified\n");
2082
2083 /* class name with one char buffer */
2084 memset(classbuffer, 0x55, sizeof(classbuffer));
2085 classlen = 1;
2086 ret = RegQueryInfoKeyA(subkey, classbuffer, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2087 ok(ret == ERROR_MORE_DATA, "ret = %ld\n", ret);
2088 ok(classlen == 0, "classlen = %lu\n", classlen);
2089 memset(expectbuffer, 0x55, sizeof(expectbuffer));
2090 expectbuffer[0] = 0;
2091 ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)), "classbuffer was modified\n");
2092
2093 memset(classbufferW, 0x55, sizeof(classbufferW));
2094 classlen = 1;
2095 ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2096 /* failure-code changed to ERROR_MORE_DATA in recent win10 */
2097 ok((ret == ERROR_INSUFFICIENT_BUFFER) || (ret == ERROR_MORE_DATA), "ret = %ld\n", ret);
2098 ok(classlen == 0 /* win8 */ ||
2099 classlen == strlen(subkey_class), "classlen = %lu\n", classlen);
2100 memset(expectbufferW, 0x55, sizeof(expectbufferW));
2101 ok(!memcmp(classbufferW, expectbufferW, sizeof(classbufferW)), "classbufferW was modified\n");
2102
2103 /* class name with buffer one char too small */
2104 memset(classbuffer, 0x55, sizeof(classbuffer));
2105 classlen = sizeof(subkey_class) - 1;
2106 ret = RegQueryInfoKeyA(subkey, classbuffer, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2107 ok(ret == ERROR_MORE_DATA, "ret = %ld\n", ret);
2108 ok(classlen == sizeof(subkey_class) - 2, "classlen = %lu\n", classlen);
2109 memset(expectbuffer, 0x55, sizeof(expectbuffer));
2110 strcpy(expectbuffer, subkey_class);
2111 expectbuffer[sizeof(subkey_class) - 2] = 0;
2112 expectbuffer[sizeof(subkey_class) - 1] = 0x55;
2113 ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)),
2114 "classbuffer = %.*s, expected %s\n",
2115 (int)sizeof(classbuffer), classbuffer, expectbuffer);
2116
2117 memset(classbufferW, 0x55, sizeof(classbufferW));
2118 classlen = sizeof(subkey_class) - 1;
2119 ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2120 ok(ret == ERROR_INSUFFICIENT_BUFFER, "ret = %ld\n", ret);
2121 ok(classlen == sizeof(subkey_class) - 2 /* win8 */ ||
2122 classlen == strlen(subkey_class), "classlen = %lu\n", classlen);
2123 memset(expectbufferW, 0x55, sizeof(expectbufferW));
2124 ok(!memcmp(classbufferW, expectbufferW, sizeof(classbufferW)), "classbufferW was modified\n");
2125
2126 /* class name with large enough buffer */
2127 memset(classbuffer, 0x55, sizeof(classbuffer));
2128 classlen = sizeof(subkey_class);
2129 ret = RegQueryInfoKeyA(subkey, classbuffer, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2130 ok(ret == ERROR_SUCCESS, "ret = %ld\n", ret);
2131 ok(classlen == sizeof(subkey_class) - 1, "classlen = %lu\n", classlen);
2132 memset(expectbuffer, 0x55, sizeof(expectbuffer));
2133 strcpy(expectbuffer, subkey_class);
2134 ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)),
2135 "classbuffer = \"%.*s\", expected %s\n",
2136 (int)sizeof(classbuffer), classbuffer, expectbuffer);
2137
2138 memset(classbuffer, 0x55, sizeof(classbuffer));
2139 classlen = 0xdeadbeef;
2140 ret = RegQueryInfoKeyA(subkey, classbuffer, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2141 ok(ret == ERROR_SUCCESS, "ret = %ld\n", ret);
2142 ok(classlen == sizeof(subkey_class) - 1, "classlen = %lu\n", classlen);
2143 memset(expectbuffer, 0x55, sizeof(expectbuffer));
2144 strcpy(expectbuffer, subkey_class);
2145 ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)),
2146 "classbuffer = \"%.*s\", expected %s\n",
2147 (int)sizeof(classbuffer), classbuffer, expectbuffer);
2148
2149 memset(classbufferW, 0x55, sizeof(classbufferW));
2150 classlen = sizeof(subkey_class);
2151 ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2152 ok(ret == ERROR_SUCCESS, "ret = %ld\n", ret);
2153 ok(classlen == sizeof(subkey_class) - 1, "classlen = %lu\n", classlen);
2154 memset(expectbufferW, 0x55, sizeof(expectbufferW));
2155 lstrcpyW(expectbufferW, subkey_classW);
2156 ok(!memcmp(classbufferW, expectbufferW, sizeof(classbufferW)),
2157 "classbufferW = %s, expected %s\n",
2158 wine_dbgstr_wn(classbufferW, ARRAY_SIZE(classbufferW)), wine_dbgstr_w(expectbufferW));
2159
2160 memset(classbufferW, 0x55, sizeof(classbufferW));
2161 classlen = 0xdeadbeef;
2162 ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2163 ok(ret == ERROR_SUCCESS, "ret = %ld\n", ret);
2164 ok(classlen == sizeof(subkey_class) - 1, "classlen = %lu\n", classlen);
2165 memset(expectbufferW, 0x55, sizeof(expectbufferW));
2166 lstrcpyW(expectbufferW, subkey_classW);
2167 ok(!memcmp(classbufferW, expectbufferW, sizeof(classbufferW)),
2168 "classbufferW = %s, expected %s\n",
2169 wine_dbgstr_wn(classbufferW, ARRAY_SIZE(classbufferW)), wine_dbgstr_w(expectbufferW));
2170
2171 RegDeleteKeyA(subsubkey, "");
2172 RegCloseKey(subsubkey);
2173 RegDeleteKeyA(subkey, "");
2174 RegCloseKey(subkey);
2175}
2176
2178{
2179 HKEY subkey;
2180 LSTATUS ret;
2181 static const char string[] = "FullString";
2182 char name[11];
2183 BYTE buffer[11];
2184 DWORD insize, outsize, nsize;
2185
2186 ret = RegCreateKeyA(hkey_main, "string_termination", &subkey);
2187 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2188
2189 /* Off-by-one RegSetValueExA -> adds a trailing '\0'! */
2190 insize=sizeof(string)-1;
2191 ret = RegSetValueExA(subkey, "stringtest", 0, REG_SZ, (BYTE*)string, insize);
2192 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %ld\n", ret);
2194 ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize);
2195 ok(ret == ERROR_MORE_DATA, "RegQueryValueExA returned: %ld\n", ret);
2196
2197 /* Off-by-two RegSetValueExA -> no trailing '\0' */
2198 insize=sizeof(string)-2;
2199 ret = RegSetValueExA(subkey, "stringtest", 0, REG_SZ, (BYTE*)string, insize);
2200 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %ld\n", ret);
2201 outsize=0;
2202 ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, NULL, &outsize);
2203 ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", ret);
2204 ok(outsize == insize, "wrong size %lu != %lu\n", outsize, insize);
2205
2206 /* RegQueryValueExA may return a string with no trailing '\0' */
2208 memset(buffer, 0xbd, sizeof(buffer));
2209 ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize);
2210 ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", ret);
2211 ok(outsize == insize, "wrong size: %lu != %lu\n", outsize, insize);
2212 ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%lu != %s\n",
2213 debugstr_an((char*)buffer, outsize), outsize, string);
2214 ok(buffer[insize] == 0xbd, "buffer overflow at %lu %02x\n", insize, buffer[insize]);
2215
2216 /* RegQueryValueExA adds a trailing '\0' if there is room */
2217 outsize=insize+1;
2218 memset(buffer, 0xbd, sizeof(buffer));
2219 ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize);
2220 ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", ret);
2221 ok(outsize == insize, "wrong size: %lu != %lu\n", outsize, insize);
2222 ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%lu != %s\n",
2223 debugstr_an((char*)buffer, outsize), outsize, string);
2224 ok(buffer[insize] == 0, "buffer overflow at %lu %02x\n", insize, buffer[insize]);
2225
2226 /* RegEnumValueA may return a string with no trailing '\0' */
2228 memset(buffer, 0xbd, sizeof(buffer));
2229 nsize=sizeof(name);
2230 ret = RegEnumValueA(subkey, 0, name, &nsize, NULL, NULL, buffer, &outsize);
2231 ok(ret == ERROR_SUCCESS, "RegEnumValueA failed: %ld\n", ret);
2232 ok(strcmp(name, "stringtest") == 0, "wrong name: %s\n", name);
2233 ok(outsize == insize, "wrong size: %lu != %lu\n", outsize, insize);
2234 ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%lu != %s\n",
2235 debugstr_an((char*)buffer, outsize), outsize, string);
2236 ok(buffer[insize] == 0xbd, "buffer overflow at %lu %02x\n", insize, buffer[insize]);
2237
2238 /* RegEnumValueA adds a trailing '\0' if there is room */
2239 outsize=insize+1;
2240 memset(buffer, 0xbd, sizeof(buffer));
2241 nsize=sizeof(name);
2242 ret = RegEnumValueA(subkey, 0, name, &nsize, NULL, NULL, buffer, &outsize);
2243 ok(ret == ERROR_SUCCESS, "RegEnumValueA failed: %ld\n", ret);
2244 ok(strcmp(name, "stringtest") == 0, "wrong name: %s\n", name);
2245 ok(outsize == insize, "wrong size: %lu != %lu\n", outsize, insize);
2246 ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%lu != %s\n",
2247 debugstr_an((char*)buffer, outsize), outsize, string);
2248 ok(buffer[insize] == 0, "buffer overflow at %lu %02x\n", insize, buffer[insize]);
2249
2250 /* RegGetValueA always adds the trailing '\0' */
2251 if (pRegGetValueA)
2252 {
2253 outsize = insize;
2254 ret = pRegGetValueA(subkey, NULL, "stringtest", RRF_RT_REG_SZ, NULL, buffer, &outsize);
2255 ok(ret == ERROR_MORE_DATA, "RegGetValueA returned: %ld\n", ret);
2256 ok(outsize == insize + 1, "wrong size: %lu != %lu\n", outsize, insize + 1);
2257 memset(buffer, 0xbd, sizeof(buffer));
2258 ret = pRegGetValueA(subkey, NULL, "stringtest", RRF_RT_REG_SZ, NULL, buffer, &outsize);
2259 ok(ret == ERROR_SUCCESS, "RegGetValueA returned: %ld\n", ret);
2260 ok(outsize == insize + 1, "wrong size: %lu != %lu\n", outsize, insize + 1);
2261 ok(memcmp(buffer, string, insize) == 0, "bad string: %s/%lu != %s\n",
2262 debugstr_an((char*)buffer, insize), insize, string);
2263 ok(buffer[insize] == 0, "buffer overflow at %lu %02x\n", insize, buffer[insize]);
2264 }
2265
2266 RegDeleteKeyA(subkey, "");
2267 RegCloseKey(subkey);
2268}
2269
2271{
2272 HKEY subkey;
2273 LSTATUS ret;
2274 static const char multistring[] = "Aa\0Bb\0Cc\0";
2275 char name[sizeof("multistringtest")];
2276 BYTE buffer[sizeof(multistring)];
2277 DWORD insize, outsize, nsize;
2278
2279 ret = RegCreateKeyA(hkey_main, "multistring_termination", &subkey);
2280 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2281
2282 /* Off-by-one RegSetValueExA -> only one trailing '\0' */
2283 insize = sizeof(multistring) - 1;
2284 ret = RegSetValueExA(subkey, "multistringtest", 0, REG_SZ, (BYTE*)multistring, insize);
2285 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %ld\n", ret);
2286 outsize = 0;
2287 ret = RegQueryValueExA(subkey, "multistringtest", NULL, NULL, NULL, &outsize);
2288 ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", ret);
2289 ok(outsize == insize, "wrong size %lu != %lu\n", outsize, insize);
2290
2291 /* Off-by-two RegSetValueExA -> adds a trailing '\0'! */
2292 insize = sizeof(multistring) - 2;
2293 ret = RegSetValueExA(subkey, "multistringtest", 0, REG_SZ, (BYTE*)multistring, insize);
2294 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %ld\n", ret);
2295 outsize = insize;
2296 ret = RegQueryValueExA(subkey, "multistringtest", NULL, NULL, buffer, &outsize);
2297 ok(ret == ERROR_MORE_DATA, "RegQueryValueExA returned: %ld\n", ret);
2298
2299 /* Off-by-three RegSetValueExA -> no trailing '\0' */
2300 insize = sizeof(multistring) - 3;
2301 ret = RegSetValueExA(subkey, "multistringtest", 0, REG_SZ, (BYTE*)multistring, insize);
2302 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %ld\n", ret);
2303 outsize = 0;
2304 ret = RegQueryValueExA(subkey, "multistringtest", NULL, NULL, NULL, &outsize);
2305 ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", ret);
2306 ok(outsize == insize, "wrong size %lu != %lu\n", outsize, insize);
2307
2308 /* RegQueryValueExA may return a multistring with no trailing '\0' */
2309 outsize = insize;
2310 memset(buffer, 0xbd, sizeof(buffer));
2311 ret = RegQueryValueExA(subkey, "multistringtest", NULL, NULL, buffer, &outsize);
2312 ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", ret);
2313 ok(outsize == insize, "wrong size: %lu != %lu\n", outsize, insize);
2314 ok(memcmp(buffer, multistring, outsize) == 0, "bad multistring: %s/%lu != %s\n",
2315 debugstr_an((char*)buffer, outsize), outsize, multistring);
2316 ok(buffer[insize] == 0xbd, "buffer overflow at %lu %02x\n", insize, buffer[insize]);
2317
2318 /* RegQueryValueExA adds one trailing '\0' if there is room */
2319 outsize = insize + 1;
2320 memset(buffer, 0xbd, sizeof(buffer));
2321 ret = RegQueryValueExA(subkey, "multistringtest", NULL, NULL, buffer, &outsize);
2322 ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", ret);
2323 ok(outsize == insize, "wrong size: %lu != %lu\n", outsize, insize);
2324 ok(memcmp(buffer, multistring, outsize) == 0, "bad multistring: %s/%lu != %s\n",
2325 debugstr_an((char*)buffer, outsize), outsize, multistring);
2326 ok(buffer[insize] == 0, "buffer overflow at %lu %02x\n", insize, buffer[insize]);
2327
2328 /* RegQueryValueExA doesn't add a second trailing '\0' even if there is room */
2329 outsize = insize + 2;
2330 memset(buffer, 0xbd, sizeof(buffer));
2331 ret = RegQueryValueExA(subkey, "multistringtest", NULL, NULL, buffer, &outsize);
2332 ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", ret);
2333 ok(outsize == insize, "wrong size: %lu != %lu\n", outsize, insize);
2334 ok(memcmp(buffer, multistring, outsize) == 0, "bad multistring: %s/%lu != %s\n",
2335 debugstr_an((char*)buffer, outsize), outsize, multistring);
2336 ok(buffer[insize + 1] == 0xbd, "buffer overflow at %lu %02x\n", insize, buffer[insize + 1]);
2337
2338 /* RegEnumValueA may return a multistring with no trailing '\0' */
2339 outsize = insize;
2340 memset(buffer, 0xbd, sizeof(buffer));
2341 nsize = sizeof(name);
2342 ret = RegEnumValueA(subkey, 0, name, &nsize, NULL, NULL, buffer, &outsize);
2343 ok(ret == ERROR_SUCCESS, "RegEnumValueA failed: %ld\n", ret);
2344 ok(strcmp(name, "multistringtest") == 0, "wrong name: %s\n", name);
2345 ok(outsize == insize, "wrong size: %lu != %lu\n", outsize, insize);
2346 ok(memcmp(buffer, multistring, outsize) == 0, "bad multistring: %s/%lu != %s\n",
2347 debugstr_an((char*)buffer, outsize), outsize, multistring);
2348 ok(buffer[insize] == 0xbd, "buffer overflow at %lu %02x\n", insize, buffer[insize]);
2349
2350 /* RegEnumValueA adds one trailing '\0' even if there's room for two */
2351 outsize = insize + 2;
2352 memset(buffer, 0xbd, sizeof(buffer));
2353 nsize = sizeof(name);
2354 ret = RegEnumValueA(subkey, 0, name, &nsize, NULL, NULL, buffer, &outsize);
2355 ok(ret == ERROR_SUCCESS, "RegEnumValueA failed: %ld\n", ret);
2356 ok(strcmp(name, "multistringtest") == 0, "wrong name: %s\n", name);
2357 ok(outsize == insize, "wrong size: %lu != %lu\n", outsize, insize);
2358 ok(memcmp(buffer, multistring, outsize) == 0, "bad multistring: %s/%lu != %s\n",
2359 debugstr_an((char*)buffer, outsize), outsize, multistring);
2360 ok(buffer[insize] == 0, "buffer overflow at %lu %02x\n", insize, buffer[insize]);
2361 ok(buffer[insize + 1] == 0xbd, "buffer overflow at %lu %02x\n", insize, buffer[insize]);
2362
2363 /* RegGetValueA always adds one trailing '\0' even if there's room for two */
2364 if (pRegGetValueA)
2365 {
2366 outsize = insize;
2367 ret = pRegGetValueA(subkey, NULL, "multistringtest", RRF_RT_REG_SZ, NULL, buffer, &outsize);
2368 ok(ret == ERROR_MORE_DATA, "RegGetValueA returned: %ld\n", ret);
2369 ok(outsize == insize + 1, "wrong size: %lu != %lu\n", outsize, insize + 1);
2370 outsize = insize + 2;
2371 memset(buffer, 0xbd, sizeof(buffer));
2372 ret = pRegGetValueA(subkey, NULL, "multistringtest", RRF_RT_REG_SZ, NULL, buffer, &outsize);
2373 ok(ret == ERROR_SUCCESS, "RegGetValueA returned: %ld\n", ret);
2374 ok(outsize == insize + 1, "wrong size: %lu != %lu\n", outsize, insize + 1);
2375 ok(buffer[insize] == 0, "buffer overflow at %lu %02x\n", insize, buffer[insize + 1]);
2376 ok(buffer[insize + 1] == 0xbd, "buffer overflow at %lu %02x\n", insize, buffer[insize + 1]);
2377 }
2378
2379 RegDeleteKeyA(subkey, "");
2380 RegCloseKey(subkey);
2381}
2382
2383static void test_reg_copy_tree(void)
2384{
2385 HKEY src, dst, subkey;
2387 DWORD dwsize, type;
2388 LONG size, ret;
2389
2390 if (!pRegCopyTreeA)
2391 {
2392 win_skip("Skipping RegCopyTreeA tests, function not present\n");
2393 return;
2394 }
2395
2396 ret = RegCreateKeyA(hkey_main, "src", &src);
2397 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2398 ret = RegCreateKeyA(hkey_main, "dst", &dst);
2399 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2400
2401 /* Copy nonexistent subkey */
2402 ret = pRegCopyTreeA(src, "nonexistent_subkey", dst);
2403 ok(ret == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %ld\n", ret);
2404
2405 /* Create test keys and values */
2406 ret = RegSetValueA(src, NULL, REG_SZ, "data", 4);
2407 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2408 ret = RegSetValueExA(src, "value", 0, REG_SZ, (const BYTE *)"data2", 5);
2409 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2410
2411 ret = RegCreateKeyA(src, "subkey2", &subkey);
2412 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2413 ret = RegSetValueA(subkey, NULL, REG_SZ, "data3", 5);
2414 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2415 ret = RegSetValueExA(subkey, "value", 0, REG_SZ, (const BYTE *)"data4", 5);
2416 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2417 ret = RegCloseKey(subkey);
2418 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2419
2420 ret = RegCreateKeyA(src, "subkey3", &subkey);
2421 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2422 ret = RegCloseKey(subkey);
2423 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2424
2425 /* Copy subkey */
2426 ret = pRegCopyTreeA(src, "subkey2", dst);
2427 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2428
2429 size = MAX_PATH;
2431 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2432 ok(!strcmp(buffer, "data3"), "Expected 'data3', got '%s'\n", buffer);
2433
2434 dwsize = MAX_PATH;
2435 ret = RegQueryValueExA(dst, "value", NULL, &type, (BYTE *)buffer, &dwsize);
2436 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2437 ok(type == REG_SZ, "Expected REG_SZ, got %lu\n", type);
2438 ok(!strcmp(buffer, "data4"), "Expected 'data4', got '%s'\n", buffer);
2439
2440 /* Copy full tree */
2441 ret = pRegCopyTreeA(src, NULL, dst);
2442 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2443
2444 size = MAX_PATH;
2446 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2447 ok(!strcmp(buffer, "data"), "Expected 'data', got '%s'\n", buffer);
2448
2449 dwsize = MAX_PATH;
2450 ret = RegQueryValueExA(dst, "value", NULL, &type, (BYTE *)buffer, &dwsize);
2451 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2452 ok(type == REG_SZ, "Expected REG_SZ, got %lu\n", type);
2453 ok(!strcmp(buffer, "data2"), "Expected 'data2', got '%s'\n", buffer);
2454
2455 ret = RegOpenKeyA(dst, "subkey2", &subkey);
2456 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2457 size = MAX_PATH;
2458 ret = RegQueryValueA(subkey, NULL, buffer, &size);
2459 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2460 ok(!strcmp(buffer, "data3"), "Expected 'data3', got '%s'\n", buffer);
2461 dwsize = MAX_PATH;
2462 ret = RegQueryValueExA(subkey, "value", NULL, &type, (BYTE *)buffer, &dwsize);
2463 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2464 ok(type == REG_SZ, "Expected REG_SZ, got %lu\n", type);
2465 ok(!strcmp(buffer, "data4"), "Expected 'data4', got '%s'\n", buffer);
2466 ret = RegCloseKey(subkey);
2467 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2468
2469 ret = RegOpenKeyA(dst, "subkey3", &subkey);
2470 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2471 ret = RegCloseKey(subkey);
2472 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2473
2474 delete_key(src);
2475 delete_key(dst);
2476}
2477
2478static void test_reg_delete_tree(void)
2479{
2481 HKEY subkey, subkey2;
2482 DWORD dwsize, type;
2483 LONG size, ret;
2484
2485 if(!pRegDeleteTreeA) {
2486 win_skip("Skipping RegDeleteTreeA tests, function not present\n");
2487 return;
2488 }
2489
2490 ret = RegCreateKeyA(hkey_main, "subkey", &subkey);
2491 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2492 ret = RegCreateKeyA(subkey, "subkey2", &subkey2);
2493 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2494 ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4);
2495 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2496 ret = RegSetValueA(subkey2, NULL, REG_SZ, "data2", 5);
2497 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2498 ret = RegCloseKey(subkey2);
2499 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2500
2501 ret = pRegDeleteTreeA(subkey, "subkey2");
2502 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2503 ok(RegOpenKeyA(subkey, "subkey2", &subkey2),
2504 "subkey2 was not deleted\n");
2505 size = MAX_PATH;
2506 ok(!RegQueryValueA(subkey, NULL, buffer, &size),
2507 "Default value of subkey no longer present\n");
2508
2509 ret = RegCreateKeyA(subkey, "subkey2", &subkey2);
2510 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2511 ret = RegCloseKey(subkey2);
2512 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2513 ret = pRegDeleteTreeA(hkey_main, "subkey\\subkey2");
2514 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2515 ok(RegOpenKeyA(subkey, "subkey2", &subkey2),
2516 "subkey2 was not deleted\n");
2517 ok(!RegQueryValueA(subkey, NULL, buffer, &size),
2518 "Default value of subkey no longer present\n");
2519
2520 ret = RegCreateKeyA(subkey, "subkey2", &subkey2);
2521 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2522 ret = RegCloseKey(subkey2);
2523 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2524 ret = RegCreateKeyA(subkey, "subkey3", &subkey2);
2525 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2526 ret = RegCloseKey(subkey2);
2527 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2528 ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4);
2529 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2530 ret = RegSetValueExA(subkey, "value", 0, REG_SZ, (const BYTE *)"data2", 5);
2531 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2532 ret = pRegDeleteTreeA(subkey, NULL);
2533 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2534 ok(!RegOpenKeyA(hkey_main, "subkey", &subkey),
2535 "subkey was deleted\n");
2536 ok(RegOpenKeyA(subkey, "subkey2", &subkey2),
2537 "subkey2 was not deleted\n");
2538 ok(RegOpenKeyA(subkey, "subkey3", &subkey2),
2539 "subkey3 was not deleted\n");
2540 size = MAX_PATH;
2541 ret = RegQueryValueA(subkey, NULL, buffer, &size);
2542 ok(ret == ERROR_SUCCESS,
2543 "Default value of subkey is not present\n");
2544 ok(!buffer[0], "Expected length 0 got length %u(%s)\n", lstrlenA(buffer), buffer);
2545 dwsize = MAX_PATH;
2546 ok(RegQueryValueExA(subkey, "value", NULL, &type, (BYTE *)buffer, &dwsize),
2547 "Value is still present\n");
2548 ret = RegCloseKey(subkey);
2549 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2550
2551 ret = RegOpenKeyA(hkey_main, "subkey", &subkey);
2552 ok(ret == ERROR_SUCCESS, "subkey was deleted\n");
2553 ret = pRegDeleteTreeA(subkey, "");
2554 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2555 ret = RegCloseKey(subkey);
2556 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2557
2558 ret = RegOpenKeyA(hkey_main, "subkey", &subkey);
2559 ok(ret == ERROR_SUCCESS, "subkey was deleted\n");
2560 ret = RegCloseKey(subkey);
2561 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", ret);
2562
2563 ret = pRegDeleteTreeA(hkey_main, "not-here");
2565 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", ret);
2566}
2567
2568static void test_rw_order(void)
2569{
2570 HKEY hKey;
2571 DWORD dw = 0;
2572 static const char keyname[] = "test_rw_order";
2573 char value_buf[2];
2574 DWORD values, value_len, value_name_max_len;
2575 LSTATUS ret;
2576
2579 if(ret != ERROR_SUCCESS) {
2580 skip("Couldn't create key. Skipping.\n");
2581 return;
2582 }
2583
2584 ok(!RegSetValueExA(hKey, "A", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)),
2585 "RegSetValueExA for value \"A\" failed\n");
2586 ok(!RegSetValueExA(hKey, "C", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)),
2587 "RegSetValueExA for value \"C\" failed\n");
2588 ok(!RegSetValueExA(hKey, "D", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)),
2589 "RegSetValueExA for value \"D\" failed\n");
2590 ok(!RegSetValueExA(hKey, "B", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)),
2591 "RegSetValueExA for value \"B\" failed\n");
2592
2594 &value_name_max_len, NULL, NULL, NULL), "RegQueryInfoKeyA failed\n");
2595 ok(values == 4, "Expected 4 values, got %lu\n", values);
2596
2597 /* Value enumeration preserves RegSetValueEx call order */
2598 value_len = 2;
2599 ok(!RegEnumValueA(hKey, 0, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n");
2600 ok(strcmp(value_buf, "A") == 0, "Expected name \"A\", got %s\n", value_buf);
2601 value_len = 2;
2602 ok(!RegEnumValueA(hKey, 1, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n");
2603 todo_wine ok(strcmp(value_buf, "C") == 0, "Expected name \"C\", got %s\n", value_buf);
2604 value_len = 2;
2605 ok(!RegEnumValueA(hKey, 2, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n");
2606 todo_wine ok(strcmp(value_buf, "D") == 0, "Expected name \"D\", got %s\n", value_buf);
2607 value_len = 2;
2608 ok(!RegEnumValueA(hKey, 3, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n");
2609 todo_wine ok(strcmp(value_buf, "B") == 0, "Expected name \"B\", got %s\n", value_buf);
2610
2611 ok(!RegDeleteKeyA(HKEY_CURRENT_USER, keyname), "Failed to delete key\n");
2612}
2613
2614static void test_symlinks(void)
2615{
2616 static const WCHAR targetW[] = L"\\Software\\Wine\\Test\\target";
2617 BYTE buffer[1024];
2618 UNICODE_STRING target_str;
2619 WCHAR *target;
2620 HKEY key, link;
2622 DWORD target_len, type, len, dw, err;
2623
2624 if (!pRtlFormatCurrentUserKeyPath || !pNtDeleteKey)
2625 {
2626 win_skip( "Can't perform symlink tests\n" );
2627 return;
2628 }
2629
2630 pRtlFormatCurrentUserKeyPath( &target_str );
2631
2632 target_len = target_str.Length + sizeof(targetW);
2633 target = malloc( target_len );
2634 memcpy( target, target_str.Buffer, target_str.Length );
2635 memcpy( target + target_str.Length/sizeof(WCHAR), targetW, sizeof(targetW) );
2636
2639 ok( err == ERROR_SUCCESS, "RegCreateKeyEx failed: %lu\n", err );
2640
2641 /* REG_SZ is not allowed */
2642 err = RegSetValueExA( link, "SymbolicLinkValue", 0, REG_SZ, (BYTE *)"foobar", sizeof("foobar") );
2643 ok( err == ERROR_ACCESS_DENIED, "RegSetValueEx wrong error %lu\n", err );
2644 err = RegSetValueExA( link, "SymbolicLinkValue", 0, REG_LINK,
2645 (BYTE *)target, target_len - sizeof(WCHAR) );
2646 ok( err == ERROR_SUCCESS, "RegSetValueEx failed error %lu\n", err );
2647 /* other values are not allowed */
2648 err = RegSetValueExA( link, "link", 0, REG_LINK, (BYTE *)target, target_len - sizeof(WCHAR) );
2649 ok( err == ERROR_ACCESS_DENIED, "RegSetValueEx wrong error %lu\n", err );
2650
2651 /* try opening the target through the link */
2652
2653 err = RegOpenKeyA( hkey_main, "link", &key );
2654 ok( err == ERROR_FILE_NOT_FOUND, "RegOpenKey wrong error %lu\n", err );
2655
2656 err = RegCreateKeyExA( hkey_main, "target", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL );
2657 ok( err == ERROR_SUCCESS, "RegCreateKeyEx failed error %lu\n", err );
2658
2659 dw = 0xbeef;
2660 err = RegSetValueExA( key, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) );
2661 ok( err == ERROR_SUCCESS, "RegSetValueEx failed error %lu\n", err );
2662 RegCloseKey( key );
2663
2664 err = RegOpenKeyA( hkey_main, "link", &key );
2665 ok( err == ERROR_SUCCESS, "RegOpenKey failed error %lu\n", err );
2666
2667 len = sizeof(buffer);
2668 err = RegQueryValueExA( key, "value", NULL, &type, buffer, &len );
2669 ok( err == ERROR_SUCCESS, "RegOpenKey failed error %lu\n", err );
2670 ok( len == sizeof(DWORD), "wrong len %lu\n", len );
2671
2672 len = sizeof(buffer);
2673 err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len );
2674 ok( err == ERROR_FILE_NOT_FOUND, "RegQueryValueEx wrong error %lu\n", err );
2675
2676 /* REG_LINK can be created in non-link keys */
2677 err = RegSetValueExA( key, "SymbolicLinkValue", 0, REG_LINK,
2678 (BYTE *)target, target_len - sizeof(WCHAR) );
2679 ok( err == ERROR_SUCCESS, "RegSetValueEx failed error %lu\n", err );
2680 len = sizeof(buffer);
2681 err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len );
2682 ok( err == ERROR_SUCCESS, "RegQueryValueEx failed error %lu\n", err );
2683 ok( len == target_len - sizeof(WCHAR), "wrong len %lu\n", len );
2684 err = RegDeleteValueA( key, "SymbolicLinkValue" );
2685 ok( err == ERROR_SUCCESS, "RegDeleteValue failed error %lu\n", err );
2686
2687 RegCloseKey( key );
2688
2689 err = RegCreateKeyExA( hkey_main, "link", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL );
2690 ok( err == ERROR_SUCCESS, "RegCreateKeyEx failed error %lu\n", err );
2691
2692 len = sizeof(buffer);
2693 err = RegQueryValueExA( key, "value", NULL, &type, buffer, &len );
2694 ok( err == ERROR_SUCCESS, "RegQueryValueEx failed error %lu\n", err );
2695 ok( len == sizeof(DWORD), "wrong len %lu\n", len );
2696
2697 err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len );
2698 ok( err == ERROR_FILE_NOT_FOUND, "RegQueryValueEx wrong error %lu\n", err );
2699 RegCloseKey( key );
2700
2701 /* now open the symlink itself */
2702
2704 ok( err == ERROR_SUCCESS, "RegOpenKeyEx failed error %lu\n", err );
2705 len = sizeof(buffer);
2706 err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len );
2707 ok( err == ERROR_SUCCESS, "RegQueryValueEx failed error %lu\n", err );
2708 ok( len == target_len - sizeof(WCHAR), "wrong len %lu\n", len );
2709 RegCloseKey( key );
2710
2713 ok( err == ERROR_SUCCESS, "RegCreateKeyEx failed error %lu\n", err );
2714 len = sizeof(buffer);
2715 err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len );
2716 ok( err == ERROR_SUCCESS, "RegQueryValueEx failed error %lu\n", err );
2717 ok( len == target_len - sizeof(WCHAR), "wrong len %lu\n", len );
2718 RegCloseKey( key );
2719
2722 ok( err == ERROR_ALREADY_EXISTS, "RegCreateKeyEx wrong error %lu\n", err );
2723
2726 ok( err == ERROR_ALREADY_EXISTS, "RegCreateKeyEx wrong error %lu\n", err );
2727
2728 err = RegDeleteKeyA( hkey_main, "target" );
2729 ok( err == ERROR_SUCCESS, "RegDeleteKey failed error %lu\n", err );
2730
2731 err = RegDeleteKeyA( hkey_main, "link" );
2732 ok( err == ERROR_FILE_NOT_FOUND, "RegDeleteKey wrong error %lu\n", err );
2733
2734 status = pNtDeleteKey( link );
2735 ok( !status, "NtDeleteKey failed: 0x%08lx\n", status );
2736 RegCloseKey( link );
2737
2738 free( target );
2739 pRtlFreeUnicodeString( &target_str );
2740}
2741
2742static DWORD get_key_value( HKEY root, const char *name, DWORD flags )
2743{
2744 HKEY key;
2745 DWORD err, type, dw = 1, len = sizeof(dw);
2746
2748 if (err == ERROR_FILE_NOT_FOUND) return 0;
2749 ok( err == ERROR_SUCCESS, "%08lx: RegOpenKeyEx failed: %lu\n", flags, err );
2750
2751 err = RegQueryValueExA( key, "value", NULL, &type, (BYTE *)&dw, &len );
2753 dw = 0;
2754 else
2755 ok( err == ERROR_SUCCESS, "%08lx: RegQueryValueEx failed: %lu\n", flags, err );
2756 RegCloseKey( key );
2757 return dw;
2758}
2759
2760static void _check_key_value( int line, HANDLE root, const char *name, DWORD flags, DWORD expect )
2761{
2763 ok_(__FILE__,line)( dw == expect, "%08lx: wrong value %lu/%lu\n", flags, dw, expect );
2764}
2765#define check_key_value(root,name,flags,expect) _check_key_value( __LINE__, root, name, flags, expect )
2766
2767static void _check_enum_value( int line, const char *name, DWORD flags, DWORD subkeys_in, BOOL found_in)
2768{
2769 char buffer[1024];
2770 DWORD err, i, subkeys;
2771 BOOL found;
2772 HKEY key;
2773
2775 ok_( __FILE__, line )( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
2776
2777 err = RegQueryInfoKeyA( key, NULL, NULL, NULL, &subkeys,
2778 NULL, NULL, NULL, NULL, NULL, NULL, NULL );
2779 ok_( __FILE__, line )( err == ERROR_SUCCESS, "RegQueryInfoKeyA failed: %lu\n", err );
2780 ok_( __FILE__, line )( subkeys == subkeys_in, "wrong number of subkeys: %lu\n", subkeys );
2781
2782 found = FALSE;
2783 for (i = 0; i < subkeys; i++)
2784 {
2785 err = RegEnumKeyA( key, i, buffer, sizeof(buffer) );
2786 ok_( __FILE__, line )( err == ERROR_SUCCESS, "RegEnumKeyA failed: %lu\n", err );
2787
2788 if (!strcmp(buffer, "Wine"))
2789 found = TRUE;
2790 }
2791 ok_( __FILE__, line )( found == found_in, "found equals %d\n", found );
2792 RegCloseKey( key );
2793}
2794#define check_enum_value(name, flags, subkeys, found) _check_enum_value( __LINE__, name, flags, subkeys, found )
2795
2796static void test_redirection(void)
2797{
2798 DWORD err, type, dw, len;
2799 HKEY key, key32, key64, root, root32, root64;
2800 DWORD subkeys, subkeys32, subkeys64;
2801
2802 if (!has_wow64())
2803 {
2804 skip( "Not on Wow64, no redirection\n" );
2805 return;
2806 }
2807
2808 if (limited_user)
2809 {
2810 skip("not enough privileges to modify HKLM\n");
2811 return;
2812 }
2813#if defined(__REACTOS__) && defined(_WIN64)
2815 skip("test_redirection() invalid for Vista x64 and hangs.\n");
2816 return;
2817 }
2818#endif
2819
2820 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
2821 KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &root64, NULL );
2822 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err );
2823
2824 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
2825 KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &root32, NULL );
2826 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err );
2827
2828 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", 0, NULL, 0,
2830 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err );
2831
2832 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", 0, NULL, 0,
2834 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err );
2835
2836 dw = 64;
2837 err = RegSetValueExA( key64, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) );
2838 ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %lu\n", err );
2839
2840 dw = 32;
2841 err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) );
2842 ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %lu\n", err );
2843
2844 dw = 0;
2845 len = sizeof(dw);
2846 err = RegQueryValueExA( key32, "value", NULL, &type, (BYTE *)&dw, &len );
2847 ok( err == ERROR_SUCCESS, "RegQueryValueExA failed: %lu\n", err );
2848 ok( dw == 32, "wrong value %lu\n", dw );
2849
2850 dw = 0;
2851 len = sizeof(dw);
2852 err = RegQueryValueExA( key64, "value", NULL, &type, (BYTE *)&dw, &len );
2853 ok( err == ERROR_SUCCESS, "RegQueryValueExA failed: %lu\n", err );
2854 ok( dw == 64, "wrong value %lu\n", dw );
2855
2856 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0,
2858 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err );
2859 check_key_value( key, "Wine\\Winetest", 0, ptr_size );
2860 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, ptr_size );
2861 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2862 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, ptr_size == 32 ? 0 : 32 );
2863 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, ptr_size == 32 ? 0 : 32 );
2864 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, ptr_size == 32 ? 0 : 32 );
2865 RegCloseKey( key );
2866
2867 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0,
2869 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err );
2870 dw = get_key_value( key, "Wine\\Winetest", 0 );
2871 ok( dw == 64 || broken(dw == 32) /* win7 */, "wrong value %lu\n", dw );
2872 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, 64 );
2873 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2874 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, 32 );
2875 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, 32 );
2876 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2877 RegCloseKey( key );
2878
2879 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0,
2881 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err );
2882 check_key_value( key, "Wine\\Winetest", 0, 32 );
2883 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, 32 );
2884 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2885 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, 0 );
2886 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, 0 );
2887 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 0 );
2888 RegCloseKey( key );
2889
2890 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", 0, ptr_size );
2891 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine\\Winetest", 0, 32 );
2892 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", KEY_WOW64_64KEY, 64 );
2893 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2894 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, 32 );
2895 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2896
2897 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node", 0, NULL, 0,
2899 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err );
2900 check_key_value( key, "Wine\\Winetest", 0, 32 );
2901 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, 32 );
2902 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2903 RegCloseKey( key );
2904
2905 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node", 0, NULL, 0,
2907 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err );
2908 check_key_value( key, "Wine\\Winetest", 0, 32 );
2909 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, 32 );
2910 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2911 RegCloseKey( key );
2912
2913 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node", 0, NULL, 0,
2915 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err );
2916 check_key_value( key, "Wine\\Winetest", 0, 32 );
2917 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, 32 );
2918 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
2919 RegCloseKey( key );
2920
2921 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine", 0, NULL, 0,
2923 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err );
2924 check_key_value( key, "Winetest", 0, 32 );
2925 check_key_value( key, "Winetest", KEY_WOW64_64KEY, 32 );
2926 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
2927 RegCloseKey( key );
2928
2929 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine", 0, NULL, 0,
2931 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err );
2932 check_key_value( key, "Winetest", 0, 32 );
2933 check_key_value( key, "Winetest", KEY_WOW64_64KEY, 32 );
2934 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
2935 RegCloseKey( key );
2936
2937 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine", 0, NULL, 0,
2939 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err );
2940 check_key_value( key, "Winetest", 0, 32 );
2941 check_key_value( key, "Winetest", KEY_WOW64_64KEY, 32 );
2942 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
2943 RegCloseKey( key );
2944
2945 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
2947 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err );
2948 check_key_value( key, "Winetest", 0, ptr_size );
2950 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
2951 RegCloseKey( key );
2952
2953 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
2955 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err );
2956 check_key_value( key, "Winetest", 0, 64 );
2957 check_key_value( key, "Winetest", KEY_WOW64_64KEY, 64 );
2958 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
2959 RegCloseKey( key );
2960
2961 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0,
2963 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %lu\n", err );
2964 check_key_value( key, "Winetest", 0, 32 );
2965 check_key_value( key, "Winetest", KEY_WOW64_64KEY, 32 );
2966 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
2967 RegCloseKey( key );
2968
2969 if (pRegDeleteKeyExA)
2970 {
2971 err = pRegDeleteKeyExA( key32, "", KEY_WOW64_32KEY, 0 );
2972 ok( err == ERROR_SUCCESS, "RegDeleteKey failed: %lu\n", err );
2973 err = pRegDeleteKeyExA( key64, "", KEY_WOW64_64KEY, 0 );
2974 ok( err == ERROR_SUCCESS, "RegDeleteKey failed: %lu\n", err );
2975 pRegDeleteKeyExA( key64, "", KEY_WOW64_64KEY, 0 );
2976 pRegDeleteKeyExA( root64, "", KEY_WOW64_64KEY, 0 );
2977 }
2978 else
2979 {
2980 err = RegDeleteKeyA( key32, "" );
2981 ok( err == ERROR_SUCCESS, "RegDeleteKey failed: %lu\n", err );
2982 err = RegDeleteKeyA( key64, "" );
2983 ok( err == ERROR_SUCCESS, "RegDeleteKey failed: %lu\n", err );
2984 RegDeleteKeyA( key64, "" );
2985 RegDeleteKeyA( root64, "" );
2986 }
2987 RegCloseKey( key32 );
2988 RegCloseKey( key64 );
2989 RegCloseKey( root32 );
2990 RegCloseKey( root64 );
2991
2992 err = RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"Software\\WOW6432Node\\test1\\test2", 0, NULL, 0,
2994 ok(!err, "got %#lx.\n", err);
2996
2997 err = RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"Software\\test1\\test2", 0, NULL, 0, KEY_WRITE | KEY_WOW64_32KEY,
2998 NULL, &key, NULL );
2999 ok(!err, "got %#lx.\n", err);
3001
3002 err = RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"Software\\test1\\test2", 0, KEY_WRITE | KEY_WOW64_32KEY, &key );
3003 ok(!err, "got %#lx.\n", err);
3005
3006 if (pRegDeleteTreeA)
3007 {
3008 err = pRegDeleteTreeA(HKEY_LOCAL_MACHINE, "Software\\WOW6432Node\\test1");
3009 ok(!err, "got %#lx.\n", err);
3010 err = pRegDeleteTreeA(HKEY_LOCAL_MACHINE, "Software\\test1");
3011 ok(err == ERROR_FILE_NOT_FOUND, "got %#lx.\n", err);
3012 }
3013
3014 /* Software\Classes is shared/reflected so behavior is different */
3015
3016 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wine",
3017 0, NULL, 0, KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &key64, NULL);
3018 if (err == ERROR_ACCESS_DENIED)
3019 {
3020 skip("Not authorized to modify the Classes key\n");
3021 return;
3022 }
3023 ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err );
3024
3025 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node\\Wine",
3027 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3028 RegCloseKey( key );
3029
3030 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node\\Wine",
3031 0, KEY_ALL_ACCESS, &key );
3033 "RegOpenKeyExA failed: %lu\n", err );
3034 if (!err) RegCloseKey( key );
3035
3036 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node\\Wine",
3037 0, NULL, 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key32, NULL);
3038 ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err );
3039
3040 dw = 32;
3041 err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) );
3042 ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %lu\n", err );
3043
3044 dw = 64;
3045 err = RegSetValueExA( key64, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) );
3046 ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %lu\n", err );
3047
3048 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wine", 0, 64 );
3049 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wine", KEY_WOW64_64KEY, 64 );
3050 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wine", KEY_WOW64_32KEY, 64 );
3051 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node\\Wine", 0, ptr_size == 64 ? 0 : 64 );
3052 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node\\Wine", KEY_WOW64_64KEY, 0 );
3053 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node\\Wine", KEY_WOW64_32KEY, 64 );
3054
3055 RegDeleteKeyA( key32, "" );
3056 RegCloseKey( key32 );
3057
3058 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wine", 0, 0 );
3059 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wine", KEY_WOW64_64KEY, 0 );
3060 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wine", KEY_WOW64_32KEY, 0 );
3061 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node\\Wine", 0, 0 );
3062 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node\\Wine", KEY_WOW64_64KEY, 0 );
3063 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node\\Wine", KEY_WOW64_32KEY, 0 );
3064
3065 RegDeleteKeyA( key64, "" );
3066 RegCloseKey( key64 );
3067
3068 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes", 0, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &root64 );
3069 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3070
3071 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes", 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &root32 );
3072 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3073
3074 err = RegCreateKeyExA( root64, "Wine", 0, NULL, 0,
3075 KEY_ALL_ACCESS, NULL, &key64, NULL);
3076 ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err );
3077
3078 err = RegCreateKeyExA( key64, "Wine", 0, NULL, 0,
3080 ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err );
3081 RegDeleteKeyA( key, "" );
3082 RegCloseKey( key );
3083
3084 err = RegOpenKeyExA( root32, "Wine", 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &key );
3085 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3086 RegCloseKey( key );
3087
3088 err = RegOpenKeyExA( root32, "Wine", 0, KEY_ALL_ACCESS, &key );
3089 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3090 RegCloseKey( key );
3091
3092 err = RegCreateKeyExA( root32, "Wine", 0, NULL, 0,
3093 KEY_ALL_ACCESS, NULL, &key32, NULL);
3094 ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err );
3095
3096 dw = 32;
3097 err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) );
3098 ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %lu\n", err );
3099
3100 dw = 64;
3101 err = RegSetValueExA( key64, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) );
3102 ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %lu\n", err );
3103
3104 check_key_value( root64, "Wine", 0, 64 );
3105 check_key_value( root64, "Wine", KEY_WOW64_64KEY, 64 );
3106 check_key_value( root64, "Wine", KEY_WOW64_32KEY, 64 );
3107 check_key_value( root32, "Wine", 0, 64 );
3108 check_key_value( root32, "Wine", KEY_WOW64_64KEY, 64 );
3109 check_key_value( root32, "Wine", KEY_WOW64_32KEY, 64 );
3110
3111 RegDeleteKeyA( key32, "" );
3112 RegCloseKey( key32 );
3113
3114 check_key_value( root64, "Wine", 0, 0 );
3115 check_key_value( root64, "Wine", KEY_WOW64_64KEY, 0 );
3116 check_key_value( root64, "Wine", KEY_WOW64_32KEY, 0 );
3117 check_key_value( root32, "Wine", 0, 0 );
3118 check_key_value( root32, "Wine", KEY_WOW64_64KEY, 0 );
3119 check_key_value( root32, "Wine", KEY_WOW64_32KEY, 0 );
3120
3121 RegDeleteKeyA( key64, "" );
3122 RegCloseKey( key64 );
3123
3124 err = RegCreateKeyExA( root32, "Wine", 0, NULL, 0,
3125 KEY_ALL_ACCESS, NULL, &key32, NULL);
3126 ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err );
3127
3128 dw = 32;
3129 err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) );
3130 ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %lu\n", err );
3131
3132 check_key_value( root64, "Wine", 0, 32 );
3133 check_key_value( root64, "Wine", KEY_WOW64_64KEY, 32 );
3134 check_key_value( root64, "Wine", KEY_WOW64_32KEY, 32 );
3135 check_key_value( root32, "Wine", 0, 32 );
3136 check_key_value( root32, "Wine", KEY_WOW64_64KEY, 32 );
3137 check_key_value( root32, "Wine", KEY_WOW64_32KEY, 32 );
3138
3139 RegDeleteKeyA( key32, "" );
3140 RegCloseKey( key32 );
3141
3142 RegCloseKey( root64 );
3143 RegCloseKey( root32 );
3144
3145 err = RegOpenKeyExA( HKEY_CLASSES_ROOT, "Interface",
3146 0, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &root64 );
3147 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3148
3149 err = RegOpenKeyExA( HKEY_CLASSES_ROOT, "Interface",
3150 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &root32 );
3151 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3152
3153 err = RegOpenKeyExA( HKEY_CLASSES_ROOT, "Interface",
3154 0, KEY_ALL_ACCESS, &root );
3155 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3156
3157 err = RegCreateKeyExA( root32, "Wine", 0, NULL, 0,
3159 ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err );
3160
3161 err = RegOpenKeyExA( root, "Wine", 0, KEY_ALL_ACCESS, &key );
3163 "RegOpenKeyExA failed: %lu\n", err );
3164 if (!err) RegCloseKey( key );
3165
3166 RegDeleteKeyA( key32, "" );
3167 RegCloseKey( key32 );
3168
3169 err = RegCreateKeyExA( root64, "Wine", 0, NULL, 0,
3171 ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err );
3172
3173 err = RegOpenKeyExA( root, "Wine", 0, KEY_ALL_ACCESS, &key );
3175 "RegOpenKeyExA failed: %lu\n", err );
3176 if (!err) RegCloseKey( key );
3177
3178 RegDeleteKeyA( key64, "" );
3179 RegCloseKey( key64 );
3180
3181 RegDeleteKeyA( root64, "" );
3182 RegDeleteKeyA( root32, "" );
3183 RegDeleteKeyA( root, "" );
3184
3185 RegCloseKey( root64 );
3186 RegCloseKey( root32 );
3187 RegCloseKey( root );
3188
3189 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes",
3190 0, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &root64 );
3191 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3192
3193 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes",
3194 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &root32 );
3195 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3196
3197 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes",
3198 0, KEY_ALL_ACCESS, &root );
3199 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3200
3201 err = RegOpenKeyExA( root64, "Interface",
3202 0, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &key64 );
3203 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3204
3205 err = RegOpenKeyExA( root32, "Interface",
3206 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &key32 );
3207 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3208
3209 err = RegOpenKeyExA( root, "Interface",
3210 0, KEY_ALL_ACCESS, &key );
3211 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3212
3213 RegCloseKey( root64 );
3214 RegCloseKey( root32 );
3215 RegCloseKey( root );
3216
3217 root64 = key64;
3218 root32 = key32;
3219 root = key;
3220
3221 err = RegCreateKeyExA( root32, "Wine", 0, NULL, 0,
3223 ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err );
3224
3225 err = RegOpenKeyExA( root, "Wine", 0, KEY_ALL_ACCESS, &key );
3227 "RegOpenKeyExA failed: %lu\n", err );
3228 if (!err) RegCloseKey( key );
3229
3230 RegDeleteKeyA( key32, "" );
3231 RegCloseKey( key32 );
3232
3233 err = RegCreateKeyExA( root64, "Wine", 0, NULL, 0,
3235 ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err );
3236
3237 err = RegOpenKeyExA( root, "Wine", 0, KEY_ALL_ACCESS, &key );
3239 "RegOpenKeyExA failed: %lu\n", err );
3240 if (!err) RegCloseKey( key );
3241
3242 RegDeleteKeyA( key64, "" );
3243 RegCloseKey( key64 );
3244
3245 RegDeleteKeyA( root, "" );
3246 RegCloseKey( root );
3247
3248 err = RegCreateKeyExA( root64, "Wine", 0, NULL, 0,
3249 KEY_ALL_ACCESS, NULL, &key64, NULL);
3250 ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err );
3251
3252 err = RegOpenKeyExA( root32, "Wine", 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &key );
3253 ok( err == ERROR_FILE_NOT_FOUND, "RegOpenKeyExA failed: %lu\n", err );
3254
3255 err = RegOpenKeyExA( root32, "Wine", 0, KEY_ALL_ACCESS, &key );
3256 ok( err == ERROR_FILE_NOT_FOUND, "RegOpenKeyExA failed: %lu\n", err );
3257
3258 err = RegCreateKeyExA( root32, "Wine", 0, NULL, 0,
3259 KEY_ALL_ACCESS, NULL, &key32, NULL);
3260 ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err );
3261
3262 dw = 32;
3263 err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) );
3264 ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %lu\n", err );
3265
3266 dw = 64;
3267 err = RegSetValueExA( key64, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) );
3268 ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %lu\n", err );
3269
3270 check_key_value( root64, "Wine", 0, 64 );
3271 check_key_value( root64, "Wine", KEY_WOW64_64KEY, 64 );
3272 check_key_value( root64, "Wine", KEY_WOW64_32KEY, 32 );
3273 check_key_value( root32, "Wine", 0, 32 );
3274 check_key_value( root32, "Wine", KEY_WOW64_64KEY, 32 );
3275 check_key_value( root32, "Wine", KEY_WOW64_32KEY, 32 );
3276
3277 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Interface",
3279 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3280 check_key_value( key, "Wine", 0, 64 );
3281 check_key_value( key, "Wine", KEY_WOW64_64KEY, 64 );
3282 check_key_value( key, "Wine", KEY_WOW64_32KEY, 32 );
3283 RegCloseKey( key );
3284
3285 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Interface",
3287 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3288 check_key_value( key, "Wine", 0, 32 );
3289 check_key_value( key, "Wine", KEY_WOW64_64KEY, 32 );
3290 check_key_value( key, "Wine", KEY_WOW64_32KEY, 32 );
3291 RegCloseKey( key );
3292
3293 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Interface\\Wine", 0, ptr_size );
3294 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Interface\\Wine", KEY_WOW64_64KEY, 64 );
3295 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Interface\\Wine", KEY_WOW64_32KEY, 32 );
3296
3297 RegDeleteKeyA( key32, "" );
3298 RegCloseKey( key32 );
3299
3300 check_key_value( root64, "Wine", 0, 64 );
3301 check_key_value( root64, "Wine", KEY_WOW64_64KEY, 64 );
3302 check_key_value( root64, "Wine", KEY_WOW64_32KEY, 0 );
3303 check_key_value( root32, "Wine", 0, 0 );
3304 check_key_value( root32, "Wine", KEY_WOW64_64KEY, 0 );
3305 check_key_value( root32, "Wine", KEY_WOW64_32KEY, 0 );
3306
3307 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Interface\\Wine", 0, ptr_size == 64 ? 64 : 0 );
3308 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Interface\\Wine", KEY_WOW64_64KEY, 64 );
3309 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Classes\\Interface\\Wine", KEY_WOW64_32KEY, 0 );
3310
3311 RegDeleteKeyA( key64, "" );
3312 RegCloseKey( key64 );
3313
3314 err = RegCreateKeyExA( root32, "Wine", 0, NULL, 0,
3315 KEY_ALL_ACCESS, NULL, &key32, NULL);
3316 ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err );
3317
3318 dw = 32;
3319 err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) );
3320 ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %lu\n", err );
3321
3322 check_key_value( root64, "Wine", 0, 0 );
3323 check_key_value( root64, "Wine", KEY_WOW64_64KEY, 0 );
3324 check_key_value( root64, "Wine", KEY_WOW64_32KEY, 32 );
3325 check_key_value( root32, "Wine", 0, 32 );
3326 check_key_value( root32, "Wine", KEY_WOW64_64KEY, 32 );
3327 check_key_value( root32, "Wine", KEY_WOW64_32KEY, 32 );
3328
3329 RegDeleteKeyA( key32, "" );
3330 RegCloseKey( key32 );
3331
3332 RegCloseKey( root64 );
3333 RegCloseKey( root32 );
3334
3335 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node\\Wine",
3336 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key32, NULL);
3337 ok( err == ERROR_SUCCESS, "RegCreateKeyA failed: %lu\n", err );
3338
3339 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node\\Wine",
3340 0, KEY_ALL_ACCESS, &key );
3341 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3342 RegCloseKey( key );
3343
3344 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node\\Wine",
3347 "RegOpenKeyExA failed: %lu\n", err );
3348 if (!err) RegCloseKey( key );
3349
3350 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node\\Wine",
3353 "RegOpenKeyExA failed: %lu\n", err );
3354 if (!err) RegCloseKey( key );
3355
3356 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wine",
3357 0, KEY_ALL_ACCESS, &key );
3359 "RegOpenKeyExA failed: %lu\n", err );
3360 if (!err) RegCloseKey( key );
3361
3362 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wine",
3365 "RegOpenKeyExA failed: %lu\n", err );
3366 if (!err) RegCloseKey( key );
3367
3368 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wine",
3371 "RegOpenKeyExA failed: %lu\n", err );
3372 if (!err) RegCloseKey( key );
3373
3374 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\Wow6432Node",
3375 0, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &root32 );
3376 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3377
3378 err = RegQueryInfoKeyA(root32, NULL, NULL, NULL, &subkeys,
3379 NULL, NULL, NULL, NULL, NULL, NULL, NULL );
3380 ok( err == ERROR_SUCCESS, "RegQueryInfoKeyA failed: %lu\n", err );
3381 ok( subkeys > 0, "wrong number of subkeys: %lu\n", subkeys );
3382 subkeys32 = subkeys;
3383 RegCloseKey( root32 );
3384
3385 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes",
3386 0, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &root64 );
3387 ok( err == ERROR_SUCCESS, "RegOpenKeyExA failed: %lu\n", err );
3388
3389 err = RegQueryInfoKeyA(root64, NULL, NULL, NULL, &subkeys,
3390 NULL, NULL, NULL, NULL, NULL, NULL, NULL );
3391 ok( err == ERROR_SUCCESS, "RegQueryInfoKeyA failed: %lu\n", err );
3392 ok( subkeys > subkeys32, "wrong number of subkeys: %lu\n", subkeys );
3393 subkeys64 = subkeys;
3394 RegCloseKey( root64 );
3395
3396 check_enum_value( "Software\\Classes",
3397 KEY_WOW64_32KEY | KEY_ALL_ACCESS, subkeys64, ptr_size == 32 );
3398 check_enum_value( "Software\\Classes",
3399 KEY_WOW64_64KEY | KEY_ALL_ACCESS, subkeys64, ptr_size == 32 );
3400 check_enum_value( "Software\\Classes",
3401 KEY_ALL_ACCESS, subkeys64, ptr_size == 32 );
3402 check_enum_value( "Software\\Classes\\Wow6432Node",
3403 KEY_WOW64_32KEY | KEY_ALL_ACCESS, subkeys32, ptr_size == 64 );
3404 check_enum_value( "Software\\Classes\\Wow6432Node",
3405 KEY_WOW64_64KEY | KEY_ALL_ACCESS, subkeys32, ptr_size == 64 );
3406 check_enum_value( "Software\\Classes\\Wow6432Node",
3407 KEY_ALL_ACCESS, subkeys32, ptr_size == 64 );
3408 check_enum_value( "Software\\Wow6432Node\\Classes",
3409 KEY_WOW64_32KEY | KEY_ALL_ACCESS, subkeys64, ptr_size == 32 );
3410 check_enum_value( "Software\\Wow6432Node\\Classes",
3411 KEY_WOW64_64KEY | KEY_ALL_ACCESS, subkeys32, ptr_size == 64 );
3412 check_enum_value( "Software\\Wow6432Node\\Classes",
3413 KEY_ALL_ACCESS, ptr_size == 32 ? subkeys64 : subkeys32, TRUE );
3414
3415 RegDeleteKeyA( key32, "" );
3416 RegCloseKey( key32 );
3417}
3418
3419static void test_classesroot(void)
3420{
3421 HKEY hkey, hklm, hkcr, hkeysub1, hklmsub1, hkcrsub1, hklmsub2, hkcrsub2;
3422 DWORD size = 8;
3423 DWORD type = REG_SZ;
3424 static CHAR buffer[8];
3425 LONG res;
3426
3427 /* create a key in the user's classes */
3428 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", &hkey ))
3429 {
3430 delete_key( hkey );
3431 RegCloseKey( hkey );
3432 }
3433 res = RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", 0, NULL, 0,
3435 if (res == ERROR_ACCESS_DENIED)
3436 {
3437 skip("not enough privileges to add a user class\n");
3438 return;
3439 }
3440 ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey);
3441
3442 /* try to open that key in hkcr */
3443 res = RegOpenKeyExA( HKEY_CLASSES_ROOT, "WineTestCls", 0,
3446 broken(res == ERROR_FILE_NOT_FOUND /* WinNT */),
3447 "test key not found in hkcr: %ld\n", res);
3448 if (res)
3449 {
3450 skip("HKCR key merging not supported\n");
3451 delete_key( hkey );
3452 RegCloseKey( hkey );
3453 return;
3454 }
3455
3456 todo_wine ok(IS_HKCR(hkcr), "hkcr mask not set in %p\n", hkcr);
3457
3458 /* set a value in user's classes */
3459 res = RegSetValueExA(hkey, "val1", 0, REG_SZ, (const BYTE *)"user", sizeof("user"));
3460 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3461
3462 /* try to find the value in hkcr */
3463 res = RegQueryValueExA(hkcr, "val1", NULL, &type, (LPBYTE)buffer, &size);
3464 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", res);
3465 ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer );
3466
3467 /* modify the value in hkcr */
3468 res = RegSetValueExA(hkcr, "val1", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr"));
3469 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3470
3471 /* check if the value is also modified in user's classes */
3472 res = RegQueryValueExA(hkey, "val1", NULL, &type, (LPBYTE)buffer, &size);
3473 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3474 ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer );
3475
3476 /* set a value in hkcr */
3477 res = RegSetValueExA(hkcr, "val0", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr"));
3478 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3479
3480 /* try to find the value in user's classes */
3481 res = RegQueryValueExA(hkey, "val0", NULL, &type, (LPBYTE)buffer, &size);
3482 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", res);
3483 ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer );
3484
3485 /* modify the value in user's classes */
3486 res = RegSetValueExA(hkey, "val0", 0, REG_SZ, (const BYTE *)"user", sizeof("user"));
3487 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3488
3489 /* check if the value is also modified in hkcr */
3490 res = RegQueryValueExA(hkcr, "val0", NULL, &type, (LPBYTE)buffer, &size);
3491 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3492 ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer );
3493
3494 /* cleanup */
3495 delete_key( hkey );
3496 delete_key( hkcr );
3497 RegCloseKey( hkey );
3498 RegCloseKey( hkcr );
3499
3500 /* create a key in the hklm classes */
3501 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Classes\\WineTestCls", &hklm ))
3502 {
3503 delete_key( hklm );
3504 RegCloseKey( hklm );
3505 }
3506 res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\WineTestCls", 0, NULL, REG_OPTION_NON_VOLATILE,
3507 KEY_ALL_ACCESS, NULL, &hklm, NULL );
3508 if (res == ERROR_ACCESS_DENIED)
3509 {
3510 skip("not enough privileges to add a system class\n");
3511 return;
3512 }
3513 ok(!IS_HKCR(hklm), "hkcr mask set in %p\n", hklm);
3514
3515 /* try to open that key in hkcr */
3516 res = RegOpenKeyExA( HKEY_CLASSES_ROOT, "WineTestCls", 0,
3518 ok(res == ERROR_SUCCESS,
3519 "test key not found in hkcr: %ld\n", res);
3520 ok(IS_HKCR(hkcr), "hkcr mask not set in %p\n", hkcr);
3521 if (res)
3522 {
3523 delete_key( hklm );
3524 RegCloseKey( hklm );
3525 return;
3526 }
3527
3528 /* set a value in hklm classes */
3529 res = RegSetValueExA(hklm, "val2", 0, REG_SZ, (const BYTE *)"hklm", sizeof("hklm"));
3530 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3531
3532 /* try to find the value in hkcr */
3533 res = RegQueryValueExA(hkcr, "val2", NULL, &type, (LPBYTE)buffer, &size);
3534 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", res);
3535 ok(!strcmp( buffer, "hklm" ), "value set to '%s'\n", buffer );
3536
3537 /* modify the value in hkcr */
3538 res = RegSetValueExA(hkcr, "val2", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr"));
3539 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3540
3541 /* check that the value is modified in hklm classes */
3542 res = RegQueryValueExA(hklm, "val2", NULL, &type, (LPBYTE)buffer, &size);
3543 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3544 ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer );
3545
3546 if (RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", 0, NULL, 0,
3547 KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hkey, NULL )) return;
3548 ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey);
3549
3550 /* try to open that key in hkcr */
3551 res = RegOpenKeyExA( HKEY_CLASSES_ROOT, "WineTestCls", 0,
3553 ok(res == ERROR_SUCCESS,
3554 "test key not found in hkcr: %ld\n", res);
3555 ok(IS_HKCR(hkcr), "hkcr mask not set in %p\n", hkcr);
3556
3557 /* set a value in user's classes */
3558 res = RegSetValueExA(hkey, "val2", 0, REG_SZ, (const BYTE *)"user", sizeof("user"));
3559 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3560
3561 /* try to find the value in hkcr */
3562 res = RegQueryValueExA(hkcr, "val2", NULL, &type, (LPBYTE)buffer, &size);
3563 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", res);
3564 ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer );
3565
3566 /* modify the value in hklm */
3567 res = RegSetValueExA(hklm, "val2", 0, REG_SZ, (const BYTE *)"hklm", sizeof("hklm"));
3568 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3569
3570 /* check that the value is not overwritten in hkcr or user's classes */
3571 res = RegQueryValueExA(hkcr, "val2", NULL, &type, (LPBYTE)buffer, &size);
3572 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", res);
3573 ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer );
3574 res = RegQueryValueExA(hkey, "val2", NULL, &type, (LPBYTE)buffer, &size);
3575 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3576 ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer );
3577
3578 /* modify the value in hkcr */
3579 res = RegSetValueExA(hkcr, "val2", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr"));
3580 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3581
3582 /* check that the value is overwritten in hklm and user's classes */
3583 res = RegQueryValueExA(hkcr, "val2", NULL, &type, (LPBYTE)buffer, &size);
3584 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", res);
3585 ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer );
3586 res = RegQueryValueExA(hkey, "val2", NULL, &type, (LPBYTE)buffer, &size);
3587 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3588 ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer );
3589
3590 /* create a subkey in hklm */
3591 if (RegCreateKeyExA( hklm, "subkey1", 0, NULL, 0,
3592 KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hklmsub1, NULL )) return;
3593 ok(!IS_HKCR(hklmsub1), "hkcr mask set in %p\n", hklmsub1);
3594 /* try to open that subkey in hkcr */
3595 res = RegOpenKeyExA( hkcr, "subkey1", 0, KEY_QUERY_VALUE|KEY_SET_VALUE, &hkcrsub1 );
3596 ok(res == ERROR_SUCCESS, "test key not found in hkcr: %ld\n", res);
3597 ok(IS_HKCR(hkcrsub1), "hkcr mask not set in %p\n", hkcrsub1);
3598
3599 /* set a value in hklm classes */
3600 res = RegSetValueExA(hklmsub1, "subval1", 0, REG_SZ, (const BYTE *)"hklm", sizeof("hklm"));
3601 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3602
3603 /* try to find the value in hkcr */
3604 res = RegQueryValueExA(hkcrsub1, "subval1", NULL, &type, (LPBYTE)buffer, &size);
3605 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", res);
3606 ok(!strcmp( buffer, "hklm" ), "value set to '%s'\n", buffer );
3607
3608 /* modify the value in hkcr */
3609 res = RegSetValueExA(hkcrsub1, "subval1", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr"));
3610 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3611
3612 /* check that the value is modified in hklm classes */
3613 res = RegQueryValueExA(hklmsub1, "subval1", NULL, &type, (LPBYTE)buffer, &size);
3614 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3615 ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer );
3616
3617 /* create a subkey in user's classes */
3618 if (RegCreateKeyExA( hkey, "subkey1", 0, NULL, 0,
3619 KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hkeysub1, NULL )) return;
3620 ok(!IS_HKCR(hkeysub1), "hkcr mask set in %p\n", hkeysub1);
3621
3622 /* set a value in user's classes */
3623 res = RegSetValueExA(hkeysub1, "subval1", 0, REG_SZ, (const BYTE *)"user", sizeof("user"));
3624 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3625
3626 /* try to find the value in hkcr */
3627 res = RegQueryValueExA(hkcrsub1, "subval1", NULL, &type, (LPBYTE)buffer, &size);
3628 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", res);
3629 ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer );
3630
3631 /* modify the value in hklm */
3632 res = RegSetValueExA(hklmsub1, "subval1", 0, REG_SZ, (const BYTE *)"hklm", sizeof("hklm"));
3633 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3634
3635 /* check that the value is not overwritten in hkcr or user's classes */
3636 res = RegQueryValueExA(hkcrsub1, "subval1", NULL, &type, (LPBYTE)buffer, &size);
3637 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", res);
3638 ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer );
3639 res = RegQueryValueExA(hkeysub1, "subval1", NULL, &type, (LPBYTE)buffer, &size);
3640 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3641 ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer );
3642
3643 /* modify the value in hkcr */
3644 res = RegSetValueExA(hkcrsub1, "subval1", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr"));
3645 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3646
3647 /* check that the value is not overwritten in hklm, but in user's classes */
3648 res = RegQueryValueExA(hklmsub1, "subval1", NULL, &type, (LPBYTE)buffer, &size);
3649 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", res);
3650 ok(!strcmp( buffer, "hklm" ), "value set to '%s'\n", buffer );
3651 res = RegQueryValueExA(hkeysub1, "subval1", NULL, &type, (LPBYTE)buffer, &size);
3652 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3653 ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer );
3654
3655 /* new subkey in hkcr */
3656 if (RegCreateKeyExA( hkcr, "subkey2", 0, NULL, 0,
3657 KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hkcrsub2, NULL )) return;
3658 ok(IS_HKCR(hkcrsub2), "hkcr mask not set in %p\n", hkcrsub2);
3659 res = RegSetValueExA(hkcrsub2, "subval1", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr"));
3660 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld, GLE=%lx\n", res, GetLastError());
3661
3662 /* try to open that new subkey in user's classes and hklm */
3663 res = RegOpenKeyExA( hkey, "subkey2", 0, KEY_QUERY_VALUE|KEY_SET_VALUE, &hklmsub2 );
3664 ok(res != ERROR_SUCCESS, "test key found in user's classes: %ld\n", res);
3665 hklmsub2 = 0;
3666 res = RegOpenKeyExA( hklm, "subkey2", 0, KEY_QUERY_VALUE|KEY_SET_VALUE, &hklmsub2 );
3667 ok(res == ERROR_SUCCESS, "test key not found in hklm: %ld\n", res);
3668 ok(!IS_HKCR(hklmsub2), "hkcr mask set in %p\n", hklmsub2);
3669
3670 /* check that the value is present in hklm */
3671 res = RegQueryValueExA(hklmsub2, "subval1", NULL, &type, (LPBYTE)buffer, &size);
3672 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %ld\n", res);
3673 ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer );
3674
3675 /* cleanup */
3676 RegCloseKey( hkeysub1 );
3677 RegCloseKey( hklmsub1 );
3678
3679 /* delete subkey1 from hkcr (should point at user's classes) */
3680 res = RegDeleteKeyA(hkcr, "subkey1");
3681 ok(res == ERROR_SUCCESS, "RegDeleteKey failed: %ld\n", res);
3682
3683 /* confirm key was removed in hkey but not hklm */
3684 res = RegOpenKeyExA(hkey, "subkey1", 0, KEY_READ, &hkeysub1);
3685 ok(res == ERROR_FILE_NOT_FOUND, "test key found in user's classes: %ld\n", res);
3686 res = RegOpenKeyExA(hklm, "subkey1", 0, KEY_READ, &hklmsub1);
3687 ok(res == ERROR_SUCCESS, "test key not found in hklm: %ld\n", res);
3688 ok(!IS_HKCR(hklmsub1), "hkcr mask set in %p\n", hklmsub1);
3689
3690 /* delete subkey1 from hkcr again (which should now point at hklm) */
3691 res = RegDeleteKeyA(hkcr, "subkey1");
3692 ok(res == ERROR_SUCCESS, "RegDeleteKey failed: %ld\n", res);
3693
3694 /* confirm hkey was removed in hklm */
3695 RegCloseKey( hklmsub1 );
3696 res = RegOpenKeyExA(hklm, "subkey1", 0, KEY_READ, &hklmsub1);
3697 ok(res == ERROR_FILE_NOT_FOUND, "test key found in hklm: %ld\n", res);
3698
3699 /* final cleanup */
3700 delete_key( hkey );
3701 delete_key( hklm );
3702 delete_key( hkcr );
3703 delete_key( hkeysub1 );
3704 delete_key( hklmsub1 );
3705 delete_key( hkcrsub1 );
3706 delete_key( hklmsub2 );
3707 delete_key( hkcrsub2 );
3708 RegCloseKey( hkey );
3709 RegCloseKey( hklm );
3710 RegCloseKey( hkcr );
3711 RegCloseKey( hkeysub1 );
3712 RegCloseKey( hklmsub1 );
3713 RegCloseKey( hkcrsub1 );
3714 RegCloseKey( hklmsub2 );
3715 RegCloseKey( hkcrsub2 );
3716}
3717
3718static void test_classesroot_enum(void)
3719{
3720 HKEY hkcu=0, hklm=0, hkcr=0, hkcusub[2]={0}, hklmsub[2]={0};
3721 DWORD size;
3722 static CHAR buffer[2];
3723 LONG res;
3724
3725 /* prepare initial testing env in HKCU */
3726 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", &hkcu ))
3727 {
3728 delete_key( hkcu );
3729 RegCloseKey( hkcu );
3730 }
3731 res = RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", 0, NULL, 0,
3733
3734 if (res != ERROR_SUCCESS)
3735 {
3736 skip("failed to add a user class\n");
3737 return;
3738 }
3739
3740 res = RegOpenKeyA( HKEY_CLASSES_ROOT, "WineTestCls", &hkcr );
3742 broken(res == ERROR_FILE_NOT_FOUND /* WinNT */),
3743 "test key not found in hkcr: %ld\n", res);
3744 if (res)
3745 {
3746 skip("HKCR key merging not supported\n");
3747 delete_key( hkcu );
3748 RegCloseKey( hkcu );
3749 return;
3750 }
3751
3752 res = RegSetValueExA( hkcu, "X", 0, REG_SZ, (const BYTE *) "AA", 3 );
3753 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld\n", res);
3754 res = RegSetValueExA( hkcu, "Y", 0, REG_SZ, (const BYTE *) "B", 2 );
3755 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld\n", res);
3756 res = RegCreateKeyA( hkcu, "A", &hkcusub[0] );
3757 ok(res == ERROR_SUCCESS, "RegCreateKeyA failed: %ld\n", res);
3758 res = RegCreateKeyA( hkcu, "B", &hkcusub[1] );
3759 ok(res == ERROR_SUCCESS, "RegCreateKeyA failed: %ld\n", res);
3760
3761 /* test on values in HKCU */
3762 size = sizeof(buffer);
3763 res = RegEnumValueA( hkcr, 0, buffer, &size, NULL, NULL, NULL, NULL );
3764 ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %ld\n", res );
3765 ok(!strcmp( buffer, "X" ), "expected 'X', got '%s'\n", buffer);
3766 size = sizeof(buffer);
3767 res = RegEnumValueA( hkcr, 1, buffer, &size, NULL, NULL, NULL, NULL );
3768 ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %ld\n", res );
3769 ok(!strcmp( buffer, "Y" ), "expected 'Y', got '%s'\n", buffer);
3770 size = sizeof(buffer);
3771 res = RegEnumValueA( hkcr, 2, buffer, &size, NULL, NULL, NULL, NULL );
3772 ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %ld\n", res );
3773
3774 res = RegEnumKeyA( hkcr, 0, buffer, size );
3775 ok(res == ERROR_SUCCESS, "RegEnumKey failed: %ld\n", res );
3776 ok(!strcmp( buffer, "A" ), "expected 'A', got '%s'\n", buffer);
3777 res = RegEnumKeyA( hkcr, 1, buffer, size );
3778 ok(res == ERROR_SUCCESS, "RegEnumKey failed: %ld\n", res );
3779 ok(!strcmp( buffer, "B" ), "expected 'B', got '%s'\n", buffer);
3780 res = RegEnumKeyA( hkcr, 2, buffer, size );
3781 ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %ld\n", res );
3782
3783 /* prepare test env in HKLM */
3784 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Classes\\WineTestCls", &hklm ))
3785 {
3786 delete_key( hklm );
3787 RegCloseKey( hklm );
3788 }
3789
3790 res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\WineTestCls", 0, NULL, 0,
3792
3793 if (res == ERROR_ACCESS_DENIED)
3794 {
3795 RegCloseKey( hkcusub[0] );
3796 RegCloseKey( hkcusub[1] );
3797 delete_key( hkcu );
3798 RegCloseKey( hkcu );
3799 RegCloseKey( hkcr );
3800 skip("not enough privileges to add a system class\n");
3801 return;
3802 }
3803
3804 res = RegSetValueExA( hklm, "X", 0, REG_SZ, (const BYTE *) "AB", 3 );
3805 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld\n", res);
3806 res = RegSetValueExA( hklm, "Z", 0, REG_SZ, (const BYTE *) "C", 2 );
3807 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %ld\n", res);
3808 res = RegCreateKeyA( hklm, "A", &hklmsub[0] );
3809 ok(res == ERROR_SUCCESS, "RegCreateKeyA failed: %ld\n", res);
3810 res = RegCreateKeyA( hklm, "C", &hklmsub[1] );
3811 ok(res == ERROR_SUCCESS, "RegCreateKeyA failed: %ld\n", res);
3812
3813 /* test on values/keys in both HKCU and HKLM */
3814 size = sizeof(buffer);
3815 res = RegEnumValueA( hkcr, 0, buffer, &size, NULL, NULL, NULL, NULL );
3816 ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %ld\n", res );
3817 ok(!strcmp( buffer, "X" ), "expected 'X', got '%s'\n", buffer);
3818 size = sizeof(buffer);
3819 res = RegEnumValueA( hkcr, 1, buffer, &size, NULL, NULL, NULL, NULL );
3820 ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %ld\n", res );
3821 ok(!strcmp( buffer, "Y" ), "expected 'Y', got '%s'\n", buffer);
3822 size = sizeof(buffer);
3823 res = RegEnumValueA( hkcr, 2, buffer, &size, NULL, NULL, NULL, NULL );
3824 ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %ld\n", res );
3825 ok(!strcmp( buffer, "Z" ), "expected 'Z', got '%s'\n", buffer);
3826 size = sizeof(buffer);
3827 res = RegEnumValueA( hkcr, 3, buffer, &size, NULL, NULL, NULL, NULL );
3828 ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %ld\n", res );
3829
3830 res = RegEnumKeyA( hkcr, 0, buffer, size );
3831 ok(res == ERROR_SUCCESS, "RegEnumKey failed: %ld\n", res );
3832 ok(!strcmp( buffer, "A" ), "expected 'A', got '%s'\n", buffer);
3833 res = RegEnumKeyA( hkcr, 1, buffer, size );
3834 ok(res == ERROR_SUCCESS, "RegEnumKey failed: %ld\n", res );
3835 ok(!strcmp( buffer, "B" ), "expected 'B', got '%s'\n", buffer);
3836 res = RegEnumKeyA( hkcr, 2, buffer, size );
3837 ok(res == ERROR_SUCCESS, "RegEnumKey failed: %ld\n", res );
3838 ok(!strcmp( buffer, "C" ), "expected 'C', got '%s'\n", buffer);
3839 res = RegEnumKeyA( hkcr, 3, buffer, size );
3840 ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %ld\n", res );
3841
3842 /* delete values/keys from HKCU to test only on HKLM */
3843 RegCloseKey( hkcusub[0] );
3844 RegCloseKey( hkcusub[1] );
3845 delete_key( hkcu );
3846 RegCloseKey( hkcu );
3847
3848 size = sizeof(buffer);
3849 res = RegEnumValueA( hkcr, 0, buffer, &size, NULL, NULL, NULL, NULL );
3851 res == ERROR_NO_SYSTEM_RESOURCES, /* Windows XP */
3852 "expected ERROR_KEY_DELETED, got %ld\n", res);
3853 size = sizeof(buffer);
3854 res = RegEnumKeyA( hkcr, 0, buffer, size );
3856 res == ERROR_NO_SYSTEM_RESOURCES, /* Windows XP */
3857 "expected ERROR_KEY_DELETED, got %ld\n", res);
3858
3859 /* reopen HKCR handle */
3860 RegCloseKey( hkcr );
3861 res = RegOpenKeyA( HKEY_CLASSES_ROOT, "WineTestCls", &hkcr );
3862 ok(res == ERROR_SUCCESS, "test key not found in hkcr: %ld\n", res);
3863 if (res) goto cleanup;
3864
3865 /* test on values/keys in HKLM */
3866 size = sizeof(buffer);
3867 res = RegEnumValueA( hkcr, 0, buffer, &size, NULL, NULL, NULL, NULL );
3868 ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %ld\n", res );
3869 ok(!strcmp( buffer, "X" ), "expected 'X', got '%s'\n", buffer);
3870 size = sizeof(buffer);
3871 res = RegEnumValueA( hkcr, 1, buffer, &size, NULL, NULL, NULL, NULL );
3872 ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %ld\n", res );
3873 ok(!strcmp( buffer, "Z" ), "expected 'Z', got '%s'\n", buffer);
3874 size = sizeof(buffer);
3875 res = RegEnumValueA( hkcr, 2, buffer, &size, NULL, NULL, NULL, NULL );
3876 ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %ld\n", res );
3877
3878 res = RegEnumKeyA( hkcr, 0, buffer, size );
3879 ok(res == ERROR_SUCCESS, "RegEnumKey failed: %ld\n", res );
3880 ok(!strcmp( buffer, "A" ), "expected 'A', got '%s'\n", buffer);
3881 res = RegEnumKeyA( hkcr, 1, buffer, size );
3882 ok(res == ERROR_SUCCESS, "RegEnumKey failed: %ld\n", res );
3883 ok(!strcmp( buffer, "C" ), "expected 'C', got '%s'\n", buffer);
3884 res = RegEnumKeyA( hkcr, 2, buffer, size );
3885 ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %ld\n", res );
3886
3887cleanup:
3888 RegCloseKey( hklmsub[0] );
3889 RegCloseKey( hklmsub[1] );
3890 delete_key( hklm );
3891 RegCloseKey( hklm );
3892 RegCloseKey( hkcr );
3893}
3894
3895static void test_classesroot_mask(void)
3896{
3897 HKEY hkey;
3898 LSTATUS res;
3899
3900 res = RegOpenKeyA( HKEY_CLASSES_ROOT, "CLSID", &hkey );
3901 ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %ld\n", res);
3902 todo_wine ok(IS_HKCR(hkey) || broken(!IS_HKCR(hkey)) /* WinNT */,
3903 "hkcr mask not set in %p\n", hkey);
3904 RegCloseKey( hkey );
3905
3906 res = RegOpenKeyA( HKEY_CURRENT_USER, "Software", &hkey );
3907 ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %ld\n", res);
3908 ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey);
3909 RegCloseKey( hkey );
3910
3911 res = RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software", &hkey );
3912 ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %ld\n", res);
3913 ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey);
3914 RegCloseKey( hkey );
3915
3916 res = RegOpenKeyA( HKEY_USERS, ".Default", &hkey );
3917 ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %ld\n", res);
3918 ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey);
3919 RegCloseKey( hkey );
3920
3921 res = RegOpenKeyA( HKEY_CURRENT_CONFIG, "Software", &hkey );
3922 ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %ld\n", res);
3923 ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey);
3924 RegCloseKey( hkey );
3925}
3926
3927static void test_deleted_key(void)
3928{
3929 HKEY hkey, hkey2;
3930 char value[20];
3931 DWORD val_count, type;
3932 LONG res;
3933
3934 /* Open the test key, then delete it while it's open */
3935 RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey );
3936
3938
3939 val_count = sizeof(value);
3940 type = 0;
3941 res = RegEnumValueA( hkey, 0, value, &val_count, NULL, &type, 0, 0 );
3942 ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %li\n", res);
3943
3944 res = RegEnumKeyA( hkey, 0, value, sizeof(value) );
3945 ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %li\n", res);
3946
3947 val_count = sizeof(value);
3948 type = 0;
3949 res = RegQueryValueExA( hkey, "test", NULL, &type, (BYTE *)value, &val_count );
3950 ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %li\n", res);
3951
3952 res = RegSetValueExA( hkey, "test", 0, REG_SZ, (const BYTE*)"value", 6);
3953 ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %li\n", res);
3954
3955 res = RegOpenKeyA( hkey, "test", &hkey2 );
3956 ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %li\n", res);
3957 if (res == 0)
3958 RegCloseKey( hkey2 );
3959
3960 res = RegCreateKeyA( hkey, "test", &hkey2 );
3961 ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %li\n", res);
3962 if (res == 0)
3963 RegCloseKey( hkey2 );
3964
3965 res = RegFlushKey( hkey );
3966 ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %li\n", res);
3967
3968 RegCloseKey( hkey );
3969
3971}
3972
3973static void test_delete_value(void)
3974{
3975 LONG res;
3976 char longname[401];
3977
3978 res = RegSetValueExA( hkey_main, "test", 0, REG_SZ, (const BYTE*)"value", 6 );
3979 ok(res == ERROR_SUCCESS, "expect ERROR_SUCCESS, got %li\n", res);
3980
3982 ok(res == ERROR_SUCCESS, "expect ERROR_SUCCESS, got %li\n", res);
3983
3984 res = RegDeleteValueA( hkey_main, "test" );
3985 ok(res == ERROR_SUCCESS, "expect ERROR_SUCCESS, got %li\n", res);
3986
3988 ok(res == ERROR_FILE_NOT_FOUND, "expect ERROR_FILE_NOT_FOUND, got %li\n", res);
3989
3990 res = RegDeleteValueA( hkey_main, "test" );
3991 ok(res == ERROR_FILE_NOT_FOUND, "expect ERROR_FILE_NOT_FOUND, got %li\n", res);
3992
3993 memset(longname, 'a', 400);
3994 longname[400] = 0;
3995 res = RegDeleteValueA( hkey_main, longname );
3996 ok(res == ERROR_FILE_NOT_FOUND, "expect ERROR_FILE_NOT_FOUND, got %li\n", res);
3997
3998 /* Default registry value */
3999 res = RegSetValueExA(hkey_main, "", 0, REG_SZ, (const BYTE *)"value", 6);
4000 ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res);
4001
4003 ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res);
4004
4006 ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res);
4007
4009 ok(res == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %ld\n", res);
4010}
4011
4012static void test_delete_key_value(void)
4013{
4014 HKEY subkey;
4015 LONG ret;
4016
4017 if (!pRegDeleteKeyValueA)
4018 {
4019 win_skip("RegDeleteKeyValue is not available.\n");
4020 return;
4021 }
4022
4023 ret = pRegDeleteKeyValueA(NULL, NULL, NULL);
4024 ok(ret == ERROR_INVALID_HANDLE, "got %ld\n", ret);
4025
4026 ret = pRegDeleteKeyValueA(hkey_main, NULL, NULL);
4027 ok(ret == ERROR_FILE_NOT_FOUND, "got %ld\n", ret);
4028
4029 ret = RegSetValueExA(hkey_main, "test", 0, REG_SZ, (const BYTE*)"value", 6);
4030 ok(ret == ERROR_SUCCESS, "got %ld\n", ret);
4031
4033 ok(ret == ERROR_SUCCESS, "got %ld\n", ret);
4034
4035 /* NULL subkey name means delete from open key */
4036 ret = pRegDeleteKeyValueA(hkey_main, NULL, "test");
4037 ok(ret == ERROR_SUCCESS, "got %ld\n", ret);
4038
4040 ok(ret == ERROR_FILE_NOT_FOUND, "got %ld\n", ret);
4041
4042 /* now with real subkey */
4043 ret = RegCreateKeyExA(hkey_main, "Subkey1", 0, NULL, 0, KEY_WRITE|KEY_READ, NULL, &subkey, NULL);
4044 ok(!ret, "failed with error %ld\n", ret);
4045
4046 ret = RegSetValueExA(subkey, "test", 0, REG_SZ, (const BYTE*)"value", 6);
4047 ok(ret == ERROR_SUCCESS, "got %ld\n", ret);
4048
4049 ret = RegQueryValueExA(subkey, "test", NULL, NULL, NULL, NULL);
4050 ok(ret == ERROR_SUCCESS, "got %ld\n", ret);
4051
4052 ret = pRegDeleteKeyValueA(hkey_main, "Subkey1", "test");
4053 ok(ret == ERROR_SUCCESS, "got %ld\n", ret);
4054
4055 ret = RegQueryValueExA(subkey, "test", NULL, NULL, NULL, NULL);
4056 ok(ret == ERROR_FILE_NOT_FOUND, "got %ld\n", ret);
4057
4058 /* Default registry value */
4059 ret = RegSetValueExA(subkey, "", 0, REG_SZ, (const BYTE *)"value", 6);
4060 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4061
4062 ret = RegQueryValueExA(subkey, "", NULL, NULL, NULL, NULL);
4063 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4064
4065 ret = pRegDeleteKeyValueA(hkey_main, "Subkey1", "" );
4066 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4067
4068 ret = RegQueryValueExA(subkey, "", NULL, NULL, NULL, NULL);
4069 ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %ld\n", ret);
4070
4071 RegDeleteKeyA(subkey, "");
4072 RegCloseKey(subkey);
4073}
4074
4076{
4077 HKEY key;
4078 LONG ret;
4079
4082 ok(!ret, "got %ld, error %ld\n", ret, GetLastError());
4083 ok(key != HKEY_CURRENT_USER, "got %p\n", key);
4085}
4086
4087struct notify_data {
4091};
4092
4094{
4095 struct notify_data *data = arg;
4096 LONG ret;
4097
4099 REG_NOTIFY_CHANGE_NAME|data->flags, data->event, TRUE);
4100 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4101 return 0;
4102}
4103
4105{
4106 struct notify_data data;
4107 HKEY key, subkey, subsubkey;
4108 HANDLE thread;
4109 HANDLE event;
4110 DWORD dwret;
4111 LONG ret;
4112
4113 event = CreateEventW(NULL, FALSE, TRUE, NULL);
4114 ok(event != NULL, "CreateEvent failed, error %lu\n", GetLastError());
4115 ret = RegCreateKeyA(hkey_main, "TestKey", &key);
4116 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4117
4119 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4120 dwret = WaitForSingleObject(event, 0);
4121 ok(dwret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %lu\n", dwret);
4122
4123 ret = RegCreateKeyA(key, "SubKey", &subkey);
4124 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4125 dwret = WaitForSingleObject(event, 0);
4126 ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", dwret);
4127
4128 /* watching deeper keys */
4130 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4131 dwret = WaitForSingleObject(event, 0);
4132 ok(dwret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %lu\n", dwret);
4133
4134 ret = RegCreateKeyA(subkey, "SubKey", &subsubkey);
4135 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4136 dwret = WaitForSingleObject(event, 0);
4137 ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", dwret);
4138
4139 /* watching deeper values */
4141 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4142 dwret = WaitForSingleObject(event, 0);
4143 ok(dwret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %lu\n", dwret);
4144
4145 ret = RegSetValueA(subsubkey, NULL, REG_SZ, "SubSubKeyValue", 0);
4146 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4147 dwret = WaitForSingleObject(event, 0);
4148 ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", dwret);
4149
4150 /* don't watch deeper values */
4152 ret = RegOpenKeyA(hkey_main, "TestKey", &key);
4153 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4154
4156 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4157 dwret = WaitForSingleObject(event, 0);
4158 ok(dwret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %lu\n", dwret);
4159
4160 ret = RegSetValueA(subsubkey, NULL, REG_SZ, "SubSubKeyValueNEW", 0);
4161 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4162 dwret = WaitForSingleObject(event, 0);
4163 ok(dwret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %lu\n", dwret);
4164
4165 RegDeleteKeyA(subkey, "SubKey");
4166 RegDeleteKeyA(key, "SubKey");
4167 RegCloseKey(subsubkey);
4168 RegCloseKey(subkey);
4170
4171 /* test same thread with REG_NOTIFY_THREAD_AGNOSTIC */
4172 ret = RegOpenKeyA(hkey_main, "TestKey", &key);
4173 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4175 event, TRUE);
4177 {
4178 win_skip("REG_NOTIFY_THREAD_AGNOSTIC is not supported\n");
4181 return;
4182 }
4183
4184 ret = RegCreateKeyA(key, "SubKey", &subkey);
4185 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4186 dwret = WaitForSingleObject(event, 0);
4187 ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", dwret);
4188
4189 RegDeleteKeyA(key, "SubKey");
4190 RegCloseKey(subkey);
4192
4193 /* test different thread without REG_NOTIFY_THREAD_AGNOSTIC */
4194 ret = RegOpenKeyA(hkey_main, "TestKey", &key);
4195 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4196
4197 data.key = key;
4198 data.flags = 0;
4199 data.event = event;
4203
4204 /* the thread exiting causes event to signal on Windows
4205 this is worked around on Windows using REG_NOTIFY_THREAD_AGNOSTIC
4206 Wine already behaves as if the flag is set */
4207 dwret = WaitForSingleObject(event, 0);
4208 todo_wine
4209 ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", dwret);
4211
4212 /* test different thread with REG_NOTIFY_THREAD_AGNOSTIC */
4213 ret = RegOpenKeyA(hkey_main, "TestKey", &key);
4214 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4215
4216 data.key = key;
4221
4222 dwret = WaitForSingleObject(event, 0);
4223 ok(dwret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %lu\n", dwret);
4224
4225 ret = RegCreateKeyA(key, "SubKey", &subkey);
4226 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret);
4227
4228 dwret = WaitForSingleObject(event, 0);
4229 ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", dwret);
4230
4231 RegDeleteKeyA(key, "SubKey");
4232 RegDeleteKeyA(key, "");
4233 RegCloseKey(subkey);
4236}
4237
4238static const char *find_counter_value(const char *text, const char *index)
4239{
4240 const char *p = text;
4241
4242 while (*p)
4243 {
4244 if (!strcmp(p, index))
4245 return p + strlen(p) + 1;
4246
4247 p += strlen(p) + 1;
4248 p += strlen(p) + 1;
4249 }
4250
4251 return NULL;
4252}
4253
4254static void test_counter_values(const char *text, HKEY key)
4255{
4256 const char *p = text;
4257 const char *name;
4258
4259 ok(!strcmp(p, "1"), "got first index %s\n", debugstr_a(p));
4260 p += strlen(p) + 1;
4261 ok(!strcmp(p, "1847"), "got first name %s\n", debugstr_a(p));
4262 p += strlen(p) + 1;
4263
4264 while (*p)
4265 {
4266 unsigned int index = atoi(p);
4267
4268 ok(index > 0, "expected nonzero index\n");
4269
4270 p += strlen(p) + 1;
4271 ok(*p, "name missing for %u\n", index);
4272 p += strlen(p) + 1;
4273 }
4274
4275 name = find_counter_value(text, "1846");
4276 ok(name != NULL, "did not find name\n");
4278 ok(!strcmp(name, "End Marker"), "got name %s\n", debugstr_a(name));
4279}
4280
4281static void test_help_values(const char *text, HKEY key)
4282{
4283 const char *p = text;
4284 const char *name;
4285
4286 while (*p)
4287 {
4288 unsigned int index = atoi(p);
4289
4290 ok(index > 0, "expected nonzero index\n");
4291
4292 p += strlen(p) + 1;
4293 p += strlen(p) + 1;
4294 }
4295
4296 name = find_counter_value(text, "1847");
4297 ok(name != NULL, "did not find name\n");
4299 ok(!strcmp(name, "End Marker"), "got name %s\n", debugstr_a(name));
4300}
4301
4302static void test_performance_keys(void)
4303{
4305 static const char *const names[] = {NULL, "", "Global", "2", "invalid counter name", "System"};
4306 DWORD size, type, sysname_len, expect_size, key_count, value_count;
4307 LARGE_INTEGER perftime1, perftime2, systime1, systime2, freq;
4308 WCHAR sysname[MAX_COMPUTERNAME_LENGTH + 1];
4309 unsigned int buffer_size = 1024 * 1024;
4310 void *buffer, *bufferW;
4312 union
4313 {
4314 FILETIME f;
4315 LONGLONG l;
4316 } file_time;
4317 unsigned int i, j;
4318 HKEY key;
4319 LONG ret;
4320
4321#ifdef __REACTOS__
4322#ifdef _WIN64
4324#else
4326#endif
4327 skip("test_performance_keys() is invalid for Vista x64 and WS03\n");
4328 return;
4329 }
4330#endif
4332
4333 sysname_len = ARRAY_SIZE(sysname);
4334 GetComputerNameW(sysname, &sysname_len);
4335
4336 for (i = 0; i < ARRAY_SIZE(keys); ++i)
4337 {
4338 winetest_push_context("key %p", keys[i]);
4339
4340 for (j = 0; j < ARRAY_SIZE(names); ++j)
4341 {
4342 winetest_push_context("value %s", debugstr_a(names[j]));
4343
4345
4346 size = 0;
4348 ok(ret == ERROR_MORE_DATA, "got %lu\n", ret);
4349 ok(!size, "got size %lu\n", size);
4350
4351 size = 10;
4353 ok(ret == ERROR_MORE_DATA, "got %lu\n", ret);
4354 todo_wine
4355 ok(size == 10, "got size %lu\n", size);
4356
4357 size = buffer_size;
4359 ok(ret == ERROR_MORE_DATA, "got %lu\n", ret);
4360
4361 QueryPerformanceCounter(&perftime1);
4362 NtQuerySystemTime(&systime1);
4363
4364 size = buffer_size;
4365 type = 0xdeadbeef;
4367 ok(!ret, "got %lu\n", ret);
4368 ok(type == REG_BINARY, "got type %lu\n", type);
4369 ok(size >= sizeof(PERF_DATA_BLOCK) && size < buffer_size, "got size %lu\n", size);
4370
4371 QueryPerformanceCounter(&perftime2);
4372 NtQuerySystemTime(&systime2);
4373
4374 data = buffer;
4375 ok(!wcsncmp(data->Signature, L"PERF", 4), "got signature %s\n",
4376 debugstr_wn(data->Signature, 4));
4377 ok(data->LittleEndian == 1, "got endianness %lu\n", data->LittleEndian);
4378 ok(data->Version == 1, "got version %lu\n", data->Version);
4379 ok(data->Revision == 1, "got version %lu\n", data->Revision);
4380 ok(data->TotalByteLength == size, "expected size %lu, got %lu\n",
4381 size, data->TotalByteLength);
4382
4383 expect_size = sizeof(PERF_DATA_BLOCK) + data->SystemNameLength;
4384 expect_size = (expect_size + 7) & ~7;
4385
4386 ok(data->HeaderLength == expect_size, "expected header size %lu, got %lu\n",
4387 expect_size, data->HeaderLength);
4388 /* todo: test objects... */
4389 todo_wine ok(data->DefaultObject == 238, "got default object %lu\n", data->DefaultObject);
4390
4391 ok(data->PerfTime.QuadPart >= perftime1.QuadPart
4392 && data->PerfTime.QuadPart <= perftime2.QuadPart,
4393 "got times %I64d, %I64d, %I64d\n",
4394 perftime1.QuadPart, data->PerfTime.QuadPart, perftime2.QuadPart);
4395 ok(data->PerfFreq.QuadPart == freq.QuadPart, "expected frequency %I64d, got %I64d\n",
4396 freq.QuadPart, data->PerfFreq.QuadPart);
4397 ok(data->PerfTime100nSec.QuadPart >= systime1.QuadPart
4398 && data->PerfTime100nSec.QuadPart <= systime2.QuadPart,
4399 "got times %I64d, %I64d, %I64d\n",
4400 systime1.QuadPart, data->PerfTime100nSec.QuadPart, systime2.QuadPart);
4401 SystemTimeToFileTime(&data->SystemTime, &file_time.f);
4402 /* SYSTEMTIME has a granularity of 1 ms */
4403 ok(file_time.l >= systime1.QuadPart - 10000 && file_time.l <= systime2.QuadPart,
4404 "got times %I64d, %I64d, %I64d\n", systime1.QuadPart, file_time.l, systime2.QuadPart);
4405
4406 ok(data->SystemNameLength == (sysname_len + 1) * sizeof(WCHAR), "got %lu\n", data->SystemNameLength);
4407 ok(data->SystemNameOffset == sizeof(PERF_DATA_BLOCK),
4408 "got name offset %lu\n", data->SystemNameOffset);
4409 ok(!wcscmp(sysname, (const WCHAR *)(data + 1)), "expected name %s, got %s\n",
4410 debugstr_w(sysname), debugstr_w((const WCHAR *)(data + 1)));
4411
4413 }
4414
4415 /* test the "Counter" value */
4416
4417 size = 0xdeadbeef;
4418 ret = RegQueryValueExA(keys[i], "cOuNtEr", NULL, NULL, NULL, &size);
4419 ok(!ret, "got %lu\n", ret);
4420 ok(size > 0 && size < 0xdeadbeef, "got size %lu\n", size);
4421
4422 type = 0xdeadbeef;
4423 size = 0;
4424 ret = RegQueryValueExA(keys[i], "cOuNtEr", NULL, &type, buffer, &size);
4425 ok(ret == ERROR_MORE_DATA, "got %lu\n", ret);
4426 ok(size > 0, "got size %lu\n", size);
4427
4428 type = 0xdeadbeef;
4429 size = buffer_size;
4430 ret = RegQueryValueExA(keys[i], "cOuNtEr", NULL, &type, buffer, &size);
4431 ok(!ret, "got %lu\n", ret);
4432 ok(type == REG_MULTI_SZ, "got type %lu\n", type);
4434
4435 type = 0xdeadbeef;
4436 size = buffer_size;
4437 ret = RegQueryValueExA(keys[i], "cOuNtErwine", NULL, &type, buffer, &size);
4438 ok(!ret, "got %lu\n", ret);
4439 ok(type == REG_MULTI_SZ, "got type %lu\n", type);
4441
4442 size = 0;
4443 ret = RegQueryValueExW(keys[i], L"cOuNtEr", NULL, NULL, NULL, &size);
4444 ok(!ret, "got %lu\n", ret);
4445 ok(size > 0, "got size %lu\n", size);
4446
4447 bufferW = malloc(size);
4448
4449 type = 0xdeadbeef;
4450 ret = RegQueryValueExW(keys[i], L"cOuNtEr", NULL, &type, bufferW, &size);
4451 ok(!ret, "got %lu\n", ret);
4452 ok(type == REG_MULTI_SZ, "got type %lu\n", type);
4453 WideCharToMultiByte(CP_ACP, 0, bufferW, size / sizeof(WCHAR), buffer, buffer_size, NULL, NULL);
4455
4456 /* test the "Help" value */
4457
4458 size = 0xdeadbeef;
4459 ret = RegQueryValueExA(keys[i], "hElP", NULL, NULL, NULL, &size);
4460 ok(!ret, "got %lu\n", ret);
4461 ok(size > 0 && size < 0xdeadbeef, "got size %lu\n", size);
4462
4463 type = 0xdeadbeef;
4464 size = 0;
4465 ret = RegQueryValueExA(keys[i], "hElP", NULL, &type, buffer, &size);
4466 ok(ret == ERROR_MORE_DATA, "got %lu\n", ret);
4467 ok(size > 0, "got size %lu\n", size);
4468
4469 type = 0xdeadbeef;
4470 size = buffer_size;
4471 ret = RegQueryValueExA(keys[i], "hElP", NULL, &type, buffer, &size);
4473
4474 type = 0xdeadbeef;
4475 size = buffer_size;
4476 ret = RegQueryValueExA(keys[i], "hElPwine", NULL, &type, buffer, &size);
4477 ok(!ret, "got %lu\n", ret);
4478 ok(type == REG_MULTI_SZ, "got type %lu\n", type);
4480
4481 size = 0;
4482 ret = RegQueryValueExW(keys[i], L"hElP", NULL, NULL, NULL, &size);
4483 ok(!ret, "got %lu\n", ret);
4484 ok(size > 0, "got size %lu\n", size);
4485
4486 bufferW = malloc(size);
4487
4488 type = 0xdeadbeef;
4489 ret = RegQueryValueExW(keys[i], L"hElP", NULL, &type, bufferW, &size);
4490 ok(!ret, "got %lu\n", ret);
4491 ok(type == REG_MULTI_SZ, "got type %lu\n", type);
4492 WideCharToMultiByte(CP_ACP, 0, bufferW, size / sizeof(WCHAR), buffer, buffer_size, NULL, NULL);
4494
4495 /* test other registry APIs */
4496
4497 ret = RegOpenKeyA(keys[i], NULL, &key);
4498 todo_wine ok(ret == ERROR_INVALID_HANDLE, "got %lu\n", ret);
4499
4500 ret = RegOpenKeyA(keys[i], "Global", &key);
4501 ok(ret == ERROR_INVALID_HANDLE, "got %lu\n", ret);
4502
4503 ret = RegOpenKeyExA(keys[i], "Global", 0, KEY_READ, &key);
4504 ok(ret == ERROR_INVALID_HANDLE, "got %lu\n", ret);
4505
4506 size = 0;
4507 ret = RegQueryValueA(keys[i], "Global", NULL, (LONG *)&size);
4508 ok(ret == ERROR_INVALID_HANDLE, "got %lu\n", ret);
4509
4510 ret = RegSetValueA(keys[i], "Global", REG_SZ, "dummy", 5);
4511 ok(ret == ERROR_INVALID_HANDLE, "got %lu\n", ret);
4512
4513 key_count = 0x900ddeed;
4514 ret = RegQueryInfoKeyA(keys[i], NULL, NULL, NULL, &key_count, NULL,
4515 NULL, &value_count, NULL, NULL, NULL, NULL);
4516 todo_wine ok(!ret, "got %lu\n", ret);
4517 todo_wine ok(!key_count, "got %lu subkeys\n", key_count);
4518 todo_wine ok(value_count == 2, "got %lu values\n", value_count);
4519
4520 size = buffer_size;
4522 todo_wine ok(ret == ERROR_MORE_DATA, "got %lu\n", ret);
4523 ok(size == buffer_size, "got size %lu\n", size);
4524
4525 ret = RegCloseKey(keys[i]);
4526 ok(!ret, "got %lu\n", ret);
4527
4528 ret = RegCloseKey(keys[i]);
4529 ok(!ret, "got %lu\n", ret);
4530
4532 }
4533
4534 ret = RegSetValueExA(HKEY_PERFORMANCE_DATA, "Global", 0, REG_SZ, (const BYTE *)"dummy", 5);
4535 ok(ret == ERROR_INVALID_HANDLE, "got %lu\n", ret);
4536
4537 ret = RegSetValueExA(HKEY_PERFORMANCE_TEXT, "Global", 0, REG_SZ, (const BYTE *)"dummy", 5);
4538 todo_wine ok(ret == ERROR_BADKEY, "got %lu\n", ret);
4539
4540 ret = RegSetValueExA(HKEY_PERFORMANCE_NLSTEXT, "Global", 0, REG_SZ, (const BYTE *)"dummy", 5);
4541 todo_wine ok(ret == ERROR_BADKEY, "got %lu\n", ret);
4542
4543 if (pRegSetKeyValueW)
4544 {
4545 ret = pRegSetKeyValueW(HKEY_PERFORMANCE_DATA, NULL, L"Global", REG_SZ, L"dummy", 10);
4546 ok(ret == ERROR_INVALID_HANDLE, "got %lu\n", ret);
4547
4548 ret = pRegSetKeyValueW(HKEY_PERFORMANCE_TEXT, NULL, L"Global", REG_SZ, L"dummy", 10);
4549 todo_wine ok(ret == ERROR_BADKEY, "got %lu\n", ret);
4550
4551 ret = pRegSetKeyValueW(HKEY_PERFORMANCE_NLSTEXT, NULL, L"Global", REG_SZ, L"dummy", 10);
4552 todo_wine ok(ret == ERROR_BADKEY, "got %lu\n", ret);
4553 }
4554
4556 ok(ret == ERROR_INVALID_HANDLE, "got %lu\n", ret);
4557
4559 todo_wine ok(ret == ERROR_NO_MORE_ITEMS, "got %lu\n", ret);
4560
4562 todo_wine ok(ret == ERROR_NO_MORE_ITEMS, "got %lu\n", ret);
4563
4564 free(buffer);
4565}
4566
4567static void test_perflib_key(void)
4568{
4569 unsigned int primary_lang = PRIMARYLANGID(GetUserDefaultLangID());
4570 unsigned int buffer_size = 1024 * 1024;
4571 OBJECT_NAME_INFORMATION *name_info;
4572 HKEY perflib_key, key, key2;
4575 char lang_name[5];
4576 const char *knames[2] = {"009", "CurrentLanguage"};
4577 char *buffer;
4578 DWORD size;
4579 LONG ret, l;
4580
4582 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Perflib", 0, KEY_READ, &perflib_key);
4583 ok(!ret, "got %lu\n", ret);
4584
4585 ret = RegOpenKeyExA(perflib_key, "009", 0, KEY_READ, &key);
4586 ok(!ret, "got %lu\n", ret);
4587 /* English always returns TEXT; most other languages return NLSTEXT, but
4588 * some (e.g. Hindi) return TEXT */
4589 ok(key == HKEY_PERFORMANCE_TEXT || key == HKEY_PERFORMANCE_NLSTEXT, "got key %p\n", key);
4590
4591 ret = RegCloseKey(key);
4592 ok(!ret, "got %lu\n", ret);
4593
4594 RtlInitUnicodeString(&string, L"009");
4595 InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE, perflib_key, NULL);
4598 || ret == STATUS_SUCCESS /* Win < 7 */, "got %#lx\n", ret);
4600 ok(!is_special_key(key), "expected a normal handle, got %p\n", key);
4601 else if (ret == STATUS_SUCCESS)
4602 ok(key == HKEY_PERFORMANCE_TEXT, "got key %p\n", key);
4603 else
4604 {
4605 skip("Not enough permissions to test the perflib key.\n");
4606 RegCloseKey(perflib_key);
4607 return;
4608 }
4609
4611
4613 ok(ret == STATUS_INVALID_HANDLE, "got %#lx\n", ret);
4614
4616 ok(ret == STATUS_INVALID_HANDLE, "got %#lx\n", ret);
4617
4618 RtlInitUnicodeString(&string, L"counter");
4620 ok(ret == STATUS_INVALID_HANDLE, "got %#lx\n", ret);
4621
4623 ok(ret == STATUS_INVALID_HANDLE, "got %#lx\n", ret);
4624
4625 ret = NtSetValueKey(key, &string, 0, REG_SZ, "test", 5);
4626 ok(ret == STATUS_INVALID_HANDLE, "got %#lx\n", ret);
4627
4628 ret = NtDeleteValueKey(key, &string);
4629 ok(ret == STATUS_INVALID_HANDLE, "got %#lx\n", ret);
4630
4631 ret = NtDeleteKey(key);
4632 ok(ret == STATUS_INVALID_HANDLE, "got %#lx\n", ret);
4633
4634 RtlInitUnicodeString(&string, L"subkey");
4636 ret = NtOpenKey((HANDLE *)&key2, KEY_READ, &attr);
4637 if (is_special_key(key))
4638 ok(ret == STATUS_INVALID_HANDLE, "got %#lx\n", ret);
4639 else
4641 || broken(ret == STATUS_INVALID_HANDLE) /* WoW64 */, "got %#lx\n", ret);
4642
4643 ret = NtCreateKey((HANDLE *)&key2, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL);
4644 if (is_special_key(key))
4645 ok(ret == STATUS_INVALID_HANDLE, "got %#lx\n", ret);
4646 else
4647 ok(!ret || broken(ret == STATUS_ACCESS_DENIED) /* w8adm */
4648 || broken(ret == STATUS_INVALID_HANDLE) /* WoW64 */, "got %#lx\n", ret);
4649 if (!ret)
4650 {
4651 NtDeleteKey(key2);
4652 NtClose(key2);
4653 }
4654
4655 /* it's a real handle, though */
4657 if (is_special_key(key))
4658 ok(ret == STATUS_INVALID_HANDLE, "got %#lx\n", ret);
4659 else
4660 ok(!ret, "got %#lx\n", ret);
4661 if (!ret)
4662 {
4663 name_info = (OBJECT_NAME_INFORMATION *)buffer;
4664 ok(!wcsicmp(name_info->Name.Buffer, L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows NT"
4665 "\\CurrentVersion\\Perflib\\009"), "got name %s\n", debugstr_w(name_info->Name.Buffer));
4666 }
4667
4668 ret = NtClose(key);
4669 if (is_special_key(key))
4670 ok(ret == STATUS_INVALID_HANDLE, "got %#lx\n", ret);
4671 else
4672 ok(!ret, "got %#lx\n", ret);
4673
4674 for (l = 0; l < ARRAY_SIZE(knames); l++)
4675 {
4676 winetest_push_context("%ld", l);
4677 todo_wine_if(l == 1) {
4678 ret = RegOpenKeyExA(perflib_key, knames[l], 0, KEY_READ, &key);
4679#ifdef __REACTOS__
4680 if (ret == ERROR_FILE_NOT_FOUND) /* WS03, Vista */
4681 continue;
4682#endif
4683 ok(!ret, "got %lu\n", ret);
4684 if (is_special_key(key))
4685 {
4686 size = buffer_size;
4687 ret = RegQueryValueExA(key, "counter", NULL, NULL, (BYTE *)buffer, &size);
4688 ok(!ret, "got %lu\n", ret);
4689 if (!ret)
4690 {
4691 char *str;
4692 int c = 0;
4693 for (str = buffer; *str; str += strlen(str) + 1)
4694 c++;
4695 /* Note that the two keys may not have the same number of
4696 * entries if they are in different languages.
4697 */
4698 ok(c >= 2 && (c % 2) == 0, "%d is not a valid number of entries in %s\n", c, knames[l]);
4699 trace("%s has %d entries\n", knames[l], c);
4700 }
4701 }
4702 else
4703 {
4704 /* Windows 7 does not always return a special key for 009
4705 * when running without elevated privileges.
4706 */
4707 ok(broken(l == 0), "expected a special handle, got %p\n", key);
4708 }
4709
4710 ret = RegCloseKey(key);
4711 ok(!ret, "got %lu\n", ret);
4712 }
4714 }
4715
4716 /* multilingual support was not really completely thought through */
4717 switch (primary_lang)
4718 {
4719 case LANG_PORTUGUESE:
4720 case LANG_CHINESE:
4721 sprintf(lang_name, "%04x", GetUserDefaultLangID());
4722 break;
4723 default:
4724 sprintf(lang_name, "%03x", primary_lang);
4725 break;
4726 }
4727 if (primary_lang != LANG_ENGLISH &&
4728 !RegOpenKeyExA(perflib_key, lang_name, 0, KEY_READ, &key))
4729 {
4730 ok(!is_special_key(key), "expected a normal handle, got %p\n", key);
4731
4732 size = buffer_size;
4733 ret = RegQueryValueExA(key, "counter", NULL, NULL, (BYTE *)buffer, &size);
4734 todo_wine ok(ret == ERROR_FILE_NOT_FOUND, "got %lu\n", ret);
4735
4736 ret = RegCloseKey(key);
4737 todo_wine ok(!ret, "got %lu\n", ret);
4738 }
4739 /* else some languages don't have their own key. The keys are not really
4740 * usable anyway so assume it does not really matter.
4741 */
4742
4743 ret = RegCloseKey(perflib_key);
4744 ok(!ret, "got %lu\n", ret);
4745
4746 RtlInitUnicodeString(&string, L"\\Registry\\PerfData");
4748 ret = NtOpenKey((HANDLE *)&key, KEY_READ, &attr);
4749 ok(ret == STATUS_OBJECT_NAME_NOT_FOUND, "got %#lx\n", ret);
4750
4751 free(buffer);
4752}
4753
4754static void test_RegLoadMUIString(void)
4755{
4756 HMODULE hUser32, hResDll, hFile;
4757 int (WINAPI *pLoadStringW)(HMODULE, UINT, WCHAR *, int);
4758 LONG ret;
4759 HKEY hkey;
4760 DWORD type, size, text_size;
4761 UINT i;
4762 char buf[64], *p, sysdir[MAX_PATH];
4763 char with_env_var[128], filename[MAX_PATH], tmp_path[MAX_PATH];
4764 WCHAR textW[64], bufW[64];
4765 WCHAR curdirW[MAX_PATH], sysdirW[MAX_PATH];
4766 const static char tz_value[] = "MUI_Std";
4767 const static WCHAR tz_valueW[] = L"MUI_Std";
4768 struct {
4769 const char* value;
4770 DWORD type;
4771 BOOL use_sysdir;
4773 DWORD broken_ret;
4774 } test_case[] = {
4775 /* 0 */
4777 { "not a MUI string", REG_SZ, FALSE, ERROR_INVALID_DATA },
4778 { "@unknown.dll", REG_SZ, TRUE, ERROR_INVALID_DATA },
4779 { "@unknown.dll,-10", REG_SZ, TRUE, ERROR_FILE_NOT_FOUND },
4780 /* 4 */
4781 { with_env_var, REG_SZ, FALSE, ERROR_SUCCESS },
4782 { with_env_var, REG_EXPAND_SZ, FALSE, ERROR_SUCCESS },
4783 { "%WineMuiTest1%", REG_EXPAND_SZ, TRUE, ERROR_INVALID_DATA },
4784 { "@%WineMuiTest2%", REG_EXPAND_SZ, TRUE, ERROR_SUCCESS },
4785 /* 8 */
4786 { "@%WineMuiExe%,a", REG_SZ, FALSE, ERROR_INVALID_DATA },
4787 { "@%WineMuiExe%,-4", REG_SZ, FALSE, ERROR_NOT_FOUND, ERROR_FILE_NOT_FOUND },
4788#ifdef __REACTOS__
4790#else
4791 { "@%WineMuiExe%,-39", REG_SZ, FALSE, ERROR_RESOURCE_NAME_NOT_FOUND },
4792#endif
4794 };
4795
4796 if (!pRegLoadMUIStringA || !pRegLoadMUIStringW)
4797 {
4798 win_skip("RegLoadMUIString is not available\n");
4799 return;
4800 }
4801#if defined(__REACTOS__) && defined(_WIN64)
4803 skip("test_RegLoadMUIString() spams the console with garbage and crashes on Vista x64.\n");
4804 return;
4805 }
4806#endif
4807
4808 hUser32 = LoadLibraryA("user32.dll");
4809 ok(hUser32 != NULL, "cannot load user32.dll\n");
4810 pLoadStringW = (void *)GetProcAddress(hUser32, "LoadStringW");
4811 ok(pLoadStringW != NULL, "failed to get LoadStringW address\n");
4812
4814 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\UTC", 0,
4815 KEY_READ, &hkey);
4816 ok(ret == ERROR_SUCCESS, "got %ld\n", ret);
4817
4818 size = ARRAY_SIZE(buf);
4819 ret = RegQueryValueExA(hkey, tz_value, NULL, &type, (BYTE *)buf, &size);
4820 ok(ret == ERROR_SUCCESS, "got %ld\n", ret);
4821 ok(buf[0] == '@', "got %s\n", buf);
4822
4823 /* setup MUI string for tests */
4824 strcpy(with_env_var, "@%windir%\\system32\\");
4825 strcat(with_env_var, &buf[1]);
4826 SetEnvironmentVariableA("WineMuiTest1", buf);
4827 SetEnvironmentVariableA("WineMuiTest2", &buf[1]);
4828
4829 /* load expecting text */
4830 p = strrchr(buf, ',');
4831 *p = '\0';
4832 i = atoi(p + 2); /* skip ',-' */
4834 memset(textW, 0xaa, sizeof(textW));
4835 ret = pLoadStringW(hResDll, i, textW, ARRAY_SIZE(textW));
4836 ok(ret > 0, "failed to load string resource\n");
4837 text_size = (ret + 1) * sizeof(WCHAR);
4838 FreeLibrary(hResDll);
4839 FreeLibrary(hUser32);
4840
4841 ret = GetSystemDirectoryW(sysdirW, ARRAY_SIZE(sysdirW));
4842 ok(ret > 0, "GetSystemDirectoryW failed\n");
4843 ret = GetSystemDirectoryA(sysdir, ARRAY_SIZE(sysdir));
4844 ok(ret > 0, "GetSystemDirectoryA failed\n");
4845
4846 /* change the current directory to system32 */
4847 GetCurrentDirectoryW(ARRAY_SIZE(curdirW), curdirW);
4848 SetCurrentDirectoryW(sysdirW);
4849
4850 size = 0xdeadbeef;
4851 ret = pRegLoadMUIStringW(hkey, tz_valueW, NULL, 0, &size, 0, NULL);
4852 ok(ret == ERROR_MORE_DATA, "got %ld, expected ERROR_MORE_DATA\n", ret);
4853#ifdef __REACTOS__
4854 ok(size == text_size || broken(size == text_size + sizeof(WCHAR)) /* Vista */, "got %lu, expected %lu\n", size, text_size);
4855#else
4856 ok(size == text_size, "got %lu, expected %lu\n", size, text_size);
4857#endif
4858
4859 memset(bufW, 0xff, sizeof(bufW));
4860 ret = pRegLoadMUIStringW(hkey, tz_valueW, bufW, sizeof(WCHAR)+1, &size, 0, NULL);
4861 ok(ret == ERROR_INVALID_PARAMETER, "got %ld, expected ERROR_INVALID_PARAMETER\n", ret);
4862 ok(bufW[0] == 0xffff, "got 0x%04x, expected 0xffff\n", bufW[0]);
4863
4864 size = 0xdeadbeef;
4865 memset(bufW, 0xff, sizeof(bufW));
4866 ret = pRegLoadMUIStringW(hkey, tz_valueW, bufW, sizeof(WCHAR)*2, &size, 0, NULL);
4867 ok(ret == ERROR_MORE_DATA, "got %ld, expected ERROR_MORE_DATA\n", ret);
4868 ok(size == text_size || broken(size == text_size + sizeof(WCHAR) /* vista */),
4869 "got %lu, expected %lu\n", size, text_size);
4870 ok(bufW[0] == 0xffff, "got 0x%04x, expected 0xffff\n", bufW[0]);
4871
4872 memset(bufW, 0xff, sizeof(bufW));
4873 ret = pRegLoadMUIStringW(hkey, tz_valueW, bufW, sizeof(WCHAR)*2, &size, REG_MUI_STRING_TRUNCATE, NULL);
4874 ok(ret == ERROR_INVALID_PARAMETER, "got %ld, expected ERROR_INVALID_PARAMETER\n", ret);
4875 ok(bufW[0] == 0xffff, "got 0x%04x, expected 0xffff\n", bufW[0]);
4876
4877 memset(bufW, 0xff, sizeof(bufW));
4878 ret = pRegLoadMUIStringW(hkey, tz_valueW, bufW, sizeof(WCHAR)*2, NULL, 0xdeadbeef, NULL);
4879 ok(ret == ERROR_INVALID_PARAMETER, "got %ld, expected ERROR_INVALID_PARAMETER\n", ret);
4880 ok(bufW[0] == 0xffff, "got 0x%04x, expected 0xffff\n", bufW[0]);
4881
4882 memset(bufW, 0xff, sizeof(bufW));
4883 ret = pRegLoadMUIStringW(hkey, tz_valueW, bufW, sizeof(WCHAR)*2, NULL, REG_MUI_STRING_TRUNCATE, NULL);
4884 ok(ret == ERROR_SUCCESS, "got %ld, expected ERROR_SUCCESS\n", ret);
4885 ok(bufW[0] == textW[0], "got 0x%04x, expected 0x%04x\n", bufW[0], textW[0]);
4886 ok(bufW[1] == 0, "got 0x%04x, expected nul\n", bufW[1]);
4887
4888 size = 0xdeadbeef;
4889 memset(bufW, 0xff, sizeof(bufW));
4890 ret = pRegLoadMUIStringW(hkey, tz_valueW, bufW, ARRAY_SIZE(bufW), &size, 0, NULL);
4891 ok(ret == ERROR_SUCCESS, "got %ld, expected ERROR_SUCCESS\n", ret);
4892 ok(size == text_size, "got %lu, expected %lu\n", size, text_size);
4893 ok(!memcmp(textW, bufW, size), "got %s, expected %s\n",
4894 wine_dbgstr_wn(bufW, size / sizeof(WCHAR)), wine_dbgstr_wn(textW, text_size / sizeof(WCHAR)));
4895
4896 ret = pRegLoadMUIStringA(hkey, tz_value, buf, ARRAY_SIZE(buf), &size, 0, NULL);
4897 ok(ret == ERROR_CALL_NOT_IMPLEMENTED, "got %ld, expected ERROR_CALL_NOT_IMPLEMENTED\n", ret);
4898
4899 /* change the current directory to other than system32 directory */
4901
4902 size = 0xdeadbeef;
4903 memset(bufW, 0xff, sizeof(bufW));
4904 ret = pRegLoadMUIStringW(hkey, tz_valueW, bufW, ARRAY_SIZE(bufW), &size, 0, sysdirW);
4905 ok(ret == ERROR_SUCCESS, "got %ld, expected ERROR_SUCCESS\n", ret);
4906 ok(size == text_size, "got %lu, expected %lu\n", size, text_size);
4907 ok(!memcmp(textW, bufW, size), "got %s, expected %s\n",
4908 wine_dbgstr_wn(bufW, size / sizeof(WCHAR)), wine_dbgstr_wn(textW, text_size / sizeof(WCHAR)));
4909
4910 ret = pRegLoadMUIStringA(hkey, tz_value, buf, ARRAY_SIZE(buf), &size, 0, sysdir);
4911 ok(ret == ERROR_CALL_NOT_IMPLEMENTED, "got %ld, expected ERROR_CALL_NOT_IMPLEMENTED\n", ret);
4912
4913 ret = pRegLoadMUIStringW(hkey, tz_valueW, bufW, ARRAY_SIZE(bufW), &size, 0, NULL);
4914 ok(ret == ERROR_FILE_NOT_FOUND, "got %ld, expected ERROR_FILE_NOT_FOUND\n", ret);
4915
4916 ret = pRegLoadMUIStringA(hkey, tz_value, buf, ARRAY_SIZE(buf), &size, 0, NULL);
4917 ok(ret == ERROR_CALL_NOT_IMPLEMENTED, "got %ld, expected ERROR_CALL_NOT_IMPLEMENTED\n", ret);
4918
4919 RegCloseKey(hkey);
4920
4922 SetEnvironmentVariableA("WineMuiExe", filename);
4923
4924 GetTempPathA(ARRAY_SIZE(tmp_path), tmp_path);
4925 GetTempFileNameA(tmp_path, "mui", 0, filename);
4926 SetEnvironmentVariableA("WineMuiDat", filename);
4927
4928 /* write dummy data to the file, i.e. it's not a PE file. */
4930 ok(hFile != INVALID_HANDLE_VALUE, "can't open %s\n", filename);
4933
4934 for (i = 0; i < ARRAY_SIZE(test_case); i++)
4935 {
4936 size = test_case[i].value ? strlen(test_case[i].value) + 1 : 0;
4937 ret = RegSetValueExA(hkey_main, tz_value, 0, test_case[i].type,
4938 (const BYTE *)test_case[i].value, size);
4939 ok(ret == ERROR_SUCCESS, "[%2u] got %ld\n", i, ret);
4940
4941 size = 0xdeadbeef;
4942 memset(bufW, 0xff, sizeof(bufW));
4943 ret = pRegLoadMUIStringW(hkey_main, tz_valueW, bufW, ARRAY_SIZE(bufW),
4944 &size, 0,
4945 test_case[i].use_sysdir ? sysdirW : NULL);
4946 ok(ret == test_case[i].expected ||
4947#ifdef __REACTOS__
4948 broken(i == 9 && ret == ERROR_RESOURCE_DATA_NOT_FOUND /* Vista */) ||
4949#endif
4950 broken(test_case[i].value[0] == '%' && ret == ERROR_SUCCESS /* vista */) ||
4951 broken(test_case[i].broken_ret && ret == test_case[i].broken_ret /* vista */),
4952 "[%2u] expected %ld, got %ld\n", i, test_case[i].expected, ret);
4953 if (ret == ERROR_SUCCESS && test_case[i].expected == ERROR_SUCCESS)
4954 {
4955 ok(size == text_size, "[%2u] got %lu, expected %lu\n", i, size, text_size);
4956 ok(!memcmp(bufW, textW, size), "[%2u] got %s, expected %s\n", i,
4957 wine_dbgstr_wn(bufW, size/sizeof(WCHAR)),
4958 wine_dbgstr_wn(textW, text_size/sizeof(WCHAR)));
4959 }
4960 }
4961
4962 SetCurrentDirectoryW(curdirW);
4964 SetEnvironmentVariableA("WineMuiTest1", NULL);
4965 SetEnvironmentVariableA("WineMuiTest2", NULL);
4966 SetEnvironmentVariableA("WineMuiExe", NULL);
4967 SetEnvironmentVariableA("WineMuiDat", NULL);
4968}
4969
4971{
4973 HKEY key, subkey;
4974 WCHAR name[128];
4975 WCHAR keyname[128];
4976 WCHAR sysdir[MAX_PATH];
4977 DWORD index, ret, gle, size;
4978 DYNAMIC_TIME_ZONE_INFORMATION bogus_dtzi, dtzi;
4979 struct tz_reg_data
4980 {
4981 LONG bias;
4982 LONG std_bias;
4983 LONG dlt_bias;
4984 SYSTEMTIME std_date;
4985 SYSTEMTIME dlt_date;
4986 } tz_data;
4987
4988 if (!pEnumDynamicTimeZoneInformation)
4989 {
4990 win_skip("EnumDynamicTimeZoneInformation is not supported.\n");
4991 return;
4992 }
4993
4994 if (pRegLoadMUIStringW)
4995 GetSystemDirectoryW(sysdir, ARRAY_SIZE(sysdir));
4996
4997 SetLastError(0xdeadbeef);
4998 ret = pEnumDynamicTimeZoneInformation(0, NULL);
4999 gle = GetLastError();
5000 ok(gle == 0xdeadbeef, "got 0x%lx\n", gle);
5001 ok(ret == ERROR_INVALID_PARAMETER, "got %ld\n", ret);
5002
5003 memset(&bogus_dtzi, 0xcc, sizeof(bogus_dtzi));
5004 memset(&dtzi, 0xcc, sizeof(dtzi));
5005 SetLastError(0xdeadbeef);
5006 ret = pEnumDynamicTimeZoneInformation(-1, &dtzi);
5007 gle = GetLastError();
5008 ok(gle == 0xdeadbeef, "got 0x%lx\n", gle);
5009 ok(ret == ERROR_NO_MORE_ITEMS, "got %ld\n", ret);
5010 ok(!memcmp(&dtzi, &bogus_dtzi, sizeof(dtzi)), "mismatch\n");
5011
5013 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones", 0,
5015 ok(status == ERROR_SUCCESS, "got %ld\n", status);
5016 index = 0;
5017 while (!(status = RegEnumKeyW(key, index, keyname, ARRAY_SIZE(keyname))))
5018 {
5019 winetest_push_context("%s" , wine_dbgstr_w(keyname));
5020 subkey = NULL;
5021 status = RegOpenKeyExW(key, keyname, 0, KEY_QUERY_VALUE, &subkey);
5022 ok(status == ERROR_SUCCESS, "got %ld\n", status);
5023
5024 memset(&dtzi, 0xcc, sizeof(dtzi));
5025 SetLastError(0xdeadbeef);
5026 ret = pEnumDynamicTimeZoneInformation(index, &dtzi);
5027 gle = GetLastError();
5028 /* recently added time zones may not have MUI strings */
5029 ok(gle == ERROR_SUCCESS ||
5030 gle == ERROR_RESOURCE_TYPE_NOT_FOUND /* Win10 1809 32-bit */ ||
5031 gle == ERROR_MUI_FILE_NOT_FOUND /* Win10 1809 64-bit */,
5032 "got 0x%lx\n", gle);
5033 ok(ret == ERROR_SUCCESS, "got %ld\n", ret);
5034 ok(!lstrcmpW(dtzi.TimeZoneKeyName, keyname), "expected %s, got %s\n",
5036
5037 if (gle == ERROR_SUCCESS)
5038 {
5039 size = sizeof(name);
5040 memset(name, 0, sizeof(name));
5041 status = pRegGetValueW(subkey, NULL, L"Std", RRF_RT_REG_SZ, NULL, name, &size);
5042 ok(status == ERROR_SUCCESS, "status %ld Std %s\n", status,
5044 ok(*name, "Std name is empty\n");
5045 if (pRegLoadMUIStringW)
5046 {
5047 size = sizeof(name);
5048 memset(name, 0, sizeof(name));
5049 status = pRegLoadMUIStringW(subkey, L"MUI_Std", name, size, &size, 0, sysdir);
5050 ok(status == ERROR_SUCCESS, "status %ld MUI_Std %s\n",
5052 ok(*name, "MUI_Std name is empty\n");
5053 }
5054 ok(!memcmp(&dtzi.StandardName, name, size), "expected %s, got %s\n",
5056
5057 size = sizeof(name);
5058 memset(name, 0, sizeof(name));
5059 status = pRegGetValueW(subkey, NULL, L"Dlt", RRF_RT_REG_SZ, NULL, name, &size);
5060 ok(status == ERROR_SUCCESS, "status %ld %s Dlt %s\n",
5062 ok(*name, "Dlt name is empty\n");
5063 if (pRegLoadMUIStringW)
5064 {
5065 size = sizeof(name);
5066 memset(name, 0, sizeof(name));
5067 status = pRegLoadMUIStringW(subkey, L"MUI_Dlt", name, size, &size, 0, sysdir);
5068 ok(status == ERROR_SUCCESS, "status %ld %s MUI_Dlt %s\n",
5070 ok(*name, "MUI_Dlt name is empty\n");
5071 }
5072 ok(!memcmp(&dtzi.DaylightName, name, size), "expected %s, got %s\n",
5074
5075 size = sizeof(name);
5076 memset(name, 0, sizeof(name));
5077 status = pRegGetValueW(subkey, NULL, L"Display", RRF_RT_REG_SZ, NULL, name, &size);
5078 ok(status == ERROR_SUCCESS, "status %ld %s Display %s\n",
5080 ok(*name, "Display name is empty\n");
5081 if (pRegLoadMUIStringW)
5082 {
5083 size = sizeof(name);
5084 memset(name, 0, sizeof(name));
5085 status = pRegLoadMUIStringW(subkey, L"MUI_Display", name, size, &size, 0, sysdir);
5086 /* recently added time zones may not have MUI strings */
5087 ok((status == ERROR_SUCCESS && *name) ||
5088 broken(status == ERROR_RESOURCE_TYPE_NOT_FOUND) /* Win10 1809 32-bit */ ||
5089 broken(status == ERROR_MUI_FILE_NOT_FOUND) /* Win10 1809 64-bit */,
5090 "status %ld MUI_Display %s\n", status, wine_dbgstr_w(name));
5091 }
5092 }
5093 else
5094 {
5095 ok(!dtzi.StandardName[0], "expected empty StandardName\n");
5096 ok(!dtzi.DaylightName[0], "expected empty DaylightName\n");
5097 }
5098
5100
5101 size = sizeof(tz_data);
5102 status = pRegGetValueW(key, keyname, L"TZI", RRF_RT_REG_BINARY, NULL, &tz_data, &size);
5103 ok(status == ERROR_SUCCESS, "got %ld\n", status);
5104
5105 ok(dtzi.Bias == tz_data.bias, "expected %ld, got %ld\n",
5106 tz_data.bias, dtzi.Bias);
5107 ok(dtzi.StandardBias == tz_data.std_bias, "expected %ld, got %ld\n",
5108 tz_data.std_bias, dtzi.StandardBias);
5109 ok(dtzi.DaylightBias == tz_data.dlt_bias, "expected %ld, got %ld\n",
5110 tz_data.dlt_bias, dtzi.DaylightBias);
5111
5112 ok(!memcmp(&dtzi.StandardDate, &tz_data.std_date, sizeof(dtzi.StandardDate)),
5113 "expected %s, got %s\n",
5114 dbgstr_SYSTEMTIME(&tz_data.std_date), dbgstr_SYSTEMTIME(&dtzi.StandardDate));
5115
5116 ok(!memcmp(&dtzi.DaylightDate, &tz_data.dlt_date, sizeof(dtzi.DaylightDate)),
5117 "expected %s, got %s\n",
5118 dbgstr_SYSTEMTIME(&tz_data.dlt_date), dbgstr_SYSTEMTIME(&dtzi.DaylightDate));
5119
5121 RegCloseKey(subkey);
5122 index++;
5123 }
5124 ok(status == ERROR_NO_MORE_ITEMS, "got %ld\n", status);
5125
5126 memset(&dtzi, 0xcc, sizeof(dtzi));
5127 SetLastError(0xdeadbeef);
5128 ret = pEnumDynamicTimeZoneInformation(index, &dtzi);
5129 gle = GetLastError();
5130 ok(gle == 0xdeadbeef, "got 0x%lx\n", gle);
5131 ok(ret == ERROR_NO_MORE_ITEMS, "got %ld\n", ret);
5132 ok(!memcmp(&dtzi, &bogus_dtzi, sizeof(dtzi)), "mismatch\n");
5133
5135}
5136
5137static void test_RegRenameKey(void)
5138{
5139#if defined(__REACTOS__) && DLL_EXPORT_VERSION < 0x600
5140 skip("test_RegRenameKey() can't be built unless DLL_EXPORT_VERSION >= 0x600\n");
5141#else
5142 HKEY key, key2;
5143 LSTATUS ret;
5144
5145 ret = RegRenameKey(NULL, NULL, NULL);
5146 ok(ret == ERROR_INVALID_PARAMETER, "Unexpected return value %ld.\n", ret);
5147 ret = RegRenameKey(NULL, NULL, L"newname");
5148 ok(ret == ERROR_INVALID_HANDLE, "Unexpected return value %ld.\n", ret);
5149 ret = RegRenameKey(NULL, L"oldname", NULL);
5150 ok(ret == ERROR_INVALID_HANDLE, "Unexpected return value %ld.\n", ret);
5151 ret = RegRenameKey(NULL, L"oldname", L"newname");
5152 ok(ret == ERROR_INVALID_HANDLE, "Unexpected return value %ld.\n", ret);
5153
5154 ret = RegCreateKeyExA(hkey_main, "TestRenameKey", 0, NULL, 0, KEY_READ, NULL, &key, NULL);
5155 ok(!ret, "Unexpected return value %ld.\n", ret);
5156 ret = RegRenameKey(key, NULL, L"TestNewRenameKey");
5157 ok(ret == ERROR_ACCESS_DENIED, "Unexpected return value %ld.\n", ret);
5159
5160 /* Rename itself. */
5161 ret = RegCreateKeyExA(hkey_main, "TestRenameKey", 0, NULL, 0, KEY_WRITE, NULL, &key, NULL);
5162 ok(!ret, "Unexpected return value %ld.\n", ret);
5163 ret = RegRenameKey(key, NULL, NULL);
5164 ok(ret == ERROR_INVALID_PARAMETER, "Unexpected return value %ld.\n", ret);
5165 ret = RegRenameKey(key, NULL, L"TestNewRenameKey");
5166 ok(!ret, "Unexpected return value %ld.\n", ret);
5168
5169 ret = RegDeleteKeyA(hkey_main, "TestNewRenameKey");
5170 ok(!ret, "Unexpected return value %ld.\n", ret);
5171 ret = RegDeleteKeyA(hkey_main, "TestRenameKey");
5172 ok(ret, "Unexpected return value %ld.\n", ret);
5173
5174 /* Subkey does not exist. */
5175 ret = RegCreateKeyExA(hkey_main, "TestRenameKey", 0, NULL, 0, KEY_WRITE, NULL, &key, NULL);
5176 ok(!ret, "Unexpected return value %ld.\n", ret);
5177 ret = RegRenameKey(key, L"unknown_subkey", NULL);
5178 ok(ret == ERROR_FILE_NOT_FOUND, "Unexpected return value %ld.\n", ret);
5179 ret = RegRenameKey(key, L"unknown_subkey", L"known_subkey");
5180 ok(ret == ERROR_FILE_NOT_FOUND, "Unexpected return value %ld.\n", ret);
5181
5182 /* Rename existing subkey. */
5183 ret = RegCreateKeyExA(key, "known_subkey", 0, NULL, 0, KEY_WRITE, NULL, &key2, NULL);
5184 ok(!ret, "Unexpected return value %ld.\n", ret);
5185 RegCloseKey(key2);
5186
5187 ret = RegRenameKey(key, L"known_subkey", L"renamed_subkey");
5188 ok(!ret, "Unexpected return value %ld.\n", ret);
5189
5190 ret = RegDeleteKeyA(key, "renamed_subkey");
5191 ok(!ret, "Unexpected return value %ld.\n", ret);
5192 ret = RegDeleteKeyA(key, "known_subkey");
5193 ok(ret, "Unexpected return value %ld.\n", ret);
5194
5196#endif
5197}
5198
5200{
5201 if (str[0] < '0' || str[0] > '9' || str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9')
5202 return FALSE;
5203 if (str[0] == '0' && str[1] == '0' && str[2] == '0')
5204 return FALSE;
5205 return TRUE;
5206}
5207
5209{
5210 static const WCHAR target_pfxW[] = L"\\REGISTRY\\Machine\\System\\ControlSet";
5211 DWORD target_len, type, len, err;
5212 BYTE buffer[1024];
5213 HKEY key;
5214
5215 target_len = sizeof(target_pfxW) + 3 * sizeof(WCHAR);
5216
5217 err = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "System\\CurrentControlSet", REG_OPTION_OPEN_LINK, KEY_QUERY_VALUE, &key );
5218 ok( err == ERROR_SUCCESS, "RegOpenKeyEx failed error %lu\n", err );
5219 len = sizeof(buffer);
5220 err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len );
5221 ok( err == ERROR_SUCCESS, "RegQueryValueEx failed error %lu\n", err );
5222 ok( len == target_len - sizeof(WCHAR), "wrong len %lu\n", len );
5223 ok( !wcsnicmp( (WCHAR*)buffer, target_pfxW, ARRAY_SIZE(target_pfxW) - 1 ) &&
5224 check_cs_number( (WCHAR*)buffer + ARRAY_SIZE(target_pfxW) - 1 ),
5225 "wrong link target\n" );
5226 RegCloseKey( key );
5227}
5228
5230{
5231 /* Load pointers for functions that are not available in all Windows versions */
5233
5249 test_symlinks();
5258 test_rw_order();
5270
5271 /* cleanup */
5273
5275}
@ ObjectNameInformation
Definition: DriverTester.h:55
NTSTATUS NtQueryObject(IN HANDLE Handle, IN OBJECT_INFO_CLASS ObjectInformationClass, OUT PVOID ObjectInformation, IN ULONG ObjectInformationLength, OUT PULONG ReturnLength)
#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:190
@ TRUSTEE_IS_WELL_KNOWN_GROUP
Definition: accctrl.h:182
@ NO_MULTIPLE_TRUSTEE
Definition: accctrl.h:199
@ SET_ACCESS
Definition: accctrl.h:150
#define GetNTVersion()
Definition: apitest.h:17
#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 index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:20
static HANDLE thread
Definition: service.c:33
#define UlongToHandle(ul)
Definition: basetsd.h:91
#define HandleToUlong(h)
Definition: basetsd.h:73
#define RegCloseKey(hKey)
Definition: registry.h:49
HANDLE HKEY
Definition: registry.h:26
struct _root root
r l[0]
Definition: byte_order.h:168
const char ** registry
Definition: cffdrivr.c:696
Definition: _set.h:50
BOOL WINAPI GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
Definition: compname.c:446
#define STATUS_INVALID_HANDLE
Definition: d3dkmdt.h:40
const WCHAR * link
Definition: db.cpp:998
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#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
#define NTSTATUS
Definition: precomp.h:19
LONG WINAPI RegCreateKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1179
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1096
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3234
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 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
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 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 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 RegEnumKeyW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, DWORD cbName)
Definition: reg.c:2393
LONG WINAPI RegCreateKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1201
LONG WINAPI RegDeleteKeyA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey)
Definition: reg.c:1224
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
const char * wine_dbg_sprintf(const char *format,...)
Definition: compat.c:296
#define CloseHandle
Definition: compat.h:739
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define wcsnicmp
Definition: compat.h:14
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:756
#define CP_ACP
Definition: compat.h:109
#define OPEN_EXISTING
Definition: compat.h:775
#define lstrcpynA
Definition: compat.h:751
#define SetLastError(x)
Definition: compat.h:752
#define GetProcAddress(x, y)
Definition: compat.h:753
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
static __inline const char * debugstr_an(const char *s, int n)
Definition: compat.h:55
#define FreeLibrary(x)
Definition: compat.h:748
#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 ERROR_INVALID_HANDLE
Definition: compat.h:98
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define wcsicmp
Definition: compat.h:15
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:219
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
BOOL WINAPI RemoveDirectoryA(IN LPCSTR lpPathName)
Definition: dir.c:682
BOOL WINAPI CreateDirectoryA(IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:37
HANDLE WINAPI FindFirstFileA(IN LPCSTR lpFileName, OUT LPWIN32_FIND_DATAA lpFindFileData)
Definition: find.c:263
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
BOOL WINAPI FindNextFileA(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAA lpFindFileData)
Definition: find.c:336
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
Definition: loader.c:159
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
DWORD WINAPI GetModuleFileNameA(HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
Definition: loader.c:539
BOOL WINAPI SetCurrentDirectoryW(IN LPCWSTR lpPathName)
Definition: path.c:2168
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2232
BOOL WINAPI SetCurrentDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:2125
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:1973
UINT WINAPI GetSystemDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2202
BOOL WINAPI QueryPerformanceFrequency(OUT PLARGE_INTEGER lpFrequency)
Definition: perfcnt.c:45
BOOL WINAPI QueryPerformanceCounter(OUT PLARGE_INTEGER lpPerformanceCount)
Definition: perfcnt.c:23
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
BOOL WINAPI SystemTimeToFileTime(IN CONST SYSTEMTIME *lpSystemTime, OUT LPFILETIME lpFileTime)
Definition: time.c:158
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4152
int WINAPI lstrcmpA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4104
LANGID WINAPI GetUserDefaultLangID(void)
Definition: locale.c:1182
const UINT * keys
Definition: locale.c:416
DWORD WINAPI DECLSPEC_HOTPATCH EnumDynamicTimeZoneInformation(DWORD index, DYNAMIC_TIME_ZONE_INFORMATION *info)
Definition: locale.c:4986
LSTATUS WINAPI RegEnumValueW(HKEY hkey, DWORD index, LPWSTR value, LPDWORD val_count, LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
Definition: registry.c:2167
LSTATUS WINAPI RegDeleteValueA(HKEY hkey, LPCSTR name)
Definition: registry.c:2362
LSTATUS WINAPI RegGetValueW(HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData)
Definition: registry.c:1923
LSTATUS WINAPI RegOpenCurrentUser(REGSAM access, PHKEY retkey)
Definition: registry.c:764
LSTATUS WINAPI RegLoadMUIStringW(HKEY hKey, LPCWSTR pwszValue, LPWSTR pwszBuffer, DWORD cbBuffer, LPDWORD pcbData, DWORD dwFlags, LPCWSTR pwszBaseDir)
Definition: registry.c:2973
LONG WINAPI RegDeleteKeyValueA(HKEY hkey, LPCSTR subkey, LPCSTR name)
Definition: registry.c:2394
LSTATUS WINAPI RegDeleteTreeA(HKEY hkey, const char *subkey)
Definition: registry.c:3152
LSTATUS WINAPI RegNotifyChangeKeyValue(HKEY hkey, BOOL fWatchSubTree, DWORD fdwNotifyFilter, HANDLE hEvent, BOOL fAsync)
Definition: registry.c:2740
LONG WINAPI RegSetKeyValueW(HKEY hkey, LPCWSTR subkey, LPCWSTR name, DWORD type, const void *data, DWORD len)
Definition: registry.c:1312
LSTATUS WINAPI RegEnumValueA(HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count, LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
Definition: registry.c:2244
LSTATUS WINAPI DECLSPEC_HOTPATCH RegQueryValueExA(HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
Definition: registry.c:1753
LSTATUS WINAPI RegSetKeySecurity(HKEY hkey, SECURITY_INFORMATION SecurityInfo, PSECURITY_DESCRIPTOR pSecurityDesc)
Definition: registry.c:2650
LSTATUS WINAPI RegGetValueA(HKEY hKey, LPCSTR pszSubKey, LPCSTR pszValue, DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData)
Definition: registry.c:2038
LSTATUS WINAPI RegLoadKeyA(HKEY hkey, LPCSTR subkey, LPCSTR filename)
Definition: registry.c:2473
LSTATUS WINAPI RegLoadAppKeyA(const char *file, HKEY *result, REGSAM sam, DWORD options, DWORD reserved)
Definition: registry.c:3246
LSTATUS WINAPI RegDeleteKeyExA(HKEY hkey, LPCSTR name, REGSAM access, DWORD reserved)
Definition: registry.c:1186
LSTATUS WINAPI RegQueryInfoKeyA(HKEY hkey, LPSTR class, LPDWORD class_len, LPDWORD reserved, LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class, LPDWORD values, LPDWORD max_value, LPDWORD max_data, LPDWORD security, FILETIME *modif)
Definition: registry.c:1070
LSTATUS WINAPI DECLSPEC_HOTPATCH RegOpenKeyExA(HKEY hkey, LPCSTR name, DWORD options, REGSAM access, PHKEY retkey)
Definition: registry.c:711
LSTATUS WINAPI DECLSPEC_HOTPATCH RegSetValueExA(HKEY hkey, LPCSTR name, DWORD reserved, DWORD type, const BYTE *data, DWORD count)
Definition: registry.c:1264
LSTATUS WINAPI DECLSPEC_HOTPATCH RegCreateKeyExA(HKEY hkey, LPCSTR name, DWORD reserved, LPSTR class, DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa, PHKEY retkey, LPDWORD dispos)
Definition: registry.c:629
LSTATUS WINAPI RegLoadMUIStringA(HKEY hKey, LPCSTR pszValue, LPSTR pszBuffer, DWORD cbBuffer, LPDWORD pcbData, DWORD dwFlags, LPCSTR pszBaseDir)
Definition: registry.c:3072
LSTATUS WINAPI RegUnLoadKeyA(HKEY hkey, LPCSTR lpSubKey)
Definition: registry.c:2624
LSTATUS WINAPI RegFlushKey(HKEY hkey)
Definition: registry.c:2715
DWORD WINAPI GetVersion(void)
Definition: version.c:1458
const WCHAR * text
Definition: package.c:1794
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1972
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
_ACRTIMP int __cdecl wcsncmp(const wchar_t *, const wchar_t *, size_t)
Definition: wcs.c:518
#define va_end(v)
Definition: stdarg.h:28
#define va_start(v, l)
Definition: stdarg.h:26
_ACRTIMP int __cdecl atoi(const char *)
Definition: string.c:1715
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
_ACRTIMP size_t __cdecl strspn(const char *, const char *)
Definition: string.c:3515
_ACRTIMP char *__cdecl strrchr(const char *, int)
Definition: string.c:3298
char * va_list
Definition: vadefs.h:50
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2996
#define INFINITE
Definition: serial.h:102
#define ULONG_PTR
Definition: config.h:101
UNICODE_STRING * PUNICODE_STRING
Definition: env_spec_w32.h:373
UINT WINAPI GetTempFileNameA(IN LPCSTR lpPathName, IN LPCSTR lpPrefixString, IN UINT uUnique, OUT LPSTR lpTempFileName)
Definition: filename.c:26
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
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
struct _cl_event * event
Definition: glext.h:7739
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
GLsizeiptr size
Definition: glext.h:5919
GLfloat bias
Definition: glext.h:7909
const GLubyte * c
Definition: glext.h:8905
GLuint index
Definition: glext.h:6031
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
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
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 GLint GLint j
Definition: glfuncs.h:250
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
static const WCHAR emptyW[]
Definition: navigate.c:40
REFIID LPVOID DWORD_PTR dw
Definition: atlbase.h:40
const char * filename
Definition: ioapi.h:137
const unsigned char size_t insize
Definition: jpeglib.h:984
unsigned char size_t * outsize
Definition: jpeglib.h:981
#define f
Definition: ke_i.h:83
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_wn
Definition: kernel32.h:33
#define debugstr_w
Definition: kernel32.h:32
#define wine_dbgstr_w
Definition: kernel32.h:34
BOOL is_wow64
Definition: main.c:38
#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
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl winetest_push_context(const char *fmt,...) __WINE_PRINTF_ATTR(1
#define win_skip
Definition: minitest.h:67
#define todo_wine_if(is_todo)
Definition: minitest.h:81
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl void winetest_pop_context(void)
#define todo_wine
Definition: minitest.h:80
#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
Definition: sprintf.c:45
static const char * dbgstr_SYSTEMTIME(const SYSTEMTIME *st)
Definition: registry.c:92
static void test_multistring_termination(void)
Definition: registry.c:2270
static void test_performance_keys(void)
Definition: registry.c:4302
static HKEY hkey_main
Definition: registry.c:53
static void test_reg_copy_tree(void)
Definition: registry.c:2383
static PCWSTR
Definition: registry.c:70
static BOOL set_privileges(LPCSTR privilege, BOOL set)
Definition: registry.c:1537
static const BOOL is_64bit
Definition: registry.c:79
static DWORD get_key_value(HKEY root, const char *name, DWORD flags)
Definition: registry.c:2742
static DWORD GLE
Definition: registry.c:54
static LPSTR
Definition: registry.c:73
static void check_user_privs(void)
Definition: registry.c:166
static void create_test_entries(void)
Definition: registry.c:473
#define check_enum_value(name, flags, subkeys, found)
Definition: registry.c:2794
#define IS_HKCR(hk)
Definition: registry.c:51
static void test_RegLoadMUIString(void)
Definition: registry.c:4754
static void test_reg_load_app_key(void)
Definition: registry.c:1706
static const char * sTestpath2
Definition: registry.c:57
static void test_enum_value(void)
Definition: registry.c:496
static void test_string_termination(void)
Definition: registry.c:2177
static void test_reg_delete_tree(void)
Definition: registry.c:2478
static void test_RegNotifyChangeKeyValue(void)
Definition: registry.c:4104
static void test_redirection(void)
Definition: registry.c:2796
static void test_symlinks(void)
Definition: registry.c:2614
static void test_query_value_ex(void)
Definition: registry.c:764
static void test_reg_open_key(void)
Definition: registry.c:1005
static void test_reg_query_value(void)
Definition: registry.c:1814
static void test_get_value(void)
Definition: registry.c:791
static void test_reg_close_key(void)
Definition: registry.c:1469
static void test_classesroot(void)
Definition: registry.c:3419
static void test_reg_create_key(void)
Definition: registry.c:1290
static void test_reg_query_info(void)
Definition: registry.c:1935
#define test_hkey_main_Value_A(name, string, full_byte_len)
Definition: registry.c:187
static void test_help_values(const char *text, HKEY key)
Definition: registry.c:4281
static void _test_hkey_main_Value_W(int line, LPCWSTR name, LPCWSTR string, DWORD full_byte_len)
Definition: registry.c:234
#define ADVAPI32_GET_PROC(func)
Definition: registry.c:99
static void test_perflib_key(void)
Definition: registry.c:4567
static void wait_file_available(char *path)
Definition: registry.c:1691
static void test_classesroot_mask(void)
Definition: registry.c:3895
static void _check_enum_value(int line, const char *name, DWORD flags, DWORD subkeys_in, BOOL found_in)
Definition: registry.c:2767
static const DWORD ptr_size
Definition: registry.c:58
static void InitFunctionPtrs(void)
Definition: registry.c:102
#define check_key_value(root, name, flags, expect)
Definition: registry.c:2765
static BOOL check_cs_number(const WCHAR *str)
Definition: registry.c:5199
static PBOOL
Definition: registry.c:65
static DYNAMIC_TIME_ZONE_INFORMATION *static BOOL limited_user
Definition: registry.c:78
static void test_counter_values(const char *text, HKEY key)
Definition: registry.c:4254
static void test_classesroot_enum(void)
Definition: registry.c:3718
static void _check_key_value(int line, HANDLE root, const char *name, DWORD flags, DWORD expect)
Definition: registry.c:2760
static const char * sTestpath1
Definition: registry.c:56
static const char * find_counter_value(const char *text, const char *index)
Definition: registry.c:4238
static void test_control_set_symlink(void)
Definition: registry.c:5208
static BOOL has_wow64(void)
Definition: registry.c:81
static void test_reg_delete_key(void)
Definition: registry.c:1503
static void test_deleted_key(void)
Definition: registry.c:3927
static BOOL is_special_key(HKEY key)
Definition: registry.c:128
static LPDWORD
Definition: registry.c:60
static void test_EnumDynamicTimeZoneInformation(void)
Definition: registry.c:4970
static const char *static REGSAM
Definition: registry.c:64
static void test_delete_key_value(void)
Definition: registry.c:4012
static void test_RegOpenCurrentUser(void)
Definition: registry.c:4075
static LPCSTR
Definition: registry.c:60
#define lok
Definition: registry.c:186
static void delete_dir(const char *path)
Definition: registry.c:1571
static void test_rw_order(void)
Definition: registry.c:2568
static DWORD WINAPI notify_change_thread(void *arg)
Definition: registry.c:4093
static void test_delete_value(void)
Definition: registry.c:3973
static void _test_hkey_main_Value_A(int line, LPCSTR name, LPCSTR string, DWORD full_byte_len)
Definition: registry.c:188
#define test_hkey_main_Value_W(name, string, full_byte_len)
Definition: registry.c:233
static void test_reg_load_key(void)
Definition: registry.c:1602
static void test_set_value(void)
Definition: registry.c:278
static void test_RegRenameKey(void)
Definition: registry.c:5137
static void setup_main_key(void)
Definition: registry.c:156
static void test_regconnectregistry(void)
Definition: registry.c:1770
static const WCHAR textW[]
Definition: itemdlg.c:1559
static const CHAR emptyA[]
Definition: printdlg.c:52
BOOL expected
Definition: store.c:2000
static HINSTANCE hkernel32
Definition: process.c:68
static HINSTANCE hntdll
Definition: process.c:68
static const WCHAR sd[]
Definition: suminfo.c:286
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
_In_ HANDLE hFile
Definition: mswsock.h:90
unsigned int UINT
Definition: ndis.h:50
NTSYSAPI NTSTATUS NTAPI NtOpenKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: ntapi.c:336
NTSYSAPI NTSTATUS NTAPI NtSetValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN ULONG TitleIndex OPTIONAL, IN ULONG Type, IN PVOID Data, IN ULONG DataSize)
Definition: ntapi.c:859
@ KeyFullInformation
Definition: nt_native.h:1136
#define REG_BINARY
Definition: nt_native.h:1499
#define REG_OPTION_OPEN_LINK
Definition: nt_native.h:1073
@ KeyValuePartialInformation
Definition: nt_native.h:1185
#define KEY_ALL_ACCESS
Definition: nt_native.h:1044
#define KEY_READ
Definition: nt_native.h:1026
NTSYSAPI NTSTATUS NTAPI NtDeleteValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName)
Definition: ntapi.c:1014
#define REG_OPTION_CREATE_LINK
Definition: nt_native.h:1066
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI NTSTATUS NTAPI NtQueryValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, IN PULONG ResultLength)
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1060
#define KEY_QUERY_VALUE
Definition: nt_native.h:1019
#define REG_MULTI_SZ
Definition: nt_native.h:1504
NTSYSAPI NTSTATUS NTAPI NtEnumerateKey(IN HANDLE KeyHandle, IN ULONG Index, IN KEY_INFORMATION_CLASS KeyInformationClass, IN PVOID KeyInformation, IN ULONG Length, IN PULONG ResultLength)
#define STANDARD_RIGHTS_ALL
Definition: nt_native.h:69
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1022
#define GENERIC_ALL
Definition: nt_native.h:92
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define BOOL
Definition: nt_native.h:43
#define KEY_WRITE
Definition: nt_native.h:1034
#define REG_LINK
Definition: nt_native.h:1503
#define DWORD
Definition: nt_native.h:44
#define GENERIC_WRITE
Definition: nt_native.h:90
#define REG_EXPAND_SZ
Definition: nt_native.h:1497
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1063
#define KEY_NOTIFY
Definition: nt_native.h:1023
#define KEY_SET_VALUE
Definition: nt_native.h:1020
NTSTATUS NTAPI NtDeleteKey(IN HANDLE KeyHandle)
Definition: ntapi.c:408
NTSTATUS NTAPI NtCreateKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG TitleIndex, IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL)
Definition: ntapi.c:240
NTSTATUS NTAPI NtEnumerateValueKey(IN HANDLE KeyHandle, IN ULONG Index, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, OUT PVOID KeyValueInformation, IN ULONG Length, OUT PULONG ResultLength)
Definition: ntapi.c:542
NTSTATUS NTAPI NtQueryKey(IN HANDLE KeyHandle, IN KEY_INFORMATION_CLASS KeyInformationClass, OUT PVOID KeyInformation, IN ULONG Length, OUT PULONG ResultLength)
Definition: ntapi.c:632
NTSTATUS NTAPI NtQuerySystemTime(OUT PLARGE_INTEGER SystemTime)
Definition: time.c:569
#define STATUS_PREDEFINED_HANDLE
Definition: ntstatus.h:211
long LONG
Definition: pedump.c:60
_In_opt_ _In_opt_ _In_ _In_ DWORD cbData
Definition: shlwapi.h:761
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define err(...)
#define delete_key(r, p, s)
Definition: reg_test.h:64
#define wine_dbgstr_wn
Definition: testlist.c:2
const WCHAR * str
SC_HANDLE WINAPI OpenSCManagerA(LPCSTR lpMachineName, LPCSTR lpDatabaseName, DWORD dwDesiredAccess)
Definition: scm.c:2063
BOOL WINAPI CloseServiceHandle(SC_HANDLE hSCObject)
Definition: scm.c:580
#define REG_DWORD
Definition: sdbapi.c:615
#define LANG_ENGLISH
Definition: nls.h:52
#define LANG_CHINESE
Definition: nls.h:42
#define PRIMARYLANGID(l)
Definition: nls.h:16
#define LANG_PORTUGUESE
Definition: nls.h:108
wcscpy
strcat
Definition: string.h:92
strcpy
Definition: string.h:131
static int fd
Definition: io.c:51
#define memset(x, y, z)
Definition: compat.h:39
#define args
Definition: format.c:66
#define _WIN32_WINNT_WS03
Definition: sdkddkver.h:23
#define _WIN32_WINNT_VISTA
Definition: sdkddkver.h:25
BOOL WINAPI SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl, BOOL bDaclDefaulted)
Definition: sec.c:262
#define STATUS_CANNOT_DELETE
Definition: shellext.h:71
#define STATUS_SUCCESS
Definition: shellext.h:65
BOOL WINAPI SHIM_OBJ_NAME() GetComputerNameA(LPSTR lpBuffer, LPDWORD lpnSize)
Definition: shimtest.c:21
wchar_t const *const size_t const buffer_size
Definition: stat.cpp:95
DWORD dwHighDateTime
Definition: mapidefs.h:66
DWORD dwLowDateTime
Definition: mapidefs.h:65
UNICODE_STRING Name
Definition: nt_native.h:1273
WORD wMilliseconds
Definition: minwinbase.h:263
WORD wSecond
Definition: minwinbase.h:262
WORD wMinute
Definition: minwinbase.h:261
Definition: match.c:390
Definition: cookie.c:202
Definition: fci.c:127
Definition: format.c:58
Definition: copy.c:22
Definition: parser.c:49
Definition: name.c:39
HANDLE event
Definition: registry.c:4090
DWORD flags
Definition: registry.c:4089
Definition: ps.c:97
Definition: tools.h:99
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:726
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:587
#define vsnprintf
Definition: tif_win32.c:406
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
HANDLE HMODULE
Definition: typedefs.h:77
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
struct _OBJECT_ATTRIBUTES * POBJECT_ATTRIBUTES
Definition: file.c:85
LONGLONG QuadPart
Definition: typedefs.h:114
Definition: pdh_main.c:96
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define LOAD_LIBRARY_AS_IMAGE_RESOURCE
Definition: winbase.h:343
#define LOAD_LIBRARY_AS_DATAFILE
Definition: winbase.h:338
#define WAIT_OBJECT_0
Definition: winbase.h:383
#define MAX_COMPUTERNAME_LENGTH
Definition: winbase.h:267
void * arg
Definition: msvc.h:10
#define WINAPI
Definition: msvc.h:6
#define ERROR_MUI_FILE_NOT_FOUND
Definition: winerror.h:3250
#define ERROR_UNSUPPORTED_TYPE
Definition: winerror.h:1336
#define ERROR_BADKEY
Definition: winerror.h:913
#define ERROR_BAD_PATHNAME
Definition: winerror.h:355
#define ERROR_KEY_DELETED
Definition: winerror.h:921
#define ERROR_BAD_EXE_FORMAT
Definition: winerror.h:373
#define ERROR_NO_SYSTEM_RESOURCES
Definition: winerror.h:1276
#define ERROR_CHILD_MUST_BE_VOLATILE
Definition: winerror.h:924
#define ERROR_RESOURCE_TYPE_NOT_FOUND
Definition: winerror.h:1477
#define ERROR_RESOURCE_NAME_NOT_FOUND
Definition: winerror.h:1478
#define ERROR_DATATYPE_MISMATCH
Definition: winerror.h:1335
#define ERROR_RESOURCE_DATA_NOT_FOUND
Definition: winerror.h:1476
#define ERROR_NOACCESS
Definition: winerror.h:902
#define ERROR_INVALID_DATA
Definition: winerror.h:238
#define ERROR_NOT_FOUND
Definition: winerror.h:1014
struct _PERF_DATA_BLOCK PERF_DATA_BLOCK
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_CONFIG
Definition: winreg.h:15
#define RRF_NOEXPAND
Definition: winreg.h:72
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define REG_MUI_STRING_TRUNCATE
Definition: winreg.h:43
#define REG_NOTIFY_CHANGE_NAME
Definition: winreg.h:38
#define HKEY_PERFORMANCE_TEXT
Definition: winreg.h:17
#define RRF_RT_ANY
Definition: winreg.h:66
#define HKEY_PERFORMANCE_NLSTEXT
Definition: winreg.h:18
#define RRF_SUBKEY_WOW6464KEY
Definition: winreg.h:68
#define REG_NOTIFY_CHANGE_LAST_SET
Definition: winreg.h:40
#define RRF_RT_REG_BINARY
Definition: winreg.h:60
#define RRF_RT_REG_DWORD
Definition: winreg.h:61
#define RRF_ZEROONFAILURE
Definition: winreg.h:73
#define REG_NOTIFY_THREAD_AGNOSTIC
Definition: winreg.h:42
#define RRF_RT_DWORD
Definition: winreg.h:64
#define RRF_RT_REG_EXPAND_SZ
Definition: winreg.h:59
#define HKEY_PERFORMANCE_DATA
Definition: winreg.h:14
#define RRF_RT_QWORD
Definition: winreg.h:65
#define RRF_RT_REG_SZ
Definition: winreg.h:58
#define HKEY_CLASSES_ROOT
Definition: winreg.h:10
#define RRF_SUBKEY_WOW6432KEY
Definition: winreg.h:69
#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:942
#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:827
const char * LPCSTR
Definition: xmlstorage.h:183
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193