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