1 /*
2  * Unit tests for security functions
3  *
4  * Copyright (c) 2004 Mike McCormack
5  * Copyright (c) 2011,2013,2014,2016 Dmitry Timoshkov
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #include "precomp.h"
23 
24 /* FIXME: Inspect */
25 #define GetCurrentProcessToken() ((HANDLE)~(ULONG_PTR)3)
26 #define GetCurrentThreadToken() ((HANDLE)~(ULONG_PTR)4)
27 #define GetCurrentThreadEffectiveToken() ((HANDLE)~(ULONG_PTR)5)
28 
29 #ifndef PROCESS_QUERY_LIMITED_INFORMATION
30 #define PROCESS_QUERY_LIMITED_INFORMATION 0x1000
31 #endif
32 
33 /* PROCESS_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
34 #define PROCESS_ALL_ACCESS_NT4 (PROCESS_ALL_ACCESS & ~0xf000)
35 #define PROCESS_ALL_ACCESS_VISTA (PROCESS_ALL_ACCESS | 0xf000)
36 
37 #ifndef EVENT_QUERY_STATE
38 #define EVENT_QUERY_STATE 0x0001
39 #endif
40 
41 #ifndef SEMAPHORE_QUERY_STATE
42 #define SEMAPHORE_QUERY_STATE 0x0001
43 #endif
44 
45 #ifndef THREAD_SET_LIMITED_INFORMATION
46 #define THREAD_SET_LIMITED_INFORMATION 0x0400
47 #define THREAD_QUERY_LIMITED_INFORMATION 0x0800
48 #endif
49 
50 #define THREAD_ALL_ACCESS_NT4 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff)
51 #define THREAD_ALL_ACCESS_VISTA (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xffff)
52 
53 #define expect_eq(expr, value, type, format) { type ret_ = expr; ok((value) == ret_, #expr " expected " format "  got " format "\n", (value), (ret_)); }
54 
55 static BOOL (WINAPI *pAddAccessAllowedAceEx)(PACL, DWORD, DWORD, DWORD, PSID);
56 static BOOL (WINAPI *pAddAccessDeniedAceEx)(PACL, DWORD, DWORD, DWORD, PSID);
57 static BOOL (WINAPI *pAddAuditAccessAceEx)(PACL, DWORD, DWORD, DWORD, PSID, BOOL, BOOL);
58 static BOOL (WINAPI *pAddMandatoryAce)(PACL,DWORD,DWORD,DWORD,PSID);
59 static VOID (WINAPI *pBuildTrusteeWithSidA)( PTRUSTEEA pTrustee, PSID pSid );
60 static VOID (WINAPI *pBuildTrusteeWithNameA)( PTRUSTEEA pTrustee, LPSTR pName );
61 static VOID (WINAPI *pBuildTrusteeWithObjectsAndNameA)( PTRUSTEEA pTrustee,
62                                                           POBJECTS_AND_NAME_A pObjName,
63                                                           SE_OBJECT_TYPE ObjectType,
64                                                           LPSTR ObjectTypeName,
65                                                           LPSTR InheritedObjectTypeName,
66                                                           LPSTR Name );
67 static VOID (WINAPI *pBuildTrusteeWithObjectsAndSidA)( PTRUSTEEA pTrustee,
68                                                          POBJECTS_AND_SID pObjSid,
69                                                          GUID* pObjectGuid,
70                                                          GUID* pInheritedObjectGuid,
71                                                          PSID pSid );
72 static LPSTR (WINAPI *pGetTrusteeNameA)( PTRUSTEEA pTrustee );
73 static BOOL (WINAPI *pMakeSelfRelativeSD)( PSECURITY_DESCRIPTOR, PSECURITY_DESCRIPTOR, LPDWORD );
74 static BOOL (WINAPI *pConvertStringSidToSidA)( LPCSTR str, PSID pSid );
75 static BOOL (WINAPI *pCheckTokenMembership)(HANDLE, PSID, PBOOL);
76 static BOOL (WINAPI *pConvertStringSecurityDescriptorToSecurityDescriptorA)(LPCSTR, DWORD,
77                                                                             PSECURITY_DESCRIPTOR*, PULONG );
78 static BOOL (WINAPI *pConvertStringSecurityDescriptorToSecurityDescriptorW)(LPCWSTR, DWORD,
79                                                                             PSECURITY_DESCRIPTOR*, PULONG );
80 static BOOL (WINAPI *pConvertSecurityDescriptorToStringSecurityDescriptorA)(PSECURITY_DESCRIPTOR, DWORD,
81                                                                             SECURITY_INFORMATION, LPSTR *, PULONG );
82 static BOOL (WINAPI *pGetFileSecurityA)(LPCSTR, SECURITY_INFORMATION,
83                                           PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
84 static BOOL (WINAPI *pSetFileSecurityA)(LPCSTR, SECURITY_INFORMATION,
85                                           PSECURITY_DESCRIPTOR);
86 static DWORD (WINAPI *pGetNamedSecurityInfoA)(LPSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION,
87                                               PSID*, PSID*, PACL*, PACL*,
88                                               PSECURITY_DESCRIPTOR*);
89 static DWORD (WINAPI *pSetNamedSecurityInfoA)(LPSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION,
90                                               PSID, PSID, PACL, PACL);
91 static PDWORD (WINAPI *pGetSidSubAuthority)(PSID, DWORD);
92 static PUCHAR (WINAPI *pGetSidSubAuthorityCount)(PSID);
93 static BOOL (WINAPI *pIsValidSid)(PSID);
94 static DWORD (WINAPI *pRtlAdjustPrivilege)(ULONG,BOOLEAN,BOOLEAN,PBOOLEAN);
95 static BOOL (WINAPI *pCreateWellKnownSid)(WELL_KNOWN_SID_TYPE,PSID,PSID,DWORD*);
96 static BOOL (WINAPI *pDuplicateTokenEx)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES,
97                                         SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,PHANDLE);
98 
99 static NTSTATUS (WINAPI *pLsaQueryInformationPolicy)(LSA_HANDLE,POLICY_INFORMATION_CLASS,PVOID*);
100 static NTSTATUS (WINAPI *pLsaClose)(LSA_HANDLE);
101 static NTSTATUS (WINAPI *pLsaFreeMemory)(PVOID);
102 static NTSTATUS (WINAPI *pLsaOpenPolicy)(PLSA_UNICODE_STRING,PLSA_OBJECT_ATTRIBUTES,ACCESS_MASK,PLSA_HANDLE);
103 static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,ULONG,PULONG);
104 static DWORD (WINAPI *pSetEntriesInAclW)(ULONG, PEXPLICIT_ACCESSW, PACL, PACL*);
105 static DWORD (WINAPI *pSetEntriesInAclA)(ULONG, PEXPLICIT_ACCESSA, PACL, PACL*);
106 static BOOL (WINAPI *pSetSecurityDescriptorControl)(PSECURITY_DESCRIPTOR, SECURITY_DESCRIPTOR_CONTROL,
107                                                     SECURITY_DESCRIPTOR_CONTROL);
108 static DWORD (WINAPI *pGetSecurityInfo)(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
109                                         PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*);
110 static DWORD (WINAPI *pSetSecurityInfo)(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
111                                         PSID, PSID, PACL, PACL);
112 static NTSTATUS (WINAPI *pNtAccessCheck)(PSECURITY_DESCRIPTOR, HANDLE, ACCESS_MASK, PGENERIC_MAPPING,
113                                          PPRIVILEGE_SET, PULONG, PULONG, NTSTATUS*);
114 static BOOL (WINAPI *pCreateRestrictedToken)(HANDLE, DWORD, DWORD, PSID_AND_ATTRIBUTES, DWORD,
115                                              PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE);
116 static BOOL (WINAPI *pGetAclInformation)(PACL,LPVOID,DWORD,ACL_INFORMATION_CLASS);
117 static BOOL (WINAPI *pGetAce)(PACL,DWORD,LPVOID*);
118 static NTSTATUS (WINAPI *pNtSetSecurityObject)(HANDLE,SECURITY_INFORMATION,PSECURITY_DESCRIPTOR);
119 static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG);
120 static BOOL     (WINAPI *pRtlDosPathNameToNtPathName_U)(LPCWSTR,PUNICODE_STRING,PWSTR*,CURDIR*);
121 static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING,PCANSI_STRING,BOOLEAN);
122 static BOOL     (WINAPI *pGetWindowsAccountDomainSid)(PSID,PSID,DWORD*);
123 static void     (WINAPI *pRtlInitAnsiString)(PANSI_STRING,PCSZ);
124 static NTSTATUS (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
125 static PSID_IDENTIFIER_AUTHORITY (WINAPI *pGetSidIdentifierAuthority)(PSID);
126 static DWORD    (WINAPI *pGetExplicitEntriesFromAclW)(PACL,PULONG,PEXPLICIT_ACCESSW*);
127 
128 static HMODULE hmod;
129 static int     myARGC;
130 static char**  myARGV;
131 
132 #define SID_SLOTS 4
133 static char debugsid_str[SID_SLOTS][256];
134 static int debugsid_index = 0;
135 static const char* debugstr_sid(PSID sid)
136 {
137     LPSTR sidstr;
138     DWORD le = GetLastError();
139     char* res = debugsid_str[debugsid_index];
140     debugsid_index = (debugsid_index + 1) % SID_SLOTS;
141 
142     if (!ConvertSidToStringSidA(sid, &sidstr))
143         sprintf(res, "ConvertSidToStringSidA failed le=%u", GetLastError());
144     else if (strlen(sidstr) > sizeof(*debugsid_str) - 1)
145     {
146         memcpy(res, sidstr, sizeof(*debugsid_str) - 4);
147         strcpy(res + sizeof(*debugsid_str) - 4, "...");
148         LocalFree(sidstr);
149     }
150     else
151     {
152         strcpy(res, sidstr);
153         LocalFree(sidstr);
154     }
155     /* Restore the last error in case ConvertSidToStringSidA() modified it */
156     SetLastError(le);
157     return res;
158 }
159 
160 static void init(void)
161 {
162     HMODULE hntdll;
163 
164     hntdll = GetModuleHandleA("ntdll.dll");
165     pNtQueryObject = (void *)GetProcAddress( hntdll, "NtQueryObject" );
166     pNtAccessCheck = (void *)GetProcAddress( hntdll, "NtAccessCheck" );
167     pNtSetSecurityObject = (void *)GetProcAddress(hntdll, "NtSetSecurityObject");
168     pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile");
169     pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
170     pRtlAnsiStringToUnicodeString = (void *)GetProcAddress(hntdll, "RtlAnsiStringToUnicodeString");
171     pRtlInitAnsiString = (void *)GetProcAddress(hntdll, "RtlInitAnsiString");
172     pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
173 
174     hmod = GetModuleHandleA("advapi32.dll");
175     pAddAccessAllowedAceEx = (void *)GetProcAddress(hmod, "AddAccessAllowedAceEx");
176     pAddAccessDeniedAceEx = (void *)GetProcAddress(hmod, "AddAccessDeniedAceEx");
177     pAddAuditAccessAceEx = (void *)GetProcAddress(hmod, "AddAuditAccessAceEx");
178     pAddMandatoryAce = (void *)GetProcAddress(hmod, "AddMandatoryAce");
179     pCheckTokenMembership = (void *)GetProcAddress(hmod, "CheckTokenMembership");
180     pConvertStringSecurityDescriptorToSecurityDescriptorA =
181         (void *)GetProcAddress(hmod, "ConvertStringSecurityDescriptorToSecurityDescriptorA" );
182     pConvertStringSecurityDescriptorToSecurityDescriptorW =
183         (void *)GetProcAddress(hmod, "ConvertStringSecurityDescriptorToSecurityDescriptorW" );
184     pConvertSecurityDescriptorToStringSecurityDescriptorA =
185         (void *)GetProcAddress(hmod, "ConvertSecurityDescriptorToStringSecurityDescriptorA" );
186     pGetFileSecurityA = (void *)GetProcAddress(hmod, "GetFileSecurityA" );
187     pSetFileSecurityA = (void *)GetProcAddress(hmod, "SetFileSecurityA" );
188     pCreateWellKnownSid = (void *)GetProcAddress( hmod, "CreateWellKnownSid" );
189     pGetNamedSecurityInfoA = (void *)GetProcAddress(hmod, "GetNamedSecurityInfoA");
190     pSetNamedSecurityInfoA = (void *)GetProcAddress(hmod, "SetNamedSecurityInfoA");
191     pGetSidSubAuthority = (void *)GetProcAddress(hmod, "GetSidSubAuthority");
192     pGetSidSubAuthorityCount = (void *)GetProcAddress(hmod, "GetSidSubAuthorityCount");
193     pIsValidSid = (void *)GetProcAddress(hmod, "IsValidSid");
194     pMakeSelfRelativeSD = (void *)GetProcAddress(hmod, "MakeSelfRelativeSD");
195     pSetEntriesInAclW = (void *)GetProcAddress(hmod, "SetEntriesInAclW");
196     pSetEntriesInAclA = (void *)GetProcAddress(hmod, "SetEntriesInAclA");
197     pSetSecurityDescriptorControl = (void *)GetProcAddress(hmod, "SetSecurityDescriptorControl");
198     pGetSecurityInfo = (void *)GetProcAddress(hmod, "GetSecurityInfo");
199     pSetSecurityInfo = (void *)GetProcAddress(hmod, "SetSecurityInfo");
200     pCreateRestrictedToken = (void *)GetProcAddress(hmod, "CreateRestrictedToken");
201     pConvertStringSidToSidA = (void *)GetProcAddress(hmod, "ConvertStringSidToSidA");
202     pGetAclInformation = (void *)GetProcAddress(hmod, "GetAclInformation");
203     pGetAce = (void *)GetProcAddress(hmod, "GetAce");
204     pGetWindowsAccountDomainSid = (void *)GetProcAddress(hmod, "GetWindowsAccountDomainSid");
205     pGetSidIdentifierAuthority = (void *)GetProcAddress(hmod, "GetSidIdentifierAuthority");
206     pDuplicateTokenEx = (void *)GetProcAddress(hmod, "DuplicateTokenEx");
207     pGetExplicitEntriesFromAclW = (void *)GetProcAddress(hmod, "GetExplicitEntriesFromAclW");
208 
209     myARGC = winetest_get_mainargs( &myARGV );
210 }
211 
212 static SECURITY_DESCRIPTOR* test_get_security_descriptor(HANDLE handle, int line)
213 {
214     /* use HeapFree(GetProcessHeap(), 0, sd); when done */
215     DWORD ret, length, needed;
216     SECURITY_DESCRIPTOR *sd;
217 
218     needed = 0xdeadbeef;
219     SetLastError(0xdeadbeef);
220     ret = GetKernelObjectSecurity(handle, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
221                                   NULL, 0, &needed);
222     ok_(__FILE__, line)(!ret, "GetKernelObjectSecurity should fail\n");
223     ok_(__FILE__, line)(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
224     ok_(__FILE__, line)(needed != 0xdeadbeef, "GetKernelObjectSecurity should return required buffer length\n");
225 
226     length = needed;
227     sd = HeapAlloc(GetProcessHeap(), 0, length);
228 
229     needed = 0xdeadbeef;
230     SetLastError(0xdeadbeef);
231     ret = GetKernelObjectSecurity(handle, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
232                                   sd, length, &needed);
233     ok_(__FILE__, line)(ret, "GetKernelObjectSecurity error %d\n", GetLastError());
234     ok_(__FILE__, line)(needed == length || needed == 0 /* file, pipe */, "GetKernelObjectSecurity should return %u instead of %u\n", length, needed);
235     return sd;
236 }
237 
238 static void test_owner_equal(HANDLE Handle, PSID expected, int line)
239 {
240     BOOL res;
241     SECURITY_DESCRIPTOR *queriedSD = NULL;
242     PSID owner;
243     BOOL owner_defaulted;
244 
245     queriedSD = test_get_security_descriptor( Handle, line );
246 
247     res = GetSecurityDescriptorOwner(queriedSD, &owner, &owner_defaulted);
248     ok_(__FILE__, line)(res, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
249 
250     ok_(__FILE__, line)(EqualSid(owner, expected), "Owner SIDs are not equal %s != %s\n",
251                         debugstr_sid(owner), debugstr_sid(expected));
252     ok_(__FILE__, line)(!owner_defaulted, "Defaulted is true\n");
253 
254     HeapFree(GetProcessHeap(), 0, queriedSD);
255 }
256 
257 static void test_group_equal(HANDLE Handle, PSID expected, int line)
258 {
259     BOOL res;
260     SECURITY_DESCRIPTOR *queriedSD = NULL;
261     PSID group;
262     BOOL group_defaulted;
263 
264     queriedSD = test_get_security_descriptor( Handle, line );
265 
266     res = GetSecurityDescriptorGroup(queriedSD, &group, &group_defaulted);
267     ok_(__FILE__, line)(res, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
268 
269     ok_(__FILE__, line)(EqualSid(group, expected), "Group SIDs are not equal %s != %s\n",
270                         debugstr_sid(group), debugstr_sid(expected));
271     ok_(__FILE__, line)(!group_defaulted, "Defaulted is true\n");
272 
273     HeapFree(GetProcessHeap(), 0, queriedSD);
274 }
275 
276 static void test_sid(void)
277 {
278     static struct
279     {
280         SID_IDENTIFIER_AUTHORITY auth;
281         const char *refStr;
282     } refs[] = {
283      { { {0x00,0x00,0x33,0x44,0x55,0x66} }, "S-1-860116326-1" },
284      { { {0x00,0x00,0x01,0x02,0x03,0x04} }, "S-1-16909060-1"  },
285      { { {0x00,0x00,0x00,0x01,0x02,0x03} }, "S-1-66051-1"     },
286      { { {0x00,0x00,0x00,0x00,0x01,0x02} }, "S-1-258-1"       },
287      { { {0x00,0x00,0x00,0x00,0x00,0x02} }, "S-1-2-1"         },
288      { { {0x00,0x00,0x00,0x00,0x00,0x0c} }, "S-1-12-1"        },
289     };
290     static const struct
291     {
292         const char *str;
293         WELL_KNOWN_SID_TYPE sid_type;
294         BOOL optional;
295     } strsid_table[] = {
296         /* Please keep the list sorted. */
297         { "AC", WinBuiltinAnyPackageSid, TRUE },
298         { "AN", WinAnonymousSid },
299         { "AO", WinBuiltinAccountOperatorsSid },
300         { "AU", WinAuthenticatedUserSid },
301         { "BA", WinBuiltinAdministratorsSid },
302         { "BG", WinBuiltinGuestsSid },
303         { "BO", WinBuiltinBackupOperatorsSid },
304         { "BU", WinBuiltinUsersSid },
305         { "CA", WinAccountCertAdminsSid, TRUE},
306         { "CG", WinCreatorGroupSid },
307         { "CO", WinCreatorOwnerSid },
308         { "DA", WinAccountDomainAdminsSid, TRUE},
309         { "DC", WinAccountComputersSid, TRUE},
310         { "DD", WinAccountControllersSid, TRUE},
311         { "DG", WinAccountDomainGuestsSid, TRUE},
312         { "DU", WinAccountDomainUsersSid, TRUE},
313         { "EA", WinAccountEnterpriseAdminsSid, TRUE},
314         { "ED", WinEnterpriseControllersSid },
315         { "IU", WinInteractiveSid },
316         { "LA", WinAccountAdministratorSid },
317         { "LG", WinAccountGuestSid },
318         { "LS", WinLocalServiceSid },
319         { "NO", WinBuiltinNetworkConfigurationOperatorsSid },
320         { "NS", WinNetworkServiceSid },
321         { "NU", WinNetworkSid },
322         { "PA", WinAccountPolicyAdminsSid, TRUE},
323         { "PO", WinBuiltinPrintOperatorsSid },
324         { "PS", WinSelfSid },
325         { "PU", WinBuiltinPowerUsersSid },
326         { "RC", WinRestrictedCodeSid },
327         { "RD", WinBuiltinRemoteDesktopUsersSid },
328         { "RE", WinBuiltinReplicatorSid },
329         { "RS", WinAccountRasAndIasServersSid, TRUE },
330         { "RU", WinBuiltinPreWindows2000CompatibleAccessSid },
331         { "SA", WinAccountSchemaAdminsSid, TRUE },
332         { "SO", WinBuiltinSystemOperatorsSid },
333         { "SU", WinServiceSid },
334         { "SY", WinLocalSystemSid },
335         { "WD", WinWorldSid },
336     };
337     SID_IDENTIFIER_AUTHORITY domain_ident = { SECURITY_NT_AUTHORITY };
338     const char noSubAuthStr[] = "S-1-5";
339     unsigned int i;
340     PSID psid, domain_sid;
341     SID *pisid;
342     BOOL r;
343     LPSTR str;
344 
345     if( !pConvertStringSidToSidA )
346     {
347         win_skip("ConvertSidToStringSidA or ConvertStringSidToSidA not available\n");
348         return;
349     }
350 
351     r = pConvertStringSidToSidA( NULL, NULL );
352     ok( !r, "expected failure with NULL parameters\n" );
353     if( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED )
354         return;
355     ok( GetLastError() == ERROR_INVALID_PARAMETER,
356      "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n",
357      GetLastError() );
358 
359     r = pConvertStringSidToSidA( refs[0].refStr, NULL );
360     ok( !r && GetLastError() == ERROR_INVALID_PARAMETER,
361      "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n",
362      GetLastError() );
363 
364     r = pConvertStringSidToSidA( NULL, &str );
365     ok( !r && GetLastError() == ERROR_INVALID_PARAMETER,
366      "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n",
367      GetLastError() );
368 
369     r = pConvertStringSidToSidA( noSubAuthStr, &psid );
370     ok( !r,
371      "expected failure with no sub authorities\n" );
372     ok( GetLastError() == ERROR_INVALID_SID,
373      "expected GetLastError() is ERROR_INVALID_SID, got %d\n",
374      GetLastError() );
375 
376     ok(pConvertStringSidToSidA("S-1-5-21-93476-23408-4576", &psid), "ConvertStringSidToSidA failed\n");
377     pisid = psid;
378     ok(pisid->SubAuthorityCount == 4, "Invalid sub authority count - expected 4, got %d\n", pisid->SubAuthorityCount);
379     ok(pisid->SubAuthority[0] == 21, "Invalid subauthority 0 - expected 21, got %d\n", pisid->SubAuthority[0]);
380     ok(pisid->SubAuthority[3] == 4576, "Invalid subauthority 0 - expected 4576, got %d\n", pisid->SubAuthority[3]);
381     LocalFree(str);
382     LocalFree(psid);
383 
384     for( i = 0; i < sizeof(refs) / sizeof(refs[0]); i++ )
385     {
386         r = AllocateAndInitializeSid( &refs[i].auth, 1,1,0,0,0,0,0,0,0,
387          &psid );
388         ok( r, "failed to allocate sid\n" );
389         r = ConvertSidToStringSidA( psid, &str );
390         ok( r, "failed to convert sid\n" );
391         if (r)
392         {
393             ok( !strcmp( str, refs[i].refStr ),
394                 "incorrect sid, expected %s, got %s\n", refs[i].refStr, str );
395             LocalFree( str );
396         }
397         if( psid )
398             FreeSid( psid );
399 
400         r = pConvertStringSidToSidA( refs[i].refStr, &psid );
401         ok( r, "failed to parse sid string\n" );
402         pisid = psid;
403         ok( pisid &&
404          !memcmp( pisid->IdentifierAuthority.Value, refs[i].auth.Value,
405          sizeof(refs[i].auth) ),
406          "string sid %s didn't parse to expected value\n"
407          "(got 0x%04x%08x, expected 0x%04x%08x)\n",
408          refs[i].refStr,
409          MAKEWORD( pisid->IdentifierAuthority.Value[1],
410          pisid->IdentifierAuthority.Value[0] ),
411          MAKELONG( MAKEWORD( pisid->IdentifierAuthority.Value[5],
412          pisid->IdentifierAuthority.Value[4] ),
413          MAKEWORD( pisid->IdentifierAuthority.Value[3],
414          pisid->IdentifierAuthority.Value[2] ) ),
415          MAKEWORD( refs[i].auth.Value[1], refs[i].auth.Value[0] ),
416          MAKELONG( MAKEWORD( refs[i].auth.Value[5], refs[i].auth.Value[4] ),
417          MAKEWORD( refs[i].auth.Value[3], refs[i].auth.Value[2] ) ) );
418         if( psid )
419             LocalFree( psid );
420     }
421 
422     /* string constant format not supported before XP */
423     r = pConvertStringSidToSidA("AN", &psid);
424     if(!r)
425     {
426         win_skip("String constant format not supported\n");
427         return;
428     }
429     LocalFree(psid);
430 
431     AllocateAndInitializeSid(&domain_ident, 4, SECURITY_NT_NON_UNIQUE, 0, 0, 0, 0, 0, 0, 0, &domain_sid);
432 
433     for(i = 0; i < sizeof(strsid_table) / sizeof(strsid_table[0]); i++)
434     {
435         SetLastError(0xdeadbeef);
436         r = pConvertStringSidToSidA(strsid_table[i].str, &psid);
437 
438         if (!(strsid_table[i].optional))
439         {
440             ok(r, "%s: got %u\n", strsid_table[i].str, GetLastError());
441         }
442 
443         if (r)
444         {
445             char buf[SECURITY_MAX_SID_SIZE];
446             char *sid_string, *well_known_sid_string;
447             DWORD n, size;
448 
449             /* zero out domain id before comparison to simplify things */
450             if (strsid_table[i].sid_type == WinAccountAdministratorSid ||
451                 strsid_table[i].sid_type == WinAccountGuestSid)
452             {
453                 for (n = 1; n <= 3; n++)
454                     *GetSidSubAuthority(psid, n) = 0;
455             }
456 
457             r = ConvertSidToStringSidA(psid, &sid_string);
458             ok(r, "%s: ConvertSidToStringSid error %u\n", strsid_table[i].str, GetLastError());
459             if (winetest_debug > 1)
460                 trace("%s => %s\n", strsid_table[i].str, sid_string);
461 
462             size = sizeof(buf);
463             r = pCreateWellKnownSid(strsid_table[i].sid_type, domain_sid, buf, &size);
464             ok(r, "%u: CreateWellKnownSid(%u) error %u\n", i, strsid_table[i].sid_type, GetLastError());
465 
466             r = ConvertSidToStringSidA(buf, &well_known_sid_string);
467             ok(r, "%u: ConvertSidToStringSi(%u) error %u\n", i, strsid_table[i].sid_type, GetLastError());
468             if (winetest_debug > 1)
469                 trace("%u => %s\n", strsid_table[i].sid_type, well_known_sid_string);
470 
471             ok(strcmp(sid_string, well_known_sid_string) == 0,
472                "%u: (%u) expected %s, got %s\n", i, strsid_table[i].sid_type, well_known_sid_string, sid_string);
473 
474             LocalFree(well_known_sid_string);
475             LocalFree(sid_string);
476             LocalFree(psid);
477         }
478         else
479         {
480             if (GetLastError() != ERROR_INVALID_SID)
481                 trace(" %s: couldn't be converted, returned %d\n", strsid_table[i].str, GetLastError());
482             else
483                 trace(" %s: couldn't be converted\n", strsid_table[i].str);
484         }
485     }
486 
487     LocalFree(domain_sid);
488 }
489 
490 static void test_trustee(void)
491 {
492     GUID ObjectType = {0x12345678, 0x1234, 0x5678, {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}};
493     GUID InheritedObjectType = {0x23456789, 0x2345, 0x6786, {0x2, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}};
494     GUID ZeroGuid;
495     OBJECTS_AND_NAME_A oan;
496     OBJECTS_AND_SID oas;
497     TRUSTEEA trustee;
498     PSID psid;
499     char szObjectTypeName[] = "ObjectTypeName";
500     char szInheritedObjectTypeName[] = "InheritedObjectTypeName";
501     char szTrusteeName[] = "szTrusteeName";
502     SID_IDENTIFIER_AUTHORITY auth = { {0x11,0x22,0,0,0, 0} };
503 
504     memset( &ZeroGuid, 0x00, sizeof (ZeroGuid) );
505 
506     pBuildTrusteeWithSidA = (void *)GetProcAddress( hmod, "BuildTrusteeWithSidA" );
507     pBuildTrusteeWithNameA = (void *)GetProcAddress( hmod, "BuildTrusteeWithNameA" );
508     pBuildTrusteeWithObjectsAndNameA = (void *)GetProcAddress (hmod, "BuildTrusteeWithObjectsAndNameA" );
509     pBuildTrusteeWithObjectsAndSidA = (void *)GetProcAddress (hmod, "BuildTrusteeWithObjectsAndSidA" );
510     pGetTrusteeNameA = (void *)GetProcAddress (hmod, "GetTrusteeNameA" );
511     if( !pBuildTrusteeWithSidA || !pBuildTrusteeWithNameA ||
512         !pBuildTrusteeWithObjectsAndNameA || !pBuildTrusteeWithObjectsAndSidA ||
513         !pGetTrusteeNameA )
514         return;
515 
516     if ( ! AllocateAndInitializeSid( &auth, 1, 42, 0,0,0,0,0,0,0,&psid ) )
517     {
518         trace( "failed to init SID\n" );
519        return;
520     }
521 
522     /* test BuildTrusteeWithSidA */
523     memset( &trustee, 0xff, sizeof trustee );
524     pBuildTrusteeWithSidA( &trustee, psid );
525 
526     ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
527     ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE,
528         "MultipleTrusteeOperation wrong\n");
529     ok( trustee.TrusteeForm == TRUSTEE_IS_SID, "TrusteeForm wrong\n");
530     ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
531     ok( trustee.ptstrName == psid, "ptstrName wrong\n" );
532 
533     /* test BuildTrusteeWithObjectsAndSidA (test 1) */
534     memset( &trustee, 0xff, sizeof trustee );
535     memset( &oas, 0xff, sizeof(oas) );
536     pBuildTrusteeWithObjectsAndSidA(&trustee, &oas, &ObjectType,
537                                     &InheritedObjectType, psid);
538 
539     ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
540     ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
541     ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_SID, "TrusteeForm wrong\n");
542     ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
543     ok(trustee.ptstrName == (LPSTR)&oas, "ptstrName wrong\n");
544 
545     ok(oas.ObjectsPresent == (ACE_OBJECT_TYPE_PRESENT | ACE_INHERITED_OBJECT_TYPE_PRESENT), "ObjectsPresent wrong\n");
546     ok(!memcmp(&oas.ObjectTypeGuid, &ObjectType, sizeof(GUID)), "ObjectTypeGuid wrong\n");
547     ok(!memcmp(&oas.InheritedObjectTypeGuid, &InheritedObjectType, sizeof(GUID)), "InheritedObjectTypeGuid wrong\n");
548     ok(oas.pSid == psid, "pSid wrong\n");
549 
550     /* test GetTrusteeNameA */
551     ok(pGetTrusteeNameA(&trustee) == (LPSTR)&oas, "GetTrusteeName returned wrong value\n");
552 
553     /* test BuildTrusteeWithObjectsAndSidA (test 2) */
554     memset( &trustee, 0xff, sizeof trustee );
555     memset( &oas, 0xff, sizeof(oas) );
556     pBuildTrusteeWithObjectsAndSidA(&trustee, &oas, NULL,
557                                     &InheritedObjectType, psid);
558 
559     ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
560     ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
561     ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_SID, "TrusteeForm wrong\n");
562     ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
563     ok(trustee.ptstrName == (LPSTR)&oas, "ptstrName wrong\n");
564 
565     ok(oas.ObjectsPresent == ACE_INHERITED_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
566     ok(!memcmp(&oas.ObjectTypeGuid, &ZeroGuid, sizeof(GUID)), "ObjectTypeGuid wrong\n");
567     ok(!memcmp(&oas.InheritedObjectTypeGuid, &InheritedObjectType, sizeof(GUID)), "InheritedObjectTypeGuid wrong\n");
568     ok(oas.pSid == psid, "pSid wrong\n");
569 
570     FreeSid( psid );
571 
572     /* test BuildTrusteeWithNameA */
573     memset( &trustee, 0xff, sizeof trustee );
574     pBuildTrusteeWithNameA( &trustee, szTrusteeName );
575 
576     ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
577     ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE,
578         "MultipleTrusteeOperation wrong\n");
579     ok( trustee.TrusteeForm == TRUSTEE_IS_NAME, "TrusteeForm wrong\n");
580     ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
581     ok( trustee.ptstrName == szTrusteeName, "ptstrName wrong\n" );
582 
583     /* test BuildTrusteeWithObjectsAndNameA (test 1) */
584     memset( &trustee, 0xff, sizeof trustee );
585     memset( &oan, 0xff, sizeof(oan) );
586     pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, szObjectTypeName,
587                                      szInheritedObjectTypeName, szTrusteeName);
588 
589     ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
590     ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
591     ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
592     ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
593     ok(trustee.ptstrName == (LPSTR)&oan, "ptstrName wrong\n");
594 
595     ok(oan.ObjectsPresent == (ACE_OBJECT_TYPE_PRESENT | ACE_INHERITED_OBJECT_TYPE_PRESENT), "ObjectsPresent wrong\n");
596     ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
597     ok(oan.InheritedObjectTypeName == szInheritedObjectTypeName, "InheritedObjectTypeName wrong\n");
598     ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
599 
600     /* test GetTrusteeNameA */
601     ok(pGetTrusteeNameA(&trustee) == (LPSTR)&oan, "GetTrusteeName returned wrong value\n");
602 
603     /* test BuildTrusteeWithObjectsAndNameA (test 2) */
604     memset( &trustee, 0xff, sizeof trustee );
605     memset( &oan, 0xff, sizeof(oan) );
606     pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, NULL,
607                                      szInheritedObjectTypeName, szTrusteeName);
608 
609     ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
610     ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
611     ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
612     ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
613     ok(trustee.ptstrName == (LPSTR)&oan, "ptstrName wrong\n");
614 
615     ok(oan.ObjectsPresent == ACE_INHERITED_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
616     ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
617     ok(oan.InheritedObjectTypeName == szInheritedObjectTypeName, "InheritedObjectTypeName wrong\n");
618     ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
619 
620     /* test BuildTrusteeWithObjectsAndNameA (test 3) */
621     memset( &trustee, 0xff, sizeof trustee );
622     memset( &oan, 0xff, sizeof(oan) );
623     pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, szObjectTypeName,
624                                      NULL, szTrusteeName);
625 
626     ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
627     ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
628     ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
629     ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
630     ok(trustee.ptstrName == (LPSTR)&oan, "ptstrName wrong\n");
631 
632     ok(oan.ObjectsPresent == ACE_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
633     ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
634     ok(oan.InheritedObjectTypeName == NULL, "InheritedObjectTypeName wrong\n");
635     ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
636 }
637 
638 /* If the first isn't defined, assume none is */
639 #ifndef SE_MIN_WELL_KNOWN_PRIVILEGE
640 #define SE_MIN_WELL_KNOWN_PRIVILEGE       2L
641 #define SE_CREATE_TOKEN_PRIVILEGE         2L
642 #define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE   3L
643 #define SE_LOCK_MEMORY_PRIVILEGE          4L
644 #define SE_INCREASE_QUOTA_PRIVILEGE       5L
645 #define SE_MACHINE_ACCOUNT_PRIVILEGE      6L
646 #define SE_TCB_PRIVILEGE                  7L
647 #define SE_SECURITY_PRIVILEGE             8L
648 #define SE_TAKE_OWNERSHIP_PRIVILEGE       9L
649 #define SE_LOAD_DRIVER_PRIVILEGE         10L
650 #define SE_SYSTEM_PROFILE_PRIVILEGE      11L
651 #define SE_SYSTEMTIME_PRIVILEGE          12L
652 #define SE_PROF_SINGLE_PROCESS_PRIVILEGE 13L
653 #define SE_INC_BASE_PRIORITY_PRIVILEGE   14L
654 #define SE_CREATE_PAGEFILE_PRIVILEGE     15L
655 #define SE_CREATE_PERMANENT_PRIVILEGE    16L
656 #define SE_BACKUP_PRIVILEGE              17L
657 #define SE_RESTORE_PRIVILEGE             18L
658 #define SE_SHUTDOWN_PRIVILEGE            19L
659 #define SE_DEBUG_PRIVILEGE               20L
660 #define SE_AUDIT_PRIVILEGE               21L
661 #define SE_SYSTEM_ENVIRONMENT_PRIVILEGE  22L
662 #define SE_CHANGE_NOTIFY_PRIVILEGE       23L
663 #define SE_REMOTE_SHUTDOWN_PRIVILEGE     24L
664 #define SE_UNDOCK_PRIVILEGE              25L
665 #define SE_SYNC_AGENT_PRIVILEGE          26L
666 #define SE_ENABLE_DELEGATION_PRIVILEGE   27L
667 #define SE_MANAGE_VOLUME_PRIVILEGE       28L
668 #define SE_IMPERSONATE_PRIVILEGE         29L
669 #define SE_CREATE_GLOBAL_PRIVILEGE       30L
670 #define SE_MAX_WELL_KNOWN_PRIVILEGE      SE_CREATE_GLOBAL_PRIVILEGE
671 #endif /* ndef SE_MIN_WELL_KNOWN_PRIVILEGE */
672 
673 static void test_allocateLuid(void)
674 {
675     BOOL (WINAPI *pAllocateLocallyUniqueId)(PLUID);
676     LUID luid1, luid2;
677     BOOL ret;
678 
679     pAllocateLocallyUniqueId = (void*)GetProcAddress(hmod, "AllocateLocallyUniqueId");
680     if (!pAllocateLocallyUniqueId) return;
681 
682     ret = pAllocateLocallyUniqueId(&luid1);
683     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
684         return;
685 
686     ok(ret,
687      "AllocateLocallyUniqueId failed: %d\n", GetLastError());
688     ret = pAllocateLocallyUniqueId(&luid2);
689     ok( ret,
690      "AllocateLocallyUniqueId failed: %d\n", GetLastError());
691     ok(luid1.LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE || luid1.HighPart != 0,
692      "AllocateLocallyUniqueId returned a well-known LUID\n");
693     ok(luid1.LowPart != luid2.LowPart || luid1.HighPart != luid2.HighPart,
694      "AllocateLocallyUniqueId returned non-unique LUIDs\n");
695     ret = pAllocateLocallyUniqueId(NULL);
696     ok( !ret && GetLastError() == ERROR_NOACCESS,
697      "AllocateLocallyUniqueId(NULL) didn't return ERROR_NOACCESS: %d\n",
698      GetLastError());
699 }
700 
701 static void test_lookupPrivilegeName(void)
702 {
703     BOOL (WINAPI *pLookupPrivilegeNameA)(LPCSTR, PLUID, LPSTR, LPDWORD);
704     char buf[MAX_PATH]; /* arbitrary, seems long enough */
705     DWORD cchName = sizeof(buf);
706     LUID luid = { 0, 0 };
707     LONG i;
708     BOOL ret;
709 
710     /* check whether it's available first */
711     pLookupPrivilegeNameA = (void*)GetProcAddress(hmod, "LookupPrivilegeNameA");
712     if (!pLookupPrivilegeNameA) return;
713     luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
714     ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
715     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
716         return;
717 
718     /* check with a short buffer */
719     cchName = 0;
720     luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
721     ret = pLookupPrivilegeNameA(NULL, &luid, NULL, &cchName);
722     ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
723      "LookupPrivilegeNameA didn't fail with ERROR_INSUFFICIENT_BUFFER: %d\n",
724      GetLastError());
725     ok(cchName == strlen("SeCreateTokenPrivilege") + 1,
726      "LookupPrivilegeNameA returned an incorrect required length for\n"
727      "SeCreateTokenPrivilege (got %d, expected %d)\n", cchName,
728      lstrlenA("SeCreateTokenPrivilege") + 1);
729     /* check a known value and its returned length on success */
730     cchName = sizeof(buf);
731     ok(pLookupPrivilegeNameA(NULL, &luid, buf, &cchName) &&
732      cchName == strlen("SeCreateTokenPrivilege"),
733      "LookupPrivilegeNameA returned an incorrect output length for\n"
734      "SeCreateTokenPrivilege (got %d, expected %d)\n", cchName,
735      (int)strlen("SeCreateTokenPrivilege"));
736     /* check known values */
737     for (i = SE_MIN_WELL_KNOWN_PRIVILEGE; i <= SE_MAX_WELL_KNOWN_PRIVILEGE; i++)
738     {
739         luid.LowPart = i;
740         cchName = sizeof(buf);
741         ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
742         ok( ret || GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
743          "LookupPrivilegeNameA(0.%d) failed: %d\n", i, GetLastError());
744     }
745     /* check a bogus LUID */
746     luid.LowPart = 0xdeadbeef;
747     cchName = sizeof(buf);
748     ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
749     ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
750      "LookupPrivilegeNameA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n",
751      GetLastError());
752     /* check on a bogus system */
753     luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
754     cchName = sizeof(buf);
755     ret = pLookupPrivilegeNameA("b0gu5.Nam3", &luid, buf, &cchName);
756     ok( !ret && (GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
757                  GetLastError() == RPC_S_INVALID_NET_ADDR) /* w2k8 */,
758      "LookupPrivilegeNameA didn't fail with RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR: %d\n",
759      GetLastError());
760 }
761 
762 struct NameToLUID
763 {
764     const char *name;
765     DWORD lowPart;
766 };
767 
768 static void test_lookupPrivilegeValue(void)
769 {
770     static const struct NameToLUID privs[] = {
771      { "SeCreateTokenPrivilege", SE_CREATE_TOKEN_PRIVILEGE },
772      { "SeAssignPrimaryTokenPrivilege", SE_ASSIGNPRIMARYTOKEN_PRIVILEGE },
773      { "SeLockMemoryPrivilege", SE_LOCK_MEMORY_PRIVILEGE },
774      { "SeIncreaseQuotaPrivilege", SE_INCREASE_QUOTA_PRIVILEGE },
775      { "SeMachineAccountPrivilege", SE_MACHINE_ACCOUNT_PRIVILEGE },
776      { "SeTcbPrivilege", SE_TCB_PRIVILEGE },
777      { "SeSecurityPrivilege", SE_SECURITY_PRIVILEGE },
778      { "SeTakeOwnershipPrivilege", SE_TAKE_OWNERSHIP_PRIVILEGE },
779      { "SeLoadDriverPrivilege", SE_LOAD_DRIVER_PRIVILEGE },
780      { "SeSystemProfilePrivilege", SE_SYSTEM_PROFILE_PRIVILEGE },
781      { "SeSystemtimePrivilege", SE_SYSTEMTIME_PRIVILEGE },
782      { "SeProfileSingleProcessPrivilege", SE_PROF_SINGLE_PROCESS_PRIVILEGE },
783      { "SeIncreaseBasePriorityPrivilege", SE_INC_BASE_PRIORITY_PRIVILEGE },
784      { "SeCreatePagefilePrivilege", SE_CREATE_PAGEFILE_PRIVILEGE },
785      { "SeCreatePermanentPrivilege", SE_CREATE_PERMANENT_PRIVILEGE },
786      { "SeBackupPrivilege", SE_BACKUP_PRIVILEGE },
787      { "SeRestorePrivilege", SE_RESTORE_PRIVILEGE },
788      { "SeShutdownPrivilege", SE_SHUTDOWN_PRIVILEGE },
789      { "SeDebugPrivilege", SE_DEBUG_PRIVILEGE },
790      { "SeAuditPrivilege", SE_AUDIT_PRIVILEGE },
791      { "SeSystemEnvironmentPrivilege", SE_SYSTEM_ENVIRONMENT_PRIVILEGE },
792      { "SeChangeNotifyPrivilege", SE_CHANGE_NOTIFY_PRIVILEGE },
793      { "SeRemoteShutdownPrivilege", SE_REMOTE_SHUTDOWN_PRIVILEGE },
794      { "SeUndockPrivilege", SE_UNDOCK_PRIVILEGE },
795      { "SeSyncAgentPrivilege", SE_SYNC_AGENT_PRIVILEGE },
796      { "SeEnableDelegationPrivilege", SE_ENABLE_DELEGATION_PRIVILEGE },
797      { "SeManageVolumePrivilege", SE_MANAGE_VOLUME_PRIVILEGE },
798      { "SeImpersonatePrivilege", SE_IMPERSONATE_PRIVILEGE },
799      { "SeCreateGlobalPrivilege", SE_CREATE_GLOBAL_PRIVILEGE },
800     };
801     BOOL (WINAPI *pLookupPrivilegeValueA)(LPCSTR, LPCSTR, PLUID);
802     unsigned int i;
803     LUID luid;
804     BOOL ret;
805 
806     /* check whether it's available first */
807     pLookupPrivilegeValueA = (void*)GetProcAddress(hmod, "LookupPrivilegeValueA");
808     if (!pLookupPrivilegeValueA) return;
809     ret = pLookupPrivilegeValueA(NULL, "SeCreateTokenPrivilege", &luid);
810     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
811         return;
812 
813     /* check a bogus system name */
814     ret = pLookupPrivilegeValueA("b0gu5.Nam3", "SeCreateTokenPrivilege", &luid);
815     ok( !ret && (GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
816                 GetLastError() == RPC_S_INVALID_NET_ADDR) /* w2k8 */,
817      "LookupPrivilegeValueA didn't fail with RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR: %d\n",
818      GetLastError());
819     /* check a NULL string */
820     ret = pLookupPrivilegeValueA(NULL, 0, &luid);
821     ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
822      "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n",
823      GetLastError());
824     /* check a bogus privilege name */
825     ret = pLookupPrivilegeValueA(NULL, "SeBogusPrivilege", &luid);
826     ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
827      "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n",
828      GetLastError());
829     /* check case insensitive */
830     ret = pLookupPrivilegeValueA(NULL, "sEcREATEtOKENpRIVILEGE", &luid);
831     ok( ret,
832      "LookupPrivilegeValueA(NULL, sEcREATEtOKENpRIVILEGE, &luid) failed: %d\n",
833      GetLastError());
834     for (i = 0; i < sizeof(privs) / sizeof(privs[0]); i++)
835     {
836         /* Not all privileges are implemented on all Windows versions, so
837          * don't worry if the call fails
838          */
839         if (pLookupPrivilegeValueA(NULL, privs[i].name, &luid))
840         {
841             ok(luid.LowPart == privs[i].lowPart,
842              "LookupPrivilegeValueA returned an invalid LUID for %s\n",
843              privs[i].name);
844         }
845     }
846 }
847 
848 static void test_luid(void)
849 {
850     test_allocateLuid();
851     test_lookupPrivilegeName();
852     test_lookupPrivilegeValue();
853 }
854 
855 static void test_FileSecurity(void)
856 {
857     char wintmpdir [MAX_PATH];
858     char path [MAX_PATH];
859     char file [MAX_PATH];
860     HANDLE fh, token;
861     DWORD sdSize, retSize, rc, granted, priv_set_len;
862     PRIVILEGE_SET priv_set;
863     BOOL status;
864     BYTE *sd;
865     GENERIC_MAPPING mapping = { FILE_READ_DATA, FILE_WRITE_DATA, FILE_EXECUTE, FILE_ALL_ACCESS };
866     const SECURITY_INFORMATION request = OWNER_SECURITY_INFORMATION
867                                        | GROUP_SECURITY_INFORMATION
868                                        | DACL_SECURITY_INFORMATION;
869 
870     if (!pGetFileSecurityA) {
871         win_skip ("GetFileSecurity is not available\n");
872         return;
873     }
874 
875     if (!pSetFileSecurityA) {
876         win_skip ("SetFileSecurity is not available\n");
877         return;
878     }
879 
880     if (!GetTempPathA (sizeof (wintmpdir), wintmpdir)) {
881         win_skip ("GetTempPathA failed\n");
882         return;
883     }
884 
885     /* Create a temporary directory and in it a temporary file */
886     strcat (strcpy (path, wintmpdir), "rary");
887     SetLastError(0xdeadbeef);
888     rc = CreateDirectoryA (path, NULL);
889     ok (rc || GetLastError() == ERROR_ALREADY_EXISTS, "CreateDirectoryA "
890         "failed for '%s' with %d\n", path, GetLastError());
891 
892     strcat (strcpy (file, path), "\\ess");
893     SetLastError(0xdeadbeef);
894     fh = CreateFileA (file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
895     ok (fh != INVALID_HANDLE_VALUE, "CreateFileA "
896         "failed for '%s' with %d\n", file, GetLastError());
897     CloseHandle (fh);
898 
899     /* For the temporary file ... */
900 
901     /* Get size needed */
902     retSize = 0;
903     SetLastError(0xdeadbeef);
904     rc = pGetFileSecurityA (file, request, NULL, 0, &retSize);
905     if (!rc && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) {
906         win_skip("GetFileSecurityA is not implemented\n");
907         goto cleanup;
908     }
909     ok (!rc, "GetFileSecurityA "
910         "was expected to fail for '%s'\n", file);
911     ok (GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetFileSecurityA "
912         "returned %d; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError());
913     ok (retSize > sizeof (SECURITY_DESCRIPTOR), "GetFileSecurityA returned size %d\n", retSize);
914 
915     sdSize = retSize;
916     sd = HeapAlloc (GetProcessHeap (), 0, sdSize);
917 
918     /* Get security descriptor for real */
919     retSize = -1;
920     SetLastError(0xdeadbeef);
921     rc = pGetFileSecurityA (file, request, sd, sdSize, &retSize);
922     ok (rc, "GetFileSecurityA "
923         "was not expected to fail '%s': %d\n", file, GetLastError());
924     ok (retSize == sdSize ||
925         broken(retSize == 0), /* NT4 */
926         "GetFileSecurityA returned size %d; expected %d\n", retSize, sdSize);
927 
928     /* Use it to set security descriptor */
929     SetLastError(0xdeadbeef);
930     rc = pSetFileSecurityA (file, request, sd);
931     ok (rc, "SetFileSecurityA "
932         "was not expected to fail '%s': %d\n", file, GetLastError());
933 
934     HeapFree (GetProcessHeap (), 0, sd);
935 
936     /* Repeat for the temporary directory ... */
937 
938     /* Get size needed */
939     retSize = 0;
940     SetLastError(0xdeadbeef);
941     rc = pGetFileSecurityA (path, request, NULL, 0, &retSize);
942     ok (!rc, "GetFileSecurityA "
943         "was expected to fail for '%s'\n", path);
944     ok (GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetFileSecurityA "
945         "returned %d; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError());
946     ok (retSize > sizeof (SECURITY_DESCRIPTOR), "GetFileSecurityA returned size %d\n", retSize);
947 
948     sdSize = retSize;
949     sd = HeapAlloc (GetProcessHeap (), 0, sdSize);
950 
951     /* Get security descriptor for real */
952     retSize = -1;
953     SetLastError(0xdeadbeef);
954     rc = pGetFileSecurityA (path, request, sd, sdSize, &retSize);
955     ok (rc, "GetFileSecurityA "
956         "was not expected to fail '%s': %d\n", path, GetLastError());
957     ok (retSize == sdSize ||
958         broken(retSize == 0), /* NT4 */
959         "GetFileSecurityA returned size %d; expected %d\n", retSize, sdSize);
960 
961     /* Use it to set security descriptor */
962     SetLastError(0xdeadbeef);
963     rc = pSetFileSecurityA (path, request, sd);
964     ok (rc, "SetFileSecurityA "
965         "was not expected to fail '%s': %d\n", path, GetLastError());
966     HeapFree (GetProcessHeap (), 0, sd);
967 
968     /* Old test */
969     strcpy (wintmpdir, "\\Should not exist");
970     SetLastError(0xdeadbeef);
971     rc = pGetFileSecurityA (wintmpdir, OWNER_SECURITY_INFORMATION, NULL, 0, &sdSize);
972     ok (!rc, "GetFileSecurityA should fail for not existing directories/files\n");
973     ok (GetLastError() == ERROR_FILE_NOT_FOUND,
974         "last error ERROR_FILE_NOT_FOUND expected, got %d\n", GetLastError());
975 
976 cleanup:
977     /* Remove temporary file and directory */
978     DeleteFileA(file);
979     RemoveDirectoryA(path);
980 
981     /* Test file access permissions for a file with FILE_ATTRIBUTE_ARCHIVE */
982     SetLastError(0xdeadbeef);
983     rc = GetTempPathA(sizeof(wintmpdir), wintmpdir);
984     ok(rc, "GetTempPath error %d\n", GetLastError());
985 
986     SetLastError(0xdeadbeef);
987     rc = GetTempFileNameA(wintmpdir, "tmp", 0, file);
988     ok(rc, "GetTempFileName error %d\n", GetLastError());
989 
990     rc = GetFileAttributesA(file);
991     rc &= ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|FILE_ATTRIBUTE_COMPRESSED);
992     ok(rc == FILE_ATTRIBUTE_ARCHIVE, "expected FILE_ATTRIBUTE_ARCHIVE got %#x\n", rc);
993 
994     rc = GetFileSecurityA(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
995                           NULL, 0, &sdSize);
996     ok(!rc, "GetFileSecurity should fail\n");
997     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
998        "expected ERROR_INSUFFICIENT_BUFFER got %d\n", GetLastError());
999     ok(sdSize > sizeof(SECURITY_DESCRIPTOR), "got sd size %d\n", sdSize);
1000 
1001     sd = HeapAlloc(GetProcessHeap (), 0, sdSize);
1002     retSize = 0xdeadbeef;
1003     SetLastError(0xdeadbeef);
1004     rc = GetFileSecurityA(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
1005                           sd, sdSize, &retSize);
1006     ok(rc, "GetFileSecurity error %d\n", GetLastError());
1007     ok(retSize == sdSize || broken(retSize == 0) /* NT4 */, "expected %d, got %d\n", sdSize, retSize);
1008 
1009     SetLastError(0xdeadbeef);
1010     rc = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &token);
1011     ok(!rc, "OpenThreadToken should fail\n");
1012     ok(GetLastError() == ERROR_NO_TOKEN, "expected ERROR_NO_TOKEN, got %d\n", GetLastError());
1013 
1014     SetLastError(0xdeadbeef);
1015     rc = ImpersonateSelf(SecurityIdentification);
1016     ok(rc, "ImpersonateSelf error %d\n", GetLastError());
1017 
1018     SetLastError(0xdeadbeef);
1019     rc = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &token);
1020     ok(rc, "OpenThreadToken error %d\n", GetLastError());
1021 
1022     SetLastError(0xdeadbeef);
1023     rc = RevertToSelf();
1024     ok(rc, "RevertToSelf error %d\n", GetLastError());
1025 
1026     priv_set_len = sizeof(priv_set);
1027     granted = 0xdeadbeef;
1028     status = 0xdeadbeef;
1029     SetLastError(0xdeadbeef);
1030     rc = AccessCheck(sd, token, FILE_READ_DATA, &mapping, &priv_set, &priv_set_len, &granted, &status);
1031     ok(rc, "AccessCheck error %d\n", GetLastError());
1032     ok(status == 1, "expected 1, got %d\n", status);
1033     ok(granted == FILE_READ_DATA, "expected FILE_READ_DATA, got %#x\n", granted);
1034 
1035     granted = 0xdeadbeef;
1036     status = 0xdeadbeef;
1037     SetLastError(0xdeadbeef);
1038     rc = AccessCheck(sd, token, FILE_WRITE_DATA, &mapping, &priv_set, &priv_set_len, &granted, &status);
1039     ok(rc, "AccessCheck error %d\n", GetLastError());
1040     ok(status == 1, "expected 1, got %d\n", status);
1041     ok(granted == FILE_WRITE_DATA, "expected FILE_WRITE_DATA, got %#x\n", granted);
1042 
1043     granted = 0xdeadbeef;
1044     status = 0xdeadbeef;
1045     SetLastError(0xdeadbeef);
1046     rc = AccessCheck(sd, token, FILE_EXECUTE, &mapping, &priv_set, &priv_set_len, &granted, &status);
1047     ok(rc, "AccessCheck error %d\n", GetLastError());
1048     ok(status == 1, "expected 1, got %d\n", status);
1049     ok(granted == FILE_EXECUTE, "expected FILE_EXECUTE, got %#x\n", granted);
1050 
1051     granted = 0xdeadbeef;
1052     status = 0xdeadbeef;
1053     SetLastError(0xdeadbeef);
1054     rc = AccessCheck(sd, token, DELETE, &mapping, &priv_set, &priv_set_len, &granted, &status);
1055     ok(rc, "AccessCheck error %d\n", GetLastError());
1056     ok(status == 1, "expected 1, got %d\n", status);
1057     ok(granted == DELETE, "expected DELETE, got %#x\n", granted);
1058 
1059     granted = 0xdeadbeef;
1060     status = 0xdeadbeef;
1061     SetLastError(0xdeadbeef);
1062     rc = AccessCheck(sd, token, FILE_DELETE_CHILD, &mapping, &priv_set, &priv_set_len, &granted, &status);
1063     ok(rc, "AccessCheck error %d\n", GetLastError());
1064     ok(status == 1, "expected 1, got %d\n", status);
1065     ok(granted == FILE_DELETE_CHILD, "expected FILE_DELETE_CHILD, got %#x\n", granted);
1066 
1067     granted = 0xdeadbeef;
1068     status = 0xdeadbeef;
1069     SetLastError(0xdeadbeef);
1070     rc = AccessCheck(sd, token, 0x1ff, &mapping, &priv_set, &priv_set_len, &granted, &status);
1071     ok(rc, "AccessCheck error %d\n", GetLastError());
1072     ok(status == 1, "expected 1, got %d\n", status);
1073     ok(granted == 0x1ff, "expected 0x1ff, got %#x\n", granted);
1074 
1075     granted = 0xdeadbeef;
1076     status = 0xdeadbeef;
1077     SetLastError(0xdeadbeef);
1078     rc = AccessCheck(sd, token, FILE_ALL_ACCESS, &mapping, &priv_set, &priv_set_len, &granted, &status);
1079     ok(rc, "AccessCheck error %d\n", GetLastError());
1080     ok(status == 1, "expected 1, got %d\n", status);
1081     ok(granted == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", granted);
1082 
1083     SetLastError(0xdeadbeef);
1084     rc = AccessCheck(sd, token, 0xffffffff, &mapping, &priv_set, &priv_set_len, &granted, &status);
1085     ok(!rc, "AccessCheck should fail\n");
1086     ok(GetLastError() == ERROR_GENERIC_NOT_MAPPED, "expected ERROR_GENERIC_NOT_MAPPED, got %d\n", GetLastError());
1087 
1088     /* Test file access permissions for a file with FILE_ATTRIBUTE_READONLY */
1089     SetLastError(0xdeadbeef);
1090     fh = CreateFileA(file, FILE_READ_DATA, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
1091     ok(fh != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
1092     retSize = 0xdeadbeef;
1093     SetLastError(0xdeadbeef);
1094     rc = WriteFile(fh, "1", 1, &retSize, NULL);
1095     ok(!rc, "WriteFile should fail\n");
1096     ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1097     ok(retSize == 0, "expected 0, got %d\n", retSize);
1098     CloseHandle(fh);
1099 
1100     rc = GetFileAttributesA(file);
1101     rc &= ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|FILE_ATTRIBUTE_COMPRESSED);
1102 todo_wine
1103     ok(rc == (FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY),
1104        "expected FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY got %#x\n", rc);
1105 
1106     SetLastError(0xdeadbeef);
1107     rc = SetFileAttributesA(file, FILE_ATTRIBUTE_ARCHIVE);
1108     ok(rc, "SetFileAttributes error %d\n", GetLastError());
1109     SetLastError(0xdeadbeef);
1110     rc = DeleteFileA(file);
1111     ok(rc, "DeleteFile error %d\n", GetLastError());
1112 
1113     SetLastError(0xdeadbeef);
1114     fh = CreateFileA(file, FILE_READ_DATA, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
1115     ok(fh != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
1116     retSize = 0xdeadbeef;
1117     SetLastError(0xdeadbeef);
1118     rc = WriteFile(fh, "1", 1, &retSize, NULL);
1119     ok(!rc, "WriteFile should fail\n");
1120     ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1121     ok(retSize == 0, "expected 0, got %d\n", retSize);
1122     CloseHandle(fh);
1123 
1124     rc = GetFileAttributesA(file);
1125     rc &= ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|FILE_ATTRIBUTE_COMPRESSED);
1126     ok(rc == (FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY),
1127        "expected FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY got %#x\n", rc);
1128 
1129     retSize = 0xdeadbeef;
1130     SetLastError(0xdeadbeef);
1131     rc = GetFileSecurityA(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
1132                           sd, sdSize, &retSize);
1133     ok(rc, "GetFileSecurity error %d\n", GetLastError());
1134     ok(retSize == sdSize || broken(retSize == 0) /* NT4 */, "expected %d, got %d\n", sdSize, retSize);
1135 
1136     priv_set_len = sizeof(priv_set);
1137     granted = 0xdeadbeef;
1138     status = 0xdeadbeef;
1139     SetLastError(0xdeadbeef);
1140     rc = AccessCheck(sd, token, FILE_READ_DATA, &mapping, &priv_set, &priv_set_len, &granted, &status);
1141     ok(rc, "AccessCheck error %d\n", GetLastError());
1142     ok(status == 1, "expected 1, got %d\n", status);
1143     ok(granted == FILE_READ_DATA, "expected FILE_READ_DATA, got %#x\n", granted);
1144 
1145     granted = 0xdeadbeef;
1146     status = 0xdeadbeef;
1147     SetLastError(0xdeadbeef);
1148     rc = AccessCheck(sd, token, FILE_WRITE_DATA, &mapping, &priv_set, &priv_set_len, &granted, &status);
1149     ok(rc, "AccessCheck error %d\n", GetLastError());
1150 todo_wine {
1151     ok(status == 1, "expected 1, got %d\n", status);
1152     ok(granted == FILE_WRITE_DATA, "expected FILE_WRITE_DATA, got %#x\n", granted);
1153 }
1154     granted = 0xdeadbeef;
1155     status = 0xdeadbeef;
1156     SetLastError(0xdeadbeef);
1157     rc = AccessCheck(sd, token, FILE_EXECUTE, &mapping, &priv_set, &priv_set_len, &granted, &status);
1158     ok(rc, "AccessCheck error %d\n", GetLastError());
1159     ok(status == 1, "expected 1, got %d\n", status);
1160     ok(granted == FILE_EXECUTE, "expected FILE_EXECUTE, got %#x\n", granted);
1161 
1162     granted = 0xdeadbeef;
1163     status = 0xdeadbeef;
1164     SetLastError(0xdeadbeef);
1165     rc = AccessCheck(sd, token, DELETE, &mapping, &priv_set, &priv_set_len, &granted, &status);
1166     ok(rc, "AccessCheck error %d\n", GetLastError());
1167 todo_wine {
1168     ok(status == 1, "expected 1, got %d\n", status);
1169     ok(granted == DELETE, "expected DELETE, got %#x\n", granted);
1170 }
1171     granted = 0xdeadbeef;
1172     status = 0xdeadbeef;
1173     SetLastError(0xdeadbeef);
1174     rc = AccessCheck(sd, token, FILE_DELETE_CHILD, &mapping, &priv_set, &priv_set_len, &granted, &status);
1175     ok(rc, "AccessCheck error %d\n", GetLastError());
1176 todo_wine {
1177     ok(status == 1, "expected 1, got %d\n", status);
1178     ok(granted == FILE_DELETE_CHILD, "expected FILE_DELETE_CHILD, got %#x\n", granted);
1179 }
1180     granted = 0xdeadbeef;
1181     status = 0xdeadbeef;
1182     SetLastError(0xdeadbeef);
1183     rc = AccessCheck(sd, token, 0x1ff, &mapping, &priv_set, &priv_set_len, &granted, &status);
1184     ok(rc, "AccessCheck error %d\n", GetLastError());
1185 todo_wine {
1186     ok(status == 1, "expected 1, got %d\n", status);
1187     ok(granted == 0x1ff, "expected 0x1ff, got %#x\n", granted);
1188 }
1189     granted = 0xdeadbeef;
1190     status = 0xdeadbeef;
1191     SetLastError(0xdeadbeef);
1192     rc = AccessCheck(sd, token, FILE_ALL_ACCESS, &mapping, &priv_set, &priv_set_len, &granted, &status);
1193     ok(rc, "AccessCheck error %d\n", GetLastError());
1194 todo_wine {
1195     ok(status == 1, "expected 1, got %d\n", status);
1196     ok(granted == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", granted);
1197 }
1198     SetLastError(0xdeadbeef);
1199     rc = DeleteFileA(file);
1200     ok(!rc, "DeleteFile should fail\n");
1201     ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1202     SetLastError(0xdeadbeef);
1203     rc = SetFileAttributesA(file, FILE_ATTRIBUTE_ARCHIVE);
1204     ok(rc, "SetFileAttributes error %d\n", GetLastError());
1205     SetLastError(0xdeadbeef);
1206     rc = DeleteFileA(file);
1207     ok(rc, "DeleteFile error %d\n", GetLastError());
1208 
1209     CloseHandle(token);
1210     HeapFree(GetProcessHeap(), 0, sd);
1211 }
1212 
1213 static void test_AccessCheck(void)
1214 {
1215     PSID EveryoneSid = NULL, AdminSid = NULL, UsersSid = NULL;
1216     PACL Acl = NULL;
1217     SECURITY_DESCRIPTOR *SecurityDescriptor = NULL;
1218     SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
1219     SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
1220     GENERIC_MAPPING Mapping = { KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS };
1221     ACCESS_MASK Access;
1222     BOOL AccessStatus;
1223     HANDLE Token;
1224     HANDLE ProcessToken;
1225     BOOL ret;
1226     DWORD PrivSetLen;
1227     PRIVILEGE_SET *PrivSet;
1228     BOOL res;
1229     HMODULE NtDllModule;
1230     BOOLEAN Enabled;
1231     DWORD err;
1232     NTSTATUS ntret, ntAccessStatus;
1233 
1234     NtDllModule = GetModuleHandleA("ntdll.dll");
1235     if (!NtDllModule)
1236     {
1237         skip("not running on NT, skipping test\n");
1238         return;
1239     }
1240     pRtlAdjustPrivilege = (void *)GetProcAddress(NtDllModule, "RtlAdjustPrivilege");
1241     if (!pRtlAdjustPrivilege)
1242     {
1243         win_skip("missing RtlAdjustPrivilege, skipping test\n");
1244         return;
1245     }
1246 
1247     Acl = HeapAlloc(GetProcessHeap(), 0, 256);
1248     res = InitializeAcl(Acl, 256, ACL_REVISION);
1249     if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1250     {
1251         skip("ACLs not implemented - skipping tests\n");
1252         HeapFree(GetProcessHeap(), 0, Acl);
1253         return;
1254     }
1255     ok(res, "InitializeAcl failed with error %d\n", GetLastError());
1256 
1257     res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
1258     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
1259 
1260     res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
1261         DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminSid);
1262     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
1263 
1264     res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
1265         DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid);
1266     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
1267 
1268     SecurityDescriptor = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
1269 
1270     res = InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
1271     ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
1272 
1273     res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
1274     ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
1275 
1276     PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
1277     PrivSet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, PrivSetLen);
1278     PrivSet->PrivilegeCount = 16;
1279 
1280     res = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &ProcessToken);
1281     ok(res, "OpenProcessToken failed with error %d\n", GetLastError());
1282 
1283     pRtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, FALSE, TRUE, &Enabled);
1284 
1285     res = DuplicateToken(ProcessToken, SecurityImpersonation, &Token);
1286     ok(res, "DuplicateToken failed with error %d\n", GetLastError());
1287 
1288     /* SD without owner/group */
1289     SetLastError(0xdeadbeef);
1290     Access = AccessStatus = 0x1abe11ed;
1291     ret = AccessCheck(SecurityDescriptor, Token, KEY_QUERY_VALUE, &Mapping,
1292                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1293     err = GetLastError();
1294     ok(!ret && err == ERROR_INVALID_SECURITY_DESCR, "AccessCheck should have "
1295        "failed with ERROR_INVALID_SECURITY_DESCR, instead of %d\n", err);
1296     ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1297        "Access and/or AccessStatus were changed!\n");
1298 
1299     /* Set owner and group */
1300     res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE);
1301     ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
1302     res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, TRUE);
1303     ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
1304 
1305     /* Generic access mask */
1306     SetLastError(0xdeadbeef);
1307     Access = AccessStatus = 0x1abe11ed;
1308     ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1309                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1310     err = GetLastError();
1311     ok(!ret && err == ERROR_GENERIC_NOT_MAPPED, "AccessCheck should have failed "
1312        "with ERROR_GENERIC_NOT_MAPPED, instead of %d\n", err);
1313     ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1314        "Access and/or AccessStatus were changed!\n");
1315 
1316     /* Generic access mask - no privilegeset buffer */
1317     SetLastError(0xdeadbeef);
1318     Access = AccessStatus = 0x1abe11ed;
1319     ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1320                       NULL, &PrivSetLen, &Access, &AccessStatus);
1321     err = GetLastError();
1322     ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have failed "
1323        "with ERROR_NOACCESS, instead of %d\n", err);
1324     ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1325        "Access and/or AccessStatus were changed!\n");
1326 
1327     /* Generic access mask - no returnlength */
1328     SetLastError(0xdeadbeef);
1329     Access = AccessStatus = 0x1abe11ed;
1330     ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1331                       PrivSet, NULL, &Access, &AccessStatus);
1332     err = GetLastError();
1333     ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have failed "
1334        "with ERROR_NOACCESS, instead of %d\n", err);
1335     ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1336        "Access and/or AccessStatus were changed!\n");
1337 
1338     /* Generic access mask - no privilegeset buffer, no returnlength */
1339     SetLastError(0xdeadbeef);
1340     Access = AccessStatus = 0x1abe11ed;
1341     ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1342                       NULL, NULL, &Access, &AccessStatus);
1343     err = GetLastError();
1344     ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have failed "
1345        "with ERROR_NOACCESS, instead of %d\n", err);
1346     ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1347        "Access and/or AccessStatus were changed!\n");
1348 
1349     /* sd with no dacl present */
1350     Access = AccessStatus = 0x1abe11ed;
1351     ret = SetSecurityDescriptorDacl(SecurityDescriptor, FALSE, NULL, FALSE);
1352     ok(ret, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
1353     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1354                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1355     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1356     ok(AccessStatus && (Access == KEY_READ),
1357         "AccessCheck failed to grant access with error %d\n",
1358         GetLastError());
1359 
1360     /* sd with no dacl present - no privilegeset buffer */
1361     SetLastError(0xdeadbeef);
1362     Access = AccessStatus = 0x1abe11ed;
1363     ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1364                       NULL, &PrivSetLen, &Access, &AccessStatus);
1365     err = GetLastError();
1366     ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have failed "
1367        "with ERROR_NOACCESS, instead of %d\n", err);
1368     ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1369        "Access and/or AccessStatus were changed!\n");
1370 
1371     if(pNtAccessCheck)
1372     {
1373        /* Generic access mask - no privilegeset buffer */
1374        SetLastError(0xdeadbeef);
1375        Access = ntAccessStatus = 0x1abe11ed;
1376        ntret = pNtAccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1377                               NULL, &PrivSetLen, &Access, &ntAccessStatus);
1378        err = GetLastError();
1379        ok(ntret == STATUS_ACCESS_VIOLATION,
1380           "NtAccessCheck should have failed with STATUS_ACCESS_VIOLATION, got %x\n", ntret);
1381        ok(err == 0xdeadbeef,
1382           "NtAccessCheck shouldn't set last error, got %d\n", err);
1383        ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed,
1384           "Access and/or AccessStatus were changed!\n");
1385 
1386       /* Generic access mask - no returnlength */
1387       SetLastError(0xdeadbeef);
1388       Access = ntAccessStatus = 0x1abe11ed;
1389       ntret = pNtAccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1390                              PrivSet, NULL, &Access, &ntAccessStatus);
1391       err = GetLastError();
1392       ok(ntret == STATUS_ACCESS_VIOLATION,
1393          "NtAccessCheck should have failed with STATUS_ACCESS_VIOLATION, got %x\n", ntret);
1394       ok(err == 0xdeadbeef,
1395          "NtAccessCheck shouldn't set last error, got %d\n", err);
1396       ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed,
1397          "Access and/or AccessStatus were changed!\n");
1398 
1399       /* Generic access mask - no privilegeset buffer, no returnlength */
1400       SetLastError(0xdeadbeef);
1401       Access = ntAccessStatus = 0x1abe11ed;
1402       ntret = pNtAccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1403                              NULL, NULL, &Access, &ntAccessStatus);
1404       err = GetLastError();
1405       ok(ntret == STATUS_ACCESS_VIOLATION,
1406          "NtAccessCheck should have failed with STATUS_ACCESS_VIOLATION, got %x\n", ntret);
1407       ok(err == 0xdeadbeef,
1408          "NtAccessCheck shouldn't set last error, got %d\n", err);
1409       ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed,
1410          "Access and/or AccessStatus were changed!\n");
1411     }
1412     else
1413        win_skip("NtAccessCheck unavailable. Skipping.\n");
1414 
1415     /* sd with NULL dacl */
1416     Access = AccessStatus = 0x1abe11ed;
1417     ret = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, NULL, FALSE);
1418     ok(ret, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
1419     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1420                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1421     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1422     ok(AccessStatus && (Access == KEY_READ),
1423         "AccessCheck failed to grant access with error %d\n",
1424         GetLastError());
1425     ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping,
1426                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1427     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1428     ok(AccessStatus && (Access == KEY_ALL_ACCESS),
1429         "AccessCheck failed to grant access with error %d\n",
1430         GetLastError());
1431 
1432     /* sd with blank dacl */
1433     ret = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
1434     ok(ret, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
1435     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1436                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1437     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1438     err = GetLastError();
1439     ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed "
1440        "with ERROR_ACCESS_DENIED, instead of %d\n", err);
1441     ok(!Access, "Should have failed to grant any access, got 0x%08x\n", Access);
1442 
1443     res = AddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, EveryoneSid);
1444     ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
1445 
1446     res = AddAccessDeniedAce(Acl, ACL_REVISION, KEY_SET_VALUE, AdminSid);
1447     ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError());
1448 
1449     /* sd with dacl */
1450     Access = AccessStatus = 0x1abe11ed;
1451     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1452                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1453     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1454     ok(AccessStatus && (Access == KEY_READ),
1455         "AccessCheck failed to grant access with error %d\n",
1456         GetLastError());
1457 
1458     ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping,
1459                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1460     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1461     ok(AccessStatus,
1462         "AccessCheck failed to grant any access with error %d\n",
1463         GetLastError());
1464     trace("AccessCheck with MAXIMUM_ALLOWED got Access 0x%08x\n", Access);
1465 
1466     /* Null PrivSet with null PrivSetLen pointer */
1467     SetLastError(0xdeadbeef);
1468     Access = AccessStatus = 0x1abe11ed;
1469     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1470                       NULL, NULL, &Access, &AccessStatus);
1471     err = GetLastError();
1472     ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have "
1473        "failed with ERROR_NOACCESS, instead of %d\n", err);
1474     ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1475        "Access and/or AccessStatus were changed!\n");
1476 
1477     /* Null PrivSet with zero PrivSetLen */
1478     SetLastError(0xdeadbeef);
1479     Access = AccessStatus = 0x1abe11ed;
1480     PrivSetLen = 0;
1481     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1482                       0, &PrivSetLen, &Access, &AccessStatus);
1483     err = GetLastError();
1484     ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1485        "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err);
1486     ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen);
1487     ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1488        "Access and/or AccessStatus were changed!\n");
1489 
1490     /* Null PrivSet with insufficient PrivSetLen */
1491     SetLastError(0xdeadbeef);
1492     Access = AccessStatus = 0x1abe11ed;
1493     PrivSetLen = 1;
1494     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1495                       0, &PrivSetLen, &Access, &AccessStatus);
1496     err = GetLastError();
1497     ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have "
1498        "failed with ERROR_NOACCESS, instead of %d\n", err);
1499     ok(PrivSetLen == 1, "PrivSetLen returns %d\n", PrivSetLen);
1500     ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1501        "Access and/or AccessStatus were changed!\n");
1502 
1503     /* Null PrivSet with insufficient PrivSetLen */
1504     SetLastError(0xdeadbeef);
1505     Access = AccessStatus = 0x1abe11ed;
1506     PrivSetLen = sizeof(PRIVILEGE_SET) - 1;
1507     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1508                       0, &PrivSetLen, &Access, &AccessStatus);
1509     err = GetLastError();
1510     ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have "
1511        "failed with ERROR_NOACCESS, instead of %d\n", err);
1512     ok(PrivSetLen == sizeof(PRIVILEGE_SET) - 1, "PrivSetLen returns %d\n", PrivSetLen);
1513     ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1514        "Access and/or AccessStatus were changed!\n");
1515 
1516     /* Null PrivSet with minimal sufficient PrivSetLen */
1517     SetLastError(0xdeadbeef);
1518     Access = AccessStatus = 0x1abe11ed;
1519     PrivSetLen = sizeof(PRIVILEGE_SET);
1520     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1521                       0, &PrivSetLen, &Access, &AccessStatus);
1522     err = GetLastError();
1523     ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have "
1524        "failed with ERROR_NOACCESS, instead of %d\n", err);
1525     ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen);
1526     ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1527        "Access and/or AccessStatus were changed!\n");
1528 
1529     /* Valid PrivSet with zero PrivSetLen */
1530     SetLastError(0xdeadbeef);
1531     Access = AccessStatus = 0x1abe11ed;
1532     PrivSetLen = 0;
1533     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1534                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1535     err = GetLastError();
1536     ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1537        "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err);
1538     ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen);
1539     ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1540        "Access and/or AccessStatus were changed!\n");
1541 
1542     /* Valid PrivSet with insufficient PrivSetLen */
1543     SetLastError(0xdeadbeef);
1544     Access = AccessStatus = 0x1abe11ed;
1545     PrivSetLen = 1;
1546     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1547                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1548     err = GetLastError();
1549 todo_wine
1550     ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1551        "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err);
1552 todo_wine
1553     ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen);
1554     ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1555        "Access and/or AccessStatus were changed!\n");
1556 
1557     /* Valid PrivSet with insufficient PrivSetLen */
1558     SetLastError(0xdeadbeef);
1559     Access = AccessStatus = 0x1abe11ed;
1560     PrivSetLen = sizeof(PRIVILEGE_SET) - 1;
1561     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1562                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1563     err = GetLastError();
1564 todo_wine
1565     ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1566        "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err);
1567 todo_wine
1568     ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen);
1569 todo_wine
1570     ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1571        "Access and/or AccessStatus were changed!\n");
1572 
1573     /* Valid PrivSet with minimal sufficient PrivSetLen */
1574     SetLastError(0xdeadbeef);
1575     Access = AccessStatus = 0x1abe11ed;
1576     PrivSetLen = sizeof(PRIVILEGE_SET);
1577     memset(PrivSet, 0xcc, PrivSetLen);
1578     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1579                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1580     err = GetLastError();
1581     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1582 todo_wine
1583     ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen);
1584     ok(AccessStatus && (Access == KEY_READ),
1585         "AccessCheck failed to grant access with error %d\n", GetLastError());
1586     ok(PrivSet->PrivilegeCount == 0, "PrivilegeCount returns %d, expects 0\n",
1587         PrivSet->PrivilegeCount);
1588 
1589     /* Valid PrivSet with sufficient PrivSetLen */
1590     SetLastError(0xdeadbeef);
1591     Access = AccessStatus = 0x1abe11ed;
1592     PrivSetLen = sizeof(PRIVILEGE_SET) + 1;
1593     memset(PrivSet, 0xcc, PrivSetLen);
1594     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1595                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1596     err = GetLastError();
1597     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1598 todo_wine
1599     ok(PrivSetLen == sizeof(PRIVILEGE_SET) + 1, "PrivSetLen returns %d\n", PrivSetLen);
1600     ok(AccessStatus && (Access == KEY_READ),
1601         "AccessCheck failed to grant access with error %d\n", GetLastError());
1602     ok(PrivSet->PrivilegeCount == 0, "PrivilegeCount returns %d, expects 0\n",
1603         PrivSet->PrivilegeCount);
1604 
1605     PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
1606 
1607     /* Null PrivSet with valid PrivSetLen */
1608     SetLastError(0xdeadbeef);
1609     Access = AccessStatus = 0x1abe11ed;
1610     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1611                       0, &PrivSetLen, &Access, &AccessStatus);
1612     err = GetLastError();
1613     ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have "
1614        "failed with ERROR_NOACCESS, instead of %d\n", err);
1615     ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1616        "Access and/or AccessStatus were changed!\n");
1617 
1618     /* Access denied by SD */
1619     SetLastError(0xdeadbeef);
1620     Access = AccessStatus = 0x1abe11ed;
1621     ret = AccessCheck(SecurityDescriptor, Token, KEY_WRITE, &Mapping,
1622                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1623     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1624     err = GetLastError();
1625     ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed "
1626        "with ERROR_ACCESS_DENIED, instead of %d\n", err);
1627     ok(!Access, "Should have failed to grant any access, got 0x%08x\n", Access);
1628 
1629     SetLastError(0xdeadbeef);
1630     PrivSet->PrivilegeCount = 16;
1631     ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping,
1632                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1633     ok(ret && !AccessStatus && GetLastError() == ERROR_PRIVILEGE_NOT_HELD,
1634         "AccessCheck should have failed with ERROR_PRIVILEGE_NOT_HELD, instead of %d\n",
1635         GetLastError());
1636 
1637     ret = ImpersonateLoggedOnUser(Token);
1638     ok(ret, "ImpersonateLoggedOnUser failed with error %d\n", GetLastError());
1639     ret = pRtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, TRUE, TRUE, &Enabled);
1640     if (!ret)
1641     {
1642         /* Valid PrivSet with zero PrivSetLen */
1643         SetLastError(0xdeadbeef);
1644         Access = AccessStatus = 0x1abe11ed;
1645         PrivSetLen = 0;
1646         ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1647                           PrivSet, &PrivSetLen, &Access, &AccessStatus);
1648         err = GetLastError();
1649         ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1650            "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err);
1651         ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen);
1652         ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1653            "Access and/or AccessStatus were changed!\n");
1654 
1655         /* Valid PrivSet with insufficient PrivSetLen */
1656         SetLastError(0xdeadbeef);
1657         Access = AccessStatus = 0x1abe11ed;
1658         PrivSetLen = sizeof(PRIVILEGE_SET) - 1;
1659         ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1660                           PrivSet, &PrivSetLen, &Access, &AccessStatus);
1661         err = GetLastError();
1662     todo_wine
1663         ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1664            "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err);
1665     todo_wine
1666         ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen);
1667     todo_wine
1668         ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1669            "Access and/or AccessStatus were changed!\n");
1670 
1671         /* Valid PrivSet with minimal sufficient PrivSetLen */
1672         SetLastError(0xdeadbeef);
1673         Access = AccessStatus = 0x1abe11ed;
1674         PrivSetLen = sizeof(PRIVILEGE_SET);
1675         memset(PrivSet, 0xcc, PrivSetLen);
1676         ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping,
1677                           PrivSet, &PrivSetLen, &Access, &AccessStatus);
1678         ok(ret && AccessStatus && GetLastError() == 0xdeadbeef,
1679             "AccessCheck should have succeeded, error %d\n",
1680             GetLastError());
1681         ok(Access == ACCESS_SYSTEM_SECURITY,
1682             "Access should be equal to ACCESS_SYSTEM_SECURITY instead of 0x%08x\n",
1683             Access);
1684         ok(PrivSet->PrivilegeCount == 1, "PrivilegeCount returns %d, expects 1\n",
1685             PrivSet->PrivilegeCount);
1686 
1687         /* Valid PrivSet with large PrivSetLen */
1688         SetLastError(0xdeadbeef);
1689         Access = AccessStatus = 0x1abe11ed;
1690         PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
1691         memset(PrivSet, 0xcc, PrivSetLen);
1692         ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping,
1693                           PrivSet, &PrivSetLen, &Access, &AccessStatus);
1694         ok(ret && AccessStatus && GetLastError() == 0xdeadbeef,
1695             "AccessCheck should have succeeded, error %d\n",
1696             GetLastError());
1697         ok(Access == ACCESS_SYSTEM_SECURITY,
1698             "Access should be equal to ACCESS_SYSTEM_SECURITY instead of 0x%08x\n",
1699             Access);
1700         ok(PrivSet->PrivilegeCount == 1, "PrivilegeCount returns %d, expects 1\n",
1701             PrivSet->PrivilegeCount);
1702     }
1703     else
1704         trace("Couldn't get SE_SECURITY_PRIVILEGE (0x%08x), skipping ACCESS_SYSTEM_SECURITY test\n",
1705             ret);
1706     ret = RevertToSelf();
1707     ok(ret, "RevertToSelf failed with error %d\n", GetLastError());
1708 
1709     /* test INHERIT_ONLY_ACE */
1710     ret = InitializeAcl(Acl, 256, ACL_REVISION);
1711     ok(ret, "InitializeAcl failed with error %d\n", GetLastError());
1712 
1713     /* NT doesn't have AddAccessAllowedAceEx. Skipping this call/test doesn't influence
1714      * the next ones.
1715      */
1716     if (pAddAccessAllowedAceEx)
1717     {
1718         ret = pAddAccessAllowedAceEx(Acl, ACL_REVISION, INHERIT_ONLY_ACE, KEY_READ, EveryoneSid);
1719         ok(ret, "AddAccessAllowedAceEx failed with error %d\n", GetLastError());
1720     }
1721     else
1722         win_skip("AddAccessAllowedAceEx is not available\n");
1723 
1724     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1725                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1726     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1727     err = GetLastError();
1728     ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed "
1729        "with ERROR_ACCESS_DENIED, instead of %d\n", err);
1730     ok(!Access, "Should have failed to grant any access, got 0x%08x\n", Access);
1731 
1732     CloseHandle(Token);
1733 
1734     res = DuplicateToken(ProcessToken, SecurityAnonymous, &Token);
1735     ok(res, "DuplicateToken failed with error %d\n", GetLastError());
1736 
1737     SetLastError(0xdeadbeef);
1738     ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping,
1739                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1740     err = GetLastError();
1741     ok(!ret && err == ERROR_BAD_IMPERSONATION_LEVEL, "AccessCheck should have failed "
1742        "with ERROR_BAD_IMPERSONATION_LEVEL, instead of %d\n", err);
1743 
1744     CloseHandle(Token);
1745 
1746     SetLastError(0xdeadbeef);
1747     ret = AccessCheck(SecurityDescriptor, ProcessToken, KEY_READ, &Mapping,
1748                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
1749     err = GetLastError();
1750     ok(!ret && err == ERROR_NO_IMPERSONATION_TOKEN, "AccessCheck should have failed "
1751        "with ERROR_NO_IMPERSONATION_TOKEN, instead of %d\n", err);
1752 
1753     CloseHandle(ProcessToken);
1754 
1755     if (EveryoneSid)
1756         FreeSid(EveryoneSid);
1757     if (AdminSid)
1758         FreeSid(AdminSid);
1759     if (UsersSid)
1760         FreeSid(UsersSid);
1761     HeapFree(GetProcessHeap(), 0, Acl);
1762     HeapFree(GetProcessHeap(), 0, SecurityDescriptor);
1763     HeapFree(GetProcessHeap(), 0, PrivSet);
1764 }
1765 
1766 /* test GetTokenInformation for the various attributes */
1767 static void test_token_attr(void)
1768 {
1769     HANDLE Token, ImpersonationToken;
1770     DWORD Size, Size2;
1771     TOKEN_PRIVILEGES *Privileges;
1772     TOKEN_GROUPS *Groups;
1773     TOKEN_USER *User;
1774     TOKEN_DEFAULT_DACL *Dacl;
1775     BOOL ret;
1776     DWORD i, GLE;
1777     LPSTR SidString;
1778     SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
1779     ACL *acl;
1780 
1781     /* cygwin-like use case */
1782     SetLastError(0xdeadbeef);
1783     ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &Token);
1784     if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
1785     {
1786         win_skip("OpenProcessToken is not implemented\n");
1787         return;
1788     }
1789     ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1790     if (ret)
1791     {
1792         DWORD buf[256]; /* GetTokenInformation wants a dword-aligned buffer */
1793         Size = sizeof(buf);
1794         ret = GetTokenInformation(Token, TokenUser,(void*)buf, Size, &Size);
1795         ok(ret, "GetTokenInformation failed with error %d\n", GetLastError());
1796         Size = sizeof(ImpersonationLevel);
1797         ret = GetTokenInformation(Token, TokenImpersonationLevel, &ImpersonationLevel, Size, &Size);
1798         GLE = GetLastError();
1799         ok(!ret && (GLE == ERROR_INVALID_PARAMETER), "GetTokenInformation(TokenImpersonationLevel) on primary token should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GLE);
1800         CloseHandle(Token);
1801     }
1802 
1803     SetLastError(0xdeadbeef);
1804     ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &Token);
1805     ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1806 
1807     /* groups */
1808     /* insufficient buffer length */
1809     SetLastError(0xdeadbeef);
1810     Size2 = 0;
1811     ret = GetTokenInformation(Token, TokenGroups, NULL, 0, &Size2);
1812     ok(Size2 > 1, "got %d\n", Size2);
1813     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1814         "%d with error %d\n", ret, GetLastError());
1815     Size2 -= 1;
1816     Groups = HeapAlloc(GetProcessHeap(), 0, Size2);
1817     memset(Groups, 0xcc, Size2);
1818     Size = 0;
1819     ret = GetTokenInformation(Token, TokenGroups, Groups, Size2, &Size);
1820     ok(Size > 1, "got %d\n", Size);
1821     ok((!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) || broken(ret) /* wow64 */,
1822         "%d with error %d\n", ret, GetLastError());
1823     if(!ret)
1824         ok(*((BYTE*)Groups) == 0xcc, "buffer altered\n");
1825 
1826     HeapFree(GetProcessHeap(), 0, Groups);
1827 
1828     SetLastError(0xdeadbeef);
1829     ret = GetTokenInformation(Token, TokenGroups, NULL, 0, &Size);
1830     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1831         "GetTokenInformation(TokenGroups) %s with error %d\n",
1832         ret ? "succeeded" : "failed", GetLastError());
1833     Groups = HeapAlloc(GetProcessHeap(), 0, Size);
1834     SetLastError(0xdeadbeef);
1835     ret = GetTokenInformation(Token, TokenGroups, Groups, Size, &Size);
1836     ok(ret, "GetTokenInformation(TokenGroups) failed with error %d\n", GetLastError());
1837     ok(GetLastError() == 0xdeadbeef,
1838        "GetTokenInformation shouldn't have set last error to %d\n",
1839        GetLastError());
1840     trace("TokenGroups:\n");
1841     for (i = 0; i < Groups->GroupCount; i++)
1842     {
1843         DWORD NameLength = 255;
1844         CHAR Name[255];
1845         DWORD DomainLength = 255;
1846         CHAR Domain[255];
1847         SID_NAME_USE SidNameUse;
1848         Name[0] = '\0';
1849         Domain[0] = '\0';
1850         ret = LookupAccountSidA(NULL, Groups->Groups[i].Sid, Name, &NameLength, Domain, &DomainLength, &SidNameUse);
1851         if (ret)
1852         {
1853             ConvertSidToStringSidA(Groups->Groups[i].Sid, &SidString);
1854             trace("%s, %s\\%s use: %d attr: 0x%08x\n", SidString, Domain, Name, SidNameUse, Groups->Groups[i].Attributes);
1855             LocalFree(SidString);
1856         }
1857         else trace("attr: 0x%08x LookupAccountSid failed with error %d\n", Groups->Groups[i].Attributes, GetLastError());
1858     }
1859     HeapFree(GetProcessHeap(), 0, Groups);
1860 
1861     /* user */
1862     ret = GetTokenInformation(Token, TokenUser, NULL, 0, &Size);
1863     ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1864         "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
1865     User = HeapAlloc(GetProcessHeap(), 0, Size);
1866     ret = GetTokenInformation(Token, TokenUser, User, Size, &Size);
1867     ok(ret,
1868         "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
1869 
1870     ConvertSidToStringSidA(User->User.Sid, &SidString);
1871     trace("TokenUser: %s attr: 0x%08x\n", SidString, User->User.Attributes);
1872     LocalFree(SidString);
1873     HeapFree(GetProcessHeap(), 0, User);
1874 
1875     /* privileges */
1876     ret = GetTokenInformation(Token, TokenPrivileges, NULL, 0, &Size);
1877     ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1878         "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError());
1879     Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1880     ret = GetTokenInformation(Token, TokenPrivileges, Privileges, Size, &Size);
1881     ok(ret,
1882         "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError());
1883     trace("TokenPrivileges:\n");
1884     for (i = 0; i < Privileges->PrivilegeCount; i++)
1885     {
1886         CHAR Name[256];
1887         DWORD NameLen = sizeof(Name)/sizeof(Name[0]);
1888         LookupPrivilegeNameA(NULL, &Privileges->Privileges[i].Luid, Name, &NameLen);
1889         trace("\t%s, 0x%x\n", Name, Privileges->Privileges[i].Attributes);
1890     }
1891     HeapFree(GetProcessHeap(), 0, Privileges);
1892 
1893     ret = DuplicateToken(Token, SecurityAnonymous, &ImpersonationToken);
1894     ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
1895 
1896     Size = sizeof(ImpersonationLevel);
1897     ret = GetTokenInformation(ImpersonationToken, TokenImpersonationLevel, &ImpersonationLevel, Size, &Size);
1898     ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError());
1899     ok(ImpersonationLevel == SecurityAnonymous, "ImpersonationLevel should have been SecurityAnonymous instead of %d\n", ImpersonationLevel);
1900 
1901     CloseHandle(ImpersonationToken);
1902 
1903     /* default dacl */
1904     ret = GetTokenInformation(Token, TokenDefaultDacl, NULL, 0, &Size);
1905     ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1906         "GetTokenInformation(TokenDefaultDacl) failed with error %u\n", GetLastError());
1907 
1908     Dacl = HeapAlloc(GetProcessHeap(), 0, Size);
1909     ret = GetTokenInformation(Token, TokenDefaultDacl, Dacl, Size, &Size);
1910     ok(ret, "GetTokenInformation(TokenDefaultDacl) failed with error %u\n", GetLastError());
1911 
1912     SetLastError(0xdeadbeef);
1913     ret = SetTokenInformation(Token, TokenDefaultDacl, NULL, 0);
1914     GLE = GetLastError();
1915     ok(!ret, "SetTokenInformation(TokenDefaultDacl) succeeded\n");
1916     ok(GLE == ERROR_BAD_LENGTH, "expected ERROR_BAD_LENGTH got %u\n", GLE);
1917 
1918     SetLastError(0xdeadbeef);
1919     ret = SetTokenInformation(Token, TokenDefaultDacl, NULL, Size);
1920     GLE = GetLastError();
1921     ok(!ret, "SetTokenInformation(TokenDefaultDacl) succeeded\n");
1922     ok(GLE == ERROR_NOACCESS, "expected ERROR_NOACCESS got %u\n", GLE);
1923 
1924     acl = Dacl->DefaultDacl;
1925     Dacl->DefaultDacl = NULL;
1926 
1927     ret = SetTokenInformation(Token, TokenDefaultDacl, Dacl, Size);
1928     ok(ret, "SetTokenInformation(TokenDefaultDacl) succeeded\n");
1929 
1930     Size2 = 0;
1931     Dacl->DefaultDacl = (ACL *)0xdeadbeef;
1932     ret = GetTokenInformation(Token, TokenDefaultDacl, Dacl, Size, &Size2);
1933     ok(ret, "GetTokenInformation(TokenDefaultDacl) failed with error %u\n", GetLastError());
1934     ok(Dacl->DefaultDacl == NULL, "expected NULL, got %p\n", Dacl->DefaultDacl);
1935     ok(Size2 == sizeof(TOKEN_DEFAULT_DACL) || broken(Size2 == 2*sizeof(TOKEN_DEFAULT_DACL)), /* WoW64 */
1936        "got %u expected sizeof(TOKEN_DEFAULT_DACL)\n", Size2);
1937 
1938     Dacl->DefaultDacl = acl;
1939     ret = SetTokenInformation(Token, TokenDefaultDacl, Dacl, Size);
1940     ok(ret, "SetTokenInformation(TokenDefaultDacl) failed with error %u\n", GetLastError());
1941 
1942     if (Size2 == sizeof(TOKEN_DEFAULT_DACL)) {
1943         ret = GetTokenInformation(Token, TokenDefaultDacl, Dacl, Size, &Size2);
1944         ok(ret, "GetTokenInformation(TokenDefaultDacl) failed with error %u\n", GetLastError());
1945     } else
1946         win_skip("TOKEN_DEFAULT_DACL size too small on WoW64\n");
1947 
1948     HeapFree(GetProcessHeap(), 0, Dacl);
1949     CloseHandle(Token);
1950 }
1951 
1952 static void test_GetTokenInformation(void)
1953 {
1954     DWORD is_app_container, size;
1955     HANDLE token;
1956     BOOL ret;
1957 
1958     ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
1959     ok(ret, "OpenProcessToken failed: %u\n", GetLastError());
1960 
1961     size = 0;
1962     is_app_container = 0xdeadbeef;
1963     ret = GetTokenInformation(token, TokenIsAppContainer, &is_app_container,
1964                               sizeof(is_app_container), &size);
1965     ok(ret || broken(GetLastError() == ERROR_INVALID_PARAMETER ||
1966                      GetLastError() == ERROR_INVALID_FUNCTION), /* pre-win8 */
1967        "GetTokenInformation failed: %u\n", GetLastError());
1968     if(ret) {
1969         ok(size == sizeof(is_app_container), "size = %u\n", size);
1970         ok(!is_app_container, "is_app_container = %x\n", is_app_container);
1971     }
1972 
1973     CloseHandle(token);
1974 }
1975 
1976 typedef union _MAX_SID
1977 {
1978     SID sid;
1979     char max[SECURITY_MAX_SID_SIZE];
1980 } MAX_SID;
1981 
1982 static void test_sid_str(PSID * sid)
1983 {
1984     char *str_sid;
1985     BOOL ret = ConvertSidToStringSidA(sid, &str_sid);
1986     ok(ret, "ConvertSidToStringSidA() failed: %d\n", GetLastError());
1987     if (ret)
1988     {
1989         char account[MAX_PATH], domain[MAX_PATH];
1990         SID_NAME_USE use;
1991         DWORD acc_size = MAX_PATH;
1992         DWORD dom_size = MAX_PATH;
1993         ret = LookupAccountSidA (NULL, sid, account, &acc_size, domain, &dom_size, &use);
1994         ok(ret || GetLastError() == ERROR_NONE_MAPPED,
1995            "LookupAccountSid(%s) failed: %d\n", str_sid, GetLastError());
1996         if (ret)
1997             trace(" %s %s\\%s %d\n", str_sid, domain, account, use);
1998         else if (GetLastError() == ERROR_NONE_MAPPED)
1999             trace(" %s couldn't be mapped\n", str_sid);
2000         LocalFree(str_sid);
2001     }
2002 }
2003 
2004 static const struct well_known_sid_value
2005 {
2006     BOOL without_domain;
2007     const char *sid_string;
2008 } well_known_sid_values[] = {
2009 /*  0 */ {TRUE, "S-1-0-0"},  {TRUE, "S-1-1-0"},  {TRUE, "S-1-2-0"},  {TRUE, "S-1-3-0"},
2010 /*  4 */ {TRUE, "S-1-3-1"},  {TRUE, "S-1-3-2"},  {TRUE, "S-1-3-3"},  {TRUE, "S-1-5"},
2011 /*  8 */ {FALSE, "S-1-5-1"}, {TRUE, "S-1-5-2"},  {TRUE, "S-1-5-3"},  {TRUE, "S-1-5-4"},
2012 /* 12 */ {TRUE, "S-1-5-6"},  {TRUE, "S-1-5-7"},  {TRUE, "S-1-5-8"},  {TRUE, "S-1-5-9"},
2013 /* 16 */ {TRUE, "S-1-5-10"}, {TRUE, "S-1-5-11"}, {TRUE, "S-1-5-12"}, {TRUE, "S-1-5-13"},
2014 /* 20 */ {TRUE, "S-1-5-14"}, {FALSE, NULL},      {TRUE, "S-1-5-18"}, {TRUE, "S-1-5-19"},
2015 /* 24 */ {TRUE, "S-1-5-20"}, {TRUE, "S-1-5-32"},
2016 /* 26 */ {FALSE, "S-1-5-32-544"}, {TRUE, "S-1-5-32-545"}, {TRUE, "S-1-5-32-546"},
2017 /* 29 */ {TRUE, "S-1-5-32-547"},  {TRUE, "S-1-5-32-548"}, {TRUE, "S-1-5-32-549"},
2018 /* 32 */ {TRUE, "S-1-5-32-550"},  {TRUE, "S-1-5-32-551"}, {TRUE, "S-1-5-32-552"},
2019 /* 35 */ {TRUE, "S-1-5-32-554"},  {TRUE, "S-1-5-32-555"}, {TRUE, "S-1-5-32-556"},
2020 /* 38 */ {FALSE, "S-1-5-21-12-23-34-45-56-500"}, {FALSE, "S-1-5-21-12-23-34-45-56-501"},
2021 /* 40 */ {FALSE, "S-1-5-21-12-23-34-45-56-502"}, {FALSE, "S-1-5-21-12-23-34-45-56-512"},
2022 /* 42 */ {FALSE, "S-1-5-21-12-23-34-45-56-513"}, {FALSE, "S-1-5-21-12-23-34-45-56-514"},
2023 /* 44 */ {FALSE, "S-1-5-21-12-23-34-45-56-515"}, {FALSE, "S-1-5-21-12-23-34-45-56-516"},
2024 /* 46 */ {FALSE, "S-1-5-21-12-23-34-45-56-517"}, {FALSE, "S-1-5-21-12-23-34-45-56-518"},
2025 /* 48 */ {FALSE, "S-1-5-21-12-23-34-45-56-519"}, {FALSE, "S-1-5-21-12-23-34-45-56-520"},
2026 /* 50 */ {FALSE, "S-1-5-21-12-23-34-45-56-553"},
2027 /* Added in Windows Server 2003 */
2028 /* 51 */ {TRUE, "S-1-5-64-10"},   {TRUE, "S-1-5-64-21"},   {TRUE, "S-1-5-64-14"},
2029 /* 54 */ {TRUE, "S-1-5-15"},      {TRUE, "S-1-5-1000"},    {FALSE, "S-1-5-32-557"},
2030 /* 57 */ {TRUE, "S-1-5-32-558"},  {TRUE, "S-1-5-32-559"},  {TRUE, "S-1-5-32-560"},
2031 /* 60 */ {TRUE, "S-1-5-32-561"}, {TRUE, "S-1-5-32-562"},
2032 /* Added in Windows Vista: */
2033 /* 62 */ {TRUE, "S-1-5-32-568"},
2034 /* 63 */ {TRUE, "S-1-5-17"},      {FALSE, "S-1-5-32-569"}, {TRUE, "S-1-16-0"},
2035 /* 66 */ {TRUE, "S-1-16-4096"},   {TRUE, "S-1-16-8192"},   {TRUE, "S-1-16-12288"},
2036 /* 69 */ {TRUE, "S-1-16-16384"},  {TRUE, "S-1-5-33"},      {TRUE, "S-1-3-4"},
2037 /* 72 */ {FALSE, "S-1-5-21-12-23-34-45-56-571"},  {FALSE, "S-1-5-21-12-23-34-45-56-572"},
2038 /* 74 */ {TRUE, "S-1-5-22"}, {FALSE, "S-1-5-21-12-23-34-45-56-521"}, {TRUE, "S-1-5-32-573"},
2039 /* 77 */ {FALSE, "S-1-5-21-12-23-34-45-56-498"}, {TRUE, "S-1-5-32-574"}, {TRUE, "S-1-16-8448"},
2040 /* 80 */ {FALSE, NULL}, {TRUE, "S-1-2-1"}, {TRUE, "S-1-5-65-1"}, {FALSE, NULL},
2041 /* 84 */ {TRUE, "S-1-15-2-1"},
2042 };
2043 
2044 static void test_CreateWellKnownSid(void)
2045 {
2046     SID_IDENTIFIER_AUTHORITY ident = { SECURITY_NT_AUTHORITY };
2047     PSID domainsid, sid;
2048     DWORD size, error;
2049     BOOL ret;
2050     unsigned int i;
2051 
2052     if (!pCreateWellKnownSid)
2053     {
2054         win_skip("CreateWellKnownSid not available\n");
2055         return;
2056     }
2057 
2058     size = 0;
2059     SetLastError(0xdeadbeef);
2060     ret = pCreateWellKnownSid(WinInteractiveSid, NULL, NULL, &size);
2061     error = GetLastError();
2062     ok(!ret, "CreateWellKnownSid succeeded\n");
2063     ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
2064     ok(size, "expected size > 0\n");
2065 
2066     SetLastError(0xdeadbeef);
2067     ret = pCreateWellKnownSid(WinInteractiveSid, NULL, NULL, &size);
2068     error = GetLastError();
2069     ok(!ret, "CreateWellKnownSid succeeded\n");
2070     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2071 
2072     sid = HeapAlloc(GetProcessHeap(), 0, size);
2073     ret = pCreateWellKnownSid(WinInteractiveSid, NULL, sid, &size);
2074     ok(ret, "CreateWellKnownSid failed %u\n", GetLastError());
2075     HeapFree(GetProcessHeap(), 0, sid);
2076 
2077     /* a domain sid usually have three subauthorities but we test that CreateWellKnownSid doesn't check it */
2078     AllocateAndInitializeSid(&ident, 6, SECURITY_NT_NON_UNIQUE, 12, 23, 34, 45, 56, 0, 0, &domainsid);
2079 
2080     for (i = 0; i < sizeof(well_known_sid_values)/sizeof(well_known_sid_values[0]); i++)
2081     {
2082         const struct well_known_sid_value *value = &well_known_sid_values[i];
2083         char sid_buffer[SECURITY_MAX_SID_SIZE];
2084         LPSTR str;
2085         DWORD cb;
2086 
2087         if (value->sid_string == NULL)
2088             continue;
2089 
2090         /* some SIDs aren't implemented by all Windows versions - detect it */
2091         cb = sizeof(sid_buffer);
2092         if (!pCreateWellKnownSid(i, NULL, sid_buffer, &cb))
2093         {
2094             skip("Well known SID %u not implemented\n", i);
2095             continue;
2096         }
2097 
2098         cb = sizeof(sid_buffer);
2099         ok(pCreateWellKnownSid(i, value->without_domain ? NULL : domainsid, sid_buffer, &cb), "Couldn't create well known sid %u\n", i);
2100         expect_eq(GetSidLengthRequired(*GetSidSubAuthorityCount(sid_buffer)), cb, DWORD, "%d");
2101         ok(IsValidSid(sid_buffer), "The sid is not valid\n");
2102         ok(ConvertSidToStringSidA(sid_buffer, &str), "Couldn't convert SID to string\n");
2103         ok(strcmp(str, value->sid_string) == 0, "%d: SID mismatch - expected %s, got %s\n", i,
2104             value->sid_string, str);
2105         LocalFree(str);
2106 
2107         if (value->without_domain)
2108         {
2109             char buf2[SECURITY_MAX_SID_SIZE];
2110             cb = sizeof(buf2);
2111             ok(pCreateWellKnownSid(i, domainsid, buf2, &cb), "Couldn't create well known sid %u with optional domain\n", i);
2112             expect_eq(GetSidLengthRequired(*GetSidSubAuthorityCount(sid_buffer)), cb, DWORD, "%d");
2113             ok(memcmp(buf2, sid_buffer, cb) == 0, "SID create with domain is different than without (%u)\n", i);
2114         }
2115     }
2116 
2117     FreeSid(domainsid);
2118 }
2119 
2120 static void test_LookupAccountSid(void)
2121 {
2122     SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
2123     CHAR accountA[MAX_PATH], domainA[MAX_PATH], usernameA[MAX_PATH];
2124     DWORD acc_sizeA, dom_sizeA, user_sizeA;
2125     DWORD real_acc_sizeA, real_dom_sizeA;
2126     WCHAR accountW[MAX_PATH], domainW[MAX_PATH];
2127     DWORD acc_sizeW, dom_sizeW;
2128     DWORD real_acc_sizeW, real_dom_sizeW;
2129     PSID pUsersSid = NULL;
2130     SID_NAME_USE use;
2131     BOOL ret;
2132     DWORD error, size, cbti = 0;
2133     MAX_SID  max_sid;
2134     CHAR *str_sidA;
2135     int i;
2136     HANDLE hToken;
2137     PTOKEN_USER ptiUser = NULL;
2138 
2139     /* native windows crashes if account size, domain size, or name use is NULL */
2140 
2141     ret = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
2142         DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &pUsersSid);
2143     ok(ret || (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED),
2144        "AllocateAndInitializeSid failed with error %d\n", GetLastError());
2145 
2146     /* not running on NT so give up */
2147     if (!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
2148         return;
2149 
2150     real_acc_sizeA = MAX_PATH;
2151     real_dom_sizeA = MAX_PATH;
2152     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &real_acc_sizeA, domainA, &real_dom_sizeA, &use);
2153     ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
2154 
2155     /* try NULL account */
2156     acc_sizeA = MAX_PATH;
2157     dom_sizeA = MAX_PATH;
2158     ret = LookupAccountSidA(NULL, pUsersSid, NULL, &acc_sizeA, domainA, &dom_sizeA, &use);
2159     ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
2160 
2161     /* try NULL domain */
2162     acc_sizeA = MAX_PATH;
2163     dom_sizeA = MAX_PATH;
2164     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, NULL, &dom_sizeA, &use);
2165     ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
2166 
2167     /* try a small account buffer */
2168     acc_sizeA = 1;
2169     dom_sizeA = MAX_PATH;
2170     accountA[0] = 0;
2171     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
2172     ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n");
2173     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2174        "LookupAccountSidA() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
2175 
2176     /* try a 0 sized account buffer */
2177     acc_sizeA = 0;
2178     dom_sizeA = MAX_PATH;
2179     accountA[0] = 0;
2180     LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
2181     /* this can fail or succeed depending on OS version but the size will always be returned */
2182     ok(acc_sizeA == real_acc_sizeA + 1,
2183        "LookupAccountSidA() Expected acc_size = %u, got %u\n",
2184        real_acc_sizeA + 1, acc_sizeA);
2185 
2186     /* try a 0 sized account buffer */
2187     acc_sizeA = 0;
2188     dom_sizeA = MAX_PATH;
2189     LookupAccountSidA(NULL, pUsersSid, NULL, &acc_sizeA, domainA, &dom_sizeA, &use);
2190     /* this can fail or succeed depending on OS version but the size will always be returned */
2191     ok(acc_sizeA == real_acc_sizeA + 1,
2192        "LookupAccountSid() Expected acc_size = %u, got %u\n",
2193        real_acc_sizeA + 1, acc_sizeA);
2194 
2195     /* try a small domain buffer */
2196     dom_sizeA = 1;
2197     acc_sizeA = MAX_PATH;
2198     accountA[0] = 0;
2199     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
2200     ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n");
2201     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2202        "LookupAccountSidA() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
2203 
2204     /* try a 0 sized domain buffer */
2205     dom_sizeA = 0;
2206     acc_sizeA = MAX_PATH;
2207     accountA[0] = 0;
2208     LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
2209     /* this can fail or succeed depending on OS version but the size will always be returned */
2210     ok(dom_sizeA == real_dom_sizeA + 1,
2211        "LookupAccountSidA() Expected dom_size = %u, got %u\n",
2212        real_dom_sizeA + 1, dom_sizeA);
2213 
2214     /* try a 0 sized domain buffer */
2215     dom_sizeA = 0;
2216     acc_sizeA = MAX_PATH;
2217     LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, NULL, &dom_sizeA, &use);
2218     /* this can fail or succeed depending on OS version but the size will always be returned */
2219     ok(dom_sizeA == real_dom_sizeA + 1,
2220        "LookupAccountSidA() Expected dom_size = %u, got %u\n",
2221        real_dom_sizeA + 1, dom_sizeA);
2222 
2223     real_acc_sizeW = MAX_PATH;
2224     real_dom_sizeW = MAX_PATH;
2225     ret = LookupAccountSidW(NULL, pUsersSid, accountW, &real_acc_sizeW, domainW, &real_dom_sizeW, &use);
2226     ok(ret, "LookupAccountSidW() Expected TRUE, got FALSE\n");
2227 
2228     /* try an invalid system name */
2229     real_acc_sizeA = MAX_PATH;
2230     real_dom_sizeA = MAX_PATH;
2231     ret = LookupAccountSidA("deepthought", pUsersSid, accountA, &real_acc_sizeA, domainA, &real_dom_sizeA, &use);
2232     ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n");
2233     ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR /* Vista */,
2234        "LookupAccountSidA() Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %u\n", GetLastError());
2235 
2236     /* native windows crashes if domainW or accountW is NULL */
2237 
2238     /* try a small account buffer */
2239     acc_sizeW = 1;
2240     dom_sizeW = MAX_PATH;
2241     accountW[0] = 0;
2242     ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
2243     ok(!ret, "LookupAccountSidW() Expected FALSE got TRUE\n");
2244     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2245        "LookupAccountSidW() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
2246 
2247     /* try a 0 sized account buffer */
2248     acc_sizeW = 0;
2249     dom_sizeW = MAX_PATH;
2250     accountW[0] = 0;
2251     LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
2252     /* this can fail or succeed depending on OS version but the size will always be returned */
2253     ok(acc_sizeW == real_acc_sizeW + 1,
2254        "LookupAccountSidW() Expected acc_size = %u, got %u\n",
2255        real_acc_sizeW + 1, acc_sizeW);
2256 
2257     /* try a 0 sized account buffer */
2258     acc_sizeW = 0;
2259     dom_sizeW = MAX_PATH;
2260     LookupAccountSidW(NULL, pUsersSid, NULL, &acc_sizeW, domainW, &dom_sizeW, &use);
2261     /* this can fail or succeed depending on OS version but the size will always be returned */
2262     ok(acc_sizeW == real_acc_sizeW + 1,
2263        "LookupAccountSidW() Expected acc_size = %u, got %u\n",
2264        real_acc_sizeW + 1, acc_sizeW);
2265 
2266     /* try a small domain buffer */
2267     dom_sizeW = 1;
2268     acc_sizeW = MAX_PATH;
2269     accountW[0] = 0;
2270     ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
2271     ok(!ret, "LookupAccountSidW() Expected FALSE got TRUE\n");
2272     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2273        "LookupAccountSidW() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
2274 
2275     /* try a 0 sized domain buffer */
2276     dom_sizeW = 0;
2277     acc_sizeW = MAX_PATH;
2278     accountW[0] = 0;
2279     LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
2280     /* this can fail or succeed depending on OS version but the size will always be returned */
2281     ok(dom_sizeW == real_dom_sizeW + 1,
2282        "LookupAccountSidW() Expected dom_size = %u, got %u\n",
2283        real_dom_sizeW + 1, dom_sizeW);
2284 
2285     /* try a 0 sized domain buffer */
2286     dom_sizeW = 0;
2287     acc_sizeW = MAX_PATH;
2288     LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, NULL, &dom_sizeW, &use);
2289     /* this can fail or succeed depending on OS version but the size will always be returned */
2290     ok(dom_sizeW == real_dom_sizeW + 1,
2291        "LookupAccountSidW() Expected dom_size = %u, got %u\n",
2292        real_dom_sizeW + 1, dom_sizeW);
2293 
2294     acc_sizeW = dom_sizeW = use = 0;
2295     SetLastError(0xdeadbeef);
2296     ret = LookupAccountSidW(NULL, pUsersSid, NULL, &acc_sizeW, NULL, &dom_sizeW, &use);
2297     error = GetLastError();
2298     ok(!ret, "LookupAccountSidW failed %u\n", GetLastError());
2299     ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
2300     ok(acc_sizeW, "expected non-zero account size\n");
2301     ok(dom_sizeW, "expected non-zero domain size\n");
2302     ok(!use, "expected zero use %u\n", use);
2303 
2304     FreeSid(pUsersSid);
2305 
2306     /* Test LookupAccountSid with Sid retrieved from token information.
2307      This assumes this process is running under the account of the current user.*/
2308     ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_DUPLICATE, &hToken);
2309     ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
2310     ret = GetTokenInformation(hToken, TokenUser, NULL, 0, &cbti);
2311     ok(!ret, "GetTokenInformation failed with error %d\n", GetLastError());
2312     ptiUser = HeapAlloc(GetProcessHeap(), 0, cbti);
2313     if (GetTokenInformation(hToken, TokenUser, ptiUser, cbti, &cbti))
2314     {
2315         acc_sizeA = dom_sizeA = MAX_PATH;
2316         ret = LookupAccountSidA(NULL, ptiUser->User.Sid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
2317         ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
2318         user_sizeA = MAX_PATH;
2319         ret = GetUserNameA(usernameA , &user_sizeA);
2320         ok(ret, "GetUserNameA() Expected TRUE, got FALSE\n");
2321         ok(lstrcmpA(usernameA, accountA) == 0, "LookupAccountSidA() Expected account name: %s got: %s\n", usernameA, accountA );
2322     }
2323     HeapFree(GetProcessHeap(), 0, ptiUser);
2324 
2325     if (pCreateWellKnownSid)
2326     {
2327         trace("Well Known SIDs:\n");
2328         for (i = 0; i <= 84; i++)
2329         {
2330             size = SECURITY_MAX_SID_SIZE;
2331             if (pCreateWellKnownSid(i, NULL, &max_sid.sid, &size))
2332             {
2333                 if (ConvertSidToStringSidA(&max_sid.sid, &str_sidA))
2334                 {
2335                     acc_sizeA = MAX_PATH;
2336                     dom_sizeA = MAX_PATH;
2337                     if (LookupAccountSidA(NULL, &max_sid.sid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use))
2338                         trace(" %d: %s %s\\%s %d\n", i, str_sidA, domainA, accountA, use);
2339                     LocalFree(str_sidA);
2340                 }
2341             }
2342             else
2343             {
2344                 if (GetLastError() != ERROR_INVALID_PARAMETER)
2345                     trace(" CreateWellKnownSid(%d) failed: %d\n", i, GetLastError());
2346                 else
2347                     trace(" %d: not supported\n", i);
2348             }
2349         }
2350 
2351         pLsaQueryInformationPolicy = (void *)GetProcAddress( hmod, "LsaQueryInformationPolicy");
2352         pLsaOpenPolicy = (void *)GetProcAddress( hmod, "LsaOpenPolicy");
2353         pLsaFreeMemory = (void *)GetProcAddress( hmod, "LsaFreeMemory");
2354         pLsaClose = (void *)GetProcAddress( hmod, "LsaClose");
2355 
2356         if (pLsaQueryInformationPolicy && pLsaOpenPolicy && pLsaFreeMemory && pLsaClose)
2357         {
2358             NTSTATUS status;
2359             LSA_HANDLE handle;
2360             LSA_OBJECT_ATTRIBUTES object_attributes;
2361 
2362             ZeroMemory(&object_attributes, sizeof(object_attributes));
2363             object_attributes.Length = sizeof(object_attributes);
2364 
2365             status = pLsaOpenPolicy( NULL, &object_attributes, POLICY_ALL_ACCESS, &handle);
2366             ok(status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED,
2367                "LsaOpenPolicy(POLICY_ALL_ACCESS) returned 0x%08x\n", status);
2368 
2369             /* try a more restricted access mask if necessary */
2370             if (status == STATUS_ACCESS_DENIED) {
2371                 trace("LsaOpenPolicy(POLICY_ALL_ACCESS) failed, trying POLICY_VIEW_LOCAL_INFORMATION\n");
2372                 status = pLsaOpenPolicy( NULL, &object_attributes, POLICY_VIEW_LOCAL_INFORMATION, &handle);
2373                 ok(status == STATUS_SUCCESS, "LsaOpenPolicy(POLICY_VIEW_LOCAL_INFORMATION) returned 0x%08x\n", status);
2374             }
2375 
2376             if (status == STATUS_SUCCESS)
2377             {
2378                 PPOLICY_ACCOUNT_DOMAIN_INFO info;
2379                 status = pLsaQueryInformationPolicy(handle, PolicyAccountDomainInformation, (PVOID*)&info);
2380                 ok(status == STATUS_SUCCESS, "LsaQueryInformationPolicy() failed, returned 0x%08x\n", status);
2381                 if (status == STATUS_SUCCESS)
2382                 {
2383                     ok(info->DomainSid!=0, "LsaQueryInformationPolicy(PolicyAccountDomainInformation) missing SID\n");
2384                     if (info->DomainSid)
2385                     {
2386                         int count = *GetSidSubAuthorityCount(info->DomainSid);
2387                         CopySid(GetSidLengthRequired(count), &max_sid, info->DomainSid);
2388                         test_sid_str((PSID)&max_sid.sid);
2389                         max_sid.sid.SubAuthority[count] = DOMAIN_USER_RID_ADMIN;
2390                         max_sid.sid.SubAuthorityCount = count + 1;
2391                         test_sid_str((PSID)&max_sid.sid);
2392                         max_sid.sid.SubAuthority[count] = DOMAIN_USER_RID_GUEST;
2393                         test_sid_str((PSID)&max_sid.sid);
2394                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_ADMINS;
2395                         test_sid_str((PSID)&max_sid.sid);
2396                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_USERS;
2397                         test_sid_str((PSID)&max_sid.sid);
2398                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_GUESTS;
2399                         test_sid_str((PSID)&max_sid.sid);
2400                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_COMPUTERS;
2401                         test_sid_str((PSID)&max_sid.sid);
2402                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_CONTROLLERS;
2403                         test_sid_str((PSID)&max_sid.sid);
2404                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_CERT_ADMINS;
2405                         test_sid_str((PSID)&max_sid.sid);
2406                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_SCHEMA_ADMINS;
2407                         test_sid_str((PSID)&max_sid.sid);
2408                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_ENTERPRISE_ADMINS;
2409                         test_sid_str((PSID)&max_sid.sid);
2410                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_POLICY_ADMINS;
2411                         test_sid_str((PSID)&max_sid.sid);
2412                         max_sid.sid.SubAuthority[count] = DOMAIN_ALIAS_RID_RAS_SERVERS;
2413                         test_sid_str((PSID)&max_sid.sid);
2414                         max_sid.sid.SubAuthority[count] = 1000;	/* first user account */
2415                         test_sid_str((PSID)&max_sid.sid);
2416                     }
2417 
2418                     pLsaFreeMemory((LPVOID)info);
2419                 }
2420 
2421                 status = pLsaClose(handle);
2422                 ok(status == STATUS_SUCCESS, "LsaClose() failed, returned 0x%08x\n", status);
2423             }
2424         }
2425     }
2426 }
2427 
2428 static BOOL get_sid_info(PSID psid, LPSTR *user, LPSTR *dom)
2429 {
2430     static CHAR account[UNLEN + 1];
2431     static CHAR domain[UNLEN + 1];
2432     DWORD size, dom_size;
2433     SID_NAME_USE use;
2434 
2435     *user = account;
2436     *dom = domain;
2437 
2438     size = dom_size = UNLEN + 1;
2439     account[0] = '\0';
2440     domain[0] = '\0';
2441     SetLastError(0xdeadbeef);
2442     return LookupAccountSidA(NULL, psid, account, &size, domain, &dom_size, &use);
2443 }
2444 
2445 static void check_wellknown_name(const char* name, WELL_KNOWN_SID_TYPE result)
2446 {
2447     SID_IDENTIFIER_AUTHORITY ident = { SECURITY_NT_AUTHORITY };
2448     PSID domainsid = NULL;
2449     char wk_sid[SECURITY_MAX_SID_SIZE];
2450     DWORD cb;
2451 
2452     DWORD sid_size, domain_size;
2453     SID_NAME_USE sid_use;
2454     LPSTR domain, account, sid_domain, wk_domain, wk_account;
2455     PSID psid;
2456     BOOL ret ,ret2;
2457 
2458     sid_size = 0;
2459     domain_size = 0;
2460     ret = LookupAccountNameA(NULL, name, NULL, &sid_size, NULL, &domain_size, &sid_use);
2461     ok(!ret, " %s Should have failed to lookup account name\n", name);
2462     psid = HeapAlloc(GetProcessHeap(),0,sid_size);
2463     domain = HeapAlloc(GetProcessHeap(),0,domain_size);
2464     ret = LookupAccountNameA(NULL, name, psid, &sid_size, domain, &domain_size, &sid_use);
2465 
2466     if (!result)
2467     {
2468         ok(!ret, " %s Should have failed to lookup account name\n",name);
2469         goto cleanup;
2470     }
2471 
2472     AllocateAndInitializeSid(&ident, 6, SECURITY_NT_NON_UNIQUE, 12, 23, 34, 45, 56, 0, 0, &domainsid);
2473     cb = sizeof(wk_sid);
2474     if (!pCreateWellKnownSid(result, domainsid, wk_sid, &cb))
2475     {
2476         win_skip("SID %i is not available on the system\n",result);
2477         goto cleanup;
2478     }
2479 
2480     ret2 = get_sid_info(wk_sid, &wk_account, &wk_domain);
2481     if (!ret2 && GetLastError() == ERROR_NONE_MAPPED)
2482     {
2483         win_skip("CreateWellKnownSid() succeeded but the account '%s' is not present (W2K)\n", name);
2484         goto cleanup;
2485     }
2486 
2487     get_sid_info(psid, &account, &sid_domain);
2488 
2489     ok(ret, "Failed to lookup account name %s\n",name);
2490     ok(sid_size != 0, "sid_size was zero\n");
2491 
2492     ok(EqualSid(psid,wk_sid),"%s Sid %s fails to match well known sid %s!\n",
2493        name, debugstr_sid(psid), debugstr_sid(wk_sid));
2494 
2495     ok(!lstrcmpA(account, wk_account), "Expected %s , got %s\n", account, wk_account);
2496     ok(!lstrcmpA(domain, wk_domain), "Expected %s, got %s\n", wk_domain, domain);
2497     ok(sid_use == SidTypeWellKnownGroup , "Expected Use (5), got %d\n", sid_use);
2498 
2499 cleanup:
2500     FreeSid(domainsid);
2501     HeapFree(GetProcessHeap(),0,psid);
2502     HeapFree(GetProcessHeap(),0,domain);
2503 }
2504 
2505 static void test_LookupAccountName(void)
2506 {
2507     DWORD sid_size, domain_size, user_size;
2508     DWORD sid_save, domain_save;
2509     CHAR user_name[UNLEN + 1];
2510     CHAR computer_name[UNLEN + 1];
2511     SID_NAME_USE sid_use;
2512     LPSTR domain, account, sid_dom;
2513     PSID psid;
2514     BOOL ret;
2515 
2516     /* native crashes if (assuming all other parameters correct):
2517      *  - peUse is NULL
2518      *  - Sid is NULL and cbSid is > 0
2519      *  - cbSid or cchReferencedDomainName are NULL
2520      *  - ReferencedDomainName is NULL and cchReferencedDomainName is the correct size
2521      */
2522 
2523     user_size = UNLEN + 1;
2524     SetLastError(0xdeadbeef);
2525     ret = GetUserNameA(user_name, &user_size);
2526     ok(ret, "Failed to get user name : %d\n", GetLastError());
2527 
2528     /* get sizes */
2529     sid_size = 0;
2530     domain_size = 0;
2531     sid_use = 0xcafebabe;
2532     SetLastError(0xdeadbeef);
2533     ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, NULL, &domain_size, &sid_use);
2534     if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
2535     {
2536         win_skip("LookupAccountNameA is not implemented\n");
2537         return;
2538     }
2539     ok(!ret, "Expected 0, got %d\n", ret);
2540     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2541        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2542     ok(sid_size != 0, "Expected non-zero sid size\n");
2543     ok(domain_size != 0, "Expected non-zero domain size\n");
2544     ok(sid_use == 0xcafebabe, "Expected 0xcafebabe, got %d\n", sid_use);
2545 
2546     sid_save = sid_size;
2547     domain_save = domain_size;
2548 
2549     psid = HeapAlloc(GetProcessHeap(), 0, sid_size);
2550     domain = HeapAlloc(GetProcessHeap(), 0, domain_size);
2551 
2552     /* try valid account name */
2553     ret = LookupAccountNameA(NULL, user_name, psid, &sid_size, domain, &domain_size, &sid_use);
2554     get_sid_info(psid, &account, &sid_dom);
2555     ok(ret, "Failed to lookup account name\n");
2556     ok(sid_size == GetLengthSid(psid), "Expected %d, got %d\n", GetLengthSid(psid), sid_size);
2557     ok(!lstrcmpA(account, user_name), "Expected %s, got %s\n", user_name, account);
2558     ok(!lstrcmpiA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
2559     ok(domain_size == domain_save - 1, "Expected %d, got %d\n", domain_save - 1, domain_size);
2560     ok(strlen(domain) == domain_size, "Expected %d, got %d\n", lstrlenA(domain), domain_size);
2561     ok(sid_use == SidTypeUser, "Expected SidTypeUser (%d), got %d\n", SidTypeUser, sid_use);
2562     domain_size = domain_save;
2563     sid_size = sid_save;
2564 
2565     if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH)
2566     {
2567         skip("Non-English locale (test with hardcoded 'Everyone')\n");
2568     }
2569     else
2570     {
2571         ret = LookupAccountNameA(NULL, "Everyone", psid, &sid_size, domain, &domain_size, &sid_use);
2572         get_sid_info(psid, &account, &sid_dom);
2573         ok(ret, "Failed to lookup account name\n");
2574         ok(sid_size != 0, "sid_size was zero\n");
2575         ok(!lstrcmpA(account, "Everyone"), "Expected Everyone, got %s\n", account);
2576         ok(!lstrcmpiA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
2577         ok(domain_size == 0, "Expected 0, got %d\n", domain_size);
2578         ok(strlen(domain) == domain_size, "Expected %d, got %d\n", lstrlenA(domain), domain_size);
2579         ok(sid_use == SidTypeWellKnownGroup, "Expected SidTypeWellKnownGroup (%d), got %d\n", SidTypeWellKnownGroup, sid_use);
2580         domain_size = domain_save;
2581     }
2582 
2583     /* NULL Sid with zero sid size */
2584     SetLastError(0xdeadbeef);
2585     sid_size = 0;
2586     ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, domain, &domain_size, &sid_use);
2587     ok(!ret, "Expected 0, got %d\n", ret);
2588     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2589        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2590     ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size);
2591     ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
2592 
2593     /* try cchReferencedDomainName - 1 */
2594     SetLastError(0xdeadbeef);
2595     domain_size--;
2596     ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, domain, &domain_size, &sid_use);
2597     ok(!ret, "Expected 0, got %d\n", ret);
2598     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2599        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2600     ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size);
2601     ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
2602 
2603     /* NULL ReferencedDomainName with zero domain name size */
2604     SetLastError(0xdeadbeef);
2605     domain_size = 0;
2606     ret = LookupAccountNameA(NULL, user_name, psid, &sid_size, NULL, &domain_size, &sid_use);
2607     ok(!ret, "Expected 0, got %d\n", ret);
2608     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2609        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2610     ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size);
2611     ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
2612 
2613     HeapFree(GetProcessHeap(), 0, psid);
2614     HeapFree(GetProcessHeap(), 0, domain);
2615 
2616     /* get sizes for NULL account name */
2617     sid_size = 0;
2618     domain_size = 0;
2619     sid_use = 0xcafebabe;
2620     SetLastError(0xdeadbeef);
2621     ret = LookupAccountNameA(NULL, NULL, NULL, &sid_size, NULL, &domain_size, &sid_use);
2622     if (!ret && GetLastError() == ERROR_NONE_MAPPED)
2623         win_skip("NULL account name doesn't work on NT4\n");
2624     else
2625     {
2626         ok(!ret, "Expected 0, got %d\n", ret);
2627         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2628            "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2629         ok(sid_size != 0, "Expected non-zero sid size\n");
2630         ok(domain_size != 0, "Expected non-zero domain size\n");
2631         ok(sid_use == 0xcafebabe, "Expected 0xcafebabe, got %d\n", sid_use);
2632 
2633         psid = HeapAlloc(GetProcessHeap(), 0, sid_size);
2634         domain = HeapAlloc(GetProcessHeap(), 0, domain_size);
2635 
2636         /* try NULL account name */
2637         ret = LookupAccountNameA(NULL, NULL, psid, &sid_size, domain, &domain_size, &sid_use);
2638         get_sid_info(psid, &account, &sid_dom);
2639         ok(ret, "Failed to lookup account name\n");
2640         /* Using a fixed string will not work on different locales */
2641         ok(!lstrcmpiA(account, domain),
2642            "Got %s for account and %s for domain, these should be the same\n", account, domain);
2643         ok(sid_use == SidTypeDomain, "Expected SidTypeDomain (%d), got %d\n", SidTypeDomain, sid_use);
2644 
2645         HeapFree(GetProcessHeap(), 0, psid);
2646         HeapFree(GetProcessHeap(), 0, domain);
2647     }
2648 
2649     /* try an invalid account name */
2650     SetLastError(0xdeadbeef);
2651     sid_size = 0;
2652     domain_size = 0;
2653     ret = LookupAccountNameA(NULL, "oogabooga", NULL, &sid_size, NULL, &domain_size, &sid_use);
2654     ok(!ret, "Expected 0, got %d\n", ret);
2655     ok(GetLastError() == ERROR_NONE_MAPPED ||
2656        broken(GetLastError() == ERROR_TRUSTED_RELATIONSHIP_FAILURE),
2657        "Expected ERROR_NONE_MAPPED, got %d\n", GetLastError());
2658     ok(sid_size == 0, "Expected 0, got %d\n", sid_size);
2659     ok(domain_size == 0, "Expected 0, got %d\n", domain_size);
2660 
2661     /* try an invalid system name */
2662     SetLastError(0xdeadbeef);
2663     sid_size = 0;
2664     domain_size = 0;
2665     ret = LookupAccountNameA("deepthought", NULL, NULL, &sid_size, NULL, &domain_size, &sid_use);
2666     ok(!ret, "Expected 0, got %d\n", ret);
2667     ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR /* Vista */,
2668        "Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %d\n", GetLastError());
2669     ok(sid_size == 0, "Expected 0, got %d\n", sid_size);
2670     ok(domain_size == 0, "Expected 0, got %d\n", domain_size);
2671 
2672     /* try with the computer name as the account name */
2673     domain_size = sizeof(computer_name);
2674     GetComputerNameA(computer_name, &domain_size);
2675     sid_size = 0;
2676     domain_size = 0;
2677     ret = LookupAccountNameA(NULL, computer_name, NULL, &sid_size, NULL, &domain_size, &sid_use);
2678     ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
2679        GetLastError() == ERROR_NONE_MAPPED /* in a domain */ ||
2680        broken(GetLastError() == ERROR_TRUSTED_DOMAIN_FAILURE) ||
2681        broken(GetLastError() == ERROR_TRUSTED_RELATIONSHIP_FAILURE)),
2682        "LookupAccountNameA failed: %d\n", GetLastError());
2683     if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2684     {
2685         psid = HeapAlloc(GetProcessHeap(), 0, sid_size);
2686         domain = HeapAlloc(GetProcessHeap(), 0, domain_size);
2687         ret = LookupAccountNameA(NULL, computer_name, psid, &sid_size, domain, &domain_size, &sid_use);
2688         ok(ret, "LookupAccountNameA failed: %d\n", GetLastError());
2689         ok(sid_use == SidTypeDomain ||
2690            (sid_use == SidTypeUser && ! strcmp(computer_name, user_name)), "expected SidTypeDomain for %s, got %d\n", computer_name, sid_use);
2691         HeapFree(GetProcessHeap(), 0, domain);
2692         HeapFree(GetProcessHeap(), 0, psid);
2693     }
2694 
2695     /* Well Known names */
2696     if (!pCreateWellKnownSid)
2697     {
2698         win_skip("CreateWellKnownSid not available\n");
2699         return;
2700     }
2701 
2702     if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH)
2703     {
2704         skip("Non-English locale (skipping well known name creation tests)\n");
2705         return;
2706     }
2707 
2708     check_wellknown_name("LocalService", WinLocalServiceSid);
2709     check_wellknown_name("Local Service", WinLocalServiceSid);
2710     /* 2 spaces */
2711     check_wellknown_name("Local  Service", 0);
2712     check_wellknown_name("NetworkService", WinNetworkServiceSid);
2713     check_wellknown_name("Network Service", WinNetworkServiceSid);
2714 
2715     /* example of some names where the spaces are not optional */
2716     check_wellknown_name("Terminal Server User", WinTerminalServerSid);
2717     check_wellknown_name("TerminalServer User", 0);
2718     check_wellknown_name("TerminalServerUser", 0);
2719     check_wellknown_name("Terminal ServerUser", 0);
2720 
2721     check_wellknown_name("enterprise domain controllers",WinEnterpriseControllersSid);
2722     check_wellknown_name("enterprisedomain controllers", 0);
2723     check_wellknown_name("enterprise domaincontrollers", 0);
2724     check_wellknown_name("enterprisedomaincontrollers", 0);
2725 
2726     /* case insensitivity */
2727     check_wellknown_name("lOCAlServICE", WinLocalServiceSid);
2728 
2729     /* fully qualified account names */
2730     check_wellknown_name("NT AUTHORITY\\LocalService", WinLocalServiceSid);
2731     check_wellknown_name("nt authority\\Network Service", WinNetworkServiceSid);
2732     check_wellknown_name("nt authority test\\Network Service", 0);
2733     check_wellknown_name("Dummy\\Network Service", 0);
2734     check_wellknown_name("ntauthority\\Network Service", 0);
2735 }
2736 
2737 static void test_security_descriptor(void)
2738 {
2739     SECURITY_DESCRIPTOR sd;
2740     char buf[8192];
2741     DWORD size;
2742     BOOL isDefault, isPresent, ret;
2743     PACL pacl;
2744     PSID psid;
2745 
2746     SetLastError(0xdeadbeef);
2747     ret = InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
2748     if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2749     {
2750         win_skip("InitializeSecurityDescriptor is not implemented\n");
2751         return;
2752     }
2753 
2754     ok(GetSecurityDescriptorOwner(&sd, &psid, &isDefault), "GetSecurityDescriptorOwner failed\n");
2755     expect_eq(psid, NULL, PSID, "%p");
2756     expect_eq(isDefault, FALSE, BOOL, "%d");
2757     sd.Control |= SE_DACL_PRESENT | SE_SACL_PRESENT;
2758 
2759     SetLastError(0xdeadbeef);
2760     size = 5;
2761     expect_eq(MakeSelfRelativeSD(&sd, buf, &size), FALSE, BOOL, "%d");
2762     expect_eq(GetLastError(), ERROR_INSUFFICIENT_BUFFER, DWORD, "%u");
2763     ok(size > 5, "Size not increased\n");
2764     if (size <= 8192)
2765     {
2766         expect_eq(MakeSelfRelativeSD(&sd, buf, &size), TRUE, BOOL, "%d");
2767         ok(GetSecurityDescriptorOwner(&sd, &psid, &isDefault), "GetSecurityDescriptorOwner failed\n");
2768         expect_eq(psid, NULL, PSID, "%p");
2769         expect_eq(isDefault, FALSE, BOOL, "%d");
2770         ok(GetSecurityDescriptorGroup(&sd, &psid, &isDefault), "GetSecurityDescriptorGroup failed\n");
2771         expect_eq(psid, NULL, PSID, "%p");
2772         expect_eq(isDefault, FALSE, BOOL, "%d");
2773         ok(GetSecurityDescriptorDacl(&sd, &isPresent, &pacl, &isDefault), "GetSecurityDescriptorDacl failed\n");
2774         expect_eq(isPresent, TRUE, BOOL, "%d");
2775         expect_eq(psid, NULL, PSID, "%p");
2776         expect_eq(isDefault, FALSE, BOOL, "%d");
2777         ok(GetSecurityDescriptorSacl(&sd, &isPresent, &pacl, &isDefault), "GetSecurityDescriptorSacl failed\n");
2778         expect_eq(isPresent, TRUE, BOOL, "%d");
2779         expect_eq(psid, NULL, PSID, "%p");
2780         expect_eq(isDefault, FALSE, BOOL, "%d");
2781     }
2782 }
2783 
2784 #define TEST_GRANTED_ACCESS(a,b) test_granted_access(a,b,0,__LINE__)
2785 #define TEST_GRANTED_ACCESS2(a,b,c) test_granted_access(a,b,c,__LINE__)
2786 static void test_granted_access(HANDLE handle, ACCESS_MASK access,
2787                                 ACCESS_MASK alt, int line)
2788 {
2789     OBJECT_BASIC_INFORMATION obj_info;
2790     NTSTATUS status;
2791 
2792     if (!pNtQueryObject)
2793     {
2794         skip_(__FILE__, line)("Not NT platform - skipping tests\n");
2795         return;
2796     }
2797 
2798     status = pNtQueryObject( handle, ObjectBasicInformation, &obj_info,
2799                              sizeof(obj_info), NULL );
2800     ok_(__FILE__, line)(!status, "NtQueryObject with err: %08x\n", status);
2801     if (alt)
2802         ok_(__FILE__, line)(obj_info.GrantedAccess == access ||
2803             obj_info.GrantedAccess == alt, "Granted access should be 0x%08x "
2804             "or 0x%08x, instead of 0x%08x\n", access, alt, obj_info.GrantedAccess);
2805     else
2806         ok_(__FILE__, line)(obj_info.GrantedAccess == access, "Granted access should "
2807             "be 0x%08x, instead of 0x%08x\n", access, obj_info.GrantedAccess);
2808 }
2809 
2810 #define CHECK_SET_SECURITY(o,i,e) \
2811     do{ \
2812         BOOL res_; \
2813         DWORD err; \
2814         SetLastError( 0xdeadbeef ); \
2815         res_ = SetKernelObjectSecurity( o, i, SecurityDescriptor ); \
2816         err = GetLastError(); \
2817         if (e == ERROR_SUCCESS) \
2818             ok(res_, "SetKernelObjectSecurity failed with %d\n", err); \
2819         else \
2820             ok(!res_ && err == e, "SetKernelObjectSecurity should have failed " \
2821                "with %s, instead of %d\n", #e, err); \
2822     }while(0)
2823 
2824 static void test_process_security(void)
2825 {
2826     BOOL res;
2827     PTOKEN_USER user;
2828     PTOKEN_OWNER owner;
2829     PTOKEN_PRIMARY_GROUP group;
2830     PSID AdminSid = NULL, UsersSid = NULL, UserSid = NULL;
2831     PACL Acl = NULL, ThreadAcl = NULL;
2832     SECURITY_DESCRIPTOR *SecurityDescriptor = NULL, *ThreadSecurityDescriptor = NULL;
2833     char buffer[MAX_PATH], account[MAX_PATH], domain[MAX_PATH];
2834     PROCESS_INFORMATION info;
2835     STARTUPINFOA startup;
2836     SECURITY_ATTRIBUTES psa, tsa;
2837     HANDLE token, event;
2838     DWORD size, acc_size, dom_size, ret;
2839     SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
2840     PSID EveryoneSid = NULL;
2841     SID_NAME_USE use;
2842 
2843     Acl = HeapAlloc(GetProcessHeap(), 0, 256);
2844     res = InitializeAcl(Acl, 256, ACL_REVISION);
2845     if (!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2846     {
2847         win_skip("ACLs not implemented - skipping tests\n");
2848         HeapFree(GetProcessHeap(), 0, Acl);
2849         return;
2850     }
2851     ok(res, "InitializeAcl failed with error %d\n", GetLastError());
2852 
2853     res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
2854     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
2855 
2856     /* get owner from the token we might be running as a user not admin */
2857     res = OpenProcessToken( GetCurrentProcess(), MAXIMUM_ALLOWED, &token );
2858     ok(res, "OpenProcessToken failed with error %d\n", GetLastError());
2859     if (!res)
2860     {
2861         HeapFree(GetProcessHeap(), 0, Acl);
2862         return;
2863     }
2864 
2865     res = GetTokenInformation( token, TokenOwner, NULL, 0, &size );
2866     ok(!res, "Expected failure, got %d\n", res);
2867     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2868        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2869 
2870     owner = HeapAlloc(GetProcessHeap(), 0, size);
2871     res = GetTokenInformation( token, TokenOwner, owner, size, &size );
2872     ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
2873     AdminSid = owner->Owner;
2874     test_sid_str(AdminSid);
2875 
2876     res = GetTokenInformation( token, TokenPrimaryGroup, NULL, 0, &size );
2877     ok(!res, "Expected failure, got %d\n", res);
2878     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2879        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2880 
2881     group = HeapAlloc(GetProcessHeap(), 0, size);
2882     res = GetTokenInformation( token, TokenPrimaryGroup, group, size, &size );
2883     ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
2884     UsersSid = group->PrimaryGroup;
2885     test_sid_str(UsersSid);
2886 
2887     acc_size = sizeof(account);
2888     dom_size = sizeof(domain);
2889     ret = LookupAccountSidA( NULL, UsersSid, account, &acc_size, domain, &dom_size, &use );
2890     ok(ret, "LookupAccountSid failed with %d\n", ret);
2891     ok(use == SidTypeGroup, "expect SidTypeGroup, got %d\n", use);
2892     ok(!strcmp(account, "None"), "expect None, got %s\n", account);
2893 
2894     res = GetTokenInformation( token, TokenUser, NULL, 0, &size );
2895     ok(!res, "Expected failure, got %d\n", res);
2896     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2897        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2898 
2899     user = HeapAlloc(GetProcessHeap(), 0, size);
2900     res = GetTokenInformation( token, TokenUser, user, size, &size );
2901     ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
2902     UserSid = user->User.Sid;
2903     test_sid_str(UserSid);
2904     ok(EqualPrefixSid(UsersSid, UserSid), "TokenPrimaryGroup Sid and TokenUser Sid don't match.\n");
2905 
2906     CloseHandle( token );
2907     if (!res)
2908     {
2909         HeapFree(GetProcessHeap(), 0, group);
2910         HeapFree(GetProcessHeap(), 0, owner);
2911         HeapFree(GetProcessHeap(), 0, user);
2912         HeapFree(GetProcessHeap(), 0, Acl);
2913         return;
2914     }
2915 
2916     res = AddAccessDeniedAce(Acl, ACL_REVISION, PROCESS_VM_READ, AdminSid);
2917     ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError());
2918     res = AddAccessAllowedAce(Acl, ACL_REVISION, PROCESS_ALL_ACCESS, AdminSid);
2919     ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
2920 
2921     SecurityDescriptor = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
2922     res = InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
2923     ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
2924 
2925     event = CreateEventA( NULL, TRUE, TRUE, "test_event" );
2926     ok(event != NULL, "CreateEvent %d\n", GetLastError());
2927 
2928     SecurityDescriptor->Revision = 0;
2929     CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_UNKNOWN_REVISION );
2930     SecurityDescriptor->Revision = SECURITY_DESCRIPTOR_REVISION;
2931 
2932     CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR );
2933     CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR );
2934     CHECK_SET_SECURITY( event, SACL_SECURITY_INFORMATION, ERROR_ACCESS_DENIED );
2935     CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
2936     /* NULL DACL is valid and means that everyone has access */
2937     SecurityDescriptor->Control |= SE_DACL_PRESENT;
2938     CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
2939 
2940     /* Set owner and group and dacl */
2941     res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE);
2942     ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
2943     CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_SUCCESS );
2944     test_owner_equal( event, AdminSid, __LINE__ );
2945 
2946     res = SetSecurityDescriptorGroup(SecurityDescriptor, EveryoneSid, FALSE);
2947     ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
2948     CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_SUCCESS );
2949     test_group_equal( event, EveryoneSid, __LINE__ );
2950 
2951     res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
2952     ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
2953     CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
2954     /* setting a dacl should not change the owner or group */
2955     test_owner_equal( event, AdminSid, __LINE__ );
2956     test_group_equal( event, EveryoneSid, __LINE__ );
2957 
2958     /* Test again with a different SID in case the previous SID also happens to
2959      * be the one that is incorrectly replacing the group. */
2960     res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, FALSE);
2961     ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
2962     CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_SUCCESS );
2963     test_group_equal( event, UsersSid, __LINE__ );
2964 
2965     res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
2966     ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
2967     CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
2968     test_group_equal( event, UsersSid, __LINE__ );
2969 
2970     sprintf(buffer, "%s tests/security.c test", myARGV[0]);
2971     memset(&startup, 0, sizeof(startup));
2972     startup.cb = sizeof(startup);
2973     startup.dwFlags = STARTF_USESHOWWINDOW;
2974     startup.wShowWindow = SW_SHOWNORMAL;
2975 
2976     psa.nLength = sizeof(psa);
2977     psa.lpSecurityDescriptor = SecurityDescriptor;
2978     psa.bInheritHandle = TRUE;
2979 
2980     ThreadSecurityDescriptor = HeapAlloc( GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH );
2981     res = InitializeSecurityDescriptor( ThreadSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
2982     ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
2983 
2984     ThreadAcl = HeapAlloc( GetProcessHeap(), 0, 256 );
2985     res = InitializeAcl( ThreadAcl, 256, ACL_REVISION );
2986     ok(res, "InitializeAcl failed with error %d\n", GetLastError());
2987     res = AddAccessDeniedAce( ThreadAcl, ACL_REVISION, THREAD_SET_THREAD_TOKEN, AdminSid );
2988     ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError() );
2989     res = AddAccessAllowedAce( ThreadAcl, ACL_REVISION, THREAD_ALL_ACCESS, AdminSid );
2990     ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
2991 
2992     res = SetSecurityDescriptorOwner( ThreadSecurityDescriptor, AdminSid, FALSE );
2993     ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
2994     res = SetSecurityDescriptorGroup( ThreadSecurityDescriptor, UsersSid, FALSE );
2995     ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
2996     res = SetSecurityDescriptorDacl( ThreadSecurityDescriptor, TRUE, ThreadAcl, FALSE );
2997     ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
2998 
2999     tsa.nLength = sizeof(tsa);
3000     tsa.lpSecurityDescriptor = ThreadSecurityDescriptor;
3001     tsa.bInheritHandle = TRUE;
3002 
3003     /* Doesn't matter what ACL say we should get full access for ourselves */
3004     res = CreateProcessA( NULL, buffer, &psa, &tsa, FALSE, 0, NULL, NULL, &startup, &info );
3005     ok(res, "CreateProcess with err:%d\n", GetLastError());
3006     TEST_GRANTED_ACCESS2( info.hProcess, PROCESS_ALL_ACCESS_NT4,
3007                           STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
3008     TEST_GRANTED_ACCESS2( info.hThread, THREAD_ALL_ACCESS_NT4,
3009                           STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
3010     winetest_wait_child_process( info.hProcess );
3011 
3012     FreeSid(EveryoneSid);
3013     CloseHandle( info.hProcess );
3014     CloseHandle( info.hThread );
3015     CloseHandle( event );
3016     HeapFree(GetProcessHeap(), 0, group);
3017     HeapFree(GetProcessHeap(), 0, owner);
3018     HeapFree(GetProcessHeap(), 0, user);
3019     HeapFree(GetProcessHeap(), 0, Acl);
3020     HeapFree(GetProcessHeap(), 0, SecurityDescriptor);
3021     HeapFree(GetProcessHeap(), 0, ThreadAcl);
3022     HeapFree(GetProcessHeap(), 0, ThreadSecurityDescriptor);
3023 }
3024 
3025 static void test_process_security_child(void)
3026 {
3027     HANDLE handle, handle1;
3028     BOOL ret;
3029     DWORD err;
3030 
3031     handle = OpenProcess( PROCESS_TERMINATE, FALSE, GetCurrentProcessId() );
3032     ok(handle != NULL, "OpenProcess(PROCESS_TERMINATE) with err:%d\n", GetLastError());
3033     TEST_GRANTED_ACCESS( handle, PROCESS_TERMINATE );
3034 
3035     ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
3036                            &handle1, 0, TRUE, DUPLICATE_SAME_ACCESS );
3037     ok(ret, "duplicating handle err:%d\n", GetLastError());
3038     TEST_GRANTED_ACCESS( handle1, PROCESS_TERMINATE );
3039 
3040     CloseHandle( handle1 );
3041 
3042     SetLastError( 0xdeadbeef );
3043     ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
3044                            &handle1, PROCESS_ALL_ACCESS, TRUE, 0 );
3045     err = GetLastError();
3046     ok(!ret && err == ERROR_ACCESS_DENIED, "duplicating handle should have failed "
3047        "with STATUS_ACCESS_DENIED, instead of err:%d\n", err);
3048 
3049     CloseHandle( handle );
3050 
3051     /* These two should fail - they are denied by ACL */
3052     handle = OpenProcess( PROCESS_VM_READ, FALSE, GetCurrentProcessId() );
3053     ok(handle == NULL, "OpenProcess(PROCESS_VM_READ) should have failed\n");
3054     handle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId() );
3055     ok(handle == NULL, "OpenProcess(PROCESS_ALL_ACCESS) should have failed\n");
3056 
3057     /* Documented privilege elevation */
3058     ret = DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
3059                            &handle, 0, TRUE, DUPLICATE_SAME_ACCESS );
3060     ok(ret, "duplicating handle err:%d\n", GetLastError());
3061     TEST_GRANTED_ACCESS2( handle, PROCESS_ALL_ACCESS_NT4,
3062                           STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
3063 
3064     CloseHandle( handle );
3065 
3066     /* Same only explicitly asking for all access rights */
3067     ret = DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
3068                            &handle, PROCESS_ALL_ACCESS, TRUE, 0 );
3069     ok(ret, "duplicating handle err:%d\n", GetLastError());
3070     TEST_GRANTED_ACCESS2( handle, PROCESS_ALL_ACCESS_NT4,
3071                           PROCESS_ALL_ACCESS | PROCESS_QUERY_LIMITED_INFORMATION );
3072     ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
3073                            &handle1, PROCESS_VM_READ, TRUE, 0 );
3074     ok(ret, "duplicating handle err:%d\n", GetLastError());
3075     TEST_GRANTED_ACCESS( handle1, PROCESS_VM_READ );
3076     CloseHandle( handle1 );
3077     CloseHandle( handle );
3078 
3079     /* Test thread security */
3080     handle = OpenThread( THREAD_TERMINATE, FALSE, GetCurrentThreadId() );
3081     ok(handle != NULL, "OpenThread(THREAD_TERMINATE) with err:%d\n", GetLastError());
3082     TEST_GRANTED_ACCESS( handle, PROCESS_TERMINATE );
3083     CloseHandle( handle );
3084 
3085     handle = OpenThread( THREAD_SET_THREAD_TOKEN, FALSE, GetCurrentThreadId() );
3086     ok(handle == NULL, "OpenThread(THREAD_SET_THREAD_TOKEN) should have failed\n");
3087 }
3088 
3089 static void test_impersonation_level(void)
3090 {
3091     HANDLE Token, ProcessToken;
3092     HANDLE Token2;
3093     DWORD Size;
3094     TOKEN_PRIVILEGES *Privileges;
3095     TOKEN_USER *User;
3096     PRIVILEGE_SET *PrivilegeSet;
3097     BOOL AccessGranted;
3098     BOOL ret;
3099     HKEY hkey;
3100     DWORD error;
3101 
3102     if( !pDuplicateTokenEx ) {
3103         win_skip("DuplicateTokenEx is not available\n");
3104         return;
3105     }
3106     SetLastError(0xdeadbeef);
3107     ret = ImpersonateSelf(SecurityAnonymous);
3108     if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
3109     {
3110         win_skip("ImpersonateSelf is not implemented\n");
3111         return;
3112     }
3113     ok(ret, "ImpersonateSelf(SecurityAnonymous) failed with error %d\n", GetLastError());
3114     ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
3115     ok(!ret, "OpenThreadToken should have failed\n");
3116     error = GetLastError();
3117     ok(error == ERROR_CANT_OPEN_ANONYMOUS, "OpenThreadToken on anonymous token should have returned ERROR_CANT_OPEN_ANONYMOUS instead of %d\n", error);
3118     /* can't perform access check when opening object against an anonymous impersonation token */
3119     todo_wine {
3120     error = RegOpenKeyExA(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
3121     ok(error == ERROR_INVALID_HANDLE || error == ERROR_CANT_OPEN_ANONYMOUS || error == ERROR_BAD_IMPERSONATION_LEVEL,
3122        "RegOpenKeyEx failed with %d\n", error);
3123     }
3124     RevertToSelf();
3125 
3126     ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
3127     ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
3128 
3129     ret = pDuplicateTokenEx(ProcessToken,
3130         TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE, NULL,
3131         SecurityAnonymous, TokenImpersonation, &Token);
3132     ok(ret, "DuplicateTokenEx failed with error %d\n", GetLastError());
3133     /* can't increase the impersonation level */
3134     ret = DuplicateToken(Token, SecurityIdentification, &Token2);
3135     error = GetLastError();
3136     ok(!ret && error == ERROR_BAD_IMPERSONATION_LEVEL,
3137         "Duplicating a token and increasing the impersonation level should have failed with ERROR_BAD_IMPERSONATION_LEVEL instead of %d\n", error);
3138     /* we can query anything from an anonymous token, including the user */
3139     ret = GetTokenInformation(Token, TokenUser, NULL, 0, &Size);
3140     error = GetLastError();
3141     ok(!ret && error == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenUser) should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", error);
3142     User = HeapAlloc(GetProcessHeap(), 0, Size);
3143     ret = GetTokenInformation(Token, TokenUser, User, Size, &Size);
3144     ok(ret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
3145     HeapFree(GetProcessHeap(), 0, User);
3146 
3147     /* PrivilegeCheck fails with SecurityAnonymous level */
3148     ret = GetTokenInformation(Token, TokenPrivileges, NULL, 0, &Size);
3149     error = GetLastError();
3150     ok(!ret && error == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", error);
3151     Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
3152     ret = GetTokenInformation(Token, TokenPrivileges, Privileges, Size, &Size);
3153     ok(ret, "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError());
3154 
3155     PrivilegeSet = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(PRIVILEGE_SET, Privilege[Privileges->PrivilegeCount]));
3156     PrivilegeSet->PrivilegeCount = Privileges->PrivilegeCount;
3157     memcpy(PrivilegeSet->Privilege, Privileges->Privileges, PrivilegeSet->PrivilegeCount * sizeof(PrivilegeSet->Privilege[0]));
3158     PrivilegeSet->Control = PRIVILEGE_SET_ALL_NECESSARY;
3159     HeapFree(GetProcessHeap(), 0, Privileges);
3160 
3161     ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
3162     error = GetLastError();
3163     ok(!ret && error == ERROR_BAD_IMPERSONATION_LEVEL, "PrivilegeCheck for SecurityAnonymous token should have failed with ERROR_BAD_IMPERSONATION_LEVEL instead of %d\n", error);
3164 
3165     CloseHandle(Token);
3166 
3167     ret = ImpersonateSelf(SecurityIdentification);
3168     ok(ret, "ImpersonateSelf(SecurityIdentification) failed with error %d\n", GetLastError());
3169     ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
3170     ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
3171 
3172     /* can't perform access check when opening object against an identification impersonation token */
3173     error = RegOpenKeyExA(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
3174     todo_wine {
3175     ok(error == ERROR_INVALID_HANDLE || error == ERROR_BAD_IMPERSONATION_LEVEL,
3176        "RegOpenKeyEx should have failed with ERROR_INVALID_HANDLE or ERROR_BAD_IMPERSONATION_LEVEL instead of %d\n", error);
3177     }
3178     ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
3179     ok(ret, "PrivilegeCheck for SecurityIdentification failed with error %d\n", GetLastError());
3180     CloseHandle(Token);
3181     RevertToSelf();
3182 
3183     ret = ImpersonateSelf(SecurityImpersonation);
3184     ok(ret, "ImpersonateSelf(SecurityImpersonation) failed with error %d\n", GetLastError());
3185     ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
3186     ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
3187     error = RegOpenKeyExA(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
3188     ok(error == ERROR_SUCCESS, "RegOpenKeyEx should have succeeded instead of failing with %d\n", error);
3189     RegCloseKey(hkey);
3190     ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
3191     ok(ret, "PrivilegeCheck for SecurityImpersonation failed with error %d\n", GetLastError());
3192     RevertToSelf();
3193 
3194     CloseHandle(Token);
3195     CloseHandle(ProcessToken);
3196 
3197     HeapFree(GetProcessHeap(), 0, PrivilegeSet);
3198 }
3199 
3200 static void test_SetEntriesInAclW(void)
3201 {
3202     DWORD res;
3203     PSID EveryoneSid = NULL, UsersSid = NULL;
3204     PACL OldAcl = NULL, NewAcl;
3205     SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
3206     SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
3207     EXPLICIT_ACCESSW ExplicitAccess;
3208     static const WCHAR wszEveryone[] = {'E','v','e','r','y','o','n','e',0};
3209     static const WCHAR wszCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'};
3210 
3211     if (!pSetEntriesInAclW)
3212     {
3213         win_skip("SetEntriesInAclW is not available\n");
3214         return;
3215     }
3216 
3217     NewAcl = (PACL)0xdeadbeef;
3218     res = pSetEntriesInAclW(0, NULL, NULL, &NewAcl);
3219     if(res == ERROR_CALL_NOT_IMPLEMENTED)
3220     {
3221         win_skip("SetEntriesInAclW is not implemented\n");
3222         return;
3223     }
3224     ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
3225     ok(NewAcl == NULL ||
3226         broken(NewAcl != NULL), /* NT4 */
3227         "NewAcl=%p, expected NULL\n", NewAcl);
3228     LocalFree(NewAcl);
3229 
3230     OldAcl = HeapAlloc(GetProcessHeap(), 0, 256);
3231     res = InitializeAcl(OldAcl, 256, ACL_REVISION);
3232     if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
3233     {
3234         win_skip("ACLs not implemented - skipping tests\n");
3235         HeapFree(GetProcessHeap(), 0, OldAcl);
3236         return;
3237     }
3238     ok(res, "InitializeAcl failed with error %d\n", GetLastError());
3239 
3240     res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
3241     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
3242 
3243     res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
3244         DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid);
3245     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
3246 
3247     res = AddAccessAllowedAce(OldAcl, ACL_REVISION, KEY_READ, UsersSid);
3248     ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
3249 
3250     ExplicitAccess.grfAccessPermissions = KEY_WRITE;
3251     ExplicitAccess.grfAccessMode = GRANT_ACCESS;
3252     ExplicitAccess.grfInheritance = NO_INHERITANCE;
3253     ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
3254     ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
3255     ExplicitAccess.Trustee.ptstrName = EveryoneSid;
3256     ExplicitAccess.Trustee.MultipleTrusteeOperation = 0xDEADBEEF;
3257     ExplicitAccess.Trustee.pMultipleTrustee = (PVOID)0xDEADBEEF;
3258     res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3259     ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
3260     ok(NewAcl != NULL, "returned acl was NULL\n");
3261     LocalFree(NewAcl);
3262 
3263     ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3264     ExplicitAccess.Trustee.pMultipleTrustee = NULL;
3265     ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3266     res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3267     ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
3268     ok(NewAcl != NULL, "returned acl was NULL\n");
3269     LocalFree(NewAcl);
3270 
3271     if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH)
3272     {
3273         skip("Non-English locale (test with hardcoded 'Everyone')\n");
3274     }
3275     else
3276     {
3277         ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3278         ExplicitAccess.Trustee.ptstrName = (LPWSTR)wszEveryone;
3279         res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3280         ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
3281         ok(NewAcl != NULL, "returned acl was NULL\n");
3282         LocalFree(NewAcl);
3283 
3284         ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_BAD_FORM;
3285         res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3286         ok(res == ERROR_INVALID_PARAMETER ||
3287             broken(res == ERROR_NOT_SUPPORTED), /* NT4 */
3288             "SetEntriesInAclW failed: %u\n", res);
3289         ok(NewAcl == NULL ||
3290             broken(NewAcl != NULL), /* NT4 */
3291             "returned acl wasn't NULL: %p\n", NewAcl);
3292 
3293         ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3294         ExplicitAccess.Trustee.MultipleTrusteeOperation = TRUSTEE_IS_IMPERSONATE;
3295         res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3296         ok(res == ERROR_INVALID_PARAMETER ||
3297             broken(res == ERROR_NOT_SUPPORTED), /* NT4 */
3298             "SetEntriesInAclW failed: %u\n", res);
3299         ok(NewAcl == NULL ||
3300             broken(NewAcl != NULL), /* NT4 */
3301             "returned acl wasn't NULL: %p\n", NewAcl);
3302 
3303         ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3304         ExplicitAccess.grfAccessMode = SET_ACCESS;
3305         res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3306         ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
3307         ok(NewAcl != NULL, "returned acl was NULL\n");
3308         LocalFree(NewAcl);
3309     }
3310 
3311     ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3312     ExplicitAccess.Trustee.ptstrName = (LPWSTR)wszCurrentUser;
3313     res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3314     ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
3315     ok(NewAcl != NULL, "returned acl was NULL\n");
3316     LocalFree(NewAcl);
3317 
3318     ExplicitAccess.grfAccessMode = REVOKE_ACCESS;
3319     ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
3320     ExplicitAccess.Trustee.ptstrName = UsersSid;
3321     res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3322     ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
3323     ok(NewAcl != NULL, "returned acl was NULL\n");
3324     LocalFree(NewAcl);
3325 
3326     FreeSid(UsersSid);
3327     FreeSid(EveryoneSid);
3328     HeapFree(GetProcessHeap(), 0, OldAcl);
3329 }
3330 
3331 static void test_SetEntriesInAclA(void)
3332 {
3333     DWORD res;
3334     PSID EveryoneSid = NULL, UsersSid = NULL;
3335     PACL OldAcl = NULL, NewAcl;
3336     SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
3337     SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
3338     EXPLICIT_ACCESSA ExplicitAccess;
3339     static const CHAR szEveryone[] = {'E','v','e','r','y','o','n','e',0};
3340     static const CHAR szCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'};
3341 
3342     if (!pSetEntriesInAclA)
3343     {
3344         win_skip("SetEntriesInAclA is not available\n");
3345         return;
3346     }
3347 
3348     NewAcl = (PACL)0xdeadbeef;
3349     res = pSetEntriesInAclA(0, NULL, NULL, &NewAcl);
3350     if(res == ERROR_CALL_NOT_IMPLEMENTED)
3351     {
3352         win_skip("SetEntriesInAclA is not implemented\n");
3353         return;
3354     }
3355     ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res);
3356     ok(NewAcl == NULL ||
3357         broken(NewAcl != NULL), /* NT4 */
3358         "NewAcl=%p, expected NULL\n", NewAcl);
3359     LocalFree(NewAcl);
3360 
3361     OldAcl = HeapAlloc(GetProcessHeap(), 0, 256);
3362     res = InitializeAcl(OldAcl, 256, ACL_REVISION);
3363     if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
3364     {
3365         win_skip("ACLs not implemented - skipping tests\n");
3366         HeapFree(GetProcessHeap(), 0, OldAcl);
3367         return;
3368     }
3369     ok(res, "InitializeAcl failed with error %d\n", GetLastError());
3370 
3371     res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
3372     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
3373 
3374     res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
3375         DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid);
3376     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
3377 
3378     res = AddAccessAllowedAce(OldAcl, ACL_REVISION, KEY_READ, UsersSid);
3379     ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
3380 
3381     ExplicitAccess.grfAccessPermissions = KEY_WRITE;
3382     ExplicitAccess.grfAccessMode = GRANT_ACCESS;
3383     ExplicitAccess.grfInheritance = NO_INHERITANCE;
3384     ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
3385     ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
3386     ExplicitAccess.Trustee.ptstrName = EveryoneSid;
3387     ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3388     ExplicitAccess.Trustee.pMultipleTrustee = NULL;
3389     res = pSetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3390     ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res);
3391     ok(NewAcl != NULL, "returned acl was NULL\n");
3392     LocalFree(NewAcl);
3393 
3394     ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3395     ExplicitAccess.Trustee.pMultipleTrustee = NULL;
3396     ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3397     res = pSetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3398     ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res);
3399     ok(NewAcl != NULL, "returned acl was NULL\n");
3400     LocalFree(NewAcl);
3401 
3402     if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH)
3403     {
3404         skip("Non-English locale (test with hardcoded 'Everyone')\n");
3405     }
3406     else
3407     {
3408         ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3409         ExplicitAccess.Trustee.ptstrName = (LPSTR)szEveryone;
3410         res = pSetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3411         ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res);
3412         ok(NewAcl != NULL, "returned acl was NULL\n");
3413         LocalFree(NewAcl);
3414 
3415         ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_BAD_FORM;
3416         res = pSetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3417         ok(res == ERROR_INVALID_PARAMETER ||
3418             broken(res == ERROR_NOT_SUPPORTED), /* NT4 */
3419             "SetEntriesInAclA failed: %u\n", res);
3420         ok(NewAcl == NULL ||
3421             broken(NewAcl != NULL), /* NT4 */
3422             "returned acl wasn't NULL: %p\n", NewAcl);
3423 
3424         ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3425         ExplicitAccess.Trustee.MultipleTrusteeOperation = TRUSTEE_IS_IMPERSONATE;
3426         res = pSetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3427         ok(res == ERROR_INVALID_PARAMETER ||
3428             broken(res == ERROR_NOT_SUPPORTED), /* NT4 */
3429             "SetEntriesInAclA failed: %u\n", res);
3430         ok(NewAcl == NULL ||
3431             broken(NewAcl != NULL), /* NT4 */
3432             "returned acl wasn't NULL: %p\n", NewAcl);
3433 
3434         ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3435         ExplicitAccess.grfAccessMode = SET_ACCESS;
3436         res = pSetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3437         ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res);
3438         ok(NewAcl != NULL, "returned acl was NULL\n");
3439         LocalFree(NewAcl);
3440     }
3441 
3442     ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3443     ExplicitAccess.Trustee.ptstrName = (LPSTR)szCurrentUser;
3444     res = pSetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3445     ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res);
3446     ok(NewAcl != NULL, "returned acl was NULL\n");
3447     LocalFree(NewAcl);
3448 
3449     ExplicitAccess.grfAccessMode = REVOKE_ACCESS;
3450     ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
3451     ExplicitAccess.Trustee.ptstrName = UsersSid;
3452     res = pSetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3453     ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res);
3454     ok(NewAcl != NULL, "returned acl was NULL\n");
3455     LocalFree(NewAcl);
3456 
3457     FreeSid(UsersSid);
3458     FreeSid(EveryoneSid);
3459     HeapFree(GetProcessHeap(), 0, OldAcl);
3460 }
3461 
3462 /* helper function for test_CreateDirectoryA */
3463 static void get_nt_pathW(const char *name, UNICODE_STRING *nameW)
3464 {
3465     UNICODE_STRING strW;
3466     ANSI_STRING str;
3467     NTSTATUS status;
3468     BOOLEAN ret;
3469 
3470     pRtlInitAnsiString(&str, name);
3471 
3472     status = pRtlAnsiStringToUnicodeString(&strW, &str, TRUE);
3473     ok(!status, "RtlAnsiStringToUnicodeString failed with %08x\n", status);
3474 
3475     ret = pRtlDosPathNameToNtPathName_U(strW.Buffer, nameW, NULL, NULL);
3476     ok(ret, "RtlDosPathNameToNtPathName_U failed\n");
3477 
3478     pRtlFreeUnicodeString(&strW);
3479 }
3480 
3481 static void test_inherited_dacl(PACL dacl, PSID admin_sid, PSID user_sid, DWORD flags, DWORD mask,
3482                                 BOOL todo_count, BOOL todo_sid, BOOL todo_flags, int line)
3483 {
3484     ACL_SIZE_INFORMATION acl_size;
3485     ACCESS_ALLOWED_ACE *ace;
3486     BOOL bret;
3487 
3488     bret = pGetAclInformation(dacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3489     ok_(__FILE__, line)(bret, "GetAclInformation failed\n");
3490 
3491     todo_wine_if (todo_count)
3492         ok_(__FILE__, line)(acl_size.AceCount == 2,
3493             "GetAclInformation returned unexpected entry count (%d != 2)\n",
3494             acl_size.AceCount);
3495 
3496     if (acl_size.AceCount > 0)
3497     {
3498         bret = pGetAce(dacl, 0, (VOID **)&ace);
3499         ok_(__FILE__, line)(bret, "Failed to get Current User ACE\n");
3500 
3501         bret = EqualSid(&ace->SidStart, user_sid);
3502         todo_wine_if (todo_sid)
3503             ok_(__FILE__, line)(bret, "Current User ACE (%s) != Current User SID (%s)\n", debugstr_sid(&ace->SidStart), debugstr_sid(user_sid));
3504 
3505         todo_wine_if (todo_flags)
3506             ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags,
3507                 "Current User ACE has unexpected flags (0x%x != 0x%x)\n",
3508                 ((ACE_HEADER *)ace)->AceFlags, flags);
3509 
3510         ok_(__FILE__, line)(ace->Mask == mask,
3511             "Current User ACE has unexpected mask (0x%x != 0x%x)\n",
3512             ace->Mask, mask);
3513     }
3514     if (acl_size.AceCount > 1)
3515     {
3516         bret = pGetAce(dacl, 1, (VOID **)&ace);
3517         ok_(__FILE__, line)(bret, "Failed to get Administators Group ACE\n");
3518 
3519         bret = EqualSid(&ace->SidStart, admin_sid);
3520         todo_wine_if (todo_sid)
3521             ok_(__FILE__, line)(bret, "Administators Group ACE (%s) != Administators Group SID (%s)\n", debugstr_sid(&ace->SidStart), debugstr_sid(admin_sid));
3522 
3523         todo_wine_if (todo_flags)
3524             ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags,
3525                 "Administators Group ACE has unexpected flags (0x%x != 0x%x)\n",
3526                 ((ACE_HEADER *)ace)->AceFlags, flags);
3527 
3528         ok_(__FILE__, line)(ace->Mask == mask,
3529             "Administators Group ACE has unexpected mask (0x%x != 0x%x)\n",
3530             ace->Mask, mask);
3531     }
3532 }
3533 
3534 static void test_CreateDirectoryA(void)
3535 {
3536     char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], *user;
3537     DWORD sid_size = sizeof(admin_ptr), user_size;
3538     PSID admin_sid = (PSID) admin_ptr, user_sid;
3539     char sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
3540     PSECURITY_DESCRIPTOR pSD = &sd;
3541     ACL_SIZE_INFORMATION acl_size;
3542     UNICODE_STRING tmpfileW;
3543     SECURITY_ATTRIBUTES sa;
3544     OBJECT_ATTRIBUTES attr;
3545     char tmpfile[MAX_PATH];
3546     char tmpdir[MAX_PATH];
3547     HANDLE token, hTemp;
3548     IO_STATUS_BLOCK io;
3549     struct _SID *owner;
3550     BOOL bret = TRUE;
3551     NTSTATUS status;
3552     DWORD error;
3553     PACL pDacl;
3554 
3555     if (!pGetSecurityInfo || !pGetNamedSecurityInfoA || !pCreateWellKnownSid)
3556     {
3557         win_skip("Required functions are not available\n");
3558         return;
3559     }
3560 
3561     if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
3562     {
3563         if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE;
3564         else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE;
3565     }
3566     if (!bret)
3567     {
3568         win_skip("Failed to get current user token\n");
3569         return;
3570     }
3571     bret = GetTokenInformation(token, TokenUser, NULL, 0, &user_size);
3572     ok(!bret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
3573         "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
3574     user = HeapAlloc(GetProcessHeap(), 0, user_size);
3575     bret = GetTokenInformation(token, TokenUser, user, user_size, &user_size);
3576     ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
3577     CloseHandle( token );
3578     user_sid = ((TOKEN_USER *)user)->User.Sid;
3579 
3580     sa.nLength = sizeof(sa);
3581     sa.lpSecurityDescriptor = pSD;
3582     sa.bInheritHandle = TRUE;
3583     InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
3584     pCreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size);
3585     pDacl = HeapAlloc(GetProcessHeap(), 0, 100);
3586     bret = InitializeAcl(pDacl, 100, ACL_REVISION);
3587     ok(bret, "Failed to initialize ACL.\n");
3588     bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
3589                                   GENERIC_ALL, user_sid);
3590     ok(bret, "Failed to add Current User to ACL.\n");
3591     bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
3592                                   GENERIC_ALL, admin_sid);
3593     ok(bret, "Failed to add Administrator Group to ACL.\n");
3594     bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
3595     ok(bret, "Failed to add ACL to security descriptor.\n");
3596 
3597     GetTempPathA(MAX_PATH, tmpdir);
3598     lstrcatA(tmpdir, "Please Remove Me");
3599     bret = CreateDirectoryA(tmpdir, &sa);
3600     ok(bret == TRUE, "CreateDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
3601     HeapFree(GetProcessHeap(), 0, pDacl);
3602 
3603     SetLastError(0xdeadbeef);
3604     error = pGetNamedSecurityInfoA(tmpdir, SE_FILE_OBJECT,
3605                                    OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, (PSID*)&owner,
3606                                    NULL, &pDacl, NULL, &pSD);
3607     if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
3608     {
3609         win_skip("GetNamedSecurityInfoA is not implemented\n");
3610         goto done;
3611     }
3612     ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
3613     test_inherited_dacl(pDacl, admin_sid, user_sid, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
3614                         0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
3615     LocalFree(pSD);
3616 
3617     /* Test inheritance of ACLs in CreateFile without security descriptor */
3618     strcpy(tmpfile, tmpdir);
3619     lstrcatA(tmpfile, "/tmpfile");
3620 
3621     hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
3622                         CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, NULL);
3623     ok(hTemp != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError());
3624 
3625     error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
3626                                    OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3627                                    (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3628     ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
3629     test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
3630                         0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
3631     LocalFree(pSD);
3632     CloseHandle(hTemp);
3633 
3634     /* Test inheritance of ACLs in CreateFile with security descriptor -
3635      * When a security descriptor is set, then inheritance doesn't take effect */
3636     pSD = &sd;
3637     InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
3638     pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
3639     bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
3640     ok(bret, "Failed to initialize ACL\n");
3641     bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
3642     ok(bret, "Failed to add ACL to security descriptor\n");
3643 
3644     strcpy(tmpfile, tmpdir);
3645     lstrcatA(tmpfile, "/tmpfile");
3646 
3647     sa.nLength = sizeof(sa);
3648     sa.lpSecurityDescriptor = pSD;
3649     sa.bInheritHandle = TRUE;
3650     hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, &sa,
3651                         CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, NULL);
3652     ok(hTemp != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError());
3653     HeapFree(GetProcessHeap(), 0, pDacl);
3654 
3655     error = pGetSecurityInfo(hTemp, SE_FILE_OBJECT,
3656                              OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3657                              (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3658     ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
3659     bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3660     ok(bret, "GetAclInformation failed\n");
3661     ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
3662                                acl_size.AceCount);
3663     LocalFree(pSD);
3664 
3665     error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
3666                                    OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3667                                    (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3668     ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
3669     bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3670     ok(bret, "GetAclInformation failed\n");
3671     ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
3672                                acl_size.AceCount);
3673     LocalFree(pSD);
3674     CloseHandle(hTemp);
3675 
3676     /* Test inheritance of ACLs in NtCreateFile without security descriptor */
3677     strcpy(tmpfile, tmpdir);
3678     lstrcatA(tmpfile, "/tmpfile");
3679     get_nt_pathW(tmpfile, &tmpfileW);
3680 
3681     attr.Length = sizeof(attr);
3682     attr.RootDirectory = 0;
3683     attr.ObjectName = &tmpfileW;
3684     attr.Attributes = OBJ_CASE_INSENSITIVE;
3685     attr.SecurityDescriptor = NULL;
3686     attr.SecurityQualityOfService = NULL;
3687 
3688     status = pNtCreateFile(&hTemp, GENERIC_WRITE | DELETE, &attr, &io, NULL, 0,
3689                            FILE_SHARE_READ, FILE_CREATE, FILE_DELETE_ON_CLOSE, NULL, 0);
3690     ok(!status, "NtCreateFile failed with %08x\n", status);
3691     pRtlFreeUnicodeString(&tmpfileW);
3692 
3693     error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
3694                                    OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3695                                    (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3696     ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
3697     test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
3698                         0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
3699     LocalFree(pSD);
3700     CloseHandle(hTemp);
3701 
3702     /* Test inheritance of ACLs in NtCreateFile with security descriptor -
3703      * When a security descriptor is set, then inheritance doesn't take effect */
3704     pSD = &sd;
3705     InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
3706     pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
3707     bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
3708     ok(bret, "Failed to initialize ACL\n");
3709     bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
3710     ok(bret, "Failed to add ACL to security descriptor\n");
3711 
3712     strcpy(tmpfile, tmpdir);
3713     lstrcatA(tmpfile, "/tmpfile");
3714     get_nt_pathW(tmpfile, &tmpfileW);
3715 
3716     attr.Length = sizeof(attr);
3717     attr.RootDirectory = 0;
3718     attr.ObjectName = &tmpfileW;
3719     attr.Attributes = OBJ_CASE_INSENSITIVE;
3720     attr.SecurityDescriptor = pSD;
3721     attr.SecurityQualityOfService = NULL;
3722 
3723     status = pNtCreateFile(&hTemp, GENERIC_WRITE | DELETE, &attr, &io, NULL, 0,
3724                            FILE_SHARE_READ, FILE_CREATE, FILE_DELETE_ON_CLOSE, NULL, 0);
3725     ok(!status, "NtCreateFile failed with %08x\n", status);
3726     pRtlFreeUnicodeString(&tmpfileW);
3727     HeapFree(GetProcessHeap(), 0, pDacl);
3728 
3729     error = pGetSecurityInfo(hTemp, SE_FILE_OBJECT,
3730                              OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3731                              (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3732     ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
3733     bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3734     ok(bret, "GetAclInformation failed\n");
3735     todo_wine
3736     ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
3737                                acl_size.AceCount);
3738     LocalFree(pSD);
3739 
3740     error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
3741                                    OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3742                                    (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3743     ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
3744     bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3745     ok(bret, "GetAclInformation failed\n");
3746     ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
3747                                acl_size.AceCount);
3748     LocalFree(pSD);
3749     CloseHandle(hTemp);
3750 
3751     /* Test inheritance of ACLs in CreateDirectory without security descriptor */
3752     strcpy(tmpfile, tmpdir);
3753     lstrcatA(tmpfile, "/tmpdir");
3754     bret = CreateDirectoryA(tmpfile, NULL);
3755     ok(bret == TRUE, "CreateDirectoryA failed with error %u\n", GetLastError());
3756 
3757     error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
3758                                    OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3759                                    (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3760     ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
3761     test_inherited_dacl(pDacl, admin_sid, user_sid,
3762                         OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERITED_ACE,
3763                         0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
3764     LocalFree(pSD);
3765     bret = RemoveDirectoryA(tmpfile);
3766     ok(bret == TRUE, "RemoveDirectoryA failed with error %u\n", GetLastError());
3767 
3768     /* Test inheritance of ACLs in CreateDirectory with security descriptor */
3769     pSD = &sd;
3770     InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
3771     pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
3772     bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
3773     ok(bret, "Failed to initialize ACL\n");
3774     bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
3775     ok(bret, "Failed to add ACL to security desciptor\n");
3776 
3777     strcpy(tmpfile, tmpdir);
3778     lstrcatA(tmpfile, "/tmpdir1");
3779 
3780     sa.nLength = sizeof(sa);
3781     sa.lpSecurityDescriptor = pSD;
3782     sa.bInheritHandle = TRUE;
3783     bret = CreateDirectoryA(tmpfile, &sa);
3784     ok(bret == TRUE, "CreateDirectoryA failed with error %u\n", GetLastError());
3785     HeapFree(GetProcessHeap(), 0, pDacl);
3786 
3787     error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
3788                                    OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3789                                    (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3790     ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
3791     bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3792     ok(bret, "GetAclInformation failed\n");
3793     todo_wine
3794     ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
3795                                acl_size.AceCount);
3796     LocalFree(pSD);
3797 
3798     SetLastError(0xdeadbeef);
3799     bret = RemoveDirectoryA(tmpfile);
3800     error = GetLastError();
3801     ok(bret == FALSE, "RemoveDirectoryA unexpected succeeded\n");
3802     ok(error == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %u\n", error);
3803 
3804     pSD = &sd;
3805     InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
3806     pDacl = HeapAlloc(GetProcessHeap(), 0, 100);
3807     bret = InitializeAcl(pDacl, 100, ACL_REVISION);
3808     ok(bret, "Failed to initialize ACL.\n");
3809     bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
3810     ok(bret, "Failed to add Current User to ACL.\n");
3811     bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
3812     ok(bret, "Failed to add ACL to security desciptor.\n");
3813     error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL,
3814                                    NULL, pDacl, NULL);
3815     ok(error == ERROR_SUCCESS, "SetNamedSecurityInfoA failed with error %u\n", error);
3816     HeapFree(GetProcessHeap(), 0, pDacl);
3817 
3818     bret = RemoveDirectoryA(tmpfile);
3819     ok(bret == TRUE, "RemoveDirectoryA failed with error %u\n", GetLastError());
3820 
3821     /* Test inheritance of ACLs in NtCreateFile(..., FILE_DIRECTORY_FILE, ...) without security descriptor */
3822     strcpy(tmpfile, tmpdir);
3823     lstrcatA(tmpfile, "/tmpdir");
3824     get_nt_pathW(tmpfile, &tmpfileW);
3825 
3826     attr.Length = sizeof(attr);
3827     attr.RootDirectory = 0;
3828     attr.ObjectName = &tmpfileW;
3829     attr.Attributes = OBJ_CASE_INSENSITIVE;
3830     attr.SecurityDescriptor = NULL;
3831     attr.SecurityQualityOfService = NULL;
3832 
3833     status = pNtCreateFile(&hTemp, GENERIC_READ | DELETE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL,
3834                            FILE_SHARE_READ, FILE_CREATE, FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE, NULL, 0);
3835     ok(!status, "NtCreateFile failed with %08x\n", status);
3836     RtlFreeUnicodeString(&tmpfileW);
3837 
3838     error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
3839                                    OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3840                                    (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3841     ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
3842     test_inherited_dacl(pDacl, admin_sid, user_sid,
3843                         OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERITED_ACE,
3844                         0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
3845     LocalFree(pSD);
3846     CloseHandle(hTemp);
3847 
3848     /* Test inheritance of ACLs in NtCreateFile(..., FILE_DIRECTORY_FILE, ...) with security descriptor */
3849     pSD = &sd;
3850     InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
3851     pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
3852     bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
3853     ok(bret, "Failed to initialize ACL\n");
3854     bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
3855     ok(bret, "Failed to add ACL to security desciptor\n");
3856 
3857     strcpy(tmpfile, tmpdir);
3858     lstrcatA(tmpfile, "/tmpdir2");
3859     get_nt_pathW(tmpfile, &tmpfileW);
3860 
3861     attr.Length = sizeof(attr);
3862     attr.RootDirectory = 0;
3863     attr.ObjectName = &tmpfileW;
3864     attr.Attributes = OBJ_CASE_INSENSITIVE;
3865     attr.SecurityDescriptor = pSD;
3866     attr.SecurityQualityOfService = NULL;
3867 
3868     status = pNtCreateFile(&hTemp, GENERIC_READ | DELETE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL,
3869                            FILE_SHARE_READ, FILE_CREATE, FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE, NULL, 0);
3870     ok(!status, "NtCreateFile failed with %08x\n", status);
3871     RtlFreeUnicodeString(&tmpfileW);
3872     HeapFree(GetProcessHeap(), 0, pDacl);
3873 
3874     error = pGetSecurityInfo(hTemp, SE_FILE_OBJECT,
3875                              OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3876                              (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3877     ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
3878     bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3879     ok(bret, "GetAclInformation failed\n");
3880     todo_wine
3881     ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
3882                                acl_size.AceCount);
3883     LocalFree(pSD);
3884 
3885     error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
3886                                    OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3887                                    (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3888     ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
3889     bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3890     ok(bret, "GetAclInformation failed\n");
3891     todo_wine
3892     ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
3893                                acl_size.AceCount);
3894     LocalFree(pSD);
3895     CloseHandle(hTemp);
3896 
3897 done:
3898     HeapFree(GetProcessHeap(), 0, user);
3899     bret = RemoveDirectoryA(tmpdir);
3900     ok(bret == TRUE, "RemoveDirectoryA should always succeed\n");
3901 }
3902 
3903 static void test_GetNamedSecurityInfoA(void)
3904 {
3905     char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], *user;
3906     char system_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES];
3907     char users_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES];
3908     SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
3909     PSID admin_sid = (PSID) admin_ptr, users_sid = (PSID) users_ptr;
3910     PSID system_sid = (PSID) system_ptr, user_sid, localsys_sid;
3911     DWORD sid_size = sizeof(admin_ptr), user_size;
3912     char invalid_path[] = "/an invalid file path";
3913     int users_ace_id = -1, admins_ace_id = -1, i;
3914     char software_key[] = "MACHINE\\Software";
3915     char sd[SECURITY_DESCRIPTOR_MIN_LENGTH+sizeof(void*)];
3916     SECURITY_DESCRIPTOR_CONTROL control;
3917     ACL_SIZE_INFORMATION acl_size;
3918     CHAR windows_dir[MAX_PATH];
3919     PSECURITY_DESCRIPTOR pSD;
3920     ACCESS_ALLOWED_ACE *ace;
3921     BOOL bret = TRUE, isNT4;
3922     char tmpfile[MAX_PATH];
3923     DWORD error, revision;
3924     BOOL owner_defaulted;
3925     BOOL group_defaulted;
3926     BOOL dacl_defaulted;
3927     HANDLE token, hTemp, h;
3928     PSID owner, group;
3929     BOOL dacl_present;
3930     PACL pDacl;
3931     BYTE flags;
3932     NTSTATUS status;
3933 
3934     if (!pSetNamedSecurityInfoA || !pGetNamedSecurityInfoA || !pCreateWellKnownSid)
3935     {
3936         win_skip("Required functions are not available\n");
3937         return;
3938     }
3939 
3940     if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
3941     {
3942         if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE;
3943         else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE;
3944     }
3945     if (!bret)
3946     {
3947         win_skip("Failed to get current user token\n");
3948         return;
3949     }
3950     bret = GetTokenInformation(token, TokenUser, NULL, 0, &user_size);
3951     ok(!bret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
3952         "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
3953     user = HeapAlloc(GetProcessHeap(), 0, user_size);
3954     bret = GetTokenInformation(token, TokenUser, user, user_size, &user_size);
3955     ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
3956     CloseHandle( token );
3957     user_sid = ((TOKEN_USER *)user)->User.Sid;
3958 
3959     bret = GetWindowsDirectoryA(windows_dir, MAX_PATH);
3960     ok(bret, "GetWindowsDirectory failed with error %d\n", GetLastError());
3961 
3962     SetLastError(0xdeadbeef);
3963     error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,
3964         OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
3965         NULL, NULL, NULL, NULL, &pSD);
3966     if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
3967     {
3968         win_skip("GetNamedSecurityInfoA is not implemented\n");
3969         HeapFree(GetProcessHeap(), 0, user);
3970         return;
3971     }
3972     ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
3973 
3974     bret = GetSecurityDescriptorControl(pSD, &control, &revision);
3975     ok(bret, "GetSecurityDescriptorControl failed with error %d\n", GetLastError());
3976     ok((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == (SE_SELF_RELATIVE|SE_DACL_PRESENT) ||
3977         broken((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT), /* NT4 */
3978         "control (0x%x) doesn't have (SE_SELF_RELATIVE|SE_DACL_PRESENT) flags set\n", control);
3979     ok(revision == SECURITY_DESCRIPTOR_REVISION1, "revision was %d instead of 1\n", revision);
3980 
3981     isNT4 = (control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT;
3982 
3983     bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted);
3984     ok(bret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
3985     ok(owner != NULL, "owner should not be NULL\n");
3986 
3987     bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted);
3988     ok(bret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
3989     ok(group != NULL, "group should not be NULL\n");
3990     LocalFree(pSD);
3991 
3992 
3993     /* NULL descriptor tests */
3994     if(isNT4)
3995     {
3996         win_skip("NT4 does not support GetNamedSecutityInfo with a NULL descriptor\n");
3997         HeapFree(GetProcessHeap(), 0, user);
3998         return;
3999     }
4000 
4001     error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,
4002         NULL, NULL, NULL, NULL, NULL);
4003     ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error);
4004 
4005     pDacl = NULL;
4006     error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,
4007         NULL, NULL, &pDacl, NULL, &pSD);
4008     ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
4009     ok(pDacl != NULL, "DACL should not be NULL\n");
4010     LocalFree(pSD);
4011 
4012     error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,OWNER_SECURITY_INFORMATION,
4013         NULL, NULL, &pDacl, NULL, NULL);
4014     ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error);
4015 
4016     /* Test behavior of SetNamedSecurityInfo with an invalid path */
4017     SetLastError(0xdeadbeef);
4018     error = pSetNamedSecurityInfoA(invalid_path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL,
4019                                    NULL, NULL, NULL);
4020     ok(error == ERROR_FILE_NOT_FOUND, "Unexpected error returned: 0x%x\n", error);
4021     ok(GetLastError() == 0xdeadbeef, "Expected last error to remain unchanged.\n");
4022 
4023     /* Create security descriptor information and test that it comes back the same */
4024     pSD = &sd;
4025     pDacl = HeapAlloc(GetProcessHeap(), 0, 100);
4026     InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
4027     pCreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size);
4028     bret = InitializeAcl(pDacl, 100, ACL_REVISION);
4029     ok(bret, "Failed to initialize ACL.\n");
4030     bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
4031     ok(bret, "Failed to add Current User to ACL.\n");
4032     bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, admin_sid);
4033     ok(bret, "Failed to add Administrator Group to ACL.\n");
4034     bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
4035     ok(bret, "Failed to add ACL to security descriptor.\n");
4036     GetTempFileNameA(".", "foo", 0, tmpfile);
4037     hTemp = CreateFileA(tmpfile, WRITE_DAC|GENERIC_WRITE, FILE_SHARE_DELETE|FILE_SHARE_READ,
4038                         NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
4039     SetLastError(0xdeadbeef);
4040     error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL,
4041                                    NULL, pDacl, NULL);
4042     HeapFree(GetProcessHeap(), 0, pDacl);
4043     if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
4044     {
4045         win_skip("SetNamedSecurityInfoA is not implemented\n");
4046         HeapFree(GetProcessHeap(), 0, user);
4047         CloseHandle(hTemp);
4048         return;
4049     }
4050     ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error);
4051     SetLastError(0xdeadbeef);
4052     error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
4053                                    NULL, NULL, &pDacl, NULL, &pSD);
4054     if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
4055     {
4056         win_skip("GetNamedSecurityInfoA is not implemented\n");
4057         HeapFree(GetProcessHeap(), 0, user);
4058         CloseHandle(hTemp);
4059         return;
4060     }
4061     ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
4062 
4063     bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
4064     ok(bret, "GetAclInformation failed\n");
4065     if (acl_size.AceCount > 0)
4066     {
4067         bret = pGetAce(pDacl, 0, (VOID **)&ace);
4068         ok(bret, "Failed to get Current User ACE.\n");
4069         bret = EqualSid(&ace->SidStart, user_sid);
4070         ok(bret, "Current User ACE (%s) != Current User SID (%s).\n",
4071            debugstr_sid(&ace->SidStart), debugstr_sid(user_sid));
4072         ok(((ACE_HEADER *)ace)->AceFlags == 0,
4073            "Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
4074         ok(ace->Mask == 0x1f01ff,
4075            "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
4076     }
4077     if (acl_size.AceCount > 1)
4078     {
4079         bret = pGetAce(pDacl, 1, (VOID **)&ace);
4080         ok(bret, "Failed to get Administators Group ACE.\n");
4081         bret = EqualSid(&ace->SidStart, admin_sid);
4082         ok(bret || broken(!bret) /* win2k */, "Administators Group ACE (%s) != Administators Group SID (%s).\n",
4083            debugstr_sid(&ace->SidStart), debugstr_sid(admin_sid));
4084         ok(((ACE_HEADER *)ace)->AceFlags == 0,
4085            "Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
4086         ok(ace->Mask == 0x1f01ff || broken(ace->Mask == GENERIC_ALL) /* win2k */,
4087            "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
4088     }
4089     LocalFree(pSD);
4090 
4091     /* show that setting empty DACL is not removing all file permissions */
4092     pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
4093     bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
4094     ok(bret, "Failed to initialize ACL.\n");
4095     error =  pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
4096             NULL, NULL, pDacl, NULL);
4097     ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error);
4098     HeapFree(GetProcessHeap(), 0, pDacl);
4099 
4100     error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
4101             NULL, NULL, &pDacl, NULL, &pSD);
4102     ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
4103 
4104     bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
4105     ok(bret, "GetAclInformation failed\n");
4106     if (acl_size.AceCount > 0)
4107     {
4108         bret = pGetAce(pDacl, 0, (VOID **)&ace);
4109         ok(bret, "Failed to get ACE.\n");
4110         ok(((ACE_HEADER *)ace)->AceFlags & INHERITED_ACE,
4111            "ACE has unexpected flags: 0x%x\n", ((ACE_HEADER *)ace)->AceFlags);
4112     }
4113     LocalFree(pSD);
4114 
4115     h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4116             NULL, OPEN_EXISTING, 0, NULL);
4117     ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
4118     CloseHandle(h);
4119 
4120     /* test setting NULL DACL */
4121     error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
4122             DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL);
4123     ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error);
4124 
4125     error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
4126                 NULL, NULL, &pDacl, NULL, &pSD);
4127     ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
4128     todo_wine ok(!pDacl, "pDacl != NULL\n");
4129     LocalFree(pSD);
4130 
4131     h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4132             NULL, OPEN_EXISTING, 0, NULL);
4133     ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
4134     CloseHandle(h);
4135 
4136     /* NtSetSecurityObject doesn't inherit DACL entries */
4137     pSD = sd+sizeof(void*)-((ULONG_PTR)sd)%sizeof(void*);
4138     InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
4139     pDacl = HeapAlloc(GetProcessHeap(), 0, 100);
4140     bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
4141     ok(bret, "Failed to initialize ACL.\n");
4142     bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
4143     ok(bret, "Failed to add ACL to security descriptor.\n");
4144     status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
4145     ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
4146 
4147     h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4148             NULL, OPEN_EXISTING, 0, NULL);
4149     ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
4150     CloseHandle(h);
4151 
4152     pSetSecurityDescriptorControl(pSD, SE_DACL_AUTO_INHERIT_REQ, SE_DACL_AUTO_INHERIT_REQ);
4153     status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
4154     ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
4155 
4156     h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4157             NULL, OPEN_EXISTING, 0, NULL);
4158     ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
4159     CloseHandle(h);
4160 
4161     pSetSecurityDescriptorControl(pSD, SE_DACL_AUTO_INHERIT_REQ|SE_DACL_AUTO_INHERITED,
4162             SE_DACL_AUTO_INHERIT_REQ|SE_DACL_AUTO_INHERITED);
4163     status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
4164     ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
4165 
4166     h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4167             NULL, OPEN_EXISTING, 0, NULL);
4168     ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
4169     CloseHandle(h);
4170 
4171     /* test if DACL is properly mapped to permission */
4172     bret = InitializeAcl(pDacl, 100, ACL_REVISION);
4173     ok(bret, "Failed to initialize ACL.\n");
4174     bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
4175     ok(bret, "Failed to add Current User to ACL.\n");
4176     bret = pAddAccessDeniedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
4177     ok(bret, "Failed to add Current User to ACL.\n");
4178     bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
4179     ok(bret, "Failed to add ACL to security descriptor.\n");
4180     status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
4181     ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
4182 
4183     h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4184             NULL, OPEN_EXISTING, 0, NULL);
4185     ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
4186     CloseHandle(h);
4187 
4188     bret = InitializeAcl(pDacl, 100, ACL_REVISION);
4189     ok(bret, "Failed to initialize ACL.\n");
4190     bret = pAddAccessDeniedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
4191     ok(bret, "Failed to add Current User to ACL.\n");
4192     bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
4193     ok(bret, "Failed to add Current User to ACL.\n");
4194     bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
4195     ok(bret, "Failed to add ACL to security descriptor.\n");
4196     status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
4197     ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
4198 
4199     h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4200             NULL, OPEN_EXISTING, 0, NULL);
4201     ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
4202     HeapFree(GetProcessHeap(), 0, pDacl);
4203     HeapFree(GetProcessHeap(), 0, user);
4204     CloseHandle(hTemp);
4205 
4206     /* Test querying the ownership of a built-in registry key */
4207     sid_size = sizeof(system_ptr);
4208     pCreateWellKnownSid(WinLocalSystemSid, NULL, system_sid, &sid_size);
4209     error = pGetNamedSecurityInfoA(software_key, SE_REGISTRY_KEY,
4210                                    OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION,
4211                                    NULL, NULL, NULL, NULL, &pSD);
4212     ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
4213 
4214     bret = AllocateAndInitializeSid(&SIDAuthNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &localsys_sid);
4215     ok(bret, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
4216 
4217     bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted);
4218     ok(bret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
4219     ok(owner != NULL, "owner should not be NULL\n");
4220     ok(EqualSid(owner, admin_sid) || EqualSid(owner, localsys_sid),
4221                 "MACHINE\\Software owner SID (%s) != Administrators SID (%s) or Local System Sid (%s).\n",
4222                 debugstr_sid(owner), debugstr_sid(admin_sid), debugstr_sid(localsys_sid));
4223 
4224     bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted);
4225     ok(bret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
4226     ok(group != NULL, "group should not be NULL\n");
4227     ok(EqualSid(group, admin_sid) || broken(EqualSid(group, system_sid)) /* before Win7 */
4228        || broken(((SID*)group)->SubAuthority[0] == SECURITY_NT_NON_UNIQUE) /* Vista */,
4229        "MACHINE\\Software group SID (%s) != Local System SID (%s or %s)\n",
4230        debugstr_sid(group), debugstr_sid(admin_sid), debugstr_sid(system_sid));
4231     LocalFree(pSD);
4232 
4233     /* Test querying the DACL of a built-in registry key */
4234     sid_size = sizeof(users_ptr);
4235     pCreateWellKnownSid(WinBuiltinUsersSid, NULL, users_sid, &sid_size);
4236     error = pGetNamedSecurityInfoA(software_key, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION,
4237                                    NULL, NULL, NULL, NULL, &pSD);
4238     ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
4239 
4240     bret = GetSecurityDescriptorDacl(pSD, &dacl_present, &pDacl, &dacl_defaulted);
4241     ok(bret, "GetSecurityDescriptorDacl failed with error %d\n", GetLastError());
4242     ok(dacl_present, "DACL should be present\n");
4243     ok(pDacl && IsValidAcl(pDacl), "GetSecurityDescriptorDacl returned invalid DACL.\n");
4244     bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
4245     ok(bret, "GetAclInformation failed\n");
4246     ok(acl_size.AceCount != 0, "GetAclInformation returned no ACLs\n");
4247     for (i=0; i<acl_size.AceCount; i++)
4248     {
4249         bret = pGetAce(pDacl, i, (VOID **)&ace);
4250         ok(bret, "Failed to get ACE %d.\n", i);
4251         bret = EqualSid(&ace->SidStart, users_sid);
4252         if (bret) users_ace_id = i;
4253         bret = EqualSid(&ace->SidStart, admin_sid);
4254         if (bret) admins_ace_id = i;
4255     }
4256     ok(users_ace_id != -1 || broken(users_ace_id == -1) /* win2k */,
4257        "Builtin Users ACE not found.\n");
4258     if (users_ace_id != -1)
4259     {
4260         bret = pGetAce(pDacl, users_ace_id, (VOID **)&ace);
4261         ok(bret, "Failed to get Builtin Users ACE.\n");
4262         flags = ((ACE_HEADER *)ace)->AceFlags;
4263         ok(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE)
4264            || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* w2k8 */
4265            || broken(flags == (CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* win 10 wow64 */
4266            || broken(flags == CONTAINER_INHERIT_ACE), /* win 10 */
4267            "Builtin Users ACE has unexpected flags (0x%x != 0x%x)\n", flags,
4268            INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE);
4269         ok(ace->Mask == GENERIC_READ
4270            || broken(ace->Mask == KEY_READ), /* win 10 */
4271            "Builtin Users ACE has unexpected mask (0x%x != 0x%x)\n",
4272                                       ace->Mask, GENERIC_READ);
4273     }
4274     ok(admins_ace_id != -1, "Builtin Admins ACE not found.\n");
4275     if (admins_ace_id != -1)
4276     {
4277         bret = pGetAce(pDacl, admins_ace_id, (VOID **)&ace);
4278         ok(bret, "Failed to get Builtin Admins ACE.\n");
4279         flags = ((ACE_HEADER *)ace)->AceFlags;
4280         ok(flags == 0x0
4281            || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* w2k8 */
4282            || broken(flags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)) /* win7 */
4283            || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE)) /* win8+ */
4284            || broken(flags == (CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* win 10 wow64 */
4285            || broken(flags == CONTAINER_INHERIT_ACE), /* win 10 */
4286            "Builtin Admins ACE has unexpected flags (0x%x != 0x0)\n", flags);
4287         ok(ace->Mask == KEY_ALL_ACCESS || broken(ace->Mask == GENERIC_ALL) /* w2k8 */,
4288            "Builtin Admins ACE has unexpected mask (0x%x != 0x%x)\n", ace->Mask, KEY_ALL_ACCESS);
4289     }
4290 
4291     FreeSid(localsys_sid);
4292     LocalFree(pSD);
4293 }
4294 
4295 static void test_ConvertStringSecurityDescriptor(void)
4296 {
4297     BOOL ret;
4298     PSECURITY_DESCRIPTOR pSD;
4299     static const WCHAR Blank[] = { 0 };
4300     unsigned int i;
4301     static const struct
4302     {
4303         const char *sidstring;
4304         DWORD      revision;
4305         BOOL       ret;
4306         DWORD      GLE;
4307         DWORD      altGLE;
4308     } cssd[] =
4309     {
4310         { "D:(A;;GA;;;WD)",                  0xdeadbeef,      FALSE, ERROR_UNKNOWN_REVISION },
4311         /* test ACE string type */
4312         { "D:(A;;GA;;;WD)",                  SDDL_REVISION_1, TRUE },
4313         { "D:(D;;GA;;;WD)",                  SDDL_REVISION_1, TRUE },
4314         { "ERROR:(D;;GA;;;WD)",              SDDL_REVISION_1, FALSE, ERROR_INVALID_PARAMETER },
4315         /* test ACE string with spaces */
4316         { " D:(D;;GA;;;WD)",                SDDL_REVISION_1, TRUE },
4317         { "D: (D;;GA;;;WD)",                SDDL_REVISION_1, TRUE },
4318         { "D:( D;;GA;;;WD)",                SDDL_REVISION_1, TRUE },
4319         { "D:(D ;;GA;;;WD)",                SDDL_REVISION_1, FALSE, RPC_S_INVALID_STRING_UUID, ERROR_INVALID_ACL }, /* Vista+ */
4320         { "D:(D; ;GA;;;WD)",                SDDL_REVISION_1, TRUE },
4321         { "D:(D;; GA;;;WD)",                SDDL_REVISION_1, TRUE },
4322         { "D:(D;;GA ;;;WD)",                SDDL_REVISION_1, FALSE, ERROR_INVALID_ACL },
4323         { "D:(D;;GA; ;;WD)",                SDDL_REVISION_1, TRUE },
4324         { "D:(D;;GA;; ;WD)",                SDDL_REVISION_1, TRUE },
4325         { "D:(D;;GA;;; WD)",                SDDL_REVISION_1, TRUE },
4326         { "D:(D;;GA;;;WD )",                SDDL_REVISION_1, TRUE },
4327         /* test ACE string access rights */
4328         { "D:(A;;GA;;;WD)",                  SDDL_REVISION_1, TRUE },
4329         { "D:(A;;GRGWGX;;;WD)",              SDDL_REVISION_1, TRUE },
4330         { "D:(A;;RCSDWDWO;;;WD)",            SDDL_REVISION_1, TRUE },
4331         { "D:(A;;RPWPCCDCLCSWLODTCR;;;WD)",  SDDL_REVISION_1, TRUE },
4332         { "D:(A;;FAFRFWFX;;;WD)",            SDDL_REVISION_1, TRUE },
4333         { "D:(A;;KAKRKWKX;;;WD)",            SDDL_REVISION_1, TRUE },
4334         { "D:(A;;0xFFFFFFFF;;;WD)",          SDDL_REVISION_1, TRUE },
4335         { "S:(AU;;0xFFFFFFFF;;;WD)",         SDDL_REVISION_1, TRUE },
4336         /* test ACE string access right error case */
4337         { "D:(A;;ROB;;;WD)",                 SDDL_REVISION_1, FALSE, ERROR_INVALID_ACL },
4338         /* test behaviour with empty strings */
4339         { "",                                SDDL_REVISION_1, TRUE },
4340         /* test ACE string SID */
4341         { "D:(D;;GA;;;S-1-0-0)",             SDDL_REVISION_1, TRUE },
4342         { "D:(D;;GA;;;Nonexistent account)", SDDL_REVISION_1, FALSE, ERROR_INVALID_ACL, ERROR_INVALID_SID } /* W2K */
4343     };
4344 
4345     if (!pConvertStringSecurityDescriptorToSecurityDescriptorA)
4346     {
4347         win_skip("ConvertStringSecurityDescriptorToSecurityDescriptor is not available\n");
4348         return;
4349     }
4350 
4351     for (i = 0; i < sizeof(cssd)/sizeof(cssd[0]); i++)
4352     {
4353         DWORD GLE;
4354 
4355         SetLastError(0xdeadbeef);
4356         ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
4357             cssd[i].sidstring, cssd[i].revision, &pSD, NULL);
4358         GLE = GetLastError();
4359         ok(ret == cssd[i].ret, "(%02u) Expected %s (%d)\n", i, cssd[i].ret ? "success" : "failure", GLE);
4360         if (!cssd[i].ret)
4361             ok(GLE == cssd[i].GLE ||
4362                (cssd[i].altGLE && GLE == cssd[i].altGLE),
4363                "(%02u) Unexpected last error %d\n", i, GLE);
4364         if (ret)
4365             LocalFree(pSD);
4366     }
4367 
4368     /* test behaviour with NULL parameters */
4369     SetLastError(0xdeadbeef);
4370     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
4371         NULL, 0xdeadbeef, &pSD, NULL);
4372     todo_wine
4373     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4374         "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
4375         GetLastError());
4376 
4377     SetLastError(0xdeadbeef);
4378     ret = pConvertStringSecurityDescriptorToSecurityDescriptorW(
4379         NULL, 0xdeadbeef, &pSD, NULL);
4380     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4381         "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
4382         GetLastError());
4383 
4384     SetLastError(0xdeadbeef);
4385     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
4386         "D:(A;;ROB;;;WD)", 0xdeadbeef, NULL, NULL);
4387     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4388         "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
4389         GetLastError());
4390 
4391     SetLastError(0xdeadbeef);
4392     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
4393         "D:(A;;ROB;;;WD)", SDDL_REVISION_1, NULL, NULL);
4394     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4395         "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
4396         GetLastError());
4397 
4398     /* test behaviour with empty strings */
4399     SetLastError(0xdeadbeef);
4400     ret = pConvertStringSecurityDescriptorToSecurityDescriptorW(
4401         Blank, SDDL_REVISION_1, &pSD, NULL);
4402     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
4403     LocalFree(pSD);
4404 
4405     SetLastError(0xdeadbeef);
4406     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
4407         "D:P(A;;GRGW;;;BA)(A;;GRGW;;;S-1-5-21-0-0-0-1000)S:(ML;;NWNR;;;S-1-16-12288)", SDDL_REVISION_1, &pSD, NULL);
4408     ok(ret || broken(!ret && GetLastError() == ERROR_INVALID_DATATYPE) /* win2k */,
4409        "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %u\n", GetLastError());
4410     if (ret) LocalFree(pSD);
4411 }
4412 
4413 static void test_ConvertSecurityDescriptorToString(void)
4414 {
4415     SECURITY_DESCRIPTOR desc;
4416     SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION;
4417     LPSTR string;
4418     DWORD size;
4419     PSID psid, psid2;
4420     PACL pacl;
4421     char sid_buf[256];
4422     char acl_buf[8192];
4423     ULONG len;
4424 
4425     if (!pConvertSecurityDescriptorToStringSecurityDescriptorA)
4426     {
4427         win_skip("ConvertSecurityDescriptorToStringSecurityDescriptor is not available\n");
4428         return;
4429     }
4430     if (!pCreateWellKnownSid)
4431     {
4432         win_skip("CreateWellKnownSid is not available\n");
4433         return;
4434     }
4435 
4436 /* It seems Windows XP adds an extra character to the length of the string for each ACE in an ACL. We
4437  * don't replicate this feature so we only test len >= strlen+1. */
4438 #define CHECK_RESULT_AND_FREE(exp_str) \
4439     ok(strcmp(string, (exp_str)) == 0, "String mismatch (expected \"%s\", got \"%s\")\n", (exp_str), string); \
4440     ok(len >= (strlen(exp_str) + 1), "Length mismatch (expected %d, got %d)\n", lstrlenA(exp_str) + 1, len); \
4441     LocalFree(string);
4442 
4443 #define CHECK_ONE_OF_AND_FREE(exp_str1, exp_str2) \
4444     ok(strcmp(string, (exp_str1)) == 0 || strcmp(string, (exp_str2)) == 0, "String mismatch (expected\n\"%s\" or\n\"%s\", got\n\"%s\")\n", (exp_str1), (exp_str2), string); \
4445     ok(len >= (strlen(exp_str1) + 1) || len >= (strlen(exp_str2) + 1), "Length mismatch (expected %d or %d, got %d)\n", lstrlenA(exp_str1) + 1, lstrlenA(exp_str2) + 1, len); \
4446     LocalFree(string);
4447 
4448     InitializeSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION);
4449     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4450     CHECK_RESULT_AND_FREE("");
4451 
4452     size = 4096;
4453     pCreateWellKnownSid(WinLocalSid, NULL, sid_buf, &size);
4454     SetSecurityDescriptorOwner(&desc, sid_buf, FALSE);
4455     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4456     CHECK_RESULT_AND_FREE("O:S-1-2-0");
4457 
4458     SetSecurityDescriptorOwner(&desc, sid_buf, TRUE);
4459     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4460     CHECK_RESULT_AND_FREE("O:S-1-2-0");
4461 
4462     size = sizeof(sid_buf);
4463     pCreateWellKnownSid(WinLocalSystemSid, NULL, sid_buf, &size);
4464     SetSecurityDescriptorOwner(&desc, sid_buf, TRUE);
4465     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4466     CHECK_RESULT_AND_FREE("O:SY");
4467 
4468     pConvertStringSidToSidA("S-1-5-21-93476-23408-4576", &psid);
4469     SetSecurityDescriptorGroup(&desc, psid, TRUE);
4470     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4471     CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576");
4472 
4473     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, GROUP_SECURITY_INFORMATION, &string, &len), "Conversion failed\n");
4474     CHECK_RESULT_AND_FREE("G:S-1-5-21-93476-23408-4576");
4475 
4476     pacl = (PACL)acl_buf;
4477     InitializeAcl(pacl, sizeof(acl_buf), ACL_REVISION);
4478     SetSecurityDescriptorDacl(&desc, TRUE, pacl, TRUE);
4479     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4480     CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:");
4481 
4482     SetSecurityDescriptorDacl(&desc, TRUE, pacl, FALSE);
4483     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4484     CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:");
4485 
4486     pConvertStringSidToSidA("S-1-5-6", &psid2);
4487     pAddAccessAllowedAceEx(pacl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, 0xf0000000, psid2);
4488     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4489     CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)");
4490 
4491     pAddAccessAllowedAceEx(pacl, ACL_REVISION, INHERIT_ONLY_ACE|INHERITED_ACE, 0x00000003, psid2);
4492     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4493     CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)");
4494 
4495     pAddAccessDeniedAceEx(pacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE, 0xffffffff, psid);
4496     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4497     CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)");
4498 
4499 
4500     pacl = (PACL)acl_buf;
4501     InitializeAcl(pacl, sizeof(acl_buf), ACL_REVISION);
4502     SetSecurityDescriptorSacl(&desc, TRUE, pacl, FALSE);
4503     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4504     CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:");
4505 
4506     /* fails in win2k */
4507     SetSecurityDescriptorDacl(&desc, TRUE, NULL, FALSE);
4508     pAddAuditAccessAceEx(pacl, ACL_REVISION, VALID_INHERIT_FLAGS, KEY_READ|KEY_WRITE, psid2, TRUE, TRUE);
4509     if (pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len))
4510     {
4511         CHECK_ONE_OF_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)", /* XP */
4512             "O:SYG:S-1-5-21-93476-23408-4576D:NO_ACCESS_CONTROLS:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)" /* Vista */);
4513     }
4514 
4515     /* fails in win2k */
4516     pAddAuditAccessAceEx(pacl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, FILE_GENERIC_READ|FILE_GENERIC_WRITE, psid2, TRUE, FALSE);
4517     if (pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len))
4518     {
4519         CHECK_ONE_OF_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)", /* XP */
4520             "O:SYG:S-1-5-21-93476-23408-4576D:NO_ACCESS_CONTROLS:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)" /* Vista */);
4521     }
4522 
4523     LocalFree(psid2);
4524     LocalFree(psid);
4525 }
4526 
4527 static void test_SetSecurityDescriptorControl (PSECURITY_DESCRIPTOR sec)
4528 {
4529     SECURITY_DESCRIPTOR_CONTROL ref;
4530     SECURITY_DESCRIPTOR_CONTROL test;
4531 
4532     SECURITY_DESCRIPTOR_CONTROL const mutable
4533         = SE_DACL_AUTO_INHERIT_REQ | SE_SACL_AUTO_INHERIT_REQ
4534         | SE_DACL_AUTO_INHERITED   | SE_SACL_AUTO_INHERITED
4535         | SE_DACL_PROTECTED        | SE_SACL_PROTECTED
4536         | 0x00000040               | 0x00000080        /* not defined in winnt.h */
4537         ;
4538     SECURITY_DESCRIPTOR_CONTROL const immutable
4539         = SE_OWNER_DEFAULTED       | SE_GROUP_DEFAULTED
4540         | SE_DACL_PRESENT          | SE_DACL_DEFAULTED
4541         | SE_SACL_PRESENT          | SE_SACL_DEFAULTED
4542         | SE_RM_CONTROL_VALID      | SE_SELF_RELATIVE
4543         ;
4544 
4545     int     bit;
4546     DWORD   dwRevision;
4547     LPCSTR  fmt = "Expected error %s, got %u\n";
4548 
4549     GetSecurityDescriptorControl (sec, &ref, &dwRevision);
4550 
4551     /* The mutable bits are mutable regardless of the truth of
4552        SE_DACL_PRESENT and/or SE_SACL_PRESENT */
4553 
4554     /* Check call barfs if any bit-of-interest is immutable */
4555     for (bit = 0; bit < 16; ++bit)
4556     {
4557         SECURITY_DESCRIPTOR_CONTROL const bitOfInterest = 1 << bit;
4558         SECURITY_DESCRIPTOR_CONTROL setOrClear = ref & bitOfInterest;
4559 
4560         SECURITY_DESCRIPTOR_CONTROL ctrl;
4561 
4562         DWORD   dwExpect  = (bitOfInterest & immutable)
4563                           ?  ERROR_INVALID_PARAMETER  :  0xbebecaca;
4564         LPCSTR  strExpect = (bitOfInterest & immutable)
4565                           ? "ERROR_INVALID_PARAMETER" : "0xbebecaca";
4566 
4567         ctrl = (bitOfInterest & mutable) ? ref + bitOfInterest : ref;
4568         setOrClear ^= bitOfInterest;
4569         SetLastError (0xbebecaca);
4570         pSetSecurityDescriptorControl (sec, bitOfInterest, setOrClear);
4571         ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ());
4572         GetSecurityDescriptorControl(sec, &test, &dwRevision);
4573         expect_eq(test, ctrl, int, "%x");
4574 
4575         setOrClear ^= bitOfInterest;
4576         SetLastError (0xbebecaca);
4577         pSetSecurityDescriptorControl (sec, bitOfInterest, setOrClear);
4578         ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ());
4579         GetSecurityDescriptorControl (sec, &test, &dwRevision);
4580         expect_eq(test, ref, int, "%x");
4581     }
4582 
4583     /* Check call barfs if any bit-to-set is immutable
4584        even when not a bit-of-interest */
4585     for (bit = 0; bit < 16; ++bit)
4586     {
4587         SECURITY_DESCRIPTOR_CONTROL const bitsOfInterest = mutable;
4588         SECURITY_DESCRIPTOR_CONTROL setOrClear = ref & bitsOfInterest;
4589 
4590         SECURITY_DESCRIPTOR_CONTROL ctrl;
4591 
4592         DWORD   dwExpect  = ((1 << bit) & immutable)
4593                           ?  ERROR_INVALID_PARAMETER  :  0xbebecaca;
4594         LPCSTR  strExpect = ((1 << bit) & immutable)
4595                           ? "ERROR_INVALID_PARAMETER" : "0xbebecaca";
4596 
4597         ctrl = ((1 << bit) & immutable) ? test : ref | mutable;
4598         setOrClear ^= bitsOfInterest;
4599         SetLastError (0xbebecaca);
4600         pSetSecurityDescriptorControl (sec, bitsOfInterest, setOrClear | (1 << bit));
4601         ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ());
4602         GetSecurityDescriptorControl(sec, &test, &dwRevision);
4603         expect_eq(test, ctrl, int, "%x");
4604 
4605         ctrl = ((1 << bit) & immutable) ? test : ref | (1 << bit);
4606         setOrClear ^= bitsOfInterest;
4607         SetLastError (0xbebecaca);
4608         pSetSecurityDescriptorControl (sec, bitsOfInterest, setOrClear | (1 << bit));
4609         ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ());
4610         GetSecurityDescriptorControl(sec, &test, &dwRevision);
4611         expect_eq(test, ctrl, int, "%x");
4612     }
4613 }
4614 
4615 static void test_PrivateObjectSecurity(void)
4616 {
4617     SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION;
4618     SECURITY_DESCRIPTOR_CONTROL ctrl;
4619     PSECURITY_DESCRIPTOR sec;
4620     DWORD dwDescSize;
4621     DWORD dwRevision;
4622     DWORD retSize;
4623     LPSTR string;
4624     ULONG len;
4625     PSECURITY_DESCRIPTOR buf;
4626     BOOL ret;
4627 
4628     if (!pConvertStringSecurityDescriptorToSecurityDescriptorA)
4629     {
4630         win_skip("ConvertStringSecurityDescriptorToSecurityDescriptor is not available\n");
4631         return;
4632     }
4633 
4634     ok(pConvertStringSecurityDescriptorToSecurityDescriptorA(
4635         "O:SY"
4636         "G:S-1-5-21-93476-23408-4576"
4637         "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)"
4638           "(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
4639         "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)",
4640         SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n");
4641 
4642     test_SetSecurityDescriptorControl(sec);
4643 
4644     LocalFree(sec);
4645 
4646     ok(pConvertStringSecurityDescriptorToSecurityDescriptorA(
4647         "O:SY"
4648         "G:S-1-5-21-93476-23408-4576",
4649         SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n");
4650 
4651     test_SetSecurityDescriptorControl(sec);
4652 
4653     LocalFree(sec);
4654 
4655     ok(pConvertStringSecurityDescriptorToSecurityDescriptorA(
4656         "O:SY"
4657         "G:S-1-5-21-93476-23408-4576"
4658         "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
4659         "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)", SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n");
4660     buf = HeapAlloc(GetProcessHeap(), 0, dwDescSize);
4661     pSetSecurityDescriptorControl(sec, SE_DACL_PROTECTED, SE_DACL_PROTECTED);
4662     GetSecurityDescriptorControl(sec, &ctrl, &dwRevision);
4663     expect_eq(ctrl, 0x9014, int, "%x");
4664 
4665     ret = GetPrivateObjectSecurity(sec, GROUP_SECURITY_INFORMATION, buf, dwDescSize, &retSize);
4666     ok(ret, "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError());
4667     ok(retSize <= dwDescSize, "Buffer too small (%d vs %d)\n", retSize, dwDescSize);
4668     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4669     CHECK_RESULT_AND_FREE("G:S-1-5-21-93476-23408-4576");
4670     GetSecurityDescriptorControl(buf, &ctrl, &dwRevision);
4671     expect_eq(ctrl, 0x8000, int, "%x");
4672 
4673     ret = GetPrivateObjectSecurity(sec, GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, buf, dwDescSize, &retSize);
4674     ok(ret, "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError());
4675     ok(retSize <= dwDescSize, "Buffer too small (%d vs %d)\n", retSize, dwDescSize);
4676     ret = pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len);
4677     ok(ret, "Conversion failed err=%u\n", GetLastError());
4678     CHECK_ONE_OF_AND_FREE("G:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)",
4679         "G:S-1-5-21-93476-23408-4576D:P(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"); /* Win7 */
4680     GetSecurityDescriptorControl(buf, &ctrl, &dwRevision);
4681     expect_eq(ctrl & (~ SE_DACL_PROTECTED), 0x8004, int, "%x");
4682 
4683     ret = GetPrivateObjectSecurity(sec, sec_info, buf, dwDescSize, &retSize);
4684     ok(ret, "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError());
4685     ok(retSize == dwDescSize, "Buffer too small (%d vs %d)\n", retSize, dwDescSize);
4686     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4687     CHECK_ONE_OF_AND_FREE("O:SY"
4688         "G:S-1-5-21-93476-23408-4576"
4689         "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
4690         "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)",
4691       "O:SY"
4692         "G:S-1-5-21-93476-23408-4576"
4693         "D:P(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
4694         "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)"); /* Win7 */
4695     GetSecurityDescriptorControl(buf, &ctrl, &dwRevision);
4696     expect_eq(ctrl & (~ SE_DACL_PROTECTED), 0x8014, int, "%x");
4697 
4698     SetLastError(0xdeadbeef);
4699     ok(GetPrivateObjectSecurity(sec, sec_info, buf, 5, &retSize) == FALSE, "GetPrivateObjectSecurity should have failed\n");
4700     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected error ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
4701 
4702     LocalFree(sec);
4703     HeapFree(GetProcessHeap(), 0, buf);
4704 }
4705 #undef CHECK_RESULT_AND_FREE
4706 #undef CHECK_ONE_OF_AND_FREE
4707 
4708 static void test_acls(void)
4709 {
4710     char buffer[256];
4711     PACL pAcl = (PACL)buffer;
4712     BOOL ret;
4713 
4714     SetLastError(0xdeadbeef);
4715     ret = InitializeAcl(pAcl, sizeof(ACL) - 1, ACL_REVISION);
4716     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
4717     {
4718         win_skip("InitializeAcl is not implemented\n");
4719         return;
4720     }
4721 
4722     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InitializeAcl with too small a buffer should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", GetLastError());
4723 
4724     SetLastError(0xdeadbeef);
4725     ret = InitializeAcl(pAcl, 0xffffffff, ACL_REVISION);
4726     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl with too large a buffer should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
4727 
4728     SetLastError(0xdeadbeef);
4729     ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION1);
4730     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl(ACL_REVISION1) should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
4731 
4732     ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION2);
4733     ok(ret, "InitializeAcl(ACL_REVISION2) failed with error %d\n", GetLastError());
4734 
4735     ret = IsValidAcl(pAcl);
4736     ok(ret, "IsValidAcl failed with error %d\n", GetLastError());
4737 
4738     ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION3);
4739     ok(ret, "InitializeAcl(ACL_REVISION3) failed with error %d\n", GetLastError());
4740 
4741     ret = IsValidAcl(pAcl);
4742     ok(ret, "IsValidAcl failed with error %d\n", GetLastError());
4743 
4744     SetLastError(0xdeadbeef);
4745     ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION4);
4746     if (GetLastError() != ERROR_INVALID_PARAMETER)
4747     {
4748         ok(ret, "InitializeAcl(ACL_REVISION4) failed with error %d\n", GetLastError());
4749 
4750         ret = IsValidAcl(pAcl);
4751         ok(ret, "IsValidAcl failed with error %d\n", GetLastError());
4752     }
4753     else
4754         win_skip("ACL_REVISION4 is not implemented on NT4\n");
4755 
4756     SetLastError(0xdeadbeef);
4757     ret = InitializeAcl(pAcl, sizeof(buffer), -1);
4758     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl(-1) failed with error %d\n", GetLastError());
4759 }
4760 
4761 static void test_GetSecurityInfo(void)
4762 {
4763     char domain_users_ptr[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
4764     char b[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
4765     char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], dacl[100];
4766     PSID domain_users_sid = (PSID) domain_users_ptr, domain_sid;
4767     SID_IDENTIFIER_AUTHORITY sia = { SECURITY_NT_AUTHORITY };
4768     int domain_users_ace_id = -1, admins_ace_id = -1, i;
4769     DWORD sid_size = sizeof(admin_ptr), l = sizeof(b);
4770     PSID admin_sid = (PSID) admin_ptr, user_sid;
4771     char sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
4772     BOOL owner_defaulted, group_defaulted;
4773     BOOL dacl_defaulted, dacl_present;
4774     ACL_SIZE_INFORMATION acl_size;
4775     PSECURITY_DESCRIPTOR pSD;
4776     ACCESS_ALLOWED_ACE *ace;
4777     HANDLE token, obj;
4778     PSID owner, group;
4779     BOOL bret = TRUE;
4780     PACL pDacl;
4781     BYTE flags;
4782     DWORD ret;
4783 
4784     if (!pGetSecurityInfo || !pSetSecurityInfo)
4785     {
4786         win_skip("[Get|Set]SecurityInfo is not available\n");
4787         return;
4788     }
4789 
4790     if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
4791     {
4792         if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE;
4793         else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE;
4794     }
4795     if (!bret)
4796     {
4797         win_skip("Failed to get current user token\n");
4798         return;
4799     }
4800     bret = GetTokenInformation(token, TokenUser, b, l, &l);
4801     ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
4802     CloseHandle( token );
4803     user_sid = ((TOKEN_USER *)b)->User.Sid;
4804 
4805     /* Create something.  Files have lots of associated security info.  */
4806     obj = CreateFileA(myARGV[0], GENERIC_READ|WRITE_DAC, FILE_SHARE_READ, NULL,
4807                       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
4808     if (obj == INVALID_HANDLE_VALUE)
4809     {
4810         skip("Couldn't create an object for GetSecurityInfo test\n");
4811         return;
4812     }
4813 
4814     ret = pGetSecurityInfo(obj, SE_FILE_OBJECT,
4815                           OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
4816                           &owner, &group, &pDacl, NULL, &pSD);
4817     if (ret == ERROR_CALL_NOT_IMPLEMENTED)
4818     {
4819         win_skip("GetSecurityInfo is not implemented\n");
4820         CloseHandle(obj);
4821         return;
4822     }
4823     ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret);
4824     ok(pSD != NULL, "GetSecurityInfo\n");
4825     ok(owner != NULL, "GetSecurityInfo\n");
4826     ok(group != NULL, "GetSecurityInfo\n");
4827     if (pDacl != NULL)
4828         ok(IsValidAcl(pDacl), "GetSecurityInfo\n");
4829     else
4830         win_skip("No ACL information returned\n");
4831 
4832     LocalFree(pSD);
4833 
4834     if (!pCreateWellKnownSid)
4835     {
4836         win_skip("NULL parameter test would crash on NT4\n");
4837         CloseHandle(obj);
4838         return;
4839     }
4840 
4841     /* If we don't ask for the security descriptor, Windows will still give us
4842        the other stuff, leaving us no way to free it.  */
4843     ret = pGetSecurityInfo(obj, SE_FILE_OBJECT,
4844                           OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
4845                           &owner, &group, &pDacl, NULL, NULL);
4846     ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret);
4847     ok(owner != NULL, "GetSecurityInfo\n");
4848     ok(group != NULL, "GetSecurityInfo\n");
4849     if (pDacl != NULL)
4850         ok(IsValidAcl(pDacl), "GetSecurityInfo\n");
4851     else
4852         win_skip("No ACL information returned\n");
4853 
4854     /* Create security descriptor information and test that it comes back the same */
4855     pSD = &sd;
4856     pDacl = (PACL)&dacl;
4857     InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
4858     pCreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size);
4859     bret = InitializeAcl(pDacl, sizeof(dacl), ACL_REVISION);
4860     ok(bret, "Failed to initialize ACL.\n");
4861     bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
4862     ok(bret, "Failed to add Current User to ACL.\n");
4863     bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, admin_sid);
4864     ok(bret, "Failed to add Administrator Group to ACL.\n");
4865     bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
4866     ok(bret, "Failed to add ACL to security descriptor.\n");
4867     ret = pSetSecurityInfo(obj, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
4868                           NULL, NULL, pDacl, NULL);
4869     ok(ret == ERROR_SUCCESS, "SetSecurityInfo returned %d\n", ret);
4870     ret = pGetSecurityInfo(obj, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
4871                           NULL, NULL, &pDacl, NULL, &pSD);
4872     ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret);
4873     ok(pDacl && IsValidAcl(pDacl), "GetSecurityInfo returned invalid DACL.\n");
4874     bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
4875     ok(bret, "GetAclInformation failed\n");
4876     if (acl_size.AceCount > 0)
4877     {
4878         bret = pGetAce(pDacl, 0, (VOID **)&ace);
4879         ok(bret, "Failed to get Current User ACE.\n");
4880         bret = EqualSid(&ace->SidStart, user_sid);
4881         ok(bret, "Current User ACE (%s) != Current User SID (%s).\n", debugstr_sid(&ace->SidStart), debugstr_sid(user_sid));
4882         ok(((ACE_HEADER *)ace)->AceFlags == 0,
4883            "Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
4884         ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
4885                                   ace->Mask);
4886     }
4887     if (acl_size.AceCount > 1)
4888     {
4889         bret = pGetAce(pDacl, 1, (VOID **)&ace);
4890         ok(bret, "Failed to get Administators Group ACE.\n");
4891         bret = EqualSid(&ace->SidStart, admin_sid);
4892         ok(bret, "Administators Group ACE (%s) != Administators Group SID (%s).\n", debugstr_sid(&ace->SidStart), debugstr_sid(admin_sid));
4893         ok(((ACE_HEADER *)ace)->AceFlags == 0,
4894            "Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
4895         ok(ace->Mask == 0x1f01ff,
4896                      "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
4897     }
4898     LocalFree(pSD);
4899     CloseHandle(obj);
4900 
4901     /* Obtain the "domain users" SID from the user SID */
4902     if (!AllocateAndInitializeSid(&sia, 4, *GetSidSubAuthority(user_sid, 0),
4903                                   *GetSidSubAuthority(user_sid, 1),
4904                                   *GetSidSubAuthority(user_sid, 2),
4905                                   *GetSidSubAuthority(user_sid, 3), 0, 0, 0, 0, &domain_sid))
4906     {
4907         win_skip("Failed to get current domain SID\n");
4908         return;
4909     }
4910     sid_size = sizeof(domain_users_ptr);
4911     pCreateWellKnownSid(WinAccountDomainUsersSid, domain_sid, domain_users_sid, &sid_size);
4912     FreeSid(domain_sid);
4913 
4914     /* Test querying the ownership of a process */
4915     ret = pGetSecurityInfo(GetCurrentProcess(), SE_KERNEL_OBJECT,
4916                            OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION,
4917                            NULL, NULL, NULL, NULL, &pSD);
4918     ok(!ret, "GetNamedSecurityInfo failed with error %d\n", ret);
4919 
4920     bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted);
4921     ok(bret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
4922     ok(owner != NULL, "owner should not be NULL\n");
4923     ok(EqualSid(owner, admin_sid) || EqualSid(owner, user_sid),
4924        "Process owner SID != Administrators SID.\n");
4925 
4926     bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted);
4927     ok(bret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
4928     ok(group != NULL, "group should not be NULL\n");
4929     ok(EqualSid(group, domain_users_sid), "Process group SID != Domain Users SID.\n");
4930     LocalFree(pSD);
4931 
4932     /* Test querying the DACL of a process */
4933     ret = pGetSecurityInfo(GetCurrentProcess(), SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
4934                                    NULL, NULL, NULL, NULL, &pSD);
4935     ok(!ret, "GetSecurityInfo failed with error %d\n", ret);
4936 
4937     bret = GetSecurityDescriptorDacl(pSD, &dacl_present, &pDacl, &dacl_defaulted);
4938     ok(bret, "GetSecurityDescriptorDacl failed with error %d\n", GetLastError());
4939     ok(dacl_present, "DACL should be present\n");
4940     ok(pDacl && IsValidAcl(pDacl), "GetSecurityDescriptorDacl returned invalid DACL.\n");
4941     bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
4942     ok(bret, "GetAclInformation failed\n");
4943     ok(acl_size.AceCount != 0, "GetAclInformation returned no ACLs\n");
4944     for (i=0; i<acl_size.AceCount; i++)
4945     {
4946         bret = pGetAce(pDacl, i, (VOID **)&ace);
4947         ok(bret, "Failed to get ACE %d.\n", i);
4948         bret = EqualSid(&ace->SidStart, domain_users_sid);
4949         if (bret) domain_users_ace_id = i;
4950         bret = EqualSid(&ace->SidStart, admin_sid);
4951         if (bret) admins_ace_id = i;
4952     }
4953     ok(domain_users_ace_id != -1 || broken(domain_users_ace_id == -1) /* win2k */,
4954        "Domain Users ACE not found.\n");
4955     if (domain_users_ace_id != -1)
4956     {
4957         bret = pGetAce(pDacl, domain_users_ace_id, (VOID **)&ace);
4958         ok(bret, "Failed to get Domain Users ACE.\n");
4959         flags = ((ACE_HEADER *)ace)->AceFlags;
4960         ok(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE),
4961            "Domain Users ACE has unexpected flags (0x%x != 0x%x)\n", flags,
4962            INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE);
4963         ok(ace->Mask == GENERIC_READ, "Domain Users ACE has unexpected mask (0x%x != 0x%x)\n",
4964                                       ace->Mask, GENERIC_READ);
4965     }
4966     ok(admins_ace_id != -1 || broken(admins_ace_id == -1) /* xp */,
4967        "Builtin Admins ACE not found.\n");
4968     if (admins_ace_id != -1)
4969     {
4970         bret = pGetAce(pDacl, admins_ace_id, (VOID **)&ace);
4971         ok(bret, "Failed to get Builtin Admins ACE.\n");
4972         flags = ((ACE_HEADER *)ace)->AceFlags;
4973         ok(flags == 0x0, "Builtin Admins ACE has unexpected flags (0x%x != 0x0)\n", flags);
4974         ok(ace->Mask == PROCESS_ALL_ACCESS || broken(ace->Mask == 0x1f0fff) /* win2k */,
4975            "Builtin Admins ACE has unexpected mask (0x%x != 0x%x)\n", ace->Mask, PROCESS_ALL_ACCESS);
4976     }
4977     LocalFree(pSD);
4978 }
4979 
4980 static void test_GetSidSubAuthority(void)
4981 {
4982     PSID psid = NULL;
4983 
4984     if (!pGetSidSubAuthority || !pConvertStringSidToSidA || !pIsValidSid || !pGetSidSubAuthorityCount)
4985     {
4986         win_skip("Some functions not available\n");
4987         return;
4988     }
4989     /* Note: on windows passing in an invalid index like -1, lets GetSidSubAuthority return 0x05000000 but
4990              still GetLastError returns ERROR_SUCCESS then. We don't test these unlikely cornercases here for now */
4991     ok(pConvertStringSidToSidA("S-1-5-21-93476-23408-4576",&psid),"ConvertStringSidToSidA failed\n");
4992     ok(pIsValidSid(psid),"Sid is not valid\n");
4993     SetLastError(0xbebecaca);
4994     ok(*pGetSidSubAuthorityCount(psid) == 4,"GetSidSubAuthorityCount gave %d expected 4\n",*pGetSidSubAuthorityCount(psid));
4995     ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
4996     SetLastError(0xbebecaca);
4997     ok(*pGetSidSubAuthority(psid,0) == 21,"GetSidSubAuthority gave %d expected 21\n",*pGetSidSubAuthority(psid,0));
4998     ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
4999     SetLastError(0xbebecaca);
5000     ok(*pGetSidSubAuthority(psid,1) == 93476,"GetSidSubAuthority gave %d expected 93476\n",*pGetSidSubAuthority(psid,1));
5001     ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
5002     SetLastError(0xbebecaca);
5003     ok(pGetSidSubAuthority(psid,4) != NULL,"Expected out of bounds GetSidSubAuthority to return a non-NULL pointer\n");
5004     ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
5005     LocalFree(psid);
5006 }
5007 
5008 static void test_CheckTokenMembership(void)
5009 {
5010     PTOKEN_GROUPS token_groups;
5011     DWORD size;
5012     HANDLE process_token, token;
5013     BOOL is_member;
5014     BOOL ret;
5015     DWORD i;
5016 
5017     if (!pCheckTokenMembership)
5018     {
5019         win_skip("CheckTokenMembership is not available\n");
5020         return;
5021     }
5022     ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &process_token);
5023     ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
5024 
5025     ret = DuplicateToken(process_token, SecurityImpersonation, &token);
5026     ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
5027 
5028     /* groups */
5029     ret = GetTokenInformation(token, TokenGroups, NULL, 0, &size);
5030     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
5031         "GetTokenInformation(TokenGroups) %s with error %d\n",
5032         ret ? "succeeded" : "failed", GetLastError());
5033     token_groups = HeapAlloc(GetProcessHeap(), 0, size);
5034     ret = GetTokenInformation(token, TokenGroups, token_groups, size, &size);
5035     ok(ret, "GetTokenInformation(TokenGroups) failed with error %d\n", GetLastError());
5036 
5037     for (i = 0; i < token_groups->GroupCount; i++)
5038     {
5039         if (token_groups->Groups[i].Attributes & SE_GROUP_ENABLED)
5040             break;
5041     }
5042 
5043     if (i == token_groups->GroupCount)
5044     {
5045         HeapFree(GetProcessHeap(), 0, token_groups);
5046         CloseHandle(token);
5047         skip("user not a member of any group\n");
5048         return;
5049     }
5050 
5051     is_member = FALSE;
5052     ret = pCheckTokenMembership(token, token_groups->Groups[i].Sid, &is_member);
5053     ok(ret, "CheckTokenMembership failed with error %d\n", GetLastError());
5054     ok(is_member, "CheckTokenMembership should have detected sid as member\n");
5055 
5056     is_member = FALSE;
5057     ret = pCheckTokenMembership(NULL, token_groups->Groups[i].Sid, &is_member);
5058     ok(ret, "CheckTokenMembership failed with error %d\n", GetLastError());
5059     ok(is_member, "CheckTokenMembership should have detected sid as member\n");
5060 
5061     is_member = TRUE;
5062     SetLastError(0xdeadbeef);
5063     ret = pCheckTokenMembership(process_token, token_groups->Groups[i].Sid, &is_member);
5064     ok(!ret && GetLastError() == ERROR_NO_IMPERSONATION_TOKEN,
5065         "CheckTokenMembership with process token %s with error %d\n",
5066         ret ? "succeeded" : "failed", GetLastError());
5067     ok(!is_member, "CheckTokenMembership should have cleared is_member\n");
5068 
5069     HeapFree(GetProcessHeap(), 0, token_groups);
5070     CloseHandle(token);
5071     CloseHandle(process_token);
5072 }
5073 
5074 static void test_EqualSid(void)
5075 {
5076     PSID sid1, sid2;
5077     BOOL ret;
5078     SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
5079     SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
5080 
5081     SetLastError(0xdeadbeef);
5082     ret = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
5083         DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid1);
5084     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
5085     {
5086         win_skip("AllocateAndInitializeSid is not implemented\n");
5087         return;
5088     }
5089     ok(ret, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
5090     ok(GetLastError() == 0xdeadbeef,
5091        "AllocateAndInitializeSid shouldn't have set last error to %d\n",
5092        GetLastError());
5093 
5094     ret = AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID,
5095         0, 0, 0, 0, 0, 0, 0, &sid2);
5096     ok(ret, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
5097 
5098     SetLastError(0xdeadbeef);
5099     ret = EqualSid(sid1, sid2);
5100     ok(!ret, "World and domain admins sids shouldn't have been equal\n");
5101     ok(GetLastError() == ERROR_SUCCESS ||
5102        broken(GetLastError() == 0xdeadbeef), /* NT4 */
5103        "EqualSid should have set last error to ERROR_SUCCESS instead of %d\n",
5104        GetLastError());
5105 
5106     SetLastError(0xdeadbeef);
5107     sid2 = FreeSid(sid2);
5108     ok(!sid2, "FreeSid should have returned NULL instead of %p\n", sid2);
5109     ok(GetLastError() == 0xdeadbeef,
5110        "FreeSid shouldn't have set last error to %d\n",
5111        GetLastError());
5112 
5113     ret = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
5114         DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid2);
5115     ok(ret, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
5116 
5117     SetLastError(0xdeadbeef);
5118     ret = EqualSid(sid1, sid2);
5119     ok(ret, "Same sids should have been equal %s != %s\n",
5120        debugstr_sid(sid1), debugstr_sid(sid2));
5121     ok(GetLastError() == ERROR_SUCCESS ||
5122        broken(GetLastError() == 0xdeadbeef), /* NT4 */
5123        "EqualSid should have set last error to ERROR_SUCCESS instead of %d\n",
5124        GetLastError());
5125 
5126     ((SID *)sid2)->Revision = 2;
5127     SetLastError(0xdeadbeef);
5128     ret = EqualSid(sid1, sid2);
5129     ok(!ret, "EqualSid with invalid sid should have returned FALSE\n");
5130     ok(GetLastError() == ERROR_SUCCESS ||
5131        broken(GetLastError() == 0xdeadbeef), /* NT4 */
5132        "EqualSid should have set last error to ERROR_SUCCESS instead of %d\n",
5133        GetLastError());
5134     ((SID *)sid2)->Revision = SID_REVISION;
5135 
5136     FreeSid(sid1);
5137     FreeSid(sid2);
5138 }
5139 
5140 static void test_GetUserNameA(void)
5141 {
5142     char buffer[UNLEN + 1], filler[UNLEN + 1];
5143     DWORD required_len, buffer_len;
5144     BOOL ret;
5145 
5146     /* Test crashes on Windows. */
5147     if (0)
5148     {
5149         SetLastError(0xdeadbeef);
5150         GetUserNameA(NULL, NULL);
5151     }
5152 
5153     SetLastError(0xdeadbeef);
5154     required_len = 0;
5155     ret = GetUserNameA(NULL, &required_len);
5156     ok(ret == FALSE, "GetUserNameA returned %d\n", ret);
5157     ok(required_len != 0, "Outputted buffer length was %u\n", required_len);
5158     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
5159 
5160     SetLastError(0xdeadbeef);
5161     required_len = 1;
5162     ret = GetUserNameA(NULL, &required_len);
5163     ok(ret == FALSE, "GetUserNameA returned %d\n", ret);
5164     ok(required_len != 0 && required_len != 1, "Outputted buffer length was %u\n", required_len);
5165     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
5166 
5167     /* Tests crashes on Windows. */
5168     if (0)
5169     {
5170         SetLastError(0xdeadbeef);
5171         required_len = UNLEN + 1;
5172         GetUserNameA(NULL, &required_len);
5173 
5174         SetLastError(0xdeadbeef);
5175         GetUserNameA(buffer, NULL);
5176     }
5177 
5178     memset(filler, 'x', sizeof(filler));
5179 
5180     /* Note that GetUserNameA on XP and newer outputs the number of bytes
5181      * required for a Unicode string, which affects a test in the next block. */
5182     SetLastError(0xdeadbeef);
5183     memcpy(buffer, filler, sizeof(filler));
5184     required_len = 0;
5185     ret = GetUserNameA(buffer, &required_len);
5186     ok(ret == FALSE, "GetUserNameA returned %d\n", ret);
5187     ok(!memcmp(buffer, filler, sizeof(filler)), "Output buffer was altered\n");
5188     ok(required_len != 0, "Outputted buffer length was %u\n", required_len);
5189     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
5190 
5191     SetLastError(0xdeadbeef);
5192     memcpy(buffer, filler, sizeof(filler));
5193     buffer_len = required_len;
5194     ret = GetUserNameA(buffer, &buffer_len);
5195     ok(ret == TRUE, "GetUserNameA returned %d, last error %u\n", ret, GetLastError());
5196     ok(memcmp(buffer, filler, sizeof(filler)) != 0, "Output buffer was untouched\n");
5197     ok(buffer_len == required_len ||
5198        broken(buffer_len == required_len / sizeof(WCHAR)), /* XP+ */
5199        "Outputted buffer length was %u\n", buffer_len);
5200 
5201     /* Use the reported buffer size from the last GetUserNameA call and pass
5202      * a length that is one less than the required value. */
5203     SetLastError(0xdeadbeef);
5204     memcpy(buffer, filler, sizeof(filler));
5205     buffer_len--;
5206     ret = GetUserNameA(buffer, &buffer_len);
5207     ok(ret == FALSE, "GetUserNameA returned %d\n", ret);
5208     ok(!memcmp(buffer, filler, sizeof(filler)), "Output buffer was untouched\n");
5209     ok(buffer_len == required_len, "Outputted buffer length was %u\n", buffer_len);
5210     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
5211 }
5212 
5213 static void test_GetUserNameW(void)
5214 {
5215     WCHAR buffer[UNLEN + 1], filler[UNLEN + 1];
5216     DWORD required_len, buffer_len;
5217     BOOL ret;
5218 
5219     /* Test crashes on Windows. */
5220     if (0)
5221     {
5222         SetLastError(0xdeadbeef);
5223         GetUserNameW(NULL, NULL);
5224     }
5225 
5226     SetLastError(0xdeadbeef);
5227     required_len = 0;
5228     ret = GetUserNameW(NULL, &required_len);
5229     ok(ret == FALSE, "GetUserNameW returned %d\n", ret);
5230     ok(required_len != 0, "Outputted buffer length was %u\n", required_len);
5231     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
5232 
5233     SetLastError(0xdeadbeef);
5234     required_len = 1;
5235     ret = GetUserNameW(NULL, &required_len);
5236     ok(ret == FALSE, "GetUserNameW returned %d\n", ret);
5237     ok(required_len != 0 && required_len != 1, "Outputted buffer length was %u\n", required_len);
5238     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
5239 
5240     /* Tests crash on Windows. */
5241     if (0)
5242     {
5243         SetLastError(0xdeadbeef);
5244         required_len = UNLEN + 1;
5245         GetUserNameW(NULL, &required_len);
5246 
5247         SetLastError(0xdeadbeef);
5248         GetUserNameW(buffer, NULL);
5249     }
5250 
5251     memset(filler, 'x', sizeof(filler));
5252 
5253     SetLastError(0xdeadbeef);
5254     memcpy(buffer, filler, sizeof(filler));
5255     required_len = 0;
5256     ret = GetUserNameW(buffer, &required_len);
5257     ok(ret == FALSE, "GetUserNameW returned %d\n", ret);
5258     ok(!memcmp(buffer, filler, sizeof(filler)), "Output buffer was altered\n");
5259     ok(required_len != 0, "Outputted buffer length was %u\n", required_len);
5260     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
5261 
5262     SetLastError(0xdeadbeef);
5263     memcpy(buffer, filler, sizeof(filler));
5264     buffer_len = required_len;
5265     ret = GetUserNameW(buffer, &buffer_len);
5266     ok(ret == TRUE, "GetUserNameW returned %d, last error %u\n", ret, GetLastError());
5267     ok(memcmp(buffer, filler, sizeof(filler)) != 0, "Output buffer was untouched\n");
5268     ok(buffer_len == required_len, "Outputted buffer length was %u\n", buffer_len);
5269 
5270     /* GetUserNameW on XP and newer writes a truncated portion of the username string to the buffer. */
5271     SetLastError(0xdeadbeef);
5272     memcpy(buffer, filler, sizeof(filler));
5273     buffer_len--;
5274     ret = GetUserNameW(buffer, &buffer_len);
5275     ok(ret == FALSE, "GetUserNameW returned %d\n", ret);
5276     ok(!memcmp(buffer, filler, sizeof(filler)) ||
5277        broken(memcmp(buffer, filler, sizeof(filler)) != 0), /* XP+ */
5278        "Output buffer was altered\n");
5279     ok(buffer_len == required_len, "Outputted buffer length was %u\n", buffer_len);
5280     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
5281 }
5282 
5283 static void test_CreateRestrictedToken(void)
5284 {
5285     TOKEN_PRIMARY_GROUP *primary_group, *primary_group2;
5286     HANDLE process_token, token, r_token;
5287     PTOKEN_GROUPS token_groups, groups2;
5288     SID_AND_ATTRIBUTES sattr;
5289     SECURITY_IMPERSONATION_LEVEL level;
5290     TOKEN_PRIVILEGES *privs;
5291     PRIVILEGE_SET privset;
5292     TOKEN_TYPE type;
5293     BOOL is_member;
5294     DWORD size;
5295     BOOL ret;
5296     DWORD i, j;
5297 
5298     if (!pCreateRestrictedToken)
5299     {
5300         win_skip("CreateRestrictedToken is not available\n");
5301         return;
5302     }
5303 
5304     ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &process_token);
5305     ok(ret, "got error %d\n", GetLastError());
5306 
5307     ret = DuplicateTokenEx(process_token, TOKEN_DUPLICATE|TOKEN_ADJUST_GROUPS|TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
5308         NULL, SecurityImpersonation, TokenImpersonation, &token);
5309     ok(ret, "got error %d\n", GetLastError());
5310 
5311     /* groups */
5312     ret = GetTokenInformation(token, TokenGroups, NULL, 0, &size);
5313     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
5314         "got %d with error %d\n", ret, GetLastError());
5315     token_groups = HeapAlloc(GetProcessHeap(), 0, size);
5316     ret = GetTokenInformation(token, TokenGroups, token_groups, size, &size);
5317     ok(ret, "got error %d\n", GetLastError());
5318 
5319     for (i = 0; i < token_groups->GroupCount; i++)
5320     {
5321         if (token_groups->Groups[i].Attributes & SE_GROUP_ENABLED)
5322             break;
5323     }
5324 
5325     if (i == token_groups->GroupCount)
5326     {
5327         HeapFree(GetProcessHeap(), 0, token_groups);
5328         CloseHandle(token);
5329         skip("User not a member of any group\n");
5330         return;
5331     }
5332 
5333     is_member = FALSE;
5334     ret = pCheckTokenMembership(token, token_groups->Groups[i].Sid, &is_member);
5335     ok(ret, "got error %d\n", GetLastError());
5336     ok(is_member, "not a member\n");
5337 
5338     privset.PrivilegeCount = 1;
5339     privset.Control = PRIVILEGE_SET_ALL_NECESSARY;
5340     ret = LookupPrivilegeValueA(NULL, "SeChangeNotifyPrivilege", &privset.Privilege[0].Luid);
5341     ok(ret, "got error %d\n", GetLastError());
5342 
5343     is_member = FALSE;
5344     ret = PrivilegeCheck(token, &privset, &is_member);
5345     ok(ret, "got error %d\n", GetLastError());
5346     ok(is_member, "Expected SeChangeNotifyPrivilege to be enabled\n");
5347 
5348     /* disable a SID and a privilege in new token */
5349     sattr.Sid = token_groups->Groups[i].Sid;
5350     sattr.Attributes = 0;
5351     r_token = NULL;
5352     ret = pCreateRestrictedToken(token, 0, 1, &sattr, 1, &privset.Privilege[0], 0, NULL, &r_token);
5353     ok(ret, "got error %d\n", GetLastError());
5354 
5355     if (ret)
5356     {
5357         /* check if a SID is enabled */
5358         is_member = TRUE;
5359         ret = pCheckTokenMembership(r_token, token_groups->Groups[i].Sid, &is_member);
5360         ok(ret, "got error %d\n", GetLastError());
5361         ok(!is_member, "not a member\n");
5362 
5363         ret = GetTokenInformation(r_token, TokenGroups, NULL, 0, &size);
5364         ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n",
5365             ret, GetLastError());
5366         groups2 = HeapAlloc(GetProcessHeap(), 0, size);
5367         ret = GetTokenInformation(r_token, TokenGroups, groups2, size, &size);
5368         ok(ret, "got error %d\n", GetLastError());
5369 
5370         for (j = 0; j < groups2->GroupCount; j++)
5371         {
5372             if (EqualSid(groups2->Groups[j].Sid, token_groups->Groups[i].Sid))
5373                 break;
5374         }
5375 
5376         ok(groups2->Groups[j].Attributes & SE_GROUP_USE_FOR_DENY_ONLY,
5377             "got wrong attributes\n");
5378         ok((groups2->Groups[j].Attributes & SE_GROUP_ENABLED) == 0,
5379             "got wrong attributes\n");
5380 
5381         HeapFree(GetProcessHeap(), 0, groups2);
5382 
5383         size = sizeof(type);
5384         ret = GetTokenInformation(r_token, TokenType, &type, size, &size);
5385         ok(ret, "got error %d\n", GetLastError());
5386         ok(type == TokenImpersonation, "got type %u\n", type);
5387 
5388         size = sizeof(level);
5389         ret = GetTokenInformation(r_token, TokenImpersonationLevel, &level, size, &size);
5390         ok(ret, "got error %d\n", GetLastError());
5391         ok(level == SecurityImpersonation, "got level %u\n", type);
5392 
5393         is_member = TRUE;
5394         ret = PrivilegeCheck(r_token, &privset, &is_member);
5395         ok(ret, "got error %d\n", GetLastError());
5396         ok(!is_member, "Expected SeChangeNotifyPrivilege not to be enabled\n");
5397 
5398         ret = GetTokenInformation(r_token, TokenPrivileges, NULL, 0, &size);
5399         ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n",
5400             ret, GetLastError());
5401         privs = HeapAlloc(GetProcessHeap(), 0, size);
5402         ret = GetTokenInformation(r_token, TokenPrivileges, privs, size, &size);
5403         ok(ret, "got error %d\n", GetLastError());
5404 
5405         is_member = FALSE;
5406         for (j = 0; j < privs->PrivilegeCount; j++)
5407         {
5408             if (RtlEqualLuid(&privs->Privileges[j].Luid, &privset.Privilege[0].Luid))
5409             {
5410                 is_member = TRUE;
5411                 break;
5412             }
5413         }
5414 
5415         ok(!is_member, "Expected not to find privilege\n");
5416         HeapFree(GetProcessHeap(), 0, privs);
5417     }
5418 
5419     HeapFree(GetProcessHeap(), 0, token_groups);
5420     CloseHandle(r_token);
5421 
5422     ret = GetTokenInformation(token, TokenPrimaryGroup, NULL, 0, &size);
5423     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n",
5424         ret, GetLastError());
5425     primary_group = HeapAlloc(GetProcessHeap(), 0, size);
5426     ret = GetTokenInformation(token, TokenPrimaryGroup, primary_group, size, &size);
5427     ok(ret, "got error %d\n", GetLastError());
5428 
5429     /* disable primary group */
5430     sattr.Sid = primary_group->PrimaryGroup;
5431     sattr.Attributes = 0;
5432     r_token = NULL;
5433     ret = pCreateRestrictedToken(token, 0, 1, &sattr, 0, NULL, 0, NULL, &r_token);
5434     ok(ret, "got error %d\n", GetLastError());
5435 
5436     if (ret)
5437     {
5438         is_member = TRUE;
5439         ret = pCheckTokenMembership(r_token, primary_group->PrimaryGroup, &is_member);
5440         ok(ret, "got error %d\n", GetLastError());
5441         ok(!is_member, "not a member\n");
5442 
5443         ret = GetTokenInformation(r_token, TokenPrimaryGroup, NULL, 0, &size);
5444         ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n",
5445             ret, GetLastError());
5446         primary_group2 = HeapAlloc(GetProcessHeap(), 0, size);
5447         ret = GetTokenInformation(r_token, TokenPrimaryGroup, primary_group2, size, &size);
5448         ok(ret, "got error %d\n", GetLastError());
5449 
5450         ok(EqualSid(primary_group2->PrimaryGroup, primary_group->PrimaryGroup),
5451            "Expected same primary group\n");
5452 
5453         HeapFree(GetProcessHeap(), 0, primary_group2);
5454     }
5455 
5456     HeapFree(GetProcessHeap(), 0, primary_group);
5457     CloseHandle(r_token);
5458 
5459     CloseHandle(token);
5460     CloseHandle(process_token);
5461 }
5462 
5463 static void validate_default_security_descriptor(SECURITY_DESCRIPTOR *sd)
5464 {
5465     BOOL ret, present, defaulted;
5466     ACL *acl;
5467     void *sid;
5468 
5469     ret = IsValidSecurityDescriptor(sd);
5470     ok(ret, "security descriptor is not valid\n");
5471 
5472     present = -1;
5473     defaulted = -1;
5474     acl = (void *)0xdeadbeef;
5475     SetLastError(0xdeadbeef);
5476     ret = GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted);
5477     ok(ret, "GetSecurityDescriptorDacl error %d\n", GetLastError());
5478 todo_wine
5479     ok(present == 1, "acl is not present\n");
5480 todo_wine
5481     ok(acl != (void *)0xdeadbeef && acl != NULL, "acl pointer is not set\n");
5482     ok(defaulted == 0, "defaulted is set to TRUE\n");
5483 
5484     defaulted = -1;
5485     sid = (void *)0xdeadbeef;
5486     SetLastError(0xdeadbeef);
5487     ret = GetSecurityDescriptorOwner(sd, &sid, &defaulted);
5488     ok(ret, "GetSecurityDescriptorOwner error %d\n", GetLastError());
5489 todo_wine
5490     ok(sid != (void *)0xdeadbeef && sid != NULL, "sid pointer is not set\n");
5491     ok(defaulted == 0, "defaulted is set to TRUE\n");
5492 
5493     defaulted = -1;
5494     sid = (void *)0xdeadbeef;
5495     SetLastError(0xdeadbeef);
5496     ret = GetSecurityDescriptorGroup(sd, &sid, &defaulted);
5497     ok(ret, "GetSecurityDescriptorGroup error %d\n", GetLastError());
5498 todo_wine
5499     ok(sid != (void *)0xdeadbeef && sid != NULL, "sid pointer is not set\n");
5500     ok(defaulted == 0, "defaulted is set to TRUE\n");
5501 }
5502 
5503 static void test_default_handle_security(HANDLE token, HANDLE handle, GENERIC_MAPPING *mapping)
5504 {
5505     DWORD ret, granted, priv_set_len;
5506     BOOL status;
5507     PRIVILEGE_SET priv_set;
5508     SECURITY_DESCRIPTOR *sd;
5509 
5510     sd = test_get_security_descriptor(handle, __LINE__);
5511     validate_default_security_descriptor(sd);
5512 
5513     priv_set_len = sizeof(priv_set);
5514     granted = 0xdeadbeef;
5515     status = 0xdeadbeef;
5516     SetLastError(0xdeadbeef);
5517     ret = AccessCheck(sd, token, MAXIMUM_ALLOWED, mapping, &priv_set, &priv_set_len, &granted, &status);
5518 todo_wine {
5519     ok(ret, "AccessCheck error %d\n", GetLastError());
5520     ok(status == 1, "expected 1, got %d\n", status);
5521     ok(granted == mapping->GenericAll, "expected all access %#x, got %#x\n", mapping->GenericAll, granted);
5522 }
5523     priv_set_len = sizeof(priv_set);
5524     granted = 0xdeadbeef;
5525     status = 0xdeadbeef;
5526     SetLastError(0xdeadbeef);
5527     ret = AccessCheck(sd, token, 0, mapping, &priv_set, &priv_set_len, &granted, &status);
5528 todo_wine {
5529     ok(ret, "AccessCheck error %d\n", GetLastError());
5530     ok(status == 0 || broken(status == 1) /* NT4 */, "expected 0, got %d\n", status);
5531     ok(granted == 0 || broken(granted == mapping->GenericRead) /* NT4 */, "expected 0, got %#x\n", granted);
5532 }
5533     priv_set_len = sizeof(priv_set);
5534     granted = 0xdeadbeef;
5535     status = 0xdeadbeef;
5536     SetLastError(0xdeadbeef);
5537     ret = AccessCheck(sd, token, ACCESS_SYSTEM_SECURITY, mapping, &priv_set, &priv_set_len, &granted, &status);
5538 todo_wine {
5539     ok(ret, "AccessCheck error %d\n", GetLastError());
5540     ok(status == 0, "expected 0, got %d\n", status);
5541     ok(granted == 0, "expected 0, got %#x\n", granted);
5542 }
5543     priv_set_len = sizeof(priv_set);
5544     granted = 0xdeadbeef;
5545     status = 0xdeadbeef;
5546     SetLastError(0xdeadbeef);
5547     ret = AccessCheck(sd, token, mapping->GenericRead, mapping, &priv_set, &priv_set_len, &granted, &status);
5548 todo_wine {
5549     ok(ret, "AccessCheck error %d\n", GetLastError());
5550     ok(status == 1, "expected 1, got %d\n", status);
5551     ok(granted == mapping->GenericRead, "expected read access %#x, got %#x\n", mapping->GenericRead, granted);
5552 }
5553     priv_set_len = sizeof(priv_set);
5554     granted = 0xdeadbeef;
5555     status = 0xdeadbeef;
5556     SetLastError(0xdeadbeef);
5557     ret = AccessCheck(sd, token, mapping->GenericWrite, mapping, &priv_set, &priv_set_len, &granted, &status);
5558 todo_wine {
5559     ok(ret, "AccessCheck error %d\n", GetLastError());
5560     ok(status == 1, "expected 1, got %d\n", status);
5561     ok(granted == mapping->GenericWrite, "expected write access %#x, got %#x\n", mapping->GenericWrite, granted);
5562 }
5563     priv_set_len = sizeof(priv_set);
5564     granted = 0xdeadbeef;
5565     status = 0xdeadbeef;
5566     SetLastError(0xdeadbeef);
5567     ret = AccessCheck(sd, token, mapping->GenericExecute, mapping, &priv_set, &priv_set_len, &granted, &status);
5568 todo_wine {
5569     ok(ret, "AccessCheck error %d\n", GetLastError());
5570     ok(status == 1, "expected 1, got %d\n", status);
5571     ok(granted == mapping->GenericExecute, "expected execute access %#x, got %#x\n", mapping->GenericExecute, granted);
5572 }
5573     HeapFree(GetProcessHeap(), 0, sd);
5574 }
5575 
5576 static ACCESS_MASK get_obj_access(HANDLE obj)
5577 {
5578     OBJECT_BASIC_INFORMATION info;
5579     NTSTATUS status;
5580 
5581     if (!pNtQueryObject) return 0;
5582 
5583     status = pNtQueryObject(obj, ObjectBasicInformation, &info, sizeof(info), NULL);
5584     ok(!status, "NtQueryObject error %#x\n", status);
5585 
5586     return info.GrantedAccess;
5587 }
5588 
5589 static void test_mutex_security(HANDLE token)
5590 {
5591     DWORD ret, i, access;
5592     HANDLE mutex, dup;
5593     GENERIC_MAPPING mapping = { STANDARD_RIGHTS_READ | MUTANT_QUERY_STATE | SYNCHRONIZE,
5594                                 STANDARD_RIGHTS_WRITE | MUTEX_MODIFY_STATE | SYNCHRONIZE,
5595                                 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
5596                                 STANDARD_RIGHTS_ALL | MUTEX_ALL_ACCESS };
5597     static const struct
5598     {
5599         int generic, mapped;
5600     } map[] =
5601     {
5602         { 0, 0 },
5603         { GENERIC_READ, STANDARD_RIGHTS_READ | MUTANT_QUERY_STATE },
5604         { GENERIC_WRITE, STANDARD_RIGHTS_WRITE },
5605         { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
5606         { GENERIC_ALL, STANDARD_RIGHTS_ALL | MUTANT_QUERY_STATE }
5607     };
5608 
5609     SetLastError(0xdeadbeef);
5610     mutex = OpenMutexA(0, FALSE, "WineTestMutex");
5611     ok(!mutex, "mutex should not exist\n");
5612     ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
5613 
5614     SetLastError(0xdeadbeef);
5615     mutex = CreateMutexA(NULL, FALSE, "WineTestMutex");
5616     ok(mutex != 0, "CreateMutex error %d\n", GetLastError());
5617 
5618     access = get_obj_access(mutex);
5619     ok(access == MUTANT_ALL_ACCESS, "expected MUTANT_ALL_ACCESS, got %#x\n", access);
5620 
5621     for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
5622     {
5623         SetLastError( 0xdeadbeef );
5624         ret = DuplicateHandle(GetCurrentProcess(), mutex, GetCurrentProcess(), &dup,
5625                               map[i].generic, FALSE, 0);
5626         ok(ret, "DuplicateHandle error %d\n", GetLastError());
5627 
5628         access = get_obj_access(dup);
5629         ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
5630 
5631         CloseHandle(dup);
5632 
5633         SetLastError(0xdeadbeef);
5634         dup = OpenMutexA(0, FALSE, "WineTestMutex");
5635 todo_wine
5636         ok(!dup, "OpenMutex should fail\n");
5637 todo_wine
5638         ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError());
5639     }
5640 
5641     test_default_handle_security(token, mutex, &mapping);
5642 
5643     CloseHandle (mutex);
5644 }
5645 
5646 static void test_event_security(HANDLE token)
5647 {
5648     DWORD ret, i, access;
5649     HANDLE event, dup;
5650     GENERIC_MAPPING mapping = { STANDARD_RIGHTS_READ | EVENT_QUERY_STATE | SYNCHRONIZE,
5651                                 STANDARD_RIGHTS_WRITE | EVENT_MODIFY_STATE | SYNCHRONIZE,
5652                                 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
5653                                 STANDARD_RIGHTS_ALL | EVENT_ALL_ACCESS };
5654     static const struct
5655     {
5656         int generic, mapped;
5657     } map[] =
5658     {
5659         { 0, 0 },
5660         { GENERIC_READ, STANDARD_RIGHTS_READ | EVENT_QUERY_STATE },
5661         { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | EVENT_MODIFY_STATE },
5662         { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
5663         { GENERIC_ALL, STANDARD_RIGHTS_ALL | EVENT_QUERY_STATE | EVENT_MODIFY_STATE }
5664     };
5665 
5666     SetLastError(0xdeadbeef);
5667     event = OpenEventA(0, FALSE, "WineTestEvent");
5668     ok(!event, "event should not exist\n");
5669     ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
5670 
5671     SetLastError(0xdeadbeef);
5672     event = CreateEventA(NULL, FALSE, FALSE, "WineTestEvent");
5673     ok(event != 0, "CreateEvent error %d\n", GetLastError());
5674 
5675     access = get_obj_access(event);
5676     ok(access == EVENT_ALL_ACCESS, "expected EVENT_ALL_ACCESS, got %#x\n", access);
5677 
5678     for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
5679     {
5680         SetLastError( 0xdeadbeef );
5681         ret = DuplicateHandle(GetCurrentProcess(), event, GetCurrentProcess(), &dup,
5682                               map[i].generic, FALSE, 0);
5683         ok(ret, "DuplicateHandle error %d\n", GetLastError());
5684 
5685         access = get_obj_access(dup);
5686         ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
5687 
5688         CloseHandle(dup);
5689 
5690         SetLastError(0xdeadbeef);
5691         dup = OpenEventA(0, FALSE, "WineTestEvent");
5692 todo_wine
5693         ok(!dup, "OpenEvent should fail\n");
5694 todo_wine
5695         ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError());
5696     }
5697 
5698     test_default_handle_security(token, event, &mapping);
5699 
5700     CloseHandle(event);
5701 }
5702 
5703 static void test_semaphore_security(HANDLE token)
5704 {
5705     DWORD ret, i, access;
5706     HANDLE sem, dup;
5707     GENERIC_MAPPING mapping = { STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE,
5708                                 STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE,
5709                                 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
5710                                 STANDARD_RIGHTS_ALL | SEMAPHORE_ALL_ACCESS };
5711     static const struct
5712     {
5713         int generic, mapped;
5714     } map[] =
5715     {
5716         { 0, 0 },
5717         { GENERIC_READ, STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE },
5718         { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE },
5719         { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
5720         { GENERIC_ALL, STANDARD_RIGHTS_ALL | SEMAPHORE_QUERY_STATE | SEMAPHORE_MODIFY_STATE }
5721     };
5722 
5723     SetLastError(0xdeadbeef);
5724     sem = OpenSemaphoreA(0, FALSE, "WineTestSemaphore");
5725     ok(!sem, "semaphore should not exist\n");
5726     ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
5727 
5728     SetLastError(0xdeadbeef);
5729     sem = CreateSemaphoreA(NULL, 0, 10, "WineTestSemaphore");
5730     ok(sem != 0, "CreateSemaphore error %d\n", GetLastError());
5731 
5732     access = get_obj_access(sem);
5733     ok(access == SEMAPHORE_ALL_ACCESS, "expected SEMAPHORE_ALL_ACCESS, got %#x\n", access);
5734 
5735     for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
5736     {
5737         SetLastError( 0xdeadbeef );
5738         ret = DuplicateHandle(GetCurrentProcess(), sem, GetCurrentProcess(), &dup,
5739                               map[i].generic, FALSE, 0);
5740         ok(ret, "DuplicateHandle error %d\n", GetLastError());
5741 
5742         access = get_obj_access(dup);
5743         ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
5744 
5745         CloseHandle(dup);
5746     }
5747 
5748     test_default_handle_security(token, sem, &mapping);
5749 
5750     CloseHandle(sem);
5751 }
5752 
5753 #define WINE_TEST_PIPE "\\\\.\\pipe\\WineTestPipe"
5754 static void test_named_pipe_security(HANDLE token)
5755 {
5756     DWORD ret, i, access;
5757     HANDLE pipe, file, dup;
5758     GENERIC_MAPPING mapping = { FILE_GENERIC_READ,
5759                                 FILE_GENERIC_WRITE,
5760                                 FILE_GENERIC_EXECUTE,
5761                                 STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS };
5762     static const struct
5763     {
5764         int todo, generic, mapped;
5765     } map[] =
5766     {
5767         { 0, 0, 0 },
5768         { 1, GENERIC_READ, FILE_GENERIC_READ },
5769         { 1, GENERIC_WRITE, FILE_GENERIC_WRITE },
5770         { 1, GENERIC_EXECUTE, FILE_GENERIC_EXECUTE },
5771         { 1, GENERIC_ALL, STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS }
5772     };
5773     static const struct
5774     {
5775         DWORD open_mode;
5776         DWORD access;
5777     } creation_access[] =
5778     {
5779         { PIPE_ACCESS_INBOUND, FILE_GENERIC_READ },
5780         { PIPE_ACCESS_OUTBOUND, FILE_GENERIC_WRITE },
5781         { PIPE_ACCESS_DUPLEX, FILE_GENERIC_READ|FILE_GENERIC_WRITE },
5782         { PIPE_ACCESS_INBOUND|WRITE_DAC, FILE_GENERIC_READ|WRITE_DAC },
5783         { PIPE_ACCESS_INBOUND|WRITE_OWNER, FILE_GENERIC_READ|WRITE_OWNER }
5784         /* ACCESS_SYSTEM_SECURITY is also valid, but will fail with ERROR_PRIVILEGE_NOT_HELD */
5785     };
5786 
5787     /* Test the different security access options for pipes */
5788     for (i = 0; i < sizeof(creation_access)/sizeof(creation_access[0]); i++)
5789     {
5790         SetLastError(0xdeadbeef);
5791         pipe = CreateNamedPipeA(WINE_TEST_PIPE, creation_access[i].open_mode,
5792                                 PIPE_TYPE_BYTE | PIPE_NOWAIT, PIPE_UNLIMITED_INSTANCES, 0, 0,
5793                                 NMPWAIT_USE_DEFAULT_WAIT, NULL);
5794         ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe(0x%x) error %d\n",
5795                                          creation_access[i].open_mode, GetLastError());
5796         access = get_obj_access(pipe);
5797         ok(access == creation_access[i].access,
5798            "CreateNamedPipeA(0x%x) pipe expected access 0x%x (got 0x%x)\n",
5799            creation_access[i].open_mode, creation_access[i].access, access);
5800         CloseHandle(pipe);
5801     }
5802 
5803     SetLastError(0xdeadbeef);
5804     pipe = CreateNamedPipeA(WINE_TEST_PIPE, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,
5805                             PIPE_TYPE_BYTE | PIPE_NOWAIT, PIPE_UNLIMITED_INSTANCES,
5806                             0, 0, NMPWAIT_USE_DEFAULT_WAIT, NULL);
5807     ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe error %d\n", GetLastError());
5808 
5809     test_default_handle_security(token, pipe, &mapping);
5810 
5811     SetLastError(0xdeadbeef);
5812     file = CreateFileA(WINE_TEST_PIPE, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, 0, 0);
5813     ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
5814 
5815     access = get_obj_access(file);
5816     ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", access);
5817 
5818     for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
5819     {
5820         SetLastError( 0xdeadbeef );
5821         ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup,
5822                               map[i].generic, FALSE, 0);
5823         ok(ret, "DuplicateHandle error %d\n", GetLastError());
5824 
5825         access = get_obj_access(dup);
5826         ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
5827 
5828         CloseHandle(dup);
5829     }
5830 
5831     CloseHandle(file);
5832     CloseHandle(pipe);
5833 
5834     SetLastError(0xdeadbeef);
5835     file = CreateFileA("\\\\.\\pipe\\", FILE_ALL_ACCESS, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
5836     ok(file != INVALID_HANDLE_VALUE || broken(file == INVALID_HANDLE_VALUE) /* before Vista */, "CreateFile error %d\n", GetLastError());
5837 
5838     if (file != INVALID_HANDLE_VALUE)
5839     {
5840         access = get_obj_access(file);
5841         ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", access);
5842 
5843         for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
5844         {
5845             SetLastError( 0xdeadbeef );
5846             ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup,
5847                                   map[i].generic, FALSE, 0);
5848             ok(ret, "DuplicateHandle error %d\n", GetLastError());
5849 
5850             access = get_obj_access(dup);
5851             todo_wine_if (map[i].todo)
5852                 ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
5853 
5854             CloseHandle(dup);
5855         }
5856     }
5857 
5858     CloseHandle(file);
5859 }
5860 
5861 static void test_file_security(HANDLE token)
5862 {
5863     DWORD ret, i, access, bytes;
5864     HANDLE file, dup;
5865     static const struct
5866     {
5867         int generic, mapped;
5868     } map[] =
5869     {
5870         { 0, 0 },
5871         { GENERIC_READ, FILE_GENERIC_READ },
5872         { GENERIC_WRITE, FILE_GENERIC_WRITE },
5873         { GENERIC_EXECUTE, FILE_GENERIC_EXECUTE },
5874         { GENERIC_ALL, STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS }
5875     };
5876     char temp_path[MAX_PATH];
5877     char file_name[MAX_PATH];
5878     char buf[16];
5879 
5880     GetTempPathA(MAX_PATH, temp_path);
5881     GetTempFileNameA(temp_path, "tmp", 0, file_name);
5882 
5883     /* file */
5884     SetLastError(0xdeadbeef);
5885     file = CreateFileA(file_name, GENERIC_ALL, 0, NULL, CREATE_ALWAYS, 0, NULL);
5886     ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
5887 
5888     access = get_obj_access(file);
5889     ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", access);
5890 
5891     for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
5892     {
5893         SetLastError( 0xdeadbeef );
5894         ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup,
5895                               map[i].generic, FALSE, 0);
5896         ok(ret, "DuplicateHandle error %d\n", GetLastError());
5897 
5898         access = get_obj_access(dup);
5899         ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
5900 
5901         CloseHandle(dup);
5902     }
5903 
5904     CloseHandle(file);
5905 
5906     SetLastError(0xdeadbeef);
5907     file = CreateFileA(file_name, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
5908     ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
5909 
5910     access = get_obj_access(file);
5911 todo_wine
5912     ok(access == (FILE_READ_ATTRIBUTES | SYNCHRONIZE), "expected FILE_READ_ATTRIBUTES | SYNCHRONIZE, got %#x\n", access);
5913 
5914     bytes = 0xdeadbeef;
5915     SetLastError(0xdeadbeef);
5916     ret = ReadFile(file, buf, sizeof(buf), &bytes, NULL);
5917     ok(!ret, "ReadFile should fail\n");
5918     ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
5919     ok(bytes == 0, "expected 0, got %u\n", bytes);
5920 
5921     CloseHandle(file);
5922 
5923     SetLastError(0xdeadbeef);
5924     file = CreateFileA(file_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
5925     ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
5926 
5927     access = get_obj_access(file);
5928 todo_wine
5929     ok(access == (FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES), "expected FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES, got %#x\n", access);
5930 
5931     bytes = 0xdeadbeef;
5932     SetLastError(0xdeadbeef);
5933     ret = ReadFile(file, buf, sizeof(buf), &bytes, NULL);
5934     ok(!ret, "ReadFile should fail\n");
5935     ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
5936     ok(bytes == 0, "expected 0, got %u\n", bytes);
5937 
5938     CloseHandle(file);
5939     DeleteFileA(file_name);
5940 
5941     /* directory */
5942     SetLastError(0xdeadbeef);
5943     file = CreateFileA(temp_path, GENERIC_ALL, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
5944     ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
5945 
5946     access = get_obj_access(file);
5947     ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", access);
5948 
5949     for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
5950     {
5951         SetLastError( 0xdeadbeef );
5952         ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup,
5953                               map[i].generic, FALSE, 0);
5954         ok(ret, "DuplicateHandle error %d\n", GetLastError());
5955 
5956         access = get_obj_access(dup);
5957         ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
5958 
5959         CloseHandle(dup);
5960     }
5961 
5962     CloseHandle(file);
5963 
5964     SetLastError(0xdeadbeef);
5965     file = CreateFileA(temp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
5966     ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
5967 
5968     access = get_obj_access(file);
5969 todo_wine
5970     ok(access == (FILE_READ_ATTRIBUTES | SYNCHRONIZE), "expected FILE_READ_ATTRIBUTES | SYNCHRONIZE, got %#x\n", access);
5971 
5972     CloseHandle(file);
5973 
5974     SetLastError(0xdeadbeef);
5975     file = CreateFileA(temp_path, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
5976     ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
5977 
5978     access = get_obj_access(file);
5979 todo_wine
5980     ok(access == (FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES), "expected FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES, got %#x\n", access);
5981 
5982     CloseHandle(file);
5983 }
5984 
5985 static void test_filemap_security(void)
5986 {
5987     char temp_path[MAX_PATH];
5988     char file_name[MAX_PATH];
5989     DWORD ret, i, access;
5990     HANDLE file, mapping, dup, created_mapping;
5991     static const struct
5992     {
5993         int generic, mapped;
5994         BOOL open_only;
5995     } map[] =
5996     {
5997         { 0, 0 },
5998         { GENERIC_READ, STANDARD_RIGHTS_READ | SECTION_QUERY | SECTION_MAP_READ },
5999         { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | SECTION_MAP_WRITE },
6000         { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SECTION_MAP_EXECUTE },
6001         { GENERIC_ALL, STANDARD_RIGHTS_REQUIRED | SECTION_ALL_ACCESS },
6002         { SECTION_MAP_READ | SECTION_MAP_WRITE, SECTION_MAP_READ | SECTION_MAP_WRITE },
6003         { SECTION_MAP_WRITE, SECTION_MAP_WRITE },
6004         { SECTION_MAP_READ | SECTION_QUERY, SECTION_MAP_READ | SECTION_QUERY },
6005         { SECTION_QUERY, SECTION_MAP_READ, TRUE },
6006         { SECTION_QUERY | SECTION_MAP_READ, SECTION_QUERY | SECTION_MAP_READ }
6007     };
6008     static const struct
6009     {
6010         int prot, mapped;
6011     } prot_map[] =
6012     {
6013         { 0, 0 },
6014         { PAGE_NOACCESS, 0 },
6015         { PAGE_READONLY, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ },
6016         { PAGE_READWRITE, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE },
6017         { PAGE_WRITECOPY, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ },
6018         { PAGE_EXECUTE, 0 },
6019         { PAGE_EXECUTE_READ, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE },
6020         { PAGE_EXECUTE_READWRITE, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE },
6021         { PAGE_EXECUTE_WRITECOPY, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE }
6022     };
6023 
6024     GetTempPathA(MAX_PATH, temp_path);
6025     GetTempFileNameA(temp_path, "tmp", 0, file_name);
6026 
6027     SetLastError(0xdeadbeef);
6028     file = CreateFileA(file_name, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, CREATE_ALWAYS, 0, 0);
6029     ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
6030     SetFilePointer(file, 4096, NULL, FILE_BEGIN);
6031     SetEndOfFile(file);
6032 
6033     for (i = 0; i < sizeof(prot_map)/sizeof(prot_map[0]); i++)
6034     {
6035         if (map[i].open_only) continue;
6036 
6037         SetLastError(0xdeadbeef);
6038         mapping = CreateFileMappingW(file, NULL, prot_map[i].prot, 0, 4096, NULL);
6039         if (prot_map[i].mapped)
6040         {
6041             if (!mapping)
6042             {
6043                 /* NT4 and win2k don't support EXEC on file mappings */
6044                 if (prot_map[i].prot == PAGE_EXECUTE_READ || prot_map[i].prot == PAGE_EXECUTE_READWRITE || prot_map[i].prot == PAGE_EXECUTE_WRITECOPY)
6045                 {
6046                     win_skip("CreateFileMapping doesn't support PAGE_EXECUTE protection\n");
6047                     continue;
6048                 }
6049             }
6050             ok(mapping != 0, "CreateFileMapping(%04x) error %d\n", prot_map[i].prot, GetLastError());
6051         }
6052         else
6053         {
6054             ok(!mapping, "CreateFileMapping(%04x) should fail\n", prot_map[i].prot);
6055             ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
6056             continue;
6057         }
6058 
6059         access = get_obj_access(mapping);
6060         ok(access == prot_map[i].mapped, "%d: expected %#x, got %#x\n", i, prot_map[i].mapped, access);
6061 
6062         CloseHandle(mapping);
6063     }
6064 
6065     SetLastError(0xdeadbeef);
6066     mapping = CreateFileMappingW(file, NULL, PAGE_EXECUTE_READWRITE, 0, 4096, NULL);
6067     if (!mapping)
6068     {
6069         /* NT4 and win2k don't support EXEC on file mappings */
6070         win_skip("CreateFileMapping doesn't support PAGE_EXECUTE protection\n");
6071         CloseHandle(file);
6072         DeleteFileA(file_name);
6073         return;
6074     }
6075     ok(mapping != 0, "CreateFileMapping error %d\n", GetLastError());
6076 
6077     access = get_obj_access(mapping);
6078     ok(access == (STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE),
6079        "expected STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE, got %#x\n", access);
6080 
6081     for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
6082     {
6083         if (map[i].open_only) continue;
6084 
6085         SetLastError( 0xdeadbeef );
6086         ret = DuplicateHandle(GetCurrentProcess(), mapping, GetCurrentProcess(), &dup,
6087                               map[i].generic, FALSE, 0);
6088         ok(ret, "DuplicateHandle error %d\n", GetLastError());
6089 
6090         access = get_obj_access(dup);
6091         ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6092 
6093         CloseHandle(dup);
6094     }
6095 
6096     CloseHandle(mapping);
6097     CloseHandle(file);
6098     DeleteFileA(file_name);
6099 
6100     created_mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 0x1000,
6101                                          "Wine Test Open Mapping");
6102     ok(created_mapping != NULL, "CreateFileMapping failed with error %u\n", GetLastError());
6103 
6104     for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
6105     {
6106         if (!map[i].generic) continue;
6107 
6108         mapping = OpenFileMappingA(map[i].generic, FALSE, "Wine Test Open Mapping");
6109         ok(mapping != NULL, "OpenFileMapping failed with error %d\n", GetLastError());
6110         access = get_obj_access(mapping);
6111         ok(access == map[i].mapped, "%d: unexpected access flags %#x, expected %#x\n",
6112            i, access, map[i].mapped);
6113         CloseHandle(mapping);
6114     }
6115 
6116     CloseHandle(created_mapping);
6117 }
6118 
6119 static void test_thread_security(void)
6120 {
6121     DWORD ret, i, access;
6122     HANDLE thread, dup;
6123     static const struct
6124     {
6125         int generic, mapped;
6126     } map[] =
6127     {
6128         { 0, 0 },
6129         { GENERIC_READ, STANDARD_RIGHTS_READ | THREAD_QUERY_INFORMATION | THREAD_GET_CONTEXT },
6130         { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | THREAD_SET_INFORMATION | THREAD_SET_CONTEXT | THREAD_TERMINATE | THREAD_SUSPEND_RESUME | 0x4 },
6131         { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
6132         { GENERIC_ALL, THREAD_ALL_ACCESS_NT4 }
6133     };
6134 
6135     SetLastError(0xdeadbeef);
6136     thread = CreateThread(NULL, 0, (void *)0xdeadbeef, NULL, CREATE_SUSPENDED, &ret);
6137     ok(thread != 0, "CreateThread error %d\n", GetLastError());
6138 
6139     access = get_obj_access(thread);
6140     ok(access == THREAD_ALL_ACCESS_NT4 || access == THREAD_ALL_ACCESS_VISTA, "expected THREAD_ALL_ACCESS, got %#x\n", access);
6141 
6142     for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
6143     {
6144         SetLastError( 0xdeadbeef );
6145         ret = DuplicateHandle(GetCurrentProcess(), thread, GetCurrentProcess(), &dup,
6146                               map[i].generic, FALSE, 0);
6147         ok(ret, "DuplicateHandle error %d\n", GetLastError());
6148 
6149         access = get_obj_access(dup);
6150         switch (map[i].generic)
6151         {
6152         case GENERIC_READ:
6153         case GENERIC_EXECUTE:
6154             ok(access == map[i].mapped ||
6155                access == (map[i].mapped | THREAD_QUERY_LIMITED_INFORMATION) /* Vista+ */ ||
6156                access == (map[i].mapped | THREAD_QUERY_LIMITED_INFORMATION | THREAD_RESUME) /* win8 */,
6157                "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6158             break;
6159         case GENERIC_WRITE:
6160 todo_wine
6161             ok(access == map[i].mapped ||
6162                access == (map[i].mapped | THREAD_SET_LIMITED_INFORMATION) /* Vista+ */ ||
6163                access == (map[i].mapped | THREAD_SET_LIMITED_INFORMATION | THREAD_RESUME) /* win8 */,
6164                "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6165             break;
6166         case GENERIC_ALL:
6167             ok(access == map[i].mapped || access == THREAD_ALL_ACCESS_VISTA,
6168                "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6169             break;
6170         default:
6171             ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6172             break;
6173         }
6174 
6175         CloseHandle(dup);
6176     }
6177 
6178     SetLastError( 0xdeadbeef );
6179     ret = DuplicateHandle(GetCurrentProcess(), thread, GetCurrentProcess(), &dup,
6180                           THREAD_QUERY_INFORMATION, FALSE, 0);
6181     ok(ret, "DuplicateHandle error %d\n", GetLastError());
6182     access = get_obj_access(dup);
6183     ok(access == (THREAD_QUERY_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION) /* Vista+ */ ||
6184        access == THREAD_QUERY_INFORMATION /* before Vista */,
6185        "expected THREAD_QUERY_INFORMATION|THREAD_QUERY_LIMITED_INFORMATION, got %#x\n", access);
6186     CloseHandle(dup);
6187 
6188     TerminateThread(thread, 0);
6189     CloseHandle(thread);
6190 }
6191 
6192 static void test_process_access(void)
6193 {
6194     DWORD ret, i, access;
6195     HANDLE process, dup;
6196     STARTUPINFOA sti;
6197     PROCESS_INFORMATION pi;
6198     char cmdline[] = "winver.exe";
6199     static const struct
6200     {
6201         int generic, mapped;
6202     } map[] =
6203     {
6204         { 0, 0 },
6205         { GENERIC_READ, STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ },
6206         { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION | PROCESS_SUSPEND_RESUME |
6207                          PROCESS_VM_WRITE | PROCESS_DUP_HANDLE | PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION },
6208         { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
6209         { GENERIC_ALL, PROCESS_ALL_ACCESS_NT4 }
6210     };
6211 
6212     memset(&sti, 0, sizeof(sti));
6213     sti.cb = sizeof(sti);
6214     SetLastError(0xdeadbeef);
6215     ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &sti, &pi);
6216     ok(ret, "CreateProcess() error %d\n", GetLastError());
6217 
6218     CloseHandle(pi.hThread);
6219     process = pi.hProcess;
6220 
6221     access = get_obj_access(process);
6222     ok(access == PROCESS_ALL_ACCESS_NT4 || access == PROCESS_ALL_ACCESS_VISTA, "expected PROCESS_ALL_ACCESS, got %#x\n", access);
6223 
6224     for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
6225     {
6226         SetLastError( 0xdeadbeef );
6227         ret = DuplicateHandle(GetCurrentProcess(), process, GetCurrentProcess(), &dup,
6228                               map[i].generic, FALSE, 0);
6229         ok(ret, "DuplicateHandle error %d\n", GetLastError());
6230 
6231         access = get_obj_access(dup);
6232         switch (map[i].generic)
6233         {
6234         case GENERIC_READ:
6235             ok(access == map[i].mapped || access == (map[i].mapped | PROCESS_QUERY_LIMITED_INFORMATION) /* Vista+ */,
6236                "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6237             break;
6238         case GENERIC_WRITE:
6239             ok(access == map[i].mapped ||
6240                access == (map[i].mapped | PROCESS_TERMINATE) /* before Vista */ ||
6241                access == (map[i].mapped | PROCESS_SET_LIMITED_INFORMATION) /* win8 */ ||
6242                access == (map[i].mapped | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_SET_LIMITED_INFORMATION) /* Win10 Anniversary Update */,
6243                "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6244             break;
6245         case GENERIC_EXECUTE:
6246             ok(access == map[i].mapped || access == (map[i].mapped | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE) /* Vista+ */,
6247                "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6248             break;
6249         case GENERIC_ALL:
6250             ok(access == map[i].mapped || access == PROCESS_ALL_ACCESS_VISTA,
6251                "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6252             break;
6253         default:
6254             ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6255             break;
6256         }
6257 
6258         CloseHandle(dup);
6259     }
6260 
6261     SetLastError( 0xdeadbeef );
6262     ret = DuplicateHandle(GetCurrentProcess(), process, GetCurrentProcess(), &dup,
6263                           PROCESS_QUERY_INFORMATION, FALSE, 0);
6264     ok(ret, "DuplicateHandle error %d\n", GetLastError());
6265     access = get_obj_access(dup);
6266     ok(access == (PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION) /* Vista+ */ ||
6267        access == PROCESS_QUERY_INFORMATION /* before Vista */,
6268        "expected PROCESS_QUERY_INFORMATION|PROCESS_QUERY_LIMITED_INFORMATION, got %#x\n", access);
6269     CloseHandle(dup);
6270 
6271     TerminateProcess(process, 0);
6272     CloseHandle(process);
6273 }
6274 
6275 static BOOL validate_impersonation_token(HANDLE token, DWORD *token_type)
6276 {
6277     DWORD ret, needed;
6278     TOKEN_TYPE type;
6279     SECURITY_IMPERSONATION_LEVEL sil;
6280 
6281     type = 0xdeadbeef;
6282     needed = 0;
6283     SetLastError(0xdeadbeef);
6284     ret = GetTokenInformation(token, TokenType, &type, sizeof(type), &needed);
6285     ok(ret, "GetTokenInformation error %d\n", GetLastError());
6286     ok(needed == sizeof(type), "GetTokenInformation should return required buffer length\n");
6287     ok(type == TokenPrimary || type == TokenImpersonation, "expected TokenPrimary or TokenImpersonation, got %d\n", type);
6288 
6289     *token_type = type;
6290     if (type != TokenImpersonation) return FALSE;
6291 
6292     needed = 0;
6293     SetLastError(0xdeadbeef);
6294     ret = GetTokenInformation(token, TokenImpersonationLevel, &sil, sizeof(sil), &needed);
6295     ok(ret, "GetTokenInformation error %d\n", GetLastError());
6296     ok(needed == sizeof(sil), "GetTokenInformation should return required buffer length\n");
6297     ok(sil == SecurityImpersonation, "expected SecurityImpersonation, got %d\n", sil);
6298 
6299     needed = 0xdeadbeef;
6300     SetLastError(0xdeadbeef);
6301     ret = GetTokenInformation(token, TokenDefaultDacl, NULL, 0, &needed);
6302     ok(!ret, "GetTokenInformation should fail\n");
6303     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
6304     ok(needed != 0xdeadbeef, "GetTokenInformation should return required buffer length\n");
6305     ok(needed > sizeof(TOKEN_DEFAULT_DACL), "GetTokenInformation returned empty default DACL\n");
6306 
6307     needed = 0xdeadbeef;
6308     SetLastError(0xdeadbeef);
6309     ret = GetTokenInformation(token, TokenOwner, NULL, 0, &needed);
6310     ok(!ret, "GetTokenInformation should fail\n");
6311     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
6312     ok(needed != 0xdeadbeef, "GetTokenInformation should return required buffer length\n");
6313     ok(needed > sizeof(TOKEN_OWNER), "GetTokenInformation returned empty token owner\n");
6314 
6315     needed = 0xdeadbeef;
6316     SetLastError(0xdeadbeef);
6317     ret = GetTokenInformation(token, TokenPrimaryGroup, NULL, 0, &needed);
6318     ok(!ret, "GetTokenInformation should fail\n");
6319     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
6320     ok(needed != 0xdeadbeef, "GetTokenInformation should return required buffer length\n");
6321     ok(needed > sizeof(TOKEN_PRIMARY_GROUP), "GetTokenInformation returned empty token primary group\n");
6322 
6323     return TRUE;
6324 }
6325 
6326 static void test_kernel_objects_security(void)
6327 {
6328     HANDLE token, process_token;
6329     DWORD ret, token_type;
6330 
6331     ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_QUERY, &process_token);
6332     ok(ret, "OpenProcessToken error %d\n", GetLastError());
6333 
6334     ret = validate_impersonation_token(process_token, &token_type);
6335     ok(token_type == TokenPrimary, "expected TokenPrimary, got %d\n", token_type);
6336     ok(!ret, "access token should not be an impersonation token\n");
6337 
6338     ret = DuplicateToken(process_token, SecurityImpersonation, &token);
6339     ok(ret, "DuplicateToken error %d\n", GetLastError());
6340 
6341     ret = validate_impersonation_token(token, &token_type);
6342     ok(ret, "access token should be a valid impersonation token\n");
6343     ok(token_type == TokenImpersonation, "expected TokenImpersonation, got %d\n", token_type);
6344 
6345     test_mutex_security(token);
6346     test_event_security(token);
6347     test_named_pipe_security(token);
6348     test_semaphore_security(token);
6349     test_file_security(token);
6350     test_filemap_security();
6351     test_thread_security();
6352     test_process_access();
6353     /* FIXME: test other kernel object types */
6354 
6355     CloseHandle(process_token);
6356     CloseHandle(token);
6357 }
6358 
6359 static void test_TokenIntegrityLevel(void)
6360 {
6361     TOKEN_MANDATORY_LABEL *tml;
6362     BYTE buffer[64];        /* using max. 28 byte in win7 x64 */
6363     HANDLE token;
6364     DWORD size;
6365     DWORD res;
6366     static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
6367                                                     {SECURITY_MANDATORY_HIGH_RID}};
6368     static SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
6369                                                     {SECURITY_MANDATORY_MEDIUM_RID}};
6370 
6371     SetLastError(0xdeadbeef);
6372     res = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
6373     ok(res, "got %d with %d (expected TRUE)\n", res, GetLastError());
6374 
6375     SetLastError(0xdeadbeef);
6376     res = GetTokenInformation(token, TokenIntegrityLevel, buffer, sizeof(buffer), &size);
6377 
6378     /* not supported before Vista */
6379     if (!res && ((GetLastError() == ERROR_INVALID_PARAMETER) || GetLastError() == ERROR_INVALID_FUNCTION))
6380     {
6381         win_skip("TokenIntegrityLevel not supported\n");
6382         CloseHandle(token);
6383         return;
6384     }
6385 
6386     ok(res, "got %u with %u (expected TRUE)\n", res, GetLastError());
6387     if (!res)
6388     {
6389         CloseHandle(token);
6390         return;
6391     }
6392 
6393     tml = (TOKEN_MANDATORY_LABEL*) buffer;
6394     ok(tml->Label.Attributes == (SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED),
6395         "got 0x%x (expected 0x%x)\n", tml->Label.Attributes, (SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED));
6396 
6397     ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level),
6398        "got %s (expected %s or %s)\n", debugstr_sid(tml->Label.Sid),
6399        debugstr_sid(&medium_level), debugstr_sid(&high_level));
6400 
6401     CloseHandle(token);
6402 }
6403 
6404 static void test_default_dacl_owner_sid(void)
6405 {
6406     HANDLE handle;
6407     BOOL ret, defaulted, present, found;
6408     DWORD size, index;
6409     SECURITY_DESCRIPTOR *sd;
6410     SECURITY_ATTRIBUTES sa;
6411     PSID owner;
6412     ACL *dacl;
6413     ACCESS_ALLOWED_ACE *ace;
6414 
6415     sd = HeapAlloc( GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH );
6416     ret = InitializeSecurityDescriptor( sd, SECURITY_DESCRIPTOR_REVISION );
6417     ok( ret, "error %u\n", GetLastError() );
6418 
6419     sa.nLength              = sizeof(SECURITY_ATTRIBUTES);
6420     sa.lpSecurityDescriptor = sd;
6421     sa.bInheritHandle       = FALSE;
6422     handle = CreateEventA( &sa, TRUE, TRUE, "test_event" );
6423     ok( handle != NULL, "error %u\n", GetLastError() );
6424 
6425     size = 0;
6426     ret = GetKernelObjectSecurity( handle, OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, NULL, 0, &size );
6427     ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "error %u\n", GetLastError() );
6428 
6429     sd = HeapAlloc( GetProcessHeap(), 0, size );
6430     ret = GetKernelObjectSecurity( handle, OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, sd, size, &size );
6431     ok( ret, "error %u\n", GetLastError() );
6432 
6433     owner = (void *)0xdeadbeef;
6434     defaulted = TRUE;
6435     ret = GetSecurityDescriptorOwner( sd, &owner, &defaulted );
6436     ok( ret, "error %u\n", GetLastError() );
6437     ok( owner != (void *)0xdeadbeef, "owner not set\n" );
6438     ok( !defaulted, "owner defaulted\n" );
6439 
6440     dacl = (void *)0xdeadbeef;
6441     present = FALSE;
6442     defaulted = TRUE;
6443     ret = GetSecurityDescriptorDacl( sd, &present, &dacl, &defaulted );
6444     ok( ret, "error %u\n", GetLastError() );
6445     ok( present, "dacl not present\n" );
6446     ok( dacl != (void *)0xdeadbeef, "dacl not set\n" );
6447     ok( !defaulted, "dacl defaulted\n" );
6448 
6449     index = 0;
6450     found = FALSE;
6451     while (pGetAce( dacl, index++, (void **)&ace ))
6452     {
6453         if (EqualSid( &ace->SidStart, owner )) found = TRUE;
6454     }
6455     ok( found, "owner sid not found in dacl\n" );
6456 
6457     HeapFree( GetProcessHeap(), 0, sa.lpSecurityDescriptor );
6458     HeapFree( GetProcessHeap(), 0, sd );
6459     CloseHandle( handle );
6460 }
6461 
6462 static void test_AdjustTokenPrivileges(void)
6463 {
6464     TOKEN_PRIVILEGES tp;
6465     HANDLE token;
6466     DWORD len;
6467     LUID luid;
6468     BOOL ret;
6469 
6470     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
6471         return;
6472 
6473     if (!LookupPrivilegeValueA(NULL, SE_BACKUP_NAME, &luid))
6474     {
6475         CloseHandle(token);
6476         return;
6477     }
6478 
6479     tp.PrivilegeCount = 1;
6480     tp.Privileges[0].Luid = luid;
6481     tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
6482 
6483     len = 0xdeadbeef;
6484     ret = AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, &len);
6485     ok(ret, "got %d\n", ret);
6486     ok(len == 0xdeadbeef, "got length %d\n", len);
6487 
6488     /* revert */
6489     tp.PrivilegeCount = 1;
6490     tp.Privileges[0].Luid = luid;
6491     tp.Privileges[0].Attributes = 0;
6492     ret = AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
6493     ok(ret, "got %d\n", ret);
6494 
6495     CloseHandle(token);
6496 }
6497 
6498 static void test_AddAce(void)
6499 {
6500     static SID const sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
6501 
6502     char acl_buf[1024], ace_buf[256];
6503     ACCESS_ALLOWED_ACE *ace = (ACCESS_ALLOWED_ACE*)ace_buf;
6504     PACL acl = (PACL)acl_buf;
6505     BOOL ret;
6506 
6507     memset(ace, 0, sizeof(ace_buf));
6508     ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
6509     ace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD)+sizeof(SID);
6510     memcpy(&ace->SidStart, &sidWorld, sizeof(sidWorld));
6511 
6512     ret = InitializeAcl(acl, sizeof(acl_buf), ACL_REVISION2);
6513     ok(ret, "InitializeAcl failed: %d\n", GetLastError());
6514 
6515     ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize);
6516     ok(ret, "AddAce failed: %d\n", GetLastError());
6517     ret = AddAce(acl, ACL_REVISION2, MAXDWORD, ace, ace->Header.AceSize);
6518     ok(ret, "AddAce failed: %d\n", GetLastError());
6519     ret = AddAce(acl, ACL_REVISION3, MAXDWORD, ace, ace->Header.AceSize);
6520     ok(ret, "AddAce failed: %d\n", GetLastError());
6521     ok(acl->AclRevision == ACL_REVISION3, "acl->AclRevision = %d\n", acl->AclRevision);
6522     ret = AddAce(acl, ACL_REVISION4, MAXDWORD, ace, ace->Header.AceSize);
6523     ok(ret, "AddAce failed: %d\n", GetLastError());
6524     ok(acl->AclRevision == ACL_REVISION4, "acl->AclRevision = %d\n", acl->AclRevision);
6525     ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize);
6526     ok(ret, "AddAce failed: %d\n", GetLastError());
6527     ok(acl->AclRevision == ACL_REVISION4, "acl->AclRevision = %d\n", acl->AclRevision);
6528     ret = AddAce(acl, ACL_REVISION2, MAXDWORD, ace, ace->Header.AceSize);
6529     ok(ret, "AddAce failed: %d\n", GetLastError());
6530 
6531     ret = AddAce(acl, MIN_ACL_REVISION-1, MAXDWORD, ace, ace->Header.AceSize);
6532     ok(ret, "AddAce failed: %d\n", GetLastError());
6533     /* next test succeededs but corrupts ACL */
6534     ret = AddAce(acl, MAX_ACL_REVISION+1, MAXDWORD, ace, ace->Header.AceSize);
6535     ok(ret, "AddAce failed: %d\n", GetLastError());
6536     ok(acl->AclRevision == MAX_ACL_REVISION+1, "acl->AclRevision = %d\n", acl->AclRevision);
6537     SetLastError(0xdeadbeef);
6538     ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize);
6539     ok(!ret, "AddAce succeeded\n");
6540     ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError() = %d\n", GetLastError());
6541 }
6542 
6543 static void test_AddMandatoryAce(void)
6544 {
6545     static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
6546                             {SECURITY_MANDATORY_LOW_RID}};
6547     static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
6548                                {SECURITY_MANDATORY_MEDIUM_RID}};
6549     static SID_IDENTIFIER_AUTHORITY sia_world = {SECURITY_WORLD_SID_AUTHORITY};
6550     char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
6551     SECURITY_DESCRIPTOR *sd2, *sd = (SECURITY_DESCRIPTOR *)&buffer_sd;
6552     BOOL defaulted, present, ret, found, found2;
6553     ACL_SIZE_INFORMATION acl_size_info;
6554     SYSTEM_MANDATORY_LABEL_ACE *ace;
6555     char buffer_acl[256];
6556     ACL *acl = (ACL *)&buffer_acl;
6557     SECURITY_ATTRIBUTES sa;
6558     DWORD index, size;
6559     HANDLE handle;
6560     SID *everyone;
6561     ACL *sacl;
6562 
6563     if (!pAddMandatoryAce)
6564     {
6565         win_skip("AddMandatoryAce not supported, skipping test\n");
6566         return;
6567     }
6568 
6569     ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
6570     ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
6571 
6572     sa.nLength = sizeof(sa);
6573     sa.lpSecurityDescriptor = sd;
6574     sa.bInheritHandle = FALSE;
6575 
6576     handle = CreateEventA(&sa, TRUE, TRUE, "test_event");
6577     ok(handle != NULL, "CreateEventA failed with error %u\n", GetLastError());
6578 
6579     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6580     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6581        "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
6582 
6583     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
6584     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6585     ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
6586 
6587     sacl = (void *)0xdeadbeef;
6588     present = TRUE;
6589     ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6590     ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6591     ok(!present, "SACL is present\n");
6592     ok(sacl == (void *)0xdeadbeef, "SACL is set\n");
6593 
6594     HeapFree(GetProcessHeap(), 0, sd2);
6595     CloseHandle(handle);
6596 
6597     ret = InitializeAcl(acl, 256, ACL_REVISION);
6598     ok(ret, "InitializeAcl failed with %u\n", GetLastError());
6599 
6600     SetLastError(0xdeadbeef);
6601     ret = pAddMandatoryAce(acl, ACL_REVISION, 0, 0x1234, &low_level);
6602     ok(!ret, "AddMandatoryAce succeeded\n");
6603     ok(GetLastError() == ERROR_INVALID_PARAMETER,
6604        "Expected ERROR_INVALID_PARAMETER got %u\n", GetLastError());
6605 
6606     ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level);
6607     ok(ret, "AddMandatoryAce failed with %u\n", GetLastError());
6608 
6609     index = 0;
6610     found = FALSE;
6611     while (pGetAce(acl, index++, (void **)&ace))
6612     {
6613         if (ace->Header.AceType != SYSTEM_MANDATORY_LABEL_ACE_TYPE) continue;
6614         ok(ace->Header.AceFlags == 0, "Expected flags 0, got %x\n", ace->Header.AceFlags);
6615         ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP,
6616            "Expected mask SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, got %x\n", ace->Mask);
6617         ok(EqualSid(&ace->SidStart, &low_level), "Expected low integrity level\n");
6618         found = TRUE;
6619     }
6620     ok(found, "Could not find mandatory label ace\n");
6621 
6622     ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
6623     ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6624 
6625     handle = CreateEventA(&sa, TRUE, TRUE, "test_event");
6626     ok(handle != NULL, "CreateEventA failed with error %u\n", GetLastError());
6627 
6628     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6629     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6630        "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
6631 
6632     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
6633     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6634     ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
6635 
6636     sacl = (void *)0xdeadbeef;
6637     present = FALSE;
6638     defaulted = TRUE;
6639     ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6640     ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6641     ok(present, "SACL not present\n");
6642     ok(sacl != (void *)0xdeadbeef, "SACL not set\n");
6643     ok(!defaulted, "SACL defaulted\n");
6644     ret = pGetAclInformation(sacl, &acl_size_info, sizeof(acl_size_info), AclSizeInformation);
6645     ok(ret, "GetAclInformation failed with error %u\n", GetLastError());
6646     ok(acl_size_info.AceCount == 1, "SACL contains an unexpected ACE count %u\n", acl_size_info.AceCount);
6647 
6648     ret = pGetAce(sacl, 0, (void **)&ace);
6649     ok(ret, "GetAce failed with error %u\n", GetLastError());
6650     ok (ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType);
6651     ok(!ace->Header.AceFlags, "Unexpected ACE flags %#x\n", ace->Header.AceFlags);
6652     ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "Unexpected ACE mask %#x\n", ace->Mask);
6653     ok(EqualSid(&ace->SidStart, &low_level), "Expected low integrity level\n");
6654 
6655     HeapFree(GetProcessHeap(), 0, sd2);
6656 
6657     ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level);
6658     ok(ret, "AddMandatoryAce failed with error %u\n", GetLastError());
6659 
6660     ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
6661     ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
6662 
6663     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6664     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6665        "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
6666 
6667     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
6668     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6669     ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
6670 
6671     sacl = (void *)0xdeadbeef;
6672     present = FALSE;
6673     defaulted = TRUE;
6674     ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6675     ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6676     ok(present, "SACL not present\n");
6677     ok(sacl != (void *)0xdeadbeef, "SACL not set\n");
6678     ok(sacl->AceCount == 2, "Expected 2 ACEs, got %d\n", sacl->AceCount);
6679     ok(!defaulted, "SACL defaulted\n");
6680 
6681     index = 0;
6682     found = found2 = FALSE;
6683     while (pGetAce(sacl, index++, (void **)&ace))
6684     {
6685         if (ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE)
6686         {
6687             if (EqualSid(&ace->SidStart, &low_level))
6688             {
6689                 found = TRUE;
6690                 ok(!ace->Header.AceFlags, "Expected 0 as flags, got %#x\n", ace->Header.AceFlags);
6691                 ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP,
6692                    "Expected SYSTEM_MANDATORY_LABEL_NO_WRITE_UP as mask, got %#x\n", ace->Mask);
6693             }
6694             if (EqualSid(&ace->SidStart, &medium_level))
6695             {
6696                 found2 = TRUE;
6697                 ok(!ace->Header.AceFlags, "Expected 0 as flags, got %#x\n", ace->Header.AceFlags);
6698                 ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP,
6699                    "Expected SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP as mask, got %#x\n", ace->Mask);
6700             }
6701         }
6702     }
6703     ok(found, "Could not find low mandatory label\n");
6704     ok(found2, "Could not find medium mandatory label\n");
6705 
6706     HeapFree(GetProcessHeap(), 0, sd2);
6707 
6708     ret = SetSecurityDescriptorSacl(sd, FALSE, NULL, FALSE);
6709     ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6710 
6711     ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
6712     ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
6713 
6714     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6715     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6716        "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
6717 
6718     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
6719     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6720     ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
6721 
6722     sacl = (void *)0xdeadbeef;
6723     present = FALSE;
6724     defaulted = TRUE;
6725     ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6726     ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6727     ok(present, "SACL not present\n");
6728     ok(sacl && sacl != (void *)0xdeadbeef, "SACL not set\n");
6729     ok(!defaulted, "SACL defaulted\n");
6730     ok(!sacl->AceCount, "SACL contains an unexpected ACE count %u\n", sacl->AceCount);
6731 
6732     HeapFree(GetProcessHeap(), 0, sd2);
6733 
6734     ret = InitializeAcl(acl, 256, ACL_REVISION);
6735     ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
6736 
6737     ret = pAddMandatoryAce(acl, ACL_REVISION3, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level);
6738     ok(ret, "AddMandatoryAce failed with error %u\n", GetLastError());
6739 
6740     ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
6741     ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6742 
6743     ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
6744     ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
6745 
6746     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6747     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6748        "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
6749 
6750     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
6751     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6752     ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
6753 
6754     sacl = (void *)0xdeadbeef;
6755     present = FALSE;
6756     defaulted = TRUE;
6757     ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6758     ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6759     ok(present, "SACL not present\n");
6760     ok(sacl != (void *)0xdeadbeef, "SACL not set\n");
6761     ok(sacl->AclRevision == ACL_REVISION3, "Expected revision 3, got %d\n", sacl->AclRevision);
6762     ok(!defaulted, "SACL defaulted\n");
6763 
6764     HeapFree(GetProcessHeap(), 0, sd2);
6765 
6766     ret = InitializeAcl(acl, 256, ACL_REVISION);
6767     ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
6768 
6769     ret = AllocateAndInitializeSid(&sia_world, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, (void **)&everyone);
6770     ok(ret, "AllocateAndInitializeSid failed with error %u\n", GetLastError());
6771 
6772     ret = AddAccessAllowedAce(acl, ACL_REVISION, KEY_READ, everyone);
6773     ok(ret, "AddAccessAllowedAce failed with error %u\n", GetLastError());
6774 
6775     ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
6776     ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6777 
6778     ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
6779     ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
6780 
6781     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6782     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6783        "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
6784 
6785     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
6786     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6787     ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
6788 
6789     sacl = (void *)0xdeadbeef;
6790     present = FALSE;
6791     defaulted = TRUE;
6792     ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6793     ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6794     ok(present, "SACL not present\n");
6795     ok(sacl && sacl != (void *)0xdeadbeef, "SACL not set\n");
6796     ok(!defaulted, "SACL defaulted\n");
6797     ok(!sacl->AceCount, "SACL contains an unexpected ACE count %u\n", sacl->AceCount);
6798 
6799     FreeSid(everyone);
6800     HeapFree(GetProcessHeap(), 0, sd2);
6801     CloseHandle(handle);
6802 }
6803 
6804 static void test_system_security_access(void)
6805 {
6806     static const WCHAR testkeyW[] =
6807         {'S','O','F','T','W','A','R','E','\\','W','i','n','e','\\','S','A','C','L','t','e','s','t',0};
6808     LONG res;
6809     HKEY hkey;
6810     PSECURITY_DESCRIPTOR sd;
6811     ACL *sacl;
6812     DWORD err, len = 128;
6813     TOKEN_PRIVILEGES priv, *priv_prev;
6814     HANDLE token;
6815     LUID luid;
6816     BOOL ret;
6817 
6818     if (!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &token )) return;
6819     if (!LookupPrivilegeValueA( NULL, SE_SECURITY_NAME, &luid ))
6820     {
6821         CloseHandle( token );
6822         return;
6823     }
6824 
6825     /* ACCESS_SYSTEM_SECURITY requires special privilege */
6826     res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ|ACCESS_SYSTEM_SECURITY, NULL, &hkey, NULL );
6827     if (res == ERROR_ACCESS_DENIED)
6828     {
6829         skip( "unprivileged user\n" );
6830         CloseHandle( token );
6831         return;
6832     }
6833     todo_wine ok( res == ERROR_PRIVILEGE_NOT_HELD, "got %d\n", res );
6834 
6835     priv.PrivilegeCount = 1;
6836     priv.Privileges[0].Luid = luid;
6837     priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
6838 
6839     priv_prev = HeapAlloc( GetProcessHeap(), 0, len );
6840     ret = AdjustTokenPrivileges( token, FALSE, &priv, len, priv_prev, &len );
6841     ok( ret, "got %u\n", GetLastError());
6842 
6843     res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ|ACCESS_SYSTEM_SECURITY, NULL, &hkey, NULL );
6844     if (res == ERROR_PRIVILEGE_NOT_HELD)
6845     {
6846         win_skip( "privilege not held\n" );
6847         HeapFree( GetProcessHeap(), 0, priv_prev );
6848         CloseHandle( token );
6849         return;
6850     }
6851     ok( !res, "got %d\n", res );
6852 
6853     /* restore privileges */
6854     ret = AdjustTokenPrivileges( token, FALSE, priv_prev, 0, NULL, NULL );
6855     ok( ret, "got %u\n", GetLastError() );
6856     HeapFree( GetProcessHeap(), 0, priv_prev );
6857 
6858     /* privilege is checked on access */
6859     err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
6860     todo_wine ok( err == ERROR_PRIVILEGE_NOT_HELD, "got %u\n", err );
6861 
6862     priv.PrivilegeCount = 1;
6863     priv.Privileges[0].Luid = luid;
6864     priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
6865 
6866     priv_prev = HeapAlloc( GetProcessHeap(), 0, len );
6867     ret = AdjustTokenPrivileges( token, FALSE, &priv, len, priv_prev, &len );
6868     ok( ret, "got %u\n", GetLastError());
6869 
6870     err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
6871     ok( err == ERROR_SUCCESS, "got %u\n", err );
6872     RegCloseKey( hkey );
6873     LocalFree( sd );
6874 
6875     /* handle created without ACCESS_SYSTEM_SECURITY, privilege held */
6876     res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ, NULL, &hkey, NULL );
6877     ok( res == ERROR_SUCCESS, "got %d\n", res );
6878 
6879     sd = NULL;
6880     err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
6881     todo_wine ok( err == ERROR_SUCCESS, "got %u\n", err );
6882     RegCloseKey( hkey );
6883     LocalFree( sd );
6884 
6885     /* restore privileges */
6886     ret = AdjustTokenPrivileges( token, FALSE, priv_prev, 0, NULL, NULL );
6887     ok( ret, "got %u\n", GetLastError() );
6888     HeapFree( GetProcessHeap(), 0, priv_prev );
6889 
6890     /* handle created without ACCESS_SYSTEM_SECURITY, privilege not held */
6891     res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ, NULL, &hkey, NULL );
6892     ok( res == ERROR_SUCCESS, "got %d\n", res );
6893 
6894     err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
6895     todo_wine ok( err == ERROR_PRIVILEGE_NOT_HELD, "got %u\n", err );
6896     RegCloseKey( hkey );
6897 
6898     res = RegDeleteKeyW( HKEY_LOCAL_MACHINE, testkeyW );
6899     ok( !res, "got %d\n", res );
6900     CloseHandle( token );
6901 }
6902 
6903 static void test_GetWindowsAccountDomainSid(void)
6904 {
6905     char *user, buffer1[SECURITY_MAX_SID_SIZE], buffer2[SECURITY_MAX_SID_SIZE];
6906     SID_IDENTIFIER_AUTHORITY domain_ident = { SECURITY_NT_AUTHORITY };
6907     PSID domain_sid = (PSID *)&buffer1;
6908     PSID domain_sid2 = (PSID *)&buffer2;
6909     DWORD sid_size;
6910     PSID user_sid;
6911     HANDLE token;
6912     BOOL bret = TRUE;
6913     int i;
6914 
6915     if (!pGetWindowsAccountDomainSid)
6916     {
6917         win_skip("GetWindowsAccountDomainSid not available\n");
6918         return;
6919     }
6920 
6921     if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
6922     {
6923         if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE;
6924         else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE;
6925     }
6926     if (!bret)
6927     {
6928         win_skip("Failed to get current user token\n");
6929         return;
6930     }
6931 
6932     bret = GetTokenInformation(token, TokenUser, NULL, 0, &sid_size);
6933     ok(!bret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6934        "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
6935     user = HeapAlloc(GetProcessHeap(), 0, sid_size);
6936     bret = GetTokenInformation(token, TokenUser, user, sid_size, &sid_size);
6937     ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
6938     CloseHandle(token);
6939     user_sid = ((TOKEN_USER *)user)->User.Sid;
6940 
6941     SetLastError(0xdeadbeef);
6942     bret = pGetWindowsAccountDomainSid(0, 0, 0);
6943     ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
6944     ok(GetLastError() == ERROR_INVALID_SID, "expected ERROR_INVALID_SID, got %d\n", GetLastError());
6945 
6946     SetLastError(0xdeadbeef);
6947     bret = pGetWindowsAccountDomainSid(user_sid, 0, 0);
6948     ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
6949     ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
6950 
6951     sid_size = SECURITY_MAX_SID_SIZE;
6952     SetLastError(0xdeadbeef);
6953     bret = pGetWindowsAccountDomainSid(user_sid, 0, &sid_size);
6954     ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
6955     ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
6956     ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size);
6957 
6958     SetLastError(0xdeadbeef);
6959     bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, 0);
6960     ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
6961     ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
6962 
6963     sid_size = 1;
6964     SetLastError(0xdeadbeef);
6965     bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, &sid_size);
6966     ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
6967     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
6968     ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size);
6969 
6970     sid_size = SECURITY_MAX_SID_SIZE;
6971     bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, &sid_size);
6972     ok(bret, "GetWindowsAccountDomainSid failed with error %d\n", GetLastError());
6973     ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size);
6974     InitializeSid(domain_sid2, &domain_ident, 4);
6975     for (i = 0; i < 4; i++)
6976         *GetSidSubAuthority(domain_sid2, i) = *GetSidSubAuthority(user_sid, i);
6977     ok(EqualSid(domain_sid, domain_sid2), "unexpected domain sid %s != %s\n",
6978        debugstr_sid(domain_sid), debugstr_sid(domain_sid2));
6979 
6980     HeapFree(GetProcessHeap(), 0, user);
6981 }
6982 
6983 static void test_GetSidIdentifierAuthority(void)
6984 {
6985     char buffer[SECURITY_MAX_SID_SIZE];
6986     PSID authority_sid = (PSID *)buffer;
6987     PSID_IDENTIFIER_AUTHORITY id;
6988     BOOL ret;
6989 
6990     if (!pGetSidIdentifierAuthority)
6991     {
6992         win_skip("GetSidIdentifierAuthority not available\n");
6993         return;
6994     }
6995 
6996     memset(buffer, 0xcc, sizeof(buffer));
6997     ret = IsValidSid(authority_sid);
6998     ok(!ret, "expected FALSE, got %u\n", ret);
6999 
7000     SetLastError(0xdeadbeef);
7001     id = GetSidIdentifierAuthority(authority_sid);
7002     ok(id != NULL, "got NULL pointer as identifier authority\n");
7003     ok(GetLastError() == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", GetLastError());
7004 
7005     SetLastError(0xdeadbeef);
7006     id = GetSidIdentifierAuthority(NULL);
7007     ok(id != NULL, "got NULL pointer as identifier authority\n");
7008     ok(GetLastError() == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", GetLastError());
7009 }
7010 
7011 static void test_pseudo_tokens(void)
7012 {
7013     TOKEN_STATISTICS statistics1, statistics2;
7014     HANDLE token;
7015     DWORD retlen;
7016     BOOL ret;
7017 
7018     ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
7019     ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
7020     memset(&statistics1, 0x11, sizeof(statistics1));
7021     ret = GetTokenInformation(token, TokenStatistics, &statistics1, sizeof(statistics1), &retlen);
7022     ok(ret, "GetTokenInformation failed with %u\n", GetLastError());
7023     CloseHandle(token);
7024 
7025     /* test GetCurrentProcessToken() */
7026     SetLastError(0xdeadbeef);
7027     memset(&statistics2, 0x22, sizeof(statistics2));
7028     ret = GetTokenInformation(GetCurrentProcessToken(), TokenStatistics,
7029                               &statistics2, sizeof(statistics2), &retlen);
7030     ok(ret || broken(GetLastError() == ERROR_INVALID_HANDLE),
7031        "GetTokenInformation failed with %u\n", GetLastError());
7032     if (ret)
7033         ok(!memcmp(&statistics1, &statistics2, sizeof(statistics1)), "Token statistics do not match\n");
7034     else
7035         win_skip("CurrentProcessToken not supported, skipping test\n");
7036 
7037     /* test GetCurrentThreadEffectiveToken() */
7038     SetLastError(0xdeadbeef);
7039     memset(&statistics2, 0x22, sizeof(statistics2));
7040     ret = GetTokenInformation(GetCurrentThreadEffectiveToken(), TokenStatistics,
7041                               &statistics2, sizeof(statistics2), &retlen);
7042     ok(ret || broken(GetLastError() == ERROR_INVALID_HANDLE),
7043        "GetTokenInformation failed with %u\n", GetLastError());
7044     if (ret)
7045         ok(!memcmp(&statistics1, &statistics2, sizeof(statistics1)), "Token statistics do not match\n");
7046     else
7047         win_skip("CurrentThreadEffectiveToken not supported, skipping test\n");
7048 
7049     SetLastError(0xdeadbeef);
7050     ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &token);
7051     ok(!ret, "OpenThreadToken should have failed\n");
7052     ok(GetLastError() == ERROR_NO_TOKEN, "Expected ERROR_NO_TOKEN, got %u\n", GetLastError());
7053 
7054     /* test GetCurrentThreadToken() */
7055     SetLastError(0xdeadbeef);
7056     ret = GetTokenInformation(GetCurrentThreadToken(), TokenStatistics,
7057                               &statistics2, sizeof(statistics2), &retlen);
7058     todo_wine ok(GetLastError() == ERROR_NO_TOKEN || broken(GetLastError() == ERROR_INVALID_HANDLE),
7059                  "Expected ERROR_NO_TOKEN, got %u\n", GetLastError());
7060 }
7061 
7062 static void test_maximum_allowed(void)
7063 {
7064     HANDLE (WINAPI *pCreateEventExA)(SECURITY_ATTRIBUTES *, LPCSTR, DWORD, DWORD);
7065     char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH], buffer_acl[256];
7066     SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)&buffer_sd;
7067     SECURITY_ATTRIBUTES sa;
7068     ACL *acl = (ACL *)&buffer_acl;
7069     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
7070     ACCESS_MASK mask;
7071     HANDLE handle;
7072     BOOL ret;
7073 
7074     pCreateEventExA = (void *)GetProcAddress(hkernel32, "CreateEventExA");
7075     if (!pCreateEventExA)
7076     {
7077         win_skip("CreateEventExA is not available\n");
7078         return;
7079     }
7080 
7081     ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
7082     ok(ret, "InitializeSecurityDescriptor failed with %u\n", GetLastError());
7083     ret = InitializeAcl(acl, 256, ACL_REVISION);
7084     ok(ret, "InitializeAcl failed with %u\n", GetLastError());
7085     ret = SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE);
7086     ok(ret, "SetSecurityDescriptorDacl failed with %u\n", GetLastError());
7087 
7088     sa.nLength              = sizeof(SECURITY_ATTRIBUTES);
7089     sa.lpSecurityDescriptor = sd;
7090     sa.bInheritHandle       = FALSE;
7091 
7092     handle = pCreateEventExA(&sa, NULL, 0, MAXIMUM_ALLOWED | 0x4);
7093     ok(handle != NULL, "CreateEventExA failed with error %u\n", GetLastError());
7094     mask = get_obj_access(handle);
7095     ok(mask == EVENT_ALL_ACCESS, "Expected %x, got %x\n", EVENT_ALL_ACCESS, mask);
7096     CloseHandle(handle);
7097 }
7098 
7099 static void test_token_label(void)
7100 {
7101     static SID medium_sid = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
7102                              {SECURITY_MANDATORY_MEDIUM_RID}};
7103     static SID high_sid = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
7104                            {SECURITY_MANDATORY_HIGH_RID}};
7105     SECURITY_DESCRIPTOR_CONTROL control;
7106     SYSTEM_MANDATORY_LABEL_ACE *ace;
7107     BOOL ret, present, defaulted;
7108     SECURITY_DESCRIPTOR *sd;
7109     ACL *sacl = NULL, *dacl;
7110     DWORD size, revision;
7111     HANDLE token;
7112     char *str;
7113     SID *sid;
7114 
7115     ret = OpenProcessToken(GetCurrentProcess(), READ_CONTROL | WRITE_OWNER, &token);
7116     ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
7117 
7118     ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
7119     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7120        "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
7121 
7122     sd = HeapAlloc(GetProcessHeap(), 0, size);
7123     ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size);
7124     ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7125 
7126     ret = GetSecurityDescriptorControl(sd, &control, &revision);
7127     ok(ret, "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
7128     todo_wine ok(control == (SE_SELF_RELATIVE | SE_SACL_AUTO_INHERITED | SE_SACL_PRESENT) ||
7129                  broken(control == SE_SELF_RELATIVE) /* WinXP, Win2003 */,
7130                  "Unexpected security descriptor control %#x\n", control);
7131     ok(revision == 1, "Unexpected security descriptor revision %u\n", revision);
7132 
7133     sid = (void *)0xdeadbeef;
7134     defaulted = TRUE;
7135     ret = GetSecurityDescriptorOwner(sd, (void **)&sid, &defaulted);
7136     ok(ret, "GetSecurityDescriptorOwner failed with error %u\n", GetLastError());
7137     ok(!sid, "Owner present\n");
7138     ok(!defaulted, "Owner defaulted\n");
7139 
7140     sid = (void *)0xdeadbeef;
7141     defaulted = TRUE;
7142     ret = GetSecurityDescriptorGroup(sd, (void **)&sid, &defaulted);
7143     ok(ret, "GetSecurityDescriptorGroup failed with error %u\n", GetLastError());
7144     ok(!sid, "Group present\n");
7145     ok(!defaulted, "Group defaulted\n");
7146 
7147     ret = GetSecurityDescriptorSacl(sd, &present, &sacl, &defaulted);
7148     ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
7149     ok(present || broken(!present) /* WinXP, Win2003 */, "No SACL in the security descriptor\n");
7150     ok(sacl || broken(!sacl) /* WinXP, Win2003 */, "NULL SACL in the security descriptor\n");
7151 
7152     if (present)
7153     {
7154         ok(!defaulted, "SACL defaulted\n");
7155         ok(sacl->AceCount == 1, "SACL contains an unexpected ACE count %u\n", sacl->AceCount);
7156 
7157         ret = pGetAce(sacl, 0, (void **)&ace);
7158         ok(ret, "GetAce failed with error %u\n", GetLastError());
7159 
7160         ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
7161            "Unexpected ACE type %#x\n", ace->Header.AceType);
7162         ok(!ace->Header.AceFlags, "Unexpected ACE flags %#x\n", ace->Header.AceFlags);
7163         ok(ace->Header.AceSize, "Unexpected ACE size %u\n", ace->Header.AceSize);
7164         ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "Unexpected ACE mask %#x\n", ace->Mask);
7165 
7166         sid = (SID *)&ace->SidStart;
7167         ConvertSidToStringSidA(sid, &str);
7168         ok(EqualSid(sid, &medium_sid) || EqualSid(sid, &high_sid), "Got unexpected SID %s\n", str);
7169         LocalFree(str);
7170     }
7171 
7172     ret = GetSecurityDescriptorDacl(sd, &present, &dacl, &defaulted);
7173     ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
7174     todo_wine ok(!present, "DACL present\n");
7175 
7176     HeapFree(GetProcessHeap(), 0, sd);
7177     CloseHandle(token);
7178 }
7179 
7180 static void test_token_security_descriptor(void)
7181 {
7182     static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
7183                             {SECURITY_MANDATORY_LOW_RID}};
7184     static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
7185                                {SECURITY_MANDATORY_MEDIUM_RID}};
7186     static SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
7187                              {SECURITY_MANDATORY_HIGH_RID}};
7188     char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
7189     SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)&buffer_sd, *sd2, *sd3;
7190     char buffer_acl[256], buffer[MAX_PATH];
7191     ACL *acl = (ACL *)&buffer_acl, *acl2, *acl_child, *sacl;
7192     BOOL defaulted, present, ret, found;
7193     HANDLE token, token2, token3, token4, token5, token6;
7194     EXPLICIT_ACCESSW exp_access;
7195     TOKEN_MANDATORY_LABEL *tml;
7196     BYTE buffer_integrity[64];
7197     PROCESS_INFORMATION info;
7198     DWORD size, index, retd;
7199     ACCESS_ALLOWED_ACE *ace;
7200     SECURITY_ATTRIBUTES sa;
7201     STARTUPINFOA startup;
7202     PSID psid;
7203 
7204     if (!pDuplicateTokenEx || !pConvertStringSidToSidA || !pAddAccessAllowedAceEx || !pGetAce
7205         || !pSetEntriesInAclW)
7206     {
7207         win_skip("Some functions not available\n");
7208         return;
7209     }
7210 
7211     /* Test whether we can create tokens with security descriptors */
7212     ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
7213     ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
7214 
7215     ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
7216     ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
7217 
7218     ret = InitializeAcl(acl, 256, ACL_REVISION);
7219     ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
7220 
7221     ret = pConvertStringSidToSidA("S-1-5-6", &psid);
7222     ok(ret, "ConvertStringSidToSidA failed with error %u\n", GetLastError());
7223 
7224     ret = pAddAccessAllowedAceEx(acl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, GENERIC_ALL, psid);
7225     ok(ret, "AddAccessAllowedAceEx failed with error %u\n", GetLastError());
7226 
7227     ret = SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE);
7228     ok(ret, "SetSecurityDescriptorDacl failed with error %u\n", GetLastError());
7229 
7230     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
7231     sa.lpSecurityDescriptor = sd;
7232     sa.bInheritHandle = FALSE;
7233 
7234     ret = pDuplicateTokenEx(token, MAXIMUM_ALLOWED, &sa, SecurityImpersonation, TokenImpersonation, &token2);
7235     ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
7236 
7237     ret = GetKernelObjectSecurity(token2, DACL_SECURITY_INFORMATION, NULL, 0, &size);
7238     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7239        "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
7240 
7241     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
7242     ret = GetKernelObjectSecurity(token2, DACL_SECURITY_INFORMATION, sd2, size, &size);
7243     ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7244 
7245     acl2 = (void *)0xdeadbeef;
7246     present = FALSE;
7247     defaulted = TRUE;
7248     ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted);
7249     ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
7250     ok(present, "acl2 not present\n");
7251     ok(acl2 != (void *)0xdeadbeef, "acl2 not set\n");
7252     ok(acl2->AceCount == 1, "Expected 1 ACE, got %d\n", acl2->AceCount);
7253     ok(!defaulted, "acl2 defaulted\n");
7254 
7255     ret = pGetAce(acl2, 0, (void **)&ace);
7256     ok(ret, "GetAce failed with error %u\n", GetLastError());
7257     ok(ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType);
7258     ok(EqualSid(&ace->SidStart, psid), "Expected access allowed ACE\n");
7259     ok(ace->Header.AceFlags == NO_PROPAGATE_INHERIT_ACE,
7260        "Expected NO_PROPAGATE_INHERIT_ACE as flags, got %x\n", ace->Header.AceFlags);
7261 
7262     HeapFree(GetProcessHeap(), 0, sd2);
7263 
7264     /* Duplicate token without security attributes.
7265      * Tokens do not inherit the security descriptor in DuplicateToken. */
7266     ret = pDuplicateTokenEx(token2, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenImpersonation, &token3);
7267     ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
7268 
7269     ret = GetKernelObjectSecurity(token3, DACL_SECURITY_INFORMATION, NULL, 0, &size);
7270     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7271        "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
7272 
7273     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
7274     ret = GetKernelObjectSecurity(token3, DACL_SECURITY_INFORMATION, sd2, size, &size);
7275     ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7276 
7277     acl2 = (void *)0xdeadbeef;
7278     present = FALSE;
7279     defaulted = TRUE;
7280     ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted);
7281     ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
7282     ok(present, "DACL not present\n");
7283 
7284     if (present)
7285     {
7286         ok(acl2 != (void *)0xdeadbeef, "DACL not set\n");
7287         ok(!defaulted, "DACL defaulted\n");
7288 
7289         index = 0;
7290         found = FALSE;
7291         while (pGetAce(acl2, index++, (void **)&ace))
7292         {
7293             if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE && EqualSid(&ace->SidStart, psid))
7294                 found = TRUE;
7295         }
7296         ok(!found, "Access allowed ACE was inherited\n");
7297     }
7298 
7299     HeapFree(GetProcessHeap(), 0, sd2);
7300 
7301     /* When creating a child process, the process does inherit the token of
7302      * the parent but not the DACL of the token */
7303     ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, NULL, 0, &size);
7304     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7305        "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
7306 
7307     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
7308     ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd2, size, &size);
7309     ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7310 
7311     acl2 = (void *)0xdeadbeef;
7312     present = FALSE;
7313     defaulted = TRUE;
7314     ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted);
7315     ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
7316     ok(present, "DACL not present\n");
7317     ok(acl2 != (void *)0xdeadbeef, "DACL not set\n");
7318     ok(!defaulted, "DACL defaulted\n");
7319 
7320     exp_access.grfAccessPermissions = GENERIC_ALL;
7321     exp_access.grfAccessMode = GRANT_ACCESS;
7322     exp_access.grfInheritance = NO_PROPAGATE_INHERIT_ACE;
7323     exp_access.Trustee.pMultipleTrustee = NULL;
7324     exp_access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
7325     exp_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
7326     exp_access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
7327     exp_access.Trustee.ptstrName = (void*)psid;
7328 
7329     retd = pSetEntriesInAclW(1, &exp_access, acl2, &acl_child);
7330     ok(retd == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", retd);
7331 
7332     memset(sd, 0, sizeof(buffer_sd));
7333     ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
7334     ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
7335 
7336     ret = SetSecurityDescriptorDacl(sd, TRUE, acl_child, FALSE);
7337     ok(ret, "SetSecurityDescriptorDacl failed with error %u\n", GetLastError());
7338 
7339     ret = SetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd);
7340     ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
7341 
7342     /* The security label is also not inherited */
7343     if (pAddMandatoryAce)
7344     {
7345         memset(buffer_integrity, 0, sizeof(buffer_integrity));
7346         ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
7347         ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
7348         tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
7349         ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level),
7350            "Expected medium or high integrity level\n");
7351 
7352         if (EqualSid(tml->Label.Sid, &high_level))
7353         {
7354             DWORD process_id;
7355             HANDLE process;
7356             HWND shell;
7357 
7358             /* This test tries to get a medium token and then impersonates this token. The
7359              * idea is to check whether the sd label of a newly created token depends on the
7360              * current active token or the integrity level of the newly created token. */
7361 
7362              /* Steal process token of the explorer.exe process */
7363             shell = GetShellWindow();
7364             todo_wine ok(shell != NULL, "Failed to get shell window\n");
7365             if (!shell) shell = GetDesktopWindow();  /* FIXME: Workaround for Wine */
7366             ok(GetWindowThreadProcessId(shell, &process_id),
7367                "Failed to get process id of shell window: %u\n", GetLastError());
7368             process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, process_id);
7369             ok(process != NULL, "Failed to open process: %u\n", GetLastError());
7370             ok(OpenProcessToken(process, TOKEN_ALL_ACCESS, &token4),
7371                "Failed to open process token: %u\n", GetLastError());
7372             CloseHandle(process);
7373 
7374             /* Check TokenIntegrityLevel and LABEL_SECURITY_INFORMATION of explorer.exe token */
7375             memset(buffer_integrity, 0, sizeof(buffer_integrity));
7376             ret = GetTokenInformation(token4, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
7377             ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
7378             tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
7379             ok(EqualSid(tml->Label.Sid, &medium_level), "Expected medium integrity level\n");
7380 
7381             size = 0;
7382             ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
7383             ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7384                "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
7385 
7386             sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7387             ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, sd3, size, &size);
7388             ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7389 
7390             sacl = NULL;
7391             ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted);
7392             ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
7393             ok(present, "No SACL in the security descriptor\n");
7394             ok(sacl != NULL, "NULL SACL in the security descriptor\n");
7395 
7396             if (sacl)
7397             {
7398                 ret = pGetAce(sacl, 0, (void **)&ace);
7399                 ok(ret, "GetAce failed with error %u\n", GetLastError());
7400                 ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
7401                    "Unexpected ACE type %#x\n", ace->Header.AceType);
7402                 ok(EqualSid(&ace->SidStart, &medium_level),
7403                    "Expected medium integrity level\n");
7404             }
7405 
7406             HeapFree(GetProcessHeap(), 0, sd3);
7407 
7408             /* Start child process with the explorer.exe token */
7409             memset(&startup, 0, sizeof(startup));
7410             startup.cb = sizeof(startup);
7411             startup.dwFlags = STARTF_USESHOWWINDOW;
7412             startup.wShowWindow = SW_SHOWNORMAL;
7413 
7414             sprintf(buffer, "%s tests/security.c test_token_sd_medium", myARGV[0]);
7415             ret = CreateProcessAsUserA(token4, NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info);
7416             ok(ret || GetLastError() == ERROR_PRIVILEGE_NOT_HELD,
7417                 "CreateProcess failed with error %u\n", GetLastError());
7418             if (ret)
7419             {
7420                 winetest_wait_child_process(info.hProcess);
7421                 CloseHandle(info.hProcess);
7422                 CloseHandle(info.hThread);
7423             }
7424             else
7425                 win_skip("Skipping test for creating process with medium level token\n");
7426 
7427             ret = DuplicateTokenEx(token4, 0, NULL, SecurityImpersonation, TokenImpersonation, &token5);
7428             ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
7429             ret = SetThreadToken(NULL, token5);
7430             ok(ret, "SetThreadToken failed with error %u\n", GetLastError());
7431             CloseHandle(token4);
7432 
7433             /* Restrict current process token while impersonating a medium integrity token */
7434             ret = CreateRestrictedToken(token, 0, 0, NULL, 0, NULL, 0, NULL, &token6);
7435             ok(ret, "CreateRestrictedToken failed with error %u\n", GetLastError());
7436 
7437             memset(buffer_integrity, 0, sizeof(buffer_integrity));
7438             ret = GetTokenInformation(token6, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
7439             ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
7440             tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
7441             ok(EqualSid(tml->Label.Sid, &high_level), "Expected high integrity level\n");
7442 
7443             size = 0;
7444             ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
7445             ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7446                "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
7447 
7448             sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7449             ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, sd3, size, &size);
7450             ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7451 
7452             sacl = NULL;
7453             ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted);
7454             ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
7455             ok(present, "No SACL in the security descriptor\n");
7456             ok(sacl != NULL, "NULL SACL in the security descriptor\n");
7457 
7458             if (sacl)
7459             {
7460                 ret = pGetAce(sacl, 0, (void **)&ace);
7461                 ok(ret, "GetAce failed with error %u\n", GetLastError());
7462                 ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
7463                    "Unexpected ACE type %#x\n", ace->Header.AceType);
7464                 ok(EqualSid(&ace->SidStart, &medium_level),
7465                    "Expected medium integrity level\n");
7466             }
7467 
7468             HeapFree(GetProcessHeap(), 0, sd3);
7469             RevertToSelf();
7470             CloseHandle(token5);
7471 
7472             /* Start child process with the restricted token */
7473             sprintf(buffer, "%s tests/security.c test_token_sd_restricted", myARGV[0]);
7474             ret = CreateProcessAsUserA(token6, NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info);
7475             ok(ret, "CreateProcess failed with error %u\n", GetLastError());
7476             winetest_wait_child_process(info.hProcess);
7477             CloseHandle(info.hProcess);
7478             CloseHandle(info.hThread);
7479             CloseHandle(token6);
7480 
7481             /* DuplicateTokenEx should assign security label even when SA points to empty SD */
7482             memset(sd, 0, sizeof(buffer_sd));
7483             ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
7484             ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
7485 
7486             sa.nLength = sizeof(SECURITY_ATTRIBUTES);
7487             sa.lpSecurityDescriptor = sd;
7488             sa.bInheritHandle = FALSE;
7489 
7490             ret = DuplicateTokenEx(token, 0, &sa, 0, TokenPrimary, &token6);
7491             ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
7492 
7493             size = 0;
7494             ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
7495             ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7496                "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
7497 
7498             sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7499             ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, sd3, size, &size);
7500             ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7501 
7502             sacl = NULL;
7503             ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted);
7504             ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
7505             ok(present, "No SACL in the security descriptor\n");
7506             ok(sacl != NULL, "NULL SACL in the security descriptor\n");
7507 
7508             if (sacl)
7509             {
7510                 ret = pGetAce(sacl, 0, (void **)&ace);
7511                 ok(ret, "GetAce failed with error %u\n", GetLastError());
7512                 ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
7513                    "Unexpected ACE type %#x\n", ace->Header.AceType);
7514                 ok(EqualSid(&ace->SidStart, &high_level),
7515                    "Expected high integrity level\n");
7516             }
7517 
7518             HeapFree(GetProcessHeap(), 0, sd3);
7519             CloseHandle(token6);
7520         }
7521         else
7522             skip("Skipping test, running without admin rights\n");
7523 
7524         ret = InitializeAcl(acl, 256, ACL_REVISION);
7525         ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
7526 
7527         ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level);
7528         ok(ret, "AddMandatoryAce failed with error %u\n", GetLastError());
7529 
7530         memset(sd, 0, sizeof(buffer_sd));
7531         ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
7532         ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
7533 
7534         ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
7535         ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
7536 
7537         ret = SetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd);
7538         ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
7539 
7540         /* changing the label of the security descriptor does not change the integrity level of the token itself */
7541         memset(buffer_integrity, 0, sizeof(buffer_integrity));
7542         ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
7543         ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
7544         tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
7545         ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level),
7546             "Expected medium or high integrity level\n");
7547 
7548         /* restricting / duplicating a token resets the mandatory sd label */
7549         ret = CreateRestrictedToken(token, 0, 0, NULL, 0, NULL, 0, NULL, &token4);
7550         ok(ret, "CreateRestrictedToken failed with error %u\n", GetLastError());
7551 
7552         memset(buffer_integrity, 0, sizeof(buffer_integrity));
7553         ret = GetTokenInformation(token4, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
7554         ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
7555         tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
7556         ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level),
7557             "Expected medium or high integrity level\n");
7558 
7559         size = 0;
7560         ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
7561         ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7562            "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
7563 
7564         sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7565         ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, sd3, size, &size);
7566         ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7567 
7568         ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted);
7569         ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
7570         ok(present, "No SACL in the security descriptor\n");
7571         ok(sacl != NULL, "NULL SACL in the security descriptor\n");
7572 
7573         if (sacl)
7574         {
7575             ret = pGetAce(sacl, 0, (void **)&ace);
7576             ok(ret, "GetAce failed with error %u\n", GetLastError());
7577             ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
7578                "Unexpected ACE type %#x\n", ace->Header.AceType);
7579             ok(EqualSid(&ace->SidStart, &medium_level) || EqualSid(&ace->SidStart, &high_level),
7580                "Low integrity level should not have been inherited\n");
7581         }
7582 
7583         HeapFree(GetProcessHeap(), 0, sd3);
7584         CloseHandle(token4);
7585 
7586         ret = DuplicateTokenEx(token, 0, NULL, 0, TokenPrimary, &token4);
7587         ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
7588 
7589         memset(buffer_integrity, 0, sizeof(buffer_integrity));
7590         ret = GetTokenInformation(token4, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
7591         ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
7592         tml = (TOKEN_MANDATORY_LABEL*) buffer_integrity;
7593         ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level),
7594             "Expected medium or high integrity level\n");
7595 
7596         size = 0;
7597         ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
7598         ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7599            "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
7600 
7601         sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7602         ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, sd3, size, &size);
7603         ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7604 
7605         sacl = NULL;
7606         ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted);
7607         ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
7608         ok(present, "No SACL in the security descriptor\n");
7609         ok(sacl != NULL, "NULL SACL in the security descriptor\n");
7610 
7611         if (sacl)
7612         {
7613             ret = pGetAce(sacl, 0, (void **)&ace);
7614             ok(ret, "GetAce failed with error %u\n", GetLastError());
7615             ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
7616                "Unexpected ACE type %#x\n", ace->Header.AceType);
7617             ok(EqualSid(&ace->SidStart, &medium_level) || EqualSid(&ace->SidStart, &high_level),
7618                "Low integrity level should not have been inherited\n");
7619         }
7620 
7621         HeapFree(GetProcessHeap(), 0, sd3);
7622         CloseHandle(token4);
7623     }
7624     else
7625         win_skip("SYSTEM_MANDATORY_LABEL not supported\n");
7626 
7627     /* Start child process with our modified token */
7628     memset(&startup, 0, sizeof(startup));
7629     startup.cb = sizeof(startup);
7630     startup.dwFlags = STARTF_USESHOWWINDOW;
7631     startup.wShowWindow = SW_SHOWNORMAL;
7632 
7633     sprintf(buffer, "%s tests/security.c test_token_sd", myARGV[0]);
7634     ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info);
7635     ok(ret, "CreateProcess failed with error %u\n", GetLastError());
7636     winetest_wait_child_process(info.hProcess);
7637     CloseHandle(info.hProcess);
7638     CloseHandle(info.hThread);
7639 
7640     LocalFree(acl_child);
7641     LocalFree(psid);
7642 
7643     CloseHandle(token3);
7644     CloseHandle(token2);
7645     CloseHandle(token);
7646 }
7647 
7648 static void test_child_token_sd(void)
7649 {
7650     static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
7651                             {SECURITY_MANDATORY_LOW_RID}};
7652     SYSTEM_MANDATORY_LABEL_ACE *ace_label;
7653     BOOL ret, present, defaulted;
7654     ACCESS_ALLOWED_ACE *acc_ace;
7655     SECURITY_DESCRIPTOR *sd;
7656     DWORD size, i;
7657     HANDLE token;
7658     PSID psid;
7659     ACL *acl;
7660 
7661     ret = pConvertStringSidToSidA("S-1-5-6", &psid);
7662     ok(ret, "ConvertStringSidToSidA failed with error %u\n", GetLastError());
7663 
7664     ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
7665     ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
7666 
7667     ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, NULL, 0, &size);
7668     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7669        "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
7670 
7671     sd = HeapAlloc(GetProcessHeap(), 0, size);
7672     ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd, size, &size);
7673     ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7674 
7675     acl = NULL;
7676     present = FALSE;
7677     defaulted = TRUE;
7678     ret = GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted);
7679     ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
7680     ok(present, "DACL not present\n");
7681     ok(acl && acl != (void *)0xdeadbeef, "Got invalid DACL\n");
7682     ok(!defaulted, "DACL defaulted\n");
7683 
7684     ok(acl->AceCount, "Expected at least one ACE\n");
7685     for (i = 0; i < acl->AceCount; i++)
7686     {
7687         ok(pGetAce(acl, i, (void **)&acc_ace), "GetAce failed with error %u\n", GetLastError());
7688         ok(acc_ace->Header.AceType != ACCESS_ALLOWED_ACE_TYPE || !EqualSid(&acc_ace->SidStart, psid),
7689            "ACE inherited from the parent\n");
7690     }
7691 
7692     LocalFree(psid);
7693     HeapFree(GetProcessHeap(), 0, sd);
7694 
7695     if (!pAddMandatoryAce)
7696     {
7697         win_skip("SYSTEM_MANDATORY_LABEL not supported\n");
7698         return;
7699     }
7700 
7701     ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
7702     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7703        "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
7704 
7705     sd = HeapAlloc(GetProcessHeap(), 0, size);
7706     ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size);
7707     ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7708 
7709     acl = NULL;
7710     present = FALSE;
7711     defaulted = TRUE;
7712     ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted);
7713     ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
7714     ok(present, "SACL not present\n");
7715     ok(acl && acl != (void *)0xdeadbeef, "Got invalid SACL\n");
7716     ok(!defaulted, "SACL defaulted\n");
7717     ok(acl->AceCount == 1, "Expected exactly one ACE\n");
7718     ret = pGetAce(acl, 0, (void **)&ace_label);
7719     ok(ret, "GetAce failed with error %u\n", GetLastError());
7720     ok(ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
7721        "Unexpected ACE type %#x\n", ace_label->Header.AceType);
7722     ok(!EqualSid(&ace_label->SidStart, &low_level),
7723        "Low integrity level should not have been inherited\n");
7724 
7725     HeapFree(GetProcessHeap(), 0, sd);
7726 }
7727 
7728 static void test_child_token_sd_restricted(void)
7729 {
7730     static SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
7731                              {SECURITY_MANDATORY_HIGH_RID}};
7732     SYSTEM_MANDATORY_LABEL_ACE *ace_label;
7733     BOOL ret, present, defaulted;
7734     TOKEN_MANDATORY_LABEL *tml;
7735     BYTE buffer_integrity[64];
7736     SECURITY_DESCRIPTOR *sd;
7737     HANDLE token;
7738     DWORD size;
7739     ACL *acl;
7740 
7741     if (!pAddMandatoryAce)
7742     {
7743         win_skip("SYSTEM_MANDATORY_LABEL not supported\n");
7744         return;
7745     }
7746 
7747     ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
7748     ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
7749 
7750     ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
7751     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7752        "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
7753 
7754     sd = HeapAlloc(GetProcessHeap(), 0, size);
7755     ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size);
7756     ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7757 
7758     acl = NULL;
7759     present = FALSE;
7760     defaulted = TRUE;
7761     ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted);
7762     ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
7763     ok(present, "SACL not present\n");
7764     ok(acl && acl != (void *)0xdeadbeef, "Got invalid SACL\n");
7765     ok(!defaulted, "SACL defaulted\n");
7766     ok(acl->AceCount == 1, "Expected exactly one ACE\n");
7767     ret = pGetAce(acl, 0, (void **)&ace_label);
7768     ok(ret, "GetAce failed with error %u\n", GetLastError());
7769     ok(ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
7770        "Unexpected ACE type %#x\n", ace_label->Header.AceType);
7771     ok(EqualSid(&ace_label->SidStart, &high_level),
7772        "Expected high integrity level\n");
7773 
7774     memset(buffer_integrity, 0, sizeof(buffer_integrity));
7775     ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
7776     ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
7777     tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
7778     ok(EqualSid(tml->Label.Sid, &high_level), "Expected high integrity level\n");
7779 
7780     HeapFree(GetProcessHeap(), 0, sd);
7781 }
7782 
7783 static void test_child_token_sd_medium(void)
7784 {
7785     static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
7786                                {SECURITY_MANDATORY_MEDIUM_RID}};
7787     SYSTEM_MANDATORY_LABEL_ACE *ace_label;
7788     BOOL ret, present, defaulted;
7789     TOKEN_MANDATORY_LABEL *tml;
7790     BYTE buffer_integrity[64];
7791     SECURITY_DESCRIPTOR *sd;
7792     HANDLE token;
7793     DWORD size;
7794     ACL *acl;
7795 
7796     if (!pAddMandatoryAce)
7797     {
7798         win_skip("SYSTEM_MANDATORY_LABEL not supported\n");
7799         return;
7800     }
7801 
7802     ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
7803     ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
7804 
7805     ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
7806     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7807        "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
7808 
7809     sd = HeapAlloc(GetProcessHeap(), 0, size);
7810     ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size);
7811     ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7812 
7813     acl = NULL;
7814     present = FALSE;
7815     defaulted = TRUE;
7816     ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted);
7817     ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
7818     ok(present, "SACL not present\n");
7819     ok(acl && acl != (void *)0xdeadbeef, "Got invalid SACL\n");
7820     ok(!defaulted, "SACL defaulted\n");
7821     ok(acl->AceCount == 1, "Expected exactly one ACE\n");
7822     ret = pGetAce(acl, 0, (void **)&ace_label);
7823     ok(ret, "GetAce failed with error %u\n", GetLastError());
7824     ok(ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
7825        "Unexpected ACE type %#x\n", ace_label->Header.AceType);
7826     ok(EqualSid(&ace_label->SidStart, &medium_level),
7827        "Expected medium integrity level\n");
7828 
7829     memset(buffer_integrity, 0, sizeof(buffer_integrity));
7830     ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
7831     ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
7832     tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
7833     ok(EqualSid(tml->Label.Sid, &medium_level), "Expected medium integrity level\n");
7834 
7835     HeapFree(GetProcessHeap(), 0, sd);
7836 }
7837 
7838 static void test_GetExplicitEntriesFromAclW(void)
7839 {
7840     static const WCHAR wszCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'};
7841     SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
7842     SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
7843     PSID everyone_sid = NULL, users_sid = NULL;
7844     EXPLICIT_ACCESSW access;
7845     EXPLICIT_ACCESSW *access2;
7846     PACL new_acl, old_acl = NULL;
7847     ULONG count;
7848     DWORD res;
7849 
7850     if (!pGetExplicitEntriesFromAclW)
7851     {
7852         win_skip("GetExplicitEntriesFromAclW is not available\n");
7853         return;
7854     }
7855 
7856     if (!pSetEntriesInAclW)
7857     {
7858         win_skip("SetEntriesInAclW is not available\n");
7859         return;
7860     }
7861 
7862     old_acl = HeapAlloc(GetProcessHeap(), 0, 256);
7863     res = InitializeAcl(old_acl, 256, ACL_REVISION);
7864     if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
7865     {
7866         win_skip("ACLs not implemented - skipping tests\n");
7867         HeapFree(GetProcessHeap(), 0, old_acl);
7868         return;
7869     }
7870     ok(res, "InitializeAcl failed with error %d\n", GetLastError());
7871 
7872     res = AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyone_sid);
7873     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
7874 
7875     res = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
7876                                    DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &users_sid);
7877     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
7878 
7879     res = AddAccessAllowedAce(old_acl, ACL_REVISION, KEY_READ, users_sid);
7880     ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
7881 
7882     access2 = NULL;
7883     res = pGetExplicitEntriesFromAclW(old_acl, &count, &access2);
7884     ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
7885     ok(count == 1, "Expected count == 1, got %d\n", count);
7886     ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
7887     ok(access2[0].grfAccessPermissions == KEY_READ, "Expected KEY_READ, got %d\n", access2[0].grfAccessPermissions);
7888     ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
7889     ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
7890     ok(EqualSid(access2[0].Trustee.ptstrName, users_sid), "Expected equal SIDs\n");
7891     LocalFree(access2);
7892 
7893     access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
7894     access.Trustee.pMultipleTrustee = NULL;
7895 
7896     access.grfAccessPermissions = KEY_WRITE;
7897     access.grfAccessMode = GRANT_ACCESS;
7898     access.grfInheritance = NO_INHERITANCE;
7899     access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
7900     access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
7901     access.Trustee.ptstrName = everyone_sid;
7902     res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
7903     ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
7904     ok(new_acl != NULL, "returned acl was NULL\n");
7905 
7906     access2 = NULL;
7907     res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
7908     ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
7909     ok(count == 2, "Expected count == 2, got %d\n", count);
7910     ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
7911     ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions);
7912     ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
7913        "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
7914     ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
7915     ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
7916     ok(EqualSid(access2[0].Trustee.ptstrName, everyone_sid), "Expected equal SIDs\n");
7917     LocalFree(access2);
7918     LocalFree(new_acl);
7919 
7920     access.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
7921     res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
7922     ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
7923     ok(new_acl != NULL, "returned acl was NULL\n");
7924 
7925     access2 = NULL;
7926     res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
7927     ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
7928     ok(count == 2, "Expected count == 2, got %d\n", count);
7929     ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
7930     ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions);
7931     ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
7932        "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
7933     ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
7934     ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
7935     ok(EqualSid(access2[0].Trustee.ptstrName, everyone_sid), "Expected equal SIDs\n");
7936     LocalFree(access2);
7937     LocalFree(new_acl);
7938 
7939     access.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
7940     access.Trustee.ptstrName = (LPWSTR)wszCurrentUser;
7941     res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
7942     ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
7943     ok(new_acl != NULL, "returned acl was NULL\n");
7944 
7945     access2 = NULL;
7946     res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
7947     ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
7948     ok(count == 2, "Expected count == 2, got %d\n", count);
7949     ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
7950     ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions);
7951     ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
7952        "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
7953     ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
7954     ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
7955     LocalFree(access2);
7956     LocalFree(new_acl);
7957 
7958     access.grfAccessMode = REVOKE_ACCESS;
7959     access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
7960     access.Trustee.ptstrName = users_sid;
7961     res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
7962     ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
7963     ok(new_acl != NULL, "returned acl was NULL\n");
7964 
7965     access2 = (void *)0xdeadbeef;
7966     res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
7967     ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
7968     ok(count == 0, "Expected count == 0, got %d\n", count);
7969     ok(access2 == NULL, "access2 was not NULL\n");
7970     LocalFree(new_acl);
7971 
7972     FreeSid(users_sid);
7973     FreeSid(everyone_sid);
7974     HeapFree(GetProcessHeap(), 0, old_acl);
7975 }
7976 
7977 static void test_BuildSecurityDescriptorW(void)
7978 {
7979     SECURITY_DESCRIPTOR old_sd, *new_sd, *rel_sd;
7980     ULONG new_sd_size;
7981     DWORD buf_size;
7982     char buf[1024];
7983     BOOL success;
7984     DWORD ret;
7985 
7986     InitializeSecurityDescriptor(&old_sd, SECURITY_DESCRIPTOR_REVISION);
7987 
7988     buf_size = sizeof(buf);
7989     rel_sd = (SECURITY_DESCRIPTOR *)buf;
7990     success = MakeSelfRelativeSD(&old_sd, rel_sd, &buf_size);
7991     ok(success, "MakeSelfRelativeSD failed with %u\n", GetLastError());
7992 
7993     new_sd = NULL;
7994     new_sd_size = 0;
7995     ret = BuildSecurityDescriptorW(NULL, NULL, 0, NULL, 0, NULL, NULL, &new_sd_size, (void **)&new_sd);
7996     ok(ret == ERROR_SUCCESS, "BuildSecurityDescriptor failed with %u\n", ret);
7997     ok(new_sd != NULL, "expected new_sd != NULL\n");
7998     ok(new_sd_size == sizeof(old_sd), "expected new_sd_size == sizeof(old_sd), got %u\n", new_sd_size);
7999     LocalFree(new_sd);
8000 
8001     new_sd = (void *)0xdeadbeef;
8002     ret = BuildSecurityDescriptorW(NULL, NULL, 0, NULL, 0, NULL, &old_sd, &new_sd_size, (void **)&new_sd);
8003     ok(ret == ERROR_INVALID_SECURITY_DESCR, "expected ERROR_INVALID_SECURITY_DESCR, got %u\n", ret);
8004     ok(new_sd == (void *)0xdeadbeef, "expected new_sd == 0xdeadbeef, got %p\n", new_sd);
8005 
8006     new_sd = NULL;
8007     new_sd_size = 0;
8008     ret = BuildSecurityDescriptorW(NULL, NULL, 0, NULL, 0, NULL, rel_sd, &new_sd_size, (void **)&new_sd);
8009     ok(ret == ERROR_SUCCESS, "BuildSecurityDescriptor failed with %u\n", ret);
8010     ok(new_sd != NULL, "expected new_sd != NULL\n");
8011     ok(new_sd_size == sizeof(old_sd), "expected new_sd_size == sizeof(old_sd), got %u\n", new_sd_size);
8012     LocalFree(new_sd);
8013 }
8014 
8015 START_TEST(security)
8016 {
8017     init();
8018     if (!hmod) return;
8019 
8020     if (myARGC >= 3)
8021     {
8022         if (!strcmp(myARGV[2], "test_token_sd"))
8023             test_child_token_sd();
8024         else if (!strcmp(myARGV[2], "test_token_sd_restricted"))
8025             test_child_token_sd_restricted();
8026         else if (!strcmp(myARGV[2], "test_token_sd_medium"))
8027             test_child_token_sd_medium();
8028         else
8029             test_process_security_child();
8030         return;
8031     }
8032     test_kernel_objects_security();
8033     test_sid();
8034     test_trustee();
8035     test_luid();
8036     test_CreateWellKnownSid();
8037     test_FileSecurity();
8038     test_AccessCheck();
8039     test_token_attr();
8040     test_GetTokenInformation();
8041     test_LookupAccountSid();
8042     test_LookupAccountName();
8043     test_security_descriptor();
8044     test_process_security();
8045     test_impersonation_level();
8046     test_SetEntriesInAclW();
8047     test_SetEntriesInAclA();
8048     test_CreateDirectoryA();
8049     test_GetNamedSecurityInfoA();
8050     test_ConvertStringSecurityDescriptor();
8051     test_ConvertSecurityDescriptorToString();
8052     test_PrivateObjectSecurity();
8053     test_acls();
8054     test_GetWindowsAccountDomainSid();
8055     test_GetSecurityInfo();
8056     test_GetSidSubAuthority();
8057     test_CheckTokenMembership();
8058     test_EqualSid();
8059     test_GetUserNameA();
8060     test_GetUserNameW();
8061     test_CreateRestrictedToken();
8062     test_TokenIntegrityLevel();
8063     test_default_dacl_owner_sid();
8064     test_AdjustTokenPrivileges();
8065     test_AddAce();
8066     test_AddMandatoryAce();
8067     test_system_security_access();
8068     test_GetSidIdentifierAuthority();
8069     test_pseudo_tokens();
8070     test_maximum_allowed();
8071     test_token_label();
8072     test_GetExplicitEntriesFromAclW();
8073     test_BuildSecurityDescriptorW();
8074 
8075     /* Must be the last test, modifies process token */
8076     test_token_security_descriptor();
8077 }
8078