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 }
259