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"
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
,
65 typedef struct _RTL_QUERY_REGISTRY_TABLE
{
66 PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
;
73 } RTL_QUERY_REGISTRY_TABLE
, *PRTL_QUERY_REGISTRY_TABLE
;
75 typedef struct _KEY_VALUE_BASIC_INFORMATION
{
80 } KEY_VALUE_BASIC_INFORMATION
, *PKEY_VALUE_BASIC_INFORMATION
;
82 typedef struct _KEY_VALUE_PARTIAL_INFORMATION
{
87 } KEY_VALUE_PARTIAL_INFORMATION
, *PKEY_VALUE_PARTIAL_INFORMATION
;
89 typedef struct _KEY_VALUE_FULL_INFORMATION
{
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) \
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; \
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
,
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); \
161 trace("GetProcAddress(%s) failed\n", #func); \
162 FreeLibrary(hntdll); \
166 static BOOL
InitFunctionPtrs(void)
168 hntdll
= LoadLibraryA("ntdll.dll");
170 trace("Could not load ntdll.dll\n");
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");
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
));
223 trace("ValueType: REG_NONE\n");
224 trace("ValueData: %p\n", ValueData
);
228 trace("ValueType: REG_BINARY\n");
229 trace("ValueData: %p\n", ValueData
);
233 trace("ValueType: REG_SZ\n");
234 trace("ValueData: %s\n", (char*)ValueData
);
238 trace("ValueType: REG_MULTI_SZ\n");
239 trace("ValueData: %s\n", (char*)ValueData
);
243 trace("ValueType: REG_EXPAND_SZ\n");
244 trace("ValueData: %s\n", (char*)ValueData
);
248 trace("ValueType: REG_DWORD\n");
249 trace("ValueData: %p\n", ValueData
);
252 trace("ValueLength: %d\n", (int)ValueLength
);
255 ok(1, "\n"); /*checks that QueryRoutine is called*/
257 ok(!1, "Invalid Test Specified!\n");
264 static void test_RtlQueryRegistryValues(void)
268 ******************************
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
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)
341 OBJECT_ATTRIBUTES attr
;
342 ACCESS_MASK am
= KEY_READ
;
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);
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) */
361 status
= pNtOpenKey(&key
, am
, &attr
);
362 ok(status
== STATUS_INVALID_PARAMETER
, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status
);
366 win_skip("NtOpenKeyEx not available\n");
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
);
377 static void test_NtCreateKey(void)
380 OBJECT_ATTRIBUTES attr
;
382 ACCESS_MASK am
= GENERIC_ALL
;
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
);
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) */
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
);
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
);
461 static void test_NtSetValueKey(void)
465 OBJECT_ATTRIBUTES attr
;
466 ACCESS_MASK am
= KEY_WRITE
;
467 UNICODE_STRING ValName
;
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
);
487 static void test_RtlOpenCurrentUser(void)
491 status
=pRtlOpenCurrentUser(KEY_READ
, &handle
);
492 ok(status
== STATUS_SUCCESS
, "RtlOpenCurrentUser Failed: 0x%08x\n", status
);
496 static void test_RtlCheckRegistryKey(void)
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)
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
);
526 static void test_NtQueryValueKey(void)
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
;
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
));
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
);
650 static void test_NtDeleteKey(void)
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};
677 if (!pNtQueryLicenseValue
)
679 win_skip("NtQueryLicenseValue not found, skipping tests\n");
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
, "");
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
);
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
);
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
);
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");
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
);
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
);
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
);
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");
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
);
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
);
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
);
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
);
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");
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");
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
);
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
);
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
);
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
);
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");
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)
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
;
858 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
860 UNICODE_STRING symlink_str
, link_str
, target_str
, value_str
;
861 HANDLE root
, key
, link
;
862 OBJECT_ATTRIBUTES attr
;
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;
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
);
911 status
= pNtSetValueKey( key
, &value_str
, 0, REG_DWORD
, &dw
, sizeof(dw
) );
912 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
1072 status
= pNtDeleteKey( link
);
1073 ok( status
== STATUS_SUCCESS
, "NtDeleteKey failed: 0x%08x\n", status
);
1076 status
= pNtDeleteKey( root
);
1077 ok( status
== STATUS_SUCCESS
, "NtDeleteKey failed: 0x%08x\n", status
);
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
)
1091 OBJECT_ATTRIBUTES attr
;
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
)
1114 ok( status
== STATUS_SUCCESS
, "%08x: NtQueryValueKey failed: 0x%08x\n", flags
, status
);
1115 dw
= *(DWORD
*)info
->Data
;
1118 pRtlFreeUnicodeString( &str
);
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','\\',
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','\\',
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','\\',
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','\\',
1168 OBJECT_ATTRIBUTES attr
;
1171 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
1173 HANDLE key
, root32
, root64
, key32
, key64
;
1174 BOOL is_vista
= FALSE
;
1178 ULONG is_wow64
, len
;
1179 if (pNtQueryInformationProcess( GetCurrentProcess(), ProcessWow64Information
,
1180 &is_wow64
, sizeof(is_wow64
), &len
) ||
1183 trace( "Not on Wow64, no redirection\n" );
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
);
1212 status
= pNtSetValueKey( key64
, &value_str
, 0, REG_DWORD
, &dw
, sizeof(dw
) );
1213 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
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
);
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" );
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 );
1253 check_key_value( key
, "Wine\\Winetest", 0, 64 );
1254 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", 0, 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 );
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 );
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 );
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 );
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 );
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 );
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 );
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 );
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 );
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 );
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
);
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
);
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 );
1380 status
= pNtDeleteKey( key32
);
1381 ok( status
== STATUS_SUCCESS
, "NtDeleteKey failed: 0x%08x\n", status
);
1384 status
= pNtDeleteKey( key64
);
1385 ok( status
== STATUS_SUCCESS
, "NtDeleteKey failed: 0x%08x\n", status
);
1388 pNtDeleteKey( root32
);
1390 pNtDeleteKey( 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");
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
);
1409 status
= pNtSetValueKey( key64
, &value_str
, 0, REG_DWORD
, &dw
, sizeof(dw
) );
1410 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
1414 status
= pNtSetValueKey( key32
, &value_str
, 0, REG_DWORD
, &dw
, sizeof(dw
) );
1415 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
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
);
1438 pNtDeleteKey( key64
);
1442 static void test_long_value_name(void)
1445 NTSTATUS status
, expected
;
1446 OBJECT_ATTRIBUTES attr
;
1447 UNICODE_STRING ValName
;
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
);
1477 static void test_NtQueryKey(void)
1479 HANDLE key
, subkey
, subkey2
;
1481 OBJECT_ATTRIBUTES attr
;
1483 KEY_NAME_INFORMATION
*info
= NULL
;
1484 KEY_CACHED_INFORMATION cached_info
;
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");
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");
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
);
1577 static void test_notify(void)
1579 OBJECT_ATTRIBUTES attr
;
1580 LARGE_INTEGER timeout
;
1581 IO_STATUS_BLOCK iosb
;
1583 HANDLE key
, events
[2], subkey
;
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
);
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
);
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
);
1674 win_skip("NtNotifyChangeMultipleKeys not available\n");
1677 pNtClose(events
[0]);
1678 pNtClose(events
[1]);
1683 static const WCHAR winetest
[] = {'\\','W','i','n','e','T','e','s','t',0};
1684 if(!InitFunctionPtrs())
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
);
1695 test_NtSetValueKey();
1696 test_RtlCheckRegistryKey();
1697 test_RtlOpenCurrentUser();
1698 test_RtlQueryRegistryValues();
1699 test_RtlpNtQueryValueKey();
1702 test_NtQueryLicenseKey();
1703 test_NtQueryValueKey();
1704 test_long_value_name();
1710 pRtlFreeUnicodeString(&winetestpath
);
1712 FreeLibrary(hntdll
);