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