ntdll/tests: Fix a couple of tests failing on NT4.
[wine.git] / dlls / ntdll / tests / reg.c
blob70864b6f2508a999ef8fcd7421f1cb737d05e6aa
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 #ifndef __WINE_WINTERNL_H
34 /* RtlQueryRegistryValues structs and defines */
35 #define RTL_REGISTRY_ABSOLUTE 0
36 #define RTL_REGISTRY_SERVICES 1
37 #define RTL_REGISTRY_CONTROL 2
38 #define RTL_REGISTRY_WINDOWS_NT 3
39 #define RTL_REGISTRY_DEVICEMAP 4
40 #define RTL_REGISTRY_USER 5
42 #define RTL_REGISTRY_HANDLE 0x40000000
43 #define RTL_REGISTRY_OPTIONAL 0x80000000
45 #define RTL_QUERY_REGISTRY_SUBKEY 0x00000001
46 #define RTL_QUERY_REGISTRY_TOPKEY 0x00000002
47 #define RTL_QUERY_REGISTRY_REQUIRED 0x00000004
48 #define RTL_QUERY_REGISTRY_NOVALUE 0x00000008
49 #define RTL_QUERY_REGISTRY_NOEXPAND 0x00000010
50 #define RTL_QUERY_REGISTRY_DIRECT 0x00000020
51 #define RTL_QUERY_REGISTRY_DELETE 0x00000040
53 typedef NTSTATUS (WINAPI *PRTL_QUERY_REGISTRY_ROUTINE)( PCWSTR ValueName,
54 ULONG ValueType,
55 PVOID ValueData,
56 ULONG ValueLength,
57 PVOID Context,
58 PVOID EntryContext);
60 typedef struct _RTL_QUERY_REGISTRY_TABLE {
61 PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine;
62 ULONG Flags;
63 PWSTR Name;
64 PVOID EntryContext;
65 ULONG DefaultType;
66 PVOID DefaultData;
67 ULONG DefaultLength;
68 } RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE;
70 typedef struct _KEY_VALUE_BASIC_INFORMATION {
71 ULONG TitleIndex;
72 ULONG Type;
73 ULONG NameLength;
74 WCHAR Name[1];
75 } KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION;
77 typedef struct _KEY_VALUE_PARTIAL_INFORMATION {
78 ULONG TitleIndex;
79 ULONG Type;
80 ULONG DataLength;
81 UCHAR Data[1];
82 } KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION;
84 typedef struct _KEY_VALUE_FULL_INFORMATION {
85 ULONG TitleIndex;
86 ULONG Type;
87 ULONG DataOffset;
88 ULONG DataLength;
89 ULONG NameLength;
90 WCHAR Name[1];
91 } KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION;
93 typedef enum _KEY_VALUE_INFORMATION_CLASS {
94 KeyValueBasicInformation,
95 KeyValueFullInformation,
96 KeyValuePartialInformation,
97 KeyValueFullInformationAlign64,
98 KeyValuePartialInformationAlign64
99 } KEY_VALUE_INFORMATION_CLASS;
101 #define InitializeObjectAttributes(p,n,a,r,s) \
102 do { \
103 (p)->Length = sizeof(OBJECT_ATTRIBUTES); \
104 (p)->RootDirectory = r; \
105 (p)->Attributes = a; \
106 (p)->ObjectName = n; \
107 (p)->SecurityDescriptor = s; \
108 (p)->SecurityQualityOfService = NULL; \
109 } while (0)
111 #endif
113 static NTSTATUS (WINAPI * pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPCSTR);
114 static NTSTATUS (WINAPI * pRtlFreeUnicodeString)(PUNICODE_STRING);
115 static NTSTATUS (WINAPI * pNtDeleteValueKey)(IN HANDLE, IN PUNICODE_STRING);
116 static NTSTATUS (WINAPI * pRtlQueryRegistryValues)(IN ULONG, IN PCWSTR,IN PRTL_QUERY_REGISTRY_TABLE, IN PVOID,IN PVOID);
117 static NTSTATUS (WINAPI * pRtlCheckRegistryKey)(IN ULONG,IN PWSTR);
118 static NTSTATUS (WINAPI * pRtlOpenCurrentUser)(IN ACCESS_MASK, OUT PHKEY);
119 static NTSTATUS (WINAPI * pNtOpenKey)(PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES);
120 static NTSTATUS (WINAPI * pNtClose)(IN HANDLE);
121 static NTSTATUS (WINAPI * pNtDeleteValueKey)(IN HANDLE, IN PUNICODE_STRING);
122 static NTSTATUS (WINAPI * pNtFlushKey)(HKEY);
123 static NTSTATUS (WINAPI * pNtDeleteKey)(HKEY);
124 static NTSTATUS (WINAPI * pNtCreateKey)( PHKEY retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
125 ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
126 PULONG dispos );
127 static NTSTATUS (WINAPI * pNtQueryValueKey)(HANDLE,const UNICODE_STRING *,KEY_VALUE_INFORMATION_CLASS,void *,DWORD,DWORD *);
128 static NTSTATUS (WINAPI * pNtSetValueKey)( PHKEY, const PUNICODE_STRING, ULONG,
129 ULONG, const PVOID, ULONG );
130 static NTSTATUS (WINAPI * pRtlFormatCurrentUserKeyPath)(PUNICODE_STRING);
131 static NTSTATUS (WINAPI * pRtlCreateUnicodeString)( PUNICODE_STRING, LPCWSTR);
132 static NTSTATUS (WINAPI * pRtlReAllocateHeap)(IN PVOID, IN ULONG, IN PVOID, IN ULONG);
133 static NTSTATUS (WINAPI * pRtlAppendUnicodeToString)(PUNICODE_STRING, PCWSTR);
134 static NTSTATUS (WINAPI * pRtlUnicodeStringToAnsiString)(PSTRING, PUNICODE_STRING, BOOL);
135 static NTSTATUS (WINAPI * pRtlFreeHeap)(PVOID, ULONG, PVOID);
136 static NTSTATUS (WINAPI * pRtlAllocateHeap)(PVOID,ULONG,ULONG);
137 static NTSTATUS (WINAPI * pRtlZeroMemory)(PVOID, ULONG);
138 static NTSTATUS (WINAPI * pRtlpNtQueryValueKey)(HANDLE,ULONG*,PBYTE,DWORD*);
140 static HMODULE hntdll = 0;
141 static int CurrentTest = 0;
142 static UNICODE_STRING winetestpath;
144 #define NTDLL_GET_PROC(func) \
145 p ## func = (void*)GetProcAddress(hntdll, #func); \
146 if(!p ## func) { \
147 trace("GetProcAddress(%s) failed\n", #func); \
148 FreeLibrary(hntdll); \
149 return FALSE; \
152 static BOOL InitFunctionPtrs(void)
154 hntdll = LoadLibraryA("ntdll.dll");
155 if(!hntdll) {
156 trace("Could not load ntdll.dll\n");
157 return FALSE;
159 if (hntdll)
161 NTDLL_GET_PROC(RtlCreateUnicodeStringFromAsciiz)
162 NTDLL_GET_PROC(RtlCreateUnicodeString)
163 NTDLL_GET_PROC(RtlFreeUnicodeString)
164 NTDLL_GET_PROC(NtDeleteValueKey)
165 NTDLL_GET_PROC(RtlQueryRegistryValues)
166 NTDLL_GET_PROC(RtlCheckRegistryKey)
167 NTDLL_GET_PROC(RtlOpenCurrentUser)
168 NTDLL_GET_PROC(NtClose)
169 NTDLL_GET_PROC(NtDeleteValueKey)
170 NTDLL_GET_PROC(NtCreateKey)
171 NTDLL_GET_PROC(NtFlushKey)
172 NTDLL_GET_PROC(NtDeleteKey)
173 NTDLL_GET_PROC(NtQueryValueKey)
174 NTDLL_GET_PROC(NtSetValueKey)
175 NTDLL_GET_PROC(NtOpenKey)
176 NTDLL_GET_PROC(RtlFormatCurrentUserKeyPath)
177 NTDLL_GET_PROC(RtlReAllocateHeap)
178 NTDLL_GET_PROC(RtlAppendUnicodeToString)
179 NTDLL_GET_PROC(RtlUnicodeStringToAnsiString)
180 NTDLL_GET_PROC(RtlFreeHeap)
181 NTDLL_GET_PROC(RtlAllocateHeap)
182 NTDLL_GET_PROC(RtlZeroMemory)
183 NTDLL_GET_PROC(RtlpNtQueryValueKey)
185 return TRUE;
187 #undef NTDLL_GET_PROC
189 static NTSTATUS WINAPI QueryRoutine (IN PCWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData,
190 IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
192 NTSTATUS ret = STATUS_SUCCESS;
193 int ValueNameLength = 0;
194 LPSTR ValName = 0;
195 trace("**Test %d**\n", CurrentTest);
197 if(ValueName)
199 ValueNameLength = lstrlenW(ValueName);
201 ValName = (LPSTR)pRtlAllocateHeap(GetProcessHeap(), 0, ValueNameLength);
203 WideCharToMultiByte(0, 0, ValueName, ValueNameLength+1,ValName, ValueNameLength, 0, 0);
205 trace("ValueName: %s\n", ValName);
207 else
208 trace("ValueName: (null)\n");
210 switch(ValueType)
212 case REG_NONE:
213 trace("ValueType: REG_NONE\n");
214 trace("ValueData: %d\n", (int)ValueData);
215 break;
217 case REG_BINARY:
218 trace("ValueType: REG_BINARY\n");
219 trace("ValueData: %d\n", (int)ValueData);
220 break;
222 case REG_SZ:
223 trace("ValueType: REG_SZ\n");
224 trace("ValueData: %s\n", (char*)ValueData);
225 break;
227 case REG_MULTI_SZ:
228 trace("ValueType: REG_MULTI_SZ\n");
229 trace("ValueData: %s\n", (char*)ValueData);
230 break;
232 case REG_EXPAND_SZ:
233 trace("ValueType: REG_EXPAND_SZ\n");
234 trace("ValueData: %s\n", (char*)ValueData);
235 break;
237 case REG_DWORD:
238 trace("ValueType: REG_DWORD\n");
239 trace("ValueData: %d\n", (int)ValueData);
240 break;
242 trace("ValueLength: %d\n", (int)ValueLength);
244 if(CurrentTest == 0)
245 ok(1, "\n"); /*checks that QueryRoutine is called*/
246 if(CurrentTest > 7)
247 ok(!1, "Invalid Test Specified!\n");
249 CurrentTest++;
251 if(ValName)
252 pRtlFreeHeap(GetProcessHeap(), 0, ValName);
254 return ret;
257 static void test_RtlQueryRegistryValues(void)
261 ******************************
262 * QueryTable Flags *
263 ******************************
264 *RTL_QUERY_REGISTRY_SUBKEY * Name is the name of a subkey relative to Path
265 *RTL_QUERY_REGISTRY_TOPKEY * Resets location to original RelativeTo and Path
266 *RTL_QUERY_REGISTRY_REQUIRED * Key required. returns STATUS_OBJECT_NAME_NOT_FOUND if not present
267 *RTL_QUERY_REGISTRY_NOVALUE * We just want a call-back
268 *RTL_QUERY_REGISTRY_NOEXPAND * Don't expand the variables!
269 *RTL_QUERY_REGISTRY_DIRECT * Results of query will be stored in EntryContext(QueryRoutine ignored)
270 *RTL_QUERY_REGISTRY_DELETE * Delete value key after query
271 ******************************
274 **Test layout(numbered according to CurrentTest value)**
275 0)NOVALUE Just make sure call-back works
276 1)Null Name See if QueryRoutine is called for every value in current key
277 2)SUBKEY See if we can use SUBKEY to change the current path on the fly
278 3)REQUIRED Test for value that's not there
279 4)NOEXPAND See if it will return multiple strings(no expand should split strings up)
280 5)DIRECT Make it store data directly in EntryContext and not call QueryRoutine
281 6)DefaultType Test return values when key isn't present
282 7)DefaultValue Test Default Value returned with key isn't present(and no REQUIRED flag set)
283 8)DefaultLength Test Default Length with DefaultType = REG_SZ
284 9)DefaultLength Test Default Length with DefaultType = REG_MULTI_SZ
285 10)DefaultLength Test Default Length with DefaultType = REG_EXPAND_SZ
286 11)DefaultData Test whether DefaultData is used while DefaultType = REG_NONE(shouldn't be)
287 12)Delete Try to delete value key
290 NTSTATUS status;
291 ULONG RelativeTo;
293 PRTL_QUERY_REGISTRY_TABLE QueryTable = NULL;
294 RelativeTo = RTL_REGISTRY_ABSOLUTE;/*Only using absolute - no need to test all relativeto variables*/
296 QueryTable = (PRTL_QUERY_REGISTRY_TABLE)pRtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_QUERY_REGISTRY_TABLE)*26);
298 pRtlZeroMemory( QueryTable, sizeof(RTL_QUERY_REGISTRY_TABLE) * 26);
300 QueryTable[0].QueryRoutine = QueryRoutine;
301 QueryTable[0].Flags = RTL_QUERY_REGISTRY_NOVALUE;
302 QueryTable[0].Name = NULL;
303 QueryTable[0].EntryContext = NULL;
304 QueryTable[0].DefaultType = REG_BINARY;
305 QueryTable[0].DefaultData = NULL;
306 QueryTable[0].DefaultLength = 100;
308 QueryTable[1].QueryRoutine = QueryRoutine;
309 QueryTable[1].Flags = 0;
310 QueryTable[1].Name = NULL;
311 QueryTable[1].EntryContext = 0;
312 QueryTable[1].DefaultType = REG_NONE;
313 QueryTable[1].DefaultData = NULL;
314 QueryTable[1].DefaultLength = 0;
316 QueryTable[2].QueryRoutine = NULL;
317 QueryTable[2].Flags = 0;
318 QueryTable[2].Name = NULL;
319 QueryTable[2].EntryContext = 0;
320 QueryTable[2].DefaultType = REG_NONE;
321 QueryTable[2].DefaultData = NULL;
322 QueryTable[2].DefaultLength = 0;
324 status = pRtlQueryRegistryValues(RelativeTo, winetestpath.Buffer, QueryTable, 0, 0);
325 ok(status == STATUS_SUCCESS, "RtlQueryRegistryValues return: 0x%08x\n", status);
327 pRtlFreeHeap(GetProcessHeap(), 0, QueryTable);
330 static void test_NtOpenKey(void)
332 HANDLE key;
333 NTSTATUS status;
334 OBJECT_ATTRIBUTES attr;
335 ACCESS_MASK am = KEY_READ;
337 if (0)
339 /* Crashes Wine */
340 /* All NULL */
341 status = pNtOpenKey(NULL, 0, NULL);
342 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
344 /* NULL attributes */
345 status = pNtOpenKey(&key, 0, NULL);
346 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
347 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
350 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
352 /* NULL key */
353 status = pNtOpenKey(NULL, 0, &attr);
354 todo_wine
355 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
357 /* Length > sizeof(OBJECT_ATTRIBUTES) */
358 attr.Length *= 2;
359 status = pNtOpenKey(&key, am, &attr);
360 todo_wine
361 ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
364 static void test_NtCreateKey(void)
366 /*Create WineTest*/
367 OBJECT_ATTRIBUTES attr;
368 HKEY key;
369 ACCESS_MASK am = GENERIC_ALL;
370 NTSTATUS status;
372 /* All NULL */
373 status = pNtCreateKey(NULL, 0, NULL, 0, 0, 0, 0);
374 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
376 /* Only the key */
377 status = pNtCreateKey(&key, 0, NULL, 0, 0, 0, 0);
378 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
379 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
381 /* Only accessmask */
382 status = pNtCreateKey(NULL, am, NULL, 0, 0, 0, 0);
383 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, 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 pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
418 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
419 status = pNtOpenKey(&key, am, &attr);
420 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
422 status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &data, sizeof(data));
423 ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status);
425 pRtlFreeUnicodeString(&ValName);
426 pNtClose(key);
429 static void test_RtlOpenCurrentUser(void)
431 NTSTATUS status;
432 HKEY handle;
433 status=pRtlOpenCurrentUser(KEY_READ, &handle);
434 ok(status == STATUS_SUCCESS, "RtlOpenCurrentUser Failed: 0x%08x\n", status);
435 pNtClose(handle);
438 static void test_RtlCheckRegistryKey(void)
440 NTSTATUS status;
442 status = pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, winetestpath.Buffer);
443 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08x\n", status);
445 status = pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL), winetestpath.Buffer);
446 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE and RTL_REGISTRY_OPTIONAL: 0x%08x\n", status);
449 static void test_NtFlushKey(void)
451 NTSTATUS status;
452 HANDLE hkey;
453 OBJECT_ATTRIBUTES attr;
454 ACCESS_MASK am = KEY_ALL_ACCESS;
456 status = pNtFlushKey(NULL);
457 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
459 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
460 pNtOpenKey(&hkey, am, &attr);
462 status = pNtFlushKey(hkey);
463 ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
465 pNtClose(hkey);
468 static void test_NtQueryValueKey(void)
470 HANDLE key;
471 NTSTATUS status;
472 OBJECT_ATTRIBUTES attr;
473 UNICODE_STRING ValName;
474 KEY_VALUE_BASIC_INFORMATION *basic_info;
475 KEY_VALUE_PARTIAL_INFORMATION *partial_info;
476 KEY_VALUE_FULL_INFORMATION *full_info;
477 DWORD len;
479 pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
481 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
482 status = pNtOpenKey(&key, KEY_READ, &attr);
483 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
485 len = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]);
486 basic_info = HeapAlloc(GetProcessHeap(), 0, len);
487 status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, basic_info, len, &len);
488 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
489 ok(basic_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info->Type);
490 ok(basic_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", basic_info->Type);
491 ok(basic_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info->NameLength);
492 ok(len == FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[basic_info->NameLength/sizeof(WCHAR)]), "NtQueryValueKey returned wrong len %d\n", len);
494 basic_info = HeapReAlloc(GetProcessHeap(), 0, basic_info, len);
495 status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, basic_info, len, &len);
496 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
497 ok(basic_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info->Type);
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);
501 ok(!memcmp(basic_info->Name, ValName.Buffer, ValName.Length), "incorrect Name returned\n");
502 HeapFree(GetProcessHeap(), 0, basic_info);
504 len = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
505 partial_info = HeapAlloc(GetProcessHeap(), 0, len);
506 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
507 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
508 ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->Type);
509 ok(partial_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type);
510 ok(partial_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength);
511 ok(len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[partial_info->DataLength]), "NtQueryValueKey returned wrong len %d\n", len);
513 partial_info = HeapReAlloc(GetProcessHeap(), 0, partial_info, len);
514 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
515 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
516 ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->Type);
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);
520 ok(*(DWORD *)partial_info->Data == 711, "incorrect Data returned: 0x%x\n", *(DWORD *)partial_info->Data);
521 HeapFree(GetProcessHeap(), 0, partial_info);
523 len = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]);
524 full_info = HeapAlloc(GetProcessHeap(), 0, len);
525 status = pNtQueryValueKey(key, &ValName, KeyValueFullInformation, full_info, len, &len);
526 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
527 ok(full_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info->Type);
528 ok(full_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", full_info->Type);
529 ok(full_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info->DataLength);
530 ok(full_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info->NameLength);
531 ok(len == FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) + full_info->DataLength + full_info->NameLength,
532 "NtQueryValueKey returned wrong len %d\n", len);
533 len = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) + full_info->DataLength + full_info->NameLength;
535 full_info = HeapReAlloc(GetProcessHeap(), 0, full_info, len);
536 status = pNtQueryValueKey(key, &ValName, KeyValueFullInformation, full_info, len, &len);
537 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
538 ok(full_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info->Type);
539 ok(full_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", full_info->Type);
540 ok(full_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info->DataLength);
541 ok(full_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info->NameLength);
542 ok(!memcmp(full_info->Name, ValName.Buffer, ValName.Length), "incorrect Name returned\n");
543 ok(*(DWORD *)((char *)full_info + full_info->DataOffset) == 711, "incorrect Data returned: 0x%x\n",
544 *(DWORD *)((char *)full_info + full_info->DataOffset));
545 HeapFree(GetProcessHeap(), 0, full_info);
547 pRtlFreeUnicodeString(&ValName);
548 pNtClose(key);
551 static void test_NtDeleteKey(void)
553 NTSTATUS status;
554 HANDLE hkey;
555 OBJECT_ATTRIBUTES attr;
556 ACCESS_MASK am = KEY_ALL_ACCESS;
558 status = pNtDeleteKey(NULL);
559 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
561 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
562 status = pNtOpenKey(&hkey, am, &attr);
564 status = pNtDeleteKey(hkey);
565 ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
568 static void test_RtlpNtQueryValueKey(void)
570 NTSTATUS status;
572 status = pRtlpNtQueryValueKey(NULL, NULL, NULL, NULL);
573 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
576 START_TEST(reg)
578 static const WCHAR winetest[] = {'\\','W','i','n','e','T','e','s','t',0};
579 if(!InitFunctionPtrs())
580 return;
581 pRtlFormatCurrentUserKeyPath(&winetestpath);
582 winetestpath.Buffer = (PWSTR)pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, winetestpath.Buffer,
583 winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR));
584 winetestpath.MaximumLength = winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR);
586 pRtlAppendUnicodeToString(&winetestpath, winetest);
588 test_NtOpenKey();
589 test_NtCreateKey();
590 test_NtSetValueKey();
591 test_RtlCheckRegistryKey();
592 test_RtlOpenCurrentUser();
593 test_RtlQueryRegistryValues();
594 test_RtlpNtQueryValueKey();
595 test_NtFlushKey();
596 test_NtQueryValueKey();
597 test_NtDeleteKey();
599 pRtlFreeUnicodeString(&winetestpath);
601 FreeLibrary(hntdll);