1 /* Unit test suite for Rtl* Registry API functions
3 * Copyright 2003 Thomas Mertes
4 * Copyright 2005 Brad DeMorrow
5 * Copyright 2006 Dmitry Philippov
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * NOTE: I don't test every RelativeTo value because it would be redundant, all calls go through
22 * helper function RTL_GetKeyHandle().--Brad DeMorrow
26 #include "ntdll_test.h"
33 #ifndef __WINE_WINTERNL_H
35 /* RtlQueryRegistryValues structs and defines */
36 #define RTL_REGISTRY_ABSOLUTE 0
37 #define RTL_REGISTRY_SERVICES 1
38 #define RTL_REGISTRY_CONTROL 2
39 #define RTL_REGISTRY_WINDOWS_NT 3
40 #define RTL_REGISTRY_DEVICEMAP 4
41 #define RTL_REGISTRY_USER 5
43 #define RTL_REGISTRY_HANDLE 0x40000000
44 #define RTL_REGISTRY_OPTIONAL 0x80000000
46 #define RTL_QUERY_REGISTRY_SUBKEY 0x00000001
47 #define RTL_QUERY_REGISTRY_TOPKEY 0x00000002
48 #define RTL_QUERY_REGISTRY_REQUIRED 0x00000004
49 #define RTL_QUERY_REGISTRY_NOVALUE 0x00000008
50 #define RTL_QUERY_REGISTRY_NOEXPAND 0x00000010
51 #define RTL_QUERY_REGISTRY_DIRECT 0x00000020
52 #define RTL_QUERY_REGISTRY_DELETE 0x00000040
54 typedef NTSTATUS (WINAPI
*PRTL_QUERY_REGISTRY_ROUTINE
)( PCWSTR ValueName
,
61 typedef struct _RTL_QUERY_REGISTRY_TABLE
{
62 PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
;
69 } RTL_QUERY_REGISTRY_TABLE
, *PRTL_QUERY_REGISTRY_TABLE
;
71 #define InitializeObjectAttributes(p,n,a,r,s) \
73 (p)->Length = sizeof(OBJECT_ATTRIBUTES); \
74 (p)->RootDirectory = r; \
75 (p)->Attributes = a; \
76 (p)->ObjectName = n; \
77 (p)->SecurityDescriptor = s; \
78 (p)->SecurityQualityOfService = NULL; \
83 static NTSTATUS (WINAPI
* pRtlCreateUnicodeStringFromAsciiz
)(PUNICODE_STRING
, LPCSTR
);
84 static NTSTATUS (WINAPI
* pRtlFreeUnicodeString
)(PUNICODE_STRING
);
85 static NTSTATUS (WINAPI
* pNtDeleteValueKey
)(IN HANDLE
, IN PUNICODE_STRING
);
86 static NTSTATUS (WINAPI
* pRtlQueryRegistryValues
)(IN ULONG
, IN PCWSTR
,IN PRTL_QUERY_REGISTRY_TABLE
, IN PVOID
,IN PVOID
);
87 static NTSTATUS (WINAPI
* pRtlCheckRegistryKey
)(IN ULONG
,IN PWSTR
);
88 static NTSTATUS (WINAPI
* pRtlOpenCurrentUser
)(IN ACCESS_MASK
, OUT PHANDLE
);
89 static NTSTATUS (WINAPI
* pNtOpenKey
)(PHANDLE
, IN ACCESS_MASK
, IN POBJECT_ATTRIBUTES
);
90 static NTSTATUS (WINAPI
* pNtClose
)(IN HANDLE
);
91 static NTSTATUS (WINAPI
* pNtDeleteValueKey
)(IN HANDLE
, IN PUNICODE_STRING
);
92 static NTSTATUS (WINAPI
* pNtDeleteKey
)(HANDLE
);
93 static NTSTATUS (WINAPI
* pNtCreateKey
)( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
94 ULONG TitleIndex
, const UNICODE_STRING
*class, ULONG options
,
96 static NTSTATUS (WINAPI
* pNtSetValueKey
)( HANDLE
, const PUNICODE_STRING
, ULONG
,
97 ULONG
, const PVOID
, ULONG
);
98 static NTSTATUS (WINAPI
* pNtQueryValueKey
)( HANDLE
,const UNICODE_STRING
*,KEY_VALUE_INFORMATION_CLASS
,
99 void *,DWORD
,DWORD
* );
100 static NTSTATUS (WINAPI
* pRtlFormatCurrentUserKeyPath
)(PUNICODE_STRING
);
101 static NTSTATUS (WINAPI
* pRtlCreateUnicodeString
)( PUNICODE_STRING
, LPCWSTR
);
102 static NTSTATUS (WINAPI
* pRtlReAllocateHeap
)(IN PVOID
, IN ULONG
, IN PVOID
, IN ULONG
);
103 static NTSTATUS (WINAPI
* pRtlAppendUnicodeToString
)(PUNICODE_STRING
, PCWSTR
);
104 static NTSTATUS (WINAPI
* pRtlUnicodeStringToAnsiString
)(PSTRING
, PUNICODE_STRING
, BOOL
);
105 static NTSTATUS (WINAPI
* pRtlFreeHeap
)(PVOID
, ULONG
, PVOID
);
106 static NTSTATUS (WINAPI
* pRtlAllocateHeap
)(PVOID
,ULONG
,ULONG
);
107 static NTSTATUS (WINAPI
* pRtlZeroMemory
)(PVOID
, ULONG
);
109 static HMODULE hntdll
= 0;
110 static int CurrentTest
= 0;
111 static UNICODE_STRING winetestpath
;
113 #define NTDLL_GET_PROC(func) \
114 p ## func = (void*)GetProcAddress(hntdll, #func); \
116 trace("GetProcAddress(%s) failed\n", #func); \
117 FreeLibrary(hntdll); \
121 static BOOL
InitFunctionPtrs(void)
123 hntdll
= LoadLibraryA("ntdll.dll");
125 trace("Could not load ntdll.dll\n");
130 NTDLL_GET_PROC(RtlCreateUnicodeStringFromAsciiz
)
131 NTDLL_GET_PROC(RtlCreateUnicodeString
)
132 NTDLL_GET_PROC(RtlFreeUnicodeString
)
133 NTDLL_GET_PROC(NtDeleteValueKey
)
134 NTDLL_GET_PROC(RtlQueryRegistryValues
)
135 NTDLL_GET_PROC(RtlCheckRegistryKey
)
136 NTDLL_GET_PROC(RtlOpenCurrentUser
)
137 NTDLL_GET_PROC(NtClose
)
138 NTDLL_GET_PROC(NtDeleteValueKey
)
139 NTDLL_GET_PROC(NtCreateKey
)
140 NTDLL_GET_PROC(NtDeleteKey
)
141 NTDLL_GET_PROC(NtSetValueKey
)
142 NTDLL_GET_PROC(NtQueryValueKey
)
143 NTDLL_GET_PROC(NtOpenKey
)
144 NTDLL_GET_PROC(RtlFormatCurrentUserKeyPath
)
145 NTDLL_GET_PROC(RtlReAllocateHeap
)
146 NTDLL_GET_PROC(RtlAppendUnicodeToString
)
147 NTDLL_GET_PROC(RtlUnicodeStringToAnsiString
)
148 NTDLL_GET_PROC(RtlFreeHeap
)
149 NTDLL_GET_PROC(RtlAllocateHeap
)
150 NTDLL_GET_PROC(RtlZeroMemory
)
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
;
162 int ValueNameLength
= 0;
163 trace("**Test %d**\n", CurrentTest
);
167 ValueNameLength
= lstrlenW(ValueName
);
169 ValName
= (LPSTR
)pRtlAllocateHeap(GetProcessHeap(), 0, ValueNameLength
);
170 WideCharToMultiByte(0, 0, ValueName
, ValueNameLength
+1,ValName
, ValueNameLength
, 0, 0);
172 trace("ValueName: %s\n", ValName
);
175 trace("ValueName: (null)\n");
177 if( ValueType
== REG_SZ
||
178 ValueType
== REG_MULTI_SZ
||
179 ValueType
== REG_EXPAND_SZ
)
181 ValData
= (LPSTR
)pRtlAllocateHeap(GetProcessHeap(), 0, ValueLength
);
182 WideCharToMultiByte(0, 0, ValueData
, ValueLength
, ValData
, ValueLength
, 0, 0);
188 trace("ValueType: REG_NONE\n");
189 trace("ValueData: %d\n", (int)ValueData
);
193 trace("ValueType: REG_BINARY\n");
194 trace("ValueData: %d\n", *(unsigned int *)ValueData
);
198 trace("ValueType: REG_SZ\n");
199 trace("ValueData: %s\n", ValData
);
203 trace("ValueType: REG_MULTI_SZ\n");
204 trace("ValueData: %s", (char*)ValData
);
208 trace("ValueType: REG_EXPAND_SZ\n");
209 trace("ValueData: %s\n", (char*)ValData
);
213 trace("ValueType: REG_DWORD\n");
214 trace("ValueData: %d\n", *(unsigned int *)ValueData
);
217 trace("ValueLength: %d\n", (int)ValueLength
);
220 ok(1, "\n"); /*checks that QueryRoutine is called*/
222 ok(!1, "Invalid Test Specified!\n");
227 pRtlFreeHeap(GetProcessHeap(), 0, ValName
);
230 pRtlFreeHeap(GetProcessHeap(), 0, ValData
);
235 static void test_RtlQueryRegistryValues(void)
239 ******************************
241 ******************************
242 *RTL_QUERY_REGISTRY_SUBKEY * Name is the name of a subkey relative to Path
243 *RTL_QUERY_REGISTRY_TOPKEY * Resets location to original RelativeTo and Path
244 *RTL_QUERY_REGISTRY_REQUIRED * Key required. returns STATUS_OBJECT_NAME_NOT_FOUND if not present
245 *RTL_QUERY_REGISTRY_NOVALUE * We just want a call-back
246 *RTL_QUERY_REGISTRY_NOEXPAND * Don't expand the variables!
247 *RTL_QUERY_REGISTRY_DIRECT * Results of query will be stored in EntryContext(QueryRoutine ignored)
248 *RTL_QUERY_REGISTRY_DELETE * Delete value key after query
249 ******************************
252 **Test layout(numbered according to CurrentTest value)**
253 0)NOVALUE Just make sure call-back works
254 1)Null Name See if QueryRoutine is called for every value in current key
255 2)SUBKEY See if we can use SUBKEY to change the current path on the fly
256 3)REQUIRED Test for value that's not there
257 4)NOEXPAND See if it will return multiple strings(no expand should split strings up)
258 5)DIRECT Make it store data directly in EntryContext and not call QueryRoutine
259 6)DefaultType Test return values when key isn't present
260 7)DefaultValue Test Default Value returned with key isn't present(and no REQUIRED flag set)
261 8)DefaultLength Test Default Length with DefaultType = REG_SZ
262 9)DefaultLength Test Default Length with DefaultType = REG_MULTI_SZ
263 10)DefaultLength Test Default Length with DefaultType = REG_EXPAND_SZ
264 11)DefaultData Test whether DefaultData is used while DefaltType = REG_NONE(shouldn't be)
265 12)Delete Try to delete value key
271 PRTL_QUERY_REGISTRY_TABLE QueryTable
= NULL
;
272 RelativeTo
= RTL_REGISTRY_ABSOLUTE
;/*Only using absolute - no need to test all relativeto variables*/
274 QueryTable
= (PRTL_QUERY_REGISTRY_TABLE
)pRtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_QUERY_REGISTRY_TABLE
)*26);
276 pRtlZeroMemory( QueryTable
, sizeof(RTL_QUERY_REGISTRY_TABLE
) * 26);
278 QueryTable
[0].QueryRoutine
= QueryRoutine
;
279 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_NOVALUE
;
280 QueryTable
[0].Name
= NULL
;
281 QueryTable
[0].EntryContext
= NULL
;
282 QueryTable
[0].DefaultType
= REG_BINARY
;
283 QueryTable
[0].DefaultData
= NULL
;
284 QueryTable
[0].DefaultLength
= 100;
286 QueryTable
[1].QueryRoutine
= QueryRoutine
;
287 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DELETE
;
288 QueryTable
[1].Name
= L
"multisztest";
289 QueryTable
[1].EntryContext
= 0;
290 QueryTable
[1].DefaultType
= REG_NONE
;
291 QueryTable
[1].DefaultData
= NULL
;
292 QueryTable
[1].DefaultLength
= 0;
294 QueryTable
[2].QueryRoutine
= QueryRoutine
;
295 QueryTable
[2].Flags
= 0;
296 QueryTable
[2].Name
= NULL
;
297 QueryTable
[2].EntryContext
= 0;
298 QueryTable
[2].DefaultType
= REG_NONE
;
299 QueryTable
[2].DefaultData
= NULL
;
300 QueryTable
[2].DefaultLength
= 0;
302 status
= pRtlQueryRegistryValues(RelativeTo
, winetestpath
.Buffer
, QueryTable
, 0, 0);
303 ok(status
== STATUS_SUCCESS
, "RtlQueryRegistryValues return: 0x%08lx\n", status
);
305 pRtlFreeHeap(GetProcessHeap(), 0, QueryTable
);
308 static void test_NtCreateKey(void)
311 OBJECT_ATTRIBUTES attr
;
313 ACCESS_MASK am
= GENERIC_ALL
;
316 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
317 status
= pNtCreateKey(&key
, am
, &attr
, 0, 0, 0, 0);
318 ok(status
== STATUS_SUCCESS
, "NtCreateKey Failed: 0x%08lx\n", status
);
323 static void test_NtSetValueKey(void)
327 OBJECT_ATTRIBUTES attr
;
328 ACCESS_MASK am
= KEY_WRITE
;
329 UNICODE_STRING ValName
;
330 UNICODE_STRING ValNameMultiSz
;
332 static const WCHAR DataMultiSz
[] = {'T','e','s','t','V','a','l','u','e','1',0,
333 'T','e','s','t','V','a','l','u','e','2',0,
334 'T','e','s','t','V','a','l','u','e','3',0,0,
335 'T','e','s','t','V','a','l','u','e','5',0,0,0};
337 pRtlCreateUnicodeStringFromAsciiz(&ValName
, "deletetest");
338 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
339 status
= pNtOpenKey(&key
, am
, &attr
);
340 ok(status
== STATUS_SUCCESS
, "NtOpenKey Failed: 0x%08lx\n", status
);
342 status
= pNtSetValueKey(key
, &ValName
, 0, REG_DWORD
, &data
, sizeof(data
));
343 ok(status
== STATUS_SUCCESS
, "NtSetValueKey Failed: 0x%08lx\n", status
);
345 pRtlFreeUnicodeString(&ValName
);
347 pRtlCreateUnicodeStringFromAsciiz(&ValNameMultiSz
, "multisztest");
349 status
= pNtSetValueKey(key
, &ValNameMultiSz
, 0, REG_MULTI_SZ
, (PVOID
)DataMultiSz
, sizeof(DataMultiSz
));
350 ok(status
== STATUS_SUCCESS
, "NtSetValueKey Failed: 0x%08lx\n", status
);
352 pRtlFreeUnicodeString(&ValNameMultiSz
);
357 static void test_RtlOpenCurrentUser(void)
361 status
=pRtlOpenCurrentUser(KEY_READ
, &handle
);
362 ok(status
== STATUS_SUCCESS
, "RtlOpenCurrentUser Failed: 0x%08lx\n", status
);
366 static void test_RtlCheckRegistryKey(void)
370 status
= pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE
, winetestpath
.Buffer
);
371 ok(status
== STATUS_SUCCESS
, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08lx\n", status
);
373 status
= pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE
| RTL_REGISTRY_OPTIONAL
), winetestpath
.Buffer
);
374 ok(status
== STATUS_SUCCESS
, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE and RTL_REGISTRY_OPTIONAL: 0x%08lx\n", status
);
377 static void test_RtlQueryRegistryDelete(void)
381 OBJECT_ATTRIBUTES attr
;
382 UNICODE_STRING ValNameMultiSz
;
386 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
387 status
= pNtOpenKey(&key
, KEY_READ
, &attr
);
388 ok(status
== STATUS_SUCCESS
, "NtOpenKey Failed: 0x%08lx\n", status
);
390 pRtlCreateUnicodeStringFromAsciiz(&ValNameMultiSz
, "multisztest");
392 status
= pNtQueryValueKey(key
, &ValNameMultiSz
, 0, (void*)sBuf
, sizeof(sBuf
), &ValueSize
);
393 ok(status
== STATUS_OBJECT_NAME_NOT_FOUND
, "NtOpenKey returns: 0x%08lx instead of STATUS_OBJECT_NAME_NOT_FOUND\n", status
);
395 pRtlFreeUnicodeString(&ValNameMultiSz
);
400 static void test_NtDeleteKey(void)
404 OBJECT_ATTRIBUTES attr
;
405 ACCESS_MASK am
= KEY_ALL_ACCESS
;
407 InitializeObjectAttributes(&attr
, &winetestpath
, 0, 0, 0);
408 status
= pNtOpenKey(&hkey
, am
, &attr
);
410 status
= pNtDeleteKey(hkey
);
411 ok(status
== STATUS_SUCCESS
, "NtDeleteKey Failed: 0x%08lx\n", status
);
418 static const WCHAR winetest
[] = {'\\','W','i','n','e','T','e','s','t','\\',0};
419 if(!InitFunctionPtrs())
421 pRtlFormatCurrentUserKeyPath(&winetestpath
);
422 winetestpath
.Buffer
= (PWSTR
)pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, winetestpath
.Buffer
,
423 winetestpath
.MaximumLength
+ sizeof(winetest
)*sizeof(WCHAR
));
424 winetestpath
.MaximumLength
= winetestpath
.MaximumLength
+ sizeof(winetest
)*sizeof(WCHAR
);
426 pRtlAppendUnicodeToString(&winetestpath
, winetest
);
429 test_NtSetValueKey();
430 test_RtlCheckRegistryKey();
431 test_RtlOpenCurrentUser();
432 test_RtlQueryRegistryValues();
433 test_RtlQueryRegistryDelete();
436 pRtlFreeUnicodeString(&winetestpath
);