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
* pNtClose
)(IN HANDLE
);
127 static NTSTATUS (WINAPI
* pNtFlushKey
)(HANDLE
);
128 static NTSTATUS (WINAPI
* pNtDeleteKey
)(HANDLE
);
129 static NTSTATUS (WINAPI
* pNtCreateKey
)( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
130 ULONG TitleIndex
, const UNICODE_STRING
*class, ULONG options
,
132 static NTSTATUS (WINAPI
* pNtQueryKey
)(HANDLE
,KEY_INFORMATION_CLASS
,PVOID
,ULONG
,PULONG
);
133 static NTSTATUS (WINAPI
* pNtQueryValueKey
)(HANDLE
,const UNICODE_STRING
*,KEY_VALUE_INFORMATION_CLASS
,void *,DWORD
,DWORD
*);
134 static NTSTATUS (WINAPI
* pNtSetValueKey
)(HANDLE
, const PUNICODE_STRING
, ULONG
,
135 ULONG
, const void*, ULONG
);
136 static NTSTATUS (WINAPI
* pNtQueryInformationProcess
)(HANDLE
,PROCESSINFOCLASS
,PVOID
,ULONG
,PULONG
);
137 static NTSTATUS (WINAPI
* pRtlFormatCurrentUserKeyPath
)(PUNICODE_STRING
);
138 static LONG (WINAPI
* pRtlCompareUnicodeString
)(const PUNICODE_STRING
,const PUNICODE_STRING
,BOOLEAN
);
139 static BOOLEAN (WINAPI
* pRtlCreateUnicodeString
)(PUNICODE_STRING
, LPCWSTR
);
140 static LPVOID (WINAPI
* pRtlReAllocateHeap
)(IN PVOID
, IN ULONG
, IN PVOID
, IN ULONG
);
141 static NTSTATUS (WINAPI
* pRtlAppendUnicodeToString
)(PUNICODE_STRING
, PCWSTR
);
142 static NTSTATUS (WINAPI
* pRtlUnicodeStringToAnsiString
)(PSTRING
, PUNICODE_STRING
, BOOL
);
143 static NTSTATUS (WINAPI
* pRtlFreeHeap
)(PVOID
, ULONG
, PVOID
);
144 static LPVOID (WINAPI
* pRtlAllocateHeap
)(PVOID
,ULONG
,ULONG
);
145 static NTSTATUS (WINAPI
* pRtlZeroMemory
)(PVOID
, ULONG
);
146 static NTSTATUS (WINAPI
* pRtlpNtQueryValueKey
)(HANDLE
,ULONG
*,PBYTE
,DWORD
*,void *);
148 static HMODULE hntdll
= 0;
149 static int CurrentTest
= 0;
150 static UNICODE_STRING winetestpath
;
152 #define NTDLL_GET_PROC(func) \
153 p ## func = (void*)GetProcAddress(hntdll, #func); \
155 trace("GetProcAddress(%s) failed\n", #func); \
156 FreeLibrary(hntdll); \
160 static BOOL
InitFunctionPtrs(void)
162 hntdll
= LoadLibraryA("ntdll.dll");
164 trace("Could not load ntdll.dll\n");
167 NTDLL_GET_PROC(RtlInitUnicodeString
)
168 NTDLL_GET_PROC(RtlCreateUnicodeStringFromAsciiz
)
169 NTDLL_GET_PROC(RtlCreateUnicodeString
)
170 NTDLL_GET_PROC(RtlFreeUnicodeString
)
171 NTDLL_GET_PROC(RtlQueryRegistryValues
)
172 NTDLL_GET_PROC(RtlCheckRegistryKey
)
173 NTDLL_GET_PROC(RtlOpenCurrentUser
)
174 NTDLL_GET_PROC(NtClose
)
175 NTDLL_GET_PROC(NtDeleteValueKey
)
176 NTDLL_GET_PROC(NtCreateKey
)
177 NTDLL_GET_PROC(NtFlushKey
)
178 NTDLL_GET_PROC(NtDeleteKey
)
179 NTDLL_GET_PROC(NtQueryKey
)
180 NTDLL_GET_PROC(NtQueryValueKey
)
181 NTDLL_GET_PROC(NtQueryInformationProcess
)
182 NTDLL_GET_PROC(NtSetValueKey
)
183 NTDLL_GET_PROC(NtOpenKey
)
184 NTDLL_GET_PROC(RtlFormatCurrentUserKeyPath
)
185 NTDLL_GET_PROC(RtlCompareUnicodeString
)
186 NTDLL_GET_PROC(RtlReAllocateHeap
)
187 NTDLL_GET_PROC(RtlAppendUnicodeToString
)
188 NTDLL_GET_PROC(RtlUnicodeStringToAnsiString
)
189 NTDLL_GET_PROC(RtlFreeHeap
)
190 NTDLL_GET_PROC(RtlAllocateHeap
)
191 NTDLL_GET_PROC(RtlZeroMemory
)
192 NTDLL_GET_PROC(RtlpNtQueryValueKey
)
193 NTDLL_GET_PROC(RtlOpenCurrentUser
)
196 #undef NTDLL_GET_PROC
198 static NTSTATUS WINAPI
QueryRoutine (IN PCWSTR ValueName
, IN ULONG ValueType
, IN PVOID ValueData
,
199 IN ULONG ValueLength
, IN PVOID Context
, IN PVOID EntryContext
)
201 NTSTATUS ret
= STATUS_SUCCESS
;
202 int ValueNameLength
= 0;
204 trace("**Test %d**\n", CurrentTest
);
208 ValueNameLength
= lstrlenW(ValueName
);
210 ValName
= pRtlAllocateHeap(GetProcessHeap(), 0, ValueNameLength
);
212 WideCharToMultiByte(CP_ACP
, 0, ValueName
, ValueNameLength
+1, ValName
, ValueNameLength
, NULL
, NULL
);
214 trace("ValueName: %s\n", ValName
);
217 trace("ValueName: (null)\n");
222 trace("ValueType: REG_NONE\n");
223 trace("ValueData: %p\n", ValueData
);
227 trace("ValueType: REG_BINARY\n");
228 trace("ValueData: %p\n", ValueData
);
232 trace("ValueType: REG_SZ\n");
233 trace("ValueData: %s\n", (char*)ValueData
);
237 trace("ValueType: REG_MULTI_SZ\n");
238 trace("ValueData: %s\n", (char*)ValueData
);
242 trace("ValueType: REG_EXPAND_SZ\n");
243 trace("ValueData: %s\n", (char*)ValueData
);
247 trace("ValueType: REG_DWORD\n");
248 trace("ValueData: %p\n", ValueData
);
251 trace("ValueLength: %d\n", (int)ValueLength
);
254 ok(1, "\n"); /*checks that QueryRoutine is called*/
256 ok(!1, "Invalid Test Specified!\n");
261 pRtlFreeHeap(GetProcessHeap(), 0, ValName
);
266 static void test_RtlQueryRegistryValues(void)
270 ******************************
272 ******************************
273 *RTL_QUERY_REGISTRY_SUBKEY * Name is the name of a subkey relative to Path
274 *RTL_QUERY_REGISTRY_TOPKEY * Resets location to original RelativeTo and Path
275 *RTL_QUERY_REGISTRY_REQUIRED * Key required. returns STATUS_OBJECT_NAME_NOT_FOUND if not present
276 *RTL_QUERY_REGISTRY_NOVALUE * We just want a call-back
277 *RTL_QUERY_REGISTRY_NOEXPAND * Don't expand the variables!
278 *RTL_QUERY_REGISTRY_DIRECT * Results of query will be stored in EntryContext(QueryRoutine ignored)
279 *RTL_QUERY_REGISTRY_DELETE * Delete value key after query
280 ******************************
283 **Test layout(numbered according to CurrentTest value)**
284 0)NOVALUE Just make sure call-back works
285 1)Null Name See if QueryRoutine is called for every value in current key
286 2)SUBKEY See if we can use SUBKEY to change the current path on the fly
287 3)REQUIRED Test for value that's not there
288 4)NOEXPAND See if it will return multiple strings(no expand should split strings up)
289 5)DIRECT Make it store data directly in EntryContext and not call QueryRoutine
290 6)DefaultType Test return values when key isn't present
291 7)DefaultValue Test Default Value returned with key isn't present(and no REQUIRED flag set)
292 8)DefaultLength Test Default Length with DefaultType = REG_SZ
293 9)DefaultLength Test Default Length with DefaultType = REG_MULTI_SZ
294 10)DefaultLength Test Default Length with DefaultType = REG_EXPAND_SZ
295 11)DefaultData Test whether DefaultData is used while DefaultType = REG_NONE(shouldn't be)
296 12)Delete Try to delete value key
302 PRTL_QUERY_REGISTRY_TABLE QueryTable
= NULL
;
303 RelativeTo
= RTL_REGISTRY_ABSOLUTE
;/*Only using absolute - no need to test all relativeto variables*/
305 QueryTable
= pRtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_QUERY_REGISTRY_TABLE
)*26);
307 pRtlZeroMemory( QueryTable
, sizeof(RTL_QUERY_REGISTRY_TABLE
) * 26);
309 QueryTable
[0].QueryRoutine
= QueryRoutine
;
310 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_NOVALUE
;
311 QueryTable
[0].Name
= NULL
;
312 QueryTable
[0].EntryContext
= NULL
;
313 QueryTable
[0].DefaultType
= REG_BINARY
;
314 QueryTable
[0].DefaultData
= NULL
;
315 QueryTable
[0].DefaultLength
= 100;
317 QueryTable
[1].QueryRoutine
= QueryRoutine
;
318 QueryTable
[1].Flags
= 0;
319 QueryTable
[1].Name
= NULL
;
320 QueryTable
[1].EntryContext
= 0;
321 QueryTable
[1].DefaultType
= REG_NONE
;
322 QueryTable
[1].DefaultData
= NULL
;
323 QueryTable
[1].DefaultLength
= 0;
325 QueryTable
[2].QueryRoutine
= NULL
;
326 QueryTable
[2].Flags
= 0;
327 QueryTable
[2].Name
= NULL
;
328 QueryTable
[2].EntryContext
= 0;
329 QueryTable
[2].DefaultType
= REG_NONE
;
330 QueryTable
[2].DefaultData
= NULL
;
331 QueryTable
[2].DefaultLength
= 0;
333 status
= pRtlQueryRegistryValues(RelativeTo
, winetestpath
.Buffer
, QueryTable
, 0, 0);
334 ok(status
== STATUS_SUCCESS
, "RtlQueryRegistryValues return: 0x%08x\n", status
);
336 pRtlFreeHeap(GetProcessHeap(), 0, QueryTable
);
339 static void test_NtOpenKey(void)
343 OBJECT_ATTRIBUTES attr
;
344 ACCESS_MASK am
= KEY_READ
;
347 status
= pNtOpenKey(NULL
, 0, NULL
);
348 ok(status
== STATUS_ACCESS_VIOLATION
, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status
);
350 /* NULL attributes */
351 status
= pNtOpenKey(&key
, 0, NULL
);
352 ok(status
== STATUS_ACCESS_VIOLATION
/* W2K3/XP/W2K */ || status
== STATUS_INVALID_PARAMETER
/* NT4 */,
353 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status
);
355 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
358 status
= pNtOpenKey(NULL
, am
, &attr
);
359 ok(status
== STATUS_ACCESS_VIOLATION
, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status
);
361 /* Length > sizeof(OBJECT_ATTRIBUTES) */
363 status
= pNtOpenKey(&key
, am
, &attr
);
364 ok(status
== STATUS_INVALID_PARAMETER
, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status
);
367 static void test_NtCreateKey(void)
370 OBJECT_ATTRIBUTES attr
;
372 ACCESS_MASK am
= GENERIC_ALL
;
377 status
= pNtCreateKey(NULL
, 0, NULL
, 0, 0, 0, 0);
378 ok(status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_PARAMETER
,
379 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got: 0x%08x\n", status
);
382 status
= pNtCreateKey(&key
, 0, NULL
, 0, 0, 0, 0);
383 ok(status
== STATUS_ACCESS_VIOLATION
/* W2K3/XP/W2K */ || status
== STATUS_INVALID_PARAMETER
/* NT4 */,
384 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status
);
386 /* Only accessmask */
387 status
= pNtCreateKey(NULL
, am
, NULL
, 0, 0, 0, 0);
388 ok(status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_PARAMETER
,
389 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got: 0x%08x\n", status
);
391 /* Key and accessmask */
392 status
= pNtCreateKey(&key
, am
, 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 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
398 /* Only attributes */
399 status
= pNtCreateKey(NULL
, 0, &attr
, 0, 0, 0, 0);
400 ok(status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_ACCESS_DENIED
/* Win7 */,
401 "Expected STATUS_ACCESS_VIOLATION or STATUS_ACCESS_DENIED, got: 0x%08x\n", status
);
403 /* Length > sizeof(OBJECT_ATTRIBUTES) */
405 status
= pNtCreateKey(&key
, am
, &attr
, 0, 0, 0, 0);
406 ok(status
== STATUS_INVALID_PARAMETER
, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status
);
408 attr
.Length
= sizeof(attr
);
409 status
= pNtCreateKey(&key
, am
, &attr
, 0, 0, 0, 0);
410 ok(status
== STATUS_SUCCESS
, "NtCreateKey Failed: 0x%08x\n", status
);
412 attr
.RootDirectory
= key
;
413 attr
.ObjectName
= &str
;
415 pRtlCreateUnicodeStringFromAsciiz( &str
, "test\\sub\\key" );
416 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
417 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtCreateKey failed: 0x%08x\n", status
);
418 pRtlFreeUnicodeString( &str
);
420 pRtlCreateUnicodeStringFromAsciiz( &str
, "test\\subkey" );
421 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
422 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtCreateKey failed: 0x%08x\n", status
);
423 pRtlFreeUnicodeString( &str
);
425 pRtlCreateUnicodeStringFromAsciiz( &str
, "test\\subkey\\" );
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_SUCCESS
|| broken(status
== STATUS_OBJECT_NAME_NOT_FOUND
), /* nt4 */
433 "NtCreateKey failed: 0x%08x\n", status
);
434 if (status
== STATUS_SUCCESS
)
436 pNtDeleteKey( subkey
);
439 pRtlFreeUnicodeString( &str
);
441 pRtlCreateUnicodeStringFromAsciiz( &str
, "test_subkey" );
442 status
= pNtCreateKey( &subkey
, am
, &attr
, 0, 0, 0, 0 );
443 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
444 pRtlFreeUnicodeString( &str
);
445 pNtDeleteKey( subkey
);
451 static void test_NtSetValueKey(void)
455 OBJECT_ATTRIBUTES attr
;
456 ACCESS_MASK am
= KEY_WRITE
;
457 UNICODE_STRING ValName
;
460 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
461 status
= pNtOpenKey(&key
, am
, &attr
);
462 ok(status
== STATUS_SUCCESS
, "NtOpenKey Failed: 0x%08x\n", status
);
464 pRtlCreateUnicodeStringFromAsciiz(&ValName
, "deletetest");
465 status
= pNtSetValueKey(key
, &ValName
, 0, REG_DWORD
, &data
, sizeof(data
));
466 ok(status
== STATUS_SUCCESS
, "NtSetValueKey Failed: 0x%08x\n", status
);
467 pRtlFreeUnicodeString(&ValName
);
469 pRtlCreateUnicodeStringFromAsciiz(&ValName
, "stringtest");
470 status
= pNtSetValueKey(key
, &ValName
, 0, REG_SZ
, (VOID
*)stringW
, STR_TRUNC_SIZE
);
471 ok(status
== STATUS_SUCCESS
, "NtSetValueKey Failed: 0x%08x\n", status
);
472 pRtlFreeUnicodeString(&ValName
);
477 static void test_RtlOpenCurrentUser(void)
481 status
=pRtlOpenCurrentUser(KEY_READ
, &handle
);
482 ok(status
== STATUS_SUCCESS
, "RtlOpenCurrentUser Failed: 0x%08x\n", status
);
486 static void test_RtlCheckRegistryKey(void)
490 status
= pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE
, winetestpath
.Buffer
);
491 ok(status
== STATUS_SUCCESS
, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08x\n", status
);
493 status
= pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE
| RTL_REGISTRY_OPTIONAL
), winetestpath
.Buffer
);
494 ok(status
== STATUS_SUCCESS
, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE and RTL_REGISTRY_OPTIONAL: 0x%08x\n", status
);
497 static void test_NtFlushKey(void)
501 OBJECT_ATTRIBUTES attr
;
502 ACCESS_MASK am
= KEY_ALL_ACCESS
;
504 status
= pNtFlushKey(NULL
);
505 ok(status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status
);
507 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
508 pNtOpenKey(&hkey
, am
, &attr
);
510 status
= pNtFlushKey(hkey
);
511 ok(status
== STATUS_SUCCESS
, "NtDeleteKey Failed: 0x%08x\n", status
);
516 static void test_NtQueryValueKey(void)
520 OBJECT_ATTRIBUTES attr
;
521 UNICODE_STRING ValName
;
522 KEY_VALUE_BASIC_INFORMATION
*basic_info
;
523 KEY_VALUE_PARTIAL_INFORMATION
*partial_info
;
524 KEY_VALUE_FULL_INFORMATION
*full_info
;
527 pRtlCreateUnicodeStringFromAsciiz(&ValName
, "deletetest");
529 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
530 status
= pNtOpenKey(&key
, KEY_READ
, &attr
);
531 ok(status
== STATUS_SUCCESS
, "NtOpenKey Failed: 0x%08x\n", status
);
533 len
= FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]);
534 basic_info
= HeapAlloc(GetProcessHeap(), 0, len
);
535 status
= pNtQueryValueKey(key
, &ValName
, KeyValueBasicInformation
, basic_info
, len
, &len
);
536 ok(status
== STATUS_BUFFER_OVERFLOW
, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status
);
537 ok(basic_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info
->TitleIndex
);
538 ok(basic_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", basic_info
->Type
);
539 ok(basic_info
->NameLength
== 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info
->NameLength
);
540 ok(len
== FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[basic_info
->NameLength
/sizeof(WCHAR
)]), "NtQueryValueKey returned wrong len %d\n", len
);
542 basic_info
= HeapReAlloc(GetProcessHeap(), 0, basic_info
, len
);
543 status
= pNtQueryValueKey(key
, &ValName
, KeyValueBasicInformation
, basic_info
, len
, &len
);
544 ok(status
== STATUS_SUCCESS
, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status
);
545 ok(basic_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info
->TitleIndex
);
546 ok(basic_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", basic_info
->Type
);
547 ok(basic_info
->NameLength
== 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info
->NameLength
);
548 ok(len
== FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[basic_info
->NameLength
/sizeof(WCHAR
)]), "NtQueryValueKey returned wrong len %d\n", len
);
549 ok(!memcmp(basic_info
->Name
, ValName
.Buffer
, ValName
.Length
), "incorrect Name returned\n");
550 HeapFree(GetProcessHeap(), 0, basic_info
);
552 len
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
553 partial_info
= HeapAlloc(GetProcessHeap(), 0, len
);
554 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, partial_info
, len
, &len
);
555 ok(status
== STATUS_BUFFER_OVERFLOW
, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status
);
556 ok(partial_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info
->TitleIndex
);
557 ok(partial_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", partial_info
->Type
);
558 ok(partial_info
->DataLength
== 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info
->DataLength
);
559 ok(len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[partial_info
->DataLength
]), "NtQueryValueKey returned wrong len %d\n", len
);
561 partial_info
= HeapReAlloc(GetProcessHeap(), 0, partial_info
, len
);
562 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, partial_info
, len
, &len
);
563 ok(status
== STATUS_SUCCESS
, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status
);
564 ok(partial_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info
->TitleIndex
);
565 ok(partial_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", partial_info
->Type
);
566 ok(partial_info
->DataLength
== 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info
->DataLength
);
567 ok(len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[partial_info
->DataLength
]), "NtQueryValueKey returned wrong len %d\n", len
);
568 ok(*(DWORD
*)partial_info
->Data
== 711, "incorrect Data returned: 0x%x\n", *(DWORD
*)partial_info
->Data
);
569 HeapFree(GetProcessHeap(), 0, partial_info
);
571 len
= FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]);
572 full_info
= HeapAlloc(GetProcessHeap(), 0, len
);
573 status
= pNtQueryValueKey(key
, &ValName
, KeyValueFullInformation
, full_info
, len
, &len
);
574 ok(status
== STATUS_BUFFER_OVERFLOW
, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status
);
575 ok(full_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info
->TitleIndex
);
576 ok(full_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", full_info
->Type
);
577 ok(full_info
->DataLength
== 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info
->DataLength
);
578 ok(full_info
->NameLength
== 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info
->NameLength
);
579 ok(len
== FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]) + full_info
->DataLength
+ full_info
->NameLength
,
580 "NtQueryValueKey returned wrong len %d\n", len
);
581 len
= FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]) + full_info
->DataLength
+ full_info
->NameLength
;
583 full_info
= HeapReAlloc(GetProcessHeap(), 0, full_info
, len
);
584 status
= pNtQueryValueKey(key
, &ValName
, KeyValueFullInformation
, full_info
, len
, &len
);
585 ok(status
== STATUS_SUCCESS
, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status
);
586 ok(full_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info
->TitleIndex
);
587 ok(full_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", full_info
->Type
);
588 ok(full_info
->DataLength
== 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info
->DataLength
);
589 ok(full_info
->NameLength
== 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info
->NameLength
);
590 ok(!memcmp(full_info
->Name
, ValName
.Buffer
, ValName
.Length
), "incorrect Name returned\n");
591 ok(*(DWORD
*)((char *)full_info
+ full_info
->DataOffset
) == 711, "incorrect Data returned: 0x%x\n",
592 *(DWORD
*)((char *)full_info
+ full_info
->DataOffset
));
593 HeapFree(GetProcessHeap(), 0, full_info
);
595 pRtlFreeUnicodeString(&ValName
);
596 pRtlCreateUnicodeStringFromAsciiz(&ValName
, "stringtest");
598 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, NULL
, 0, &len
);
599 ok(status
== STATUS_BUFFER_TOO_SMALL
, "NtQueryValueKey should have returned STATUS_BUFFER_TOO_SMALL instead of 0x%08x\n", status
);
600 partial_info
= HeapAlloc(GetProcessHeap(), 0, len
+1);
601 memset(partial_info
, 0xbd, len
+1);
602 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, partial_info
, len
, &len
);
603 ok(status
== STATUS_SUCCESS
, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status
);
604 ok(partial_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info
->TitleIndex
);
605 ok(partial_info
->Type
== REG_SZ
, "NtQueryValueKey returned wrong Type %d\n", partial_info
->Type
);
606 ok(partial_info
->DataLength
== STR_TRUNC_SIZE
, "NtQueryValueKey returned wrong DataLength %d\n", partial_info
->DataLength
);
607 ok(!memcmp(partial_info
->Data
, stringW
, STR_TRUNC_SIZE
), "incorrect Data returned\n");
608 ok(*(partial_info
->Data
+STR_TRUNC_SIZE
) == 0xbd, "string overflowed %02x\n", *(partial_info
->Data
+STR_TRUNC_SIZE
));
611 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, partial_info
, 0, &len
);
612 ok(status
== STATUS_BUFFER_TOO_SMALL
, "NtQueryValueKey wrong status 0x%08x\n", status
);
613 ok(len
== expected
, "NtQueryValueKey wrong len %u\n", len
);
614 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, partial_info
, 1, &len
);
615 ok(status
== STATUS_BUFFER_TOO_SMALL
, "NtQueryValueKey wrong status 0x%08x\n", status
);
616 ok(len
== expected
, "NtQueryValueKey wrong len %u\n", len
);
617 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, partial_info
, FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
) - 1, &len
);
618 ok(status
== STATUS_BUFFER_TOO_SMALL
, "NtQueryValueKey wrong status 0x%08x\n", status
);
619 ok(len
== expected
, "NtQueryValueKey wrong len %u\n", len
);
620 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, partial_info
, FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
), &len
);
621 ok(status
== STATUS_BUFFER_OVERFLOW
, "NtQueryValueKey wrong status 0x%08x\n", status
);
622 ok(len
== expected
, "NtQueryValueKey wrong len %u\n", len
);
624 HeapFree(GetProcessHeap(), 0, partial_info
);
626 pRtlFreeUnicodeString(&ValName
);
630 static void test_NtDeleteKey(void)
634 OBJECT_ATTRIBUTES attr
;
635 ACCESS_MASK am
= KEY_ALL_ACCESS
;
637 status
= pNtDeleteKey(NULL
);
638 ok(status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status
);
640 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
641 status
= pNtOpenKey(&hkey
, am
, &attr
);
642 ok(status
== STATUS_SUCCESS
, "NtOpenKey Failed: 0x%08x\n", status
);
644 status
= pNtDeleteKey(hkey
);
645 ok(status
== STATUS_SUCCESS
, "NtDeleteKey Failed: 0x%08x\n", status
);
648 static void test_RtlpNtQueryValueKey(void)
652 status
= pRtlpNtQueryValueKey(NULL
, NULL
, NULL
, NULL
, NULL
);
653 ok(status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status
);
656 static void test_symlinks(void)
658 static const WCHAR linkW
[] = {'l','i','n','k',0};
659 static const WCHAR valueW
[] = {'v','a','l','u','e',0};
660 static const WCHAR symlinkW
[] = {'S','y','m','b','o','l','i','c','L','i','n','k','V','a','l','u','e',0};
661 static const WCHAR targetW
[] = {'\\','t','a','r','g','e','t',0};
662 static UNICODE_STRING null_str
;
664 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
666 UNICODE_STRING symlink_str
, link_str
, target_str
, value_str
;
667 HANDLE root
, key
, link
;
668 OBJECT_ATTRIBUTES attr
;
670 DWORD target_len
, len
, dw
;
672 pRtlInitUnicodeString( &link_str
, linkW
);
673 pRtlInitUnicodeString( &symlink_str
, symlinkW
);
674 pRtlInitUnicodeString( &target_str
, targetW
+ 1 );
675 pRtlInitUnicodeString( &value_str
, valueW
);
677 target_len
= winetestpath
.Length
+ sizeof(targetW
);
678 target
= pRtlAllocateHeap( GetProcessHeap(), 0, target_len
+ sizeof(targetW
) /*for loop test*/ );
679 memcpy( target
, winetestpath
.Buffer
, winetestpath
.Length
);
680 memcpy( target
+ winetestpath
.Length
/sizeof(WCHAR
), targetW
, sizeof(targetW
) );
682 attr
.Length
= sizeof(attr
);
683 attr
.RootDirectory
= 0;
685 attr
.ObjectName
= &winetestpath
;
686 attr
.SecurityDescriptor
= NULL
;
687 attr
.SecurityQualityOfService
= NULL
;
689 status
= pNtCreateKey( &root
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
690 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
692 attr
.RootDirectory
= root
;
693 attr
.ObjectName
= &link_str
;
694 status
= pNtCreateKey( &link
, KEY_ALL_ACCESS
, &attr
, 0, 0, REG_OPTION_CREATE_LINK
, 0 );
695 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
697 /* REG_SZ is not allowed */
698 status
= pNtSetValueKey( link
, &symlink_str
, 0, REG_SZ
, target
, target_len
);
699 ok( status
== STATUS_ACCESS_DENIED
, "NtSetValueKey wrong status 0x%08x\n", status
);
700 status
= pNtSetValueKey( link
, &symlink_str
, 0, REG_LINK
, target
, target_len
- sizeof(WCHAR
) );
701 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
702 /* other values are not allowed */
703 status
= pNtSetValueKey( link
, &link_str
, 0, REG_LINK
, target
, target_len
- sizeof(WCHAR
) );
704 ok( status
== STATUS_ACCESS_DENIED
, "NtSetValueKey wrong status 0x%08x\n", status
);
706 /* try opening the target through the link */
708 attr
.ObjectName
= &link_str
;
709 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
710 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtOpenKey wrong status 0x%08x\n", status
);
712 attr
.ObjectName
= &target_str
;
713 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
714 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
717 status
= pNtSetValueKey( key
, &value_str
, 0, REG_DWORD
, &dw
, sizeof(dw
) );
718 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
721 attr
.ObjectName
= &link_str
;
722 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
723 ok( status
== STATUS_SUCCESS
, "NtOpenKey failed: 0x%08x\n", status
);
725 len
= sizeof(buffer
);
726 status
= pNtQueryValueKey( key
, &value_str
, KeyValuePartialInformation
, info
, len
, &len
);
727 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
728 ok( len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,Data
) + sizeof(DWORD
), "wrong len %u\n", len
);
730 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
731 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtQueryValueKey failed: 0x%08x\n", status
);
733 /* REG_LINK can be created in non-link keys */
734 status
= pNtSetValueKey( key
, &symlink_str
, 0, REG_LINK
, target
, target_len
- sizeof(WCHAR
) );
735 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
736 len
= sizeof(buffer
);
737 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
738 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
739 ok( len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,Data
) + target_len
- sizeof(WCHAR
),
740 "wrong len %u\n", len
);
741 status
= pNtDeleteValueKey( key
, &symlink_str
);
742 ok( status
== STATUS_SUCCESS
, "NtDeleteValueKey failed: 0x%08x\n", status
);
747 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
748 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
750 len
= sizeof(buffer
);
751 status
= pNtQueryValueKey( key
, &value_str
, KeyValuePartialInformation
, info
, len
, &len
);
752 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
753 ok( len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,Data
) + sizeof(DWORD
), "wrong len %u\n", len
);
755 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
756 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtQueryValueKey failed: 0x%08x\n", status
);
759 /* now open the symlink itself */
761 attr
.RootDirectory
= root
;
762 attr
.Attributes
= OBJ_OPENLINK
;
763 attr
.ObjectName
= &link_str
;
764 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
765 ok( status
== STATUS_SUCCESS
, "NtOpenKey failed: 0x%08x\n", status
);
767 len
= sizeof(buffer
);
768 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
769 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
770 ok( len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,Data
) + target_len
- sizeof(WCHAR
),
771 "wrong len %u\n", len
);
774 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
775 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
776 len
= sizeof(buffer
);
777 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
778 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
779 ok( len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,Data
) + target_len
- sizeof(WCHAR
),
780 "wrong len %u\n", len
);
783 if (0) /* crashes the Windows kernel on some Vista systems */
785 /* reopen the link from itself */
787 attr
.RootDirectory
= link
;
788 attr
.Attributes
= OBJ_OPENLINK
;
789 attr
.ObjectName
= &null_str
;
790 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
791 ok( status
== STATUS_SUCCESS
, "NtOpenKey failed: 0x%08x\n", status
);
792 len
= sizeof(buffer
);
793 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
794 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
795 ok( len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,Data
) + target_len
- sizeof(WCHAR
),
796 "wrong len %u\n", len
);
799 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
800 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
801 len
= sizeof(buffer
);
802 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
803 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
804 ok( len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,Data
) + target_len
- sizeof(WCHAR
),
805 "wrong len %u\n", len
);
809 if (0) /* crashes the Windows kernel in most versions */
811 attr
.RootDirectory
= link
;
813 attr
.ObjectName
= &null_str
;
814 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
815 ok( status
== STATUS_SUCCESS
, "NtOpenKey failed: 0x%08x\n", status
);
816 len
= sizeof(buffer
);
817 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
818 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtQueryValueKey failed: 0x%08x\n", status
);
821 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
822 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
823 len
= sizeof(buffer
);
824 status
= pNtQueryValueKey( key
, &symlink_str
, KeyValuePartialInformation
, info
, len
, &len
);
825 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtQueryValueKey failed: 0x%08x\n", status
);
829 /* target with terminating null doesn't work */
830 status
= pNtSetValueKey( link
, &symlink_str
, 0, REG_LINK
, target
, target_len
);
831 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
832 attr
.RootDirectory
= root
;
834 attr
.ObjectName
= &link_str
;
835 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
836 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtOpenKey wrong status 0x%08x\n", status
);
838 /* relative symlink, works only on win2k */
839 status
= pNtSetValueKey( link
, &symlink_str
, 0, REG_LINK
, targetW
+1, sizeof(targetW
)-2*sizeof(WCHAR
) );
840 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
841 attr
.ObjectName
= &link_str
;
842 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
843 ok( status
== STATUS_SUCCESS
|| status
== STATUS_OBJECT_NAME_NOT_FOUND
,
844 "NtOpenKey wrong status 0x%08x\n", status
);
846 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, REG_OPTION_CREATE_LINK
, 0 );
847 ok( status
== STATUS_OBJECT_NAME_COLLISION
, "NtCreateKey failed: 0x%08x\n", status
);
849 status
= pNtDeleteKey( link
);
850 ok( status
== STATUS_SUCCESS
, "NtDeleteKey failed: 0x%08x\n", status
);
853 attr
.ObjectName
= &target_str
;
854 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
855 ok( status
== STATUS_SUCCESS
, "NtOpenKey failed: 0x%08x\n", status
);
856 status
= pNtDeleteKey( key
);
857 ok( status
== STATUS_SUCCESS
, "NtDeleteKey failed: 0x%08x\n", status
);
862 status
= pNtCreateKey( &link
, KEY_ALL_ACCESS
, &attr
, 0, 0, REG_OPTION_CREATE_LINK
, 0 );
863 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
864 memcpy( target
+ target_len
/sizeof(WCHAR
) - 1, targetW
, sizeof(targetW
) );
865 status
= pNtSetValueKey( link
, &symlink_str
, 0, REG_LINK
,
866 target
, target_len
+ sizeof(targetW
) - sizeof(WCHAR
) );
867 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
869 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
870 ok( status
== STATUS_OBJECT_NAME_NOT_FOUND
|| status
== STATUS_NAME_TOO_LONG
,
871 "NtOpenKey failed: 0x%08x\n", status
);
873 attr
.Attributes
= OBJ_OPENLINK
;
874 status
= pNtOpenKey( &key
, KEY_ALL_ACCESS
, &attr
);
875 ok( status
== STATUS_SUCCESS
, "NtOpenKey failed: 0x%08x\n", status
);
878 status
= pNtDeleteKey( link
);
879 ok( status
== STATUS_SUCCESS
, "NtDeleteKey failed: 0x%08x\n", status
);
882 status
= pNtDeleteKey( root
);
883 ok( status
== STATUS_SUCCESS
, "NtDeleteKey failed: 0x%08x\n", status
);
886 pRtlFreeHeap(GetProcessHeap(), 0, target
);
889 static WCHAR valueW
[] = {'v','a','l','u','e'};
890 static UNICODE_STRING value_str
= { sizeof(valueW
), sizeof(valueW
), valueW
};
891 static const DWORD ptr_size
= 8 * sizeof(void*);
893 static DWORD
get_key_value( HANDLE root
, const char *name
, DWORD flags
)
897 OBJECT_ATTRIBUTES attr
;
900 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)tmp
;
901 DWORD dw
, len
= sizeof(tmp
);
903 attr
.Length
= sizeof(attr
);
904 attr
.RootDirectory
= root
;
905 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
906 attr
.ObjectName
= &str
;
907 attr
.SecurityDescriptor
= NULL
;
908 attr
.SecurityQualityOfService
= NULL
;
909 pRtlCreateUnicodeStringFromAsciiz( &str
, name
);
911 status
= pNtCreateKey( &key
, flags
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
912 if (status
== STATUS_OBJECT_NAME_NOT_FOUND
) return 0;
913 ok( status
== STATUS_SUCCESS
, "%08x: NtCreateKey failed: 0x%08x\n", flags
, status
);
915 status
= pNtQueryValueKey( key
, &value_str
, KeyValuePartialInformation
, info
, len
, &len
);
916 if (status
== STATUS_OBJECT_NAME_NOT_FOUND
)
920 ok( status
== STATUS_SUCCESS
, "%08x: NtQueryValueKey failed: 0x%08x\n", flags
, status
);
921 dw
= *(DWORD
*)info
->Data
;
924 pRtlFreeUnicodeString( &str
);
928 static void _check_key_value( int line
, HANDLE root
, const char *name
, DWORD flags
, DWORD expect
)
930 DWORD dw
= get_key_value( root
, name
, flags
);
931 ok_(__FILE__
,line
)( dw
== expect
, "%08x: wrong value %u/%u\n", flags
, dw
, expect
);
933 #define check_key_value(root,name,flags,expect) _check_key_value( __LINE__, root, name, flags, expect )
935 static void test_redirection(void)
937 static const WCHAR softwareW
[] = {'\\','R','e','g','i','s','t','r','y','\\',
938 'M','a','c','h','i','n','e','\\',
939 'S','o','f','t','w','a','r','e',0};
940 static const WCHAR wownodeW
[] = {'\\','R','e','g','i','s','t','r','y','\\',
941 'M','a','c','h','i','n','e','\\',
942 'S','o','f','t','w','a','r','e','\\',
943 'W','o','w','6','4','3','2','N','o','d','e',0};
944 static const WCHAR wine64W
[] = {'\\','R','e','g','i','s','t','r','y','\\',
945 'M','a','c','h','i','n','e','\\',
946 'S','o','f','t','w','a','r','e','\\',
948 static const WCHAR wine32W
[] = {'\\','R','e','g','i','s','t','r','y','\\',
949 'M','a','c','h','i','n','e','\\',
950 'S','o','f','t','w','a','r','e','\\',
951 'W','o','w','6','4','3','2','N','o','d','e','\\',
953 static const WCHAR key64W
[] = {'\\','R','e','g','i','s','t','r','y','\\',
954 'M','a','c','h','i','n','e','\\',
955 'S','o','f','t','w','a','r','e','\\',
956 'W','i','n','e','\\','W','i','n','e','t','e','s','t',0};
957 static const WCHAR key32W
[] = {'\\','R','e','g','i','s','t','r','y','\\',
958 'M','a','c','h','i','n','e','\\',
959 'S','o','f','t','w','a','r','e','\\',
960 'W','o','w','6','4','3','2','N','o','d','e','\\',
961 'W','i','n','e','\\', 'W','i','n','e','t','e','s','t',0};
962 static const WCHAR classes64W
[] = {'\\','R','e','g','i','s','t','r','y','\\',
963 'M','a','c','h','i','n','e','\\',
964 'S','o','f','t','w','a','r','e','\\',
965 'C','l','a','s','s','e','s','\\',
967 static const WCHAR classes32W
[] = {'\\','R','e','g','i','s','t','r','y','\\',
968 'M','a','c','h','i','n','e','\\',
969 'S','o','f','t','w','a','r','e','\\',
970 'C','l','a','s','s','e','s','\\',
971 'W','o','w','6','4','3','2','N','o','d','e','\\',
974 OBJECT_ATTRIBUTES attr
;
977 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
979 HANDLE key
, root32
, root64
, key32
, key64
;
980 BOOL is_vista
= FALSE
;
985 if (pNtQueryInformationProcess( GetCurrentProcess(), ProcessWow64Information
,
986 &is_wow64
, sizeof(is_wow64
), &len
) ||
989 trace( "Not on Wow64, no redirection\n" );
994 attr
.Length
= sizeof(attr
);
995 attr
.RootDirectory
= 0;
996 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
997 attr
.ObjectName
= &str
;
998 attr
.SecurityDescriptor
= NULL
;
999 attr
.SecurityQualityOfService
= NULL
;
1001 pRtlInitUnicodeString( &str
, wine64W
);
1002 status
= pNtCreateKey( &root64
, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1003 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1005 pRtlInitUnicodeString( &str
, wine32W
);
1006 status
= pNtCreateKey( &root32
, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1007 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1009 pRtlInitUnicodeString( &str
, key64W
);
1010 status
= pNtCreateKey( &key64
, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1011 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1013 pRtlInitUnicodeString( &str
, key32W
);
1014 status
= pNtCreateKey( &key32
, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1015 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1018 status
= pNtSetValueKey( key64
, &value_str
, 0, REG_DWORD
, &dw
, sizeof(dw
) );
1019 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
1022 status
= pNtSetValueKey( key32
, &value_str
, 0, REG_DWORD
, &dw
, sizeof(dw
) );
1023 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
1025 len
= sizeof(buffer
);
1026 status
= pNtQueryValueKey( key32
, &value_str
, KeyValuePartialInformation
, info
, len
, &len
);
1027 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
1028 dw
= *(DWORD
*)info
->Data
;
1029 ok( dw
== 32, "wrong value %u\n", dw
);
1031 len
= sizeof(buffer
);
1032 status
= pNtQueryValueKey( key64
, &value_str
, KeyValuePartialInformation
, info
, len
, &len
);
1033 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
1034 dw
= *(DWORD
*)info
->Data
;
1035 ok( dw
== 64, "wrong value %u\n", dw
);
1037 pRtlInitUnicodeString( &str
, softwareW
);
1038 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1039 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1043 /* the Vista mechanism allows opening Wow6432Node from a 32-bit key too */
1044 /* the new (and simpler) Win7 mechanism doesn't */
1045 if (get_key_value( key
, "Wow6432Node\\Wine\\Winetest", 0 ) == 32)
1047 trace( "using Vista-style Wow6432Node handling\n" );
1050 check_key_value( key
, "Wine\\Winetest", 0, 32 );
1051 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 32 );
1052 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1053 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", 0, is_vista
? 32 : 0 );
1054 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 0 );
1055 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY
, is_vista
? 32 : 0 );
1059 check_key_value( key
, "Wine\\Winetest", 0, 64 );
1060 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", 0, 32 );
1066 status
= pNtCreateKey( &key
, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1067 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1068 dw
= get_key_value( key
, "Wine\\Winetest", 0 );
1069 ok( dw
== 64 || broken(dw
== 32) /* xp64 */, "wrong value %u\n", dw
);
1070 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, 64 );
1071 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1072 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", 0, 32 );
1073 dw
= get_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY
);
1074 ok( dw
== 32 || broken(dw
== 64) /* xp64 */, "wrong value %u\n", dw
);
1075 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1078 status
= pNtCreateKey( &key
, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1079 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1080 check_key_value( key
, "Wine\\Winetest", 0, 32 );
1081 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 32 );
1082 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1083 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", 0, is_vista
? 32 : 0 );
1084 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 0 );
1085 check_key_value( key
, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY
, is_vista
? 32 : 0 );
1089 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", 0, ptr_size
);
1090 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", 0, 32 );
1093 /* KEY_WOW64 flags have no effect on 64-bit */
1094 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_64KEY
, 64 );
1095 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_32KEY
, 64 );
1096 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY
, 32 );
1097 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1101 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_64KEY
, 64 );
1102 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1103 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 32 );
1104 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1107 pRtlInitUnicodeString( &str
, wownodeW
);
1108 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1109 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1110 check_key_value( key
, "Wine\\Winetest", 0, 32 );
1111 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, (ptr_size
== 64) ? 32 : (is_vista
? 64 : 32) );
1112 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1117 status
= pNtCreateKey( &key
, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1118 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1119 dw
= get_key_value( key
, "Wine\\Winetest", 0 );
1120 ok( dw
== (is_vista
? 64 : 32) || broken(dw
== 32) /* xp64 */, "wrong value %u\n", dw
);
1121 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 32 );
1122 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1125 status
= pNtCreateKey( &key
, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1126 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1127 check_key_value( key
, "Wine\\Winetest", 0, 32 );
1128 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 32 );
1129 check_key_value( key
, "Wine\\Winetest", KEY_WOW64_32KEY
, 32 );
1133 pRtlInitUnicodeString( &str
, wine32W
);
1134 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1135 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1136 check_key_value( key
, "Winetest", 0, 32 );
1137 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, (ptr_size
== 32 && is_vista
) ? 64 : 32 );
1138 check_key_value( key
, "Winetest", KEY_WOW64_32KEY
, 32 );
1143 status
= pNtCreateKey( &key
, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1144 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1145 dw
= get_key_value( key
, "Winetest", 0 );
1146 ok( dw
== 32 || (is_vista
&& dw
== 64), "wrong value %u\n", dw
);
1147 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 32 );
1148 check_key_value( key
, "Winetest", KEY_WOW64_32KEY
, 32 );
1151 status
= pNtCreateKey( &key
, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1152 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1153 check_key_value( key
, "Winetest", 0, 32 );
1154 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 32 );
1155 check_key_value( key
, "Winetest", KEY_WOW64_32KEY
, 32 );
1159 pRtlInitUnicodeString( &str
, wine64W
);
1160 status
= pNtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1161 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1162 check_key_value( key
, "Winetest", 0, ptr_size
);
1163 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : ptr_size
);
1164 check_key_value( key
, "Winetest", KEY_WOW64_32KEY
, ptr_size
);
1169 status
= pNtCreateKey( &key
, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1170 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1171 dw
= get_key_value( key
, "Winetest", 0 );
1172 ok( dw
== 64 || broken(dw
== 32) /* xp64 */, "wrong value %u\n", dw
);
1173 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, 64 );
1174 dw
= get_key_value( key
, "Winetest", KEY_WOW64_32KEY
);
1175 todo_wine
ok( dw
== 32, "wrong value %u\n", dw
);
1178 status
= pNtCreateKey( &key
, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1179 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1180 check_key_value( key
, "Winetest", 0, 32 );
1181 check_key_value( key
, "Winetest", KEY_WOW64_64KEY
, is_vista
? 64 : 32 );
1182 check_key_value( key
, "Winetest", KEY_WOW64_32KEY
, 32 );
1186 status
= pNtDeleteKey( key32
);
1187 ok( status
== STATUS_SUCCESS
, "NtDeleteKey failed: 0x%08x\n", status
);
1190 status
= pNtDeleteKey( key64
);
1191 ok( status
== STATUS_SUCCESS
, "NtDeleteKey failed: 0x%08x\n", status
);
1194 pNtDeleteKey( root32
);
1196 pNtDeleteKey( root64
);
1199 /* Software\Classes is shared/reflected so behavior is different */
1201 pRtlInitUnicodeString( &str
, classes64W
);
1202 status
= pNtCreateKey( &key64
, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1203 if (status
== STATUS_ACCESS_DENIED
)
1205 skip("Not authorized to modify the Classes key\n");
1208 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1210 pRtlInitUnicodeString( &str
, classes32W
);
1211 status
= pNtCreateKey( &key32
, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1212 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1215 status
= pNtSetValueKey( key64
, &value_str
, 0, REG_DWORD
, &dw
, sizeof(dw
) );
1216 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
1220 status
= pNtSetValueKey( key32
, &value_str
, 0, REG_DWORD
, &dw
, sizeof(dw
) );
1221 ok( status
== STATUS_SUCCESS
, "NtSetValueKey failed: 0x%08x\n", status
);
1224 pRtlInitUnicodeString( &str
, classes64W
);
1225 status
= pNtCreateKey( &key64
, KEY_WOW64_64KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1226 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1227 len
= sizeof(buffer
);
1228 status
= pNtQueryValueKey( key64
, &value_str
, KeyValuePartialInformation
, info
, len
, &len
);
1229 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
1230 dw
= *(DWORD
*)info
->Data
;
1231 ok( dw
== ptr_size
, "wrong value %u\n", dw
);
1233 pRtlInitUnicodeString( &str
, classes32W
);
1234 status
= pNtCreateKey( &key32
, KEY_WOW64_32KEY
| KEY_ALL_ACCESS
, &attr
, 0, 0, 0, 0 );
1235 ok( status
== STATUS_SUCCESS
, "NtCreateKey failed: 0x%08x\n", status
);
1236 len
= sizeof(buffer
);
1237 status
= pNtQueryValueKey( key32
, &value_str
, KeyValuePartialInformation
, info
, len
, &len
);
1238 ok( status
== STATUS_SUCCESS
, "NtQueryValueKey failed: 0x%08x\n", status
);
1239 dw
= *(DWORD
*)info
->Data
;
1240 ok( dw
== 32, "wrong value %u\n", dw
);
1242 pNtDeleteKey( key32
);
1244 pNtDeleteKey( key64
);
1248 static void test_long_value_name(void)
1251 NTSTATUS status
, expected
;
1252 OBJECT_ATTRIBUTES attr
;
1253 UNICODE_STRING ValName
;
1256 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
1257 status
= pNtOpenKey(&key
, KEY_WRITE
|KEY_READ
, &attr
);
1258 ok(status
== STATUS_SUCCESS
, "NtOpenKey Failed: 0x%08x\n", status
);
1260 ValName
.MaximumLength
= 0xfffc;
1261 ValName
.Length
= ValName
.MaximumLength
- sizeof(WCHAR
);
1262 ValName
.Buffer
= HeapAlloc(GetProcessHeap(), 0, ValName
.MaximumLength
);
1263 for (i
= 0; i
< ValName
.Length
/ sizeof(WCHAR
); i
++)
1264 ValName
.Buffer
[i
] = 'a';
1265 ValName
.Buffer
[i
] = 0;
1267 status
= pNtDeleteValueKey(key
, &ValName
);
1268 ok(status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtDeleteValueKey with nonexistent long value name returned 0x%08x\n", status
);
1269 status
= pNtSetValueKey(key
, &ValName
, 0, REG_DWORD
, &i
, sizeof(i
));
1270 ok(status
== STATUS_INVALID_PARAMETER
|| broken(status
== STATUS_SUCCESS
) /* nt4 */,
1271 "NtSetValueKey with long value name returned 0x%08x\n", status
);
1272 expected
= (status
== STATUS_SUCCESS
) ? STATUS_SUCCESS
: STATUS_OBJECT_NAME_NOT_FOUND
;
1273 status
= pNtDeleteValueKey(key
, &ValName
);
1274 ok(status
== expected
, "NtDeleteValueKey with long value name returned 0x%08x\n", status
);
1276 status
= pNtQueryValueKey(key
, &ValName
, KeyValueBasicInformation
, NULL
, 0, &i
);
1277 ok(status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtQueryValueKey with nonexistent long value name returned 0x%08x\n", status
);
1279 pRtlFreeUnicodeString(&ValName
);
1283 static void test_NtQueryKey(void)
1287 OBJECT_ATTRIBUTES attr
;
1289 KEY_NAME_INFORMATION
*info
= NULL
;
1292 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
1293 status
= pNtOpenKey(&key
, KEY_READ
, &attr
);
1294 ok(status
== STATUS_SUCCESS
, "NtOpenKey Failed: 0x%08x\n", status
);
1296 status
= pNtQueryKey(key
, KeyNameInformation
, NULL
, 0, &len
);
1297 if (status
== STATUS_INVALID_PARAMETER
) {
1298 win_skip("KeyNameInformation is not supported\n");
1302 todo_wine
ok(status
== STATUS_BUFFER_TOO_SMALL
, "NtQueryKey Failed: 0x%08x\n", status
);
1304 info
= HeapAlloc(GetProcessHeap(), 0, len
);
1305 status
= pNtQueryKey(key
, KeyNameInformation
, info
, len
, &len
);
1306 ok(status
== STATUS_SUCCESS
, "NtQueryKey Failed: 0x%08x\n", status
);
1308 str
.Buffer
= info
->Name
;
1309 str
.Length
= info
->NameLength
;
1310 todo_wine
ok(pRtlCompareUnicodeString(&winetestpath
, &str
, TRUE
) == 0,
1311 "got %s, expected %s\n",
1312 wine_dbgstr_wn(str
.Buffer
, str
.Length
/sizeof(WCHAR
)),
1313 wine_dbgstr_wn(winetestpath
.Buffer
, winetestpath
.Length
/sizeof(WCHAR
)));
1315 HeapFree(GetProcessHeap(), 0, info
);
1321 static const WCHAR winetest
[] = {'\\','W','i','n','e','T','e','s','t',0};
1322 if(!InitFunctionPtrs())
1324 pRtlFormatCurrentUserKeyPath(&winetestpath
);
1325 winetestpath
.Buffer
= pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, winetestpath
.Buffer
,
1326 winetestpath
.MaximumLength
+ sizeof(winetest
)*sizeof(WCHAR
));
1327 winetestpath
.MaximumLength
= winetestpath
.MaximumLength
+ sizeof(winetest
)*sizeof(WCHAR
);
1329 pRtlAppendUnicodeToString(&winetestpath
, winetest
);
1333 test_NtSetValueKey();
1334 test_RtlCheckRegistryKey();
1335 test_RtlOpenCurrentUser();
1336 test_RtlQueryRegistryValues();
1337 test_RtlpNtQueryValueKey();
1340 test_NtQueryValueKey();
1341 test_long_value_name();
1346 pRtlFreeUnicodeString(&winetestpath
);
1348 FreeLibrary(hntdll
);