2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for the HKEY_CLASSES_ROOT key
5 * PROGRAMMER: Jérôme Gardou <jerome.gardou@reactos.org>
10 #define WIN32_NO_STATUS
12 #include <ndk/rtlfuncs.h>
13 #include <ndk/cmfuncs.h>
14 #include <ndk/cmtypes.h>
16 #define IS_HKCR(hk) (((UINT_PTR)hk & 3) == 2)
18 /* HKCU and HKLM system paths */
19 static UNICODE_STRING HKLM_ClassesPath
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\Software\\Classes");
20 static UNICODE_STRING HKCU_ClassesPath
;
24 DeleteSubKey(HKEY hKey
, LPWSTR Root
, LPWSTR SubKey
)
29 ErrorCode
= RegOpenKeyExW(
35 ok_dec(ErrorCode
, ERROR_SUCCESS
);
36 ErrorCode
= RegDeleteKeyW(RootKey
, SubKey
);
44 GetKeyName(HKEY hKey
, PUNICODE_STRING KeyName
)
46 UNICODE_STRING InfoName
;
47 PKEY_NAME_INFORMATION NameInformation
;
53 Status
= NtQueryKey(hKey
, KeyNameInformation
, NULL
, 0, &InfoLength
);
54 ok_ntstatus(Status
, STATUS_BUFFER_TOO_SMALL
);
57 NameInformation
= RtlAllocateHeap(RtlGetProcessHeap(), 0, InfoLength
);
58 ok(NameInformation
!= NULL
, "\n");
60 Status
= NtQueryKey(hKey
, KeyNameInformation
, NameInformation
, InfoLength
, &InfoLength
);
61 ok_ntstatus(Status
, STATUS_SUCCESS
);
63 RtlInitUnicodeString(&InfoName
, NameInformation
->Name
);
64 InfoName
.Length
= NameInformation
->NameLength
;
66 RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &InfoName
, KeyName
);
68 RtlFreeHeap(RtlGetProcessHeap(), 0, NameInformation
);
71 static void _test_key_deleted(HKEY hKey
, BOOL Deleted
, ULONG LineNumber
)
73 DWORD ErrorCode
= RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
75 ok_(__FILE__
, LineNumber
)(ErrorCode
== ERROR_KEY_DELETED
, "\n");
77 ok_(__FILE__
, LineNumber
)(ErrorCode
== ERROR_SUCCESS
, "\n");
79 #define ok_key_deleted(hKey) _test_key_deleted(hKey, TRUE, __LINE__)
80 #define ok_key_not_deleted(hKey) _test_key_deleted(hKey, FALSE, __LINE__)
82 static void _test_key_name(HKEY hKey
, PUNICODE_STRING Prefix
, LPCWSTR Name
, ULONG LineNumber
)
84 UNICODE_STRING ExpectedName
, KeyName
;
87 ExpectedName
.Length
= 0;
88 ExpectedName
.MaximumLength
= sizeof(Buffer
);
89 ExpectedName
.Buffer
= Buffer
;
91 RtlAppendUnicodeStringToString(&ExpectedName
, Prefix
);
92 RtlAppendUnicodeToString(&ExpectedName
, L
"\\");
93 RtlAppendUnicodeToString(&ExpectedName
, Name
);
95 GetKeyName(hKey
, &KeyName
);
97 ok_(__FILE__
, LineNumber
)(RtlCompareUnicodeString(&KeyName
, &ExpectedName
, TRUE
) == 0,
98 "Key name is %.*S, expected %.*S\n",
99 KeyName
.Length
, KeyName
.Buffer
,
100 ExpectedName
.Length
, ExpectedName
.Buffer
);
102 RtlFreeUnicodeString(&KeyName
);
105 #define ok_key_name(hKey, Prefix, Name) _test_key_name(hKey, Prefix, Name, __LINE__)
109 Test_CreateOpenKey(void)
111 HKEY MachineKey
, UserKey
, ClassesRootKey
;
114 /* First create a subkey in HKLM */
115 ErrorCode
= RegCreateKeyExW(
117 L
"Software\\Classes\\Apitest_HKLM_Only",
125 ok_dec(ErrorCode
, ERROR_SUCCESS
);
126 ok(!IS_HKCR(MachineKey
), "\n");
128 /* Open it in HKCR */
129 ErrorCode
= RegOpenKeyExW(
131 L
"Apitest_HKLM_Only",
135 ok_dec(ErrorCode
, ERROR_SUCCESS
);
136 ok(IS_HKCR(ClassesRootKey
), "\n");
137 ok_key_name(ClassesRootKey
, &HKLM_ClassesPath
, L
"Apitest_HKLM_Only");
139 /* Try opening it in HKCU */
140 UserKey
= (HKEY
)0xCAFEF00D;
141 ErrorCode
= RegOpenKeyExW(
143 L
"Software\\Classes\\Apitest_HKLM_Only",
147 ok_dec(ErrorCode
, ERROR_FILE_NOT_FOUND
);
148 ok_hdl(UserKey
, NULL
);
151 RegCloseKey(ClassesRootKey
);
152 RegCloseKey(MachineKey
);
153 ErrorCode
= DeleteSubKey(HKEY_LOCAL_MACHINE
, L
"Software\\Classes", L
"Apitest_HKLM_Only");
154 ok_dec(ErrorCode
, ERROR_SUCCESS
);
156 /* Try creating in HKCR */
157 ErrorCode
= RegCreateKeyExW(
167 ok_dec(ErrorCode
, ERROR_SUCCESS
);
168 ok(IS_HKCR(ClassesRootKey
), "\n");
169 ok_key_name(ClassesRootKey
, &HKLM_ClassesPath
, L
"Apitest_HKCR");
171 /* It should be present in HKLM */
172 ErrorCode
= RegOpenKeyExW(
174 L
"Software\\Classes\\Apitest_HKCR",
178 ok_dec(ErrorCode
, ERROR_SUCCESS
);
179 ok(!IS_HKCR(MachineKey
), "\n");
181 /* But not in HKCU */
182 UserKey
= (HKEY
)0xCAFEF00D;
183 ErrorCode
= RegOpenKeyExW(
185 L
"Software\\Classes\\Apitest_HKCR",
189 ok_dec(ErrorCode
, ERROR_FILE_NOT_FOUND
);
190 ok_hdl(UserKey
, NULL
);
192 /* This must delete the one in HKLM */
193 ErrorCode
= RegDeleteKeyW(HKEY_CLASSES_ROOT
, L
"Apitest_HKCR");
194 ok_dec(ErrorCode
, ERROR_SUCCESS
);
195 ok_key_deleted(ClassesRootKey
);
196 ok_key_deleted(MachineKey
);
197 RegCloseKey(ClassesRootKey
);
198 RegCloseKey(MachineKey
);
200 /* Test that it is really not present anymore */
201 MachineKey
= (HKEY
)0xCAFEF00D;
202 ErrorCode
= RegOpenKeyExW(
204 L
"Software\\Classes\\Apitest_HKCR",
208 ok_dec(ErrorCode
, ERROR_FILE_NOT_FOUND
);
209 ok_hdl(MachineKey
, NULL
);
211 /* Try creating in HKCU */
212 ErrorCode
= RegCreateKeyExW(
214 L
"Software\\Classes\\Apitest_HKCU",
222 ok_dec(ErrorCode
, ERROR_SUCCESS
);
223 ok(!IS_HKCR(UserKey
), "\n");
225 /* Try opening it in HKCR */
226 ErrorCode
= RegOpenKeyExW(
232 ok_dec(ErrorCode
, ERROR_SUCCESS
);
233 ok(IS_HKCR(ClassesRootKey
), "\n");
234 ok_key_name(ClassesRootKey
, &HKCU_ClassesPath
, L
"Apitest_HKCU");
237 ErrorCode
= RegOpenKeyExW(
239 L
"Software\\Classes\\Apitest_HKCU",
243 ok_dec(ErrorCode
, ERROR_FILE_NOT_FOUND
);
244 ok_hdl(MachineKey
, NULL
);
246 ErrorCode
= RegDeleteKeyW(HKEY_CLASSES_ROOT
, L
"Apitest_HKCU");
247 ok_dec(ErrorCode
, ERROR_SUCCESS
);
248 ok_key_deleted(ClassesRootKey
);
249 ok_key_deleted(UserKey
);
250 RegCloseKey(ClassesRootKey
);
251 RegCloseKey(UserKey
);
253 /* Test that it is really not present anymore */
254 UserKey
= (HKEY
)0xCAFEF00D;
255 ErrorCode
= RegOpenKeyExW(
257 L
"Software\\Classes\\Apitest_HKCU",
261 ok_dec(ErrorCode
, ERROR_FILE_NOT_FOUND
);
262 ok_hdl(UserKey
, NULL
);
264 /* Try creating in both HKLM and HKCU */
265 ErrorCode
= RegCreateKeyExW(
267 L
"Software\\Classes\\Apitest_HKLM_HKCU",
275 ok_dec(ErrorCode
, ERROR_SUCCESS
);
276 ok(!IS_HKCR(UserKey
), "\n");
278 ErrorCode
= RegCreateKeyExW(
280 L
"Software\\Classes\\Apitest_HKLM_HKCU",
288 ok_dec(ErrorCode
, ERROR_SUCCESS
);
289 ok(!IS_HKCR(MachineKey
), "\n");
291 /* Open it in HKCR */
292 ErrorCode
= RegOpenKeyExW(
294 L
"Apitest_HKLM_HKCU",
298 ok_dec(ErrorCode
, ERROR_SUCCESS
);
299 ok(IS_HKCR(ClassesRootKey
), "\n");
300 /* Verify it has opened the HKCU one */
301 ok_key_name(ClassesRootKey
, &HKCU_ClassesPath
, L
"Apitest_HKLM_HKCU");
303 /* Deleting it from HKCR first deletes the one in HKCU */
304 ErrorCode
= RegDeleteKeyW(HKEY_CLASSES_ROOT
, L
"Apitest_HKLM_HKCU");
305 ok_dec(ErrorCode
, ERROR_SUCCESS
);
306 ok_key_deleted(UserKey
);
307 ok_key_deleted(ClassesRootKey
);
308 ok_key_not_deleted(MachineKey
);
310 RegCloseKey(UserKey
);
311 RegCloseKey(ClassesRootKey
);
313 /* This deletes it from HKLM this time */
314 ErrorCode
= RegDeleteKeyW(HKEY_CLASSES_ROOT
, L
"Apitest_HKLM_HKCU");
315 ok_dec(ErrorCode
, ERROR_SUCCESS
);
316 ok_key_deleted(MachineKey
);
317 RegCloseKey(MachineKey
);
328 ErrorCode
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, L
"CLSID", 0, KEY_READ
, &KeyHandle
);
329 ok_dec(ErrorCode
, ERROR_SUCCESS
);
330 ok(IS_HKCR(KeyHandle
), "\n");
331 ok_key_name(KeyHandle
, &HKLM_ClassesPath
, L
"CLSID");
333 RegCloseKey(KeyHandle
);
338 Test_DuplicateHandle(void)
340 HKEY KeyHandle
, DupHandle
;
344 ErrorCode
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, L
"CLSID", 0, KEY_READ
, &KeyHandle
);
345 ok_dec(ErrorCode
, ERROR_SUCCESS
);
346 ok(IS_HKCR(KeyHandle
), "\n");
348 Duplicated
= DuplicateHandle(GetCurrentProcess(), KeyHandle
, GetCurrentProcess(), (PHANDLE
)&DupHandle
, 0, 0, DUPLICATE_SAME_ACCESS
);
349 ok(Duplicated
, "\n");
350 ok(DupHandle
!= NULL
, "\n");
351 ok(!IS_HKCR(DupHandle
), "\n");
353 ok_key_name(DupHandle
, &HKLM_ClassesPath
, L
"CLSID");
355 RegCloseKey(KeyHandle
);
356 RegCloseKey(DupHandle
);
359 START_TEST(HKEY_CLASSES_ROOT
)
364 /* Get HKCU real key name */
365 ErrorCode
= RegOpenKeyExW(
367 L
"Software\\Classes",
371 ok_dec(ErrorCode
, ERROR_SUCCESS
);
372 GetKeyName(UserKey
, &HKCU_ClassesPath
);
373 RegCloseKey(UserKey
);
375 Test_CreateOpenKey();
376 Test_DuplicateHandle();