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 "precomp.h"
9 
10 static
11 PACL
12 MakeAcl(
13     _In_ ULONG AceCount,
14     ...)
15 {
16     PACL Acl;
17     PACE_HEADER AceHeader;
18     ULONG AclSize;
19     ULONG AceSizes[10];
20     ULONG i;
21     va_list Args;
22 
23     ASSERT(AceCount <= RTL_NUMBER_OF(AceSizes));
24     AclSize = sizeof(ACL);
25     va_start(Args, AceCount);
26     for (i = 0; i < AceCount; i++)
27     {
28         AceSizes[i] = va_arg(Args, int);
29         AclSize += AceSizes[i];
30     }
31     va_end(Args);
32 
33     Acl = AllocateGuarded(AclSize);
34     if (!Acl)
35     {
36         skip("Failed to allocate %lu bytes\n", AclSize);
37         return NULL;
38     }
39 
40     Acl->AclRevision = ACL_REVISION;
41     Acl->Sbz1 = 0;
42     Acl->AclSize = AclSize;
43     Acl->AceCount = AceCount;
44     Acl->Sbz2 = 0;
45 
46     AceHeader = (PACE_HEADER)(Acl + 1);
47     for (i = 0; i < AceCount; i++)
48     {
49         AceHeader->AceType = 0;
50         AceHeader->AceFlags = 0;
51         AceHeader->AceSize = AceSizes[i];
52         AceHeader = (PACE_HEADER)((PCHAR)AceHeader + AceHeader->AceSize);
53     }
54 
55     return Acl;
56 }
57 
58 START_TEST(RtlFirstFreeAce)
59 {
60     PACL Acl;
61     PACE FirstAce;
62     BOOLEAN Found;
63 
64     Acl = MakeAcl(0);
65     if (Acl)
66     {
67         /* Simple empty ACL */
68         FirstAce = InvalidPointer;
69         Found = RtlFirstFreeAce(Acl, &FirstAce);
70         ok(Found == TRUE, "Found = %u\n", Found);
71         ok(FirstAce == (PACE)(Acl + 1), "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
72 
73         /* Not enough space */
74         Acl->AclSize = sizeof(ACL) - 1;
75         FirstAce = InvalidPointer;
76         Found = RtlFirstFreeAce(Acl, &FirstAce);
77         ok(Found == TRUE, "Found = %u\n", Found);
78         ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
79 
80         /* Invalid values for all the other fields */
81         Acl->AclRevision = 76;
82         Acl->Sbz1 = 0x55;
83         Acl->AclSize = sizeof(ACL);
84         Acl->Sbz2 = 0x55;
85         FirstAce = InvalidPointer;
86         Found = RtlFirstFreeAce(Acl, &FirstAce);
87         ok(Found == TRUE, "Found = %u\n", Found);
88         ok(FirstAce == (PACE)(Acl + 1), "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
89 
90         FreeGuarded(Acl);
91     }
92 
93     Acl = MakeAcl(1, (int)sizeof(ACE_HEADER));
94     if (Acl)
95     {
96         /* ACL with one ACE */
97         FirstAce = InvalidPointer;
98         Found = RtlFirstFreeAce(Acl, &FirstAce);
99         ok(Found == TRUE, "Found = %u\n", Found);
100         ok(FirstAce == (PACE)((PACE_HEADER)(Acl + 1) + 1), "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
101 
102         /* The one ACE doesn't actually fit */
103         Acl->AclSize = sizeof(ACL);
104         FirstAce = InvalidPointer;
105         Found = RtlFirstFreeAce(Acl, &FirstAce);
106         ok(Found == FALSE, "Found = %u\n", Found);
107         ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
108 
109         /* Only the first byte fits */
110         Acl->AclSize = sizeof(ACL) + 1;
111         FirstAce = InvalidPointer;
112         Found = RtlFirstFreeAce(Acl, &FirstAce);
113         ok(Found == TRUE, "Found = %u\n", Found);
114         ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
115 
116         /* Until we cover the whole size we get NULL */
117         Acl->AclSize = sizeof(ACL) + sizeof(ACE_HEADER) - 1;
118         FirstAce = InvalidPointer;
119         Found = RtlFirstFreeAce(Acl, &FirstAce);
120         ok(Found == TRUE, "Found = %u\n", Found);
121         ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
122 
123         FreeGuarded(Acl);
124     }
125 
126     /* Same but bigger */
127     Acl = MakeAcl(1, (int)sizeof(ACE_HEADER) + 4);
128     if (Acl)
129     {
130         /* ACL with one ACE */
131         FirstAce = InvalidPointer;
132         Found = RtlFirstFreeAce(Acl, &FirstAce);
133         ok(Found == TRUE, "Found = %u\n", Found);
134         ok(FirstAce == (PACE)((PCHAR)(Acl + 1) + sizeof(ACE_HEADER) + 4), "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
135 
136         /* The one ACE doesn't actually fit */
137         Acl->AclSize = sizeof(ACL);
138         FirstAce = InvalidPointer;
139         Found = RtlFirstFreeAce(Acl, &FirstAce);
140         ok(Found == FALSE, "Found = %u\n", Found);
141         ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
142 
143         /* Only the first byte fits */
144         Acl->AclSize = sizeof(ACL) + 1;
145         FirstAce = InvalidPointer;
146         Found = RtlFirstFreeAce(Acl, &FirstAce);
147         ok(Found == TRUE, "Found = %u\n", Found);
148         ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
149 
150         /* Until we cover the whole size we get NULL */
151         Acl->AclSize = sizeof(ACL) + sizeof(ACE_HEADER) - 3;
152         FirstAce = InvalidPointer;
153         Found = RtlFirstFreeAce(Acl, &FirstAce);
154         ok(Found == TRUE, "Found = %u\n", Found);
155         ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
156 
157         FreeGuarded(Acl);
158     }
159 
160     Acl = MakeAcl(4, (int)sizeof(ACE_HEADER), (int)sizeof(ACE_HEADER), (int)sizeof(ACCESS_ALLOWED_ACE), (int)sizeof(ACCESS_ALLOWED_ACE));
161     if (Acl)
162     {
163         /* ACL with one ACE */
164         FirstAce = InvalidPointer;
165         Found = RtlFirstFreeAce(Acl, &FirstAce);
166         ok(Found == TRUE, "Found = %u\n", Found);
167         ok(FirstAce == (PACE)((PCHAR)(Acl + 1) + 2 * sizeof(ACE_HEADER) + 2 * sizeof(ACCESS_ALLOWED_ACE)), "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
168 
169         /* One less gives us NULL */
170         Acl->AclSize = sizeof(ACL) + 2 * sizeof(ACE_HEADER) + 2 * sizeof(ACCESS_ALLOWED_ACE) - 1;
171         FirstAce = InvalidPointer;
172         Found = RtlFirstFreeAce(Acl, &FirstAce);
173         ok(Found == TRUE, "Found = %u\n", Found);
174         ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
175 
176         /* One ACE less also gives us FALSE */
177         Acl->AclSize = sizeof(ACL) + 2 * sizeof(ACE_HEADER) + sizeof(ACCESS_ALLOWED_ACE);
178         FirstAce = InvalidPointer;
179         Found = RtlFirstFreeAce(Acl, &FirstAce);
180         ok(Found == FALSE, "Found = %u\n", Found);
181         ok(FirstAce == NULL, "FirstAce = %p (Acl was %p)\n", FirstAce, Acl);
182 
183         FreeGuarded(Acl);
184     }
185 }
186