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
;
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);
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) */
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 pRtlFreeUnicodeString( &str
);
372 /* Open is case sensitive unless OBJ_CASE_INSENSITIVE is specified. */
373 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\Registry\\Machine" );
374 status
= pNtOpenKey(&key
, KEY_READ
, &attr
);
375 todo_wine
ok(status
== STATUS_OBJECT_PATH_NOT_FOUND
, "NtOpenKey Failed: 0x%08x\n", status
);
377 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
378 status
= pNtOpenKey(&key
, KEY_READ
, &attr
);
379 ok(status
== STATUS_SUCCESS
, "NtOpenKey Failed: 0x%08x\n", status
);
381 pRtlFreeUnicodeString( &str
);
383 pRtlCreateUnicodeStringFromAsciiz( &str
, "" );
384 status
= pNtOpenKey(&key
, KEY_READ
, &attr
);
386 ok( status
== STATUS_OBJECT_PATH_SYNTAX_BAD
, "NtOpenKey failed: 0x%08x\n", status
);
387 pRtlFreeUnicodeString( &str
);
389 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\" );
390 status
= pNtOpenKey(&key
, KEY_READ
, &attr
);
392 ok( status
== STATUS_OBJECT_TYPE_MISMATCH
, "NtOpenKey failed: 0x%08x\n", status
);
393 pRtlFreeUnicodeString( &str
);
395 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\Registry" );
396 status
= pNtOpenKey(&key
, KEY_READ
, &attr
);
398 ok( status
== STATUS_SUCCESS
, "NtOpenKey failed: 0x%08x\n", status
);
400 pRtlFreeUnicodeString( &str
);
402 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\Registry\\" );
403 status
= pNtOpenKey(&key
, KEY_READ
, &attr
);
404 ok( status
== STATUS_SUCCESS
, "NtOpenKey failed: 0x%08x\n", status
);
406 pRtlFreeUnicodeString( &str
);
408 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\Foobar" );
409 status
= pNtOpenKey(&key
, KEY_READ
, &attr
);
411 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtOpenKey failed: 0x%08x\n", status
);
412 pRtlFreeUnicodeString( &str
);
414 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\Foobar\\Machine" );
415 status
= pNtOpenKey(&key
, KEY_READ
, &attr
);
417 ok( status
== STATUS_OBJECT_PATH_NOT_FOUND
, "NtOpenKey failed: 0x%08x\n", status
);
418 pRtlFreeUnicodeString( &str
);
420 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\Machine\\Software\\Classes" );
421 status
= pNtOpenKey(&key
, KEY_READ
, &attr
);
423 ok( status
== STATUS_OBJECT_PATH_NOT_FOUND
, "NtOpenKey failed: 0x%08x\n", status
);
424 pRtlFreeUnicodeString( &str
);
426 pRtlCreateUnicodeStringFromAsciiz( &str
, "Machine\\Software\\Classes" );
427 status
= pNtOpenKey(&key
, KEY_READ
, &attr
);
429 ok( status
== STATUS_OBJECT_PATH_SYNTAX_BAD
, "NtOpenKey failed: 0x%08x\n", status
);
430 pRtlFreeUnicodeString( &str
);
432 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\Device\\Null" );
433 status
= pNtOpenKey(&key
, KEY_READ
, &attr
);
435 ok( status
== STATUS_OBJECT_TYPE_MISMATCH
, "NtOpenKey failed: 0x%08x\n", status
);
436 pRtlFreeUnicodeString( &str
);
440 win_skip("NtOpenKeyEx not available\n");
444 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
445 status
= pNtOpenKeyEx(&key
, KEY_WRITE
|KEY_READ
, &attr
, 0);
446 ok(status
== STATUS_SUCCESS
, "NtOpenKeyEx Failed: 0x%08x\n", status
);
451 static void test_NtCreateKey(void)
454 OBJECT_ATTRIBUTES attr
;
456 ACCESS_MASK am
= GENERIC_ALL
;
461 status
= pNtCreateKey(NULL
, 0, NULL
, 0, 0, 0, 0);
462 ok(status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_PARAMETER
,
463 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got: 0x%08x\n", status
);
466 status
= pNtCreateKey(&key
, 0, NULL
, 0, 0, 0, 0);
467 ok(status
== STATUS_ACCESS_VIOLATION
/* W2K3/XP/W2K */ || status
== STATUS_INVALID_PARAMETER
/* NT4 */,
468 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status
);
470 /* Only accessmask */
471 status
= pNtCreateKey(NULL
, am
, NULL
, 0, 0, 0, 0);
472 ok(status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_PARAMETER
,
473 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got: 0x%08x\n", status
);
475 /* Key and accessmask */
476 status
= pNtCreateKey(&key
, am
, NULL
, 0, 0, 0, 0);
477 ok(status
== STATUS_ACCESS_VIOLATION
/* W2K3/XP/W2K */ || status
== STATUS_INVALID_PARAMETER
/* NT4 */,
478 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status
);
480 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
482 /* Only attributes */
483 status
= pNtCreateKey(NULL
, 0, &attr
, 0, 0, 0, 0);
484 ok(status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_ACCESS_DENIED
/* Win7 */,
485 "Expected STATUS_ACCESS_VIOLATION or STATUS_ACCESS_DENIED, got: 0x%08x\n", status
);
487 /* Length > sizeof(OBJECT_ATTRIBUTES) */
489 status
= pNtCreateKey(&key
, am
, &attr
, 0, 0, 0, 0);
490 ok(status
== STATUS_INVALID_PARAMETER
, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status
);
492 attr
.Length
= sizeof(attr
);
493 status
= pNtCreateKey(&key
, am
, &attr
, 0, 0, 0, 0);
494 ok(status
== STATUS_SUCCESS
, "NtCreateKey Failed: 0x%08x\n", status
);
496 attr
.RootDirectory
= key
;
497 attr
.ObjectName
= &str
;
499 pRtlCreateUnicodeStringFromAsciiz( &str
, "test\\sub\\key" );
500 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
501 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtCreateKey failed: 0x%08x\n", status
);
502 pRtlFreeUnicodeString( &str
);
504 pRtlCreateUnicodeStringFromAsciiz( &str
, "test\\subkey" );
505 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
506 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtCreateKey failed: 0x%08x\n", status
);
507 pRtlFreeUnicodeString( &str
);
509 pRtlCreateUnicodeStringFromAsciiz( &str
, "test\\subkey\\" );
510 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
511 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtCreateKey failed: 0x%08x\n", status
);
512 pRtlFreeUnicodeString( &str
);
514 pRtlCreateUnicodeStringFromAsciiz( &str
, "test_subkey\\" );
515 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
516 ok( status
== STATUS_SUCCESS
|| broken(status
== STATUS_OBJECT_NAME_NOT_FOUND
), /* nt4 */
517 "NtCreateKey failed: 0x%08x\n", status
);
518 if (status
== STATUS_SUCCESS
)
520 pNtDeleteKey( subkey
);
523 pRtlFreeUnicodeString( &str
);
525 pRtlCreateUnicodeStringFromAsciiz( &str
, "test_subkey" );
526 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
527 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
528 pRtlFreeUnicodeString( &str
);
529 pNtDeleteKey( subkey
);
532 attr
.RootDirectory
= 0;
533 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
535 pRtlCreateUnicodeStringFromAsciiz( &str
, "" );
536 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
538 ok( status
== STATUS_OBJECT_PATH_SYNTAX_BAD
, "NtCreateKey failed: 0x%08x\n", status
);
539 pRtlFreeUnicodeString( &str
);
541 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\" );
542 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
544 ok( status
== STATUS_OBJECT_TYPE_MISMATCH
, "NtCreateKey failed: 0x%08x\n", status
);
545 pRtlFreeUnicodeString( &str
);
547 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\Registry" );
548 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
550 ok( status
== STATUS_SUCCESS
|| status
== STATUS_ACCESS_DENIED
,
551 "NtCreateKey failed: 0x%08x\n", status
);
552 if (!status
) pNtClose( subkey
);
553 pRtlFreeUnicodeString( &str
);
555 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\Registry\\" );
556 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
557 ok( status
== STATUS_SUCCESS
|| status
== STATUS_ACCESS_DENIED
,
558 "NtCreateKey failed: 0x%08x\n", status
);
559 if (!status
) pNtClose( subkey
);
560 pRtlFreeUnicodeString( &str
);
562 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\Foobar" );
563 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
565 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtCreateKey failed: 0x%08x\n", status
);
566 pRtlFreeUnicodeString( &str
);
568 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\Foobar\\Machine" );
569 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
571 ok( status
== STATUS_OBJECT_PATH_NOT_FOUND
, "NtCreateKey failed: 0x%08x\n", status
);
572 pRtlFreeUnicodeString( &str
);
574 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\Machine\\Software\\Classes" );
575 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
577 ok( status
== STATUS_OBJECT_PATH_NOT_FOUND
, "NtCreateKey failed: 0x%08x\n", status
);
578 pRtlFreeUnicodeString( &str
);
580 pRtlCreateUnicodeStringFromAsciiz( &str
, "Machine\\Software\\Classes" );
581 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
583 ok( status
== STATUS_OBJECT_PATH_SYNTAX_BAD
, "NtCreateKey failed: 0x%08x\n", status
);
584 pRtlFreeUnicodeString( &str
);
586 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\Device\\Null" );
587 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
589 ok( status
== STATUS_OBJECT_TYPE_MISMATCH
, "NtCreateKey failed: 0x%08x\n", status
);
590 pRtlFreeUnicodeString( &str
);
592 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\Registry\\Machine\\Software\\Classes" );
593 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
594 ok( status
== STATUS_SUCCESS
|| status
== STATUS_ACCESS_DENIED
,
595 "NtCreateKey failed: 0x%08x\n", status
);
596 if (!status
) pNtClose( subkey
);
597 pRtlFreeUnicodeString( &str
);
599 /* the REGISTRY part is case-sensitive unless OBJ_CASE_INSENSITIVE is specified */
601 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\Registry\\Machine\\Software\\Classes" );
602 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
604 ok( status
== STATUS_OBJECT_PATH_NOT_FOUND
, "NtCreateKey failed: 0x%08x\n", status
);
605 pRtlFreeUnicodeString( &str
);
607 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\REGISTRY\\Machine\\Software\\Classes" );
608 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
609 ok( status
== STATUS_SUCCESS
|| status
== STATUS_ACCESS_DENIED
,
610 "NtCreateKey failed: 0x%08x\n", status
);
611 if (!status
) pNtClose( subkey
);
612 pRtlFreeUnicodeString( &str
);
614 pRtlCreateUnicodeStringFromAsciiz( &str
, "\\REGISTRY\\MACHINE\\SOFTWARE\\CLASSES" );
615 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
616 ok( status
== STATUS_SUCCESS
|| status
== STATUS_ACCESS_DENIED
,
617 "NtCreateKey failed: 0x%08x\n", status
);
618 if (!status
) pNtClose( subkey
);
619 pRtlFreeUnicodeString( &str
);
624 static void test_NtSetValueKey(void)
628 OBJECT_ATTRIBUTES attr
;
629 ACCESS_MASK am
= KEY_WRITE
;
630 UNICODE_STRING ValName
;
633 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
634 status
= pNtOpenKey(&key
, am
, &attr
);
635 ok(status
== STATUS_SUCCESS
, "NtOpenKey Failed: 0x%08x\n", status
);
637 pRtlCreateUnicodeStringFromAsciiz(&ValName
, "deletetest");
638 status
= pNtSetValueKey(key
, &ValName
, 0, REG_DWORD
, &data
, sizeof(data
));
639 ok(status
== STATUS_SUCCESS
, "NtSetValueKey Failed: 0x%08x\n", status
);
640 pRtlFreeUnicodeString(&ValName
);
642 pRtlCreateUnicodeStringFromAsciiz(&ValName
, "stringtest");
643 status
= pNtSetValueKey(key
, &ValName
, 0, REG_SZ
, (VOID
*)stringW
, STR_TRUNC_SIZE
);
644 ok(status
== STATUS_SUCCESS
, "NtSetValueKey Failed: 0x%08x\n", status
);
645 pRtlFreeUnicodeString(&ValName
);
650 static void test_RtlOpenCurrentUser(void)
654 status
=pRtlOpenCurrentUser(KEY_READ
, &handle
);
655 ok(status
== STATUS_SUCCESS
, "RtlOpenCurrentUser Failed: 0x%08x\n", status
);
659 static void test_RtlCheckRegistryKey(void)
663 status
= pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE
, winetestpath
.Buffer
);
664 ok(status
== STATUS_SUCCESS
, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08x\n", status
);
666 status
= pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE
| RTL_REGISTRY_OPTIONAL
), winetestpath
.Buffer
);
667 ok(status
== STATUS_SUCCESS
, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE and RTL_REGISTRY_OPTIONAL: 0x%08x\n", status
);
670 static void test_NtFlushKey(void)
674 OBJECT_ATTRIBUTES attr
;
675 ACCESS_MASK am
= KEY_ALL_ACCESS
;
677 status
= pNtFlushKey(NULL
);
678 ok(status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status
);
680 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
681 pNtOpenKey(&hkey
, am
, &attr
);
683 status
= pNtFlushKey(hkey
);
684 ok(status
== STATUS_SUCCESS
, "NtDeleteKey Failed: 0x%08x\n", status
);
689 static void test_NtQueryValueKey(void)
693 OBJECT_ATTRIBUTES attr
;
694 UNICODE_STRING ValName
;
695 KEY_VALUE_BASIC_INFORMATION
*basic_info
;
696 KEY_VALUE_PARTIAL_INFORMATION
*partial_info
, pi
;
697 KEY_VALUE_FULL_INFORMATION
*full_info
;
700 pRtlCreateUnicodeStringFromAsciiz(&ValName
, "deletetest");
702 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
703 status
= pNtOpenKey(&key
, KEY_READ
|KEY_SET_VALUE
, &attr
);
704 ok(status
== STATUS_SUCCESS
, "NtOpenKey Failed: 0x%08x\n", status
);
706 len
= FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]);
707 basic_info
= HeapAlloc(GetProcessHeap(), 0, len
);
708 status
= pNtQueryValueKey(key
, &ValName
, KeyValueBasicInformation
, basic_info
, len
, &len
);
709 ok(status
== STATUS_BUFFER_OVERFLOW
, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status
);
710 ok(basic_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info
->TitleIndex
);
711 ok(basic_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", basic_info
->Type
);
712 ok(basic_info
->NameLength
== 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info
->NameLength
);
713 ok(len
== FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[basic_info
->NameLength
/sizeof(WCHAR
)]), "NtQueryValueKey returned wrong len %d\n", len
);
715 basic_info
= HeapReAlloc(GetProcessHeap(), 0, basic_info
, len
);
716 status
= pNtQueryValueKey(key
, &ValName
, KeyValueBasicInformation
, basic_info
, len
, &len
);
717 ok(status
== STATUS_SUCCESS
, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status
);
718 ok(basic_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info
->TitleIndex
);
719 ok(basic_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", basic_info
->Type
);
720 ok(basic_info
->NameLength
== 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info
->NameLength
);
721 ok(len
== FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[basic_info
->NameLength
/sizeof(WCHAR
)]), "NtQueryValueKey returned wrong len %d\n", len
);
722 ok(!memcmp(basic_info
->Name
, ValName
.Buffer
, ValName
.Length
), "incorrect Name returned\n");
723 HeapFree(GetProcessHeap(), 0, basic_info
);
725 len
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
726 partial_info
= HeapAlloc(GetProcessHeap(), 0, len
);
727 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, partial_info
, len
, &len
);
728 ok(status
== STATUS_BUFFER_OVERFLOW
, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status
);
729 ok(partial_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info
->TitleIndex
);
730 ok(partial_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", partial_info
->Type
);
731 ok(partial_info
->DataLength
== 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info
->DataLength
);
732 ok(len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[partial_info
->DataLength
]), "NtQueryValueKey returned wrong len %d\n", len
);
734 partial_info
= HeapReAlloc(GetProcessHeap(), 0, partial_info
, len
);
735 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, partial_info
, len
, &len
);
736 ok(status
== STATUS_SUCCESS
, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status
);
737 ok(partial_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info
->TitleIndex
);
738 ok(partial_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", partial_info
->Type
);
739 ok(partial_info
->DataLength
== 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info
->DataLength
);
740 ok(len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[partial_info
->DataLength
]), "NtQueryValueKey returned wrong len %d\n", len
);
741 ok(*(DWORD
*)partial_info
->Data
== 711, "incorrect Data returned: 0x%x\n", *(DWORD
*)partial_info
->Data
);
742 HeapFree(GetProcessHeap(), 0, partial_info
);
744 len
= FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]);
745 full_info
= HeapAlloc(GetProcessHeap(), 0, len
);
746 status
= pNtQueryValueKey(key
, &ValName
, KeyValueFullInformation
, full_info
, len
, &len
);
747 ok(status
== STATUS_BUFFER_OVERFLOW
, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status
);
748 ok(full_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info
->TitleIndex
);
749 ok(full_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", full_info
->Type
);
750 ok(full_info
->DataLength
== 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info
->DataLength
);
751 ok(full_info
->NameLength
== 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info
->NameLength
);
752 ok(len
== FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]) + full_info
->DataLength
+ full_info
->NameLength
,
753 "NtQueryValueKey returned wrong len %d\n", len
);
754 len
= FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]) + full_info
->DataLength
+ full_info
->NameLength
;
756 full_info
= HeapReAlloc(GetProcessHeap(), 0, full_info
, len
);
757 status
= pNtQueryValueKey(key
, &ValName
, KeyValueFullInformation
, full_info
, len
, &len
);
758 ok(status
== STATUS_SUCCESS
, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status
);
759 ok(full_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info
->TitleIndex
);
760 ok(full_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", full_info
->Type
);
761 ok(full_info
->DataLength
== 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info
->DataLength
);
762 ok(full_info
->NameLength
== 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info
->NameLength
);
763 ok(!memcmp(full_info
->Name
, ValName
.Buffer
, ValName
.Length
), "incorrect Name returned\n");
764 ok(*(DWORD
*)((char *)full_info
+ full_info
->DataOffset
) == 711, "incorrect Data returned: 0x%x\n",
765 *(DWORD
*)((char *)full_info
+ full_info
->DataOffset
));
766 HeapFree(GetProcessHeap(), 0, full_info
);
768 pRtlFreeUnicodeString(&ValName
);
769 pRtlCreateUnicodeStringFromAsciiz(&ValName
, "stringtest");
771 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, NULL
, 0, &len
);
772 ok(status
== STATUS_BUFFER_TOO_SMALL
, "NtQueryValueKey should have returned STATUS_BUFFER_TOO_SMALL instead of 0x%08x\n", status
);
773 partial_info
= HeapAlloc(GetProcessHeap(), 0, len
+1);
774 memset(partial_info
, 0xbd, len
+1);
775 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, partial_info
, len
, &len
);
776 ok(status
== STATUS_SUCCESS
, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status
);
777 ok(partial_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info
->TitleIndex
);
778 ok(partial_info
->Type
== REG_SZ
, "NtQueryValueKey returned wrong Type %d\n", partial_info
->Type
);
779 ok(partial_info
->DataLength
== STR_TRUNC_SIZE
, "NtQueryValueKey returned wrong DataLength %d\n", partial_info
->DataLength
);
780 ok(!memcmp(partial_info
->Data
, stringW
, STR_TRUNC_SIZE
), "incorrect Data returned\n");
781 ok(*(partial_info
->Data
+STR_TRUNC_SIZE
) == 0xbd, "string overflowed %02x\n", *(partial_info
->Data
+STR_TRUNC_SIZE
));
784 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, partial_info
, 0, &len
);
785 ok(status
== STATUS_BUFFER_TOO_SMALL
, "NtQueryValueKey wrong status 0x%08x\n", status
);
786 ok(len
== expected
, "NtQueryValueKey wrong len %u\n", len
);
787 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, partial_info
, 1, &len
);
788 ok(status
== STATUS_BUFFER_TOO_SMALL
, "NtQueryValueKey wrong status 0x%08x\n", status
);
789 ok(len
== expected
, "NtQueryValueKey wrong len %u\n", len
);
790 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, partial_info
, FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
) - 1, &len
);
791 ok(status
== STATUS_BUFFER_TOO_SMALL
, "NtQueryValueKey wrong status 0x%08x\n", status
);
792 ok(len
== expected
, "NtQueryValueKey wrong len %u\n", len
);
793 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, partial_info
, FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
), &len
);
794 ok(status
== STATUS_BUFFER_OVERFLOW
, "NtQueryValueKey wrong status 0x%08x\n", status
);
795 ok(len
== expected
, "NtQueryValueKey wrong len %u\n", len
);
797 HeapFree(GetProcessHeap(), 0, partial_info
);
798 pRtlFreeUnicodeString(&ValName
);
800 pRtlCreateUnicodeStringFromAsciiz(&ValName
, "custtest");
801 status
= pNtSetValueKey(key
, &ValName
, 0, 0xff00ff00, NULL
, 0);
802 ok(status
== STATUS_SUCCESS
, "NtSetValueKey Failed: 0x%08x\n", status
);
804 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, &pi
, sizeof(pi
), &len
);
805 ok(status
== STATUS_SUCCESS
, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status
);
806 ok(pi
.Type
== 0xff00ff00, "Type=%x\n", pi
.Type
);
807 ok(pi
.DataLength
== 0, "DataLength=%u\n", pi
.DataLength
);
808 pRtlFreeUnicodeString(&ValName
);
813 static void test_NtDeleteKey(void)
817 OBJECT_ATTRIBUTES attr
;
818 ACCESS_MASK am
= KEY_ALL_ACCESS
;
820 status
= pNtDeleteKey(NULL
);
821 ok(status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status
);
823 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
824 status
= pNtOpenKey(&hkey
, am
, &attr
);
825 ok(status
== STATUS_SUCCESS
, "NtOpenKey Failed: 0x%08x\n", status
);
827 status
= pNtDeleteKey(hkey
);
828 ok(status
== STATUS_SUCCESS
, "NtDeleteKey Failed: 0x%08x\n", status
);
831 static void test_NtQueryLicenseKey(void)
833 static const WCHAR emptyW
[] = {'E','M','P','T','Y',0};
840 if (!pNtQueryLicenseValue
)
842 win_skip("NtQueryLicenseValue not found, skipping tests\n");
848 memset(&name
, 0, sizeof(name
));
849 status
= pNtQueryLicenseValue(&name
, &type
, buffer
, sizeof(buffer
), &len
);
850 ok(status
== STATUS_INVALID_PARAMETER
, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status
);
851 ok(type
== 0xdead, "expected unmodified value for type, got %u\n", type
);
852 ok(len
== 0xbeef, "expected unmodified value for len, got %u\n", len
);
854 /* test with empty key */
855 pRtlCreateUnicodeStringFromAsciiz(&name
, "");
859 status
= pNtQueryLicenseValue(NULL
, &type
, buffer
, sizeof(buffer
), &len
);
860 ok(status
== STATUS_INVALID_PARAMETER
, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status
);
861 ok(type
== 0xdead, "expected unmodified value for type, got %u\n", type
);
862 ok(len
== 0xbeef, "expected unmodified value for len, got %u\n", len
);
865 status
= pNtQueryLicenseValue(&name
, &type
, buffer
, sizeof(buffer
), NULL
);
866 ok(status
== STATUS_INVALID_PARAMETER
, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status
);
867 ok(type
== 0xdead, "expected unmodified value for type, got %u\n", type
);
870 status
= pNtQueryLicenseValue(&name
, NULL
, buffer
, sizeof(buffer
), &len
);
871 ok(status
== STATUS_INVALID_PARAMETER
, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status
);
872 ok(len
== 0xbeef, "expected unmodified value for len, got %u\n", len
);
876 status
= pNtQueryLicenseValue(&name
, &type
, buffer
, sizeof(buffer
), &len
);
877 ok(status
== STATUS_INVALID_PARAMETER
, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status
);
878 ok(type
== 0xdead, "expected unmodified value for type, got %u\n", type
);
879 ok(len
== 0xbeef, "expected unmodified value for len, got %u\n", len
);
881 pRtlFreeUnicodeString(&name
);
883 /* test with nonexistent licence key */
884 pRtlCreateUnicodeStringFromAsciiz(&name
, "Nonexistent-License-Value");
888 status
= pNtQueryLicenseValue(NULL
, &type
, buffer
, sizeof(buffer
), &len
);
889 ok(status
== STATUS_INVALID_PARAMETER
, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status
);
890 ok(type
== 0xdead, "expected unmodified value for type, got %u\n", type
);
891 ok(len
== 0xbeef, "expected unmodified value for len, got %u\n", len
);
894 status
= pNtQueryLicenseValue(&name
, &type
, buffer
, sizeof(buffer
), NULL
);
895 ok(status
== STATUS_INVALID_PARAMETER
, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status
);
896 ok(type
== 0xdead, "expected unmodified value for type, got %u\n", type
);
899 status
= pNtQueryLicenseValue(&name
, NULL
, buffer
, sizeof(buffer
), &len
);
900 ok(status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtQueryLicenseValue returned %08x, expected STATUS_OBJECT_NAME_NOT_FOUND\n", status
);
901 ok(len
== 0xbeef, "expected unmodified value for len, got %u\n", len
);
905 status
= pNtQueryLicenseValue(&name
, &type
, buffer
, sizeof(buffer
), &len
);
906 ok(status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtQueryLicenseValue unexpected succeeded\n");
907 ok(type
== 0xdead, "expected unmodified value for type, got %u\n", type
);
908 ok(len
== 0xbeef, "expected unmodified value for len, got %u\n", len
);
910 pRtlFreeUnicodeString(&name
);
912 /* test with REG_SZ license key */
913 pRtlCreateUnicodeStringFromAsciiz(&name
, "Kernel-MUI-Language-Allowed");
917 status
= pNtQueryLicenseValue(NULL
, &type
, buffer
, sizeof(buffer
), &len
);
918 ok(status
== STATUS_INVALID_PARAMETER
, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status
);
919 ok(type
== 0xdead, "expected unmodified value for type, got %u\n", type
);
920 ok(len
== 0xbeef, "expected unmodified value for len, got %u\n", len
);
923 status
= pNtQueryLicenseValue(&name
, &type
, buffer
, sizeof(buffer
), NULL
);
924 ok(status
== STATUS_INVALID_PARAMETER
, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status
);
925 ok(type
== 0xdead, "expected unmodified value for type, got %u\n", type
);
929 status
= pNtQueryLicenseValue(&name
, &type
, buffer
, 0, &len
);
930 ok(status
== STATUS_BUFFER_TOO_SMALL
, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status
);
931 ok(type
== REG_SZ
, "expected type = REG_SZ, got %u\n", type
);
932 ok(len
== sizeof(emptyW
), "expected len = %u, got %u\n", (DWORD
)sizeof(emptyW
), len
);
935 status
= pNtQueryLicenseValue(&name
, NULL
, buffer
, 0, &len
);
936 ok(status
== STATUS_BUFFER_TOO_SMALL
, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status
);
937 ok(len
== sizeof(emptyW
), "expected len = %u, got %u\n", (DWORD
)sizeof(emptyW
), len
);
941 memset(buffer
, 0x11, sizeof(buffer
));
942 status
= pNtQueryLicenseValue(&name
, &type
, buffer
, sizeof(buffer
), &len
);
943 ok(status
== STATUS_SUCCESS
, "NtQueryLicenseValue returned %08x, expected STATUS_SUCCESS\n", status
);
944 ok(type
== REG_SZ
, "expected type = REG_SZ, got %u\n", type
);
945 ok(len
== sizeof(emptyW
), "expected len = %u, got %u\n", (DWORD
)sizeof(emptyW
), len
);
946 ok(!memcmp(buffer
, emptyW
, sizeof(emptyW
)), "unexpected buffer content\n");
950 memset(buffer
, 0x11, sizeof(buffer
));
951 status
= pNtQueryLicenseValue(&name
, &type
, buffer
, 2, &len
);
952 ok(status
== STATUS_BUFFER_TOO_SMALL
, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status
);
953 ok(type
== REG_SZ
, "expected type REG_SZ, got %u\n", type
);
954 ok(len
== sizeof(emptyW
), "expected len = %u, got %u\n", (DWORD
)sizeof(emptyW
), len
);
955 ok(buffer
[0] == 0x1111, "expected buffer[0] = 0x1111, got %u\n", buffer
[0]);
957 pRtlFreeUnicodeString(&name
);
959 /* test with REG_DWORD license key */
960 pRtlCreateUnicodeStringFromAsciiz(&name
, "Kernel-MUI-Number-Allowed");
964 status
= pNtQueryLicenseValue(NULL
, &type
, &value
, sizeof(value
), &len
);
965 ok(status
== STATUS_INVALID_PARAMETER
, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status
);
966 ok(type
== 0xdead, "expected unmodified value for type, got %u\n", type
);
967 ok(len
== 0xbeef, "expected unmodified value for len, got %u\n", len
);
970 status
= pNtQueryLicenseValue(&name
, &type
, &value
, sizeof(value
), NULL
);
971 ok(status
== STATUS_INVALID_PARAMETER
, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status
);
972 ok(type
== 0xdead, "expected unmodified value for type, got %u\n", type
);
976 status
= pNtQueryLicenseValue(&name
, &type
, &value
, 0, &len
);
977 ok(status
== STATUS_BUFFER_TOO_SMALL
, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status
);
978 ok(type
== REG_DWORD
, "expected type = REG_DWORD, got %u\n", type
);
979 ok(len
== sizeof(value
), "expected len = %u, got %u\n", (DWORD
)sizeof(value
), len
);
982 status
= pNtQueryLicenseValue(&name
, NULL
, &value
, 0, &len
);
983 ok(status
== STATUS_BUFFER_TOO_SMALL
, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status
);
984 ok(len
== sizeof(value
), "expected len = %u, got %u\n", (DWORD
)sizeof(value
), len
);
989 status
= pNtQueryLicenseValue(&name
, &type
, &value
, sizeof(value
), &len
);
990 ok(status
== STATUS_SUCCESS
, "NtQueryLicenseValue returned %08x, expected STATUS_SUCCESS\n", status
);
991 ok(type
== REG_DWORD
, "expected type = REG_DWORD, got %u\n", type
);
992 ok(len
== sizeof(value
), "expected len = %u, got %u\n", (DWORD
)sizeof(value
), len
);
993 ok(value
!= 0xdeadbeef, "expected value != 0xdeadbeef\n");
997 status
= pNtQueryLicenseValue(&name
, &type
, &value
, 2, &len
);
998 ok(status
== STATUS_BUFFER_TOO_SMALL
, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status
);
999 ok(type
== REG_DWORD
, "expected type REG_DWORD, got %u\n", type
);
1000 ok(len
== sizeof(value
), "expected len = %u, got %u\n", (DWORD
)sizeof(value
), len
);
1002 pRtlFreeUnicodeString(&name
);
1005 static void test_RtlpNtQueryValueKey(void)
1009 status
= pRtlpNtQueryValueKey(NULL
, NULL
, NULL
, NULL
, NULL
);
1010 ok(status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status
);
1013 static void test_symlinks(void)
1015 static const WCHAR linkW
[] = {'l','i','n','k',0};
1016 static const WCHAR valueW
[] = {'v','a','l','u','e',0};
1017 static const WCHAR symlinkW
[] = {'S','y','m','b','o','l','i','c','L','i','n','k','V','a','l','u','e',0};
1018 static const WCHAR targetW
[] = {'\\','t','a','r','g','e','t',0};
1019 static UNICODE_STRING null_str
;
1021 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
1023 UNICODE_STRING symlink_str
, link_str
, target_str
, value_str
;
1024 HANDLE root
, key
, link
;
1025 OBJECT_ATTRIBUTES attr
;
1027 DWORD target_len
, len
, dw
;
1029 pRtlInitUnicodeString( &link_str
, linkW
);
1030 pRtlInitUnicodeString( &symlink_str
, symlinkW
);
1031 pRtlInitUnicodeString( &target_str
, targetW
+ 1 );
1032 pRtlInitUnicodeString( &value_str
, valueW
);
1034 target_len
= winetestpath
.Length
+ sizeof(targetW
);
1035 target
= pRtlAllocateHeap( GetProcessHeap(), 0, target_len
+ sizeof(targetW
) /*for loop test*/ );
1036 memcpy( target
, winetestpath
.Buffer
, winetestpath
.Length
);
1037 memcpy( target
+ winetestpath
.Length
/sizeof(WCHAR
), targetW
, sizeof(targetW
) );
1039 attr
.Length
= sizeof(attr
);
1040 attr
.RootDirectory
= 0;
1041 attr
.Attributes
= 0;
1042 attr
.ObjectName
= &winetestpath
;
1043 attr
.SecurityDescriptor
= NULL
;
1044 attr
.SecurityQualityOfService
= NULL
;
1046 status
= pNtCreateKey( &root
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1047 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1049 attr
.RootDirectory
= root
;
1050 attr
.ObjectName
= &link_str
;
1051 status
= pNtCreateKey( &link
, KEY_ALL_ACCESS
, &attr
, 0, 0, REG_OPTION_CREATE_LINK
, 0 );
1052 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1054 /* REG_SZ is not allowed */
1055 status
= pNtSetValueKey( link
, &symlink_str
, 0, REG_SZ
, target
, target_len
);
1056 ok( status
== STATUS_ACCESS_DENIED
, "NtSetValueKey wrong status 0x%08x\n", status
);
1057 status
= pNtSetValueKey( link
, &symlink_str
, 0, REG_LINK
, target
, target_len
- sizeof(WCHAR
) );
1058 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
1059 /* other values are not allowed */
1060 status
= pNtSetValueKey( link
, &link_str
, 0, REG_LINK
, target
, target_len
- sizeof(WCHAR
) );
1061 ok( status
== STATUS_ACCESS_DENIED
, "NtSetValueKey wrong status 0x%08x\n", status
);
1063 /* try opening the target through the link */
1065 attr
.ObjectName
= &link_str
;
1066 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
1067 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtOpenKey wrong status 0x%08x\n", status
);
1069 attr
.ObjectName
= &target_str
;
1070 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1071 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1074 status
= pNtSetValueKey( key
, &value_str
, 0, REG_DWORD
, &dw
, sizeof(dw
) );
1075 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
1078 attr
.ObjectName
= &link_str
;
1079 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
1080 ok( status
== STATUS_SUCCESS
, "NtOpenKey failed: 0x%08x\n", status
);
1082 len
= sizeof(buffer
);
1083 status
= pNtQueryValueKey( key
, &value_str
, KeyValuePartialInformation
, info
, len
, &len
);
1084 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
1085 ok( len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,Data
) + sizeof(DWORD
), "wrong len %u\n", len
);
1087 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
1088 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtQueryValueKey failed: 0x%08x\n", status
);
1090 /* REG_LINK can be created in non-link keys */
1091 status
= pNtSetValueKey( key
, &symlink_str
, 0, REG_LINK
, target
, target_len
- sizeof(WCHAR
) );
1092 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
1093 len
= sizeof(buffer
);
1094 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
1095 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
1096 ok( len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,Data
) + target_len
- sizeof(WCHAR
),
1097 "wrong len %u\n", len
);
1098 status
= pNtDeleteValueKey( key
, &symlink_str
);
1099 ok( status
== STATUS_SUCCESS
, "NtDeleteValueKey failed: 0x%08x\n", status
);
1103 attr
.Attributes
= 0;
1104 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1105 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1107 len
= sizeof(buffer
);
1108 status
= pNtQueryValueKey( key
, &value_str
, KeyValuePartialInformation
, info
, len
, &len
);
1109 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
1110 ok( len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,Data
) + sizeof(DWORD
), "wrong len %u\n", len
);
1112 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
1113 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtQueryValueKey failed: 0x%08x\n", status
);
1116 /* now open the symlink itself */
1118 attr
.RootDirectory
= root
;
1119 attr
.Attributes
= OBJ_OPENLINK
;
1120 attr
.ObjectName
= &link_str
;
1121 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
1122 ok( status
== STATUS_SUCCESS
, "NtOpenKey failed: 0x%08x\n", status
);
1124 len
= sizeof(buffer
);
1125 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
1126 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
1127 ok( len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,Data
) + target_len
- sizeof(WCHAR
),
1128 "wrong len %u\n", len
);
1131 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1132 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1133 len
= sizeof(buffer
);
1134 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
1135 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
1136 ok( len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,Data
) + target_len
- sizeof(WCHAR
),
1137 "wrong len %u\n", len
);
1140 if (0) /* crashes the Windows kernel on some Vista systems */
1142 /* reopen the link from itself */
1144 attr
.RootDirectory
= link
;
1145 attr
.Attributes
= OBJ_OPENLINK
;
1146 attr
.ObjectName
= &null_str
;
1147 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
1148 ok( status
== STATUS_SUCCESS
, "NtOpenKey failed: 0x%08x\n", status
);
1149 len
= sizeof(buffer
);
1150 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
1151 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
1152 ok( len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,Data
) + target_len
- sizeof(WCHAR
),
1153 "wrong len %u\n", len
);
1156 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1157 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1158 len
= sizeof(buffer
);
1159 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
1160 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
1161 ok( len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,Data
) + target_len
- sizeof(WCHAR
),
1162 "wrong len %u\n", len
);
1166 if (0) /* crashes the Windows kernel in most versions */
1168 attr
.RootDirectory
= link
;
1169 attr
.Attributes
= 0;
1170 attr
.ObjectName
= &null_str
;
1171 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
1172 ok( status
== STATUS_SUCCESS
, "NtOpenKey failed: 0x%08x\n", status
);
1173 len
= sizeof(buffer
);
1174 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
1175 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtQueryValueKey failed: 0x%08x\n", status
);
1178 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1179 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1180 len
= sizeof(buffer
);
1181 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
1182 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtQueryValueKey failed: 0x%08x\n", status
);
1186 /* target with terminating null doesn't work */
1187 status
= pNtSetValueKey( link
, &symlink_str
, 0, REG_LINK
, target
, target_len
);
1188 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
1189 attr
.RootDirectory
= root
;
1190 attr
.Attributes
= 0;
1191 attr
.ObjectName
= &link_str
;
1192 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
1193 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtOpenKey wrong status 0x%08x\n", status
);
1195 /* relative symlink, works only on win2k */
1196 status
= pNtSetValueKey( link
, &symlink_str
, 0, REG_LINK
, targetW
+1, sizeof(targetW
)-2*sizeof(WCHAR
) );
1197 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
1198 attr
.ObjectName
= &link_str
;
1199 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
1200 ok( status
== STATUS_SUCCESS
|| status
== STATUS_OBJECT_NAME_NOT_FOUND
,
1201 "NtOpenKey wrong status 0x%08x\n", status
);
1203 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, REG_OPTION_CREATE_LINK
, 0 );
1204 ok( status
== STATUS_OBJECT_NAME_COLLISION
, "NtCreateKey failed: 0x%08x\n", status
);
1206 status
= pNtDeleteKey( link
);
1207 ok( status
== STATUS_SUCCESS
, "NtDeleteKey failed: 0x%08x\n", status
);
1210 attr
.ObjectName
= &target_str
;
1211 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
1212 ok( status
== STATUS_SUCCESS
, "NtOpenKey failed: 0x%08x\n", status
);
1213 status
= pNtDeleteKey( key
);
1214 ok( status
== STATUS_SUCCESS
, "NtDeleteKey failed: 0x%08x\n", status
);
1219 status
= pNtCreateKey( &link
, KEY_ALL_ACCESS
, &attr
, 0, 0, REG_OPTION_CREATE_LINK
, 0 );
1220 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1221 memcpy( target
+ target_len
/sizeof(WCHAR
) - 1, targetW
, sizeof(targetW
) );
1222 status
= pNtSetValueKey( link
, &symlink_str
, 0, REG_LINK
,
1223 target
, target_len
+ sizeof(targetW
) - sizeof(WCHAR
) );
1224 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
1226 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
1227 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
|| status
== STATUS_NAME_TOO_LONG
,
1228 "NtOpenKey failed: 0x%08x\n", status
);
1230 attr
.Attributes
= OBJ_OPENLINK
;
1231 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
1232 ok( status
== STATUS_SUCCESS
, "NtOpenKey failed: 0x%08x\n", status
);
1235 status
= pNtDeleteKey( link
);
1236 ok( status
== STATUS_SUCCESS
, "NtDeleteKey failed: 0x%08x\n", status
);
1239 status
= pNtDeleteKey( root
);
1240 ok( status
== STATUS_SUCCESS
, "NtDeleteKey failed: 0x%08x\n", status
);
1243 pRtlFreeHeap(GetProcessHeap(), 0, target
);
1246 static WCHAR valueW
[] = {'v','a','l','u','e'};
1247 static UNICODE_STRING value_str
= { sizeof(valueW
), sizeof(valueW
), valueW
};
1248 static const DWORD ptr_size
= 8 * sizeof(void*);
1250 static DWORD
get_key_value( HANDLE root
, const char *name
, DWORD flags
)
1254 OBJECT_ATTRIBUTES attr
;
1257 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)tmp
;
1258 DWORD dw
, len
= sizeof(tmp
);
1260 attr
.Length
= sizeof(attr
);
1261 attr
.RootDirectory
= root
;
1262 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1263 attr
.ObjectName
= &str
;
1264 attr
.SecurityDescriptor
= NULL
;
1265 attr
.SecurityQualityOfService
= NULL
;
1266 pRtlCreateUnicodeStringFromAsciiz( &str
, name
);
1268 status
= pNtCreateKey( &key
, flags
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1269 if (status
== STATUS_OBJECT_NAME_NOT_FOUND
) return 0;
1270 ok( status
== STATUS_SUCCESS
, "%08x: NtCreateKey failed: 0x%08x\n", flags
, status
);
1272 status
= pNtQueryValueKey( key
, &value_str
, KeyValuePartialInformation
, info
, len
, &len
);
1273 if (status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1277 ok( status
== STATUS_SUCCESS
, "%08x: NtQueryValueKey failed: 0x%08x\n", flags
, status
);
1278 dw
= *(DWORD
*)info
->Data
;
1281 pRtlFreeUnicodeString( &str
);
1285 static void _check_key_value( int line
, HANDLE root
, const char *name
, DWORD flags
, DWORD expect
)
1287 DWORD dw
= get_key_value( root
, name
, flags
);
1288 ok_(__FILE__
,line
)( dw
== expect
, "%08x: wrong value %u/%u\n", flags
, dw
, expect
);
1290 #define check_key_value(root,name,flags,expect) _check_key_value( __LINE__, root, name, flags, expect )
1292 static void test_redirection(void)
1294 static const WCHAR softwareW
[] = {'\\','R','e','g','i','s','t','r','y','\\',
1295 'M','a','c','h','i','n','e','\\',
1296 'S','o','f','t','w','a','r','e',0};
1297 static const WCHAR wownodeW
[] = {'\\','R','e','g','i','s','t','r','y','\\',
1298 'M','a','c','h','i','n','e','\\',
1299 'S','o','f','t','w','a','r','e','\\',
1300 'W','o','w','6','4','3','2','N','o','d','e',0};
1301 static const WCHAR wine64W
[] = {'\\','R','e','g','i','s','t','r','y','\\',
1302 'M','a','c','h','i','n','e','\\',
1303 'S','o','f','t','w','a','r','e','\\',
1305 static const WCHAR wine32W
[] = {'\\','R','e','g','i','s','t','r','y','\\',
1306 'M','a','c','h','i','n','e','\\',
1307 'S','o','f','t','w','a','r','e','\\',
1308 'W','o','w','6','4','3','2','N','o','d','e','\\',
1310 static const WCHAR key64W
[] = {'\\','R','e','g','i','s','t','r','y','\\',
1311 'M','a','c','h','i','n','e','\\',
1312 'S','o','f','t','w','a','r','e','\\',
1313 'W','i','n','e','\\','W','i','n','e','t','e','s','t',0};
1314 static const WCHAR key32W
[] = {'\\','R','e','g','i','s','t','r','y','\\',
1315 'M','a','c','h','i','n','e','\\',
1316 'S','o','f','t','w','a','r','e','\\',
1317 'W','o','w','6','4','3','2','N','o','d','e','\\',
1318 'W','i','n','e','\\', 'W','i','n','e','t','e','s','t',0};
1319 static const WCHAR classes64W
[] = {'\\','R','e','g','i','s','t','r','y','\\',
1320 'M','a','c','h','i','n','e','\\',
1321 'S','o','f','t','w','a','r','e','\\',
1322 'C','l','a','s','s','e','s','\\',
1324 static const WCHAR classes32W
[] = {'\\','R','e','g','i','s','t','r','y','\\',
1325 'M','a','c','h','i','n','e','\\',
1326 'S','o','f','t','w','a','r','e','\\',
1327 'C','l','a','s','s','e','s','\\',
1328 'W','o','w','6','4','3','2','N','o','d','e','\\',
1331 OBJECT_ATTRIBUTES attr
;
1334 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
1336 HANDLE key
, root32
, root64
, key32
, key64
;
1337 BOOL is_vista
= FALSE
;
1341 ULONG is_wow64
, len
;
1342 if (pNtQueryInformationProcess( GetCurrentProcess(), ProcessWow64Information
,
1343 &is_wow64
, sizeof(is_wow64
), &len
) ||
1346 trace( "Not on Wow64, no redirection\n" );
1351 attr
.Length
= sizeof(attr
);
1352 attr
.RootDirectory
= 0;
1353 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1354 attr
.ObjectName
= &str
;
1355 attr
.SecurityDescriptor
= NULL
;
1356 attr
.SecurityQualityOfService
= NULL
;
1358 pRtlInitUnicodeString( &str
, wine64W
);
1359 status
= pNtCreateKey( &root64
, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1360 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1362 pRtlInitUnicodeString( &str
, wine32W
);
1363 status
= pNtCreateKey( &root32
, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1364 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1366 pRtlInitUnicodeString( &str
, key64W
);
1367 status
= pNtCreateKey( &key64
, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1368 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1370 pRtlInitUnicodeString( &str
, key32W
);
1371 status
= pNtCreateKey( &key32
, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1372 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1375 status
= pNtSetValueKey( key64
, &value_str
, 0, REG_DWORD
, &dw
, sizeof(dw
) );
1376 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
1379 status
= pNtSetValueKey( key32
, &value_str
, 0, REG_DWORD
, &dw
, sizeof(dw
) );
1380 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
1382 len
= sizeof(buffer
);
1383 status
= pNtQueryValueKey( key32
, &value_str
, KeyValuePartialInformation
, info
, len
, &len
);
1384 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
1385 dw
= *(DWORD
*)info
->Data
;
1386 ok( dw
== 32, "wrong value %u\n", dw
);
1388 len
= sizeof(buffer
);
1389 status
= pNtQueryValueKey( key64
, &value_str
, KeyValuePartialInformation
, info
, len
, &len
);
1390 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
1391 dw
= *(DWORD
*)info
->Data
;
1392 ok( dw
== 64, "wrong value %u\n", dw
);
1394 pRtlInitUnicodeString( &str
, softwareW
);
1395 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1396 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1400 /* the Vista mechanism allows opening Wow6432Node from a 32-bit key too */
1401 /* the new (and simpler) Win7 mechanism doesn't */
1402 if (get_key_value( key
, "Wow6432Node\\Wine\\Winetest", 0 ) == 32)
1404 trace( "using Vista-style Wow6432Node handling\n" );
1407 check_key_value( key
, "Wine\\Winetest", 0, 32 );
1408 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 32 );
1409 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1410 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", 0, is_vista
? 32 : 0 );
1411 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 0 );
1412 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY
, is_vista
? 32 : 0 );
1416 check_key_value( key
, "Wine\\Winetest", 0, 64 );
1417 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", 0, 32 );
1423 status
= pNtCreateKey( &key
, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1424 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1425 dw
= get_key_value( key
, "Wine\\Winetest", 0 );
1426 ok( dw
== 64 || broken(dw
== 32) /* xp64 */, "wrong value %u\n", dw
);
1427 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, 64 );
1428 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1429 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", 0, 32 );
1430 dw
= get_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY
);
1431 ok( dw
== 32 || broken(dw
== 64) /* xp64 */, "wrong value %u\n", dw
);
1432 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1435 status
= pNtCreateKey( &key
, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1436 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1437 check_key_value( key
, "Wine\\Winetest", 0, 32 );
1438 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 32 );
1439 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1440 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", 0, is_vista
? 32 : 0 );
1441 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 0 );
1442 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY
, is_vista
? 32 : 0 );
1446 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", 0, ptr_size
);
1447 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", 0, 32 );
1450 /* KEY_WOW64 flags have no effect on 64-bit */
1451 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_64KEY
, 64 );
1452 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_32KEY
, 64 );
1453 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY
, 32 );
1454 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1458 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_64KEY
, 64 );
1459 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1460 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 32 );
1461 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1464 pRtlInitUnicodeString( &str
, wownodeW
);
1465 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1466 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1467 check_key_value( key
, "Wine\\Winetest", 0, 32 );
1468 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, (ptr_size
== 64) ? 32 : (is_vista
? 64 : 32) );
1469 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1474 status
= pNtCreateKey( &key
, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1475 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1476 dw
= get_key_value( key
, "Wine\\Winetest", 0 );
1477 ok( dw
== (is_vista
? 64 : 32) || broken(dw
== 32) /* xp64 */, "wrong value %u\n", dw
);
1478 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 32 );
1479 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1482 status
= pNtCreateKey( &key
, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1483 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1484 check_key_value( key
, "Wine\\Winetest", 0, 32 );
1485 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 32 );
1486 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1490 pRtlInitUnicodeString( &str
, wine32W
);
1491 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1492 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1493 check_key_value( key
, "Winetest", 0, 32 );
1494 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, (ptr_size
== 32 && is_vista
) ? 64 : 32 );
1495 check_key_value( key
, "Winetest", KEY_WOW64_32KEY
, 32 );
1500 status
= pNtCreateKey( &key
, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1501 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1502 dw
= get_key_value( key
, "Winetest", 0 );
1503 ok( dw
== 32 || (is_vista
&& dw
== 64), "wrong value %u\n", dw
);
1504 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 32 );
1505 check_key_value( key
, "Winetest", KEY_WOW64_32KEY
, 32 );
1508 status
= pNtCreateKey( &key
, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1509 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1510 check_key_value( key
, "Winetest", 0, 32 );
1511 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 32 );
1512 check_key_value( key
, "Winetest", KEY_WOW64_32KEY
, 32 );
1516 pRtlInitUnicodeString( &str
, wine64W
);
1517 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1518 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1519 check_key_value( key
, "Winetest", 0, ptr_size
);
1520 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : ptr_size
);
1521 check_key_value( key
, "Winetest", KEY_WOW64_32KEY
, ptr_size
);
1526 status
= pNtCreateKey( &key
, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1527 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1528 dw
= get_key_value( key
, "Winetest", 0 );
1529 ok( dw
== 64 || broken(dw
== 32) /* xp64 */, "wrong value %u\n", dw
);
1530 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, 64 );
1531 dw
= get_key_value( key
, "Winetest", KEY_WOW64_32KEY
);
1532 todo_wine
ok( dw
== 32, "wrong value %u\n", dw
);
1535 status
= pNtCreateKey( &key
, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1536 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1537 check_key_value( key
, "Winetest", 0, 32 );
1538 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 32 );
1539 check_key_value( key
, "Winetest", KEY_WOW64_32KEY
, 32 );
1543 status
= pNtDeleteKey( key32
);
1544 ok( status
== STATUS_SUCCESS
, "NtDeleteKey failed: 0x%08x\n", status
);
1547 status
= pNtDeleteKey( key64
);
1548 ok( status
== STATUS_SUCCESS
, "NtDeleteKey failed: 0x%08x\n", status
);
1551 pNtDeleteKey( root32
);
1553 pNtDeleteKey( root64
);
1556 /* Software\Classes is shared/reflected so behavior is different */
1558 pRtlInitUnicodeString( &str
, classes64W
);
1559 status
= pNtCreateKey( &key64
, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1560 if (status
== STATUS_ACCESS_DENIED
)
1562 skip("Not authorized to modify the Classes key\n");
1565 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1567 pRtlInitUnicodeString( &str
, classes32W
);
1568 status
= pNtCreateKey( &key32
, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1569 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1572 status
= pNtSetValueKey( key64
, &value_str
, 0, REG_DWORD
, &dw
, sizeof(dw
) );
1573 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
1577 status
= pNtSetValueKey( key32
, &value_str
, 0, REG_DWORD
, &dw
, sizeof(dw
) );
1578 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
1581 pRtlInitUnicodeString( &str
, classes64W
);
1582 status
= pNtCreateKey( &key64
, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1583 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1584 len
= sizeof(buffer
);
1585 status
= pNtQueryValueKey( key64
, &value_str
, KeyValuePartialInformation
, info
, len
, &len
);
1586 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
1587 dw
= *(DWORD
*)info
->Data
;
1588 ok( dw
== ptr_size
, "wrong value %u\n", dw
);
1590 pRtlInitUnicodeString( &str
, classes32W
);
1591 status
= pNtCreateKey( &key32
, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1592 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1593 len
= sizeof(buffer
);
1594 status
= pNtQueryValueKey( key32
, &value_str
, KeyValuePartialInformation
, info
, len
, &len
);
1595 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
1596 dw
= *(DWORD
*)info
->Data
;
1597 ok( dw
== 32, "wrong value %u\n", dw
);
1599 pNtDeleteKey( key32
);
1601 pNtDeleteKey( key64
);
1605 static void test_long_value_name(void)
1608 NTSTATUS status
, expected
;
1609 OBJECT_ATTRIBUTES attr
;
1610 UNICODE_STRING ValName
;
1613 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
1614 status
= pNtOpenKey(&key
, KEY_WRITE
|KEY_READ
, &attr
);
1615 ok(status
== STATUS_SUCCESS
, "NtOpenKey Failed: 0x%08x\n", status
);
1617 ValName
.MaximumLength
= 0xfffc;
1618 ValName
.Length
= ValName
.MaximumLength
- sizeof(WCHAR
);
1619 ValName
.Buffer
= HeapAlloc(GetProcessHeap(), 0, ValName
.MaximumLength
);
1620 for (i
= 0; i
< ValName
.Length
/ sizeof(WCHAR
); i
++)
1621 ValName
.Buffer
[i
] = 'a';
1622 ValName
.Buffer
[i
] = 0;
1624 status
= pNtDeleteValueKey(key
, &ValName
);
1625 ok(status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtDeleteValueKey with nonexistent long value name returned 0x%08x\n", status
);
1626 status
= pNtSetValueKey(key
, &ValName
, 0, REG_DWORD
, &i
, sizeof(i
));
1627 ok(status
== STATUS_INVALID_PARAMETER
|| broken(status
== STATUS_SUCCESS
) /* nt4 */,
1628 "NtSetValueKey with long value name returned 0x%08x\n", status
);
1629 expected
= (status
== STATUS_SUCCESS
) ? STATUS_SUCCESS
: STATUS_OBJECT_NAME_NOT_FOUND
;
1630 status
= pNtDeleteValueKey(key
, &ValName
);
1631 ok(status
== expected
, "NtDeleteValueKey with long value name returned 0x%08x\n", status
);
1633 status
= pNtQueryValueKey(key
, &ValName
, KeyValueBasicInformation
, NULL
, 0, &i
);
1634 ok(status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtQueryValueKey with nonexistent long value name returned 0x%08x\n", status
);
1636 pRtlFreeUnicodeString(&ValName
);
1640 static void test_NtQueryKey(void)
1642 HANDLE key
, subkey
, subkey2
;
1644 OBJECT_ATTRIBUTES attr
;
1646 KEY_NAME_INFORMATION
*info
= NULL
;
1647 KEY_CACHED_INFORMATION cached_info
;
1651 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
1652 status
= pNtOpenKey(&key
, KEY_READ
, &attr
);
1653 ok(status
== STATUS_SUCCESS
, "NtOpenKey Failed: 0x%08x\n", status
);
1655 status
= pNtQueryKey(key
, KeyNameInformation
, NULL
, 0, &length
);
1656 if (status
== STATUS_INVALID_PARAMETER
) {
1657 win_skip("KeyNameInformation is not supported\n");
1661 todo_wine
ok(status
== STATUS_BUFFER_TOO_SMALL
, "NtQueryKey Failed: 0x%08x\n", status
);
1662 info
= HeapAlloc(GetProcessHeap(), 0, length
);
1664 /* non-zero buffer size, but insufficient */
1665 status
= pNtQueryKey(key
, KeyNameInformation
, info
, sizeof(*info
), &len
);
1666 ok(status
== STATUS_BUFFER_OVERFLOW
, "NtQueryKey Failed: 0x%08x\n", status
);
1667 ok(length
== len
, "got %d, expected %d\n", len
, length
);
1668 ok(info
->NameLength
== winetestpath
.Length
, "got %d, expected %d\n",
1669 info
->NameLength
, winetestpath
.Length
);
1671 /* correct buffer size */
1672 status
= pNtQueryKey(key
, KeyNameInformation
, info
, length
, &len
);
1673 ok(status
== STATUS_SUCCESS
, "NtQueryKey Failed: 0x%08x\n", status
);
1674 ok(length
== len
, "got %d, expected %d\n", len
, length
);
1676 str
.Buffer
= info
->Name
;
1677 str
.Length
= info
->NameLength
;
1678 ok(pRtlCompareUnicodeString(&winetestpath
, &str
, TRUE
) == 0,
1679 "got %s, expected %s\n",
1680 wine_dbgstr_wn(str
.Buffer
, str
.Length
/sizeof(WCHAR
)),
1681 wine_dbgstr_wn(winetestpath
.Buffer
, winetestpath
.Length
/sizeof(WCHAR
)));
1683 HeapFree(GetProcessHeap(), 0, info
);
1685 attr
.RootDirectory
= key
;
1686 attr
.ObjectName
= &str
;
1687 pRtlCreateUnicodeStringFromAsciiz(&str
, "test_subkey");
1688 status
= pNtCreateKey(&subkey
, GENERIC_ALL
, &attr
, 0, 0, 0, 0);
1689 ok(status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1691 status
= pNtQueryKey(subkey
, KeyCachedInformation
, &cached_info
, sizeof(cached_info
), &len
);
1692 ok(status
== STATUS_SUCCESS
, "NtQueryKey Failed: 0x%08x\n", status
);
1694 if (status
== STATUS_SUCCESS
)
1696 ok(len
== sizeof(cached_info
), "got unexpected length %d\n", len
);
1697 ok(cached_info
.SubKeys
== 0, "cached_info.SubKeys = %u\n", cached_info
.SubKeys
);
1698 ok(cached_info
.MaxNameLen
== 0, "cached_info.MaxNameLen = %u\n", cached_info
.MaxNameLen
);
1699 ok(cached_info
.Values
== 0, "cached_info.Values = %u\n", cached_info
.Values
);
1700 ok(cached_info
.MaxValueNameLen
== 0, "cached_info.MaxValueNameLen = %u\n", cached_info
.MaxValueNameLen
);
1701 ok(cached_info
.MaxValueDataLen
== 0, "cached_info.MaxValueDataLen = %u\n", cached_info
.MaxValueDataLen
);
1702 ok(cached_info
.NameLength
== 22, "cached_info.NameLength = %u\n", cached_info
.NameLength
);
1705 attr
.RootDirectory
= subkey
;
1706 attr
.ObjectName
= &str
;
1707 pRtlCreateUnicodeStringFromAsciiz(&str
, "test_subkey2");
1708 status
= pNtCreateKey(&subkey2
, GENERIC_ALL
, &attr
, 0, 0, 0, 0);
1709 ok(status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1711 pRtlCreateUnicodeStringFromAsciiz(&str
, "val");
1713 status
= pNtSetValueKey( subkey
, &str
, 0, REG_DWORD
, &dw
, sizeof(dw
) );
1714 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
1716 status
= pNtQueryKey(subkey
, KeyCachedInformation
, &cached_info
, sizeof(cached_info
), &len
);
1717 ok(status
== STATUS_SUCCESS
, "NtQueryKey Failed: 0x%08x\n", status
);
1719 if (status
== STATUS_SUCCESS
)
1721 ok(len
== sizeof(cached_info
), "got unexpected length %d\n", len
);
1722 ok(cached_info
.SubKeys
== 1, "cached_info.SubKeys = %u\n", cached_info
.SubKeys
);
1723 ok(cached_info
.MaxNameLen
== 24, "cached_info.MaxNameLen = %u\n", cached_info
.MaxNameLen
);
1724 ok(cached_info
.Values
== 1, "cached_info.Values = %u\n", cached_info
.Values
);
1725 ok(cached_info
.MaxValueNameLen
== 6, "cached_info.MaxValueNameLen = %u\n", cached_info
.MaxValueNameLen
);
1726 ok(cached_info
.MaxValueDataLen
== 4, "cached_info.MaxValueDataLen = %u\n", cached_info
.MaxValueDataLen
);
1727 ok(cached_info
.NameLength
== 22, "cached_info.NameLength = %u\n", cached_info
.NameLength
);
1730 status
= pNtDeleteKey(subkey2
);
1731 ok(status
== STATUS_SUCCESS
, "NtDeleteSubkey failed: %x\n", status
);
1732 status
= pNtDeleteKey(subkey
);
1733 ok(status
== STATUS_SUCCESS
, "NtDeleteSubkey failed: %x\n", status
);
1740 static void test_notify(void)
1742 OBJECT_ATTRIBUTES attr
;
1743 LARGE_INTEGER timeout
;
1744 IO_STATUS_BLOCK iosb
;
1746 HANDLE key
, events
[2], subkey
;
1749 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
1750 status
= pNtOpenKey(&key
, KEY_ALL_ACCESS
, &attr
);
1751 ok(status
== STATUS_SUCCESS
, "NtOpenKey Failed: 0x%08x\n", status
);
1753 events
[0] = CreateEventW(NULL
, FALSE
, TRUE
, NULL
);
1754 ok(events
[0] != NULL
, "CreateEvent failed: %u\n", GetLastError());
1755 events
[1] = CreateEventW(NULL
, FALSE
, TRUE
, NULL
);
1756 ok(events
[1] != NULL
, "CreateEvent failed: %u\n", GetLastError());
1758 status
= pNtNotifyChangeKey(key
, events
[0], NULL
, NULL
, &iosb
, REG_NOTIFY_CHANGE_NAME
, FALSE
, NULL
, 0, TRUE
);
1759 ok(status
== STATUS_PENDING
, "NtNotifyChangeKey returned %x\n", status
);
1760 status
= pNtNotifyChangeKey(key
, events
[1], NULL
, NULL
, &iosb
, REG_NOTIFY_CHANGE_NAME
, FALSE
, NULL
, 0, TRUE
);
1761 ok(status
== STATUS_PENDING
, "NtNotifyChangeKey returned %x\n", status
);
1763 timeout
.QuadPart
= 0;
1764 status
= pNtWaitForSingleObject(events
[0], FALSE
, &timeout
);
1765 ok(status
== STATUS_TIMEOUT
, "NtWaitForSingleObject returned %x\n", status
);
1766 status
= pNtWaitForSingleObject(events
[1], FALSE
, &timeout
);
1767 ok(status
== STATUS_TIMEOUT
, "NtWaitForSingleObject returned %x\n", status
);
1769 attr
.RootDirectory
= key
;
1770 attr
.ObjectName
= &str
;
1772 pRtlCreateUnicodeStringFromAsciiz(&str
, "test_subkey");
1773 status
= pNtCreateKey(&subkey
, GENERIC_ALL
, &attr
, 0, 0, 0, 0);
1774 ok(status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1776 status
= pNtWaitForSingleObject(events
[0], FALSE
, &timeout
);
1777 todo_wine
ok(status
== STATUS_SUCCESS
, "NtWaitForSingleObject returned %x\n", status
);
1778 status
= pNtWaitForSingleObject(events
[1], FALSE
, &timeout
);
1779 ok(status
== STATUS_SUCCESS
, "NtWaitForSingleObject returned %x\n", status
);
1781 status
= pNtNotifyChangeKey(key
, events
[0], NULL
, NULL
, &iosb
, 0, FALSE
, NULL
, 0, TRUE
);
1782 ok(status
== STATUS_PENDING
, "NtNotifyChangeKey returned %x\n", status
);
1783 status
= pNtNotifyChangeKey(key
, events
[1], NULL
, NULL
, &iosb
, 0, FALSE
, NULL
, 0, TRUE
);
1784 ok(status
== STATUS_PENDING
, "NtNotifyChangeKey returned %x\n", status
);
1786 status
= pNtDeleteKey(subkey
);
1787 ok(status
== STATUS_SUCCESS
, "NtDeleteSubkey failed: %x\n", status
);
1789 status
= pNtWaitForSingleObject(events
[0], FALSE
, &timeout
);
1790 todo_wine
ok(status
== STATUS_SUCCESS
, "NtWaitForSingleObject returned %x\n", status
);
1791 status
= pNtWaitForSingleObject(events
[1], FALSE
, &timeout
);
1792 ok(status
== STATUS_SUCCESS
, "NtWaitForSingleObject returned %x\n", status
);
1796 status
= pNtNotifyChangeKey(key
, events
[0], NULL
, NULL
, &iosb
, 0, FALSE
, NULL
, 0, TRUE
);
1797 ok(status
== STATUS_PENDING
, "NtNotifyChangeKey returned %x\n", status
);
1798 status
= pNtNotifyChangeKey(key
, events
[1], NULL
, NULL
, &iosb
, 0, FALSE
, NULL
, 0, TRUE
);
1799 ok(status
== STATUS_PENDING
, "NtNotifyChangeKey returned %x\n", status
);
1803 status
= pNtWaitForSingleObject(events
[0], FALSE
, &timeout
);
1804 todo_wine
ok(status
== STATUS_SUCCESS
, "NtWaitForSingleObject returned %x\n", status
);
1805 status
= pNtWaitForSingleObject(events
[1], FALSE
, &timeout
);
1806 ok(status
== STATUS_SUCCESS
, "NtWaitForSingleObject returned %x\n", status
);
1808 if (pNtNotifyChangeMultipleKeys
)
1810 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
1811 status
= pNtOpenKey(&key
, KEY_ALL_ACCESS
, &attr
);
1812 ok(status
== STATUS_SUCCESS
, "NtOpenKey Failed: 0x%08x\n", status
);
1814 status
= pNtNotifyChangeMultipleKeys(key
, 0, NULL
, events
[0], NULL
, NULL
, &iosb
, REG_NOTIFY_CHANGE_NAME
, FALSE
, NULL
, 0, TRUE
);
1815 ok(status
== STATUS_PENDING
, "NtNotifyChangeKey returned %x\n", status
);
1817 timeout
.QuadPart
= 0;
1818 status
= pNtWaitForSingleObject(events
[0], FALSE
, &timeout
);
1819 ok(status
== STATUS_TIMEOUT
, "NtWaitForSingleObject returned %x\n", status
);
1821 attr
.RootDirectory
= key
;
1822 attr
.ObjectName
= &str
;
1823 pRtlCreateUnicodeStringFromAsciiz(&str
, "test_subkey");
1824 status
= pNtCreateKey(&subkey
, GENERIC_ALL
, &attr
, 0, 0, 0, 0);
1825 ok(status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1827 status
= pNtWaitForSingleObject(events
[0], FALSE
, &timeout
);
1828 ok(status
== STATUS_SUCCESS
, "NtWaitForSingleObject returned %x\n", status
);
1830 status
= pNtDeleteKey(subkey
);
1831 ok(status
== STATUS_SUCCESS
, "NtDeleteSubkey failed: %x\n", status
);
1837 win_skip("NtNotifyChangeMultipleKeys not available\n");
1840 pNtClose(events
[0]);
1841 pNtClose(events
[1]);
1846 static const WCHAR winetest
[] = {'\\','W','i','n','e','T','e','s','t',0};
1847 if(!InitFunctionPtrs())
1849 pRtlFormatCurrentUserKeyPath(&winetestpath
);
1850 winetestpath
.Buffer
= pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, winetestpath
.Buffer
,
1851 winetestpath
.MaximumLength
+ sizeof(winetest
)*sizeof(WCHAR
));
1852 winetestpath
.MaximumLength
= winetestpath
.MaximumLength
+ sizeof(winetest
)*sizeof(WCHAR
);
1854 pRtlAppendUnicodeToString(&winetestpath
, winetest
);
1858 test_NtSetValueKey();
1859 test_RtlCheckRegistryKey();
1860 test_RtlOpenCurrentUser();
1861 test_RtlQueryRegistryValues();
1862 test_RtlpNtQueryValueKey();
1865 test_NtQueryLicenseKey();
1866 test_NtQueryValueKey();
1867 test_long_value_name();
1873 pRtlFreeUnicodeString(&winetestpath
);
1875 FreeLibrary(hntdll
);