[ADVAPI32_APITEST]
[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, UserKey, ClassesRootKey;
112 DWORD ErrorCode;
113
114 /* First create a subkey in HKLM */
115 ErrorCode = RegCreateKeyExW(
116 HKEY_LOCAL_MACHINE,
117 L"Software\\Classes\\Apitest_HKLM_Only",
118 0,
119 NULL,
120 0,
121 MAXIMUM_ALLOWED,
122 NULL,
123 &MachineKey,
124 NULL);
125 ok_dec(ErrorCode, ERROR_SUCCESS);
126 ok(!IS_HKCR(MachineKey), "\n");
127
128 /* Open it in HKCR */
129 ErrorCode = RegOpenKeyExW(
130 HKEY_CLASSES_ROOT,
131 L"Apitest_HKLM_Only",
132 0,
133 MAXIMUM_ALLOWED,
134 &ClassesRootKey);
135 ok_dec(ErrorCode, ERROR_SUCCESS);
136 ok(IS_HKCR(ClassesRootKey), "\n");
137 ok_key_name(ClassesRootKey, &HKLM_ClassesPath, L"Apitest_HKLM_Only");
138
139 /* Try opening it in HKCU */
140 UserKey = (HKEY)0xCAFEF00D;
141 ErrorCode = RegOpenKeyExW(
142 HKEY_CURRENT_USER,
143 L"Software\\Classes\\Apitest_HKLM_Only",
144 0,
145 MAXIMUM_ALLOWED,
146 &UserKey);
147 ok_dec(ErrorCode, ERROR_FILE_NOT_FOUND);
148 ok_hdl(UserKey, NULL);
149
150 /* Cleanup */
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);
155
156 /* Try creating in HKCR */
157 ErrorCode = RegCreateKeyExW(
158 HKEY_CLASSES_ROOT,
159 L"Apitest_HKCR",
160 0,
161 NULL,
162 0,
163 MAXIMUM_ALLOWED,
164 NULL,
165 &ClassesRootKey,
166 NULL);
167 ok_dec(ErrorCode, ERROR_SUCCESS);
168 ok(IS_HKCR(ClassesRootKey), "\n");
169 ok_key_name(ClassesRootKey, &HKLM_ClassesPath, L"Apitest_HKCR");
170
171 /* It should be present in HKLM */
172 ErrorCode = RegOpenKeyExW(
173 HKEY_LOCAL_MACHINE,
174 L"Software\\Classes\\Apitest_HKCR",
175 0,
176 MAXIMUM_ALLOWED,
177 &MachineKey);
178 ok_dec(ErrorCode, ERROR_SUCCESS);
179 ok(!IS_HKCR(MachineKey), "\n");
180
181 /* But not in HKCU */
182 UserKey = (HKEY)0xCAFEF00D;
183 ErrorCode = RegOpenKeyExW(
184 HKEY_CURRENT_USER,
185 L"Software\\Classes\\Apitest_HKCR",
186 0,
187 MAXIMUM_ALLOWED,
188 &UserKey);
189 ok_dec(ErrorCode, ERROR_FILE_NOT_FOUND);
190 ok_hdl(UserKey, NULL);
191
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);
199
200 /* Test that it is really not present anymore */
201 MachineKey = (HKEY)0xCAFEF00D;
202 ErrorCode = RegOpenKeyExW(
203 HKEY_LOCAL_MACHINE,
204 L"Software\\Classes\\Apitest_HKCR",
205 0,
206 MAXIMUM_ALLOWED,
207 &MachineKey);
208 ok_dec(ErrorCode, ERROR_FILE_NOT_FOUND);
209 ok_hdl(MachineKey, NULL);
210
211 /* Try creating in HKCU */
212 ErrorCode = RegCreateKeyExW(
213 HKEY_CURRENT_USER,
214 L"Software\\Classes\\Apitest_HKCU",
215 0,
216 NULL,
217 0,
218 MAXIMUM_ALLOWED,
219 NULL,
220 &UserKey,
221 NULL);
222 ok_dec(ErrorCode, ERROR_SUCCESS);
223 ok(!IS_HKCR(UserKey), "\n");
224
225 /* Try opening it in HKCR */
226 ErrorCode = RegOpenKeyExW(
227 HKEY_CLASSES_ROOT,
228 L"Apitest_HKCU",
229 0,
230 MAXIMUM_ALLOWED,
231 &ClassesRootKey);
232 ok_dec(ErrorCode, ERROR_SUCCESS);
233 ok(IS_HKCR(ClassesRootKey), "\n");
234 ok_key_name(ClassesRootKey, &HKCU_ClassesPath, L"Apitest_HKCU");
235
236 /* And in HKLM */
237 ErrorCode = RegOpenKeyExW(
238 HKEY_LOCAL_MACHINE,
239 L"Software\\Classes\\Apitest_HKCU",
240 0,
241 MAXIMUM_ALLOWED,
242 &MachineKey);
243 ok_dec(ErrorCode, ERROR_FILE_NOT_FOUND);
244 ok_hdl(MachineKey, NULL);
245
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);
252
253 /* Test that it is really not present anymore */
254 UserKey = (HKEY)0xCAFEF00D;
255 ErrorCode = RegOpenKeyExW(
256 HKEY_CURRENT_USER,
257 L"Software\\Classes\\Apitest_HKCU",
258 0,
259 MAXIMUM_ALLOWED,
260 &UserKey);
261 ok_dec(ErrorCode, ERROR_FILE_NOT_FOUND);
262 ok_hdl(UserKey, NULL);
263
264 /* Try creating in both HKLM and HKCU */
265 ErrorCode = RegCreateKeyExW(
266 HKEY_CURRENT_USER,
267 L"Software\\Classes\\Apitest_HKLM_HKCU",
268 0,
269 NULL,
270 0,
271 MAXIMUM_ALLOWED,
272 NULL,
273 &UserKey,
274 NULL);
275 ok_dec(ErrorCode, ERROR_SUCCESS);
276 ok(!IS_HKCR(UserKey), "\n");
277
278 ErrorCode = RegCreateKeyExW(
279 HKEY_LOCAL_MACHINE,
280 L"Software\\Classes\\Apitest_HKLM_HKCU",
281 0,
282 NULL,
283 0,
284 MAXIMUM_ALLOWED,
285 NULL,
286 &MachineKey,
287 NULL);
288 ok_dec(ErrorCode, ERROR_SUCCESS);
289 ok(!IS_HKCR(MachineKey), "\n");
290
291 /* Open it in HKCR */
292 ErrorCode = RegOpenKeyExW(
293 HKEY_CLASSES_ROOT,
294 L"Apitest_HKLM_HKCU",
295 0,
296 MAXIMUM_ALLOWED,
297 &ClassesRootKey);
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");
302
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);
309
310 RegCloseKey(UserKey);
311 RegCloseKey(ClassesRootKey);
312
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);
318 }
319
320 static
321 void
322 Test_KeyName(void)
323 {
324 HKEY KeyHandle;
325 DWORD ErrorCode;
326
327
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");
332
333 RegCloseKey(KeyHandle);
334 }
335
336 static
337 void
338 Test_DuplicateHandle(void)
339 {
340 HKEY KeyHandle, DupHandle;
341 DWORD ErrorCode;
342 BOOL Duplicated;
343
344 ErrorCode = RegOpenKeyExW(HKEY_CLASSES_ROOT, L"CLSID", 0, KEY_READ, &KeyHandle);
345 ok_dec(ErrorCode, ERROR_SUCCESS);
346 ok(IS_HKCR(KeyHandle), "\n");
347
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");
352
353 ok_key_name(DupHandle, &HKLM_ClassesPath, L"CLSID");
354
355 RegCloseKey(KeyHandle);
356 RegCloseKey(DupHandle);
357 }
358
359 START_TEST(HKEY_CLASSES_ROOT)
360 {
361 HKEY UserKey;
362 LONG ErrorCode;
363
364 /* Get HKCU real key name */
365 ErrorCode = RegOpenKeyExW(
366 HKEY_CURRENT_USER,
367 L"Software\\Classes",
368 0,
369 KEY_READ,
370 &UserKey);
371 ok_dec(ErrorCode, ERROR_SUCCESS);
372 GetKeyName(UserKey, &HKCU_ClassesPath);
373 RegCloseKey(UserKey);
374
375 Test_CreateOpenKey();
376 Test_DuplicateHandle();
377 Test_KeyName();
378 }