[RTL]
[reactos.git] / rostests / apitests / ntdll / RtlFirstFreeAce.c
1 /*
2 * PROJECT: ReactOS API tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test for RtlFirstFreeAce
5 * PROGRAMMERS: Thomas Faber <thomas.faber@reactos.org>
6 */
7
8 #include <apitest.h>
9 #include <ndk/mmfuncs.h>
10 #include <ndk/rtlfuncs.h>
11
12 static
13 PVOID
14 AllocateGuarded(
15 _In_ SIZE_T SizeRequested)
16 {
17 NTSTATUS Status;
18 SIZE_T Size = PAGE_ROUND_UP(SizeRequested + PAGE_SIZE);
19 PVOID VirtualMemory = NULL;
20 PCHAR StartOfBuffer;
21
22 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &VirtualMemory, 0, &Size, MEM_RESERVE, PAGE_NOACCESS);
23
24 if (!NT_SUCCESS(Status))
25 return NULL;
26
27 Size -= PAGE_SIZE;
28 if (Size)
29 {
30 Status = NtAllocateVirtualMemory(NtCurrentProcess(), &VirtualMemory, 0, &Size, MEM_COMMIT, PAGE_READWRITE);
31 if (!NT_SUCCESS(Status))
32 {
33 Size = 0;
34 Status = NtFreeVirtualMemory(NtCurrentProcess(), &VirtualMemory, &Size, MEM_RELEASE);
35 ok(Status == STATUS_SUCCESS, "Status = %lx\n", Status);
36 return NULL;
37 }
38 }
39
40 StartOfBuffer = VirtualMemory;
41 StartOfBuffer += Size - SizeRequested;
42
43 return StartOfBuffer;
44 }
45
46 static
47 VOID
48 FreeGuarded(
49 _In_ PVOID Pointer)
50 {
51 NTSTATUS Status;
52 PVOID VirtualMemory = (PVOID)PAGE_ROUND_DOWN((SIZE_T)Pointer);
53 SIZE_T Size = 0;
54
55 Status = NtFreeVirtualMemory(NtCurrentProcess(), &VirtualMemory, &Size, MEM_RELEASE);
56 ok(Status == STATUS_SUCCESS, "Status = %lx\n", Status);
57 }
58
59 static
60 PACL
61 MakeAcl(
62 _In_ ULONG AceCount,
63 ...)
64 {
65 PACL Acl;
66 PACE_HEADER AceHeader;
67 ULONG AclSize;
68 ULONG AceSizes[10];
69 ULONG i;
70 va_list Args;
71
72 ASSERT(AceCount <= RTL_NUMBER_OF(AceSizes));
73 AclSize = sizeof(ACL);
74 va_start(Args, AceCount);
75 for (i = 0; i < AceCount; i++)
76 {
77 AceSizes[i] = va_arg(Args, int);
78 AclSize += AceSizes[i];
79 }
80 va_end(Args);
81
82 Acl = AllocateGuarded(AclSize);
83 if (!Acl)
84 {
85 skip("Failed to allocate %lu bytes\n", AclSize);
86 return NULL;
87 }
88
89 Acl->AclRevision = ACL_REVISION;
90 Acl->Sbz1 = 0;
91 Acl->AclSize = AclSize;
92 Acl->AceCount = AceCount;
93 Acl->Sbz2 = 0;
94
95 AceHeader = (PACE_HEADER)(Acl + 1);
96 for (i = 0; i < AceCount; i++)
97 {
98 AceHeader->AceType = 0;
99 AceHeader->AceFlags = 0;
100 AceHeader->AceSize = AceSizes[i];
101 AceHeader = (PACE_HEADER)((PCHAR)AceHeader + AceHeader->AceSize);
102 }
103
104 return Acl;
105 }
106
107 START_TEST(RtlFirstFreeAce)
108 {
109 PACL Acl;
110 PACE FirstAce;
111 BOOLEAN Found;
112
113 Acl = MakeAcl(0);
114 if (Acl)
115 {
116 /* Simple empty ACL */
117 FirstAce = InvalidPointer;
118 Found = RtlFirstFreeAce(Acl, &FirstAce);
119 ok(Found == TRUE, "Found = %u\n", Found);
120 ok(FirstAce == (PACE)(Acl + 1), "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
121
122 /* Not enough space */
123 Acl->AclSize = sizeof(ACL) - 1;
124 FirstAce = InvalidPointer;
125 Found = RtlFirstFreeAce(Acl, &FirstAce);
126 ok(Found == TRUE, "Found = %u\n", Found);
127 ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
128
129 /* Invalid values for all the other fields */
130 Acl->AclRevision = 76;
131 Acl->Sbz1 = 0x55;
132 Acl->AclSize = sizeof(ACL);
133 Acl->Sbz2 = 0x55;
134 FirstAce = InvalidPointer;
135 Found = RtlFirstFreeAce(Acl, &FirstAce);
136 ok(Found == TRUE, "Found = %u\n", Found);
137 ok(FirstAce == (PACE)(Acl + 1), "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
138
139 FreeGuarded(Acl);
140 }
141
142 Acl = MakeAcl(1, (int)sizeof(ACE_HEADER));
143 if (Acl)
144 {
145 /* ACL with one ACE */
146 FirstAce = InvalidPointer;
147 Found = RtlFirstFreeAce(Acl, &FirstAce);
148 ok(Found == TRUE, "Found = %u\n", Found);
149 ok(FirstAce == (PACE)((PACE_HEADER)(Acl + 1) + 1), "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
150
151 /* The one ACE doesn't actually fit */
152 Acl->AclSize = sizeof(ACL);
153 FirstAce = InvalidPointer;
154 Found = RtlFirstFreeAce(Acl, &FirstAce);
155 ok(Found == FALSE, "Found = %u\n", Found);
156 ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
157
158 /* Only the first byte fits */
159 Acl->AclSize = sizeof(ACL) + 1;
160 FirstAce = InvalidPointer;
161 Found = RtlFirstFreeAce(Acl, &FirstAce);
162 ok(Found == TRUE, "Found = %u\n", Found);
163 ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
164
165 /* Until we cover the whole size we get NULL */
166 Acl->AclSize = sizeof(ACL) + sizeof(ACE_HEADER) - 1;
167 FirstAce = InvalidPointer;
168 Found = RtlFirstFreeAce(Acl, &FirstAce);
169 ok(Found == TRUE, "Found = %u\n", Found);
170 ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
171
172 FreeGuarded(Acl);
173 }
174
175 /* Same but bigger */
176 Acl = MakeAcl(1, (int)sizeof(ACE_HEADER) + 4);
177 if (Acl)
178 {
179 /* ACL with one ACE */
180 FirstAce = InvalidPointer;
181 Found = RtlFirstFreeAce(Acl, &FirstAce);
182 ok(Found == TRUE, "Found = %u\n", Found);
183 ok(FirstAce == (PACE)((PCHAR)(Acl + 1) + sizeof(ACE_HEADER) + 4), "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
184
185 /* The one ACE doesn't actually fit */
186 Acl->AclSize = sizeof(ACL);
187 FirstAce = InvalidPointer;
188 Found = RtlFirstFreeAce(Acl, &FirstAce);
189 ok(Found == FALSE, "Found = %u\n", Found);
190 ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
191
192 /* Only the first byte fits */
193 Acl->AclSize = sizeof(ACL) + 1;
194 FirstAce = InvalidPointer;
195 Found = RtlFirstFreeAce(Acl, &FirstAce);
196 ok(Found == TRUE, "Found = %u\n", Found);
197 ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
198
199 /* Until we cover the whole size we get NULL */
200 Acl->AclSize = sizeof(ACL) + sizeof(ACE_HEADER) - 3;
201 FirstAce = InvalidPointer;
202 Found = RtlFirstFreeAce(Acl, &FirstAce);
203 ok(Found == TRUE, "Found = %u\n", Found);
204 ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
205
206 FreeGuarded(Acl);
207 }
208
209 Acl = MakeAcl(4, (int)sizeof(ACE_HEADER), (int)sizeof(ACE_HEADER), (int)sizeof(ACCESS_ALLOWED_ACE), (int)sizeof(ACCESS_ALLOWED_ACE));
210 if (Acl)
211 {
212 /* ACL with one ACE */
213 FirstAce = InvalidPointer;
214 Found = RtlFirstFreeAce(Acl, &FirstAce);
215 ok(Found == TRUE, "Found = %u\n", Found);
216 ok(FirstAce == (PACE)((PCHAR)(Acl + 1) + 2 * sizeof(ACE_HEADER) + 2 * sizeof(ACCESS_ALLOWED_ACE)), "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
217
218 /* One less gives us NULL */
219 Acl->AclSize = sizeof(ACL) + 2 * sizeof(ACE_HEADER) + 2 * sizeof(ACCESS_ALLOWED_ACE) - 1;
220 FirstAce = InvalidPointer;
221 Found = RtlFirstFreeAce(Acl, &FirstAce);
222 ok(Found == TRUE, "Found = %u\n", Found);
223 ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
224
225 /* One ACE less also gives us FALSE */
226 Acl->AclSize = sizeof(ACL) + 2 * sizeof(ACE_HEADER) + sizeof(ACCESS_ALLOWED_ACE);
227 FirstAce = InvalidPointer;
228 Found = RtlFirstFreeAce(Acl, &FirstAce);
229 ok(Found == FALSE, "Found = %u\n", Found);
230 ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
231
232 FreeGuarded(Acl);
233 }
234 }