1 /*
2  * PROJECT:         ReactOS API Tests
3  * LICENSE:         GPLv2+ - See COPYING in the top level directory
4  * PURPOSE:         Test for NtDeleteKey
5  */
6 
7 #include "precomp.h"
8 
9 static
10 NTSTATUS
11 CreateRegistryKeyHandle(PHANDLE KeyHandle,
12                       ACCESS_MASK AccessMask,
13                       PWCHAR RegistryPath)
14 {
15     UNICODE_STRING KeyName;
16     OBJECT_ATTRIBUTES Attributes;
17 
18     RtlInitUnicodeString(&KeyName, RegistryPath);
19     InitializeObjectAttributes(&Attributes,
20                                &KeyName,
21                                OBJ_CASE_INSENSITIVE,
22                                NULL,
23                                NULL);
24 
25     return NtCreateKey(KeyHandle, AccessMask, &Attributes, 0, NULL, REG_OPTION_VOLATILE, 0);
26 }
27 
28 START_TEST(NtDeleteKey)
29 {
30     NTSTATUS Status;
31     HANDLE ParentKey, ChildKey, PetKey;
32     WCHAR Buffer[sizeof("\\Registry\\Machine\\Software\\RosTests\\Child\\Pet") + 5];
33     ULONG i;
34 
35     /* Create a registry key */
36     Status = CreateRegistryKeyHandle(&ParentKey, KEY_READ | DELETE, L"\\Registry\\Machine\\Software\\RosTests");
37     ok_ntstatus(Status, STATUS_SUCCESS);
38 
39     /* Create a children registry key */
40     Status = CreateRegistryKeyHandle(&ChildKey, KEY_READ | DELETE, L"\\Registry\\Machine\\Software\\RosTests\\Child");
41     ok_ntstatus(Status, STATUS_SUCCESS);
42 
43     /* Try deleting the parent one */
44     Status = NtDeleteKey(ParentKey);
45     ok_ntstatus(Status, STATUS_CANNOT_DELETE);
46 
47     /* See what happens with Child one */
48     Status = NtDeleteKey(ChildKey);
49     ok_ntstatus(Status, STATUS_SUCCESS);
50 
51     /* Retry with parent one */
52     Status = NtDeleteKey(ParentKey);
53     ok_ntstatus(Status, STATUS_SUCCESS);
54 
55     /* re-retry */
56     Status = NtDeleteKey(ParentKey);
57     ok_ntstatus(Status, STATUS_SUCCESS);
58 
59     /* Close everything */
60     NtClose(ChildKey);
61     NtClose(ParentKey);
62 
63     /* Same, but this time close the child handle before trying to delete the parent */
64     /* Create a registry key */
65     Status = CreateRegistryKeyHandle(&ParentKey, KEY_READ | DELETE, L"\\Registry\\Machine\\Software\\RosTests");
66     ok_ntstatus(Status, STATUS_SUCCESS);
67 
68     /* Create a children registry key */
69     Status = CreateRegistryKeyHandle(&ChildKey, KEY_READ, L"\\Registry\\Machine\\Software\\RosTests\\Child");
70     ok_ntstatus(Status, STATUS_SUCCESS);
71 
72     /* Close the Child */
73     NtClose(ChildKey);
74 
75     /* Try deleting the parent one */
76     Status = NtDeleteKey(ParentKey);
77     ok_ntstatus(Status, STATUS_CANNOT_DELETE);
78 
79     /* See what happens with Child one */
80     Status = CreateRegistryKeyHandle(&ChildKey, DELETE, L"\\Registry\\Machine\\Software\\RosTests\\Child");
81     ok_ntstatus(Status, STATUS_SUCCESS);
82     Status = NtDeleteKey(ChildKey);
83     ok_ntstatus(Status, STATUS_SUCCESS);
84 
85     /* Retry with parent one */
86     Status = NtDeleteKey(ParentKey);
87     ok_ntstatus(Status, STATUS_SUCCESS);
88 
89     /* Close everything */
90     NtClose(ChildKey);
91     NtClose(ParentKey);
92 
93     /* Stress test key creation */
94     Status = CreateRegistryKeyHandle(&ParentKey, KEY_READ | DELETE, L"\\Registry\\Machine\\Software\\RosTests");
95 
96     for (i = 0; i <= 9999; i++) {
97         swprintf(Buffer, L"\\Registry\\Machine\\Software\\RosTests\\Child%04d", i);
98         Status = CreateRegistryKeyHandle(&ChildKey, KEY_READ, Buffer);
99         NtClose(ChildKey);
100 
101         swprintf(Buffer, L"\\Registry\\Machine\\Software\\RosTests\\Child%04d\\Pet", i);
102         Status = CreateRegistryKeyHandle(&PetKey, KEY_READ, Buffer);
103         NtClose(PetKey);
104     }
105     ok_ntstatus(Status, STATUS_SUCCESS);
106 
107     /* Test hive rerooting */
108     Status = CreateRegistryKeyHandle(&PetKey, DELETE, L"\\Registry\\Machine\\Software\\RosTests\\Child5000\\Pet");
109     ok_ntstatus(Status, STATUS_SUCCESS);
110     Status = NtDeleteKey(PetKey);
111     ok_ntstatus(Status, STATUS_SUCCESS);
112 
113     NtClose(PetKey);
114 
115     Status = CreateRegistryKeyHandle(&ChildKey, DELETE, L"\\Registry\\Machine\\Software\\RosTests\\Child5000");
116     ok_ntstatus(Status, STATUS_SUCCESS);
117     Status = NtDeleteKey(ChildKey);
118     ok_ntstatus(Status, STATUS_SUCCESS);
119 
120     /* Test mass key deletion */
121     for (i = 0; i <= 9999; i++) {
122         if (i != 5000) {
123             swprintf(Buffer, L"\\Registry\\Machine\\Software\\RosTests\\Child%04d\\Pet", i);
124             CreateRegistryKeyHandle(&PetKey, DELETE, Buffer);
125             Status = NtDeleteKey(PetKey);
126             NtClose(PetKey);
127 
128             swprintf(Buffer, L"\\Registry\\Machine\\Software\\RosTests\\Child%04d", i);
129             CreateRegistryKeyHandle(&ChildKey, DELETE, Buffer);
130             Status = NtDeleteKey(ChildKey);
131             NtClose(ChildKey);
132         }
133     }
134     ok_ntstatus(Status, STATUS_SUCCESS);
135 
136     Status = NtDeleteKey(ParentKey);
137     ok_ntstatus(Status, STATUS_SUCCESS);
138 
139     /* Close ParentKey */
140     NtClose(ParentKey);
141 }
142