ntdll/tests: Test NtOpenKey with an existing key.
[wine/multimedia.git] / dlls / ntdll / tests / reg.c
blobbb541bb8b2c71602520caba6575a9eabf751e1ad
1 /* Unit test suite for Rtl* Registry API functions
3 * Copyright 2003 Thomas Mertes
4 * Copyright 2005 Brad DeMorrow
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * NOTE: I don't test every RelativeTo value because it would be redundant, all calls go through
21 * helper function RTL_GetKeyHandle().--Brad DeMorrow
25 #include "ntdll_test.h"
26 #include "winternl.h"
27 #include "stdio.h"
28 #include "winnt.h"
29 #include "winnls.h"
30 #include "stdlib.h"
32 /* A test string */
33 static const WCHAR stringW[] = {'s', 't', 'r', 'i', 'n', 'g', 'W', 0};
34 /* A size, in bytes, short enough to cause truncation of the above */
35 #define STR_TRUNC_SIZE (sizeof(stringW)-2*sizeof(*stringW))
37 #ifndef __WINE_WINTERNL_H
39 /* RtlQueryRegistryValues structs and defines */
40 #define RTL_REGISTRY_ABSOLUTE 0
41 #define RTL_REGISTRY_SERVICES 1
42 #define RTL_REGISTRY_CONTROL 2
43 #define RTL_REGISTRY_WINDOWS_NT 3
44 #define RTL_REGISTRY_DEVICEMAP 4
45 #define RTL_REGISTRY_USER 5
47 #define RTL_REGISTRY_HANDLE 0x40000000
48 #define RTL_REGISTRY_OPTIONAL 0x80000000
50 #define RTL_QUERY_REGISTRY_SUBKEY 0x00000001
51 #define RTL_QUERY_REGISTRY_TOPKEY 0x00000002
52 #define RTL_QUERY_REGISTRY_REQUIRED 0x00000004
53 #define RTL_QUERY_REGISTRY_NOVALUE 0x00000008
54 #define RTL_QUERY_REGISTRY_NOEXPAND 0x00000010
55 #define RTL_QUERY_REGISTRY_DIRECT 0x00000020
56 #define RTL_QUERY_REGISTRY_DELETE 0x00000040
58 typedef NTSTATUS (WINAPI *PRTL_QUERY_REGISTRY_ROUTINE)( PCWSTR ValueName,
59 ULONG ValueType,
60 PVOID ValueData,
61 ULONG ValueLength,
62 PVOID Context,
63 PVOID EntryContext);
65 typedef struct _RTL_QUERY_REGISTRY_TABLE {
66 PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine;
67 ULONG Flags;
68 PWSTR Name;
69 PVOID EntryContext;
70 ULONG DefaultType;
71 PVOID DefaultData;
72 ULONG DefaultLength;
73 } RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE;
75 typedef struct _KEY_VALUE_BASIC_INFORMATION {
76 ULONG TitleIndex;
77 ULONG Type;
78 ULONG NameLength;
79 WCHAR Name[1];
80 } KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION;
82 typedef struct _KEY_VALUE_PARTIAL_INFORMATION {
83 ULONG TitleIndex;
84 ULONG Type;
85 ULONG DataLength;
86 UCHAR Data[1];
87 } KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION;
89 typedef struct _KEY_VALUE_FULL_INFORMATION {
90 ULONG TitleIndex;
91 ULONG Type;
92 ULONG DataOffset;
93 ULONG DataLength;
94 ULONG NameLength;
95 WCHAR Name[1];
96 } KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION;
98 typedef enum _KEY_VALUE_INFORMATION_CLASS {
99 KeyValueBasicInformation,
100 KeyValueFullInformation,
101 KeyValuePartialInformation,
102 KeyValueFullInformationAlign64,
103 KeyValuePartialInformationAlign64
104 } KEY_VALUE_INFORMATION_CLASS;
106 #define InitializeObjectAttributes(p,n,a,r,s) \
107 do { \
108 (p)->Length = sizeof(OBJECT_ATTRIBUTES); \
109 (p)->RootDirectory = r; \
110 (p)->Attributes = a; \
111 (p)->ObjectName = n; \
112 (p)->SecurityDescriptor = s; \
113 (p)->SecurityQualityOfService = NULL; \
114 } while (0)
116 #endif
118 static 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, PHANDLE);
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)(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,
131 PULONG dispos );
132 static NTSTATUS (WINAPI * pNtQueryValueKey)(HANDLE,const UNICODE_STRING *,KEY_VALUE_INFORMATION_CLASS,void *,DWORD,DWORD *);
133 static NTSTATUS (WINAPI * pNtSetValueKey)(HANDLE, const PUNICODE_STRING, ULONG,
134 ULONG, const void*, 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*,void *);
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); \
151 if(!p ## func) { \
152 trace("GetProcAddress(%s) failed\n", #func); \
153 FreeLibrary(hntdll); \
154 return FALSE; \
157 static BOOL InitFunctionPtrs(void)
159 hntdll = LoadLibraryA("ntdll.dll");
160 if(!hntdll) {
161 trace("Could not load ntdll.dll\n");
162 return FALSE;
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)
187 return TRUE;
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;
196 LPSTR ValName = 0;
197 trace("**Test %d**\n", CurrentTest);
199 if(ValueName)
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);
209 else
210 trace("ValueName: (null)\n");
212 switch(ValueType)
214 case REG_NONE:
215 trace("ValueType: REG_NONE\n");
216 trace("ValueData: %p\n", ValueData);
217 break;
219 case REG_BINARY:
220 trace("ValueType: REG_BINARY\n");
221 trace("ValueData: %p\n", ValueData);
222 break;
224 case REG_SZ:
225 trace("ValueType: REG_SZ\n");
226 trace("ValueData: %s\n", (char*)ValueData);
227 break;
229 case REG_MULTI_SZ:
230 trace("ValueType: REG_MULTI_SZ\n");
231 trace("ValueData: %s\n", (char*)ValueData);
232 break;
234 case REG_EXPAND_SZ:
235 trace("ValueType: REG_EXPAND_SZ\n");
236 trace("ValueData: %s\n", (char*)ValueData);
237 break;
239 case REG_DWORD:
240 trace("ValueType: REG_DWORD\n");
241 trace("ValueData: %p\n", ValueData);
242 break;
244 trace("ValueLength: %d\n", (int)ValueLength);
246 if(CurrentTest == 0)
247 ok(1, "\n"); /*checks that QueryRoutine is called*/
248 if(CurrentTest > 7)
249 ok(!1, "Invalid Test Specified!\n");
251 CurrentTest++;
253 if(ValName)
254 pRtlFreeHeap(GetProcessHeap(), 0, ValName);
256 return ret;
259 static void test_RtlQueryRegistryValues(void)
263 ******************************
264 * QueryTable Flags *
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
292 NTSTATUS status;
293 ULONG RelativeTo;
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)
334 HANDLE key;
335 NTSTATUS status;
336 OBJECT_ATTRIBUTES attr;
337 ACCESS_MASK am = KEY_READ;
339 /* All NULL */
340 status = pNtOpenKey(NULL, 0, NULL);
341 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
343 /* NULL attributes */
344 status = pNtOpenKey(&key, 0, NULL);
345 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
346 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
348 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
350 /* NULL key */
351 status = pNtOpenKey(NULL, 0, &attr);
352 todo_wine
353 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
355 /* Length > sizeof(OBJECT_ATTRIBUTES) */
356 attr.Length *= 2;
357 status = pNtOpenKey(&key, am, &attr);
358 todo_wine
359 ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
362 static void test_NtCreateKey(void)
364 /*Create WineTest*/
365 OBJECT_ATTRIBUTES attr;
366 HANDLE key;
367 ACCESS_MASK am = GENERIC_ALL;
368 NTSTATUS status;
370 /* All NULL */
371 status = pNtCreateKey(NULL, 0, NULL, 0, 0, 0, 0);
372 ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER,
373 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
375 /* Only the key */
376 status = pNtCreateKey(&key, 0, NULL, 0, 0, 0, 0);
377 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
378 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
380 /* Only accessmask */
381 status = pNtCreateKey(NULL, am, NULL, 0, 0, 0, 0);
382 ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER,
383 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
385 /* Key and accessmask */
386 status = pNtCreateKey(&key, am, NULL, 0, 0, 0, 0);
387 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
388 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
390 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
392 /* Only attributes */
393 status = pNtCreateKey(NULL, 0, &attr, 0, 0, 0, 0);
394 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
396 status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
397 ok(status == STATUS_SUCCESS, "NtCreateKey Failed: 0x%08x\n", status);
399 /* Length > sizeof(OBJECT_ATTRIBUTES) */
400 attr.Length *= 2;
401 status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
402 ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
404 pNtClose(key);
407 static void test_NtSetValueKey(void)
409 HANDLE key;
410 NTSTATUS status;
411 OBJECT_ATTRIBUTES attr;
412 ACCESS_MASK am = KEY_WRITE;
413 UNICODE_STRING ValName;
414 DWORD data = 711;
416 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
417 status = pNtOpenKey(&key, am, &attr);
418 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
420 pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
421 status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &data, sizeof(data));
422 ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status);
423 pRtlFreeUnicodeString(&ValName);
425 pRtlCreateUnicodeStringFromAsciiz(&ValName, "stringtest");
426 status = pNtSetValueKey(key, &ValName, 0, REG_SZ, (VOID*)stringW, STR_TRUNC_SIZE);
427 ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status);
428 pRtlFreeUnicodeString(&ValName);
430 pNtClose(key);
433 static void test_RtlOpenCurrentUser(void)
435 NTSTATUS status;
436 HANDLE handle;
437 status=pRtlOpenCurrentUser(KEY_READ, &handle);
438 ok(status == STATUS_SUCCESS, "RtlOpenCurrentUser Failed: 0x%08x\n", status);
439 pNtClose(handle);
442 static void test_RtlCheckRegistryKey(void)
444 NTSTATUS status;
446 status = pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, winetestpath.Buffer);
447 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08x\n", status);
449 status = pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL), winetestpath.Buffer);
450 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE and RTL_REGISTRY_OPTIONAL: 0x%08x\n", status);
453 static void test_NtFlushKey(void)
455 NTSTATUS status;
456 HANDLE hkey;
457 OBJECT_ATTRIBUTES attr;
458 ACCESS_MASK am = KEY_ALL_ACCESS;
460 status = pNtFlushKey(NULL);
461 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
463 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
464 pNtOpenKey(&hkey, am, &attr);
466 status = pNtFlushKey(hkey);
467 ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
469 pNtClose(hkey);
472 static void test_NtQueryValueKey(void)
474 HANDLE key;
475 NTSTATUS status;
476 OBJECT_ATTRIBUTES attr;
477 UNICODE_STRING ValName;
478 KEY_VALUE_BASIC_INFORMATION *basic_info;
479 KEY_VALUE_PARTIAL_INFORMATION *partial_info;
480 KEY_VALUE_FULL_INFORMATION *full_info;
481 DWORD len;
483 pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
485 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
486 status = pNtOpenKey(&key, KEY_READ, &attr);
487 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
489 len = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]);
490 basic_info = HeapAlloc(GetProcessHeap(), 0, len);
491 status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, basic_info, len, &len);
492 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
493 ok(basic_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info->TitleIndex);
494 ok(basic_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", basic_info->Type);
495 ok(basic_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info->NameLength);
496 ok(len == FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[basic_info->NameLength/sizeof(WCHAR)]), "NtQueryValueKey returned wrong len %d\n", len);
498 basic_info = HeapReAlloc(GetProcessHeap(), 0, basic_info, len);
499 status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, basic_info, len, &len);
500 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
501 ok(basic_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info->TitleIndex);
502 ok(basic_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", basic_info->Type);
503 ok(basic_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info->NameLength);
504 ok(len == FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[basic_info->NameLength/sizeof(WCHAR)]), "NtQueryValueKey returned wrong len %d\n", len);
505 ok(!memcmp(basic_info->Name, ValName.Buffer, ValName.Length), "incorrect Name returned\n");
506 HeapFree(GetProcessHeap(), 0, basic_info);
508 len = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
509 partial_info = HeapAlloc(GetProcessHeap(), 0, len);
510 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
511 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
512 ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->TitleIndex);
513 ok(partial_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type);
514 ok(partial_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength);
515 ok(len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[partial_info->DataLength]), "NtQueryValueKey returned wrong len %d\n", len);
517 partial_info = HeapReAlloc(GetProcessHeap(), 0, partial_info, len);
518 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
519 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
520 ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->TitleIndex);
521 ok(partial_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type);
522 ok(partial_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength);
523 ok(len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[partial_info->DataLength]), "NtQueryValueKey returned wrong len %d\n", len);
524 ok(*(DWORD *)partial_info->Data == 711, "incorrect Data returned: 0x%x\n", *(DWORD *)partial_info->Data);
525 HeapFree(GetProcessHeap(), 0, partial_info);
527 len = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]);
528 full_info = HeapAlloc(GetProcessHeap(), 0, len);
529 status = pNtQueryValueKey(key, &ValName, KeyValueFullInformation, full_info, len, &len);
530 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
531 ok(full_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info->TitleIndex);
532 ok(full_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", full_info->Type);
533 ok(full_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info->DataLength);
534 ok(full_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info->NameLength);
535 ok(len == FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) + full_info->DataLength + full_info->NameLength,
536 "NtQueryValueKey returned wrong len %d\n", len);
537 len = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) + full_info->DataLength + full_info->NameLength;
539 full_info = HeapReAlloc(GetProcessHeap(), 0, full_info, len);
540 status = pNtQueryValueKey(key, &ValName, KeyValueFullInformation, full_info, len, &len);
541 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
542 ok(full_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info->TitleIndex);
543 ok(full_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", full_info->Type);
544 ok(full_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info->DataLength);
545 ok(full_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info->NameLength);
546 ok(!memcmp(full_info->Name, ValName.Buffer, ValName.Length), "incorrect Name returned\n");
547 ok(*(DWORD *)((char *)full_info + full_info->DataOffset) == 711, "incorrect Data returned: 0x%x\n",
548 *(DWORD *)((char *)full_info + full_info->DataOffset));
549 HeapFree(GetProcessHeap(), 0, full_info);
551 pRtlFreeUnicodeString(&ValName);
552 pRtlCreateUnicodeStringFromAsciiz(&ValName, "stringtest");
554 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, NULL, 0, &len);
555 todo_wine ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey should have returned STATUS_BUFFER_TOO_SMALL instead of 0x%08x\n", status);
556 partial_info = HeapAlloc(GetProcessHeap(), 0, len+1);
557 memset(partial_info, 0xbd, len+1);
558 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
559 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
560 ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->TitleIndex);
561 ok(partial_info->Type == REG_SZ, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type);
562 ok(partial_info->DataLength == STR_TRUNC_SIZE, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength);
563 ok(!memcmp(partial_info->Data, stringW, STR_TRUNC_SIZE), "incorrect Data returned\n");
564 ok(*(partial_info->Data+STR_TRUNC_SIZE) == 0xbd, "string overflowed %02x\n", *(partial_info->Data+STR_TRUNC_SIZE));
565 HeapFree(GetProcessHeap(), 0, partial_info);
567 pRtlFreeUnicodeString(&ValName);
568 pNtClose(key);
571 static void test_NtDeleteKey(void)
573 NTSTATUS status;
574 HANDLE hkey;
575 OBJECT_ATTRIBUTES attr;
576 ACCESS_MASK am = KEY_ALL_ACCESS;
578 status = pNtDeleteKey(NULL);
579 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
581 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
582 status = pNtOpenKey(&hkey, am, &attr);
584 status = pNtDeleteKey(hkey);
585 ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
588 static void test_RtlpNtQueryValueKey(void)
590 NTSTATUS status;
592 status = pRtlpNtQueryValueKey(NULL, NULL, NULL, NULL, NULL);
593 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
596 START_TEST(reg)
598 static const WCHAR winetest[] = {'\\','W','i','n','e','T','e','s','t',0};
599 if(!InitFunctionPtrs())
600 return;
601 pRtlFormatCurrentUserKeyPath(&winetestpath);
602 winetestpath.Buffer = pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, winetestpath.Buffer,
603 winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR));
604 winetestpath.MaximumLength = winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR);
606 pRtlAppendUnicodeToString(&winetestpath, winetest);
608 test_NtCreateKey();
609 test_NtOpenKey();
610 test_NtSetValueKey();
611 test_RtlCheckRegistryKey();
612 test_RtlOpenCurrentUser();
613 test_RtlQueryRegistryValues();
614 test_RtlpNtQueryValueKey();
615 test_NtFlushKey();
616 test_NtQueryValueKey();
617 test_NtDeleteKey();
619 pRtlFreeUnicodeString(&winetestpath);
621 FreeLibrary(hntdll);