ntdll: Add a test for NtNotifyChangeDirectoryFile.
[wine/multimedia.git] / dlls / ntdll / tests / reg.c
blobc94748a45b2ccff342c5e68d168de89ab2e166e7
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 * pNtDeleteKey)(HKEY);
92 static NTSTATUS (WINAPI * pNtCreateKey)( PHKEY retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
93 ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
94 PULONG dispos );
95 static NTSTATUS (WINAPI * pNtSetValueKey)( PHKEY, const PUNICODE_STRING, ULONG,
96 ULONG, const PVOID, ULONG );
97 static NTSTATUS (WINAPI * pRtlFormatCurrentUserKeyPath)(PUNICODE_STRING);
98 static NTSTATUS (WINAPI * pRtlCreateUnicodeString)( PUNICODE_STRING, LPCWSTR);
99 static NTSTATUS (WINAPI * pRtlReAllocateHeap)(IN PVOID, IN ULONG, IN PVOID, IN ULONG);
100 static NTSTATUS (WINAPI * pRtlAppendUnicodeToString)(PUNICODE_STRING, PCWSTR);
101 static NTSTATUS (WINAPI * pRtlUnicodeStringToAnsiString)(PSTRING, PUNICODE_STRING, BOOL);
102 static NTSTATUS (WINAPI * pRtlFreeHeap)(PVOID, ULONG, PVOID);
103 static NTSTATUS (WINAPI * pRtlAllocateHeap)(PVOID,ULONG,ULONG);
104 static NTSTATUS (WINAPI * pRtlZeroMemory)(PVOID, ULONG);
106 static HMODULE hntdll = 0;
107 static int CurrentTest = 0;
108 static UNICODE_STRING winetestpath;
110 #define NTDLL_GET_PROC(func) \
111 p ## func = (void*)GetProcAddress(hntdll, #func); \
112 if(!p ## func) { \
113 trace("GetProcAddress(%s) failed\n", #func); \
114 FreeLibrary(hntdll); \
115 return FALSE; \
118 static BOOL InitFunctionPtrs(void)
120 hntdll = LoadLibraryA("ntdll.dll");
121 if(!hntdll) {
122 trace("Could not load ntdll.dll\n");
123 return FALSE;
125 if (hntdll)
127 NTDLL_GET_PROC(RtlCreateUnicodeStringFromAsciiz)
128 NTDLL_GET_PROC(RtlCreateUnicodeString)
129 NTDLL_GET_PROC(RtlFreeUnicodeString)
130 NTDLL_GET_PROC(NtDeleteValueKey)
131 NTDLL_GET_PROC(RtlQueryRegistryValues)
132 NTDLL_GET_PROC(RtlCheckRegistryKey)
133 NTDLL_GET_PROC(RtlOpenCurrentUser)
134 NTDLL_GET_PROC(NtClose)
135 NTDLL_GET_PROC(NtDeleteValueKey)
136 NTDLL_GET_PROC(NtCreateKey)
137 NTDLL_GET_PROC(NtDeleteKey)
138 NTDLL_GET_PROC(NtSetValueKey)
139 NTDLL_GET_PROC(NtOpenKey)
140 NTDLL_GET_PROC(RtlFormatCurrentUserKeyPath)
141 NTDLL_GET_PROC(RtlReAllocateHeap)
142 NTDLL_GET_PROC(RtlAppendUnicodeToString)
143 NTDLL_GET_PROC(RtlUnicodeStringToAnsiString)
144 NTDLL_GET_PROC(RtlFreeHeap)
145 NTDLL_GET_PROC(RtlAllocateHeap)
146 NTDLL_GET_PROC(RtlZeroMemory)
148 return TRUE;
150 #undef NTDLL_GET_PROC
152 static NTSTATUS WINAPI QueryRoutine (IN PCWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData,
153 IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
155 NTSTATUS ret = STATUS_SUCCESS;
156 int ValueNameLength = 0;
157 LPSTR ValName = 0;
158 trace("**Test %d**\n", CurrentTest);
160 if(ValueName)
162 ValueNameLength = lstrlenW(ValueName);
164 ValName = (LPSTR)pRtlAllocateHeap(GetProcessHeap(), 0, ValueNameLength);
166 WideCharToMultiByte(0, 0, ValueName, ValueNameLength+1,ValName, ValueNameLength, 0, 0);
168 trace("ValueName: %s\n", ValName);
170 else
171 trace("ValueName: (null)\n");
173 switch(ValueType)
175 case REG_NONE:
176 trace("ValueType: REG_NONE\n");
177 trace("ValueData: %d\n", (int)ValueData);
178 break;
180 case REG_BINARY:
181 trace("ValueType: REG_BINARY\n");
182 trace("ValueData: %d\n", (int)ValueData);
183 break;
185 case REG_SZ:
186 trace("ValueType: REG_SZ\n");
187 trace("ValueData: %s\n", (char*)ValueData);
188 break;
190 case REG_MULTI_SZ:
191 trace("ValueType: REG_MULTI_SZ\n");
192 trace("ValueData: %s\n", (char*)ValueData);
193 break;
195 case REG_EXPAND_SZ:
196 trace("ValueType: REG_EXPAND_SZ\n");
197 trace("ValueData: %s\n", (char*)ValueData);
198 break;
200 case REG_DWORD:
201 trace("ValueType: REG_DWORD\n");
202 trace("ValueData: %d\n", (int)ValueData);
203 break;
205 trace("ValueLength: %d\n", (int)ValueLength);
207 if(CurrentTest == 0)
208 ok(1, "\n"); /*checks that QueryRoutine is called*/
209 if(CurrentTest > 7)
210 ok(!1, "Invalid Test Specified!\n");
212 CurrentTest++;
214 if(ValName)
215 pRtlFreeHeap(GetProcessHeap(), 0, ValName);
217 return ret;
220 static void test_RtlQueryRegistryValues(void)
224 ******************************
225 * QueryTable Flags *
226 ******************************
227 *RTL_QUERY_REGISTRY_SUBKEY * Name is the name of a subkey relative to Path
228 *RTL_QUERY_REGISTRY_TOPKEY * Resets location to original RelativeTo and Path
229 *RTL_QUERY_REGISTRY_REQUIRED * Key required. returns STATUS_OBJECT_NAME_NOT_FOUND if not present
230 *RTL_QUERY_REGISTRY_NOVALUE * We just want a call-back
231 *RTL_QUERY_REGISTRY_NOEXPAND * Don't expand the variables!
232 *RTL_QUERY_REGISTRY_DIRECT * Results of query will be stored in EntryContext(QueryRoutine ignored)
233 *RTL_QUERY_REGISTRY_DELETE * Delete value key after query
234 ******************************
237 **Test layout(numbered according to CurrentTest value)**
238 0)NOVALUE Just make sure call-back works
239 1)Null Name See if QueryRoutine is called for every value in current key
240 2)SUBKEY See if we can use SUBKEY to change the current path on the fly
241 3)REQUIRED Test for value that's not there
242 4)NOEXPAND See if it will return multiple strings(no expand should split strings up)
243 5)DIRECT Make it store data directly in EntryContext and not call QueryRoutine
244 6)DefaultType Test return values when key isn't present
245 7)DefaultValue Test Default Value returned with key isn't present(and no REQUIRED flag set)
246 8)DefaultLength Test Default Length with DefaultType = REG_SZ
247 9)DefaultLength Test Default Length with DefaultType = REG_MULTI_SZ
248 10)DefaultLength Test Default Length with DefaultType = REG_EXPAND_SZ
249 11)DefaultData Test whether DefaultData is used while DefaltType = REG_NONE(shouldn't be)
250 12)Delete Try to delete value key
253 NTSTATUS status;
254 ULONG RelativeTo;
256 PRTL_QUERY_REGISTRY_TABLE QueryTable = NULL;
257 RelativeTo = RTL_REGISTRY_ABSOLUTE;/*Only using absolute - no need to test all relativeto variables*/
259 QueryTable = (PRTL_QUERY_REGISTRY_TABLE)pRtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_QUERY_REGISTRY_TABLE)*26);
261 pRtlZeroMemory( QueryTable, sizeof(RTL_QUERY_REGISTRY_TABLE) * 26);
263 QueryTable[0].QueryRoutine = QueryRoutine;
264 QueryTable[0].Flags = RTL_QUERY_REGISTRY_NOVALUE;
265 QueryTable[0].Name = NULL;
266 QueryTable[0].EntryContext = NULL;
267 QueryTable[0].DefaultType = REG_BINARY;
268 QueryTable[0].DefaultData = NULL;
269 QueryTable[0].DefaultLength = 100;
271 QueryTable[1].QueryRoutine = QueryRoutine;
272 QueryTable[1].Flags = 0;
273 QueryTable[1].Name = NULL;
274 QueryTable[1].EntryContext = 0;
275 QueryTable[1].DefaultType = REG_NONE;
276 QueryTable[1].DefaultData = NULL;
277 QueryTable[1].DefaultLength = 0;
279 QueryTable[2].QueryRoutine = NULL;
280 QueryTable[2].Flags = 0;
281 QueryTable[2].Name = NULL;
282 QueryTable[2].EntryContext = 0;
283 QueryTable[2].DefaultType = REG_NONE;
284 QueryTable[2].DefaultData = NULL;
285 QueryTable[2].DefaultLength = 0;
287 status = pRtlQueryRegistryValues(RelativeTo, winetestpath.Buffer, QueryTable, 0, 0);
288 ok(status == STATUS_SUCCESS, "RtlQueryRegistryValues return: 0x%08lx\n", status);
290 pRtlFreeHeap(GetProcessHeap(), 0, QueryTable);
293 static void test_NtCreateKey(void)
295 /*Create WineTest*/
296 OBJECT_ATTRIBUTES attr;
297 UNICODE_STRING ValName;
298 HKEY key;
299 ACCESS_MASK am = GENERIC_ALL;
300 NTSTATUS status;
302 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
303 status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
304 ok(status == STATUS_SUCCESS, "NtCreateKey Failed: 0x%08lx\n", status);
306 pRtlFreeUnicodeString(&ValName);
307 pNtClose(&key);
310 static void test_NtSetValueKey(void)
312 HANDLE key;
313 NTSTATUS status;
314 OBJECT_ATTRIBUTES attr;
315 ACCESS_MASK am = KEY_WRITE;
316 UNICODE_STRING ValName;
317 DWORD data = 711;
319 pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
321 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
322 status = pNtOpenKey(&key, am, &attr);
323 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08lx\n", status);
325 status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &data, sizeof(data));
326 ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08lx\n", status);
328 pRtlFreeUnicodeString(&ValName);
329 pNtClose(&key);
332 static void test_RtlOpenCurrentUser(void)
334 NTSTATUS status;
335 HKEY handle;
336 status=pRtlOpenCurrentUser(KEY_READ, &handle);
337 ok(status == STATUS_SUCCESS, "RtlOpenCurrentUser Failed: 0x%08lx\n", status);
338 pNtClose(&handle);
341 static void test_RtlCheckRegistryKey(void)
343 NTSTATUS status;
345 status = pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, winetestpath.Buffer);
346 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08lx\n", status);
348 status = pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL), winetestpath.Buffer);
349 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE and RTL_REGISTRY_OPTIONAL: 0x%08lx\n", status);
352 static void test_NtDeleteKey(void)
354 NTSTATUS status;
355 HANDLE hkey;
356 OBJECT_ATTRIBUTES attr;
357 ACCESS_MASK am = KEY_ALL_ACCESS;
359 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
360 status = pNtOpenKey(&hkey, am, &attr);
362 status = pNtDeleteKey(hkey);
363 ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08lx\n", status);
366 START_TEST(reg)
368 static const WCHAR winetest[] = {'\\','W','i','n','e','T','e','s','t','\\',0};
369 if(!InitFunctionPtrs())
370 return;
371 pRtlFormatCurrentUserKeyPath(&winetestpath);
372 winetestpath.Buffer = (PWSTR)pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, winetestpath.Buffer,
373 winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR));
374 winetestpath.MaximumLength = winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR);
376 pRtlAppendUnicodeToString(&winetestpath, winetest);
378 test_NtCreateKey();
379 test_NtSetValueKey();
380 test_RtlCheckRegistryKey();
381 test_RtlOpenCurrentUser();
382 test_RtlQueryRegistryValues();
383 test_NtDeleteKey();
385 pRtlFreeUnicodeString(&winetestpath);
387 FreeLibrary(hntdll);