TESTING -- override pthreads to fix gstreamer v5
[wine/multimedia.git] / dlls / ntdll / tests / reg.c
blobe688fd2e68f1177f04df654f2f8378e97434dbbb
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;
343 UNICODE_STRING str;
345 /* All NULL */
346 status = pNtOpenKey(NULL, 0, NULL);
347 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
349 /* NULL attributes */
350 status = pNtOpenKey(&key, 0, NULL);
351 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
352 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
354 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
356 /* NULL key */
357 status = pNtOpenKey(NULL, am, &attr);
358 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
360 /* Length > sizeof(OBJECT_ATTRIBUTES) */
361 attr.Length *= 2;
362 status = pNtOpenKey(&key, am, &attr);
363 ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
365 /* Calling without parent key requres full registry path. */
366 pRtlCreateUnicodeStringFromAsciiz( &str, "Machine" );
367 InitializeObjectAttributes(&attr, &str, 0, 0, 0);
368 status = pNtOpenKey(&key, KEY_READ, &attr);
369 todo_wine ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD, "NtOpenKey Failed: 0x%08x\n", status);
370 if (!status)
371 pNtClose(key);
373 /* Open is case sensitive unless OBJ_CASE_INSENSITIVE is specified. */
374 pRtlCreateUnicodeStringFromAsciiz( &str, "\\Registry\\Machine" );
375 status = pNtOpenKey(&key, KEY_READ, &attr);
376 todo_wine ok(status == STATUS_OBJECT_PATH_NOT_FOUND, "NtOpenKey Failed: 0x%08x\n", status);
377 if (!status)
378 pNtClose(key);
380 attr.Attributes = OBJ_CASE_INSENSITIVE;
381 status = pNtOpenKey(&key, KEY_READ, &attr);
382 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
383 if (!status)
384 pNtClose(key);
386 if (!pNtOpenKeyEx)
388 win_skip("NtOpenKeyEx not available\n");
389 return;
392 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
393 status = pNtOpenKeyEx(&key, KEY_WRITE|KEY_READ, &attr, 0);
394 ok(status == STATUS_SUCCESS, "NtOpenKeyEx Failed: 0x%08x\n", status);
396 pNtClose(key);
399 static void test_NtCreateKey(void)
401 /*Create WineTest*/
402 OBJECT_ATTRIBUTES attr;
403 HANDLE key, subkey;
404 ACCESS_MASK am = GENERIC_ALL;
405 NTSTATUS status;
406 UNICODE_STRING str;
408 /* All NULL */
409 status = pNtCreateKey(NULL, 0, NULL, 0, 0, 0, 0);
410 ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER,
411 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
413 /* Only the key */
414 status = pNtCreateKey(&key, 0, NULL, 0, 0, 0, 0);
415 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
416 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
418 /* Only accessmask */
419 status = pNtCreateKey(NULL, am, NULL, 0, 0, 0, 0);
420 ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER,
421 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
423 /* Key and accessmask */
424 status = pNtCreateKey(&key, am, NULL, 0, 0, 0, 0);
425 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
426 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
428 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
430 /* Only attributes */
431 status = pNtCreateKey(NULL, 0, &attr, 0, 0, 0, 0);
432 ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_ACCESS_DENIED /* Win7 */,
433 "Expected STATUS_ACCESS_VIOLATION or STATUS_ACCESS_DENIED, got: 0x%08x\n", status);
435 /* Length > sizeof(OBJECT_ATTRIBUTES) */
436 attr.Length *= 2;
437 status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
438 ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
440 attr.Length = sizeof(attr);
441 status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
442 ok(status == STATUS_SUCCESS, "NtCreateKey Failed: 0x%08x\n", status);
444 attr.RootDirectory = key;
445 attr.ObjectName = &str;
447 pRtlCreateUnicodeStringFromAsciiz( &str, "test\\sub\\key" );
448 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 );
449 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtCreateKey failed: 0x%08x\n", status );
450 pRtlFreeUnicodeString( &str );
452 pRtlCreateUnicodeStringFromAsciiz( &str, "test\\subkey" );
453 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 );
454 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtCreateKey failed: 0x%08x\n", status );
455 pRtlFreeUnicodeString( &str );
457 pRtlCreateUnicodeStringFromAsciiz( &str, "test\\subkey\\" );
458 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 );
459 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtCreateKey failed: 0x%08x\n", status );
460 pRtlFreeUnicodeString( &str );
462 pRtlCreateUnicodeStringFromAsciiz( &str, "test_subkey\\" );
463 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 );
464 ok( status == STATUS_SUCCESS || broken(status == STATUS_OBJECT_NAME_NOT_FOUND), /* nt4 */
465 "NtCreateKey failed: 0x%08x\n", status );
466 if (status == STATUS_SUCCESS)
468 pNtDeleteKey( subkey );
469 pNtClose( subkey );
471 pRtlFreeUnicodeString( &str );
473 pRtlCreateUnicodeStringFromAsciiz( &str, "test_subkey" );
474 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 );
475 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
476 pRtlFreeUnicodeString( &str );
477 pNtDeleteKey( subkey );
478 pNtClose( subkey );
480 pNtClose(key);
483 static void test_NtSetValueKey(void)
485 HANDLE key;
486 NTSTATUS status;
487 OBJECT_ATTRIBUTES attr;
488 ACCESS_MASK am = KEY_WRITE;
489 UNICODE_STRING ValName;
490 DWORD data = 711;
492 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
493 status = pNtOpenKey(&key, am, &attr);
494 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
496 pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
497 status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &data, sizeof(data));
498 ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status);
499 pRtlFreeUnicodeString(&ValName);
501 pRtlCreateUnicodeStringFromAsciiz(&ValName, "stringtest");
502 status = pNtSetValueKey(key, &ValName, 0, REG_SZ, (VOID*)stringW, STR_TRUNC_SIZE);
503 ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status);
504 pRtlFreeUnicodeString(&ValName);
506 pNtClose(key);
509 static void test_RtlOpenCurrentUser(void)
511 NTSTATUS status;
512 HANDLE handle;
513 status=pRtlOpenCurrentUser(KEY_READ, &handle);
514 ok(status == STATUS_SUCCESS, "RtlOpenCurrentUser Failed: 0x%08x\n", status);
515 pNtClose(handle);
518 static void test_RtlCheckRegistryKey(void)
520 NTSTATUS status;
522 status = pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, winetestpath.Buffer);
523 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08x\n", status);
525 status = pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL), winetestpath.Buffer);
526 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE and RTL_REGISTRY_OPTIONAL: 0x%08x\n", status);
529 static void test_NtFlushKey(void)
531 NTSTATUS status;
532 HANDLE hkey;
533 OBJECT_ATTRIBUTES attr;
534 ACCESS_MASK am = KEY_ALL_ACCESS;
536 status = pNtFlushKey(NULL);
537 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
539 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
540 pNtOpenKey(&hkey, am, &attr);
542 status = pNtFlushKey(hkey);
543 ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
545 pNtClose(hkey);
548 static void test_NtQueryValueKey(void)
550 HANDLE key;
551 NTSTATUS status;
552 OBJECT_ATTRIBUTES attr;
553 UNICODE_STRING ValName;
554 KEY_VALUE_BASIC_INFORMATION *basic_info;
555 KEY_VALUE_PARTIAL_INFORMATION *partial_info, pi;
556 KEY_VALUE_FULL_INFORMATION *full_info;
557 DWORD len, expected;
559 pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
561 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
562 status = pNtOpenKey(&key, KEY_READ|KEY_SET_VALUE, &attr);
563 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
565 len = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]);
566 basic_info = HeapAlloc(GetProcessHeap(), 0, len);
567 status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, basic_info, len, &len);
568 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
569 ok(basic_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info->TitleIndex);
570 ok(basic_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", basic_info->Type);
571 ok(basic_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info->NameLength);
572 ok(len == FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[basic_info->NameLength/sizeof(WCHAR)]), "NtQueryValueKey returned wrong len %d\n", len);
574 basic_info = HeapReAlloc(GetProcessHeap(), 0, basic_info, len);
575 status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, basic_info, len, &len);
576 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
577 ok(basic_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info->TitleIndex);
578 ok(basic_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", basic_info->Type);
579 ok(basic_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info->NameLength);
580 ok(len == FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[basic_info->NameLength/sizeof(WCHAR)]), "NtQueryValueKey returned wrong len %d\n", len);
581 ok(!memcmp(basic_info->Name, ValName.Buffer, ValName.Length), "incorrect Name returned\n");
582 HeapFree(GetProcessHeap(), 0, basic_info);
584 len = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
585 partial_info = HeapAlloc(GetProcessHeap(), 0, len);
586 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
587 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
588 ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->TitleIndex);
589 ok(partial_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type);
590 ok(partial_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength);
591 ok(len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[partial_info->DataLength]), "NtQueryValueKey returned wrong len %d\n", len);
593 partial_info = HeapReAlloc(GetProcessHeap(), 0, partial_info, len);
594 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
595 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
596 ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->TitleIndex);
597 ok(partial_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type);
598 ok(partial_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength);
599 ok(len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[partial_info->DataLength]), "NtQueryValueKey returned wrong len %d\n", len);
600 ok(*(DWORD *)partial_info->Data == 711, "incorrect Data returned: 0x%x\n", *(DWORD *)partial_info->Data);
601 HeapFree(GetProcessHeap(), 0, partial_info);
603 len = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]);
604 full_info = HeapAlloc(GetProcessHeap(), 0, len);
605 status = pNtQueryValueKey(key, &ValName, KeyValueFullInformation, full_info, len, &len);
606 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
607 ok(full_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info->TitleIndex);
608 ok(full_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", full_info->Type);
609 ok(full_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info->DataLength);
610 ok(full_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info->NameLength);
611 ok(len == FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) + full_info->DataLength + full_info->NameLength,
612 "NtQueryValueKey returned wrong len %d\n", len);
613 len = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) + full_info->DataLength + full_info->NameLength;
615 full_info = HeapReAlloc(GetProcessHeap(), 0, full_info, len);
616 status = pNtQueryValueKey(key, &ValName, KeyValueFullInformation, full_info, len, &len);
617 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
618 ok(full_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info->TitleIndex);
619 ok(full_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", full_info->Type);
620 ok(full_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info->DataLength);
621 ok(full_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info->NameLength);
622 ok(!memcmp(full_info->Name, ValName.Buffer, ValName.Length), "incorrect Name returned\n");
623 ok(*(DWORD *)((char *)full_info + full_info->DataOffset) == 711, "incorrect Data returned: 0x%x\n",
624 *(DWORD *)((char *)full_info + full_info->DataOffset));
625 HeapFree(GetProcessHeap(), 0, full_info);
627 pRtlFreeUnicodeString(&ValName);
628 pRtlCreateUnicodeStringFromAsciiz(&ValName, "stringtest");
630 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, NULL, 0, &len);
631 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey should have returned STATUS_BUFFER_TOO_SMALL instead of 0x%08x\n", status);
632 partial_info = HeapAlloc(GetProcessHeap(), 0, len+1);
633 memset(partial_info, 0xbd, len+1);
634 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
635 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
636 ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->TitleIndex);
637 ok(partial_info->Type == REG_SZ, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type);
638 ok(partial_info->DataLength == STR_TRUNC_SIZE, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength);
639 ok(!memcmp(partial_info->Data, stringW, STR_TRUNC_SIZE), "incorrect Data returned\n");
640 ok(*(partial_info->Data+STR_TRUNC_SIZE) == 0xbd, "string overflowed %02x\n", *(partial_info->Data+STR_TRUNC_SIZE));
642 expected = len;
643 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, 0, &len);
644 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey wrong status 0x%08x\n", status);
645 ok(len == expected, "NtQueryValueKey wrong len %u\n", len);
646 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, 1, &len);
647 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey wrong status 0x%08x\n", status);
648 ok(len == expected, "NtQueryValueKey wrong len %u\n", len);
649 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) - 1, &len);
650 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey wrong status 0x%08x\n", status);
651 ok(len == expected, "NtQueryValueKey wrong len %u\n", len);
652 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data), &len);
653 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey wrong status 0x%08x\n", status);
654 ok(len == expected, "NtQueryValueKey wrong len %u\n", len);
656 HeapFree(GetProcessHeap(), 0, partial_info);
657 pRtlFreeUnicodeString(&ValName);
659 pRtlCreateUnicodeStringFromAsciiz(&ValName, "custtest");
660 status = pNtSetValueKey(key, &ValName, 0, 0xff00ff00, NULL, 0);
661 ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status);
663 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, &pi, sizeof(pi), &len);
664 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
665 ok(pi.Type == 0xff00ff00, "Type=%x\n", pi.Type);
666 ok(pi.DataLength == 0, "DataLength=%u\n", pi.DataLength);
667 pRtlFreeUnicodeString(&ValName);
669 pNtClose(key);
672 static void test_NtDeleteKey(void)
674 NTSTATUS status;
675 HANDLE hkey;
676 OBJECT_ATTRIBUTES attr;
677 ACCESS_MASK am = KEY_ALL_ACCESS;
679 status = pNtDeleteKey(NULL);
680 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
682 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
683 status = pNtOpenKey(&hkey, am, &attr);
684 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
686 status = pNtDeleteKey(hkey);
687 ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
690 static void test_NtQueryLicenseKey(void)
692 static const WCHAR emptyW[] = {'E','M','P','T','Y',0};
693 UNICODE_STRING name;
694 WORD buffer[32];
695 NTSTATUS status;
696 ULONG type, len;
697 DWORD value;
699 if (!pNtQueryLicenseValue)
701 win_skip("NtQueryLicenseValue not found, skipping tests\n");
702 return;
705 type = 0xdead;
706 len = 0xbeef;
707 memset(&name, 0, sizeof(name));
708 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), &len);
709 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
710 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
711 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
713 /* test with empty key */
714 pRtlCreateUnicodeStringFromAsciiz(&name, "");
716 type = 0xdead;
717 len = 0xbeef;
718 status = pNtQueryLicenseValue(NULL, &type, buffer, sizeof(buffer), &len);
719 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
720 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
721 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
723 type = 0xdead;
724 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), NULL);
725 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
726 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
728 len = 0xbeef;
729 status = pNtQueryLicenseValue(&name, NULL, buffer, sizeof(buffer), &len);
730 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
731 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
733 type = 0xdead;
734 len = 0xbeef;
735 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), &len);
736 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
737 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
738 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
740 pRtlFreeUnicodeString(&name);
742 /* test with nonexistent licence key */
743 pRtlCreateUnicodeStringFromAsciiz(&name, "Nonexistent-License-Value");
745 type = 0xdead;
746 len = 0xbeef;
747 status = pNtQueryLicenseValue(NULL, &type, buffer, sizeof(buffer), &len);
748 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
749 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
750 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
752 type = 0xdead;
753 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), NULL);
754 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
755 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
757 len = 0xbeef;
758 status = pNtQueryLicenseValue(&name, NULL, buffer, sizeof(buffer), &len);
759 ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryLicenseValue returned %08x, expected STATUS_OBJECT_NAME_NOT_FOUND\n", status);
760 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
762 type = 0xdead;
763 len = 0xbeef;
764 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), &len);
765 ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryLicenseValue unexpected succeeded\n");
766 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
767 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
769 pRtlFreeUnicodeString(&name);
771 /* test with REG_SZ license key */
772 pRtlCreateUnicodeStringFromAsciiz(&name, "Kernel-MUI-Language-Allowed");
774 type = 0xdead;
775 len = 0xbeef;
776 status = pNtQueryLicenseValue(NULL, &type, buffer, sizeof(buffer), &len);
777 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
778 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
779 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
781 type = 0xdead;
782 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), NULL);
783 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
784 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
786 type = 0xdead;
787 len = 0;
788 status = pNtQueryLicenseValue(&name, &type, buffer, 0, &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);
793 len = 0;
794 status = pNtQueryLicenseValue(&name, NULL, buffer, 0, &len);
795 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status);
796 ok(len == sizeof(emptyW), "expected len = %u, got %u\n", (DWORD)sizeof(emptyW), len);
798 type = 0xdead;
799 len = 0;
800 memset(buffer, 0x11, sizeof(buffer));
801 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), &len);
802 ok(status == STATUS_SUCCESS, "NtQueryLicenseValue returned %08x, expected STATUS_SUCCESS\n", status);
803 ok(type == REG_SZ, "expected type = REG_SZ, got %u\n", type);
804 ok(len == sizeof(emptyW), "expected len = %u, got %u\n", (DWORD)sizeof(emptyW), len);
805 ok(!memcmp(buffer, emptyW, sizeof(emptyW)), "unexpected buffer content\n");
807 type = 0xdead;
808 len = 0;
809 memset(buffer, 0x11, sizeof(buffer));
810 status = pNtQueryLicenseValue(&name, &type, buffer, 2, &len);
811 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status);
812 ok(type == REG_SZ, "expected type REG_SZ, got %u\n", type);
813 ok(len == sizeof(emptyW), "expected len = %u, got %u\n", (DWORD)sizeof(emptyW), len);
814 ok(buffer[0] == 0x1111, "expected buffer[0] = 0x1111, got %u\n", buffer[0]);
816 pRtlFreeUnicodeString(&name);
818 /* test with REG_DWORD license key */
819 pRtlCreateUnicodeStringFromAsciiz(&name, "Kernel-MUI-Number-Allowed");
821 type = 0xdead;
822 len = 0xbeef;
823 status = pNtQueryLicenseValue(NULL, &type, &value, sizeof(value), &len);
824 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
825 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
826 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len);
828 type = 0xdead;
829 status = pNtQueryLicenseValue(&name, &type, &value, sizeof(value), NULL);
830 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status);
831 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type);
833 type = 0xdead;
834 len = 0;
835 status = pNtQueryLicenseValue(&name, &type, &value, 0, &len);
836 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status);
837 ok(type == REG_DWORD, "expected type = REG_DWORD, got %u\n", type);
838 ok(len == sizeof(value), "expected len = %u, got %u\n", (DWORD)sizeof(value), len);
840 len = 0;
841 status = pNtQueryLicenseValue(&name, NULL, &value, 0, &len);
842 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status);
843 ok(len == sizeof(value), "expected len = %u, got %u\n", (DWORD)sizeof(value), len);
845 type = 0xdead;
846 len = 0;
847 value = 0xdeadbeef;
848 status = pNtQueryLicenseValue(&name, &type, &value, sizeof(value), &len);
849 ok(status == STATUS_SUCCESS, "NtQueryLicenseValue returned %08x, expected STATUS_SUCCESS\n", status);
850 ok(type == REG_DWORD, "expected type = REG_DWORD, got %u\n", type);
851 ok(len == sizeof(value), "expected len = %u, got %u\n", (DWORD)sizeof(value), len);
852 ok(value != 0xdeadbeef, "expected value != 0xdeadbeef\n");
854 type = 0xdead;
855 len = 0;
856 status = pNtQueryLicenseValue(&name, &type, &value, 2, &len);
857 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status);
858 ok(type == REG_DWORD, "expected type REG_DWORD, got %u\n", type);
859 ok(len == sizeof(value), "expected len = %u, got %u\n", (DWORD)sizeof(value), len);
861 pRtlFreeUnicodeString(&name);
864 static void test_RtlpNtQueryValueKey(void)
866 NTSTATUS status;
868 status = pRtlpNtQueryValueKey(NULL, NULL, NULL, NULL, NULL);
869 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
872 static void test_symlinks(void)
874 static const WCHAR linkW[] = {'l','i','n','k',0};
875 static const WCHAR valueW[] = {'v','a','l','u','e',0};
876 static const WCHAR symlinkW[] = {'S','y','m','b','o','l','i','c','L','i','n','k','V','a','l','u','e',0};
877 static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0};
878 static UNICODE_STRING null_str;
879 char buffer[1024];
880 KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
881 WCHAR *target;
882 UNICODE_STRING symlink_str, link_str, target_str, value_str;
883 HANDLE root, key, link;
884 OBJECT_ATTRIBUTES attr;
885 NTSTATUS status;
886 DWORD target_len, len, dw;
888 pRtlInitUnicodeString( &link_str, linkW );
889 pRtlInitUnicodeString( &symlink_str, symlinkW );
890 pRtlInitUnicodeString( &target_str, targetW + 1 );
891 pRtlInitUnicodeString( &value_str, valueW );
893 target_len = winetestpath.Length + sizeof(targetW);
894 target = pRtlAllocateHeap( GetProcessHeap(), 0, target_len + sizeof(targetW) /*for loop test*/ );
895 memcpy( target, winetestpath.Buffer, winetestpath.Length );
896 memcpy( target + winetestpath.Length/sizeof(WCHAR), targetW, sizeof(targetW) );
898 attr.Length = sizeof(attr);
899 attr.RootDirectory = 0;
900 attr.Attributes = 0;
901 attr.ObjectName = &winetestpath;
902 attr.SecurityDescriptor = NULL;
903 attr.SecurityQualityOfService = NULL;
905 status = pNtCreateKey( &root, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
906 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
908 attr.RootDirectory = root;
909 attr.ObjectName = &link_str;
910 status = pNtCreateKey( &link, KEY_ALL_ACCESS, &attr, 0, 0, REG_OPTION_CREATE_LINK, 0 );
911 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
913 /* REG_SZ is not allowed */
914 status = pNtSetValueKey( link, &symlink_str, 0, REG_SZ, target, target_len );
915 ok( status == STATUS_ACCESS_DENIED, "NtSetValueKey wrong status 0x%08x\n", status );
916 status = pNtSetValueKey( link, &symlink_str, 0, REG_LINK, target, target_len - sizeof(WCHAR) );
917 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
918 /* other values are not allowed */
919 status = pNtSetValueKey( link, &link_str, 0, REG_LINK, target, target_len - sizeof(WCHAR) );
920 ok( status == STATUS_ACCESS_DENIED, "NtSetValueKey wrong status 0x%08x\n", status );
922 /* try opening the target through the link */
924 attr.ObjectName = &link_str;
925 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
926 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey wrong status 0x%08x\n", status );
928 attr.ObjectName = &target_str;
929 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
930 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
932 dw = 0xbeef;
933 status = pNtSetValueKey( key, &value_str, 0, REG_DWORD, &dw, sizeof(dw) );
934 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
935 pNtClose( key );
937 attr.ObjectName = &link_str;
938 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
939 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status );
941 len = sizeof(buffer);
942 status = pNtQueryValueKey( key, &value_str, KeyValuePartialInformation, info, len, &len );
943 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
944 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + sizeof(DWORD), "wrong len %u\n", len );
946 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
947 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status );
949 /* REG_LINK can be created in non-link keys */
950 status = pNtSetValueKey( key, &symlink_str, 0, REG_LINK, target, target_len - sizeof(WCHAR) );
951 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
952 len = sizeof(buffer);
953 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
954 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
955 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR),
956 "wrong len %u\n", len );
957 status = pNtDeleteValueKey( key, &symlink_str );
958 ok( status == STATUS_SUCCESS, "NtDeleteValueKey failed: 0x%08x\n", status );
960 pNtClose( key );
962 attr.Attributes = 0;
963 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
964 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
966 len = sizeof(buffer);
967 status = pNtQueryValueKey( key, &value_str, KeyValuePartialInformation, info, len, &len );
968 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
969 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + sizeof(DWORD), "wrong len %u\n", len );
971 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
972 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status );
973 pNtClose( key );
975 /* now open the symlink itself */
977 attr.RootDirectory = root;
978 attr.Attributes = OBJ_OPENLINK;
979 attr.ObjectName = &link_str;
980 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
981 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status );
983 len = sizeof(buffer);
984 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
985 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
986 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR),
987 "wrong len %u\n", len );
988 pNtClose( key );
990 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
991 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
992 len = sizeof(buffer);
993 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
994 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
995 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR),
996 "wrong len %u\n", len );
997 pNtClose( key );
999 if (0) /* crashes the Windows kernel on some Vista systems */
1001 /* reopen the link from itself */
1003 attr.RootDirectory = link;
1004 attr.Attributes = OBJ_OPENLINK;
1005 attr.ObjectName = &null_str;
1006 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
1007 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status );
1008 len = sizeof(buffer);
1009 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
1010 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
1011 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR),
1012 "wrong len %u\n", len );
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_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
1020 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR),
1021 "wrong len %u\n", len );
1022 pNtClose( key );
1025 if (0) /* crashes the Windows kernel in most versions */
1027 attr.RootDirectory = link;
1028 attr.Attributes = 0;
1029 attr.ObjectName = &null_str;
1030 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
1031 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status );
1032 len = sizeof(buffer);
1033 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
1034 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status );
1035 pNtClose( key );
1037 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1038 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1039 len = sizeof(buffer);
1040 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len );
1041 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status );
1042 pNtClose( key );
1045 /* target with terminating null doesn't work */
1046 status = pNtSetValueKey( link, &symlink_str, 0, REG_LINK, target, target_len );
1047 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
1048 attr.RootDirectory = root;
1049 attr.Attributes = 0;
1050 attr.ObjectName = &link_str;
1051 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
1052 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey wrong status 0x%08x\n", status );
1054 /* relative symlink, works only on win2k */
1055 status = pNtSetValueKey( link, &symlink_str, 0, REG_LINK, targetW+1, sizeof(targetW)-2*sizeof(WCHAR) );
1056 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
1057 attr.ObjectName = &link_str;
1058 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
1059 ok( status == STATUS_SUCCESS || status == STATUS_OBJECT_NAME_NOT_FOUND,
1060 "NtOpenKey wrong status 0x%08x\n", status );
1062 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, REG_OPTION_CREATE_LINK, 0 );
1063 ok( status == STATUS_OBJECT_NAME_COLLISION, "NtCreateKey failed: 0x%08x\n", status );
1065 status = pNtDeleteKey( link );
1066 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status );
1067 pNtClose( link );
1069 attr.ObjectName = &target_str;
1070 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
1071 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status );
1072 status = pNtDeleteKey( key );
1073 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status );
1074 pNtClose( key );
1076 /* symlink loop */
1078 status = pNtCreateKey( &link, KEY_ALL_ACCESS, &attr, 0, 0, REG_OPTION_CREATE_LINK, 0 );
1079 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1080 memcpy( target + target_len/sizeof(WCHAR) - 1, targetW, sizeof(targetW) );
1081 status = pNtSetValueKey( link, &symlink_str, 0, REG_LINK,
1082 target, target_len + sizeof(targetW) - sizeof(WCHAR) );
1083 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
1085 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
1086 ok( status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_NAME_TOO_LONG,
1087 "NtOpenKey failed: 0x%08x\n", status );
1089 attr.Attributes = OBJ_OPENLINK;
1090 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr );
1091 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status );
1092 pNtClose( key );
1094 status = pNtDeleteKey( link );
1095 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status );
1096 pNtClose( link );
1098 status = pNtDeleteKey( root );
1099 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status );
1100 pNtClose( root );
1102 pRtlFreeHeap(GetProcessHeap(), 0, target);
1105 static WCHAR valueW[] = {'v','a','l','u','e'};
1106 static UNICODE_STRING value_str = { sizeof(valueW), sizeof(valueW), valueW };
1107 static const DWORD ptr_size = 8 * sizeof(void*);
1109 static DWORD get_key_value( HANDLE root, const char *name, DWORD flags )
1111 char tmp[32];
1112 NTSTATUS status;
1113 OBJECT_ATTRIBUTES attr;
1114 UNICODE_STRING str;
1115 HANDLE key;
1116 KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)tmp;
1117 DWORD dw, len = sizeof(tmp);
1119 attr.Length = sizeof(attr);
1120 attr.RootDirectory = root;
1121 attr.Attributes = OBJ_CASE_INSENSITIVE;
1122 attr.ObjectName = &str;
1123 attr.SecurityDescriptor = NULL;
1124 attr.SecurityQualityOfService = NULL;
1125 pRtlCreateUnicodeStringFromAsciiz( &str, name );
1127 status = pNtCreateKey( &key, flags | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1128 if (status == STATUS_OBJECT_NAME_NOT_FOUND) return 0;
1129 ok( status == STATUS_SUCCESS, "%08x: NtCreateKey failed: 0x%08x\n", flags, status );
1131 status = pNtQueryValueKey( key, &value_str, KeyValuePartialInformation, info, len, &len );
1132 if (status == STATUS_OBJECT_NAME_NOT_FOUND)
1133 dw = 0;
1134 else
1136 ok( status == STATUS_SUCCESS, "%08x: NtQueryValueKey failed: 0x%08x\n", flags, status );
1137 dw = *(DWORD *)info->Data;
1139 pNtClose( key );
1140 pRtlFreeUnicodeString( &str );
1141 return dw;
1144 static void _check_key_value( int line, HANDLE root, const char *name, DWORD flags, DWORD expect )
1146 DWORD dw = get_key_value( root, name, flags );
1147 ok_(__FILE__,line)( dw == expect, "%08x: wrong value %u/%u\n", flags, dw, expect );
1149 #define check_key_value(root,name,flags,expect) _check_key_value( __LINE__, root, name, flags, expect )
1151 static void test_redirection(void)
1153 static const WCHAR softwareW[] = {'\\','R','e','g','i','s','t','r','y','\\',
1154 'M','a','c','h','i','n','e','\\',
1155 'S','o','f','t','w','a','r','e',0};
1156 static const WCHAR wownodeW[] = {'\\','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 'W','o','w','6','4','3','2','N','o','d','e',0};
1160 static const WCHAR wine64W[] = {'\\','R','e','g','i','s','t','r','y','\\',
1161 'M','a','c','h','i','n','e','\\',
1162 'S','o','f','t','w','a','r','e','\\',
1163 'W','i','n','e',0};
1164 static const WCHAR wine32W[] = {'\\','R','e','g','i','s','t','r','y','\\',
1165 'M','a','c','h','i','n','e','\\',
1166 'S','o','f','t','w','a','r','e','\\',
1167 'W','o','w','6','4','3','2','N','o','d','e','\\',
1168 'W','i','n','e',0};
1169 static const WCHAR key64W[] = {'\\','R','e','g','i','s','t','r','y','\\',
1170 'M','a','c','h','i','n','e','\\',
1171 'S','o','f','t','w','a','r','e','\\',
1172 'W','i','n','e','\\','W','i','n','e','t','e','s','t',0};
1173 static const WCHAR key32W[] = {'\\','R','e','g','i','s','t','r','y','\\',
1174 'M','a','c','h','i','n','e','\\',
1175 'S','o','f','t','w','a','r','e','\\',
1176 'W','o','w','6','4','3','2','N','o','d','e','\\',
1177 'W','i','n','e','\\', 'W','i','n','e','t','e','s','t',0};
1178 static const WCHAR classes64W[] = {'\\','R','e','g','i','s','t','r','y','\\',
1179 'M','a','c','h','i','n','e','\\',
1180 'S','o','f','t','w','a','r','e','\\',
1181 'C','l','a','s','s','e','s','\\',
1182 'W','i','n','e',0};
1183 static const WCHAR classes32W[] = {'\\','R','e','g','i','s','t','r','y','\\',
1184 'M','a','c','h','i','n','e','\\',
1185 'S','o','f','t','w','a','r','e','\\',
1186 'C','l','a','s','s','e','s','\\',
1187 'W','o','w','6','4','3','2','N','o','d','e','\\',
1188 'W','i','n','e',0};
1189 NTSTATUS status;
1190 OBJECT_ATTRIBUTES attr;
1191 UNICODE_STRING str;
1192 char buffer[1024];
1193 KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
1194 DWORD dw, len;
1195 HANDLE key, root32, root64, key32, key64;
1196 BOOL is_vista = FALSE;
1198 if (ptr_size != 64)
1200 ULONG is_wow64, len;
1201 if (pNtQueryInformationProcess( GetCurrentProcess(), ProcessWow64Information,
1202 &is_wow64, sizeof(is_wow64), &len ) ||
1203 !is_wow64)
1205 trace( "Not on Wow64, no redirection\n" );
1206 return;
1210 attr.Length = sizeof(attr);
1211 attr.RootDirectory = 0;
1212 attr.Attributes = OBJ_CASE_INSENSITIVE;
1213 attr.ObjectName = &str;
1214 attr.SecurityDescriptor = NULL;
1215 attr.SecurityQualityOfService = NULL;
1217 pRtlInitUnicodeString( &str, wine64W );
1218 status = pNtCreateKey( &root64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1219 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1221 pRtlInitUnicodeString( &str, wine32W );
1222 status = pNtCreateKey( &root32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1223 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1225 pRtlInitUnicodeString( &str, key64W );
1226 status = pNtCreateKey( &key64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1227 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1229 pRtlInitUnicodeString( &str, key32W );
1230 status = pNtCreateKey( &key32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1231 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1233 dw = 64;
1234 status = pNtSetValueKey( key64, &value_str, 0, REG_DWORD, &dw, sizeof(dw) );
1235 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
1237 dw = 32;
1238 status = pNtSetValueKey( key32, &value_str, 0, REG_DWORD, &dw, sizeof(dw) );
1239 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
1241 len = sizeof(buffer);
1242 status = pNtQueryValueKey( key32, &value_str, KeyValuePartialInformation, info, len, &len );
1243 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
1244 dw = *(DWORD *)info->Data;
1245 ok( dw == 32, "wrong value %u\n", dw );
1247 len = sizeof(buffer);
1248 status = pNtQueryValueKey( key64, &value_str, KeyValuePartialInformation, info, len, &len );
1249 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
1250 dw = *(DWORD *)info->Data;
1251 ok( dw == 64, "wrong value %u\n", dw );
1253 pRtlInitUnicodeString( &str, softwareW );
1254 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1255 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1257 if (ptr_size == 32)
1259 /* the Vista mechanism allows opening Wow6432Node from a 32-bit key too */
1260 /* the new (and simpler) Win7 mechanism doesn't */
1261 if (get_key_value( key, "Wow6432Node\\Wine\\Winetest", 0 ) == 32)
1263 trace( "using Vista-style Wow6432Node handling\n" );
1264 is_vista = TRUE;
1266 check_key_value( key, "Wine\\Winetest", 0, 32 );
1267 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
1268 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1269 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, is_vista ? 32 : 0 );
1270 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 0 );
1271 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, is_vista ? 32 : 0 );
1273 else
1275 check_key_value( key, "Wine\\Winetest", 0, 64 );
1276 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, 32 );
1278 pNtClose( key );
1280 if (ptr_size == 32)
1282 status = pNtCreateKey( &key, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1283 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1284 dw = get_key_value( key, "Wine\\Winetest", 0 );
1285 ok( dw == 64 || broken(dw == 32) /* xp64 */, "wrong value %u\n", dw );
1286 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, 64 );
1287 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1288 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, 32 );
1289 dw = get_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY );
1290 ok( dw == 32 || broken(dw == 64) /* xp64 */, "wrong value %u\n", dw );
1291 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1292 pNtClose( key );
1294 status = pNtCreateKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1295 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1296 check_key_value( key, "Wine\\Winetest", 0, 32 );
1297 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
1298 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1299 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, is_vista ? 32 : 0 );
1300 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 0 );
1301 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, is_vista ? 32 : 0 );
1302 pNtClose( key );
1305 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", 0, ptr_size );
1306 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", 0, 32 );
1307 if (ptr_size == 64)
1309 /* KEY_WOW64 flags have no effect on 64-bit */
1310 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_64KEY, 64 );
1311 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_32KEY, 64 );
1312 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, 32 );
1313 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1315 else
1317 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_64KEY, 64 );
1318 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1319 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
1320 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1323 pRtlInitUnicodeString( &str, wownodeW );
1324 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1325 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1326 check_key_value( key, "Wine\\Winetest", 0, 32 );
1327 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, (ptr_size == 64) ? 32 : (is_vista ? 64 : 32) );
1328 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1329 pNtClose( key );
1331 if (ptr_size == 32)
1333 status = pNtCreateKey( &key, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1334 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1335 dw = get_key_value( key, "Wine\\Winetest", 0 );
1336 ok( dw == (is_vista ? 64 : 32) || broken(dw == 32) /* xp64 */, "wrong value %u\n", dw );
1337 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
1338 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1339 pNtClose( key );
1341 status = pNtCreateKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1342 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1343 check_key_value( key, "Wine\\Winetest", 0, 32 );
1344 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
1345 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 );
1346 pNtClose( key );
1349 pRtlInitUnicodeString( &str, wine32W );
1350 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1351 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1352 check_key_value( key, "Winetest", 0, 32 );
1353 check_key_value( key, "Winetest", KEY_WOW64_64KEY, (ptr_size == 32 && is_vista) ? 64 : 32 );
1354 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
1355 pNtClose( key );
1357 if (ptr_size == 32)
1359 status = pNtCreateKey( &key, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1360 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1361 dw = get_key_value( key, "Winetest", 0 );
1362 ok( dw == 32 || (is_vista && dw == 64), "wrong value %u\n", dw );
1363 check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
1364 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
1365 pNtClose( key );
1367 status = pNtCreateKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1368 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1369 check_key_value( key, "Winetest", 0, 32 );
1370 check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
1371 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
1372 pNtClose( key );
1375 pRtlInitUnicodeString( &str, wine64W );
1376 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1377 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1378 check_key_value( key, "Winetest", 0, ptr_size );
1379 check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : ptr_size );
1380 check_key_value( key, "Winetest", KEY_WOW64_32KEY, ptr_size );
1381 pNtClose( key );
1383 if (ptr_size == 32)
1385 status = pNtCreateKey( &key, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1386 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1387 dw = get_key_value( key, "Winetest", 0 );
1388 ok( dw == 64 || broken(dw == 32) /* xp64 */, "wrong value %u\n", dw );
1389 check_key_value( key, "Winetest", KEY_WOW64_64KEY, 64 );
1390 dw = get_key_value( key, "Winetest", KEY_WOW64_32KEY );
1391 todo_wine ok( dw == 32, "wrong value %u\n", dw );
1392 pNtClose( key );
1394 status = pNtCreateKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1395 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1396 check_key_value( key, "Winetest", 0, 32 );
1397 check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 );
1398 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 );
1399 pNtClose( key );
1402 status = pNtDeleteKey( key32 );
1403 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status );
1404 pNtClose( key32 );
1406 status = pNtDeleteKey( key64 );
1407 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status );
1408 pNtClose( key64 );
1410 pNtDeleteKey( root32 );
1411 pNtClose( root32 );
1412 pNtDeleteKey( root64 );
1413 pNtClose( root64 );
1415 /* Software\Classes is shared/reflected so behavior is different */
1417 pRtlInitUnicodeString( &str, classes64W );
1418 status = pNtCreateKey( &key64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1419 if (status == STATUS_ACCESS_DENIED)
1421 skip("Not authorized to modify the Classes key\n");
1422 return;
1424 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1426 pRtlInitUnicodeString( &str, classes32W );
1427 status = pNtCreateKey( &key32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1428 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1430 dw = 64;
1431 status = pNtSetValueKey( key64, &value_str, 0, REG_DWORD, &dw, sizeof(dw) );
1432 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
1433 pNtClose( key64 );
1435 dw = 32;
1436 status = pNtSetValueKey( key32, &value_str, 0, REG_DWORD, &dw, sizeof(dw) );
1437 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
1438 pNtClose( key32 );
1440 pRtlInitUnicodeString( &str, classes64W );
1441 status = pNtCreateKey( &key64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1442 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1443 len = sizeof(buffer);
1444 status = pNtQueryValueKey( key64, &value_str, KeyValuePartialInformation, info, len, &len );
1445 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
1446 dw = *(DWORD *)info->Data;
1447 ok( dw == ptr_size, "wrong value %u\n", dw );
1449 pRtlInitUnicodeString( &str, classes32W );
1450 status = pNtCreateKey( &key32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 );
1451 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status );
1452 len = sizeof(buffer);
1453 status = pNtQueryValueKey( key32, &value_str, KeyValuePartialInformation, info, len, &len );
1454 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status );
1455 dw = *(DWORD *)info->Data;
1456 ok( dw == 32, "wrong value %u\n", dw );
1458 pNtDeleteKey( key32 );
1459 pNtClose( key32 );
1460 pNtDeleteKey( key64 );
1461 pNtClose( key64 );
1464 static void test_long_value_name(void)
1466 HANDLE key;
1467 NTSTATUS status, expected;
1468 OBJECT_ATTRIBUTES attr;
1469 UNICODE_STRING ValName;
1470 DWORD i;
1472 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
1473 status = pNtOpenKey(&key, KEY_WRITE|KEY_READ, &attr);
1474 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
1476 ValName.MaximumLength = 0xfffc;
1477 ValName.Length = ValName.MaximumLength - sizeof(WCHAR);
1478 ValName.Buffer = HeapAlloc(GetProcessHeap(), 0, ValName.MaximumLength);
1479 for (i = 0; i < ValName.Length / sizeof(WCHAR); i++)
1480 ValName.Buffer[i] = 'a';
1481 ValName.Buffer[i] = 0;
1483 status = pNtDeleteValueKey(key, &ValName);
1484 ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "NtDeleteValueKey with nonexistent long value name returned 0x%08x\n", status);
1485 status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &i, sizeof(i));
1486 ok(status == STATUS_INVALID_PARAMETER || broken(status == STATUS_SUCCESS) /* nt4 */,
1487 "NtSetValueKey with long value name returned 0x%08x\n", status);
1488 expected = (status == STATUS_SUCCESS) ? STATUS_SUCCESS : STATUS_OBJECT_NAME_NOT_FOUND;
1489 status = pNtDeleteValueKey(key, &ValName);
1490 ok(status == expected, "NtDeleteValueKey with long value name returned 0x%08x\n", status);
1492 status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, NULL, 0, &i);
1493 ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey with nonexistent long value name returned 0x%08x\n", status);
1495 pRtlFreeUnicodeString(&ValName);
1496 pNtClose(key);
1499 static void test_NtQueryKey(void)
1501 HANDLE key, subkey, subkey2;
1502 NTSTATUS status;
1503 OBJECT_ATTRIBUTES attr;
1504 ULONG length, len;
1505 KEY_NAME_INFORMATION *info = NULL;
1506 KEY_CACHED_INFORMATION cached_info;
1507 UNICODE_STRING str;
1508 DWORD dw;
1510 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
1511 status = pNtOpenKey(&key, KEY_READ, &attr);
1512 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
1514 status = pNtQueryKey(key, KeyNameInformation, NULL, 0, &length);
1515 if (status == STATUS_INVALID_PARAMETER) {
1516 win_skip("KeyNameInformation is not supported\n");
1517 pNtClose(key);
1518 return;
1520 todo_wine ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryKey Failed: 0x%08x\n", status);
1521 info = HeapAlloc(GetProcessHeap(), 0, length);
1523 /* non-zero buffer size, but insufficient */
1524 status = pNtQueryKey(key, KeyNameInformation, info, sizeof(*info), &len);
1525 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryKey Failed: 0x%08x\n", status);
1526 ok(length == len, "got %d, expected %d\n", len, length);
1527 ok(info->NameLength == winetestpath.Length, "got %d, expected %d\n",
1528 info->NameLength, winetestpath.Length);
1530 /* correct buffer size */
1531 status = pNtQueryKey(key, KeyNameInformation, info, length, &len);
1532 ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08x\n", status);
1533 ok(length == len, "got %d, expected %d\n", len, length);
1535 str.Buffer = info->Name;
1536 str.Length = info->NameLength;
1537 ok(pRtlCompareUnicodeString(&winetestpath, &str, TRUE) == 0,
1538 "got %s, expected %s\n",
1539 wine_dbgstr_wn(str.Buffer, str.Length/sizeof(WCHAR)),
1540 wine_dbgstr_wn(winetestpath.Buffer, winetestpath.Length/sizeof(WCHAR)));
1542 HeapFree(GetProcessHeap(), 0, info);
1544 attr.RootDirectory = key;
1545 attr.ObjectName = &str;
1546 pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey");
1547 status = pNtCreateKey(&subkey, GENERIC_ALL, &attr, 0, 0, 0, 0);
1548 ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status);
1550 status = pNtQueryKey(subkey, KeyCachedInformation, &cached_info, sizeof(cached_info), &len);
1551 ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08x\n", status);
1553 if (status == STATUS_SUCCESS)
1555 ok(len == sizeof(cached_info), "got unexpected length %d\n", len);
1556 ok(cached_info.SubKeys == 0, "cached_info.SubKeys = %u\n", cached_info.SubKeys);
1557 ok(cached_info.MaxNameLen == 0, "cached_info.MaxNameLen = %u\n", cached_info.MaxNameLen);
1558 ok(cached_info.Values == 0, "cached_info.Values = %u\n", cached_info.Values);
1559 ok(cached_info.MaxValueNameLen == 0, "cached_info.MaxValueNameLen = %u\n", cached_info.MaxValueNameLen);
1560 ok(cached_info.MaxValueDataLen == 0, "cached_info.MaxValueDataLen = %u\n", cached_info.MaxValueDataLen);
1561 ok(cached_info.NameLength == 22, "cached_info.NameLength = %u\n", cached_info.NameLength);
1564 attr.RootDirectory = subkey;
1565 attr.ObjectName = &str;
1566 pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey2");
1567 status = pNtCreateKey(&subkey2, GENERIC_ALL, &attr, 0, 0, 0, 0);
1568 ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status);
1570 pRtlCreateUnicodeStringFromAsciiz(&str, "val");
1571 dw = 64;
1572 status = pNtSetValueKey( subkey, &str, 0, REG_DWORD, &dw, sizeof(dw) );
1573 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
1575 status = pNtQueryKey(subkey, KeyCachedInformation, &cached_info, sizeof(cached_info), &len);
1576 ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08x\n", status);
1578 if (status == STATUS_SUCCESS)
1580 ok(len == sizeof(cached_info), "got unexpected length %d\n", len);
1581 ok(cached_info.SubKeys == 1, "cached_info.SubKeys = %u\n", cached_info.SubKeys);
1582 ok(cached_info.MaxNameLen == 24, "cached_info.MaxNameLen = %u\n", cached_info.MaxNameLen);
1583 ok(cached_info.Values == 1, "cached_info.Values = %u\n", cached_info.Values);
1584 ok(cached_info.MaxValueNameLen == 6, "cached_info.MaxValueNameLen = %u\n", cached_info.MaxValueNameLen);
1585 ok(cached_info.MaxValueDataLen == 4, "cached_info.MaxValueDataLen = %u\n", cached_info.MaxValueDataLen);
1586 ok(cached_info.NameLength == 22, "cached_info.NameLength = %u\n", cached_info.NameLength);
1589 status = pNtDeleteKey(subkey2);
1590 ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status);
1591 status = pNtDeleteKey(subkey);
1592 ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status);
1594 pNtClose(subkey2);
1595 pNtClose(subkey);
1596 pNtClose(key);
1599 static void test_notify(void)
1601 OBJECT_ATTRIBUTES attr;
1602 LARGE_INTEGER timeout;
1603 IO_STATUS_BLOCK iosb;
1604 UNICODE_STRING str;
1605 HANDLE key, events[2], subkey;
1606 NTSTATUS status;
1608 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
1609 status = pNtOpenKey(&key, KEY_ALL_ACCESS, &attr);
1610 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
1612 events[0] = CreateEventW(NULL, FALSE, TRUE, NULL);
1613 ok(events[0] != NULL, "CreateEvent failed: %u\n", GetLastError());
1614 events[1] = CreateEventW(NULL, FALSE, TRUE, NULL);
1615 ok(events[1] != NULL, "CreateEvent failed: %u\n", GetLastError());
1617 status = pNtNotifyChangeKey(key, events[0], NULL, NULL, &iosb, REG_NOTIFY_CHANGE_NAME, FALSE, NULL, 0, TRUE);
1618 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
1619 status = pNtNotifyChangeKey(key, events[1], NULL, NULL, &iosb, REG_NOTIFY_CHANGE_NAME, FALSE, NULL, 0, TRUE);
1620 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
1622 timeout.QuadPart = 0;
1623 status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
1624 ok(status == STATUS_TIMEOUT, "NtWaitForSingleObject returned %x\n", status);
1625 status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
1626 ok(status == STATUS_TIMEOUT, "NtWaitForSingleObject returned %x\n", status);
1628 attr.RootDirectory = key;
1629 attr.ObjectName = &str;
1631 pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey");
1632 status = pNtCreateKey(&subkey, GENERIC_ALL, &attr, 0, 0, 0, 0);
1633 ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status);
1635 status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
1636 todo_wine ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
1637 status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
1638 ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
1640 status = pNtNotifyChangeKey(key, events[0], NULL, NULL, &iosb, 0, FALSE, NULL, 0, TRUE);
1641 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
1642 status = pNtNotifyChangeKey(key, events[1], NULL, NULL, &iosb, 0, FALSE, NULL, 0, TRUE);
1643 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
1645 status = pNtDeleteKey(subkey);
1646 ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status);
1648 status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
1649 todo_wine ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
1650 status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
1651 ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
1653 pNtClose(subkey);
1655 status = pNtNotifyChangeKey(key, events[0], NULL, NULL, &iosb, 0, FALSE, NULL, 0, TRUE);
1656 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
1657 status = pNtNotifyChangeKey(key, events[1], NULL, NULL, &iosb, 0, FALSE, NULL, 0, TRUE);
1658 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
1660 pNtClose(key);
1662 status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
1663 todo_wine ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
1664 status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
1665 ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
1667 if (pNtNotifyChangeMultipleKeys)
1669 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
1670 status = pNtOpenKey(&key, KEY_ALL_ACCESS, &attr);
1671 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
1673 status = pNtNotifyChangeMultipleKeys(key, 0, NULL, events[0], NULL, NULL, &iosb, REG_NOTIFY_CHANGE_NAME, FALSE, NULL, 0, TRUE);
1674 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status);
1676 timeout.QuadPart = 0;
1677 status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
1678 ok(status == STATUS_TIMEOUT, "NtWaitForSingleObject returned %x\n", status);
1680 attr.RootDirectory = key;
1681 attr.ObjectName = &str;
1682 pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey");
1683 status = pNtCreateKey(&subkey, GENERIC_ALL, &attr, 0, 0, 0, 0);
1684 ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status);
1686 status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
1687 ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
1689 status = pNtDeleteKey(subkey);
1690 ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status);
1691 pNtClose(subkey);
1692 pNtClose(key);
1694 else
1696 win_skip("NtNotifyChangeMultipleKeys not available\n");
1699 pNtClose(events[0]);
1700 pNtClose(events[1]);
1703 START_TEST(reg)
1705 static const WCHAR winetest[] = {'\\','W','i','n','e','T','e','s','t',0};
1706 if(!InitFunctionPtrs())
1707 return;
1708 pRtlFormatCurrentUserKeyPath(&winetestpath);
1709 winetestpath.Buffer = pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, winetestpath.Buffer,
1710 winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR));
1711 winetestpath.MaximumLength = winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR);
1713 pRtlAppendUnicodeToString(&winetestpath, winetest);
1715 test_NtCreateKey();
1716 test_NtOpenKey();
1717 test_NtSetValueKey();
1718 test_RtlCheckRegistryKey();
1719 test_RtlOpenCurrentUser();
1720 test_RtlQueryRegistryValues();
1721 test_RtlpNtQueryValueKey();
1722 test_NtFlushKey();
1723 test_NtQueryKey();
1724 test_NtQueryLicenseKey();
1725 test_NtQueryValueKey();
1726 test_long_value_name();
1727 test_notify();
1728 test_NtDeleteKey();
1729 test_symlinks();
1730 test_redirection();
1732 pRtlFreeUnicodeString(&winetestpath);
1734 FreeLibrary(hntdll);