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"
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,
60 typedef struct _RTL_QUERY_REGISTRY_TABLE {
61 PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine;
68 } RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE;
70 #define InitializeObjectAttributes(p,n,a,r,s) \
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; \
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,
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);
107 static HMODULE hntdll = 0;
108 static int CurrentTest = 0;
109 static UNICODE_STRING winetestpath;
111 #define NTDLL_GET_PROC(func) \
112 p ## func = (void*)GetProcAddress(hntdll, #func); \
114 trace("GetProcAddress(%s) failed\n", #func); \
115 FreeLibrary(hntdll); \
119 static BOOL InitFunctionPtrs(void)
121 hntdll = LoadLibraryA("ntdll.dll");
123 trace("Could not load ntdll.dll\n");
128 NTDLL_GET_PROC(RtlCreateUnicodeStringFromAsciiz)
129 NTDLL_GET_PROC(RtlCreateUnicodeString)
130 NTDLL_GET_PROC(RtlFreeUnicodeString)
131 NTDLL_GET_PROC(NtDeleteValueKey)
132 NTDLL_GET_PROC(RtlQueryRegistryValues)
133 NTDLL_GET_PROC(RtlCheckRegistryKey)
134 NTDLL_GET_PROC(RtlOpenCurrentUser)
135 NTDLL_GET_PROC(NtClose)
136 NTDLL_GET_PROC(NtDeleteValueKey)
137 NTDLL_GET_PROC(NtCreateKey)
138 NTDLL_GET_PROC(NtFlushKey)
139 NTDLL_GET_PROC(NtDeleteKey)
140 NTDLL_GET_PROC(NtSetValueKey)
141 NTDLL_GET_PROC(NtOpenKey)
142 NTDLL_GET_PROC(RtlFormatCurrentUserKeyPath)
143 NTDLL_GET_PROC(RtlReAllocateHeap)
144 NTDLL_GET_PROC(RtlAppendUnicodeToString)
145 NTDLL_GET_PROC(RtlUnicodeStringToAnsiString)
146 NTDLL_GET_PROC(RtlFreeHeap)
147 NTDLL_GET_PROC(RtlAllocateHeap)
148 NTDLL_GET_PROC(RtlZeroMemory)
152 #undef NTDLL_GET_PROC
154 static NTSTATUS WINAPI QueryRoutine (IN PCWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData,
155 IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
157 NTSTATUS ret = STATUS_SUCCESS;
158 int ValueNameLength = 0;
160 trace("**Test %d**\n", CurrentTest);
164 ValueNameLength = lstrlenW(ValueName);
166 ValName = (LPSTR)pRtlAllocateHeap(GetProcessHeap(), 0, ValueNameLength);
168 WideCharToMultiByte(0, 0, ValueName, ValueNameLength+1,ValName, ValueNameLength, 0, 0);
170 trace("ValueName: %s\n", ValName);
173 trace("ValueName: (null)\n");
178 trace("ValueType: REG_NONE\n");
179 trace("ValueData: %d\n", (int)ValueData);
183 trace("ValueType: REG_BINARY\n");
184 trace("ValueData: %d\n", (int)ValueData);
188 trace("ValueType: REG_SZ\n");
189 trace("ValueData: %s\n", (char*)ValueData);
193 trace("ValueType: REG_MULTI_SZ\n");
194 trace("ValueData: %s\n", (char*)ValueData);
198 trace("ValueType: REG_EXPAND_SZ\n");
199 trace("ValueData: %s\n", (char*)ValueData);
203 trace("ValueType: REG_DWORD\n");
204 trace("ValueData: %d\n", (int)ValueData);
207 trace("ValueLength: %d\n", (int)ValueLength);
210 ok(1, "\n"); /*checks that QueryRoutine is called*/
212 ok(!1, "Invalid Test Specified!\n");
217 pRtlFreeHeap(GetProcessHeap(), 0, ValName);
222 static void test_RtlQueryRegistryValues(void)
226 ******************************
228 ******************************
229 *RTL_QUERY_REGISTRY_SUBKEY * Name is the name of a subkey relative to Path
230 *RTL_QUERY_REGISTRY_TOPKEY * Resets location to original RelativeTo and Path
231 *RTL_QUERY_REGISTRY_REQUIRED * Key required. returns STATUS_OBJECT_NAME_NOT_FOUND if not present
232 *RTL_QUERY_REGISTRY_NOVALUE * We just want a call-back
233 *RTL_QUERY_REGISTRY_NOEXPAND * Don't expand the variables!
234 *RTL_QUERY_REGISTRY_DIRECT * Results of query will be stored in EntryContext(QueryRoutine ignored)
235 *RTL_QUERY_REGISTRY_DELETE * Delete value key after query
236 ******************************
239 **Test layout(numbered according to CurrentTest value)**
240 0)NOVALUE Just make sure call-back works
241 1)Null Name See if QueryRoutine is called for every value in current key
242 2)SUBKEY See if we can use SUBKEY to change the current path on the fly
243 3)REQUIRED Test for value that's not there
244 4)NOEXPAND See if it will return multiple strings(no expand should split strings up)
245 5)DIRECT Make it store data directly in EntryContext and not call QueryRoutine
246 6)DefaultType Test return values when key isn't present
247 7)DefaultValue Test Default Value returned with key isn't present(and no REQUIRED flag set)
248 8)DefaultLength Test Default Length with DefaultType = REG_SZ
249 9)DefaultLength Test Default Length with DefaultType = REG_MULTI_SZ
250 10)DefaultLength Test Default Length with DefaultType = REG_EXPAND_SZ
251 11)DefaultData Test whether DefaultData is used while DefaltType = REG_NONE(shouldn't be)
252 12)Delete Try to delete value key
258 PRTL_QUERY_REGISTRY_TABLE QueryTable = NULL;
259 RelativeTo = RTL_REGISTRY_ABSOLUTE;/*Only using absolute - no need to test all relativeto variables*/
261 QueryTable = (PRTL_QUERY_REGISTRY_TABLE)pRtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_QUERY_REGISTRY_TABLE)*26);
263 pRtlZeroMemory( QueryTable, sizeof(RTL_QUERY_REGISTRY_TABLE) * 26);
265 QueryTable[0].QueryRoutine = QueryRoutine;
266 QueryTable[0].Flags = RTL_QUERY_REGISTRY_NOVALUE;
267 QueryTable[0].Name = NULL;
268 QueryTable[0].EntryContext = NULL;
269 QueryTable[0].DefaultType = REG_BINARY;
270 QueryTable[0].DefaultData = NULL;
271 QueryTable[0].DefaultLength = 100;
273 QueryTable[1].QueryRoutine = QueryRoutine;
274 QueryTable[1].Flags = 0;
275 QueryTable[1].Name = NULL;
276 QueryTable[1].EntryContext = 0;
277 QueryTable[1].DefaultType = REG_NONE;
278 QueryTable[1].DefaultData = NULL;
279 QueryTable[1].DefaultLength = 0;
281 QueryTable[2].QueryRoutine = NULL;
282 QueryTable[2].Flags = 0;
283 QueryTable[2].Name = NULL;
284 QueryTable[2].EntryContext = 0;
285 QueryTable[2].DefaultType = REG_NONE;
286 QueryTable[2].DefaultData = NULL;
287 QueryTable[2].DefaultLength = 0;
289 status = pRtlQueryRegistryValues(RelativeTo, winetestpath.Buffer, QueryTable, 0, 0);
290 ok(status == STATUS_SUCCESS, "RtlQueryRegistryValues return: 0x%08lx\n", status);
292 pRtlFreeHeap(GetProcessHeap(), 0, QueryTable);
295 static void test_NtOpenKey(void)
299 OBJECT_ATTRIBUTES attr;
300 ACCESS_MASK am = KEY_READ;
302 #if 0 /* Crashes Wine */
304 status = pNtOpenKey(NULL, 0, NULL);
305 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08lx\n", status);
307 /* NULL attributes */
308 status = pNtOpenKey(&key, 0, NULL);
309 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
310 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08lx\n", status);
313 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
316 status = pNtOpenKey(NULL, 0, &attr);
318 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08lx\n", status);
320 /* Length > sizeof(OBJECT_ATTRIBUTES) */
322 status = pNtOpenKey(&key, am, &attr);
324 ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08lx\n", status);
327 static void test_NtCreateKey(void)
330 OBJECT_ATTRIBUTES attr;
332 ACCESS_MASK am = GENERIC_ALL;
336 status = pNtCreateKey(NULL, 0, NULL, 0, 0, 0, 0);
337 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08lx\n", status);
340 status = pNtCreateKey(&key, 0, NULL, 0, 0, 0, 0);
341 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
342 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08lx\n", status);
344 /* Only accessmask */
345 status = pNtCreateKey(NULL, am, NULL, 0, 0, 0, 0);
346 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08lx\n", status);
348 /* Key and accessmask */
349 status = pNtCreateKey(&key, am, NULL, 0, 0, 0, 0);
350 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */,
351 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08lx\n", status);
353 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
355 /* Only attributes */
356 status = pNtCreateKey(NULL, 0, &attr, 0, 0, 0, 0);
357 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08lx\n", status);
359 status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
360 ok(status == STATUS_SUCCESS, "NtCreateKey Failed: 0x%08lx\n", status);
362 /* Length > sizeof(OBJECT_ATTRIBUTES) */
364 status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
365 ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08lx\n", status);
370 static void test_NtSetValueKey(void)
374 OBJECT_ATTRIBUTES attr;
375 ACCESS_MASK am = KEY_WRITE;
376 UNICODE_STRING ValName;
379 pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
381 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
382 status = pNtOpenKey(&key, am, &attr);
383 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08lx\n", status);
385 status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &data, sizeof(data));
386 ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08lx\n", status);
388 pRtlFreeUnicodeString(&ValName);
392 static void test_RtlOpenCurrentUser(void)
396 status=pRtlOpenCurrentUser(KEY_READ, &handle);
397 ok(status == STATUS_SUCCESS, "RtlOpenCurrentUser Failed: 0x%08lx\n", status);
401 static void test_RtlCheckRegistryKey(void)
405 status = pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, winetestpath.Buffer);
406 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08lx\n", status);
408 status = pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL), winetestpath.Buffer);
409 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE and RTL_REGISTRY_OPTIONAL: 0x%08lx\n", status);
412 static void test_NtFlushKey(void)
416 OBJECT_ATTRIBUTES attr;
417 ACCESS_MASK am = KEY_ALL_ACCESS;
419 status = pNtFlushKey(NULL);
420 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08lx\n", status);
422 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
423 pNtOpenKey(&hkey, am, &attr);
425 status = pNtFlushKey(hkey);
426 ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08lx\n", status);
431 static void test_NtDeleteKey(void)
435 OBJECT_ATTRIBUTES attr;
436 ACCESS_MASK am = KEY_ALL_ACCESS;
438 status = pNtDeleteKey(NULL);
439 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08lx\n", status);
441 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
442 status = pNtOpenKey(&hkey, am, &attr);
444 status = pNtDeleteKey(hkey);
445 ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08lx\n", status);
450 static const WCHAR winetest[] = {'\\','W','i','n','e','T','e','s','t','\\',0};
451 if(!InitFunctionPtrs())
453 pRtlFormatCurrentUserKeyPath(&winetestpath);
454 winetestpath.Buffer = (PWSTR)pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, winetestpath.Buffer,
455 winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR));
456 winetestpath.MaximumLength = winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR);
458 pRtlAppendUnicodeToString(&winetestpath, winetest);
462 test_NtSetValueKey();
463 test_RtlCheckRegistryKey();
464 test_RtlOpenCurrentUser();
465 test_RtlQueryRegistryValues();
469 pRtlFreeUnicodeString(&winetestpath);