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 NTSTATUS (WINAPI
* pRtlCreateUnicodeStringFromAsciiz
)(PUNICODE_STRING
, LPCSTR
);
119 static NTSTATUS (WINAPI
* pRtlFreeUnicodeString
)(PUNICODE_STRING
);
120 static NTSTATUS (WINAPI
* pNtDeleteValueKey
)(IN HANDLE
, IN PUNICODE_STRING
);
121 static NTSTATUS (WINAPI
* pRtlQueryRegistryValues
)(IN ULONG
, IN PCWSTR
,IN PRTL_QUERY_REGISTRY_TABLE
, IN PVOID
,IN PVOID
);
122 static NTSTATUS (WINAPI
* pRtlCheckRegistryKey
)(IN ULONG
,IN PWSTR
);
123 static NTSTATUS (WINAPI
* pRtlOpenCurrentUser
)(IN ACCESS_MASK
, OUT PHKEY
);
124 static NTSTATUS (WINAPI
* pNtOpenKey
)(PHANDLE
, IN ACCESS_MASK
, IN POBJECT_ATTRIBUTES
);
125 static NTSTATUS (WINAPI
* pNtClose
)(IN HANDLE
);
126 static NTSTATUS (WINAPI
* pNtDeleteValueKey
)(IN HANDLE
, IN PUNICODE_STRING
);
127 static NTSTATUS (WINAPI
* pNtFlushKey
)(HKEY
);
128 static NTSTATUS (WINAPI
* pNtDeleteKey
)(HKEY
);
129 static NTSTATUS (WINAPI
* pNtCreateKey
)( PHKEY retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
130 ULONG TitleIndex
, const UNICODE_STRING
*class, ULONG options
,
132 static NTSTATUS (WINAPI
* pNtQueryValueKey
)(HANDLE
,const UNICODE_STRING
*,KEY_VALUE_INFORMATION_CLASS
,void *,DWORD
,DWORD
*);
133 static NTSTATUS (WINAPI
* pNtSetValueKey
)( PHKEY
, const PUNICODE_STRING
, ULONG
,
134 ULONG
, const PVOID
, ULONG
);
135 static NTSTATUS (WINAPI
* pRtlFormatCurrentUserKeyPath
)(PUNICODE_STRING
);
136 static NTSTATUS (WINAPI
* pRtlCreateUnicodeString
)( PUNICODE_STRING
, LPCWSTR
);
137 static LPVOID (WINAPI
* pRtlReAllocateHeap
)(IN PVOID
, IN ULONG
, IN PVOID
, IN ULONG
);
138 static NTSTATUS (WINAPI
* pRtlAppendUnicodeToString
)(PUNICODE_STRING
, PCWSTR
);
139 static NTSTATUS (WINAPI
* pRtlUnicodeStringToAnsiString
)(PSTRING
, PUNICODE_STRING
, BOOL
);
140 static NTSTATUS (WINAPI
* pRtlFreeHeap
)(PVOID
, ULONG
, PVOID
);
141 static LPVOID (WINAPI
* pRtlAllocateHeap
)(PVOID
,ULONG
,ULONG
);
142 static NTSTATUS (WINAPI
* pRtlZeroMemory
)(PVOID
, ULONG
);
143 static NTSTATUS (WINAPI
* pRtlpNtQueryValueKey
)(HANDLE
,ULONG
*,PBYTE
,DWORD
*);
145 static HMODULE hntdll
= 0;
146 static int CurrentTest
= 0;
147 static UNICODE_STRING winetestpath
;
149 #define NTDLL_GET_PROC(func) \
150 p ## func = (void*)GetProcAddress(hntdll, #func); \
152 trace("GetProcAddress(%s) failed\n", #func); \
153 FreeLibrary(hntdll); \
157 static BOOL
InitFunctionPtrs(void)
159 hntdll
= LoadLibraryA("ntdll.dll");
161 trace("Could not load ntdll.dll\n");
164 NTDLL_GET_PROC(RtlCreateUnicodeStringFromAsciiz
)
165 NTDLL_GET_PROC(RtlCreateUnicodeString
)
166 NTDLL_GET_PROC(RtlFreeUnicodeString
)
167 NTDLL_GET_PROC(NtDeleteValueKey
)
168 NTDLL_GET_PROC(RtlQueryRegistryValues
)
169 NTDLL_GET_PROC(RtlCheckRegistryKey
)
170 NTDLL_GET_PROC(RtlOpenCurrentUser
)
171 NTDLL_GET_PROC(NtClose
)
172 NTDLL_GET_PROC(NtDeleteValueKey
)
173 NTDLL_GET_PROC(NtCreateKey
)
174 NTDLL_GET_PROC(NtFlushKey
)
175 NTDLL_GET_PROC(NtDeleteKey
)
176 NTDLL_GET_PROC(NtQueryValueKey
)
177 NTDLL_GET_PROC(NtSetValueKey
)
178 NTDLL_GET_PROC(NtOpenKey
)
179 NTDLL_GET_PROC(RtlFormatCurrentUserKeyPath
)
180 NTDLL_GET_PROC(RtlReAllocateHeap
)
181 NTDLL_GET_PROC(RtlAppendUnicodeToString
)
182 NTDLL_GET_PROC(RtlUnicodeStringToAnsiString
)
183 NTDLL_GET_PROC(RtlFreeHeap
)
184 NTDLL_GET_PROC(RtlAllocateHeap
)
185 NTDLL_GET_PROC(RtlZeroMemory
)
186 NTDLL_GET_PROC(RtlpNtQueryValueKey
)
189 #undef NTDLL_GET_PROC
191 static NTSTATUS WINAPI
QueryRoutine (IN PCWSTR ValueName
, IN ULONG ValueType
, IN PVOID ValueData
,
192 IN ULONG ValueLength
, IN PVOID Context
, IN PVOID EntryContext
)
194 NTSTATUS ret
= STATUS_SUCCESS
;
195 int ValueNameLength
= 0;
197 trace("**Test %d**\n", CurrentTest
);
201 ValueNameLength
= lstrlenW(ValueName
);
203 ValName
= pRtlAllocateHeap(GetProcessHeap(), 0, ValueNameLength
);
205 WideCharToMultiByte(0, 0, ValueName
, ValueNameLength
+1,ValName
, ValueNameLength
, 0, 0);
207 trace("ValueName: %s\n", ValName
);
210 trace("ValueName: (null)\n");
215 trace("ValueType: REG_NONE\n");
216 trace("ValueData: %p\n", ValueData
);
220 trace("ValueType: REG_BINARY\n");
221 trace("ValueData: %p\n", ValueData
);
225 trace("ValueType: REG_SZ\n");
226 trace("ValueData: %s\n", (char*)ValueData
);
230 trace("ValueType: REG_MULTI_SZ\n");
231 trace("ValueData: %s\n", (char*)ValueData
);
235 trace("ValueType: REG_EXPAND_SZ\n");
236 trace("ValueData: %s\n", (char*)ValueData
);
240 trace("ValueType: REG_DWORD\n");
241 trace("ValueData: %p\n", ValueData
);
244 trace("ValueLength: %d\n", (int)ValueLength
);
247 ok(1, "\n"); /*checks that QueryRoutine is called*/
249 ok(!1, "Invalid Test Specified!\n");
254 pRtlFreeHeap(GetProcessHeap(), 0, ValName
);
259 static void test_RtlQueryRegistryValues(void)
263 ******************************
265 ******************************
266 *RTL_QUERY_REGISTRY_SUBKEY * Name is the name of a subkey relative to Path
267 *RTL_QUERY_REGISTRY_TOPKEY * Resets location to original RelativeTo and Path
268 *RTL_QUERY_REGISTRY_REQUIRED * Key required. returns STATUS_OBJECT_NAME_NOT_FOUND if not present
269 *RTL_QUERY_REGISTRY_NOVALUE * We just want a call-back
270 *RTL_QUERY_REGISTRY_NOEXPAND * Don't expand the variables!
271 *RTL_QUERY_REGISTRY_DIRECT * Results of query will be stored in EntryContext(QueryRoutine ignored)
272 *RTL_QUERY_REGISTRY_DELETE * Delete value key after query
273 ******************************
276 **Test layout(numbered according to CurrentTest value)**
277 0)NOVALUE Just make sure call-back works
278 1)Null Name See if QueryRoutine is called for every value in current key
279 2)SUBKEY See if we can use SUBKEY to change the current path on the fly
280 3)REQUIRED Test for value that's not there
281 4)NOEXPAND See if it will return multiple strings(no expand should split strings up)
282 5)DIRECT Make it store data directly in EntryContext and not call QueryRoutine
283 6)DefaultType Test return values when key isn't present
284 7)DefaultValue Test Default Value returned with key isn't present(and no REQUIRED flag set)
285 8)DefaultLength Test Default Length with DefaultType = REG_SZ
286 9)DefaultLength Test Default Length with DefaultType = REG_MULTI_SZ
287 10)DefaultLength Test Default Length with DefaultType = REG_EXPAND_SZ
288 11)DefaultData Test whether DefaultData is used while DefaultType = REG_NONE(shouldn't be)
289 12)Delete Try to delete value key
295 PRTL_QUERY_REGISTRY_TABLE QueryTable
= NULL
;
296 RelativeTo
= RTL_REGISTRY_ABSOLUTE
;/*Only using absolute - no need to test all relativeto variables*/
298 QueryTable
= pRtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_QUERY_REGISTRY_TABLE
)*26);
300 pRtlZeroMemory( QueryTable
, sizeof(RTL_QUERY_REGISTRY_TABLE
) * 26);
302 QueryTable
[0].QueryRoutine
= QueryRoutine
;
303 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_NOVALUE
;
304 QueryTable
[0].Name
= NULL
;
305 QueryTable
[0].EntryContext
= NULL
;
306 QueryTable
[0].DefaultType
= REG_BINARY
;
307 QueryTable
[0].DefaultData
= NULL
;
308 QueryTable
[0].DefaultLength
= 100;
310 QueryTable
[1].QueryRoutine
= QueryRoutine
;
311 QueryTable
[1].Flags
= 0;
312 QueryTable
[1].Name
= NULL
;
313 QueryTable
[1].EntryContext
= 0;
314 QueryTable
[1].DefaultType
= REG_NONE
;
315 QueryTable
[1].DefaultData
= NULL
;
316 QueryTable
[1].DefaultLength
= 0;
318 QueryTable
[2].QueryRoutine
= NULL
;
319 QueryTable
[2].Flags
= 0;
320 QueryTable
[2].Name
= NULL
;
321 QueryTable
[2].EntryContext
= 0;
322 QueryTable
[2].DefaultType
= REG_NONE
;
323 QueryTable
[2].DefaultData
= NULL
;
324 QueryTable
[2].DefaultLength
= 0;
326 status
= pRtlQueryRegistryValues(RelativeTo
, winetestpath
.Buffer
, QueryTable
, 0, 0);
327 ok(status
== STATUS_SUCCESS
, "RtlQueryRegistryValues return: 0x%08x\n", status
);
329 pRtlFreeHeap(GetProcessHeap(), 0, QueryTable
);
332 static void test_NtOpenKey(void)
336 OBJECT_ATTRIBUTES attr
;
337 ACCESS_MASK am
= KEY_READ
;
343 status
= pNtOpenKey(NULL
, 0, NULL
);
344 ok(status
== STATUS_ACCESS_VIOLATION
, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status
);
346 /* NULL attributes */
347 status
= pNtOpenKey(&key
, 0, NULL
);
348 ok(status
== STATUS_ACCESS_VIOLATION
/* W2K3/XP/W2K */ || status
== STATUS_INVALID_PARAMETER
/* NT4 */,
349 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status
);
352 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
355 status
= pNtOpenKey(NULL
, 0, &attr
);
357 ok(status
== STATUS_ACCESS_VIOLATION
, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status
);
359 /* Length > sizeof(OBJECT_ATTRIBUTES) */
361 status
= pNtOpenKey(&key
, am
, &attr
);
363 ok(status
== STATUS_INVALID_PARAMETER
, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status
);
366 static void test_NtCreateKey(void)
369 OBJECT_ATTRIBUTES attr
;
371 ACCESS_MASK am
= GENERIC_ALL
;
375 status
= pNtCreateKey(NULL
, 0, NULL
, 0, 0, 0, 0);
376 ok(status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_PARAMETER
,
377 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got: 0x%08x\n", status
);
380 status
= pNtCreateKey(&key
, 0, NULL
, 0, 0, 0, 0);
381 ok(status
== STATUS_ACCESS_VIOLATION
/* W2K3/XP/W2K */ || status
== STATUS_INVALID_PARAMETER
/* NT4 */,
382 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status
);
384 /* Only accessmask */
385 status
= pNtCreateKey(NULL
, am
, NULL
, 0, 0, 0, 0);
386 ok(status
== STATUS_ACCESS_VIOLATION
|| status
== STATUS_INVALID_PARAMETER
,
387 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got: 0x%08x\n", status
);
389 /* Key and accessmask */
390 status
= pNtCreateKey(&key
, am
, NULL
, 0, 0, 0, 0);
391 ok(status
== STATUS_ACCESS_VIOLATION
/* W2K3/XP/W2K */ || status
== STATUS_INVALID_PARAMETER
/* NT4 */,
392 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status
);
394 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
396 /* Only attributes */
397 status
= pNtCreateKey(NULL
, 0, &attr
, 0, 0, 0, 0);
398 ok(status
== STATUS_ACCESS_VIOLATION
, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status
);
400 status
= pNtCreateKey(&key
, am
, &attr
, 0, 0, 0, 0);
401 ok(status
== STATUS_SUCCESS
, "NtCreateKey Failed: 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
);
411 static void test_NtSetValueKey(void)
415 OBJECT_ATTRIBUTES attr
;
416 ACCESS_MASK am
= KEY_WRITE
;
417 UNICODE_STRING ValName
;
420 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
421 status
= pNtOpenKey(&key
, am
, &attr
);
422 ok(status
== STATUS_SUCCESS
, "NtOpenKey Failed: 0x%08x\n", status
);
424 pRtlCreateUnicodeStringFromAsciiz(&ValName
, "deletetest");
425 status
= pNtSetValueKey(key
, &ValName
, 0, REG_DWORD
, &data
, sizeof(data
));
426 ok(status
== STATUS_SUCCESS
, "NtSetValueKey Failed: 0x%08x\n", status
);
427 pRtlFreeUnicodeString(&ValName
);
429 pRtlCreateUnicodeStringFromAsciiz(&ValName
, "stringtest");
430 status
= pNtSetValueKey(key
, &ValName
, 0, REG_SZ
, (VOID
*)stringW
, STR_TRUNC_SIZE
);
431 ok(status
== STATUS_SUCCESS
, "NtSetValueKey Failed: 0x%08x\n", status
);
432 pRtlFreeUnicodeString(&ValName
);
437 static void test_RtlOpenCurrentUser(void)
441 status
=pRtlOpenCurrentUser(KEY_READ
, &handle
);
442 ok(status
== STATUS_SUCCESS
, "RtlOpenCurrentUser Failed: 0x%08x\n", status
);
446 static void test_RtlCheckRegistryKey(void)
450 status
= pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE
, winetestpath
.Buffer
);
451 ok(status
== STATUS_SUCCESS
, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08x\n", status
);
453 status
= pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE
| RTL_REGISTRY_OPTIONAL
), winetestpath
.Buffer
);
454 ok(status
== STATUS_SUCCESS
, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE and RTL_REGISTRY_OPTIONAL: 0x%08x\n", status
);
457 static void test_NtFlushKey(void)
461 OBJECT_ATTRIBUTES attr
;
462 ACCESS_MASK am
= KEY_ALL_ACCESS
;
464 status
= pNtFlushKey(NULL
);
465 ok(status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status
);
467 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
468 pNtOpenKey(&hkey
, am
, &attr
);
470 status
= pNtFlushKey(hkey
);
471 ok(status
== STATUS_SUCCESS
, "NtDeleteKey Failed: 0x%08x\n", status
);
476 static void test_NtQueryValueKey(void)
480 OBJECT_ATTRIBUTES attr
;
481 UNICODE_STRING ValName
;
482 KEY_VALUE_BASIC_INFORMATION
*basic_info
;
483 KEY_VALUE_PARTIAL_INFORMATION
*partial_info
;
484 KEY_VALUE_FULL_INFORMATION
*full_info
;
487 pRtlCreateUnicodeStringFromAsciiz(&ValName
, "deletetest");
489 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
490 status
= pNtOpenKey(&key
, KEY_READ
, &attr
);
491 ok(status
== STATUS_SUCCESS
, "NtOpenKey Failed: 0x%08x\n", status
);
493 len
= FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]);
494 basic_info
= HeapAlloc(GetProcessHeap(), 0, len
);
495 status
= pNtQueryValueKey(key
, &ValName
, KeyValueBasicInformation
, basic_info
, len
, &len
);
496 ok(status
== STATUS_BUFFER_OVERFLOW
, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status
);
497 ok(basic_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info
->TitleIndex
);
498 ok(basic_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", basic_info
->Type
);
499 ok(basic_info
->NameLength
== 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info
->NameLength
);
500 ok(len
== FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[basic_info
->NameLength
/sizeof(WCHAR
)]), "NtQueryValueKey returned wrong len %d\n", len
);
502 basic_info
= HeapReAlloc(GetProcessHeap(), 0, basic_info
, len
);
503 status
= pNtQueryValueKey(key
, &ValName
, KeyValueBasicInformation
, basic_info
, len
, &len
);
504 ok(status
== STATUS_SUCCESS
, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status
);
505 ok(basic_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info
->TitleIndex
);
506 ok(basic_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", basic_info
->Type
);
507 ok(basic_info
->NameLength
== 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info
->NameLength
);
508 ok(len
== FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[basic_info
->NameLength
/sizeof(WCHAR
)]), "NtQueryValueKey returned wrong len %d\n", len
);
509 ok(!memcmp(basic_info
->Name
, ValName
.Buffer
, ValName
.Length
), "incorrect Name returned\n");
510 HeapFree(GetProcessHeap(), 0, basic_info
);
512 len
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
513 partial_info
= HeapAlloc(GetProcessHeap(), 0, len
);
514 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, partial_info
, len
, &len
);
515 ok(status
== STATUS_BUFFER_OVERFLOW
, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status
);
516 ok(partial_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info
->TitleIndex
);
517 ok(partial_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", partial_info
->Type
);
518 ok(partial_info
->DataLength
== 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info
->DataLength
);
519 ok(len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[partial_info
->DataLength
]), "NtQueryValueKey returned wrong len %d\n", len
);
521 partial_info
= HeapReAlloc(GetProcessHeap(), 0, partial_info
, len
);
522 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, partial_info
, len
, &len
);
523 ok(status
== STATUS_SUCCESS
, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status
);
524 ok(partial_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info
->TitleIndex
);
525 ok(partial_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", partial_info
->Type
);
526 ok(partial_info
->DataLength
== 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info
->DataLength
);
527 ok(len
== FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[partial_info
->DataLength
]), "NtQueryValueKey returned wrong len %d\n", len
);
528 ok(*(DWORD
*)partial_info
->Data
== 711, "incorrect Data returned: 0x%x\n", *(DWORD
*)partial_info
->Data
);
529 HeapFree(GetProcessHeap(), 0, partial_info
);
531 len
= FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]);
532 full_info
= HeapAlloc(GetProcessHeap(), 0, len
);
533 status
= pNtQueryValueKey(key
, &ValName
, KeyValueFullInformation
, full_info
, len
, &len
);
534 ok(status
== STATUS_BUFFER_OVERFLOW
, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status
);
535 ok(full_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info
->TitleIndex
);
536 ok(full_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", full_info
->Type
);
537 ok(full_info
->DataLength
== 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info
->DataLength
);
538 ok(full_info
->NameLength
== 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info
->NameLength
);
539 ok(len
== FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]) + full_info
->DataLength
+ full_info
->NameLength
,
540 "NtQueryValueKey returned wrong len %d\n", len
);
541 len
= FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]) + full_info
->DataLength
+ full_info
->NameLength
;
543 full_info
= HeapReAlloc(GetProcessHeap(), 0, full_info
, len
);
544 status
= pNtQueryValueKey(key
, &ValName
, KeyValueFullInformation
, full_info
, len
, &len
);
545 ok(status
== STATUS_SUCCESS
, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status
);
546 ok(full_info
->TitleIndex
== 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info
->TitleIndex
);
547 ok(full_info
->Type
== REG_DWORD
, "NtQueryValueKey returned wrong Type %d\n", full_info
->Type
);
548 ok(full_info
->DataLength
== 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info
->DataLength
);
549 ok(full_info
->NameLength
== 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info
->NameLength
);
550 ok(!memcmp(full_info
->Name
, ValName
.Buffer
, ValName
.Length
), "incorrect Name returned\n");
551 ok(*(DWORD
*)((char *)full_info
+ full_info
->DataOffset
) == 711, "incorrect Data returned: 0x%x\n",
552 *(DWORD
*)((char *)full_info
+ full_info
->DataOffset
));
553 HeapFree(GetProcessHeap(), 0, full_info
);
555 pRtlFreeUnicodeString(&ValName
);
556 pRtlCreateUnicodeStringFromAsciiz(&ValName
, "stringtest");
558 status
= pNtQueryValueKey(key
, &ValName
, KeyValuePartialInformation
, NULL
, 0, &len
);
559 todo_wine
ok(status
== STATUS_BUFFER_TOO_SMALL
, "NtQueryValueKey should have returned STATUS_BUFFER_TOO_SMALL instead of 0x%08x\n", status
);
560 partial_info
= HeapAlloc(GetProcessHeap(), 0, len
+1);
561 memset((BYTE
*)partial_info
, 0xbd, len
+1);
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_SZ
, "NtQueryValueKey returned wrong Type %d\n", partial_info
->Type
);
566 ok(partial_info
->DataLength
== STR_TRUNC_SIZE
, "NtQueryValueKey returned wrong DataLength %d\n", partial_info
->DataLength
);
567 ok(!memcmp(partial_info
->Data
, stringW
, STR_TRUNC_SIZE
), "incorrect Data returned\n");
568 ok(*(partial_info
->Data
+STR_TRUNC_SIZE
) == 0xbd, "string overflowed %02x\n", *(partial_info
->Data
+STR_TRUNC_SIZE
));
569 HeapFree(GetProcessHeap(), 0, partial_info
);
571 pRtlFreeUnicodeString(&ValName
);
575 static void test_NtDeleteKey(void)
579 OBJECT_ATTRIBUTES attr
;
580 ACCESS_MASK am
= KEY_ALL_ACCESS
;
582 status
= pNtDeleteKey(NULL
);
583 ok(status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status
);
585 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
586 status
= pNtOpenKey(&hkey
, am
, &attr
);
588 status
= pNtDeleteKey(hkey
);
589 ok(status
== STATUS_SUCCESS
, "NtDeleteKey Failed: 0x%08x\n", status
);
592 static void test_RtlpNtQueryValueKey(void)
596 status
= pRtlpNtQueryValueKey(NULL
, NULL
, NULL
, NULL
);
597 ok(status
== STATUS_INVALID_HANDLE
, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status
);
602 static const WCHAR winetest
[] = {'\\','W','i','n','e','T','e','s','t',0};
603 if(!InitFunctionPtrs())
605 pRtlFormatCurrentUserKeyPath(&winetestpath
);
606 winetestpath
.Buffer
= pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, winetestpath
.Buffer
,
607 winetestpath
.MaximumLength
+ sizeof(winetest
)*sizeof(WCHAR
));
608 winetestpath
.MaximumLength
= winetestpath
.MaximumLength
+ sizeof(winetest
)*sizeof(WCHAR
);
610 pRtlAppendUnicodeToString(&winetestpath
, winetest
);
614 test_NtSetValueKey();
615 test_RtlCheckRegistryKey();
616 test_RtlOpenCurrentUser();
617 test_RtlQueryRegistryValues();
618 test_RtlpNtQueryValueKey();
620 test_NtQueryValueKey();
623 pRtlFreeUnicodeString(&winetestpath
);