winmm: Turkish translation.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdio.h>
22
23 #include "wine/test.h"
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "aclapi.h"
28 #include "winnt.h"
29
30 typedef BOOL (WINAPI *fnBuildTrusteeWithSidA)( TRUSTEE *trustee, PSID psid );
31 typedef BOOL (WINAPI *fnBuildTrusteeWithNameA)( TRUSTEE *trustee, LPSTR str );
32 typedef BOOL (WINAPI *fnConvertSidToStringSidA)( PSID pSid, LPSTR *str );
33 typedef BOOL (WINAPI *fnConvertStringSidToSidA)( LPCSTR str, PSID pSid );
34 typedef BOOL (WINAPI *fnGetFileSecurityA)(LPCSTR, SECURITY_INFORMATION,
35                                           PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
36 typedef DWORD (WINAPI *fnRtlAdjustPrivilege)(ULONG,BOOLEAN,BOOLEAN,PBOOLEAN);
37
38 static HMODULE hmod;
39
40 fnBuildTrusteeWithSidA   pBuildTrusteeWithSidA;
41 fnBuildTrusteeWithNameA  pBuildTrusteeWithNameA;
42 fnConvertSidToStringSidA pConvertSidToStringSidA;
43 fnConvertStringSidToSidA pConvertStringSidToSidA;
44 fnGetFileSecurityA pGetFileSecurityA;
45 fnRtlAdjustPrivilege pRtlAdjustPrivilege;
46
47 struct sidRef
48 {
49     SID_IDENTIFIER_AUTHORITY auth;
50     const char *refStr;
51 };
52
53 static void init(void)
54 {
55     hmod = GetModuleHandle("advapi32.dll");
56 }
57
58 static void test_sid(void)
59 {
60     struct sidRef refs[] = {
61      { { {0x00,0x00,0x33,0x44,0x55,0x66} }, "S-1-860116326-1" },
62      { { {0x00,0x00,0x01,0x02,0x03,0x04} }, "S-1-16909060-1"  },
63      { { {0x00,0x00,0x00,0x01,0x02,0x03} }, "S-1-66051-1"     },
64      { { {0x00,0x00,0x00,0x00,0x01,0x02} }, "S-1-258-1"       },
65      { { {0x00,0x00,0x00,0x00,0x00,0x02} }, "S-1-2-1"         },
66      { { {0x00,0x00,0x00,0x00,0x00,0x0c} }, "S-1-12-1"        },
67     };
68     const char noSubAuthStr[] = "S-1-5";
69     unsigned int i;
70     PSID psid = NULL;
71     BOOL r;
72     LPSTR str = NULL;
73
74     pConvertSidToStringSidA = (fnConvertSidToStringSidA)
75                     GetProcAddress( hmod, "ConvertSidToStringSidA" );
76     if( !pConvertSidToStringSidA )
77         return;
78     pConvertStringSidToSidA = (fnConvertStringSidToSidA)
79                     GetProcAddress( hmod, "ConvertStringSidToSidA" );
80     if( !pConvertStringSidToSidA )
81         return;
82
83     r = pConvertStringSidToSidA( NULL, NULL );
84     ok( !r, "expected failure with NULL parameters\n" );
85     if( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED )
86         return;
87     ok( GetLastError() == ERROR_INVALID_PARAMETER,
88      "expected GetLastError() is ERROR_INVALID_PARAMETER, got %ld\n",
89      GetLastError() );
90
91     r = pConvertStringSidToSidA( refs[0].refStr, NULL );
92     ok( !r && GetLastError() == ERROR_INVALID_PARAMETER,
93      "expected GetLastError() is ERROR_INVALID_PARAMETER, got %ld\n",
94      GetLastError() );
95
96     r = pConvertStringSidToSidA( NULL, &str );
97     ok( !r && GetLastError() == ERROR_INVALID_PARAMETER,
98      "expected GetLastError() is ERROR_INVALID_PARAMETER, got %ld\n",
99      GetLastError() );
100
101     r = pConvertStringSidToSidA( noSubAuthStr, &psid );
102     ok( !r,
103      "expected failure with no sub authorities\n" );
104     ok( GetLastError() == ERROR_INVALID_SID,
105      "expected GetLastError() is ERROR_INVALID_SID, got %ld\n",
106      GetLastError() );
107
108     for( i = 0; i < sizeof(refs) / sizeof(refs[0]); i++ )
109     {
110         PISID pisid;
111
112         r = AllocateAndInitializeSid( &refs[i].auth, 1,1,0,0,0,0,0,0,0,
113          &psid );
114         ok( r, "failed to allocate sid\n" );
115         r = pConvertSidToStringSidA( psid, &str );
116         ok( r, "failed to convert sid\n" );
117         if (r)
118         {
119             ok( !strcmp( str, refs[i].refStr ),
120                 "incorrect sid, expected %s, got %s\n", refs[i].refStr, str );
121             LocalFree( str );
122         }
123         if( psid )
124             FreeSid( psid );
125
126         r = pConvertStringSidToSidA( refs[i].refStr, &psid );
127         ok( r, "failed to parse sid string\n" );
128         pisid = (PISID)psid;
129         ok( pisid &&
130          !memcmp( pisid->IdentifierAuthority.Value, refs[i].auth.Value,
131          sizeof(refs[i].auth) ),
132          "string sid %s didn't parse to expected value\n"
133          "(got 0x%04x%08lx, expected 0x%04x%08lx)\n",
134          refs[i].refStr,
135          MAKEWORD( pisid->IdentifierAuthority.Value[1],
136          pisid->IdentifierAuthority.Value[0] ),
137          MAKELONG( MAKEWORD( pisid->IdentifierAuthority.Value[5],
138          pisid->IdentifierAuthority.Value[4] ),
139          MAKEWORD( pisid->IdentifierAuthority.Value[3],
140          pisid->IdentifierAuthority.Value[2] ) ),
141          MAKEWORD( refs[i].auth.Value[1], refs[i].auth.Value[0] ),
142          MAKELONG( MAKEWORD( refs[i].auth.Value[5], refs[i].auth.Value[4] ),
143          MAKEWORD( refs[i].auth.Value[3], refs[i].auth.Value[2] ) ) );
144         if( psid )
145             LocalFree( psid );
146     }
147 }
148
149 static void test_trustee(void)
150 {
151     TRUSTEE trustee;
152     PSID psid;
153     char str[] = "2jjj";
154
155     SID_IDENTIFIER_AUTHORITY auth = { {0x11,0x22,0,0,0, 0} };
156
157     pBuildTrusteeWithSidA = (fnBuildTrusteeWithSidA)
158                     GetProcAddress( hmod, "BuildTrusteeWithSidA" );
159     pBuildTrusteeWithNameA = (fnBuildTrusteeWithNameA)
160                     GetProcAddress( hmod, "BuildTrusteeWithNameA" );
161     if( !pBuildTrusteeWithSidA || !pBuildTrusteeWithNameA)
162         return;
163
164     if ( ! AllocateAndInitializeSid( &auth, 1, 42, 0,0,0,0,0,0,0,&psid ) )
165     {
166         trace( "failed to init SID\n" );
167        return;
168     }
169
170     memset( &trustee, 0xff, sizeof trustee );
171     pBuildTrusteeWithSidA( &trustee, psid );
172
173     ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
174     ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, 
175         "MultipleTrusteeOperation wrong\n");
176     ok( trustee.TrusteeForm == TRUSTEE_IS_SID, "TrusteeForm wrong\n");
177     ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
178     ok( trustee.ptstrName == (LPSTR) psid, "ptstrName wrong\n" );
179     FreeSid( psid );
180
181     /* test BuildTrusteeWithNameA */
182     memset( &trustee, 0xff, sizeof trustee );
183     pBuildTrusteeWithNameA( &trustee, str );
184
185     ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
186     ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, 
187         "MultipleTrusteeOperation wrong\n");
188     ok( trustee.TrusteeForm == TRUSTEE_IS_NAME, "TrusteeForm wrong\n");
189     ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
190     ok( trustee.ptstrName == str, "ptstrName wrong\n" );
191 }
192  
193 /* If the first isn't defined, assume none is */
194 #ifndef SE_MIN_WELL_KNOWN_PRIVILEGE
195 #define SE_MIN_WELL_KNOWN_PRIVILEGE       2L
196 #define SE_CREATE_TOKEN_PRIVILEGE         2L
197 #define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE   3L
198 #define SE_LOCK_MEMORY_PRIVILEGE          4L
199 #define SE_INCREASE_QUOTA_PRIVILEGE       5L
200 #define SE_MACHINE_ACCOUNT_PRIVILEGE      6L
201 #define SE_TCB_PRIVILEGE                  7L
202 #define SE_SECURITY_PRIVILEGE             8L
203 #define SE_TAKE_OWNERSHIP_PRIVILEGE       9L
204 #define SE_LOAD_DRIVER_PRIVILEGE         10L
205 #define SE_SYSTEM_PROFILE_PRIVILEGE      11L
206 #define SE_SYSTEMTIME_PRIVILEGE          12L
207 #define SE_PROF_SINGLE_PROCESS_PRIVILEGE 13L
208 #define SE_INC_BASE_PRIORITY_PRIVILEGE   14L
209 #define SE_CREATE_PAGEFILE_PRIVILEGE     15L
210 #define SE_CREATE_PERMANENT_PRIVILEGE    16L
211 #define SE_BACKUP_PRIVILEGE              17L
212 #define SE_RESTORE_PRIVILEGE             18L
213 #define SE_SHUTDOWN_PRIVILEGE            19L
214 #define SE_DEBUG_PRIVILEGE               20L
215 #define SE_AUDIT_PRIVILEGE               21L
216 #define SE_SYSTEM_ENVIRONMENT_PRIVILEGE  22L
217 #define SE_CHANGE_NOTIFY_PRIVILLEGE      23L
218 #define SE_REMOTE_SHUTDOWN_PRIVILEGE     24L
219 #define SE_UNDOCK_PRIVILEGE              25L
220 #define SE_SYNC_AGENT_PRIVILEGE          26L
221 #define SE_ENABLE_DELEGATION_PRIVILEGE   27L
222 #define SE_MANAGE_VOLUME_PRIVILEGE       28L
223 #define SE_IMPERSONATE_PRIVILEGE         29L
224 #define SE_CREATE_GLOBAL_PRIVILEGE       30L
225 #define SE_MAX_WELL_KNOWN_PRIVILEGE      SE_CREATE_GLOBAL_PRIVILEGE
226 #endif /* ndef SE_MIN_WELL_KNOWN_PRIVILEGE */
227
228 static void test_allocateLuid(void)
229 {
230     BOOL (WINAPI *pAllocateLocallyUniqueId)(PLUID);
231     LUID luid1, luid2;
232     BOOL ret;
233
234     pAllocateLocallyUniqueId = (void*)GetProcAddress(hmod, "AllocateLocallyUniqueId");
235     if (!pAllocateLocallyUniqueId) return;
236
237     ret = pAllocateLocallyUniqueId(&luid1);
238     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
239         return;
240
241     ok(ret,
242      "AllocateLocallyUniqueId failed: %ld\n", GetLastError());
243     ret = pAllocateLocallyUniqueId(&luid2);
244     ok( ret,
245      "AllocateLocallyUniqueId failed: %ld\n", GetLastError());
246     ok(luid1.LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE || luid1.HighPart != 0,
247      "AllocateLocallyUniqueId returned a well-known LUID\n");
248     ok(luid1.LowPart != luid2.LowPart || luid1.HighPart != luid2.HighPart,
249      "AllocateLocallyUniqueId returned non-unique LUIDs\n");
250     ret = pAllocateLocallyUniqueId(NULL);
251     ok( !ret && GetLastError() == ERROR_NOACCESS,
252      "AllocateLocallyUniqueId(NULL) didn't return ERROR_NOACCESS: %ld\n",
253      GetLastError());
254 }
255
256 static void test_lookupPrivilegeName(void)
257 {
258     BOOL (WINAPI *pLookupPrivilegeNameA)(LPCSTR, PLUID, LPSTR, LPDWORD);
259     char buf[MAX_PATH]; /* arbitrary, seems long enough */
260     DWORD cchName = sizeof(buf);
261     LUID luid = { 0, 0 };
262     LONG i;
263     BOOL ret;
264
265     /* check whether it's available first */
266     pLookupPrivilegeNameA = (void*)GetProcAddress(hmod, "LookupPrivilegeNameA");
267     if (!pLookupPrivilegeNameA) return;
268     luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
269     ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
270     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
271         return;
272
273     /* check with a short buffer */
274     cchName = 0;
275     luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
276     ret = pLookupPrivilegeNameA(NULL, &luid, NULL, &cchName);
277     ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
278      "LookupPrivilegeNameA didn't fail with ERROR_INSUFFICIENT_BUFFER: %ld\n",
279      GetLastError());
280     ok(cchName == strlen("SeCreateTokenPrivilege") + 1,
281      "LookupPrivilegeNameA returned an incorrect required length for\n"
282      "SeCreateTokenPrivilege (got %ld, expected %d)\n", cchName,
283      strlen("SeCreateTokenPrivilege") + 1);
284     /* check a known value and its returned length on success */
285     cchName = sizeof(buf);
286     ok(pLookupPrivilegeNameA(NULL, &luid, buf, &cchName) &&
287      cchName == strlen("SeCreateTokenPrivilege"),
288      "LookupPrivilegeNameA returned an incorrect output length for\n"
289      "SeCreateTokenPrivilege (got %ld, expected %d)\n", cchName,
290      (int)strlen("SeCreateTokenPrivilege"));
291     /* check known values */
292     for (i = SE_MIN_WELL_KNOWN_PRIVILEGE; i < SE_MAX_WELL_KNOWN_PRIVILEGE; i++)
293     {
294         luid.LowPart = i;
295         cchName = sizeof(buf);
296         ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
297         ok( ret || GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
298          "LookupPrivilegeNameA(0.%ld) failed: %ld\n", i, GetLastError());
299     }
300     /* check a bogus LUID */
301     luid.LowPart = 0xdeadbeef;
302     cchName = sizeof(buf);
303     ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
304     ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
305      "LookupPrivilegeNameA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %ld\n",
306      GetLastError());
307     /* check on a bogus system */
308     luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
309     cchName = sizeof(buf);
310     ret = pLookupPrivilegeNameA("b0gu5.Nam3", &luid, buf, &cchName);
311     ok( !ret && GetLastError() == RPC_S_SERVER_UNAVAILABLE,
312      "LookupPrivilegeNameA didn't fail with RPC_S_SERVER_UNAVAILABLE: %ld\n",
313      GetLastError());
314 }
315
316 struct NameToLUID
317 {
318     const char *name;
319     DWORD lowPart;
320 };
321
322 static void test_lookupPrivilegeValue(void)
323 {
324     static const struct NameToLUID privs[] = {
325      { "SeCreateTokenPrivilege", SE_CREATE_TOKEN_PRIVILEGE },
326      { "SeAssignPrimaryTokenPrivilege", SE_ASSIGNPRIMARYTOKEN_PRIVILEGE },
327      { "SeLockMemoryPrivilege", SE_LOCK_MEMORY_PRIVILEGE },
328      { "SeIncreaseQuotaPrivilege", SE_INCREASE_QUOTA_PRIVILEGE },
329      { "SeMachineAccountPrivilege", SE_MACHINE_ACCOUNT_PRIVILEGE },
330      { "SeTcbPrivilege", SE_TCB_PRIVILEGE },
331      { "SeSecurityPrivilege", SE_SECURITY_PRIVILEGE },
332      { "SeTakeOwnershipPrivilege", SE_TAKE_OWNERSHIP_PRIVILEGE },
333      { "SeLoadDriverPrivilege", SE_LOAD_DRIVER_PRIVILEGE },
334      { "SeSystemProfilePrivilege", SE_SYSTEM_PROFILE_PRIVILEGE },
335      { "SeSystemtimePrivilege", SE_SYSTEMTIME_PRIVILEGE },
336      { "SeProfileSingleProcessPrivilege", SE_PROF_SINGLE_PROCESS_PRIVILEGE },
337      { "SeIncreaseBasePriorityPrivilege", SE_INC_BASE_PRIORITY_PRIVILEGE },
338      { "SeCreatePagefilePrivilege", SE_CREATE_PAGEFILE_PRIVILEGE },
339      { "SeCreatePermanentPrivilege", SE_CREATE_PERMANENT_PRIVILEGE },
340      { "SeBackupPrivilege", SE_BACKUP_PRIVILEGE },
341      { "SeRestorePrivilege", SE_RESTORE_PRIVILEGE },
342      { "SeShutdownPrivilege", SE_SHUTDOWN_PRIVILEGE },
343      { "SeDebugPrivilege", SE_DEBUG_PRIVILEGE },
344      { "SeAuditPrivilege", SE_AUDIT_PRIVILEGE },
345      { "SeSystemEnvironmentPrivilege", SE_SYSTEM_ENVIRONMENT_PRIVILEGE },
346      { "SeChangeNotifyPrivilege", SE_CHANGE_NOTIFY_PRIVILLEGE },
347      { "SeRemoteShutdownPrivilege", SE_REMOTE_SHUTDOWN_PRIVILEGE },
348      { "SeUndockPrivilege", SE_UNDOCK_PRIVILEGE },
349      { "SeSyncAgentPrivilege", SE_SYNC_AGENT_PRIVILEGE },
350      { "SeEnableDelegationPrivilege", SE_ENABLE_DELEGATION_PRIVILEGE },
351      { "SeManageVolumePrivilege", SE_MANAGE_VOLUME_PRIVILEGE },
352      { "SeImpersonatePrivilege", SE_IMPERSONATE_PRIVILEGE },
353      { "SeCreateGlobalPrivilege", SE_CREATE_GLOBAL_PRIVILEGE },
354     };
355     BOOL (WINAPI *pLookupPrivilegeValueA)(LPCSTR, LPCSTR, PLUID);
356     int i;
357     LUID luid;
358     BOOL ret;
359
360     /* check whether it's available first */
361     pLookupPrivilegeValueA = (void*)GetProcAddress(hmod, "LookupPrivilegeValueA");
362     if (!pLookupPrivilegeValueA) return;
363     ret = pLookupPrivilegeValueA(NULL, "SeCreateTokenPrivilege", &luid);
364     if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
365         return;
366
367     /* check a bogus system name */
368     ret = pLookupPrivilegeValueA("b0gu5.Nam3", "SeCreateTokenPrivilege", &luid);
369     ok( !ret && GetLastError() == RPC_S_SERVER_UNAVAILABLE,
370      "LookupPrivilegeValueA didn't fail with RPC_S_SERVER_UNAVAILABLE: %ld\n",
371      GetLastError());
372     /* check a NULL string */
373     ret = pLookupPrivilegeValueA(NULL, 0, &luid);
374     ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
375      "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %ld\n",
376      GetLastError());
377     /* check a bogus privilege name */
378     ret = pLookupPrivilegeValueA(NULL, "SeBogusPrivilege", &luid);
379     ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
380      "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %ld\n",
381      GetLastError());
382     /* check case insensitive */
383     ret = pLookupPrivilegeValueA(NULL, "sEcREATEtOKENpRIVILEGE", &luid);
384     ok( ret,
385      "LookupPrivilegeValueA(NULL, sEcREATEtOKENpRIVILEGE, &luid) failed: %ld\n",
386      GetLastError());
387     for (i = 0; i < sizeof(privs) / sizeof(privs[0]); i++)
388     {
389         /* Not all privileges are implemented on all Windows versions, so
390          * don't worry if the call fails
391          */
392         if (pLookupPrivilegeValueA(NULL, privs[i].name, &luid))
393         {
394             ok(luid.LowPart == privs[i].lowPart,
395              "LookupPrivilegeValueA returned an invalid LUID for %s\n",
396              privs[i].name);
397         }
398     }
399 }
400
401 static void test_luid(void)
402 {
403     test_allocateLuid();
404     test_lookupPrivilegeName();
405     test_lookupPrivilegeValue();
406 }
407
408 static void test_FileSecurity(void)
409 {
410     char directory[MAX_PATH];
411     DWORD retval, outSize;
412     BOOL result;
413     BYTE buffer[0x40];
414
415     pGetFileSecurityA = (fnGetFileSecurityA)
416                     GetProcAddress( hmod, "GetFileSecurityA" );
417     if( !pGetFileSecurityA )
418         return;
419
420     retval = GetTempPathA(sizeof(directory), directory);
421     if (!retval) {
422         trace("GetTempPathA failed\n");
423         return;
424     }
425
426     strcpy(directory, "\\Should not exist");
427
428     SetLastError(NO_ERROR);
429     result = pGetFileSecurityA( directory,OWNER_SECURITY_INFORMATION,buffer,0x40,&outSize);
430     ok(!result, "GetFileSecurityA should fail for not existing directories/files\n"); 
431     ok( (GetLastError() == ERROR_FILE_NOT_FOUND ) ||
432         (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) , 
433         "last error ERROR_FILE_NOT_FOUND / ERROR_CALL_NOT_IMPLEMENTED (98) "
434         "expected, got %ld\n", GetLastError());
435 }
436
437 static void test_AccessCheck(void)
438 {
439     PSID EveryoneSid = NULL, AdminSid = NULL, UsersSid = NULL;
440     PACL Acl = NULL;
441     SECURITY_DESCRIPTOR *SecurityDescriptor = NULL;
442     SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
443     SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
444     GENERIC_MAPPING Mapping = { KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS };
445     ACCESS_MASK Access;
446     BOOL AccessStatus;
447     HANDLE Token;
448     BOOL ret;
449     DWORD PrivSetLen;
450     PRIVILEGE_SET *PrivSet;
451     BOOL res;
452     HMODULE NtDllModule;
453     BOOLEAN Enabled;
454
455     NtDllModule = GetModuleHandle("ntdll.dll");
456
457     if (!NtDllModule)
458     {
459         trace("not running on NT, skipping test\n");
460         return;
461     }
462     pRtlAdjustPrivilege = (fnRtlAdjustPrivilege)
463                           GetProcAddress(NtDllModule, "RtlAdjustPrivilege");
464     if (!pRtlAdjustPrivilege) return;
465
466     Acl = HeapAlloc(GetProcessHeap(), 0, 256);
467     res = InitializeAcl(Acl, 256, ACL_REVISION);
468     if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
469     {
470         trace("ACLs not implemented - skipping tests\n");
471         return;
472     }
473     ok(res, "InitializeAcl failed with error %ld\n", GetLastError());
474
475     res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
476     ok(res, "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
477
478     res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
479         DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminSid);
480     ok(res, "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
481
482     res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
483         DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid);
484     ok(res, "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
485
486     res = AddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, EveryoneSid);
487     ok(res, "AddAccessAllowedAceEx failed with error %ld\n", GetLastError());
488
489     res = AddAccessAllowedAce(Acl, ACL_REVISION, KEY_ALL_ACCESS, AdminSid);
490     ok(res, "AddAccessAllowedAceEx failed with error %ld\n", GetLastError());
491
492     SecurityDescriptor = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
493
494     res = InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
495     ok(res, "InitializeSecurityDescriptor failed with error %ld\n", GetLastError());
496
497     res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
498     ok(res, "SetSecurityDescriptorDacl failed with error %ld\n", GetLastError());
499
500     res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE);
501     ok(res, "SetSecurityDescriptorOwner failed with error %ld\n", GetLastError());
502
503     res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, TRUE);
504     ok(res, "SetSecurityDescriptorGroup failed with error %ld\n", GetLastError());
505
506     PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
507     PrivSet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, PrivSetLen);
508     PrivSet->PrivilegeCount = 16;
509
510     ImpersonateSelf(SecurityImpersonation);
511
512     pRtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, FALSE, TRUE, &Enabled);
513
514     ret = OpenThreadToken(GetCurrentThread(),
515                           TOKEN_QUERY, TRUE, &Token);
516     ok(ret, "OpenThreadToken failed with error %ld\n", GetLastError());
517
518     ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
519                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
520     ok(ret, "AccessCheck failed with error %ld\n", GetLastError());
521     ok(AccessStatus && (Access == KEY_READ),
522         "AccessCheck failed to grant access with error %ld\n",
523         GetLastError());
524
525     ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping,
526                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
527     ok(ret, "AccessCheck failed with error %ld\n", GetLastError());
528     ok(AccessStatus,
529         "AccessCheck failed to grant any access with error %ld\n",
530         GetLastError());
531     trace("AccessCheck with MAXIMUM_ALLOWED got Access 0x%08lx\n", Access);
532
533     SetLastError(0);
534     PrivSet->PrivilegeCount = 16;
535     ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping,
536                       PrivSet, &PrivSetLen, &Access, &AccessStatus);
537     ok(ret && !AccessStatus && GetLastError() == ERROR_PRIVILEGE_NOT_HELD,
538         "AccessCheck should have failed with ERROR_PRIVILEGE_NOT_HELD, instead of %ld\n",
539         GetLastError());
540
541     ret = pRtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, TRUE, TRUE, &Enabled);
542     if (!ret)
543     {
544         SetLastError(0);
545         PrivSet->PrivilegeCount = 16;
546         ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping,
547                           PrivSet, &PrivSetLen, &Access, &AccessStatus);
548         ok(ret && AccessStatus && GetLastError() == 0,
549             "AccessCheck should have succeeded, error %ld\n",
550             GetLastError());
551         ok(Access == ACCESS_SYSTEM_SECURITY,
552             "Access should be equal to ACCESS_SYSTEM_SECURITY instead of 0x%08lx\n",
553             Access);
554     }
555     else
556         trace("Couldn't get SE_SECURITY_PRIVILEGE (0x%08x), skipping ACCESS_SYSTEM_SECURITY test\n",
557             ret);
558
559     RevertToSelf();
560
561     if (EveryoneSid)
562         FreeSid(EveryoneSid);
563     if (AdminSid)
564         FreeSid(AdminSid);
565     if (UsersSid)
566         FreeSid(UsersSid);
567     HeapFree(GetProcessHeap(), 0, Acl);
568     HeapFree(GetProcessHeap(), 0, SecurityDescriptor);
569     HeapFree(GetProcessHeap(), 0, PrivSet);
570 }
571
572 START_TEST(security)
573 {
574     init();
575     if (!hmod) return;
576     test_sid();
577     test_trustee();
578     test_luid();
579     test_FileSecurity();
580     test_AccessCheck();
581 }