dinput: Silence incorrect warning and move it to a valid place.
[wine] / dlls / ntdll / tests / reg.c
1 /* Unit test suite for Rtl* Registry API functions
2  *
3  * Copyright 2003 Thomas Mertes
4  * Copyright 2005 Brad DeMorrow
5  *
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.
10  *
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.
15  *
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
19  *
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
22  *
23  */
24
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"
31
32 #ifndef __WINE_WINTERNL_H
33
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
41
42 #define RTL_REGISTRY_HANDLE       0x40000000
43 #define RTL_REGISTRY_OPTIONAL     0x80000000
44
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
52
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);
59
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;
69
70 typedef struct _KEY_VALUE_PARTIAL_INFORMATION {
71     ULONG TitleIndex;
72     ULONG Type;
73     ULONG DataLength;
74     UCHAR Data[1];
75 } KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION;
76
77 typedef struct _KEY_VALUE_FULL_INFORMATION {
78     ULONG TitleIndex;
79     ULONG Type;
80     ULONG DataOffset;
81     ULONG DataLength;
82     ULONG NameLength;
83     WCHAR Name[1];
84 } KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION;
85
86 typedef enum _KEY_VALUE_INFORMATION_CLASS {
87     KeyValueBasicInformation,
88     KeyValueFullInformation,
89     KeyValuePartialInformation,
90     KeyValueFullInformationAlign64,
91     KeyValuePartialInformationAlign64
92 } KEY_VALUE_INFORMATION_CLASS;
93
94 #define InitializeObjectAttributes(p,n,a,r,s) \
95     do { \
96         (p)->Length = sizeof(OBJECT_ATTRIBUTES); \
97         (p)->RootDirectory = r; \
98         (p)->Attributes = a; \
99         (p)->ObjectName = n; \
100         (p)->SecurityDescriptor = s; \
101         (p)->SecurityQualityOfService = NULL; \
102     } while (0)
103
104 #endif
105
106 static NTSTATUS (WINAPI * pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPCSTR);
107 static NTSTATUS (WINAPI * pRtlFreeUnicodeString)(PUNICODE_STRING);
108 static NTSTATUS (WINAPI * pNtDeleteValueKey)(IN HANDLE, IN PUNICODE_STRING);
109 static NTSTATUS (WINAPI * pRtlQueryRegistryValues)(IN ULONG, IN PCWSTR,IN PRTL_QUERY_REGISTRY_TABLE, IN PVOID,IN PVOID);
110 static NTSTATUS (WINAPI * pRtlCheckRegistryKey)(IN ULONG,IN PWSTR);
111 static NTSTATUS (WINAPI * pRtlOpenCurrentUser)(IN ACCESS_MASK, OUT PHKEY);
112 static NTSTATUS (WINAPI * pNtOpenKey)(PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES);
113 static NTSTATUS (WINAPI * pNtClose)(IN HANDLE);
114 static NTSTATUS (WINAPI * pNtDeleteValueKey)(IN HANDLE, IN PUNICODE_STRING);
115 static NTSTATUS (WINAPI * pNtFlushKey)(HKEY);
116 static NTSTATUS (WINAPI * pNtDeleteKey)(HKEY);
117 static NTSTATUS (WINAPI * pNtCreateKey)( PHKEY retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
118                              ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
119                              PULONG dispos );
120 static NTSTATUS (WINAPI * pNtQueryValueKey)(HANDLE,const UNICODE_STRING *,KEY_VALUE_INFORMATION_CLASS,void *,DWORD,DWORD *);
121 static NTSTATUS (WINAPI * pNtSetValueKey)( PHKEY, const PUNICODE_STRING, ULONG,
122                                ULONG, const PVOID, ULONG  );
123 static NTSTATUS (WINAPI * pRtlFormatCurrentUserKeyPath)(PUNICODE_STRING);
124 static NTSTATUS (WINAPI * pRtlCreateUnicodeString)( PUNICODE_STRING, LPCWSTR);
125 static NTSTATUS (WINAPI * pRtlReAllocateHeap)(IN PVOID, IN ULONG, IN PVOID, IN ULONG);
126 static NTSTATUS (WINAPI * pRtlAppendUnicodeToString)(PUNICODE_STRING, PCWSTR);
127 static NTSTATUS (WINAPI * pRtlUnicodeStringToAnsiString)(PSTRING, PUNICODE_STRING, BOOL);
128 static NTSTATUS (WINAPI * pRtlFreeHeap)(PVOID, ULONG, PVOID);
129 static NTSTATUS (WINAPI * pRtlAllocateHeap)(PVOID,ULONG,ULONG);
130 static NTSTATUS (WINAPI * pRtlZeroMemory)(PVOID, ULONG);
131 static NTSTATUS (WINAPI * pRtlpNtQueryValueKey)(HANDLE,ULONG*,PBYTE,DWORD*);
132
133 static HMODULE hntdll = 0;
134 static int CurrentTest = 0;
135 static UNICODE_STRING winetestpath;
136
137 #define NTDLL_GET_PROC(func) \
138     p ## func = (void*)GetProcAddress(hntdll, #func); \
139     if(!p ## func) { \
140         trace("GetProcAddress(%s) failed\n", #func); \
141         FreeLibrary(hntdll); \
142         return FALSE; \
143     }
144
145 static BOOL InitFunctionPtrs(void)
146 {
147     hntdll = LoadLibraryA("ntdll.dll");
148     if(!hntdll) {
149         trace("Could not load ntdll.dll\n");
150         return FALSE;
151     }
152     if (hntdll)
153     {
154         NTDLL_GET_PROC(RtlCreateUnicodeStringFromAsciiz)
155         NTDLL_GET_PROC(RtlCreateUnicodeString)
156         NTDLL_GET_PROC(RtlFreeUnicodeString)
157         NTDLL_GET_PROC(NtDeleteValueKey)
158         NTDLL_GET_PROC(RtlQueryRegistryValues)
159         NTDLL_GET_PROC(RtlCheckRegistryKey)
160         NTDLL_GET_PROC(RtlOpenCurrentUser)
161         NTDLL_GET_PROC(NtClose)
162         NTDLL_GET_PROC(NtDeleteValueKey)
163         NTDLL_GET_PROC(NtCreateKey)
164         NTDLL_GET_PROC(NtFlushKey)
165         NTDLL_GET_PROC(NtDeleteKey)
166         NTDLL_GET_PROC(NtQueryValueKey)
167         NTDLL_GET_PROC(NtSetValueKey)
168         NTDLL_GET_PROC(NtOpenKey)
169         NTDLL_GET_PROC(RtlFormatCurrentUserKeyPath)
170         NTDLL_GET_PROC(RtlReAllocateHeap)
171         NTDLL_GET_PROC(RtlAppendUnicodeToString)
172         NTDLL_GET_PROC(RtlUnicodeStringToAnsiString)
173         NTDLL_GET_PROC(RtlFreeHeap)
174         NTDLL_GET_PROC(RtlAllocateHeap)
175         NTDLL_GET_PROC(RtlZeroMemory)
176         NTDLL_GET_PROC(RtlpNtQueryValueKey)
177     }
178     return TRUE;
179 }
180 #undef NTDLL_GET_PROC
181
182 static NTSTATUS WINAPI QueryRoutine (IN PCWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData,
183                               IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
184 {
185     NTSTATUS ret = STATUS_SUCCESS;
186     int ValueNameLength = 0;
187     LPSTR ValName = 0;
188     trace("**Test %d**\n", CurrentTest);
189
190     if(ValueName)
191     {
192         ValueNameLength = lstrlenW(ValueName);
193
194         ValName = (LPSTR)pRtlAllocateHeap(GetProcessHeap(), 0, ValueNameLength);
195
196         WideCharToMultiByte(0, 0, ValueName, ValueNameLength+1,ValName, ValueNameLength, 0, 0);
197
198         trace("ValueName: %s\n", ValName);
199     }
200     else
201         trace("ValueName: (null)\n");
202
203     switch(ValueType)
204     {
205             case REG_NONE:
206                 trace("ValueType: REG_NONE\n");
207                 trace("ValueData: %d\n", (int)ValueData);
208                 break;
209
210             case REG_BINARY:
211                 trace("ValueType: REG_BINARY\n");
212                 trace("ValueData: %d\n", (int)ValueData);
213                 break;
214
215             case REG_SZ:
216                 trace("ValueType: REG_SZ\n");
217                 trace("ValueData: %s\n", (char*)ValueData);
218                 break;
219
220             case REG_MULTI_SZ:
221                 trace("ValueType: REG_MULTI_SZ\n");
222                 trace("ValueData: %s\n", (char*)ValueData);
223                 break;
224
225             case REG_EXPAND_SZ:
226                 trace("ValueType: REG_EXPAND_SZ\n");
227                 trace("ValueData: %s\n", (char*)ValueData);
228                 break;
229
230             case REG_DWORD:
231                 trace("ValueType: REG_DWORD\n");
232                 trace("ValueData: %d\n", (int)ValueData);
233                 break;
234     };
235     trace("ValueLength: %d\n", (int)ValueLength);
236
237     if(CurrentTest == 0)
238         ok(1, "\n"); /*checks that QueryRoutine is called*/
239     if(CurrentTest > 7)
240         ok(!1, "Invalid Test Specified!\n");
241
242     CurrentTest++;
243
244     if(ValName)
245         pRtlFreeHeap(GetProcessHeap(), 0, ValName);
246
247     return ret;
248 }
249
250 static void test_RtlQueryRegistryValues(void)
251 {
252
253     /*
254     ******************************
255     *       QueryTable Flags     *
256     ******************************
257     *RTL_QUERY_REGISTRY_SUBKEY   * Name is the name of a subkey relative to Path
258     *RTL_QUERY_REGISTRY_TOPKEY   * Resets location to original RelativeTo and Path
259     *RTL_QUERY_REGISTRY_REQUIRED * Key required. returns STATUS_OBJECT_NAME_NOT_FOUND if not present
260     *RTL_QUERY_REGISTRY_NOVALUE  * We just want a call-back
261     *RTL_QUERY_REGISTRY_NOEXPAND * Don't expand the variables!
262     *RTL_QUERY_REGISTRY_DIRECT   * Results of query will be stored in EntryContext(QueryRoutine ignored)
263     *RTL_QUERY_REGISTRY_DELETE   * Delete value key after query
264     ******************************
265
266
267     **Test layout(numbered according to CurrentTest value)**
268     0)NOVALUE           Just make sure call-back works
269     1)Null Name         See if QueryRoutine is called for every value in current key
270     2)SUBKEY            See if we can use SUBKEY to change the current path on the fly
271     3)REQUIRED          Test for value that's not there
272     4)NOEXPAND          See if it will return multiple strings(no expand should split strings up)
273     5)DIRECT            Make it store data directly in EntryContext and not call QueryRoutine
274     6)DefaultType       Test return values when key isn't present
275     7)DefaultValue      Test Default Value returned with key isn't present(and no REQUIRED flag set)
276     8)DefaultLength     Test Default Length with DefaultType = REG_SZ
277    9)DefaultLength      Test Default Length with DefaultType = REG_MULTI_SZ
278    10)DefaultLength     Test Default Length with DefaultType = REG_EXPAND_SZ
279    11)DefaultData       Test whether DefaultData is used while DefaltType = REG_NONE(shouldn't be)
280    12)Delete            Try to delete value key
281
282     */
283     NTSTATUS status;
284     ULONG RelativeTo;
285
286     PRTL_QUERY_REGISTRY_TABLE QueryTable = NULL;
287     RelativeTo = RTL_REGISTRY_ABSOLUTE;/*Only using absolute - no need to test all relativeto variables*/
288
289     QueryTable = (PRTL_QUERY_REGISTRY_TABLE)pRtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_QUERY_REGISTRY_TABLE)*26);
290
291     pRtlZeroMemory( QueryTable, sizeof(RTL_QUERY_REGISTRY_TABLE) * 26);
292
293     QueryTable[0].QueryRoutine = QueryRoutine;
294     QueryTable[0].Flags = RTL_QUERY_REGISTRY_NOVALUE;
295     QueryTable[0].Name = NULL;
296     QueryTable[0].EntryContext = NULL;
297     QueryTable[0].DefaultType = REG_BINARY;
298     QueryTable[0].DefaultData = NULL;
299     QueryTable[0].DefaultLength = 100;
300
301     QueryTable[1].QueryRoutine = QueryRoutine;
302     QueryTable[1].Flags = 0;
303     QueryTable[1].Name = NULL;
304     QueryTable[1].EntryContext = 0;
305     QueryTable[1].DefaultType = REG_NONE;
306     QueryTable[1].DefaultData = NULL;
307     QueryTable[1].DefaultLength = 0;
308
309     QueryTable[2].QueryRoutine = NULL;
310     QueryTable[2].Flags = 0;
311     QueryTable[2].Name = NULL;
312     QueryTable[2].EntryContext = 0;
313     QueryTable[2].DefaultType = REG_NONE;
314     QueryTable[2].DefaultData = NULL;
315     QueryTable[2].DefaultLength = 0;
316
317     status = pRtlQueryRegistryValues(RelativeTo, winetestpath.Buffer, QueryTable, 0, 0);
318     ok(status == STATUS_SUCCESS, "RtlQueryRegistryValues return: 0x%08x\n", status);
319
320     pRtlFreeHeap(GetProcessHeap(), 0, QueryTable);
321 }
322
323 static void test_NtOpenKey(void)
324 {
325     HANDLE key;
326     NTSTATUS status;
327     OBJECT_ATTRIBUTES attr;
328     ACCESS_MASK am = KEY_READ;
329
330     if (0)
331     {
332     /* Crashes Wine */
333     /* All NULL */
334     status = pNtOpenKey(NULL, 0, NULL);
335     ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
336
337     /* NULL attributes */
338     status = pNtOpenKey(&key, 0, NULL);
339     ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
340         "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
341     }
342
343     InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
344
345     /* NULL key */
346     status = pNtOpenKey(NULL, 0, &attr);
347     todo_wine
348         ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
349
350     /* Length > sizeof(OBJECT_ATTRIBUTES) */
351     attr.Length *= 2;
352     status = pNtOpenKey(&key, am, &attr);
353     todo_wine
354         ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
355 }
356
357 static void test_NtCreateKey(void)
358 {
359     /*Create WineTest*/
360     OBJECT_ATTRIBUTES attr;
361     HKEY key;
362     ACCESS_MASK am = GENERIC_ALL;
363     NTSTATUS status;
364
365     /* All NULL */
366     status = pNtCreateKey(NULL, 0, NULL, 0, 0, 0, 0);
367     ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
368
369     /* Only the key */
370     status = pNtCreateKey(&key, 0, NULL, 0, 0, 0, 0);
371     ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
372         "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
373
374     /* Only accessmask */
375     status = pNtCreateKey(NULL, am, NULL, 0, 0, 0, 0);
376     ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
377
378     /* Key and accessmask */
379     status = pNtCreateKey(&key, am, NULL, 0, 0, 0, 0);
380     ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
381         "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
382
383     InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
384
385     /* Only attributes */
386     status = pNtCreateKey(NULL, 0, &attr, 0, 0, 0, 0);
387     ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
388
389     status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
390     ok(status == STATUS_SUCCESS, "NtCreateKey Failed: 0x%08x\n", status);
391
392     /* Length > sizeof(OBJECT_ATTRIBUTES) */
393     attr.Length *= 2;
394     status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
395     ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
396
397     pNtClose(key);
398 }
399
400 static void test_NtSetValueKey(void)
401 {
402     HANDLE key;
403     NTSTATUS status;
404     OBJECT_ATTRIBUTES attr;
405     ACCESS_MASK am = KEY_WRITE;
406     UNICODE_STRING ValName;
407     DWORD data = 711;
408
409     pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
410
411     InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
412     status = pNtOpenKey(&key, am, &attr);
413     ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
414
415     status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &data, sizeof(data));
416     ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status);
417
418     pRtlFreeUnicodeString(&ValName);
419     pNtClose(key);
420 }
421
422 static void test_RtlOpenCurrentUser(void)
423 {
424     NTSTATUS status;
425     HKEY handle;
426     status=pRtlOpenCurrentUser(KEY_READ, &handle);
427     ok(status == STATUS_SUCCESS, "RtlOpenCurrentUser Failed: 0x%08x\n", status);
428     pNtClose(handle);
429 }
430
431 static void test_RtlCheckRegistryKey(void)
432 {
433     NTSTATUS status;
434
435     status = pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, winetestpath.Buffer);
436     ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08x\n", status);
437
438     status = pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL), winetestpath.Buffer);
439     ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE and RTL_REGISTRY_OPTIONAL: 0x%08x\n", status);
440 }
441
442 static void test_NtFlushKey(void)
443 {
444     NTSTATUS status;
445     HANDLE hkey;
446     OBJECT_ATTRIBUTES attr;
447     ACCESS_MASK am = KEY_ALL_ACCESS;
448
449     status = pNtFlushKey(NULL);
450     ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
451
452     InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
453     pNtOpenKey(&hkey, am, &attr);
454
455     status = pNtFlushKey(hkey);
456     ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
457
458     pNtClose(hkey);
459 }
460
461 static void test_NtQueryValueKey(void)
462 {
463     HANDLE key;
464     NTSTATUS status;
465     OBJECT_ATTRIBUTES attr;
466     UNICODE_STRING ValName;
467     KEY_VALUE_PARTIAL_INFORMATION *partial_info;
468     KEY_VALUE_FULL_INFORMATION *full_info;
469     DWORD len;
470
471     pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
472
473     InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
474     status = pNtOpenKey(&key, KEY_READ, &attr);
475     ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
476
477     len = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
478     partial_info = HeapAlloc(GetProcessHeap(), 0, len);
479     status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
480     ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
481     ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->Type);
482     ok(partial_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type);
483     ok(partial_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength);
484     ok(len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[partial_info->DataLength]), "NtQueryValueKey returned wrong len %d\n", len);
485     HeapFree(GetProcessHeap(), 0, partial_info);
486
487     len = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]);
488     full_info = HeapAlloc(GetProcessHeap(), 0, len);
489     status = pNtQueryValueKey(key, &ValName, KeyValueFullInformation, full_info, len, &len);
490     ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
491     ok(full_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info->Type);
492     ok(full_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", full_info->Type);
493     ok(full_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info->DataLength);
494     ok(full_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info->NameLength);
495     todo_wine
496     ok(len == FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) + full_info->DataLength + full_info->NameLength,
497         "NtQueryValueKey returned wrong len %d\n", len);
498     HeapFree(GetProcessHeap(), 0, full_info);
499
500     pRtlFreeUnicodeString(&ValName);
501     pNtClose(key);
502 }
503
504 static void test_NtDeleteKey(void)
505 {
506     NTSTATUS status;
507     HANDLE hkey;
508     OBJECT_ATTRIBUTES attr;
509     ACCESS_MASK am = KEY_ALL_ACCESS;
510
511     status = pNtDeleteKey(NULL);
512     ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
513
514     InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
515     status = pNtOpenKey(&hkey, am, &attr);
516
517     status = pNtDeleteKey(hkey);
518     ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
519 }
520
521 static void test_RtlpNtQueryValueKey(void)
522 {
523     NTSTATUS status;
524
525     status = pRtlpNtQueryValueKey(NULL, NULL, NULL, NULL);
526     ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
527 }
528
529 START_TEST(reg)
530 {
531     static const WCHAR winetest[] = {'\\','W','i','n','e','T','e','s','t','\\',0};
532     if(!InitFunctionPtrs())
533         return;
534     pRtlFormatCurrentUserKeyPath(&winetestpath);
535     winetestpath.Buffer = (PWSTR)pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, winetestpath.Buffer,
536                            winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR));
537     winetestpath.MaximumLength = winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR);
538
539     pRtlAppendUnicodeToString(&winetestpath, winetest);
540
541     test_NtOpenKey();
542     test_NtCreateKey();
543     test_NtSetValueKey();
544     test_RtlCheckRegistryKey();
545     test_RtlOpenCurrentUser();
546     test_RtlQueryRegistryValues();
547     test_RtlpNtQueryValueKey();
548     test_NtFlushKey();
549     test_NtQueryValueKey();
550     test_NtDeleteKey();
551
552     pRtlFreeUnicodeString(&winetestpath);
553
554     FreeLibrary(hntdll);
555 }