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