ntdll pending some winerror.h fixes
[reactos.git] / reactos / regtests / winetests / ntdll / 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 "wine/library.h"
28 #include "stdio.h"
29 #include "winnt.h"
30 #include "winnls.h"
31 #include "stdlib.h"
32 #include "wine/unicode.h"
33
34 #ifndef __WINE_WINTERNL_H
35
36 /* RtlQueryRegistryValues structs and defines */
37 #define RTL_REGISTRY_ABSOLUTE 0
38 #define RTL_REGISTRY_SERVICES 1
39 #define RTL_REGISTRY_CONTROL 2
40 #define RTL_REGISTRY_WINDOWS_NT 3
41 #define RTL_REGISTRY_DEVICEMAP 4
42 #define RTL_REGISTRY_USER 5
43
44 #define RTL_REGISTRY_HANDLE 0x40000000
45 #define RTL_REGISTRY_OPTIONAL 0x80000000
46
47 #define RTL_QUERY_REGISTRY_SUBKEY 0x00000001
48 #define RTL_QUERY_REGISTRY_TOPKEY 0x00000002
49 #define RTL_QUERY_REGISTRY_REQUIRED 0x00000004
50 #define RTL_QUERY_REGISTRY_NOVALUE 0x00000008
51 #define RTL_QUERY_REGISTRY_NOEXPAND 0x00000010
52 #define RTL_QUERY_REGISTRY_DIRECT 0x00000020
53 #define RTL_QUERY_REGISTRY_DELETE 0x00000040
54
55 typedef NTSTATUS (WINAPI *PRTL_QUERY_REGISTRY_ROUTINE)( PCWSTR ValueName,
56 ULONG ValueType,
57 PVOID ValueData,
58 ULONG ValueLength,
59 PVOID Context,
60 PVOID EntryContext);
61
62 typedef struct _RTL_QUERY_REGISTRY_TABLE {
63 PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine;
64 ULONG Flags;
65 PWSTR Name;
66 PVOID EntryContext;
67 ULONG DefaultType;
68 PVOID DefaultData;
69 ULONG DefaultLength;
70 } RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE;
71
72 #endif
73
74 static NTSTATUS (WINAPI * pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPCSTR);
75 static NTSTATUS (WINAPI * pRtlFreeUnicodeString)(PUNICODE_STRING);
76 static NTSTATUS (WINAPI * pNtDeleteValueKey)(IN HANDLE, IN PUNICODE_STRING);
77 static NTSTATUS (WINAPI * pRtlQueryRegistryValues)(IN ULONG, IN PCWSTR,IN PRTL_QUERY_REGISTRY_TABLE, IN PVOID,IN PVOID);
78 static NTSTATUS (WINAPI * pRtlCheckRegistryKey)(IN ULONG,IN PWSTR);
79 static NTSTATUS (WINAPI * pRtlOpenCurrentUser)(IN ACCESS_MASK, OUT PHKEY);
80 static NTSTATUS (WINAPI * pNtOpenKey)(PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES);
81 static NTSTATUS (WINAPI * pNtClose)(IN HANDLE);
82 static NTSTATUS (WINAPI * pNtDeleteValueKey)(IN HANDLE, IN PUNICODE_STRING);
83 static NTSTATUS (WINAPI * pNtDeleteKey)(HKEY);
84 static NTSTATUS (WINAPI * pNtCreateKey)( PHKEY retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
85 ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
86 PULONG dispos );
87 static NTSTATUS (WINAPI * pNtSetValueKey)( PHKEY, const PUNICODE_STRING, ULONG,
88 ULONG, const PVOID, ULONG );
89 static NTSTATUS (WINAPI * pRtlFormatCurrentUserKeyPath)(PUNICODE_STRING);
90 static NTSTATUS (WINAPI * pRtlCreateUnicodeString)( PUNICODE_STRING, LPCWSTR);
91 static NTSTATUS (WINAPI * pRtlReAllocateHeap)(IN PVOID, IN ULONG, IN PVOID, IN ULONG);
92 static NTSTATUS (WINAPI * pRtlAppendUnicodeToString)(PUNICODE_STRING, PCWSTR);
93 static NTSTATUS (WINAPI * pRtlUnicodeStringToAnsiString)(PSTRING, PUNICODE_STRING, BOOL);
94 static NTSTATUS (WINAPI * pRtlFreeHeap)(PVOID, ULONG, PVOID);
95 static NTSTATUS (WINAPI * pRtlAllocateHeap)(PVOID,ULONG,ULONG);
96 static NTSTATUS (WINAPI * pRtlZeroMemory)(PVOID, ULONG);
97
98 static HMODULE hntdll = 0;
99 static int CurrentTest = 0;
100 static UNICODE_STRING winetestpath;
101
102 #define NTDLL_GET_PROC(func) \
103 p ## func = (void*)GetProcAddress(hntdll, #func); \
104 if(!p ## func) { \
105 trace("GetProcAddress(%s) failed\n", #func); \
106 FreeLibrary(hntdll); \
107 return FALSE; \
108 }
109
110 static BOOL InitFunctionPtrs(void)
111 {
112 hntdll = LoadLibraryA("ntdll.dll");
113 if(!hntdll) {
114 trace("Could not load ntdll.dll\n");
115 return FALSE;
116 }
117 if (hntdll)
118 {
119 NTDLL_GET_PROC(RtlCreateUnicodeStringFromAsciiz)
120 NTDLL_GET_PROC(RtlCreateUnicodeString)
121 NTDLL_GET_PROC(RtlFreeUnicodeString)
122 NTDLL_GET_PROC(NtDeleteValueKey)
123 NTDLL_GET_PROC(RtlQueryRegistryValues)
124 NTDLL_GET_PROC(RtlCheckRegistryKey)
125 NTDLL_GET_PROC(RtlOpenCurrentUser)
126 NTDLL_GET_PROC(NtClose)
127 NTDLL_GET_PROC(NtDeleteValueKey)
128 NTDLL_GET_PROC(NtCreateKey)
129 NTDLL_GET_PROC(NtDeleteKey)
130 NTDLL_GET_PROC(NtSetValueKey)
131 NTDLL_GET_PROC(NtOpenKey)
132 NTDLL_GET_PROC(RtlFormatCurrentUserKeyPath)
133 NTDLL_GET_PROC(RtlReAllocateHeap)
134 NTDLL_GET_PROC(RtlAppendUnicodeToString)
135 NTDLL_GET_PROC(RtlUnicodeStringToAnsiString)
136 NTDLL_GET_PROC(RtlFreeHeap)
137 NTDLL_GET_PROC(RtlAllocateHeap)
138 NTDLL_GET_PROC(RtlZeroMemory)
139 }
140 return TRUE;
141 }
142 #undef NTDLL_GET_PROC
143
144 static NTSTATUS WINAPI QueryRoutine (IN PCWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData,
145 IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
146 {
147 NTSTATUS ret = STATUS_SUCCESS;
148 int ValueNameLength = 0;
149 LPSTR ValName = 0;
150 trace("**Test %d**\n", CurrentTest);
151
152 if(ValueName)
153 {
154 ValueNameLength = strlenW(ValueName);
155
156 ValName = (LPSTR)pRtlAllocateHeap(GetProcessHeap(), 0, ValueNameLength);
157
158 WideCharToMultiByte(0, 0, ValueName, ValueNameLength+1,ValName, ValueNameLength, 0, 0);
159
160 trace("ValueName: %s\n", ValName);
161 }
162 else
163 trace("ValueName: (null)\n");
164
165 switch(ValueType)
166 {
167 case REG_NONE:
168 trace("ValueType: REG_NONE\n");
169 trace("ValueData: %d\n", (int)ValueData);
170 break;
171
172 case REG_BINARY:
173 trace("ValueType: REG_BINARY\n");
174 trace("ValueData: %d\n", (int)ValueData);
175 break;
176
177 case REG_SZ:
178 trace("ValueType: REG_SZ\n");
179 trace("ValueData: %s\n", (char*)ValueData);
180 break;
181
182 case REG_MULTI_SZ:
183 trace("ValueType: REG_MULTI_SZ\n");
184 trace("ValueData: %s\n", (char*)ValueData);
185 break;
186
187 case REG_EXPAND_SZ:
188 trace("ValueType: REG_EXPAND_SZ\n");
189 trace("ValueData: %s\n", (char*)ValueData);
190 break;
191
192 case REG_DWORD:
193 trace("ValueType: REG_DWORD\n");
194 trace("ValueData: %d\n", (int)ValueData);
195 break;
196 };
197 trace("ValueLength: %d\n", (int)ValueLength);
198
199 if(CurrentTest == 0)
200 ok(1, "\n"); /*checks that QueryRoutine is called*/
201 if(CurrentTest > 7)
202 ok(!1, "Invalid Test Specified!\n");
203
204 CurrentTest++;
205
206 if(ValName)
207 pRtlFreeHeap(GetProcessHeap(), 0, ValName);
208
209 return ret;
210 }
211
212 static void test_RtlQueryRegistryValues(void)
213 {
214
215 /*
216 ******************************
217 * QueryTable Flags *
218 ******************************
219 *RTL_QUERY_REGISTRY_SUBKEY * Name is the name of a subkey relative to Path
220 *RTL_QUERY_REGISTRY_TOPKEY * Resets location to original RelativeTo and Path
221 *RTL_QUERY_REGISTRY_REQUIRED * Key required. returns STATUS_OBJECT_NAME_NOT_FOUND if not present
222 *RTL_QUERY_REGISTRY_NOVALUE * We just want a call-back
223 *RTL_QUERY_REGISTRY_NOEXPAND * Don't expand the variables!
224 *RTL_QUERY_REGISTRY_DIRECT * Results of query will be stored in EntryContext(QueryRoutine ignored)
225 *RTL_QUERY_REGISTRY_DELETE * Delete value key after query
226 ******************************
227
228
229 **Test layout(numbered according to CurrentTest value)**
230 0)NOVALUE Just make sure call-back works
231 1)Null Name See if QueryRoutine is called for every value in current key
232 2)SUBKEY See if we can use SUBKEY to change the current path on the fly
233 3)REQUIRED Test for value that's not there
234 4)NOEXPAND See if it will return multiple strings(no expand should split strings up)
235 5)DIRECT Make it store data directly in EntryContext and not call QueryRoutine
236 6)DefaultType Test return values when key isn't present
237 7)DefaultValue Test Default Value returned with key isn't present(and no REQUIRED flag set)
238 8)DefaultLength Test Default Length with DefaultType = REG_SZ
239 9)DefaultLength Test Default Length with DefaultType = REG_MULTI_SZ
240 10)DefaultLength Test Default Length with DefaultType = REG_EXPAND_SZ
241 11)DefaultData Test whether DefaultData is used while DefaltType = REG_NONE(shouldn't be)
242 12)Delete Try to delete value key
243
244 */
245 NTSTATUS status;
246 ULONG RelativeTo;
247
248 PRTL_QUERY_REGISTRY_TABLE QueryTable = NULL;
249 RelativeTo = RTL_REGISTRY_ABSOLUTE;/*Only using absolute - no need to test all relativeto variables*/
250
251 QueryTable = (PRTL_QUERY_REGISTRY_TABLE)pRtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_QUERY_REGISTRY_TABLE)*26);
252
253 pRtlZeroMemory( QueryTable, sizeof(RTL_QUERY_REGISTRY_TABLE) * 26);
254
255 QueryTable[0].QueryRoutine = QueryRoutine;
256 QueryTable[0].Flags = RTL_QUERY_REGISTRY_NOVALUE;
257 QueryTable[0].Name = NULL;
258 QueryTable[0].EntryContext = NULL;
259 QueryTable[0].DefaultType = REG_BINARY;
260 QueryTable[0].DefaultData = NULL;
261 QueryTable[0].DefaultLength = 100;
262
263 QueryTable[1].QueryRoutine = QueryRoutine;
264 QueryTable[1].Flags = 0;
265 QueryTable[1].Name = NULL;
266 QueryTable[1].EntryContext = 0;
267 QueryTable[1].DefaultType = REG_NONE;
268 QueryTable[1].DefaultData = NULL;
269 QueryTable[1].DefaultLength = 0;
270
271 QueryTable[2].QueryRoutine = NULL;
272 QueryTable[2].Flags = 0;
273 QueryTable[2].Name = NULL;
274 QueryTable[2].EntryContext = 0;
275 QueryTable[2].DefaultType = REG_NONE;
276 QueryTable[2].DefaultData = NULL;
277 QueryTable[2].DefaultLength = 0;
278
279 status = pRtlQueryRegistryValues(RelativeTo, winetestpath.Buffer, QueryTable, 0, 0);
280 ok(status == STATUS_SUCCESS, "RtlQueryRegistryValues return: 0x%08lx\n", status);
281
282 pRtlFreeHeap(GetProcessHeap(), 0, QueryTable);
283 }
284
285 static void test_NtCreateKey(void)
286 {
287 /*Create WineTest*/
288 OBJECT_ATTRIBUTES attr;
289 UNICODE_STRING ValName;
290 HKEY key;
291 ACCESS_MASK am = GENERIC_ALL;
292 NTSTATUS status;
293
294 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
295 status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
296 ok(status == STATUS_SUCCESS, "NtCreateKey Failed: 0x%08lx\n", status);
297
298 pRtlFreeUnicodeString(&ValName);
299 pNtClose(&key);
300 }
301
302 static void test_NtSetValueKey(void)
303 {
304 HANDLE key;
305 NTSTATUS status;
306 OBJECT_ATTRIBUTES attr;
307 ACCESS_MASK am = KEY_WRITE;
308 UNICODE_STRING ValName;
309 DWORD data = 711;
310
311 pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
312
313 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
314 status = pNtOpenKey(&key, am, &attr);
315 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08lx\n", status);
316
317 status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &data, sizeof(data));
318 ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08lx\n", status);
319
320 pRtlFreeUnicodeString(&ValName);
321 pNtClose(&key);
322 }
323
324 static void test_RtlOpenCurrentUser(void)
325 {
326 NTSTATUS status;
327 HKEY handle;
328 status=pRtlOpenCurrentUser(KEY_READ, &handle);
329 ok(status == STATUS_SUCCESS, "RtlOpenCurrentUser Failed: 0x%08lx\n", status);
330 pNtClose(&handle);
331 }
332
333 static void test_RtlCheckRegistryKey(void)
334 {
335 NTSTATUS status;
336
337 status = pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, winetestpath.Buffer);
338 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08lx\n", status);
339
340 status = pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL), winetestpath.Buffer);
341 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE and RTL_REGISTRY_OPTIONAL: 0x%08lx\n", status);
342 }
343
344 static void test_NtDeleteKey(void)
345 {
346 NTSTATUS status;
347 HANDLE hkey;
348 OBJECT_ATTRIBUTES attr;
349 ACCESS_MASK am = KEY_ALL_ACCESS;
350
351 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
352 status = pNtOpenKey(&hkey, am, &attr);
353
354 status = pNtDeleteKey(hkey);
355 ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08lx\n", status);
356 }
357
358 START_TEST(reg)
359 {
360 static const WCHAR winetest[] = {'\\','W','i','n','e','T','e','s','t','\\',0};
361 if(!InitFunctionPtrs())
362 return;
363 pRtlFormatCurrentUserKeyPath(&winetestpath);
364 winetestpath.Buffer = (PWSTR)pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, winetestpath.Buffer,
365 winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR));
366 winetestpath.MaximumLength = winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR);
367
368 pRtlAppendUnicodeToString(&winetestpath, winetest);
369
370 test_NtCreateKey();
371 test_NtSetValueKey();
372 test_RtlCheckRegistryKey();
373 test_RtlOpenCurrentUser();
374 test_RtlQueryRegistryValues();
375 test_NtDeleteKey();
376
377 pRtlFreeUnicodeString(&winetestpath);
378
379 FreeLibrary(hntdll);
380 }