Assorted spelling fixes.
[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 #include "winternl.h"
35
36 #include "wine/test.h"
37
38 typedef VOID (WINAPI *fnBuildTrusteeWithSidA)( PTRUSTEEA pTrustee, PSID pSid );
39 typedef VOID (WINAPI *fnBuildTrusteeWithNameA)( PTRUSTEEA pTrustee, LPSTR pName );
40 typedef VOID (WINAPI *fnBuildTrusteeWithObjectsAndNameA)( PTRUSTEEA pTrustee,
41                                                           POBJECTS_AND_NAME_A pObjName,
42                                                           SE_OBJECT_TYPE ObjectType,
43                                                           LPSTR ObjectTypeName,
44                                                           LPSTR InheritedObjectTypeName,
45                                                           LPSTR Name );
46 typedef VOID (WINAPI *fnBuildTrusteeWithObjectsAndSidA)( PTRUSTEEA pTrustee,
47                                                          POBJECTS_AND_SID pObjSid,
48                                                          GUID* pObjectGuid,
49                                                          GUID* pInheritedObjectGuid,
50                                                          PSID pSid );
51 typedef LPSTR (WINAPI *fnGetTrusteeNameA)( PTRUSTEEA pTrustee );
52 typedef BOOL (WINAPI *fnConvertSidToStringSidA)( PSID pSid, LPSTR *str );
53 typedef BOOL (WINAPI *fnConvertStringSidToSidA)( LPCSTR str, PSID pSid );
54 static BOOL (WINAPI *pConvertStringSecurityDescriptorToSecurityDescriptorA)(LPCSTR, DWORD,
55                                                                             PSECURITY_DESCRIPTOR*, PULONG );
56 typedef BOOL (WINAPI *fnGetFileSecurityA)(LPCSTR, SECURITY_INFORMATION,
57                                           PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
58 typedef DWORD (WINAPI *fnRtlAdjustPrivilege)(ULONG,BOOLEAN,BOOLEAN,PBOOLEAN);
59 typedef BOOL (WINAPI *fnCreateWellKnownSid)(WELL_KNOWN_SID_TYPE,PSID,PSID,DWORD*);
60 typedef BOOL (WINAPI *fnDuplicateTokenEx)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES,
61                                         SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,PHANDLE);
62
63 typedef NTSTATUS (WINAPI *fnLsaQueryInformationPolicy)(LSA_HANDLE,POLICY_INFORMATION_CLASS,PVOID*);
64 typedef NTSTATUS (WINAPI *fnLsaClose)(LSA_HANDLE);
65 typedef NTSTATUS (WINAPI *fnLsaFreeMemory)(PVOID);
66 typedef NTSTATUS (WINAPI *fnLsaOpenPolicy)(PLSA_UNICODE_STRING,PLSA_OBJECT_ATTRIBUTES,ACCESS_MASK,PLSA_HANDLE);
67 static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,ULONG,PULONG);
68
69 static HMODULE hmod;
70 static int     myARGC;
71 static char**  myARGV;
72
73 fnBuildTrusteeWithSidA   pBuildTrusteeWithSidA;
74 fnBuildTrusteeWithNameA  pBuildTrusteeWithNameA;
75 fnBuildTrusteeWithObjectsAndNameA pBuildTrusteeWithObjectsAndNameA;
76 fnBuildTrusteeWithObjectsAndSidA pBuildTrusteeWithObjectsAndSidA;
77 fnGetTrusteeNameA pGetTrusteeNameA;
78 fnConvertSidToStringSidA pConvertSidToStringSidA;
79 fnConvertStringSidToSidA pConvertStringSidToSidA;
80 fnGetFileSecurityA pGetFileSecurityA;
81 fnRtlAdjustPrivilege pRtlAdjustPrivilege;
82 fnCreateWellKnownSid pCreateWellKnownSid;
83 fnDuplicateTokenEx pDuplicateTokenEx;
84 fnLsaQueryInformationPolicy pLsaQueryInformationPolicy;
85 fnLsaClose pLsaClose;
86 fnLsaFreeMemory pLsaFreeMemory;
87 fnLsaOpenPolicy pLsaOpenPolicy;
88
89 struct sidRef
90 {
91     SID_IDENTIFIER_AUTHORITY auth;
92     const char *refStr;
93 };
94
95 static void init(void)
96 {
97     HMODULE hntdll;
98
99     hntdll = GetModuleHandleA("ntdll.dll");
100     pNtQueryObject = (void *)GetProcAddress( hntdll, "NtQueryObject" );
101
102     hmod = GetModuleHandle("advapi32.dll");
103     pConvertStringSecurityDescriptorToSecurityDescriptorA =
104         (void *)GetProcAddress(hmod, "ConvertStringSecurityDescriptorToSecurityDescriptorA" );
105
106     myARGC = winetest_get_mainargs( &myARGV );
107 }
108
109 static void test_str_sid(const char *str_sid)
110 {
111     PSID psid;
112     char *temp;
113
114     if (pConvertStringSidToSidA(str_sid, &psid))
115     {
116         if (pConvertSidToStringSidA(psid, &temp))
117         {
118             trace(" %s: %s\n", str_sid, temp);
119             LocalFree(temp);
120         }
121         LocalFree(psid);
122     }
123     else
124     {
125         if (GetLastError() != ERROR_INVALID_SID)
126             trace(" %s: couldn't be converted, returned %d\n", str_sid, GetLastError());
127         else
128             trace(" %s: couldn't be converted\n", str_sid);
129     }
130 }
131
132 static void test_sid(void)
133 {
134     struct sidRef refs[] = {
135      { { {0x00,0x00,0x33,0x44,0x55,0x66} }, "S-1-860116326-1" },
136      { { {0x00,0x00,0x01,0x02,0x03,0x04} }, "S-1-16909060-1"  },
137      { { {0x00,0x00,0x00,0x01,0x02,0x03} }, "S-1-66051-1"     },
138      { { {0x00,0x00,0x00,0x00,0x01,0x02} }, "S-1-258-1"       },
139      { { {0x00,0x00,0x00,0x00,0x00,0x02} }, "S-1-2-1"         },
140      { { {0x00,0x00,0x00,0x00,0x00,0x0c} }, "S-1-12-1"        },
141     };
142     const char noSubAuthStr[] = "S-1-5";
143     unsigned int i;
144     PSID psid = NULL;
145     BOOL r;
146     LPSTR str = NULL;
147
148     pConvertSidToStringSidA = (fnConvertSidToStringSidA)
149                     GetProcAddress( hmod, "ConvertSidToStringSidA" );
150     if( !pConvertSidToStringSidA )
151         return;
152     pConvertStringSidToSidA = (fnConvertStringSidToSidA)
153                     GetProcAddress( hmod, "ConvertStringSidToSidA" );
154     if( !pConvertStringSidToSidA )
155         return;
156
157     r = pConvertStringSidToSidA( NULL, NULL );
158     ok( !r, "expected failure with NULL parameters\n" );
159     if( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED )
160         return;
161     ok( GetLastError() == ERROR_INVALID_PARAMETER,
162      "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n",
163      GetLastError() );
164
165     r = pConvertStringSidToSidA( refs[0].refStr, NULL );
166     ok( !r && GetLastError() == ERROR_INVALID_PARAMETER,
167      "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n",
168      GetLastError() );
169
170     r = pConvertStringSidToSidA( NULL, &str );
171     ok( !r && GetLastError() == ERROR_INVALID_PARAMETER,
172      "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n",
173      GetLastError() );
174
175     r = pConvertStringSidToSidA( noSubAuthStr, &psid );
176     ok( !r,
177      "expected failure with no sub authorities\n" );
178     ok( GetLastError() == ERROR_INVALID_SID,
179      "expected GetLastError() is ERROR_INVALID_SID, got %d\n",
180      GetLastError() );
181
182     for( i = 0; i < sizeof(refs) / sizeof(refs[0]); i++ )
183     {
184         PISID pisid;
185
186         r = AllocateAndInitializeSid( &refs[i].auth, 1,1,0,0,0,0,0,0,0,
187          &psid );
188         ok( r, "failed to allocate sid\n" );
189         r = pConvertSidToStringSidA( psid, &str );
190         ok( r, "failed to convert sid\n" );
191         if (r)
192         {
193             ok( !strcmp( str, refs[i].refStr ),
194                 "incorrect sid, expected %s, got %s\n", refs[i].refStr, str );
195             LocalFree( str );
196         }
197         if( psid )
198             FreeSid( psid );
199
200         r = pConvertStringSidToSidA( refs[i].refStr, &psid );
201         ok( r, "failed to parse sid string\n" );
202         pisid = (PISID)psid;
203         ok( pisid &&
204          !memcmp( pisid->IdentifierAuthority.Value, refs[i].auth.Value,
205          sizeof(refs[i].auth) ),
206          "string sid %s didn't parse to expected value\n"
207          "(got 0x%04x%08x, expected 0x%04x%08x)\n",
208          refs[i].refStr,
209          MAKEWORD( pisid->IdentifierAuthority.Value[1],
210          pisid->IdentifierAuthority.Value[0] ),
211          MAKELONG( MAKEWORD( pisid->IdentifierAuthority.Value[5],
212          pisid->IdentifierAuthority.Value[4] ),
213          MAKEWORD( pisid->IdentifierAuthority.Value[3],
214          pisid->IdentifierAuthority.Value[2] ) ),
215          MAKEWORD( refs[i].auth.Value[1], refs[i].auth.Value[0] ),
216          MAKELONG( MAKEWORD( refs[i].auth.Value[5], refs[i].auth.Value[4] ),
217          MAKEWORD( refs[i].auth.Value[3], refs[i].auth.Value[2] ) ) );
218         if( psid )
219             LocalFree( psid );
220     }
221
222     trace("String SIDs:\n");
223     test_str_sid("AO");
224     test_str_sid("RU");
225     test_str_sid("AN");
226     test_str_sid("AU");
227     test_str_sid("BA");
228     test_str_sid("BG");
229     test_str_sid("BO");
230     test_str_sid("BU");
231     test_str_sid("CA");
232     test_str_sid("CG");
233     test_str_sid("CO");
234     test_str_sid("DA");
235     test_str_sid("DC");
236     test_str_sid("DD");
237     test_str_sid("DG");
238     test_str_sid("DU");
239     test_str_sid("EA");
240     test_str_sid("ED");
241     test_str_sid("WD");
242     test_str_sid("PA");
243     test_str_sid("IU");
244     test_str_sid("LA");
245     test_str_sid("LG");
246     test_str_sid("LS");
247     test_str_sid("SY");
248     test_str_sid("NU");
249     test_str_sid("NO");
250     test_str_sid("NS");
251     test_str_sid("PO");
252     test_str_sid("PS");
253     test_str_sid("PU");
254     test_str_sid("RS");
255     test_str_sid("RD");
256     test_str_sid("RE");
257     test_str_sid("RC");
258     test_str_sid("SA");
259     test_str_sid("SO");
260     test_str_sid("SU");
261 }
262
263 static void test_trustee(void)
264 {
265     GUID ObjectType = {0x12345678, 0x1234, 0x5678, {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}};
266     GUID InheritedObjectType = {0x23456789, 0x2345, 0x6786, {0x2, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}};
267     GUID ZeroGuid;
268     OBJECTS_AND_NAME_ oan;
269     OBJECTS_AND_SID oas;
270     TRUSTEE trustee;
271     PSID psid;
272     char szObjectTypeName[] = "ObjectTypeName";
273     char szInheritedObjectTypeName[] = "InheritedObjectTypeName";
274     char szTrusteeName[] = "szTrusteeName";
275     SID_IDENTIFIER_AUTHORITY auth = { {0x11,0x22,0,0,0, 0} };
276
277     memset( &ZeroGuid, 0x00, sizeof (ZeroGuid) );
278
279     pBuildTrusteeWithSidA = (fnBuildTrusteeWithSidA)
280                     GetProcAddress( hmod, "BuildTrusteeWithSidA" );
281     pBuildTrusteeWithNameA = (fnBuildTrusteeWithNameA)
282                     GetProcAddress( hmod, "BuildTrusteeWithNameA" );
283     pBuildTrusteeWithObjectsAndNameA = (fnBuildTrusteeWithObjectsAndNameA)
284                     GetProcAddress (hmod, "BuildTrusteeWithObjectsAndNameA" );
285     pBuildTrusteeWithObjectsAndSidA = (fnBuildTrusteeWithObjectsAndSidA)
286                     GetProcAddress (hmod, "BuildTrusteeWithObjectsAndSidA" );
287     pGetTrusteeNameA = (fnGetTrusteeNameA)
288                     GetProcAddress (hmod, "GetTrusteeNameA" );
289     if( !pBuildTrusteeWithSidA || !pBuildTrusteeWithNameA ||
290         !pBuildTrusteeWithObjectsAndNameA || !pBuildTrusteeWithObjectsAndSidA ||
291         !pGetTrusteeNameA )
292         return;
293
294     if ( ! AllocateAndInitializeSid( &auth, 1, 42, 0,0,0,0,0,0,0,&psid ) )
295     {
296         trace( "failed to init SID\n" );
297        return;
298     }
299
300     /* test BuildTrusteeWithSidA */
301     memset( &trustee, 0xff, sizeof trustee );
302     pBuildTrusteeWithSidA( &trustee, psid );
303
304     ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
305     ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, 
306         "MultipleTrusteeOperation wrong\n");
307     ok( trustee.TrusteeForm == TRUSTEE_IS_SID, "TrusteeForm wrong\n");
308     ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
309     ok( trustee.ptstrName == (LPSTR) psid, "ptstrName wrong\n" );
310
311     /* test BuildTrusteeWithObjectsAndSidA (test 1) */
312     memset( &trustee, 0xff, sizeof trustee );
313     memset( &oas, 0xff, sizeof(oas) );
314     pBuildTrusteeWithObjectsAndSidA(&trustee, &oas, &ObjectType,
315                                     &InheritedObjectType, psid);
316
317     ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
318     ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
319     ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_SID, "TrusteeForm wrong\n");
320     ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
321     ok(trustee.ptstrName == (LPSTR)&oas, "ptstrName wrong\n");
322  
323     ok(oas.ObjectsPresent == (ACE_OBJECT_TYPE_PRESENT | ACE_INHERITED_OBJECT_TYPE_PRESENT), "ObjectsPresent wrong\n");
324     ok(!memcmp(&oas.ObjectTypeGuid, &ObjectType, sizeof(GUID)), "ObjectTypeGuid wrong\n");
325     ok(!memcmp(&oas.InheritedObjectTypeGuid, &InheritedObjectType, sizeof(GUID)), "InheritedObjectTypeGuid wrong\n");
326     ok(oas.pSid == psid, "pSid wrong\n");
327
328     /* test GetTrusteeNameA */
329     ok(pGetTrusteeNameA(&trustee) == (LPSTR)&oas, "GetTrusteeName returned wrong value\n");
330
331     /* test BuildTrusteeWithObjectsAndSidA (test 2) */
332     memset( &trustee, 0xff, sizeof trustee );
333     memset( &oas, 0xff, sizeof(oas) );
334     pBuildTrusteeWithObjectsAndSidA(&trustee, &oas, NULL,
335                                     &InheritedObjectType, psid);
336
337     ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
338     ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
339     ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_SID, "TrusteeForm wrong\n");
340     ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
341     ok(trustee.ptstrName == (LPSTR)&oas, "ptstrName wrong\n");
342  
343     ok(oas.ObjectsPresent == ACE_INHERITED_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
344     ok(!memcmp(&oas.ObjectTypeGuid, &ZeroGuid, sizeof(GUID)), "ObjectTypeGuid wrong\n");
345     ok(!memcmp(&oas.InheritedObjectTypeGuid, &InheritedObjectType, sizeof(GUID)), "InheritedObjectTypeGuid wrong\n");
346     ok(oas.pSid == psid, "pSid wrong\n");
347
348     FreeSid( psid );
349
350     /* test BuildTrusteeWithNameA */
351     memset( &trustee, 0xff, sizeof trustee );
352     pBuildTrusteeWithNameA( &trustee, szTrusteeName );
353
354     ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
355     ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, 
356         "MultipleTrusteeOperation wrong\n");
357     ok( trustee.TrusteeForm == TRUSTEE_IS_NAME, "TrusteeForm wrong\n");
358     ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
359     ok( trustee.ptstrName == szTrusteeName, "ptstrName wrong\n" );
360
361     /* test BuildTrusteeWithObjectsAndNameA (test 1) */
362     memset( &trustee, 0xff, sizeof trustee );
363     memset( &oan, 0xff, sizeof(oan) );
364     pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, szObjectTypeName,
365                                      szInheritedObjectTypeName, szTrusteeName);
366
367     ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
368     ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
369     ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
370     ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
371     ok(trustee.ptstrName == (LPTSTR)&oan, "ptstrName wrong\n");
372  
373     ok(oan.ObjectsPresent == (ACE_OBJECT_TYPE_PRESENT | ACE_INHERITED_OBJECT_TYPE_PRESENT), "ObjectsPresent wrong\n");
374     ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
375     ok(oan.InheritedObjectTypeName == szInheritedObjectTypeName, "InheritedObjectTypeName wrong\n");
376     ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
377
378     /* test GetTrusteeNameA */
379     ok(pGetTrusteeNameA(&trustee) == (LPSTR)&oan, "GetTrusteeName returned wrong value\n");
380
381     /* test BuildTrusteeWithObjectsAndNameA (test 2) */
382     memset( &trustee, 0xff, sizeof trustee );
383     memset( &oan, 0xff, sizeof(oan) );
384     pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, NULL,
385                                      szInheritedObjectTypeName, szTrusteeName);
386
387     ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
388     ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
389     ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
390     ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
391     ok(trustee.ptstrName == (LPSTR)&oan, "ptstrName wrong\n");
392  
393     ok(oan.ObjectsPresent == ACE_INHERITED_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
394     ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
395     ok(oan.InheritedObjectTypeName == szInheritedObjectTypeName, "InheritedObjectTypeName wrong\n");
396     ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
397
398     /* test BuildTrusteeWithObjectsAndNameA (test 3) */
399     memset( &trustee, 0xff, sizeof trustee );
400     memset( &oan, 0xff, sizeof(oan) );
401     pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, szObjectTypeName,
402                                      NULL, szTrusteeName);
403
404     ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
405     ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
406     ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
407     ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
408     ok(trustee.ptstrName == (LPTSTR)&oan, "ptstrName wrong\n");
409  
410     ok(oan.ObjectsPresent == ACE_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
411     ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
412     ok(oan.InheritedObjectTypeName == NULL, "InheritedObjectTypeName wrong\n");
413     ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
414 }
415  
416 /* If the first isn't defined, assume none is */
417 #ifndef SE_MIN_WELL_KNOWN_PRIVILEGE
418 #define SE_MIN_WELL_KNOWN_PRIVILEGE       2L
419 #define SE_CREATE_TOKEN_PRIVILEGE         2L
420 #define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE   3L
421 #define SE_LOCK_MEMORY_PRIVILEGE          4L
422 #define SE_INCREASE_QUOTA_PRIVILEGE       5L
423 #define SE_MACHINE_ACCOUNT_PRIVILEGE      6L
424 #define SE_TCB_PRIVILEGE                  7L
425 #define SE_SECURITY_PRIVILEGE             8L
426 #define SE_TAKE_OWNERSHIP_PRIVILEGE       9L
427 #define SE_LOAD_DRIVER_PRIVILEGE         10L
428 #define SE_SYSTEM_PROFILE_PRIVILEGE      11L
429 #define SE_SYSTEMTIME_PRIVILEGE          12L
430 #define SE_PROF_SINGLE_PROCESS_PRIVILEGE 13L
431 #define SE_INC_BASE_PRIORITY_PRIVILEGE   14L
432 #define SE_CREATE_PAGEFILE_PRIVILEGE     15L
433 #define SE_CREATE_PERMANENT_PRIVILEGE    16L
434 #define SE_BACKUP_PRIVILEGE              17L
435 #define SE_RESTORE_PRIVILEGE             18L
436 #define SE_SHUTDOWN_PRIVILEGE            19L
437 #define SE_DEBUG_PRIVILEGE               20L
438 #define SE_AUDIT_PRIVILEGE               21L
439 #define SE_SYSTEM_ENVIRONMENT_PRIVILEGE  22L
440 #define SE_CHANGE_NOTIFY_PRIVILLEGE      23L
441 #define SE_REMOTE_SHUTDOWN_PRIVILEGE     24L
442 #define SE_UNDOCK_PRIVILEGE              25L
443 #define SE_SYNC_AGENT_PRIVILEGE          26L
444 #define SE_ENABLE_DELEGATION_PRIVILEGE   27L
445 #define SE_MANAGE_VOLUME_PRIVILEGE       28L
446 #define SE_IMPERSONATE_PRIVILEGE         29L
447 #define SE_CREATE_GLOBAL_PRIVILEGE       30L
448 #define SE_MAX_WELL_KNOWN_PRIVILEGE      SE_CREATE_GLOBAL_PRIVILEGE
449 #endif /* ndef SE_MIN_WELL_KNOWN_PRIVILEGE */
450
451 static void test_allocateLuid(void)
452 {
453     BOOL (WINAPI *pAllocateLocallyUniqueId)(PLUID);
454     LUID luid1, luid2;
455     BOOL ret;
456
457     pAllocateLocallyUniqueId = (void*)GetProcAddress(hmod, "AllocateLocallyUniqueId");
458     if (!pAllocateLocallyUniqueId) return;
459
460     ret = pAllocateLocallyUniqueId(&luid1);
461     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
462         return;
463
464     ok(ret,
465      "AllocateLocallyUniqueId failed: %d\n", GetLastError());
466     ret = pAllocateLocallyUniqueId(&luid2);
467     ok( ret,
468      "AllocateLocallyUniqueId failed: %d\n", GetLastError());
469     ok(luid1.LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE || luid1.HighPart != 0,
470      "AllocateLocallyUniqueId returned a well-known LUID\n");
471     ok(luid1.LowPart != luid2.LowPart || luid1.HighPart != luid2.HighPart,
472      "AllocateLocallyUniqueId returned non-unique LUIDs\n");
473     ret = pAllocateLocallyUniqueId(NULL);
474     ok( !ret && GetLastError() == ERROR_NOACCESS,
475      "AllocateLocallyUniqueId(NULL) didn't return ERROR_NOACCESS: %d\n",
476      GetLastError());
477 }
478
479 static void test_lookupPrivilegeName(void)
480 {
481     BOOL (WINAPI *pLookupPrivilegeNameA)(LPCSTR, PLUID, LPSTR, LPDWORD);
482     char buf[MAX_PATH]; /* arbitrary, seems long enough */
483     DWORD cchName = sizeof(buf);
484     LUID luid = { 0, 0 };
485     LONG i;
486     BOOL ret;
487
488     /* check whether it's available first */
489     pLookupPrivilegeNameA = (void*)GetProcAddress(hmod, "LookupPrivilegeNameA");
490     if (!pLookupPrivilegeNameA) return;
491     luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
492     ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
493     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
494         return;
495
496     /* check with a short buffer */
497     cchName = 0;
498     luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
499     ret = pLookupPrivilegeNameA(NULL, &luid, NULL, &cchName);
500     ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
501      "LookupPrivilegeNameA didn't fail with ERROR_INSUFFICIENT_BUFFER: %d\n",
502      GetLastError());
503     ok(cchName == strlen("SeCreateTokenPrivilege") + 1,
504      "LookupPrivilegeNameA returned an incorrect required length for\n"
505      "SeCreateTokenPrivilege (got %d, expected %d)\n", cchName,
506      lstrlenA("SeCreateTokenPrivilege") + 1);
507     /* check a known value and its returned length on success */
508     cchName = sizeof(buf);
509     ok(pLookupPrivilegeNameA(NULL, &luid, buf, &cchName) &&
510      cchName == strlen("SeCreateTokenPrivilege"),
511      "LookupPrivilegeNameA returned an incorrect output length for\n"
512      "SeCreateTokenPrivilege (got %d, expected %d)\n", cchName,
513      (int)strlen("SeCreateTokenPrivilege"));
514     /* check known values */
515     for (i = SE_MIN_WELL_KNOWN_PRIVILEGE; i < SE_MAX_WELL_KNOWN_PRIVILEGE; i++)
516     {
517         luid.LowPart = i;
518         cchName = sizeof(buf);
519         ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
520         ok( ret || GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
521          "LookupPrivilegeNameA(0.%d) failed: %d\n", i, GetLastError());
522     }
523     /* check a bogus LUID */
524     luid.LowPart = 0xdeadbeef;
525     cchName = sizeof(buf);
526     ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
527     ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
528      "LookupPrivilegeNameA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n",
529      GetLastError());
530     /* check on a bogus system */
531     luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
532     cchName = sizeof(buf);
533     ret = pLookupPrivilegeNameA("b0gu5.Nam3", &luid, buf, &cchName);
534     ok( !ret && GetLastError() == RPC_S_SERVER_UNAVAILABLE,
535      "LookupPrivilegeNameA didn't fail with RPC_S_SERVER_UNAVAILABLE: %d\n",
536      GetLastError());
537 }
538
539 struct NameToLUID
540 {
541     const char *name;
542     DWORD lowPart;
543 };
544
545 static void test_lookupPrivilegeValue(void)
546 {
547     static const struct NameToLUID privs[] = {
548      { "SeCreateTokenPrivilege", SE_CREATE_TOKEN_PRIVILEGE },
549      { "SeAssignPrimaryTokenPrivilege", SE_ASSIGNPRIMARYTOKEN_PRIVILEGE },
550      { "SeLockMemoryPrivilege", SE_LOCK_MEMORY_PRIVILEGE },
551      { "SeIncreaseQuotaPrivilege", SE_INCREASE_QUOTA_PRIVILEGE },
552      { "SeMachineAccountPrivilege", SE_MACHINE_ACCOUNT_PRIVILEGE },
553      { "SeTcbPrivilege", SE_TCB_PRIVILEGE },
554      { "SeSecurityPrivilege", SE_SECURITY_PRIVILEGE },
555      { "SeTakeOwnershipPrivilege", SE_TAKE_OWNERSHIP_PRIVILEGE },
556      { "SeLoadDriverPrivilege", SE_LOAD_DRIVER_PRIVILEGE },
557      { "SeSystemProfilePrivilege", SE_SYSTEM_PROFILE_PRIVILEGE },
558      { "SeSystemtimePrivilege", SE_SYSTEMTIME_PRIVILEGE },
559      { "SeProfileSingleProcessPrivilege", SE_PROF_SINGLE_PROCESS_PRIVILEGE },
560      { "SeIncreaseBasePriorityPrivilege", SE_INC_BASE_PRIORITY_PRIVILEGE },
561      { "SeCreatePagefilePrivilege", SE_CREATE_PAGEFILE_PRIVILEGE },
562      { "SeCreatePermanentPrivilege", SE_CREATE_PERMANENT_PRIVILEGE },
563      { "SeBackupPrivilege", SE_BACKUP_PRIVILEGE },
564      { "SeRestorePrivilege", SE_RESTORE_PRIVILEGE },
565      { "SeShutdownPrivilege", SE_SHUTDOWN_PRIVILEGE },
566      { "SeDebugPrivilege", SE_DEBUG_PRIVILEGE },
567      { "SeAuditPrivilege", SE_AUDIT_PRIVILEGE },
568      { "SeSystemEnvironmentPrivilege", SE_SYSTEM_ENVIRONMENT_PRIVILEGE },
569      { "SeChangeNotifyPrivilege", SE_CHANGE_NOTIFY_PRIVILLEGE },
570      { "SeRemoteShutdownPrivilege", SE_REMOTE_SHUTDOWN_PRIVILEGE },
571      { "SeUndockPrivilege", SE_UNDOCK_PRIVILEGE },
572      { "SeSyncAgentPrivilege", SE_SYNC_AGENT_PRIVILEGE },
573      { "SeEnableDelegationPrivilege", SE_ENABLE_DELEGATION_PRIVILEGE },
574      { "SeManageVolumePrivilege", SE_MANAGE_VOLUME_PRIVILEGE },
575      { "SeImpersonatePrivilege", SE_IMPERSONATE_PRIVILEGE },
576      { "SeCreateGlobalPrivilege", SE_CREATE_GLOBAL_PRIVILEGE },
577     };
578     BOOL (WINAPI *pLookupPrivilegeValueA)(LPCSTR, LPCSTR, PLUID);
579     int i;
580     LUID luid;
581     BOOL ret;
582
583     /* check whether it's available first */
584     pLookupPrivilegeValueA = (void*)GetProcAddress(hmod, "LookupPrivilegeValueA");
585     if (!pLookupPrivilegeValueA) return;
586     ret = pLookupPrivilegeValueA(NULL, "SeCreateTokenPrivilege", &luid);
587     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
588         return;
589
590     /* check a bogus system name */
591     ret = pLookupPrivilegeValueA("b0gu5.Nam3", "SeCreateTokenPrivilege", &luid);
592     ok( !ret && GetLastError() == RPC_S_SERVER_UNAVAILABLE,
593      "LookupPrivilegeValueA didn't fail with RPC_S_SERVER_UNAVAILABLE: %d\n",
594      GetLastError());
595     /* check a NULL string */
596     ret = pLookupPrivilegeValueA(NULL, 0, &luid);
597     ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
598      "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n",
599      GetLastError());
600     /* check a bogus privilege name */
601     ret = pLookupPrivilegeValueA(NULL, "SeBogusPrivilege", &luid);
602     ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
603      "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n",
604      GetLastError());
605     /* check case insensitive */
606     ret = pLookupPrivilegeValueA(NULL, "sEcREATEtOKENpRIVILEGE", &luid);
607     ok( ret,
608      "LookupPrivilegeValueA(NULL, sEcREATEtOKENpRIVILEGE, &luid) failed: %d\n",
609      GetLastError());
610     for (i = 0; i < sizeof(privs) / sizeof(privs[0]); i++)
611     {
612         /* Not all privileges are implemented on all Windows versions, so
613          * don't worry if the call fails
614          */
615         if (pLookupPrivilegeValueA(NULL, privs[i].name, &luid))
616         {
617             ok(luid.LowPart == privs[i].lowPart,
618              "LookupPrivilegeValueA returned an invalid LUID for %s\n",
619              privs[i].name);
620         }
621     }
622 }
623
624 static void test_luid(void)
625 {
626     test_allocateLuid();
627     test_lookupPrivilegeName();
628     test_lookupPrivilegeValue();
629 }
630
631 static void test_FileSecurity(void)
632 {
633     char directory[MAX_PATH];
634     DWORD retval, outSize;
635     BOOL result;
636     BYTE buffer[0x40];
637
638     pGetFileSecurityA = (fnGetFileSecurityA)
639                     GetProcAddress( hmod, "GetFileSecurityA" );
640     if( !pGetFileSecurityA )
641         return;
642
643     retval = GetTempPathA(sizeof(directory), directory);
644     if (!retval) {
645         trace("GetTempPathA failed\n");
646         return;
647     }
648
649     strcpy(directory, "\\Should not exist");
650
651     SetLastError(NO_ERROR);
652     result = pGetFileSecurityA( directory,OWNER_SECURITY_INFORMATION,buffer,0x40,&outSize);
653     ok(!result, "GetFileSecurityA should fail for not existing directories/files\n"); 
654     ok( (GetLastError() == ERROR_FILE_NOT_FOUND ) ||
655         (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) , 
656         "last error ERROR_FILE_NOT_FOUND / ERROR_CALL_NOT_IMPLEMENTED (98) "
657         "expected, got %d\n", GetLastError());
658 }
659
660 static void test_AccessCheck(void)
661 {
662     PSID EveryoneSid = NULL, AdminSid = NULL, UsersSid = NULL;
663     PACL Acl = NULL;
664     SECURITY_DESCRIPTOR *SecurityDescriptor = NULL;
665     SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
666     SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
667     GENERIC_MAPPING Mapping = { KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS };
668     ACCESS_MASK Access;
669     BOOL AccessStatus;
670     HANDLE Token;
671     HANDLE ProcessToken;
672     BOOL ret;
673     DWORD PrivSetLen;
674     PRIVILEGE_SET *PrivSet;
675     BOOL res;
676     HMODULE NtDllModule;
677     BOOLEAN Enabled;
678     DWORD err;
679
680     NtDllModule = GetModuleHandle("ntdll.dll");
681     if (!NtDllModule)
682     {
683         skip("not running on NT, skipping test\n");
684         return;
685     }
686     pRtlAdjustPrivilege = (fnRtlAdjustPrivilege)
687                           GetProcAddress(NtDllModule, "RtlAdjustPrivilege");
688     if (!pRtlAdjustPrivilege)
689     {
690         skip("missing RtlAdjustPrivilege, skipping test\n");
691         return;
692     }
693
694     Acl = HeapAlloc(GetProcessHeap(), 0, 256);
695     res = InitializeAcl(Acl, 256, ACL_REVISION);
696     if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
697     {
698         skip("ACLs not implemented - skipping tests\n");
699         return;
700     }
701     ok(res, "InitializeAcl failed with error %d\n", GetLastError());
702
703     res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
704     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
705
706     res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
707         DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminSid);
708     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
709
710     res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
711         DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid);
712     ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
713
714     res = AddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, EveryoneSid);
715     ok(res, "AddAccessAllowedAceEx failed with error %d\n", GetLastError());
716
717     res = AddAccessDeniedAce(Acl, ACL_REVISION, KEY_SET_VALUE, AdminSid);
718     ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError());
719
720     SecurityDescriptor = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
721
722     res = InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
723     ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
724
725     res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
726     ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
727
728     PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
729     PrivSet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, PrivSetLen);
730     PrivSet->PrivilegeCount = 16;
731
732     res = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &ProcessToken);
733     ok(res, "OpenProcessToken failed with error %d\n", GetLastError());
734
735     pRtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, FALSE, TRUE, &Enabled);
736
737     res = DuplicateToken(ProcessToken, SecurityIdentification, &Token);
738     ok(res, "DuplicateToken failed with error %d\n", GetLastError());
739
740     /* SD without owner/group */
741     SetLastError(0xdeadbeef);
742     Access = AccessStatus = 0xdeadbeef;
743     ret = AccessCheck(SecurityDescriptor, Token, KEY_QUERY_VALUE, &Mapping,
744                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
745     err = GetLastError();
746     ok(!ret && err == ERROR_INVALID_SECURITY_DESCR, "AccessCheck should have "
747        "failed with ERROR_INVALID_SECURITY_DESCR, instead of %d\n", err);
748     ok(Access == 0xdeadbeef && AccessStatus == 0xdeadbeef,
749        "Access and/or AccessStatus were changed!\n");
750
751     /* Set owner and group */
752     res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE);
753     ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
754     res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, TRUE);
755     ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
756
757     /* Generic access mask */
758     SetLastError(0xdeadbeef);
759     ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
760                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
761     err = GetLastError();
762     ok(!ret && err == ERROR_GENERIC_NOT_MAPPED, "AccessCheck should have failed "
763        "with ERROR_GENERIC_NOT_MAPPED, instead of %d\n", err);
764     ok(Access == 0xdeadbeef && AccessStatus == 0xdeadbeef,
765        "Access and/or AccessStatus were changed!\n");
766
767     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
768                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
769     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
770     ok(AccessStatus && (Access == KEY_READ),
771         "AccessCheck failed to grant access with error %d\n",
772         GetLastError());
773
774     ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping,
775                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
776     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
777     ok(AccessStatus,
778         "AccessCheck failed to grant any access with error %d\n",
779         GetLastError());
780     trace("AccessCheck with MAXIMUM_ALLOWED got Access 0x%08x\n", Access);
781
782     /* Access denied by SD */
783     SetLastError(0xdeadbeef);
784     ret = AccessCheck(SecurityDescriptor, Token, KEY_WRITE, &Mapping,
785                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
786     ok(ret, "AccessCheck failed with error %d\n", GetLastError());
787     err = GetLastError();
788     ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed "
789        "with ERROR_ACCESS_DENIED, instead of %d\n", err);
790     ok(!Access, "Should have failed to grant any access, got 0x%08x\n", Access);
791
792     SetLastError(0);
793     PrivSet->PrivilegeCount = 16;
794     ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping,
795                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
796     ok(ret && !AccessStatus && GetLastError() == ERROR_PRIVILEGE_NOT_HELD,
797         "AccessCheck should have failed with ERROR_PRIVILEGE_NOT_HELD, instead of %d\n",
798         GetLastError());
799
800     ret = pRtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, TRUE, TRUE, &Enabled);
801     if (!ret)
802     {
803         SetLastError(0);
804         PrivSet->PrivilegeCount = 16;
805         ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping,
806                           PrivSet, &PrivSetLen, &Access, &AccessStatus);
807         ok(ret && AccessStatus && GetLastError() == 0,
808             "AccessCheck should have succeeded, error %d\n",
809             GetLastError());
810         ok(Access == ACCESS_SYSTEM_SECURITY,
811             "Access should be equal to ACCESS_SYSTEM_SECURITY instead of 0x%08x\n",
812             Access);
813     }
814     else
815         trace("Couldn't get SE_SECURITY_PRIVILEGE (0x%08x), skipping ACCESS_SYSTEM_SECURITY test\n",
816             ret);
817
818     CloseHandle(Token);
819
820     res = DuplicateToken(ProcessToken, SecurityAnonymous, &Token);
821     ok(res, "DuplicateToken failed with error %d\n", GetLastError());
822
823     SetLastError(0xdeadbeef);
824     ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping,
825                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
826     err = GetLastError();
827     ok(!ret && err == ERROR_BAD_IMPERSONATION_LEVEL, "AccessCheck should have failed "
828        "with ERROR_BAD_IMPERSONATION_LEVEL, instead of %d\n", err);
829
830     CloseHandle(Token);
831
832     SetLastError(0xdeadbeef);
833     ret = AccessCheck(SecurityDescriptor, ProcessToken, KEY_READ, &Mapping,
834                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
835     err = GetLastError();
836     ok(!ret && err == ERROR_NO_IMPERSONATION_TOKEN, "AccessCheck should have failed "
837        "with ERROR_NO_IMPERSONATION_TOKEN, instead of %d\n", err);
838
839     CloseHandle(ProcessToken);
840
841     if (EveryoneSid)
842         FreeSid(EveryoneSid);
843     if (AdminSid)
844         FreeSid(AdminSid);
845     if (UsersSid)
846         FreeSid(UsersSid);
847     HeapFree(GetProcessHeap(), 0, Acl);
848     HeapFree(GetProcessHeap(), 0, SecurityDescriptor);
849     HeapFree(GetProcessHeap(), 0, PrivSet);
850 }
851
852 /* test GetTokenInformation for the various attributes */
853 static void test_token_attr(void)
854 {
855     HANDLE Token, ImpersonationToken;
856     DWORD Size;
857     TOKEN_PRIVILEGES *Privileges;
858     TOKEN_GROUPS *Groups;
859     TOKEN_USER *User;
860     BOOL ret;
861     DWORD i, GLE;
862     LPSTR SidString;
863     SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
864
865     /* cygwin-like use case */
866     SetLastError(0xdeadbeef);
867     ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &Token);
868     if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
869     {
870         skip("OpenProcessToken is not implemented\n");
871         return;
872     }
873     ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
874     if (ret)
875     {
876         BYTE buf[1024];
877         Size = sizeof(buf);
878         ret = GetTokenInformation(Token, TokenUser,(void*)buf, Size, &Size);
879         ok(ret, "GetTokenInformation failed with error %d\n", GetLastError());
880         Size = sizeof(ImpersonationLevel);
881         ret = GetTokenInformation(Token, TokenImpersonationLevel, &ImpersonationLevel, Size, &Size);
882         GLE = GetLastError();
883         ok(!ret && (GLE == ERROR_INVALID_PARAMETER), "GetTokenInformation(TokenImpersonationLevel) on primary token should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GLE);
884         CloseHandle(Token);
885     }
886
887     if(!pConvertSidToStringSidA)
888     {
889         skip("ConvertSidToStringSidA is not available\n");
890         return;
891     }
892
893     SetLastError(0xdeadbeef);
894     ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_DUPLICATE, &Token);
895     ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
896
897     /* groups */
898     ret = GetTokenInformation(Token, TokenGroups, NULL, 0, &Size);
899     Groups = HeapAlloc(GetProcessHeap(), 0, Size);
900     ret = GetTokenInformation(Token, TokenGroups, Groups, Size, &Size);
901     ok(ret, "GetTokenInformation(TokenGroups) failed with error %d\n", GetLastError());
902     trace("TokenGroups:\n");
903     for (i = 0; i < Groups->GroupCount; i++)
904     {
905         DWORD NameLength = 255;
906         TCHAR Name[255];
907         DWORD DomainLength = 255;
908         TCHAR Domain[255];
909         SID_NAME_USE SidNameUse;
910         pConvertSidToStringSidA(Groups->Groups[i].Sid, &SidString);
911         Name[0] = '\0';
912         Domain[0] = '\0';
913         ret = LookupAccountSid(NULL, Groups->Groups[i].Sid, Name, &NameLength, Domain, &DomainLength, &SidNameUse);
914         if (ret)
915             trace("\t%s, %s\\%s use: %d attr: 0x%08x\n", SidString, Domain, Name, SidNameUse, Groups->Groups[i].Attributes);
916         else
917             trace("\t%s, attr: 0x%08x LookupAccountSid failed with error %d\n", SidString, Groups->Groups[i].Attributes, GetLastError());
918         LocalFree(SidString);
919     }
920     HeapFree(GetProcessHeap(), 0, Groups);
921
922     /* user */
923     ret = GetTokenInformation(Token, TokenUser, NULL, 0, &Size);
924     ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
925         "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
926     User = HeapAlloc(GetProcessHeap(), 0, Size);
927     ret = GetTokenInformation(Token, TokenUser, User, Size, &Size);
928     ok(ret,
929         "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
930
931     pConvertSidToStringSidA(User->User.Sid, &SidString);
932     trace("TokenUser: %s attr: 0x%08x\n", SidString, User->User.Attributes);
933     LocalFree(SidString);
934     HeapFree(GetProcessHeap(), 0, User);
935
936     /* privileges */
937     ret = GetTokenInformation(Token, TokenPrivileges, NULL, 0, &Size);
938     ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
939         "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError());
940     Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
941     ret = GetTokenInformation(Token, TokenPrivileges, Privileges, Size, &Size);
942     ok(ret,
943         "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError());
944     trace("TokenPrivileges:\n");
945     for (i = 0; i < Privileges->PrivilegeCount; i++)
946     {
947         TCHAR Name[256];
948         DWORD NameLen = sizeof(Name)/sizeof(Name[0]);
949         LookupPrivilegeName(NULL, &Privileges->Privileges[i].Luid, Name, &NameLen);
950         trace("\t%s, 0x%x\n", Name, Privileges->Privileges[i].Attributes);
951     }
952     HeapFree(GetProcessHeap(), 0, Privileges);
953
954     ret = DuplicateToken(Token, SecurityAnonymous, &ImpersonationToken);
955     ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
956
957     Size = sizeof(ImpersonationLevel);
958     ret = GetTokenInformation(ImpersonationToken, TokenImpersonationLevel, &ImpersonationLevel, Size, &Size);
959     ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError());
960     ok(ImpersonationLevel == SecurityAnonymous, "ImpersonationLevel should have been SecurityAnonymous instead of %d\n", ImpersonationLevel);
961
962     CloseHandle(ImpersonationToken);
963     CloseHandle(Token);
964 }
965
966 typedef union _MAX_SID
967 {
968     SID sid;
969     char max[SECURITY_MAX_SID_SIZE];
970 } MAX_SID;
971
972 static void test_sid_str(PSID * sid)
973 {
974     char *str_sid;
975     BOOL ret = pConvertSidToStringSidA(sid, &str_sid);
976     ok(ret, "ConvertSidToStringSidA() failed: %d\n", GetLastError());
977     if (ret)
978     {
979         char account[MAX_PATH], domain[MAX_PATH];
980         SID_NAME_USE use;
981         DWORD acc_size = MAX_PATH;
982         DWORD dom_size = MAX_PATH;
983         ret = LookupAccountSid(NULL, sid, account, &acc_size, domain, &dom_size, &use);
984         ok(ret || (!ret && (GetLastError() == ERROR_NONE_MAPPED)),
985            "LookupAccountSid(%s) failed: %d\n", str_sid, GetLastError());
986         if (ret)
987             trace(" %s %s\\%s %d\n", str_sid, domain, account, use);
988         else if (GetLastError() == ERROR_NONE_MAPPED)
989             trace(" %s couldn't be mapped\n", str_sid);
990         LocalFree(str_sid);
991     }
992 }
993
994 static void test_LookupAccountSid(void)
995 {
996     SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
997     CHAR accountA[MAX_PATH], domainA[MAX_PATH];
998     DWORD acc_sizeA, dom_sizeA;
999     DWORD real_acc_sizeA, real_dom_sizeA;
1000     WCHAR accountW[MAX_PATH], domainW[MAX_PATH];
1001     DWORD acc_sizeW, dom_sizeW;
1002     DWORD real_acc_sizeW, real_dom_sizeW;
1003     PSID pUsersSid = NULL;
1004     SID_NAME_USE use;
1005     BOOL ret;
1006     DWORD size;
1007     MAX_SID  max_sid;
1008     CHAR *str_sidA;
1009     int i;
1010
1011     /* native windows crashes if account size, domain size, or name use is NULL */
1012
1013     ret = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
1014         DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &pUsersSid);
1015     ok(ret || (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED),
1016        "AllocateAndInitializeSid failed with error %d\n", GetLastError());
1017
1018     /* not running on NT so give up */
1019     if (!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
1020         return;
1021
1022     real_acc_sizeA = MAX_PATH;
1023     real_dom_sizeA = MAX_PATH;
1024     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &real_acc_sizeA, domainA, &real_dom_sizeA, &use);
1025     ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
1026
1027     /* try NULL account */
1028     acc_sizeA = MAX_PATH;
1029     dom_sizeA = MAX_PATH;
1030     ret = LookupAccountSidA(NULL, pUsersSid, NULL, &acc_sizeA, domainA, &dom_sizeA, &use);
1031     ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
1032
1033     /* try NULL domain */
1034     acc_sizeA = MAX_PATH;
1035     dom_sizeA = MAX_PATH;
1036     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, NULL, &dom_sizeA, &use);
1037     ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
1038
1039     /* try a small account buffer */
1040     acc_sizeA = 1;
1041     dom_sizeA = MAX_PATH;
1042     accountA[0] = 0;
1043     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
1044     ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n");
1045     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1046        "LookupAccountSidA() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
1047
1048     /* try a 0 sized account buffer */
1049     acc_sizeA = 0;
1050     dom_sizeA = MAX_PATH;
1051     accountA[0] = 0;
1052     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
1053     /* this can fail or succeed depending on OS version but the size will always be returned */
1054     ok(acc_sizeA == real_acc_sizeA + 1,
1055        "LookupAccountSidA() Expected acc_size = %u, got %u\n",
1056        real_acc_sizeA + 1, acc_sizeA);
1057
1058     /* try a 0 sized account buffer */
1059     acc_sizeA = 0;
1060     dom_sizeA = MAX_PATH;
1061     ret = LookupAccountSidA(NULL, pUsersSid, NULL, &acc_sizeA, domainA, &dom_sizeA, &use);
1062     /* this can fail or succeed depending on OS version but the size will always be returned */
1063     ok(acc_sizeA == real_acc_sizeA + 1,
1064        "LookupAccountSid() Expected acc_size = %u, got %u\n",
1065        real_acc_sizeA + 1, acc_sizeA);
1066
1067     /* try a small domain buffer */
1068     dom_sizeA = 1;
1069     acc_sizeA = MAX_PATH;
1070     accountA[0] = 0;
1071     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
1072     ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n");
1073     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1074        "LookupAccountSidA() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
1075
1076     /* try a 0 sized domain buffer */
1077     dom_sizeA = 0;
1078     acc_sizeA = MAX_PATH;
1079     accountA[0] = 0;
1080     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
1081     /* this can fail or succeed depending on OS version but the size will always be returned */
1082     ok(dom_sizeA == real_dom_sizeA + 1,
1083        "LookupAccountSidA() Expected dom_size = %u, got %u\n",
1084        real_dom_sizeA + 1, dom_sizeA);
1085
1086     /* try a 0 sized domain buffer */
1087     dom_sizeA = 0;
1088     acc_sizeA = MAX_PATH;
1089     ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, NULL, &dom_sizeA, &use);
1090     /* this can fail or succeed depending on OS version but the size will always be returned */
1091     ok(dom_sizeA == real_dom_sizeA + 1,
1092        "LookupAccountSidA() Expected dom_size = %u, got %u\n",
1093        real_dom_sizeA + 1, dom_sizeA);
1094
1095     real_acc_sizeW = MAX_PATH;
1096     real_dom_sizeW = MAX_PATH;
1097     ret = LookupAccountSidW(NULL, pUsersSid, accountW, &real_acc_sizeW, domainW, &real_dom_sizeW, &use);
1098     ok(ret, "LookupAccountSidW() Expected TRUE, got FALSE\n");
1099
1100     /* native windows crashes if domainW or accountW is NULL */
1101
1102     /* try a small account buffer */
1103     acc_sizeW = 1;
1104     dom_sizeW = MAX_PATH;
1105     accountW[0] = 0;
1106     ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
1107     ok(!ret, "LookupAccountSidW() Expected FALSE got TRUE\n");
1108     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1109        "LookupAccountSidW() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
1110
1111     /* try a 0 sized account buffer */
1112     acc_sizeW = 0;
1113     dom_sizeW = MAX_PATH;
1114     accountW[0] = 0;
1115     ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
1116     /* this can fail or succeed depending on OS version but the size will always be returned */
1117     ok(acc_sizeW == real_acc_sizeW + 1,
1118        "LookupAccountSidW() Expected acc_size = %u, got %u\n",
1119        real_acc_sizeW + 1, acc_sizeW);
1120
1121     /* try a 0 sized account buffer */
1122     acc_sizeW = 0;
1123     dom_sizeW = MAX_PATH;
1124     ret = LookupAccountSidW(NULL, pUsersSid, NULL, &acc_sizeW, domainW, &dom_sizeW, &use);
1125     /* this can fail or succeed depending on OS version but the size will always be returned */
1126     ok(acc_sizeW == real_acc_sizeW + 1,
1127        "LookupAccountSidW() Expected acc_size = %u, got %u\n",
1128        real_acc_sizeW + 1, acc_sizeW);
1129
1130     /* try a small domain buffer */
1131     dom_sizeW = 1;
1132     acc_sizeW = MAX_PATH;
1133     accountW[0] = 0;
1134     ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
1135     ok(!ret, "LookupAccountSidW() Expected FALSE got TRUE\n");
1136     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1137        "LookupAccountSidW() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
1138
1139     /* try a 0 sized domain buffer */
1140     dom_sizeW = 0;
1141     acc_sizeW = MAX_PATH;
1142     accountW[0] = 0;
1143     ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
1144     /* this can fail or succeed depending on OS version but the size will always be returned */
1145     ok(dom_sizeW == real_dom_sizeW + 1,
1146        "LookupAccountSidW() Expected dom_size = %u, got %u\n",
1147        real_dom_sizeW + 1, dom_sizeW);
1148
1149     /* try a 0 sized domain buffer */
1150     dom_sizeW = 0;
1151     acc_sizeW = MAX_PATH;
1152     ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, NULL, &dom_sizeW, &use);
1153     /* this can fail or succeed depending on OS version but the size will always be returned */
1154     ok(dom_sizeW == real_dom_sizeW + 1,
1155        "LookupAccountSidW() Expected dom_size = %u, got %u\n",
1156        real_dom_sizeW + 1, dom_sizeW);
1157
1158     FreeSid(pUsersSid);
1159
1160     pCreateWellKnownSid = (fnCreateWellKnownSid)GetProcAddress( hmod, "CreateWellKnownSid" );
1161
1162     if (pCreateWellKnownSid && pConvertSidToStringSidA)
1163     {
1164         trace("Well Known SIDs:\n");
1165         for (i = 0; i <= 60; i++)
1166         {
1167             size = SECURITY_MAX_SID_SIZE;
1168             if (pCreateWellKnownSid(i, NULL, &max_sid.sid, &size))
1169             {
1170                 if (pConvertSidToStringSidA(&max_sid.sid, &str_sidA))
1171                 {
1172                     acc_sizeA = MAX_PATH;
1173                     dom_sizeA = MAX_PATH;
1174                     if (LookupAccountSidA(NULL, &max_sid.sid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use))
1175                         trace(" %d: %s %s\\%s %d\n", i, str_sidA, domainA, accountA, use);
1176                     LocalFree(str_sidA);
1177                 }
1178             }
1179             else
1180             {
1181                 if (GetLastError() != ERROR_INVALID_PARAMETER)
1182                     trace(" CreateWellKnownSid(%d) failed: %d\n", i, GetLastError());
1183                 else
1184                     trace(" %d: not supported\n", i);
1185             }
1186         }
1187
1188         pLsaQueryInformationPolicy = (fnLsaQueryInformationPolicy)GetProcAddress( hmod, "LsaQueryInformationPolicy");
1189         pLsaOpenPolicy = (fnLsaOpenPolicy)GetProcAddress( hmod, "LsaOpenPolicy");
1190         pLsaFreeMemory = (fnLsaFreeMemory)GetProcAddress( hmod, "LsaFreeMemory");
1191         pLsaClose = (fnLsaClose)GetProcAddress( hmod, "LsaClose");
1192
1193         if (pLsaQueryInformationPolicy && pLsaOpenPolicy && pLsaFreeMemory && pLsaClose)
1194         {
1195             NTSTATUS status;
1196             LSA_HANDLE handle;
1197             LSA_OBJECT_ATTRIBUTES object_attributes;
1198
1199             ZeroMemory(&object_attributes, sizeof(object_attributes));
1200             object_attributes.Length = sizeof(object_attributes);
1201
1202             status = pLsaOpenPolicy( NULL, &object_attributes, POLICY_ALL_ACCESS, &handle);
1203             ok(status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED,
1204                "LsaOpenPolicy(POLICY_ALL_ACCESS) returned 0x%08x\n", status);
1205
1206             /* try a more restricted access mask if necessary */
1207             if (status == STATUS_ACCESS_DENIED) {
1208                 trace("LsaOpenPolicy(POLICY_ALL_ACCESS) failed, trying POLICY_VIEW_LOCAL_INFORMATION\n");
1209                 status = pLsaOpenPolicy( NULL, &object_attributes, POLICY_VIEW_LOCAL_INFORMATION, &handle);
1210                 ok(status == STATUS_SUCCESS, "LsaOpenPolicy(POLICY_VIEW_LOCAL_INFORMATION) returned 0x%08x\n", status);
1211             }
1212
1213             if (status == STATUS_SUCCESS)
1214             {
1215                 PPOLICY_ACCOUNT_DOMAIN_INFO info;
1216                 status = pLsaQueryInformationPolicy(handle, PolicyAccountDomainInformation, (PVOID*)&info);
1217                 ok(status == STATUS_SUCCESS, "LsaQueryInformationPolicy() failed, returned 0x%08x\n", status);
1218                 if (status == STATUS_SUCCESS)
1219                 {
1220                     ok(info->DomainSid!=0, "LsaQueryInformationPolicy(PolicyAccountDomainInformation) missing SID\n");
1221                     if (info->DomainSid)
1222                     {
1223                         int count = *GetSidSubAuthorityCount(info->DomainSid);
1224                         CopySid(GetSidLengthRequired(count), &max_sid, info->DomainSid);
1225                         test_sid_str((PSID)&max_sid.sid);
1226                         max_sid.sid.SubAuthority[count] = DOMAIN_USER_RID_ADMIN;
1227                         max_sid.sid.SubAuthorityCount = count + 1;
1228                         test_sid_str((PSID)&max_sid.sid);
1229                         max_sid.sid.SubAuthority[count] = DOMAIN_USER_RID_GUEST;
1230                         test_sid_str((PSID)&max_sid.sid);
1231                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_ADMINS;
1232                         test_sid_str((PSID)&max_sid.sid);
1233                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_USERS;
1234                         test_sid_str((PSID)&max_sid.sid);
1235                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_GUESTS;
1236                         test_sid_str((PSID)&max_sid.sid);
1237                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_COMPUTERS;
1238                         test_sid_str((PSID)&max_sid.sid);
1239                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_CONTROLLERS;
1240                         test_sid_str((PSID)&max_sid.sid);
1241                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_CERT_ADMINS;
1242                         test_sid_str((PSID)&max_sid.sid);
1243                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_SCHEMA_ADMINS;
1244                         test_sid_str((PSID)&max_sid.sid);
1245                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_ENTERPRISE_ADMINS;
1246                         test_sid_str((PSID)&max_sid.sid);
1247                         max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_POLICY_ADMINS;
1248                         test_sid_str((PSID)&max_sid.sid);
1249                         max_sid.sid.SubAuthority[count] = DOMAIN_ALIAS_RID_RAS_SERVERS;
1250                         test_sid_str((PSID)&max_sid.sid);
1251                         max_sid.sid.SubAuthority[count] = 1000; /* first user account */
1252                         test_sid_str((PSID)&max_sid.sid);
1253                     }
1254
1255                     pLsaFreeMemory((LPVOID)info);
1256                 }
1257
1258                 status = pLsaClose(handle);
1259                 ok(status == STATUS_SUCCESS, "LsaClose() failed, returned 0x%08x\n", status);
1260             }
1261         }
1262     }
1263 }
1264
1265 static void get_sid_info(PSID psid, LPSTR *user, LPSTR *dom)
1266 {
1267     static CHAR account[UNLEN + 1];
1268     static CHAR domain[UNLEN + 1];
1269     DWORD size, dom_size;
1270     SID_NAME_USE use;
1271
1272     *user = account;
1273     *dom = domain;
1274
1275     size = dom_size = UNLEN + 1;
1276     account[0] = '\0';
1277     domain[0] = '\0';
1278     LookupAccountSidA(NULL, psid, account, &size, domain, &dom_size, &use);
1279 }
1280
1281 static void test_LookupAccountName(void)
1282 {
1283     DWORD sid_size, domain_size, user_size;
1284     DWORD sid_save, domain_save;
1285     CHAR user_name[UNLEN + 1];
1286     SID_NAME_USE sid_use;
1287     LPSTR domain, account, sid_dom;
1288     PSID psid;
1289     BOOL ret;
1290
1291     /* native crashes if (assuming all other parameters correct):
1292      *  - peUse is NULL
1293      *  - Sid is NULL and cbSid is > 0
1294      *  - cbSid or cchReferencedDomainName are NULL
1295      *  - ReferencedDomainName is NULL and cchReferencedDomainName is the correct size
1296      */
1297
1298     user_size = UNLEN + 1;
1299     ret = GetUserNameA(user_name, &user_size);
1300     ok(ret, "Failed to get user name\n");
1301
1302     /* get sizes */
1303     sid_size = 0;
1304     domain_size = 0;
1305     sid_use = 0xcafebabe;
1306     SetLastError(0xdeadbeef);
1307     ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, NULL, &domain_size, &sid_use);
1308     if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
1309     {
1310         skip("LookupAccountNameA is not implemented\n");
1311         return;
1312     }
1313     ok(!ret, "Expected 0, got %d\n", ret);
1314     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1315        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1316     ok(sid_size != 0, "Expected non-zero sid size\n");
1317     ok(domain_size != 0, "Expected non-zero domain size\n");
1318     ok(sid_use == 0xcafebabe, "Expected 0xcafebabe, got %d\n", sid_use);
1319
1320     sid_save = sid_size;
1321     domain_save = domain_size;
1322
1323     psid = HeapAlloc(GetProcessHeap(), 0, sid_size);
1324     domain = HeapAlloc(GetProcessHeap(), 0, domain_size);
1325
1326     /* try valid account name */
1327     ret = LookupAccountNameA(NULL, user_name, psid, &sid_size, domain, &domain_size, &sid_use);
1328     get_sid_info(psid, &account, &sid_dom);
1329     ok(ret, "Failed to lookup account name\n");
1330     ok(sid_size == GetLengthSid(psid), "Expected %d, got %d\n", GetLengthSid(psid), sid_size);
1331     todo_wine
1332     {
1333         ok(!lstrcmp(account, user_name), "Expected %s, got %s\n", user_name, account);
1334         ok(!lstrcmp(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
1335         ok(domain_size == domain_save - 1, "Expected %d, got %d\n", domain_save - 1, domain_size);
1336         ok(lstrlen(domain) == domain_size, "Expected %d\n", lstrlen(domain));
1337         ok(sid_use == SidTypeUser, "Expected SidTypeUser, got %d\n", SidTypeUser);
1338     }
1339     domain_size = domain_save;
1340
1341     /* NULL Sid with zero sid size */
1342     SetLastError(0xdeadbeef);
1343     sid_size = 0;
1344     ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, domain, &domain_size, &sid_use);
1345     ok(!ret, "Expected 0, got %d\n", ret);
1346     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1347        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1348     ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size);
1349     ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
1350
1351     /* try cchReferencedDomainName - 1 */
1352     SetLastError(0xdeadbeef);
1353     domain_size--;
1354     ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, domain, &domain_size, &sid_use);
1355     ok(!ret, "Expected 0, got %d\n", ret);
1356     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1357        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1358     ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size);
1359     ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
1360
1361     /* NULL ReferencedDomainName with zero domain name size */
1362     SetLastError(0xdeadbeef);
1363     domain_size = 0;
1364     ret = LookupAccountNameA(NULL, user_name, psid, &sid_size, NULL, &domain_size, &sid_use);
1365     ok(!ret, "Expected 0, got %d\n", ret);
1366     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1367        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1368     ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size);
1369     ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
1370
1371     HeapFree(GetProcessHeap(), 0, psid);
1372     HeapFree(GetProcessHeap(), 0, domain);
1373
1374     /* get sizes for NULL account name */
1375     sid_size = 0;
1376     domain_size = 0;
1377     sid_use = 0xcafebabe;
1378     SetLastError(0xdeadbeef);
1379     ret = LookupAccountNameA(NULL, NULL, NULL, &sid_size, NULL, &domain_size, &sid_use);
1380     ok(!ret, "Expected 0, got %d\n", ret);
1381     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1382        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1383     ok(sid_size != 0, "Expected non-zero sid size\n");
1384     ok(domain_size != 0, "Expected non-zero domain size\n");
1385     ok(sid_use == 0xcafebabe, "Expected 0xcafebabe, got %d\n", sid_use);
1386
1387     psid = HeapAlloc(GetProcessHeap(), 0, sid_size);
1388     domain = HeapAlloc(GetProcessHeap(), 0, domain_size);
1389
1390     /* try NULL account name */
1391     ret = LookupAccountNameA(NULL, NULL, psid, &sid_size, domain, &domain_size, &sid_use);
1392     get_sid_info(psid, &account, &sid_dom);
1393     ok(ret, "Failed to lookup account name\n");
1394     todo_wine
1395     {
1396         ok(!lstrcmp(account, "BUILTIN"), "Expected BUILTIN, got %s\n", account);
1397         ok(!lstrcmp(domain, "BUILTIN"), "Expected BUILTIN, got %s\n", domain);
1398         ok(sid_use == SidTypeDomain, "Expected SidTypeDomain, got %d\n", SidTypeDomain);
1399     }
1400
1401     /* try an invalid account name */
1402     SetLastError(0xdeadbeef);
1403     sid_size = 0;
1404     domain_size = 0;
1405     ret = LookupAccountNameA(NULL, "oogabooga", NULL, &sid_size, NULL, &domain_size, &sid_use);
1406     ok(!ret, "Expected 0, got %d\n", ret);
1407     todo_wine
1408     {
1409         ok(GetLastError() == ERROR_NONE_MAPPED,
1410            "Expected ERROR_NONE_MAPPED, got %d\n", GetLastError());
1411         ok(sid_size == 0, "Expected 0, got %d\n", sid_size);
1412         ok(domain_size == 0, "Expected 0, got %d\n", domain_size);
1413     }
1414
1415     HeapFree(GetProcessHeap(), 0, psid);
1416     HeapFree(GetProcessHeap(), 0, domain);
1417 }
1418
1419 #define TEST_GRANTED_ACCESS(a,b) test_granted_access(a,b,__LINE__)
1420 static void test_granted_access(HANDLE handle, ACCESS_MASK access, int line)
1421 {
1422     OBJECT_BASIC_INFORMATION obj_info;
1423     NTSTATUS status;
1424
1425     if (!pNtQueryObject)
1426     {
1427         skip_(__FILE__, line)("Not NT platform - skipping tests\n");
1428         return;
1429     }
1430
1431     status = pNtQueryObject( handle, ObjectBasicInformation, &obj_info,
1432                              sizeof(obj_info), NULL );
1433     ok_(__FILE__, line)(!status, "NtQueryObject with err: %08x\n", status);
1434     ok_(__FILE__, line)(obj_info.GrantedAccess == access, "Gratned access should "
1435         "be 0x%08x, instead of 0x%08x\n", access, obj_info.GrantedAccess);
1436 }
1437
1438 #define CHECK_SET_SECURITY(o,i,e) \
1439     do{ \
1440         BOOL res; \
1441         DWORD err; \
1442         SetLastError( 0xdeadbeef ); \
1443         res = SetKernelObjectSecurity( o, i, SecurityDescriptor ); \
1444         err = GetLastError(); \
1445         if (e == ERROR_SUCCESS) \
1446             ok(res, "SetKernelObjectSecurity failed with %d\n", err); \
1447         else \
1448             ok(!res && err == e, "SetKernelObjectSecurity should have failed " \
1449                "with %s, instead of %d\n", #e, err); \
1450     }while(0)
1451
1452 static void test_process_security(void)
1453 {
1454     BOOL res;
1455     char owner[32], group[32];
1456     PSID AdminSid = NULL, UsersSid = NULL;
1457     PACL Acl = NULL;
1458     SECURITY_DESCRIPTOR *SecurityDescriptor = NULL;
1459     char buffer[MAX_PATH];
1460     PROCESS_INFORMATION info;
1461     STARTUPINFOA startup;
1462     SECURITY_ATTRIBUTES psa;
1463     HANDLE token, event;
1464     DWORD tmp;
1465
1466     Acl = HeapAlloc(GetProcessHeap(), 0, 256);
1467     res = InitializeAcl(Acl, 256, ACL_REVISION);
1468     if (!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1469     {
1470         skip("ACLs not implemented - skipping tests\n");
1471         return;
1472     }
1473     ok(res, "InitializeAcl failed with error %d\n", GetLastError());
1474
1475     /* get owner from the token we might be running as a user not admin */
1476     res = OpenProcessToken( GetCurrentProcess(), MAXIMUM_ALLOWED, &token );
1477     ok(res, "OpenProcessToken failed with error %d\n", GetLastError());
1478     if (!res) return;
1479
1480     res = GetTokenInformation( token, TokenOwner, owner, sizeof(owner), &tmp );
1481     ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
1482     AdminSid = ((TOKEN_OWNER*)owner)->Owner;
1483     res = GetTokenInformation( token, TokenPrimaryGroup, group, sizeof(group), &tmp );
1484     ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
1485     UsersSid = ((TOKEN_PRIMARY_GROUP*)group)->PrimaryGroup;
1486
1487     CloseHandle( token );
1488     if (!res) return;
1489
1490     res = AddAccessDeniedAce(Acl, ACL_REVISION, PROCESS_VM_READ, AdminSid);
1491     ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError());
1492     res = AddAccessAllowedAce(Acl, ACL_REVISION, PROCESS_ALL_ACCESS, AdminSid);
1493     ok(res, "AddAccessAllowedAceEx failed with error %d\n", GetLastError());
1494
1495     SecurityDescriptor = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
1496     res = InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
1497     ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
1498
1499     event = CreateEvent( NULL, TRUE, TRUE, "test_event" );
1500     ok(event != NULL, "CreateEvent %d\n", GetLastError());
1501
1502     SecurityDescriptor->Revision = 0;
1503     CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_UNKNOWN_REVISION );
1504     SecurityDescriptor->Revision = SECURITY_DESCRIPTOR_REVISION;
1505
1506     CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR );
1507     CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR );
1508     CHECK_SET_SECURITY( event, SACL_SECURITY_INFORMATION, ERROR_ACCESS_DENIED );
1509     CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
1510     /* NULL DACL is valid and means default DACL from token */
1511     SecurityDescriptor->Control |= SE_DACL_PRESENT;
1512     CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
1513
1514     /* Set owner and group and dacl */
1515     res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE);
1516     ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
1517     CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_SUCCESS );
1518     res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, FALSE);
1519     ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
1520     CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_SUCCESS );
1521     res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
1522     ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
1523     CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
1524
1525     sprintf(buffer, "%s tests/security.c test", myARGV[0]);
1526     memset(&startup, 0, sizeof(startup));
1527     startup.cb = sizeof(startup);
1528     startup.dwFlags = STARTF_USESHOWWINDOW;
1529     startup.wShowWindow = SW_SHOWNORMAL;
1530
1531     psa.nLength = sizeof(psa);
1532     psa.lpSecurityDescriptor = SecurityDescriptor;
1533     psa.bInheritHandle = TRUE;
1534
1535     /* Doesn't matter what ACL say we should get full access for ourselves */
1536     ok(CreateProcessA( NULL, buffer, &psa, NULL, FALSE, 0, NULL, NULL, &startup, &info ),
1537         "CreateProcess with err:%d\n", GetLastError());
1538     TEST_GRANTED_ACCESS( info.hProcess, PROCESS_ALL_ACCESS );
1539     ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
1540
1541     CloseHandle( event );
1542     HeapFree(GetProcessHeap(), 0, Acl);
1543     HeapFree(GetProcessHeap(), 0, SecurityDescriptor);
1544 }
1545
1546 static void test_process_security_child(void)
1547 {
1548     HANDLE handle, handle1;
1549     BOOL ret;
1550     DWORD err;
1551
1552     handle = OpenProcess( PROCESS_TERMINATE, FALSE, GetCurrentProcessId() );
1553     ok(handle != NULL, "OpenProcess(PROCESS_TERMINATE) with err:%d\n", GetLastError());
1554     TEST_GRANTED_ACCESS( handle, PROCESS_TERMINATE );
1555
1556     ok(DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
1557                         &handle1, 0, TRUE, DUPLICATE_SAME_ACCESS ),
1558        "duplicating handle err:%d\n", GetLastError());
1559     TEST_GRANTED_ACCESS( handle1, PROCESS_TERMINATE );
1560
1561     CloseHandle( handle1 );
1562
1563     SetLastError( 0xdeadbeef );
1564     ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
1565                            &handle1, PROCESS_ALL_ACCESS, TRUE, 0 );
1566     err = GetLastError();
1567     todo_wine
1568     ok(!ret && err == ERROR_ACCESS_DENIED, "duplicating handle should have failed "
1569        "with STATUS_ACCESS_DENIED, instead of err:%d\n", err);
1570
1571     CloseHandle( handle );
1572
1573     /* These two should fail - they are denied by ACL */
1574     handle = OpenProcess( PROCESS_VM_READ, FALSE, GetCurrentProcessId() );
1575     todo_wine
1576     ok(handle == NULL, "OpenProcess(PROCESS_VM_READ) should have failed\n");
1577     handle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId() );
1578     todo_wine
1579     ok(handle == NULL, "OpenProcess(PROCESS_ALL_ACCESS) should have failed\n");
1580
1581     /* Documented privilege elevation */
1582     ok(DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
1583                         &handle, 0, TRUE, DUPLICATE_SAME_ACCESS ),
1584        "duplicating handle err:%d\n", GetLastError());
1585     TEST_GRANTED_ACCESS( handle, PROCESS_ALL_ACCESS );
1586
1587     CloseHandle( handle );
1588
1589     /* Same only explicitly asking for all access rights */
1590     ok(DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
1591                         &handle, PROCESS_ALL_ACCESS, TRUE, 0 ),
1592        "duplicating handle err:%d\n", GetLastError());
1593     TEST_GRANTED_ACCESS( handle, PROCESS_ALL_ACCESS );
1594     ok(DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
1595                         &handle1, PROCESS_VM_READ, TRUE, 0 ),
1596        "duplicating handle err:%d\n", GetLastError());
1597     TEST_GRANTED_ACCESS( handle1, PROCESS_VM_READ );
1598     CloseHandle( handle1 );
1599     CloseHandle( handle );
1600 }
1601
1602 static void test_impersonation_level(void)
1603 {
1604     HANDLE Token, ProcessToken;
1605     HANDLE Token2;
1606     DWORD Size;
1607     TOKEN_PRIVILEGES *Privileges;
1608     TOKEN_USER *User;
1609     PRIVILEGE_SET *PrivilegeSet;
1610     BOOL AccessGranted;
1611     BOOL ret;
1612     HKEY hkey;
1613     DWORD error;
1614
1615     pDuplicateTokenEx = (fnDuplicateTokenEx) GetProcAddress(hmod, "DuplicateTokenEx");
1616     if( !pDuplicateTokenEx ) {
1617         skip("DuplicateTokenEx is not available\n");
1618         return;
1619     }
1620     SetLastError(0xdeadbeef);
1621     ret = ImpersonateSelf(SecurityAnonymous);
1622     if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
1623     {
1624         skip("ImpersonateSelf is not implemented\n");
1625         return;
1626     }
1627     ok(ret, "ImpersonateSelf(SecurityAnonymous) failed with error %d\n", GetLastError());
1628     ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
1629     ok(!ret, "OpenThreadToken should have failed\n");
1630     error = GetLastError();
1631     ok(error == ERROR_CANT_OPEN_ANONYMOUS, "OpenThreadToken on anonymous token should have returned ERROR_CANT_OPEN_ANONYMOUS instead of %d\n", error);
1632     /* can't perform access check when opening object against an anonymous impersonation token */
1633     todo_wine {
1634     error = RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
1635     ok(error == ERROR_INVALID_HANDLE, "RegOpenKeyEx should have failed with ERROR_INVALID_HANDLE instead of %d\n", error);
1636     }
1637     RevertToSelf();
1638
1639     ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
1640     ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1641
1642     ret = pDuplicateTokenEx(ProcessToken,
1643         TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE, NULL,
1644         SecurityAnonymous, TokenImpersonation, &Token);
1645     ok(ret, "DuplicateTokenEx failed with error %d\n", GetLastError());
1646     /* can't increase the impersonation level */
1647     ret = DuplicateToken(Token, SecurityIdentification, &Token2);
1648     error = GetLastError();
1649     ok(!ret && error == ERROR_BAD_IMPERSONATION_LEVEL,
1650         "Duplicating a token and increasing the impersonation level should have failed with ERROR_BAD_IMPERSONATION_LEVEL instead of %d\n", error);
1651     /* we can query anything from an anonymous token, including the user */
1652     ret = GetTokenInformation(Token, TokenUser, NULL, 0, &Size);
1653     error = GetLastError();
1654     ok(!ret && error == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenUser) should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", error);
1655     User = (TOKEN_USER *)HeapAlloc(GetProcessHeap(), 0, Size);
1656     ret = GetTokenInformation(Token, TokenUser, User, Size, &Size);
1657     ok(ret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
1658     HeapFree(GetProcessHeap(), 0, User);
1659
1660     /* PrivilegeCheck fails with SecurityAnonymous level */
1661     ret = GetTokenInformation(Token, TokenPrivileges, NULL, 0, &Size);
1662     error = GetLastError();
1663     ok(!ret && error == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", error);
1664     Privileges = (TOKEN_PRIVILEGES *)HeapAlloc(GetProcessHeap(), 0, Size);
1665     ret = GetTokenInformation(Token, TokenPrivileges, Privileges, Size, &Size);
1666     ok(ret, "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError());
1667
1668     PrivilegeSet = (PRIVILEGE_SET *)HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(PRIVILEGE_SET, Privilege[Privileges->PrivilegeCount]));
1669     PrivilegeSet->PrivilegeCount = Privileges->PrivilegeCount;
1670     memcpy(PrivilegeSet->Privilege, Privileges->Privileges, PrivilegeSet->PrivilegeCount * sizeof(PrivilegeSet->Privilege[0]));
1671     PrivilegeSet->Control = PRIVILEGE_SET_ALL_NECESSARY;
1672     HeapFree(GetProcessHeap(), 0, Privileges);
1673
1674     ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
1675     error = GetLastError();
1676     ok(!ret && error == ERROR_BAD_IMPERSONATION_LEVEL, "PrivilegeCheck for SecurityAnonymous token should have failed with ERROR_BAD_IMPERSONATION_LEVEL instead of %d\n", error);
1677
1678     CloseHandle(Token);
1679
1680     ret = ImpersonateSelf(SecurityIdentification);
1681     ok(ret, "ImpersonateSelf(SecurityIdentification) failed with error %d\n", GetLastError());
1682     ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
1683     ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1684
1685     /* can't perform access check when opening object against an identification impersonation token */
1686     error = RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
1687     todo_wine {
1688     ok(error == ERROR_INVALID_HANDLE, "RegOpenKeyEx should have failed with ERROR_INVALID_HANDLE instead of %d\n", error);
1689     }
1690     ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
1691     ok(ret, "PrivilegeCheck for SecurityIdentification failed with error %d\n", GetLastError());
1692     CloseHandle(Token);
1693     RevertToSelf();
1694
1695     ret = ImpersonateSelf(SecurityImpersonation);
1696     ok(ret, "ImpersonateSelf(SecurityImpersonation) failed with error %d\n", GetLastError());
1697     ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
1698     ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
1699     error = RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
1700     ok(error == ERROR_SUCCESS, "RegOpenKeyEx should have succeeded instead of failing with %d\n", error);
1701     RegCloseKey(hkey);
1702     ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
1703     ok(ret, "PrivilegeCheck for SecurityImpersonation failed with error %d\n", GetLastError());
1704     RevertToSelf();
1705
1706     CloseHandle(Token);
1707     CloseHandle(ProcessToken);
1708
1709     HeapFree(GetProcessHeap(), 0, PrivilegeSet);
1710 }
1711
1712 static void test_SetEntriesInAcl(void)
1713 {
1714     ACL *acl = (ACL*)0xdeadbeef;
1715     DWORD res;
1716
1717     res = SetEntriesInAclW(0, NULL, NULL, &acl);
1718     if(res == ERROR_CALL_NOT_IMPLEMENTED)
1719     {
1720         skip("SetEntriesInAclW is not implemented\n");
1721         return;
1722     }
1723     ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
1724     ok(acl == NULL, "acl=%p, expected NULL\n", acl);
1725 }
1726
1727 static void test_GetNamedSecurityInfoA(void)
1728 {
1729     PSECURITY_DESCRIPTOR pSecDesc;
1730     DWORD revision;
1731     SECURITY_DESCRIPTOR_CONTROL control;
1732     PSID owner;
1733     PSID group;
1734     BOOL owner_defaulted;
1735     BOOL group_defaulted;
1736     DWORD error;
1737     BOOL ret;
1738     CHAR windows_dir[MAX_PATH];
1739
1740     ret = GetWindowsDirectoryA(windows_dir, MAX_PATH);
1741     ok(ret, "GetWindowsDirectory failed with error %d\n", GetLastError());
1742
1743     SetLastError(0xdeadbeef);
1744     error = GetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,
1745         OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
1746         NULL, NULL, NULL, NULL, &pSecDesc);
1747     if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
1748     {
1749         skip("GetNamedSecurityInfoA is not implemented\n");
1750         return;
1751     }
1752     ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
1753
1754     ret = GetSecurityDescriptorControl(pSecDesc, &control, &revision);
1755     ok(ret, "GetSecurityDescriptorControl failed with error %d\n", GetLastError());
1756     ok((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == (SE_SELF_RELATIVE|SE_DACL_PRESENT),
1757         "control (0x%x) doesn't have (SE_SELF_RELATIVE|SE_DACL_PRESENT) flags set\n", control);
1758     ok(revision == SECURITY_DESCRIPTOR_REVISION1, "revision was %d instead of 1\n", revision);
1759     ret = GetSecurityDescriptorOwner(pSecDesc, &owner, &owner_defaulted);
1760     ok(ret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
1761     ok(owner != NULL, "owner should not be NULL\n");
1762     ret = GetSecurityDescriptorGroup(pSecDesc, &group, &group_defaulted);
1763     ok(ret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
1764     ok(group != NULL, "group should not be NULL\n");
1765 }
1766
1767 static void test_ConvertStringSecurityDescriptor(void)
1768 {
1769     BOOL ret;
1770     PSECURITY_DESCRIPTOR pSD;
1771
1772     if (!pConvertStringSecurityDescriptorToSecurityDescriptorA)
1773     {
1774         skip("ConvertStringSecurityDescriptorToSecurityDescriptor is not available\n");
1775         return;
1776     }
1777
1778     SetLastError(0xdeadbeef);
1779     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
1780         "D:(A;;GA;;;WD)", 0xdeadbeef, &pSD, NULL);
1781     ok(!ret && GetLastError() == ERROR_UNKNOWN_REVISION,
1782         "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_UNKNOWN_REVISION instead of %d\n",
1783         GetLastError());
1784
1785     /* test ACE string type */
1786     SetLastError(0xdeadbeef);
1787     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
1788         "D:(A;;GA;;;WD)", SDDL_REVISION_1, &pSD, NULL);
1789     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
1790     LocalFree(pSD);
1791
1792     SetLastError(0xdeadbeef);
1793     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
1794         "D:(D;;GA;;;WD)", SDDL_REVISION_1, &pSD, NULL);
1795     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
1796     LocalFree(pSD);
1797
1798     SetLastError(0xdeadbeef);
1799     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
1800         "ERROR:(D;;GA;;;WD)", SDDL_REVISION_1, &pSD, NULL);
1801     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1802         "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
1803         GetLastError());
1804
1805     /* test ACE string access rights */
1806     SetLastError(0xdeadbeef);
1807     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
1808         "D:(A;;GA;;;WD)", SDDL_REVISION_1, &pSD, NULL);
1809     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
1810     LocalFree(pSD);
1811     SetLastError(0xdeadbeef);
1812     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
1813         "D:(A;;GRGWGX;;;WD)", SDDL_REVISION_1, &pSD, NULL);
1814     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
1815     LocalFree(pSD);
1816     SetLastError(0xdeadbeef);
1817     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
1818         "D:(A;;RCSDWDWO;;;WD)", SDDL_REVISION_1, &pSD, NULL);
1819     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
1820     LocalFree(pSD);
1821     SetLastError(0xdeadbeef);
1822     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
1823         "D:(A;;RPWPCCDCLCSWLODTCR;;;WD)", SDDL_REVISION_1, &pSD, NULL);
1824     todo_wine
1825     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
1826     LocalFree(pSD);
1827     SetLastError(0xdeadbeef);
1828     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
1829         "D:(A;;FAFRFWFX;;;WD)", SDDL_REVISION_1, &pSD, NULL);
1830     todo_wine
1831     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
1832     LocalFree(pSD);
1833     SetLastError(0xdeadbeef);
1834     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
1835         "D:(A;;KAKRKWKX;;;WD)", SDDL_REVISION_1, &pSD, NULL);
1836     todo_wine
1837     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
1838     LocalFree(pSD);
1839     SetLastError(0xdeadbeef);
1840     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
1841         "D:(A;;0xFFFFFFFF;;;WD)", SDDL_REVISION_1, &pSD, NULL);
1842     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
1843     LocalFree(pSD);
1844
1845     /* test ACE string access right error case */
1846     SetLastError(0xdeadbeef);
1847     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
1848         "D:(A;;ROB;;;WD)", SDDL_REVISION_1, &pSD, NULL);
1849     todo_wine
1850     ok(!ret && GetLastError() == ERROR_INVALID_ACL,
1851         "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_ACL instead of %d\n",
1852         GetLastError());
1853
1854     /* test ACE string SID */
1855     SetLastError(0xdeadbeef);
1856     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
1857         "D:(D;;GA;;;S-1-0-0)", SDDL_REVISION_1, &pSD, NULL);
1858     ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
1859     LocalFree(pSD);
1860
1861     SetLastError(0xdeadbeef);
1862     ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
1863         "D:(D;;GA;;;Nonexistent account)", SDDL_REVISION_1, &pSD, NULL);
1864     todo_wine
1865     ok(!ret && GetLastError() == ERROR_INVALID_ACL,
1866         "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_ACL instead of %d\n",
1867         GetLastError());
1868 }
1869
1870 START_TEST(security)
1871 {
1872     init();
1873     if (!hmod) return;
1874
1875     if (myARGC >= 3)
1876     {
1877         test_process_security_child();
1878         return;
1879     }
1880     test_sid();
1881     test_trustee();
1882     test_luid();
1883     test_FileSecurity();
1884     test_AccessCheck();
1885     test_token_attr();
1886     test_LookupAccountSid();
1887     test_LookupAccountName();
1888     test_process_security();
1889     test_impersonation_level();
1890     test_SetEntriesInAcl();
1891     test_GetNamedSecurityInfoA();
1892     test_ConvertStringSecurityDescriptor();
1893 }