advapi32: LookupAccountNameW() - add got clause to test.
[wine] / dlls / advapi32 / tests / security.c
1 /*
2  * Unit tests for security functions
3  *
4  * Copyright (c) 2004 Mike McCormack
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winerror.h"
29 #include "aclapi.h"
30 #include "winnt.h"
31 #include "sddl.h"
32 #include "ntsecapi.h"
33 #include "lmcons.h"
34
35 #include "wine/test.h"
36
37 /* copied from Wine winternl.h - not included in the Windows SDK */
38 typedef enum _OBJECT_INFORMATION_CLASS {
39     ObjectBasicInformation,
40     ObjectNameInformation,
41     ObjectTypeInformation,
42     ObjectAllInformation,
43     ObjectDataInformation
44 } OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;
45
46 typedef struct _OBJECT_BASIC_INFORMATION {
47     ULONG  Attributes;
48     ACCESS_MASK  GrantedAccess;
49     ULONG  HandleCount;
50     ULONG  PointerCount;
51     ULONG  PagedPoolUsage;
52     ULONG  NonPagedPoolUsage;
53     ULONG  Reserved[3];
54     ULONG  NameInformationLength;
55     ULONG  TypeInformationLength;
56     ULONG  SecurityDescriptorLength;
57     LARGE_INTEGER  CreateTime;
58 } OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION;
59
60 #define expect_eq(expr, value, type, format) { type ret = expr; ok((value) == ret, #expr " expected " format "  got " format "\n", (value), (ret)); }
61
62 static BOOL (WINAPI *pAddAccessAllowedAceEx)(PACL, DWORD, DWORD, DWORD, PSID);
63 static BOOL (WINAPI *pAddAccessDeniedAceEx)(PACL, DWORD, DWORD, DWORD, PSID);
64 static BOOL (WINAPI *pAddAuditAccessAceEx)(PACL, DWORD, DWORD, DWORD, PSID, BOOL, BOOL);
65 typedef VOID (WINAPI *fnBuildTrusteeWithSidA)( PTRUSTEEA pTrustee, PSID pSid );
66 typedef VOID (WINAPI *fnBuildTrusteeWithNameA)( PTRUSTEEA pTrustee, LPSTR pName );
67 typedef VOID (WINAPI *fnBuildTrusteeWithObjectsAndNameA)( PTRUSTEEA pTrustee,
68                                                           POBJECTS_AND_NAME_A pObjName,
69                                                           SE_OBJECT_TYPE ObjectType,
70                                                           LPSTR ObjectTypeName,
71                                                           LPSTR InheritedObjectTypeName,
72                                                           LPSTR Name );
73 typedef VOID (WINAPI *fnBuildTrusteeWithObjectsAndSidA)( PTRUSTEEA pTrustee,
74                                                          POBJECTS_AND_SID pObjSid,
75                                                          GUID* pObjectGuid,
76                                                          GUID* pInheritedObjectGuid,
77                                                          PSID pSid );
78 typedef LPSTR (WINAPI *fnGetTrusteeNameA)( PTRUSTEEA pTrustee );
79 typedef BOOL (WINAPI *fnMakeSelfRelativeSD)( PSECURITY_DESCRIPTOR, PSECURITY_DESCRIPTOR, LPDWORD );
80 typedef BOOL (WINAPI *fnConvertSidToStringSidA)( PSID pSid, LPSTR *str );
81 typedef BOOL (WINAPI *fnConvertStringSidToSidA)( LPCSTR str, PSID pSid );
82 static BOOL (WINAPI *pConvertStringSecurityDescriptorToSecurityDescriptorA)(LPCSTR, DWORD,
83                                                                             PSECURITY_DESCRIPTOR*, PULONG );
84 static BOOL (WINAPI *pConvertStringSecurityDescriptorToSecurityDescriptorW)(LPCWSTR, DWORD,
85                                                                             PSECURITY_DESCRIPTOR*, PULONG );
86 static BOOL (WINAPI *pConvertSecurityDescriptorToStringSecurityDescriptorA)(PSECURITY_DESCRIPTOR, DWORD,
87                                                                             SECURITY_INFORMATION, LPSTR *, PULONG );
88 typedef BOOL (WINAPI *fnGetFileSecurityA)(LPCSTR, SECURITY_INFORMATION,
89                                           PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
90 static DWORD (WINAPI *pGetNamedSecurityInfoA)(LPSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION,
91                                               PSID*, PSID*, PACL*, PACL*,
92                                               PSECURITY_DESCRIPTOR*);
93 typedef DWORD (WINAPI *fnRtlAdjustPrivilege)(ULONG,BOOLEAN,BOOLEAN,PBOOLEAN);
94 typedef BOOL (WINAPI *fnCreateWellKnownSid)(WELL_KNOWN_SID_TYPE,PSID,PSID,DWORD*);
95 typedef BOOL (WINAPI *fnDuplicateTokenEx)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES,
96                                         SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,PHANDLE);
97
98 typedef NTSTATUS (WINAPI *fnLsaQueryInformationPolicy)(LSA_HANDLE,POLICY_INFORMATION_CLASS,PVOID*);
99 typedef NTSTATUS (WINAPI *fnLsaClose)(LSA_HANDLE);
100 typedef NTSTATUS (WINAPI *fnLsaFreeMemory)(PVOID);
101 typedef NTSTATUS (WINAPI *fnLsaOpenPolicy)(PLSA_UNICODE_STRING,PLSA_OBJECT_ATTRIBUTES,ACCESS_MASK,PLSA_HANDLE);
102 static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,ULONG,PULONG);
103 static DWORD (WINAPI *pSetEntriesInAclW)(ULONG, PEXPLICIT_ACCESSW, PACL, PACL*);
104 static BOOL (WINAPI *pSetSecurityDescriptorControl)(PSECURITY_DESCRIPTOR, SECURITY_DESCRIPTOR_CONTROL,
105                                                     SECURITY_DESCRIPTOR_CONTROL);
106 static DWORD (WINAPI *pGetSecurityInfo)(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
107                                         PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*);
108
109 static HMODULE hmod;
110 static int     myARGC;
111 static char**  myARGV;
112
113 fnBuildTrusteeWithSidA   pBuildTrusteeWithSidA;
114 fnBuildTrusteeWithNameA  pBuildTrusteeWithNameA;
115 fnBuildTrusteeWithObjectsAndNameA pBuildTrusteeWithObjectsAndNameA;
116 fnBuildTrusteeWithObjectsAndSidA pBuildTrusteeWithObjectsAndSidA;
117 fnGetTrusteeNameA pGetTrusteeNameA;
118 fnMakeSelfRelativeSD pMakeSelfRelativeSD;
119 fnConvertSidToStringSidA pConvertSidToStringSidA;
120 fnConvertStringSidToSidA pConvertStringSidToSidA;
121 fnGetFileSecurityA pGetFileSecurityA;
122 fnRtlAdjustPrivilege pRtlAdjustPrivilege;
123 fnCreateWellKnownSid pCreateWellKnownSid;
124 fnDuplicateTokenEx pDuplicateTokenEx;
125 fnLsaQueryInformationPolicy pLsaQueryInformationPolicy;
126 fnLsaClose pLsaClose;
127 fnLsaFreeMemory pLsaFreeMemory;
128 fnLsaOpenPolicy pLsaOpenPolicy;
129
130 struct sidRef
131 {
132     SID_IDENTIFIER_AUTHORITY auth;
133     const char *refStr;
134 };
135
136 static void init(void)
137 {
138     HMODULE hntdll;
139
140     hntdll = GetModuleHandleA("ntdll.dll");
141     pNtQueryObject = (void *)GetProcAddress( hntdll, "NtQueryObject" );
142
143     hmod = GetModuleHandle("advapi32.dll");
144     pAddAccessAllowedAceEx = (void *)GetProcAddress(hmod, "AddAccessAllowedAceEx");
145     pAddAccessDeniedAceEx = (void *)GetProcAddress(hmod, "AddAccessDeniedAceEx");
146     pAddAuditAccessAceEx = (void *)GetProcAddress(hmod, "AddAuditAccessAceEx");
147     pConvertStringSecurityDescriptorToSecurityDescriptorA =
148         (void *)GetProcAddress(hmod, "ConvertStringSecurityDescriptorToSecurityDescriptorA" );
149     pConvertStringSecurityDescriptorToSecurityDescriptorW =
150         (void *)GetProcAddress(hmod, "ConvertStringSecurityDescriptorToSecurityDescriptorW" );
151     pConvertSecurityDescriptorToStringSecurityDescriptorA =
152         (void *)GetProcAddress(hmod, "ConvertSecurityDescriptorToStringSecurityDescriptorA" );
153     pCreateWellKnownSid = (fnCreateWellKnownSid)GetProcAddress( hmod, "CreateWellKnownSid" );
154     pGetNamedSecurityInfoA = (void *)GetProcAddress(hmod, "GetNamedSecurityInfoA");
155     pMakeSelfRelativeSD = (void *)GetProcAddress(hmod, "MakeSelfRelativeSD");
156     pSetEntriesInAclW = (void *)GetProcAddress(hmod, "SetEntriesInAclW");
157     pSetSecurityDescriptorControl = (void *)GetProcAddress(hmod, "SetSecurityDescriptorControl");
158     pGetSecurityInfo = (void *)GetProcAddress(hmod, "GetSecurityInfo");
159
160     myARGC = winetest_get_mainargs( &myARGV );
161 }
162
163 static void test_str_sid(const char *str_sid)
164 {
165     PSID psid;
166     char *temp;
167
168     if (pConvertStringSidToSidA(str_sid, &psid))
169     {
170         if (pConvertSidToStringSidA(psid, &temp))
171         {
172             trace(" %s: %s\n", str_sid, temp);
173             LocalFree(temp);
174         }
175         LocalFree(psid);
176     }
177     else
178     {
179         if (GetLastError() != ERROR_INVALID_SID)
180             trace(" %s: couldn't be converted, returned %d\n", str_sid, GetLastError());
181         else
182             trace(" %s: couldn't be converted\n", str_sid);
183     }
184 }
185
186 static void test_sid(void)
187 {
188     struct sidRef refs[] = {
189      { { {0x00,0x00,0x33,0x44,0x55,0x66} }, "S-1-860116326-1" },
190      { { {0x00,0x00,0x01,0x02,0x03,0x04} }, "S-1-16909060-1"  },
191      { { {0x00,0x00,0x00,0x01,0x02,0x03} }, "S-1-66051-1"     },
192      { { {0x00,0x00,0x00,0x00,0x01,0x02} }, "S-1-258-1"       },
193      { { {0x00,0x00,0x00,0x00,0x00,0x02} }, "S-1-2-1"         },
194      { { {0x00,0x00,0x00,0x00,0x00,0x0c} }, "S-1-12-1"        },
195     };
196     const char noSubAuthStr[] = "S-1-5";
197     unsigned int i;
198     PSID psid = NULL;
199     SID *pisid;
200     BOOL r;
201     LPSTR str = NULL;
202
203     pConvertSidToStringSidA = (fnConvertSidToStringSidA)
204                     GetProcAddress( hmod, "ConvertSidToStringSidA" );
205     if( !pConvertSidToStringSidA )
206         return;
207     pConvertStringSidToSidA = (fnConvertStringSidToSidA)
208                     GetProcAddress( hmod, "ConvertStringSidToSidA" );
209     if( !pConvertStringSidToSidA )
210         return;
211
212     r = pConvertStringSidToSidA( NULL, NULL );
213     ok( !r, "expected failure with NULL parameters\n" );
214     if( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED )
215         return;
216     ok( GetLastError() == ERROR_INVALID_PARAMETER,
217      "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n",
218      GetLastError() );
219
220     r = pConvertStringSidToSidA( refs[0].refStr, NULL );
221     ok( !r && GetLastError() == ERROR_INVALID_PARAMETER,
222      "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n",
223      GetLastError() );
224
225     r = pConvertStringSidToSidA( NULL, &str );
226     ok( !r && GetLastError() == ERROR_INVALID_PARAMETER,
227      "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n",
228      GetLastError() );
229
230     r = pConvertStringSidToSidA( noSubAuthStr, &psid );
231     ok( !r,
232      "expected failure with no sub authorities\n" );
233     ok( GetLastError() == ERROR_INVALID_SID,
234      "expected GetLastError() is ERROR_INVALID_SID, got %d\n",
235      GetLastError() );
236
237     ok(pConvertStringSidToSidA("S-1-5-21-93476-23408-4576", &psid), "ConvertStringSidToSidA failed\n");
238     pisid = (SID *)psid;
239     ok(pisid->SubAuthorityCount == 4, "Invalid sub authority count - expected 4, got %d\n", pisid->SubAuthorityCount);
240     ok(pisid->SubAuthority[0] == 21, "Invalid subauthority 0 - expceted 21, got %d\n", pisid->SubAuthority[0]);
241     ok(pisid->SubAuthority[3] == 4576, "Invalid subauthority 0 - expceted 4576, got %d\n", pisid->SubAuthority[3]);
242     LocalFree(str);
243
244     for( i = 0; i < sizeof(refs) / sizeof(refs[0]); i++ )
245     {
246         PISID pisid;
247
248         r = AllocateAndInitializeSid( &refs[i].auth, 1,1,0,0,0,0,0,0,0,
249          &psid );
250         ok( r, "failed to allocate sid\n" );
251         r = pConvertSidToStringSidA( psid, &str );
252         ok( r, "failed to convert sid\n" );
253         if (r)
254         {
255             ok( !strcmp( str, refs[i].refStr ),
256                 "incorrect sid, expected %s, got %s\n", refs[i].refStr, str );
257             LocalFree( str );
258         }
259         if( psid )
260             FreeSid( psid );
261
262         r = pConvertStringSidToSidA( refs[i].refStr, &psid );
263         ok( r, "failed to parse sid string\n" );
264         pisid = (PISID)psid;
265         ok( pisid &&
266          !memcmp( pisid->IdentifierAuthority.Value, refs[i].auth.Value,
267          sizeof(refs[i].auth) ),
268          "string sid %s didn't parse to expected value\n"
269          "(got 0x%04x%08x, expected 0x%04x%08x)\n",
270          refs[i].refStr,
271          MAKEWORD( pisid->IdentifierAuthority.Value[1],
272          pisid->IdentifierAuthority.Value[0] ),
273          MAKELONG( MAKEWORD( pisid->IdentifierAuthority.Value[5],
274          pisid->IdentifierAuthority.Value[4] ),
275          MAKEWORD( pisid->IdentifierAuthority.Value[3],
276          pisid->IdentifierAuthority.Value[2] ) ),
277          MAKEWORD( refs[i].auth.Value[1], refs[i].auth.Value[0] ),
278          MAKELONG( MAKEWORD( refs[i].auth.Value[5], refs[i].auth.Value[4] ),
279          MAKEWORD( refs[i].auth.Value[3], refs[i].auth.Value[2] ) ) );
280         if( psid )
281             LocalFree( psid );
282     }
283
284     trace("String SIDs:\n");
285     test_str_sid("AO");
286     test_str_sid("RU");
287     test_str_sid("AN");
288     test_str_sid("AU");
289     test_str_sid("BA");
290     test_str_sid("BG");
291     test_str_sid("BO");
292     test_str_sid("BU");
293     test_str_sid("CA");
294     test_str_sid("CG");
295     test_str_sid("CO");
296     test_str_sid("DA");
297     test_str_sid("DC");
298     test_str_sid("DD");
299     test_str_sid("DG");
300     test_str_sid("DU");
301     test_str_sid("EA");
302     test_str_sid("ED");
303     test_str_sid("WD");
304     test_str_sid("PA");
305     test_str_sid("IU");
306     test_str_sid("LA");
307     test_str_sid("LG");
308     test_str_sid("LS");
309     test_str_sid("SY");
310     test_str_sid("NU");
311     test_str_sid("NO");
312     test_str_sid("NS");
313     test_str_sid("PO");
314     test_str_sid("PS");
315     test_str_sid("PU");
316     test_str_sid("RS");
317     test_str_sid("RD");
318     test_str_sid("RE");
319     test_str_sid("RC");
320     test_str_sid("SA");
321     test_str_sid("SO");
322     test_str_sid("SU");
323 }
324
325 static void test_trustee(void)
326 {
327     GUID ObjectType = {0x12345678, 0x1234, 0x5678, {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}};
328     GUID InheritedObjectType = {0x23456789, 0x2345, 0x6786, {0x2, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}};
329     GUID ZeroGuid;
330     OBJECTS_AND_NAME_ oan;
331     OBJECTS_AND_SID oas;
332     TRUSTEE trustee;
333     PSID psid;
334     char szObjectTypeName[] = "ObjectTypeName";
335     char szInheritedObjectTypeName[] = "InheritedObjectTypeName";
336     char szTrusteeName[] = "szTrusteeName";
337     SID_IDENTIFIER_AUTHORITY auth = { {0x11,0x22,0,0,0, 0} };
338
339     memset( &ZeroGuid, 0x00, sizeof (ZeroGuid) );
340
341     pBuildTrusteeWithSidA = (fnBuildTrusteeWithSidA)
342                     GetProcAddress( hmod, "BuildTrusteeWithSidA" );
343     pBuildTrusteeWithNameA = (fnBuildTrusteeWithNameA)
344                     GetProcAddress( hmod, "BuildTrusteeWithNameA" );
345     pBuildTrusteeWithObjectsAndNameA = (fnBuildTrusteeWithObjectsAndNameA)
346                     GetProcAddress (hmod, "BuildTrusteeWithObjectsAndNameA" );
347     pBuildTrusteeWithObjectsAndSidA = (fnBuildTrusteeWithObjectsAndSidA)
348                     GetProcAddress (hmod, "BuildTrusteeWithObjectsAndSidA" );
349     pGetTrusteeNameA = (fnGetTrusteeNameA)
350                     GetProcAddress (hmod, "GetTrusteeNameA" );
351     if( !pBuildTrusteeWithSidA || !pBuildTrusteeWithNameA ||
352         !pBuildTrusteeWithObjectsAndNameA || !pBuildTrusteeWithObjectsAndSidA ||
353         !pGetTrusteeNameA )
354         return;
355
356     if ( ! AllocateAndInitializeSid( &auth, 1, 42, 0,0,0,0,0,0,0,&psid ) )
357     {
358         trace( "failed to init SID\n" );
359        return;
360     }
361
362     /* test BuildTrusteeWithSidA */
363     memset( &trustee, 0xff, sizeof trustee );
364     pBuildTrusteeWithSidA( &trustee, psid );
365
366     ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
367     ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, 
368         "MultipleTrusteeOperation wrong\n");
369     ok( trustee.TrusteeForm == TRUSTEE_IS_SID, "TrusteeForm wrong\n");
370     ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
371     ok( trustee.ptstrName == (LPSTR) psid, "ptstrName wrong\n" );
372
373     /* test BuildTrusteeWithObjectsAndSidA (test 1) */
374     memset( &trustee, 0xff, sizeof trustee );
375     memset( &oas, 0xff, sizeof(oas) );
376     pBuildTrusteeWithObjectsAndSidA(&trustee, &oas, &ObjectType,
377                                     &InheritedObjectType, psid);
378
379     ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
380     ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
381     ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_SID, "TrusteeForm wrong\n");
382     ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
383     ok(trustee.ptstrName == (LPSTR)&oas, "ptstrName wrong\n");
384  
385     ok(oas.ObjectsPresent == (ACE_OBJECT_TYPE_PRESENT | ACE_INHERITED_OBJECT_TYPE_PRESENT), "ObjectsPresent wrong\n");
386     ok(!memcmp(&oas.ObjectTypeGuid, &ObjectType, sizeof(GUID)), "ObjectTypeGuid wrong\n");
387     ok(!memcmp(&oas.InheritedObjectTypeGuid, &InheritedObjectType, sizeof(GUID)), "InheritedObjectTypeGuid wrong\n");
388     ok(oas.pSid == psid, "pSid wrong\n");
389
390     /* test GetTrusteeNameA */
391     ok(pGetTrusteeNameA(&trustee) == (LPSTR)&oas, "GetTrusteeName returned wrong value\n");
392
393     /* test BuildTrusteeWithObjectsAndSidA (test 2) */
394     memset( &trustee, 0xff, sizeof trustee );
395     memset( &oas, 0xff, sizeof(oas) );
396     pBuildTrusteeWithObjectsAndSidA(&trustee, &oas, NULL,
397                                     &InheritedObjectType, psid);
398
399     ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
400     ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
401     ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_SID, "TrusteeForm wrong\n");
402     ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
403     ok(trustee.ptstrName == (LPSTR)&oas, "ptstrName wrong\n");
404  
405     ok(oas.ObjectsPresent == ACE_INHERITED_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
406     ok(!memcmp(&oas.ObjectTypeGuid, &ZeroGuid, sizeof(GUID)), "ObjectTypeGuid wrong\n");
407     ok(!memcmp(&oas.InheritedObjectTypeGuid, &InheritedObjectType, sizeof(GUID)), "InheritedObjectTypeGuid wrong\n");
408     ok(oas.pSid == psid, "pSid wrong\n");
409
410     FreeSid( psid );
411
412     /* test BuildTrusteeWithNameA */
413     memset( &trustee, 0xff, sizeof trustee );
414     pBuildTrusteeWithNameA( &trustee, szTrusteeName );
415
416     ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
417     ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, 
418         "MultipleTrusteeOperation wrong\n");
419     ok( trustee.TrusteeForm == TRUSTEE_IS_NAME, "TrusteeForm wrong\n");
420     ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
421     ok( trustee.ptstrName == szTrusteeName, "ptstrName wrong\n" );
422
423     /* test BuildTrusteeWithObjectsAndNameA (test 1) */
424     memset( &trustee, 0xff, sizeof trustee );
425     memset( &oan, 0xff, sizeof(oan) );
426     pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, szObjectTypeName,
427                                      szInheritedObjectTypeName, szTrusteeName);
428
429     ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
430     ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
431     ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
432     ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
433     ok(trustee.ptstrName == (LPTSTR)&oan, "ptstrName wrong\n");
434  
435     ok(oan.ObjectsPresent == (ACE_OBJECT_TYPE_PRESENT | ACE_INHERITED_OBJECT_TYPE_PRESENT), "ObjectsPresent wrong\n");
436     ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
437     ok(oan.InheritedObjectTypeName == szInheritedObjectTypeName, "InheritedObjectTypeName wrong\n");
438     ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
439
440     /* test GetTrusteeNameA */
441     ok(pGetTrusteeNameA(&trustee) == (LPSTR)&oan, "GetTrusteeName returned wrong value\n");
442
443     /* test BuildTrusteeWithObjectsAndNameA (test 2) */
444     memset( &trustee, 0xff, sizeof trustee );
445     memset( &oan, 0xff, sizeof(oan) );
446     pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, NULL,
447                                      szInheritedObjectTypeName, szTrusteeName);
448
449     ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
450     ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
451     ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
452     ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
453     ok(trustee.ptstrName == (LPSTR)&oan, "ptstrName wrong\n");
454  
455     ok(oan.ObjectsPresent == ACE_INHERITED_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
456     ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
457     ok(oan.InheritedObjectTypeName == szInheritedObjectTypeName, "InheritedObjectTypeName wrong\n");
458     ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
459
460     /* test BuildTrusteeWithObjectsAndNameA (test 3) */
461     memset( &trustee, 0xff, sizeof trustee );
462     memset( &oan, 0xff, sizeof(oan) );
463     pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, szObjectTypeName,
464                                      NULL, szTrusteeName);
465
466     ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
467     ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
468     ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
469     ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
470     ok(trustee.ptstrName == (LPTSTR)&oan, "ptstrName wrong\n");
471  
472     ok(oan.ObjectsPresent == ACE_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
473     ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
474     ok(oan.InheritedObjectTypeName == NULL, "InheritedObjectTypeName wrong\n");
475     ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
476 }
477  
478 /* If the first isn't defined, assume none is */
479 #ifndef SE_MIN_WELL_KNOWN_PRIVILEGE
480 #define SE_MIN_WELL_KNOWN_PRIVILEGE       2L
481 #define SE_CREATE_TOKEN_PRIVILEGE         2L
482 #define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE   3L
483 #define SE_LOCK_MEMORY_PRIVILEGE          4L
484 #define SE_INCREASE_QUOTA_PRIVILEGE       5L
485 #define SE_MACHINE_ACCOUNT_PRIVILEGE      6L
486 #define SE_TCB_PRIVILEGE                  7L
487 #define SE_SECURITY_PRIVILEGE             8L
488 #define SE_TAKE_OWNERSHIP_PRIVILEGE       9L
489 #define SE_LOAD_DRIVER_PRIVILEGE         10L
490 #define SE_SYSTEM_PROFILE_PRIVILEGE      11L
491 #define SE_SYSTEMTIME_PRIVILEGE          12L
492 #define SE_PROF_SINGLE_PROCESS_PRIVILEGE 13L
493 #define SE_INC_BASE_PRIORITY_PRIVILEGE   14L
494 #define SE_CREATE_PAGEFILE_PRIVILEGE     15L
495 #define SE_CREATE_PERMANENT_PRIVILEGE    16L
496 #define SE_BACKUP_PRIVILEGE              17L
497 #define SE_RESTORE_PRIVILEGE             18L
498 #define SE_SHUTDOWN_PRIVILEGE            19L
499 #define SE_DEBUG_PRIVILEGE               20L
500 #define SE_AUDIT_PRIVILEGE               21L
501 #define SE_SYSTEM_ENVIRONMENT_PRIVILEGE  22L
502 #define SE_CHANGE_NOTIFY_PRIVILLEGE      23L
503 #define SE_REMOTE_SHUTDOWN_PRIVILEGE     24L
504 #define SE_UNDOCK_PRIVILEGE              25L
505 #define SE_SYNC_AGENT_PRIVILEGE          26L
506 #define SE_ENABLE_DELEGATION_PRIVILEGE   27L
507 #define SE_MANAGE_VOLUME_PRIVILEGE       28L
508 #define SE_IMPERSONATE_PRIVILEGE         29L
509 #define SE_CREATE_GLOBAL_PRIVILEGE       30L
510 #define SE_MAX_WELL_KNOWN_PRIVILEGE      SE_CREATE_GLOBAL_PRIVILEGE
511 #endif /* ndef SE_MIN_WELL_KNOWN_PRIVILEGE */
512
513 static void test_allocateLuid(void)
514 {
515     BOOL (WINAPI *pAllocateLocallyUniqueId)(PLUID);
516     LUID luid1, luid2;
517     BOOL ret;
518
519     pAllocateLocallyUniqueId = (void*)GetProcAddress(hmod, "AllocateLocallyUniqueId");
520     if (!pAllocateLocallyUniqueId) return;
521
522     ret = pAllocateLocallyUniqueId(&luid1);
523     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
524         return;
525
526     ok(ret,
527      "AllocateLocallyUniqueId failed: %d\n", GetLastError());
528     ret = pAllocateLocallyUniqueId(&luid2);
529     ok( ret,
530      "AllocateLocallyUniqueId failed: %d\n", GetLastError());
531     ok(luid1.LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE || luid1.HighPart != 0,
532      "AllocateLocallyUniqueId returned a well-known LUID\n");
533     ok(luid1.LowPart != luid2.LowPart || luid1.HighPart != luid2.HighPart,
534      "AllocateLocallyUniqueId returned non-unique LUIDs\n");
535     ret = pAllocateLocallyUniqueId(NULL);
536     ok( !ret && GetLastError() == ERROR_NOACCESS,
537      "AllocateLocallyUniqueId(NULL) didn't return ERROR_NOACCESS: %d\n",
538      GetLastError());
539 }
540
541 static void test_lookupPrivilegeName(void)
542 {
543     BOOL (WINAPI *pLookupPrivilegeNameA)(LPCSTR, PLUID, LPSTR, LPDWORD);
544     char buf[MAX_PATH]; /* arbitrary, seems long enough */
545     DWORD cchName = sizeof(buf);
546     LUID luid = { 0, 0 };
547     LONG i;
548     BOOL ret;
549
550     /* check whether it's available first */
551     pLookupPrivilegeNameA = (void*)GetProcAddress(hmod, "LookupPrivilegeNameA");
552     if (!pLookupPrivilegeNameA) return;
553     luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
554     ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
555     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
556         return;
557
558     /* check with a short buffer */
559     cchName = 0;
560     luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
561     ret = pLookupPrivilegeNameA(NULL, &luid, NULL, &cchName);
562     ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
563      "LookupPrivilegeNameA didn't fail with ERROR_INSUFFICIENT_BUFFER: %d\n",
564      GetLastError());
565     ok(cchName == strlen("SeCreateTokenPrivilege") + 1,
566      "LookupPrivilegeNameA returned an incorrect required length for\n"
567      "SeCreateTokenPrivilege (got %d, expected %d)\n", cchName,
568      lstrlenA("SeCreateTokenPrivilege") + 1);
569     /* check a known value and its returned length on success */
570     cchName = sizeof(buf);
571     ok(pLookupPrivilegeNameA(NULL, &luid, buf, &cchName) &&
572      cchName == strlen("SeCreateTokenPrivilege"),
573      "LookupPrivilegeNameA returned an incorrect output length for\n"
574      "SeCreateTokenPrivilege (got %d, expected %d)\n", cchName,
575      (int)strlen("SeCreateTokenPrivilege"));
576     /* check known values */
577     for (i = SE_MIN_WELL_KNOWN_PRIVILEGE; i < SE_MAX_WELL_KNOWN_PRIVILEGE; i++)
578     {
579         luid.LowPart = i;
580         cchName = sizeof(buf);
581         ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
582         ok( ret || GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
583          "LookupPrivilegeNameA(0.%d) failed: %d\n", i, GetLastError());
584     }
585     /* check a bogus LUID */
586     luid.LowPart = 0xdeadbeef;
587     cchName = sizeof(buf);
588     ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
589     ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
590      "LookupPrivilegeNameA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n",
591      GetLastError());
592     /* check on a bogus system */
593     luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
594     cchName = sizeof(buf);
595     ret = pLookupPrivilegeNameA("b0gu5.Nam3", &luid, buf, &cchName);
596     ok( !ret && (GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
597                  GetLastError() == RPC_S_INVALID_NET_ADDR) /* w2k8 */,
598      "LookupPrivilegeNameA didn't fail with RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR: %d\n",
599      GetLastError());
600 }
601
602 struct NameToLUID
603 {
604     const char *name;
605     DWORD lowPart;
606 };
607
608 static void test_lookupPrivilegeValue(void)
609 {
610     static const struct NameToLUID privs[] = {
611      { "SeCreateTokenPrivilege", SE_CREATE_TOKEN_PRIVILEGE },
612      { "SeAssignPrimaryTokenPrivilege", SE_ASSIGNPRIMARYTOKEN_PRIVILEGE },
613      { "SeLockMemoryPrivilege", SE_LOCK_MEMORY_PRIVILEGE },
614      { "SeIncreaseQuotaPrivilege", SE_INCREASE_QUOTA_PRIVILEGE },
615      { "SeMachineAccountPrivilege", SE_MACHINE_ACCOUNT_PRIVILEGE },
616      { "SeTcbPrivilege", SE_TCB_PRIVILEGE },
617      { "SeSecurityPrivilege", SE_SECURITY_PRIVILEGE },
618      { "SeTakeOwnershipPrivilege", SE_TAKE_OWNERSHIP_PRIVILEGE },
619      { "SeLoadDriverPrivilege", SE_LOAD_DRIVER_PRIVILEGE },
620      { "SeSystemProfilePrivilege", SE_SYSTEM_PROFILE_PRIVILEGE },
621      { "SeSystemtimePrivilege", SE_SYSTEMTIME_PRIVILEGE },
622      { "SeProfileSingleProcessPrivilege", SE_PROF_SINGLE_PROCESS_PRIVILEGE },
623      { "SeIncreaseBasePriorityPrivilege", SE_INC_BASE_PRIORITY_PRIVILEGE },
624      { "SeCreatePagefilePrivilege", SE_CREATE_PAGEFILE_PRIVILEGE },
625      { "SeCreatePermanentPrivilege", SE_CREATE_PERMANENT_PRIVILEGE },
626      { "SeBackupPrivilege", SE_BACKUP_PRIVILEGE },
627      { "SeRestorePrivilege", SE_RESTORE_PRIVILEGE },
628      { "SeShutdownPrivilege", SE_SHUTDOWN_PRIVILEGE },
629      { "SeDebugPrivilege", SE_DEBUG_PRIVILEGE },
630      { "SeAuditPrivilege", SE_AUDIT_PRIVILEGE },
631      { "SeSystemEnvironmentPrivilege", SE_SYSTEM_ENVIRONMENT_PRIVILEGE },
632      { "SeChangeNotifyPrivilege", SE_CHANGE_NOTIFY_PRIVILLEGE },
633      { "SeRemoteShutdownPrivilege", SE_REMOTE_SHUTDOWN_PRIVILEGE },
634      { "SeUndockPrivilege", SE_UNDOCK_PRIVILEGE },
635      { "SeSyncAgentPrivilege", SE_SYNC_AGENT_PRIVILEGE },
636      { "SeEnableDelegationPrivilege", SE_ENABLE_DELEGATION_PRIVILEGE },
637      { "SeManageVolumePrivilege", SE_MANAGE_VOLUME_PRIVILEGE },
638      { "SeImpersonatePrivilege", SE_IMPERSONATE_PRIVILEGE },
639      { "SeCreateGlobalPrivilege", SE_CREATE_GLOBAL_PRIVILEGE },
640     };
641     BOOL (WINAPI *pLookupPrivilegeValueA)(LPCSTR, LPCSTR, PLUID);
642     int i;
643     LUID luid;
644     BOOL ret;
645
646     /* check whether it's available first */
647     pLookupPrivilegeValueA = (void*)GetProcAddress(hmod, "LookupPrivilegeValueA");
648     if (!pLookupPrivilegeValueA) return;
649     ret = pLookupPrivilegeValueA(NULL, "SeCreateTokenPrivilege", &luid);
650     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
651         return;
652
653     /* check a bogus system name */
654     ret = pLookupPrivilegeValueA("b0gu5.Nam3", "SeCreateTokenPrivilege", &luid);
655     ok( !ret && (GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
656                 GetLastError() == RPC_S_INVALID_NET_ADDR) /* w2k8 */,
657      "LookupPrivilegeValueA didn't fail with RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR: %d\n",
658      GetLastError());
659     /* check a NULL string */
660     ret = pLookupPrivilegeValueA(NULL, 0, &luid);
661     ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
662      "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n",
663      GetLastError());
664     /* check a bogus privilege name */
665     ret = pLookupPrivilegeValueA(NULL, "SeBogusPrivilege", &luid);
666     ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
667      "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n",
668      GetLastError());
669     /* check case insensitive */
670     ret = pLookupPrivilegeValueA(NULL, "sEcREATEtOKENpRIVILEGE", &luid);
671     ok( ret,
672      "LookupPrivilegeValueA(NULL, sEcREATEtOKENpRIVILEGE, &luid) failed: %d\n",
673      GetLastError());
674     for (i = 0; i < sizeof(privs) / sizeof(privs[0]); i++)
675     {
676         /* Not all privileges are implemented on all Windows versions, so
677          * don't worry if the call fails
678          */
679         if (pLookupPrivilegeValueA(NULL, privs[i].name, &luid))
680         {
681             ok(luid.LowPart == privs[i].lowPart,
682              "LookupPrivilegeValueA returned an invalid LUID for %s\n",
683              privs[i].name);
684         }
685     }
686 }
687
688 static void test_luid(void)
689 {
690     test_allocateLuid();
691     test_lookupPrivilegeName();
692     test_lookupPrivilegeValue();
693 }
694
695 static void test_FileSecurity(void)
696 {
697     char directory[MAX_PATH];
698     DWORD retval, outSize;
699     BOOL result;
700     BYTE buffer[0x40];
701
702     pGetFileSecurityA = (fnGetFileSecurityA)
703                     GetProcAddress( hmod, "GetFileSecurityA" );
704     if( !pGetFileSecurityA )
705         return;
706
707     retval = GetTempPathA(sizeof(directory), directory);
708     if (!retval) {
709         trace("GetTempPathA failed\n");
710         return;
711     }
712
713     strcpy(directory, "\\Should not exist");
714
715     SetLastError(NO_ERROR);
716     result = pGetFileSecurityA( directory,OWNER_SECURITY_INFORMATION,buffer,0x40,&outSize);
717     ok(!result, "GetFileSecurityA should fail for not existing directories/files\n"); 
718     ok( (GetLastError() == ERROR_FILE_NOT_FOUND ) ||
719         (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) , 
720         "last error ERROR_FILE_NOT_FOUND / ERROR_CALL_NOT_IMPLEMENTED (98) "
721         "expected, got %d\n", GetLastError());
722 }
723
724 static void test_AccessCheck(void)
725 {
726     PSID EveryoneSid = NULL, AdminSid = NULL, UsersSid = NULL;
727     PACL Acl = NULL;
728     SECURITY_DESCRIPTOR *SecurityDescriptor = NULL;
729     SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
730     SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
731     GENERIC_MAPPING Mapping = { KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS };
732     ACCESS_MASK Access;
733     BOOL AccessStatus;
734     HANDLE Token;
735     HANDLE ProcessToken;
736     BOOL ret;
737     DWORD PrivSetLen;
738     PRIVILEGE_SET *PrivSet;
739     BOOL res;
740     HMODULE NtDllModule;
741     BOOLEAN Enabled;
742     DWORD err;
743
744     NtDllModule = GetModuleHandle("ntdll.dll");
745     if (!NtDllModule)
746     {
747         skip("not running on NT, skipping test\n");
748         return;
749     }
750     pRtlAdjustPrivilege = (fnRtlAdjustPrivilege)
751                           GetProcAddress(NtDllModule, "RtlAdjustPrivilege");
752     if (!pRtlAdjustPrivilege)
753     {
754         skip("missing RtlAdjustPrivilege, skipping test\n");
755         return;
756     }
757
758     Acl = HeapAlloc(GetProcessHeap(), 0, 256);
759     res = InitializeAcl(Acl, 256, ACL_REVISION);
760     if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
761     {
762         skip("ACLs not implemented - skipping tests\n");
763         HeapFree(GetProcessHeap(), 0, Acl);
764         return;
765     }
766     ok(res, "InitializeAcl failed with error %d\n", GetLastError());
767
768     res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
769     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
770
771     res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
772         DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminSid);
773     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
774
775     res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
776         DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid);
777     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
778
779     SecurityDescriptor = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
780
781     res = InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
782     ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
783
784     res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
785     ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
786
787     PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
788     PrivSet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, PrivSetLen);
789     PrivSet->PrivilegeCount = 16;
790
791     res = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &ProcessToken);
792     ok(res, "OpenProcessToken failed with error %d\n", GetLastError());
793
794     pRtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, FALSE, TRUE, &Enabled);
795
796     res = DuplicateToken(ProcessToken, SecurityImpersonation, &Token);
797     ok(res, "DuplicateToken failed with error %d\n", GetLastError());
798
799     /* SD without owner/group */
800     SetLastError(0xdeadbeef);
801     Access = AccessStatus = 0xdeadbeef;
802     ret = AccessCheck(SecurityDescriptor, Token, KEY_QUERY_VALUE, &Mapping,
803                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
804     err = GetLastError();
805     ok(!ret && err == ERROR_INVALID_SECURITY_DESCR, "AccessCheck should have "
806        "failed with ERROR_INVALID_SECURITY_DESCR, instead of %d\n", err);
807     ok(Access == 0xdeadbeef && AccessStatus == 0xdeadbeef,
808        "Access and/or AccessStatus were changed!\n");
809
810     /* Set owner and group */
811     res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE);
812     ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
813     res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, TRUE);
814     ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
815
816     /* Generic access mask */
817     SetLastError(0xdeadbeef);
818     ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
819                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
820     err = GetLastError();
821     ok(!ret && err == ERROR_GENERIC_NOT_MAPPED, "AccessCheck should have failed "
822        "with ERROR_GENERIC_NOT_MAPPED, instead of %d\n", err);
823     ok(Access == 0xdeadbeef && AccessStatus == 0xdeadbeef,
824        "Access and/or AccessStatus were changed!\n");
825
826     /* sd with no dacl present */
827     ret = SetSecurityDescriptorDacl(SecurityDescriptor, FALSE, NULL, FALSE);
828     ok(ret, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
829     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
830                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
831     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
832     ok(AccessStatus && (Access == KEY_READ),
833         "AccessCheck failed to grant access with error %d\n",
834         GetLastError());
835
836     /* sd with NULL dacl */
837     ret = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, NULL, FALSE);
838     ok(ret, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
839     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
840                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
841     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
842     ok(AccessStatus && (Access == KEY_READ),
843         "AccessCheck failed to grant access with error %d\n",
844         GetLastError());
845
846     /* sd with blank dacl */
847     ret = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
848     ok(ret, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
849     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
850                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
851     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
852     err = GetLastError();
853     ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed "
854        "with ERROR_ACCESS_DENIED, instead of %d\n", err);
855     ok(!Access, "Should have failed to grant any access, got 0x%08x\n", Access);
856
857     res = AddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, EveryoneSid);
858     ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
859
860     res = AddAccessDeniedAce(Acl, ACL_REVISION, KEY_SET_VALUE, AdminSid);
861     ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError());
862
863     /* sd with dacl */
864     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
865                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
866     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
867     ok(AccessStatus && (Access == KEY_READ),
868         "AccessCheck failed to grant access with error %d\n",
869         GetLastError());
870
871     ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping,
872                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
873     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
874     ok(AccessStatus,
875         "AccessCheck failed to grant any access with error %d\n",
876         GetLastError());
877     trace("AccessCheck with MAXIMUM_ALLOWED got Access 0x%08x\n", Access);
878
879     /* Access denied by SD */
880     SetLastError(0xdeadbeef);
881     ret = AccessCheck(SecurityDescriptor, Token, KEY_WRITE, &Mapping,
882                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
883     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
884     err = GetLastError();
885     ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed "
886        "with ERROR_ACCESS_DENIED, instead of %d\n", err);
887     ok(!Access, "Should have failed to grant any access, got 0x%08x\n", Access);
888
889     SetLastError(0);
890     PrivSet->PrivilegeCount = 16;
891     ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping,
892                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
893     ok(ret && !AccessStatus && GetLastError() == ERROR_PRIVILEGE_NOT_HELD,
894         "AccessCheck should have failed with ERROR_PRIVILEGE_NOT_HELD, instead of %d\n",
895         GetLastError());
896
897     ret = ImpersonateLoggedOnUser(Token);
898     ok(ret, "ImpersonateLoggedOnUser failed with error %d\n", GetLastError());
899     ret = pRtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, TRUE, TRUE, &Enabled);
900     if (!ret)
901     {
902         SetLastError(0);
903         PrivSet->PrivilegeCount = 16;
904         ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping,
905                           PrivSet, &PrivSetLen, &Access, &AccessStatus);
906         ok(ret && AccessStatus && GetLastError() == 0,
907             "AccessCheck should have succeeded, error %d\n",
908             GetLastError());
909         ok(Access == ACCESS_SYSTEM_SECURITY,
910             "Access should be equal to ACCESS_SYSTEM_SECURITY instead of 0x%08x\n",
911             Access);
912     }
913     else
914         trace("Couldn't get SE_SECURITY_PRIVILEGE (0x%08x), skipping ACCESS_SYSTEM_SECURITY test\n",
915             ret);
916     ret = RevertToSelf();
917     ok(ret, "RevertToSelf failed with error %d\n", GetLastError());
918
919     /* test INHERIT_ONLY_ACE */
920     ret = InitializeAcl(Acl, 256, ACL_REVISION);
921     ok(ret, "InitializeAcl failed with error %d\n", GetLastError());
922
923     /* NT doesn't have AddAccessAllowedAceEx. Skipping this call/test doesn't influence
924      * the next ones.
925      */
926     if (pAddAccessAllowedAceEx)
927     {
928         ret = pAddAccessAllowedAceEx(Acl, ACL_REVISION, INHERIT_ONLY_ACE, KEY_READ, EveryoneSid);
929         ok(ret, "AddAccessAllowedAceEx failed with error %d\n", GetLastError());
930     }
931     else
932         skip("AddAccessAllowedAceEx is not available\n");
933
934     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
935                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
936     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
937     err = GetLastError();
938     ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed "
939        "with ERROR_ACCESS_DENIED, instead of %d\n", err);
940     ok(!Access, "Should have failed to grant any access, got 0x%08x\n", Access);
941
942     CloseHandle(Token);
943
944     res = DuplicateToken(ProcessToken, SecurityAnonymous, &Token);
945     ok(res, "DuplicateToken failed with error %d\n", GetLastError());
946
947     SetLastError(0xdeadbeef);
948     ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping,
949                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
950     err = GetLastError();
951     ok(!ret && err == ERROR_BAD_IMPERSONATION_LEVEL, "AccessCheck should have failed "
952        "with ERROR_BAD_IMPERSONATION_LEVEL, instead of %d\n", err);
953
954     CloseHandle(Token);
955
956     SetLastError(0xdeadbeef);
957     ret = AccessCheck(SecurityDescriptor, ProcessToken, KEY_READ, &Mapping,
958                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
959     err = GetLastError();
960     ok(!ret && err == ERROR_NO_IMPERSONATION_TOKEN, "AccessCheck should have failed "
961        "with ERROR_NO_IMPERSONATION_TOKEN, instead of %d\n", err);
962
963     CloseHandle(ProcessToken);
964
965     if (EveryoneSid)
966         FreeSid(EveryoneSid);
967     if (AdminSid)
968         FreeSid(AdminSid);
969     if (UsersSid)
970         FreeSid(UsersSid);
971     HeapFree(GetProcessHeap(), 0, Acl);
972     HeapFree(GetProcessHeap(), 0, SecurityDescriptor);
973     HeapFree(GetProcessHeap(), 0, PrivSet);
974 }
975
976 /* test GetTokenInformation for the various attributes */
977 static void test_token_attr(void)
978 {
979     HANDLE Token, ImpersonationToken;
980     DWORD Size;
981     TOKEN_PRIVILEGES *Privileges;
982     TOKEN_GROUPS *Groups;
983     TOKEN_USER *User;
984     BOOL ret;
985     DWORD i, GLE;
986     LPSTR SidString;
987     SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
988
989     /* cygwin-like use case */
990     SetLastError(0xdeadbeef);
991     ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &Token);
992     if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
993     {
994         skip("OpenProcessToken is not implemented\n");
995         return;
996     }
997     ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
998     if (ret)
999     {
1000         BYTE buf[1024];
1001         Size = sizeof(buf);
1002         ret = GetTokenInformation(Token, TokenUser,(void*)buf, Size, &Size);
1003         ok(ret, "GetTokenInformation failed with error %d\n", GetLastError());
1004         Size = sizeof(ImpersonationLevel);
1005         ret = GetTokenInformation(Token, TokenImpersonationLevel, &ImpersonationLevel, Size, &Size);
1006         GLE = GetLastError();
1007         ok(!ret && (GLE == ERROR_INVALID_PARAMETER), "GetTokenInformation(TokenImpersonationLevel) on primary token should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GLE);
1008         CloseHandle(Token);
1009     }
1010
1011     if(!pConvertSidToStringSidA)
1012     {
1013         skip("ConvertSidToStringSidA is not available\n");
1014         return;
1015     }
1016
1017     SetLastError(0xdeadbeef);
1018     ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_DUPLICATE, &Token);
1019     ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1020
1021     /* groups */
1022     ret = GetTokenInformation(Token, TokenGroups, NULL, 0, &Size);
1023     Groups = HeapAlloc(GetProcessHeap(), 0, Size);
1024     ret = GetTokenInformation(Token, TokenGroups, Groups, Size, &Size);
1025     ok(ret, "GetTokenInformation(TokenGroups) failed with error %d\n", GetLastError());
1026     trace("TokenGroups:\n");
1027     for (i = 0; i < Groups->GroupCount; i++)
1028     {
1029         DWORD NameLength = 255;
1030         TCHAR Name[255];
1031         DWORD DomainLength = 255;
1032         TCHAR Domain[255];
1033         SID_NAME_USE SidNameUse;
1034         pConvertSidToStringSidA(Groups->Groups[i].Sid, &SidString);
1035         Name[0] = '\0';
1036         Domain[0] = '\0';
1037         ret = LookupAccountSid(NULL, Groups->Groups[i].Sid, Name, &NameLength, Domain, &DomainLength, &SidNameUse);
1038         if (ret)
1039             trace("\t%s, %s\\%s use: %d attr: 0x%08x\n", SidString, Domain, Name, SidNameUse, Groups->Groups[i].Attributes);
1040         else
1041             trace("\t%s, attr: 0x%08x LookupAccountSid failed with error %d\n", SidString, Groups->Groups[i].Attributes, GetLastError());
1042         LocalFree(SidString);
1043     }
1044     HeapFree(GetProcessHeap(), 0, Groups);
1045
1046     /* user */
1047     ret = GetTokenInformation(Token, TokenUser, NULL, 0, &Size);
1048     ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1049         "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
1050     User = HeapAlloc(GetProcessHeap(), 0, Size);
1051     ret = GetTokenInformation(Token, TokenUser, User, Size, &Size);
1052     ok(ret,
1053         "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
1054
1055     pConvertSidToStringSidA(User->User.Sid, &SidString);
1056     trace("TokenUser: %s attr: 0x%08x\n", SidString, User->User.Attributes);
1057     LocalFree(SidString);
1058     HeapFree(GetProcessHeap(), 0, User);
1059
1060     /* privileges */
1061     ret = GetTokenInformation(Token, TokenPrivileges, NULL, 0, &Size);
1062     ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1063         "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError());
1064     Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1065     ret = GetTokenInformation(Token, TokenPrivileges, Privileges, Size, &Size);
1066     ok(ret,
1067         "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError());
1068     trace("TokenPrivileges:\n");
1069     for (i = 0; i < Privileges->PrivilegeCount; i++)
1070     {
1071         TCHAR Name[256];
1072         DWORD NameLen = sizeof(Name)/sizeof(Name[0]);
1073         LookupPrivilegeName(NULL, &Privileges->Privileges[i].Luid, Name, &NameLen);
1074         trace("\t%s, 0x%x\n", Name, Privileges->Privileges[i].Attributes);
1075     }
1076     HeapFree(GetProcessHeap(), 0, Privileges);
1077
1078     ret = DuplicateToken(Token, SecurityAnonymous, &ImpersonationToken);
1079     ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
1080
1081     Size = sizeof(ImpersonationLevel);
1082     ret = GetTokenInformation(ImpersonationToken, TokenImpersonationLevel, &ImpersonationLevel, Size, &Size);
1083     ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError());
1084     ok(ImpersonationLevel == SecurityAnonymous, "ImpersonationLevel should have been SecurityAnonymous instead of %d\n", ImpersonationLevel);
1085
1086     CloseHandle(ImpersonationToken);
1087     CloseHandle(Token);
1088 }
1089
1090 typedef union _MAX_SID
1091 {
1092     SID sid;
1093     char max[SECURITY_MAX_SID_SIZE];
1094 } MAX_SID;
1095
1096 static void test_sid_str(PSID * sid)
1097 {
1098     char *str_sid;
1099     BOOL ret = pConvertSidToStringSidA(sid, &str_sid);
1100     ok(ret, "ConvertSidToStringSidA() failed: %d\n", GetLastError());
1101     if (ret)
1102     {
1103         char account[MAX_PATH], domain[MAX_PATH];
1104         SID_NAME_USE use;
1105         DWORD acc_size = MAX_PATH;
1106         DWORD dom_size = MAX_PATH;
1107         ret = LookupAccountSid(NULL, sid, account, &acc_size, domain, &dom_size, &use);
1108         ok(ret || (!ret && (GetLastError() == ERROR_NONE_MAPPED)),
1109            "LookupAccountSid(%s) failed: %d\n", str_sid, GetLastError());
1110         if (ret)
1111             trace(" %s %s\\%s %d\n", str_sid, domain, account, use);
1112         else if (GetLastError() == ERROR_NONE_MAPPED)
1113             trace(" %s couldn't be mapped\n", str_sid);
1114         LocalFree(str_sid);
1115     }
1116 }
1117
1118 struct well_known_sid_value
1119 {
1120     BOOL without_domain;
1121     const char *sid_string;
1122 } well_known_sid_values[] = {
1123 /*  0 */ {TRUE, "S-1-0-0"},  {TRUE, "S-1-1-0"},  {TRUE, "S-1-2-0"},  {TRUE, "S-1-3-0"},
1124 /*  4 */ {TRUE, "S-1-3-1"},  {TRUE, "S-1-3-2"},  {TRUE, "S-1-3-3"},  {TRUE, "S-1-5"},
1125 /*  8 */ {FALSE, "S-1-5-1"}, {TRUE, "S-1-5-2"},  {TRUE, "S-1-5-3"},  {TRUE, "S-1-5-4"},
1126 /* 12 */ {TRUE, "S-1-5-6"},  {TRUE, "S-1-5-7"},  {TRUE, "S-1-5-8"},  {TRUE, "S-1-5-9"},
1127 /* 16 */ {TRUE, "S-1-5-10"}, {TRUE, "S-1-5-11"}, {TRUE, "S-1-5-12"}, {TRUE, "S-1-5-13"},
1128 /* 20 */ {TRUE, "S-1-5-14"}, {FALSE, NULL},      {TRUE, "S-1-5-18"}, {TRUE, "S-1-5-19"},
1129 /* 24 */ {TRUE, "S-1-5-20"}, {TRUE, "S-1-5-32"},
1130 /* 26 */ {FALSE, "S-1-5-32-544"}, {TRUE, "S-1-5-32-545"}, {TRUE, "S-1-5-32-546"},
1131 /* 29 */ {TRUE, "S-1-5-32-547"},  {TRUE, "S-1-5-32-548"}, {TRUE, "S-1-5-32-549"},
1132 /* 32 */ {TRUE, "S-1-5-32-550"},  {TRUE, "S-1-5-32-551"}, {TRUE, "S-1-5-32-552"},
1133 /* 35 */ {TRUE, "S-1-5-32-554"},  {TRUE, "S-1-5-32-555"}, {TRUE, "S-1-5-32-556"},
1134 /* 38 */ {FALSE, "S-1-5-21-12-23-34-45-56-500"}, {FALSE, "S-1-5-21-12-23-34-45-56-501"},
1135 /* 40 */ {FALSE, "S-1-5-21-12-23-34-45-56-502"}, {FALSE, "S-1-5-21-12-23-34-45-56-512"},
1136 /* 42 */ {FALSE, "S-1-5-21-12-23-34-45-56-513"}, {FALSE, "S-1-5-21-12-23-34-45-56-514"},
1137 /* 44 */ {FALSE, "S-1-5-21-12-23-34-45-56-515"}, {FALSE, "S-1-5-21-12-23-34-45-56-516"},
1138 /* 46 */ {FALSE, "S-1-5-21-12-23-34-45-56-517"}, {FALSE, "S-1-5-21-12-23-34-45-56-518"},
1139 /* 48 */ {FALSE, "S-1-5-21-12-23-34-45-56-519"}, {FALSE, "S-1-5-21-12-23-34-45-56-520"},
1140 /* 50 */ {FALSE, "S-1-5-21-12-23-34-45-56-553"},
1141 /* Added in Windows Server 2003 */
1142 /* 51 */ {TRUE, "S-1-5-64-10"},   {TRUE, "S-1-5-64-21"},   {TRUE, "S-1-5-64-14"},
1143 /* 54 */ {TRUE, "S-1-5-15"},      {TRUE, "S-1-5-1000"},    {FALSE, "S-1-5-32-557"},
1144 /* 57 */ {TRUE, "S-1-5-32-558"},  {TRUE, "S-1-5-32-559"},  {TRUE, "S-1-5-32-560"},
1145 /* 60 */ {TRUE, "S-1-5-32-561"}, {TRUE, "S-1-5-32-562"},
1146 /* Added in Windows Vista: */
1147 /* 62 */ {TRUE, "S-1-5-32-568"},
1148 /* 63 */ {TRUE, "S-1-5-17"},      {FALSE, "S-1-5-32-569"}, {TRUE, "S-1-16-0"},
1149 /* 66 */ {TRUE, "S-1-16-4096"},   {TRUE, "S-1-16-8192"},   {TRUE, "S-1-16-12288"},
1150 /* 69 */ {TRUE, "S-1-16-16384"},  {TRUE, "S-1-5-33"},      {TRUE, "S-1-3-4"},
1151 /* 72 */ {FALSE, "S-1-5-21-12-23-34-45-56-571"},  {FALSE, "S-1-5-21-12-23-34-45-56-572"},
1152 /* 74 */ {TRUE, "S-1-5-22"}, {FALSE, "S-1-5-21-12-23-34-45-56-521"}, {TRUE, "S-1-5-32-573"}
1153 };
1154
1155 static void test_CreateWellKnownSid()
1156 {
1157     SID_IDENTIFIER_AUTHORITY ident = { SECURITY_NT_AUTHORITY };
1158     PSID domainsid;
1159     int i;
1160
1161     if (!pCreateWellKnownSid)
1162     {
1163         skip("CreateWellKnownSid not available\n");
1164         return;
1165     }
1166
1167     /* a domain sid usually have three subauthorities but we test that CreateWellKnownSid doesn't check it */
1168     AllocateAndInitializeSid(&ident, 6, SECURITY_NT_NON_UNIQUE, 12, 23, 34, 45, 56, 0, 0, &domainsid);
1169
1170     for (i = 0; i < sizeof(well_known_sid_values)/sizeof(well_known_sid_values[0]); i++)
1171     {
1172         struct well_known_sid_value *value = &well_known_sid_values[i];
1173         char sid_buffer[SECURITY_MAX_SID_SIZE];
1174         LPSTR str;
1175         DWORD cb;
1176
1177         if (value->sid_string == NULL)
1178             continue;
1179
1180         if (i > WinAccountRasAndIasServersSid)
1181         {
1182             /* These SIDs aren't implemented by all Windows versions - detect it and break the loop */
1183             cb = sizeof(sid_buffer);
1184             if (!pCreateWellKnownSid(i, domainsid, sid_buffer, &cb))
1185             {
1186                 skip("Well known SIDs starting from %d are not implemented\n", i);
1187                 break;
1188             }
1189         }
1190
1191         cb = sizeof(sid_buffer);
1192         ok(pCreateWellKnownSid(i, value->without_domain ? NULL : domainsid, sid_buffer, &cb), "Couldn't create well known sid %d\n", i);
1193         expect_eq(GetSidLengthRequired(*GetSidSubAuthorityCount(sid_buffer)), cb, DWORD, "%d");
1194         ok(IsValidSid(sid_buffer), "The sid is not valid\n");
1195         ok(pConvertSidToStringSidA(sid_buffer, &str), "Couldn't convert SID to string\n");
1196         ok(strcmp(str, value->sid_string) == 0, "SID mismatch - expected %s, got %s\n",
1197             value->sid_string, str);
1198         LocalFree(str);
1199
1200         if (value->without_domain)
1201         {
1202             char buf2[SECURITY_MAX_SID_SIZE];
1203             cb = sizeof(buf2);
1204             ok(pCreateWellKnownSid(i, domainsid, buf2, &cb), "Couldn't create well known sid %d with optional domain\n", i);
1205             expect_eq(GetSidLengthRequired(*GetSidSubAuthorityCount(sid_buffer)), cb, DWORD, "%d");
1206             ok(memcmp(buf2, sid_buffer, cb) == 0, "SID create with domain is different than without (%d)\n", i);
1207         }
1208     }
1209 }
1210
1211 static void test_LookupAccountSid(void)
1212 {
1213     SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
1214     CHAR accountA[MAX_PATH], domainA[MAX_PATH];
1215     DWORD acc_sizeA, dom_sizeA;
1216     DWORD real_acc_sizeA, real_dom_sizeA;
1217     WCHAR accountW[MAX_PATH], domainW[MAX_PATH];
1218     DWORD acc_sizeW, dom_sizeW;
1219     DWORD real_acc_sizeW, real_dom_sizeW;
1220     PSID pUsersSid = NULL;
1221     SID_NAME_USE use;
1222     BOOL ret;
1223     DWORD size;
1224     MAX_SID  max_sid;
1225     CHAR *str_sidA;
1226     int i;
1227
1228     /* native windows crashes if account size, domain size, or name use is NULL */
1229
1230     ret = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
1231         DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &pUsersSid);
1232     ok(ret || (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED),
1233        "AllocateAndInitializeSid failed with error %d\n", GetLastError());
1234
1235     /* not running on NT so give up */
1236     if (!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
1237         return;
1238
1239     real_acc_sizeA = MAX_PATH;
1240     real_dom_sizeA = MAX_PATH;
1241     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &real_acc_sizeA, domainA, &real_dom_sizeA, &use);
1242     ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
1243
1244     /* try NULL account */
1245     acc_sizeA = MAX_PATH;
1246     dom_sizeA = MAX_PATH;
1247     ret = LookupAccountSidA(NULL, pUsersSid, NULL, &acc_sizeA, domainA, &dom_sizeA, &use);
1248     ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
1249
1250     /* try NULL domain */
1251     acc_sizeA = MAX_PATH;
1252     dom_sizeA = MAX_PATH;
1253     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, NULL, &dom_sizeA, &use);
1254     ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
1255
1256     /* try a small account buffer */
1257     acc_sizeA = 1;
1258     dom_sizeA = MAX_PATH;
1259     accountA[0] = 0;
1260     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
1261     ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n");
1262     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1263        "LookupAccountSidA() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
1264
1265     /* try a 0 sized account buffer */
1266     acc_sizeA = 0;
1267     dom_sizeA = MAX_PATH;
1268     accountA[0] = 0;
1269     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
1270     /* this can fail or succeed depending on OS version but the size will always be returned */
1271     ok(acc_sizeA == real_acc_sizeA + 1,
1272        "LookupAccountSidA() Expected acc_size = %u, got %u\n",
1273        real_acc_sizeA + 1, acc_sizeA);
1274
1275     /* try a 0 sized account buffer */
1276     acc_sizeA = 0;
1277     dom_sizeA = MAX_PATH;
1278     ret = LookupAccountSidA(NULL, pUsersSid, NULL, &acc_sizeA, domainA, &dom_sizeA, &use);
1279     /* this can fail or succeed depending on OS version but the size will always be returned */
1280     ok(acc_sizeA == real_acc_sizeA + 1,
1281        "LookupAccountSid() Expected acc_size = %u, got %u\n",
1282        real_acc_sizeA + 1, acc_sizeA);
1283
1284     /* try a small domain buffer */
1285     dom_sizeA = 1;
1286     acc_sizeA = MAX_PATH;
1287     accountA[0] = 0;
1288     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
1289     ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n");
1290     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1291        "LookupAccountSidA() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
1292
1293     /* try a 0 sized domain buffer */
1294     dom_sizeA = 0;
1295     acc_sizeA = MAX_PATH;
1296     accountA[0] = 0;
1297     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
1298     /* this can fail or succeed depending on OS version but the size will always be returned */
1299     ok(dom_sizeA == real_dom_sizeA + 1,
1300        "LookupAccountSidA() Expected dom_size = %u, got %u\n",
1301        real_dom_sizeA + 1, dom_sizeA);
1302
1303     /* try a 0 sized domain buffer */
1304     dom_sizeA = 0;
1305     acc_sizeA = MAX_PATH;
1306     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, NULL, &dom_sizeA, &use);
1307     /* this can fail or succeed depending on OS version but the size will always be returned */
1308     ok(dom_sizeA == real_dom_sizeA + 1,
1309        "LookupAccountSidA() Expected dom_size = %u, got %u\n",
1310        real_dom_sizeA + 1, dom_sizeA);
1311
1312     real_acc_sizeW = MAX_PATH;
1313     real_dom_sizeW = MAX_PATH;
1314     ret = LookupAccountSidW(NULL, pUsersSid, accountW, &real_acc_sizeW, domainW, &real_dom_sizeW, &use);
1315     ok(ret, "LookupAccountSidW() Expected TRUE, got FALSE\n");
1316
1317     /* native windows crashes if domainW or accountW is NULL */
1318
1319     /* try a small account buffer */
1320     acc_sizeW = 1;
1321     dom_sizeW = MAX_PATH;
1322     accountW[0] = 0;
1323     ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
1324     ok(!ret, "LookupAccountSidW() Expected FALSE got TRUE\n");
1325     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1326        "LookupAccountSidW() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
1327
1328     /* try a 0 sized account buffer */
1329     acc_sizeW = 0;
1330     dom_sizeW = MAX_PATH;
1331     accountW[0] = 0;
1332     ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
1333     /* this can fail or succeed depending on OS version but the size will always be returned */
1334     ok(acc_sizeW == real_acc_sizeW + 1,
1335        "LookupAccountSidW() Expected acc_size = %u, got %u\n",
1336        real_acc_sizeW + 1, acc_sizeW);
1337
1338     /* try a 0 sized account buffer */
1339     acc_sizeW = 0;
1340     dom_sizeW = MAX_PATH;
1341     ret = LookupAccountSidW(NULL, pUsersSid, NULL, &acc_sizeW, domainW, &dom_sizeW, &use);
1342     /* this can fail or succeed depending on OS version but the size will always be returned */
1343     ok(acc_sizeW == real_acc_sizeW + 1,
1344        "LookupAccountSidW() Expected acc_size = %u, got %u\n",
1345        real_acc_sizeW + 1, acc_sizeW);
1346
1347     /* try a small domain buffer */
1348     dom_sizeW = 1;
1349     acc_sizeW = MAX_PATH;
1350     accountW[0] = 0;
1351     ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
1352     ok(!ret, "LookupAccountSidW() Expected FALSE got TRUE\n");
1353     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1354        "LookupAccountSidW() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
1355
1356     /* try a 0 sized domain buffer */
1357     dom_sizeW = 0;
1358     acc_sizeW = MAX_PATH;
1359     accountW[0] = 0;
1360     ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
1361     /* this can fail or succeed depending on OS version but the size will always be returned */
1362     ok(dom_sizeW == real_dom_sizeW + 1,
1363        "LookupAccountSidW() Expected dom_size = %u, got %u\n",
1364        real_dom_sizeW + 1, dom_sizeW);
1365
1366     /* try a 0 sized domain buffer */
1367     dom_sizeW = 0;
1368     acc_sizeW = MAX_PATH;
1369     ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, NULL, &dom_sizeW, &use);
1370     /* this can fail or succeed depending on OS version but the size will always be returned */
1371     ok(dom_sizeW == real_dom_sizeW + 1,
1372        "LookupAccountSidW() Expected dom_size = %u, got %u\n",
1373        real_dom_sizeW + 1, dom_sizeW);
1374
1375     FreeSid(pUsersSid);
1376
1377     if (pCreateWellKnownSid && pConvertSidToStringSidA)
1378     {
1379         trace("Well Known SIDs:\n");
1380         for (i = 0; i <= 60; i++)
1381         {
1382             size = SECURITY_MAX_SID_SIZE;
1383             if (pCreateWellKnownSid(i, NULL, &max_sid.sid, &size))
1384             {
1385                 if (pConvertSidToStringSidA(&max_sid.sid, &str_sidA))
1386                 {
1387                     acc_sizeA = MAX_PATH;
1388                     dom_sizeA = MAX_PATH;
1389                     if (LookupAccountSidA(NULL, &max_sid.sid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use))
1390                         trace(" %d: %s %s\\%s %d\n", i, str_sidA, domainA, accountA, use);
1391                     LocalFree(str_sidA);
1392                 }
1393             }
1394             else
1395             {
1396                 if (GetLastError() != ERROR_INVALID_PARAMETER)
1397                     trace(" CreateWellKnownSid(%d) failed: %d\n", i, GetLastError());
1398                 else
1399                     trace(" %d: not supported\n", i);
1400             }
1401         }
1402
1403         pLsaQueryInformationPolicy = (fnLsaQueryInformationPolicy)GetProcAddress( hmod, "LsaQueryInformationPolicy");
1404         pLsaOpenPolicy = (fnLsaOpenPolicy)GetProcAddress( hmod, "LsaOpenPolicy");
1405         pLsaFreeMemory = (fnLsaFreeMemory)GetProcAddress( hmod, "LsaFreeMemory");
1406         pLsaClose = (fnLsaClose)GetProcAddress( hmod, "LsaClose");
1407
1408         if (pLsaQueryInformationPolicy && pLsaOpenPolicy && pLsaFreeMemory && pLsaClose)
1409         {
1410             NTSTATUS status;
1411             LSA_HANDLE handle;
1412             LSA_OBJECT_ATTRIBUTES object_attributes;
1413
1414             ZeroMemory(&object_attributes, sizeof(object_attributes));
1415             object_attributes.Length = sizeof(object_attributes);
1416
1417             status = pLsaOpenPolicy( NULL, &object_attributes, POLICY_ALL_ACCESS, &handle);
1418             ok(status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED,
1419                "LsaOpenPolicy(POLICY_ALL_ACCESS) returned 0x%08x\n", status);
1420
1421             /* try a more restricted access mask if necessary */
1422             if (status == STATUS_ACCESS_DENIED) {
1423                 trace("LsaOpenPolicy(POLICY_ALL_ACCESS) failed, trying POLICY_VIEW_LOCAL_INFORMATION\n");
1424                 status = pLsaOpenPolicy( NULL, &object_attributes, POLICY_VIEW_LOCAL_INFORMATION, &handle);
1425                 ok(status == STATUS_SUCCESS, "LsaOpenPolicy(POLICY_VIEW_LOCAL_INFORMATION) returned 0x%08x\n", status);
1426             }
1427
1428             if (status == STATUS_SUCCESS)
1429             {
1430                 PPOLICY_ACCOUNT_DOMAIN_INFO info;
1431                 status = pLsaQueryInformationPolicy(handle, PolicyAccountDomainInformation, (PVOID*)&info);
1432                 ok(status == STATUS_SUCCESS, "LsaQueryInformationPolicy() failed, returned 0x%08x\n", status);
1433                 if (status == STATUS_SUCCESS)
1434                 {
1435                     ok(info->DomainSid!=0, "LsaQueryInformationPolicy(PolicyAccountDomainInformation) missing SID\n");
1436                     if (info->DomainSid)
1437                     {
1438                         int count = *GetSidSubAuthorityCount(info->DomainSid);
1439                         CopySid(GetSidLengthRequired(count), &max_sid, info->DomainSid);
1440                         test_sid_str((PSID)&max_sid.sid);
1441                         max_sid.sid.SubAuthority[count] = DOMAIN_USER_RID_ADMIN;
1442                         max_sid.sid.SubAuthorityCount = count + 1;
1443                         test_sid_str((PSID)&max_sid.sid);
1444                         max_sid.sid.SubAuthority[count] = DOMAIN_USER_RID_GUEST;
1445                         test_sid_str((PSID)&max_sid.sid);
1446                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_ADMINS;
1447                         test_sid_str((PSID)&max_sid.sid);
1448                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_USERS;
1449                         test_sid_str((PSID)&max_sid.sid);
1450                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_GUESTS;
1451                         test_sid_str((PSID)&max_sid.sid);
1452                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_COMPUTERS;
1453                         test_sid_str((PSID)&max_sid.sid);
1454                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_CONTROLLERS;
1455                         test_sid_str((PSID)&max_sid.sid);
1456                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_CERT_ADMINS;
1457                         test_sid_str((PSID)&max_sid.sid);
1458                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_SCHEMA_ADMINS;
1459                         test_sid_str((PSID)&max_sid.sid);
1460                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_ENTERPRISE_ADMINS;
1461                         test_sid_str((PSID)&max_sid.sid);
1462                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_POLICY_ADMINS;
1463                         test_sid_str((PSID)&max_sid.sid);
1464                         max_sid.sid.SubAuthority[count] = DOMAIN_ALIAS_RID_RAS_SERVERS;
1465                         test_sid_str((PSID)&max_sid.sid);
1466                         max_sid.sid.SubAuthority[count] = 1000; /* first user account */
1467                         test_sid_str((PSID)&max_sid.sid);
1468                     }
1469
1470                     pLsaFreeMemory((LPVOID)info);
1471                 }
1472
1473                 status = pLsaClose(handle);
1474                 ok(status == STATUS_SUCCESS, "LsaClose() failed, returned 0x%08x\n", status);
1475             }
1476         }
1477     }
1478 }
1479
1480 static void get_sid_info(PSID psid, LPSTR *user, LPSTR *dom)
1481 {
1482     static CHAR account[UNLEN + 1];
1483     static CHAR domain[UNLEN + 1];
1484     DWORD size, dom_size;
1485     SID_NAME_USE use;
1486
1487     *user = account;
1488     *dom = domain;
1489
1490     size = dom_size = UNLEN + 1;
1491     account[0] = '\0';
1492     domain[0] = '\0';
1493     LookupAccountSidA(NULL, psid, account, &size, domain, &dom_size, &use);
1494 }
1495
1496 static void test_LookupAccountName(void)
1497 {
1498     DWORD sid_size, domain_size, user_size;
1499     DWORD sid_save, domain_save;
1500     CHAR user_name[UNLEN + 1];
1501     SID_NAME_USE sid_use;
1502     LPSTR domain, account, sid_dom;
1503     PSID psid;
1504     BOOL ret;
1505
1506     /* native crashes if (assuming all other parameters correct):
1507      *  - peUse is NULL
1508      *  - Sid is NULL and cbSid is > 0
1509      *  - cbSid or cchReferencedDomainName are NULL
1510      *  - ReferencedDomainName is NULL and cchReferencedDomainName is the correct size
1511      */
1512
1513     user_size = UNLEN + 1;
1514     SetLastError(0xdeadbeef);
1515     ret = GetUserNameA(user_name, &user_size);
1516     if (!ret && (GetLastError() == ERROR_NOT_LOGGED_ON))
1517     {
1518         /* Probably on win9x where the user used 'Cancel' instead of properly logging in */
1519         skip("Cannot get the user name (win9x and not logged in properly)\n");
1520         return;
1521     }
1522     ok(ret, "Failed to get user name : %d\n", GetLastError());
1523
1524     /* get sizes */
1525     sid_size = 0;
1526     domain_size = 0;
1527     sid_use = 0xcafebabe;
1528     SetLastError(0xdeadbeef);
1529     ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, NULL, &domain_size, &sid_use);
1530     if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
1531     {
1532         skip("LookupAccountNameA is not implemented\n");
1533         return;
1534     }
1535     ok(!ret, "Expected 0, got %d\n", ret);
1536     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1537        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1538     ok(sid_size != 0, "Expected non-zero sid size\n");
1539     ok(domain_size != 0, "Expected non-zero domain size\n");
1540     ok(sid_use == 0xcafebabe, "Expected 0xcafebabe, got %d\n", sid_use);
1541
1542     sid_save = sid_size;
1543     domain_save = domain_size;
1544
1545     psid = HeapAlloc(GetProcessHeap(), 0, sid_size);
1546     domain = HeapAlloc(GetProcessHeap(), 0, domain_size);
1547
1548     /* try valid account name */
1549     ret = LookupAccountNameA(NULL, user_name, psid, &sid_size, domain, &domain_size, &sid_use);
1550     get_sid_info(psid, &account, &sid_dom);
1551     ok(ret, "Failed to lookup account name\n");
1552     ok(sid_size == GetLengthSid(psid), "Expected %d, got %d\n", GetLengthSid(psid), sid_size);
1553     todo_wine
1554     {
1555         ok(!lstrcmp(account, user_name), "Expected %s, got %s\n", user_name, account);
1556         ok(!lstrcmp(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
1557         ok(domain_size == domain_save - 1, "Expected %d, got %d\n", domain_save - 1, domain_size);
1558         ok(lstrlen(domain) == domain_size, "Expected %d, got %d\n", lstrlen(domain), domain_size);
1559         ok(sid_use == SidTypeUser, "Expected SidTypeUser (%d), got %d\n", SidTypeUser, sid_use);
1560     }
1561     domain_size = domain_save;
1562     sid_size = sid_save;
1563
1564     if (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH)
1565     {
1566         skip("Non-english locale (test with hardcoded 'Everyone')\n");
1567     }
1568     else
1569     {
1570         ret = LookupAccountNameA(NULL, "Everyone", psid, &sid_size, domain, &domain_size, &sid_use);
1571         get_sid_info(psid, &account, &sid_dom);
1572         ok(ret, "Failed to lookup account name\n");
1573         ok(sid_size != 0, "sid_size was zero\n");
1574         ok(!lstrcmp(account, "Everyone"), "Expected Everyone, got %s\n", account);
1575         todo_wine
1576         ok(!lstrcmp(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
1577         ok(domain_size == 0, "Expected 0, got %d\n", domain_size);
1578         todo_wine
1579         ok(lstrlen(domain) == domain_size, "Expected %d, got %d\n", lstrlen(domain), domain_size);
1580         ok(sid_use == SidTypeWellKnownGroup, "Expected SidTypeWellKnownGroup (%d), got %d\n", SidTypeWellKnownGroup, sid_use);
1581         domain_size = domain_save;
1582     }
1583
1584     /* NULL Sid with zero sid size */
1585     SetLastError(0xdeadbeef);
1586     sid_size = 0;
1587     ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, domain, &domain_size, &sid_use);
1588     ok(!ret, "Expected 0, got %d\n", ret);
1589     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1590        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1591     ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size);
1592     ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
1593
1594     /* try cchReferencedDomainName - 1 */
1595     SetLastError(0xdeadbeef);
1596     domain_size--;
1597     ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, domain, &domain_size, &sid_use);
1598     ok(!ret, "Expected 0, got %d\n", ret);
1599     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1600        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1601     ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size);
1602     ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
1603
1604     /* NULL ReferencedDomainName with zero domain name size */
1605     SetLastError(0xdeadbeef);
1606     domain_size = 0;
1607     ret = LookupAccountNameA(NULL, user_name, psid, &sid_size, NULL, &domain_size, &sid_use);
1608     ok(!ret, "Expected 0, got %d\n", ret);
1609     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1610        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1611     ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size);
1612     ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
1613
1614     HeapFree(GetProcessHeap(), 0, psid);
1615     HeapFree(GetProcessHeap(), 0, domain);
1616
1617     /* get sizes for NULL account name */
1618     sid_size = 0;
1619     domain_size = 0;
1620     sid_use = 0xcafebabe;
1621     SetLastError(0xdeadbeef);
1622     ret = LookupAccountNameA(NULL, NULL, NULL, &sid_size, NULL, &domain_size, &sid_use);
1623     ok(!ret, "Expected 0, got %d\n", ret);
1624     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1625        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1626     ok(sid_size != 0, "Expected non-zero sid size\n");
1627     ok(domain_size != 0, "Expected non-zero domain size\n");
1628     ok(sid_use == 0xcafebabe, "Expected 0xcafebabe, got %d\n", sid_use);
1629
1630     psid = HeapAlloc(GetProcessHeap(), 0, sid_size);
1631     domain = HeapAlloc(GetProcessHeap(), 0, domain_size);
1632
1633     /* try NULL account name */
1634     ret = LookupAccountNameA(NULL, NULL, psid, &sid_size, domain, &domain_size, &sid_use);
1635     get_sid_info(psid, &account, &sid_dom);
1636     ok(ret, "Failed to lookup account name\n");
1637     todo_wine
1638     {
1639         /* Using a fixed string will not work on different locales */
1640         ok(!lstrcmp(account, domain),
1641            "Got %s for account and %s for domain, these should be the same\n",
1642            account, domain);
1643         ok(sid_use == SidTypeDomain, "Expected SidTypeDomain (%d), got %d\n", SidTypeDomain, sid_use);
1644     }
1645
1646     /* try an invalid account name */
1647     SetLastError(0xdeadbeef);
1648     sid_size = 0;
1649     domain_size = 0;
1650     ret = LookupAccountNameA(NULL, "oogabooga", NULL, &sid_size, NULL, &domain_size, &sid_use);
1651     ok(!ret, "Expected 0, got %d\n", ret);
1652     todo_wine
1653     {
1654         ok(GetLastError() == ERROR_NONE_MAPPED ||
1655            broken(GetLastError() == ERROR_TRUSTED_RELATIONSHIP_FAILURE),
1656            "Expected ERROR_NONE_MAPPED, got %d\n", GetLastError());
1657         ok(sid_size == 0, "Expected 0, got %d\n", sid_size);
1658         ok(domain_size == 0, "Expected 0, got %d\n", domain_size);
1659     }
1660
1661     HeapFree(GetProcessHeap(), 0, psid);
1662     HeapFree(GetProcessHeap(), 0, domain);
1663 }
1664
1665 static void test_security_descriptor(void)
1666 {
1667     SECURITY_DESCRIPTOR sd;
1668     char buf[8192];
1669     DWORD size;
1670     BOOL isDefault, isPresent, ret;
1671     PACL pacl;
1672     PSID psid;
1673
1674     SetLastError(0xdeadbeef);
1675     ret = InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
1676     if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1677     {
1678         skip("InitializeSecurityDescriptor is not implemented\n");
1679         return;
1680     }
1681
1682     ok(GetSecurityDescriptorOwner(&sd, &psid, &isDefault), "GetSecurityDescriptorOwner failed\n");
1683     expect_eq(psid, NULL, PSID, "%p");
1684     expect_eq(isDefault, FALSE, BOOL, "%d");
1685     sd.Control |= SE_DACL_PRESENT | SE_SACL_PRESENT;
1686
1687     SetLastError(0xdeadbeef);
1688     size = 5;
1689     expect_eq(MakeSelfRelativeSD(&sd, buf, &size), FALSE, BOOL, "%d");
1690     expect_eq(GetLastError(), ERROR_INSUFFICIENT_BUFFER, DWORD, "%u");
1691     ok(size > 5, "Size not increased\n");
1692     if (size <= 8192)
1693     {
1694         expect_eq(MakeSelfRelativeSD(&sd, buf, &size), TRUE, BOOL, "%d");
1695         ok(GetSecurityDescriptorOwner(&sd, &psid, &isDefault), "GetSecurityDescriptorOwner failed\n");
1696         expect_eq(psid, NULL, PSID, "%p");
1697         expect_eq(isDefault, FALSE, BOOL, "%d");
1698         ok(GetSecurityDescriptorGroup(&sd, &psid, &isDefault), "GetSecurityDescriptorGroup failed\n");
1699         expect_eq(psid, NULL, PSID, "%p");
1700         expect_eq(isDefault, FALSE, BOOL, "%d");
1701         ok(GetSecurityDescriptorDacl(&sd, &isPresent, &pacl, &isDefault), "GetSecurityDescriptorDacl failed\n");
1702         expect_eq(isPresent, TRUE, BOOL, "%d");
1703         expect_eq(psid, NULL, PSID, "%p");
1704         expect_eq(isDefault, FALSE, BOOL, "%d");
1705         ok(GetSecurityDescriptorSacl(&sd, &isPresent, &pacl, &isDefault), "GetSecurityDescriptorSacl failed\n");
1706         expect_eq(isPresent, TRUE, BOOL, "%d");
1707         expect_eq(psid, NULL, PSID, "%p");
1708         expect_eq(isDefault, FALSE, BOOL, "%d");
1709     }
1710 }
1711
1712 #define TEST_GRANTED_ACCESS(a,b) test_granted_access(a,b,0,__LINE__)
1713 #define TEST_GRANTED_ACCESS2(a,b,c) test_granted_access(a,b,c,__LINE__)
1714 static void test_granted_access(HANDLE handle, ACCESS_MASK access,
1715                                 ACCESS_MASK alt, int line)
1716 {
1717     OBJECT_BASIC_INFORMATION obj_info;
1718     NTSTATUS status;
1719
1720     if (!pNtQueryObject)
1721     {
1722         skip_(__FILE__, line)("Not NT platform - skipping tests\n");
1723         return;
1724     }
1725
1726     status = pNtQueryObject( handle, ObjectBasicInformation, &obj_info,
1727                              sizeof(obj_info), NULL );
1728     ok_(__FILE__, line)(!status, "NtQueryObject with err: %08x\n", status);
1729     if (alt)
1730         ok_(__FILE__, line)(obj_info.GrantedAccess == access ||
1731             obj_info.GrantedAccess == alt, "Granted access should be 0x%08x "
1732             "or 0x%08x, instead of 0x%08x\n", access, alt, obj_info.GrantedAccess);
1733     else
1734         ok_(__FILE__, line)(obj_info.GrantedAccess == access, "Granted access should "
1735             "be 0x%08x, instead of 0x%08x\n", access, obj_info.GrantedAccess);
1736 }
1737
1738 #define CHECK_SET_SECURITY(o,i,e) \
1739     do{ \
1740         BOOL res; \
1741         DWORD err; \
1742         SetLastError( 0xdeadbeef ); \
1743         res = SetKernelObjectSecurity( o, i, SecurityDescriptor ); \
1744         err = GetLastError(); \
1745         if (e == ERROR_SUCCESS) \
1746             ok(res, "SetKernelObjectSecurity failed with %d\n", err); \
1747         else \
1748             ok(!res && err == e, "SetKernelObjectSecurity should have failed " \
1749                "with %s, instead of %d\n", #e, err); \
1750     }while(0)
1751
1752 static void test_process_security(void)
1753 {
1754     BOOL res;
1755     char owner[32], group[32];
1756     PSID AdminSid = NULL, UsersSid = NULL;
1757     PACL Acl = NULL;
1758     SECURITY_DESCRIPTOR *SecurityDescriptor = NULL;
1759     char buffer[MAX_PATH];
1760     PROCESS_INFORMATION info;
1761     STARTUPINFOA startup;
1762     SECURITY_ATTRIBUTES psa;
1763     HANDLE token, event;
1764     DWORD tmp;
1765
1766     Acl = HeapAlloc(GetProcessHeap(), 0, 256);
1767     res = InitializeAcl(Acl, 256, ACL_REVISION);
1768     if (!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1769     {
1770         skip("ACLs not implemented - skipping tests\n");
1771         HeapFree(GetProcessHeap(), 0, Acl);
1772         return;
1773     }
1774     ok(res, "InitializeAcl failed with error %d\n", GetLastError());
1775
1776     /* get owner from the token we might be running as a user not admin */
1777     res = OpenProcessToken( GetCurrentProcess(), MAXIMUM_ALLOWED, &token );
1778     ok(res, "OpenProcessToken failed with error %d\n", GetLastError());
1779     if (!res)
1780     {
1781         HeapFree(GetProcessHeap(), 0, Acl);
1782         return;
1783     }
1784
1785     res = GetTokenInformation( token, TokenOwner, owner, sizeof(owner), &tmp );
1786     ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
1787     AdminSid = ((TOKEN_OWNER*)owner)->Owner;
1788     res = GetTokenInformation( token, TokenPrimaryGroup, group, sizeof(group), &tmp );
1789     ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
1790     UsersSid = ((TOKEN_PRIMARY_GROUP*)group)->PrimaryGroup;
1791
1792     CloseHandle( token );
1793     if (!res)
1794     {
1795         HeapFree(GetProcessHeap(), 0, Acl);
1796         return;
1797     }
1798
1799     res = AddAccessDeniedAce(Acl, ACL_REVISION, PROCESS_VM_READ, AdminSid);
1800     ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError());
1801     res = AddAccessAllowedAce(Acl, ACL_REVISION, PROCESS_ALL_ACCESS, AdminSid);
1802     ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
1803
1804     SecurityDescriptor = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
1805     res = InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
1806     ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
1807
1808     event = CreateEvent( NULL, TRUE, TRUE, "test_event" );
1809     ok(event != NULL, "CreateEvent %d\n", GetLastError());
1810
1811     SecurityDescriptor->Revision = 0;
1812     CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_UNKNOWN_REVISION );
1813     SecurityDescriptor->Revision = SECURITY_DESCRIPTOR_REVISION;
1814
1815     CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR );
1816     CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR );
1817     CHECK_SET_SECURITY( event, SACL_SECURITY_INFORMATION, ERROR_ACCESS_DENIED );
1818     CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
1819     /* NULL DACL is valid and means default DACL from token */
1820     SecurityDescriptor->Control |= SE_DACL_PRESENT;
1821     CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
1822
1823     /* Set owner and group and dacl */
1824     res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE);
1825     ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
1826     CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_SUCCESS );
1827     res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, FALSE);
1828     ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
1829     CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_SUCCESS );
1830     res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
1831     ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
1832     CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
1833
1834     sprintf(buffer, "%s tests/security.c test", myARGV[0]);
1835     memset(&startup, 0, sizeof(startup));
1836     startup.cb = sizeof(startup);
1837     startup.dwFlags = STARTF_USESHOWWINDOW;
1838     startup.wShowWindow = SW_SHOWNORMAL;
1839
1840     psa.nLength = sizeof(psa);
1841     psa.lpSecurityDescriptor = SecurityDescriptor;
1842     psa.bInheritHandle = TRUE;
1843
1844     /* Doesn't matter what ACL say we should get full access for ourselves */
1845     ok(CreateProcessA( NULL, buffer, &psa, NULL, FALSE, 0, NULL, NULL, &startup, &info ),
1846         "CreateProcess with err:%d\n", GetLastError());
1847     TEST_GRANTED_ACCESS2( info.hProcess, PROCESS_ALL_ACCESS,
1848                           STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
1849     winetest_wait_child_process( info.hProcess );
1850
1851     CloseHandle( info.hProcess );
1852     CloseHandle( info.hThread );
1853     CloseHandle( event );
1854     HeapFree(GetProcessHeap(), 0, Acl);
1855     HeapFree(GetProcessHeap(), 0, SecurityDescriptor);
1856 }
1857
1858 static void test_process_security_child(void)
1859 {
1860     HANDLE handle, handle1;
1861     BOOL ret;
1862     DWORD err;
1863
1864     handle = OpenProcess( PROCESS_TERMINATE, FALSE, GetCurrentProcessId() );
1865     ok(handle != NULL, "OpenProcess(PROCESS_TERMINATE) with err:%d\n", GetLastError());
1866     TEST_GRANTED_ACCESS( handle, PROCESS_TERMINATE );
1867
1868     ok(DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
1869                         &handle1, 0, TRUE, DUPLICATE_SAME_ACCESS ),
1870        "duplicating handle err:%d\n", GetLastError());
1871     TEST_GRANTED_ACCESS( handle1, PROCESS_TERMINATE );
1872
1873     CloseHandle( handle1 );
1874
1875     SetLastError( 0xdeadbeef );
1876     ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
1877                            &handle1, PROCESS_ALL_ACCESS, TRUE, 0 );
1878     err = GetLastError();
1879     todo_wine
1880     ok(!ret && err == ERROR_ACCESS_DENIED, "duplicating handle should have failed "
1881        "with STATUS_ACCESS_DENIED, instead of err:%d\n", err);
1882
1883     CloseHandle( handle );
1884
1885     /* These two should fail - they are denied by ACL */
1886     handle = OpenProcess( PROCESS_VM_READ, FALSE, GetCurrentProcessId() );
1887     todo_wine
1888     ok(handle == NULL, "OpenProcess(PROCESS_VM_READ) should have failed\n");
1889     handle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId() );
1890     todo_wine
1891     ok(handle == NULL, "OpenProcess(PROCESS_ALL_ACCESS) should have failed\n");
1892
1893     /* Documented privilege elevation */
1894     ok(DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
1895                         &handle, 0, TRUE, DUPLICATE_SAME_ACCESS ),
1896        "duplicating handle err:%d\n", GetLastError());
1897     TEST_GRANTED_ACCESS2( handle, PROCESS_ALL_ACCESS,
1898                           STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
1899
1900     CloseHandle( handle );
1901
1902     /* Same only explicitly asking for all access rights */
1903     ok(DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
1904                         &handle, PROCESS_ALL_ACCESS, TRUE, 0 ),
1905        "duplicating handle err:%d\n", GetLastError());
1906     TEST_GRANTED_ACCESS2( handle, PROCESS_ALL_ACCESS,
1907                           PROCESS_ALL_ACCESS | PROCESS_QUERY_LIMITED_INFORMATION );
1908     ok(DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
1909                         &handle1, PROCESS_VM_READ, TRUE, 0 ),
1910        "duplicating handle err:%d\n", GetLastError());
1911     TEST_GRANTED_ACCESS( handle1, PROCESS_VM_READ );
1912     CloseHandle( handle1 );
1913     CloseHandle( handle );
1914 }
1915
1916 static void test_impersonation_level(void)
1917 {
1918     HANDLE Token, ProcessToken;
1919     HANDLE Token2;
1920     DWORD Size;
1921     TOKEN_PRIVILEGES *Privileges;
1922     TOKEN_USER *User;
1923     PRIVILEGE_SET *PrivilegeSet;
1924     BOOL AccessGranted;
1925     BOOL ret;
1926     HKEY hkey;
1927     DWORD error;
1928
1929     pDuplicateTokenEx = (fnDuplicateTokenEx) GetProcAddress(hmod, "DuplicateTokenEx");
1930     if( !pDuplicateTokenEx ) {
1931         skip("DuplicateTokenEx is not available\n");
1932         return;
1933     }
1934     SetLastError(0xdeadbeef);
1935     ret = ImpersonateSelf(SecurityAnonymous);
1936     if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
1937     {
1938         skip("ImpersonateSelf is not implemented\n");
1939         return;
1940     }
1941     ok(ret, "ImpersonateSelf(SecurityAnonymous) failed with error %d\n", GetLastError());
1942     ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
1943     ok(!ret, "OpenThreadToken should have failed\n");
1944     error = GetLastError();
1945     ok(error == ERROR_CANT_OPEN_ANONYMOUS, "OpenThreadToken on anonymous token should have returned ERROR_CANT_OPEN_ANONYMOUS instead of %d\n", error);
1946     /* can't perform access check when opening object against an anonymous impersonation token */
1947     todo_wine {
1948     error = RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
1949     ok(error == ERROR_INVALID_HANDLE, "RegOpenKeyEx should have failed with ERROR_INVALID_HANDLE instead of %d\n", error);
1950     }
1951     RevertToSelf();
1952
1953     ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
1954     ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1955
1956     ret = pDuplicateTokenEx(ProcessToken,
1957         TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE, NULL,
1958         SecurityAnonymous, TokenImpersonation, &Token);
1959     ok(ret, "DuplicateTokenEx failed with error %d\n", GetLastError());
1960     /* can't increase the impersonation level */
1961     ret = DuplicateToken(Token, SecurityIdentification, &Token2);
1962     error = GetLastError();
1963     ok(!ret && error == ERROR_BAD_IMPERSONATION_LEVEL,
1964         "Duplicating a token and increasing the impersonation level should have failed with ERROR_BAD_IMPERSONATION_LEVEL instead of %d\n", error);
1965     /* we can query anything from an anonymous token, including the user */
1966     ret = GetTokenInformation(Token, TokenUser, NULL, 0, &Size);
1967     error = GetLastError();
1968     ok(!ret && error == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenUser) should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", error);
1969     User = HeapAlloc(GetProcessHeap(), 0, Size);
1970     ret = GetTokenInformation(Token, TokenUser, User, Size, &Size);
1971     ok(ret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
1972     HeapFree(GetProcessHeap(), 0, User);
1973
1974     /* PrivilegeCheck fails with SecurityAnonymous level */
1975     ret = GetTokenInformation(Token, TokenPrivileges, NULL, 0, &Size);
1976     error = GetLastError();
1977     ok(!ret && error == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", error);
1978     Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1979     ret = GetTokenInformation(Token, TokenPrivileges, Privileges, Size, &Size);
1980     ok(ret, "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError());
1981
1982     PrivilegeSet = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(PRIVILEGE_SET, Privilege[Privileges->PrivilegeCount]));
1983     PrivilegeSet->PrivilegeCount = Privileges->PrivilegeCount;
1984     memcpy(PrivilegeSet->Privilege, Privileges->Privileges, PrivilegeSet->PrivilegeCount * sizeof(PrivilegeSet->Privilege[0]));
1985     PrivilegeSet->Control = PRIVILEGE_SET_ALL_NECESSARY;
1986     HeapFree(GetProcessHeap(), 0, Privileges);
1987
1988     ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
1989     error = GetLastError();
1990     ok(!ret && error == ERROR_BAD_IMPERSONATION_LEVEL, "PrivilegeCheck for SecurityAnonymous token should have failed with ERROR_BAD_IMPERSONATION_LEVEL instead of %d\n", error);
1991
1992     CloseHandle(Token);
1993
1994     ret = ImpersonateSelf(SecurityIdentification);
1995     ok(ret, "ImpersonateSelf(SecurityIdentification) failed with error %d\n", GetLastError());
1996     ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
1997     ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1998
1999     /* can't perform access check when opening object against an identification impersonation token */
2000     error = RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
2001     todo_wine {
2002     ok(error == ERROR_INVALID_HANDLE, "RegOpenKeyEx should have failed with ERROR_INVALID_HANDLE instead of %d\n", error);
2003     }
2004     ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
2005     ok(ret, "PrivilegeCheck for SecurityIdentification failed with error %d\n", GetLastError());
2006     CloseHandle(Token);
2007     RevertToSelf();
2008
2009     ret = ImpersonateSelf(SecurityImpersonation);
2010     ok(ret, "ImpersonateSelf(SecurityImpersonation) failed with error %d\n", GetLastError());
2011     ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
2012     ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
2013     error = RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
2014     ok(error == ERROR_SUCCESS, "RegOpenKeyEx should have succeeded instead of failing with %d\n", error);
2015     RegCloseKey(hkey);
2016     ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
2017     ok(ret, "PrivilegeCheck for SecurityImpersonation failed with error %d\n", GetLastError());
2018     RevertToSelf();
2019
2020     CloseHandle(Token);
2021     CloseHandle(ProcessToken);
2022
2023     HeapFree(GetProcessHeap(), 0, PrivilegeSet);
2024 }
2025
2026 static void test_SetEntriesInAcl(void)
2027 {
2028     DWORD res;
2029     PSID EveryoneSid = NULL, UsersSid = NULL;
2030     PACL OldAcl = NULL, NewAcl;
2031     SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
2032     SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
2033     EXPLICIT_ACCESSW ExplicitAccess;
2034     static const WCHAR wszEveryone[] = {'E','v','e','r','y','o','n','e',0};
2035
2036     if (!pSetEntriesInAclW)
2037     {
2038         skip("SetEntriesInAclW is not available\n");
2039         return;
2040     }
2041
2042     NewAcl = (PACL)0xdeadbeef;
2043     res = pSetEntriesInAclW(0, NULL, NULL, &NewAcl);
2044     if(res == ERROR_CALL_NOT_IMPLEMENTED)
2045     {
2046         skip("SetEntriesInAclW is not implemented\n");
2047         return;
2048     }
2049     ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
2050     ok(NewAcl == NULL, "NewAcl=%p, expected NULL\n", NewAcl);
2051
2052     OldAcl = HeapAlloc(GetProcessHeap(), 0, 256);
2053     res = InitializeAcl(OldAcl, 256, ACL_REVISION);
2054     if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2055     {
2056         skip("ACLs not implemented - skipping tests\n");
2057         HeapFree(GetProcessHeap(), 0, OldAcl);
2058         return;
2059     }
2060     ok(res, "InitializeAcl failed with error %d\n", GetLastError());
2061
2062     res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
2063     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
2064
2065     res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
2066         DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid);
2067     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
2068
2069     res = AddAccessAllowedAce(OldAcl, ACL_REVISION, KEY_READ, UsersSid);
2070     ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
2071
2072     ExplicitAccess.grfAccessPermissions = KEY_WRITE;
2073     ExplicitAccess.grfAccessMode = GRANT_ACCESS;
2074     ExplicitAccess.grfInheritance = NO_INHERITANCE;
2075     ExplicitAccess.Trustee.pMultipleTrustee = NULL;
2076     ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2077     ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
2078     ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
2079     ExplicitAccess.Trustee.ptstrName = (LPWSTR)EveryoneSid;
2080     res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
2081     ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
2082     ok(NewAcl != NULL, "returned acl was NULL\n");
2083     LocalFree(NewAcl);
2084
2085     if (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH)
2086     {
2087         skip("Non-english locale (test with hardcoded 'Everyone')\n");
2088     }
2089     else
2090     {
2091         ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_USER;
2092         ExplicitAccess.Trustee.ptstrName = (LPWSTR)wszEveryone;
2093         res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
2094         ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
2095         ok(NewAcl != NULL, "returned acl was NULL\n");
2096         LocalFree(NewAcl);
2097
2098         ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_BAD_FORM;
2099         res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
2100         ok(res == ERROR_INVALID_PARAMETER, "SetEntriesInAclW failed: %u\n", res);
2101         ok(NewAcl == NULL, "returned acl wasn't NULL: %p\n", NewAcl);
2102         LocalFree(NewAcl);
2103
2104         ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_USER;
2105         ExplicitAccess.Trustee.MultipleTrusteeOperation = TRUSTEE_IS_IMPERSONATE;
2106         res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
2107         ok(res == ERROR_INVALID_PARAMETER, "SetEntriesInAclW failed: %u\n", res);
2108         ok(NewAcl == NULL, "returned acl wasn't NULL: %p\n", NewAcl);
2109         LocalFree(NewAcl);
2110
2111         ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2112         ExplicitAccess.grfAccessMode = SET_ACCESS;
2113         res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
2114         ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
2115         ok(NewAcl != NULL, "returned acl was NULL\n");
2116         LocalFree(NewAcl);
2117     }
2118
2119     ExplicitAccess.grfAccessMode = REVOKE_ACCESS;
2120     ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
2121     ExplicitAccess.Trustee.ptstrName = (LPWSTR)UsersSid;
2122     res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
2123     ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
2124     ok(NewAcl != NULL, "returned acl was NULL\n");
2125     LocalFree(NewAcl);
2126
2127     LocalFree(UsersSid);
2128     LocalFree(EveryoneSid);
2129     HeapFree(GetProcessHeap(), 0, OldAcl);
2130 }
2131
2132 static void test_GetNamedSecurityInfoA(void)
2133 {
2134     PSECURITY_DESCRIPTOR pSecDesc;
2135     DWORD revision;
2136     SECURITY_DESCRIPTOR_CONTROL control;
2137     PSID owner;
2138     PSID group;
2139     BOOL owner_defaulted;
2140     BOOL group_defaulted;
2141     DWORD error;
2142     BOOL ret;
2143     CHAR windows_dir[MAX_PATH];
2144
2145     if (!pGetNamedSecurityInfoA)
2146     {
2147         skip("GetNamedSecurityInfoA is not available\n");
2148         return;
2149     }
2150
2151     ret = GetWindowsDirectoryA(windows_dir, MAX_PATH);
2152     ok(ret, "GetWindowsDirectory failed with error %d\n", GetLastError());
2153
2154     SetLastError(0xdeadbeef);
2155     error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,
2156         OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
2157         NULL, NULL, NULL, NULL, &pSecDesc);
2158     if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
2159     {
2160         skip("GetNamedSecurityInfoA is not implemented\n");
2161         return;
2162     }
2163     ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
2164
2165     ret = GetSecurityDescriptorControl(pSecDesc, &control, &revision);
2166     ok(ret, "GetSecurityDescriptorControl failed with error %d\n", GetLastError());
2167     ok((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == (SE_SELF_RELATIVE|SE_DACL_PRESENT),
2168         "control (0x%x) doesn't have (SE_SELF_RELATIVE|SE_DACL_PRESENT) flags set\n", control);
2169     ok(revision == SECURITY_DESCRIPTOR_REVISION1, "revision was %d instead of 1\n", revision);
2170     ret = GetSecurityDescriptorOwner(pSecDesc, &owner, &owner_defaulted);
2171     ok(ret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
2172     ok(owner != NULL, "owner should not be NULL\n");
2173     ret = GetSecurityDescriptorGroup(pSecDesc, &group, &group_defaulted);
2174     ok(ret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
2175     ok(group != NULL, "group should not be NULL\n");
2176 }
2177
2178 static void test_ConvertStringSecurityDescriptor(void)
2179 {
2180     BOOL ret;
2181     PSECURITY_DESCRIPTOR pSD;
2182     static const WCHAR Blank[] = { 0 };
2183
2184     if (!pConvertStringSecurityDescriptorToSecurityDescriptorA)
2185     {
2186         skip("ConvertStringSecurityDescriptorToSecurityDescriptor is not available\n");
2187         return;
2188     }
2189
2190     SetLastError(0xdeadbeef);
2191     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2192         "D:(A;;GA;;;WD)", 0xdeadbeef, &pSD, NULL);
2193     ok(!ret && GetLastError() == ERROR_UNKNOWN_REVISION,
2194         "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_UNKNOWN_REVISION instead of %d\n",
2195         GetLastError());
2196
2197     /* test ACE string type */
2198     SetLastError(0xdeadbeef);
2199     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2200         "D:(A;;GA;;;WD)", SDDL_REVISION_1, &pSD, NULL);
2201     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
2202     LocalFree(pSD);
2203
2204     SetLastError(0xdeadbeef);
2205     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2206         "D:(D;;GA;;;WD)", SDDL_REVISION_1, &pSD, NULL);
2207     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
2208     LocalFree(pSD);
2209
2210     SetLastError(0xdeadbeef);
2211     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2212         "ERROR:(D;;GA;;;WD)", SDDL_REVISION_1, &pSD, NULL);
2213     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2214         "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
2215         GetLastError());
2216
2217     /* test ACE string access rights */
2218     SetLastError(0xdeadbeef);
2219     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2220         "D:(A;;GA;;;WD)", SDDL_REVISION_1, &pSD, NULL);
2221     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
2222     LocalFree(pSD);
2223     SetLastError(0xdeadbeef);
2224     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2225         "D:(A;;GRGWGX;;;WD)", SDDL_REVISION_1, &pSD, NULL);
2226     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
2227     LocalFree(pSD);
2228     SetLastError(0xdeadbeef);
2229     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2230         "D:(A;;RCSDWDWO;;;WD)", SDDL_REVISION_1, &pSD, NULL);
2231     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
2232     LocalFree(pSD);
2233     SetLastError(0xdeadbeef);
2234     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2235         "D:(A;;RPWPCCDCLCSWLODTCR;;;WD)", SDDL_REVISION_1, &pSD, NULL);
2236     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
2237     LocalFree(pSD);
2238     SetLastError(0xdeadbeef);
2239     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2240         "D:(A;;FAFRFWFX;;;WD)", SDDL_REVISION_1, &pSD, NULL);
2241     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
2242     LocalFree(pSD);
2243     SetLastError(0xdeadbeef);
2244     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2245         "D:(A;;KAKRKWKX;;;WD)", SDDL_REVISION_1, &pSD, NULL);
2246     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
2247     LocalFree(pSD);
2248     SetLastError(0xdeadbeef);
2249     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2250         "D:(A;;0xFFFFFFFF;;;WD)", SDDL_REVISION_1, &pSD, NULL);
2251     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
2252     LocalFree(pSD);
2253     SetLastError(0xdeadbeef);
2254     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2255         "S:(AU;;0xFFFFFFFF;;;WD)", SDDL_REVISION_1, &pSD, NULL);
2256     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
2257     LocalFree(pSD);
2258
2259     /* test ACE string access right error case */
2260     SetLastError(0xdeadbeef);
2261     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2262         "D:(A;;ROB;;;WD)", SDDL_REVISION_1, &pSD, NULL);
2263     ok(!ret && GetLastError() == ERROR_INVALID_ACL,
2264         "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_ACL instead of %d\n",
2265         GetLastError());
2266
2267     /* test behaviour with NULL parameters */
2268     SetLastError(0xdeadbeef);
2269     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2270         NULL, 0xdeadbeef, &pSD, NULL);
2271     todo_wine
2272     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2273         "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
2274         GetLastError());
2275
2276     SetLastError(0xdeadbeef);
2277     ret = pConvertStringSecurityDescriptorToSecurityDescriptorW(
2278         NULL, 0xdeadbeef, &pSD, NULL);
2279     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2280         "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
2281         GetLastError());
2282
2283     SetLastError(0xdeadbeef);
2284     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2285         "D:(A;;ROB;;;WD)", 0xdeadbeef, NULL, NULL);
2286     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2287         "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
2288         GetLastError());
2289
2290     SetLastError(0xdeadbeef);
2291     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2292         "D:(A;;ROB;;;WD)", SDDL_REVISION_1, NULL, NULL);
2293     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2294         "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
2295         GetLastError());
2296
2297     /* test behaviour with empty strings */
2298     SetLastError(0xdeadbeef);
2299     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2300         "", SDDL_REVISION_1, &pSD, NULL);
2301     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
2302
2303     SetLastError(0xdeadbeef);
2304     ret = pConvertStringSecurityDescriptorToSecurityDescriptorW(
2305         Blank, SDDL_REVISION_1, &pSD, NULL);
2306     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
2307
2308     /* test ACE string SID */
2309     SetLastError(0xdeadbeef);
2310     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2311         "D:(D;;GA;;;S-1-0-0)", SDDL_REVISION_1, &pSD, NULL);
2312     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
2313     LocalFree(pSD);
2314
2315     SetLastError(0xdeadbeef);
2316     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
2317         "D:(D;;GA;;;Nonexistent account)", SDDL_REVISION_1, &pSD, NULL);
2318     ok(!ret, "Expected failure, got %d\n", ret);
2319     ok(GetLastError() == ERROR_INVALID_ACL || GetLastError() == ERROR_INVALID_SID,
2320        "Expected ERROR_INVALID_ACL or ERROR_INVALID_SID, got %d\n", GetLastError());
2321 }
2322
2323 static void test_ConvertSecurityDescriptorToString()
2324 {
2325     SECURITY_DESCRIPTOR desc;
2326     SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION;
2327     LPSTR string;
2328     DWORD size;
2329     PSID psid, psid2;
2330     PACL pacl;
2331     char sid_buf[256];
2332     char acl_buf[8192];
2333     ULONG len;
2334
2335     if (!pConvertSecurityDescriptorToStringSecurityDescriptorA)
2336     {
2337         skip("ConvertSecurityDescriptorToStringSecurityDescriptor is not available\n");
2338         return;
2339     }
2340     if (!pCreateWellKnownSid)
2341     {
2342         skip("CreateWellKnownSid is not available\n");
2343         return;
2344     }
2345
2346 /* It seems Windows XP adds an extra character to the length of the string for each ACE in an ACL. We
2347  * don't replicate this feature so we only test len >= strlen+1. */
2348 #define CHECK_RESULT_AND_FREE(exp_str) \
2349     ok(strcmp(string, (exp_str)) == 0, "String mismatch (expected \"%s\", got \"%s\")\n", (exp_str), string); \
2350     ok(len >= (lstrlen(exp_str) + 1), "Length mismatch (expected %d, got %d)\n", lstrlen(exp_str) + 1, len); \
2351     LocalFree(string);
2352
2353 #define CHECK_ONE_OF_AND_FREE(exp_str1, exp_str2) \
2354     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); \
2355     ok(len >= (strlen(string) + 1), "Length mismatch (expected %d, got %d)\n", lstrlen(string) + 1, len); \
2356     LocalFree(string);
2357
2358     InitializeSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION);
2359     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
2360     CHECK_RESULT_AND_FREE("");
2361
2362     size = 4096;
2363     pCreateWellKnownSid(WinLocalSid, NULL, sid_buf, &size);
2364     SetSecurityDescriptorOwner(&desc, (PSID)sid_buf, FALSE);
2365     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
2366     CHECK_RESULT_AND_FREE("O:S-1-2-0");
2367
2368     SetSecurityDescriptorOwner(&desc, (PSID)sid_buf, TRUE);
2369     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
2370     CHECK_RESULT_AND_FREE("O:S-1-2-0");
2371
2372     size = sizeof(sid_buf);
2373     pCreateWellKnownSid(WinLocalSystemSid, NULL, sid_buf, &size);
2374     SetSecurityDescriptorOwner(&desc, (PSID)sid_buf, TRUE);
2375     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
2376     CHECK_RESULT_AND_FREE("O:SY");
2377
2378     pConvertStringSidToSidA("S-1-5-21-93476-23408-4576", &psid);
2379     SetSecurityDescriptorGroup(&desc, psid, TRUE);
2380     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
2381     CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576");
2382
2383     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, GROUP_SECURITY_INFORMATION, &string, &len), "Conversion failed\n");
2384     CHECK_RESULT_AND_FREE("G:S-1-5-21-93476-23408-4576");
2385
2386     pacl = (PACL)acl_buf;
2387     InitializeAcl(pacl, sizeof(acl_buf), ACL_REVISION);
2388     SetSecurityDescriptorDacl(&desc, TRUE, pacl, TRUE);
2389     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
2390     CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:");
2391
2392     SetSecurityDescriptorDacl(&desc, TRUE, pacl, FALSE);
2393     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
2394     CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:");
2395
2396     pConvertStringSidToSidA("S-1-5-6", &psid2);
2397     pAddAccessAllowedAceEx(pacl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, 0xf0000000, psid2);
2398     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
2399     CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)");
2400
2401     pAddAccessAllowedAceEx(pacl, ACL_REVISION, INHERIT_ONLY_ACE|INHERITED_ACE, 0x00000003, psid2);
2402     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
2403     CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)");
2404
2405     pAddAccessDeniedAceEx(pacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE, 0xffffffff, psid);
2406     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
2407     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)");
2408
2409
2410     pacl = (PACL)acl_buf;
2411     InitializeAcl(pacl, sizeof(acl_buf), ACL_REVISION);
2412     SetSecurityDescriptorSacl(&desc, TRUE, pacl, FALSE);
2413     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
2414     CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:");
2415
2416     /* fails in win2k */
2417     SetSecurityDescriptorDacl(&desc, TRUE, NULL, FALSE);
2418     pAddAuditAccessAceEx(pacl, ACL_REVISION, VALID_INHERIT_FLAGS, KEY_READ|KEY_WRITE, psid2, TRUE, TRUE);
2419     if (pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len))
2420     {
2421         CHECK_ONE_OF_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)", /* XP */
2422             "O:SYG:S-1-5-21-93476-23408-4576D:NO_ACCESS_CONTROLS:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)" /* Vista */);
2423     }
2424
2425     /* fails in win2k */
2426     pAddAuditAccessAceEx(pacl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, FILE_GENERIC_READ|FILE_GENERIC_WRITE, psid2, TRUE, FALSE);
2427     if (pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len))
2428     {
2429         CHECK_ONE_OF_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)", /* XP */
2430             "O:SYG:S-1-5-21-93476-23408-4576D:NO_ACCESS_CONTROLS:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)" /* Vista */);
2431     }
2432 }
2433
2434 static void test_SetSecurityDescriptorControl (PSECURITY_DESCRIPTOR sec)
2435 {
2436     SECURITY_DESCRIPTOR_CONTROL ref;
2437     SECURITY_DESCRIPTOR_CONTROL test;
2438
2439     SECURITY_DESCRIPTOR_CONTROL const mutable
2440         = SE_DACL_AUTO_INHERIT_REQ | SE_SACL_AUTO_INHERIT_REQ
2441         | SE_DACL_AUTO_INHERITED   | SE_SACL_AUTO_INHERITED
2442         | SE_DACL_PROTECTED        | SE_SACL_PROTECTED
2443         | 0x00000040               | 0x00000080        /* not defined in winnt.h */
2444         ;
2445     SECURITY_DESCRIPTOR_CONTROL const immutable
2446         = SE_OWNER_DEFAULTED       | SE_GROUP_DEFAULTED
2447         | SE_DACL_PRESENT          | SE_DACL_DEFAULTED
2448         | SE_SACL_PRESENT          | SE_SACL_DEFAULTED
2449         | SE_RM_CONTROL_VALID      | SE_SELF_RELATIVE
2450         ;
2451
2452     int     bit;
2453     DWORD   dwRevision;
2454     LPCSTR  fmt = "Expected error %s, got %u\n";
2455
2456     GetSecurityDescriptorControl (sec, &ref, &dwRevision);
2457
2458     /* The mutable bits are mutable regardless of the truth of
2459        SE_DACL_PRESENT and/or SE_SACL_PRESENT */
2460
2461     /* Check call barfs if any bit-of-interest is immutable */
2462     for (bit = 0; bit < 16; ++bit)
2463     {
2464         SECURITY_DESCRIPTOR_CONTROL const bitOfInterest = 1 << bit;
2465         SECURITY_DESCRIPTOR_CONTROL setOrClear = ref & bitOfInterest;
2466
2467         SECURITY_DESCRIPTOR_CONTROL ctrl;
2468
2469         DWORD   dwExpect  = (bitOfInterest & immutable)
2470                           ?  ERROR_INVALID_PARAMETER  :  0xbebecaca;
2471         LPCSTR  strExpect = (bitOfInterest & immutable)
2472                           ? "ERROR_INVALID_PARAMETER" : "0xbebecaca";
2473
2474         ctrl = (bitOfInterest & mutable) ? ref + bitOfInterest : ref;
2475         setOrClear ^= bitOfInterest;
2476         SetLastError (0xbebecaca);
2477         pSetSecurityDescriptorControl (sec, bitOfInterest, setOrClear);
2478         ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ());
2479         GetSecurityDescriptorControl(sec, &test, &dwRevision);
2480         expect_eq(test, ctrl, int, "%x");
2481
2482         ctrl = ref;
2483         setOrClear ^= bitOfInterest;
2484         SetLastError (0xbebecaca);
2485         pSetSecurityDescriptorControl (sec, bitOfInterest, setOrClear);
2486         ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ());
2487         GetSecurityDescriptorControl (sec, &test, &dwRevision);
2488         expect_eq(test, ref, int, "%x");
2489     }
2490
2491     /* Check call barfs if any bit-to-set is immutable
2492        even when not a bit-of-interest */
2493     for (bit = 0; bit < 16; ++bit)
2494     {
2495         SECURITY_DESCRIPTOR_CONTROL const bitsOfInterest = mutable;
2496         SECURITY_DESCRIPTOR_CONTROL setOrClear = ref & bitsOfInterest;
2497
2498         SECURITY_DESCRIPTOR_CONTROL ctrl;
2499
2500         DWORD   dwExpect  = ((1 << bit) & immutable)
2501                           ?  ERROR_INVALID_PARAMETER  :  0xbebecaca;
2502         LPCSTR  strExpect = ((1 << bit) & immutable)
2503                           ? "ERROR_INVALID_PARAMETER" : "0xbebecaca";
2504
2505         ctrl = ((1 << bit) & immutable) ? test : ref | mutable;
2506         setOrClear ^= bitsOfInterest;
2507         SetLastError (0xbebecaca);
2508         pSetSecurityDescriptorControl (sec, bitsOfInterest, setOrClear | (1 << bit));
2509         ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ());
2510         GetSecurityDescriptorControl(sec, &test, &dwRevision);
2511         expect_eq(test, ctrl, int, "%x");
2512
2513         ctrl = ((1 << bit) & immutable) ? test : ref | (1 << bit);
2514         setOrClear ^= bitsOfInterest;
2515         SetLastError (0xbebecaca);
2516         pSetSecurityDescriptorControl (sec, bitsOfInterest, setOrClear | (1 << bit));
2517         ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ());
2518         GetSecurityDescriptorControl(sec, &test, &dwRevision);
2519         expect_eq(test, ctrl, int, "%x");
2520     }
2521 }
2522
2523 static void test_PrivateObjectSecurity(void)
2524 {
2525     SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION;
2526     SECURITY_DESCRIPTOR_CONTROL ctrl;
2527     PSECURITY_DESCRIPTOR sec;
2528     DWORD dwDescSize;
2529     DWORD dwRevision;
2530     DWORD retSize;
2531     LPSTR string;
2532     ULONG len;
2533     PSECURITY_DESCRIPTOR buf;
2534
2535     if (!pConvertStringSecurityDescriptorToSecurityDescriptorA)
2536     {
2537         skip("ConvertStringSecurityDescriptorToSecurityDescriptor is not available\n");
2538         return;
2539     }
2540
2541     ok(pConvertStringSecurityDescriptorToSecurityDescriptorA(
2542         "O:SY"
2543         "G:S-1-5-21-93476-23408-4576"
2544         "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)"
2545           "(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
2546         "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)",
2547         SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n");
2548
2549     test_SetSecurityDescriptorControl(sec);
2550
2551     LocalFree(sec);
2552
2553     ok(pConvertStringSecurityDescriptorToSecurityDescriptorA(
2554         "O:SY"
2555         "G:S-1-5-21-93476-23408-4576",
2556         SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n");
2557
2558     test_SetSecurityDescriptorControl(sec);
2559
2560     LocalFree(sec);
2561
2562     ok(pConvertStringSecurityDescriptorToSecurityDescriptorA(
2563         "O:SY"
2564         "G:S-1-5-21-93476-23408-4576"
2565         "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
2566         "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)", SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n");
2567     buf = HeapAlloc(GetProcessHeap(), 0, dwDescSize);
2568     pSetSecurityDescriptorControl(sec, SE_DACL_PROTECTED, SE_DACL_PROTECTED);
2569     GetSecurityDescriptorControl(sec, &ctrl, &dwRevision);
2570     expect_eq(ctrl, 0x9014, int, "%x");
2571
2572     ok(GetPrivateObjectSecurity(sec, GROUP_SECURITY_INFORMATION, buf, dwDescSize, &retSize),
2573         "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError());
2574     ok(retSize <= dwDescSize, "Buffer too small (%d vs %d)\n", retSize, dwDescSize);
2575     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
2576     CHECK_RESULT_AND_FREE("G:S-1-5-21-93476-23408-4576");
2577     GetSecurityDescriptorControl(buf, &ctrl, &dwRevision);
2578     expect_eq(ctrl, 0x8000, int, "%x");
2579
2580     ok(GetPrivateObjectSecurity(sec, GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, buf, dwDescSize, &retSize),
2581         "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError());
2582     ok(retSize <= dwDescSize, "Buffer too small (%d vs %d)\n", retSize, dwDescSize);
2583     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed err=%u\n", GetLastError());
2584     CHECK_RESULT_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)");
2585     GetSecurityDescriptorControl(buf, &ctrl, &dwRevision);
2586     expect_eq(ctrl, 0x8004, int, "%x");
2587
2588     ok(GetPrivateObjectSecurity(sec, sec_info, buf, dwDescSize, &retSize),
2589         "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError());
2590     ok(retSize == dwDescSize, "Buffer too small (%d vs %d)\n", retSize, dwDescSize);
2591     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
2592     CHECK_RESULT_AND_FREE("O:SY"
2593         "G:S-1-5-21-93476-23408-4576"
2594         "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
2595         "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)");
2596     GetSecurityDescriptorControl(buf, &ctrl, &dwRevision);
2597     expect_eq(ctrl, 0x8014, int, "%x");
2598
2599     SetLastError(0xdeadbeef);
2600     ok(GetPrivateObjectSecurity(sec, sec_info, buf, 5, &retSize) == FALSE, "GetPrivateObjectSecurity should have failed\n");
2601     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected error ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
2602
2603     LocalFree(sec);
2604     HeapFree(GetProcessHeap(), 0, buf);
2605 }
2606 #undef CHECK_RESULT_AND_FREE
2607 #undef CHECK_ONE_OF_AND_FREE
2608
2609 static void test_acls(void)
2610 {
2611     char buffer[256];
2612     PACL pAcl = (PACL)buffer;
2613     BOOL ret;
2614
2615     SetLastError(0xdeadbeef);
2616     ret = InitializeAcl(pAcl, sizeof(ACL) - 1, ACL_REVISION);
2617     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2618     {
2619         skip("InitializeAcl is not implemented\n");
2620         return;
2621     }
2622
2623     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InitializeAcl with too small a buffer should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", GetLastError());
2624
2625     SetLastError(0xdeadbeef);
2626     ret = InitializeAcl(pAcl, 0xffffffff, ACL_REVISION);
2627     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl with too large a buffer should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
2628
2629     SetLastError(0xdeadbeef);
2630     ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION1);
2631     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl(ACL_REVISION1) should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
2632
2633     ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION2);
2634     ok(ret, "InitializeAcl(ACL_REVISION2) failed with error %d\n", GetLastError());
2635
2636     ret = IsValidAcl(pAcl);
2637     ok(ret, "IsValidAcl failed with error %d\n", GetLastError());
2638
2639     ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION3);
2640     ok(ret, "InitializeAcl(ACL_REVISION3) failed with error %d\n", GetLastError());
2641
2642     ret = IsValidAcl(pAcl);
2643     ok(ret, "IsValidAcl failed with error %d\n", GetLastError());
2644
2645     ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION4);
2646     ok(ret, "InitializeAcl(ACL_REVISION4) failed with error %d\n", GetLastError());
2647
2648     ret = IsValidAcl(pAcl);
2649     ok(ret, "IsValidAcl failed with error %d\n", GetLastError());
2650
2651     SetLastError(0xdeadbeef);
2652     ret = InitializeAcl(pAcl, sizeof(buffer), -1);
2653     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl(-1) failed with error %d\n", GetLastError());
2654 }
2655
2656 static void test_GetSecurityInfo(void)
2657 {
2658     HANDLE obj;
2659     PSECURITY_DESCRIPTOR sd;
2660     PSID owner, group;
2661     PACL dacl;
2662     DWORD ret;
2663
2664     if (!pGetSecurityInfo)
2665     {
2666         win_skip("GetSecurityInfo is not available\n");
2667         return;
2668     }
2669
2670     /* Create something.  Files have lots of associated security info.  */
2671     obj = CreateFile(myARGV[0], GENERIC_READ, FILE_SHARE_READ, NULL,
2672                      OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2673     if (obj == INVALID_HANDLE_VALUE)
2674     {
2675         skip("Couldn't create an object for GetSecurityInfo test\n");
2676         return;
2677     }
2678
2679     ret = pGetSecurityInfo(obj, SE_FILE_OBJECT,
2680                           OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
2681                           &owner, &group, &dacl, NULL, &sd);
2682     if (ret == ERROR_CALL_NOT_IMPLEMENTED)
2683     {
2684         win_skip("GetSecurityInfo is not implemented\n");
2685         CloseHandle(obj);
2686         return;
2687     }
2688     ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret);
2689     ok(sd != NULL, "GetSecurityInfo\n");
2690     ok(owner != NULL, "GetSecurityInfo\n");
2691     ok(group != NULL, "GetSecurityInfo\n");
2692     ok(dacl != NULL, "GetSecurityInfo\n");
2693     ok(IsValidAcl(dacl), "GetSecurityInfo\n");
2694
2695     LocalFree(sd);
2696
2697     /* If we don't ask for the security descriptor, Windows will still give us
2698        the other stuff, leaving us no way to free it.  */
2699     ret = pGetSecurityInfo(obj, SE_FILE_OBJECT,
2700                           OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
2701                           &owner, &group, &dacl, NULL, NULL);
2702     ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret);
2703     ok(owner != NULL, "GetSecurityInfo\n");
2704     ok(group != NULL, "GetSecurityInfo\n");
2705     ok(dacl != NULL, "GetSecurityInfo\n");
2706     ok(IsValidAcl(dacl), "GetSecurityInfo\n");
2707
2708     CloseHandle(obj);
2709 }
2710
2711 START_TEST(security)
2712 {
2713     init();
2714     if (!hmod) return;
2715
2716     if (myARGC >= 3)
2717     {
2718         test_process_security_child();
2719         return;
2720     }
2721     test_sid();
2722     test_trustee();
2723     test_luid();
2724     test_CreateWellKnownSid();
2725     test_FileSecurity();
2726     test_AccessCheck();
2727     test_token_attr();
2728     test_LookupAccountSid();
2729     test_LookupAccountName();
2730     test_security_descriptor();
2731     test_process_security();
2732     test_impersonation_level();
2733     test_SetEntriesInAcl();
2734     test_GetNamedSecurityInfoA();
2735     test_ConvertStringSecurityDescriptor();
2736     test_ConvertSecurityDescriptorToString();
2737     test_PrivateObjectSecurity();
2738     test_acls();
2739     test_GetSecurityInfo();
2740 }