4c4aaf58cdbd1f6196de2df955f23446eb7f5d62
[reactos.git] / modules / rostests / apitests / ntdll / RtlDeleteAce.c
1 /*
2 * PROJECT: ReactOS API tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test for RtlDeleteAce
5 * PROGRAMMERS: Thomas Faber <thomas.faber@reactos.org>
6 */
7
8 #include "precomp.h"
9
10 static
11 PVOID
12 AllocateGuarded(
13 _In_ SIZE_T SizeRequested)
14 {
15 NTSTATUS Status;
16 SIZE_T Size = PAGE_ROUND_UP(SizeRequested + PAGE_SIZE);
17 PVOID VirtualMemory = NULL;
18 PCHAR StartOfBuffer;
19
20 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &VirtualMemory, 0, &Size, MEM_RESERVE, PAGE_NOACCESS);
21
22 if (!NT_SUCCESS(Status))
23 return NULL;
24
25 Size -= PAGE_SIZE;
26 if (Size)
27 {
28 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &VirtualMemory, 0, &Size, MEM_COMMIT, PAGE_READWRITE);
29 if (!NT_SUCCESS(Status))
30 {
31 Size = 0;
32 Status = NtFreeVirtualMemory(NtCurrentProcess(), &VirtualMemory, &Size, MEM_RELEASE);
33 ok(Status == STATUS_SUCCESS, "Status = %lx\n", Status);
34 return NULL;
35 }
36 }
37
38 StartOfBuffer = VirtualMemory;
39 StartOfBuffer += Size - SizeRequested;
40
41 return StartOfBuffer;
42 }
43
44 static
45 VOID
46 FreeGuarded(
47 _In_ PVOID Pointer)
48 {
49 NTSTATUS Status;
50 PVOID VirtualMemory = (PVOID)PAGE_ROUND_DOWN((SIZE_T)Pointer);
51 SIZE_T Size = 0;
52
53 Status = NtFreeVirtualMemory(NtCurrentProcess(), &VirtualMemory, &Size, MEM_RELEASE);
54 ok(Status == STATUS_SUCCESS, "Status = %lx\n", Status);
55 }
56
57 static
58 PACL
59 MakeAcl(
60 _In_ ULONG AceCount,
61 ...)
62 {
63 PACL Acl;
64 PACE_HEADER AceHeader;
65 ULONG AclSize;
66 ULONG AceSizes[10];
67 ULONG i;
68 va_list Args;
69
70 ASSERT(AceCount <= RTL_NUMBER_OF(AceSizes));
71 AclSize = sizeof(ACL);
72 va_start(Args, AceCount);
73 for (i = 0; i < AceCount; i++)
74 {
75 AceSizes[i] = va_arg(Args, int);
76 AclSize += AceSizes[i];
77 }
78 va_end(Args);
79
80 Acl = AllocateGuarded(AclSize);
81 if (!Acl)
82 {
83 skip("Failed to allocate %lu bytes\n", AclSize);
84 return NULL;
85 }
86
87 Acl->AclRevision = ACL_REVISION;
88 Acl->Sbz1 = 0;
89 Acl->AclSize = AclSize;
90 Acl->AceCount = AceCount;
91 Acl->Sbz2 = 0;
92
93 AceHeader = (PACE_HEADER)(Acl + 1);
94 for (i = 0; i < AceCount; i++)
95 {
96 AceHeader->AceType = 0;
97 AceHeader->AceFlags = 0;
98 AceHeader->AceSize = AceSizes[i];
99 AceHeader = (PACE_HEADER)((PCHAR)AceHeader + AceHeader->AceSize);
100 }
101
102 return Acl;
103 }
104
105 START_TEST(RtlDeleteAce)
106 {
107 PACL Acl;
108 PACCESS_ALLOWED_ACE Ace;
109 ULONG AceSize;
110 PISID Sid;
111 NTSTATUS Status;
112 int i;
113
114 Acl = MakeAcl(0);
115 if (Acl)
116 {
117 ok(RtlValidAcl(Acl), "Acl is invalid\n");
118
119 /* There is no first ACE -- should stay untouched */
120 Status = RtlDeleteAce(Acl, 0);
121 ok(Status == STATUS_INVALID_PARAMETER, "Status = %lx\n", Status);
122 ok(Acl->AclSize == sizeof(ACL), "AclSize = %u\n", Acl->AclSize);
123 ok(Acl->AceCount == 0, "AceCount = %u\n", Acl->AceCount);
124
125 /* Index -1 -- should stay untouched */
126 Status = RtlDeleteAce(Acl, 0xFFFFFFFF);
127 ok(Status == STATUS_INVALID_PARAMETER, "Status = %lx\n", Status);
128 FreeGuarded(Acl);
129 }
130
131 AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + FIELD_OFFSET(SID, SubAuthority);
132 Acl = MakeAcl(1, (int)AceSize);
133 if (Acl)
134 {
135 Ace = (PACCESS_ALLOWED_ACE)(Acl + 1);
136 Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
137 Sid = (PISID)&Ace->SidStart;
138 Sid->Revision = SID_REVISION;
139 Sid->SubAuthorityCount = 0;
140 RtlZeroMemory(&Sid->IdentifierAuthority, sizeof(Sid->IdentifierAuthority));
141
142 ok(RtlValidAcl(Acl), "Acl is invalid\n");
143
144 /* Out of bounds delete -- should stay untouched */
145 Status = RtlDeleteAce(Acl, 1);
146 ok(Status == STATUS_INVALID_PARAMETER, "Status = %lx\n", Status);
147 ok(Acl->AclSize == sizeof(ACL) + AceSize, "AclSize = %u\n", Acl->AclSize);
148 ok(Acl->AceCount == 1, "AceCount = %u\n", Acl->AceCount);
149 ok(Ace->Header.AceSize == AceSize, "AceSize = %u\n", Ace->Header.AceSize);
150
151 /* Index -1 -- should stay untouched */
152 Status = RtlDeleteAce(Acl, 0xFFFFFFFF);
153 ok(Status == STATUS_INVALID_PARAMETER, "Status = %lx\n", Status);
154 ok(Acl->AclSize == sizeof(ACL) + AceSize, "AclSize = %u\n", Acl->AclSize);
155 ok(Acl->AceCount == 1, "AceCount = %u\n", Acl->AceCount);
156 ok(Ace->Header.AceSize == AceSize, "AceSize = %u\n", Ace->Header.AceSize);
157
158 /* Delete the first (and only) ACE */
159 Status = RtlDeleteAce(Acl, 0);
160 ok(Status == STATUS_SUCCESS, "Status = %lx\n", Status);
161 ok(Acl->AclSize == sizeof(ACL) + AceSize, "AclSize = %u\n", Acl->AclSize);
162 ok(Acl->AceCount == 0, "AceCount = %u\n", Acl->AceCount);
163 ok(Ace->Header.AceSize == 0, "AceSize = %u\n", Ace->Header.AceSize);
164 FreeGuarded(Acl);
165 }
166
167 AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + FIELD_OFFSET(SID, SubAuthority[1]);
168 Acl = MakeAcl(4, (int)AceSize, (int)AceSize + 4, (int)AceSize + 8, (int)AceSize + 12);
169 if (Acl)
170 {
171 Ace = (PACCESS_ALLOWED_ACE)(Acl + 1);
172 for (i = 0; i < 4; i++)
173 {
174 Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
175 Sid = (PISID)&Ace->SidStart;
176 Sid->Revision = SID_REVISION;
177 Sid->SubAuthorityCount = 0;
178 RtlZeroMemory(&Sid->IdentifierAuthority, sizeof(Sid->IdentifierAuthority));
179 Ace = (PACCESS_ALLOWED_ACE)((PCHAR)Ace + Ace->Header.AceSize);
180 }
181
182 ok(RtlValidAcl(Acl), "Acl is invalid\n");
183
184 /* Out of bounds delete -- should stay untouched */
185 Status = RtlDeleteAce(Acl, 4);
186 ok(Status == STATUS_INVALID_PARAMETER, "Status = %lx\n", Status);
187 ok(Acl->AclSize == sizeof(ACL) + 4 * AceSize + 24, "AclSize = %u\n", Acl->AclSize);
188 ok(Acl->AceCount == 4, "AceCount = %u\n", Acl->AceCount);
189 Ace = (PACCESS_ALLOWED_ACE)(Acl + 1);
190 ok(Ace->Header.AceSize == AceSize, "AceSize = %u\n", Ace->Header.AceSize);
191 Ace = (PACCESS_ALLOWED_ACE)((PCHAR)Ace + Ace->Header.AceSize);
192 ok(Ace->Header.AceSize == AceSize + 4, "AceSize = %u\n", Ace->Header.AceSize);
193 Ace = (PACCESS_ALLOWED_ACE)((PCHAR)Ace + Ace->Header.AceSize);
194 ok(Ace->Header.AceSize == AceSize + 8, "AceSize = %u\n", Ace->Header.AceSize);
195 Ace = (PACCESS_ALLOWED_ACE)((PCHAR)Ace + Ace->Header.AceSize);
196 ok(Ace->Header.AceSize == AceSize + 12, "AceSize = %u\n", Ace->Header.AceSize);
197
198 /* Index -1 -- should stay untouched */
199 Status = RtlDeleteAce(Acl, 0xFFFFFFFF);
200 ok(Status == STATUS_INVALID_PARAMETER, "Status = %lx\n", Status);
201 ok(Acl->AclSize == sizeof(ACL) + 4 * AceSize + 24, "AclSize = %u\n", Acl->AclSize);
202 ok(Acl->AceCount == 4, "AceCount = %u\n", Acl->AceCount);
203 Ace = (PACCESS_ALLOWED_ACE)(Acl + 1);
204 ok(Ace->Header.AceSize == AceSize, "AceSize = %u\n", Ace->Header.AceSize);
205 Ace = (PACCESS_ALLOWED_ACE)((PCHAR)Ace + Ace->Header.AceSize);
206 ok(Ace->Header.AceSize == AceSize + 4, "AceSize = %u\n", Ace->Header.AceSize);
207 Ace = (PACCESS_ALLOWED_ACE)((PCHAR)Ace + Ace->Header.AceSize);
208 ok(Ace->Header.AceSize == AceSize + 8, "AceSize = %u\n", Ace->Header.AceSize);
209 Ace = (PACCESS_ALLOWED_ACE)((PCHAR)Ace + Ace->Header.AceSize);
210 ok(Ace->Header.AceSize == AceSize + 12, "AceSize = %u\n", Ace->Header.AceSize);
211
212 /* Delete the last ACE */
213 Status = RtlDeleteAce(Acl, 3);
214 ok(Status == STATUS_SUCCESS, "Status = %lx\n", Status);
215 ok(Acl->AclSize == sizeof(ACL) + 4 * AceSize + 24, "AclSize = %u\n", Acl->AclSize);
216 ok(Acl->AceCount == 3, "AceCount = %u\n", Acl->AceCount);
217 Ace = (PACCESS_ALLOWED_ACE)(Acl + 1);
218 ok(Ace->Header.AceSize == AceSize, "AceSize = %u\n", Ace->Header.AceSize);
219 Ace = (PACCESS_ALLOWED_ACE)((PCHAR)Ace + Ace->Header.AceSize);
220 ok(Ace->Header.AceSize == AceSize + 4, "AceSize = %u\n", Ace->Header.AceSize);
221 Ace = (PACCESS_ALLOWED_ACE)((PCHAR)Ace + Ace->Header.AceSize);
222 ok(Ace->Header.AceSize == AceSize + 8, "AceSize = %u\n", Ace->Header.AceSize);
223 Ace = (PACCESS_ALLOWED_ACE)((PCHAR)Ace + Ace->Header.AceSize);
224 ok(Ace->Header.AceSize == 0, "AceSize = %u\n", Ace->Header.AceSize);
225
226 /* Delete the second ACE */
227 Status = RtlDeleteAce(Acl, 1);
228 ok(Status == STATUS_SUCCESS, "Status = %lx\n", Status);
229 ok(Acl->AclSize == sizeof(ACL) + 4 * AceSize + 24, "AclSize = %u\n", Acl->AclSize);
230 ok(Acl->AceCount == 2, "AceCount = %u\n", Acl->AceCount);
231 Ace = (PACCESS_ALLOWED_ACE)(Acl + 1);
232 ok(Ace->Header.AceSize == AceSize, "AceSize = %u\n", Ace->Header.AceSize);
233 Ace = (PACCESS_ALLOWED_ACE)((PCHAR)Ace + Ace->Header.AceSize);
234 ok(Ace->Header.AceSize == AceSize + 8, "AceSize = %u\n", Ace->Header.AceSize);
235 Ace = (PACCESS_ALLOWED_ACE)((PCHAR)Ace + Ace->Header.AceSize);
236 ok(Ace->Header.AceSize == 0, "AceSize = %u\n", Ace->Header.AceSize);
237
238 /* Delete the first ACE */
239 Status = RtlDeleteAce(Acl, 0);
240 ok(Status == STATUS_SUCCESS, "Status = %lx\n", Status);
241 ok(Acl->AclSize == sizeof(ACL) + 4 * AceSize + 24, "AclSize = %u\n", Acl->AclSize);
242 ok(Acl->AceCount == 1, "AceCount = %u\n", Acl->AceCount);
243 Ace = (PACCESS_ALLOWED_ACE)(Acl + 1);
244 ok(Ace->Header.AceSize == AceSize + 8, "AceSize = %u\n", Ace->Header.AceSize);
245 Ace = (PACCESS_ALLOWED_ACE)((PCHAR)Ace + Ace->Header.AceSize);
246 ok(Ace->Header.AceSize == 0, "AceSize = %u\n", Ace->Header.AceSize);
247
248 /* Delete the remaining ACE */
249 Status = RtlDeleteAce(Acl, 0);
250 ok(Status == STATUS_SUCCESS, "Status = %lx\n", Status);
251 ok(Acl->AclSize == sizeof(ACL) + 4 * AceSize + 24, "AclSize = %u\n", Acl->AclSize);
252 ok(Acl->AceCount == 0, "AceCount = %u\n", Acl->AceCount);
253 Ace = (PACCESS_ALLOWED_ACE)(Acl + 1);
254 ok(Ace->Header.AceSize == 0, "AceSize = %u\n", Ace->Header.AceSize);
255
256 FreeGuarded(Acl);
257 }
258 }