loader: Use plain binary name of git-describe to avoid junk in version output.
[wine.git] / dlls / ntdll / tests / reg.c
blob262e33f5e43b4eb7f2b0cbfa00e4a7f6af302428
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 #define InitializeObjectAttributes(p,n,a,r,s) \
71 do { \
72 (p)->Length = sizeof(OBJECT_ATTRIBUTES); \
73 (p)->RootDirectory = r; \
74 (p)->Attributes = a; \
75 (p)->ObjectName = n; \
76 (p)->SecurityDescriptor = s; \
77 (p)->SecurityQualityOfService = NULL; \
78 } while (0)
80 #endif
82 static NTSTATUS (WINAPI * pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPCSTR);
83 static NTSTATUS (WINAPI * pRtlFreeUnicodeString)(PUNICODE_STRING);
84 static NTSTATUS (WINAPI * pNtDeleteValueKey)(IN HANDLE, IN PUNICODE_STRING);
85 static NTSTATUS (WINAPI * pRtlQueryRegistryValues)(IN ULONG, IN PCWSTR,IN PRTL_QUERY_REGISTRY_TABLE, IN PVOID,IN PVOID);
86 static NTSTATUS (WINAPI * pRtlCheckRegistryKey)(IN ULONG,IN PWSTR);
87 static NTSTATUS (WINAPI * pRtlOpenCurrentUser)(IN ACCESS_MASK, OUT PHKEY);
88 static NTSTATUS (WINAPI * pNtOpenKey)(PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES);
89 static NTSTATUS (WINAPI * pNtClose)(IN HANDLE);
90 static NTSTATUS (WINAPI * pNtDeleteValueKey)(IN HANDLE, IN PUNICODE_STRING);
91 static NTSTATUS (WINAPI * pNtFlushKey)(HKEY);
92 static NTSTATUS (WINAPI * pNtDeleteKey)(HKEY);
93 static NTSTATUS (WINAPI * pNtCreateKey)( PHKEY retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
94 ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
95 PULONG dispos );
96 static NTSTATUS (WINAPI * pNtSetValueKey)( PHKEY, const PUNICODE_STRING, ULONG,
97 ULONG, const PVOID, ULONG );
98 static NTSTATUS (WINAPI * pRtlFormatCurrentUserKeyPath)(PUNICODE_STRING);
99 static NTSTATUS (WINAPI * pRtlCreateUnicodeString)( PUNICODE_STRING, LPCWSTR);
100 static NTSTATUS (WINAPI * pRtlReAllocateHeap)(IN PVOID, IN ULONG, IN PVOID, IN ULONG);
101 static NTSTATUS (WINAPI * pRtlAppendUnicodeToString)(PUNICODE_STRING, PCWSTR);
102 static NTSTATUS (WINAPI * pRtlUnicodeStringToAnsiString)(PSTRING, PUNICODE_STRING, BOOL);
103 static NTSTATUS (WINAPI * pRtlFreeHeap)(PVOID, ULONG, PVOID);
104 static NTSTATUS (WINAPI * pRtlAllocateHeap)(PVOID,ULONG,ULONG);
105 static NTSTATUS (WINAPI * pRtlZeroMemory)(PVOID, ULONG);
106 static NTSTATUS (WINAPI * pRtlpNtQueryValueKey)(HANDLE,ULONG*,PBYTE,DWORD*);
108 static HMODULE hntdll = 0;
109 static int CurrentTest = 0;
110 static UNICODE_STRING winetestpath;
112 #define NTDLL_GET_PROC(func) \
113 p ## func = (void*)GetProcAddress(hntdll, #func); \
114 if(!p ## func) { \
115 trace("GetProcAddress(%s) failed\n", #func); \
116 FreeLibrary(hntdll); \
117 return FALSE; \
120 static BOOL InitFunctionPtrs(void)
122 hntdll = LoadLibraryA("ntdll.dll");
123 if(!hntdll) {
124 trace("Could not load ntdll.dll\n");
125 return FALSE;
127 if (hntdll)
129 NTDLL_GET_PROC(RtlCreateUnicodeStringFromAsciiz)
130 NTDLL_GET_PROC(RtlCreateUnicodeString)
131 NTDLL_GET_PROC(RtlFreeUnicodeString)
132 NTDLL_GET_PROC(NtDeleteValueKey)
133 NTDLL_GET_PROC(RtlQueryRegistryValues)
134 NTDLL_GET_PROC(RtlCheckRegistryKey)
135 NTDLL_GET_PROC(RtlOpenCurrentUser)
136 NTDLL_GET_PROC(NtClose)
137 NTDLL_GET_PROC(NtDeleteValueKey)
138 NTDLL_GET_PROC(NtCreateKey)
139 NTDLL_GET_PROC(NtFlushKey)
140 NTDLL_GET_PROC(NtDeleteKey)
141 NTDLL_GET_PROC(NtSetValueKey)
142 NTDLL_GET_PROC(NtOpenKey)
143 NTDLL_GET_PROC(RtlFormatCurrentUserKeyPath)
144 NTDLL_GET_PROC(RtlReAllocateHeap)
145 NTDLL_GET_PROC(RtlAppendUnicodeToString)
146 NTDLL_GET_PROC(RtlUnicodeStringToAnsiString)
147 NTDLL_GET_PROC(RtlFreeHeap)
148 NTDLL_GET_PROC(RtlAllocateHeap)
149 NTDLL_GET_PROC(RtlZeroMemory)
150 NTDLL_GET_PROC(RtlpNtQueryValueKey)
152 return TRUE;
154 #undef NTDLL_GET_PROC
156 static NTSTATUS WINAPI QueryRoutine (IN PCWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData,
157 IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
159 NTSTATUS ret = STATUS_SUCCESS;
160 int ValueNameLength = 0;
161 LPSTR ValName = 0;
162 trace("**Test %d**\n", CurrentTest);
164 if(ValueName)
166 ValueNameLength = lstrlenW(ValueName);
168 ValName = (LPSTR)pRtlAllocateHeap(GetProcessHeap(), 0, ValueNameLength);
170 WideCharToMultiByte(0, 0, ValueName, ValueNameLength+1,ValName, ValueNameLength, 0, 0);
172 trace("ValueName: %s\n", ValName);
174 else
175 trace("ValueName: (null)\n");
177 switch(ValueType)
179 case REG_NONE:
180 trace("ValueType: REG_NONE\n");
181 trace("ValueData: %d\n", (int)ValueData);
182 break;
184 case REG_BINARY:
185 trace("ValueType: REG_BINARY\n");
186 trace("ValueData: %d\n", (int)ValueData);
187 break;
189 case REG_SZ:
190 trace("ValueType: REG_SZ\n");
191 trace("ValueData: %s\n", (char*)ValueData);
192 break;
194 case REG_MULTI_SZ:
195 trace("ValueType: REG_MULTI_SZ\n");
196 trace("ValueData: %s\n", (char*)ValueData);
197 break;
199 case REG_EXPAND_SZ:
200 trace("ValueType: REG_EXPAND_SZ\n");
201 trace("ValueData: %s\n", (char*)ValueData);
202 break;
204 case REG_DWORD:
205 trace("ValueType: REG_DWORD\n");
206 trace("ValueData: %d\n", (int)ValueData);
207 break;
209 trace("ValueLength: %d\n", (int)ValueLength);
211 if(CurrentTest == 0)
212 ok(1, "\n"); /*checks that QueryRoutine is called*/
213 if(CurrentTest > 7)
214 ok(!1, "Invalid Test Specified!\n");
216 CurrentTest++;
218 if(ValName)
219 pRtlFreeHeap(GetProcessHeap(), 0, ValName);
221 return ret;
224 static void test_RtlQueryRegistryValues(void)
228 ******************************
229 * QueryTable Flags *
230 ******************************
231 *RTL_QUERY_REGISTRY_SUBKEY * Name is the name of a subkey relative to Path
232 *RTL_QUERY_REGISTRY_TOPKEY * Resets location to original RelativeTo and Path
233 *RTL_QUERY_REGISTRY_REQUIRED * Key required. returns STATUS_OBJECT_NAME_NOT_FOUND if not present
234 *RTL_QUERY_REGISTRY_NOVALUE * We just want a call-back
235 *RTL_QUERY_REGISTRY_NOEXPAND * Don't expand the variables!
236 *RTL_QUERY_REGISTRY_DIRECT * Results of query will be stored in EntryContext(QueryRoutine ignored)
237 *RTL_QUERY_REGISTRY_DELETE * Delete value key after query
238 ******************************
241 **Test layout(numbered according to CurrentTest value)**
242 0)NOVALUE Just make sure call-back works
243 1)Null Name See if QueryRoutine is called for every value in current key
244 2)SUBKEY See if we can use SUBKEY to change the current path on the fly
245 3)REQUIRED Test for value that's not there
246 4)NOEXPAND See if it will return multiple strings(no expand should split strings up)
247 5)DIRECT Make it store data directly in EntryContext and not call QueryRoutine
248 6)DefaultType Test return values when key isn't present
249 7)DefaultValue Test Default Value returned with key isn't present(and no REQUIRED flag set)
250 8)DefaultLength Test Default Length with DefaultType = REG_SZ
251 9)DefaultLength Test Default Length with DefaultType = REG_MULTI_SZ
252 10)DefaultLength Test Default Length with DefaultType = REG_EXPAND_SZ
253 11)DefaultData Test whether DefaultData is used while DefaltType = REG_NONE(shouldn't be)
254 12)Delete Try to delete value key
257 NTSTATUS status;
258 ULONG RelativeTo;
260 PRTL_QUERY_REGISTRY_TABLE QueryTable = NULL;
261 RelativeTo = RTL_REGISTRY_ABSOLUTE;/*Only using absolute - no need to test all relativeto variables*/
263 QueryTable = (PRTL_QUERY_REGISTRY_TABLE)pRtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_QUERY_REGISTRY_TABLE)*26);
265 pRtlZeroMemory( QueryTable, sizeof(RTL_QUERY_REGISTRY_TABLE) * 26);
267 QueryTable[0].QueryRoutine = QueryRoutine;
268 QueryTable[0].Flags = RTL_QUERY_REGISTRY_NOVALUE;
269 QueryTable[0].Name = NULL;
270 QueryTable[0].EntryContext = NULL;
271 QueryTable[0].DefaultType = REG_BINARY;
272 QueryTable[0].DefaultData = NULL;
273 QueryTable[0].DefaultLength = 100;
275 QueryTable[1].QueryRoutine = QueryRoutine;
276 QueryTable[1].Flags = 0;
277 QueryTable[1].Name = NULL;
278 QueryTable[1].EntryContext = 0;
279 QueryTable[1].DefaultType = REG_NONE;
280 QueryTable[1].DefaultData = NULL;
281 QueryTable[1].DefaultLength = 0;
283 QueryTable[2].QueryRoutine = NULL;
284 QueryTable[2].Flags = 0;
285 QueryTable[2].Name = NULL;
286 QueryTable[2].EntryContext = 0;
287 QueryTable[2].DefaultType = REG_NONE;
288 QueryTable[2].DefaultData = NULL;
289 QueryTable[2].DefaultLength = 0;
291 status = pRtlQueryRegistryValues(RelativeTo, winetestpath.Buffer, QueryTable, 0, 0);
292 ok(status == STATUS_SUCCESS, "RtlQueryRegistryValues return: 0x%08x\n", status);
294 pRtlFreeHeap(GetProcessHeap(), 0, QueryTable);
297 static void test_NtOpenKey(void)
299 HANDLE key;
300 NTSTATUS status;
301 OBJECT_ATTRIBUTES attr;
302 ACCESS_MASK am = KEY_READ;
304 #if 0 /* Crashes Wine */
305 /* All NULL */
306 status = pNtOpenKey(NULL, 0, NULL);
307 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08lx\n", status);
309 /* NULL attributes */
310 status = pNtOpenKey(&key, 0, NULL);
311 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
312 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08lx\n", status);
313 #endif
315 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
317 /* NULL key */
318 status = pNtOpenKey(NULL, 0, &attr);
319 todo_wine
320 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
322 /* Length > sizeof(OBJECT_ATTRIBUTES) */
323 attr.Length *= 2;
324 status = pNtOpenKey(&key, am, &attr);
325 todo_wine
326 ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
329 static void test_NtCreateKey(void)
331 /*Create WineTest*/
332 OBJECT_ATTRIBUTES attr;
333 HKEY key;
334 ACCESS_MASK am = GENERIC_ALL;
335 NTSTATUS status;
337 /* All NULL */
338 status = pNtCreateKey(NULL, 0, NULL, 0, 0, 0, 0);
339 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
341 /* Only the key */
342 status = pNtCreateKey(&key, 0, NULL, 0, 0, 0, 0);
343 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
344 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
346 /* Only accessmask */
347 status = pNtCreateKey(NULL, am, NULL, 0, 0, 0, 0);
348 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
350 /* Key and accessmask */
351 status = pNtCreateKey(&key, am, NULL, 0, 0, 0, 0);
352 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
353 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status);
355 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
357 /* Only attributes */
358 status = pNtCreateKey(NULL, 0, &attr, 0, 0, 0, 0);
359 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status);
361 status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
362 ok(status == STATUS_SUCCESS, "NtCreateKey Failed: 0x%08x\n", status);
364 /* Length > sizeof(OBJECT_ATTRIBUTES) */
365 attr.Length *= 2;
366 status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
367 ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status);
369 pNtClose(&key);
372 static void test_NtSetValueKey(void)
374 HANDLE key;
375 NTSTATUS status;
376 OBJECT_ATTRIBUTES attr;
377 ACCESS_MASK am = KEY_WRITE;
378 UNICODE_STRING ValName;
379 DWORD data = 711;
381 pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
383 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
384 status = pNtOpenKey(&key, am, &attr);
385 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
387 status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &data, sizeof(data));
388 ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status);
390 pRtlFreeUnicodeString(&ValName);
391 pNtClose(&key);
394 static void test_RtlOpenCurrentUser(void)
396 NTSTATUS status;
397 HKEY handle;
398 status=pRtlOpenCurrentUser(KEY_READ, &handle);
399 ok(status == STATUS_SUCCESS, "RtlOpenCurrentUser Failed: 0x%08x\n", status);
400 pNtClose(&handle);
403 static void test_RtlCheckRegistryKey(void)
405 NTSTATUS status;
407 status = pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, winetestpath.Buffer);
408 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08x\n", status);
410 status = pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL), winetestpath.Buffer);
411 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE and RTL_REGISTRY_OPTIONAL: 0x%08x\n", status);
414 static void test_NtFlushKey(void)
416 NTSTATUS status;
417 HANDLE hkey;
418 OBJECT_ATTRIBUTES attr;
419 ACCESS_MASK am = KEY_ALL_ACCESS;
421 status = pNtFlushKey(NULL);
422 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
424 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
425 pNtOpenKey(&hkey, am, &attr);
427 status = pNtFlushKey(hkey);
428 ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
430 pNtClose(hkey);
433 static void test_NtDeleteKey(void)
435 NTSTATUS status;
436 HANDLE hkey;
437 OBJECT_ATTRIBUTES attr;
438 ACCESS_MASK am = KEY_ALL_ACCESS;
440 status = pNtDeleteKey(NULL);
441 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
443 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
444 status = pNtOpenKey(&hkey, am, &attr);
446 status = pNtDeleteKey(hkey);
447 ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status);
450 static void test_RtlpNtQueryValueKey(void)
452 NTSTATUS status;
454 status = pRtlpNtQueryValueKey(NULL, NULL, NULL, NULL);
455 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
458 START_TEST(reg)
460 static const WCHAR winetest[] = {'\\','W','i','n','e','T','e','s','t','\\',0};
461 if(!InitFunctionPtrs())
462 return;
463 pRtlFormatCurrentUserKeyPath(&winetestpath);
464 winetestpath.Buffer = (PWSTR)pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, winetestpath.Buffer,
465 winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR));
466 winetestpath.MaximumLength = winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR);
468 pRtlAppendUnicodeToString(&winetestpath, winetest);
470 test_NtOpenKey();
471 test_NtCreateKey();
472 test_NtSetValueKey();
473 test_RtlCheckRegistryKey();
474 test_RtlOpenCurrentUser();
475 test_RtlQueryRegistryValues();
476 test_RtlpNtQueryValueKey();
477 test_NtFlushKey();
478 test_NtDeleteKey();
480 pRtlFreeUnicodeString(&winetestpath);
482 FreeLibrary(hntdll);