mshtml: Implement IHTMLDocument2 get_forms.
[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 /* 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))
36
37 #ifndef __WINE_WINTERNL_H
38
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
46
47 #define RTL_REGISTRY_HANDLE       0x40000000
48 #define RTL_REGISTRY_OPTIONAL     0x80000000
49
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
57
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);
64
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;
74
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;
81
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;
88
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;
97
98 typedef enum _KEY_VALUE_INFORMATION_CLASS {
99     KeyValueBasicInformation,
100     KeyValueFullInformation,
101     KeyValuePartialInformation,
102     KeyValueFullInformationAlign64,
103     KeyValuePartialInformationAlign64
104 } KEY_VALUE_INFORMATION_CLASS;
105
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)
115
116 #endif
117
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,
131                              PULONG dispos );
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 NTSTATUS (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 NTSTATUS (WINAPI * pRtlAllocateHeap)(PVOID,ULONG,ULONG);
142 static NTSTATUS (WINAPI * pRtlZeroMemory)(PVOID, ULONG);
143 static NTSTATUS (WINAPI * pRtlpNtQueryValueKey)(HANDLE,ULONG*,PBYTE,DWORD*);
144
145 static HMODULE hntdll = 0;
146 static int CurrentTest = 0;
147 static UNICODE_STRING winetestpath;
148
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; \
155     }
156
157 static BOOL InitFunctionPtrs(void)
158 {
159     hntdll = LoadLibraryA("ntdll.dll");
160     if(!hntdll) {
161         trace("Could not load ntdll.dll\n");
162         return FALSE;
163     }
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;
188 }
189 #undef NTDLL_GET_PROC
190
191 static NTSTATUS WINAPI QueryRoutine (IN PCWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData,
192                               IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
193 {
194     NTSTATUS ret = STATUS_SUCCESS;
195     int ValueNameLength = 0;
196     LPSTR ValName = 0;
197     trace("**Test %d**\n", CurrentTest);
198
199     if(ValueName)
200     {
201         ValueNameLength = lstrlenW(ValueName);
202
203         ValName = (LPSTR)pRtlAllocateHeap(GetProcessHeap(), 0, ValueNameLength);
204
205         WideCharToMultiByte(0, 0, ValueName, ValueNameLength+1,ValName, ValueNameLength, 0, 0);
206
207         trace("ValueName: %s\n", ValName);
208     }
209     else
210         trace("ValueName: (null)\n");
211
212     switch(ValueType)
213     {
214             case REG_NONE:
215                 trace("ValueType: REG_NONE\n");
216                 trace("ValueData: %d\n", (int)ValueData);
217                 break;
218
219             case REG_BINARY:
220                 trace("ValueType: REG_BINARY\n");
221                 trace("ValueData: %d\n", (int)ValueData);
222                 break;
223
224             case REG_SZ:
225                 trace("ValueType: REG_SZ\n");
226                 trace("ValueData: %s\n", (char*)ValueData);
227                 break;
228
229             case REG_MULTI_SZ:
230                 trace("ValueType: REG_MULTI_SZ\n");
231                 trace("ValueData: %s\n", (char*)ValueData);
232                 break;
233
234             case REG_EXPAND_SZ:
235                 trace("ValueType: REG_EXPAND_SZ\n");
236                 trace("ValueData: %s\n", (char*)ValueData);
237                 break;
238
239             case REG_DWORD:
240                 trace("ValueType: REG_DWORD\n");
241                 trace("ValueData: %d\n", (int)ValueData);
242                 break;
243     };
244     trace("ValueLength: %d\n", (int)ValueLength);
245
246     if(CurrentTest == 0)
247         ok(1, "\n"); /*checks that QueryRoutine is called*/
248     if(CurrentTest > 7)
249         ok(!1, "Invalid Test Specified!\n");
250
251     CurrentTest++;
252
253     if(ValName)
254         pRtlFreeHeap(GetProcessHeap(), 0, ValName);
255
256     return ret;
257 }
258
259 static void test_RtlQueryRegistryValues(void)
260 {
261
262     /*
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     ******************************
274
275
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
290
291     */
292     NTSTATUS status;
293     ULONG RelativeTo;
294
295     PRTL_QUERY_REGISTRY_TABLE QueryTable = NULL;
296     RelativeTo = RTL_REGISTRY_ABSOLUTE;/*Only using absolute - no need to test all relativeto variables*/
297
298     QueryTable = (PRTL_QUERY_REGISTRY_TABLE)pRtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_QUERY_REGISTRY_TABLE)*26);
299
300     pRtlZeroMemory( QueryTable, sizeof(RTL_QUERY_REGISTRY_TABLE) * 26);
301
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;
309
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;
317
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;
325
326     status = pRtlQueryRegistryValues(RelativeTo, winetestpath.Buffer, QueryTable, 0, 0);
327     ok(status == STATUS_SUCCESS, "RtlQueryRegistryValues return: 0x%08x\n", status);
328
329     pRtlFreeHeap(GetProcessHeap(), 0, QueryTable);
330 }
331
332 static void test_NtOpenKey(void)
333 {
334     HANDLE key;
335     NTSTATUS status;
336     OBJECT_ATTRIBUTES attr;
337     ACCESS_MASK am = KEY_READ;
338
339     if (0)
340     {
341     /* Crashes Wine */
342     /* All NULL */
343     status = pNtOpenKey(NULL, 0, NULL);
344     ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
345
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);
350     }
351
352     InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
353
354     /* NULL key */
355     status = pNtOpenKey(NULL, 0, &attr);
356     todo_wine
357         ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
358
359     /* Length > sizeof(OBJECT_ATTRIBUTES) */
360     attr.Length *= 2;
361     status = pNtOpenKey(&key, am, &attr);
362     todo_wine
363         ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
364 }
365
366 static void test_NtCreateKey(void)
367 {
368     /*Create WineTest*/
369     OBJECT_ATTRIBUTES attr;
370     HKEY key;
371     ACCESS_MASK am = GENERIC_ALL;
372     NTSTATUS status;
373
374     /* All NULL */
375     status = pNtCreateKey(NULL, 0, NULL, 0, 0, 0, 0);
376     ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
377
378     /* Only the key */
379     status = pNtCreateKey(&key, 0, 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     /* Only accessmask */
384     status = pNtCreateKey(NULL, am, NULL, 0, 0, 0, 0);
385     ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
386
387     /* Key and accessmask */
388     status = pNtCreateKey(&key, am, NULL, 0, 0, 0, 0);
389     ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
390         "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
391
392     InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
393
394     /* Only attributes */
395     status = pNtCreateKey(NULL, 0, &attr, 0, 0, 0, 0);
396     ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
397
398     status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
399     ok(status == STATUS_SUCCESS, "NtCreateKey Failed: 0x%08x\n", status);
400
401     /* Length > sizeof(OBJECT_ATTRIBUTES) */
402     attr.Length *= 2;
403     status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
404     ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
405
406     pNtClose(key);
407 }
408
409 static void test_NtSetValueKey(void)
410 {
411     HANDLE key;
412     NTSTATUS status;
413     OBJECT_ATTRIBUTES attr;
414     ACCESS_MASK am = KEY_WRITE;
415     UNICODE_STRING ValName;
416     DWORD data = 711;
417
418     InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
419     status = pNtOpenKey(&key, am, &attr);
420     ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
421
422     pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
423     status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &data, sizeof(data));
424     ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status);
425     pRtlFreeUnicodeString(&ValName);
426
427     pRtlCreateUnicodeStringFromAsciiz(&ValName, "stringtest");
428     status = pNtSetValueKey(key, &ValName, 0, REG_SZ, (VOID*)stringW, STR_TRUNC_SIZE);
429     ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status);
430     pRtlFreeUnicodeString(&ValName);
431
432     pNtClose(key);
433 }
434
435 static void test_RtlOpenCurrentUser(void)
436 {
437     NTSTATUS status;
438     HKEY handle;
439     status=pRtlOpenCurrentUser(KEY_READ, &handle);
440     ok(status == STATUS_SUCCESS, "RtlOpenCurrentUser Failed: 0x%08x\n", status);
441     pNtClose(handle);
442 }
443
444 static void test_RtlCheckRegistryKey(void)
445 {
446     NTSTATUS status;
447
448     status = pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, winetestpath.Buffer);
449     ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08x\n", status);
450
451     status = pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL), winetestpath.Buffer);
452     ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE and RTL_REGISTRY_OPTIONAL: 0x%08x\n", status);
453 }
454
455 static void test_NtFlushKey(void)
456 {
457     NTSTATUS status;
458     HANDLE hkey;
459     OBJECT_ATTRIBUTES attr;
460     ACCESS_MASK am = KEY_ALL_ACCESS;
461
462     status = pNtFlushKey(NULL);
463     ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
464
465     InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
466     pNtOpenKey(&hkey, am, &attr);
467
468     status = pNtFlushKey(hkey);
469     ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
470
471     pNtClose(hkey);
472 }
473
474 static void test_NtQueryValueKey(void)
475 {
476     HANDLE key;
477     NTSTATUS status;
478     OBJECT_ATTRIBUTES attr;
479     UNICODE_STRING ValName;
480     KEY_VALUE_BASIC_INFORMATION *basic_info;
481     KEY_VALUE_PARTIAL_INFORMATION *partial_info;
482     KEY_VALUE_FULL_INFORMATION *full_info;
483     DWORD len;
484
485     pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
486
487     InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
488     status = pNtOpenKey(&key, KEY_READ, &attr);
489     ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
490
491     len = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]);
492     basic_info = HeapAlloc(GetProcessHeap(), 0, len);
493     status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, basic_info, len, &len);
494     ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
495     ok(basic_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info->TitleIndex);
496     ok(basic_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", basic_info->Type);
497     ok(basic_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info->NameLength);
498     ok(len == FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[basic_info->NameLength/sizeof(WCHAR)]), "NtQueryValueKey returned wrong len %d\n", len);
499
500     basic_info = HeapReAlloc(GetProcessHeap(), 0, basic_info, len);
501     status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, basic_info, len, &len);
502     ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
503     ok(basic_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info->TitleIndex);
504     ok(basic_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", basic_info->Type);
505     ok(basic_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info->NameLength);
506     ok(len == FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[basic_info->NameLength/sizeof(WCHAR)]), "NtQueryValueKey returned wrong len %d\n", len);
507     ok(!memcmp(basic_info->Name, ValName.Buffer, ValName.Length), "incorrect Name returned\n");
508     HeapFree(GetProcessHeap(), 0, basic_info);
509
510     len = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
511     partial_info = HeapAlloc(GetProcessHeap(), 0, len);
512     status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
513     ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
514     ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->TitleIndex);
515     ok(partial_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type);
516     ok(partial_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength);
517     ok(len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[partial_info->DataLength]), "NtQueryValueKey returned wrong len %d\n", len);
518
519     partial_info = HeapReAlloc(GetProcessHeap(), 0, partial_info, len);
520     status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
521     ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
522     ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->TitleIndex);
523     ok(partial_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type);
524     ok(partial_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength);
525     ok(len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[partial_info->DataLength]), "NtQueryValueKey returned wrong len %d\n", len);
526     ok(*(DWORD *)partial_info->Data == 711, "incorrect Data returned: 0x%x\n", *(DWORD *)partial_info->Data);
527     HeapFree(GetProcessHeap(), 0, partial_info);
528
529     len = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]);
530     full_info = HeapAlloc(GetProcessHeap(), 0, len);
531     status = pNtQueryValueKey(key, &ValName, KeyValueFullInformation, full_info, len, &len);
532     ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status);
533     ok(full_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info->TitleIndex);
534     ok(full_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", full_info->Type);
535     ok(full_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info->DataLength);
536     ok(full_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info->NameLength);
537     ok(len == FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) + full_info->DataLength + full_info->NameLength,
538         "NtQueryValueKey returned wrong len %d\n", len);
539     len = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) + full_info->DataLength + full_info->NameLength;
540
541     full_info = HeapReAlloc(GetProcessHeap(), 0, full_info, len);
542     status = pNtQueryValueKey(key, &ValName, KeyValueFullInformation, full_info, len, &len);
543     ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
544     ok(full_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info->TitleIndex);
545     ok(full_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", full_info->Type);
546     ok(full_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info->DataLength);
547     ok(full_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info->NameLength);
548     ok(!memcmp(full_info->Name, ValName.Buffer, ValName.Length), "incorrect Name returned\n");
549     ok(*(DWORD *)((char *)full_info + full_info->DataOffset) == 711, "incorrect Data returned: 0x%x\n",
550         *(DWORD *)((char *)full_info + full_info->DataOffset));
551     HeapFree(GetProcessHeap(), 0, full_info);
552
553     pRtlFreeUnicodeString(&ValName);
554     pRtlCreateUnicodeStringFromAsciiz(&ValName, "stringtest");
555
556     status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, NULL, 0, &len);
557     todo_wine ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey should have returned STATUS_BUFFER_TOO_SMALL instead of 0x%08x\n", status);
558     partial_info = HeapAlloc(GetProcessHeap(), 0, len+1);
559     memset((BYTE*)partial_info, 0xbd, len+1);
560     status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
561     ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status);
562     ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->TitleIndex);
563     ok(partial_info->Type == REG_SZ, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type);
564     ok(partial_info->DataLength == STR_TRUNC_SIZE, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength);
565     ok(!memcmp(partial_info->Data, stringW, STR_TRUNC_SIZE), "incorrect Data returned\n");
566     ok(*(partial_info->Data+STR_TRUNC_SIZE) == 0xbd, "string overflowed %02x\n", *(partial_info->Data+STR_TRUNC_SIZE));
567     HeapFree(GetProcessHeap(), 0, partial_info);
568
569     pRtlFreeUnicodeString(&ValName);
570     pNtClose(key);
571 }
572
573 static void test_NtDeleteKey(void)
574 {
575     NTSTATUS status;
576     HANDLE hkey;
577     OBJECT_ATTRIBUTES attr;
578     ACCESS_MASK am = KEY_ALL_ACCESS;
579
580     status = pNtDeleteKey(NULL);
581     ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
582
583     InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
584     status = pNtOpenKey(&hkey, am, &attr);
585
586     status = pNtDeleteKey(hkey);
587     ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
588 }
589
590 static void test_RtlpNtQueryValueKey(void)
591 {
592     NTSTATUS status;
593
594     status = pRtlpNtQueryValueKey(NULL, NULL, NULL, NULL);
595     ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
596 }
597
598 START_TEST(reg)
599 {
600     static const WCHAR winetest[] = {'\\','W','i','n','e','T','e','s','t',0};
601     if(!InitFunctionPtrs())
602         return;
603     pRtlFormatCurrentUserKeyPath(&winetestpath);
604     winetestpath.Buffer = (PWSTR)pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, winetestpath.Buffer,
605                            winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR));
606     winetestpath.MaximumLength = winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR);
607
608     pRtlAppendUnicodeToString(&winetestpath, winetest);
609
610     test_NtOpenKey();
611     test_NtCreateKey();
612     test_NtSetValueKey();
613     test_RtlCheckRegistryKey();
614     test_RtlOpenCurrentUser();
615     test_RtlQueryRegistryValues();
616     test_RtlpNtQueryValueKey();
617     test_NtFlushKey();
618     test_NtQueryValueKey();
619     test_NtDeleteKey();
620
621     pRtlFreeUnicodeString(&winetestpath);
622
623     FreeLibrary(hntdll);
624 }