42329888c8bbbae2cb06558410471b9636f8618b
[reactos.git] / rostests / apitests / advapi32 / HKEY_CLASSES_ROOT.c
1 /*
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>
6 */
7
8 #include <apitest.h>
9
10 #define WIN32_NO_STATUS
11 #include <winreg.h>
12 #include <ndk/rtlfuncs.h>
13 #include <ndk/cmfuncs.h>
14 #include <ndk/cmtypes.h>
15
16 #define IS_HKCR(hk) (((UINT_PTR)hk & 3) == 2)
17
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;
21
22 static
23 LONG
24 DeleteSubKey(HKEY hKey, LPWSTR Root, LPWSTR SubKey)
25 {
26 HKEY RootKey;
27 LONG ErrorCode;
28
29 ErrorCode = RegOpenKeyExW(
30 hKey,
31 Root,
32 0,
33 MAXIMUM_ALLOWED,
34 &RootKey);
35 ok_dec(ErrorCode, ERROR_SUCCESS);
36 ErrorCode = RegDeleteKeyW(RootKey, SubKey);
37 RegCloseKey(RootKey);
38
39 return ErrorCode;
40 }
41
42 static
43 void
44 GetKeyName(HKEY hKey, PUNICODE_STRING KeyName)
45 {
46 UNICODE_STRING InfoName;
47 PKEY_NAME_INFORMATION NameInformation;
48 ULONG InfoLength;
49 NTSTATUS Status;
50
51 /* Get info length */
52 InfoLength = 0;
53 Status = NtQueryKey(hKey, KeyNameInformation, NULL, 0, &InfoLength);
54 ok_ntstatus(Status, STATUS_BUFFER_TOO_SMALL);
55
56 /* Get it for real */
57 NameInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, InfoLength);
58 ok(NameInformation != NULL, "\n");
59
60 Status = NtQueryKey(hKey, KeyNameInformation, NameInformation, InfoLength, &InfoLength);
61 ok_ntstatus(Status, STATUS_SUCCESS);
62
63 RtlInitUnicodeString(&InfoName, NameInformation->Name);
64 InfoName.Length = NameInformation->NameLength;
65
66 RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &InfoName, KeyName);
67
68 RtlFreeHeap(RtlGetProcessHeap(), 0, NameInformation);
69 }
70
71 static void _test_key_deleted(HKEY hKey, BOOL Deleted, ULONG LineNumber)
72 {
73 DWORD ErrorCode = RegQueryInfoKeyW(hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
74 if (Deleted)
75 ok_(__FILE__, LineNumber)(ErrorCode == ERROR_KEY_DELETED, "\n");
76 else
77 ok_(__FILE__, LineNumber)(ErrorCode == ERROR_SUCCESS, "\n");
78 }
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__)
81
82 static void _test_key_name(HKEY hKey, PUNICODE_STRING Prefix, LPCWSTR Name, ULONG LineNumber)
83 {
84 UNICODE_STRING ExpectedName, KeyName;
85 WCHAR Buffer[1024];
86
87 ExpectedName.Length = 0;
88 ExpectedName.MaximumLength = sizeof(Buffer);
89 ExpectedName.Buffer = Buffer;
90
91 RtlAppendUnicodeStringToString(&ExpectedName, Prefix);
92 RtlAppendUnicodeToString(&ExpectedName, L"\\");
93 RtlAppendUnicodeToString(&ExpectedName, Name);
94
95 GetKeyName(hKey, &KeyName);
96
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);
101
102 RtlFreeUnicodeString(&KeyName);
103 }
104
105 #define ok_key_name(hKey, Prefix, Name) _test_key_name(hKey, Prefix, Name, __LINE__)
106
107 static
108 void
109 Test_CreateOpenKey(void)
110 {
111 HKEY MachineKey, MachineSubKey;
112 HKEY UserKey, UserSubKey;
113 HKEY ClassesRootKey, ClassesRootSubKey;
114 DWORD ErrorCode;
115
116 /* First create a subkey in HKLM */
117 ErrorCode = RegCreateKeyExW(
118 HKEY_LOCAL_MACHINE,
119 L"Software\\Classes\\Apitest_HKLM",
120 0,
121 NULL,
122 0,
123 MAXIMUM_ALLOWED,
124 NULL,
125 &MachineKey,
126 NULL);
127
128 if (ErrorCode == ERROR_ACCESS_DENIED)
129 {
130 win_skip("Please run those tests with Administrator rights\n");
131 return;
132 }
133
134 ok_dec(ErrorCode, ERROR_SUCCESS);
135 ok(!IS_HKCR(MachineKey), "\n");
136
137 /* Open it in HKCR */
138 ErrorCode = RegOpenKeyExW(
139 HKEY_CLASSES_ROOT,
140 L"Apitest_HKLM",
141 0,
142 MAXIMUM_ALLOWED,
143 &ClassesRootKey);
144 ok_dec(ErrorCode, ERROR_SUCCESS);
145 ok(IS_HKCR(ClassesRootKey), "\n");
146 ok_key_name(ClassesRootKey, &HKLM_ClassesPath, L"Apitest_HKLM");
147
148 /* Try opening it in HKCU */
149 UserKey = (HKEY)0xCAFEF00D;
150 ErrorCode = RegOpenKeyExW(
151 HKEY_CURRENT_USER,
152 L"Software\\Classes\\Apitest_HKLM",
153 0,
154 MAXIMUM_ALLOWED,
155 &UserKey);
156 ok_dec(ErrorCode, ERROR_FILE_NOT_FOUND);
157 ok_hdl(UserKey, NULL);
158
159 /* Cleanup */
160 RegCloseKey(ClassesRootKey);
161 RegCloseKey(MachineKey);
162 ErrorCode = DeleteSubKey(HKEY_LOCAL_MACHINE, L"Software\\Classes", L"Apitest_HKLM");
163 ok_dec(ErrorCode, ERROR_SUCCESS);
164
165 /* Try creating in HKCR */
166 ErrorCode = RegCreateKeyExW(
167 HKEY_CLASSES_ROOT,
168 L"Apitest_HKCR",
169 0,
170 NULL,
171 0,
172 MAXIMUM_ALLOWED,
173 NULL,
174 &ClassesRootKey,
175 NULL);
176 ok_dec(ErrorCode, ERROR_SUCCESS);
177 ok(IS_HKCR(ClassesRootKey), "\n");
178 ok_key_name(ClassesRootKey, &HKLM_ClassesPath, L"Apitest_HKCR");
179
180 /* It should be present in HKLM */
181 ErrorCode = RegOpenKeyExW(
182 HKEY_LOCAL_MACHINE,
183 L"Software\\Classes\\Apitest_HKCR",
184 0,
185 MAXIMUM_ALLOWED,
186 &MachineKey);
187 ok_dec(ErrorCode, ERROR_SUCCESS);
188 ok(!IS_HKCR(MachineKey), "\n");
189
190 /* But not in HKCU */
191 UserKey = (HKEY)0xCAFEF00D;
192 ErrorCode = RegOpenKeyExW(
193 HKEY_CURRENT_USER,
194 L"Software\\Classes\\Apitest_HKCR",
195 0,
196 MAXIMUM_ALLOWED,
197 &UserKey);
198 ok_dec(ErrorCode, ERROR_FILE_NOT_FOUND);
199 ok_hdl(UserKey, NULL);
200
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);
208
209 /* Test that it is really not present anymore */
210 MachineKey = (HKEY)0xCAFEF00D;
211 ErrorCode = RegOpenKeyExW(
212 HKEY_LOCAL_MACHINE,
213 L"Software\\Classes\\Apitest_HKCR",
214 0,
215 MAXIMUM_ALLOWED,
216 &MachineKey);
217 ok_dec(ErrorCode, ERROR_FILE_NOT_FOUND);
218 ok_hdl(MachineKey, NULL);
219
220 /* Try creating in HKCU */
221 ErrorCode = RegCreateKeyExW(
222 HKEY_CURRENT_USER,
223 L"Software\\Classes\\Apitest_HKCU",
224 0,
225 NULL,
226 0,
227 MAXIMUM_ALLOWED,
228 NULL,
229 &UserKey,
230 NULL);
231 ok_dec(ErrorCode, ERROR_SUCCESS);
232 ok(!IS_HKCR(UserKey), "\n");
233
234 /* Try opening it in HKCR */
235 ErrorCode = RegOpenKeyExW(
236 HKEY_CLASSES_ROOT,
237 L"Apitest_HKCU",
238 0,
239 MAXIMUM_ALLOWED,
240 &ClassesRootKey);
241 ok_dec(ErrorCode, ERROR_SUCCESS);
242 ok(IS_HKCR(ClassesRootKey), "\n");
243 ok_key_name(ClassesRootKey, &HKCU_ClassesPath, L"Apitest_HKCU");
244
245 /* And in HKLM */
246 ErrorCode = RegOpenKeyExW(
247 HKEY_LOCAL_MACHINE,
248 L"Software\\Classes\\Apitest_HKCU",
249 0,
250 MAXIMUM_ALLOWED,
251 &MachineKey);
252 ok_dec(ErrorCode, ERROR_FILE_NOT_FOUND);
253 ok_hdl(MachineKey, NULL);
254
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);
261
262 /* Test that it is really not present anymore */
263 UserKey = (HKEY)0xCAFEF00D;
264 ErrorCode = RegOpenKeyExW(
265 HKEY_CURRENT_USER,
266 L"Software\\Classes\\Apitest_HKCU",
267 0,
268 MAXIMUM_ALLOWED,
269 &UserKey);
270 ok_dec(ErrorCode, ERROR_FILE_NOT_FOUND);
271 ok_hdl(UserKey, NULL);
272
273 /* Try creating in both HKLM and HKCU */
274 ErrorCode = RegCreateKeyExW(
275 HKEY_CURRENT_USER,
276 L"Software\\Classes\\Apitest_HKLM_HKCU",
277 0,
278 NULL,
279 0,
280 MAXIMUM_ALLOWED,
281 NULL,
282 &UserKey,
283 NULL);
284 ok_dec(ErrorCode, ERROR_SUCCESS);
285 ok(!IS_HKCR(UserKey), "\n");
286
287 ErrorCode = RegCreateKeyExW(
288 HKEY_LOCAL_MACHINE,
289 L"Software\\Classes\\Apitest_HKLM_HKCU",
290 0,
291 NULL,
292 0,
293 MAXIMUM_ALLOWED,
294 NULL,
295 &MachineKey,
296 NULL);
297 ok_dec(ErrorCode, ERROR_SUCCESS);
298 ok(!IS_HKCR(MachineKey), "\n");
299
300 /* Open it in HKCR */
301 ErrorCode = RegOpenKeyExW(
302 HKEY_CLASSES_ROOT,
303 L"Apitest_HKLM_HKCU",
304 0,
305 MAXIMUM_ALLOWED,
306 &ClassesRootKey);
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");
311
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);
318
319 RegCloseKey(UserKey);
320 RegCloseKey(ClassesRootKey);
321
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);
327
328 /* See what happens with subkeys */
329 ErrorCode = RegCreateKeyExW(
330 HKEY_LOCAL_MACHINE,
331 L"Software\\Classes\\Apitest_HKLM",
332 0,
333 NULL,
334 0,
335 MAXIMUM_ALLOWED,
336 NULL,
337 &MachineKey,
338 NULL);
339 ok_dec(ErrorCode, ERROR_SUCCESS);
340 ok(!IS_HKCR(MachineKey), "\n");
341
342 /* Open it in HKCR */
343 ErrorCode = RegOpenKeyExW(
344 HKEY_CLASSES_ROOT,
345 L"Apitest_HKLM",
346 0,
347 MAXIMUM_ALLOWED,
348 &ClassesRootKey);
349 ok_dec(ErrorCode, ERROR_SUCCESS);
350 ok(IS_HKCR(ClassesRootKey), "\n");
351 ok_key_name(ClassesRootKey, &HKLM_ClassesPath, L"Apitest_HKLM");
352
353 /* Create a corresponding subkey in HKCU */
354 ErrorCode = RegCreateKeyExW(
355 HKEY_CURRENT_USER,
356 L"Software\\Classes\\Apitest_HKLM\\HKCU_Subkey",
357 0,
358 NULL,
359 0,
360 MAXIMUM_ALLOWED,
361 NULL,
362 &UserSubKey,
363 NULL);
364 ok_dec(ErrorCode, ERROR_SUCCESS);
365 ok(!IS_HKCR(UserSubKey), "\n");
366
367 /* Open it as an HKCR subkey */
368 ErrorCode = RegOpenKeyExW(
369 ClassesRootKey,
370 L"HKCU_Subkey",
371 0,
372 MAXIMUM_ALLOWED,
373 &ClassesRootSubKey);
374 ok_dec(ErrorCode, ERROR_SUCCESS);
375 ok(IS_HKCR(ClassesRootSubKey), "\n");
376 ok_key_name(ClassesRootSubKey, &HKCU_ClassesPath, L"Apitest_HKLM\\HKCU_Subkey");
377
378 /* This one now exists */
379 ErrorCode = RegOpenKeyExW(
380 HKEY_CURRENT_USER,
381 L"Software\\Classes\\Apitest_HKLM",
382 0,
383 MAXIMUM_ALLOWED,
384 &UserKey);
385 ok_dec(ErrorCode, ERROR_SUCCESS);
386 ok(!IS_HKCR(UserKey), "\n");
387
388 /* Delete */
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);
395
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);
402
403 /* Once again */
404 RegDeleteKeyW(HKEY_CLASSES_ROOT, L"Apitest_HKLM");
405 ok_key_deleted(ClassesRootKey);
406 ok_key_deleted(MachineKey);
407 RegCloseKey(ClassesRootKey);
408 RegCloseKey(MachineKey);
409
410 /* Same, but with HKCU first */
411 ErrorCode = RegCreateKeyExW(
412 HKEY_CURRENT_USER,
413 L"Software\\Classes\\Apitest_HKCU",
414 0,
415 NULL,
416 0,
417 MAXIMUM_ALLOWED,
418 NULL,
419 &UserKey,
420 NULL);
421 ok_dec(ErrorCode, ERROR_SUCCESS);
422 ok(!IS_HKCR(UserKey), "\n");
423
424 /* Open it in HKCR */
425 ErrorCode = RegOpenKeyExW(
426 HKEY_CLASSES_ROOT,
427 L"Apitest_HKCU",
428 0,
429 MAXIMUM_ALLOWED,
430 &ClassesRootKey);
431 ok_dec(ErrorCode, ERROR_SUCCESS);
432 ok(IS_HKCR(ClassesRootKey), "\n");
433 ok_key_name(ClassesRootKey, &HKCU_ClassesPath, L"Apitest_HKCU");
434
435 /* Try creating a subkey with this HKCR handle, which points to a subkey in HKCU. */
436 ErrorCode = RegCreateKeyExW(
437 ClassesRootKey,
438 L"HKCR_Subkey",
439 0,
440 NULL,
441 0,
442 MAXIMUM_ALLOWED,
443 NULL,
444 &ClassesRootSubKey,
445 NULL);
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);
454
455 /* Create a corresponding subkey in HKLM */
456 ErrorCode = RegCreateKeyExW(
457 HKEY_LOCAL_MACHINE,
458 L"Software\\Classes\\Apitest_HKCU\\HKLM_Subkey",
459 0,
460 NULL,
461 0,
462 MAXIMUM_ALLOWED,
463 NULL,
464 &MachineSubKey,
465 NULL);
466 ok_dec(ErrorCode, ERROR_SUCCESS);
467 ok(!IS_HKCR(MachineSubKey), "\n");
468
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(
472 ClassesRootKey,
473 L"HKLM_Subkey",
474 0,
475 MAXIMUM_ALLOWED,
476 &ClassesRootSubKey);
477 ok_dec(ErrorCode, ERROR_SUCCESS);
478 ok(IS_HKCR(ClassesRootSubKey), "\n");
479 ok_key_name(ClassesRootSubKey, &HKLM_ClassesPath, L"Apitest_HKCU\\HKLM_Subkey");
480
481 /* This one now exists */
482 ErrorCode = RegOpenKeyExW(
483 HKEY_LOCAL_MACHINE,
484 L"Software\\Classes\\Apitest_HKCU",
485 0,
486 MAXIMUM_ALLOWED,
487 &MachineKey);
488 ok_dec(ErrorCode, ERROR_SUCCESS);
489 ok(!IS_HKCR(MachineKey), "\n");
490
491 /* Delete */
492 ErrorCode = RegDeleteKeyW(MachineKey, L"HKLM_Subkey");
493 ok_dec(ErrorCode, ERROR_SUCCESS);
494 ok_key_deleted(MachineSubKey);
495 ok_key_deleted(ClassesRootSubKey);
496
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(
501 ClassesRootKey,
502 L"HKCR_Subkey",
503 0,
504 NULL,
505 0,
506 MAXIMUM_ALLOWED,
507 NULL,
508 &ClassesRootSubKey,
509 NULL);
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);
516
517 RegCloseKey(MachineSubKey);
518 RegCloseKey(ClassesRootSubKey);
519
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);
527
528 /* Once again */
529 RegDeleteKeyW(HKEY_CLASSES_ROOT, L"Apitest_HKCU");
530 ok_key_deleted(MachineKey);
531 RegCloseKey(MachineKey);
532 }
533
534 static
535 void
536 Test_DuplicateHandle(void)
537 {
538 HKEY KeyHandle, DupHandle;
539 DWORD ErrorCode;
540 BOOL Duplicated;
541
542 ErrorCode = RegOpenKeyExW(HKEY_CLASSES_ROOT, L"CLSID", 0, KEY_READ, &KeyHandle);
543 ok_dec(ErrorCode, ERROR_SUCCESS);
544 ok(IS_HKCR(KeyHandle), "\n");
545
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");
550
551 RegCloseKey(KeyHandle);
552 RegCloseKey(DupHandle);
553 }
554
555 START_TEST(HKEY_CLASSES_ROOT)
556 {
557 HKEY UserKey;
558 LONG ErrorCode;
559
560 /* Get HKCU real key name */
561 ErrorCode = RegOpenKeyExW(
562 HKEY_CURRENT_USER,
563 L"Software\\Classes",
564 0,
565 KEY_READ,
566 &UserKey);
567 ok_dec(ErrorCode, ERROR_SUCCESS);
568 GetKeyName(UserKey, &HKCU_ClassesPath);
569 RegCloseKey(UserKey);
570
571 Test_CreateOpenKey();
572 Test_DuplicateHandle();
573 }