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
, MachineSubKey
;
112 HKEY UserKey
, UserSubKey
;
113 HKEY ClassesRootKey
, ClassesRootSubKey
;
116 /* First create a subkey in HKLM */
117 ErrorCode
= RegCreateKeyExW(
119 L
"Software\\Classes\\Apitest_HKLM",
128 if (ErrorCode
== ERROR_ACCESS_DENIED
)
130 win_skip("Please run those tests with Administrator rights\n");
134 ok_dec(ErrorCode
, ERROR_SUCCESS
);
135 ok(!IS_HKCR(MachineKey
), "\n");
137 /* Open it in HKCR */
138 ErrorCode
= RegOpenKeyExW(
144 ok_dec(ErrorCode
, ERROR_SUCCESS
);
145 ok(IS_HKCR(ClassesRootKey
), "\n");
146 ok_key_name(ClassesRootKey
, &HKLM_ClassesPath
, L
"Apitest_HKLM");
148 /* Try opening it in HKCU */
149 UserKey
= (HKEY
)0xCAFEF00D;
150 ErrorCode
= RegOpenKeyExW(
152 L
"Software\\Classes\\Apitest_HKLM",
156 ok_dec(ErrorCode
, ERROR_FILE_NOT_FOUND
);
157 ok_hdl(UserKey
, NULL
);
160 RegCloseKey(ClassesRootKey
);
161 RegCloseKey(MachineKey
);
162 ErrorCode
= DeleteSubKey(HKEY_LOCAL_MACHINE
, L
"Software\\Classes", L
"Apitest_HKLM");
163 ok_dec(ErrorCode
, ERROR_SUCCESS
);
165 /* Try creating in HKCR */
166 ErrorCode
= RegCreateKeyExW(
176 ok_dec(ErrorCode
, ERROR_SUCCESS
);
177 ok(IS_HKCR(ClassesRootKey
), "\n");
178 ok_key_name(ClassesRootKey
, &HKLM_ClassesPath
, L
"Apitest_HKCR");
180 /* It should be present in HKLM */
181 ErrorCode
= RegOpenKeyExW(
183 L
"Software\\Classes\\Apitest_HKCR",
187 ok_dec(ErrorCode
, ERROR_SUCCESS
);
188 ok(!IS_HKCR(MachineKey
), "\n");
190 /* But not in HKCU */
191 UserKey
= (HKEY
)0xCAFEF00D;
192 ErrorCode
= RegOpenKeyExW(
194 L
"Software\\Classes\\Apitest_HKCR",
198 ok_dec(ErrorCode
, ERROR_FILE_NOT_FOUND
);
199 ok_hdl(UserKey
, NULL
);
201 /* This must delete the one in HKLM */
202 ErrorCode
= RegDeleteKeyW(HKEY_CLASSES_ROOT
, L
"Apitest_HKCR");
203 ok_dec(ErrorCode
, ERROR_SUCCESS
);
204 ok_key_deleted(ClassesRootKey
);
205 ok_key_deleted(MachineKey
);
206 RegCloseKey(ClassesRootKey
);
207 RegCloseKey(MachineKey
);
209 /* Test that it is really not present anymore */
210 MachineKey
= (HKEY
)0xCAFEF00D;
211 ErrorCode
= RegOpenKeyExW(
213 L
"Software\\Classes\\Apitest_HKCR",
217 ok_dec(ErrorCode
, ERROR_FILE_NOT_FOUND
);
218 ok_hdl(MachineKey
, NULL
);
220 /* Try creating in HKCU */
221 ErrorCode
= RegCreateKeyExW(
223 L
"Software\\Classes\\Apitest_HKCU",
231 ok_dec(ErrorCode
, ERROR_SUCCESS
);
232 ok(!IS_HKCR(UserKey
), "\n");
234 /* Try opening it in HKCR */
235 ErrorCode
= RegOpenKeyExW(
241 ok_dec(ErrorCode
, ERROR_SUCCESS
);
242 ok(IS_HKCR(ClassesRootKey
), "\n");
243 ok_key_name(ClassesRootKey
, &HKCU_ClassesPath
, L
"Apitest_HKCU");
246 ErrorCode
= RegOpenKeyExW(
248 L
"Software\\Classes\\Apitest_HKCU",
252 ok_dec(ErrorCode
, ERROR_FILE_NOT_FOUND
);
253 ok_hdl(MachineKey
, NULL
);
255 ErrorCode
= RegDeleteKeyW(HKEY_CLASSES_ROOT
, L
"Apitest_HKCU");
256 ok_dec(ErrorCode
, ERROR_SUCCESS
);
257 ok_key_deleted(ClassesRootKey
);
258 ok_key_deleted(UserKey
);
259 RegCloseKey(ClassesRootKey
);
260 RegCloseKey(UserKey
);
262 /* Test that it is really not present anymore */
263 UserKey
= (HKEY
)0xCAFEF00D;
264 ErrorCode
= RegOpenKeyExW(
266 L
"Software\\Classes\\Apitest_HKCU",
270 ok_dec(ErrorCode
, ERROR_FILE_NOT_FOUND
);
271 ok_hdl(UserKey
, NULL
);
273 /* Try creating in both HKLM and HKCU */
274 ErrorCode
= RegCreateKeyExW(
276 L
"Software\\Classes\\Apitest_HKLM_HKCU",
284 ok_dec(ErrorCode
, ERROR_SUCCESS
);
285 ok(!IS_HKCR(UserKey
), "\n");
287 ErrorCode
= RegCreateKeyExW(
289 L
"Software\\Classes\\Apitest_HKLM_HKCU",
297 ok_dec(ErrorCode
, ERROR_SUCCESS
);
298 ok(!IS_HKCR(MachineKey
), "\n");
300 /* Open it in HKCR */
301 ErrorCode
= RegOpenKeyExW(
303 L
"Apitest_HKLM_HKCU",
307 ok_dec(ErrorCode
, ERROR_SUCCESS
);
308 ok(IS_HKCR(ClassesRootKey
), "\n");
309 /* Verify it has opened the HKCU one */
310 ok_key_name(ClassesRootKey
, &HKCU_ClassesPath
, L
"Apitest_HKLM_HKCU");
312 /* Deleting it from HKCR first deletes the one in HKCU */
313 ErrorCode
= RegDeleteKeyW(HKEY_CLASSES_ROOT
, L
"Apitest_HKLM_HKCU");
314 ok_dec(ErrorCode
, ERROR_SUCCESS
);
315 ok_key_deleted(UserKey
);
316 ok_key_deleted(ClassesRootKey
);
317 ok_key_not_deleted(MachineKey
);
319 RegCloseKey(UserKey
);
320 RegCloseKey(ClassesRootKey
);
322 /* This deletes it from HKLM this time */
323 ErrorCode
= RegDeleteKeyW(HKEY_CLASSES_ROOT
, L
"Apitest_HKLM_HKCU");
324 ok_dec(ErrorCode
, ERROR_SUCCESS
);
325 ok_key_deleted(MachineKey
);
326 RegCloseKey(MachineKey
);
328 /* See what happens with subkeys */
329 ErrorCode
= RegCreateKeyExW(
331 L
"Software\\Classes\\Apitest_HKLM",
339 ok_dec(ErrorCode
, ERROR_SUCCESS
);
340 ok(!IS_HKCR(MachineKey
), "\n");
342 /* Open it in HKCR */
343 ErrorCode
= RegOpenKeyExW(
349 ok_dec(ErrorCode
, ERROR_SUCCESS
);
350 ok(IS_HKCR(ClassesRootKey
), "\n");
351 ok_key_name(ClassesRootKey
, &HKLM_ClassesPath
, L
"Apitest_HKLM");
353 /* Create a corresponding subkey in HKCU */
354 ErrorCode
= RegCreateKeyExW(
356 L
"Software\\Classes\\Apitest_HKLM\\HKCU_Subkey",
364 ok_dec(ErrorCode
, ERROR_SUCCESS
);
365 ok(!IS_HKCR(UserSubKey
), "\n");
367 /* Open it as an HKCR subkey */
368 ErrorCode
= RegOpenKeyExW(
374 ok_dec(ErrorCode
, ERROR_SUCCESS
);
375 ok(IS_HKCR(ClassesRootSubKey
), "\n");
376 ok_key_name(ClassesRootSubKey
, &HKCU_ClassesPath
, L
"Apitest_HKLM\\HKCU_Subkey");
378 /* This one now exists */
379 ErrorCode
= RegOpenKeyExW(
381 L
"Software\\Classes\\Apitest_HKLM",
385 ok_dec(ErrorCode
, ERROR_SUCCESS
);
386 ok(!IS_HKCR(UserKey
), "\n");
389 ErrorCode
= RegDeleteKeyW(UserKey
, L
"HKCU_Subkey");
390 ok_dec(ErrorCode
, ERROR_SUCCESS
);
391 ok_key_deleted(UserSubKey
);
392 ok_key_deleted(ClassesRootSubKey
);
393 RegCloseKey(UserSubKey
);
394 RegCloseKey(ClassesRootSubKey
);
396 /* See what this deletes */
397 RegDeleteKeyW(HKEY_CLASSES_ROOT
, L
"Apitest_HKLM");
398 ok_key_deleted(UserKey
);
399 RegCloseKey(UserKey
);
400 ok_key_not_deleted(ClassesRootKey
);
401 ok_key_not_deleted(MachineKey
);
404 RegDeleteKeyW(HKEY_CLASSES_ROOT
, L
"Apitest_HKLM");
405 ok_key_deleted(ClassesRootKey
);
406 ok_key_deleted(MachineKey
);
407 RegCloseKey(ClassesRootKey
);
408 RegCloseKey(MachineKey
);
410 /* Same, but with HKCU first */
411 ErrorCode
= RegCreateKeyExW(
413 L
"Software\\Classes\\Apitest_HKCU",
421 ok_dec(ErrorCode
, ERROR_SUCCESS
);
422 ok(!IS_HKCR(UserKey
), "\n");
424 /* Open it in HKCR */
425 ErrorCode
= RegOpenKeyExW(
431 ok_dec(ErrorCode
, ERROR_SUCCESS
);
432 ok(IS_HKCR(ClassesRootKey
), "\n");
433 ok_key_name(ClassesRootKey
, &HKCU_ClassesPath
, L
"Apitest_HKCU");
435 /* Try creating a subkey with this HKCR handle, which points to a subkey in HKCU. */
436 ErrorCode
= RegCreateKeyExW(
446 ok_dec(ErrorCode
, ERROR_SUCCESS
);
447 ok(IS_HKCR(ClassesRootSubKey
), "\n");
448 /* It is in fact created in HKLM */
449 ok_key_name(ClassesRootSubKey
, &HKLM_ClassesPath
, L
"Apitest_HKCU\\HKCR_Subkey");
450 /* Let's see if we can delete it */
451 RegDeleteKeyW(ClassesRootKey
, L
"HKCR_Subkey");
452 ok_key_deleted(ClassesRootSubKey
);
453 RegCloseKey(ClassesRootSubKey
);
455 /* Create a corresponding subkey in HKLM */
456 ErrorCode
= RegCreateKeyExW(
458 L
"Software\\Classes\\Apitest_HKCU\\HKLM_Subkey",
466 ok_dec(ErrorCode
, ERROR_SUCCESS
);
467 ok(!IS_HKCR(MachineSubKey
), "\n");
469 /* Open it from the HKCR handle (which is still pointing to HKCU) */
470 ok_key_name(ClassesRootKey
, &HKCU_ClassesPath
, L
"Apitest_HKCU");
471 ErrorCode
= RegOpenKeyExW(
477 ok_dec(ErrorCode
, ERROR_SUCCESS
);
478 ok(IS_HKCR(ClassesRootSubKey
), "\n");
479 ok_key_name(ClassesRootSubKey
, &HKLM_ClassesPath
, L
"Apitest_HKCU\\HKLM_Subkey");
481 /* This one now exists */
482 ErrorCode
= RegOpenKeyExW(
484 L
"Software\\Classes\\Apitest_HKCU",
488 ok_dec(ErrorCode
, ERROR_SUCCESS
);
489 ok(!IS_HKCR(MachineKey
), "\n");
492 ErrorCode
= RegDeleteKeyW(MachineKey
, L
"HKLM_Subkey");
493 ok_dec(ErrorCode
, ERROR_SUCCESS
);
494 ok_key_deleted(MachineSubKey
);
495 ok_key_deleted(ClassesRootSubKey
);
497 /* Rery creating a subkey with this HKCR handle (which points to HKCU).
498 * It should now be created in the HKLM view. */
499 ok_key_name(ClassesRootKey
, &HKCU_ClassesPath
, L
"Apitest_HKCU");
500 ErrorCode
= RegCreateKeyExW(
510 ok_dec(ErrorCode
, ERROR_SUCCESS
);
511 ok(IS_HKCR(ClassesRootSubKey
), "\n");
512 ok_key_name(ClassesRootSubKey
, &HKLM_ClassesPath
, L
"Apitest_HKCU\\HKCR_Subkey");
513 RegDeleteKeyW(MachineKey
, L
"HKCR_Subkey");
514 ok_key_deleted(ClassesRootSubKey
);
515 RegCloseKey(ClassesRootSubKey
);
517 RegCloseKey(MachineSubKey
);
518 RegCloseKey(ClassesRootSubKey
);
520 /* See what this deletes */
521 RegDeleteKeyW(HKEY_CLASSES_ROOT
, L
"Apitest_HKCU");
522 ok_key_deleted(UserKey
);
523 RegCloseKey(UserKey
);
524 ok_key_deleted(ClassesRootKey
);
525 RegCloseKey(UserKey
);
526 ok_key_not_deleted(MachineKey
);
529 RegDeleteKeyW(HKEY_CLASSES_ROOT
, L
"Apitest_HKCU");
530 ok_key_deleted(MachineKey
);
531 RegCloseKey(MachineKey
);
536 Test_DuplicateHandle(void)
538 HKEY KeyHandle
, DupHandle
;
542 ErrorCode
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, L
"CLSID", 0, KEY_READ
, &KeyHandle
);
543 ok_dec(ErrorCode
, ERROR_SUCCESS
);
544 ok(IS_HKCR(KeyHandle
), "\n");
546 Duplicated
= DuplicateHandle(GetCurrentProcess(), KeyHandle
, GetCurrentProcess(), (PHANDLE
)&DupHandle
, 0, 0, DUPLICATE_SAME_ACCESS
);
547 ok(Duplicated
, "\n");
548 ok(DupHandle
!= NULL
, "\n");
549 ok(!IS_HKCR(DupHandle
), "\n");
551 RegCloseKey(KeyHandle
);
552 RegCloseKey(DupHandle
);
555 START_TEST(HKEY_CLASSES_ROOT
)
560 /* Get HKCU real key name */
561 ErrorCode
= RegOpenKeyExW(
563 L
"Software\\Classes",
567 ok_dec(ErrorCode
, ERROR_SUCCESS
);
568 GetKeyName(UserKey
, &HKCU_ClassesPath
);
569 RegCloseKey(UserKey
);
571 Test_CreateOpenKey();
572 Test_DuplicateHandle();