server: Store all 32 bits of value type.
[wine.git] / dlls / ntdll / tests / reg.c
blob96f190bbafd089bd12ab1fa13afa04b7d9af2afe
1 /* Unit test suite for Rtl* Registry API functions
3 * Copyright 2003 Thomas Mertes
4 * Copyright 2005 Brad DeMorrow
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * NOTE: I don't test every RelativeTo value because it would be redundant, all calls go through
21 * helper function RTL_GetKeyHandle().--Brad DeMorrow
25 #include "ntdll_test.h"
26 #include "winternl.h"
27 #include "stdio.h"
28 #include "winnt.h"
29 #include "winnls.h"
30 #include "stdlib.h"
32 /* A test string */
33 static const WCHAR stringW[] = {'s', 't', 'r', 'i', 'n', 'g', 'W', 0};
34 /* A size, in bytes, short enough to cause truncation of the above */
35 #define STR_TRUNC_SIZE (sizeof(stringW)-2*sizeof(*stringW))
37 #ifndef __WINE_WINTERNL_H
39 /* RtlQueryRegistryValues structs and defines */
40 #define RTL_REGISTRY_ABSOLUTE 0
41 #define RTL_REGISTRY_SERVICES 1
42 #define RTL_REGISTRY_CONTROL 2
43 #define RTL_REGISTRY_WINDOWS_NT 3
44 #define RTL_REGISTRY_DEVICEMAP 4
45 #define RTL_REGISTRY_USER 5
47 #define RTL_REGISTRY_HANDLE 0x40000000
48 #define RTL_REGISTRY_OPTIONAL 0x80000000
50 #define RTL_QUERY_REGISTRY_SUBKEY 0x00000001
51 #define RTL_QUERY_REGISTRY_TOPKEY 0x00000002
52 #define RTL_QUERY_REGISTRY_REQUIRED 0x00000004
53 #define RTL_QUERY_REGISTRY_NOVALUE 0x00000008
54 #define RTL_QUERY_REGISTRY_NOEXPAND 0x00000010
55 #define RTL_QUERY_REGISTRY_DIRECT 0x00000020
56 #define RTL_QUERY_REGISTRY_DELETE 0x00000040
58 typedef NTSTATUS (WINAPI *PRTL_QUERY_REGISTRY_ROUTINE)( PCWSTR ValueName,
59 ULONG ValueType,
60 PVOID ValueData,
61 ULONG ValueLength,
62 PVOID Context,
63 PVOID EntryContext);
65 typedef struct _RTL_QUERY_REGISTRY_TABLE {
66 PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine;
67 ULONG Flags;
68 PWSTR Name;
69 PVOID EntryContext;
70 ULONG DefaultType;
71 PVOID DefaultData;
72 ULONG DefaultLength;
73 } RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE;
75 typedef struct _KEY_VALUE_BASIC_INFORMATION {
76 ULONG TitleIndex;
77 ULONG Type;
78 ULONG NameLength;
79 WCHAR Name[1];
80 } KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION;
82 typedef struct _KEY_VALUE_PARTIAL_INFORMATION {
83 ULONG TitleIndex;
84 ULONG Type;
85 ULONG DataLength;
86 UCHAR Data[1];
87 } KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION;
89 typedef struct _KEY_VALUE_FULL_INFORMATION {
90 ULONG TitleIndex;
91 ULONG Type;
92 ULONG DataOffset;
93 ULONG DataLength;
94 ULONG NameLength;
95 WCHAR Name[1];
96 } KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION;
98 typedef enum _KEY_VALUE_INFORMATION_CLASS {
99 KeyValueBasicInformation,
100 KeyValueFullInformation,
101 KeyValuePartialInformation,
102 KeyValueFullInformationAlign64,
103 KeyValuePartialInformationAlign64
104 } KEY_VALUE_INFORMATION_CLASS;
106 #define InitializeObjectAttributes(p,n,a,r,s) \
107 do { \
108 (p)->Length = sizeof(OBJECT_ATTRIBUTES); \
109 (p)->RootDirectory = r; \
110 (p)->Attributes = a; \
111 (p)->ObjectName = n; \
112 (p)->SecurityDescriptor = s; \
113 (p)->SecurityQualityOfService = NULL; \
114 } while (0)
116 #endif
118 static BOOLEAN (WINAPI * pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPCSTR);
119 static void (WINAPI * pRtlInitUnicodeString)(PUNICODE_STRING,PCWSTR);
120 static NTSTATUS (WINAPI * pRtlFreeUnicodeString)(PUNICODE_STRING);
121 static NTSTATUS (WINAPI * pNtDeleteValueKey)(IN HANDLE, IN PUNICODE_STRING);
122 static NTSTATUS (WINAPI * pRtlQueryRegistryValues)(IN ULONG, IN PCWSTR,IN PRTL_QUERY_REGISTRY_TABLE, IN PVOID,IN PVOID);
123 static NTSTATUS (WINAPI * pRtlCheckRegistryKey)(IN ULONG,IN PWSTR);
124 static NTSTATUS (WINAPI * pRtlOpenCurrentUser)(IN ACCESS_MASK, PHANDLE);
125 static NTSTATUS (WINAPI * pNtOpenKey)(PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES);
126 static NTSTATUS (WINAPI * pNtOpenKeyEx)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
127 static NTSTATUS (WINAPI * pNtClose)(IN HANDLE);
128 static NTSTATUS (WINAPI * pNtFlushKey)(HANDLE);
129 static NTSTATUS (WINAPI * pNtDeleteKey)(HANDLE);
130 static NTSTATUS (WINAPI * pNtCreateKey)( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
131 ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
132 PULONG dispos );
133 static NTSTATUS (WINAPI * pNtQueryKey)(HANDLE,KEY_INFORMATION_CLASS,PVOID,ULONG,PULONG);
134 static NTSTATUS (WINAPI * pNtQueryLicenseValue)(const UNICODE_STRING *,ULONG *,PVOID,ULONG,ULONG *);
135 static NTSTATUS (WINAPI * pNtQueryValueKey)(HANDLE,const UNICODE_STRING *,KEY_VALUE_INFORMATION_CLASS,void *,DWORD,DWORD *);
136 static NTSTATUS (WINAPI * pNtSetValueKey)(HANDLE, const PUNICODE_STRING, ULONG,
137 ULONG, const void*, ULONG );
138 static NTSTATUS (WINAPI * pNtQueryInformationProcess)(HANDLE,PROCESSINFOCLASS,PVOID,ULONG,PULONG);
139 static NTSTATUS (WINAPI * pRtlFormatCurrentUserKeyPath)(PUNICODE_STRING);
140 static LONG (WINAPI * pRtlCompareUnicodeString)(const PUNICODE_STRING,const PUNICODE_STRING,BOOLEAN);
141 static BOOLEAN (WINAPI * pRtlCreateUnicodeString)(PUNICODE_STRING, LPCWSTR);
142 static LPVOID (WINAPI * pRtlReAllocateHeap)(IN PVOID, IN ULONG, IN PVOID, IN ULONG);
143 static NTSTATUS (WINAPI * pRtlAppendUnicodeToString)(PUNICODE_STRING, PCWSTR);
144 static NTSTATUS (WINAPI * pRtlUnicodeStringToAnsiString)(PSTRING, PUNICODE_STRING, BOOL);
145 static NTSTATUS (WINAPI * pRtlFreeHeap)(PVOID, ULONG, PVOID);
146 static LPVOID (WINAPI * pRtlAllocateHeap)(PVOID,ULONG,ULONG);
147 static NTSTATUS (WINAPI * pRtlZeroMemory)(PVOID, ULONG);
148 static NTSTATUS (WINAPI * pRtlpNtQueryValueKey)(HANDLE,ULONG*,PBYTE,DWORD*,void *);
149 static NTSTATUS (WINAPI * pNtNotifyChangeKey)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,ULONG,BOOLEAN,PVOID,ULONG,BOOLEAN);
150 static NTSTATUS (WINAPI * pNtNotifyChangeMultipleKeys)(HANDLE,ULONG,OBJECT_ATTRIBUTES*,HANDLE,PIO_APC_ROUTINE,
151 void*,IO_STATUS_BLOCK*,ULONG,BOOLEAN,void*,ULONG,BOOLEAN);
152 static NTSTATUS (WINAPI * pNtWaitForSingleObject)(HANDLE,BOOLEAN,const LARGE_INTEGER*);
154 static HMODULE hntdll = 0;
155 static int CurrentTest = 0;
156 static UNICODE_STRING winetestpath;
158 #define NTDLL_GET_PROC(func) \
159 p ## func = (void*)GetProcAddress(hntdll, #func); \
160 if(!p ## func) { \
161 trace("GetProcAddress(%s) failed\n", #func); \
162 FreeLibrary(hntdll); \
163 return FALSE; \
166 static BOOL InitFunctionPtrs(void)
168 hntdll = LoadLibraryA("ntdll.dll");
169 if(!hntdll) {
170 trace("Could not load ntdll.dll\n");
171 return FALSE;
173 NTDLL_GET_PROC(RtlInitUnicodeString)
174 NTDLL_GET_PROC(RtlCreateUnicodeStringFromAsciiz)
175 NTDLL_GET_PROC(RtlCreateUnicodeString)
176 NTDLL_GET_PROC(RtlFreeUnicodeString)
177 NTDLL_GET_PROC(RtlQueryRegistryValues)
178 NTDLL_GET_PROC(RtlCheckRegistryKey)
179 NTDLL_GET_PROC(RtlOpenCurrentUser)
180 NTDLL_GET_PROC(NtClose)
181 NTDLL_GET_PROC(NtDeleteValueKey)
182 NTDLL_GET_PROC(NtCreateKey)
183 NTDLL_GET_PROC(NtFlushKey)
184 NTDLL_GET_PROC(NtDeleteKey)
185 NTDLL_GET_PROC(NtQueryKey)
186 NTDLL_GET_PROC(NtQueryValueKey)
187 NTDLL_GET_PROC(NtQueryInformationProcess)
188 NTDLL_GET_PROC(NtSetValueKey)
189 NTDLL_GET_PROC(NtOpenKey)
190 NTDLL_GET_PROC(NtNotifyChangeKey)
191 NTDLL_GET_PROC(RtlFormatCurrentUserKeyPath)
192 NTDLL_GET_PROC(RtlCompareUnicodeString)
193 NTDLL_GET_PROC(RtlReAllocateHeap)
194 NTDLL_GET_PROC(RtlAppendUnicodeToString)
195 NTDLL_GET_PROC(RtlUnicodeStringToAnsiString)
196 NTDLL_GET_PROC(RtlFreeHeap)
197 NTDLL_GET_PROC(RtlAllocateHeap)
198 NTDLL_GET_PROC(RtlZeroMemory)
199 NTDLL_GET_PROC(RtlpNtQueryValueKey)
200 NTDLL_GET_PROC(RtlOpenCurrentUser)
201 NTDLL_GET_PROC(NtWaitForSingleObject)
203 /* optional functions */
204 pNtQueryLicenseValue = (void *)GetProcAddress(hntdll, "NtQueryLicenseValue");
205 pNtOpenKeyEx = (void *)GetProcAddress(hntdll, "NtOpenKeyEx");
206 pNtNotifyChangeMultipleKeys = (void *)GetProcAddress(hntdll, "NtNotifyChangeMultipleKeys");
208 return TRUE;
210 #undef NTDLL_GET_PROC
212 static NTSTATUS WINAPI QueryRoutine (IN PCWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData,
213 IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
215 NTSTATUS ret = STATUS_SUCCESS;
217 trace("**Test %d**\n", CurrentTest);
218 trace("ValueName: %s\n", wine_dbgstr_w(ValueName));
220 switch(ValueType)
222 case REG_NONE:
223 trace("ValueType: REG_NONE\n");
224 trace("ValueData: %p\n", ValueData);
225 break;
227 case REG_BINARY:
228 trace("ValueType: REG_BINARY\n");
229 trace("ValueData: %p\n", ValueData);
230 break;
232 case REG_SZ:
233 trace("ValueType: REG_SZ\n");
234 trace("ValueData: %s\n", (char*)ValueData);
235 break;
237 case REG_MULTI_SZ:
238 trace("ValueType: REG_MULTI_SZ\n");
239 trace("ValueData: %s\n", (char*)ValueData);
240 break;
242 case REG_EXPAND_SZ:
243 trace("ValueType: REG_EXPAND_SZ\n");
244 trace("ValueData: %s\n", (char*)ValueData);
245 break;
247 case REG_DWORD:
248 trace("ValueType: REG_DWORD\n");
249 trace("ValueData: %p\n", ValueData);
250 break;
252 trace("ValueLength: %d\n", (int)ValueLength);
254 if(CurrentTest == 0)
255 ok(1, "\n"); /*checks that QueryRoutine is called*/
256 if(CurrentTest > 7)
257 ok(!1, "Invalid Test Specified!\n");
259 CurrentTest++;
261 return ret;
264 static void test_RtlQueryRegistryValues(void)
268 ******************************
269 * QueryTable Flags *
270 ******************************
271 *RTL_QUERY_REGISTRY_SUBKEY * Name is the name of a subkey relative to Path
272 *RTL_QUERY_REGISTRY_TOPKEY * Resets location to original RelativeTo and Path
273 *RTL_QUERY_REGISTRY_REQUIRED * Key required. returns STATUS_OBJECT_NAME_NOT_FOUND if not present
274 *RTL_QUERY_REGISTRY_NOVALUE * We just want a call-back
275 *RTL_QUERY_REGISTRY_NOEXPAND * Don't expand the variables!
276 *RTL_QUERY_REGISTRY_DIRECT * Results of query will be stored in EntryContext(QueryRoutine ignored)
277 *RTL_QUERY_REGISTRY_DELETE * Delete value key after query
278 ******************************
281 **Test layout(numbered according to CurrentTest value)**
282 0)NOVALUE Just make sure call-back works
283 1)Null Name See if QueryRoutine is called for every value in current key
284 2)SUBKEY See if we can use SUBKEY to change the current path on the fly
285 3)REQUIRED Test for value that's not there
286 4)NOEXPAND See if it will return multiple strings(no expand should split strings up)
287 5)DIRECT Make it store data directly in EntryContext and not call QueryRoutine
288 6)DefaultType Test return values when key isn't present
289 7)DefaultValue Test Default Value returned with key isn't present(and no REQUIRED flag set)
290 8)DefaultLength Test Default Length with DefaultType = REG_SZ
291 9)DefaultLength Test Default Length with DefaultType = REG_MULTI_SZ
292 10)DefaultLength Test Default Length with DefaultType = REG_EXPAND_SZ
293 11)DefaultData Test whether DefaultData is used while DefaultType = REG_NONE(shouldn't be)
294 12)Delete Try to delete value key
297 NTSTATUS status;
298 ULONG RelativeTo;
300 PRTL_QUERY_REGISTRY_TABLE QueryTable = NULL;
301 RelativeTo = RTL_REGISTRY_ABSOLUTE;/*Only using absolute - no need to test all relativeto variables*/
303 QueryTable = pRtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_QUERY_REGISTRY_TABLE)*26);
305 pRtlZeroMemory( QueryTable, sizeof(RTL_QUERY_REGISTRY_TABLE) * 26);
307 QueryTable[0].QueryRoutine = QueryRoutine;
308 QueryTable[0].Flags = RTL_QUERY_REGISTRY_NOVALUE;
309 QueryTable[0].Name = NULL;
310 QueryTable[0].EntryContext = NULL;
311 QueryTable[0].DefaultType = REG_BINARY;
312 QueryTable[0].DefaultData = NULL;
313 QueryTable[0].DefaultLength = 100;
315 QueryTable[1].QueryRoutine = QueryRoutine;
316 QueryTable[1].Flags = 0;
317 QueryTable[1].Name = NULL;
318 QueryTable[1].EntryContext = 0;
319 QueryTable[1].DefaultType = REG_NONE;
320 QueryTable[1].DefaultData = NULL;
321 QueryTable[1].DefaultLength = 0;
323 QueryTable[2].QueryRoutine = NULL;
324 QueryTable[2].Flags = 0;
325 QueryTable[2].Name = NULL;
326 QueryTable[2].EntryContext = 0;
327 QueryTable[2].DefaultType = REG_NONE;
328 QueryTable[2].DefaultData = NULL;
329 QueryTable[2].DefaultLength = 0;
331 status = pRtlQueryRegistryValues(RelativeTo, winetestpath.Buffer, QueryTable, 0, 0);
332 ok(status == STATUS_SUCCESS, "RtlQueryRegistryValues return: 0x%08x\n", status);
334 pRtlFreeHeap(GetProcessHeap(), 0, QueryTable);
337 static void test_NtOpenKey(void)
339 HANDLE key;
340 NTSTATUS status;
341 OBJECT_ATTRIBUTES attr;
342 ACCESS_MASK am = KEY_READ;
344 /* All NULL */
345 status = pNtOpenKey(NULL, 0, NULL);
346 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
348 /* NULL attributes */
349 status = pNtOpenKey(&key, 0, NULL);
350 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
351 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
353 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
355 /* NULL key */
356 status = pNtOpenKey(NULL, am, &attr);
357 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
359 /* Length > sizeof(OBJECT_ATTRIBUTES) */
360 attr.Length *= 2;
361 status = pNtOpenKey(&key, am, &attr);
362 ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
364 if (!pNtOpenKeyEx)
366 win_skip("NtOpenKeyEx not available\n");
367 return;
370 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
371 status = pNtOpenKeyEx(&key, KEY_WRITE|KEY_READ, &attr, 0);
372 ok(status == STATUS_SUCCESS, "NtOpenKeyEx Failed: 0x%08x\n", status);
374 pNtClose(key);
377 static void test_NtCreateKey(void)
379 /*Create WineTest*/
380 OBJECT_ATTRIBUTES attr;
381 HANDLE key, subkey;
382 ACCESS_MASK am = GENERIC_ALL;
383 NTSTATUS status;
384 UNICODE_STRING str;
386 /* All NULL */
387 status = pNtCreateKey(NULL, 0, NULL, 0, 0, 0, 0);
388 ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER,
389 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
391 /* Only the key */
392 status = pNtCreateKey(&key, 0, NULL, 0, 0, 0, 0);
393 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
394 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
396 /* Only accessmask */
397 status = pNtCreateKey(NULL, am, NULL, 0, 0, 0, 0);
398 ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER,
399 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
401 /* Key and accessmask */
402 status = pNtCreateKey(&key, am, NULL, 0, 0, 0, 0);
403 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
404 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
406 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
408 /* Only attributes */
409 status = pNtCreateKey(NULL, 0, &attr, 0, 0, 0, 0);
410 ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_ACCESS_DENIED /* Win7 */,
411 "Expected STATUS_ACCESS_VIOLATION or STATUS_ACCESS_DENIED, got: 0x%08x\n", status);
413 /* Length > sizeof(OBJECT_ATTRIBUTES) */
414 attr.Length *= 2;
415 status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
416 ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
418 attr.Length = sizeof(attr);
419 status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
420 ok(status == STATUS_SUCCESS, "NtCreateKey Failed: 0x%08x\n", status);
422 attr.RootDirectory = key;
423 attr.ObjectName = &str;
425 pRtlCreateUnicodeStringFromAsciiz( &str, "test\\sub\\key" );
426 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 );
427 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtCreateKey failed: 0x%08x\n", status );
428 pRtlFreeUnicodeString( &str );
430 pRtlCreateUnicodeStringFromAsciiz( &str, "test\\subkey" );
431 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 );
432 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtCreateKey failed: 0x%08x\n", status );
433 pRtlFreeUnicodeString( &str );
435 pRtlCreateUnicodeStringFromAsciiz( &str, "test\\subkey\\" );
436 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 );
437 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtCreateKey failed: 0x%08x\n", status );
438 pRtlFreeUnicodeString( &str );
440 pRtlCreateUnicodeStringFromAsciiz( &str, "test_subkey\\" );
441 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 );
442 ok( status == STATUS_SUCCESS || broken(status == STATUS_OBJECT_NAME_NOT_FOUND), /* nt4 */
443 "NtCreateKey failed: 0x%08x\n", status );
444 if (status == STATUS_SUCCESS)
446 pNtDeleteKey( subkey );
447 pNtClose( subkey );
449 pRtlFreeUnicodeString( &str );
451 pRtlCreateUnicodeStringFromAsciiz( &str, "test_subkey" );
452 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 );
453 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
454 pRtlFreeUnicodeString( &str );
455 pNtDeleteKey( subkey );
456 pNtClose( subkey );
458 pNtClose(key);
461 static void test_NtSetValueKey(void)
463 HANDLE key;
464 NTSTATUS status;
465 OBJECT_ATTRIBUTES attr;
466 ACCESS_MASK am = KEY_WRITE;
467 UNICODE_STRING ValName;
468 DWORD data = 711;
470 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
471 status = pNtOpenKey(&key, am, &attr);
472 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
474 pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
475 status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &data, sizeof(data));
476 ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status);
477 pRtlFreeUnicodeString(&ValName);
479 pRtlCreateUnicodeStringFromAsciiz(&ValName, "stringtest");
480 status = pNtSetValueKey(key, &ValName, 0, REG_SZ, (VOID*)stringW, STR_TRUNC_SIZE);
481 ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status);
482 pRtlFreeUnicodeString(&ValName);
484 pNtClose(key);
487 static void test_RtlOpenCurrentUser(void)
489 NTSTATUS status;
490 HANDLE handle;
491 status=pRtlOpenCurrentUser(KEY_READ, &handle);
492 ok(status == STATUS_SUCCESS, "RtlOpenCurrentUser Failed: 0x%08x\n", status);
493 pNtClose(handle);
496 static void test_RtlCheckRegistryKey(void)
498 NTSTATUS status;
500 status = pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, winetestpath.Buffer);
501 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08x\n", status);
503 status = pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL), winetestpath.Buffer);
504 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE and RTL_REGISTRY_OPTIONAL: 0x%08x\n", status);
507 static void test_NtFlushKey(void)
509 NTSTATUS status;
510 HANDLE hkey;
511 OBJECT_ATTRIBUTES attr;
512 ACCESS_MASK am = KEY_ALL_ACCESS;
514 status = pNtFlushKey(NULL);
515 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
517 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
518 pNtOpenKey(&hkey, am, &attr);
520 status = pNtFlushKey(hkey);
521 ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
523 pNtClose(hkey);
526 static void test_NtQueryValueKey(void)
528 HANDLE key;
529 NTSTATUS status;
530 OBJECT_ATTRIBUTES attr;
531 UNICODE_STRING ValName;
532 KEY_VALUE_BASIC_INFORMATION *basic_info;
533 KEY_VALUE_PARTIAL_INFORMATION *partial_info, pi;
534 KEY_VALUE_FULL_INFORMATION *full_info;
535 DWORD len, expected;
537 pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
539 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
540 status = pNtOpenKey(&key, KEY_READ|KEY_SET_VALUE, &attr);
541 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
543 len = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]);
544 basic_info = HeapAlloc(GetProcessHeap(), 0, len);
545 status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, basic_info, len, &len);
546 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
547 ok(basic_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info->TitleIndex);
548 ok(basic_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", basic_info->Type);
549 ok(basic_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info->NameLength);
550 ok(len == FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[basic_info->NameLength/sizeof(WCHAR)]), "NtQueryValueKey returned wrong len %d\n", len);
552 basic_info = HeapReAlloc(GetProcessHeap(), 0, basic_info, len);
553 status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, basic_info, len, &len);
554 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
555 ok(basic_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info->TitleIndex);
556 ok(basic_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", basic_info->Type);
557 ok(basic_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info->NameLength);
558 ok(len == FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[basic_info->NameLength/sizeof(WCHAR)]), "NtQueryValueKey returned wrong len %d\n", len);
559 ok(!memcmp(basic_info->Name, ValName.Buffer, ValName.Length), "incorrect Name returned\n");
560 HeapFree(GetProcessHeap(), 0, basic_info);
562 len = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
563 partial_info = HeapAlloc(GetProcessHeap(), 0, len);
564 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
565 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
566 ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->TitleIndex);
567 ok(partial_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type);
568 ok(partial_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength);
569 ok(len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[partial_info->DataLength]), "NtQueryValueKey returned wrong len %d\n", len);
571 partial_info = HeapReAlloc(GetProcessHeap(), 0, partial_info, len);
572 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
573 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
574 ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->TitleIndex);
575 ok(partial_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type);
576 ok(partial_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength);
577 ok(len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[partial_info->DataLength]), "NtQueryValueKey returned wrong len %d\n", len);
578 ok(*(DWORD *)partial_info->Data == 711, "incorrect Data returned: 0x%x\n", *(DWORD *)partial_info->Data);
579 HeapFree(GetProcessHeap(), 0, partial_info);
581 len = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]);
582 full_info = HeapAlloc(GetProcessHeap(), 0, len);
583 status = pNtQueryValueKey(key, &ValName, KeyValueFullInformation, full_info, len, &len);
584 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
585 ok(full_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info->TitleIndex);
586 ok(full_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", full_info->Type);
587 ok(full_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info->DataLength);
588 ok(full_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info->NameLength);
589 ok(len == FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) + full_info->DataLength + full_info->NameLength,
590 "NtQueryValueKey returned wrong len %d\n", len);
591 len = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) + full_info->DataLength + full_info->NameLength;
593 full_info = HeapReAlloc(GetProcessHeap(), 0, full_info, len);
594 status = pNtQueryValueKey(key, &ValName, KeyValueFullInformation, full_info, len, &len);
595 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
596 ok(full_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info->TitleIndex);
597 ok(full_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", full_info->Type);
598 ok(full_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info->DataLength);
599 ok(full_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info->NameLength);
600 ok(!memcmp(full_info->Name, ValName.Buffer, ValName.Length), "incorrect Name returned\n");
601 ok(*(DWORD *)((char *)full_info + full_info->DataOffset) == 711, "incorrect Data returned: 0x%x\n",
602 *(DWORD *)((char *)full_info + full_info->DataOffset));
603 HeapFree(GetProcessHeap(), 0, full_info);
605 pRtlFreeUnicodeString(&ValName);
606 pRtlCreateUnicodeStringFromAsciiz(&ValName, "stringtest");
608 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, NULL, 0, &len);
609 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey should have returned STATUS_BUFFER_TOO_SMALL instead of 0x%08x\n", status);
610 partial_info = HeapAlloc(GetProcessHeap(), 0, len+1);
611 memset(partial_info, 0xbd, len+1);
612 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
613 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
614 ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->TitleIndex);
615 ok(partial_info->Type == REG_SZ, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type);
616 ok(partial_info->DataLength == STR_TRUNC_SIZE, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength);
617 ok(!memcmp(partial_info->Data, stringW, STR_TRUNC_SIZE), "incorrect Data returned\n");
618 ok(*(partial_info->Data+STR_TRUNC_SIZE) == 0xbd, "string overflowed %02x\n", *(partial_info->Data+STR_TRUNC_SIZE));
620 expected = len;
621 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, 0, &len);
622 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey wrong status 0x%08x\n", status);
623 ok(len == expected, "NtQueryValueKey wrong len %u\n", len);
624 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, 1, &len);
625 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey wrong status 0x%08x\n", status);
626 ok(len == expected, "NtQueryValueKey wrong len %u\n", len);
627 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) - 1, &len);
628 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey wrong status 0x%08x\n", status);
629 ok(len == expected, "NtQueryValueKey wrong len %u\n", len);
630 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data), &len);
631 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey wrong status 0x%08x\n", status);
632 ok(len == expected, "NtQueryValueKey wrong len %u\n", len);
634 HeapFree(GetProcessHeap(), 0, partial_info);
635 pRtlFreeUnicodeString(&ValName);
637 pRtlCreateUnicodeStringFromAsciiz(&ValName, "custtest");
638 status = pNtSetValueKey(key, &ValName, 0, 0xff00ff00, NULL, 0);
639 ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status);
641 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, &pi, sizeof(pi), &len);
642 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_BUFFER_TOO_SMALL instead of 0x%08x\n", status);
643 ok(pi.Type == 0xff00ff00, "Type=%x\n", pi.Type);
644 ok(pi.DataLength == 0, "DataLength=%u\n", pi.DataLength);
645 pRtlFreeUnicodeString(&ValName);
647 pNtClose(key);
650 static void test_NtDeleteKey(void)
652 NTSTATUS status;
653 HANDLE hkey;
654 OBJECT_ATTRIBUTES attr;
655 ACCESS_MASK am = KEY_ALL_ACCESS;
657 status = pNtDeleteKey(NULL);
658 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
660 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
661 status = pNtOpenKey(&hkey, am, &attr);
662 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
664 status = pNtDeleteKey(hkey);
665 ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
668 static void test_NtQueryLicenseKey(void)
670 static const WCHAR emptyW[] = {'E','M','P','T','Y',0};
671 UNICODE_STRING name;
672 WORD buffer[32];
673 NTSTATUS status;
674 ULONG type, len;
675 DWORD value;
677 if (!pNtQueryLicenseValue)
679 win_skip("NtQueryLicenseValue not found, skipping tests\n");
680 return;
683 type = 0xdead;
684 len = 0xbeef;
685 memset(&name, 0, sizeof(name));
686 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), &len);
687 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
688 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
689 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
691 /* test with empty key */
692 pRtlCreateUnicodeStringFromAsciiz(&name, "");
694 type = 0xdead;
695 len = 0xbeef;
696 status = pNtQueryLicenseValue(NULL, &type, buffer, sizeof(buffer), &len);
697 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
698 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
699 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
701 type = 0xdead;
702 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), NULL);
703 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
704 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
706 len = 0xbeef;
707 status = pNtQueryLicenseValue(&name, NULL, buffer, sizeof(buffer), &len);
708 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
709 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
711 type = 0xdead;
712 len = 0xbeef;
713 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), &len);
714 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
715 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
716 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
718 pRtlFreeUnicodeString(&name);
720 /* test with nonexistent licence key */
721 pRtlCreateUnicodeStringFromAsciiz(&name, "Nonexistent-License-Value");
723 type = 0xdead;
724 len = 0xbeef;
725 status = pNtQueryLicenseValue(NULL, &type, buffer, sizeof(buffer), &len);
726 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
727 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
728 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
730 type = 0xdead;
731 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), NULL);
732 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
733 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
735 len = 0xbeef;
736 status = pNtQueryLicenseValue(&name, NULL, buffer, sizeof(buffer), &len);
737 ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryLicenseValue returned %08x, expected STATUS_OBJECT_NAME_NOT_FOUND\n", status);
738 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
740 type = 0xdead;
741 len = 0xbeef;
742 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), &len);
743 ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryLicenseValue unexpected succeeded\n");
744 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
745 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
747 pRtlFreeUnicodeString(&name);
749 /* test with REG_SZ license key */
750 pRtlCreateUnicodeStringFromAsciiz(&name, "Kernel-MUI-Language-Allowed");
752 type = 0xdead;
753 len = 0xbeef;
754 status = pNtQueryLicenseValue(NULL, &type, buffer, sizeof(buffer), &len);
755 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
756 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
757 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
759 type = 0xdead;
760 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), NULL);
761 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
762 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
764 type = 0xdead;
765 len = 0;
766 status = pNtQueryLicenseValue(&name, &type, buffer, 0, &len);
767 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status);
768 ok(type == REG_SZ, "expected type = REG_SZ, got %u\n", type);
769 ok(len == sizeof(emptyW), "expected len = %u, got %u\n", (DWORD)sizeof(emptyW), len);
771 len = 0;
772 status = pNtQueryLicenseValue(&name, NULL, buffer, 0, &len);
773 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status);
774 ok(len == sizeof(emptyW), "expected len = %u, got %u\n", (DWORD)sizeof(emptyW), len);
776 type = 0xdead;
777 len = 0;
778 memset(buffer, 0x11, sizeof(buffer));
779 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), &len);
780 ok(status == STATUS_SUCCESS, "NtQueryLicenseValue returned %08x, expected STATUS_SUCCESS\n", status);
781 ok(type == REG_SZ, "expected type = REG_SZ, got %u\n", type);
782 ok(len == sizeof(emptyW), "expected len = %u, got %u\n", (DWORD)sizeof(emptyW), len);
783 ok(!memcmp(buffer, emptyW, sizeof(emptyW)), "unexpected buffer content\n");
785 type = 0xdead;
786 len = 0;
787 memset(buffer, 0x11, sizeof(buffer));
788 status = pNtQueryLicenseValue(&name, &type, buffer, 2, &len);
789 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status);
790 ok(type == REG_SZ, "expected type REG_SZ, got %u\n", type);
791 ok(len == sizeof(emptyW), "expected len = %u, got %u\n", (DWORD)sizeof(emptyW), len);
792 ok(buffer[0] == 0x1111, "expected buffer[0] = 0x1111, got %u\n", buffer[0]);
794 pRtlFreeUnicodeString(&name);
796 /* test with REG_DWORD license key */
797 pRtlCreateUnicodeStringFromAsciiz(&name, "Kernel-MUI-Number-Allowed");
799 type = 0xdead;
800 len = 0xbeef;
801 status = pNtQueryLicenseValue(NULL, &type, &value, sizeof(value), &len);
802 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
803 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
804 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
806 type = 0xdead;
807 status = pNtQueryLicenseValue(&name, &type, &value, sizeof(value), NULL);
808 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
809 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
811 type = 0xdead;
812 len = 0;
813 status = pNtQueryLicenseValue(&name, &type, &value, 0, &len);
814 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status);
815 ok(type == REG_DWORD, "expected type = REG_DWORD, got %u\n", type);
816 ok(len == sizeof(value), "expected len = %u, got %u\n", (DWORD)sizeof(value), len);
818 len = 0;
819 status = pNtQueryLicenseValue(&name, NULL, &value, 0, &len);
820 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status);
821 ok(len == sizeof(value), "expected len = %u, got %u\n", (DWORD)sizeof(value), len);
823 type = 0xdead;
824 len = 0;
825 value = 0xdeadbeef;
826 status = pNtQueryLicenseValue(&name, &type, &value, sizeof(value), &len);
827 ok(status == STATUS_SUCCESS, "NtQueryLicenseValue returned %08x, expected STATUS_SUCCESS\n", status);
828 ok(type == REG_DWORD, "expected type = REG_DWORD, got %u\n", type);
829 ok(len == sizeof(value), "expected len = %u, got %u\n", (DWORD)sizeof(value), len);
830 ok(value != 0xdeadbeef, "expected value != 0xdeadbeef\n");
832 type = 0xdead;
833 len = 0;
834 status = pNtQueryLicenseValue(&name, &type, &value, 2, &len);
835 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status);
836 ok(type == REG_DWORD, "expected type REG_DWORD, got %u\n", type);
837 ok(len == sizeof(value), "expected len = %u, got %u\n", (DWORD)sizeof(value), len);
839 pRtlFreeUnicodeString(&name);
842 static void test_RtlpNtQueryValueKey(void)
844 NTSTATUS status;
846 status = pRtlpNtQueryValueKey(NULL, NULL, NULL, NULL, NULL);
847 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
850 static void test_symlinks(void)
852 static const WCHAR linkW[] = {'l','i','n','k',0};
853 static const WCHAR valueW[] = {'v','a','l','u','e',0};
854 static const WCHAR symlinkW[] = {'S','y','m','b','o','l','i','c','L','i','n','k','V','a','l','u','e',0};
855 static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0};
856 static UNICODE_STRING null_str;
857 char buffer[1024];
858 KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
859 WCHAR *target;
860 UNICODE_STRING symlink_str, link_str, target_str, value_str;
861 HANDLE root, key, link;
862 OBJECT_ATTRIBUTES attr;
863 NTSTATUS status;
864 DWORD target_len, len, dw;
866 pRtlInitUnicodeString( &link_str, linkW );
867 pRtlInitUnicodeString( &symlink_str, symlinkW );
868 pRtlInitUnicodeString( &target_str, targetW + 1 );
869 pRtlInitUnicodeString( &value_str, valueW );
871 target_len = winetestpath.Length + sizeof(targetW);
872 target = pRtlAllocateHeap( GetProcessHeap(), 0, target_len + sizeof(targetW) /*for loop test*/ );
873 memcpy( target, winetestpath.Buffer, winetestpath.Length );
874 memcpy( target + winetestpath.Length/sizeof(WCHAR), targetW, sizeof(targetW) );
876 attr.Length = sizeof(attr);
877 attr.RootDirectory = 0;
878 attr.Attributes = 0;
879 attr.ObjectName = &winetestpath;
880 attr.SecurityDescriptor = NULL;
881 attr.SecurityQualityOfService = NULL;
883 status = pNtCreateKey( &root, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
884 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
886 attr.RootDirectory = root;
887 attr.ObjectName = &link_str;
888 status = pNtCreateKey( &link, KEY_ALL_ACCESS, &attr, 0, 0, REG_OPTION_CREATE_LINK, 0 );
889 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
891 /* REG_SZ is not allowed */
892 status = pNtSetValueKey( link, &symlink_str, 0, REG_SZ, target, target_len );
893 ok( status == STATUS_ACCESS_DENIED, "NtSetValueKey wrong status 0x%08x\n", status );
894 status = pNtSetValueKey( link, &symlink_str, 0, REG_LINK, target, target_len - sizeof(WCHAR) );
895 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
896 /* other values are not allowed */
897 status = pNtSetValueKey( link, &link_str, 0, REG_LINK, target, target_len - sizeof(WCHAR) );
898 ok( status == STATUS_ACCESS_DENIED, "NtSetValueKey wrong status 0x%08x\n", status );
900 /* try opening the target through the link */
902 attr.ObjectName = &link_str;
903 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
904 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey wrong status 0x%08x\n", status );
906 attr.ObjectName = &target_str;
907 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
908 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
910 dw = 0xbeef;
911 status = pNtSetValueKey( key, &value_str, 0, REG_DWORD, &dw, sizeof(dw) );
912 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
913 pNtClose( key );
915 attr.ObjectName = &link_str;
916 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
917 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status );
919 len = sizeof(buffer);
920 status = pNtQueryValueKey( key, &value_str, KeyValuePartialInformation, info, len, &len );
921 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
922 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + sizeof(DWORD), "wrong len %u\n", len );
924 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
925 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status );
927 /* REG_LINK can be created in non-link keys */
928 status = pNtSetValueKey( key, &symlink_str, 0, REG_LINK, target, target_len - sizeof(WCHAR) );
929 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
930 len = sizeof(buffer);
931 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
932 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
933 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR),
934 "wrong len %u\n", len );
935 status = pNtDeleteValueKey( key, &symlink_str );
936 ok( status == STATUS_SUCCESS, "NtDeleteValueKey failed: 0x%08x\n", status );
938 pNtClose( key );
940 attr.Attributes = 0;
941 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
942 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
944 len = sizeof(buffer);
945 status = pNtQueryValueKey( key, &value_str, KeyValuePartialInformation, info, len, &len );
946 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
947 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + sizeof(DWORD), "wrong len %u\n", len );
949 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
950 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status );
951 pNtClose( key );
953 /* now open the symlink itself */
955 attr.RootDirectory = root;
956 attr.Attributes = OBJ_OPENLINK;
957 attr.ObjectName = &link_str;
958 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
959 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status );
961 len = sizeof(buffer);
962 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
963 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
964 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR),
965 "wrong len %u\n", len );
966 pNtClose( key );
968 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
969 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
970 len = sizeof(buffer);
971 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
972 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
973 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR),
974 "wrong len %u\n", len );
975 pNtClose( key );
977 if (0) /* crashes the Windows kernel on some Vista systems */
979 /* reopen the link from itself */
981 attr.RootDirectory = link;
982 attr.Attributes = OBJ_OPENLINK;
983 attr.ObjectName = &null_str;
984 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
985 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status );
986 len = sizeof(buffer);
987 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
988 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
989 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR),
990 "wrong len %u\n", len );
991 pNtClose( key );
993 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
994 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
995 len = sizeof(buffer);
996 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
997 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
998 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR),
999 "wrong len %u\n", len );
1000 pNtClose( key );
1003 if (0) /* crashes the Windows kernel in most versions */
1005 attr.RootDirectory = link;
1006 attr.Attributes = 0;
1007 attr.ObjectName = &null_str;
1008 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
1009 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status );
1010 len = sizeof(buffer);
1011 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
1012 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status );
1013 pNtClose( key );
1015 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1016 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1017 len = sizeof(buffer);
1018 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
1019 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status );
1020 pNtClose( key );
1023 /* target with terminating null doesn't work */
1024 status = pNtSetValueKey( link, &symlink_str, 0, REG_LINK, target, target_len );
1025 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
1026 attr.RootDirectory = root;
1027 attr.Attributes = 0;
1028 attr.ObjectName = &link_str;
1029 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
1030 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey wrong status 0x%08x\n", status );
1032 /* relative symlink, works only on win2k */
1033 status = pNtSetValueKey( link, &symlink_str, 0, REG_LINK, targetW+1, sizeof(targetW)-2*sizeof(WCHAR) );
1034 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
1035 attr.ObjectName = &link_str;
1036 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
1037 ok( status == STATUS_SUCCESS || status == STATUS_OBJECT_NAME_NOT_FOUND,
1038 "NtOpenKey wrong status 0x%08x\n", status );
1040 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, REG_OPTION_CREATE_LINK, 0 );
1041 ok( status == STATUS_OBJECT_NAME_COLLISION, "NtCreateKey failed: 0x%08x\n", status );
1043 status = pNtDeleteKey( link );
1044 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status );
1045 pNtClose( link );
1047 attr.ObjectName = &target_str;
1048 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
1049 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status );
1050 status = pNtDeleteKey( key );
1051 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status );
1052 pNtClose( key );
1054 /* symlink loop */
1056 status = pNtCreateKey( &link, KEY_ALL_ACCESS, &attr, 0, 0, REG_OPTION_CREATE_LINK, 0 );
1057 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1058 memcpy( target + target_len/sizeof(WCHAR) - 1, targetW, sizeof(targetW) );
1059 status = pNtSetValueKey( link, &symlink_str, 0, REG_LINK,
1060 target, target_len + sizeof(targetW) - sizeof(WCHAR) );
1061 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
1063 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
1064 ok( status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_NAME_TOO_LONG,
1065 "NtOpenKey failed: 0x%08x\n", status );
1067 attr.Attributes = OBJ_OPENLINK;
1068 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
1069 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status );
1070 pNtClose( key );
1072 status = pNtDeleteKey( link );
1073 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status );
1074 pNtClose( link );
1076 status = pNtDeleteKey( root );
1077 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status );
1078 pNtClose( root );
1080 pRtlFreeHeap(GetProcessHeap(), 0, target);
1083 static WCHAR valueW[] = {'v','a','l','u','e'};
1084 static UNICODE_STRING value_str = { sizeof(valueW), sizeof(valueW), valueW };
1085 static const DWORD ptr_size = 8 * sizeof(void*);
1087 static DWORD get_key_value( HANDLE root, const char *name, DWORD flags )
1089 char tmp[32];
1090 NTSTATUS status;
1091 OBJECT_ATTRIBUTES attr;
1092 UNICODE_STRING str;
1093 HANDLE key;
1094 KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)tmp;
1095 DWORD dw, len = sizeof(tmp);
1097 attr.Length = sizeof(attr);
1098 attr.RootDirectory = root;
1099 attr.Attributes = OBJ_CASE_INSENSITIVE;
1100 attr.ObjectName = &str;
1101 attr.SecurityDescriptor = NULL;
1102 attr.SecurityQualityOfService = NULL;
1103 pRtlCreateUnicodeStringFromAsciiz( &str, name );
1105 status = pNtCreateKey( &key, flags | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1106 if (status == STATUS_OBJECT_NAME_NOT_FOUND) return 0;
1107 ok( status == STATUS_SUCCESS, "%08x: NtCreateKey failed: 0x%08x\n", flags, status );
1109 status = pNtQueryValueKey( key, &value_str, KeyValuePartialInformation, info, len, &len );
1110 if (status == STATUS_OBJECT_NAME_NOT_FOUND)
1111 dw = 0;
1112 else
1114 ok( status == STATUS_SUCCESS, "%08x: NtQueryValueKey failed: 0x%08x\n", flags, status );
1115 dw = *(DWORD *)info->Data;
1117 pNtClose( key );
1118 pRtlFreeUnicodeString( &str );
1119 return dw;
1122 static void _check_key_value( int line, HANDLE root, const char *name, DWORD flags, DWORD expect )
1124 DWORD dw = get_key_value( root, name, flags );
1125 ok_(__FILE__,line)( dw == expect, "%08x: wrong value %u/%u\n", flags, dw, expect );
1127 #define check_key_value(root,name,flags,expect) _check_key_value( __LINE__, root, name, flags, expect )
1129 static void test_redirection(void)
1131 static const WCHAR softwareW[] = {'\\','R','e','g','i','s','t','r','y','\\',
1132 'M','a','c','h','i','n','e','\\',
1133 'S','o','f','t','w','a','r','e',0};
1134 static const WCHAR wownodeW[] = {'\\','R','e','g','i','s','t','r','y','\\',
1135 'M','a','c','h','i','n','e','\\',
1136 'S','o','f','t','w','a','r','e','\\',
1137 'W','o','w','6','4','3','2','N','o','d','e',0};
1138 static const WCHAR wine64W[] = {'\\','R','e','g','i','s','t','r','y','\\',
1139 'M','a','c','h','i','n','e','\\',
1140 'S','o','f','t','w','a','r','e','\\',
1141 'W','i','n','e',0};
1142 static const WCHAR wine32W[] = {'\\','R','e','g','i','s','t','r','y','\\',
1143 'M','a','c','h','i','n','e','\\',
1144 'S','o','f','t','w','a','r','e','\\',
1145 'W','o','w','6','4','3','2','N','o','d','e','\\',
1146 'W','i','n','e',0};
1147 static const WCHAR key64W[] = {'\\','R','e','g','i','s','t','r','y','\\',
1148 'M','a','c','h','i','n','e','\\',
1149 'S','o','f','t','w','a','r','e','\\',
1150 'W','i','n','e','\\','W','i','n','e','t','e','s','t',0};
1151 static const WCHAR key32W[] = {'\\','R','e','g','i','s','t','r','y','\\',
1152 'M','a','c','h','i','n','e','\\',
1153 'S','o','f','t','w','a','r','e','\\',
1154 'W','o','w','6','4','3','2','N','o','d','e','\\',
1155 'W','i','n','e','\\', 'W','i','n','e','t','e','s','t',0};
1156 static const WCHAR classes64W[] = {'\\','R','e','g','i','s','t','r','y','\\',
1157 'M','a','c','h','i','n','e','\\',
1158 'S','o','f','t','w','a','r','e','\\',
1159 'C','l','a','s','s','e','s','\\',
1160 'W','i','n','e',0};
1161 static const WCHAR classes32W[] = {'\\','R','e','g','i','s','t','r','y','\\',
1162 'M','a','c','h','i','n','e','\\',
1163 'S','o','f','t','w','a','r','e','\\',
1164 'C','l','a','s','s','e','s','\\',
1165 'W','o','w','6','4','3','2','N','o','d','e','\\',
1166 'W','i','n','e',0};
1167 NTSTATUS status;
1168 OBJECT_ATTRIBUTES attr;
1169 UNICODE_STRING str;
1170 char buffer[1024];
1171 KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
1172 DWORD dw, len;
1173 HANDLE key, root32, root64, key32, key64;
1174 BOOL is_vista = FALSE;
1176 if (ptr_size != 64)
1178 ULONG is_wow64, len;
1179 if (pNtQueryInformationProcess( GetCurrentProcess(), ProcessWow64Information,
1180 &is_wow64, sizeof(is_wow64), &len ) ||
1181 !is_wow64)
1183 trace( "Not on Wow64, no redirection\n" );
1184 return;
1188 attr.Length = sizeof(attr);
1189 attr.RootDirectory = 0;
1190 attr.Attributes = OBJ_CASE_INSENSITIVE;
1191 attr.ObjectName = &str;
1192 attr.SecurityDescriptor = NULL;
1193 attr.SecurityQualityOfService = NULL;
1195 pRtlInitUnicodeString( &str, wine64W );
1196 status = pNtCreateKey( &root64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1197 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1199 pRtlInitUnicodeString( &str, wine32W );
1200 status = pNtCreateKey( &root32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1201 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1203 pRtlInitUnicodeString( &str, key64W );
1204 status = pNtCreateKey( &key64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1205 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1207 pRtlInitUnicodeString( &str, key32W );
1208 status = pNtCreateKey( &key32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1209 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1211 dw = 64;
1212 status = pNtSetValueKey( key64, &value_str, 0, REG_DWORD, &dw, sizeof(dw) );
1213 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
1215 dw = 32;
1216 status = pNtSetValueKey( key32, &value_str, 0, REG_DWORD, &dw, sizeof(dw) );
1217 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
1219 len = sizeof(buffer);
1220 status = pNtQueryValueKey( key32, &value_str, KeyValuePartialInformation, info, len, &len );
1221 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
1222 dw = *(DWORD *)info->Data;
1223 ok( dw == 32, "wrong value %u\n", dw );
1225 len = sizeof(buffer);
1226 status = pNtQueryValueKey( key64, &value_str, KeyValuePartialInformation, info, len, &len );
1227 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
1228 dw = *(DWORD *)info->Data;
1229 ok( dw == 64, "wrong value %u\n", dw );
1231 pRtlInitUnicodeString( &str, softwareW );
1232 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1233 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1235 if (ptr_size == 32)
1237 /* the Vista mechanism allows opening Wow6432Node from a 32-bit key too */
1238 /* the new (and simpler) Win7 mechanism doesn't */
1239 if (get_key_value( key, "Wow6432Node\\Wine\\Winetest", 0 ) == 32)
1241 trace( "using Vista-style Wow6432Node handling\n" );
1242 is_vista = TRUE;
1244 check_key_value( key, "Wine\\Winetest", 0, 32 );
1245 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
1246 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1247 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, is_vista ? 32 : 0 );
1248 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 0 );
1249 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, is_vista ? 32 : 0 );
1251 else
1253 check_key_value( key, "Wine\\Winetest", 0, 64 );
1254 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, 32 );
1256 pNtClose( key );
1258 if (ptr_size == 32)
1260 status = pNtCreateKey( &key, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1261 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1262 dw = get_key_value( key, "Wine\\Winetest", 0 );
1263 ok( dw == 64 || broken(dw == 32) /* xp64 */, "wrong value %u\n", dw );
1264 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, 64 );
1265 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1266 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, 32 );
1267 dw = get_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY );
1268 ok( dw == 32 || broken(dw == 64) /* xp64 */, "wrong value %u\n", dw );
1269 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1270 pNtClose( key );
1272 status = pNtCreateKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1273 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1274 check_key_value( key, "Wine\\Winetest", 0, 32 );
1275 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
1276 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1277 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, is_vista ? 32 : 0 );
1278 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 0 );
1279 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, is_vista ? 32 : 0 );
1280 pNtClose( key );
1283 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", 0, ptr_size );
1284 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", 0, 32 );
1285 if (ptr_size == 64)
1287 /* KEY_WOW64 flags have no effect on 64-bit */
1288 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_64KEY, 64 );
1289 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_32KEY, 64 );
1290 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, 32 );
1291 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1293 else
1295 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_64KEY, 64 );
1296 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1297 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
1298 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1301 pRtlInitUnicodeString( &str, wownodeW );
1302 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1303 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1304 check_key_value( key, "Wine\\Winetest", 0, 32 );
1305 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, (ptr_size == 64) ? 32 : (is_vista ? 64 : 32) );
1306 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1307 pNtClose( key );
1309 if (ptr_size == 32)
1311 status = pNtCreateKey( &key, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1312 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1313 dw = get_key_value( key, "Wine\\Winetest", 0 );
1314 ok( dw == (is_vista ? 64 : 32) || broken(dw == 32) /* xp64 */, "wrong value %u\n", dw );
1315 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
1316 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1317 pNtClose( key );
1319 status = pNtCreateKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1320 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1321 check_key_value( key, "Wine\\Winetest", 0, 32 );
1322 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
1323 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1324 pNtClose( key );
1327 pRtlInitUnicodeString( &str, wine32W );
1328 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1329 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1330 check_key_value( key, "Winetest", 0, 32 );
1331 check_key_value( key, "Winetest", KEY_WOW64_64KEY, (ptr_size == 32 && is_vista) ? 64 : 32 );
1332 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
1333 pNtClose( key );
1335 if (ptr_size == 32)
1337 status = pNtCreateKey( &key, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1338 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1339 dw = get_key_value( key, "Winetest", 0 );
1340 ok( dw == 32 || (is_vista && dw == 64), "wrong value %u\n", dw );
1341 check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
1342 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
1343 pNtClose( key );
1345 status = pNtCreateKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1346 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1347 check_key_value( key, "Winetest", 0, 32 );
1348 check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
1349 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
1350 pNtClose( key );
1353 pRtlInitUnicodeString( &str, wine64W );
1354 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1355 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1356 check_key_value( key, "Winetest", 0, ptr_size );
1357 check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : ptr_size );
1358 check_key_value( key, "Winetest", KEY_WOW64_32KEY, ptr_size );
1359 pNtClose( key );
1361 if (ptr_size == 32)
1363 status = pNtCreateKey( &key, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1364 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1365 dw = get_key_value( key, "Winetest", 0 );
1366 ok( dw == 64 || broken(dw == 32) /* xp64 */, "wrong value %u\n", dw );
1367 check_key_value( key, "Winetest", KEY_WOW64_64KEY, 64 );
1368 dw = get_key_value( key, "Winetest", KEY_WOW64_32KEY );
1369 todo_wine ok( dw == 32, "wrong value %u\n", dw );
1370 pNtClose( key );
1372 status = pNtCreateKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1373 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1374 check_key_value( key, "Winetest", 0, 32 );
1375 check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
1376 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
1377 pNtClose( key );
1380 status = pNtDeleteKey( key32 );
1381 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status );
1382 pNtClose( key32 );
1384 status = pNtDeleteKey( key64 );
1385 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status );
1386 pNtClose( key64 );
1388 pNtDeleteKey( root32 );
1389 pNtClose( root32 );
1390 pNtDeleteKey( root64 );
1391 pNtClose( root64 );
1393 /* Software\Classes is shared/reflected so behavior is different */
1395 pRtlInitUnicodeString( &str, classes64W );
1396 status = pNtCreateKey( &key64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1397 if (status == STATUS_ACCESS_DENIED)
1399 skip("Not authorized to modify the Classes key\n");
1400 return;
1402 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1404 pRtlInitUnicodeString( &str, classes32W );
1405 status = pNtCreateKey( &key32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1406 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1408 dw = 64;
1409 status = pNtSetValueKey( key64, &value_str, 0, REG_DWORD, &dw, sizeof(dw) );
1410 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
1411 pNtClose( key64 );
1413 dw = 32;
1414 status = pNtSetValueKey( key32, &value_str, 0, REG_DWORD, &dw, sizeof(dw) );
1415 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
1416 pNtClose( key32 );
1418 pRtlInitUnicodeString( &str, classes64W );
1419 status = pNtCreateKey( &key64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1420 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1421 len = sizeof(buffer);
1422 status = pNtQueryValueKey( key64, &value_str, KeyValuePartialInformation, info, len, &len );
1423 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
1424 dw = *(DWORD *)info->Data;
1425 ok( dw == ptr_size, "wrong value %u\n", dw );
1427 pRtlInitUnicodeString( &str, classes32W );
1428 status = pNtCreateKey( &key32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1429 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1430 len = sizeof(buffer);
1431 status = pNtQueryValueKey( key32, &value_str, KeyValuePartialInformation, info, len, &len );
1432 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
1433 dw = *(DWORD *)info->Data;
1434 ok( dw == 32, "wrong value %u\n", dw );
1436 pNtDeleteKey( key32 );
1437 pNtClose( key32 );
1438 pNtDeleteKey( key64 );
1439 pNtClose( key64 );
1442 static void test_long_value_name(void)
1444 HANDLE key;
1445 NTSTATUS status, expected;
1446 OBJECT_ATTRIBUTES attr;
1447 UNICODE_STRING ValName;
1448 DWORD i;
1450 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
1451 status = pNtOpenKey(&key, KEY_WRITE|KEY_READ, &attr);
1452 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
1454 ValName.MaximumLength = 0xfffc;
1455 ValName.Length = ValName.MaximumLength - sizeof(WCHAR);
1456 ValName.Buffer = HeapAlloc(GetProcessHeap(), 0, ValName.MaximumLength);
1457 for (i = 0; i < ValName.Length / sizeof(WCHAR); i++)
1458 ValName.Buffer[i] = 'a';
1459 ValName.Buffer[i] = 0;
1461 status = pNtDeleteValueKey(key, &ValName);
1462 ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "NtDeleteValueKey with nonexistent long value name returned 0x%08x\n", status);
1463 status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &i, sizeof(i));
1464 ok(status == STATUS_INVALID_PARAMETER || broken(status == STATUS_SUCCESS) /* nt4 */,
1465 "NtSetValueKey with long value name returned 0x%08x\n", status);
1466 expected = (status == STATUS_SUCCESS) ? STATUS_SUCCESS : STATUS_OBJECT_NAME_NOT_FOUND;
1467 status = pNtDeleteValueKey(key, &ValName);
1468 ok(status == expected, "NtDeleteValueKey with long value name returned 0x%08x\n", status);
1470 status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, NULL, 0, &i);
1471 ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey with nonexistent long value name returned 0x%08x\n", status);
1473 pRtlFreeUnicodeString(&ValName);
1474 pNtClose(key);
1477 static void test_NtQueryKey(void)
1479 HANDLE key, subkey, subkey2;
1480 NTSTATUS status;
1481 OBJECT_ATTRIBUTES attr;
1482 ULONG length, len;
1483 KEY_NAME_INFORMATION *info = NULL;
1484 KEY_CACHED_INFORMATION cached_info;
1485 UNICODE_STRING str;
1486 DWORD dw;
1488 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
1489 status = pNtOpenKey(&key, KEY_READ, &attr);
1490 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
1492 status = pNtQueryKey(key, KeyNameInformation, NULL, 0, &length);
1493 if (status == STATUS_INVALID_PARAMETER) {
1494 win_skip("KeyNameInformation is not supported\n");
1495 pNtClose(key);
1496 return;
1498 todo_wine ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryKey Failed: 0x%08x\n", status);
1499 info = HeapAlloc(GetProcessHeap(), 0, length);
1501 /* non-zero buffer size, but insufficient */
1502 status = pNtQueryKey(key, KeyNameInformation, info, sizeof(*info), &len);
1503 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryKey Failed: 0x%08x\n", status);
1504 ok(length == len, "got %d, expected %d\n", len, length);
1505 ok(info->NameLength == winetestpath.Length, "got %d, expected %d\n",
1506 info->NameLength, winetestpath.Length);
1508 /* correct buffer size */
1509 status = pNtQueryKey(key, KeyNameInformation, info, length, &len);
1510 ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08x\n", status);
1511 ok(length == len, "got %d, expected %d\n", len, length);
1513 str.Buffer = info->Name;
1514 str.Length = info->NameLength;
1515 ok(pRtlCompareUnicodeString(&winetestpath, &str, TRUE) == 0,
1516 "got %s, expected %s\n",
1517 wine_dbgstr_wn(str.Buffer, str.Length/sizeof(WCHAR)),
1518 wine_dbgstr_wn(winetestpath.Buffer, winetestpath.Length/sizeof(WCHAR)));
1520 HeapFree(GetProcessHeap(), 0, info);
1522 attr.RootDirectory = key;
1523 attr.ObjectName = &str;
1524 pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey");
1525 status = pNtCreateKey(&subkey, GENERIC_ALL, &attr, 0, 0, 0, 0);
1526 ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status);
1528 status = pNtQueryKey(subkey, KeyCachedInformation, &cached_info, sizeof(cached_info), &len);
1529 ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08x\n", status);
1531 if (status == STATUS_SUCCESS)
1533 ok(len == sizeof(cached_info), "got unexpected length %d\n", len);
1534 ok(cached_info.SubKeys == 0, "cached_info.SubKeys = %u\n", cached_info.SubKeys);
1535 ok(cached_info.MaxNameLen == 0, "cached_info.MaxNameLen = %u\n", cached_info.MaxNameLen);
1536 ok(cached_info.Values == 0, "cached_info.Values = %u\n", cached_info.Values);
1537 ok(cached_info.MaxValueNameLen == 0, "cached_info.MaxValueNameLen = %u\n", cached_info.MaxValueNameLen);
1538 ok(cached_info.MaxValueDataLen == 0, "cached_info.MaxValueDataLen = %u\n", cached_info.MaxValueDataLen);
1539 ok(cached_info.NameLength == 22, "cached_info.NameLength = %u\n", cached_info.NameLength);
1542 attr.RootDirectory = subkey;
1543 attr.ObjectName = &str;
1544 pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey2");
1545 status = pNtCreateKey(&subkey2, GENERIC_ALL, &attr, 0, 0, 0, 0);
1546 ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status);
1548 pRtlCreateUnicodeStringFromAsciiz(&str, "val");
1549 dw = 64;
1550 status = pNtSetValueKey( subkey, &str, 0, REG_DWORD, &dw, sizeof(dw) );
1551 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
1553 status = pNtQueryKey(subkey, KeyCachedInformation, &cached_info, sizeof(cached_info), &len);
1554 ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08x\n", status);
1556 if (status == STATUS_SUCCESS)
1558 ok(len == sizeof(cached_info), "got unexpected length %d\n", len);
1559 ok(cached_info.SubKeys == 1, "cached_info.SubKeys = %u\n", cached_info.SubKeys);
1560 ok(cached_info.MaxNameLen == 24, "cached_info.MaxNameLen = %u\n", cached_info.MaxNameLen);
1561 ok(cached_info.Values == 1, "cached_info.Values = %u\n", cached_info.Values);
1562 ok(cached_info.MaxValueNameLen == 6, "cached_info.MaxValueNameLen = %u\n", cached_info.MaxValueNameLen);
1563 ok(cached_info.MaxValueDataLen == 4, "cached_info.MaxValueDataLen = %u\n", cached_info.MaxValueDataLen);
1564 ok(cached_info.NameLength == 22, "cached_info.NameLength = %u\n", cached_info.NameLength);
1567 status = pNtDeleteKey(subkey2);
1568 ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status);
1569 status = pNtDeleteKey(subkey);
1570 ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status);
1572 pNtClose(subkey2);
1573 pNtClose(subkey);
1574 pNtClose(key);
1577 static void test_notify(void)
1579 OBJECT_ATTRIBUTES attr;
1580 LARGE_INTEGER timeout;
1581 IO_STATUS_BLOCK iosb;
1582 UNICODE_STRING str;
1583 HANDLE key, events[2], subkey;
1584 NTSTATUS status;
1586 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
1587 status = pNtOpenKey(&key, KEY_ALL_ACCESS, &attr);
1588 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
1590 events[0] = CreateEventW(NULL, FALSE, TRUE, NULL);
1591 ok(events[0] != NULL, "CreateEvent failed: %u\n", GetLastError());
1592 events[1] = CreateEventW(NULL, FALSE, TRUE, NULL);
1593 ok(events[1] != NULL, "CreateEvent failed: %u\n", GetLastError());
1595 status = pNtNotifyChangeKey(key, events[0], NULL, NULL, &iosb, REG_NOTIFY_CHANGE_NAME, FALSE, NULL, 0, TRUE);
1596 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
1597 status = pNtNotifyChangeKey(key, events[1], NULL, NULL, &iosb, REG_NOTIFY_CHANGE_NAME, FALSE, NULL, 0, TRUE);
1598 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
1600 timeout.QuadPart = 0;
1601 status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
1602 ok(status == STATUS_TIMEOUT, "NtWaitForSingleObject returned %x\n", status);
1603 status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
1604 ok(status == STATUS_TIMEOUT, "NtWaitForSingleObject returned %x\n", status);
1606 attr.RootDirectory = key;
1607 attr.ObjectName = &str;
1609 pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey");
1610 status = pNtCreateKey(&subkey, GENERIC_ALL, &attr, 0, 0, 0, 0);
1611 ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status);
1613 status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
1614 todo_wine ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
1615 status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
1616 ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
1618 status = pNtNotifyChangeKey(key, events[0], NULL, NULL, &iosb, 0, FALSE, NULL, 0, TRUE);
1619 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
1620 status = pNtNotifyChangeKey(key, events[1], NULL, NULL, &iosb, 0, FALSE, NULL, 0, TRUE);
1621 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
1623 status = pNtDeleteKey(subkey);
1624 ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status);
1626 status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
1627 todo_wine ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
1628 status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
1629 ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
1631 pNtClose(subkey);
1633 status = pNtNotifyChangeKey(key, events[0], NULL, NULL, &iosb, 0, FALSE, NULL, 0, TRUE);
1634 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
1635 status = pNtNotifyChangeKey(key, events[1], NULL, NULL, &iosb, 0, FALSE, NULL, 0, TRUE);
1636 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
1638 pNtClose(key);
1640 status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
1641 todo_wine ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
1642 status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
1643 ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
1645 if (pNtNotifyChangeMultipleKeys)
1647 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
1648 status = pNtOpenKey(&key, KEY_ALL_ACCESS, &attr);
1649 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
1651 status = pNtNotifyChangeMultipleKeys(key, 0, NULL, events[0], NULL, NULL, &iosb, REG_NOTIFY_CHANGE_NAME, FALSE, NULL, 0, TRUE);
1652 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
1654 timeout.QuadPart = 0;
1655 status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
1656 ok(status == STATUS_TIMEOUT, "NtWaitForSingleObject returned %x\n", status);
1658 attr.RootDirectory = key;
1659 attr.ObjectName = &str;
1660 pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey");
1661 status = pNtCreateKey(&subkey, GENERIC_ALL, &attr, 0, 0, 0, 0);
1662 ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status);
1664 status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
1665 ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
1667 status = pNtDeleteKey(subkey);
1668 ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status);
1669 pNtClose(subkey);
1670 pNtClose(key);
1672 else
1674 win_skip("NtNotifyChangeMultipleKeys not available\n");
1677 pNtClose(events[0]);
1678 pNtClose(events[1]);
1681 START_TEST(reg)
1683 static const WCHAR winetest[] = {'\\','W','i','n','e','T','e','s','t',0};
1684 if(!InitFunctionPtrs())
1685 return;
1686 pRtlFormatCurrentUserKeyPath(&winetestpath);
1687 winetestpath.Buffer = pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, winetestpath.Buffer,
1688 winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR));
1689 winetestpath.MaximumLength = winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR);
1691 pRtlAppendUnicodeToString(&winetestpath, winetest);
1693 test_NtCreateKey();
1694 test_NtOpenKey();
1695 test_NtSetValueKey();
1696 test_RtlCheckRegistryKey();
1697 test_RtlOpenCurrentUser();
1698 test_RtlQueryRegistryValues();
1699 test_RtlpNtQueryValueKey();
1700 test_NtFlushKey();
1701 test_NtQueryKey();
1702 test_NtQueryLicenseKey();
1703 test_NtQueryValueKey();
1704 test_long_value_name();
1705 test_notify();
1706 test_NtDeleteKey();
1707 test_symlinks();
1708 test_redirection();
1710 pRtlFreeUnicodeString(&winetestpath);
1712 FreeLibrary(hntdll);