advapi32/tests: Test token label inheritance.
[wine.git] / dlls / advapi32 / tests / security.c
blob77a6c747916718caabd8b821fcd8cda1c68d850c
1 /*
2 * Unit tests for security functions
4 * Copyright (c) 2004 Mike McCormack
5 * Copyright (c) 2011 Dmitry Timoshkov
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdarg.h>
23 #include <stdio.h>
25 #include "ntstatus.h"
26 #define WIN32_NO_STATUS
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #include "winternl.h"
31 #include "aclapi.h"
32 #include "winnt.h"
33 #include "sddl.h"
34 #include "ntsecapi.h"
35 #include "lmcons.h"
37 #include "wine/test.h"
39 #ifndef PROCESS_QUERY_LIMITED_INFORMATION
40 #define PROCESS_QUERY_LIMITED_INFORMATION 0x1000
41 #endif
43 /* PROCESS_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
44 #define PROCESS_ALL_ACCESS_NT4 (PROCESS_ALL_ACCESS & ~0xf000)
45 #define PROCESS_ALL_ACCESS_VISTA (PROCESS_ALL_ACCESS | 0xf000)
47 #ifndef EVENT_QUERY_STATE
48 #define EVENT_QUERY_STATE 0x0001
49 #endif
51 #ifndef SEMAPHORE_QUERY_STATE
52 #define SEMAPHORE_QUERY_STATE 0x0001
53 #endif
55 #ifndef THREAD_SET_LIMITED_INFORMATION
56 #define THREAD_SET_LIMITED_INFORMATION 0x0400
57 #define THREAD_QUERY_LIMITED_INFORMATION 0x0800
58 #endif
60 #define THREAD_ALL_ACCESS_NT4 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff)
61 #define THREAD_ALL_ACCESS_VISTA (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xffff)
63 #define expect_eq(expr, value, type, format) { type ret_ = expr; ok((value) == ret_, #expr " expected " format " got " format "\n", (value), (ret_)); }
65 static BOOL (WINAPI *pAddAccessAllowedAceEx)(PACL, DWORD, DWORD, DWORD, PSID);
66 static BOOL (WINAPI *pAddAccessDeniedAceEx)(PACL, DWORD, DWORD, DWORD, PSID);
67 static BOOL (WINAPI *pAddAuditAccessAceEx)(PACL, DWORD, DWORD, DWORD, PSID, BOOL, BOOL);
68 static BOOL (WINAPI *pAddMandatoryAce)(PACL,DWORD,DWORD,DWORD,PSID);
69 static VOID (WINAPI *pBuildTrusteeWithSidA)( PTRUSTEEA pTrustee, PSID pSid );
70 static VOID (WINAPI *pBuildTrusteeWithNameA)( PTRUSTEEA pTrustee, LPSTR pName );
71 static VOID (WINAPI *pBuildTrusteeWithObjectsAndNameA)( PTRUSTEEA pTrustee,
72 POBJECTS_AND_NAME_A pObjName,
73 SE_OBJECT_TYPE ObjectType,
74 LPSTR ObjectTypeName,
75 LPSTR InheritedObjectTypeName,
76 LPSTR Name );
77 static VOID (WINAPI *pBuildTrusteeWithObjectsAndSidA)( PTRUSTEEA pTrustee,
78 POBJECTS_AND_SID pObjSid,
79 GUID* pObjectGuid,
80 GUID* pInheritedObjectGuid,
81 PSID pSid );
82 static LPSTR (WINAPI *pGetTrusteeNameA)( PTRUSTEEA pTrustee );
83 static BOOL (WINAPI *pCheckTokenMembership)(HANDLE, PSID, PBOOL);
84 static BOOL (WINAPI *pConvertStringSecurityDescriptorToSecurityDescriptorW)(LPCWSTR, DWORD,
85 PSECURITY_DESCRIPTOR*, PULONG );
86 static BOOL (WINAPI *pConvertSecurityDescriptorToStringSecurityDescriptorA)(PSECURITY_DESCRIPTOR, DWORD,
87 SECURITY_INFORMATION, LPSTR *, PULONG );
88 static BOOL (WINAPI *pSetFileSecurityA)(LPCSTR, SECURITY_INFORMATION,
89 PSECURITY_DESCRIPTOR);
90 static DWORD (WINAPI *pGetNamedSecurityInfoA)(const char *, SE_OBJECT_TYPE, SECURITY_INFORMATION,
91 PSID*, PSID*, PACL*, PACL*,
92 PSECURITY_DESCRIPTOR*);
93 static DWORD (WINAPI *pSetNamedSecurityInfoA)(LPSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION,
94 PSID, PSID, PACL, PACL);
95 static DWORD (WINAPI *pRtlAdjustPrivilege)(ULONG,BOOLEAN,BOOLEAN,PBOOLEAN);
96 static BOOL (WINAPI *pDuplicateTokenEx)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES,
97 SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,PHANDLE);
99 static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,ULONG,PULONG);
100 static DWORD (WINAPI *pSetEntriesInAclW)(ULONG, PEXPLICIT_ACCESSW, PACL, PACL*);
101 static BOOL (WINAPI *pSetSecurityDescriptorControl)(PSECURITY_DESCRIPTOR, SECURITY_DESCRIPTOR_CONTROL,
102 SECURITY_DESCRIPTOR_CONTROL);
103 static DWORD (WINAPI *pSetSecurityInfo)(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
104 PSID, PSID, PACL, PACL);
105 static NTSTATUS (WINAPI *pNtAccessCheck)(PSECURITY_DESCRIPTOR, HANDLE, ACCESS_MASK, PGENERIC_MAPPING,
106 PPRIVILEGE_SET, PULONG, PULONG, NTSTATUS*);
107 static NTSTATUS (WINAPI *pNtSetSecurityObject)(HANDLE,SECURITY_INFORMATION,PSECURITY_DESCRIPTOR);
108 static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG);
109 static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)(LPCWSTR,PUNICODE_STRING,PWSTR*,CURDIR*);
110 static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING,PCANSI_STRING,BOOLEAN);
111 static BOOL (WINAPI *pGetWindowsAccountDomainSid)(PSID,PSID,DWORD*);
112 static BOOL (WINAPI *pEqualDomainSid)(PSID,PSID,BOOL*);
113 static void (WINAPI *pRtlInitAnsiString)(PANSI_STRING,PCSZ);
114 static NTSTATUS (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
115 static PSID_IDENTIFIER_AUTHORITY (WINAPI *pGetSidIdentifierAuthority)(PSID);
116 static DWORD (WINAPI *pGetExplicitEntriesFromAclW)(PACL,PULONG,PEXPLICIT_ACCESSW*);
118 static HMODULE hmod;
119 static int myARGC;
120 static char** myARGV;
122 static const char* debugstr_sid(PSID sid)
124 LPSTR sidstr;
125 DWORD le = GetLastError();
126 const char *res;
128 if (!ConvertSidToStringSidA(sid, &sidstr))
129 res = wine_dbg_sprintf("ConvertSidToStringSidA failed le=%lu", GetLastError());
130 else
132 res = __wine_dbg_strdup(sidstr);
133 LocalFree(sidstr);
135 /* Restore the last error in case ConvertSidToStringSidA() modified it */
136 SetLastError(le);
137 return res;
140 struct sidRef
142 SID_IDENTIFIER_AUTHORITY auth;
143 const char *refStr;
146 static void init(void)
148 HMODULE hntdll;
150 hntdll = GetModuleHandleA("ntdll.dll");
151 pNtQueryObject = (void *)GetProcAddress( hntdll, "NtQueryObject" );
152 pNtAccessCheck = (void *)GetProcAddress( hntdll, "NtAccessCheck" );
153 pNtSetSecurityObject = (void *)GetProcAddress(hntdll, "NtSetSecurityObject");
154 pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile");
155 pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
156 pRtlAnsiStringToUnicodeString = (void *)GetProcAddress(hntdll, "RtlAnsiStringToUnicodeString");
157 pRtlInitAnsiString = (void *)GetProcAddress(hntdll, "RtlInitAnsiString");
158 pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
160 hmod = GetModuleHandleA("advapi32.dll");
161 pAddAccessAllowedAceEx = (void *)GetProcAddress(hmod, "AddAccessAllowedAceEx");
162 pAddAccessDeniedAceEx = (void *)GetProcAddress(hmod, "AddAccessDeniedAceEx");
163 pAddAuditAccessAceEx = (void *)GetProcAddress(hmod, "AddAuditAccessAceEx");
164 pAddMandatoryAce = (void *)GetProcAddress(hmod, "AddMandatoryAce");
165 pCheckTokenMembership = (void *)GetProcAddress(hmod, "CheckTokenMembership");
166 pConvertStringSecurityDescriptorToSecurityDescriptorW =
167 (void *)GetProcAddress(hmod, "ConvertStringSecurityDescriptorToSecurityDescriptorW" );
168 pConvertSecurityDescriptorToStringSecurityDescriptorA =
169 (void *)GetProcAddress(hmod, "ConvertSecurityDescriptorToStringSecurityDescriptorA" );
170 pSetFileSecurityA = (void *)GetProcAddress(hmod, "SetFileSecurityA" );
171 pGetNamedSecurityInfoA = (void *)GetProcAddress(hmod, "GetNamedSecurityInfoA");
172 pSetNamedSecurityInfoA = (void *)GetProcAddress(hmod, "SetNamedSecurityInfoA");
173 pSetEntriesInAclW = (void *)GetProcAddress(hmod, "SetEntriesInAclW");
174 pSetSecurityDescriptorControl = (void *)GetProcAddress(hmod, "SetSecurityDescriptorControl");
175 pSetSecurityInfo = (void *)GetProcAddress(hmod, "SetSecurityInfo");
176 pGetWindowsAccountDomainSid = (void *)GetProcAddress(hmod, "GetWindowsAccountDomainSid");
177 pEqualDomainSid = (void *)GetProcAddress(hmod, "EqualDomainSid");
178 pGetSidIdentifierAuthority = (void *)GetProcAddress(hmod, "GetSidIdentifierAuthority");
179 pDuplicateTokenEx = (void *)GetProcAddress(hmod, "DuplicateTokenEx");
180 pGetExplicitEntriesFromAclW = (void *)GetProcAddress(hmod, "GetExplicitEntriesFromAclW");
182 myARGC = winetest_get_mainargs( &myARGV );
185 static SECURITY_DESCRIPTOR* test_get_security_descriptor(HANDLE handle, int line)
187 /* use free(sd); when done */
188 DWORD ret, length, needed;
189 SECURITY_DESCRIPTOR *sd;
191 needed = 0xdeadbeef;
192 SetLastError(0xdeadbeef);
193 ret = GetKernelObjectSecurity(handle, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
194 NULL, 0, &needed);
195 ok_(__FILE__, line)(!ret, "GetKernelObjectSecurity should fail\n");
196 ok_(__FILE__, line)(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
197 ok_(__FILE__, line)(needed != 0xdeadbeef, "GetKernelObjectSecurity should return required buffer length\n");
199 length = needed;
200 sd = malloc(length);
202 needed = 0xdeadbeef;
203 SetLastError(0xdeadbeef);
204 ret = GetKernelObjectSecurity(handle, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
205 sd, length, &needed);
206 ok_(__FILE__, line)(ret, "GetKernelObjectSecurity error %ld\n", GetLastError());
207 ok_(__FILE__, line)(needed == length || needed == 0 /* file, pipe */, "GetKernelObjectSecurity should return %lu instead of %lu\n", length, needed);
208 return sd;
211 static void test_owner_equal(HANDLE Handle, PSID expected, int line)
213 BOOL res;
214 SECURITY_DESCRIPTOR *queriedSD = NULL;
215 PSID owner;
216 BOOL owner_defaulted;
218 queriedSD = test_get_security_descriptor( Handle, line );
220 res = GetSecurityDescriptorOwner(queriedSD, &owner, &owner_defaulted);
221 ok_(__FILE__, line)(res, "GetSecurityDescriptorOwner failed with error %ld\n", GetLastError());
223 ok_(__FILE__, line)(EqualSid(owner, expected), "Owner SIDs are not equal %s != %s\n",
224 debugstr_sid(owner), debugstr_sid(expected));
225 ok_(__FILE__, line)(!owner_defaulted, "Defaulted is true\n");
227 free(queriedSD);
230 static void test_group_equal(HANDLE Handle, PSID expected, int line)
232 BOOL res;
233 SECURITY_DESCRIPTOR *queriedSD = NULL;
234 PSID group;
235 BOOL group_defaulted;
237 queriedSD = test_get_security_descriptor( Handle, line );
239 res = GetSecurityDescriptorGroup(queriedSD, &group, &group_defaulted);
240 ok_(__FILE__, line)(res, "GetSecurityDescriptorGroup failed with error %ld\n", GetLastError());
242 ok_(__FILE__, line)(EqualSid(group, expected), "Group SIDs are not equal %s != %s\n",
243 debugstr_sid(group), debugstr_sid(expected));
244 ok_(__FILE__, line)(!group_defaulted, "Defaulted is true\n");
246 free(queriedSD);
249 static void test_ConvertStringSidToSid(void)
251 struct sidRef refs[] = {
252 { { {0x00,0x00,0x33,0x44,0x55,0x66} }, "S-1-860116326-1" },
253 { { {0x00,0x00,0x01,0x02,0x03,0x04} }, "S-1-16909060-1" },
254 { { {0x00,0x00,0x00,0x01,0x02,0x03} }, "S-1-66051-1" },
255 { { {0x00,0x00,0x00,0x00,0x01,0x02} }, "S-1-258-1" },
256 { { {0x00,0x00,0x00,0x00,0x00,0x02} }, "S-1-2-1" },
257 { { {0x00,0x00,0x00,0x00,0x00,0x0c} }, "S-1-12-1" },
259 static const struct
261 const char *name;
262 const char *sid;
263 unsigned int optional;
265 str_to_sid_tests[] =
267 { "WD", "S-1-1-0" },
268 { "wD", "S-1-1-0" },
269 { "CO", "S-1-3-0" },
270 { "CG", "S-1-3-1" },
271 { "OW", "S-1-3-4", 1 }, /* Vista+ */
272 { "NU", "S-1-5-2" },
273 { "IU", "S-1-5-4" },
274 { "SU", "S-1-5-6" },
275 { "AN", "S-1-5-7" },
276 { "ED", "S-1-5-9" },
277 { "PS", "S-1-5-10" },
278 { "AU", "S-1-5-11" },
279 { "RC", "S-1-5-12" },
280 { "SY", "S-1-5-18" },
281 { "LS", "S-1-5-19" },
282 { "NS", "S-1-5-20" },
283 { "LA", "S-1-5-21-*-*-*-500" },
284 { "LG", "S-1-5-21-*-*-*-501" },
285 { "BO", "S-1-5-32-551" },
286 { "BA", "S-1-5-32-544" },
287 { "BU", "S-1-5-32-545" },
288 { "BG", "S-1-5-32-546" },
289 { "PU", "S-1-5-32-547" },
290 { "AO", "S-1-5-32-548" },
291 { "SO", "S-1-5-32-549" },
292 { "PO", "S-1-5-32-550" },
293 { "RE", "S-1-5-32-552" },
294 { "RU", "S-1-5-32-554" },
295 { "RD", "S-1-5-32-555" },
296 { "NO", "S-1-5-32-556" },
297 { "AC", "S-1-15-2-1", 1 }, /* Win8+ */
298 { "CA", "", 1 },
299 { "DA", "", 1 },
300 { "DC", "", 1 },
301 { "DD", "", 1 },
302 { "DG", "", 1 },
303 { "DU", "", 1 },
304 { "EA", "", 1 },
305 { "PA", "", 1 },
306 { "RS", "", 1 },
307 { "SA", "", 1 },
308 { "s-1-12-1", "S-1-12-1" },
309 { "S-0x1-0XC-0x1a", "S-1-12-26" },
312 const char noSubAuthStr[] = "S-1-5";
313 unsigned int i;
314 PSID psid = NULL;
315 SID *pisid;
316 BOOL r, ret;
317 LPSTR str = NULL;
319 r = ConvertStringSidToSidA( NULL, NULL );
320 ok( !r, "expected failure with NULL parameters\n" );
321 if( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED )
322 return;
323 ok( GetLastError() == ERROR_INVALID_PARAMETER,
324 "expected GetLastError() is ERROR_INVALID_PARAMETER, got %ld\n",
325 GetLastError() );
327 r = ConvertStringSidToSidA( refs[0].refStr, NULL );
328 ok( !r && GetLastError() == ERROR_INVALID_PARAMETER,
329 "expected GetLastError() is ERROR_INVALID_PARAMETER, got %ld\n",
330 GetLastError() );
332 r = ConvertStringSidToSidA( NULL, &psid );
333 ok( !r && GetLastError() == ERROR_INVALID_PARAMETER,
334 "expected GetLastError() is ERROR_INVALID_PARAMETER, got %ld\n",
335 GetLastError() );
337 r = ConvertStringSidToSidA( noSubAuthStr, &psid );
338 ok( !r,
339 "expected failure with no sub authorities\n" );
340 ok( GetLastError() == ERROR_INVALID_SID,
341 "expected GetLastError() is ERROR_INVALID_SID, got %ld\n",
342 GetLastError() );
344 r = ConvertStringSidToSidA( "WDandmorecharacters", &psid );
345 ok( !r,
346 "expected failure with too many characters\n" );
347 ok( GetLastError() == ERROR_INVALID_SID,
348 "expected GetLastError() is ERROR_INVALID_SID, got %ld\n",
349 GetLastError() );
351 r = ConvertStringSidToSidA( "WD)", &psid );
352 ok( !r,
353 "expected failure with too many characters\n" );
354 ok( GetLastError() == ERROR_INVALID_SID,
355 "expected GetLastError() is ERROR_INVALID_SID, got %ld\n",
356 GetLastError() );
358 ok(ConvertStringSidToSidA("S-1-5-21-93476-23408-4576", &psid), "ConvertStringSidToSidA failed\n");
359 pisid = psid;
360 ok(pisid->SubAuthorityCount == 4, "Invalid sub authority count - expected 4, got %d\n", pisid->SubAuthorityCount);
361 ok(pisid->SubAuthority[0] == 21, "Invalid subauthority 0 - expected 21, got %ld\n", pisid->SubAuthority[0]);
362 ok(pisid->SubAuthority[3] == 4576, "Invalid subauthority 0 - expected 4576, got %ld\n", pisid->SubAuthority[3]);
363 LocalFree(str);
364 LocalFree(psid);
366 for( i = 0; i < ARRAY_SIZE(refs); i++ )
368 r = AllocateAndInitializeSid( &refs[i].auth, 1,1,0,0,0,0,0,0,0,
369 &psid );
370 ok( r, "failed to allocate sid\n" );
371 r = ConvertSidToStringSidA( psid, &str );
372 ok( r, "failed to convert sid\n" );
373 if (r)
375 ok( !strcmp( str, refs[i].refStr ),
376 "incorrect sid, expected %s, got %s\n", refs[i].refStr, str );
377 LocalFree( str );
379 if( psid )
380 FreeSid( psid );
382 r = ConvertStringSidToSidA( refs[i].refStr, &psid );
383 ok( r, "failed to parse sid string\n" );
384 pisid = psid;
385 ok( pisid &&
386 !memcmp( pisid->IdentifierAuthority.Value, refs[i].auth.Value,
387 sizeof(refs[i].auth) ),
388 "string sid %s didn't parse to expected value\n"
389 "(got 0x%04x%08lx, expected 0x%04x%08lx)\n",
390 refs[i].refStr,
391 MAKEWORD( pisid->IdentifierAuthority.Value[1],
392 pisid->IdentifierAuthority.Value[0] ),
393 MAKELONG( MAKEWORD( pisid->IdentifierAuthority.Value[5],
394 pisid->IdentifierAuthority.Value[4] ),
395 MAKEWORD( pisid->IdentifierAuthority.Value[3],
396 pisid->IdentifierAuthority.Value[2] ) ),
397 MAKEWORD( refs[i].auth.Value[1], refs[i].auth.Value[0] ),
398 MAKELONG( MAKEWORD( refs[i].auth.Value[5], refs[i].auth.Value[4] ),
399 MAKEWORD( refs[i].auth.Value[3], refs[i].auth.Value[2] ) ) );
400 if( psid )
401 LocalFree( psid );
404 for (i = 0; i < ARRAY_SIZE(str_to_sid_tests); i++)
406 char *str;
408 ret = ConvertStringSidToSidA(str_to_sid_tests[i].name, &psid);
409 if (!ret && str_to_sid_tests[i].optional)
411 skip("%u: failed to convert %s.\n", i, str_to_sid_tests[i].name);
412 continue;
414 ok(ret, "%u: failed to convert string to sid.\n", i);
416 if (str_to_sid_tests[i].optional || !strcmp(str_to_sid_tests[i].name, "LA") ||
417 !strcmp(str_to_sid_tests[i].name, "LG"))
419 LocalFree(psid);
420 continue;
423 ret = ConvertSidToStringSidA(psid, &str);
424 ok(ret, "%u: failed to convert SID to string.\n", i);
425 ok(!strcmp(str, str_to_sid_tests[i].sid), "%u: unexpected sid %s.\n", i, str);
426 LocalFree(psid);
427 LocalFree(str);
431 static void test_trustee(void)
433 GUID ObjectType = {0x12345678, 0x1234, 0x5678, {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}};
434 GUID InheritedObjectType = {0x23456789, 0x2345, 0x6786, {0x2, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}};
435 GUID ZeroGuid;
436 OBJECTS_AND_NAME_A oan;
437 OBJECTS_AND_SID oas;
438 TRUSTEEA trustee;
439 PSID psid;
440 char szObjectTypeName[] = "ObjectTypeName";
441 char szInheritedObjectTypeName[] = "InheritedObjectTypeName";
442 char szTrusteeName[] = "szTrusteeName";
443 SID_IDENTIFIER_AUTHORITY auth = { {0x11,0x22,0,0,0, 0} };
445 memset( &ZeroGuid, 0x00, sizeof (ZeroGuid) );
447 pBuildTrusteeWithSidA = (void *)GetProcAddress( hmod, "BuildTrusteeWithSidA" );
448 pBuildTrusteeWithNameA = (void *)GetProcAddress( hmod, "BuildTrusteeWithNameA" );
449 pBuildTrusteeWithObjectsAndNameA = (void *)GetProcAddress (hmod, "BuildTrusteeWithObjectsAndNameA" );
450 pBuildTrusteeWithObjectsAndSidA = (void *)GetProcAddress (hmod, "BuildTrusteeWithObjectsAndSidA" );
451 pGetTrusteeNameA = (void *)GetProcAddress (hmod, "GetTrusteeNameA" );
452 if( !pBuildTrusteeWithSidA || !pBuildTrusteeWithNameA ||
453 !pBuildTrusteeWithObjectsAndNameA || !pBuildTrusteeWithObjectsAndSidA ||
454 !pGetTrusteeNameA )
455 return;
457 if ( ! AllocateAndInitializeSid( &auth, 1, 42, 0,0,0,0,0,0,0,&psid ) )
459 trace( "failed to init SID\n" );
460 return;
463 /* test BuildTrusteeWithSidA */
464 memset( &trustee, 0xff, sizeof trustee );
465 pBuildTrusteeWithSidA( &trustee, psid );
467 ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
468 ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE,
469 "MultipleTrusteeOperation wrong\n");
470 ok( trustee.TrusteeForm == TRUSTEE_IS_SID, "TrusteeForm wrong\n");
471 ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
472 ok( trustee.ptstrName == psid, "ptstrName wrong\n" );
474 /* test BuildTrusteeWithObjectsAndSidA (test 1) */
475 memset( &trustee, 0xff, sizeof trustee );
476 memset( &oas, 0xff, sizeof(oas) );
477 pBuildTrusteeWithObjectsAndSidA(&trustee, &oas, &ObjectType,
478 &InheritedObjectType, psid);
480 ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
481 ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
482 ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_SID, "TrusteeForm wrong\n");
483 ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
484 ok(trustee.ptstrName == (LPSTR)&oas, "ptstrName wrong\n");
486 ok(oas.ObjectsPresent == (ACE_OBJECT_TYPE_PRESENT | ACE_INHERITED_OBJECT_TYPE_PRESENT), "ObjectsPresent wrong\n");
487 ok(!memcmp(&oas.ObjectTypeGuid, &ObjectType, sizeof(GUID)), "ObjectTypeGuid wrong\n");
488 ok(!memcmp(&oas.InheritedObjectTypeGuid, &InheritedObjectType, sizeof(GUID)), "InheritedObjectTypeGuid wrong\n");
489 ok(oas.pSid == psid, "pSid wrong\n");
491 /* test GetTrusteeNameA */
492 ok(pGetTrusteeNameA(&trustee) == (LPSTR)&oas, "GetTrusteeName returned wrong value\n");
494 /* test BuildTrusteeWithObjectsAndSidA (test 2) */
495 memset( &trustee, 0xff, sizeof trustee );
496 memset( &oas, 0xff, sizeof(oas) );
497 pBuildTrusteeWithObjectsAndSidA(&trustee, &oas, NULL,
498 &InheritedObjectType, psid);
500 ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
501 ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
502 ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_SID, "TrusteeForm wrong\n");
503 ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
504 ok(trustee.ptstrName == (LPSTR)&oas, "ptstrName wrong\n");
506 ok(oas.ObjectsPresent == ACE_INHERITED_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
507 ok(!memcmp(&oas.ObjectTypeGuid, &ZeroGuid, sizeof(GUID)), "ObjectTypeGuid wrong\n");
508 ok(!memcmp(&oas.InheritedObjectTypeGuid, &InheritedObjectType, sizeof(GUID)), "InheritedObjectTypeGuid wrong\n");
509 ok(oas.pSid == psid, "pSid wrong\n");
511 FreeSid( psid );
513 /* test BuildTrusteeWithNameA */
514 memset( &trustee, 0xff, sizeof trustee );
515 pBuildTrusteeWithNameA( &trustee, szTrusteeName );
517 ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
518 ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE,
519 "MultipleTrusteeOperation wrong\n");
520 ok( trustee.TrusteeForm == TRUSTEE_IS_NAME, "TrusteeForm wrong\n");
521 ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
522 ok( trustee.ptstrName == szTrusteeName, "ptstrName wrong\n" );
524 /* test BuildTrusteeWithObjectsAndNameA (test 1) */
525 memset( &trustee, 0xff, sizeof trustee );
526 memset( &oan, 0xff, sizeof(oan) );
527 pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, szObjectTypeName,
528 szInheritedObjectTypeName, szTrusteeName);
530 ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
531 ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
532 ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
533 ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
534 ok(trustee.ptstrName == (LPSTR)&oan, "ptstrName wrong\n");
536 ok(oan.ObjectsPresent == (ACE_OBJECT_TYPE_PRESENT | ACE_INHERITED_OBJECT_TYPE_PRESENT), "ObjectsPresent wrong\n");
537 ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
538 ok(oan.InheritedObjectTypeName == szInheritedObjectTypeName, "InheritedObjectTypeName wrong\n");
539 ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
541 /* test GetTrusteeNameA */
542 ok(pGetTrusteeNameA(&trustee) == (LPSTR)&oan, "GetTrusteeName returned wrong value\n");
544 /* test BuildTrusteeWithObjectsAndNameA (test 2) */
545 memset( &trustee, 0xff, sizeof trustee );
546 memset( &oan, 0xff, sizeof(oan) );
547 pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, NULL,
548 szInheritedObjectTypeName, szTrusteeName);
550 ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
551 ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
552 ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
553 ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
554 ok(trustee.ptstrName == (LPSTR)&oan, "ptstrName wrong\n");
556 ok(oan.ObjectsPresent == ACE_INHERITED_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
557 ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
558 ok(oan.InheritedObjectTypeName == szInheritedObjectTypeName, "InheritedObjectTypeName wrong\n");
559 ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
561 /* test BuildTrusteeWithObjectsAndNameA (test 3) */
562 memset( &trustee, 0xff, sizeof trustee );
563 memset( &oan, 0xff, sizeof(oan) );
564 pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, szObjectTypeName,
565 NULL, szTrusteeName);
567 ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
568 ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
569 ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
570 ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
571 ok(trustee.ptstrName == (LPSTR)&oan, "ptstrName wrong\n");
573 ok(oan.ObjectsPresent == ACE_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
574 ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
575 ok(oan.InheritedObjectTypeName == NULL, "InheritedObjectTypeName wrong\n");
576 ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
579 /* If the first isn't defined, assume none is */
580 #ifndef SE_MIN_WELL_KNOWN_PRIVILEGE
581 #define SE_MIN_WELL_KNOWN_PRIVILEGE 2L
582 #define SE_CREATE_TOKEN_PRIVILEGE 2L
583 #define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE 3L
584 #define SE_LOCK_MEMORY_PRIVILEGE 4L
585 #define SE_INCREASE_QUOTA_PRIVILEGE 5L
586 #define SE_MACHINE_ACCOUNT_PRIVILEGE 6L
587 #define SE_TCB_PRIVILEGE 7L
588 #define SE_SECURITY_PRIVILEGE 8L
589 #define SE_TAKE_OWNERSHIP_PRIVILEGE 9L
590 #define SE_LOAD_DRIVER_PRIVILEGE 10L
591 #define SE_SYSTEM_PROFILE_PRIVILEGE 11L
592 #define SE_SYSTEMTIME_PRIVILEGE 12L
593 #define SE_PROF_SINGLE_PROCESS_PRIVILEGE 13L
594 #define SE_INC_BASE_PRIORITY_PRIVILEGE 14L
595 #define SE_CREATE_PAGEFILE_PRIVILEGE 15L
596 #define SE_CREATE_PERMANENT_PRIVILEGE 16L
597 #define SE_BACKUP_PRIVILEGE 17L
598 #define SE_RESTORE_PRIVILEGE 18L
599 #define SE_SHUTDOWN_PRIVILEGE 19L
600 #define SE_DEBUG_PRIVILEGE 20L
601 #define SE_AUDIT_PRIVILEGE 21L
602 #define SE_SYSTEM_ENVIRONMENT_PRIVILEGE 22L
603 #define SE_CHANGE_NOTIFY_PRIVILEGE 23L
604 #define SE_REMOTE_SHUTDOWN_PRIVILEGE 24L
605 #define SE_UNDOCK_PRIVILEGE 25L
606 #define SE_SYNC_AGENT_PRIVILEGE 26L
607 #define SE_ENABLE_DELEGATION_PRIVILEGE 27L
608 #define SE_MANAGE_VOLUME_PRIVILEGE 28L
609 #define SE_IMPERSONATE_PRIVILEGE 29L
610 #define SE_CREATE_GLOBAL_PRIVILEGE 30L
611 #define SE_MAX_WELL_KNOWN_PRIVILEGE SE_CREATE_GLOBAL_PRIVILEGE
612 #endif /* ndef SE_MIN_WELL_KNOWN_PRIVILEGE */
614 static void test_allocateLuid(void)
616 BOOL (WINAPI *pAllocateLocallyUniqueId)(PLUID);
617 LUID luid1, luid2;
618 BOOL ret;
620 pAllocateLocallyUniqueId = (void*)GetProcAddress(hmod, "AllocateLocallyUniqueId");
621 if (!pAllocateLocallyUniqueId) return;
623 ret = pAllocateLocallyUniqueId(&luid1);
624 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
625 return;
627 ok(ret,
628 "AllocateLocallyUniqueId failed: %ld\n", GetLastError());
629 ret = pAllocateLocallyUniqueId(&luid2);
630 ok( ret,
631 "AllocateLocallyUniqueId failed: %ld\n", GetLastError());
632 ok(luid1.LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE || luid1.HighPart != 0,
633 "AllocateLocallyUniqueId returned a well-known LUID\n");
634 ok(luid1.LowPart != luid2.LowPart || luid1.HighPart != luid2.HighPart,
635 "AllocateLocallyUniqueId returned non-unique LUIDs\n");
636 ret = pAllocateLocallyUniqueId(NULL);
637 ok( !ret && GetLastError() == ERROR_NOACCESS,
638 "AllocateLocallyUniqueId(NULL) didn't return ERROR_NOACCESS: %ld\n",
639 GetLastError());
642 static void test_lookupPrivilegeName(void)
644 BOOL (WINAPI *pLookupPrivilegeNameA)(LPCSTR, PLUID, LPSTR, LPDWORD);
645 char buf[MAX_PATH]; /* arbitrary, seems long enough */
646 DWORD cchName = sizeof(buf);
647 LUID luid = { 0, 0 };
648 LONG i;
649 BOOL ret;
651 /* check whether it's available first */
652 pLookupPrivilegeNameA = (void*)GetProcAddress(hmod, "LookupPrivilegeNameA");
653 if (!pLookupPrivilegeNameA) return;
654 luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
655 ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
656 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
657 return;
659 /* check with a short buffer */
660 cchName = 0;
661 luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
662 ret = pLookupPrivilegeNameA(NULL, &luid, NULL, &cchName);
663 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
664 "LookupPrivilegeNameA didn't fail with ERROR_INSUFFICIENT_BUFFER: %ld\n",
665 GetLastError());
666 ok(cchName == strlen("SeCreateTokenPrivilege") + 1,
667 "LookupPrivilegeNameA returned an incorrect required length for\n"
668 "SeCreateTokenPrivilege (got %ld, expected %d)\n", cchName,
669 lstrlenA("SeCreateTokenPrivilege") + 1);
670 /* check a known value and its returned length on success */
671 cchName = sizeof(buf);
672 ok(pLookupPrivilegeNameA(NULL, &luid, buf, &cchName) &&
673 cchName == strlen("SeCreateTokenPrivilege"),
674 "LookupPrivilegeNameA returned an incorrect output length for\n"
675 "SeCreateTokenPrivilege (got %ld, expected %d)\n", cchName,
676 (int)strlen("SeCreateTokenPrivilege"));
677 /* check known values */
678 for (i = SE_MIN_WELL_KNOWN_PRIVILEGE; i <= SE_MAX_WELL_KNOWN_PRIVILEGE; i++)
680 luid.LowPart = i;
681 cchName = sizeof(buf);
682 ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
683 ok( ret || GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
684 "LookupPrivilegeNameA(0.%ld) failed: %ld\n", i, GetLastError());
686 /* check a bogus LUID */
687 luid.LowPart = 0xdeadbeef;
688 cchName = sizeof(buf);
689 ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
690 ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
691 "LookupPrivilegeNameA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %ld\n",
692 GetLastError());
693 /* check on a bogus system */
694 luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
695 cchName = sizeof(buf);
696 ret = pLookupPrivilegeNameA("b0gu5.Nam3", &luid, buf, &cchName);
697 ok( !ret && (GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
698 GetLastError() == RPC_S_INVALID_NET_ADDR) /* w2k8 */,
699 "LookupPrivilegeNameA didn't fail with RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR: %ld\n",
700 GetLastError());
703 struct NameToLUID
705 const char *name;
706 DWORD lowPart;
709 static void test_lookupPrivilegeValue(void)
711 static const struct NameToLUID privs[] = {
712 { "SeCreateTokenPrivilege", SE_CREATE_TOKEN_PRIVILEGE },
713 { "SeAssignPrimaryTokenPrivilege", SE_ASSIGNPRIMARYTOKEN_PRIVILEGE },
714 { "SeLockMemoryPrivilege", SE_LOCK_MEMORY_PRIVILEGE },
715 { "SeIncreaseQuotaPrivilege", SE_INCREASE_QUOTA_PRIVILEGE },
716 { "SeMachineAccountPrivilege", SE_MACHINE_ACCOUNT_PRIVILEGE },
717 { "SeTcbPrivilege", SE_TCB_PRIVILEGE },
718 { "SeSecurityPrivilege", SE_SECURITY_PRIVILEGE },
719 { "SeTakeOwnershipPrivilege", SE_TAKE_OWNERSHIP_PRIVILEGE },
720 { "SeLoadDriverPrivilege", SE_LOAD_DRIVER_PRIVILEGE },
721 { "SeSystemProfilePrivilege", SE_SYSTEM_PROFILE_PRIVILEGE },
722 { "SeSystemtimePrivilege", SE_SYSTEMTIME_PRIVILEGE },
723 { "SeProfileSingleProcessPrivilege", SE_PROF_SINGLE_PROCESS_PRIVILEGE },
724 { "SeIncreaseBasePriorityPrivilege", SE_INC_BASE_PRIORITY_PRIVILEGE },
725 { "SeCreatePagefilePrivilege", SE_CREATE_PAGEFILE_PRIVILEGE },
726 { "SeCreatePermanentPrivilege", SE_CREATE_PERMANENT_PRIVILEGE },
727 { "SeBackupPrivilege", SE_BACKUP_PRIVILEGE },
728 { "SeRestorePrivilege", SE_RESTORE_PRIVILEGE },
729 { "SeShutdownPrivilege", SE_SHUTDOWN_PRIVILEGE },
730 { "SeDebugPrivilege", SE_DEBUG_PRIVILEGE },
731 { "SeAuditPrivilege", SE_AUDIT_PRIVILEGE },
732 { "SeSystemEnvironmentPrivilege", SE_SYSTEM_ENVIRONMENT_PRIVILEGE },
733 { "SeChangeNotifyPrivilege", SE_CHANGE_NOTIFY_PRIVILEGE },
734 { "SeRemoteShutdownPrivilege", SE_REMOTE_SHUTDOWN_PRIVILEGE },
735 { "SeUndockPrivilege", SE_UNDOCK_PRIVILEGE },
736 { "SeSyncAgentPrivilege", SE_SYNC_AGENT_PRIVILEGE },
737 { "SeEnableDelegationPrivilege", SE_ENABLE_DELEGATION_PRIVILEGE },
738 { "SeManageVolumePrivilege", SE_MANAGE_VOLUME_PRIVILEGE },
739 { "SeImpersonatePrivilege", SE_IMPERSONATE_PRIVILEGE },
740 { "SeCreateGlobalPrivilege", SE_CREATE_GLOBAL_PRIVILEGE },
742 BOOL (WINAPI *pLookupPrivilegeValueA)(LPCSTR, LPCSTR, PLUID);
743 unsigned int i;
744 LUID luid;
745 BOOL ret;
747 /* check whether it's available first */
748 pLookupPrivilegeValueA = (void*)GetProcAddress(hmod, "LookupPrivilegeValueA");
749 if (!pLookupPrivilegeValueA) return;
750 ret = pLookupPrivilegeValueA(NULL, "SeCreateTokenPrivilege", &luid);
751 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
752 return;
754 /* check a bogus system name */
755 ret = pLookupPrivilegeValueA("b0gu5.Nam3", "SeCreateTokenPrivilege", &luid);
756 ok( !ret && (GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
757 GetLastError() == RPC_S_INVALID_NET_ADDR) /* w2k8 */,
758 "LookupPrivilegeValueA didn't fail with RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR: %ld\n",
759 GetLastError());
760 /* check a NULL string */
761 ret = pLookupPrivilegeValueA(NULL, 0, &luid);
762 ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
763 "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %ld\n",
764 GetLastError());
765 /* check a bogus privilege name */
766 ret = pLookupPrivilegeValueA(NULL, "SeBogusPrivilege", &luid);
767 ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
768 "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %ld\n",
769 GetLastError());
770 /* check case insensitive */
771 ret = pLookupPrivilegeValueA(NULL, "sEcREATEtOKENpRIVILEGE", &luid);
772 ok( ret,
773 "LookupPrivilegeValueA(NULL, sEcREATEtOKENpRIVILEGE, &luid) failed: %ld\n",
774 GetLastError());
775 for (i = 0; i < ARRAY_SIZE(privs); i++)
777 /* Not all privileges are implemented on all Windows versions, so
778 * don't worry if the call fails
780 if (pLookupPrivilegeValueA(NULL, privs[i].name, &luid))
782 ok(luid.LowPart == privs[i].lowPart,
783 "LookupPrivilegeValueA returned an invalid LUID for %s\n",
784 privs[i].name);
789 static void test_FileSecurity(void)
791 char wintmpdir [MAX_PATH];
792 char path [MAX_PATH];
793 char file [MAX_PATH];
794 HANDLE fh, token;
795 DWORD sdSize, retSize, rc, granted, priv_set_len;
796 PRIVILEGE_SET priv_set;
797 BOOL status;
798 BYTE *sd;
799 GENERIC_MAPPING mapping = { FILE_READ_DATA, FILE_WRITE_DATA, FILE_EXECUTE, FILE_ALL_ACCESS };
800 const SECURITY_INFORMATION request = OWNER_SECURITY_INFORMATION
801 | GROUP_SECURITY_INFORMATION
802 | DACL_SECURITY_INFORMATION;
804 if (!pSetFileSecurityA) {
805 win_skip ("SetFileSecurity is not available\n");
806 return;
809 if (!GetTempPathA (sizeof (wintmpdir), wintmpdir)) {
810 win_skip ("GetTempPathA failed\n");
811 return;
814 /* Create a temporary directory and in it a temporary file */
815 strcat (strcpy (path, wintmpdir), "rary");
816 SetLastError(0xdeadbeef);
817 rc = CreateDirectoryA (path, NULL);
818 ok (rc || GetLastError() == ERROR_ALREADY_EXISTS, "CreateDirectoryA "
819 "failed for '%s' with %ld\n", path, GetLastError());
821 strcat (strcpy (file, path), "\\ess");
822 SetLastError(0xdeadbeef);
823 fh = CreateFileA (file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
824 ok (fh != INVALID_HANDLE_VALUE, "CreateFileA "
825 "failed for '%s' with %ld\n", file, GetLastError());
826 CloseHandle (fh);
828 /* For the temporary file ... */
830 /* Get size needed */
831 retSize = 0;
832 SetLastError(0xdeadbeef);
833 rc = GetFileSecurityA (file, request, NULL, 0, &retSize);
834 if (!rc && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) {
835 win_skip("GetFileSecurityA is not implemented\n");
836 goto cleanup;
838 ok (!rc, "GetFileSecurityA "
839 "was expected to fail for '%s'\n", file);
840 ok (GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetFileSecurityA "
841 "returned %ld; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError());
842 ok (retSize > sizeof (SECURITY_DESCRIPTOR), "GetFileSecurityA returned size %ld\n", retSize);
844 sdSize = retSize;
845 sd = malloc(sdSize);
847 /* Get security descriptor for real */
848 retSize = -1;
849 SetLastError(0xdeadbeef);
850 rc = GetFileSecurityA (file, request, sd, sdSize, &retSize);
851 ok (rc, "GetFileSecurityA "
852 "was not expected to fail '%s': %ld\n", file, GetLastError());
853 ok (retSize == sdSize ||
854 broken(retSize == 0), /* NT4 */
855 "GetFileSecurityA returned size %ld; expected %ld\n", retSize, sdSize);
857 /* Use it to set security descriptor */
858 SetLastError(0xdeadbeef);
859 rc = pSetFileSecurityA (file, request, sd);
860 ok (rc, "SetFileSecurityA "
861 "was not expected to fail '%s': %ld\n", file, GetLastError());
863 free(sd);
865 /* Repeat for the temporary directory ... */
867 /* Get size needed */
868 retSize = 0;
869 SetLastError(0xdeadbeef);
870 rc = GetFileSecurityA (path, request, NULL, 0, &retSize);
871 ok (!rc, "GetFileSecurityA "
872 "was expected to fail for '%s'\n", path);
873 ok (GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetFileSecurityA "
874 "returned %ld; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError());
875 ok (retSize > sizeof (SECURITY_DESCRIPTOR), "GetFileSecurityA returned size %ld\n", retSize);
877 sdSize = retSize;
878 sd = malloc(sdSize);
880 /* Get security descriptor for real */
881 retSize = -1;
882 SetLastError(0xdeadbeef);
883 rc = GetFileSecurityA (path, request, sd, sdSize, &retSize);
884 ok (rc, "GetFileSecurityA "
885 "was not expected to fail '%s': %ld\n", path, GetLastError());
886 ok (retSize == sdSize ||
887 broken(retSize == 0), /* NT4 */
888 "GetFileSecurityA returned size %ld; expected %ld\n", retSize, sdSize);
890 /* Use it to set security descriptor */
891 SetLastError(0xdeadbeef);
892 rc = pSetFileSecurityA (path, request, sd);
893 ok (rc, "SetFileSecurityA "
894 "was not expected to fail '%s': %ld\n", path, GetLastError());
895 free(sd);
897 /* Old test */
898 strcpy (wintmpdir, "\\Should not exist");
899 SetLastError(0xdeadbeef);
900 rc = GetFileSecurityA (wintmpdir, OWNER_SECURITY_INFORMATION, NULL, 0, &sdSize);
901 ok (!rc, "GetFileSecurityA should fail for not existing directories/files\n");
902 ok (GetLastError() == ERROR_FILE_NOT_FOUND,
903 "last error ERROR_FILE_NOT_FOUND expected, got %ld\n", GetLastError());
905 cleanup:
906 /* Remove temporary file and directory */
907 DeleteFileA(file);
908 RemoveDirectoryA(path);
910 /* Test file access permissions for a file with FILE_ATTRIBUTE_ARCHIVE */
911 SetLastError(0xdeadbeef);
912 rc = GetTempPathA(sizeof(wintmpdir), wintmpdir);
913 ok(rc, "GetTempPath error %ld\n", GetLastError());
915 SetLastError(0xdeadbeef);
916 rc = GetTempFileNameA(wintmpdir, "tmp", 0, file);
917 ok(rc, "GetTempFileName error %ld\n", GetLastError());
919 rc = GetFileAttributesA(file);
920 rc &= ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|FILE_ATTRIBUTE_COMPRESSED);
921 ok(rc == FILE_ATTRIBUTE_ARCHIVE, "expected FILE_ATTRIBUTE_ARCHIVE got %#lx\n", rc);
923 rc = GetFileSecurityA(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
924 NULL, 0, &sdSize);
925 ok(!rc, "GetFileSecurity should fail\n");
926 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
927 "expected ERROR_INSUFFICIENT_BUFFER got %ld\n", GetLastError());
928 ok(sdSize > sizeof(SECURITY_DESCRIPTOR), "got sd size %ld\n", sdSize);
930 sd = malloc(sdSize);
931 retSize = 0xdeadbeef;
932 SetLastError(0xdeadbeef);
933 rc = GetFileSecurityA(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
934 sd, sdSize, &retSize);
935 ok(rc, "GetFileSecurity error %ld\n", GetLastError());
936 ok(retSize == sdSize || broken(retSize == 0) /* NT4 */, "expected %ld, got %ld\n", sdSize, retSize);
938 SetLastError(0xdeadbeef);
939 rc = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &token);
940 ok(!rc, "OpenThreadToken should fail\n");
941 ok(GetLastError() == ERROR_NO_TOKEN, "expected ERROR_NO_TOKEN, got %ld\n", GetLastError());
943 SetLastError(0xdeadbeef);
944 rc = ImpersonateSelf(SecurityIdentification);
945 ok(rc, "ImpersonateSelf error %ld\n", GetLastError());
947 SetLastError(0xdeadbeef);
948 rc = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &token);
949 ok(rc, "OpenThreadToken error %ld\n", GetLastError());
951 SetLastError(0xdeadbeef);
952 rc = RevertToSelf();
953 ok(rc, "RevertToSelf error %ld\n", GetLastError());
955 priv_set_len = sizeof(priv_set);
956 granted = 0xdeadbeef;
957 status = 0xdeadbeef;
958 SetLastError(0xdeadbeef);
959 rc = AccessCheck(sd, token, FILE_READ_DATA, &mapping, &priv_set, &priv_set_len, &granted, &status);
960 ok(rc, "AccessCheck error %ld\n", GetLastError());
961 ok(status == 1, "expected 1, got %d\n", status);
962 ok(granted == FILE_READ_DATA, "expected FILE_READ_DATA, got %#lx\n", granted);
964 granted = 0xdeadbeef;
965 status = 0xdeadbeef;
966 SetLastError(0xdeadbeef);
967 rc = AccessCheck(sd, token, FILE_WRITE_DATA, &mapping, &priv_set, &priv_set_len, &granted, &status);
968 ok(rc, "AccessCheck error %ld\n", GetLastError());
969 ok(status == 1, "expected 1, got %d\n", status);
970 ok(granted == FILE_WRITE_DATA, "expected FILE_WRITE_DATA, got %#lx\n", granted);
972 granted = 0xdeadbeef;
973 status = 0xdeadbeef;
974 SetLastError(0xdeadbeef);
975 rc = AccessCheck(sd, token, FILE_EXECUTE, &mapping, &priv_set, &priv_set_len, &granted, &status);
976 ok(rc, "AccessCheck error %ld\n", GetLastError());
977 ok(status == 1, "expected 1, got %d\n", status);
978 ok(granted == FILE_EXECUTE, "expected FILE_EXECUTE, got %#lx\n", granted);
980 granted = 0xdeadbeef;
981 status = 0xdeadbeef;
982 SetLastError(0xdeadbeef);
983 rc = AccessCheck(sd, token, DELETE, &mapping, &priv_set, &priv_set_len, &granted, &status);
984 ok(rc, "AccessCheck error %ld\n", GetLastError());
985 ok(status == 1, "expected 1, got %d\n", status);
986 ok(granted == DELETE, "expected DELETE, got %#lx\n", granted);
988 granted = 0xdeadbeef;
989 status = 0xdeadbeef;
990 SetLastError(0xdeadbeef);
991 rc = AccessCheck(sd, token, FILE_DELETE_CHILD, &mapping, &priv_set, &priv_set_len, &granted, &status);
992 ok(rc, "AccessCheck error %ld\n", GetLastError());
993 ok(status == 1, "expected 1, got %d\n", status);
994 ok(granted == FILE_DELETE_CHILD, "expected FILE_DELETE_CHILD, got %#lx\n", granted);
996 granted = 0xdeadbeef;
997 status = 0xdeadbeef;
998 SetLastError(0xdeadbeef);
999 rc = AccessCheck(sd, token, 0x1ff, &mapping, &priv_set, &priv_set_len, &granted, &status);
1000 ok(rc, "AccessCheck error %ld\n", GetLastError());
1001 ok(status == 1, "expected 1, got %d\n", status);
1002 ok(granted == 0x1ff, "expected 0x1ff, got %#lx\n", granted);
1004 granted = 0xdeadbeef;
1005 status = 0xdeadbeef;
1006 SetLastError(0xdeadbeef);
1007 rc = AccessCheck(sd, token, FILE_ALL_ACCESS, &mapping, &priv_set, &priv_set_len, &granted, &status);
1008 ok(rc, "AccessCheck error %ld\n", GetLastError());
1009 ok(status == 1, "expected 1, got %d\n", status);
1010 ok(granted == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#lx\n", granted);
1012 SetLastError(0xdeadbeef);
1013 rc = AccessCheck(sd, token, 0xffffffff, &mapping, &priv_set, &priv_set_len, &granted, &status);
1014 ok(!rc, "AccessCheck should fail\n");
1015 ok(GetLastError() == ERROR_GENERIC_NOT_MAPPED, "expected ERROR_GENERIC_NOT_MAPPED, got %ld\n", GetLastError());
1017 /* Test file access permissions for a file with FILE_ATTRIBUTE_READONLY */
1018 SetLastError(0xdeadbeef);
1019 fh = CreateFileA(file, FILE_READ_DATA, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
1020 ok(fh != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
1021 retSize = 0xdeadbeef;
1022 SetLastError(0xdeadbeef);
1023 rc = WriteFile(fh, "1", 1, &retSize, NULL);
1024 ok(!rc, "WriteFile should fail\n");
1025 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1026 ok(retSize == 0, "expected 0, got %ld\n", retSize);
1027 CloseHandle(fh);
1029 rc = GetFileAttributesA(file);
1030 rc &= ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|FILE_ATTRIBUTE_COMPRESSED);
1031 todo_wine
1032 ok(rc == (FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY),
1033 "expected FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY got %#lx\n", rc);
1035 SetLastError(0xdeadbeef);
1036 rc = SetFileAttributesA(file, FILE_ATTRIBUTE_ARCHIVE);
1037 ok(rc, "SetFileAttributes error %ld\n", GetLastError());
1038 SetLastError(0xdeadbeef);
1039 rc = DeleteFileA(file);
1040 ok(rc, "DeleteFile error %ld\n", GetLastError());
1042 SetLastError(0xdeadbeef);
1043 fh = CreateFileA(file, FILE_READ_DATA, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
1044 ok(fh != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
1045 retSize = 0xdeadbeef;
1046 SetLastError(0xdeadbeef);
1047 rc = WriteFile(fh, "1", 1, &retSize, NULL);
1048 ok(!rc, "WriteFile should fail\n");
1049 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1050 ok(retSize == 0, "expected 0, got %ld\n", retSize);
1051 CloseHandle(fh);
1053 rc = GetFileAttributesA(file);
1054 rc &= ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|FILE_ATTRIBUTE_COMPRESSED);
1055 ok(rc == (FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY),
1056 "expected FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY got %#lx\n", rc);
1058 retSize = 0xdeadbeef;
1059 SetLastError(0xdeadbeef);
1060 rc = GetFileSecurityA(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
1061 sd, sdSize, &retSize);
1062 ok(rc, "GetFileSecurity error %ld\n", GetLastError());
1063 ok(retSize == sdSize || broken(retSize == 0) /* NT4 */, "expected %ld, got %ld\n", sdSize, retSize);
1065 priv_set_len = sizeof(priv_set);
1066 granted = 0xdeadbeef;
1067 status = 0xdeadbeef;
1068 SetLastError(0xdeadbeef);
1069 rc = AccessCheck(sd, token, FILE_READ_DATA, &mapping, &priv_set, &priv_set_len, &granted, &status);
1070 ok(rc, "AccessCheck error %ld\n", GetLastError());
1071 ok(status == 1, "expected 1, got %d\n", status);
1072 ok(granted == FILE_READ_DATA, "expected FILE_READ_DATA, got %#lx\n", granted);
1074 granted = 0xdeadbeef;
1075 status = 0xdeadbeef;
1076 SetLastError(0xdeadbeef);
1077 rc = AccessCheck(sd, token, FILE_WRITE_DATA, &mapping, &priv_set, &priv_set_len, &granted, &status);
1078 ok(rc, "AccessCheck error %ld\n", GetLastError());
1079 todo_wine {
1080 ok(status == 1, "expected 1, got %d\n", status);
1081 ok(granted == FILE_WRITE_DATA, "expected FILE_WRITE_DATA, got %#lx\n", granted);
1083 granted = 0xdeadbeef;
1084 status = 0xdeadbeef;
1085 SetLastError(0xdeadbeef);
1086 rc = AccessCheck(sd, token, FILE_EXECUTE, &mapping, &priv_set, &priv_set_len, &granted, &status);
1087 ok(rc, "AccessCheck error %ld\n", GetLastError());
1088 ok(status == 1, "expected 1, got %d\n", status);
1089 ok(granted == FILE_EXECUTE, "expected FILE_EXECUTE, got %#lx\n", granted);
1091 granted = 0xdeadbeef;
1092 status = 0xdeadbeef;
1093 SetLastError(0xdeadbeef);
1094 rc = AccessCheck(sd, token, DELETE, &mapping, &priv_set, &priv_set_len, &granted, &status);
1095 ok(rc, "AccessCheck error %ld\n", GetLastError());
1096 ok(status == 1, "expected 1, got %d\n", status);
1097 ok(granted == DELETE, "expected DELETE, got %#lx\n", granted);
1099 granted = 0xdeadbeef;
1100 status = 0xdeadbeef;
1101 SetLastError(0xdeadbeef);
1102 rc = AccessCheck(sd, token, WRITE_OWNER, &mapping, &priv_set, &priv_set_len, &granted, &status);
1103 ok(rc, "AccessCheck error %ld\n", GetLastError());
1104 ok(status == 1, "expected 1, got %d\n", status);
1105 ok(granted == WRITE_OWNER, "expected WRITE_OWNER, got %#lx\n", granted);
1107 granted = 0xdeadbeef;
1108 status = 0xdeadbeef;
1109 SetLastError(0xdeadbeef);
1110 rc = AccessCheck(sd, token, SYNCHRONIZE, &mapping, &priv_set, &priv_set_len, &granted, &status);
1111 ok(rc, "AccessCheck error %ld\n", GetLastError());
1112 ok(status == 1, "expected 1, got %d\n", status);
1113 ok(granted == SYNCHRONIZE, "expected SYNCHRONIZE, got %#lx\n", granted);
1115 granted = 0xdeadbeef;
1116 status = 0xdeadbeef;
1117 SetLastError(0xdeadbeef);
1118 rc = AccessCheck(sd, token, FILE_DELETE_CHILD, &mapping, &priv_set, &priv_set_len, &granted, &status);
1119 ok(rc, "AccessCheck error %ld\n", GetLastError());
1120 todo_wine {
1121 ok(status == 1, "expected 1, got %d\n", status);
1122 ok(granted == FILE_DELETE_CHILD, "expected FILE_DELETE_CHILD, got %#lx\n", granted);
1124 granted = 0xdeadbeef;
1125 status = 0xdeadbeef;
1126 SetLastError(0xdeadbeef);
1127 rc = AccessCheck(sd, token, 0x1ff, &mapping, &priv_set, &priv_set_len, &granted, &status);
1128 ok(rc, "AccessCheck error %ld\n", GetLastError());
1129 todo_wine {
1130 ok(status == 1, "expected 1, got %d\n", status);
1131 ok(granted == 0x1ff, "expected 0x1ff, got %#lx\n", granted);
1133 granted = 0xdeadbeef;
1134 status = 0xdeadbeef;
1135 SetLastError(0xdeadbeef);
1136 rc = AccessCheck(sd, token, FILE_ALL_ACCESS, &mapping, &priv_set, &priv_set_len, &granted, &status);
1137 ok(rc, "AccessCheck error %ld\n", GetLastError());
1138 todo_wine {
1139 ok(status == 1, "expected 1, got %d\n", status);
1140 ok(granted == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#lx\n", granted);
1142 SetLastError(0xdeadbeef);
1143 rc = DeleteFileA(file);
1144 ok(!rc, "DeleteFile should fail\n");
1145 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1146 SetLastError(0xdeadbeef);
1147 rc = SetFileAttributesA(file, FILE_ATTRIBUTE_ARCHIVE);
1148 ok(rc, "SetFileAttributes error %ld\n", GetLastError());
1149 SetLastError(0xdeadbeef);
1150 rc = DeleteFileA(file);
1151 ok(rc, "DeleteFile error %ld\n", GetLastError());
1153 CloseHandle(token);
1154 free(sd);
1157 static void test_AccessCheck(void)
1159 PSID EveryoneSid = NULL, AdminSid = NULL, UsersSid = NULL;
1160 PACL Acl = NULL;
1161 SECURITY_DESCRIPTOR *SecurityDescriptor = NULL;
1162 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
1163 SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
1164 GENERIC_MAPPING Mapping = { KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS };
1165 ACCESS_MASK Access;
1166 BOOL AccessStatus;
1167 HANDLE Token;
1168 HANDLE ProcessToken;
1169 BOOL ret;
1170 DWORD PrivSetLen;
1171 PRIVILEGE_SET *PrivSet;
1172 BOOL res;
1173 HMODULE NtDllModule;
1174 BOOLEAN Enabled;
1175 DWORD err;
1176 NTSTATUS ntret, ntAccessStatus;
1178 NtDllModule = GetModuleHandleA("ntdll.dll");
1179 if (!NtDllModule)
1181 skip("not running on NT, skipping test\n");
1182 return;
1184 pRtlAdjustPrivilege = (void *)GetProcAddress(NtDllModule, "RtlAdjustPrivilege");
1185 if (!pRtlAdjustPrivilege)
1187 win_skip("missing RtlAdjustPrivilege, skipping test\n");
1188 return;
1191 Acl = malloc(256);
1192 res = InitializeAcl(Acl, 256, ACL_REVISION);
1193 if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1195 skip("ACLs not implemented - skipping tests\n");
1196 free(Acl);
1197 return;
1199 ok(res, "InitializeAcl failed with error %ld\n", GetLastError());
1201 res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
1202 ok(res, "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
1204 res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
1205 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminSid);
1206 ok(res, "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
1208 res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
1209 DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid);
1210 ok(res, "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
1212 SecurityDescriptor = malloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
1214 res = InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
1215 ok(res, "InitializeSecurityDescriptor failed with error %ld\n", GetLastError());
1217 res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
1218 ok(res, "SetSecurityDescriptorDacl failed with error %ld\n", GetLastError());
1220 PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
1221 PrivSet = calloc(1, PrivSetLen);
1222 PrivSet->PrivilegeCount = 16;
1224 res = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &ProcessToken);
1225 ok(res, "OpenProcessToken failed with error %ld\n", GetLastError());
1227 pRtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, FALSE, TRUE, &Enabled);
1229 res = DuplicateToken(ProcessToken, SecurityImpersonation, &Token);
1230 ok(res, "DuplicateToken failed with error %ld\n", GetLastError());
1232 /* SD without owner/group */
1233 SetLastError(0xdeadbeef);
1234 Access = AccessStatus = 0x1abe11ed;
1235 ret = AccessCheck(SecurityDescriptor, Token, KEY_QUERY_VALUE, &Mapping,
1236 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1237 err = GetLastError();
1238 ok(!ret && err == ERROR_INVALID_SECURITY_DESCR, "AccessCheck should have "
1239 "failed with ERROR_INVALID_SECURITY_DESCR, instead of %ld\n", err);
1240 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1241 "Access and/or AccessStatus were changed!\n");
1243 /* Set owner and group */
1244 res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE);
1245 ok(res, "SetSecurityDescriptorOwner failed with error %ld\n", GetLastError());
1246 res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, TRUE);
1247 ok(res, "SetSecurityDescriptorGroup failed with error %ld\n", GetLastError());
1249 /* Generic access mask */
1250 SetLastError(0xdeadbeef);
1251 Access = AccessStatus = 0x1abe11ed;
1252 ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1253 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1254 err = GetLastError();
1255 ok(!ret && err == ERROR_GENERIC_NOT_MAPPED, "AccessCheck should have failed "
1256 "with ERROR_GENERIC_NOT_MAPPED, instead of %ld\n", err);
1257 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1258 "Access and/or AccessStatus were changed!\n");
1260 /* Generic access mask - no privilegeset buffer */
1261 SetLastError(0xdeadbeef);
1262 Access = AccessStatus = 0x1abe11ed;
1263 ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1264 NULL, &PrivSetLen, &Access, &AccessStatus);
1265 err = GetLastError();
1266 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have failed "
1267 "with ERROR_NOACCESS, instead of %ld\n", err);
1268 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1269 "Access and/or AccessStatus were changed!\n");
1271 /* Generic access mask - no returnlength */
1272 SetLastError(0xdeadbeef);
1273 Access = AccessStatus = 0x1abe11ed;
1274 ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1275 PrivSet, NULL, &Access, &AccessStatus);
1276 err = GetLastError();
1277 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have failed "
1278 "with ERROR_NOACCESS, instead of %ld\n", err);
1279 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1280 "Access and/or AccessStatus were changed!\n");
1282 /* Generic access mask - no privilegeset buffer, no returnlength */
1283 SetLastError(0xdeadbeef);
1284 Access = AccessStatus = 0x1abe11ed;
1285 ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1286 NULL, NULL, &Access, &AccessStatus);
1287 err = GetLastError();
1288 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have failed "
1289 "with ERROR_NOACCESS, instead of %ld\n", err);
1290 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1291 "Access and/or AccessStatus were changed!\n");
1293 /* sd with no dacl present */
1294 Access = AccessStatus = 0x1abe11ed;
1295 ret = SetSecurityDescriptorDacl(SecurityDescriptor, FALSE, NULL, FALSE);
1296 ok(ret, "SetSecurityDescriptorDacl failed with error %ld\n", GetLastError());
1297 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1298 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1299 ok(ret, "AccessCheck failed with error %ld\n", GetLastError());
1300 ok(AccessStatus && (Access == KEY_READ),
1301 "AccessCheck failed to grant access with error %ld\n",
1302 GetLastError());
1304 /* sd with no dacl present - no privilegeset buffer */
1305 SetLastError(0xdeadbeef);
1306 Access = AccessStatus = 0x1abe11ed;
1307 ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1308 NULL, &PrivSetLen, &Access, &AccessStatus);
1309 err = GetLastError();
1310 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have failed "
1311 "with ERROR_NOACCESS, instead of %ld\n", err);
1312 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1313 "Access and/or AccessStatus were changed!\n");
1315 if(pNtAccessCheck)
1317 DWORD ntPrivSetLen = sizeof(PRIVILEGE_SET);
1319 /* Generic access mask - no privilegeset buffer */
1320 SetLastError(0xdeadbeef);
1321 Access = ntAccessStatus = 0x1abe11ed;
1322 ntret = pNtAccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1323 NULL, &ntPrivSetLen, &Access, &ntAccessStatus);
1324 err = GetLastError();
1325 ok(ntret == STATUS_ACCESS_VIOLATION,
1326 "NtAccessCheck should have failed with STATUS_ACCESS_VIOLATION, got %lx\n", ntret);
1327 ok(err == 0xdeadbeef,
1328 "NtAccessCheck shouldn't set last error, got %ld\n", err);
1329 ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed,
1330 "Access and/or AccessStatus were changed!\n");
1331 ok(ntPrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %ld\n", ntPrivSetLen);
1333 /* Generic access mask - no returnlength */
1334 SetLastError(0xdeadbeef);
1335 Access = ntAccessStatus = 0x1abe11ed;
1336 ntret = pNtAccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1337 PrivSet, NULL, &Access, &ntAccessStatus);
1338 err = GetLastError();
1339 ok(ntret == STATUS_ACCESS_VIOLATION,
1340 "NtAccessCheck should have failed with STATUS_ACCESS_VIOLATION, got %lx\n", ntret);
1341 ok(err == 0xdeadbeef,
1342 "NtAccessCheck shouldn't set last error, got %ld\n", err);
1343 ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed,
1344 "Access and/or AccessStatus were changed!\n");
1346 /* Generic access mask - no privilegeset buffer, no returnlength */
1347 SetLastError(0xdeadbeef);
1348 Access = ntAccessStatus = 0x1abe11ed;
1349 ntret = pNtAccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1350 NULL, NULL, &Access, &ntAccessStatus);
1351 err = GetLastError();
1352 ok(ntret == STATUS_ACCESS_VIOLATION,
1353 "NtAccessCheck should have failed with STATUS_ACCESS_VIOLATION, got %lx\n", ntret);
1354 ok(err == 0xdeadbeef,
1355 "NtAccessCheck shouldn't set last error, got %ld\n", err);
1356 ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed,
1357 "Access and/or AccessStatus were changed!\n");
1359 /* Generic access mask - zero returnlength */
1360 SetLastError(0xdeadbeef);
1361 Access = ntAccessStatus = 0x1abe11ed;
1362 ntPrivSetLen = 0;
1363 ntret = pNtAccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1364 PrivSet, &ntPrivSetLen, &Access, &ntAccessStatus);
1365 err = GetLastError();
1366 ok(ntret == STATUS_GENERIC_NOT_MAPPED,
1367 "NtAccessCheck should have failed with STATUS_GENERIC_NOT_MAPPED, got %lx\n", ntret);
1368 ok(err == 0xdeadbeef,
1369 "NtAccessCheck shouldn't set last error, got %ld\n", err);
1370 ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed,
1371 "Access and/or AccessStatus were changed!\n");
1372 ok(ntPrivSetLen == 0, "PrivSetLen returns %ld\n", ntPrivSetLen);
1374 /* Generic access mask - insufficient returnlength */
1375 SetLastError(0xdeadbeef);
1376 Access = ntAccessStatus = 0x1abe11ed;
1377 ntPrivSetLen = sizeof(PRIVILEGE_SET)-1;
1378 ntret = pNtAccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1379 PrivSet, &ntPrivSetLen, &Access, &ntAccessStatus);
1380 err = GetLastError();
1381 ok(ntret == STATUS_GENERIC_NOT_MAPPED,
1382 "NtAccessCheck should have failed with STATUS_GENERIC_NOT_MAPPED, got %lx\n", ntret);
1383 ok(err == 0xdeadbeef,
1384 "NtAccessCheck shouldn't set last error, got %ld\n", err);
1385 ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed,
1386 "Access and/or AccessStatus were changed!\n");
1387 ok(ntPrivSetLen == sizeof(PRIVILEGE_SET)-1, "PrivSetLen returns %ld\n", ntPrivSetLen);
1389 /* Key access mask - zero returnlength */
1390 SetLastError(0xdeadbeef);
1391 Access = ntAccessStatus = 0x1abe11ed;
1392 ntPrivSetLen = 0;
1393 ntret = pNtAccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1394 PrivSet, &ntPrivSetLen, &Access, &ntAccessStatus);
1395 err = GetLastError();
1396 ok(ntret == STATUS_BUFFER_TOO_SMALL,
1397 "NtAccessCheck should have failed with STATUS_BUFFER_TOO_SMALL, got %lx\n", ntret);
1398 ok(err == 0xdeadbeef,
1399 "NtAccessCheck shouldn't set last error, got %ld\n", err);
1400 ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed,
1401 "Access and/or AccessStatus were changed!\n");
1402 ok(ntPrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %ld\n", ntPrivSetLen);
1404 /* Key access mask - insufficient returnlength */
1405 SetLastError(0xdeadbeef);
1406 Access = ntAccessStatus = 0x1abe11ed;
1407 ntPrivSetLen = sizeof(PRIVILEGE_SET)-1;
1408 ntret = pNtAccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1409 PrivSet, &ntPrivSetLen, &Access, &ntAccessStatus);
1410 err = GetLastError();
1411 ok(ntret == STATUS_BUFFER_TOO_SMALL,
1412 "NtAccessCheck should have failed with STATUS_BUFFER_TOO_SMALL, got %lx\n", ntret);
1413 ok(err == 0xdeadbeef,
1414 "NtAccessCheck shouldn't set last error, got %ld\n", err);
1415 ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed,
1416 "Access and/or AccessStatus were changed!\n");
1417 ok(ntPrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %ld\n", ntPrivSetLen);
1419 else
1420 win_skip("NtAccessCheck unavailable. Skipping.\n");
1422 /* sd with NULL dacl */
1423 Access = AccessStatus = 0x1abe11ed;
1424 ret = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, NULL, FALSE);
1425 ok(ret, "SetSecurityDescriptorDacl failed with error %ld\n", GetLastError());
1426 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1427 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1428 ok(ret, "AccessCheck failed with error %ld\n", GetLastError());
1429 ok(AccessStatus && (Access == KEY_READ),
1430 "AccessCheck failed to grant access with error %ld\n",
1431 GetLastError());
1432 ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping,
1433 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1434 ok(ret, "AccessCheck failed with error %ld\n", GetLastError());
1435 ok(AccessStatus && (Access == KEY_ALL_ACCESS),
1436 "AccessCheck failed to grant access with error %ld\n",
1437 GetLastError());
1439 /* sd with blank dacl */
1440 ret = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
1441 ok(ret, "SetSecurityDescriptorDacl failed with error %ld\n", GetLastError());
1442 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1443 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1444 ok(ret, "AccessCheck failed with error %ld\n", GetLastError());
1445 err = GetLastError();
1446 ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed "
1447 "with ERROR_ACCESS_DENIED, instead of %ld\n", err);
1448 ok(!Access, "Should have failed to grant any access, got 0x%08lx\n", Access);
1450 res = AddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, EveryoneSid);
1451 ok(res, "AddAccessAllowedAce failed with error %ld\n", GetLastError());
1453 res = AddAccessDeniedAce(Acl, ACL_REVISION, KEY_SET_VALUE, AdminSid);
1454 ok(res, "AddAccessDeniedAce failed with error %ld\n", GetLastError());
1456 /* sd with dacl */
1457 Access = AccessStatus = 0x1abe11ed;
1458 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1459 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1460 ok(ret, "AccessCheck failed with error %ld\n", GetLastError());
1461 ok(AccessStatus && (Access == KEY_READ),
1462 "AccessCheck failed to grant access with error %ld\n",
1463 GetLastError());
1465 ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping,
1466 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1467 ok(ret, "AccessCheck failed with error %ld\n", GetLastError());
1468 ok(AccessStatus,
1469 "AccessCheck failed to grant any access with error %ld\n",
1470 GetLastError());
1471 trace("AccessCheck with MAXIMUM_ALLOWED got Access 0x%08lx\n", Access);
1473 /* Null PrivSet with null PrivSetLen pointer */
1474 SetLastError(0xdeadbeef);
1475 Access = AccessStatus = 0x1abe11ed;
1476 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1477 NULL, NULL, &Access, &AccessStatus);
1478 err = GetLastError();
1479 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have "
1480 "failed with ERROR_NOACCESS, instead of %ld\n", err);
1481 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1482 "Access and/or AccessStatus were changed!\n");
1484 /* Null PrivSet with zero PrivSetLen */
1485 SetLastError(0xdeadbeef);
1486 Access = AccessStatus = 0x1abe11ed;
1487 PrivSetLen = 0;
1488 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1489 0, &PrivSetLen, &Access, &AccessStatus);
1490 err = GetLastError();
1491 todo_wine
1492 ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1493 "failed with ERROR_INSUFFICIENT_BUFFER, instead of %ld\n", err);
1494 todo_wine
1495 ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %ld\n", PrivSetLen);
1496 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1497 "Access and/or AccessStatus were changed!\n");
1499 /* Null PrivSet with insufficient PrivSetLen */
1500 SetLastError(0xdeadbeef);
1501 Access = AccessStatus = 0x1abe11ed;
1502 PrivSetLen = 1;
1503 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1504 0, &PrivSetLen, &Access, &AccessStatus);
1505 err = GetLastError();
1506 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have "
1507 "failed with ERROR_NOACCESS, instead of %ld\n", err);
1508 ok(PrivSetLen == 1, "PrivSetLen returns %ld\n", PrivSetLen);
1509 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1510 "Access and/or AccessStatus were changed!\n");
1512 /* Null PrivSet with insufficient PrivSetLen */
1513 SetLastError(0xdeadbeef);
1514 Access = AccessStatus = 0x1abe11ed;
1515 PrivSetLen = sizeof(PRIVILEGE_SET) - 1;
1516 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1517 0, &PrivSetLen, &Access, &AccessStatus);
1518 err = GetLastError();
1519 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have "
1520 "failed with ERROR_NOACCESS, instead of %ld\n", err);
1521 ok(PrivSetLen == sizeof(PRIVILEGE_SET) - 1, "PrivSetLen returns %ld\n", PrivSetLen);
1522 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1523 "Access and/or AccessStatus were changed!\n");
1525 /* Null PrivSet with minimal sufficient PrivSetLen */
1526 SetLastError(0xdeadbeef);
1527 Access = AccessStatus = 0x1abe11ed;
1528 PrivSetLen = sizeof(PRIVILEGE_SET);
1529 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1530 0, &PrivSetLen, &Access, &AccessStatus);
1531 err = GetLastError();
1532 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have "
1533 "failed with ERROR_NOACCESS, instead of %ld\n", err);
1534 ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %ld\n", PrivSetLen);
1535 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1536 "Access and/or AccessStatus were changed!\n");
1538 /* Valid PrivSet with zero PrivSetLen */
1539 SetLastError(0xdeadbeef);
1540 Access = AccessStatus = 0x1abe11ed;
1541 PrivSetLen = 0;
1542 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1543 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1544 err = GetLastError();
1545 ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1546 "failed with ERROR_INSUFFICIENT_BUFFER, instead of %ld\n", err);
1547 ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %ld\n", PrivSetLen);
1548 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1549 "Access and/or AccessStatus were changed!\n");
1551 /* Valid PrivSet with insufficient PrivSetLen */
1552 SetLastError(0xdeadbeef);
1553 Access = AccessStatus = 0x1abe11ed;
1554 PrivSetLen = 1;
1555 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1556 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1557 err = GetLastError();
1558 ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1559 "failed with ERROR_INSUFFICIENT_BUFFER, instead of %ld\n", err);
1560 ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %ld\n", PrivSetLen);
1561 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1562 "Access and/or AccessStatus were changed!\n");
1564 /* Valid PrivSet with insufficient PrivSetLen */
1565 SetLastError(0xdeadbeef);
1566 Access = AccessStatus = 0x1abe11ed;
1567 PrivSetLen = sizeof(PRIVILEGE_SET) - 1;
1568 PrivSet->PrivilegeCount = 0xdeadbeef;
1569 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1570 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1571 err = GetLastError();
1572 ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1573 "failed with ERROR_INSUFFICIENT_BUFFER, instead of %ld\n", err);
1574 ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %ld\n", PrivSetLen);
1575 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1576 "Access and/or AccessStatus were changed!\n");
1577 ok(PrivSet->PrivilegeCount == 0xdeadbeef, "buffer contents should not be changed\n");
1579 /* Valid PrivSet with minimal sufficient PrivSetLen */
1580 SetLastError(0xdeadbeef);
1581 Access = AccessStatus = 0x1abe11ed;
1582 PrivSetLen = sizeof(PRIVILEGE_SET);
1583 memset(PrivSet, 0xcc, PrivSetLen);
1584 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1585 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1586 err = GetLastError();
1587 ok(ret, "AccessCheck failed with error %ld\n", GetLastError());
1588 ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %ld\n", PrivSetLen);
1589 ok(AccessStatus && (Access == KEY_READ),
1590 "AccessCheck failed to grant access with error %ld\n", GetLastError());
1591 ok(PrivSet->PrivilegeCount == 0, "PrivilegeCount returns %ld, expects 0\n",
1592 PrivSet->PrivilegeCount);
1594 /* Valid PrivSet with sufficient PrivSetLen */
1595 SetLastError(0xdeadbeef);
1596 Access = AccessStatus = 0x1abe11ed;
1597 PrivSetLen = sizeof(PRIVILEGE_SET) + 1;
1598 memset(PrivSet, 0xcc, PrivSetLen);
1599 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1600 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1601 err = GetLastError();
1602 ok(ret, "AccessCheck failed with error %ld\n", GetLastError());
1603 todo_wine
1604 ok(PrivSetLen == sizeof(PRIVILEGE_SET) + 1, "PrivSetLen returns %ld\n", PrivSetLen);
1605 ok(AccessStatus && (Access == KEY_READ),
1606 "AccessCheck failed to grant access with error %ld\n", GetLastError());
1607 ok(PrivSet->PrivilegeCount == 0, "PrivilegeCount returns %ld, expects 0\n",
1608 PrivSet->PrivilegeCount);
1610 PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
1612 /* Null PrivSet with valid PrivSetLen */
1613 SetLastError(0xdeadbeef);
1614 Access = AccessStatus = 0x1abe11ed;
1615 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1616 0, &PrivSetLen, &Access, &AccessStatus);
1617 err = GetLastError();
1618 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have "
1619 "failed with ERROR_NOACCESS, instead of %ld\n", err);
1620 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1621 "Access and/or AccessStatus were changed!\n");
1623 /* Access denied by SD */
1624 SetLastError(0xdeadbeef);
1625 Access = AccessStatus = 0x1abe11ed;
1626 ret = AccessCheck(SecurityDescriptor, Token, KEY_WRITE, &Mapping,
1627 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1628 ok(ret, "AccessCheck failed with error %ld\n", GetLastError());
1629 err = GetLastError();
1630 ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed "
1631 "with ERROR_ACCESS_DENIED, instead of %ld\n", err);
1632 ok(!Access, "Should have failed to grant any access, got 0x%08lx\n", Access);
1634 SetLastError(0xdeadbeef);
1635 PrivSet->PrivilegeCount = 16;
1636 ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping,
1637 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1638 ok(ret && !AccessStatus && GetLastError() == ERROR_PRIVILEGE_NOT_HELD,
1639 "AccessCheck should have failed with ERROR_PRIVILEGE_NOT_HELD, instead of %ld\n",
1640 GetLastError());
1642 ret = ImpersonateLoggedOnUser(Token);
1643 ok(ret, "ImpersonateLoggedOnUser failed with error %ld\n", GetLastError());
1644 ret = pRtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, TRUE, TRUE, &Enabled);
1645 if (!ret)
1647 /* Valid PrivSet with zero PrivSetLen */
1648 SetLastError(0xdeadbeef);
1649 Access = AccessStatus = 0x1abe11ed;
1650 PrivSetLen = 0;
1651 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1652 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1653 err = GetLastError();
1654 ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1655 "failed with ERROR_INSUFFICIENT_BUFFER, instead of %ld\n", err);
1656 ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %ld\n", PrivSetLen);
1657 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1658 "Access and/or AccessStatus were changed!\n");
1660 /* Valid PrivSet with insufficient PrivSetLen */
1661 SetLastError(0xdeadbeef);
1662 Access = AccessStatus = 0x1abe11ed;
1663 PrivSetLen = sizeof(PRIVILEGE_SET) - 1;
1664 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1665 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1666 err = GetLastError();
1667 ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1668 "failed with ERROR_INSUFFICIENT_BUFFER, instead of %ld\n", err);
1669 ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %ld\n", PrivSetLen);
1670 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1671 "Access and/or AccessStatus were changed!\n");
1673 /* Valid PrivSet with minimal sufficient PrivSetLen */
1674 SetLastError(0xdeadbeef);
1675 Access = AccessStatus = 0x1abe11ed;
1676 PrivSetLen = sizeof(PRIVILEGE_SET);
1677 memset(PrivSet, 0xcc, PrivSetLen);
1678 ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping,
1679 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1680 ok(ret && AccessStatus && GetLastError() == 0xdeadbeef,
1681 "AccessCheck should have succeeded, error %ld\n",
1682 GetLastError());
1683 ok(Access == ACCESS_SYSTEM_SECURITY,
1684 "Access should be equal to ACCESS_SYSTEM_SECURITY instead of 0x%08lx\n",
1685 Access);
1686 ok(PrivSet->PrivilegeCount == 1, "PrivilegeCount returns %ld, expects 1\n",
1687 PrivSet->PrivilegeCount);
1689 /* Valid PrivSet with large PrivSetLen */
1690 SetLastError(0xdeadbeef);
1691 Access = AccessStatus = 0x1abe11ed;
1692 PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
1693 memset(PrivSet, 0xcc, PrivSetLen);
1694 ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping,
1695 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1696 ok(ret && AccessStatus && GetLastError() == 0xdeadbeef,
1697 "AccessCheck should have succeeded, error %ld\n",
1698 GetLastError());
1699 ok(Access == ACCESS_SYSTEM_SECURITY,
1700 "Access should be equal to ACCESS_SYSTEM_SECURITY instead of 0x%08lx\n",
1701 Access);
1702 ok(PrivSet->PrivilegeCount == 1, "PrivilegeCount returns %ld, expects 1\n",
1703 PrivSet->PrivilegeCount);
1705 else
1706 trace("Couldn't get SE_SECURITY_PRIVILEGE (0x%08x), skipping ACCESS_SYSTEM_SECURITY test\n",
1707 ret);
1708 ret = RevertToSelf();
1709 ok(ret, "RevertToSelf failed with error %ld\n", GetLastError());
1711 /* test INHERIT_ONLY_ACE */
1712 ret = InitializeAcl(Acl, 256, ACL_REVISION);
1713 ok(ret, "InitializeAcl failed with error %ld\n", GetLastError());
1715 /* NT doesn't have AddAccessAllowedAceEx. Skipping this call/test doesn't influence
1716 * the next ones.
1718 if (pAddAccessAllowedAceEx)
1720 ret = pAddAccessAllowedAceEx(Acl, ACL_REVISION, INHERIT_ONLY_ACE, KEY_READ, EveryoneSid);
1721 ok(ret, "AddAccessAllowedAceEx failed with error %ld\n", GetLastError());
1723 else
1724 win_skip("AddAccessAllowedAceEx is not available\n");
1726 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1727 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1728 ok(ret, "AccessCheck failed with error %ld\n", GetLastError());
1729 err = GetLastError();
1730 ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed "
1731 "with ERROR_ACCESS_DENIED, instead of %ld\n", err);
1732 ok(!Access, "Should have failed to grant any access, got 0x%08lx\n", Access);
1734 CloseHandle(Token);
1736 res = DuplicateToken(ProcessToken, SecurityAnonymous, &Token);
1737 ok(res, "DuplicateToken failed with error %ld\n", GetLastError());
1739 SetLastError(0xdeadbeef);
1740 ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping,
1741 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1742 err = GetLastError();
1743 ok(!ret && err == ERROR_BAD_IMPERSONATION_LEVEL, "AccessCheck should have failed "
1744 "with ERROR_BAD_IMPERSONATION_LEVEL, instead of %ld\n", err);
1746 CloseHandle(Token);
1748 SetLastError(0xdeadbeef);
1749 ret = AccessCheck(SecurityDescriptor, ProcessToken, KEY_READ, &Mapping,
1750 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1751 err = GetLastError();
1752 ok(!ret && err == ERROR_NO_IMPERSONATION_TOKEN, "AccessCheck should have failed "
1753 "with ERROR_NO_IMPERSONATION_TOKEN, instead of %ld\n", err);
1755 CloseHandle(ProcessToken);
1757 if (EveryoneSid)
1758 FreeSid(EveryoneSid);
1759 if (AdminSid)
1760 FreeSid(AdminSid);
1761 if (UsersSid)
1762 FreeSid(UsersSid);
1763 free(Acl);
1764 free(SecurityDescriptor);
1765 free(PrivSet);
1768 static TOKEN_USER *get_alloc_token_user( HANDLE token )
1770 TOKEN_USER *token_user;
1771 DWORD size;
1772 BOOL ret;
1774 ret = GetTokenInformation( token, TokenUser, NULL, 0, &size );
1775 ok(!ret, "Expected failure, got %d\n", ret);
1776 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1777 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
1779 token_user = malloc( size );
1780 ret = GetTokenInformation( token, TokenUser, token_user, size, &size );
1781 ok(ret, "GetTokenInformation failed with error %ld\n", GetLastError());
1783 return token_user;
1786 static TOKEN_OWNER *get_alloc_token_owner( HANDLE token )
1788 TOKEN_OWNER *token_owner;
1789 DWORD size;
1790 BOOL ret;
1792 ret = GetTokenInformation( token, TokenOwner, NULL, 0, &size );
1793 ok(!ret, "Expected failure, got %d\n", ret);
1794 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1795 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
1797 token_owner = malloc( size );
1798 ret = GetTokenInformation( token, TokenOwner, token_owner, size, &size );
1799 ok(ret, "GetTokenInformation failed with error %ld\n", GetLastError());
1801 return token_owner;
1804 static TOKEN_PRIMARY_GROUP *get_alloc_token_primary_group( HANDLE token )
1806 TOKEN_PRIMARY_GROUP *token_primary_group;
1807 DWORD size;
1808 BOOL ret;
1810 ret = GetTokenInformation( token, TokenPrimaryGroup, NULL, 0, &size );
1811 ok(!ret, "Expected failure, got %d\n", ret);
1812 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1813 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
1815 token_primary_group = malloc( size );
1816 ret = GetTokenInformation( token, TokenPrimaryGroup, token_primary_group, size, &size );
1817 ok(ret, "GetTokenInformation failed with error %ld\n", GetLastError());
1819 return token_primary_group;
1822 /* test GetTokenInformation for the various attributes */
1823 static void test_token_attr(void)
1825 HANDLE Token, ImpersonationToken;
1826 DWORD Size, Size2;
1827 TOKEN_PRIVILEGES *Privileges;
1828 TOKEN_GROUPS *Groups;
1829 TOKEN_USER *User;
1830 TOKEN_OWNER *Owner;
1831 TOKEN_DEFAULT_DACL *Dacl;
1832 BOOL ret;
1833 DWORD i, GLE;
1834 LPSTR SidString;
1835 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
1836 ACL *acl;
1838 /* cygwin-like use case */
1839 SetLastError(0xdeadbeef);
1840 ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &Token);
1841 if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
1843 win_skip("OpenProcessToken is not implemented\n");
1844 return;
1846 ok(ret, "OpenProcessToken failed with error %ld\n", GetLastError());
1847 if (ret)
1849 DWORD buf[256]; /* GetTokenInformation wants a dword-aligned buffer */
1850 Size = sizeof(buf);
1851 ret = GetTokenInformation(Token, TokenUser,(void*)buf, Size, &Size);
1852 ok(ret, "GetTokenInformation failed with error %ld\n", GetLastError());
1853 Size = sizeof(ImpersonationLevel);
1854 ret = GetTokenInformation(Token, TokenImpersonationLevel, &ImpersonationLevel, Size, &Size);
1855 GLE = GetLastError();
1856 ok(!ret && (GLE == ERROR_INVALID_PARAMETER), "GetTokenInformation(TokenImpersonationLevel) on primary token should have failed with ERROR_INVALID_PARAMETER instead of %ld\n", GLE);
1857 CloseHandle(Token);
1860 SetLastError(0xdeadbeef);
1861 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &Token);
1862 ok(ret, "OpenProcessToken failed with error %ld\n", GetLastError());
1864 /* groups */
1865 /* insufficient buffer length */
1866 SetLastError(0xdeadbeef);
1867 Size2 = 0;
1868 ret = GetTokenInformation(Token, TokenGroups, NULL, 0, &Size2);
1869 ok(Size2 > 1, "got %ld\n", Size2);
1870 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1871 "%d with error %ld\n", ret, GetLastError());
1872 Size2 -= 1;
1873 Groups = malloc(Size2);
1874 memset(Groups, 0xcc, Size2);
1875 Size = 0;
1876 ret = GetTokenInformation(Token, TokenGroups, Groups, Size2, &Size);
1877 ok(Size > 1, "got %ld\n", Size);
1878 ok((!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) || broken(ret) /* wow64 */,
1879 "%d with error %ld\n", ret, GetLastError());
1880 if(!ret)
1881 ok(*((BYTE*)Groups) == 0xcc, "buffer altered\n");
1883 free(Groups);
1885 SetLastError(0xdeadbeef);
1886 ret = GetTokenInformation(Token, TokenGroups, NULL, 0, &Size);
1887 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1888 "GetTokenInformation(TokenGroups) %s with error %ld\n",
1889 ret ? "succeeded" : "failed", GetLastError());
1890 Groups = malloc(Size);
1891 SetLastError(0xdeadbeef);
1892 ret = GetTokenInformation(Token, TokenGroups, Groups, Size, &Size);
1893 ok(ret, "GetTokenInformation(TokenGroups) failed with error %ld\n", GetLastError());
1894 ok(GetLastError() == 0xdeadbeef,
1895 "GetTokenInformation shouldn't have set last error to %ld\n",
1896 GetLastError());
1897 trace("TokenGroups:\n");
1898 for (i = 0; i < Groups->GroupCount; i++)
1900 DWORD NameLength = 255;
1901 CHAR Name[255];
1902 DWORD DomainLength = 255;
1903 CHAR Domain[255];
1904 SID_NAME_USE SidNameUse;
1905 Name[0] = '\0';
1906 Domain[0] = '\0';
1907 ret = LookupAccountSidA(NULL, Groups->Groups[i].Sid, Name, &NameLength, Domain, &DomainLength, &SidNameUse);
1908 if (ret)
1910 ConvertSidToStringSidA(Groups->Groups[i].Sid, &SidString);
1911 trace("%s, %s\\%s use: %d attr: 0x%08lx\n", SidString, Domain, Name, SidNameUse, Groups->Groups[i].Attributes);
1912 LocalFree(SidString);
1914 else trace("attr: 0x%08lx LookupAccountSid failed with error %ld\n", Groups->Groups[i].Attributes, GetLastError());
1916 free(Groups);
1918 /* user */
1919 ret = GetTokenInformation(Token, TokenUser, NULL, 0, &Size);
1920 ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1921 "GetTokenInformation(TokenUser) failed with error %ld\n", GetLastError());
1922 User = malloc(Size);
1923 ret = GetTokenInformation(Token, TokenUser, User, Size, &Size);
1924 ok(ret,
1925 "GetTokenInformation(TokenUser) failed with error %ld\n", GetLastError());
1927 ConvertSidToStringSidA(User->User.Sid, &SidString);
1928 trace("TokenUser: %s attr: 0x%08lx\n", SidString, User->User.Attributes);
1929 LocalFree(SidString);
1930 free(User);
1932 /* owner */
1933 ret = GetTokenInformation(Token, TokenOwner, NULL, 0, &Size);
1934 ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1935 "GetTokenInformation(TokenOwner) failed with error %ld\n", GetLastError());
1936 Owner = malloc(Size);
1937 ret = GetTokenInformation(Token, TokenOwner, Owner, Size, &Size);
1938 ok(ret,
1939 "GetTokenInformation(TokenOwner) failed with error %ld\n", GetLastError());
1941 ConvertSidToStringSidA(Owner->Owner, &SidString);
1942 trace("TokenOwner: %s\n", SidString);
1943 LocalFree(SidString);
1944 free(Owner);
1946 /* logon */
1947 ret = GetTokenInformation(Token, TokenLogonSid, NULL, 0, &Size);
1948 if (!ret && (GetLastError() == ERROR_INVALID_PARAMETER))
1949 todo_wine win_skip("TokenLogonSid not supported. Skipping tests\n");
1950 else
1952 ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1953 "GetTokenInformation(TokenLogonSid) failed with error %ld\n", GetLastError());
1954 Groups = malloc(Size);
1955 ret = GetTokenInformation(Token, TokenLogonSid, Groups, Size, &Size);
1956 ok(ret,
1957 "GetTokenInformation(TokenLogonSid) failed with error %ld\n", GetLastError());
1958 if (ret)
1960 ok(Groups->GroupCount == 1, "got %ld\n", Groups->GroupCount);
1961 if(Groups->GroupCount == 1)
1963 ConvertSidToStringSidA(Groups->Groups[0].Sid, &SidString);
1964 trace("TokenLogon: %s\n", SidString);
1965 LocalFree(SidString);
1967 /* S-1-5-5-0-XXXXXX */
1968 ret = IsWellKnownSid(Groups->Groups[0].Sid, WinLogonIdsSid);
1969 ok(ret, "Unknown SID\n");
1971 ok(Groups->Groups[0].Attributes == (SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED | SE_GROUP_LOGON_ID),
1972 "got %lx\n", Groups->Groups[0].Attributes);
1976 free(Groups);
1979 /* privileges */
1980 ret = GetTokenInformation(Token, TokenPrivileges, NULL, 0, &Size);
1981 ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1982 "GetTokenInformation(TokenPrivileges) failed with error %ld\n", GetLastError());
1983 Privileges = malloc(Size);
1984 ret = GetTokenInformation(Token, TokenPrivileges, Privileges, Size, &Size);
1985 ok(ret,
1986 "GetTokenInformation(TokenPrivileges) failed with error %ld\n", GetLastError());
1987 trace("TokenPrivileges:\n");
1988 for (i = 0; i < Privileges->PrivilegeCount; i++)
1990 CHAR Name[256];
1991 DWORD NameLen = ARRAY_SIZE(Name);
1992 LookupPrivilegeNameA(NULL, &Privileges->Privileges[i].Luid, Name, &NameLen);
1993 trace("\t%s, 0x%lx\n", Name, Privileges->Privileges[i].Attributes);
1995 free(Privileges);
1997 ret = DuplicateToken(Token, SecurityAnonymous, &ImpersonationToken);
1998 ok(ret, "DuplicateToken failed with error %ld\n", GetLastError());
2000 Size = sizeof(ImpersonationLevel);
2001 ret = GetTokenInformation(ImpersonationToken, TokenImpersonationLevel, &ImpersonationLevel, Size, &Size);
2002 ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %ld\n", GetLastError());
2003 ok(ImpersonationLevel == SecurityAnonymous, "ImpersonationLevel should have been SecurityAnonymous instead of %d\n", ImpersonationLevel);
2005 CloseHandle(ImpersonationToken);
2007 /* default dacl */
2008 ret = GetTokenInformation(Token, TokenDefaultDacl, NULL, 0, &Size);
2009 ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
2010 "GetTokenInformation(TokenDefaultDacl) failed with error %lu\n", GetLastError());
2012 Dacl = malloc(Size);
2013 ret = GetTokenInformation(Token, TokenDefaultDacl, Dacl, Size, &Size);
2014 ok(ret, "GetTokenInformation(TokenDefaultDacl) failed with error %lu\n", GetLastError());
2016 SetLastError(0xdeadbeef);
2017 ret = SetTokenInformation(Token, TokenDefaultDacl, NULL, 0);
2018 GLE = GetLastError();
2019 ok(!ret, "SetTokenInformation(TokenDefaultDacl) succeeded\n");
2020 ok(GLE == ERROR_BAD_LENGTH, "expected ERROR_BAD_LENGTH got %lu\n", GLE);
2022 SetLastError(0xdeadbeef);
2023 ret = SetTokenInformation(Token, TokenDefaultDacl, NULL, Size);
2024 GLE = GetLastError();
2025 ok(!ret, "SetTokenInformation(TokenDefaultDacl) succeeded\n");
2026 ok(GLE == ERROR_NOACCESS, "expected ERROR_NOACCESS got %lu\n", GLE);
2028 acl = Dacl->DefaultDacl;
2029 Dacl->DefaultDacl = NULL;
2031 ret = SetTokenInformation(Token, TokenDefaultDacl, Dacl, Size);
2032 ok(ret, "SetTokenInformation(TokenDefaultDacl) succeeded\n");
2034 Size2 = 0;
2035 Dacl->DefaultDacl = (ACL *)0xdeadbeef;
2036 ret = GetTokenInformation(Token, TokenDefaultDacl, Dacl, Size, &Size2);
2037 ok(ret, "GetTokenInformation(TokenDefaultDacl) failed with error %lu\n", GetLastError());
2038 ok(Dacl->DefaultDacl == NULL, "expected NULL, got %p\n", Dacl->DefaultDacl);
2039 ok(Size2 == sizeof(TOKEN_DEFAULT_DACL) || broken(Size2 == 2*sizeof(TOKEN_DEFAULT_DACL)), /* WoW64 */
2040 "got %lu expected sizeof(TOKEN_DEFAULT_DACL)\n", Size2);
2042 Dacl->DefaultDacl = acl;
2043 ret = SetTokenInformation(Token, TokenDefaultDacl, Dacl, Size);
2044 ok(ret, "SetTokenInformation(TokenDefaultDacl) failed with error %lu\n", GetLastError());
2046 if (Size2 == sizeof(TOKEN_DEFAULT_DACL)) {
2047 ret = GetTokenInformation(Token, TokenDefaultDacl, Dacl, Size, &Size2);
2048 ok(ret, "GetTokenInformation(TokenDefaultDacl) failed with error %lu\n", GetLastError());
2049 } else
2050 win_skip("TOKEN_DEFAULT_DACL size too small on WoW64\n");
2052 free(Dacl);
2053 CloseHandle(Token);
2056 static void test_GetTokenInformation(void)
2058 DWORD is_app_container, size;
2059 HANDLE token;
2060 BOOL ret;
2062 ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
2063 ok(ret, "OpenProcessToken failed: %lu\n", GetLastError());
2065 size = 0;
2066 is_app_container = 0xdeadbeef;
2067 ret = GetTokenInformation(token, TokenIsAppContainer, &is_app_container,
2068 sizeof(is_app_container), &size);
2069 ok(ret || broken(GetLastError() == ERROR_INVALID_PARAMETER ||
2070 GetLastError() == ERROR_INVALID_FUNCTION), /* pre-win8 */
2071 "GetTokenInformation failed: %lu\n", GetLastError());
2072 if(ret) {
2073 ok(size == sizeof(is_app_container), "size = %lu\n", size);
2074 ok(!is_app_container, "is_app_container = %lx\n", is_app_container);
2077 CloseHandle(token);
2080 typedef union _MAX_SID
2082 SID sid;
2083 char max[SECURITY_MAX_SID_SIZE];
2084 } MAX_SID;
2086 static void test_sid_str(PSID * sid)
2088 char *str_sid;
2089 BOOL ret = ConvertSidToStringSidA(sid, &str_sid);
2090 ok(ret, "ConvertSidToStringSidA() failed: %ld\n", GetLastError());
2091 if (ret)
2093 char account[MAX_PATH], domain[MAX_PATH];
2094 SID_NAME_USE use;
2095 DWORD acc_size = MAX_PATH;
2096 DWORD dom_size = MAX_PATH;
2097 ret = LookupAccountSidA (NULL, sid, account, &acc_size, domain, &dom_size, &use);
2098 ok(ret || GetLastError() == ERROR_NONE_MAPPED,
2099 "LookupAccountSid(%s) failed: %ld\n", str_sid, GetLastError());
2100 if (ret)
2101 trace(" %s %s\\%s %d\n", str_sid, domain, account, use);
2102 else if (GetLastError() == ERROR_NONE_MAPPED)
2103 trace(" %s couldn't be mapped\n", str_sid);
2104 LocalFree(str_sid);
2108 static const struct well_known_sid_value
2110 BOOL without_domain;
2111 const char *sid_string;
2112 } well_known_sid_values[] = {
2113 /* 0 */ {TRUE, "S-1-0-0"}, {TRUE, "S-1-1-0"}, {TRUE, "S-1-2-0"}, {TRUE, "S-1-3-0"},
2114 /* 4 */ {TRUE, "S-1-3-1"}, {TRUE, "S-1-3-2"}, {TRUE, "S-1-3-3"}, {TRUE, "S-1-5"},
2115 /* 8 */ {FALSE, "S-1-5-1"}, {TRUE, "S-1-5-2"}, {TRUE, "S-1-5-3"}, {TRUE, "S-1-5-4"},
2116 /* 12 */ {TRUE, "S-1-5-6"}, {TRUE, "S-1-5-7"}, {TRUE, "S-1-5-8"}, {TRUE, "S-1-5-9"},
2117 /* 16 */ {TRUE, "S-1-5-10"}, {TRUE, "S-1-5-11"}, {TRUE, "S-1-5-12"}, {TRUE, "S-1-5-13"},
2118 /* 20 */ {TRUE, "S-1-5-14"}, {FALSE, NULL}, {TRUE, "S-1-5-18"}, {TRUE, "S-1-5-19"},
2119 /* 24 */ {TRUE, "S-1-5-20"}, {TRUE, "S-1-5-32"},
2120 /* 26 */ {FALSE, "S-1-5-32-544"}, {TRUE, "S-1-5-32-545"}, {TRUE, "S-1-5-32-546"},
2121 /* 29 */ {TRUE, "S-1-5-32-547"}, {TRUE, "S-1-5-32-548"}, {TRUE, "S-1-5-32-549"},
2122 /* 32 */ {TRUE, "S-1-5-32-550"}, {TRUE, "S-1-5-32-551"}, {TRUE, "S-1-5-32-552"},
2123 /* 35 */ {TRUE, "S-1-5-32-554"}, {TRUE, "S-1-5-32-555"}, {TRUE, "S-1-5-32-556"},
2124 /* 38 */ {FALSE, "S-1-5-21-12-23-34-45-56-500"}, {FALSE, "S-1-5-21-12-23-34-45-56-501"},
2125 /* 40 */ {FALSE, "S-1-5-21-12-23-34-45-56-502"}, {FALSE, "S-1-5-21-12-23-34-45-56-512"},
2126 /* 42 */ {FALSE, "S-1-5-21-12-23-34-45-56-513"}, {FALSE, "S-1-5-21-12-23-34-45-56-514"},
2127 /* 44 */ {FALSE, "S-1-5-21-12-23-34-45-56-515"}, {FALSE, "S-1-5-21-12-23-34-45-56-516"},
2128 /* 46 */ {FALSE, "S-1-5-21-12-23-34-45-56-517"}, {FALSE, "S-1-5-21-12-23-34-45-56-518"},
2129 /* 48 */ {FALSE, "S-1-5-21-12-23-34-45-56-519"}, {FALSE, "S-1-5-21-12-23-34-45-56-520"},
2130 /* 50 */ {FALSE, "S-1-5-21-12-23-34-45-56-553"},
2131 /* Added in Windows Server 2003 */
2132 /* 51 */ {TRUE, "S-1-5-64-10"}, {TRUE, "S-1-5-64-21"}, {TRUE, "S-1-5-64-14"},
2133 /* 54 */ {TRUE, "S-1-5-15"}, {TRUE, "S-1-5-1000"}, {FALSE, "S-1-5-32-557"},
2134 /* 57 */ {TRUE, "S-1-5-32-558"}, {TRUE, "S-1-5-32-559"}, {TRUE, "S-1-5-32-560"},
2135 /* 60 */ {TRUE, "S-1-5-32-561"}, {TRUE, "S-1-5-32-562"},
2136 /* Added in Windows Vista: */
2137 /* 62 */ {TRUE, "S-1-5-32-568"},
2138 /* 63 */ {TRUE, "S-1-5-17"}, {FALSE, "S-1-5-32-569"}, {TRUE, "S-1-16-0"},
2139 /* 66 */ {TRUE, "S-1-16-4096"}, {TRUE, "S-1-16-8192"}, {TRUE, "S-1-16-12288"},
2140 /* 69 */ {TRUE, "S-1-16-16384"}, {TRUE, "S-1-5-33"}, {TRUE, "S-1-3-4"},
2141 /* 72 */ {FALSE, "S-1-5-21-12-23-34-45-56-571"}, {FALSE, "S-1-5-21-12-23-34-45-56-572"},
2142 /* 74 */ {TRUE, "S-1-5-22"}, {FALSE, "S-1-5-21-12-23-34-45-56-521"}, {TRUE, "S-1-5-32-573"},
2143 /* 77 */ {FALSE, "S-1-5-21-12-23-34-45-56-498"}, {TRUE, "S-1-5-32-574"}, {TRUE, "S-1-16-8448"},
2144 /* 80 */ {FALSE, NULL}, {TRUE, "S-1-2-1"}, {TRUE, "S-1-5-65-1"}, {FALSE, NULL},
2145 /* 84 */ {TRUE, "S-1-15-2-1"},
2148 static void test_CreateWellKnownSid(void)
2150 SID_IDENTIFIER_AUTHORITY ident = { SECURITY_NT_AUTHORITY };
2151 PSID domainsid, sid;
2152 DWORD size, error;
2153 BOOL ret;
2154 unsigned int i;
2156 size = 0;
2157 SetLastError(0xdeadbeef);
2158 ret = CreateWellKnownSid(WinInteractiveSid, NULL, NULL, &size);
2159 error = GetLastError();
2160 ok(!ret, "CreateWellKnownSid succeeded\n");
2161 ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %lu\n", error);
2162 ok(size, "expected size > 0\n");
2164 SetLastError(0xdeadbeef);
2165 ret = CreateWellKnownSid(WinInteractiveSid, NULL, NULL, &size);
2166 error = GetLastError();
2167 ok(!ret, "CreateWellKnownSid succeeded\n");
2168 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %lu\n", error);
2170 sid = malloc(size);
2171 ret = CreateWellKnownSid(WinInteractiveSid, NULL, sid, &size);
2172 ok(ret, "CreateWellKnownSid failed %lu\n", GetLastError());
2173 free(sid);
2175 /* a domain sid usually have three subauthorities but we test that CreateWellKnownSid doesn't check it */
2176 AllocateAndInitializeSid(&ident, 6, SECURITY_NT_NON_UNIQUE, 12, 23, 34, 45, 56, 0, 0, &domainsid);
2178 for (i = 0; i < ARRAY_SIZE(well_known_sid_values); i++)
2180 const struct well_known_sid_value *value = &well_known_sid_values[i];
2181 char sid_buffer[SECURITY_MAX_SID_SIZE];
2182 LPSTR str;
2183 DWORD cb;
2185 if (value->sid_string == NULL)
2186 continue;
2188 /* some SIDs aren't implemented by all Windows versions - detect it */
2189 cb = sizeof(sid_buffer);
2190 if (!CreateWellKnownSid(i, NULL, sid_buffer, &cb))
2192 skip("Well known SID %u not implemented\n", i);
2193 continue;
2196 cb = sizeof(sid_buffer);
2197 ok(CreateWellKnownSid(i, value->without_domain ? NULL : domainsid, sid_buffer, &cb), "Couldn't create well known sid %u\n", i);
2198 expect_eq(GetSidLengthRequired(*GetSidSubAuthorityCount(sid_buffer)), cb, DWORD, "%ld");
2199 ok(IsValidSid(sid_buffer), "The sid is not valid\n");
2200 ok(ConvertSidToStringSidA(sid_buffer, &str), "Couldn't convert SID to string\n");
2201 ok(strcmp(str, value->sid_string) == 0, "%d: SID mismatch - expected %s, got %s\n", i,
2202 value->sid_string, str);
2203 LocalFree(str);
2205 if (value->without_domain)
2207 char buf2[SECURITY_MAX_SID_SIZE];
2208 cb = sizeof(buf2);
2209 ok(CreateWellKnownSid(i, domainsid, buf2, &cb), "Couldn't create well known sid %u with optional domain\n", i);
2210 expect_eq(GetSidLengthRequired(*GetSidSubAuthorityCount(sid_buffer)), cb, DWORD, "%ld");
2211 ok(memcmp(buf2, sid_buffer, cb) == 0, "SID create with domain is different than without (%u)\n", i);
2215 FreeSid(domainsid);
2218 static void test_LookupAccountSid(void)
2220 SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
2221 CHAR accountA[MAX_PATH], domainA[MAX_PATH], usernameA[MAX_PATH];
2222 DWORD acc_sizeA, dom_sizeA, user_sizeA;
2223 DWORD real_acc_sizeA, real_dom_sizeA;
2224 WCHAR accountW[MAX_PATH], domainW[MAX_PATH];
2225 LSA_OBJECT_ATTRIBUTES object_attributes;
2226 DWORD acc_sizeW, dom_sizeW;
2227 DWORD real_acc_sizeW, real_dom_sizeW;
2228 PSID pUsersSid = NULL;
2229 SID_NAME_USE use;
2230 BOOL ret;
2231 DWORD error, size, cbti = 0;
2232 MAX_SID max_sid;
2233 CHAR *str_sidA;
2234 int i;
2235 HANDLE hToken;
2236 PTOKEN_USER ptiUser = NULL;
2237 LSA_HANDLE handle;
2238 NTSTATUS status;
2240 /* native windows crashes if account size, domain size, or name use is NULL */
2242 ret = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
2243 DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &pUsersSid);
2244 ok(ret || (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED),
2245 "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
2247 /* not running on NT so give up */
2248 if (!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
2249 return;
2251 real_acc_sizeA = MAX_PATH;
2252 real_dom_sizeA = MAX_PATH;
2253 ret = LookupAccountSidA(NULL, pUsersSid, accountA, &real_acc_sizeA, domainA, &real_dom_sizeA, &use);
2254 ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
2256 /* try NULL account */
2257 acc_sizeA = MAX_PATH;
2258 dom_sizeA = MAX_PATH;
2259 ret = LookupAccountSidA(NULL, pUsersSid, NULL, &acc_sizeA, domainA, &dom_sizeA, &use);
2260 ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
2262 /* try NULL domain */
2263 acc_sizeA = MAX_PATH;
2264 dom_sizeA = MAX_PATH;
2265 ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, NULL, &dom_sizeA, &use);
2266 ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
2268 /* try a small account buffer */
2269 acc_sizeA = 1;
2270 dom_sizeA = MAX_PATH;
2271 accountA[0] = 0;
2272 ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
2273 ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n");
2274 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2275 "LookupAccountSidA() Expected ERROR_NOT_ENOUGH_MEMORY, got %lu\n", GetLastError());
2277 /* try a 0 sized account buffer */
2278 acc_sizeA = 0;
2279 dom_sizeA = MAX_PATH;
2280 accountA[0] = 0;
2281 LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
2282 /* this can fail or succeed depending on OS version but the size will always be returned */
2283 ok(acc_sizeA == real_acc_sizeA + 1,
2284 "LookupAccountSidA() Expected acc_size = %lu, got %lu\n",
2285 real_acc_sizeA + 1, acc_sizeA);
2287 /* try a 0 sized account buffer */
2288 acc_sizeA = 0;
2289 dom_sizeA = MAX_PATH;
2290 LookupAccountSidA(NULL, pUsersSid, NULL, &acc_sizeA, domainA, &dom_sizeA, &use);
2291 /* this can fail or succeed depending on OS version but the size will always be returned */
2292 ok(acc_sizeA == real_acc_sizeA + 1,
2293 "LookupAccountSid() Expected acc_size = %lu, got %lu\n",
2294 real_acc_sizeA + 1, acc_sizeA);
2296 /* try a small domain buffer */
2297 dom_sizeA = 1;
2298 acc_sizeA = MAX_PATH;
2299 accountA[0] = 0;
2300 ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
2301 ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n");
2302 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2303 "LookupAccountSidA() Expected ERROR_NOT_ENOUGH_MEMORY, got %lu\n", GetLastError());
2305 /* try a 0 sized domain buffer */
2306 dom_sizeA = 0;
2307 acc_sizeA = MAX_PATH;
2308 accountA[0] = 0;
2309 LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
2310 /* this can fail or succeed depending on OS version but the size will always be returned */
2311 ok(dom_sizeA == real_dom_sizeA + 1,
2312 "LookupAccountSidA() Expected dom_size = %lu, got %lu\n",
2313 real_dom_sizeA + 1, dom_sizeA);
2315 /* try a 0 sized domain buffer */
2316 dom_sizeA = 0;
2317 acc_sizeA = MAX_PATH;
2318 LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, NULL, &dom_sizeA, &use);
2319 /* this can fail or succeed depending on OS version but the size will always be returned */
2320 ok(dom_sizeA == real_dom_sizeA + 1,
2321 "LookupAccountSidA() Expected dom_size = %lu, got %lu\n",
2322 real_dom_sizeA + 1, dom_sizeA);
2324 real_acc_sizeW = MAX_PATH;
2325 real_dom_sizeW = MAX_PATH;
2326 ret = LookupAccountSidW(NULL, pUsersSid, accountW, &real_acc_sizeW, domainW, &real_dom_sizeW, &use);
2327 ok(ret, "LookupAccountSidW() Expected TRUE, got FALSE\n");
2329 /* try an invalid system name */
2330 real_acc_sizeA = MAX_PATH;
2331 real_dom_sizeA = MAX_PATH;
2332 ret = LookupAccountSidA("deepthought", pUsersSid, accountA, &real_acc_sizeA, domainA, &real_dom_sizeA, &use);
2333 ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n");
2334 ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR /* Vista */,
2335 "LookupAccountSidA() Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %lu\n", GetLastError());
2337 /* native windows crashes if domainW or accountW is NULL */
2339 /* try a small account buffer */
2340 acc_sizeW = 1;
2341 dom_sizeW = MAX_PATH;
2342 accountW[0] = 0;
2343 ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
2344 ok(!ret, "LookupAccountSidW() Expected FALSE got TRUE\n");
2345 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2346 "LookupAccountSidW() Expected ERROR_NOT_ENOUGH_MEMORY, got %lu\n", GetLastError());
2348 /* try a 0 sized account buffer */
2349 acc_sizeW = 0;
2350 dom_sizeW = MAX_PATH;
2351 accountW[0] = 0;
2352 LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
2353 /* this can fail or succeed depending on OS version but the size will always be returned */
2354 ok(acc_sizeW == real_acc_sizeW + 1,
2355 "LookupAccountSidW() Expected acc_size = %lu, got %lu\n",
2356 real_acc_sizeW + 1, acc_sizeW);
2358 /* try a 0 sized account buffer */
2359 acc_sizeW = 0;
2360 dom_sizeW = MAX_PATH;
2361 LookupAccountSidW(NULL, pUsersSid, NULL, &acc_sizeW, domainW, &dom_sizeW, &use);
2362 /* this can fail or succeed depending on OS version but the size will always be returned */
2363 ok(acc_sizeW == real_acc_sizeW + 1,
2364 "LookupAccountSidW() Expected acc_size = %lu, got %lu\n",
2365 real_acc_sizeW + 1, acc_sizeW);
2367 /* try a small domain buffer */
2368 dom_sizeW = 1;
2369 acc_sizeW = MAX_PATH;
2370 accountW[0] = 0;
2371 ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
2372 ok(!ret, "LookupAccountSidW() Expected FALSE got TRUE\n");
2373 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2374 "LookupAccountSidW() Expected ERROR_NOT_ENOUGH_MEMORY, got %lu\n", GetLastError());
2376 /* try a 0 sized domain buffer */
2377 dom_sizeW = 0;
2378 acc_sizeW = MAX_PATH;
2379 accountW[0] = 0;
2380 LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
2381 /* this can fail or succeed depending on OS version but the size will always be returned */
2382 ok(dom_sizeW == real_dom_sizeW + 1,
2383 "LookupAccountSidW() Expected dom_size = %lu, got %lu\n",
2384 real_dom_sizeW + 1, dom_sizeW);
2386 /* try a 0 sized domain buffer */
2387 dom_sizeW = 0;
2388 acc_sizeW = MAX_PATH;
2389 LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, NULL, &dom_sizeW, &use);
2390 /* this can fail or succeed depending on OS version but the size will always be returned */
2391 ok(dom_sizeW == real_dom_sizeW + 1,
2392 "LookupAccountSidW() Expected dom_size = %lu, got %lu\n",
2393 real_dom_sizeW + 1, dom_sizeW);
2395 acc_sizeW = dom_sizeW = use = 0;
2396 SetLastError(0xdeadbeef);
2397 ret = LookupAccountSidW(NULL, pUsersSid, NULL, &acc_sizeW, NULL, &dom_sizeW, &use);
2398 error = GetLastError();
2399 ok(!ret, "LookupAccountSidW failed %lu\n", GetLastError());
2400 ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %lu\n", error);
2401 ok(acc_sizeW, "expected non-zero account size\n");
2402 ok(dom_sizeW, "expected non-zero domain size\n");
2403 ok(!use, "expected zero use %u\n", use);
2405 FreeSid(pUsersSid);
2407 /* Test LookupAccountSid with Sid retrieved from token information.
2408 This assumes this process is running under the account of the current user.*/
2409 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_DUPLICATE, &hToken);
2410 ok(ret, "OpenProcessToken failed with error %ld\n", GetLastError());
2411 ret = GetTokenInformation(hToken, TokenUser, NULL, 0, &cbti);
2412 ok(!ret, "GetTokenInformation failed with error %ld\n", GetLastError());
2413 ptiUser = malloc(cbti);
2414 if (GetTokenInformation(hToken, TokenUser, ptiUser, cbti, &cbti))
2416 acc_sizeA = dom_sizeA = MAX_PATH;
2417 ret = LookupAccountSidA(NULL, ptiUser->User.Sid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
2418 ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
2419 user_sizeA = MAX_PATH;
2420 ret = GetUserNameA(usernameA , &user_sizeA);
2421 ok(ret, "GetUserNameA() Expected TRUE, got FALSE\n");
2422 ok(lstrcmpA(usernameA, accountA) == 0, "LookupAccountSidA() Expected account name: %s got: %s\n", usernameA, accountA );
2424 free(ptiUser);
2426 trace("Well Known SIDs:\n");
2427 for (i = 0; i <= 60; i++)
2429 size = SECURITY_MAX_SID_SIZE;
2430 if (CreateWellKnownSid(i, NULL, &max_sid.sid, &size))
2432 if (ConvertSidToStringSidA(&max_sid.sid, &str_sidA))
2434 acc_sizeA = MAX_PATH;
2435 dom_sizeA = MAX_PATH;
2436 if (LookupAccountSidA(NULL, &max_sid.sid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use))
2437 trace(" %d: %s %s\\%s %d\n", i, str_sidA, domainA, accountA, use);
2438 LocalFree(str_sidA);
2441 else
2443 if (GetLastError() != ERROR_INVALID_PARAMETER)
2444 trace(" CreateWellKnownSid(%d) failed: %ld\n", i, GetLastError());
2445 else
2446 trace(" %d: not supported\n", i);
2450 ZeroMemory(&object_attributes, sizeof(object_attributes));
2451 object_attributes.Length = sizeof(object_attributes);
2453 status = LsaOpenPolicy( NULL, &object_attributes, POLICY_ALL_ACCESS, &handle);
2454 ok(status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED,
2455 "LsaOpenPolicy(POLICY_ALL_ACCESS) returned 0x%08lx\n", status);
2457 /* try a more restricted access mask if necessary */
2458 if (status == STATUS_ACCESS_DENIED) {
2459 trace("LsaOpenPolicy(POLICY_ALL_ACCESS) failed, trying POLICY_VIEW_LOCAL_INFORMATION\n");
2460 status = LsaOpenPolicy( NULL, &object_attributes, POLICY_VIEW_LOCAL_INFORMATION, &handle);
2461 ok(status == STATUS_SUCCESS, "LsaOpenPolicy(POLICY_VIEW_LOCAL_INFORMATION) returned 0x%08lx\n", status);
2464 if (status == STATUS_SUCCESS)
2466 PPOLICY_ACCOUNT_DOMAIN_INFO info;
2467 status = LsaQueryInformationPolicy(handle, PolicyAccountDomainInformation, (PVOID*)&info);
2468 ok(status == STATUS_SUCCESS, "LsaQueryInformationPolicy() failed, returned 0x%08lx\n", status);
2469 if (status == STATUS_SUCCESS)
2471 ok(info->DomainSid!=0, "LsaQueryInformationPolicy(PolicyAccountDomainInformation) missing SID\n");
2472 if (info->DomainSid)
2474 int count = *GetSidSubAuthorityCount(info->DomainSid);
2475 CopySid(GetSidLengthRequired(count), &max_sid, info->DomainSid);
2476 test_sid_str((PSID)&max_sid.sid);
2477 max_sid.sid.SubAuthority[count] = DOMAIN_USER_RID_ADMIN;
2478 max_sid.sid.SubAuthorityCount = count + 1;
2479 test_sid_str((PSID)&max_sid.sid);
2480 max_sid.sid.SubAuthority[count] = DOMAIN_USER_RID_GUEST;
2481 test_sid_str((PSID)&max_sid.sid);
2482 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_ADMINS;
2483 test_sid_str((PSID)&max_sid.sid);
2484 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_USERS;
2485 test_sid_str((PSID)&max_sid.sid);
2486 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_GUESTS;
2487 test_sid_str((PSID)&max_sid.sid);
2488 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_COMPUTERS;
2489 test_sid_str((PSID)&max_sid.sid);
2490 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_CONTROLLERS;
2491 test_sid_str((PSID)&max_sid.sid);
2492 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_CERT_ADMINS;
2493 test_sid_str((PSID)&max_sid.sid);
2494 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_SCHEMA_ADMINS;
2495 test_sid_str((PSID)&max_sid.sid);
2496 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_ENTERPRISE_ADMINS;
2497 test_sid_str((PSID)&max_sid.sid);
2498 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_POLICY_ADMINS;
2499 test_sid_str((PSID)&max_sid.sid);
2500 max_sid.sid.SubAuthority[count] = DOMAIN_ALIAS_RID_RAS_SERVERS;
2501 test_sid_str((PSID)&max_sid.sid);
2502 max_sid.sid.SubAuthority[count] = 1000; /* first user account */
2503 test_sid_str((PSID)&max_sid.sid);
2506 LsaFreeMemory(info);
2509 status = LsaClose(handle);
2510 ok(status == STATUS_SUCCESS, "LsaClose() failed, returned 0x%08lx\n", status);
2514 static BOOL get_sid_info(PSID psid, LPSTR *user, LPSTR *dom)
2516 static CHAR account[UNLEN + 1];
2517 static CHAR domain[UNLEN + 1];
2518 DWORD size, dom_size;
2519 SID_NAME_USE use;
2521 *user = account;
2522 *dom = domain;
2524 size = dom_size = UNLEN + 1;
2525 account[0] = '\0';
2526 domain[0] = '\0';
2527 SetLastError(0xdeadbeef);
2528 return LookupAccountSidA(NULL, psid, account, &size, domain, &dom_size, &use);
2531 static void check_wellknown_name(const char* name, WELL_KNOWN_SID_TYPE result)
2533 SID_IDENTIFIER_AUTHORITY ident = { SECURITY_NT_AUTHORITY };
2534 PSID domainsid = NULL;
2535 char wk_sid[SECURITY_MAX_SID_SIZE];
2536 DWORD cb;
2538 DWORD sid_size, domain_size;
2539 SID_NAME_USE sid_use;
2540 LPSTR domain, account, sid_domain, wk_domain, wk_account;
2541 PSID psid;
2542 BOOL ret ,ret2;
2544 sid_size = 0;
2545 domain_size = 0;
2546 ret = LookupAccountNameA(NULL, name, NULL, &sid_size, NULL, &domain_size, &sid_use);
2547 ok(!ret, " %s Should have failed to lookup account name\n", name);
2548 psid = malloc(sid_size);
2549 domain = malloc(domain_size);
2550 ret = LookupAccountNameA(NULL, name, psid, &sid_size, domain, &domain_size, &sid_use);
2552 if (!result)
2554 ok(!ret, " %s Should have failed to lookup account name\n",name);
2555 goto cleanup;
2558 AllocateAndInitializeSid(&ident, 6, SECURITY_NT_NON_UNIQUE, 12, 23, 34, 45, 56, 0, 0, &domainsid);
2559 cb = sizeof(wk_sid);
2560 if (!CreateWellKnownSid(result, domainsid, wk_sid, &cb))
2562 win_skip("SID %i is not available on the system\n",result);
2563 goto cleanup;
2566 ret2 = get_sid_info(wk_sid, &wk_account, &wk_domain);
2567 if (!ret2 && GetLastError() == ERROR_NONE_MAPPED)
2569 win_skip("CreateWellKnownSid() succeeded but the account '%s' is not present (W2K)\n", name);
2570 goto cleanup;
2573 get_sid_info(psid, &account, &sid_domain);
2575 ok(ret, "Failed to lookup account name %s\n",name);
2576 ok(sid_size != 0, "sid_size was zero\n");
2578 ok(EqualSid(psid,wk_sid),"%s Sid %s fails to match well known sid %s!\n",
2579 name, debugstr_sid(psid), debugstr_sid(wk_sid));
2581 ok(!lstrcmpA(account, wk_account), "Expected %s , got %s\n", account, wk_account);
2582 ok(!lstrcmpA(domain, wk_domain), "Expected %s, got %s\n", wk_domain, domain);
2583 ok(sid_use == SidTypeWellKnownGroup , "Expected Use (5), got %d\n", sid_use);
2585 cleanup:
2586 FreeSid(domainsid);
2587 free(psid);
2588 free(domain);
2591 static void test_LookupAccountName(void)
2593 DWORD sid_size, domain_size, user_size;
2594 DWORD sid_save, domain_save;
2595 CHAR user_name[UNLEN + 1];
2596 CHAR computer_name[UNLEN + 1];
2597 SID_NAME_USE sid_use;
2598 LPSTR domain, account, sid_dom;
2599 PSID psid;
2600 BOOL ret;
2602 /* native crashes if (assuming all other parameters correct):
2603 * - peUse is NULL
2604 * - Sid is NULL and cbSid is > 0
2605 * - cbSid or cchReferencedDomainName are NULL
2606 * - ReferencedDomainName is NULL and cchReferencedDomainName is the correct size
2609 user_size = UNLEN + 1;
2610 SetLastError(0xdeadbeef);
2611 ret = GetUserNameA(user_name, &user_size);
2612 ok(ret, "Failed to get user name : %ld\n", GetLastError());
2614 /* get sizes */
2615 sid_size = 0;
2616 domain_size = 0;
2617 sid_use = 0xcafebabe;
2618 SetLastError(0xdeadbeef);
2619 ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, NULL, &domain_size, &sid_use);
2620 if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
2622 win_skip("LookupAccountNameA is not implemented\n");
2623 return;
2625 ok(!ret, "Expected 0, got %d\n", ret);
2626 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2627 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2628 ok(sid_size != 0, "Expected non-zero sid size\n");
2629 ok(domain_size != 0, "Expected non-zero domain size\n");
2630 ok(sid_use == (SID_NAME_USE)0xcafebabe, "Expected 0xcafebabe, got %d\n", sid_use);
2632 sid_save = sid_size;
2633 domain_save = domain_size;
2635 psid = malloc(sid_size);
2636 domain = malloc(domain_size);
2638 /* try valid account name */
2639 ret = LookupAccountNameA(NULL, user_name, psid, &sid_size, domain, &domain_size, &sid_use);
2640 get_sid_info(psid, &account, &sid_dom);
2641 ok(ret, "Failed to lookup account name\n");
2642 ok(sid_size == GetLengthSid(psid), "Expected %ld, got %ld\n", GetLengthSid(psid), sid_size);
2643 ok(!lstrcmpA(account, user_name), "Expected %s, got %s\n", user_name, account);
2644 ok(!lstrcmpiA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
2645 ok(domain_size == domain_save - 1, "Expected %ld, got %ld\n", domain_save - 1, domain_size);
2646 ok(strlen(domain) == domain_size, "Expected %d, got %ld\n", lstrlenA(domain), domain_size);
2647 ok(sid_use == SidTypeUser, "Expected SidTypeUser (%d), got %d\n", SidTypeUser, sid_use);
2648 domain_size = domain_save;
2649 sid_size = sid_save;
2651 if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH)
2653 skip("Non-English locale (test with hardcoded 'Everyone')\n");
2655 else
2657 ret = LookupAccountNameA(NULL, "Everyone", psid, &sid_size, domain, &domain_size, &sid_use);
2658 get_sid_info(psid, &account, &sid_dom);
2659 ok(ret, "Failed to lookup account name\n");
2660 ok(sid_size != 0, "sid_size was zero\n");
2661 ok(!lstrcmpA(account, "Everyone"), "Expected Everyone, got %s\n", account);
2662 ok(!lstrcmpiA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
2663 ok(domain_size == 0, "Expected 0, got %ld\n", domain_size);
2664 ok(strlen(domain) == domain_size, "Expected %d, got %ld\n", lstrlenA(domain), domain_size);
2665 ok(sid_use == SidTypeWellKnownGroup, "Expected SidTypeWellKnownGroup (%d), got %d\n", SidTypeWellKnownGroup, sid_use);
2666 domain_size = domain_save;
2669 /* NULL Sid with zero sid size */
2670 SetLastError(0xdeadbeef);
2671 sid_size = 0;
2672 ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, domain, &domain_size, &sid_use);
2673 ok(!ret, "Expected 0, got %d\n", ret);
2674 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2675 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2676 ok(sid_size == sid_save, "Expected %ld, got %ld\n", sid_save, sid_size);
2677 ok(domain_size == domain_save, "Expected %ld, got %ld\n", domain_save, domain_size);
2679 /* try cchReferencedDomainName - 1 */
2680 SetLastError(0xdeadbeef);
2681 domain_size--;
2682 ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, domain, &domain_size, &sid_use);
2683 ok(!ret, "Expected 0, got %d\n", ret);
2684 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2685 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2686 ok(sid_size == sid_save, "Expected %ld, got %ld\n", sid_save, sid_size);
2687 ok(domain_size == domain_save, "Expected %ld, got %ld\n", domain_save, domain_size);
2689 /* NULL ReferencedDomainName with zero domain name size */
2690 SetLastError(0xdeadbeef);
2691 domain_size = 0;
2692 ret = LookupAccountNameA(NULL, user_name, psid, &sid_size, NULL, &domain_size, &sid_use);
2693 ok(!ret, "Expected 0, got %d\n", ret);
2694 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2695 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2696 ok(sid_size == sid_save, "Expected %ld, got %ld\n", sid_save, sid_size);
2697 ok(domain_size == domain_save, "Expected %ld, got %ld\n", domain_save, domain_size);
2699 free(psid);
2700 free(domain);
2702 /* get sizes for NULL account name */
2703 sid_size = 0;
2704 domain_size = 0;
2705 sid_use = 0xcafebabe;
2706 SetLastError(0xdeadbeef);
2707 ret = LookupAccountNameA(NULL, NULL, NULL, &sid_size, NULL, &domain_size, &sid_use);
2708 if (!ret && GetLastError() == ERROR_NONE_MAPPED)
2709 win_skip("NULL account name doesn't work on NT4\n");
2710 else
2712 ok(!ret, "Expected 0, got %d\n", ret);
2713 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2714 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2715 ok(sid_size != 0, "Expected non-zero sid size\n");
2716 ok(domain_size != 0, "Expected non-zero domain size\n");
2717 ok(sid_use == (SID_NAME_USE)0xcafebabe, "Expected 0xcafebabe, got %d\n", sid_use);
2719 psid = malloc(sid_size);
2720 domain = malloc(domain_size);
2722 /* try NULL account name */
2723 ret = LookupAccountNameA(NULL, NULL, psid, &sid_size, domain, &domain_size, &sid_use);
2724 get_sid_info(psid, &account, &sid_dom);
2725 ok(ret, "Failed to lookup account name\n");
2726 /* Using a fixed string will not work on different locales */
2727 ok(!lstrcmpiA(account, domain),
2728 "Got %s for account and %s for domain, these should be the same\n", account, domain);
2729 ok(sid_use == SidTypeDomain, "Expected SidTypeDomain (%d), got %d\n", SidTypeDomain, sid_use);
2731 free(psid);
2732 free(domain);
2735 /* try an invalid account name */
2736 SetLastError(0xdeadbeef);
2737 sid_size = 0;
2738 domain_size = 0;
2739 ret = LookupAccountNameA(NULL, "oogabooga", NULL, &sid_size, NULL, &domain_size, &sid_use);
2740 ok(!ret, "Expected 0, got %d\n", ret);
2741 ok(GetLastError() == ERROR_NONE_MAPPED ||
2742 broken(GetLastError() == ERROR_TRUSTED_RELATIONSHIP_FAILURE),
2743 "Expected ERROR_NONE_MAPPED, got %ld\n", GetLastError());
2744 ok(sid_size == 0, "Expected 0, got %ld\n", sid_size);
2745 ok(domain_size == 0, "Expected 0, got %ld\n", domain_size);
2747 /* try an invalid system name */
2748 SetLastError(0xdeadbeef);
2749 sid_size = 0;
2750 domain_size = 0;
2751 ret = LookupAccountNameA("deepthought", NULL, NULL, &sid_size, NULL, &domain_size, &sid_use);
2752 ok(!ret, "Expected 0, got %d\n", ret);
2753 ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR /* Vista */,
2754 "Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %ld\n", GetLastError());
2755 ok(sid_size == 0, "Expected 0, got %ld\n", sid_size);
2756 ok(domain_size == 0, "Expected 0, got %ld\n", domain_size);
2758 /* try with the computer name as the account name */
2759 domain_size = sizeof(computer_name);
2760 GetComputerNameA(computer_name, &domain_size);
2761 sid_size = 0;
2762 domain_size = 0;
2763 ret = LookupAccountNameA(NULL, computer_name, NULL, &sid_size, NULL, &domain_size, &sid_use);
2764 ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
2765 GetLastError() == ERROR_NONE_MAPPED /* in a domain */ ||
2766 broken(GetLastError() == ERROR_TRUSTED_DOMAIN_FAILURE) ||
2767 broken(GetLastError() == ERROR_TRUSTED_RELATIONSHIP_FAILURE)),
2768 "LookupAccountNameA failed: %ld\n", GetLastError());
2769 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2771 psid = malloc(sid_size);
2772 domain = malloc(domain_size);
2773 ret = LookupAccountNameA(NULL, computer_name, psid, &sid_size, domain, &domain_size, &sid_use);
2774 ok(ret, "LookupAccountNameA failed: %ld\n", GetLastError());
2775 ok(sid_use == SidTypeDomain ||
2776 (sid_use == SidTypeUser && ! strcmp(computer_name, user_name)), "expected SidTypeDomain for %s, got %d\n", computer_name, sid_use);
2777 free(domain);
2778 free(psid);
2781 /* Well Known names */
2782 if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH)
2784 skip("Non-English locale (skipping well known name creation tests)\n");
2785 return;
2788 check_wellknown_name("LocalService", WinLocalServiceSid);
2789 check_wellknown_name("Local Service", WinLocalServiceSid);
2790 /* 2 spaces */
2791 check_wellknown_name("Local Service", 0);
2792 check_wellknown_name("NetworkService", WinNetworkServiceSid);
2793 check_wellknown_name("Network Service", WinNetworkServiceSid);
2795 /* example of some names where the spaces are not optional */
2796 check_wellknown_name("Terminal Server User", WinTerminalServerSid);
2797 check_wellknown_name("TerminalServer User", 0);
2798 check_wellknown_name("TerminalServerUser", 0);
2799 check_wellknown_name("Terminal ServerUser", 0);
2801 check_wellknown_name("enterprise domain controllers",WinEnterpriseControllersSid);
2802 check_wellknown_name("enterprisedomain controllers", 0);
2803 check_wellknown_name("enterprise domaincontrollers", 0);
2804 check_wellknown_name("enterprisedomaincontrollers", 0);
2806 /* case insensitivity */
2807 check_wellknown_name("lOCAlServICE", WinLocalServiceSid);
2809 /* fully qualified account names */
2810 check_wellknown_name("NT AUTHORITY\\LocalService", WinLocalServiceSid);
2811 check_wellknown_name("nt authority\\Network Service", WinNetworkServiceSid);
2812 check_wellknown_name("nt authority test\\Network Service", 0);
2813 check_wellknown_name("Dummy\\Network Service", 0);
2814 check_wellknown_name("ntauthority\\Network Service", 0);
2817 static void test_security_descriptor(void)
2819 SECURITY_DESCRIPTOR sd, *sd_rel, *sd_rel2, *sd_abs;
2820 char buf[8192];
2821 DWORD size, size_dacl, size_sacl, size_owner, size_group;
2822 BOOL isDefault, isPresent, ret;
2823 PACL pacl, dacl, sacl;
2824 PSID psid, owner, group;
2826 SetLastError(0xdeadbeef);
2827 ret = InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
2828 if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2830 win_skip("InitializeSecurityDescriptor is not implemented\n");
2831 return;
2834 ok(GetSecurityDescriptorOwner(&sd, &psid, &isDefault), "GetSecurityDescriptorOwner failed\n");
2835 expect_eq(psid, NULL, PSID, "%p");
2836 expect_eq(isDefault, FALSE, BOOL, "%d");
2837 sd.Control |= SE_DACL_PRESENT | SE_SACL_PRESENT;
2839 SetLastError(0xdeadbeef);
2840 size = 5;
2841 expect_eq(MakeSelfRelativeSD(&sd, buf, &size), FALSE, BOOL, "%d");
2842 expect_eq(GetLastError(), (DWORD)ERROR_INSUFFICIENT_BUFFER, DWORD, "%lu");
2843 ok(size > 5, "Size not increased\n");
2844 if (size <= 8192)
2846 expect_eq(MakeSelfRelativeSD(&sd, buf, &size), TRUE, BOOL, "%d");
2847 ok(GetSecurityDescriptorOwner(&sd, &psid, &isDefault), "GetSecurityDescriptorOwner failed\n");
2848 expect_eq(psid, NULL, PSID, "%p");
2849 expect_eq(isDefault, FALSE, BOOL, "%d");
2850 ok(GetSecurityDescriptorGroup(&sd, &psid, &isDefault), "GetSecurityDescriptorGroup failed\n");
2851 expect_eq(psid, NULL, PSID, "%p");
2852 expect_eq(isDefault, FALSE, BOOL, "%d");
2853 ok(GetSecurityDescriptorDacl(&sd, &isPresent, &pacl, &isDefault), "GetSecurityDescriptorDacl failed\n");
2854 expect_eq(isPresent, TRUE, BOOL, "%d");
2855 expect_eq(psid, NULL, PSID, "%p");
2856 expect_eq(isDefault, FALSE, BOOL, "%d");
2857 ok(GetSecurityDescriptorSacl(&sd, &isPresent, &pacl, &isDefault), "GetSecurityDescriptorSacl failed\n");
2858 expect_eq(isPresent, TRUE, BOOL, "%d");
2859 expect_eq(psid, NULL, PSID, "%p");
2860 expect_eq(isDefault, FALSE, BOOL, "%d");
2863 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA(
2864 "O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)"
2865 "(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)"
2866 "(AU;NPSA;0x12019f;;;SU)", SDDL_REVISION_1, (void **)&sd_rel, NULL);
2867 ok(ret, "got %lu\n", GetLastError());
2869 size = 0;
2870 ret = MakeSelfRelativeSD(sd_rel, NULL, &size);
2871 todo_wine ok(!ret && GetLastError() == ERROR_BAD_DESCRIPTOR_FORMAT, "got %lu\n", GetLastError());
2873 /* convert to absolute form */
2874 size = size_dacl = size_sacl = size_owner = size_group = 0;
2875 ret = MakeAbsoluteSD(sd_rel, NULL, &size, NULL, &size_dacl, NULL, &size_sacl, NULL, &size_owner, NULL,
2876 &size_group);
2877 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
2879 sd_abs = malloc(size + size_dacl + size_sacl + size_owner + size_group);
2880 dacl = (PACL)(sd_abs + 1);
2881 sacl = (PACL)((char *)dacl + size_dacl);
2882 owner = (PSID)((char *)sacl + size_sacl);
2883 group = (PSID)((char *)owner + size_owner);
2884 ret = MakeAbsoluteSD(sd_rel, sd_abs, &size, dacl, &size_dacl, sacl, &size_sacl, owner, &size_owner,
2885 group, &size_group);
2886 ok(ret, "got %lu\n", GetLastError());
2888 size = 0;
2889 ret = MakeSelfRelativeSD(sd_abs, NULL, &size);
2890 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
2891 ok(size == 184, "got %lu\n", size);
2893 size += 4;
2894 sd_rel2 = malloc(size);
2895 ret = MakeSelfRelativeSD(sd_abs, sd_rel2, &size);
2896 ok(ret, "got %lu\n", GetLastError());
2897 ok(size == 188, "got %lu\n", size);
2899 free(sd_abs);
2900 free(sd_rel2);
2901 LocalFree(sd_rel);
2904 #define TEST_GRANTED_ACCESS(a,b) test_granted_access(a,b,0,__LINE__)
2905 #define TEST_GRANTED_ACCESS2(a,b,c) test_granted_access(a,b,c,__LINE__)
2906 static void test_granted_access(HANDLE handle, ACCESS_MASK access,
2907 ACCESS_MASK alt, int line)
2909 OBJECT_BASIC_INFORMATION obj_info;
2910 NTSTATUS status;
2912 if (!pNtQueryObject)
2914 skip_(__FILE__, line)("Not NT platform - skipping tests\n");
2915 return;
2918 status = pNtQueryObject( handle, ObjectBasicInformation, &obj_info,
2919 sizeof(obj_info), NULL );
2920 ok_(__FILE__, line)(!status, "NtQueryObject with err: %08lx\n", status);
2921 if (alt)
2922 ok_(__FILE__, line)(obj_info.GrantedAccess == access ||
2923 obj_info.GrantedAccess == alt, "Granted access should be 0x%08lx "
2924 "or 0x%08lx, instead of 0x%08lx\n", access, alt, obj_info.GrantedAccess);
2925 else
2926 ok_(__FILE__, line)(obj_info.GrantedAccess == access, "Granted access should "
2927 "be 0x%08lx, instead of 0x%08lx\n", access, obj_info.GrantedAccess);
2930 #define CHECK_SET_SECURITY(o,i,e) \
2931 do{ \
2932 BOOL res_; \
2933 DWORD err; \
2934 SetLastError( 0xdeadbeef ); \
2935 res_ = SetKernelObjectSecurity( o, i, SecurityDescriptor ); \
2936 err = GetLastError(); \
2937 if (e == ERROR_SUCCESS) \
2938 ok(res_, "SetKernelObjectSecurity failed with %ld\n", err); \
2939 else \
2940 ok(!res_ && err == e, "SetKernelObjectSecurity should have failed " \
2941 "with %s, instead of %ld\n", #e, err); \
2942 }while(0)
2944 static void test_process_security(void)
2946 BOOL res;
2947 PTOKEN_USER user;
2948 PTOKEN_OWNER owner;
2949 PTOKEN_PRIMARY_GROUP group;
2950 PSID AdminSid = NULL, UsersSid = NULL, UserSid = NULL;
2951 PACL Acl = NULL, ThreadAcl = NULL;
2952 SECURITY_DESCRIPTOR *SecurityDescriptor = NULL, *ThreadSecurityDescriptor = NULL;
2953 char buffer[MAX_PATH], account[MAX_PATH], domain[MAX_PATH];
2954 PROCESS_INFORMATION info;
2955 STARTUPINFOA startup;
2956 SECURITY_ATTRIBUTES psa, tsa;
2957 HANDLE token, event;
2958 DWORD size, acc_size, dom_size, ret;
2959 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
2960 PSID EveryoneSid = NULL;
2961 SID_NAME_USE use;
2963 Acl = malloc(256);
2964 res = InitializeAcl(Acl, 256, ACL_REVISION);
2965 if (!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2967 win_skip("ACLs not implemented - skipping tests\n");
2968 free(Acl);
2969 return;
2971 ok(res, "InitializeAcl failed with error %ld\n", GetLastError());
2973 res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
2974 ok(res, "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
2976 /* get owner from the token we might be running as a user not admin */
2977 res = OpenProcessToken( GetCurrentProcess(), MAXIMUM_ALLOWED, &token );
2978 ok(res, "OpenProcessToken failed with error %ld\n", GetLastError());
2979 if (!res)
2981 free(Acl);
2982 return;
2985 res = GetTokenInformation( token, TokenOwner, NULL, 0, &size );
2986 ok(!res, "Expected failure, got %d\n", res);
2987 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2988 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2990 owner = malloc(size);
2991 res = GetTokenInformation( token, TokenOwner, owner, size, &size );
2992 ok(res, "GetTokenInformation failed with error %ld\n", GetLastError());
2993 AdminSid = owner->Owner;
2994 test_sid_str(AdminSid);
2996 res = GetTokenInformation( token, TokenPrimaryGroup, NULL, 0, &size );
2997 ok(!res, "Expected failure, got %d\n", res);
2998 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2999 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
3001 group = malloc(size);
3002 res = GetTokenInformation( token, TokenPrimaryGroup, group, size, &size );
3003 ok(res, "GetTokenInformation failed with error %ld\n", GetLastError());
3004 UsersSid = group->PrimaryGroup;
3005 test_sid_str(UsersSid);
3007 acc_size = sizeof(account);
3008 dom_size = sizeof(domain);
3009 ret = LookupAccountSidA( NULL, UsersSid, account, &acc_size, domain, &dom_size, &use );
3010 ok(ret, "LookupAccountSid failed with %ld\n", ret);
3011 ok(use == SidTypeGroup, "expect SidTypeGroup, got %d\n", use);
3012 if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH)
3013 skip("Non-English locale (test with hardcoded 'None')\n");
3014 else
3015 ok(!strcmp(account, "None"), "expect None, got %s\n", account);
3017 res = GetTokenInformation( token, TokenUser, NULL, 0, &size );
3018 ok(!res, "Expected failure, got %d\n", res);
3019 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
3020 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
3022 user = malloc(size);
3023 res = GetTokenInformation( token, TokenUser, user, size, &size );
3024 ok(res, "GetTokenInformation failed with error %ld\n", GetLastError());
3025 UserSid = user->User.Sid;
3026 test_sid_str(UserSid);
3027 ok(EqualPrefixSid(UsersSid, UserSid), "TokenPrimaryGroup Sid and TokenUser Sid don't match.\n");
3029 CloseHandle( token );
3030 if (!res)
3032 free(group);
3033 free(owner);
3034 free(user);
3035 free(Acl);
3036 return;
3039 res = AddAccessDeniedAce(Acl, ACL_REVISION, PROCESS_VM_READ, AdminSid);
3040 ok(res, "AddAccessDeniedAce failed with error %ld\n", GetLastError());
3041 res = AddAccessAllowedAce(Acl, ACL_REVISION, PROCESS_ALL_ACCESS, AdminSid);
3042 ok(res, "AddAccessAllowedAce failed with error %ld\n", GetLastError());
3044 SecurityDescriptor = malloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
3045 res = InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
3046 ok(res, "InitializeSecurityDescriptor failed with error %ld\n", GetLastError());
3048 event = CreateEventA( NULL, TRUE, TRUE, "test_event" );
3049 ok(event != NULL, "CreateEvent %ld\n", GetLastError());
3051 SecurityDescriptor->Revision = 0;
3052 CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_UNKNOWN_REVISION );
3053 SecurityDescriptor->Revision = SECURITY_DESCRIPTOR_REVISION;
3055 CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR );
3056 CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR );
3057 CHECK_SET_SECURITY( event, SACL_SECURITY_INFORMATION, ERROR_ACCESS_DENIED );
3058 CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
3059 /* NULL DACL is valid and means that everyone has access */
3060 SecurityDescriptor->Control |= SE_DACL_PRESENT;
3061 CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
3063 /* Set owner and group and dacl */
3064 res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE);
3065 ok(res, "SetSecurityDescriptorOwner failed with error %ld\n", GetLastError());
3066 CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_SUCCESS );
3067 test_owner_equal( event, AdminSid, __LINE__ );
3069 res = SetSecurityDescriptorGroup(SecurityDescriptor, EveryoneSid, FALSE);
3070 ok(res, "SetSecurityDescriptorGroup failed with error %ld\n", GetLastError());
3071 CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_SUCCESS );
3072 test_group_equal( event, EveryoneSid, __LINE__ );
3074 res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
3075 ok(res, "SetSecurityDescriptorDacl failed with error %ld\n", GetLastError());
3076 CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
3077 /* setting a dacl should not change the owner or group */
3078 test_owner_equal( event, AdminSid, __LINE__ );
3079 test_group_equal( event, EveryoneSid, __LINE__ );
3081 /* Test again with a different SID in case the previous SID also happens to
3082 * be the one that is incorrectly replacing the group. */
3083 res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, FALSE);
3084 ok(res, "SetSecurityDescriptorGroup failed with error %ld\n", GetLastError());
3085 CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_SUCCESS );
3086 test_group_equal( event, UsersSid, __LINE__ );
3088 res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
3089 ok(res, "SetSecurityDescriptorDacl failed with error %ld\n", GetLastError());
3090 CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
3091 test_group_equal( event, UsersSid, __LINE__ );
3093 sprintf(buffer, "%s security test", myARGV[0]);
3094 memset(&startup, 0, sizeof(startup));
3095 startup.cb = sizeof(startup);
3096 startup.dwFlags = STARTF_USESHOWWINDOW;
3097 startup.wShowWindow = SW_SHOWNORMAL;
3099 psa.nLength = sizeof(psa);
3100 psa.lpSecurityDescriptor = SecurityDescriptor;
3101 psa.bInheritHandle = TRUE;
3103 ThreadSecurityDescriptor = malloc( SECURITY_DESCRIPTOR_MIN_LENGTH );
3104 res = InitializeSecurityDescriptor( ThreadSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
3105 ok(res, "InitializeSecurityDescriptor failed with error %ld\n", GetLastError());
3107 ThreadAcl = malloc( 256 );
3108 res = InitializeAcl( ThreadAcl, 256, ACL_REVISION );
3109 ok(res, "InitializeAcl failed with error %ld\n", GetLastError());
3110 res = AddAccessDeniedAce( ThreadAcl, ACL_REVISION, THREAD_SET_THREAD_TOKEN, AdminSid );
3111 ok(res, "AddAccessDeniedAce failed with error %ld\n", GetLastError() );
3112 res = AddAccessAllowedAce( ThreadAcl, ACL_REVISION, THREAD_ALL_ACCESS, AdminSid );
3113 ok(res, "AddAccessAllowedAce failed with error %ld\n", GetLastError());
3115 res = SetSecurityDescriptorOwner( ThreadSecurityDescriptor, AdminSid, FALSE );
3116 ok(res, "SetSecurityDescriptorOwner failed with error %ld\n", GetLastError());
3117 res = SetSecurityDescriptorGroup( ThreadSecurityDescriptor, UsersSid, FALSE );
3118 ok(res, "SetSecurityDescriptorGroup failed with error %ld\n", GetLastError());
3119 res = SetSecurityDescriptorDacl( ThreadSecurityDescriptor, TRUE, ThreadAcl, FALSE );
3120 ok(res, "SetSecurityDescriptorDacl failed with error %ld\n", GetLastError());
3122 tsa.nLength = sizeof(tsa);
3123 tsa.lpSecurityDescriptor = ThreadSecurityDescriptor;
3124 tsa.bInheritHandle = TRUE;
3126 /* Doesn't matter what ACL say we should get full access for ourselves */
3127 res = CreateProcessA( NULL, buffer, &psa, &tsa, FALSE, 0, NULL, NULL, &startup, &info );
3128 ok(res, "CreateProcess with err:%ld\n", GetLastError());
3129 TEST_GRANTED_ACCESS2( info.hProcess, PROCESS_ALL_ACCESS_NT4,
3130 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
3131 TEST_GRANTED_ACCESS2( info.hThread, THREAD_ALL_ACCESS_NT4,
3132 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
3133 wait_child_process( info.hProcess );
3135 FreeSid(EveryoneSid);
3136 CloseHandle( info.hProcess );
3137 CloseHandle( info.hThread );
3138 CloseHandle( event );
3139 free(group);
3140 free(owner);
3141 free(user);
3142 free(Acl);
3143 free(SecurityDescriptor);
3144 free(ThreadAcl);
3145 free(ThreadSecurityDescriptor);
3148 static void test_process_security_child(void)
3150 HANDLE handle, handle1;
3151 BOOL ret;
3152 DWORD err;
3154 handle = OpenProcess( PROCESS_TERMINATE, FALSE, GetCurrentProcessId() );
3155 ok(handle != NULL, "OpenProcess(PROCESS_TERMINATE) with err:%ld\n", GetLastError());
3156 TEST_GRANTED_ACCESS( handle, PROCESS_TERMINATE );
3158 ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
3159 &handle1, 0, TRUE, DUPLICATE_SAME_ACCESS );
3160 ok(ret, "duplicating handle err:%ld\n", GetLastError());
3161 TEST_GRANTED_ACCESS( handle1, PROCESS_TERMINATE );
3163 CloseHandle( handle1 );
3165 SetLastError( 0xdeadbeef );
3166 ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
3167 &handle1, PROCESS_ALL_ACCESS, TRUE, 0 );
3168 err = GetLastError();
3169 ok(!ret && err == ERROR_ACCESS_DENIED, "duplicating handle should have failed "
3170 "with STATUS_ACCESS_DENIED, instead of err:%ld\n", err);
3172 CloseHandle( handle );
3174 /* These two should fail - they are denied by ACL */
3175 handle = OpenProcess( PROCESS_VM_READ, FALSE, GetCurrentProcessId() );
3176 ok(handle == NULL, "OpenProcess(PROCESS_VM_READ) should have failed\n");
3177 handle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId() );
3178 ok(handle == NULL, "OpenProcess(PROCESS_ALL_ACCESS) should have failed\n");
3180 /* Documented privilege elevation */
3181 ret = DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
3182 &handle, 0, TRUE, DUPLICATE_SAME_ACCESS );
3183 ok(ret, "duplicating handle err:%ld\n", GetLastError());
3184 TEST_GRANTED_ACCESS2( handle, PROCESS_ALL_ACCESS_NT4,
3185 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
3187 CloseHandle( handle );
3189 /* Same only explicitly asking for all access rights */
3190 ret = DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
3191 &handle, PROCESS_ALL_ACCESS, TRUE, 0 );
3192 ok(ret, "duplicating handle err:%ld\n", GetLastError());
3193 TEST_GRANTED_ACCESS2( handle, PROCESS_ALL_ACCESS_NT4,
3194 PROCESS_ALL_ACCESS | PROCESS_QUERY_LIMITED_INFORMATION );
3195 ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
3196 &handle1, PROCESS_VM_READ, TRUE, 0 );
3197 ok(ret, "duplicating handle err:%ld\n", GetLastError());
3198 TEST_GRANTED_ACCESS( handle1, PROCESS_VM_READ );
3199 CloseHandle( handle1 );
3200 CloseHandle( handle );
3202 /* Test thread security */
3203 handle = OpenThread( THREAD_TERMINATE, FALSE, GetCurrentThreadId() );
3204 ok(handle != NULL, "OpenThread(THREAD_TERMINATE) with err:%ld\n", GetLastError());
3205 TEST_GRANTED_ACCESS( handle, PROCESS_TERMINATE );
3206 CloseHandle( handle );
3208 handle = OpenThread( THREAD_SET_THREAD_TOKEN, FALSE, GetCurrentThreadId() );
3209 ok(handle == NULL, "OpenThread(THREAD_SET_THREAD_TOKEN) should have failed\n");
3212 static void test_impersonation_level(void)
3214 HANDLE Token, ProcessToken;
3215 HANDLE Token2;
3216 DWORD Size;
3217 TOKEN_PRIVILEGES *Privileges;
3218 TOKEN_USER *User;
3219 PRIVILEGE_SET *PrivilegeSet;
3220 BOOL AccessGranted;
3221 BOOL ret;
3222 HKEY hkey;
3223 DWORD error;
3225 if( !pDuplicateTokenEx ) {
3226 win_skip("DuplicateTokenEx is not available\n");
3227 return;
3229 SetLastError(0xdeadbeef);
3230 ret = ImpersonateSelf(SecurityAnonymous);
3231 if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
3233 win_skip("ImpersonateSelf is not implemented\n");
3234 return;
3236 ok(ret, "ImpersonateSelf(SecurityAnonymous) failed with error %ld\n", GetLastError());
3237 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
3238 ok(!ret, "OpenThreadToken should have failed\n");
3239 error = GetLastError();
3240 ok(error == ERROR_CANT_OPEN_ANONYMOUS, "OpenThreadToken on anonymous token should have returned ERROR_CANT_OPEN_ANONYMOUS instead of %ld\n", error);
3241 /* can't perform access check when opening object against an anonymous impersonation token */
3242 todo_wine {
3243 error = RegOpenKeyExA(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
3244 ok(error == ERROR_INVALID_HANDLE || error == ERROR_CANT_OPEN_ANONYMOUS || error == ERROR_BAD_IMPERSONATION_LEVEL,
3245 "RegOpenKeyEx failed with %ld\n", error);
3247 RevertToSelf();
3249 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
3250 ok(ret, "OpenProcessToken failed with error %ld\n", GetLastError());
3252 ret = pDuplicateTokenEx(ProcessToken,
3253 TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE, NULL,
3254 SecurityAnonymous, TokenImpersonation, &Token);
3255 ok(ret, "DuplicateTokenEx failed with error %ld\n", GetLastError());
3256 /* can't increase the impersonation level */
3257 ret = DuplicateToken(Token, SecurityIdentification, &Token2);
3258 error = GetLastError();
3259 ok(!ret && error == ERROR_BAD_IMPERSONATION_LEVEL,
3260 "Duplicating a token and increasing the impersonation level should have failed with ERROR_BAD_IMPERSONATION_LEVEL instead of %ld\n", error);
3261 /* we can query anything from an anonymous token, including the user */
3262 ret = GetTokenInformation(Token, TokenUser, NULL, 0, &Size);
3263 error = GetLastError();
3264 ok(!ret && error == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenUser) should have failed with ERROR_INSUFFICIENT_BUFFER instead of %ld\n", error);
3265 User = malloc(Size);
3266 ret = GetTokenInformation(Token, TokenUser, User, Size, &Size);
3267 ok(ret, "GetTokenInformation(TokenUser) failed with error %ld\n", GetLastError());
3268 free(User);
3270 /* PrivilegeCheck fails with SecurityAnonymous level */
3271 ret = GetTokenInformation(Token, TokenPrivileges, NULL, 0, &Size);
3272 error = GetLastError();
3273 ok(!ret && error == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) should have failed with ERROR_INSUFFICIENT_BUFFER instead of %ld\n", error);
3274 Privileges = malloc(Size);
3275 ret = GetTokenInformation(Token, TokenPrivileges, Privileges, Size, &Size);
3276 ok(ret, "GetTokenInformation(TokenPrivileges) failed with error %ld\n", GetLastError());
3278 PrivilegeSet = malloc(FIELD_OFFSET(PRIVILEGE_SET, Privilege[Privileges->PrivilegeCount]));
3279 PrivilegeSet->PrivilegeCount = Privileges->PrivilegeCount;
3280 memcpy(PrivilegeSet->Privilege, Privileges->Privileges, PrivilegeSet->PrivilegeCount * sizeof(PrivilegeSet->Privilege[0]));
3281 PrivilegeSet->Control = PRIVILEGE_SET_ALL_NECESSARY;
3282 free(Privileges);
3284 ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
3285 error = GetLastError();
3286 ok(!ret && error == ERROR_BAD_IMPERSONATION_LEVEL, "PrivilegeCheck for SecurityAnonymous token should have failed with ERROR_BAD_IMPERSONATION_LEVEL instead of %ld\n", error);
3288 CloseHandle(Token);
3290 ret = ImpersonateSelf(SecurityIdentification);
3291 ok(ret, "ImpersonateSelf(SecurityIdentification) failed with error %ld\n", GetLastError());
3292 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
3293 ok(ret, "OpenThreadToken failed with error %ld\n", GetLastError());
3295 /* can't perform access check when opening object against an identification impersonation token */
3296 error = RegOpenKeyExA(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
3297 todo_wine {
3298 ok(error == ERROR_INVALID_HANDLE || error == ERROR_BAD_IMPERSONATION_LEVEL || error == ERROR_ACCESS_DENIED,
3299 "RegOpenKeyEx should have failed with ERROR_INVALID_HANDLE, ERROR_BAD_IMPERSONATION_LEVEL or ERROR_ACCESS_DENIED instead of %ld\n", error);
3301 ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
3302 ok(ret, "PrivilegeCheck for SecurityIdentification failed with error %ld\n", GetLastError());
3303 CloseHandle(Token);
3304 RevertToSelf();
3306 ret = ImpersonateSelf(SecurityImpersonation);
3307 ok(ret, "ImpersonateSelf(SecurityImpersonation) failed with error %ld\n", GetLastError());
3308 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
3309 ok(ret, "OpenThreadToken failed with error %ld\n", GetLastError());
3310 error = RegOpenKeyExA(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
3311 ok(error == ERROR_SUCCESS, "RegOpenKeyEx should have succeeded instead of failing with %ld\n", error);
3312 RegCloseKey(hkey);
3313 ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
3314 ok(ret, "PrivilegeCheck for SecurityImpersonation failed with error %ld\n", GetLastError());
3315 RevertToSelf();
3317 CloseHandle(Token);
3318 CloseHandle(ProcessToken);
3320 free(PrivilegeSet);
3323 static void test_SetEntriesInAclW(void)
3325 DWORD res;
3326 PSID EveryoneSid = NULL, UsersSid = NULL;
3327 PACL OldAcl = NULL, NewAcl;
3328 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
3329 SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
3330 EXPLICIT_ACCESSW ExplicitAccess;
3331 static const WCHAR wszEveryone[] = {'E','v','e','r','y','o','n','e',0};
3332 static const WCHAR wszCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'};
3334 if (!pSetEntriesInAclW)
3336 win_skip("SetEntriesInAclW is not available\n");
3337 return;
3340 NewAcl = (PACL)0xdeadbeef;
3341 res = pSetEntriesInAclW(0, NULL, NULL, &NewAcl);
3342 if(res == ERROR_CALL_NOT_IMPLEMENTED)
3344 win_skip("SetEntriesInAclW is not implemented\n");
3345 return;
3347 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %lu\n", res);
3348 ok(NewAcl == NULL ||
3349 broken(NewAcl != NULL), /* NT4 */
3350 "NewAcl=%p, expected NULL\n", NewAcl);
3351 LocalFree(NewAcl);
3353 OldAcl = malloc(256);
3354 res = InitializeAcl(OldAcl, 256, ACL_REVISION);
3355 if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
3357 win_skip("ACLs not implemented - skipping tests\n");
3358 free(OldAcl);
3359 return;
3361 ok(res, "InitializeAcl failed with error %ld\n", GetLastError());
3363 res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
3364 ok(res, "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
3366 res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
3367 DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid);
3368 ok(res, "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
3370 res = AddAccessAllowedAce(OldAcl, ACL_REVISION, KEY_READ, UsersSid);
3371 ok(res, "AddAccessAllowedAce failed with error %ld\n", GetLastError());
3373 ExplicitAccess.grfAccessPermissions = KEY_WRITE;
3374 ExplicitAccess.grfAccessMode = GRANT_ACCESS;
3375 ExplicitAccess.grfInheritance = NO_INHERITANCE;
3376 ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
3377 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
3378 ExplicitAccess.Trustee.ptstrName = EveryoneSid;
3379 ExplicitAccess.Trustee.MultipleTrusteeOperation = 0xDEADBEEF;
3380 ExplicitAccess.Trustee.pMultipleTrustee = (PVOID)0xDEADBEEF;
3381 res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3382 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %lu\n", res);
3383 ok(NewAcl != NULL, "returned acl was NULL\n");
3384 LocalFree(NewAcl);
3386 ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3387 ExplicitAccess.Trustee.pMultipleTrustee = NULL;
3388 ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3389 res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3390 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %lu\n", res);
3391 ok(NewAcl != NULL, "returned acl was NULL\n");
3392 LocalFree(NewAcl);
3394 if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH)
3396 skip("Non-English locale (test with hardcoded 'Everyone')\n");
3398 else
3400 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3401 ExplicitAccess.Trustee.ptstrName = (LPWSTR)wszEveryone;
3402 res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3403 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %lu\n", res);
3404 ok(NewAcl != NULL, "returned acl was NULL\n");
3405 LocalFree(NewAcl);
3407 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_BAD_FORM;
3408 res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3409 ok(res == ERROR_INVALID_PARAMETER ||
3410 broken(res == ERROR_NOT_SUPPORTED), /* NT4 */
3411 "SetEntriesInAclW failed: %lu\n", res);
3412 ok(NewAcl == NULL ||
3413 broken(NewAcl != NULL), /* NT4 */
3414 "returned acl wasn't NULL: %p\n", NewAcl);
3416 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3417 ExplicitAccess.Trustee.MultipleTrusteeOperation = TRUSTEE_IS_IMPERSONATE;
3418 res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3419 ok(res == ERROR_INVALID_PARAMETER ||
3420 broken(res == ERROR_NOT_SUPPORTED), /* NT4 */
3421 "SetEntriesInAclW failed: %lu\n", res);
3422 ok(NewAcl == NULL ||
3423 broken(NewAcl != NULL), /* NT4 */
3424 "returned acl wasn't NULL: %p\n", NewAcl);
3426 ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3427 ExplicitAccess.grfAccessMode = SET_ACCESS;
3428 res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3429 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %lu\n", res);
3430 ok(NewAcl != NULL, "returned acl was NULL\n");
3431 LocalFree(NewAcl);
3434 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3435 ExplicitAccess.Trustee.ptstrName = (LPWSTR)wszCurrentUser;
3436 res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3437 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %lu\n", res);
3438 ok(NewAcl != NULL, "returned acl was NULL\n");
3439 LocalFree(NewAcl);
3441 ExplicitAccess.grfAccessMode = REVOKE_ACCESS;
3442 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
3443 ExplicitAccess.Trustee.ptstrName = UsersSid;
3444 res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3445 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %lu\n", res);
3446 ok(NewAcl != NULL, "returned acl was NULL\n");
3447 LocalFree(NewAcl);
3449 FreeSid(UsersSid);
3450 FreeSid(EveryoneSid);
3451 free(OldAcl);
3454 static void test_SetEntriesInAclA(void)
3456 DWORD res;
3457 PSID EveryoneSid = NULL, UsersSid = NULL;
3458 PACL OldAcl = NULL, NewAcl;
3459 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
3460 SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
3461 EXPLICIT_ACCESSA ExplicitAccess;
3462 static const CHAR szEveryone[] = {'E','v','e','r','y','o','n','e',0};
3463 static const CHAR szCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'};
3465 NewAcl = (PACL)0xdeadbeef;
3466 res = SetEntriesInAclA(0, NULL, NULL, &NewAcl);
3467 if(res == ERROR_CALL_NOT_IMPLEMENTED)
3469 win_skip("SetEntriesInAclA is not implemented\n");
3470 return;
3472 ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %lu\n", res);
3473 ok(NewAcl == NULL ||
3474 broken(NewAcl != NULL), /* NT4 */
3475 "NewAcl=%p, expected NULL\n", NewAcl);
3476 LocalFree(NewAcl);
3478 OldAcl = malloc(256);
3479 res = InitializeAcl(OldAcl, 256, ACL_REVISION);
3480 if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
3482 win_skip("ACLs not implemented - skipping tests\n");
3483 free(OldAcl);
3484 return;
3486 ok(res, "InitializeAcl failed with error %ld\n", GetLastError());
3488 res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
3489 ok(res, "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
3491 res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
3492 DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid);
3493 ok(res, "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
3495 res = AddAccessAllowedAce(OldAcl, ACL_REVISION, KEY_READ, UsersSid);
3496 ok(res, "AddAccessAllowedAce failed with error %ld\n", GetLastError());
3498 ExplicitAccess.grfAccessPermissions = KEY_WRITE;
3499 ExplicitAccess.grfAccessMode = GRANT_ACCESS;
3500 ExplicitAccess.grfInheritance = NO_INHERITANCE;
3501 ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
3502 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
3503 ExplicitAccess.Trustee.ptstrName = EveryoneSid;
3504 ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3505 ExplicitAccess.Trustee.pMultipleTrustee = NULL;
3506 res = SetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3507 ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %lu\n", res);
3508 ok(NewAcl != NULL, "returned acl was NULL\n");
3509 LocalFree(NewAcl);
3511 ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3512 ExplicitAccess.Trustee.pMultipleTrustee = NULL;
3513 ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3514 res = SetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3515 ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %lu\n", res);
3516 ok(NewAcl != NULL, "returned acl was NULL\n");
3517 LocalFree(NewAcl);
3519 if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH)
3521 skip("Non-English locale (test with hardcoded 'Everyone')\n");
3523 else
3525 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3526 ExplicitAccess.Trustee.ptstrName = (LPSTR)szEveryone;
3527 res = SetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3528 ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %lu\n", res);
3529 ok(NewAcl != NULL, "returned acl was NULL\n");
3530 LocalFree(NewAcl);
3532 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_BAD_FORM;
3533 res = SetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3534 ok(res == ERROR_INVALID_PARAMETER ||
3535 broken(res == ERROR_NOT_SUPPORTED), /* NT4 */
3536 "SetEntriesInAclA failed: %lu\n", res);
3537 ok(NewAcl == NULL ||
3538 broken(NewAcl != NULL), /* NT4 */
3539 "returned acl wasn't NULL: %p\n", NewAcl);
3541 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3542 ExplicitAccess.Trustee.MultipleTrusteeOperation = TRUSTEE_IS_IMPERSONATE;
3543 res = SetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3544 ok(res == ERROR_INVALID_PARAMETER ||
3545 broken(res == ERROR_NOT_SUPPORTED), /* NT4 */
3546 "SetEntriesInAclA failed: %lu\n", res);
3547 ok(NewAcl == NULL ||
3548 broken(NewAcl != NULL), /* NT4 */
3549 "returned acl wasn't NULL: %p\n", NewAcl);
3551 ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3552 ExplicitAccess.grfAccessMode = SET_ACCESS;
3553 res = SetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3554 ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %lu\n", res);
3555 ok(NewAcl != NULL, "returned acl was NULL\n");
3556 LocalFree(NewAcl);
3559 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3560 ExplicitAccess.Trustee.ptstrName = (LPSTR)szCurrentUser;
3561 res = SetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3562 ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %lu\n", res);
3563 ok(NewAcl != NULL, "returned acl was NULL\n");
3564 LocalFree(NewAcl);
3566 ExplicitAccess.grfAccessMode = REVOKE_ACCESS;
3567 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
3568 ExplicitAccess.Trustee.ptstrName = UsersSid;
3569 res = SetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3570 ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %lu\n", res);
3571 ok(NewAcl != NULL, "returned acl was NULL\n");
3572 LocalFree(NewAcl);
3574 FreeSid(UsersSid);
3575 FreeSid(EveryoneSid);
3576 free(OldAcl);
3579 /* helper function for test_CreateDirectoryA */
3580 static void get_nt_pathW(const char *name, UNICODE_STRING *nameW)
3582 UNICODE_STRING strW;
3583 ANSI_STRING str;
3584 NTSTATUS status;
3585 BOOLEAN ret;
3587 pRtlInitAnsiString(&str, name);
3589 status = pRtlAnsiStringToUnicodeString(&strW, &str, TRUE);
3590 ok(!status, "RtlAnsiStringToUnicodeString failed with %08lx\n", status);
3592 ret = pRtlDosPathNameToNtPathName_U(strW.Buffer, nameW, NULL, NULL);
3593 ok(ret, "RtlDosPathNameToNtPathName_U failed\n");
3595 pRtlFreeUnicodeString(&strW);
3598 static void test_inherited_dacl(PACL dacl, PSID admin_sid, PSID user_sid, DWORD flags, DWORD mask,
3599 BOOL todo_count, BOOL todo_sid, BOOL todo_flags, int line)
3601 ACL_SIZE_INFORMATION acl_size;
3602 ACCESS_ALLOWED_ACE *ace;
3603 BOOL bret;
3605 bret = GetAclInformation(dacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3606 ok_(__FILE__, line)(bret, "GetAclInformation failed\n");
3608 todo_wine_if (todo_count)
3609 ok_(__FILE__, line)(acl_size.AceCount == 2,
3610 "GetAclInformation returned unexpected entry count (%ld != 2)\n",
3611 acl_size.AceCount);
3613 if (acl_size.AceCount > 0)
3615 bret = GetAce(dacl, 0, (VOID **)&ace);
3616 ok_(__FILE__, line)(bret, "Failed to get Current User ACE\n");
3618 bret = EqualSid(&ace->SidStart, user_sid);
3619 todo_wine_if (todo_sid)
3620 ok_(__FILE__, line)(bret, "Current User ACE (%s) != Current User SID (%s)\n", debugstr_sid(&ace->SidStart), debugstr_sid(user_sid));
3622 todo_wine_if (todo_flags)
3623 ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags,
3624 "Current User ACE has unexpected flags (0x%x != 0x%lx)\n",
3625 ((ACE_HEADER *)ace)->AceFlags, flags);
3627 ok_(__FILE__, line)(ace->Mask == mask,
3628 "Current User ACE has unexpected mask (0x%lx != 0x%lx)\n",
3629 ace->Mask, mask);
3631 if (acl_size.AceCount > 1)
3633 bret = GetAce(dacl, 1, (VOID **)&ace);
3634 ok_(__FILE__, line)(bret, "Failed to get Administators Group ACE\n");
3636 bret = EqualSid(&ace->SidStart, admin_sid);
3637 todo_wine_if (todo_sid)
3638 ok_(__FILE__, line)(bret, "Administators Group ACE (%s) != Administators Group SID (%s)\n", debugstr_sid(&ace->SidStart), debugstr_sid(admin_sid));
3640 todo_wine_if (todo_flags)
3641 ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags,
3642 "Administators Group ACE has unexpected flags (0x%x != 0x%lx)\n",
3643 ((ACE_HEADER *)ace)->AceFlags, flags);
3645 ok_(__FILE__, line)(ace->Mask == mask,
3646 "Administators Group ACE has unexpected mask (0x%lx != 0x%lx)\n",
3647 ace->Mask, mask);
3651 static void test_CreateDirectoryA(void)
3653 char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], *user;
3654 DWORD sid_size = sizeof(admin_ptr), user_size;
3655 PSID admin_sid = (PSID) admin_ptr, user_sid;
3656 char sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
3657 PSECURITY_DESCRIPTOR pSD = &sd;
3658 ACL_SIZE_INFORMATION acl_size;
3659 UNICODE_STRING tmpfileW;
3660 SECURITY_ATTRIBUTES sa;
3661 OBJECT_ATTRIBUTES attr;
3662 char tmpfile[MAX_PATH];
3663 char tmpdir[MAX_PATH];
3664 HANDLE token, hTemp;
3665 IO_STATUS_BLOCK io;
3666 struct _SID *owner;
3667 BOOL bret = TRUE;
3668 NTSTATUS status;
3669 DWORD error;
3670 PACL pDacl;
3672 if (!pGetNamedSecurityInfoA)
3674 win_skip("Required functions are not available\n");
3675 return;
3678 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
3680 if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE;
3681 else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE;
3683 if (!bret)
3685 win_skip("Failed to get current user token\n");
3686 return;
3688 bret = GetTokenInformation(token, TokenUser, NULL, 0, &user_size);
3689 ok(!bret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
3690 "GetTokenInformation(TokenUser) failed with error %ld\n", GetLastError());
3691 user = malloc(user_size);
3692 bret = GetTokenInformation(token, TokenUser, user, user_size, &user_size);
3693 ok(bret, "GetTokenInformation(TokenUser) failed with error %ld\n", GetLastError());
3694 CloseHandle( token );
3695 user_sid = ((TOKEN_USER *)user)->User.Sid;
3697 sa.nLength = sizeof(sa);
3698 sa.lpSecurityDescriptor = pSD;
3699 sa.bInheritHandle = TRUE;
3700 InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
3701 CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size);
3702 pDacl = calloc(1, 100);
3703 bret = InitializeAcl(pDacl, 100, ACL_REVISION);
3704 ok(bret, "Failed to initialize ACL.\n");
3705 bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
3706 GENERIC_ALL, user_sid);
3707 ok(bret, "Failed to add Current User to ACL.\n");
3708 bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
3709 GENERIC_ALL, admin_sid);
3710 ok(bret, "Failed to add Administrator Group to ACL.\n");
3711 bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
3712 ok(bret, "Failed to add ACL to security descriptor.\n");
3714 GetTempPathA(MAX_PATH, tmpdir);
3715 lstrcatA(tmpdir, "Please Remove Me");
3716 bret = CreateDirectoryA(tmpdir, &sa);
3717 ok(bret == TRUE, "CreateDirectoryA(%s) failed err=%ld\n", tmpdir, GetLastError());
3718 free(pDacl);
3720 SetLastError(0xdeadbeef);
3721 error = pGetNamedSecurityInfoA(tmpdir, SE_FILE_OBJECT,
3722 OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, (PSID*)&owner,
3723 NULL, &pDacl, NULL, &pSD);
3724 if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
3726 win_skip("GetNamedSecurityInfoA is not implemented\n");
3727 goto done;
3729 ok(!error, "GetNamedSecurityInfo failed with error %ld\n", error);
3730 test_inherited_dacl(pDacl, admin_sid, user_sid, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
3731 0x1f01ff, FALSE, TRUE, FALSE, __LINE__);
3732 LocalFree(pSD);
3734 /* Test inheritance of ACLs in CreateFile without security descriptor */
3735 strcpy(tmpfile, tmpdir);
3736 lstrcatA(tmpfile, "/tmpfile");
3738 hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
3739 CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, NULL);
3740 ok(hTemp != INVALID_HANDLE_VALUE, "CreateFile error %lu\n", GetLastError());
3742 error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
3743 OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3744 (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3745 ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
3746 test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
3747 0x1f01ff, TRUE, TRUE, TRUE, __LINE__);
3748 LocalFree(pSD);
3749 CloseHandle(hTemp);
3751 /* Test inheritance of ACLs in CreateFile with security descriptor -
3752 * When a security descriptor is set, then inheritance doesn't take effect */
3753 pSD = &sd;
3754 InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
3755 pDacl = malloc(sizeof(ACL));
3756 bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
3757 ok(bret, "Failed to initialize ACL\n");
3758 bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
3759 ok(bret, "Failed to add ACL to security descriptor\n");
3761 strcpy(tmpfile, tmpdir);
3762 lstrcatA(tmpfile, "/tmpfile");
3764 sa.nLength = sizeof(sa);
3765 sa.lpSecurityDescriptor = pSD;
3766 sa.bInheritHandle = TRUE;
3767 hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, &sa,
3768 CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, NULL);
3769 ok(hTemp != INVALID_HANDLE_VALUE, "CreateFile error %lu\n", GetLastError());
3770 free(pDacl);
3772 error = GetSecurityInfo(hTemp, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3773 (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3774 ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %ld\n", error);
3775 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3776 ok(bret, "GetAclInformation failed\n");
3777 todo_wine
3778 ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%ld != 0).\n",
3779 acl_size.AceCount);
3780 LocalFree(pSD);
3782 error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
3783 OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3784 (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3785 todo_wine
3786 ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %ld\n", error);
3787 if (error == ERROR_SUCCESS)
3789 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3790 ok(bret, "GetAclInformation failed\n");
3791 todo_wine
3792 ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%ld != 0).\n",
3793 acl_size.AceCount);
3794 LocalFree(pSD);
3796 CloseHandle(hTemp);
3798 /* Test inheritance of ACLs in NtCreateFile without security descriptor */
3799 strcpy(tmpfile, tmpdir);
3800 lstrcatA(tmpfile, "/tmpfile");
3801 get_nt_pathW(tmpfile, &tmpfileW);
3803 attr.Length = sizeof(attr);
3804 attr.RootDirectory = 0;
3805 attr.ObjectName = &tmpfileW;
3806 attr.Attributes = OBJ_CASE_INSENSITIVE;
3807 attr.SecurityDescriptor = NULL;
3808 attr.SecurityQualityOfService = NULL;
3810 status = pNtCreateFile(&hTemp, GENERIC_WRITE | DELETE, &attr, &io, NULL, 0,
3811 FILE_SHARE_READ, FILE_CREATE, FILE_DELETE_ON_CLOSE, NULL, 0);
3812 ok(!status, "NtCreateFile failed with %08lx\n", status);
3813 pRtlFreeUnicodeString(&tmpfileW);
3815 error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
3816 OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3817 (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3818 ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
3819 test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
3820 0x1f01ff, TRUE, TRUE, TRUE, __LINE__);
3821 LocalFree(pSD);
3822 CloseHandle(hTemp);
3824 /* Test inheritance of ACLs in NtCreateFile with security descriptor -
3825 * When a security descriptor is set, then inheritance doesn't take effect */
3826 pSD = &sd;
3827 InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
3828 pDacl = malloc(sizeof(ACL));
3829 bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
3830 ok(bret, "Failed to initialize ACL\n");
3831 bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
3832 ok(bret, "Failed to add ACL to security descriptor\n");
3834 strcpy(tmpfile, tmpdir);
3835 lstrcatA(tmpfile, "/tmpfile");
3836 get_nt_pathW(tmpfile, &tmpfileW);
3838 attr.Length = sizeof(attr);
3839 attr.RootDirectory = 0;
3840 attr.ObjectName = &tmpfileW;
3841 attr.Attributes = OBJ_CASE_INSENSITIVE;
3842 attr.SecurityDescriptor = pSD;
3843 attr.SecurityQualityOfService = NULL;
3845 status = pNtCreateFile(&hTemp, GENERIC_WRITE | DELETE, &attr, &io, NULL, 0,
3846 FILE_SHARE_READ, FILE_CREATE, FILE_DELETE_ON_CLOSE, NULL, 0);
3847 ok(!status, "NtCreateFile failed with %08lx\n", status);
3848 pRtlFreeUnicodeString(&tmpfileW);
3849 free(pDacl);
3851 error = GetSecurityInfo(hTemp, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3852 (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3853 ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %ld\n", error);
3854 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3855 ok(bret, "GetAclInformation failed\n");
3856 todo_wine
3857 ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%ld != 0).\n",
3858 acl_size.AceCount);
3859 LocalFree(pSD);
3861 error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
3862 OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3863 (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3864 todo_wine
3865 ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %ld\n", error);
3866 if (error == ERROR_SUCCESS)
3868 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3869 ok(bret, "GetAclInformation failed\n");
3870 todo_wine
3871 ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%ld != 0).\n",
3872 acl_size.AceCount);
3873 LocalFree(pSD);
3875 CloseHandle(hTemp);
3877 done:
3878 free(user);
3879 bret = RemoveDirectoryA(tmpdir);
3880 ok(bret == TRUE, "RemoveDirectoryA should always succeed\n");
3883 static void test_GetNamedSecurityInfoA(void)
3885 char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], *user;
3886 char system_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES];
3887 char users_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES];
3888 SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
3889 PSID admin_sid = (PSID) admin_ptr, users_sid = (PSID) users_ptr;
3890 PSID system_sid = (PSID) system_ptr, user_sid, localsys_sid;
3891 DWORD sid_size = sizeof(admin_ptr), user_size;
3892 char invalid_path[] = "/an invalid file path";
3893 int users_ace_id = -1, admins_ace_id = -1, i;
3894 char software_key[] = "MACHINE\\Software";
3895 char sd[SECURITY_DESCRIPTOR_MIN_LENGTH+sizeof(void*)];
3896 SECURITY_DESCRIPTOR_CONTROL control;
3897 ACL_SIZE_INFORMATION acl_size;
3898 CHAR windows_dir[MAX_PATH];
3899 PSECURITY_DESCRIPTOR pSD;
3900 ACCESS_ALLOWED_ACE *ace;
3901 BOOL bret = TRUE, isNT4;
3902 char tmpfile[MAX_PATH];
3903 DWORD error, revision;
3904 BOOL owner_defaulted;
3905 BOOL group_defaulted;
3906 BOOL dacl_defaulted;
3907 HANDLE token, hTemp, h;
3908 PSID owner, group;
3909 BOOL dacl_present;
3910 PACL pDacl;
3911 BYTE flags;
3912 NTSTATUS status;
3914 if (!pSetNamedSecurityInfoA || !pGetNamedSecurityInfoA)
3916 win_skip("Required functions are not available\n");
3917 return;
3920 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
3922 if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE;
3923 else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE;
3925 if (!bret)
3927 win_skip("Failed to get current user token\n");
3928 return;
3930 bret = GetTokenInformation(token, TokenUser, NULL, 0, &user_size);
3931 ok(!bret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
3932 "GetTokenInformation(TokenUser) failed with error %ld\n", GetLastError());
3933 user = malloc(user_size);
3934 bret = GetTokenInformation(token, TokenUser, user, user_size, &user_size);
3935 ok(bret, "GetTokenInformation(TokenUser) failed with error %ld\n", GetLastError());
3936 CloseHandle( token );
3937 user_sid = ((TOKEN_USER *)user)->User.Sid;
3939 bret = GetWindowsDirectoryA(windows_dir, MAX_PATH);
3940 ok(bret, "GetWindowsDirectory failed with error %ld\n", GetLastError());
3942 SetLastError(0xdeadbeef);
3943 error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,
3944 OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
3945 NULL, NULL, NULL, NULL, &pSD);
3946 if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
3948 win_skip("GetNamedSecurityInfoA is not implemented\n");
3949 free(user);
3950 return;
3952 ok(!error, "GetNamedSecurityInfo failed with error %ld\n", error);
3954 bret = GetSecurityDescriptorControl(pSD, &control, &revision);
3955 ok(bret, "GetSecurityDescriptorControl failed with error %ld\n", GetLastError());
3956 ok((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == (SE_SELF_RELATIVE|SE_DACL_PRESENT) ||
3957 broken((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT), /* NT4 */
3958 "control (0x%x) doesn't have (SE_SELF_RELATIVE|SE_DACL_PRESENT) flags set\n", control);
3959 ok(revision == SECURITY_DESCRIPTOR_REVISION1, "revision was %ld instead of 1\n", revision);
3961 isNT4 = (control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT;
3963 bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted);
3964 ok(bret, "GetSecurityDescriptorOwner failed with error %ld\n", GetLastError());
3965 ok(owner != NULL, "owner should not be NULL\n");
3967 bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted);
3968 ok(bret, "GetSecurityDescriptorGroup failed with error %ld\n", GetLastError());
3969 ok(group != NULL, "group should not be NULL\n");
3970 LocalFree(pSD);
3973 /* NULL descriptor tests */
3974 if(isNT4)
3976 win_skip("NT4 does not support GetNamedSecutityInfo with a NULL descriptor\n");
3977 free(user);
3978 return;
3981 error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,
3982 NULL, NULL, NULL, NULL, NULL);
3983 ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %ld\n", error);
3985 pDacl = NULL;
3986 error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,
3987 NULL, NULL, &pDacl, NULL, &pSD);
3988 ok(!error, "GetNamedSecurityInfo failed with error %ld\n", error);
3989 ok(pDacl != NULL, "DACL should not be NULL\n");
3990 LocalFree(pSD);
3992 error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,OWNER_SECURITY_INFORMATION,
3993 NULL, NULL, &pDacl, NULL, NULL);
3994 ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %ld\n", error);
3996 /* Test behavior of SetNamedSecurityInfo with an invalid path */
3997 SetLastError(0xdeadbeef);
3998 error = pSetNamedSecurityInfoA(invalid_path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL,
3999 NULL, NULL, NULL);
4000 ok(error == ERROR_FILE_NOT_FOUND, "Unexpected error returned: 0x%lx\n", error);
4001 ok(GetLastError() == 0xdeadbeef, "Expected last error to remain unchanged.\n");
4003 /* Create security descriptor information and test that it comes back the same */
4004 pSD = &sd;
4005 pDacl = malloc(100);
4006 InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
4007 CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size);
4008 bret = InitializeAcl(pDacl, 100, ACL_REVISION);
4009 ok(bret, "Failed to initialize ACL.\n");
4010 bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
4011 ok(bret, "Failed to add Current User to ACL.\n");
4012 bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, admin_sid);
4013 ok(bret, "Failed to add Administrator Group to ACL.\n");
4014 bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
4015 ok(bret, "Failed to add ACL to security descriptor.\n");
4016 GetTempFileNameA(".", "foo", 0, tmpfile);
4017 hTemp = CreateFileA(tmpfile, WRITE_DAC|GENERIC_WRITE, FILE_SHARE_DELETE|FILE_SHARE_READ,
4018 NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
4019 SetLastError(0xdeadbeef);
4020 error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL,
4021 NULL, pDacl, NULL);
4022 free(pDacl);
4023 if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
4025 win_skip("SetNamedSecurityInfoA is not implemented\n");
4026 free(user);
4027 CloseHandle(hTemp);
4028 return;
4030 ok(!error, "SetNamedSecurityInfoA failed with error %ld\n", error);
4031 SetLastError(0xdeadbeef);
4032 error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
4033 NULL, NULL, &pDacl, NULL, &pSD);
4034 if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
4036 win_skip("GetNamedSecurityInfoA is not implemented\n");
4037 free(user);
4038 CloseHandle(hTemp);
4039 return;
4041 ok(!error, "GetNamedSecurityInfo failed with error %ld\n", error);
4043 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
4044 ok(bret, "GetAclInformation failed\n");
4045 if (acl_size.AceCount > 0)
4047 bret = GetAce(pDacl, 0, (VOID **)&ace);
4048 ok(bret, "Failed to get Current User ACE.\n");
4049 bret = EqualSid(&ace->SidStart, user_sid);
4050 todo_wine ok(bret, "Current User ACE (%s) != Current User SID (%s).\n",
4051 debugstr_sid(&ace->SidStart), debugstr_sid(user_sid));
4052 ok(((ACE_HEADER *)ace)->AceFlags == 0,
4053 "Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
4054 ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%lx != 0x1f01ff)\n",
4055 ace->Mask);
4057 if (acl_size.AceCount > 1)
4059 bret = GetAce(pDacl, 1, (VOID **)&ace);
4060 ok(bret, "Failed to get Administators Group ACE.\n");
4061 bret = EqualSid(&ace->SidStart, admin_sid);
4062 todo_wine ok(bret || broken(!bret) /* win2k */,
4063 "Administators Group ACE (%s) != Administators Group SID (%s).\n",
4064 debugstr_sid(&ace->SidStart), debugstr_sid(admin_sid));
4065 ok(((ACE_HEADER *)ace)->AceFlags == 0,
4066 "Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
4067 ok(ace->Mask == 0x1f01ff || broken(ace->Mask == GENERIC_ALL) /* win2k */,
4068 "Administators Group ACE has unexpected mask (0x%lx != 0x1f01ff)\n", ace->Mask);
4070 LocalFree(pSD);
4072 /* show that setting empty DACL is not removing all file permissions */
4073 pDacl = malloc(sizeof(ACL));
4074 bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
4075 ok(bret, "Failed to initialize ACL.\n");
4076 error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
4077 NULL, NULL, pDacl, NULL);
4078 ok(!error, "SetNamedSecurityInfoA failed with error %ld\n", error);
4079 free(pDacl);
4081 error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
4082 NULL, NULL, &pDacl, NULL, &pSD);
4083 ok(!error, "GetNamedSecurityInfo failed with error %ld\n", error);
4085 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
4086 ok(bret, "GetAclInformation failed\n");
4087 if (acl_size.AceCount > 0)
4089 bret = GetAce(pDacl, 0, (VOID **)&ace);
4090 ok(bret, "Failed to get ACE.\n");
4091 todo_wine ok(((ACE_HEADER *)ace)->AceFlags & INHERITED_ACE,
4092 "ACE has unexpected flags: 0x%x\n", ((ACE_HEADER *)ace)->AceFlags);
4094 LocalFree(pSD);
4096 h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4097 NULL, OPEN_EXISTING, 0, NULL);
4098 ok(h != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
4099 CloseHandle(h);
4101 /* test setting NULL DACL */
4102 error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
4103 DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL);
4104 ok(!error, "SetNamedSecurityInfoA failed with error %ld\n", error);
4106 error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
4107 NULL, NULL, &pDacl, NULL, &pSD);
4108 ok(!error, "GetNamedSecurityInfo failed with error %ld\n", error);
4109 todo_wine ok(!pDacl, "pDacl != NULL\n");
4110 LocalFree(pSD);
4112 h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4113 NULL, OPEN_EXISTING, 0, NULL);
4114 ok(h != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
4115 CloseHandle(h);
4117 /* NtSetSecurityObject doesn't inherit DACL entries */
4118 pSD = sd+sizeof(void*)-((ULONG_PTR)sd)%sizeof(void*);
4119 InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
4120 pDacl = malloc(100);
4121 bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
4122 ok(bret, "Failed to initialize ACL.\n");
4123 bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
4124 ok(bret, "Failed to add ACL to security descriptor.\n");
4125 status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
4126 ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %lx\n", status);
4128 h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4129 NULL, OPEN_EXISTING, 0, NULL);
4130 ok(h == INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
4131 CloseHandle(h);
4133 pSetSecurityDescriptorControl(pSD, SE_DACL_AUTO_INHERIT_REQ, SE_DACL_AUTO_INHERIT_REQ);
4134 status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
4135 ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %lx\n", status);
4137 h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4138 NULL, OPEN_EXISTING, 0, NULL);
4139 ok(h == INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
4140 CloseHandle(h);
4142 pSetSecurityDescriptorControl(pSD, SE_DACL_AUTO_INHERIT_REQ|SE_DACL_AUTO_INHERITED,
4143 SE_DACL_AUTO_INHERIT_REQ|SE_DACL_AUTO_INHERITED);
4144 status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
4145 ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %lx\n", status);
4147 h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4148 NULL, OPEN_EXISTING, 0, NULL);
4149 ok(h == INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
4150 CloseHandle(h);
4152 /* test if DACL is properly mapped to permission */
4153 bret = InitializeAcl(pDacl, 100, ACL_REVISION);
4154 ok(bret, "Failed to initialize ACL.\n");
4155 bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
4156 ok(bret, "Failed to add Current User to ACL.\n");
4157 bret = pAddAccessDeniedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
4158 ok(bret, "Failed to add Current User to ACL.\n");
4159 bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
4160 ok(bret, "Failed to add ACL to security descriptor.\n");
4161 status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
4162 ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %lx\n", status);
4164 h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4165 NULL, OPEN_EXISTING, 0, NULL);
4166 ok(h != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
4167 CloseHandle(h);
4169 bret = InitializeAcl(pDacl, 100, ACL_REVISION);
4170 ok(bret, "Failed to initialize ACL.\n");
4171 bret = pAddAccessDeniedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
4172 ok(bret, "Failed to add Current User to ACL.\n");
4173 bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
4174 ok(bret, "Failed to add Current User to ACL.\n");
4175 bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
4176 ok(bret, "Failed to add ACL to security descriptor.\n");
4177 status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
4178 ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %lx\n", status);
4180 h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4181 NULL, OPEN_EXISTING, 0, NULL);
4182 ok(h == INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
4183 free(pDacl);
4184 free(user);
4185 CloseHandle(hTemp);
4187 /* Test querying the ownership of a built-in registry key */
4188 sid_size = sizeof(system_ptr);
4189 CreateWellKnownSid(WinLocalSystemSid, NULL, system_sid, &sid_size);
4190 error = pGetNamedSecurityInfoA(software_key, SE_REGISTRY_KEY,
4191 OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION,
4192 NULL, NULL, NULL, NULL, &pSD);
4193 ok(!error, "GetNamedSecurityInfo failed with error %ld\n", error);
4195 bret = AllocateAndInitializeSid(&SIDAuthNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &localsys_sid);
4196 ok(bret, "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
4198 bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted);
4199 ok(bret, "GetSecurityDescriptorOwner failed with error %ld\n", GetLastError());
4200 ok(owner != NULL, "owner should not be NULL\n");
4201 ok(EqualSid(owner, admin_sid) || EqualSid(owner, localsys_sid),
4202 "MACHINE\\Software owner SID (%s) != Administrators SID (%s) or Local System Sid (%s).\n",
4203 debugstr_sid(owner), debugstr_sid(admin_sid), debugstr_sid(localsys_sid));
4205 bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted);
4206 ok(bret, "GetSecurityDescriptorGroup failed with error %ld\n", GetLastError());
4207 ok(group != NULL, "group should not be NULL\n");
4208 ok(EqualSid(group, admin_sid) || broken(EqualSid(group, system_sid)) /* before Win7 */
4209 || broken(((SID*)group)->SubAuthority[0] == SECURITY_NT_NON_UNIQUE) /* Vista */,
4210 "MACHINE\\Software group SID (%s) != Local System SID (%s or %s)\n",
4211 debugstr_sid(group), debugstr_sid(admin_sid), debugstr_sid(system_sid));
4212 LocalFree(pSD);
4214 /* Test querying the DACL of a built-in registry key */
4215 sid_size = sizeof(users_ptr);
4216 CreateWellKnownSid(WinBuiltinUsersSid, NULL, users_sid, &sid_size);
4217 error = pGetNamedSecurityInfoA(software_key, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION,
4218 NULL, NULL, NULL, NULL, &pSD);
4219 ok(!error, "GetNamedSecurityInfo failed with error %ld\n", error);
4221 bret = GetSecurityDescriptorDacl(pSD, &dacl_present, &pDacl, &dacl_defaulted);
4222 ok(bret, "GetSecurityDescriptorDacl failed with error %ld\n", GetLastError());
4223 ok(dacl_present, "DACL should be present\n");
4224 ok(pDacl && IsValidAcl(pDacl), "GetSecurityDescriptorDacl returned invalid DACL.\n");
4225 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
4226 ok(bret, "GetAclInformation failed\n");
4227 ok(acl_size.AceCount != 0, "GetAclInformation returned no ACLs\n");
4228 for (i=0; i<acl_size.AceCount; i++)
4230 bret = GetAce(pDacl, i, (VOID **)&ace);
4231 ok(bret, "Failed to get ACE %d.\n", i);
4232 bret = EqualSid(&ace->SidStart, users_sid);
4233 if (bret) users_ace_id = i;
4234 bret = EqualSid(&ace->SidStart, admin_sid);
4235 if (bret) admins_ace_id = i;
4237 ok(users_ace_id != -1 || broken(users_ace_id == -1) /* win2k */,
4238 "Builtin Users ACE not found.\n");
4239 if (users_ace_id != -1)
4241 bret = GetAce(pDacl, users_ace_id, (VOID **)&ace);
4242 ok(bret, "Failed to get Builtin Users ACE.\n");
4243 flags = ((ACE_HEADER *)ace)->AceFlags;
4244 ok(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE)
4245 || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* w2k8 */
4246 || broken(flags == (CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* win 10 wow64 */
4247 || broken(flags == CONTAINER_INHERIT_ACE), /* win 10 */
4248 "Builtin Users ACE has unexpected flags (0x%x != 0x%x)\n", flags,
4249 INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE);
4250 ok(ace->Mask == GENERIC_READ
4251 || broken(ace->Mask == KEY_READ), /* win 10 */
4252 "Builtin Users ACE has unexpected mask (0x%lx != 0x%x)\n",
4253 ace->Mask, GENERIC_READ);
4255 ok(admins_ace_id != -1, "Builtin Admins ACE not found.\n");
4256 if (admins_ace_id != -1)
4258 bret = GetAce(pDacl, admins_ace_id, (VOID **)&ace);
4259 ok(bret, "Failed to get Builtin Admins ACE.\n");
4260 flags = ((ACE_HEADER *)ace)->AceFlags;
4261 ok(flags == 0x0
4262 || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* w2k8 */
4263 || broken(flags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)) /* win7 */
4264 || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE)) /* win8+ */
4265 || broken(flags == (CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* win 10 wow64 */
4266 || broken(flags == CONTAINER_INHERIT_ACE), /* win 10 */
4267 "Builtin Admins ACE has unexpected flags (0x%x != 0x0)\n", flags);
4268 ok(ace->Mask == KEY_ALL_ACCESS || broken(ace->Mask == GENERIC_ALL) /* w2k8 */,
4269 "Builtin Admins ACE has unexpected mask (0x%lx != 0x%x)\n", ace->Mask, KEY_ALL_ACCESS);
4272 FreeSid(localsys_sid);
4273 LocalFree(pSD);
4276 static void test_ConvertStringSecurityDescriptor(void)
4278 BOOL ret;
4279 PSECURITY_DESCRIPTOR pSD;
4280 static const WCHAR Blank[] = { 0 };
4281 unsigned int i;
4282 ULONG size;
4283 ACL *acl;
4284 static const struct
4286 const char *sidstring;
4287 DWORD revision;
4288 BOOL ret;
4289 DWORD GLE;
4290 DWORD altGLE;
4291 DWORD ace_Mask;
4292 } cssd[] =
4294 { "D:(A;;GA;;;WD)", 0xdeadbeef, FALSE, ERROR_UNKNOWN_REVISION },
4295 /* test ACE string type */
4296 { "D:(A;;GA;;;WD)", SDDL_REVISION_1, TRUE },
4297 { "D:(D;;GA;;;WD)", SDDL_REVISION_1, TRUE },
4298 { "ERROR:(D;;GA;;;WD)", SDDL_REVISION_1, FALSE, ERROR_INVALID_PARAMETER },
4299 /* test ACE string with spaces */
4300 { " D:(D;;GA;;;WD)", SDDL_REVISION_1, TRUE },
4301 { "D: (D;;GA;;;WD)", SDDL_REVISION_1, TRUE },
4302 { "D:( D;;GA;;;WD)", SDDL_REVISION_1, TRUE },
4303 { "D:(D ;;GA;;;WD)", SDDL_REVISION_1, FALSE, RPC_S_INVALID_STRING_UUID, ERROR_INVALID_ACL }, /* Vista+ */
4304 { "D:(D; ;GA;;;WD)", SDDL_REVISION_1, TRUE },
4305 { "D:(D;; GA;;;WD)", SDDL_REVISION_1, TRUE },
4306 { "D:(D;;GA ;;;WD)", SDDL_REVISION_1, FALSE, ERROR_INVALID_ACL },
4307 { "D:(D;;GA; ;;WD)", SDDL_REVISION_1, TRUE },
4308 { "D:(D;;GA;; ;WD)", SDDL_REVISION_1, TRUE },
4309 { "D:(D;;GA;;; WD)", SDDL_REVISION_1, TRUE },
4310 { "D:(D;;GA;;;WD )", SDDL_REVISION_1, TRUE },
4311 /* test ACE string access rights */
4312 { "D:(A;;GA;;;WD)", SDDL_REVISION_1, TRUE, 0, 0, GENERIC_ALL },
4313 { "D:(A;;1;;;WD)", SDDL_REVISION_1, TRUE, 0, 0, 1 },
4314 { "D:(A;;020000000000;;;WD)", SDDL_REVISION_1, TRUE, 0, 0, GENERIC_READ },
4315 { "D:(A;;0X40000000;;;WD)", SDDL_REVISION_1, TRUE, 0, 0, GENERIC_WRITE },
4316 { "D:(A;;GRGWGX;;;WD)", SDDL_REVISION_1, TRUE, 0, 0, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE },
4317 { "D:(A;;RCSDWDWO;;;WD)", SDDL_REVISION_1, TRUE, 0, 0, READ_CONTROL | DELETE | WRITE_DAC | WRITE_OWNER },
4318 { "D:(A;;RPWPCCDCLCSWLODTCR;;;WD)", SDDL_REVISION_1, TRUE },
4319 { "D:(A;;FAFRFWFX;;;WD)", SDDL_REVISION_1, TRUE },
4320 { "D:(A;;KAKRKWKX;;;WD)", SDDL_REVISION_1, TRUE },
4321 { "D:(A;;0xFFFFFFFF;;;WD)", SDDL_REVISION_1, TRUE },
4322 { "S:(AU;;0xFFFFFFFF;;;WD)", SDDL_REVISION_1, TRUE },
4323 { "S:(AU;;0xDeAdBeEf;;;WD)", SDDL_REVISION_1, TRUE },
4324 { "S:(AU;;GR0xFFFFFFFF;;;WD)", SDDL_REVISION_1, TRUE },
4325 { "S:(AU;;0xFFFFFFFFGR;;;WD)", SDDL_REVISION_1, TRUE },
4326 { "S:(AU;;0xFFFFFGR;;;WD)", SDDL_REVISION_1, TRUE },
4327 /* test ACE string access right error case */
4328 { "D:(A;;ROB;;;WD)", SDDL_REVISION_1, FALSE, ERROR_INVALID_ACL },
4329 /* test behaviour with empty strings */
4330 { "", SDDL_REVISION_1, TRUE },
4331 /* test ACE string SID */
4332 { "D:(D;;GA;;;S-1-0-0)", SDDL_REVISION_1, TRUE },
4333 { "D:(D;;GA;;;WDANDSUCH)", SDDL_REVISION_1, FALSE, ERROR_INVALID_ACL },
4334 { "D:(D;;GA;;;Nonexistent account)", SDDL_REVISION_1, FALSE, ERROR_INVALID_ACL, ERROR_INVALID_SID }, /* W2K */
4337 for (i = 0; i < ARRAY_SIZE(cssd); i++)
4339 DWORD GLE;
4341 SetLastError(0xdeadbeef);
4342 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA(
4343 cssd[i].sidstring, cssd[i].revision, &pSD, NULL);
4344 GLE = GetLastError();
4345 ok(ret == cssd[i].ret, "(%02u) Expected %s (%ld)\n", i, cssd[i].ret ? "success" : "failure", GLE);
4346 if (!cssd[i].ret)
4347 ok(GLE == cssd[i].GLE ||
4348 (cssd[i].altGLE && GLE == cssd[i].altGLE),
4349 "(%02u) Unexpected last error %ld\n", i, GLE);
4350 if (ret)
4352 if (cssd[i].ace_Mask)
4354 ACCESS_ALLOWED_ACE *ace;
4356 acl = (ACL *)((char *)pSD + sizeof(SECURITY_DESCRIPTOR_RELATIVE));
4357 ok(acl->AclRevision == ACL_REVISION, "(%02u) Got %u\n", i, acl->AclRevision);
4359 ace = (ACCESS_ALLOWED_ACE *)(acl + 1);
4360 ok(ace->Mask == cssd[i].ace_Mask, "(%02u) Expected %08lx, got %08lx\n",
4361 i, cssd[i].ace_Mask, ace->Mask);
4363 LocalFree(pSD);
4367 /* test behaviour with NULL parameters */
4368 SetLastError(0xdeadbeef);
4369 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA(
4370 NULL, 0xdeadbeef, &pSD, NULL);
4371 todo_wine
4372 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4373 "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %ld\n",
4374 GetLastError());
4376 SetLastError(0xdeadbeef);
4377 ret = pConvertStringSecurityDescriptorToSecurityDescriptorW(
4378 NULL, 0xdeadbeef, &pSD, NULL);
4379 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4380 "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %ld\n",
4381 GetLastError());
4383 SetLastError(0xdeadbeef);
4384 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA(
4385 "D:(A;;ROB;;;WD)", 0xdeadbeef, NULL, NULL);
4386 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4387 "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %ld\n",
4388 GetLastError());
4390 SetLastError(0xdeadbeef);
4391 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA(
4392 "D:(A;;ROB;;;WD)", SDDL_REVISION_1, NULL, NULL);
4393 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4394 "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %ld\n",
4395 GetLastError());
4397 /* test behaviour with empty strings */
4398 SetLastError(0xdeadbeef);
4399 ret = pConvertStringSecurityDescriptorToSecurityDescriptorW(
4400 Blank, SDDL_REVISION_1, &pSD, NULL);
4401 ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %ld\n", GetLastError());
4402 LocalFree(pSD);
4404 SetLastError(0xdeadbeef);
4405 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA(
4406 "D:P(A;;GRGW;;;BA)(A;;GRGW;;;S-1-5-21-0-0-0-1000)S:(ML;;NWNR;;;S-1-16-12288)", SDDL_REVISION_1, &pSD, NULL);
4407 ok(ret || broken(!ret && GetLastError() == ERROR_INVALID_DATATYPE) /* win2k */,
4408 "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %lu\n", GetLastError());
4409 if (ret) LocalFree(pSD);
4411 /* empty DACL */
4412 size = 0;
4413 SetLastError(0xdeadbeef);
4414 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA("D:", SDDL_REVISION_1, &pSD, &size);
4415 ok(ret, "unexpected error %lu\n", GetLastError());
4416 ok(size == sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sizeof(ACL), "got %lu\n", size);
4417 acl = (ACL *)((char *)pSD + sizeof(SECURITY_DESCRIPTOR_RELATIVE));
4418 ok(acl->AclRevision == ACL_REVISION, "got %u\n", acl->AclRevision);
4419 ok(!acl->Sbz1, "got %u\n", acl->Sbz1);
4420 ok(acl->AclSize == sizeof(*acl), "got %u\n", acl->AclSize);
4421 ok(!acl->AceCount, "got %u\n", acl->AceCount);
4422 ok(!acl->Sbz2, "got %u\n", acl->Sbz2);
4423 LocalFree(pSD);
4425 /* empty SACL */
4426 size = 0;
4427 SetLastError(0xdeadbeef);
4428 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA("S:", SDDL_REVISION_1, &pSD, &size);
4429 ok(ret, "unexpected error %lu\n", GetLastError());
4430 ok(size == sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sizeof(ACL), "got %lu\n", size);
4431 acl = (ACL *)((char *)pSD + sizeof(SECURITY_DESCRIPTOR_RELATIVE));
4432 ok(!acl->Sbz1, "got %u\n", acl->Sbz1);
4433 ok(acl->AclSize == sizeof(*acl), "got %u\n", acl->AclSize);
4434 ok(!acl->AceCount, "got %u\n", acl->AceCount);
4435 ok(!acl->Sbz2, "got %u\n", acl->Sbz2);
4436 LocalFree(pSD);
4439 static void test_ConvertSecurityDescriptorToString(void)
4441 SECURITY_DESCRIPTOR desc;
4442 SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION;
4443 LPSTR string;
4444 DWORD size;
4445 PSID psid, psid2;
4446 PACL pacl;
4447 char sid_buf[256];
4448 char acl_buf[8192];
4449 ULONG len;
4451 if (!pConvertSecurityDescriptorToStringSecurityDescriptorA)
4453 win_skip("ConvertSecurityDescriptorToStringSecurityDescriptor is not available\n");
4454 return;
4457 /* It seems Windows XP adds an extra character to the length of the string for each ACE in an ACL. We
4458 * don't replicate this feature so we only test len >= strlen+1. */
4459 #define CHECK_RESULT_AND_FREE(exp_str) \
4460 ok(strcmp(string, (exp_str)) == 0, "String mismatch (expected \"%s\", got \"%s\")\n", (exp_str), string); \
4461 ok(len >= (strlen(exp_str) + 1), "Length mismatch (expected %d, got %ld)\n", lstrlenA(exp_str) + 1, len); \
4462 LocalFree(string);
4464 #define CHECK_ONE_OF_AND_FREE(exp_str1, exp_str2) \
4465 ok(strcmp(string, (exp_str1)) == 0 || strcmp(string, (exp_str2)) == 0, "String mismatch (expected\n\"%s\" or\n\"%s\", got\n\"%s\")\n", (exp_str1), (exp_str2), string); \
4466 ok(len >= (strlen(exp_str1) + 1) || len >= (strlen(exp_str2) + 1), "Length mismatch (expected %d or %d, got %ld)\n", lstrlenA(exp_str1) + 1, lstrlenA(exp_str2) + 1, len); \
4467 LocalFree(string);
4469 InitializeSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION);
4470 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4471 CHECK_RESULT_AND_FREE("");
4473 size = 4096;
4474 CreateWellKnownSid(WinLocalSid, NULL, sid_buf, &size);
4475 SetSecurityDescriptorOwner(&desc, sid_buf, FALSE);
4476 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4477 CHECK_RESULT_AND_FREE("O:S-1-2-0");
4479 SetSecurityDescriptorOwner(&desc, sid_buf, TRUE);
4480 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4481 CHECK_RESULT_AND_FREE("O:S-1-2-0");
4483 size = sizeof(sid_buf);
4484 CreateWellKnownSid(WinLocalSystemSid, NULL, sid_buf, &size);
4485 SetSecurityDescriptorOwner(&desc, sid_buf, TRUE);
4486 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4487 CHECK_RESULT_AND_FREE("O:SY");
4489 ConvertStringSidToSidA("S-1-5-21-93476-23408-4576", &psid);
4490 SetSecurityDescriptorGroup(&desc, psid, TRUE);
4491 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4492 CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576");
4494 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, GROUP_SECURITY_INFORMATION, &string, &len), "Conversion failed\n");
4495 CHECK_RESULT_AND_FREE("G:S-1-5-21-93476-23408-4576");
4497 pacl = (PACL)acl_buf;
4498 InitializeAcl(pacl, sizeof(acl_buf), ACL_REVISION);
4499 SetSecurityDescriptorDacl(&desc, TRUE, pacl, TRUE);
4500 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4501 CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:");
4503 SetSecurityDescriptorDacl(&desc, TRUE, pacl, FALSE);
4504 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4505 CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:");
4507 ConvertStringSidToSidA("S-1-5-6", &psid2);
4508 pAddAccessAllowedAceEx(pacl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, 0xf0000000, psid2);
4509 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4510 CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)");
4512 pAddAccessAllowedAceEx(pacl, ACL_REVISION, INHERIT_ONLY_ACE|INHERITED_ACE, 0x00000003, psid2);
4513 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4514 CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)");
4516 pAddAccessDeniedAceEx(pacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE, 0xffffffff, psid);
4517 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4518 CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)");
4521 pacl = (PACL)acl_buf;
4522 InitializeAcl(pacl, sizeof(acl_buf), ACL_REVISION);
4523 SetSecurityDescriptorSacl(&desc, TRUE, pacl, FALSE);
4524 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4525 CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:");
4527 /* fails in win2k */
4528 SetSecurityDescriptorDacl(&desc, TRUE, NULL, FALSE);
4529 pAddAuditAccessAceEx(pacl, ACL_REVISION, VALID_INHERIT_FLAGS, KEY_READ|KEY_WRITE, psid2, TRUE, TRUE);
4530 if (pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len))
4532 CHECK_ONE_OF_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)", /* XP */
4533 "O:SYG:S-1-5-21-93476-23408-4576D:NO_ACCESS_CONTROLS:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)" /* Vista */);
4536 /* fails in win2k */
4537 pAddAuditAccessAceEx(pacl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, FILE_GENERIC_READ|FILE_GENERIC_WRITE, psid2, TRUE, FALSE);
4538 if (pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len))
4540 CHECK_ONE_OF_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)", /* XP */
4541 "O:SYG:S-1-5-21-93476-23408-4576D:NO_ACCESS_CONTROLS:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)" /* Vista */);
4544 LocalFree(psid2);
4545 LocalFree(psid);
4548 static void test_SetSecurityDescriptorControl (PSECURITY_DESCRIPTOR sec)
4550 SECURITY_DESCRIPTOR_CONTROL ref;
4551 SECURITY_DESCRIPTOR_CONTROL test;
4553 SECURITY_DESCRIPTOR_CONTROL const mutable
4554 = SE_DACL_AUTO_INHERIT_REQ | SE_SACL_AUTO_INHERIT_REQ
4555 | SE_DACL_AUTO_INHERITED | SE_SACL_AUTO_INHERITED
4556 | SE_DACL_PROTECTED | SE_SACL_PROTECTED
4557 | 0x00000040 | 0x00000080 /* not defined in winnt.h */
4559 SECURITY_DESCRIPTOR_CONTROL const immutable
4560 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
4561 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
4562 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
4563 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
4566 int bit;
4567 DWORD dwRevision;
4568 LPCSTR fmt = "Expected error %s, got %u\n";
4570 GetSecurityDescriptorControl (sec, &ref, &dwRevision);
4572 /* The mutable bits are mutable regardless of the truth of
4573 SE_DACL_PRESENT and/or SE_SACL_PRESENT */
4575 /* Check call barfs if any bit-of-interest is immutable */
4576 for (bit = 0; bit < 16; ++bit)
4578 SECURITY_DESCRIPTOR_CONTROL const bitOfInterest = 1 << bit;
4579 SECURITY_DESCRIPTOR_CONTROL setOrClear = ref & bitOfInterest;
4581 SECURITY_DESCRIPTOR_CONTROL ctrl;
4583 DWORD dwExpect = (bitOfInterest & immutable)
4584 ? ERROR_INVALID_PARAMETER : 0xbebecaca;
4585 LPCSTR strExpect = (bitOfInterest & immutable)
4586 ? "ERROR_INVALID_PARAMETER" : "0xbebecaca";
4588 ctrl = (bitOfInterest & mutable) ? ref + bitOfInterest : ref;
4589 setOrClear ^= bitOfInterest;
4590 SetLastError (0xbebecaca);
4591 pSetSecurityDescriptorControl (sec, bitOfInterest, setOrClear);
4592 ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ());
4593 GetSecurityDescriptorControl(sec, &test, &dwRevision);
4594 expect_eq(test, ctrl, int, "%x");
4596 setOrClear ^= bitOfInterest;
4597 SetLastError (0xbebecaca);
4598 pSetSecurityDescriptorControl (sec, bitOfInterest, setOrClear);
4599 ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ());
4600 GetSecurityDescriptorControl (sec, &test, &dwRevision);
4601 expect_eq(test, ref, int, "%x");
4604 /* Check call barfs if any bit-to-set is immutable
4605 even when not a bit-of-interest */
4606 for (bit = 0; bit < 16; ++bit)
4608 SECURITY_DESCRIPTOR_CONTROL const bitsOfInterest = mutable;
4609 SECURITY_DESCRIPTOR_CONTROL setOrClear = ref & bitsOfInterest;
4611 SECURITY_DESCRIPTOR_CONTROL ctrl;
4613 DWORD dwExpect = ((1 << bit) & immutable)
4614 ? ERROR_INVALID_PARAMETER : 0xbebecaca;
4615 LPCSTR strExpect = ((1 << bit) & immutable)
4616 ? "ERROR_INVALID_PARAMETER" : "0xbebecaca";
4618 ctrl = ((1 << bit) & immutable) ? test : ref | mutable;
4619 setOrClear ^= bitsOfInterest;
4620 SetLastError (0xbebecaca);
4621 pSetSecurityDescriptorControl (sec, bitsOfInterest, setOrClear | (1 << bit));
4622 ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ());
4623 GetSecurityDescriptorControl(sec, &test, &dwRevision);
4624 expect_eq(test, ctrl, int, "%x");
4626 ctrl = ((1 << bit) & immutable) ? test : ref | (1 << bit);
4627 setOrClear ^= bitsOfInterest;
4628 SetLastError (0xbebecaca);
4629 pSetSecurityDescriptorControl (sec, bitsOfInterest, setOrClear | (1 << bit));
4630 ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ());
4631 GetSecurityDescriptorControl(sec, &test, &dwRevision);
4632 expect_eq(test, ctrl, int, "%x");
4636 static void test_PrivateObjectSecurity(void)
4638 SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION;
4639 SECURITY_DESCRIPTOR_CONTROL ctrl;
4640 PSECURITY_DESCRIPTOR sec;
4641 DWORD dwDescSize;
4642 DWORD dwRevision;
4643 DWORD retSize;
4644 LPSTR string;
4645 ULONG len;
4646 PSECURITY_DESCRIPTOR buf;
4647 BOOL ret;
4649 ok(ConvertStringSecurityDescriptorToSecurityDescriptorA(
4650 "O:SY"
4651 "G:S-1-5-21-93476-23408-4576"
4652 "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)"
4653 "(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
4654 "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)",
4655 SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n");
4657 test_SetSecurityDescriptorControl(sec);
4659 LocalFree(sec);
4661 ok(ConvertStringSecurityDescriptorToSecurityDescriptorA(
4662 "O:SY"
4663 "G:S-1-5-21-93476-23408-4576",
4664 SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n");
4666 test_SetSecurityDescriptorControl(sec);
4668 LocalFree(sec);
4670 ok(ConvertStringSecurityDescriptorToSecurityDescriptorA(
4671 "O:SY"
4672 "G:S-1-5-21-93476-23408-4576"
4673 "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
4674 "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)", SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n");
4675 buf = malloc(dwDescSize);
4676 pSetSecurityDescriptorControl(sec, SE_DACL_PROTECTED, SE_DACL_PROTECTED);
4677 GetSecurityDescriptorControl(sec, &ctrl, &dwRevision);
4678 expect_eq(ctrl, 0x9014, int, "%x");
4680 ret = GetPrivateObjectSecurity(sec, GROUP_SECURITY_INFORMATION, buf, dwDescSize, &retSize);
4681 ok(ret, "GetPrivateObjectSecurity failed (err=%lu)\n", GetLastError());
4682 ok(retSize <= dwDescSize, "Buffer too small (%ld vs %ld)\n", retSize, dwDescSize);
4683 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4684 CHECK_RESULT_AND_FREE("G:S-1-5-21-93476-23408-4576");
4685 GetSecurityDescriptorControl(buf, &ctrl, &dwRevision);
4686 expect_eq(ctrl, 0x8000, int, "%x");
4688 ret = GetPrivateObjectSecurity(sec, GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, buf, dwDescSize, &retSize);
4689 ok(ret, "GetPrivateObjectSecurity failed (err=%lu)\n", GetLastError());
4690 ok(retSize <= dwDescSize, "Buffer too small (%ld vs %ld)\n", retSize, dwDescSize);
4691 ret = pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len);
4692 ok(ret, "Conversion failed err=%lu\n", GetLastError());
4693 CHECK_ONE_OF_AND_FREE("G:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)",
4694 "G:S-1-5-21-93476-23408-4576D:P(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"); /* Win7 */
4695 GetSecurityDescriptorControl(buf, &ctrl, &dwRevision);
4696 expect_eq(ctrl & (~ SE_DACL_PROTECTED), 0x8004, int, "%x");
4698 ret = GetPrivateObjectSecurity(sec, sec_info, buf, dwDescSize, &retSize);
4699 ok(ret, "GetPrivateObjectSecurity failed (err=%lu)\n", GetLastError());
4700 ok(retSize == dwDescSize, "Buffer too small (%ld vs %ld)\n", retSize, dwDescSize);
4701 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4702 CHECK_ONE_OF_AND_FREE("O:SY"
4703 "G:S-1-5-21-93476-23408-4576"
4704 "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
4705 "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)",
4706 "O:SY"
4707 "G:S-1-5-21-93476-23408-4576"
4708 "D:P(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
4709 "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)"); /* Win7 */
4710 GetSecurityDescriptorControl(buf, &ctrl, &dwRevision);
4711 expect_eq(ctrl & (~ SE_DACL_PROTECTED), 0x8014, int, "%x");
4713 SetLastError(0xdeadbeef);
4714 ok(GetPrivateObjectSecurity(sec, sec_info, buf, 5, &retSize) == FALSE, "GetPrivateObjectSecurity should have failed\n");
4715 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected error ERROR_INSUFFICIENT_BUFFER, got %lu\n", GetLastError());
4717 LocalFree(sec);
4718 free(buf);
4720 #undef CHECK_RESULT_AND_FREE
4721 #undef CHECK_ONE_OF_AND_FREE
4723 static void test_InitializeAcl(void)
4725 char buffer[256];
4726 PACL pAcl = (PACL)buffer;
4727 BOOL ret;
4729 SetLastError(0xdeadbeef);
4730 ret = InitializeAcl(pAcl, sizeof(ACL) - 1, ACL_REVISION);
4731 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
4733 win_skip("InitializeAcl is not implemented\n");
4734 return;
4737 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InitializeAcl with too small a buffer should have failed with ERROR_INSUFFICIENT_BUFFER instead of %ld\n", GetLastError());
4739 SetLastError(0xdeadbeef);
4740 ret = InitializeAcl(pAcl, 0xffffffff, ACL_REVISION);
4741 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl with too large a buffer should have failed with ERROR_INVALID_PARAMETER instead of %ld\n", GetLastError());
4743 SetLastError(0xdeadbeef);
4744 ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION1);
4745 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl(ACL_REVISION1) should have failed with ERROR_INVALID_PARAMETER instead of %ld\n", GetLastError());
4747 ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION2);
4748 ok(ret, "InitializeAcl(ACL_REVISION2) failed with error %ld\n", GetLastError());
4750 ret = IsValidAcl(pAcl);
4751 ok(ret, "IsValidAcl failed with error %ld\n", GetLastError());
4753 ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION3);
4754 ok(ret, "InitializeAcl(ACL_REVISION3) failed with error %ld\n", GetLastError());
4756 ret = IsValidAcl(pAcl);
4757 ok(ret, "IsValidAcl failed with error %ld\n", GetLastError());
4759 SetLastError(0xdeadbeef);
4760 ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION4);
4761 if (GetLastError() != ERROR_INVALID_PARAMETER)
4763 ok(ret, "InitializeAcl(ACL_REVISION4) failed with error %ld\n", GetLastError());
4765 ret = IsValidAcl(pAcl);
4766 ok(ret, "IsValidAcl failed with error %ld\n", GetLastError());
4768 else
4769 win_skip("ACL_REVISION4 is not implemented on NT4\n");
4771 SetLastError(0xdeadbeef);
4772 ret = InitializeAcl(pAcl, sizeof(buffer), -1);
4773 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl(-1) failed with error %ld\n", GetLastError());
4776 static void test_GetSecurityInfo(void)
4778 char domain_users_ptr[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
4779 char b[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
4780 char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], dacl[100];
4781 PSID domain_users_sid = (PSID) domain_users_ptr, domain_sid;
4782 SID_IDENTIFIER_AUTHORITY sia = { SECURITY_NT_AUTHORITY };
4783 int domain_users_ace_id = -1, admins_ace_id = -1, i;
4784 DWORD sid_size = sizeof(admin_ptr), l = sizeof(b);
4785 SECURITY_ATTRIBUTES sa = {.nLength = sizeof(sa)};
4786 PSID admin_sid = (PSID) admin_ptr, user_sid;
4787 char sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
4788 BOOL owner_defaulted, group_defaulted;
4789 BOOL dacl_defaulted, dacl_present;
4790 ACL_SIZE_INFORMATION acl_size;
4791 PSECURITY_DESCRIPTOR pSD;
4792 ACCESS_ALLOWED_ACE *ace;
4793 HANDLE token, obj;
4794 PSID owner, group;
4795 BOOL bret = TRUE;
4796 PACL pDacl;
4797 BYTE flags;
4798 DWORD ret;
4800 static const SE_OBJECT_TYPE kernel_types[] =
4802 SE_FILE_OBJECT,
4803 SE_KERNEL_OBJECT,
4804 SE_WMIGUID_OBJECT,
4807 static const SE_OBJECT_TYPE invalid_types[] =
4809 SE_UNKNOWN_OBJECT_TYPE,
4810 SE_DS_OBJECT,
4811 SE_DS_OBJECT_ALL,
4812 SE_PROVIDER_DEFINED_OBJECT,
4813 SE_REGISTRY_WOW64_32KEY,
4814 SE_REGISTRY_WOW64_64KEY,
4815 0xdeadbeef,
4818 if (!pSetSecurityInfo)
4820 win_skip("[Get|Set]SecurityInfo is not available\n");
4821 return;
4824 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
4826 if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE;
4827 else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE;
4829 if (!bret)
4831 win_skip("Failed to get current user token\n");
4832 return;
4834 bret = GetTokenInformation(token, TokenUser, b, l, &l);
4835 ok(bret, "GetTokenInformation(TokenUser) failed with error %ld\n", GetLastError());
4836 CloseHandle( token );
4837 user_sid = ((TOKEN_USER *)b)->User.Sid;
4839 /* Create something. Files have lots of associated security info. */
4840 obj = CreateFileA(myARGV[0], GENERIC_READ|WRITE_DAC, FILE_SHARE_READ, NULL,
4841 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
4842 if (obj == INVALID_HANDLE_VALUE)
4844 skip("Couldn't create an object for GetSecurityInfo test\n");
4845 return;
4848 ret = GetSecurityInfo(obj, SE_FILE_OBJECT,
4849 OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
4850 &owner, &group, &pDacl, NULL, &pSD);
4851 if (ret == ERROR_CALL_NOT_IMPLEMENTED)
4853 win_skip("GetSecurityInfo is not implemented\n");
4854 CloseHandle(obj);
4855 return;
4857 ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %ld\n", ret);
4858 ok(pSD != NULL, "GetSecurityInfo\n");
4859 ok(owner != NULL, "GetSecurityInfo\n");
4860 ok(group != NULL, "GetSecurityInfo\n");
4861 if (pDacl != NULL)
4862 ok(IsValidAcl(pDacl), "GetSecurityInfo\n");
4863 else
4864 win_skip("No ACL information returned\n");
4866 LocalFree(pSD);
4868 /* If we don't ask for the security descriptor, Windows will still give us
4869 the other stuff, leaving us no way to free it. */
4870 ret = GetSecurityInfo(obj, SE_FILE_OBJECT,
4871 OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
4872 &owner, &group, &pDacl, NULL, NULL);
4873 ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %ld\n", ret);
4874 ok(owner != NULL, "GetSecurityInfo\n");
4875 ok(group != NULL, "GetSecurityInfo\n");
4876 if (pDacl != NULL)
4877 ok(IsValidAcl(pDacl), "GetSecurityInfo\n");
4878 else
4879 win_skip("No ACL information returned\n");
4881 /* Create security descriptor information and test that it comes back the same */
4882 pSD = &sd;
4883 pDacl = (PACL)&dacl;
4884 InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
4885 CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size);
4886 bret = InitializeAcl(pDacl, sizeof(dacl), ACL_REVISION);
4887 ok(bret, "Failed to initialize ACL.\n");
4888 bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
4889 ok(bret, "Failed to add Current User to ACL.\n");
4890 bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, admin_sid);
4891 ok(bret, "Failed to add Administrator Group to ACL.\n");
4892 bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
4893 ok(bret, "Failed to add ACL to security descriptor.\n");
4894 ret = pSetSecurityInfo(obj, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
4895 NULL, NULL, pDacl, NULL);
4896 ok(ret == ERROR_SUCCESS, "SetSecurityInfo returned %ld\n", ret);
4897 ret = GetSecurityInfo(obj, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
4898 NULL, NULL, &pDacl, NULL, &pSD);
4899 ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %ld\n", ret);
4900 ok(pDacl && IsValidAcl(pDacl), "GetSecurityInfo returned invalid DACL.\n");
4901 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
4902 ok(bret, "GetAclInformation failed\n");
4903 if (acl_size.AceCount > 0)
4905 bret = GetAce(pDacl, 0, (VOID **)&ace);
4906 ok(bret, "Failed to get Current User ACE.\n");
4907 bret = EqualSid(&ace->SidStart, user_sid);
4908 todo_wine ok(bret, "Current User ACE (%s) != Current User SID (%s).\n",
4909 debugstr_sid(&ace->SidStart), debugstr_sid(user_sid));
4910 ok(((ACE_HEADER *)ace)->AceFlags == 0,
4911 "Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
4912 ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%lx != 0x1f01ff)\n",
4913 ace->Mask);
4915 if (acl_size.AceCount > 1)
4917 bret = GetAce(pDacl, 1, (VOID **)&ace);
4918 ok(bret, "Failed to get Administators Group ACE.\n");
4919 bret = EqualSid(&ace->SidStart, admin_sid);
4920 todo_wine ok(bret, "Administators Group ACE (%s) != Administators Group SID (%s).\n", debugstr_sid(&ace->SidStart), debugstr_sid(admin_sid));
4921 ok(((ACE_HEADER *)ace)->AceFlags == 0,
4922 "Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
4923 ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%lx != 0x1f01ff)\n",
4924 ace->Mask);
4926 LocalFree(pSD);
4927 CloseHandle(obj);
4929 /* Obtain the "domain users" SID from the user SID */
4930 if (!AllocateAndInitializeSid(&sia, 4, *GetSidSubAuthority(user_sid, 0),
4931 *GetSidSubAuthority(user_sid, 1),
4932 *GetSidSubAuthority(user_sid, 2),
4933 *GetSidSubAuthority(user_sid, 3), 0, 0, 0, 0, &domain_sid))
4935 win_skip("Failed to get current domain SID\n");
4936 return;
4938 sid_size = sizeof(domain_users_ptr);
4939 CreateWellKnownSid(WinAccountDomainUsersSid, domain_sid, domain_users_sid, &sid_size);
4940 FreeSid(domain_sid);
4942 /* Test querying the ownership of a process */
4943 ret = GetSecurityInfo(GetCurrentProcess(), SE_KERNEL_OBJECT,
4944 OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION,
4945 NULL, NULL, NULL, NULL, &pSD);
4946 ok(!ret, "GetNamedSecurityInfo failed with error %ld\n", ret);
4948 bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted);
4949 ok(bret, "GetSecurityDescriptorOwner failed with error %ld\n", GetLastError());
4950 ok(owner != NULL, "owner should not be NULL\n");
4951 ok(EqualSid(owner, admin_sid) || EqualSid(owner, user_sid),
4952 "Process owner SID != Administrators SID.\n");
4954 bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted);
4955 ok(bret, "GetSecurityDescriptorGroup failed with error %ld\n", GetLastError());
4956 ok(group != NULL, "group should not be NULL\n");
4957 ok(EqualSid(group, domain_users_sid), "Process group SID != Domain Users SID.\n");
4958 LocalFree(pSD);
4960 /* Test querying the DACL of a process */
4961 ret = GetSecurityInfo(GetCurrentProcess(), SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
4962 NULL, NULL, NULL, NULL, &pSD);
4963 ok(!ret, "GetSecurityInfo failed with error %ld\n", ret);
4965 bret = GetSecurityDescriptorDacl(pSD, &dacl_present, &pDacl, &dacl_defaulted);
4966 ok(bret, "GetSecurityDescriptorDacl failed with error %ld\n", GetLastError());
4967 ok(dacl_present, "DACL should be present\n");
4968 ok(pDacl && IsValidAcl(pDacl), "GetSecurityDescriptorDacl returned invalid DACL.\n");
4969 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
4970 ok(bret, "GetAclInformation failed\n");
4971 ok(acl_size.AceCount != 0, "GetAclInformation returned no ACLs\n");
4972 for (i=0; i<acl_size.AceCount; i++)
4974 bret = GetAce(pDacl, i, (VOID **)&ace);
4975 ok(bret, "Failed to get ACE %d.\n", i);
4976 bret = EqualSid(&ace->SidStart, domain_users_sid);
4977 if (bret) domain_users_ace_id = i;
4978 bret = EqualSid(&ace->SidStart, admin_sid);
4979 if (bret) admins_ace_id = i;
4981 ok(domain_users_ace_id != -1 || broken(domain_users_ace_id == -1) /* win2k */,
4982 "Domain Users ACE not found.\n");
4983 if (domain_users_ace_id != -1)
4985 bret = GetAce(pDacl, domain_users_ace_id, (VOID **)&ace);
4986 ok(bret, "Failed to get Domain Users ACE.\n");
4987 flags = ((ACE_HEADER *)ace)->AceFlags;
4988 ok(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE),
4989 "Domain Users ACE has unexpected flags (0x%x != 0x%x)\n", flags,
4990 INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE);
4991 ok(ace->Mask == GENERIC_READ, "Domain Users ACE has unexpected mask (0x%lx != 0x%x)\n",
4992 ace->Mask, GENERIC_READ);
4994 ok(admins_ace_id != -1 || broken(admins_ace_id == -1) /* xp */,
4995 "Builtin Admins ACE not found.\n");
4996 if (admins_ace_id != -1)
4998 bret = GetAce(pDacl, admins_ace_id, (VOID **)&ace);
4999 ok(bret, "Failed to get Builtin Admins ACE.\n");
5000 flags = ((ACE_HEADER *)ace)->AceFlags;
5001 ok(flags == 0x0, "Builtin Admins ACE has unexpected flags (0x%x != 0x0)\n", flags);
5002 ok(ace->Mask == PROCESS_ALL_ACCESS || broken(ace->Mask == 0x1f0fff) /* win2k */,
5003 "Builtin Admins ACE has unexpected mask (0x%lx != 0x%x)\n", ace->Mask, PROCESS_ALL_ACCESS);
5005 LocalFree(pSD);
5007 ret = GetSecurityInfo(NULL, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &pSD);
5008 ok(ret == ERROR_INVALID_HANDLE, "got error %lu\n", ret);
5010 ret = GetSecurityInfo(GetCurrentProcess(), SE_FILE_OBJECT,
5011 DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &pSD);
5012 ok(!ret, "got error %lu\n", ret);
5013 LocalFree(pSD);
5015 sa.lpSecurityDescriptor = sd;
5016 obj = CreateEventA(&sa, TRUE, TRUE, NULL);
5017 pDacl = (PACL)&dacl;
5019 for (size_t i = 0; i < ARRAY_SIZE(kernel_types); ++i)
5021 winetest_push_context("Type %#x", kernel_types[i]);
5023 ret = GetSecurityInfo(NULL, kernel_types[i],
5024 DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &pSD);
5025 ok(ret == ERROR_INVALID_HANDLE, "got error %lu\n", ret);
5027 ret = GetSecurityInfo(GetCurrentProcess(), kernel_types[i],
5028 DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &pSD);
5029 ok(!ret, "got error %lu\n", ret);
5030 LocalFree(pSD);
5032 ret = GetSecurityInfo(obj, kernel_types[i],
5033 DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &pSD);
5034 ok(!ret, "got error %lu\n", ret);
5035 LocalFree(pSD);
5037 ret = SetSecurityInfo(NULL, kernel_types[i],
5038 DACL_SECURITY_INFORMATION, NULL, NULL, pDacl, NULL);
5039 ok(ret == ERROR_INVALID_HANDLE, "got error %lu\n", ret);
5041 ret = SetSecurityInfo(obj, kernel_types[i],
5042 DACL_SECURITY_INFORMATION, NULL, NULL, pDacl, NULL);
5043 ok(!ret || ret == ERROR_NO_SECURITY_ON_OBJECT /* win 7 */, "got error %lu\n", ret);
5045 winetest_pop_context();
5048 ret = GetSecurityInfo(GetCurrentProcess(), SE_REGISTRY_KEY,
5049 DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &pSD);
5050 todo_wine ok(ret == ERROR_INVALID_HANDLE, "got error %lu\n", ret);
5052 ret = GetSecurityInfo(obj, SE_REGISTRY_KEY,
5053 DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &pSD);
5054 todo_wine ok(ret == ERROR_INVALID_HANDLE, "got error %lu\n", ret);
5056 CloseHandle(obj);
5058 for (size_t i = 0; i < ARRAY_SIZE(invalid_types); ++i)
5060 winetest_push_context("Type %#x", invalid_types[i]);
5062 ret = GetSecurityInfo(NULL, invalid_types[i],
5063 DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &pSD);
5064 ok(ret == ERROR_INVALID_HANDLE, "got error %lu\n", ret);
5066 ret = GetSecurityInfo((HANDLE)0xdeadbeef, invalid_types[i],
5067 DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &pSD);
5068 todo_wine ok(ret == ERROR_INVALID_PARAMETER, "got error %lu\n", ret);
5070 ret = SetSecurityInfo(NULL, invalid_types[i],
5071 DACL_SECURITY_INFORMATION, NULL, NULL, pDacl, NULL);
5072 ok(ret == ERROR_INVALID_HANDLE, "got error %lu\n", ret);
5074 ret = SetSecurityInfo((HANDLE)0xdeadbeef, invalid_types[i],
5075 DACL_SECURITY_INFORMATION, NULL, NULL, pDacl, NULL);
5076 todo_wine ok(ret == ERROR_INVALID_PARAMETER, "got error %lu\n", ret);
5078 winetest_pop_context();
5082 static void test_GetSidSubAuthority(void)
5084 PSID psid = NULL;
5086 /* Note: on windows passing in an invalid index like -1, lets GetSidSubAuthority return 0x05000000 but
5087 still GetLastError returns ERROR_SUCCESS then. We don't test these unlikely cornercases here for now */
5088 ok(ConvertStringSidToSidA("S-1-5-21-93476-23408-4576",&psid),"ConvertStringSidToSidA failed\n");
5089 ok(IsValidSid(psid),"Sid is not valid\n");
5090 SetLastError(0xbebecaca);
5091 ok(*GetSidSubAuthorityCount(psid) == 4,"GetSidSubAuthorityCount gave %d expected 4\n", *GetSidSubAuthorityCount(psid));
5092 ok(GetLastError() == 0,"GetLastError returned %ld instead of 0\n",GetLastError());
5093 SetLastError(0xbebecaca);
5094 ok(*GetSidSubAuthority(psid,0) == 21,"GetSidSubAuthority gave %ld expected 21\n", *GetSidSubAuthority(psid,0));
5095 ok(GetLastError() == 0,"GetLastError returned %ld instead of 0\n",GetLastError());
5096 SetLastError(0xbebecaca);
5097 ok(*GetSidSubAuthority(psid,1) == 93476,"GetSidSubAuthority gave %ld expected 93476\n", *GetSidSubAuthority(psid,1));
5098 ok(GetLastError() == 0,"GetLastError returned %ld instead of 0\n",GetLastError());
5099 SetLastError(0xbebecaca);
5100 ok(GetSidSubAuthority(psid,4) != NULL,"Expected out of bounds GetSidSubAuthority to return a non-NULL pointer\n");
5101 ok(GetLastError() == 0,"GetLastError returned %ld instead of 0\n",GetLastError());
5102 LocalFree(psid);
5105 static void test_CheckTokenMembership(void)
5107 PTOKEN_GROUPS token_groups;
5108 DWORD size;
5109 HANDLE process_token, token;
5110 BOOL is_member;
5111 BOOL ret;
5112 DWORD i;
5114 if (!pCheckTokenMembership)
5116 win_skip("CheckTokenMembership is not available\n");
5117 return;
5119 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &process_token);
5120 ok(ret, "OpenProcessToken failed with error %ld\n", GetLastError());
5122 ret = DuplicateToken(process_token, SecurityImpersonation, &token);
5123 ok(ret, "DuplicateToken failed with error %ld\n", GetLastError());
5125 /* groups */
5126 ret = GetTokenInformation(token, TokenGroups, NULL, 0, &size);
5127 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
5128 "GetTokenInformation(TokenGroups) %s with error %ld\n",
5129 ret ? "succeeded" : "failed", GetLastError());
5130 token_groups = malloc(size);
5131 ret = GetTokenInformation(token, TokenGroups, token_groups, size, &size);
5132 ok(ret, "GetTokenInformation(TokenGroups) failed with error %ld\n", GetLastError());
5134 for (i = 0; i < token_groups->GroupCount; i++)
5136 if (token_groups->Groups[i].Attributes & SE_GROUP_ENABLED)
5137 break;
5140 if (i == token_groups->GroupCount)
5142 free(token_groups);
5143 CloseHandle(token);
5144 skip("user not a member of any group\n");
5145 return;
5148 is_member = FALSE;
5149 ret = pCheckTokenMembership(token, token_groups->Groups[i].Sid, &is_member);
5150 ok(ret, "CheckTokenMembership failed with error %ld\n", GetLastError());
5151 ok(is_member, "CheckTokenMembership should have detected sid as member\n");
5153 is_member = FALSE;
5154 ret = pCheckTokenMembership(NULL, token_groups->Groups[i].Sid, &is_member);
5155 ok(ret, "CheckTokenMembership failed with error %ld\n", GetLastError());
5156 ok(is_member, "CheckTokenMembership should have detected sid as member\n");
5158 is_member = TRUE;
5159 SetLastError(0xdeadbeef);
5160 ret = pCheckTokenMembership(process_token, token_groups->Groups[i].Sid, &is_member);
5161 ok(!ret && GetLastError() == ERROR_NO_IMPERSONATION_TOKEN,
5162 "CheckTokenMembership with process token %s with error %ld\n",
5163 ret ? "succeeded" : "failed", GetLastError());
5164 ok(!is_member, "CheckTokenMembership should have cleared is_member\n");
5166 free(token_groups);
5167 CloseHandle(token);
5168 CloseHandle(process_token);
5171 static void test_EqualSid(void)
5173 PSID sid1, sid2;
5174 BOOL ret;
5175 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
5176 SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
5178 SetLastError(0xdeadbeef);
5179 ret = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
5180 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid1);
5181 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
5183 win_skip("AllocateAndInitializeSid is not implemented\n");
5184 return;
5186 ok(ret, "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
5187 ok(GetLastError() == 0xdeadbeef,
5188 "AllocateAndInitializeSid shouldn't have set last error to %ld\n",
5189 GetLastError());
5191 ret = AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID,
5192 0, 0, 0, 0, 0, 0, 0, &sid2);
5193 ok(ret, "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
5195 SetLastError(0xdeadbeef);
5196 ret = EqualSid(sid1, sid2);
5197 ok(!ret, "World and domain admins sids shouldn't have been equal\n");
5198 ok(GetLastError() == ERROR_SUCCESS ||
5199 broken(GetLastError() == 0xdeadbeef), /* NT4 */
5200 "EqualSid should have set last error to ERROR_SUCCESS instead of %ld\n",
5201 GetLastError());
5203 SetLastError(0xdeadbeef);
5204 sid2 = FreeSid(sid2);
5205 ok(!sid2, "FreeSid should have returned NULL instead of %p\n", sid2);
5206 ok(GetLastError() == 0xdeadbeef,
5207 "FreeSid shouldn't have set last error to %ld\n",
5208 GetLastError());
5210 ret = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
5211 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid2);
5212 ok(ret, "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
5214 SetLastError(0xdeadbeef);
5215 ret = EqualSid(sid1, sid2);
5216 ok(ret, "Same sids should have been equal %s != %s\n",
5217 debugstr_sid(sid1), debugstr_sid(sid2));
5218 ok(GetLastError() == ERROR_SUCCESS ||
5219 broken(GetLastError() == 0xdeadbeef), /* NT4 */
5220 "EqualSid should have set last error to ERROR_SUCCESS instead of %ld\n",
5221 GetLastError());
5223 ((SID *)sid2)->Revision = 2;
5224 SetLastError(0xdeadbeef);
5225 ret = EqualSid(sid1, sid2);
5226 ok(!ret, "EqualSid with invalid sid should have returned FALSE\n");
5227 ok(GetLastError() == ERROR_SUCCESS ||
5228 broken(GetLastError() == 0xdeadbeef), /* NT4 */
5229 "EqualSid should have set last error to ERROR_SUCCESS instead of %ld\n",
5230 GetLastError());
5231 ((SID *)sid2)->Revision = SID_REVISION;
5233 FreeSid(sid1);
5234 FreeSid(sid2);
5237 static void test_GetUserNameA(void)
5239 char buffer[UNLEN + 1], filler[UNLEN + 1];
5240 DWORD required_len, buffer_len;
5241 BOOL ret;
5243 /* Test crashes on Windows. */
5244 if (0)
5246 SetLastError(0xdeadbeef);
5247 GetUserNameA(NULL, NULL);
5250 SetLastError(0xdeadbeef);
5251 required_len = 0;
5252 ret = GetUserNameA(NULL, &required_len);
5253 ok(ret == FALSE, "GetUserNameA returned %d\n", ret);
5254 ok(required_len != 0, "Outputted buffer length was %lu\n", required_len);
5255 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %lu\n", GetLastError());
5257 SetLastError(0xdeadbeef);
5258 required_len = 1;
5259 ret = GetUserNameA(NULL, &required_len);
5260 ok(ret == FALSE, "GetUserNameA returned %d\n", ret);
5261 ok(required_len != 0 && required_len != 1, "Outputted buffer length was %lu\n", required_len);
5262 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %lu\n", GetLastError());
5264 /* Tests crashes on Windows. */
5265 if (0)
5267 SetLastError(0xdeadbeef);
5268 required_len = UNLEN + 1;
5269 GetUserNameA(NULL, &required_len);
5271 SetLastError(0xdeadbeef);
5272 GetUserNameA(buffer, NULL);
5275 memset(filler, 'x', sizeof(filler));
5277 /* Note that GetUserNameA on XP and newer outputs the number of bytes
5278 * required for a Unicode string, which affects a test in the next block. */
5279 SetLastError(0xdeadbeef);
5280 memcpy(buffer, filler, sizeof(filler));
5281 required_len = 0;
5282 ret = GetUserNameA(buffer, &required_len);
5283 ok(ret == FALSE, "GetUserNameA returned %d\n", ret);
5284 ok(!memcmp(buffer, filler, sizeof(filler)), "Output buffer was altered\n");
5285 ok(required_len != 0, "Outputted buffer length was %lu\n", required_len);
5286 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %lu\n", GetLastError());
5288 SetLastError(0xdeadbeef);
5289 memcpy(buffer, filler, sizeof(filler));
5290 buffer_len = required_len;
5291 ret = GetUserNameA(buffer, &buffer_len);
5292 ok(ret == TRUE, "GetUserNameA returned %d, last error %lu\n", ret, GetLastError());
5293 ok(memcmp(buffer, filler, sizeof(filler)) != 0, "Output buffer was untouched\n");
5294 ok(buffer_len == required_len ||
5295 broken(buffer_len == required_len / sizeof(WCHAR)), /* XP+ */
5296 "Outputted buffer length was %lu\n", buffer_len);
5297 ok(GetLastError() == 0xdeadbeef, "Last error was %lu\n", GetLastError());
5299 /* Use the reported buffer size from the last GetUserNameA call and pass
5300 * a length that is one less than the required value. */
5301 SetLastError(0xdeadbeef);
5302 memcpy(buffer, filler, sizeof(filler));
5303 buffer_len--;
5304 ret = GetUserNameA(buffer, &buffer_len);
5305 ok(ret == FALSE, "GetUserNameA returned %d\n", ret);
5306 ok(!memcmp(buffer, filler, sizeof(filler)), "Output buffer was untouched\n");
5307 ok(buffer_len == required_len, "Outputted buffer length was %lu\n", buffer_len);
5308 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %lu\n", GetLastError());
5311 static void test_GetUserNameW(void)
5313 WCHAR buffer[UNLEN + 1], filler[UNLEN + 1];
5314 DWORD required_len, buffer_len;
5315 BOOL ret;
5317 /* Test crashes on Windows. */
5318 if (0)
5320 SetLastError(0xdeadbeef);
5321 GetUserNameW(NULL, NULL);
5324 SetLastError(0xdeadbeef);
5325 required_len = 0;
5326 ret = GetUserNameW(NULL, &required_len);
5327 ok(ret == FALSE, "GetUserNameW returned %d\n", ret);
5328 ok(required_len != 0, "Outputted buffer length was %lu\n", required_len);
5329 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %lu\n", GetLastError());
5331 SetLastError(0xdeadbeef);
5332 required_len = 1;
5333 ret = GetUserNameW(NULL, &required_len);
5334 ok(ret == FALSE, "GetUserNameW returned %d\n", ret);
5335 ok(required_len != 0 && required_len != 1, "Outputted buffer length was %lu\n", required_len);
5336 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %lu\n", GetLastError());
5338 /* Tests crash on Windows. */
5339 if (0)
5341 SetLastError(0xdeadbeef);
5342 required_len = UNLEN + 1;
5343 GetUserNameW(NULL, &required_len);
5345 SetLastError(0xdeadbeef);
5346 GetUserNameW(buffer, NULL);
5349 memset(filler, 'x', sizeof(filler));
5351 SetLastError(0xdeadbeef);
5352 memcpy(buffer, filler, sizeof(filler));
5353 required_len = 0;
5354 ret = GetUserNameW(buffer, &required_len);
5355 ok(ret == FALSE, "GetUserNameW returned %d\n", ret);
5356 ok(!memcmp(buffer, filler, sizeof(filler)), "Output buffer was altered\n");
5357 ok(required_len != 0, "Outputted buffer length was %lu\n", required_len);
5358 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %lu\n", GetLastError());
5360 SetLastError(0xdeadbeef);
5361 memcpy(buffer, filler, sizeof(filler));
5362 buffer_len = required_len;
5363 ret = GetUserNameW(buffer, &buffer_len);
5364 ok(ret == TRUE, "GetUserNameW returned %d, last error %lu\n", ret, GetLastError());
5365 ok(memcmp(buffer, filler, sizeof(filler)) != 0, "Output buffer was untouched\n");
5366 ok(buffer_len == required_len, "Outputted buffer length was %lu\n", buffer_len);
5367 ok(GetLastError() == 0xdeadbeef, "Last error was %lu\n", GetLastError());
5369 /* GetUserNameW on XP and newer writes a truncated portion of the username string to the buffer. */
5370 SetLastError(0xdeadbeef);
5371 memcpy(buffer, filler, sizeof(filler));
5372 buffer_len--;
5373 ret = GetUserNameW(buffer, &buffer_len);
5374 ok(ret == FALSE, "GetUserNameW returned %d\n", ret);
5375 ok(!memcmp(buffer, filler, sizeof(filler)) ||
5376 broken(memcmp(buffer, filler, sizeof(filler)) != 0), /* XP+ */
5377 "Output buffer was altered\n");
5378 ok(buffer_len == required_len, "Outputted buffer length was %lu\n", buffer_len);
5379 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %lu\n", GetLastError());
5382 static void test_CreateRestrictedToken(void)
5384 HANDLE process_token, token, r_token;
5385 PTOKEN_GROUPS token_groups, groups2;
5386 LUID_AND_ATTRIBUTES lattr;
5387 SID_AND_ATTRIBUTES sattr;
5388 SECURITY_IMPERSONATION_LEVEL level;
5389 SID *removed_sid = NULL;
5390 char privs_buffer[1000];
5391 TOKEN_PRIVILEGES *privs = (TOKEN_PRIVILEGES *)privs_buffer;
5392 PRIVILEGE_SET priv_set;
5393 TOKEN_TYPE type;
5394 BOOL is_member;
5395 DWORD size;
5396 LUID luid = { 0, 0 };
5397 BOOL ret;
5398 DWORD i;
5400 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &process_token);
5401 ok(ret, "got error %ld\n", GetLastError());
5403 ret = DuplicateTokenEx(process_token, TOKEN_DUPLICATE|TOKEN_ADJUST_GROUPS|TOKEN_QUERY,
5404 NULL, SecurityImpersonation, TokenImpersonation, &token);
5405 ok(ret, "got error %ld\n", GetLastError());
5407 ret = GetTokenInformation(token, TokenGroups, NULL, 0, &size);
5408 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
5409 "got %d with error %ld\n", ret, GetLastError());
5410 token_groups = malloc(size);
5411 ret = GetTokenInformation(token, TokenGroups, token_groups, size, &size);
5412 ok(ret, "got error %ld\n", GetLastError());
5414 for (i = 0; i < token_groups->GroupCount; i++)
5416 if (token_groups->Groups[i].Attributes & SE_GROUP_ENABLED)
5418 removed_sid = token_groups->Groups[i].Sid;
5419 break;
5422 ok(!!removed_sid, "user is not a member of any group\n");
5424 is_member = FALSE;
5425 ret = pCheckTokenMembership(token, removed_sid, &is_member);
5426 ok(ret, "got error %ld\n", GetLastError());
5427 ok(is_member, "not a member\n");
5429 sattr.Sid = removed_sid;
5430 sattr.Attributes = 0;
5431 r_token = NULL;
5432 ret = CreateRestrictedToken(token, 0, 1, &sattr, 0, NULL, 0, NULL, &r_token);
5433 ok(ret, "got error %ld\n", GetLastError());
5435 is_member = TRUE;
5436 ret = pCheckTokenMembership(r_token, removed_sid, &is_member);
5437 ok(ret, "got error %ld\n", GetLastError());
5438 ok(!is_member, "not a member\n");
5440 ret = GetTokenInformation(r_token, TokenGroups, NULL, 0, &size);
5441 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %ld\n",
5442 ret, GetLastError());
5443 groups2 = malloc(size);
5444 ret = GetTokenInformation(r_token, TokenGroups, groups2, size, &size);
5445 ok(ret, "got error %ld\n", GetLastError());
5447 for (i = 0; i < groups2->GroupCount; i++)
5449 if (EqualSid(groups2->Groups[i].Sid, removed_sid))
5451 DWORD attr = groups2->Groups[i].Attributes;
5452 ok(attr & SE_GROUP_USE_FOR_DENY_ONLY, "got wrong attributes %#lx\n", attr);
5453 ok(!(attr & SE_GROUP_ENABLED), "got wrong attributes %#lx\n", attr);
5454 break;
5458 free(groups2);
5460 size = sizeof(type);
5461 ret = GetTokenInformation(r_token, TokenType, &type, size, &size);
5462 ok(ret, "got error %ld\n", GetLastError());
5463 ok(type == TokenImpersonation, "got type %u\n", type);
5465 size = sizeof(level);
5466 ret = GetTokenInformation(r_token, TokenImpersonationLevel, &level, size, &size);
5467 ok(ret, "got error %ld\n", GetLastError());
5468 ok(level == SecurityImpersonation, "got level %u\n", type);
5470 CloseHandle(r_token);
5472 r_token = NULL;
5473 ret = CreateRestrictedToken(process_token, 0, 1, &sattr, 0, NULL, 0, NULL, &r_token);
5474 ok(ret, "got error %lu\n", GetLastError());
5476 size = sizeof(type);
5477 ret = GetTokenInformation(r_token, TokenType, &type, size, &size);
5478 ok(ret, "got error %lu\n", GetLastError());
5479 ok(type == TokenPrimary, "got type %u\n", type);
5481 CloseHandle(r_token);
5483 ret = GetTokenInformation(token, TokenPrivileges, privs, sizeof(privs_buffer), &size);
5484 ok(ret, "got error %lu\n", GetLastError());
5486 for (i = 0; i < privs->PrivilegeCount; i++)
5488 if (privs->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
5490 luid = privs->Privileges[i].Luid;
5491 break;
5494 ok(i < privs->PrivilegeCount, "user has no privileges\n");
5496 lattr.Luid = luid;
5497 lattr.Attributes = 0;
5498 r_token = NULL;
5499 ret = CreateRestrictedToken(token, 0, 0, NULL, 1, &lattr, 0, NULL, &r_token);
5500 ok(ret, "got error %lu\n", GetLastError());
5502 priv_set.PrivilegeCount = 1;
5503 priv_set.Control = 0;
5504 priv_set.Privilege[0].Luid = luid;
5505 priv_set.Privilege[0].Attributes = 0;
5506 ret = PrivilegeCheck(r_token, &priv_set, &is_member);
5507 ok(ret, "got error %lu\n", GetLastError());
5508 ok(!is_member, "privilege should not be enabled\n");
5510 ret = GetTokenInformation(r_token, TokenPrivileges, privs, sizeof(privs_buffer), &size);
5511 ok(ret, "got error %lu\n", GetLastError());
5513 is_member = FALSE;
5514 for (i = 0; i < privs->PrivilegeCount; i++)
5516 if (!memcmp(&privs->Privileges[i].Luid, &luid, sizeof(luid)))
5517 is_member = TRUE;
5519 ok(!is_member, "disabled privilege should not be present\n");
5521 CloseHandle(r_token);
5523 removed_sid->SubAuthority[0] = 0xdeadbeef;
5524 lattr.Luid.LowPart = 0xdeadbeef;
5525 r_token = NULL;
5526 ret = CreateRestrictedToken(token, 0, 1, &sattr, 1, &lattr, 0, NULL, &r_token);
5527 ok(ret, "got error %lu\n", GetLastError());
5528 CloseHandle(r_token);
5530 free(token_groups);
5531 CloseHandle(token);
5532 CloseHandle(process_token);
5535 static void validate_default_security_descriptor(SECURITY_DESCRIPTOR *sd)
5537 BOOL ret, present, defaulted;
5538 ACL *acl;
5539 void *sid;
5541 ret = IsValidSecurityDescriptor(sd);
5542 ok(ret, "security descriptor is not valid\n");
5544 present = -1;
5545 defaulted = -1;
5546 acl = (void *)0xdeadbeef;
5547 SetLastError(0xdeadbeef);
5548 ret = GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted);
5549 ok(ret, "GetSecurityDescriptorDacl error %ld\n", GetLastError());
5550 todo_wine
5551 ok(present == 1, "acl is not present\n");
5552 todo_wine
5553 ok(acl != (void *)0xdeadbeef && acl != NULL, "acl pointer is not set\n");
5554 ok(defaulted == 0, "defaulted is set to TRUE\n");
5556 defaulted = -1;
5557 sid = (void *)0xdeadbeef;
5558 SetLastError(0xdeadbeef);
5559 ret = GetSecurityDescriptorOwner(sd, &sid, &defaulted);
5560 ok(ret, "GetSecurityDescriptorOwner error %ld\n", GetLastError());
5561 todo_wine
5562 ok(sid != (void *)0xdeadbeef && sid != NULL, "sid pointer is not set\n");
5563 ok(defaulted == 0, "defaulted is set to TRUE\n");
5565 defaulted = -1;
5566 sid = (void *)0xdeadbeef;
5567 SetLastError(0xdeadbeef);
5568 ret = GetSecurityDescriptorGroup(sd, &sid, &defaulted);
5569 ok(ret, "GetSecurityDescriptorGroup error %ld\n", GetLastError());
5570 todo_wine
5571 ok(sid != (void *)0xdeadbeef && sid != NULL, "sid pointer is not set\n");
5572 ok(defaulted == 0, "defaulted is set to TRUE\n");
5575 static void test_default_handle_security(HANDLE token, HANDLE handle, GENERIC_MAPPING *mapping)
5577 DWORD ret, granted, priv_set_len;
5578 BOOL status;
5579 PRIVILEGE_SET priv_set;
5580 SECURITY_DESCRIPTOR *sd;
5582 sd = test_get_security_descriptor(handle, __LINE__);
5583 validate_default_security_descriptor(sd);
5585 priv_set_len = sizeof(priv_set);
5586 granted = 0xdeadbeef;
5587 status = 0xdeadbeef;
5588 SetLastError(0xdeadbeef);
5589 ret = AccessCheck(sd, token, MAXIMUM_ALLOWED, mapping, &priv_set, &priv_set_len, &granted, &status);
5590 todo_wine {
5591 ok(ret, "AccessCheck error %ld\n", GetLastError());
5592 ok(status == 1, "expected 1, got %d\n", status);
5593 ok(granted == mapping->GenericAll, "expected all access %#lx, got %#lx\n", mapping->GenericAll, granted);
5595 priv_set_len = sizeof(priv_set);
5596 granted = 0xdeadbeef;
5597 status = 0xdeadbeef;
5598 SetLastError(0xdeadbeef);
5599 ret = AccessCheck(sd, token, 0, mapping, &priv_set, &priv_set_len, &granted, &status);
5600 todo_wine {
5601 ok(ret, "AccessCheck error %ld\n", GetLastError());
5602 ok(status == 0 || broken(status == 1) /* NT4 */, "expected 0, got %d\n", status);
5603 ok(granted == 0 || broken(granted == mapping->GenericRead) /* NT4 */, "expected 0, got %#lx\n", granted);
5605 priv_set_len = sizeof(priv_set);
5606 granted = 0xdeadbeef;
5607 status = 0xdeadbeef;
5608 SetLastError(0xdeadbeef);
5609 ret = AccessCheck(sd, token, ACCESS_SYSTEM_SECURITY, mapping, &priv_set, &priv_set_len, &granted, &status);
5610 todo_wine {
5611 ok(ret, "AccessCheck error %ld\n", GetLastError());
5612 ok(status == 0, "expected 0, got %d\n", status);
5613 ok(granted == 0, "expected 0, got %#lx\n", granted);
5615 priv_set_len = sizeof(priv_set);
5616 granted = 0xdeadbeef;
5617 status = 0xdeadbeef;
5618 SetLastError(0xdeadbeef);
5619 ret = AccessCheck(sd, token, mapping->GenericRead, mapping, &priv_set, &priv_set_len, &granted, &status);
5620 todo_wine {
5621 ok(ret, "AccessCheck error %ld\n", GetLastError());
5622 ok(status == 1, "expected 1, got %d\n", status);
5623 ok(granted == mapping->GenericRead, "expected read access %#lx, got %#lx\n", mapping->GenericRead, granted);
5625 priv_set_len = sizeof(priv_set);
5626 granted = 0xdeadbeef;
5627 status = 0xdeadbeef;
5628 SetLastError(0xdeadbeef);
5629 ret = AccessCheck(sd, token, mapping->GenericWrite, mapping, &priv_set, &priv_set_len, &granted, &status);
5630 todo_wine {
5631 ok(ret, "AccessCheck error %ld\n", GetLastError());
5632 ok(status == 1, "expected 1, got %d\n", status);
5633 ok(granted == mapping->GenericWrite, "expected write access %#lx, got %#lx\n", mapping->GenericWrite, granted);
5635 priv_set_len = sizeof(priv_set);
5636 granted = 0xdeadbeef;
5637 status = 0xdeadbeef;
5638 SetLastError(0xdeadbeef);
5639 ret = AccessCheck(sd, token, mapping->GenericExecute, mapping, &priv_set, &priv_set_len, &granted, &status);
5640 todo_wine {
5641 ok(ret, "AccessCheck error %ld\n", GetLastError());
5642 ok(status == 1, "expected 1, got %d\n", status);
5643 ok(granted == mapping->GenericExecute, "expected execute access %#lx, got %#lx\n", mapping->GenericExecute, granted);
5645 free(sd);
5648 static ACCESS_MASK get_obj_access(HANDLE obj)
5650 OBJECT_BASIC_INFORMATION info;
5651 NTSTATUS status;
5653 if (!pNtQueryObject) return 0;
5655 status = pNtQueryObject(obj, ObjectBasicInformation, &info, sizeof(info), NULL);
5656 ok(!status, "NtQueryObject error %#lx\n", status);
5658 return info.GrantedAccess;
5661 static void test_mutex_security(HANDLE token)
5663 DWORD ret, i, access;
5664 HANDLE mutex, dup;
5665 GENERIC_MAPPING mapping = { STANDARD_RIGHTS_READ | MUTANT_QUERY_STATE | SYNCHRONIZE,
5666 STANDARD_RIGHTS_WRITE | MUTEX_MODIFY_STATE | SYNCHRONIZE,
5667 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
5668 STANDARD_RIGHTS_ALL | MUTEX_ALL_ACCESS };
5669 static const struct
5671 int generic, mapped;
5672 } map[] =
5674 { 0, 0 },
5675 { GENERIC_READ, STANDARD_RIGHTS_READ | MUTANT_QUERY_STATE },
5676 { GENERIC_WRITE, STANDARD_RIGHTS_WRITE },
5677 { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
5678 { GENERIC_ALL, STANDARD_RIGHTS_ALL | MUTANT_QUERY_STATE }
5681 SetLastError(0xdeadbeef);
5682 mutex = OpenMutexA(0, FALSE, "WineTestMutex");
5683 ok(!mutex, "mutex should not exist\n");
5684 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
5686 SetLastError(0xdeadbeef);
5687 mutex = CreateMutexA(NULL, FALSE, "WineTestMutex");
5688 ok(mutex != 0, "CreateMutex error %ld\n", GetLastError());
5690 access = get_obj_access(mutex);
5691 ok(access == MUTANT_ALL_ACCESS, "expected MUTANT_ALL_ACCESS, got %#lx\n", access);
5693 for (i = 0; i < ARRAY_SIZE(map); i++)
5695 SetLastError( 0xdeadbeef );
5696 ret = DuplicateHandle(GetCurrentProcess(), mutex, GetCurrentProcess(), &dup,
5697 map[i].generic, FALSE, 0);
5698 ok(ret, "DuplicateHandle error %ld\n", GetLastError());
5700 access = get_obj_access(dup);
5701 ok(access == map[i].mapped, "%ld: expected %#x, got %#lx\n", i, map[i].mapped, access);
5703 CloseHandle(dup);
5705 SetLastError(0xdeadbeef);
5706 dup = OpenMutexA(0, FALSE, "WineTestMutex");
5707 todo_wine
5708 ok(!dup, "OpenMutex should fail\n");
5709 todo_wine
5710 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %lu\n", GetLastError());
5713 test_default_handle_security(token, mutex, &mapping);
5715 CloseHandle (mutex);
5718 static void test_event_security(HANDLE token)
5720 DWORD ret, i, access;
5721 HANDLE event, dup;
5722 GENERIC_MAPPING mapping = { STANDARD_RIGHTS_READ | EVENT_QUERY_STATE | SYNCHRONIZE,
5723 STANDARD_RIGHTS_WRITE | EVENT_MODIFY_STATE | SYNCHRONIZE,
5724 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
5725 STANDARD_RIGHTS_ALL | EVENT_ALL_ACCESS };
5726 static const struct
5728 int generic, mapped;
5729 } map[] =
5731 { 0, 0 },
5732 { GENERIC_READ, STANDARD_RIGHTS_READ | EVENT_QUERY_STATE },
5733 { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | EVENT_MODIFY_STATE },
5734 { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
5735 { GENERIC_ALL, STANDARD_RIGHTS_ALL | EVENT_QUERY_STATE | EVENT_MODIFY_STATE }
5738 SetLastError(0xdeadbeef);
5739 event = OpenEventA(0, FALSE, "WineTestEvent");
5740 ok(!event, "event should not exist\n");
5741 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
5743 SetLastError(0xdeadbeef);
5744 event = CreateEventA(NULL, FALSE, FALSE, "WineTestEvent");
5745 ok(event != 0, "CreateEvent error %ld\n", GetLastError());
5747 access = get_obj_access(event);
5748 ok(access == EVENT_ALL_ACCESS, "expected EVENT_ALL_ACCESS, got %#lx\n", access);
5750 for (i = 0; i < ARRAY_SIZE(map); i++)
5752 SetLastError( 0xdeadbeef );
5753 ret = DuplicateHandle(GetCurrentProcess(), event, GetCurrentProcess(), &dup,
5754 map[i].generic, FALSE, 0);
5755 ok(ret, "DuplicateHandle error %ld\n", GetLastError());
5757 access = get_obj_access(dup);
5758 ok(access == map[i].mapped, "%ld: expected %#x, got %#lx\n", i, map[i].mapped, access);
5760 CloseHandle(dup);
5762 SetLastError(0xdeadbeef);
5763 dup = OpenEventA(0, FALSE, "WineTestEvent");
5764 todo_wine
5765 ok(!dup, "OpenEvent should fail\n");
5766 todo_wine
5767 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %lu\n", GetLastError());
5770 test_default_handle_security(token, event, &mapping);
5772 CloseHandle(event);
5775 static void test_semaphore_security(HANDLE token)
5777 DWORD ret, i, access;
5778 HANDLE sem, dup;
5779 GENERIC_MAPPING mapping = { STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE,
5780 STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE,
5781 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
5782 STANDARD_RIGHTS_ALL | SEMAPHORE_ALL_ACCESS };
5783 static const struct
5785 int generic, mapped;
5786 } map[] =
5788 { 0, 0 },
5789 { GENERIC_READ, STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE },
5790 { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE },
5791 { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
5792 { GENERIC_ALL, STANDARD_RIGHTS_ALL | SEMAPHORE_QUERY_STATE | SEMAPHORE_MODIFY_STATE }
5795 SetLastError(0xdeadbeef);
5796 sem = OpenSemaphoreA(0, FALSE, "WineTestSemaphore");
5797 ok(!sem, "semaphore should not exist\n");
5798 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
5800 SetLastError(0xdeadbeef);
5801 sem = CreateSemaphoreA(NULL, 0, 10, "WineTestSemaphore");
5802 ok(sem != 0, "CreateSemaphore error %ld\n", GetLastError());
5804 access = get_obj_access(sem);
5805 ok(access == SEMAPHORE_ALL_ACCESS, "expected SEMAPHORE_ALL_ACCESS, got %#lx\n", access);
5807 for (i = 0; i < ARRAY_SIZE(map); i++)
5809 SetLastError( 0xdeadbeef );
5810 ret = DuplicateHandle(GetCurrentProcess(), sem, GetCurrentProcess(), &dup,
5811 map[i].generic, FALSE, 0);
5812 ok(ret, "DuplicateHandle error %ld\n", GetLastError());
5814 access = get_obj_access(dup);
5815 ok(access == map[i].mapped, "%ld: expected %#x, got %#lx\n", i, map[i].mapped, access);
5817 CloseHandle(dup);
5820 test_default_handle_security(token, sem, &mapping);
5822 CloseHandle(sem);
5825 #define WINE_TEST_PIPE "\\\\.\\pipe\\WineTestPipe"
5826 static void test_named_pipe_security(HANDLE token)
5828 DWORD ret, i, access;
5829 HANDLE pipe, file, dup;
5830 GENERIC_MAPPING mapping = { FILE_GENERIC_READ,
5831 FILE_GENERIC_WRITE,
5832 FILE_GENERIC_EXECUTE,
5833 STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS };
5834 static const struct
5836 int generic, mapped;
5837 } map[] =
5839 { 0, 0 },
5840 { GENERIC_READ, FILE_GENERIC_READ },
5841 { GENERIC_WRITE, FILE_GENERIC_WRITE },
5842 { GENERIC_EXECUTE, FILE_GENERIC_EXECUTE },
5843 { GENERIC_ALL, STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS }
5845 static const struct
5847 DWORD open_mode;
5848 DWORD access;
5849 } creation_access[] =
5851 { PIPE_ACCESS_INBOUND, FILE_GENERIC_READ },
5852 { PIPE_ACCESS_OUTBOUND, FILE_GENERIC_WRITE },
5853 { PIPE_ACCESS_DUPLEX, FILE_GENERIC_READ|FILE_GENERIC_WRITE },
5854 { PIPE_ACCESS_INBOUND|WRITE_DAC, FILE_GENERIC_READ|WRITE_DAC },
5855 { PIPE_ACCESS_INBOUND|WRITE_OWNER, FILE_GENERIC_READ|WRITE_OWNER }
5856 /* ACCESS_SYSTEM_SECURITY is also valid, but will fail with ERROR_PRIVILEGE_NOT_HELD */
5859 /* Test the different security access options for pipes */
5860 for (i = 0; i < ARRAY_SIZE(creation_access); i++)
5862 SetLastError(0xdeadbeef);
5863 pipe = CreateNamedPipeA(WINE_TEST_PIPE, creation_access[i].open_mode,
5864 PIPE_TYPE_BYTE | PIPE_NOWAIT, PIPE_UNLIMITED_INSTANCES, 0, 0,
5865 NMPWAIT_USE_DEFAULT_WAIT, NULL);
5866 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe(0x%lx) error %ld\n",
5867 creation_access[i].open_mode, GetLastError());
5868 access = get_obj_access(pipe);
5869 ok(access == creation_access[i].access,
5870 "CreateNamedPipeA(0x%lx) pipe expected access 0x%lx (got 0x%lx)\n",
5871 creation_access[i].open_mode, creation_access[i].access, access);
5872 CloseHandle(pipe);
5875 SetLastError(0xdeadbeef);
5876 pipe = CreateNamedPipeA(WINE_TEST_PIPE, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,
5877 PIPE_TYPE_BYTE | PIPE_NOWAIT, PIPE_UNLIMITED_INSTANCES,
5878 0, 0, NMPWAIT_USE_DEFAULT_WAIT, NULL);
5879 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe error %ld\n", GetLastError());
5881 test_default_handle_security(token, pipe, &mapping);
5883 SetLastError(0xdeadbeef);
5884 file = CreateFileA(WINE_TEST_PIPE, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, 0, 0);
5885 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
5887 access = get_obj_access(file);
5888 ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#lx\n", access);
5890 for (i = 0; i < ARRAY_SIZE(map); i++)
5892 SetLastError( 0xdeadbeef );
5893 ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup,
5894 map[i].generic, FALSE, 0);
5895 ok(ret, "DuplicateHandle error %ld\n", GetLastError());
5897 access = get_obj_access(dup);
5898 ok(access == map[i].mapped, "%ld: expected %#x, got %#lx\n", i, map[i].mapped, access);
5900 CloseHandle(dup);
5903 CloseHandle(file);
5904 CloseHandle(pipe);
5906 SetLastError(0xdeadbeef);
5907 file = CreateFileA("\\\\.\\pipe\\", FILE_ALL_ACCESS, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
5908 ok(file != INVALID_HANDLE_VALUE || broken(file == INVALID_HANDLE_VALUE) /* before Vista */, "CreateFile error %ld\n", GetLastError());
5910 if (file != INVALID_HANDLE_VALUE)
5912 access = get_obj_access(file);
5913 ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#lx\n", access);
5915 for (i = 0; i < ARRAY_SIZE(map); i++)
5917 SetLastError( 0xdeadbeef );
5918 ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup,
5919 map[i].generic, FALSE, 0);
5920 ok(ret, "DuplicateHandle error %ld\n", GetLastError());
5922 access = get_obj_access(dup);
5923 ok(access == map[i].mapped, "%ld: expected %#x, got %#lx\n", i, map[i].mapped, access);
5924 CloseHandle(dup);
5928 CloseHandle(file);
5931 static void test_file_security(HANDLE token)
5933 DWORD ret, i, access, bytes;
5934 HANDLE file, dup;
5935 static const struct
5937 int generic, mapped;
5938 } map[] =
5940 { 0, 0 },
5941 { GENERIC_READ, FILE_GENERIC_READ },
5942 { GENERIC_WRITE, FILE_GENERIC_WRITE },
5943 { GENERIC_EXECUTE, FILE_GENERIC_EXECUTE },
5944 { GENERIC_ALL, STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS }
5946 char temp_path[MAX_PATH];
5947 char file_name[MAX_PATH];
5948 char buf[16];
5950 GetTempPathA(MAX_PATH, temp_path);
5951 GetTempFileNameA(temp_path, "tmp", 0, file_name);
5953 /* file */
5954 SetLastError(0xdeadbeef);
5955 file = CreateFileA(file_name, GENERIC_ALL, 0, NULL, CREATE_ALWAYS, 0, NULL);
5956 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
5958 access = get_obj_access(file);
5959 ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#lx\n", access);
5961 for (i = 0; i < ARRAY_SIZE(map); i++)
5963 SetLastError( 0xdeadbeef );
5964 ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup,
5965 map[i].generic, FALSE, 0);
5966 ok(ret, "DuplicateHandle error %ld\n", GetLastError());
5968 access = get_obj_access(dup);
5969 ok(access == map[i].mapped, "%ld: expected %#x, got %#lx\n", i, map[i].mapped, access);
5971 CloseHandle(dup);
5974 CloseHandle(file);
5976 SetLastError(0xdeadbeef);
5977 file = CreateFileA(file_name, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
5978 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
5980 access = get_obj_access(file);
5981 ok(access == (FILE_READ_ATTRIBUTES | SYNCHRONIZE), "expected FILE_READ_ATTRIBUTES | SYNCHRONIZE, got %#lx\n", access);
5983 bytes = 0xdeadbeef;
5984 SetLastError(0xdeadbeef);
5985 ret = ReadFile(file, buf, sizeof(buf), &bytes, NULL);
5986 ok(!ret, "ReadFile should fail\n");
5987 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
5988 ok(bytes == 0, "expected 0, got %lu\n", bytes);
5990 CloseHandle(file);
5992 SetLastError(0xdeadbeef);
5993 file = CreateFileA(file_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
5994 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
5996 access = get_obj_access(file);
5997 ok(access == (FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES), "expected FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES, got %#lx\n", access);
5999 bytes = 0xdeadbeef;
6000 SetLastError(0xdeadbeef);
6001 ret = ReadFile(file, buf, sizeof(buf), &bytes, NULL);
6002 ok(!ret, "ReadFile should fail\n");
6003 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
6004 ok(bytes == 0, "expected 0, got %lu\n", bytes);
6006 CloseHandle(file);
6007 DeleteFileA(file_name);
6009 /* directory */
6010 SetLastError(0xdeadbeef);
6011 file = CreateFileA(temp_path, GENERIC_ALL, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
6012 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
6014 access = get_obj_access(file);
6015 ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#lx\n", access);
6017 for (i = 0; i < ARRAY_SIZE(map); i++)
6019 SetLastError( 0xdeadbeef );
6020 ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup,
6021 map[i].generic, FALSE, 0);
6022 ok(ret, "DuplicateHandle error %ld\n", GetLastError());
6024 access = get_obj_access(dup);
6025 ok(access == map[i].mapped, "%ld: expected %#x, got %#lx\n", i, map[i].mapped, access);
6027 CloseHandle(dup);
6030 CloseHandle(file);
6032 SetLastError(0xdeadbeef);
6033 file = CreateFileA(temp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
6034 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
6036 access = get_obj_access(file);
6037 ok(access == (FILE_READ_ATTRIBUTES | SYNCHRONIZE), "expected FILE_READ_ATTRIBUTES | SYNCHRONIZE, got %#lx\n", access);
6039 CloseHandle(file);
6041 SetLastError(0xdeadbeef);
6042 file = CreateFileA(temp_path, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
6043 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
6045 access = get_obj_access(file);
6046 ok(access == (FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES), "expected FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES, got %#lx\n", access);
6048 CloseHandle(file);
6051 static void test_filemap_security(void)
6053 char temp_path[MAX_PATH];
6054 char file_name[MAX_PATH];
6055 DWORD ret, i, access;
6056 HANDLE file, mapping, dup, created_mapping;
6057 static const struct
6059 int generic, mapped;
6060 BOOL open_only;
6061 } map[] =
6063 { 0, 0 },
6064 { GENERIC_READ, STANDARD_RIGHTS_READ | SECTION_QUERY | SECTION_MAP_READ },
6065 { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | SECTION_MAP_WRITE },
6066 { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SECTION_MAP_EXECUTE },
6067 { GENERIC_ALL, STANDARD_RIGHTS_REQUIRED | SECTION_ALL_ACCESS },
6068 { SECTION_MAP_READ | SECTION_MAP_WRITE, SECTION_MAP_READ | SECTION_MAP_WRITE },
6069 { SECTION_MAP_WRITE, SECTION_MAP_WRITE },
6070 { SECTION_MAP_READ | SECTION_QUERY, SECTION_MAP_READ | SECTION_QUERY },
6071 { SECTION_QUERY, SECTION_MAP_READ, TRUE },
6072 { SECTION_QUERY | SECTION_MAP_READ, SECTION_QUERY | SECTION_MAP_READ }
6074 static const struct
6076 int prot, mapped;
6077 } prot_map[] =
6079 { 0, 0 },
6080 { PAGE_NOACCESS, 0 },
6081 { PAGE_READONLY, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ },
6082 { PAGE_READWRITE, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE },
6083 { PAGE_WRITECOPY, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ },
6084 { PAGE_EXECUTE, 0 },
6085 { PAGE_EXECUTE_READ, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE },
6086 { PAGE_EXECUTE_READWRITE, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE },
6087 { PAGE_EXECUTE_WRITECOPY, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE }
6090 GetTempPathA(MAX_PATH, temp_path);
6091 GetTempFileNameA(temp_path, "tmp", 0, file_name);
6093 SetLastError(0xdeadbeef);
6094 file = CreateFileA(file_name, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, CREATE_ALWAYS, 0, 0);
6095 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %ld\n", GetLastError());
6096 SetFilePointer(file, 4096, NULL, FILE_BEGIN);
6097 SetEndOfFile(file);
6099 for (i = 0; i < ARRAY_SIZE(prot_map); i++)
6101 if (map[i].open_only) continue;
6103 SetLastError(0xdeadbeef);
6104 mapping = CreateFileMappingW(file, NULL, prot_map[i].prot, 0, 4096, NULL);
6105 if (prot_map[i].mapped)
6107 if (!mapping)
6109 /* NT4 and win2k don't support EXEC on file mappings */
6110 if (prot_map[i].prot == PAGE_EXECUTE_READ || prot_map[i].prot == PAGE_EXECUTE_READWRITE || prot_map[i].prot == PAGE_EXECUTE_WRITECOPY)
6112 win_skip("CreateFileMapping doesn't support PAGE_EXECUTE protection\n");
6113 continue;
6116 ok(mapping != 0, "CreateFileMapping(%04x) error %ld\n", prot_map[i].prot, GetLastError());
6118 else
6120 ok(!mapping, "CreateFileMapping(%04x) should fail\n", prot_map[i].prot);
6121 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
6122 continue;
6125 access = get_obj_access(mapping);
6126 ok(access == prot_map[i].mapped, "%ld: expected %#x, got %#lx\n", i, prot_map[i].mapped, access);
6128 CloseHandle(mapping);
6131 SetLastError(0xdeadbeef);
6132 mapping = CreateFileMappingW(file, NULL, PAGE_EXECUTE_READWRITE, 0, 4096, NULL);
6133 if (!mapping)
6135 /* NT4 and win2k don't support EXEC on file mappings */
6136 win_skip("CreateFileMapping doesn't support PAGE_EXECUTE protection\n");
6137 CloseHandle(file);
6138 DeleteFileA(file_name);
6139 return;
6141 ok(mapping != 0, "CreateFileMapping error %ld\n", GetLastError());
6143 access = get_obj_access(mapping);
6144 ok(access == (STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE),
6145 "expected STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE, got %#lx\n", access);
6147 for (i = 0; i < ARRAY_SIZE(map); i++)
6149 if (map[i].open_only) continue;
6151 SetLastError( 0xdeadbeef );
6152 ret = DuplicateHandle(GetCurrentProcess(), mapping, GetCurrentProcess(), &dup,
6153 map[i].generic, FALSE, 0);
6154 ok(ret, "DuplicateHandle error %ld\n", GetLastError());
6156 access = get_obj_access(dup);
6157 ok(access == map[i].mapped, "%ld: expected %#x, got %#lx\n", i, map[i].mapped, access);
6159 CloseHandle(dup);
6162 CloseHandle(mapping);
6163 CloseHandle(file);
6164 DeleteFileA(file_name);
6166 created_mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 0x1000,
6167 "Wine Test Open Mapping");
6168 ok(created_mapping != NULL, "CreateFileMapping failed with error %lu\n", GetLastError());
6170 for (i = 0; i < ARRAY_SIZE(map); i++)
6172 if (!map[i].generic) continue;
6174 mapping = OpenFileMappingA(map[i].generic, FALSE, "Wine Test Open Mapping");
6175 ok(mapping != NULL, "OpenFileMapping failed with error %ld\n", GetLastError());
6176 access = get_obj_access(mapping);
6177 ok(access == map[i].mapped, "%ld: unexpected access flags %#lx, expected %#x\n",
6178 i, access, map[i].mapped);
6179 CloseHandle(mapping);
6182 CloseHandle(created_mapping);
6185 static void test_thread_security(void)
6187 DWORD ret, i, access;
6188 HANDLE thread, dup;
6189 static const struct
6191 int generic, mapped;
6192 } map[] =
6194 { 0, 0 },
6195 { GENERIC_READ, STANDARD_RIGHTS_READ | THREAD_QUERY_INFORMATION | THREAD_GET_CONTEXT },
6196 { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | THREAD_SET_INFORMATION | THREAD_SET_CONTEXT | THREAD_TERMINATE | THREAD_SUSPEND_RESUME | 0x4 },
6197 { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
6198 { GENERIC_ALL, THREAD_ALL_ACCESS_NT4 }
6201 SetLastError(0xdeadbeef);
6202 thread = CreateThread(NULL, 0, (void *)0xdeadbeef, NULL, CREATE_SUSPENDED, &ret);
6203 ok(thread != 0, "CreateThread error %ld\n", GetLastError());
6205 access = get_obj_access(thread);
6206 ok(access == THREAD_ALL_ACCESS_NT4 || access == THREAD_ALL_ACCESS_VISTA, "expected THREAD_ALL_ACCESS, got %#lx\n", access);
6208 for (i = 0; i < ARRAY_SIZE(map); i++)
6210 SetLastError( 0xdeadbeef );
6211 ret = DuplicateHandle(GetCurrentProcess(), thread, GetCurrentProcess(), &dup,
6212 map[i].generic, FALSE, 0);
6213 ok(ret, "DuplicateHandle error %ld\n", GetLastError());
6215 access = get_obj_access(dup);
6216 switch (map[i].generic)
6218 case GENERIC_READ:
6219 case GENERIC_EXECUTE:
6220 ok(access == map[i].mapped ||
6221 access == (map[i].mapped | THREAD_QUERY_LIMITED_INFORMATION) /* Vista+ */ ||
6222 access == (map[i].mapped | THREAD_QUERY_LIMITED_INFORMATION | THREAD_RESUME) /* win8 */,
6223 "%ld: expected %#x, got %#lx\n", i, map[i].mapped, access);
6224 break;
6225 case GENERIC_WRITE:
6226 ok(access == map[i].mapped ||
6227 access == (map[i].mapped | THREAD_SET_LIMITED_INFORMATION) /* Vista+ */ ||
6228 access == (map[i].mapped | THREAD_SET_LIMITED_INFORMATION | THREAD_RESUME) /* win8 */,
6229 "%ld: expected %#x, got %#lx\n", i, map[i].mapped, access);
6230 break;
6231 case GENERIC_ALL:
6232 ok(access == map[i].mapped || access == THREAD_ALL_ACCESS_VISTA,
6233 "%ld: expected %#x, got %#lx\n", i, map[i].mapped, access);
6234 break;
6235 default:
6236 ok(access == map[i].mapped, "%ld: expected %#x, got %#lx\n", i, map[i].mapped, access);
6237 break;
6240 CloseHandle(dup);
6243 SetLastError( 0xdeadbeef );
6244 ret = DuplicateHandle(GetCurrentProcess(), thread, GetCurrentProcess(), &dup,
6245 THREAD_QUERY_INFORMATION, FALSE, 0);
6246 ok(ret, "DuplicateHandle error %ld\n", GetLastError());
6247 access = get_obj_access(dup);
6248 ok(access == (THREAD_QUERY_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION) /* Vista+ */ ||
6249 access == THREAD_QUERY_INFORMATION /* before Vista */,
6250 "expected THREAD_QUERY_INFORMATION|THREAD_QUERY_LIMITED_INFORMATION, got %#lx\n", access);
6251 CloseHandle(dup);
6253 TerminateThread(thread, 0);
6254 CloseHandle(thread);
6257 static void test_process_access(void)
6259 DWORD ret, i, access;
6260 HANDLE process, dup;
6261 STARTUPINFOA sti;
6262 PROCESS_INFORMATION pi;
6263 char cmdline[] = "winver.exe";
6264 static const struct
6266 int generic, mapped;
6267 } map[] =
6269 { 0, 0 },
6270 { GENERIC_READ, STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ },
6271 { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION | PROCESS_SUSPEND_RESUME |
6272 PROCESS_VM_WRITE | PROCESS_DUP_HANDLE | PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION },
6273 { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
6274 { GENERIC_ALL, PROCESS_ALL_ACCESS_NT4 }
6277 memset(&sti, 0, sizeof(sti));
6278 sti.cb = sizeof(sti);
6279 SetLastError(0xdeadbeef);
6280 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &sti, &pi);
6281 ok(ret, "CreateProcess() error %ld\n", GetLastError());
6283 CloseHandle(pi.hThread);
6284 process = pi.hProcess;
6286 access = get_obj_access(process);
6287 ok(access == PROCESS_ALL_ACCESS_NT4 || access == PROCESS_ALL_ACCESS_VISTA, "expected PROCESS_ALL_ACCESS, got %#lx\n", access);
6289 for (i = 0; i < ARRAY_SIZE(map); i++)
6291 SetLastError( 0xdeadbeef );
6292 ret = DuplicateHandle(GetCurrentProcess(), process, GetCurrentProcess(), &dup,
6293 map[i].generic, FALSE, 0);
6294 ok(ret, "DuplicateHandle error %ld\n", GetLastError());
6296 access = get_obj_access(dup);
6297 switch (map[i].generic)
6299 case GENERIC_READ:
6300 ok(access == map[i].mapped || access == (map[i].mapped | PROCESS_QUERY_LIMITED_INFORMATION) /* Vista+ */,
6301 "%ld: expected %#x, got %#lx\n", i, map[i].mapped, access);
6302 break;
6303 case GENERIC_WRITE:
6304 ok(access == map[i].mapped ||
6305 access == (map[i].mapped | PROCESS_TERMINATE) /* before Vista */ ||
6306 access == (map[i].mapped | PROCESS_SET_LIMITED_INFORMATION) /* win8 */ ||
6307 access == (map[i].mapped | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_SET_LIMITED_INFORMATION) /* Win10 Anniversary Update */,
6308 "%ld: expected %#x, got %#lx\n", i, map[i].mapped, access);
6309 break;
6310 case GENERIC_EXECUTE:
6311 ok(access == map[i].mapped || access == (map[i].mapped | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE) /* Vista+ */,
6312 "%ld: expected %#x, got %#lx\n", i, map[i].mapped, access);
6313 break;
6314 case GENERIC_ALL:
6315 ok(access == map[i].mapped || access == PROCESS_ALL_ACCESS_VISTA,
6316 "%ld: expected %#x, got %#lx\n", i, map[i].mapped, access);
6317 break;
6318 default:
6319 ok(access == map[i].mapped, "%ld: expected %#x, got %#lx\n", i, map[i].mapped, access);
6320 break;
6323 CloseHandle(dup);
6326 SetLastError( 0xdeadbeef );
6327 ret = DuplicateHandle(GetCurrentProcess(), process, GetCurrentProcess(), &dup,
6328 PROCESS_QUERY_INFORMATION, FALSE, 0);
6329 ok(ret, "DuplicateHandle error %ld\n", GetLastError());
6330 access = get_obj_access(dup);
6331 ok(access == (PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION) /* Vista+ */ ||
6332 access == PROCESS_QUERY_INFORMATION /* before Vista */,
6333 "expected PROCESS_QUERY_INFORMATION|PROCESS_QUERY_LIMITED_INFORMATION, got %#lx\n", access);
6334 CloseHandle(dup);
6336 TerminateProcess(process, 0);
6337 CloseHandle(process);
6340 static BOOL validate_impersonation_token(HANDLE token, DWORD *token_type)
6342 DWORD ret, needed;
6343 TOKEN_TYPE type;
6344 SECURITY_IMPERSONATION_LEVEL sil;
6346 type = 0xdeadbeef;
6347 needed = 0;
6348 SetLastError(0xdeadbeef);
6349 ret = GetTokenInformation(token, TokenType, &type, sizeof(type), &needed);
6350 ok(ret, "GetTokenInformation error %ld\n", GetLastError());
6351 ok(needed == sizeof(type), "GetTokenInformation should return required buffer length\n");
6352 ok(type == TokenPrimary || type == TokenImpersonation, "expected TokenPrimary or TokenImpersonation, got %d\n", type);
6354 *token_type = type;
6355 if (type != TokenImpersonation) return FALSE;
6357 needed = 0;
6358 SetLastError(0xdeadbeef);
6359 ret = GetTokenInformation(token, TokenImpersonationLevel, &sil, sizeof(sil), &needed);
6360 ok(ret, "GetTokenInformation error %ld\n", GetLastError());
6361 ok(needed == sizeof(sil), "GetTokenInformation should return required buffer length\n");
6362 ok(sil == SecurityImpersonation, "expected SecurityImpersonation, got %d\n", sil);
6364 needed = 0xdeadbeef;
6365 SetLastError(0xdeadbeef);
6366 ret = GetTokenInformation(token, TokenDefaultDacl, NULL, 0, &needed);
6367 ok(!ret, "GetTokenInformation should fail\n");
6368 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
6369 ok(needed != 0xdeadbeef, "GetTokenInformation should return required buffer length\n");
6370 ok(needed > sizeof(TOKEN_DEFAULT_DACL), "GetTokenInformation returned empty default DACL\n");
6372 needed = 0xdeadbeef;
6373 SetLastError(0xdeadbeef);
6374 ret = GetTokenInformation(token, TokenOwner, NULL, 0, &needed);
6375 ok(!ret, "GetTokenInformation should fail\n");
6376 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
6377 ok(needed != 0xdeadbeef, "GetTokenInformation should return required buffer length\n");
6378 ok(needed > sizeof(TOKEN_OWNER), "GetTokenInformation returned empty token owner\n");
6380 needed = 0xdeadbeef;
6381 SetLastError(0xdeadbeef);
6382 ret = GetTokenInformation(token, TokenPrimaryGroup, NULL, 0, &needed);
6383 ok(!ret, "GetTokenInformation should fail\n");
6384 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
6385 ok(needed != 0xdeadbeef, "GetTokenInformation should return required buffer length\n");
6386 ok(needed > sizeof(TOKEN_PRIMARY_GROUP), "GetTokenInformation returned empty token primary group\n");
6388 return TRUE;
6391 static void test_kernel_objects_security(void)
6393 HANDLE token, process_token;
6394 DWORD ret, token_type;
6396 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_QUERY, &process_token);
6397 ok(ret, "OpenProcessToken error %ld\n", GetLastError());
6399 ret = validate_impersonation_token(process_token, &token_type);
6400 ok(token_type == TokenPrimary, "expected TokenPrimary, got %ld\n", token_type);
6401 ok(!ret, "access token should not be an impersonation token\n");
6403 ret = DuplicateToken(process_token, SecurityImpersonation, &token);
6404 ok(ret, "DuplicateToken error %ld\n", GetLastError());
6406 ret = validate_impersonation_token(token, &token_type);
6407 ok(ret, "access token should be a valid impersonation token\n");
6408 ok(token_type == TokenImpersonation, "expected TokenImpersonation, got %ld\n", token_type);
6410 test_mutex_security(token);
6411 test_event_security(token);
6412 test_named_pipe_security(token);
6413 test_semaphore_security(token);
6414 test_file_security(token);
6415 test_filemap_security();
6416 test_thread_security();
6417 test_process_access();
6418 /* FIXME: test other kernel object types */
6420 CloseHandle(process_token);
6421 CloseHandle(token);
6424 static void test_TokenIntegrityLevel(void)
6426 TOKEN_MANDATORY_LABEL *tml;
6427 BYTE buffer[64]; /* using max. 28 byte in win7 x64 */
6428 HANDLE token;
6429 DWORD size;
6430 DWORD res;
6431 static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
6432 {SECURITY_MANDATORY_HIGH_RID}};
6433 static SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
6434 {SECURITY_MANDATORY_MEDIUM_RID}};
6436 SetLastError(0xdeadbeef);
6437 res = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
6438 ok(res, "got %ld with %ld (expected TRUE)\n", res, GetLastError());
6440 SetLastError(0xdeadbeef);
6441 res = GetTokenInformation(token, TokenIntegrityLevel, buffer, sizeof(buffer), &size);
6443 /* not supported before Vista */
6444 if (!res && ((GetLastError() == ERROR_INVALID_PARAMETER) || GetLastError() == ERROR_INVALID_FUNCTION))
6446 win_skip("TokenIntegrityLevel not supported\n");
6447 CloseHandle(token);
6448 return;
6451 ok(res, "got %lu with %lu (expected TRUE)\n", res, GetLastError());
6452 if (!res)
6454 CloseHandle(token);
6455 return;
6458 tml = (TOKEN_MANDATORY_LABEL*) buffer;
6459 ok(tml->Label.Attributes == (SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED),
6460 "got 0x%lx (expected 0x%x)\n", tml->Label.Attributes, (SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED));
6462 ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level),
6463 "got %s (expected %s or %s)\n", debugstr_sid(tml->Label.Sid),
6464 debugstr_sid(&medium_level), debugstr_sid(&high_level));
6466 CloseHandle(token);
6469 static void test_default_dacl_owner_group_sid(void)
6471 TOKEN_USER *token_user;
6472 TOKEN_OWNER *token_owner;
6473 TOKEN_PRIMARY_GROUP *token_primary_group;
6474 HANDLE handle, token;
6475 BOOL ret, defaulted, present, found;
6476 DWORD size, index;
6477 SECURITY_DESCRIPTOR *sd;
6478 SECURITY_ATTRIBUTES sa;
6479 PSID owner, group;
6480 ACL *dacl;
6481 ACCESS_ALLOWED_ACE *ace;
6483 ret = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &token );
6484 ok(ret, "OpenProcessToken failed with error %ld\n", GetLastError());
6486 token_user = get_alloc_token_user( token );
6487 token_owner = get_alloc_token_owner( token );
6488 token_primary_group = get_alloc_token_primary_group( token );
6490 CloseHandle( token );
6492 sd = malloc( SECURITY_DESCRIPTOR_MIN_LENGTH );
6493 ret = InitializeSecurityDescriptor( sd, SECURITY_DESCRIPTOR_REVISION );
6494 ok( ret, "error %lu\n", GetLastError() );
6496 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
6497 sa.lpSecurityDescriptor = sd;
6498 sa.bInheritHandle = FALSE;
6499 handle = CreateEventA( &sa, TRUE, TRUE, "test_event" );
6500 ok( handle != NULL, "error %lu\n", GetLastError() );
6502 size = 0;
6503 ret = GetKernelObjectSecurity( handle, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, NULL, 0, &size );
6504 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "error %lu\n", GetLastError() );
6506 sd = malloc( size );
6507 ret = GetKernelObjectSecurity( handle, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, sd, size, &size );
6508 ok( ret, "error %lu\n", GetLastError() );
6510 owner = (void *)0xdeadbeef;
6511 defaulted = TRUE;
6512 ret = GetSecurityDescriptorOwner( sd, &owner, &defaulted );
6513 ok( ret, "error %lu\n", GetLastError() );
6514 ok( owner != (void *)0xdeadbeef, "owner not set\n" );
6515 ok( !defaulted, "owner defaulted\n" );
6516 ok( EqualSid( owner, token_owner->Owner ), "owner shall equal token owner\n" );
6518 group = (void *)0xdeadbeef;
6519 defaulted = TRUE;
6520 ret = GetSecurityDescriptorGroup( sd, &group, &defaulted );
6521 ok( ret, "error %lu\n", GetLastError() );
6522 ok( group != (void *)0xdeadbeef, "group not set\n" );
6523 ok( !defaulted, "group defaulted\n" );
6524 ok( EqualSid( group, token_primary_group->PrimaryGroup ), "group shall equal token primary group\n" );
6526 dacl = (void *)0xdeadbeef;
6527 present = FALSE;
6528 defaulted = TRUE;
6529 ret = GetSecurityDescriptorDacl( sd, &present, &dacl, &defaulted );
6530 ok( ret, "error %lu\n", GetLastError() );
6531 ok( present, "dacl not present\n" );
6532 ok( dacl != (void *)0xdeadbeef, "dacl not set\n" );
6533 ok( !defaulted, "dacl defaulted\n" );
6535 index = 0;
6536 found = FALSE;
6537 while (GetAce( dacl, index++, (void **)&ace ))
6539 ok( ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE,
6540 "expected ACCESS_ALLOWED_ACE_TYPE, got %d\n", ace->Header.AceType );
6541 if (EqualSid( &ace->SidStart, owner )) found = TRUE;
6543 ok( found, "owner sid not found in dacl\n" );
6545 if (!EqualSid( token_user->User.Sid, token_owner->Owner ))
6547 index = 0;
6548 found = FALSE;
6549 while (GetAce( dacl, index++, (void **)&ace ))
6551 ok( ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE,
6552 "expected ACCESS_ALLOWED_ACE_TYPE, got %d\n", ace->Header.AceType );
6553 if (EqualSid( &ace->SidStart, token_user->User.Sid )) found = TRUE;
6555 ok( !found, "DACL shall not reference token user if it is different from token owner\n" );
6558 free( sa.lpSecurityDescriptor );
6559 free( sd );
6560 CloseHandle( handle );
6562 free( token_primary_group );
6563 free( token_owner );
6564 free( token_user );
6567 static void test_AdjustTokenPrivileges(void)
6569 TOKEN_PRIVILEGES tp;
6570 HANDLE token;
6571 DWORD len;
6572 LUID luid;
6573 BOOL ret;
6575 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
6576 return;
6578 if (!LookupPrivilegeValueA(NULL, SE_BACKUP_NAME, &luid))
6580 CloseHandle(token);
6581 return;
6584 tp.PrivilegeCount = 1;
6585 tp.Privileges[0].Luid = luid;
6586 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
6588 len = 0xdeadbeef;
6589 ret = AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, &len);
6590 ok(ret, "got %d\n", ret);
6591 ok(len == 0xdeadbeef, "got length %ld\n", len);
6593 /* revert */
6594 tp.PrivilegeCount = 1;
6595 tp.Privileges[0].Luid = luid;
6596 tp.Privileges[0].Attributes = 0;
6597 ret = AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
6598 ok(ret, "got %d\n", ret);
6600 CloseHandle(token);
6603 static void test_AddAce(void)
6605 static SID const sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
6607 char acl_buf[1024], ace_buf[256];
6608 ACCESS_ALLOWED_ACE *ace = (ACCESS_ALLOWED_ACE*)ace_buf;
6609 PACL acl = (PACL)acl_buf;
6610 BOOL ret;
6612 memset(ace, 0, sizeof(ace_buf));
6613 ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
6614 ace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD)+sizeof(SID);
6615 memcpy(&ace->SidStart, &sidWorld, sizeof(sidWorld));
6617 ret = InitializeAcl(acl, sizeof(acl_buf), ACL_REVISION2);
6618 ok(ret, "InitializeAcl failed: %ld\n", GetLastError());
6620 ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize);
6621 ok(ret, "AddAce failed: %ld\n", GetLastError());
6622 ret = AddAce(acl, ACL_REVISION2, MAXDWORD, ace, ace->Header.AceSize);
6623 ok(ret, "AddAce failed: %ld\n", GetLastError());
6624 ret = AddAce(acl, ACL_REVISION3, MAXDWORD, ace, ace->Header.AceSize);
6625 ok(ret, "AddAce failed: %ld\n", GetLastError());
6626 ok(acl->AclRevision == ACL_REVISION3, "acl->AclRevision = %d\n", acl->AclRevision);
6627 ret = AddAce(acl, ACL_REVISION4, MAXDWORD, ace, ace->Header.AceSize);
6628 ok(ret, "AddAce failed: %ld\n", GetLastError());
6629 ok(acl->AclRevision == ACL_REVISION4, "acl->AclRevision = %d\n", acl->AclRevision);
6630 ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize);
6631 ok(ret, "AddAce failed: %ld\n", GetLastError());
6632 ok(acl->AclRevision == ACL_REVISION4, "acl->AclRevision = %d\n", acl->AclRevision);
6633 ret = AddAce(acl, ACL_REVISION2, MAXDWORD, ace, ace->Header.AceSize);
6634 ok(ret, "AddAce failed: %ld\n", GetLastError());
6636 ret = AddAce(acl, MIN_ACL_REVISION-1, MAXDWORD, ace, ace->Header.AceSize);
6637 ok(ret, "AddAce failed: %ld\n", GetLastError());
6638 /* next test succeededs but corrupts ACL */
6639 ret = AddAce(acl, MAX_ACL_REVISION+1, MAXDWORD, ace, ace->Header.AceSize);
6640 ok(ret, "AddAce failed: %ld\n", GetLastError());
6641 ok(acl->AclRevision == MAX_ACL_REVISION+1, "acl->AclRevision = %d\n", acl->AclRevision);
6642 SetLastError(0xdeadbeef);
6643 ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize);
6644 ok(!ret, "AddAce succeeded\n");
6645 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError() = %ld\n", GetLastError());
6648 static void test_AddMandatoryAce(void)
6650 static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
6651 {SECURITY_MANDATORY_LOW_RID}};
6652 static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
6653 {SECURITY_MANDATORY_MEDIUM_RID}};
6654 static SID_IDENTIFIER_AUTHORITY sia_world = {SECURITY_WORLD_SID_AUTHORITY};
6655 char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
6656 SECURITY_DESCRIPTOR *sd2, *sd = (SECURITY_DESCRIPTOR *)&buffer_sd;
6657 BOOL defaulted, present, ret;
6658 ACL_SIZE_INFORMATION acl_size_info;
6659 SYSTEM_MANDATORY_LABEL_ACE *ace;
6660 char buffer_acl[256];
6661 ACL *acl = (ACL *)&buffer_acl;
6662 SECURITY_ATTRIBUTES sa;
6663 DWORD size;
6664 HANDLE handle;
6665 SID *everyone;
6666 ACL *sacl;
6668 if (!pAddMandatoryAce)
6670 win_skip("AddMandatoryAce not supported, skipping test\n");
6671 return;
6674 ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
6675 ok(ret, "InitializeSecurityDescriptor failed with error %lu\n", GetLastError());
6677 sa.nLength = sizeof(sa);
6678 sa.lpSecurityDescriptor = sd;
6679 sa.bInheritHandle = FALSE;
6681 handle = CreateEventA(&sa, TRUE, TRUE, "test_event");
6682 ok(handle != NULL, "CreateEventA failed with error %lu\n", GetLastError());
6684 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6685 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6686 "Unexpected GetKernelObjectSecurity return value %u, error %lu\n", ret, GetLastError());
6688 sd2 = malloc(size);
6689 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6690 ok(ret, "GetKernelObjectSecurity failed with error %lu\n", GetLastError());
6692 sacl = (void *)0xdeadbeef;
6693 present = TRUE;
6694 ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6695 ok(ret, "GetSecurityDescriptorSacl failed with error %lu\n", GetLastError());
6696 ok(!present, "SACL is present\n");
6697 ok(sacl == (void *)0xdeadbeef, "SACL is set\n");
6699 free(sd2);
6700 CloseHandle(handle);
6702 memset(buffer_acl, 0, sizeof(buffer_acl));
6703 ret = InitializeAcl(acl, 256, ACL_REVISION);
6704 ok(ret, "InitializeAcl failed with %lu\n", GetLastError());
6706 SetLastError(0xdeadbeef);
6707 ret = pAddMandatoryAce(acl, ACL_REVISION, 0, 0x1234, &low_level);
6708 ok(!ret, "AddMandatoryAce succeeded\n");
6709 ok(GetLastError() == ERROR_INVALID_PARAMETER,
6710 "Expected ERROR_INVALID_PARAMETER got %lu\n", GetLastError());
6712 ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level);
6713 ok(ret, "AddMandatoryAce failed with %lu\n", GetLastError());
6715 ret = GetAce(acl, 0, (void **)&ace);
6716 ok(ret, "got error %lu\n", GetLastError());
6717 ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "got type %#x\n", ace->Header.AceType);
6718 ok(!ace->Header.AceFlags, "got flags %#x\n", ace->Header.AceFlags);
6719 ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "got mask %#lx\n", ace->Mask);
6720 ok(EqualSid(&ace->SidStart, &low_level), "wrong sid\n");
6722 SetLastError(0xdeadbeef);
6723 ret = GetAce(acl, 1, (void **)&ace);
6724 ok(!ret, "expected failure\n");
6725 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError());
6727 ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
6728 ok(ret, "SetSecurityDescriptorSacl failed with error %lu\n", GetLastError());
6730 handle = CreateEventA(&sa, TRUE, TRUE, "test_event");
6731 ok(handle != NULL, "CreateEventA failed with error %lu\n", GetLastError());
6733 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6734 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6735 "Unexpected GetKernelObjectSecurity return value %u, error %lu\n", ret, GetLastError());
6737 sd2 = malloc(size);
6738 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6739 ok(ret, "GetKernelObjectSecurity failed with error %lu\n", GetLastError());
6741 sacl = (void *)0xdeadbeef;
6742 present = FALSE;
6743 defaulted = TRUE;
6744 ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6745 ok(ret, "GetSecurityDescriptorSacl failed with error %lu\n", GetLastError());
6746 ok(present, "SACL not present\n");
6747 ok(sacl != (void *)0xdeadbeef, "SACL not set\n");
6748 ok(!defaulted, "SACL defaulted\n");
6749 ret = GetAclInformation(sacl, &acl_size_info, sizeof(acl_size_info), AclSizeInformation);
6750 ok(ret, "GetAclInformation failed with error %lu\n", GetLastError());
6751 ok(acl_size_info.AceCount == 1, "SACL contains an unexpected ACE count %lu\n", acl_size_info.AceCount);
6753 ret = GetAce(sacl, 0, (void **)&ace);
6754 ok(ret, "GetAce failed with error %lu\n", GetLastError());
6755 ok (ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType);
6756 ok(!ace->Header.AceFlags, "Unexpected ACE flags %#x\n", ace->Header.AceFlags);
6757 ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "Unexpected ACE mask %#lx\n", ace->Mask);
6758 ok(EqualSid(&ace->SidStart, &low_level), "Expected low integrity level\n");
6760 free(sd2);
6762 ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level);
6763 ok(ret, "AddMandatoryAce failed with error %lu\n", GetLastError());
6765 ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
6766 ok(ret, "SetKernelObjectSecurity failed with error %lu\n", GetLastError());
6768 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6769 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6770 "Unexpected GetKernelObjectSecurity return value %u, error %lu\n", ret, GetLastError());
6772 sd2 = malloc(size);
6773 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6774 ok(ret, "GetKernelObjectSecurity failed with error %lu\n", GetLastError());
6776 sacl = (void *)0xdeadbeef;
6777 present = FALSE;
6778 defaulted = TRUE;
6779 ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6780 ok(ret, "GetSecurityDescriptorSacl failed with error %lu\n", GetLastError());
6781 ok(present, "SACL not present\n");
6782 ok(sacl != (void *)0xdeadbeef, "SACL not set\n");
6783 ok(sacl->AceCount == 2, "Expected 2 ACEs, got %d\n", sacl->AceCount);
6784 ok(!defaulted, "SACL defaulted\n");
6786 ret = GetAce(acl, 0, (void **)&ace);
6787 ok(ret, "got error %lu\n", GetLastError());
6788 ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "got type %#x\n", ace->Header.AceType);
6789 ok(!ace->Header.AceFlags, "got flags %#x\n", ace->Header.AceFlags);
6790 ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "got mask %#lx\n", ace->Mask);
6791 ok(EqualSid(&ace->SidStart, &low_level), "wrong sid\n");
6793 ret = GetAce(acl, 1, (void **)&ace);
6794 ok(ret, "got error %lu\n", GetLastError());
6795 ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "got type %#x\n", ace->Header.AceType);
6796 ok(!ace->Header.AceFlags, "got flags %#x\n", ace->Header.AceFlags);
6797 ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, "got mask %#lx\n", ace->Mask);
6798 ok(EqualSid(&ace->SidStart, &medium_level), "wrong sid\n");
6800 SetLastError(0xdeadbeef);
6801 ret = GetAce(acl, 2, (void **)&ace);
6802 ok(!ret, "expected failure\n");
6803 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError());
6805 free(sd2);
6807 ret = SetSecurityDescriptorSacl(sd, FALSE, NULL, FALSE);
6808 ok(ret, "SetSecurityDescriptorSacl failed with error %lu\n", GetLastError());
6810 ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
6811 ok(ret, "SetKernelObjectSecurity failed with error %lu\n", GetLastError());
6813 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6814 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6815 "Unexpected GetKernelObjectSecurity return value %d, error %lu\n", ret, GetLastError());
6817 sd2 = malloc(size);
6818 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6819 ok(ret, "GetKernelObjectSecurity failed with error %lu\n", GetLastError());
6821 sacl = (void *)0xdeadbeef;
6822 present = FALSE;
6823 defaulted = TRUE;
6824 ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6825 ok(ret, "GetSecurityDescriptorSacl failed with error %lu\n", GetLastError());
6826 ok(present, "SACL not present\n");
6827 ok(sacl && sacl != (void *)0xdeadbeef, "SACL not set\n");
6828 ok(!defaulted, "SACL defaulted\n");
6829 ok(!sacl->AceCount, "SACL contains an unexpected ACE count %u\n", sacl->AceCount);
6831 free(sd2);
6833 ret = InitializeAcl(acl, 256, ACL_REVISION);
6834 ok(ret, "InitializeAcl failed with error %lu\n", GetLastError());
6836 ret = pAddMandatoryAce(acl, ACL_REVISION3, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level);
6837 ok(ret, "AddMandatoryAce failed with error %lu\n", GetLastError());
6839 ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
6840 ok(ret, "SetSecurityDescriptorSacl failed with error %lu\n", GetLastError());
6842 ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
6843 ok(ret, "SetKernelObjectSecurity failed with error %lu\n", GetLastError());
6845 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6846 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6847 "Unexpected GetKernelObjectSecurity return value %d, error %lu\n", ret, GetLastError());
6849 sd2 = malloc(size);
6850 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6851 ok(ret, "GetKernelObjectSecurity failed with error %lu\n", GetLastError());
6853 sacl = (void *)0xdeadbeef;
6854 present = FALSE;
6855 defaulted = TRUE;
6856 ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6857 ok(ret, "GetSecurityDescriptorSacl failed with error %lu\n", GetLastError());
6858 ok(present, "SACL not present\n");
6859 ok(sacl != (void *)0xdeadbeef, "SACL not set\n");
6860 ok(sacl->AclRevision == ACL_REVISION3, "Expected revision 3, got %d\n", sacl->AclRevision);
6861 ok(!defaulted, "SACL defaulted\n");
6863 free(sd2);
6865 ret = InitializeAcl(acl, 256, ACL_REVISION);
6866 ok(ret, "InitializeAcl failed with error %lu\n", GetLastError());
6868 ret = AllocateAndInitializeSid(&sia_world, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, (void **)&everyone);
6869 ok(ret, "AllocateAndInitializeSid failed with error %lu\n", GetLastError());
6871 ret = AddAccessAllowedAce(acl, ACL_REVISION, KEY_READ, everyone);
6872 ok(ret, "AddAccessAllowedAce failed with error %lu\n", GetLastError());
6874 ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
6875 ok(ret, "SetSecurityDescriptorSacl failed with error %lu\n", GetLastError());
6877 ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
6878 ok(ret, "SetKernelObjectSecurity failed with error %lu\n", GetLastError());
6880 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6881 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6882 "Unexpected GetKernelObjectSecurity return value %d, error %lu\n", ret, GetLastError());
6884 sd2 = malloc(size);
6885 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6886 ok(ret, "GetKernelObjectSecurity failed with error %lu\n", GetLastError());
6888 sacl = (void *)0xdeadbeef;
6889 present = FALSE;
6890 defaulted = TRUE;
6891 ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6892 ok(ret, "GetSecurityDescriptorSacl failed with error %lu\n", GetLastError());
6893 ok(present, "SACL not present\n");
6894 ok(sacl && sacl != (void *)0xdeadbeef, "SACL not set\n");
6895 ok(!defaulted, "SACL defaulted\n");
6896 ok(!sacl->AceCount, "SACL contains an unexpected ACE count %u\n", sacl->AceCount);
6898 FreeSid(everyone);
6899 free(sd2);
6900 CloseHandle(handle);
6903 static void test_system_security_access(void)
6905 static const WCHAR testkeyW[] =
6906 {'S','O','F','T','W','A','R','E','\\','W','i','n','e','\\','S','A','C','L','t','e','s','t',0};
6907 LONG res;
6908 HKEY hkey;
6909 PSECURITY_DESCRIPTOR sd;
6910 ACL *sacl;
6911 DWORD err, len = 128;
6912 TOKEN_PRIVILEGES priv, *priv_prev;
6913 HANDLE token;
6914 LUID luid;
6915 BOOL ret;
6917 if (!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &token )) return;
6918 if (!LookupPrivilegeValueA( NULL, SE_SECURITY_NAME, &luid ))
6920 CloseHandle( token );
6921 return;
6924 /* ACCESS_SYSTEM_SECURITY requires special privilege */
6925 res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ|ACCESS_SYSTEM_SECURITY, NULL, &hkey, NULL );
6926 if (res == ERROR_ACCESS_DENIED)
6928 skip( "unprivileged user\n" );
6929 CloseHandle( token );
6930 return;
6932 todo_wine ok( res == ERROR_PRIVILEGE_NOT_HELD, "got %ld\n", res );
6934 priv.PrivilegeCount = 1;
6935 priv.Privileges[0].Luid = luid;
6936 priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
6938 priv_prev = malloc( len );
6939 ret = AdjustTokenPrivileges( token, FALSE, &priv, len, priv_prev, &len );
6940 ok( ret, "got %lu\n", GetLastError());
6942 res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ|ACCESS_SYSTEM_SECURITY, NULL, &hkey, NULL );
6943 if (res == ERROR_PRIVILEGE_NOT_HELD)
6945 win_skip( "privilege not held\n" );
6946 free( priv_prev );
6947 CloseHandle( token );
6948 return;
6950 ok( !res, "got %ld\n", res );
6952 /* restore privileges */
6953 ret = AdjustTokenPrivileges( token, FALSE, priv_prev, 0, NULL, NULL );
6954 ok( ret, "got %lu\n", GetLastError() );
6955 free( priv_prev );
6957 /* privilege is checked on access */
6958 err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
6959 todo_wine ok( err == ERROR_PRIVILEGE_NOT_HELD || err == ERROR_ACCESS_DENIED, "got %lu\n", err );
6960 if (err == ERROR_SUCCESS)
6961 LocalFree( sd );
6963 priv.PrivilegeCount = 1;
6964 priv.Privileges[0].Luid = luid;
6965 priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
6967 priv_prev = malloc( len );
6968 ret = AdjustTokenPrivileges( token, FALSE, &priv, len, priv_prev, &len );
6969 ok( ret, "got %lu\n", GetLastError());
6971 err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
6972 ok( err == ERROR_SUCCESS, "got %lu\n", err );
6973 RegCloseKey( hkey );
6974 LocalFree( sd );
6976 /* handle created without ACCESS_SYSTEM_SECURITY, privilege held */
6977 res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ, NULL, &hkey, NULL );
6978 ok( res == ERROR_SUCCESS, "got %ld\n", res );
6980 sd = NULL;
6981 err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
6982 todo_wine ok( err == ERROR_SUCCESS, "got %lu\n", err );
6983 RegCloseKey( hkey );
6984 LocalFree( sd );
6986 /* restore privileges */
6987 ret = AdjustTokenPrivileges( token, FALSE, priv_prev, 0, NULL, NULL );
6988 ok( ret, "got %lu\n", GetLastError() );
6989 free( priv_prev );
6991 /* handle created without ACCESS_SYSTEM_SECURITY, privilege not held */
6992 res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ, NULL, &hkey, NULL );
6993 ok( res == ERROR_SUCCESS, "got %ld\n", res );
6995 err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
6996 ok( err == ERROR_PRIVILEGE_NOT_HELD || err == ERROR_ACCESS_DENIED, "got %lu\n", err );
6997 RegCloseKey( hkey );
6999 res = RegDeleteKeyW( HKEY_LOCAL_MACHINE, testkeyW );
7000 ok( !res, "got %ld\n", res );
7001 CloseHandle( token );
7004 static void test_GetWindowsAccountDomainSid(void)
7006 char *user, buffer1[SECURITY_MAX_SID_SIZE], buffer2[SECURITY_MAX_SID_SIZE];
7007 SID_IDENTIFIER_AUTHORITY domain_ident = { SECURITY_NT_AUTHORITY };
7008 PSID domain_sid = (PSID *)&buffer1;
7009 PSID domain_sid2 = (PSID *)&buffer2;
7010 DWORD sid_size;
7011 PSID user_sid;
7012 HANDLE token;
7013 BOOL bret = TRUE;
7014 int i;
7016 if (!pGetWindowsAccountDomainSid)
7018 win_skip("GetWindowsAccountDomainSid not available\n");
7019 return;
7022 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
7024 if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE;
7025 else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE;
7027 if (!bret)
7029 win_skip("Failed to get current user token\n");
7030 return;
7033 bret = GetTokenInformation(token, TokenUser, NULL, 0, &sid_size);
7034 ok(!bret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7035 "GetTokenInformation(TokenUser) failed with error %ld\n", GetLastError());
7036 user = malloc(sid_size);
7037 bret = GetTokenInformation(token, TokenUser, user, sid_size, &sid_size);
7038 ok(bret, "GetTokenInformation(TokenUser) failed with error %ld\n", GetLastError());
7039 CloseHandle(token);
7040 user_sid = ((TOKEN_USER *)user)->User.Sid;
7042 SetLastError(0xdeadbeef);
7043 bret = pGetWindowsAccountDomainSid(0, 0, 0);
7044 ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
7045 ok(GetLastError() == ERROR_INVALID_SID, "expected ERROR_INVALID_SID, got %ld\n", GetLastError());
7047 SetLastError(0xdeadbeef);
7048 bret = pGetWindowsAccountDomainSid(user_sid, 0, 0);
7049 ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
7050 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
7052 sid_size = SECURITY_MAX_SID_SIZE;
7053 SetLastError(0xdeadbeef);
7054 bret = pGetWindowsAccountDomainSid(user_sid, 0, &sid_size);
7055 ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
7056 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
7057 ok(sid_size == GetSidLengthRequired(4), "expected size %ld, got %ld\n", GetSidLengthRequired(4), sid_size);
7059 SetLastError(0xdeadbeef);
7060 bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, 0);
7061 ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
7062 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
7064 sid_size = 1;
7065 SetLastError(0xdeadbeef);
7066 bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, &sid_size);
7067 ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
7068 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
7069 ok(sid_size == GetSidLengthRequired(4), "expected size %ld, got %ld\n", GetSidLengthRequired(4), sid_size);
7071 sid_size = SECURITY_MAX_SID_SIZE;
7072 bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, &sid_size);
7073 ok(bret, "GetWindowsAccountDomainSid failed with error %ld\n", GetLastError());
7074 ok(sid_size == GetSidLengthRequired(4), "expected size %ld, got %ld\n", GetSidLengthRequired(4), sid_size);
7075 InitializeSid(domain_sid2, &domain_ident, 4);
7076 for (i = 0; i < 4; i++)
7077 *GetSidSubAuthority(domain_sid2, i) = *GetSidSubAuthority(user_sid, i);
7078 ok(EqualSid(domain_sid, domain_sid2), "unexpected domain sid %s != %s\n",
7079 debugstr_sid(domain_sid), debugstr_sid(domain_sid2));
7081 free(user);
7084 static void test_GetSidIdentifierAuthority(void)
7086 char buffer[SECURITY_MAX_SID_SIZE];
7087 PSID authority_sid = (PSID *)buffer;
7088 PSID_IDENTIFIER_AUTHORITY id;
7089 BOOL ret;
7091 if (!pGetSidIdentifierAuthority)
7093 win_skip("GetSidIdentifierAuthority not available\n");
7094 return;
7097 memset(buffer, 0xcc, sizeof(buffer));
7098 ret = IsValidSid(authority_sid);
7099 ok(!ret, "expected FALSE, got %u\n", ret);
7101 SetLastError(0xdeadbeef);
7102 id = GetSidIdentifierAuthority(authority_sid);
7103 ok(id != NULL, "got NULL pointer as identifier authority\n");
7104 ok(GetLastError() == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", GetLastError());
7106 SetLastError(0xdeadbeef);
7107 id = GetSidIdentifierAuthority(NULL);
7108 ok(id != NULL, "got NULL pointer as identifier authority\n");
7109 ok(GetLastError() == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %lu\n", GetLastError());
7112 static void test_pseudo_tokens(void)
7114 TOKEN_STATISTICS statistics1, statistics2;
7115 HANDLE token;
7116 DWORD retlen;
7117 BOOL ret;
7119 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
7120 ok(ret, "OpenProcessToken failed with error %lu\n", GetLastError());
7121 memset(&statistics1, 0x11, sizeof(statistics1));
7122 ret = GetTokenInformation(token, TokenStatistics, &statistics1, sizeof(statistics1), &retlen);
7123 ok(ret, "GetTokenInformation failed with %lu\n", GetLastError());
7124 CloseHandle(token);
7126 /* test GetCurrentProcessToken() */
7127 SetLastError(0xdeadbeef);
7128 memset(&statistics2, 0x22, sizeof(statistics2));
7129 ret = GetTokenInformation(GetCurrentProcessToken(), TokenStatistics,
7130 &statistics2, sizeof(statistics2), &retlen);
7131 ok(ret || broken(GetLastError() == ERROR_INVALID_HANDLE),
7132 "GetTokenInformation failed with %lu\n", GetLastError());
7133 if (ret)
7134 ok(!memcmp(&statistics1, &statistics2, sizeof(statistics1)), "Token statistics do not match\n");
7135 else
7136 win_skip("CurrentProcessToken not supported, skipping test\n");
7138 /* test GetCurrentThreadEffectiveToken() */
7139 SetLastError(0xdeadbeef);
7140 memset(&statistics2, 0x22, sizeof(statistics2));
7141 ret = GetTokenInformation(GetCurrentThreadEffectiveToken(), TokenStatistics,
7142 &statistics2, sizeof(statistics2), &retlen);
7143 ok(ret || broken(GetLastError() == ERROR_INVALID_HANDLE),
7144 "GetTokenInformation failed with %lu\n", GetLastError());
7145 if (ret)
7146 ok(!memcmp(&statistics1, &statistics2, sizeof(statistics1)), "Token statistics do not match\n");
7147 else
7148 win_skip("CurrentThreadEffectiveToken not supported, skipping test\n");
7150 SetLastError(0xdeadbeef);
7151 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &token);
7152 ok(!ret, "OpenThreadToken should have failed\n");
7153 ok(GetLastError() == ERROR_NO_TOKEN, "Expected ERROR_NO_TOKEN, got %lu\n", GetLastError());
7155 /* test GetCurrentThreadToken() */
7156 SetLastError(0xdeadbeef);
7157 ret = GetTokenInformation(GetCurrentThreadToken(), TokenStatistics,
7158 &statistics2, sizeof(statistics2), &retlen);
7159 todo_wine ok(GetLastError() == ERROR_NO_TOKEN || broken(GetLastError() == ERROR_INVALID_HANDLE),
7160 "Expected ERROR_NO_TOKEN, got %lu\n", GetLastError());
7163 static void test_maximum_allowed(void)
7165 HANDLE (WINAPI *pCreateEventExA)(SECURITY_ATTRIBUTES *, LPCSTR, DWORD, DWORD);
7166 char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH], buffer_acl[256];
7167 SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)&buffer_sd;
7168 SECURITY_ATTRIBUTES sa;
7169 ACL *acl = (ACL *)&buffer_acl;
7170 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
7171 ACCESS_MASK mask;
7172 HANDLE handle;
7173 BOOL ret;
7175 pCreateEventExA = (void *)GetProcAddress(hkernel32, "CreateEventExA");
7176 if (!pCreateEventExA)
7178 win_skip("CreateEventExA is not available\n");
7179 return;
7182 ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
7183 ok(ret, "InitializeSecurityDescriptor failed with %lu\n", GetLastError());
7184 memset(buffer_acl, 0, sizeof(buffer_acl));
7185 ret = InitializeAcl(acl, 256, ACL_REVISION);
7186 ok(ret, "InitializeAcl failed with %lu\n", GetLastError());
7187 ret = SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE);
7188 ok(ret, "SetSecurityDescriptorDacl failed with %lu\n", GetLastError());
7190 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
7191 sa.lpSecurityDescriptor = sd;
7192 sa.bInheritHandle = FALSE;
7194 handle = pCreateEventExA(&sa, NULL, 0, MAXIMUM_ALLOWED | 0x4);
7195 ok(handle != NULL, "CreateEventExA failed with error %lu\n", GetLastError());
7196 mask = get_obj_access(handle);
7197 ok(mask == EVENT_ALL_ACCESS, "Expected %x, got %lx\n", EVENT_ALL_ACCESS, mask);
7198 CloseHandle(handle);
7201 static void check_token_label(HANDLE token, DWORD *level, BOOL sacl_inherited)
7203 static SID medium_sid = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
7204 {SECURITY_MANDATORY_MEDIUM_RID}};
7205 static SID high_sid = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
7206 {SECURITY_MANDATORY_HIGH_RID}};
7207 SECURITY_DESCRIPTOR_CONTROL control;
7208 SYSTEM_MANDATORY_LABEL_ACE *ace;
7209 BOOL ret, present, defaulted;
7210 SECURITY_DESCRIPTOR *sd;
7211 ACL *sacl = NULL, *dacl;
7212 DWORD size, revision;
7213 char *str;
7214 SID *sid;
7216 ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
7217 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7218 "Unexpected GetKernelObjectSecurity return value %d, error %lu\n", ret, GetLastError());
7220 sd = malloc(size);
7221 ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size);
7222 ok(ret, "GetKernelObjectSecurity failed with error %lu\n", GetLastError());
7224 ret = GetSecurityDescriptorControl(sd, &control, &revision);
7225 ok(ret, "GetSecurityDescriptorControl failed with error %lu\n", GetLastError());
7226 if (sacl_inherited)
7227 todo_wine ok(control == (SE_SELF_RELATIVE | SE_SACL_AUTO_INHERITED | SE_SACL_PRESENT),
7228 "Unexpected security descriptor control %#x\n", control);
7229 else
7230 todo_wine ok(control == (SE_SELF_RELATIVE | SE_SACL_PRESENT),
7231 "Unexpected security descriptor control %#x\n", control);
7232 ok(revision == 1, "Unexpected security descriptor revision %lu\n", revision);
7234 sid = (void *)0xdeadbeef;
7235 defaulted = TRUE;
7236 ret = GetSecurityDescriptorOwner(sd, (void **)&sid, &defaulted);
7237 ok(ret, "GetSecurityDescriptorOwner failed with error %lu\n", GetLastError());
7238 ok(!sid, "Owner present\n");
7239 ok(!defaulted, "Owner defaulted\n");
7241 sid = (void *)0xdeadbeef;
7242 defaulted = TRUE;
7243 ret = GetSecurityDescriptorGroup(sd, (void **)&sid, &defaulted);
7244 ok(ret, "GetSecurityDescriptorGroup failed with error %lu\n", GetLastError());
7245 ok(!sid, "Group present\n");
7246 ok(!defaulted, "Group defaulted\n");
7248 ret = GetSecurityDescriptorSacl(sd, &present, &sacl, &defaulted);
7249 ok(ret, "GetSecurityDescriptorSacl failed with error %lu\n", GetLastError());
7250 ok(present, "No SACL in the security descriptor\n");
7251 ok(!!sacl, "NULL SACL in the security descriptor\n");
7252 ok(!defaulted, "SACL defaulted\n");
7253 ok(sacl->AceCount == 1, "SACL contains an unexpected ACE count %u\n", sacl->AceCount);
7255 ret = GetAce(sacl, 0, (void **)&ace);
7256 ok(ret, "GetAce failed with error %lu\n", GetLastError());
7258 ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
7259 "Unexpected ACE type %#x\n", ace->Header.AceType);
7260 ok(!ace->Header.AceFlags, "Unexpected ACE flags %#x\n", ace->Header.AceFlags);
7261 ok(ace->Header.AceSize, "Unexpected ACE size %u\n", ace->Header.AceSize);
7262 ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "Unexpected ACE mask %#lx\n", ace->Mask);
7264 sid = (SID *)&ace->SidStart;
7265 ConvertSidToStringSidA(sid, &str);
7266 ok(EqualSid(sid, &medium_sid) || EqualSid(sid, &high_sid), "Got unexpected SID %s\n", str);
7267 *level = sid->SubAuthority[0];
7268 LocalFree(str);
7270 ret = GetSecurityDescriptorDacl(sd, &present, &dacl, &defaulted);
7271 ok(ret, "GetSecurityDescriptorDacl failed with error %lu\n", GetLastError());
7272 todo_wine ok(!present, "DACL present\n");
7274 free(sd);
7277 static void test_token_label(void)
7279 SID low_sid = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
7280 {SECURITY_MANDATORY_LOW_RID}};
7281 char sacl_buffer[50];
7282 SECURITY_ATTRIBUTES attr = {.nLength = sizeof(SECURITY_ATTRIBUTES)};
7283 ACL *sacl = (ACL *)sacl_buffer;
7284 TOKEN_LINKED_TOKEN linked;
7285 DWORD level, level2, size;
7286 PSECURITY_DESCRIPTOR sd;
7287 HANDLE token, token2;
7288 BOOL ret;
7290 if (!pAddMandatoryAce)
7292 win_skip("Mandatory integrity control is not supported.\n");
7293 return;
7296 ret = OpenProcessToken(GetCurrentProcess(), READ_CONTROL | TOKEN_QUERY | TOKEN_DUPLICATE, &token);
7297 ok(ret, "OpenProcessToken failed with error %lu\n", GetLastError());
7299 check_token_label(token, &level, TRUE);
7301 ret = DuplicateTokenEx(token, READ_CONTROL, NULL, SecurityAnonymous, TokenPrimary, &token2);
7302 ok(ret, "Failed to duplicate token, error %lu\n", GetLastError());
7304 check_token_label(token2, &level2, TRUE);
7305 ok(level2 == level, "Expected level %#lx, got %#lx.\n", level, level2);
7307 CloseHandle(token2);
7309 ret = DuplicateTokenEx(token, READ_CONTROL, NULL, SecurityImpersonation, TokenImpersonation, &token2);
7310 ok(ret, "Failed to duplicate token, error %lu\n", GetLastError());
7312 check_token_label(token2, &level2, TRUE);
7313 ok(level2 == level, "Expected level %#lx, got %#lx.\n", level, level2);
7315 CloseHandle(token2);
7317 /* Any label set in the SD when calling DuplicateTokenEx() is ignored. */
7319 ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
7320 ok(!ret, "expected failure\n");
7321 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %lu\n", GetLastError());
7323 sd = malloc(size);
7324 ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size);
7325 ok(ret, "GetKernelObjectSecurity failed with error %lu\n", GetLastError());
7327 InitializeAcl(sacl, sizeof(sacl_buffer), ACL_REVISION);
7328 AddMandatoryAce(sacl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_sid);
7329 SetSecurityDescriptorSacl(sd, TRUE, sacl, FALSE);
7331 attr.lpSecurityDescriptor = sd;
7332 ret = DuplicateTokenEx(token, TOKEN_ALL_ACCESS, &attr, SecurityImpersonation, TokenImpersonation, &token2);
7333 ok(ret, "Failed to duplicate token, error %lu\n", GetLastError());
7335 check_token_label(token2, &level2, TRUE);
7336 ok(level2 == level, "Expected level %#lx, got %#lx.\n", level, level2);
7338 /* Trying to set a SD on the token also claims success but has no effect. */
7340 ret = SetKernelObjectSecurity(token2, LABEL_SECURITY_INFORMATION, sd);
7341 ok(ret, "Failed to set SD, error %lu\n", GetLastError());
7343 check_token_label(token2, &level2, FALSE);
7344 ok(level2 == level, "Expected level %#lx, got %#lx.\n", level, level2);
7346 free(sd);
7348 /* Test the linked token. */
7350 ret = GetTokenInformation(token, TokenLinkedToken, &linked, sizeof(linked), &size);
7351 ok(ret, "Failed to get linked token, error %lu\n", GetLastError());
7353 check_token_label(linked.LinkedToken, &level2, TRUE);
7354 ok(level2 == level, "Expected level %#lx, got %#lx.\n", level, level2);
7356 CloseHandle(linked.LinkedToken);
7358 CloseHandle(token);
7361 static void test_token_security_descriptor(void)
7363 static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
7364 {SECURITY_MANDATORY_LOW_RID}};
7365 char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
7366 SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)&buffer_sd, *sd2;
7367 char buffer_acl[256], buffer[MAX_PATH];
7368 ACL *acl = (ACL *)&buffer_acl, *acl2, *acl_child;
7369 BOOL defaulted, present, ret, found;
7370 HANDLE token, token2, token3;
7371 EXPLICIT_ACCESSW exp_access;
7372 PROCESS_INFORMATION info;
7373 DWORD size, index, retd;
7374 ACCESS_ALLOWED_ACE *ace;
7375 SECURITY_ATTRIBUTES sa;
7376 STARTUPINFOA startup;
7377 PSID psid;
7379 if (!pDuplicateTokenEx || !pAddAccessAllowedAceEx || !pSetEntriesInAclW)
7381 win_skip("Some functions not available\n");
7382 return;
7385 /* Test whether we can create tokens with security descriptors */
7386 ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
7387 ok(ret, "OpenProcessToken failed with error %lu\n", GetLastError());
7389 ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
7390 ok(ret, "InitializeSecurityDescriptor failed with error %lu\n", GetLastError());
7392 memset(buffer_acl, 0, sizeof(buffer_acl));
7393 ret = InitializeAcl(acl, 256, ACL_REVISION);
7394 ok(ret, "InitializeAcl failed with error %lu\n", GetLastError());
7396 ret = ConvertStringSidToSidA("S-1-5-6", &psid);
7397 ok(ret, "ConvertStringSidToSidA failed with error %lu\n", GetLastError());
7399 ret = pAddAccessAllowedAceEx(acl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, GENERIC_ALL, psid);
7400 ok(ret, "AddAccessAllowedAceEx failed with error %lu\n", GetLastError());
7402 ret = SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE);
7403 ok(ret, "SetSecurityDescriptorDacl failed with error %lu\n", GetLastError());
7405 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
7406 sa.lpSecurityDescriptor = sd;
7407 sa.bInheritHandle = FALSE;
7409 ret = pDuplicateTokenEx(token, MAXIMUM_ALLOWED, &sa, SecurityImpersonation, TokenImpersonation, &token2);
7410 ok(ret, "DuplicateTokenEx failed with error %lu\n", GetLastError());
7412 ret = GetKernelObjectSecurity(token2, DACL_SECURITY_INFORMATION, NULL, 0, &size);
7413 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7414 "Unexpected GetKernelObjectSecurity return value %d, error %lu\n", ret, GetLastError());
7416 sd2 = malloc(size);
7417 ret = GetKernelObjectSecurity(token2, DACL_SECURITY_INFORMATION, sd2, size, &size);
7418 ok(ret, "GetKernelObjectSecurity failed with error %lu\n", GetLastError());
7420 acl2 = (void *)0xdeadbeef;
7421 present = FALSE;
7422 defaulted = TRUE;
7423 ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted);
7424 ok(ret, "GetSecurityDescriptorDacl failed with error %lu\n", GetLastError());
7425 ok(present, "acl2 not present\n");
7426 ok(acl2 != (void *)0xdeadbeef, "acl2 not set\n");
7427 ok(acl2->AceCount == 1, "Expected 1 ACE, got %d\n", acl2->AceCount);
7428 ok(!defaulted, "acl2 defaulted\n");
7430 ret = GetAce(acl2, 0, (void **)&ace);
7431 ok(ret, "GetAce failed with error %lu\n", GetLastError());
7432 ok(ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType);
7433 ok(EqualSid(&ace->SidStart, psid), "Expected access allowed ACE\n");
7434 ok(ace->Header.AceFlags == NO_PROPAGATE_INHERIT_ACE,
7435 "Expected NO_PROPAGATE_INHERIT_ACE as flags, got %x\n", ace->Header.AceFlags);
7437 free(sd2);
7439 /* Duplicate token without security attributes.
7440 * Tokens do not inherit the security descriptor in DuplicateToken. */
7441 ret = pDuplicateTokenEx(token2, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenImpersonation, &token3);
7442 ok(ret, "DuplicateTokenEx failed with error %lu\n", GetLastError());
7444 ret = GetKernelObjectSecurity(token3, DACL_SECURITY_INFORMATION, NULL, 0, &size);
7445 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7446 "Unexpected GetKernelObjectSecurity return value %d, error %lu\n", ret, GetLastError());
7448 sd2 = malloc(size);
7449 ret = GetKernelObjectSecurity(token3, DACL_SECURITY_INFORMATION, sd2, size, &size);
7450 ok(ret, "GetKernelObjectSecurity failed with error %lu\n", GetLastError());
7452 acl2 = (void *)0xdeadbeef;
7453 present = FALSE;
7454 defaulted = TRUE;
7455 ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted);
7456 ok(ret, "GetSecurityDescriptorDacl failed with error %lu\n", GetLastError());
7457 ok(present, "DACL not present\n");
7459 ok(acl2 != (void *)0xdeadbeef, "DACL not set\n");
7460 ok(!defaulted, "DACL defaulted\n");
7462 index = 0;
7463 found = FALSE;
7464 while (GetAce(acl2, index++, (void **)&ace))
7466 if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE && EqualSid(&ace->SidStart, psid))
7467 found = TRUE;
7469 ok(!found, "Access allowed ACE was inherited\n");
7471 free(sd2);
7473 /* When creating a child process, the process does inherit the token of
7474 * the parent but not the DACL of the token */
7475 ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, NULL, 0, &size);
7476 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7477 "Unexpected GetKernelObjectSecurity return value %d, error %lu\n", ret, GetLastError());
7479 sd2 = malloc(size);
7480 ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd2, size, &size);
7481 ok(ret, "GetKernelObjectSecurity failed with error %lu\n", GetLastError());
7483 acl2 = (void *)0xdeadbeef;
7484 present = FALSE;
7485 defaulted = TRUE;
7486 ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted);
7487 ok(ret, "GetSecurityDescriptorDacl failed with error %lu\n", GetLastError());
7488 ok(present, "DACL not present\n");
7489 ok(acl2 != (void *)0xdeadbeef, "DACL not set\n");
7490 ok(!defaulted, "DACL defaulted\n");
7492 exp_access.grfAccessPermissions = GENERIC_ALL;
7493 exp_access.grfAccessMode = GRANT_ACCESS;
7494 exp_access.grfInheritance = NO_PROPAGATE_INHERIT_ACE;
7495 exp_access.Trustee.pMultipleTrustee = NULL;
7496 exp_access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
7497 exp_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
7498 exp_access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
7499 exp_access.Trustee.ptstrName = (void*)psid;
7501 retd = pSetEntriesInAclW(1, &exp_access, acl2, &acl_child);
7502 ok(retd == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %lu\n", retd);
7504 memset(sd, 0, sizeof(buffer_sd));
7505 ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
7506 ok(ret, "InitializeSecurityDescriptor failed with error %lu\n", GetLastError());
7508 ret = SetSecurityDescriptorDacl(sd, TRUE, acl_child, FALSE);
7509 ok(ret, "SetSecurityDescriptorDacl failed with error %lu\n", GetLastError());
7511 ret = SetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd);
7512 ok(ret, "SetKernelObjectSecurity failed with error %lu\n", GetLastError());
7514 /* The security label is also not inherited */
7515 if (pAddMandatoryAce)
7517 ret = InitializeAcl(acl, 256, ACL_REVISION);
7518 ok(ret, "InitializeAcl failed with error %lu\n", GetLastError());
7520 ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level);
7521 ok(ret, "AddMandatoryAce failed with error %lu\n", GetLastError());
7523 memset(sd, 0, sizeof(buffer_sd));
7524 ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
7525 ok(ret, "InitializeSecurityDescriptor failed with error %lu\n", GetLastError());
7527 ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
7528 ok(ret, "SetSecurityDescriptorSacl failed with error %lu\n", GetLastError());
7530 ret = SetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd);
7531 ok(ret, "SetKernelObjectSecurity failed with error %lu\n", GetLastError());
7533 else
7534 win_skip("SYSTEM_MANDATORY_LABEL not supported\n");
7536 /* Start child process with our modified token */
7537 memset(&startup, 0, sizeof(startup));
7538 startup.cb = sizeof(startup);
7539 startup.dwFlags = STARTF_USESHOWWINDOW;
7540 startup.wShowWindow = SW_SHOWNORMAL;
7542 sprintf(buffer, "%s security test_token_sd", myARGV[0]);
7543 ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info);
7544 ok(ret, "CreateProcess failed with error %lu\n", GetLastError());
7545 wait_child_process(info.hProcess);
7546 CloseHandle(info.hProcess);
7547 CloseHandle(info.hThread);
7549 LocalFree(acl_child);
7550 free(sd2);
7551 LocalFree(psid);
7553 CloseHandle(token3);
7554 CloseHandle(token2);
7555 CloseHandle(token);
7558 static void test_child_token_sd(void)
7560 static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
7561 {SECURITY_MANDATORY_LOW_RID}};
7562 SYSTEM_MANDATORY_LABEL_ACE *ace_label;
7563 BOOL ret, present, defaulted;
7564 ACCESS_ALLOWED_ACE *acc_ace;
7565 SECURITY_DESCRIPTOR *sd;
7566 DWORD size, i;
7567 HANDLE token;
7568 PSID psid;
7569 ACL *acl;
7571 ret = ConvertStringSidToSidA("S-1-5-6", &psid);
7572 ok(ret, "ConvertStringSidToSidA failed with error %lu\n", GetLastError());
7574 ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
7575 ok(ret, "OpenProcessToken failed with error %lu\n", GetLastError());
7577 ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, NULL, 0, &size);
7578 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7579 "Unexpected GetKernelObjectSecurity return value %d, error %lu\n", ret, GetLastError());
7581 sd = malloc(size);
7582 ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd, size, &size);
7583 ok(ret, "GetKernelObjectSecurity failed with error %lu\n", GetLastError());
7585 acl = NULL;
7586 present = FALSE;
7587 defaulted = TRUE;
7588 ret = GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted);
7589 ok(ret, "GetSecurityDescriptorDacl failed with error %lu\n", GetLastError());
7590 ok(present, "DACL not present\n");
7591 ok(acl && acl != (void *)0xdeadbeef, "Got invalid DACL\n");
7592 ok(!defaulted, "DACL defaulted\n");
7594 ok(acl->AceCount, "Expected at least one ACE\n");
7595 for (i = 0; i < acl->AceCount; i++)
7597 ret = GetAce(acl, i, (void **)&acc_ace);
7598 ok(ret, "GetAce failed with error %lu\n", GetLastError());
7599 ok(acc_ace->Header.AceType != ACCESS_ALLOWED_ACE_TYPE || !EqualSid(&acc_ace->SidStart, psid),
7600 "ACE inherited from the parent\n");
7603 LocalFree(psid);
7604 free(sd);
7606 if (!pAddMandatoryAce)
7608 win_skip("SYSTEM_MANDATORY_LABEL not supported\n");
7609 return;
7612 ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
7613 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7614 "Unexpected GetKernelObjectSecurity return value %d, error %lu\n", ret, GetLastError());
7616 sd = malloc(size);
7617 ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size);
7618 ok(ret, "GetKernelObjectSecurity failed with error %lu\n", GetLastError());
7620 acl = NULL;
7621 present = FALSE;
7622 defaulted = TRUE;
7623 ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted);
7624 ok(ret, "GetSecurityDescriptorSacl failed with error %lu\n", GetLastError());
7625 ok(present, "SACL not present\n");
7626 ok(acl && acl != (void *)0xdeadbeef, "Got invalid SACL\n");
7627 ok(!defaulted, "SACL defaulted\n");
7628 ok(acl->AceCount == 1, "Expected exactly one ACE\n");
7629 ret = GetAce(acl, 0, (void **)&ace_label);
7630 ok(ret, "GetAce failed with error %lu\n", GetLastError());
7631 ok(ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
7632 "Unexpected ACE type %#x\n", ace_label->Header.AceType);
7633 ok(!EqualSid(&ace_label->SidStart, &low_level),
7634 "Low integrity level should not have been inherited\n");
7636 free(sd);
7639 static void test_GetExplicitEntriesFromAclW(void)
7641 static const WCHAR wszCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'};
7642 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
7643 SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
7644 PSID everyone_sid = NULL, users_sid = NULL;
7645 EXPLICIT_ACCESSW access;
7646 EXPLICIT_ACCESSW *access2;
7647 PACL new_acl, old_acl = NULL;
7648 ULONG count;
7649 DWORD res;
7651 if (!pGetExplicitEntriesFromAclW)
7653 win_skip("GetExplicitEntriesFromAclW is not available\n");
7654 return;
7657 if (!pSetEntriesInAclW)
7659 win_skip("SetEntriesInAclW is not available\n");
7660 return;
7663 old_acl = malloc(256);
7664 res = InitializeAcl(old_acl, 256, ACL_REVISION);
7665 if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
7667 win_skip("ACLs not implemented - skipping tests\n");
7668 free(old_acl);
7669 return;
7671 ok(res, "InitializeAcl failed with error %ld\n", GetLastError());
7673 res = AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyone_sid);
7674 ok(res, "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
7676 res = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
7677 DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &users_sid);
7678 ok(res, "AllocateAndInitializeSid failed with error %ld\n", GetLastError());
7680 res = AddAccessAllowedAce(old_acl, ACL_REVISION, KEY_READ, users_sid);
7681 ok(res, "AddAccessAllowedAce failed with error %ld\n", GetLastError());
7683 access2 = NULL;
7684 res = pGetExplicitEntriesFromAclW(old_acl, &count, &access2);
7685 ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %ld\n", GetLastError());
7686 ok(count == 1, "Expected count == 1, got %ld\n", count);
7687 ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
7688 ok(access2[0].grfAccessPermissions == KEY_READ, "Expected KEY_READ, got %ld\n", access2[0].grfAccessPermissions);
7689 ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
7690 ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %lx\n", access2[0].grfInheritance);
7691 ok(EqualSid(access2[0].Trustee.ptstrName, users_sid), "Expected equal SIDs\n");
7692 LocalFree(access2);
7694 access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
7695 access.Trustee.pMultipleTrustee = NULL;
7697 access.grfAccessPermissions = KEY_WRITE;
7698 access.grfAccessMode = GRANT_ACCESS;
7699 access.grfInheritance = NO_INHERITANCE;
7700 access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
7701 access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
7702 access.Trustee.ptstrName = everyone_sid;
7703 res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
7704 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %lu\n", res);
7705 ok(new_acl != NULL, "returned acl was NULL\n");
7707 access2 = NULL;
7708 res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
7709 ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %ld\n", GetLastError());
7710 ok(count == 2, "Expected count == 2, got %ld\n", count);
7711 ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
7712 ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %ld\n", access2[0].grfAccessPermissions);
7713 ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
7714 "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
7715 ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
7716 ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %lx\n", access2[0].grfInheritance);
7717 ok(EqualSid(access2[0].Trustee.ptstrName, everyone_sid), "Expected equal SIDs\n");
7718 LocalFree(access2);
7719 LocalFree(new_acl);
7721 access.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
7722 res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
7723 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %lu\n", res);
7724 ok(new_acl != NULL, "returned acl was NULL\n");
7726 access2 = NULL;
7727 res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
7728 ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %ld\n", GetLastError());
7729 ok(count == 2, "Expected count == 2, got %ld\n", count);
7730 ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
7731 ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %ld\n", access2[0].grfAccessPermissions);
7732 ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
7733 "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
7734 ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
7735 ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %lx\n", access2[0].grfInheritance);
7736 ok(EqualSid(access2[0].Trustee.ptstrName, everyone_sid), "Expected equal SIDs\n");
7737 LocalFree(access2);
7738 LocalFree(new_acl);
7740 access.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
7741 access.Trustee.ptstrName = (LPWSTR)wszCurrentUser;
7742 res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
7743 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %lu\n", res);
7744 ok(new_acl != NULL, "returned acl was NULL\n");
7746 access2 = NULL;
7747 res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
7748 ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %ld\n", GetLastError());
7749 ok(count == 2, "Expected count == 2, got %ld\n", count);
7750 ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
7751 ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %ld\n", access2[0].grfAccessPermissions);
7752 ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
7753 "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
7754 ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
7755 ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %lx\n", access2[0].grfInheritance);
7756 LocalFree(access2);
7757 LocalFree(new_acl);
7759 access.grfAccessMode = REVOKE_ACCESS;
7760 access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
7761 access.Trustee.ptstrName = users_sid;
7762 res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
7763 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %lu\n", res);
7764 ok(new_acl != NULL, "returned acl was NULL\n");
7766 access2 = (void *)0xdeadbeef;
7767 res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
7768 ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %ld\n", GetLastError());
7769 ok(count == 0, "Expected count == 0, got %ld\n", count);
7770 ok(access2 == NULL, "access2 was not NULL\n");
7771 LocalFree(new_acl);
7773 /* Make the ACL both Allow and Deny Everyone. */
7774 res = AddAccessAllowedAce(old_acl, ACL_REVISION, KEY_READ, everyone_sid);
7775 ok(res, "AddAccessAllowedAce failed with error %ld\n", GetLastError());
7776 res = AddAccessDeniedAce(old_acl, ACL_REVISION, KEY_WRITE, everyone_sid);
7777 ok(res, "AddAccessDeniedAce failed with error %ld\n", GetLastError());
7778 /* Revoke Everyone. */
7779 access.Trustee.ptstrName = everyone_sid;
7780 access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
7781 access.grfAccessPermissions = 0;
7782 new_acl = NULL;
7783 res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
7784 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %lu\n", res);
7785 ok(new_acl != NULL, "returned acl was NULL\n");
7786 /* Deny Everyone should remain (along with Grant Users from earlier). */
7787 access2 = NULL;
7788 res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
7789 ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %ld\n", GetLastError());
7790 ok(count == 2, "Expected count == 2, got %ld\n", count);
7791 ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
7792 ok(access2[0].grfAccessPermissions == KEY_READ , "Expected KEY_READ, got %ld\n", access2[0].grfAccessPermissions);
7793 ok(EqualSid(access2[0].Trustee.ptstrName, users_sid), "Expected equal SIDs\n");
7794 ok(access2[1].grfAccessMode == DENY_ACCESS, "Expected DENY_ACCESS, got %d\n", access2[1].grfAccessMode);
7795 ok(access2[1].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %ld\n", access2[1].grfAccessPermissions);
7796 ok(EqualSid(access2[1].Trustee.ptstrName, everyone_sid), "Expected equal SIDs\n");
7797 LocalFree(access2);
7799 FreeSid(users_sid);
7800 FreeSid(everyone_sid);
7801 free(old_acl);
7804 static void test_BuildSecurityDescriptorW(void)
7806 SECURITY_DESCRIPTOR old_sd, *new_sd, *rel_sd;
7807 ULONG new_sd_size;
7808 DWORD buf_size;
7809 char buf[1024];
7810 BOOL success;
7811 DWORD ret;
7813 InitializeSecurityDescriptor(&old_sd, SECURITY_DESCRIPTOR_REVISION);
7815 buf_size = sizeof(buf);
7816 rel_sd = (SECURITY_DESCRIPTOR *)buf;
7817 success = MakeSelfRelativeSD(&old_sd, rel_sd, &buf_size);
7818 ok(success, "MakeSelfRelativeSD failed with %lu\n", GetLastError());
7820 new_sd = NULL;
7821 new_sd_size = 0;
7822 ret = BuildSecurityDescriptorW(NULL, NULL, 0, NULL, 0, NULL, NULL, &new_sd_size, (void **)&new_sd);
7823 ok(ret == ERROR_SUCCESS, "BuildSecurityDescriptor failed with %lu\n", ret);
7824 ok(new_sd != NULL, "expected new_sd != NULL\n");
7825 LocalFree(new_sd);
7827 new_sd = (void *)0xdeadbeef;
7828 ret = BuildSecurityDescriptorW(NULL, NULL, 0, NULL, 0, NULL, &old_sd, &new_sd_size, (void **)&new_sd);
7829 ok(ret == ERROR_INVALID_SECURITY_DESCR, "expected ERROR_INVALID_SECURITY_DESCR, got %lu\n", ret);
7830 ok(new_sd == (void *)0xdeadbeef, "expected new_sd == 0xdeadbeef, got %p\n", new_sd);
7832 new_sd = NULL;
7833 new_sd_size = 0;
7834 ret = BuildSecurityDescriptorW(NULL, NULL, 0, NULL, 0, NULL, rel_sd, &new_sd_size, (void **)&new_sd);
7835 ok(ret == ERROR_SUCCESS, "BuildSecurityDescriptor failed with %lu\n", ret);
7836 ok(new_sd != NULL, "expected new_sd != NULL\n");
7837 LocalFree(new_sd);
7840 static void test_EqualDomainSid(void)
7842 SID_IDENTIFIER_AUTHORITY ident = { SECURITY_NT_AUTHORITY };
7843 char sid_buffer[SECURITY_MAX_SID_SIZE], sid_buffer2[SECURITY_MAX_SID_SIZE];
7844 PSID domainsid, sid = sid_buffer, sid2 = sid_buffer2;
7845 DWORD size;
7846 BOOL ret, equal;
7847 unsigned int i;
7849 if (!pEqualDomainSid)
7851 win_skip("EqualDomainSid not available\n");
7852 return;
7855 ret = AllocateAndInitializeSid(&ident, 6, SECURITY_NT_NON_UNIQUE, 12, 23, 34, 45, 56, 0, 0, &domainsid);
7856 ok(ret, "AllocateAndInitializeSid error %lu\n", GetLastError());
7858 SetLastError(0xdeadbeef);
7859 ret = pEqualDomainSid(NULL, NULL, NULL);
7860 ok(!ret, "got %d\n", ret);
7861 ok(GetLastError() == ERROR_INVALID_SID, "got %lu\n", GetLastError());
7863 SetLastError(0xdeadbeef);
7864 ret = pEqualDomainSid(domainsid, domainsid, NULL);
7865 ok(!ret, "got %d\n", ret);
7866 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError());
7868 for (i = 0; i < ARRAY_SIZE(well_known_sid_values); i++)
7870 SID *pisid = sid;
7872 size = sizeof(sid_buffer);
7873 if (!CreateWellKnownSid(i, NULL, sid, &size))
7875 trace("Well known SID %u not supported\n", i);
7876 continue;
7879 equal = 0xdeadbeef;
7880 SetLastError(0xdeadbeef);
7881 ret = pEqualDomainSid(sid, domainsid, &equal);
7882 if (pisid->SubAuthority[0] != SECURITY_BUILTIN_DOMAIN_RID)
7884 ok(!ret, "%u: got %d\n", i, ret);
7885 ok(GetLastError() == ERROR_NON_DOMAIN_SID, "%u: got %lu\n", i, GetLastError());
7886 ok(equal == 0xdeadbeef, "%u: got %d\n", i, equal);
7887 continue;
7890 ok(ret, "%u: got %d\n", i, ret);
7891 ok(GetLastError() == 0, "%u: got %lu\n", i, GetLastError());
7892 ok(equal == 0, "%u: got %d\n", i, equal);
7894 size = sizeof(sid_buffer2);
7895 ret = CreateWellKnownSid(i, well_known_sid_values[i].without_domain ? NULL : domainsid, sid2, &size);
7896 ok(ret, "%u: CreateWellKnownSid error %lu\n", i, GetLastError());
7898 equal = 0xdeadbeef;
7899 SetLastError(0xdeadbeef);
7900 ret = pEqualDomainSid(sid, sid2, &equal);
7901 ok(ret, "%u: got %d\n", i, ret);
7902 ok(GetLastError() == 0, "%u: got %lu\n", i, GetLastError());
7903 ok(equal == 1, "%u: got %d\n", i, equal);
7906 FreeSid(domainsid);
7909 static DWORD WINAPI duplicate_handle_access_thread(void *arg)
7911 HANDLE event = arg, event2;
7912 BOOL ret;
7914 event2 = OpenEventA(SYNCHRONIZE, FALSE, "test_dup");
7915 ok(!!event2, "got error %lu\n", GetLastError());
7916 CloseHandle(event2);
7918 event2 = OpenEventA(EVENT_MODIFY_STATE, FALSE, "test_dup");
7919 ok(!!event2, "got error %lu\n", GetLastError());
7920 CloseHandle(event2);
7922 ret = DuplicateHandle(GetCurrentProcess(), event, GetCurrentProcess(),
7923 &event2, EVENT_MODIFY_STATE, FALSE, 0);
7924 ok(ret, "got error %lu\n", GetLastError());
7925 CloseHandle(event2);
7927 return 0;
7930 static void test_duplicate_handle_access(void)
7932 char acl_buffer[200], everyone_sid_buffer[100], local_sid_buffer[100], cmdline[300];
7933 HANDLE token, restricted, impersonation, all_event, sync_event, event2, thread;
7934 SECURITY_ATTRIBUTES sa = {.nLength = sizeof(sa)};
7935 SID *everyone_sid = (SID *)everyone_sid_buffer;
7936 SID *local_sid = (SID *)local_sid_buffer;
7937 ACL *acl = (ACL *)acl_buffer;
7938 SID_AND_ATTRIBUTES sid_attr;
7939 SECURITY_DESCRIPTOR sd;
7940 PROCESS_INFORMATION pi;
7941 STARTUPINFOA si = {0};
7942 DWORD size;
7943 BOOL ret;
7945 /* DuplicateHandle() validates access against the calling thread's token and
7946 * the target process's token. It does *not* validate access against the
7947 * calling process's token, even if the calling thread is not impersonating.
7950 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, &token);
7951 ok(ret, "got error %lu\n", GetLastError());
7953 size = sizeof(everyone_sid_buffer);
7954 ret = CreateWellKnownSid(WinWorldSid, NULL, everyone_sid, &size);
7955 ok(ret, "got error %lu\n", GetLastError());
7956 size = sizeof(local_sid_buffer);
7957 ret = CreateWellKnownSid(WinLocalSid, NULL, local_sid, &size);
7958 ok(ret, "got error %lu\n", GetLastError());
7960 InitializeAcl(acl, sizeof(acl_buffer), ACL_REVISION);
7961 ret = AddAccessAllowedAce(acl, ACL_REVISION, SYNCHRONIZE, everyone_sid);
7962 ok(ret, "got error %lu\n", GetLastError());
7963 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
7964 ret = AddAccessAllowedAce(acl, ACL_REVISION, EVENT_MODIFY_STATE, local_sid);
7965 ok(ret, "got error %lu\n", GetLastError());
7966 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
7967 ret = SetSecurityDescriptorDacl(&sd, TRUE, acl, FALSE);
7968 ok(ret, "got error %lu\n", GetLastError());
7969 sa.lpSecurityDescriptor = &sd;
7971 sid_attr.Sid = local_sid;
7972 sid_attr.Attributes = 0;
7973 ret = CreateRestrictedToken(token, 0, 1, &sid_attr, 0, NULL, 0, NULL, &restricted);
7974 ok(ret, "got error %lu\n", GetLastError());
7975 ret = DuplicateTokenEx(restricted, TOKEN_IMPERSONATE, NULL,
7976 SecurityImpersonation, TokenImpersonation, &impersonation);
7977 ok(ret, "got error %lu\n", GetLastError());
7979 all_event = CreateEventA(&sa, TRUE, TRUE, "test_dup");
7980 ok(!!all_event, "got error %lu\n", GetLastError());
7981 sync_event = OpenEventA(SYNCHRONIZE, FALSE, "test_dup");
7982 ok(!!sync_event, "got error %lu\n", GetLastError());
7984 event2 = OpenEventA(SYNCHRONIZE, FALSE, "test_dup");
7985 ok(!!event2, "got error %lu\n", GetLastError());
7986 CloseHandle(event2);
7988 event2 = OpenEventA(EVENT_MODIFY_STATE, FALSE, "test_dup");
7989 ok(!!event2, "got error %lu\n", GetLastError());
7990 CloseHandle(event2);
7992 ret = DuplicateHandle(GetCurrentProcess(), all_event, GetCurrentProcess(), &event2, EVENT_MODIFY_STATE, FALSE, 0);
7993 ok(ret, "got error %lu\n", GetLastError());
7994 CloseHandle(event2);
7996 ret = DuplicateHandle(GetCurrentProcess(), sync_event, GetCurrentProcess(), &event2, EVENT_MODIFY_STATE, FALSE, 0);
7997 ok(ret, "got error %lu\n", GetLastError());
7998 CloseHandle(event2);
8000 ret = SetThreadToken(NULL, impersonation);
8001 ok(ret, "got error %lu\n", GetLastError());
8003 thread = CreateThread(NULL, 0, duplicate_handle_access_thread, sync_event, 0, NULL);
8004 ret = WaitForSingleObject(thread, 1000);
8005 ok(!ret, "wait failed\n");
8007 event2 = OpenEventA(SYNCHRONIZE, FALSE, "test_dup");
8008 ok(!!event2, "got error %lu\n", GetLastError());
8009 CloseHandle(event2);
8011 SetLastError(0xdeadbeef);
8012 event2 = OpenEventA(EVENT_MODIFY_STATE, FALSE, "test_dup");
8013 ok(!event2, "expected failure\n");
8014 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %lu\n", GetLastError());
8016 ret = DuplicateHandle(GetCurrentProcess(), all_event, GetCurrentProcess(), &event2, EVENT_MODIFY_STATE, FALSE, 0);
8017 ok(ret, "got error %lu\n", GetLastError());
8018 CloseHandle(event2);
8020 SetLastError(0xdeadbeef);
8021 ret = DuplicateHandle(GetCurrentProcess(), sync_event, GetCurrentProcess(), &event2, EVENT_MODIFY_STATE, FALSE, 0);
8022 ok(!ret, "expected failure\n");
8023 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %lu\n", GetLastError());
8025 ret = RevertToSelf();
8026 ok(ret, "got error %lu\n", GetLastError());
8028 sprintf(cmdline, "%s security duplicate %Iu %lu %Iu", myARGV[0],
8029 (ULONG_PTR)sync_event, GetCurrentProcessId(), (ULONG_PTR)impersonation );
8030 ret = CreateProcessAsUserA(restricted, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
8031 ok(ret, "got error %lu\n", GetLastError());
8033 ret = DuplicateHandle(GetCurrentProcess(), all_event, pi.hProcess, &event2, EVENT_MODIFY_STATE, FALSE, 0);
8034 ok(ret, "got error %lu\n", GetLastError());
8036 SetLastError(0xdeadbeef);
8037 ret = DuplicateHandle(GetCurrentProcess(), sync_event, pi.hProcess, &event2, EVENT_MODIFY_STATE, FALSE, 0);
8038 ok(!ret, "expected failure\n");
8039 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %lu\n", GetLastError());
8041 ret = WaitForSingleObject(pi.hProcess, 1000);
8042 ok(!ret, "wait failed\n");
8044 CloseHandle(impersonation);
8045 CloseHandle(restricted);
8046 CloseHandle(token);
8047 CloseHandle(sync_event);
8048 CloseHandle(all_event);
8051 static void test_duplicate_handle_access_child(void)
8053 HANDLE event, event2, process, token;
8054 BOOL ret;
8056 event = (HANDLE)(ULONG_PTR)_atoi64(myARGV[3]);
8057 process = OpenProcess(PROCESS_DUP_HANDLE, FALSE, atoi(myARGV[4]));
8058 ok(!!process, "failed to open process, error %lu\n", GetLastError());
8060 event2 = OpenEventA(SYNCHRONIZE, FALSE, "test_dup");
8061 ok(!!event2, "got error %lu\n", GetLastError());
8062 CloseHandle(event2);
8064 SetLastError(0xdeadbeef);
8065 event2 = OpenEventA(EVENT_MODIFY_STATE, FALSE, "test_dup");
8066 ok(!event2, "expected failure\n");
8067 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %lu\n", GetLastError());
8069 ret = DuplicateHandle(process, event, process, &event2, EVENT_MODIFY_STATE, FALSE, 0);
8070 ok(ret, "got error %lu\n", GetLastError());
8072 SetLastError(0xdeadbeef);
8073 ret = DuplicateHandle(process, event, GetCurrentProcess(), &event2, EVENT_MODIFY_STATE, FALSE, 0);
8074 ok(!ret, "expected failure\n");
8075 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %lu\n", GetLastError());
8077 ret = DuplicateHandle(process, (HANDLE)(ULONG_PTR)_atoi64(myARGV[5]),
8078 GetCurrentProcess(), &token, 0, FALSE, DUPLICATE_SAME_ACCESS);
8079 ok(ret, "failed to retrieve token, error %lu\n", GetLastError());
8080 ret = SetThreadToken(NULL, token);
8081 ok(ret, "failed to set thread token, error %lu\n", GetLastError());
8083 SetLastError(0xdeadbeef);
8084 ret = DuplicateHandle(process, event, process, &event2, EVENT_MODIFY_STATE, FALSE, 0);
8085 ok(!ret, "expected failure\n");
8086 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %lu\n", GetLastError());
8088 SetLastError(0xdeadbeef);
8089 ret = DuplicateHandle(process, event, GetCurrentProcess(), &event2, EVENT_MODIFY_STATE, FALSE, 0);
8090 ok(!ret, "expected failure\n");
8091 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %lu\n", GetLastError());
8093 ret = RevertToSelf();
8094 ok(ret, "failed to revert, error %lu\n", GetLastError());
8095 CloseHandle(token);
8096 CloseHandle(process);
8099 #define join_process(a) join_process_(__LINE__, a)
8100 static void join_process_(int line, const PROCESS_INFORMATION *pi)
8102 DWORD ret = WaitForSingleObject(pi->hProcess, 1000);
8103 ok_(__FILE__, line)(!ret, "wait failed\n");
8104 CloseHandle(pi->hProcess);
8105 CloseHandle(pi->hThread);
8108 static void test_create_process_token(void)
8110 char cmdline[300], acl_buffer[200], sid_buffer[100];
8111 SECURITY_ATTRIBUTES sa = {.nLength = sizeof(sa)};
8112 ACL *acl = (ACL *)acl_buffer;
8113 SID *sid = (SID *)sid_buffer;
8114 SID_AND_ATTRIBUTES sid_attr;
8115 HANDLE event, token, token2;
8116 PROCESS_INFORMATION pi;
8117 SECURITY_DESCRIPTOR sd;
8118 STARTUPINFOA si = {0};
8119 DWORD size;
8120 BOOL ret;
8122 size = sizeof(sid_buffer);
8123 ret = CreateWellKnownSid(WinLocalSid, NULL, sid, &size);
8124 ok(ret, "got error %lu\n", GetLastError());
8125 ret = InitializeAcl(acl, sizeof(acl_buffer), ACL_REVISION);
8126 ok(ret, "got error %lu\n", GetLastError());
8127 ret = AddAccessAllowedAce(acl, ACL_REVISION, EVENT_MODIFY_STATE, sid);
8128 ok(ret, "got error %lu\n", GetLastError());
8129 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
8130 ret = SetSecurityDescriptorDacl(&sd, TRUE, acl, FALSE);
8131 ok(ret, "got error %lu\n", GetLastError());
8132 sa.lpSecurityDescriptor = &sd;
8133 event = CreateEventA(&sa, TRUE, TRUE, "test_event");
8134 ok(!!event, "got error %lu\n", GetLastError());
8136 sprintf(cmdline, "%s security restricted 0", myARGV[0]);
8138 ret = CreateProcessAsUserA(NULL, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
8139 ok(ret, "got error %lu\n", GetLastError());
8140 join_process(&pi);
8142 ret = CreateProcessAsUserA(GetCurrentProcessToken(), NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
8143 todo_wine ok(!ret, "expected failure\n");
8144 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError());
8145 if (ret) join_process(&pi);
8147 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, &token);
8148 ok(ret, "got error %lu\n", GetLastError());
8149 ret = CreateProcessAsUserA(token, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
8150 ok(ret || broken(GetLastError() == ERROR_ACCESS_DENIED) /* < 7 */, "got error %lu\n", GetLastError());
8151 if (ret) join_process(&pi);
8152 CloseHandle(token);
8154 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
8155 ok(ret, "got error %lu\n", GetLastError());
8156 ret = CreateProcessAsUserA(token, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
8157 ok(!ret, "expected failure\n");
8158 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %lu\n", GetLastError());
8159 CloseHandle(token);
8161 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ASSIGN_PRIMARY, &token);
8162 ok(ret, "got error %lu\n", GetLastError());
8163 ret = CreateProcessAsUserA(token, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
8164 ok(!ret, "expected failure\n");
8165 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %lu\n", GetLastError());
8166 CloseHandle(token);
8168 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE, &token);
8169 ok(ret, "got error %lu\n", GetLastError());
8171 ret = DuplicateTokenEx(token, TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, NULL,
8172 SecurityImpersonation, TokenImpersonation, &token2);
8173 ok(ret, "got error %lu\n", GetLastError());
8174 ret = CreateProcessAsUserA(token2, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
8175 ok(ret || broken(GetLastError() == ERROR_BAD_TOKEN_TYPE) /* < 7 */, "got error %lu\n", GetLastError());
8176 if (ret) join_process(&pi);
8177 CloseHandle(token2);
8179 sprintf(cmdline, "%s security restricted 1", myARGV[0]);
8180 sid_attr.Sid = sid;
8181 sid_attr.Attributes = 0;
8182 ret = CreateRestrictedToken(token, 0, 1, &sid_attr, 0, NULL, 0, NULL, &token2);
8183 ok(ret, "got error %lu\n", GetLastError());
8184 ret = CreateProcessAsUserA(token2, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
8185 ok(ret, "got error %lu\n", GetLastError());
8186 join_process(&pi);
8187 CloseHandle(token2);
8189 CloseHandle(token);
8191 CloseHandle(event);
8194 static void test_create_process_token_child(void)
8196 HANDLE event;
8198 SetLastError(0xdeadbeef);
8199 event = OpenEventA(EVENT_MODIFY_STATE, FALSE, "test_event");
8200 if (!atoi(myARGV[3]))
8202 ok(!!event, "got error %lu\n", GetLastError());
8203 CloseHandle(event);
8205 else
8207 ok(!event, "expected failure\n");
8208 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %lu\n", GetLastError());
8212 static void test_pseudo_handle_security(void)
8214 char buffer[200];
8215 PSECURITY_DESCRIPTOR sd = buffer, sd_ptr;
8216 unsigned int i;
8217 DWORD size;
8218 BOOL ret;
8220 static const HKEY keys[] =
8222 HKEY_CLASSES_ROOT,
8223 HKEY_CURRENT_USER,
8224 HKEY_LOCAL_MACHINE,
8225 HKEY_USERS,
8226 HKEY_PERFORMANCE_DATA,
8227 HKEY_CURRENT_CONFIG,
8228 HKEY_DYN_DATA,
8231 ret = GetKernelObjectSecurity(GetCurrentProcess(), OWNER_SECURITY_INFORMATION, &sd, sizeof(buffer), &size);
8232 ok(ret, "got error %lu\n", GetLastError());
8234 ret = GetKernelObjectSecurity(GetCurrentThread(), OWNER_SECURITY_INFORMATION, &sd, sizeof(buffer), &size);
8235 ok(ret, "got error %lu\n", GetLastError());
8237 for (i = 0; i < ARRAY_SIZE(keys); ++i)
8239 SetLastError(0xdeadbeef);
8240 ret = GetKernelObjectSecurity(keys[i], OWNER_SECURITY_INFORMATION, &sd, sizeof(buffer), &size);
8241 ok(!ret, "key %p: expected failure\n", keys[i]);
8242 ok(GetLastError() == ERROR_INVALID_HANDLE, "key %p: got error %lu\n", keys[i], GetLastError());
8244 ret = GetSecurityInfo(keys[i], SE_REGISTRY_KEY,
8245 DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &sd_ptr);
8246 if (keys[i] == HKEY_PERFORMANCE_DATA)
8247 ok(ret == ERROR_INVALID_HANDLE, "key %p: got error %u\n", keys[i], ret);
8248 else if (keys[i] == HKEY_DYN_DATA)
8249 todo_wine ok(ret == ERROR_CALL_NOT_IMPLEMENTED || broken(ret == ERROR_INVALID_HANDLE) /* <7 */,
8250 "key %p: got error %u\n", keys[i], ret);
8251 else
8252 ok(!ret, "key %p: got error %u\n", keys[i], ret);
8253 if (!ret) LocalFree(sd_ptr);
8255 ret = GetSecurityInfo(keys[i], SE_KERNEL_OBJECT,
8256 DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &sd_ptr);
8257 ok(ret == ERROR_INVALID_HANDLE, "key %p: got error %u\n", keys[i], ret);
8261 static const LUID_AND_ATTRIBUTES *find_privilege(const TOKEN_PRIVILEGES *privs, const LUID *luid)
8263 DWORD i;
8265 for (i = 0; i < privs->PrivilegeCount; ++i)
8267 if (!memcmp(luid, &privs->Privileges[i].Luid, sizeof(LUID)))
8268 return &privs->Privileges[i];
8271 return NULL;
8274 static void test_duplicate_token(void)
8276 const DWORD orig_access = TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_PRIVILEGES;
8277 char prev_privs_buffer[128], ret_privs_buffer[1024];
8278 TOKEN_PRIVILEGES *prev_privs = (void *)prev_privs_buffer;
8279 TOKEN_PRIVILEGES *ret_privs = (void *)ret_privs_buffer;
8280 const LUID_AND_ATTRIBUTES *priv;
8281 TOKEN_PRIVILEGES privs;
8282 SECURITY_QUALITY_OF_SERVICE qos = {.Length = sizeof(qos)};
8283 OBJECT_ATTRIBUTES attr = {.Length = sizeof(attr)};
8284 SECURITY_IMPERSONATION_LEVEL level;
8285 HANDLE token, token2;
8286 DWORD size;
8287 BOOL ret;
8289 ret = OpenProcessToken(GetCurrentProcess(), orig_access, &token);
8290 ok(ret, "got error %lu\n", GetLastError());
8292 /* Disable a privilege, to see if that privilege modification is preserved
8293 * in the duplicated tokens. */
8294 privs.PrivilegeCount = 1;
8295 ret = LookupPrivilegeValueA(NULL, "SeChangeNotifyPrivilege", &privs.Privileges[0].Luid);
8296 ok(ret, "got error %lu\n", GetLastError());
8297 privs.Privileges[0].Attributes = 0;
8298 ret = AdjustTokenPrivileges(token, FALSE, &privs, sizeof(prev_privs_buffer), prev_privs, &size);
8299 ok(ret, "got error %lu\n", GetLastError());
8301 ret = DuplicateToken(token, SecurityAnonymous, &token2);
8302 ok(ret, "got error %lu\n", GetLastError());
8303 TEST_GRANTED_ACCESS(token2, TOKEN_QUERY | TOKEN_IMPERSONATE);
8304 ret = GetTokenInformation(token2, TokenImpersonationLevel, &level, sizeof(level), &size);
8305 ok(ret, "got error %lu\n", GetLastError());
8306 ok(level == SecurityAnonymous, "got impersonation level %#x\n", level);
8307 ret = GetTokenInformation(token2, TokenPrivileges, ret_privs, sizeof(ret_privs_buffer), &size);
8308 ok(ret, "got error %lu\n", GetLastError());
8309 priv = find_privilege(ret_privs, &privs.Privileges[0].Luid);
8310 ok(!!priv, "Privilege should exist\n");
8311 todo_wine ok(priv->Attributes == SE_GROUP_MANDATORY, "Got attributes %#lx\n", priv->Attributes);
8312 CloseHandle(token2);
8314 ret = DuplicateTokenEx(token, 0, NULL, SecurityAnonymous, TokenPrimary, &token2);
8315 ok(ret, "got error %lu\n", GetLastError());
8316 TEST_GRANTED_ACCESS(token2, orig_access);
8317 ret = GetTokenInformation(token2, TokenImpersonationLevel, &level, sizeof(level), &size);
8318 ok(!ret, "expected failure\n");
8319 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got error %lu.\n", GetLastError());
8320 ret = GetTokenInformation(token2, TokenPrivileges, ret_privs, sizeof(ret_privs_buffer), &size);
8321 ok(ret, "got error %lu\n", GetLastError());
8322 priv = find_privilege(ret_privs, &privs.Privileges[0].Luid);
8323 ok(!!priv, "Privilege should exist\n");
8324 todo_wine ok(priv->Attributes == SE_GROUP_MANDATORY, "Got attributes %#lx\n", priv->Attributes);
8325 CloseHandle(token2);
8327 ret = DuplicateTokenEx(token, MAXIMUM_ALLOWED, NULL, SecurityAnonymous, TokenPrimary, &token2);
8328 ok(ret, "got error %lu\n", GetLastError());
8329 TEST_GRANTED_ACCESS(token2, TOKEN_ALL_ACCESS);
8330 CloseHandle(token2);
8332 ret = DuplicateTokenEx(token, TOKEN_QUERY_SOURCE, NULL, SecurityAnonymous, TokenPrimary, &token2);
8333 ok(ret, "got error %lu\n", GetLastError());
8334 TEST_GRANTED_ACCESS(token2, TOKEN_QUERY_SOURCE);
8335 CloseHandle(token2);
8337 ret = DuplicateTokenEx(token, 0, NULL, SecurityIdentification, TokenImpersonation, &token2);
8338 ok(ret, "got error %lu\n", GetLastError());
8339 TEST_GRANTED_ACCESS(token2, orig_access);
8340 ret = GetTokenInformation(token2, TokenImpersonationLevel, &level, sizeof(level), &size);
8341 ok(ret, "got error %lu\n", GetLastError());
8342 ok(level == SecurityIdentification, "got impersonation level %#x\n", level);
8343 ret = GetTokenInformation(token2, TokenPrivileges, ret_privs, sizeof(ret_privs_buffer), &size);
8344 ok(ret, "got error %lu\n", GetLastError());
8345 priv = find_privilege(ret_privs, &privs.Privileges[0].Luid);
8346 ok(!!priv, "Privilege should exist\n");
8347 todo_wine ok(priv->Attributes == SE_GROUP_MANDATORY, "Got attributes %#lx\n", priv->Attributes);
8348 CloseHandle(token2);
8350 ret = NtDuplicateToken(token, 0, &attr, FALSE, TokenImpersonation, &token2);
8351 ok(ret == STATUS_SUCCESS, "Got status %#x.\n", ret);
8352 TEST_GRANTED_ACCESS(token2, orig_access);
8353 ret = GetTokenInformation(token2, TokenImpersonationLevel, &level, sizeof(level), &size);
8354 ok(ret, "got error %lu\n", GetLastError());
8355 ok(level == SecurityAnonymous, "got impersonation level %#x\n", level);
8356 ret = GetTokenInformation(token2, TokenPrivileges, ret_privs, sizeof(ret_privs_buffer), &size);
8357 ok(ret, "got error %lu\n", GetLastError());
8358 priv = find_privilege(ret_privs, &privs.Privileges[0].Luid);
8359 ok(!!priv, "Privilege should exist\n");
8360 todo_wine ok(priv->Attributes == SE_GROUP_MANDATORY, "Got attributes %#lx\n", priv->Attributes);
8361 CloseHandle(token2);
8363 ret = NtDuplicateToken(token, 0, &attr, TRUE, TokenImpersonation, &token2);
8364 ok(ret == STATUS_SUCCESS, "Got status %#x.\n", ret);
8365 TEST_GRANTED_ACCESS(token2, orig_access);
8366 ret = GetTokenInformation(token2, TokenPrivileges, ret_privs, sizeof(ret_privs_buffer), &size);
8367 ok(ret, "got error %lu\n", GetLastError());
8368 priv = find_privilege(ret_privs, &privs.Privileges[0].Luid);
8369 todo_wine ok(!priv, "Privilege shouldn't exist\n");
8370 CloseHandle(token2);
8372 qos.ImpersonationLevel = SecurityIdentification;
8373 qos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
8374 qos.EffectiveOnly = FALSE;
8375 attr.SecurityQualityOfService = &qos;
8376 ret = NtDuplicateToken(token, 0, &attr, FALSE, TokenImpersonation, &token2);
8377 ok(ret == STATUS_SUCCESS, "Got status %#x.\n", ret);
8378 TEST_GRANTED_ACCESS(token2, orig_access);
8379 ret = GetTokenInformation(token2, TokenImpersonationLevel, &level, sizeof(level), &size);
8380 ok(ret, "got error %lu\n", GetLastError());
8381 ok(level == SecurityIdentification, "got impersonation level %#x\n", level);
8382 CloseHandle(token2);
8384 privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
8385 ret = AdjustTokenPrivileges(token, FALSE, &privs, sizeof(prev_privs_buffer), prev_privs, &size);
8386 ok(ret, "got error %lu\n", GetLastError());
8388 CloseHandle(token);
8391 static void test_GetKernelObjectSecurity(void)
8393 /* Basic tests for parameter validation. */
8395 SECURITY_DESCRIPTOR_CONTROL control;
8396 DWORD size, ret_size, revision;
8397 BOOL ret, present, defaulted;
8398 PSECURITY_DESCRIPTOR sd;
8399 PSID sid;
8400 ACL *acl;
8402 SetLastError(0xdeadbeef);
8403 size = 0xdeadbeef;
8404 ret = GetKernelObjectSecurity(NULL, OWNER_SECURITY_INFORMATION, NULL, 0, &size);
8405 ok(!ret, "expected failure\n");
8406 ok(GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError());
8407 ok(size == 0xdeadbeef, "got size %lu\n", size);
8409 SetLastError(0xdeadbeef);
8410 ret = GetKernelObjectSecurity(GetCurrentProcess(), OWNER_SECURITY_INFORMATION, NULL, 0, NULL);
8411 ok(!ret, "expected failure\n");
8412 ok(GetLastError() == ERROR_NOACCESS, "got error %lu\n", GetLastError());
8414 SetLastError(0xdeadbeef);
8415 size = 0xdeadbeef;
8416 ret = GetKernelObjectSecurity(GetCurrentProcess(), OWNER_SECURITY_INFORMATION, NULL, 0, &size);
8417 ok(!ret, "expected failure\n");
8418 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %lu\n", GetLastError());
8419 ok(size > 0 && size != 0xdeadbeef, "got size 0\n");
8421 sd = malloc(size + 1);
8423 SetLastError(0xdeadbeef);
8424 ret = GetKernelObjectSecurity(GetCurrentProcess(), OWNER_SECURITY_INFORMATION, sd, size - 1, &ret_size);
8425 ok(!ret, "expected failure\n");
8426 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %lu\n", GetLastError());
8427 ok(ret_size == size, "expected size %lu, got %lu\n", size, ret_size);
8429 SetLastError(0xdeadbeef);
8430 ret = GetKernelObjectSecurity(GetCurrentProcess(), OWNER_SECURITY_INFORMATION, sd, size + 1, &ret_size);
8431 ok(ret, "expected success\n");
8432 ok(GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError());
8433 ok(ret_size == size, "expected size %lu, got %lu\n", size, ret_size);
8435 free(sd);
8437 /* Calling the function with flags not defined succeeds and yields an empty
8438 * descriptor. */
8440 SetLastError(0xdeadbeef);
8441 ret = GetKernelObjectSecurity(GetCurrentProcess(), 0x100000, NULL, 0, &size);
8442 ok(!ret, "expected failure\n");
8443 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %lu\n", GetLastError());
8445 sd = malloc(size);
8446 SetLastError(0xdeadbeef);
8447 ret = GetKernelObjectSecurity(GetCurrentProcess(), 0x100000, sd, size, &ret_size);
8448 ok(ret, "expected success\n");
8449 ok(GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError());
8450 ok(ret_size == size, "expected size %lu, got %lu\n", size, ret_size);
8452 ret = GetSecurityDescriptorControl(sd, &control, &revision);
8453 ok(ret, "got error %lu\n", GetLastError());
8454 todo_wine ok(control == SE_SELF_RELATIVE, "got control %#x\n", control);
8455 ok(revision == SECURITY_DESCRIPTOR_REVISION1, "got revision %lu\n", revision);
8457 ret = GetSecurityDescriptorOwner(sd, &sid, &defaulted);
8458 ok(ret, "got error %lu\n", GetLastError());
8459 ok(!sid, "expected no owner SID\n");
8460 ok(!defaulted, "expected owner not defaulted\n");
8462 ret = GetSecurityDescriptorGroup(sd, &sid, &defaulted);
8463 ok(ret, "got error %lu\n", GetLastError());
8464 ok(!sid, "expected no group SID\n");
8465 ok(!defaulted, "expected group not defaulted\n");
8467 ret = GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted);
8468 ok(ret, "got error %lu\n", GetLastError());
8469 todo_wine ok(!present, "expected no DACL present\n");
8470 /* the descriptor is defaulted only on Windows >= 7 */
8472 ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted);
8473 ok(ret, "got error %lu\n", GetLastError());
8474 ok(!present, "expected no SACL present\n");
8475 /* the descriptor is defaulted only on Windows >= 7 */
8477 free(sd);
8480 static void check_different_token(HANDLE token1, HANDLE token2)
8482 TOKEN_STATISTICS stats1, stats2;
8483 DWORD size;
8484 BOOL ret;
8486 ret = GetTokenInformation(token1, TokenStatistics, &stats1, sizeof(stats1), &size);
8487 ok(ret, "got error %lu\n", GetLastError());
8488 ret = GetTokenInformation(token2, TokenStatistics, &stats2, sizeof(stats2), &size);
8489 ok(ret, "got error %lu\n", GetLastError());
8491 ok(memcmp(&stats1.TokenId, &stats2.TokenId, sizeof(LUID)), "expected different IDs\n");
8494 static void test_elevation(void)
8496 TOKEN_LINKED_TOKEN linked, linked2;
8497 DWORD orig_type, type, size;
8498 TOKEN_ELEVATION elevation;
8499 HANDLE token, token2;
8500 BOOL ret;
8502 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | READ_CONTROL | TOKEN_DUPLICATE
8503 | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_DEFAULT, &token);
8504 ok(ret, "got error %lu\n", GetLastError());
8506 ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size);
8507 ok(ret, "got error %lu\n", GetLastError());
8508 orig_type = type;
8509 ret = GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &size);
8510 ok(ret, "got error %lu\n", GetLastError());
8511 ret = GetTokenInformation(token, TokenLinkedToken, &linked, sizeof(linked), &size);
8512 if (!ret && GetLastError() == ERROR_NO_SUCH_LOGON_SESSION) /* fails on w2008s64 */
8514 win_skip("Failed to get linked token.\n");
8515 CloseHandle(token);
8516 return;
8518 ok(ret, "got error %lu\n", GetLastError());
8520 if (type == TokenElevationTypeDefault)
8522 ok(elevation.TokenIsElevated == FALSE, "got elevation %#lx\n", elevation.TokenIsElevated);
8523 ok(!linked.LinkedToken, "expected no linked token\n");
8525 else if (type == TokenElevationTypeLimited)
8527 ok(elevation.TokenIsElevated == FALSE, "got elevation %#lx\n", elevation.TokenIsElevated);
8528 ok(!!linked.LinkedToken, "expected a linked token\n");
8530 TEST_GRANTED_ACCESS(linked.LinkedToken, TOKEN_ALL_ACCESS);
8531 ret = GetTokenInformation(linked.LinkedToken, TokenElevationType, &type, sizeof(type), &size);
8532 ok(ret, "got error %lu\n", GetLastError());
8533 ok(type == TokenElevationTypeFull, "got type %#lx\n", type);
8534 ret = GetTokenInformation(linked.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size);
8535 ok(ret, "got error %lu\n", GetLastError());
8536 ok(elevation.TokenIsElevated == TRUE, "got elevation %#lx\n", elevation.TokenIsElevated);
8537 ret = GetTokenInformation(linked.LinkedToken, TokenType, &type, sizeof(type), &size);
8538 ok(ret, "got error %lu\n", GetLastError());
8539 ok(type == TokenImpersonation, "got type %#lx\n", type);
8540 ret = GetTokenInformation(linked.LinkedToken, TokenImpersonationLevel, &type, sizeof(type), &size);
8541 ok(ret, "got error %lu\n", GetLastError());
8542 ok(type == SecurityIdentification, "got impersonation level %#lx\n", type);
8544 /* Asking for the linked token again gives us a different token. */
8545 ret = GetTokenInformation(token, TokenLinkedToken, &linked2, sizeof(linked2), &size);
8546 ok(ret, "got error %lu\n", GetLastError());
8548 ret = GetTokenInformation(linked2.LinkedToken, TokenElevationType, &type, sizeof(type), &size);
8549 ok(ret, "got error %lu\n", GetLastError());
8550 ok(type == TokenElevationTypeFull, "got type %#lx\n", type);
8551 ret = GetTokenInformation(linked2.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size);
8552 ok(ret, "got error %lu\n", GetLastError());
8553 ok(elevation.TokenIsElevated == TRUE, "got elevation %#lx\n", elevation.TokenIsElevated);
8555 check_different_token(linked.LinkedToken, linked2.LinkedToken);
8557 CloseHandle(linked2.LinkedToken);
8559 /* Asking for the linked token's linked token gives us a new limited token. */
8560 ret = GetTokenInformation(linked.LinkedToken, TokenLinkedToken, &linked2, sizeof(linked2), &size);
8561 ok(ret, "got error %lu\n", GetLastError());
8563 ret = GetTokenInformation(linked2.LinkedToken, TokenElevationType, &type, sizeof(type), &size);
8564 ok(ret, "got error %lu\n", GetLastError());
8565 ok(type == TokenElevationTypeLimited, "got type %#lx\n", type);
8566 ret = GetTokenInformation(linked2.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size);
8567 ok(ret, "got error %lu\n", GetLastError());
8568 ok(elevation.TokenIsElevated == FALSE, "got elevation %#lx\n", elevation.TokenIsElevated);
8570 check_different_token(token, linked2.LinkedToken);
8572 CloseHandle(linked2.LinkedToken);
8574 CloseHandle(linked.LinkedToken);
8576 type = TokenElevationTypeLimited;
8577 ret = SetTokenInformation(token, TokenElevationType, &type, sizeof(type));
8578 ok(!ret, "expected failure\n");
8579 todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError());
8581 elevation.TokenIsElevated = FALSE;
8582 ret = SetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation));
8583 ok(!ret, "expected failure\n");
8584 todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError());
8586 else
8588 ok(elevation.TokenIsElevated == TRUE, "got elevation %#lx\n", elevation.TokenIsElevated);
8589 ok(!!linked.LinkedToken, "expected a linked token\n");
8591 TEST_GRANTED_ACCESS(linked.LinkedToken, TOKEN_ALL_ACCESS);
8592 ret = GetTokenInformation(linked.LinkedToken, TokenElevationType, &type, sizeof(type), &size);
8593 ok(ret, "got error %lu\n", GetLastError());
8594 ok(type == TokenElevationTypeLimited, "got type %#lx\n", type);
8595 ret = GetTokenInformation(linked.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size);
8596 ok(ret, "got error %lu\n", GetLastError());
8597 ok(elevation.TokenIsElevated == FALSE, "got elevation %#lx\n", elevation.TokenIsElevated);
8598 ret = GetTokenInformation(linked.LinkedToken, TokenType, &type, sizeof(type), &size);
8599 ok(ret, "got error %lu\n", GetLastError());
8600 ok(type == TokenImpersonation, "got type %#lx\n", type);
8601 ret = GetTokenInformation(linked.LinkedToken, TokenImpersonationLevel, &type, sizeof(type), &size);
8602 ok(ret, "got error %lu\n", GetLastError());
8603 ok(type == SecurityIdentification, "got impersonation level %#lx\n", type);
8605 /* Asking for the linked token again gives us a different token. */
8606 ret = GetTokenInformation(token, TokenLinkedToken, &linked2, sizeof(linked2), &size);
8607 ok(ret, "got error %lu\n", GetLastError());
8609 ret = GetTokenInformation(linked2.LinkedToken, TokenElevationType, &type, sizeof(type), &size);
8610 ok(ret, "got error %lu\n", GetLastError());
8611 ok(type == TokenElevationTypeLimited, "got type %#lx\n", type);
8612 ret = GetTokenInformation(linked2.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size);
8613 ok(ret, "got error %lu\n", GetLastError());
8614 ok(elevation.TokenIsElevated == FALSE, "got elevation %#lx\n", elevation.TokenIsElevated);
8616 check_different_token(linked.LinkedToken, linked2.LinkedToken);
8618 CloseHandle(linked2.LinkedToken);
8620 /* Asking for the linked token's linked token gives us a new elevated token. */
8621 ret = GetTokenInformation(linked.LinkedToken, TokenLinkedToken, &linked2, sizeof(linked2), &size);
8622 ok(ret, "got error %lu\n", GetLastError());
8624 ret = GetTokenInformation(linked2.LinkedToken, TokenElevationType, &type, sizeof(type), &size);
8625 ok(ret, "got error %lu\n", GetLastError());
8626 ok(type == TokenElevationTypeFull, "got type %#lx\n", type);
8627 ret = GetTokenInformation(linked2.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size);
8628 ok(ret, "got error %lu\n", GetLastError());
8629 ok(elevation.TokenIsElevated == TRUE, "got elevation %#lx\n", elevation.TokenIsElevated);
8631 check_different_token(token, linked2.LinkedToken);
8633 CloseHandle(linked2.LinkedToken);
8635 CloseHandle(linked.LinkedToken);
8637 type = TokenElevationTypeLimited;
8638 ret = SetTokenInformation(token, TokenElevationType, &type, sizeof(type));
8639 ok(!ret, "expected failure\n");
8640 todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError());
8642 elevation.TokenIsElevated = FALSE;
8643 ret = SetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation));
8644 ok(!ret, "expected failure\n");
8645 todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError());
8648 ret = DuplicateTokenEx(token, TOKEN_ALL_ACCESS, NULL, SecurityAnonymous, TokenPrimary, &token2);
8649 ok(ret, "got error %lu\n", GetLastError());
8650 ret = GetTokenInformation(token2, TokenElevationType, &type, sizeof(type), &size);
8651 ok(ret, "got error %lu\n", GetLastError());
8652 ok(type == orig_type, "expected same type\n");
8653 ret = GetTokenInformation(token2, TokenElevation, &elevation, sizeof(elevation), &size);
8654 ok(ret, "got error %lu\n", GetLastError());
8655 ok(elevation.TokenIsElevated == (type == TokenElevationTypeFull), "got elevation %#lx\n", elevation.TokenIsElevated);
8656 ret = GetTokenInformation(token2, TokenLinkedToken, &linked, sizeof(linked), &size);
8657 ok(ret, "got error %lu\n", GetLastError());
8658 if (type == TokenElevationTypeDefault)
8660 ok(!linked.LinkedToken, "expected no linked token\n");
8661 ret = GetTokenInformation(linked.LinkedToken, TokenType, &type, sizeof(type), &size);
8662 ok(ret, "got error %lu\n", GetLastError());
8663 ok(type == TokenImpersonation, "got type %#lx\n", type);
8664 ret = GetTokenInformation(linked.LinkedToken, TokenImpersonationLevel, &type, sizeof(type), &size);
8665 ok(ret, "got error %lu\n", GetLastError());
8666 ok(type == SecurityIdentification, "got impersonation level %#lx\n", type);
8667 CloseHandle(linked.LinkedToken);
8669 else
8670 ok(!!linked.LinkedToken, "expected a linked token\n");
8671 CloseHandle(token2);
8673 ret = CreateRestrictedToken(token, 0, 0, NULL, 0, NULL, 0, NULL, &token2);
8674 ok(ret, "got error %lu\n", GetLastError());
8675 ret = GetTokenInformation(token2, TokenElevationType, &type, sizeof(type), &size);
8676 ok(ret, "got error %lu\n", GetLastError());
8677 ok(type == orig_type, "expected same type\n");
8678 ret = GetTokenInformation(token2, TokenElevation, &elevation, sizeof(elevation), &size);
8679 ok(ret, "got error %lu\n", GetLastError());
8680 ok(elevation.TokenIsElevated == (type == TokenElevationTypeFull), "got elevation %#lx\n", elevation.TokenIsElevated);
8681 ret = GetTokenInformation(token2, TokenLinkedToken, &linked, sizeof(linked), &size);
8682 ok(ret, "got error %lu\n", GetLastError());
8683 if (type == TokenElevationTypeDefault)
8684 ok(!linked.LinkedToken, "expected no linked token\n");
8685 else
8686 ok(!!linked.LinkedToken, "expected a linked token\n");
8687 CloseHandle(linked.LinkedToken);
8688 CloseHandle(token2);
8690 if (type != TokenElevationTypeDefault)
8692 char prev_privs_buffer[128], acl_buffer[256], prev_acl_buffer[256];
8693 TOKEN_PRIVILEGES privs, *prev_privs = (TOKEN_PRIVILEGES *)prev_privs_buffer;
8694 TOKEN_DEFAULT_DACL *prev_acl = (TOKEN_DEFAULT_DACL *)prev_acl_buffer;
8695 TOKEN_DEFAULT_DACL *ret_acl = (TOKEN_DEFAULT_DACL *)acl_buffer;
8696 TOKEN_DEFAULT_DACL default_acl;
8697 PRIVILEGE_SET priv_set;
8698 BOOL ret, is_member;
8699 DWORD size;
8700 ACL acl;
8702 /* Linked tokens do not preserve privilege modifications. */
8704 privs.PrivilegeCount = 1;
8705 ret = LookupPrivilegeValueA(NULL, "SeChangeNotifyPrivilege", &privs.Privileges[0].Luid);
8706 ok(ret, "got error %lu\n", GetLastError());
8707 privs.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED;
8708 ret = AdjustTokenPrivileges(token, FALSE, &privs, sizeof(prev_privs_buffer), prev_privs, &size);
8709 ok(ret, "got error %lu\n", GetLastError());
8711 priv_set.PrivilegeCount = 1;
8712 priv_set.Control = 0;
8713 priv_set.Privilege[0] = privs.Privileges[0];
8714 ret = PrivilegeCheck(token, &priv_set, &is_member);
8715 ok(ret, "got error %lu\n", GetLastError());
8716 ok(!is_member, "not a member\n");
8718 ret = GetTokenInformation(token, TokenLinkedToken, &linked, sizeof(linked), &size);
8719 ok(ret, "got error %lu\n", GetLastError());
8721 ret = PrivilegeCheck(linked.LinkedToken, &priv_set, &is_member);
8722 ok(ret, "got error %lu\n", GetLastError());
8723 ok(is_member, "not a member\n");
8725 CloseHandle(linked.LinkedToken);
8727 ret = AdjustTokenPrivileges(token, FALSE, prev_privs, 0, NULL, NULL);
8728 ok(ret, "got error %lu\n", GetLastError());
8730 /* Linked tokens do not preserve default DACL modifications. */
8732 ret = GetTokenInformation(token, TokenDefaultDacl, prev_acl, sizeof(prev_acl_buffer), &size);
8733 ok(ret, "got error %lu\n", GetLastError());
8734 ok(prev_acl->DefaultDacl->AceCount, "expected non-empty default DACL\n");
8736 InitializeAcl(&acl, sizeof(acl), ACL_REVISION);
8737 default_acl.DefaultDacl = &acl;
8738 ret = SetTokenInformation(token, TokenDefaultDacl, &default_acl, sizeof(default_acl));
8739 ok(ret, "got error %lu\n", GetLastError());
8741 ret = GetTokenInformation(token, TokenDefaultDacl, ret_acl, sizeof(acl_buffer), &size);
8742 ok(ret, "got error %lu\n", GetLastError());
8743 ok(!ret_acl->DefaultDacl->AceCount, "expected empty default DACL\n");
8745 ret = GetTokenInformation(token, TokenLinkedToken, &linked, sizeof(linked), &size);
8746 ok(ret, "got error %lu\n", GetLastError());
8748 ret = GetTokenInformation(linked.LinkedToken, TokenDefaultDacl, ret_acl, sizeof(acl_buffer), &size);
8749 ok(ret, "got error %lu\n", GetLastError());
8750 ok(ret_acl->DefaultDacl->AceCount, "expected non-empty default DACL\n");
8752 CloseHandle(linked.LinkedToken);
8754 ret = SetTokenInformation(token, TokenDefaultDacl, prev_acl, sizeof(*prev_acl));
8755 ok(ret, "got error %lu\n", GetLastError());
8758 CloseHandle(token);
8761 static void test_group_as_file_owner(void)
8763 char sd_buffer[200], sid_buffer[100];
8764 SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)sd_buffer;
8765 char temp_path[MAX_PATH], path[MAX_PATH];
8766 SID *admin_sid = (SID *)sid_buffer;
8767 BOOL ret, present, defaulted;
8768 SECURITY_DESCRIPTOR new_sd;
8769 HANDLE file;
8770 DWORD size;
8771 ACL *dacl;
8773 /* The EA Origin client sets the SD owner of a directory to Administrators,
8774 * while using the default DACL, and subsequently tries to create
8775 * subdirectories. */
8777 size = sizeof(sid_buffer);
8778 CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &size);
8780 ret = CheckTokenMembership(NULL, admin_sid, &present);
8781 ok(ret, "got error %lu\n", GetLastError());
8782 if (!present)
8784 skip("user is not an administrator\n");
8785 return;
8788 GetTempPathA(ARRAY_SIZE(temp_path), temp_path);
8789 sprintf(path, "%s\\testdir", temp_path);
8791 ret = CreateDirectoryA(path, NULL);
8792 ok(ret, "got error %lu\n", GetLastError());
8794 file = CreateFileA(path, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
8795 ok(file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError());
8797 ret = GetKernelObjectSecurity(file, DACL_SECURITY_INFORMATION, sd_buffer, sizeof(sd_buffer), &size);
8798 ok(ret, "got error %lu\n", GetLastError());
8799 ret = GetSecurityDescriptorDacl(sd, &present, &dacl, &defaulted);
8800 ok(ret, "got error %lu\n", GetLastError());
8802 InitializeSecurityDescriptor(&new_sd, SECURITY_DESCRIPTOR_REVISION);
8804 ret = SetSecurityDescriptorOwner(&new_sd, admin_sid, FALSE);
8805 ok(ret, "got error %lu\n", GetLastError());
8807 ret = GetSecurityDescriptorDacl(sd, &present, &dacl, &defaulted);
8808 ok(ret, "got error %lu\n", GetLastError());
8810 ret = SetSecurityDescriptorDacl(&new_sd, present, dacl, defaulted);
8811 ok(ret, "got error %lu\n", GetLastError());
8813 ret = SetKernelObjectSecurity(file, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, &new_sd);
8814 ok(ret, "got error %lu\n", GetLastError());
8816 CloseHandle(file);
8818 sprintf(path, "%s\\testdir\\subdir", temp_path);
8819 ret = CreateDirectoryA(path, NULL);
8820 ok(ret, "got error %lu\n", GetLastError());
8822 ret = RemoveDirectoryA(path);
8823 ok(ret, "got error %lu\n", GetLastError());
8824 sprintf(path, "%s\\testdir", temp_path);
8825 ret = RemoveDirectoryA(path);
8826 ok(ret, "got error %lu\n", GetLastError());
8829 static void test_IsValidSecurityDescriptor(void)
8831 SECURITY_DESCRIPTOR *sd;
8832 BOOL ret;
8834 SetLastError(0xdeadbeef);
8835 ret = IsValidSecurityDescriptor(NULL);
8836 ok(!ret, "Unexpected return value %d.\n", ret);
8837 ok(GetLastError() == ERROR_INVALID_SECURITY_DESCR, "Unexpected error %ld.\n", GetLastError());
8839 sd = calloc(1, SECURITY_DESCRIPTOR_MIN_LENGTH);
8841 SetLastError(0xdeadbeef);
8842 ret = IsValidSecurityDescriptor(sd);
8843 ok(!ret, "Unexpected return value %d.\n", ret);
8844 ok(GetLastError() == ERROR_INVALID_SECURITY_DESCR, "Unexpected error %ld.\n", GetLastError());
8846 ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
8847 ok(ret, "Unexpected return value %d, error %ld.\n", ret, GetLastError());
8849 SetLastError(0xdeadbeef);
8850 ret = IsValidSecurityDescriptor(sd);
8851 ok(ret, "Unexpected return value %d.\n", ret);
8852 ok(GetLastError() == 0xdeadbeef, "Unexpected error %ld.\n", GetLastError());
8854 free(sd);
8857 static void test_window_security(void)
8859 PSECURITY_DESCRIPTOR sd;
8860 BOOL present, defaulted;
8861 HDESK desktop;
8862 DWORD ret;
8863 ACL *dacl;
8865 desktop = GetThreadDesktop(GetCurrentThreadId());
8867 ret = GetSecurityInfo(desktop, SE_WINDOW_OBJECT,
8868 DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &sd);
8869 ok(!ret, "got error %lu\n", ret);
8871 ret = GetSecurityDescriptorDacl(sd, &present, &dacl, &defaulted);
8872 ok(ret == TRUE, "got error %lu\n", GetLastError());
8873 todo_wine ok(present == TRUE, "got present %d\n", present);
8874 ok(defaulted == FALSE, "got defaulted %d\n", defaulted);
8876 LocalFree(sd);
8879 START_TEST(security)
8881 init();
8882 if (!hmod) return;
8884 if (myARGC >= 3)
8886 if (!strcmp(myARGV[2], "test_token_sd"))
8887 test_child_token_sd();
8888 else if (!strcmp(myARGV[2], "test"))
8889 test_process_security_child();
8890 else if (!strcmp(myARGV[2], "duplicate"))
8891 test_duplicate_handle_access_child();
8892 else if (!strcmp(myARGV[2], "restricted"))
8893 test_create_process_token_child();
8894 return;
8896 test_kernel_objects_security();
8897 test_ConvertStringSidToSid();
8898 test_trustee();
8899 test_allocateLuid();
8900 test_lookupPrivilegeName();
8901 test_lookupPrivilegeValue();
8902 test_CreateWellKnownSid();
8903 test_FileSecurity();
8904 test_AccessCheck();
8905 test_token_attr();
8906 test_GetTokenInformation();
8907 test_LookupAccountSid();
8908 test_LookupAccountName();
8909 test_security_descriptor();
8910 test_process_security();
8911 test_impersonation_level();
8912 test_SetEntriesInAclW();
8913 test_SetEntriesInAclA();
8914 test_CreateDirectoryA();
8915 test_GetNamedSecurityInfoA();
8916 test_ConvertStringSecurityDescriptor();
8917 test_ConvertSecurityDescriptorToString();
8918 test_PrivateObjectSecurity();
8919 test_InitializeAcl();
8920 test_GetWindowsAccountDomainSid();
8921 test_EqualDomainSid();
8922 test_GetSecurityInfo();
8923 test_GetSidSubAuthority();
8924 test_CheckTokenMembership();
8925 test_EqualSid();
8926 test_GetUserNameA();
8927 test_GetUserNameW();
8928 test_CreateRestrictedToken();
8929 test_TokenIntegrityLevel();
8930 test_default_dacl_owner_group_sid();
8931 test_AdjustTokenPrivileges();
8932 test_AddAce();
8933 test_AddMandatoryAce();
8934 test_system_security_access();
8935 test_GetSidIdentifierAuthority();
8936 test_pseudo_tokens();
8937 test_maximum_allowed();
8938 test_token_label();
8939 test_GetExplicitEntriesFromAclW();
8940 test_BuildSecurityDescriptorW();
8941 test_duplicate_handle_access();
8942 test_create_process_token();
8943 test_pseudo_handle_security();
8944 test_duplicate_token();
8945 test_GetKernelObjectSecurity();
8946 test_elevation();
8947 test_group_as_file_owner();
8948 test_IsValidSecurityDescriptor();
8949 test_window_security();
8951 /* Must be the last test, modifies process token */
8952 test_token_security_descriptor();