winex11.drv: Map coordinates before calling send_mouse_input.
[wine/zf.git] / dlls / advapi32 / tests / security.c
blobce9c26d238e9a039a2fea18a31b50eedcccd884f
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)(LPSTR, 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=%u", 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 HeapFree(GetProcessHeap(), 0, 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 %d\n", GetLastError());
197 ok_(__FILE__, line)(needed != 0xdeadbeef, "GetKernelObjectSecurity should return required buffer length\n");
199 length = needed;
200 sd = HeapAlloc(GetProcessHeap(), 0, 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 %d\n", GetLastError());
207 ok_(__FILE__, line)(needed == length || needed == 0 /* file, pipe */, "GetKernelObjectSecurity should return %u instead of %u\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 %d\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 HeapFree(GetProcessHeap(), 0, 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 %d\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 HeapFree(GetProcessHeap(), 0, 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 { "CO", "S-1-3-0" },
269 { "CG", "S-1-3-1" },
270 { "OW", "S-1-3-4", 1 }, /* Vista+ */
271 { "NU", "S-1-5-2" },
272 { "IU", "S-1-5-4" },
273 { "SU", "S-1-5-6" },
274 { "AN", "S-1-5-7" },
275 { "ED", "S-1-5-9" },
276 { "PS", "S-1-5-10" },
277 { "AU", "S-1-5-11" },
278 { "RC", "S-1-5-12" },
279 { "SY", "S-1-5-18" },
280 { "LS", "S-1-5-19" },
281 { "NS", "S-1-5-20" },
282 { "LA", "S-1-5-21-*-*-*-500" },
283 { "LG", "S-1-5-21-*-*-*-501" },
284 { "BO", "S-1-5-32-551" },
285 { "BA", "S-1-5-32-544" },
286 { "BU", "S-1-5-32-545" },
287 { "BG", "S-1-5-32-546" },
288 { "PU", "S-1-5-32-547" },
289 { "AO", "S-1-5-32-548" },
290 { "SO", "S-1-5-32-549" },
291 { "PO", "S-1-5-32-550" },
292 { "RE", "S-1-5-32-552" },
293 { "RU", "S-1-5-32-554" },
294 { "RD", "S-1-5-32-555" },
295 { "NO", "S-1-5-32-556" },
296 { "AC", "S-1-15-2-1", 1 }, /* Win8+ */
297 { "CA", "", 1 },
298 { "DA", "", 1 },
299 { "DC", "", 1 },
300 { "DD", "", 1 },
301 { "DG", "", 1 },
302 { "DU", "", 1 },
303 { "EA", "", 1 },
304 { "PA", "", 1 },
305 { "RS", "", 1 },
306 { "SA", "", 1 },
309 const char noSubAuthStr[] = "S-1-5";
310 unsigned int i;
311 PSID psid = NULL;
312 SID *pisid;
313 BOOL r, ret;
314 LPSTR str = NULL;
316 r = ConvertStringSidToSidA( NULL, NULL );
317 ok( !r, "expected failure with NULL parameters\n" );
318 if( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED )
319 return;
320 ok( GetLastError() == ERROR_INVALID_PARAMETER,
321 "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n",
322 GetLastError() );
324 r = ConvertStringSidToSidA( refs[0].refStr, NULL );
325 ok( !r && GetLastError() == ERROR_INVALID_PARAMETER,
326 "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n",
327 GetLastError() );
329 r = ConvertStringSidToSidA( NULL, &psid );
330 ok( !r && GetLastError() == ERROR_INVALID_PARAMETER,
331 "expected GetLastError() is ERROR_INVALID_PARAMETER, got %d\n",
332 GetLastError() );
334 r = ConvertStringSidToSidA( noSubAuthStr, &psid );
335 ok( !r,
336 "expected failure with no sub authorities\n" );
337 ok( GetLastError() == ERROR_INVALID_SID,
338 "expected GetLastError() is ERROR_INVALID_SID, got %d\n",
339 GetLastError() );
341 ok(ConvertStringSidToSidA("S-1-5-21-93476-23408-4576", &psid), "ConvertStringSidToSidA failed\n");
342 pisid = psid;
343 ok(pisid->SubAuthorityCount == 4, "Invalid sub authority count - expected 4, got %d\n", pisid->SubAuthorityCount);
344 ok(pisid->SubAuthority[0] == 21, "Invalid subauthority 0 - expected 21, got %d\n", pisid->SubAuthority[0]);
345 ok(pisid->SubAuthority[3] == 4576, "Invalid subauthority 0 - expected 4576, got %d\n", pisid->SubAuthority[3]);
346 LocalFree(str);
347 LocalFree(psid);
349 for( i = 0; i < ARRAY_SIZE(refs); i++ )
351 r = AllocateAndInitializeSid( &refs[i].auth, 1,1,0,0,0,0,0,0,0,
352 &psid );
353 ok( r, "failed to allocate sid\n" );
354 r = ConvertSidToStringSidA( psid, &str );
355 ok( r, "failed to convert sid\n" );
356 if (r)
358 ok( !strcmp( str, refs[i].refStr ),
359 "incorrect sid, expected %s, got %s\n", refs[i].refStr, str );
360 LocalFree( str );
362 if( psid )
363 FreeSid( psid );
365 r = ConvertStringSidToSidA( refs[i].refStr, &psid );
366 ok( r, "failed to parse sid string\n" );
367 pisid = psid;
368 ok( pisid &&
369 !memcmp( pisid->IdentifierAuthority.Value, refs[i].auth.Value,
370 sizeof(refs[i].auth) ),
371 "string sid %s didn't parse to expected value\n"
372 "(got 0x%04x%08x, expected 0x%04x%08x)\n",
373 refs[i].refStr,
374 MAKEWORD( pisid->IdentifierAuthority.Value[1],
375 pisid->IdentifierAuthority.Value[0] ),
376 MAKELONG( MAKEWORD( pisid->IdentifierAuthority.Value[5],
377 pisid->IdentifierAuthority.Value[4] ),
378 MAKEWORD( pisid->IdentifierAuthority.Value[3],
379 pisid->IdentifierAuthority.Value[2] ) ),
380 MAKEWORD( refs[i].auth.Value[1], refs[i].auth.Value[0] ),
381 MAKELONG( MAKEWORD( refs[i].auth.Value[5], refs[i].auth.Value[4] ),
382 MAKEWORD( refs[i].auth.Value[3], refs[i].auth.Value[2] ) ) );
383 if( psid )
384 LocalFree( psid );
387 for (i = 0; i < ARRAY_SIZE(str_to_sid_tests); i++)
389 char *str;
391 ret = ConvertStringSidToSidA(str_to_sid_tests[i].name, &psid);
392 if (!ret && str_to_sid_tests[i].optional)
394 skip("%u: failed to convert %s.\n", i, str_to_sid_tests[i].name);
395 continue;
397 ok(ret, "%u: failed to convert string to sid.\n", i);
399 if (str_to_sid_tests[i].optional || !strcmp(str_to_sid_tests[i].name, "LA") ||
400 !strcmp(str_to_sid_tests[i].name, "LG"))
402 LocalFree(psid);
403 continue;
406 ret = ConvertSidToStringSidA(psid, &str);
407 ok(ret, "%u: failed to convert SID to string.\n", i);
408 ok(!strcmp(str, str_to_sid_tests[i].sid), "%u: unexpected sid %s.\n", i, str);
409 LocalFree(psid);
410 LocalFree(str);
414 static void test_trustee(void)
416 GUID ObjectType = {0x12345678, 0x1234, 0x5678, {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}};
417 GUID InheritedObjectType = {0x23456789, 0x2345, 0x6786, {0x2, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}};
418 GUID ZeroGuid;
419 OBJECTS_AND_NAME_A oan;
420 OBJECTS_AND_SID oas;
421 TRUSTEEA trustee;
422 PSID psid;
423 char szObjectTypeName[] = "ObjectTypeName";
424 char szInheritedObjectTypeName[] = "InheritedObjectTypeName";
425 char szTrusteeName[] = "szTrusteeName";
426 SID_IDENTIFIER_AUTHORITY auth = { {0x11,0x22,0,0,0, 0} };
428 memset( &ZeroGuid, 0x00, sizeof (ZeroGuid) );
430 pBuildTrusteeWithSidA = (void *)GetProcAddress( hmod, "BuildTrusteeWithSidA" );
431 pBuildTrusteeWithNameA = (void *)GetProcAddress( hmod, "BuildTrusteeWithNameA" );
432 pBuildTrusteeWithObjectsAndNameA = (void *)GetProcAddress (hmod, "BuildTrusteeWithObjectsAndNameA" );
433 pBuildTrusteeWithObjectsAndSidA = (void *)GetProcAddress (hmod, "BuildTrusteeWithObjectsAndSidA" );
434 pGetTrusteeNameA = (void *)GetProcAddress (hmod, "GetTrusteeNameA" );
435 if( !pBuildTrusteeWithSidA || !pBuildTrusteeWithNameA ||
436 !pBuildTrusteeWithObjectsAndNameA || !pBuildTrusteeWithObjectsAndSidA ||
437 !pGetTrusteeNameA )
438 return;
440 if ( ! AllocateAndInitializeSid( &auth, 1, 42, 0,0,0,0,0,0,0,&psid ) )
442 trace( "failed to init SID\n" );
443 return;
446 /* test BuildTrusteeWithSidA */
447 memset( &trustee, 0xff, sizeof trustee );
448 pBuildTrusteeWithSidA( &trustee, psid );
450 ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
451 ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE,
452 "MultipleTrusteeOperation wrong\n");
453 ok( trustee.TrusteeForm == TRUSTEE_IS_SID, "TrusteeForm wrong\n");
454 ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
455 ok( trustee.ptstrName == psid, "ptstrName wrong\n" );
457 /* test BuildTrusteeWithObjectsAndSidA (test 1) */
458 memset( &trustee, 0xff, sizeof trustee );
459 memset( &oas, 0xff, sizeof(oas) );
460 pBuildTrusteeWithObjectsAndSidA(&trustee, &oas, &ObjectType,
461 &InheritedObjectType, psid);
463 ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
464 ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
465 ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_SID, "TrusteeForm wrong\n");
466 ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
467 ok(trustee.ptstrName == (LPSTR)&oas, "ptstrName wrong\n");
469 ok(oas.ObjectsPresent == (ACE_OBJECT_TYPE_PRESENT | ACE_INHERITED_OBJECT_TYPE_PRESENT), "ObjectsPresent wrong\n");
470 ok(!memcmp(&oas.ObjectTypeGuid, &ObjectType, sizeof(GUID)), "ObjectTypeGuid wrong\n");
471 ok(!memcmp(&oas.InheritedObjectTypeGuid, &InheritedObjectType, sizeof(GUID)), "InheritedObjectTypeGuid wrong\n");
472 ok(oas.pSid == psid, "pSid wrong\n");
474 /* test GetTrusteeNameA */
475 ok(pGetTrusteeNameA(&trustee) == (LPSTR)&oas, "GetTrusteeName returned wrong value\n");
477 /* test BuildTrusteeWithObjectsAndSidA (test 2) */
478 memset( &trustee, 0xff, sizeof trustee );
479 memset( &oas, 0xff, sizeof(oas) );
480 pBuildTrusteeWithObjectsAndSidA(&trustee, &oas, NULL,
481 &InheritedObjectType, psid);
483 ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
484 ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
485 ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_SID, "TrusteeForm wrong\n");
486 ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
487 ok(trustee.ptstrName == (LPSTR)&oas, "ptstrName wrong\n");
489 ok(oas.ObjectsPresent == ACE_INHERITED_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
490 ok(!memcmp(&oas.ObjectTypeGuid, &ZeroGuid, sizeof(GUID)), "ObjectTypeGuid wrong\n");
491 ok(!memcmp(&oas.InheritedObjectTypeGuid, &InheritedObjectType, sizeof(GUID)), "InheritedObjectTypeGuid wrong\n");
492 ok(oas.pSid == psid, "pSid wrong\n");
494 FreeSid( psid );
496 /* test BuildTrusteeWithNameA */
497 memset( &trustee, 0xff, sizeof trustee );
498 pBuildTrusteeWithNameA( &trustee, szTrusteeName );
500 ok( trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
501 ok( trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE,
502 "MultipleTrusteeOperation wrong\n");
503 ok( trustee.TrusteeForm == TRUSTEE_IS_NAME, "TrusteeForm wrong\n");
504 ok( trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
505 ok( trustee.ptstrName == szTrusteeName, "ptstrName wrong\n" );
507 /* test BuildTrusteeWithObjectsAndNameA (test 1) */
508 memset( &trustee, 0xff, sizeof trustee );
509 memset( &oan, 0xff, sizeof(oan) );
510 pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, szObjectTypeName,
511 szInheritedObjectTypeName, szTrusteeName);
513 ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
514 ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
515 ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
516 ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
517 ok(trustee.ptstrName == (LPSTR)&oan, "ptstrName wrong\n");
519 ok(oan.ObjectsPresent == (ACE_OBJECT_TYPE_PRESENT | ACE_INHERITED_OBJECT_TYPE_PRESENT), "ObjectsPresent wrong\n");
520 ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
521 ok(oan.InheritedObjectTypeName == szInheritedObjectTypeName, "InheritedObjectTypeName wrong\n");
522 ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
524 /* test GetTrusteeNameA */
525 ok(pGetTrusteeNameA(&trustee) == (LPSTR)&oan, "GetTrusteeName returned wrong value\n");
527 /* test BuildTrusteeWithObjectsAndNameA (test 2) */
528 memset( &trustee, 0xff, sizeof trustee );
529 memset( &oan, 0xff, sizeof(oan) );
530 pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, NULL,
531 szInheritedObjectTypeName, szTrusteeName);
533 ok(trustee.pMultipleTrustee == NULL, "pMultipleTrustee wrong\n");
534 ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
535 ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
536 ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
537 ok(trustee.ptstrName == (LPSTR)&oan, "ptstrName wrong\n");
539 ok(oan.ObjectsPresent == ACE_INHERITED_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
540 ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
541 ok(oan.InheritedObjectTypeName == szInheritedObjectTypeName, "InheritedObjectTypeName wrong\n");
542 ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
544 /* test BuildTrusteeWithObjectsAndNameA (test 3) */
545 memset( &trustee, 0xff, sizeof trustee );
546 memset( &oan, 0xff, sizeof(oan) );
547 pBuildTrusteeWithObjectsAndNameA(&trustee, &oan, SE_KERNEL_OBJECT, szObjectTypeName,
548 NULL, 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_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
557 ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
558 ok(oan.InheritedObjectTypeName == NULL, "InheritedObjectTypeName wrong\n");
559 ok(oan.ptstrName == szTrusteeName, "szTrusteeName wrong\n");
562 /* If the first isn't defined, assume none is */
563 #ifndef SE_MIN_WELL_KNOWN_PRIVILEGE
564 #define SE_MIN_WELL_KNOWN_PRIVILEGE 2L
565 #define SE_CREATE_TOKEN_PRIVILEGE 2L
566 #define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE 3L
567 #define SE_LOCK_MEMORY_PRIVILEGE 4L
568 #define SE_INCREASE_QUOTA_PRIVILEGE 5L
569 #define SE_MACHINE_ACCOUNT_PRIVILEGE 6L
570 #define SE_TCB_PRIVILEGE 7L
571 #define SE_SECURITY_PRIVILEGE 8L
572 #define SE_TAKE_OWNERSHIP_PRIVILEGE 9L
573 #define SE_LOAD_DRIVER_PRIVILEGE 10L
574 #define SE_SYSTEM_PROFILE_PRIVILEGE 11L
575 #define SE_SYSTEMTIME_PRIVILEGE 12L
576 #define SE_PROF_SINGLE_PROCESS_PRIVILEGE 13L
577 #define SE_INC_BASE_PRIORITY_PRIVILEGE 14L
578 #define SE_CREATE_PAGEFILE_PRIVILEGE 15L
579 #define SE_CREATE_PERMANENT_PRIVILEGE 16L
580 #define SE_BACKUP_PRIVILEGE 17L
581 #define SE_RESTORE_PRIVILEGE 18L
582 #define SE_SHUTDOWN_PRIVILEGE 19L
583 #define SE_DEBUG_PRIVILEGE 20L
584 #define SE_AUDIT_PRIVILEGE 21L
585 #define SE_SYSTEM_ENVIRONMENT_PRIVILEGE 22L
586 #define SE_CHANGE_NOTIFY_PRIVILEGE 23L
587 #define SE_REMOTE_SHUTDOWN_PRIVILEGE 24L
588 #define SE_UNDOCK_PRIVILEGE 25L
589 #define SE_SYNC_AGENT_PRIVILEGE 26L
590 #define SE_ENABLE_DELEGATION_PRIVILEGE 27L
591 #define SE_MANAGE_VOLUME_PRIVILEGE 28L
592 #define SE_IMPERSONATE_PRIVILEGE 29L
593 #define SE_CREATE_GLOBAL_PRIVILEGE 30L
594 #define SE_MAX_WELL_KNOWN_PRIVILEGE SE_CREATE_GLOBAL_PRIVILEGE
595 #endif /* ndef SE_MIN_WELL_KNOWN_PRIVILEGE */
597 static void test_allocateLuid(void)
599 BOOL (WINAPI *pAllocateLocallyUniqueId)(PLUID);
600 LUID luid1, luid2;
601 BOOL ret;
603 pAllocateLocallyUniqueId = (void*)GetProcAddress(hmod, "AllocateLocallyUniqueId");
604 if (!pAllocateLocallyUniqueId) return;
606 ret = pAllocateLocallyUniqueId(&luid1);
607 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
608 return;
610 ok(ret,
611 "AllocateLocallyUniqueId failed: %d\n", GetLastError());
612 ret = pAllocateLocallyUniqueId(&luid2);
613 ok( ret,
614 "AllocateLocallyUniqueId failed: %d\n", GetLastError());
615 ok(luid1.LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE || luid1.HighPart != 0,
616 "AllocateLocallyUniqueId returned a well-known LUID\n");
617 ok(luid1.LowPart != luid2.LowPart || luid1.HighPart != luid2.HighPart,
618 "AllocateLocallyUniqueId returned non-unique LUIDs\n");
619 ret = pAllocateLocallyUniqueId(NULL);
620 ok( !ret && GetLastError() == ERROR_NOACCESS,
621 "AllocateLocallyUniqueId(NULL) didn't return ERROR_NOACCESS: %d\n",
622 GetLastError());
625 static void test_lookupPrivilegeName(void)
627 BOOL (WINAPI *pLookupPrivilegeNameA)(LPCSTR, PLUID, LPSTR, LPDWORD);
628 char buf[MAX_PATH]; /* arbitrary, seems long enough */
629 DWORD cchName = sizeof(buf);
630 LUID luid = { 0, 0 };
631 LONG i;
632 BOOL ret;
634 /* check whether it's available first */
635 pLookupPrivilegeNameA = (void*)GetProcAddress(hmod, "LookupPrivilegeNameA");
636 if (!pLookupPrivilegeNameA) return;
637 luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
638 ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
639 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
640 return;
642 /* check with a short buffer */
643 cchName = 0;
644 luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
645 ret = pLookupPrivilegeNameA(NULL, &luid, NULL, &cchName);
646 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
647 "LookupPrivilegeNameA didn't fail with ERROR_INSUFFICIENT_BUFFER: %d\n",
648 GetLastError());
649 ok(cchName == strlen("SeCreateTokenPrivilege") + 1,
650 "LookupPrivilegeNameA returned an incorrect required length for\n"
651 "SeCreateTokenPrivilege (got %d, expected %d)\n", cchName,
652 lstrlenA("SeCreateTokenPrivilege") + 1);
653 /* check a known value and its returned length on success */
654 cchName = sizeof(buf);
655 ok(pLookupPrivilegeNameA(NULL, &luid, buf, &cchName) &&
656 cchName == strlen("SeCreateTokenPrivilege"),
657 "LookupPrivilegeNameA returned an incorrect output length for\n"
658 "SeCreateTokenPrivilege (got %d, expected %d)\n", cchName,
659 (int)strlen("SeCreateTokenPrivilege"));
660 /* check known values */
661 for (i = SE_MIN_WELL_KNOWN_PRIVILEGE; i <= SE_MAX_WELL_KNOWN_PRIVILEGE; i++)
663 luid.LowPart = i;
664 cchName = sizeof(buf);
665 ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
666 ok( ret || GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
667 "LookupPrivilegeNameA(0.%d) failed: %d\n", i, GetLastError());
669 /* check a bogus LUID */
670 luid.LowPart = 0xdeadbeef;
671 cchName = sizeof(buf);
672 ret = pLookupPrivilegeNameA(NULL, &luid, buf, &cchName);
673 ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
674 "LookupPrivilegeNameA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n",
675 GetLastError());
676 /* check on a bogus system */
677 luid.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
678 cchName = sizeof(buf);
679 ret = pLookupPrivilegeNameA("b0gu5.Nam3", &luid, buf, &cchName);
680 ok( !ret && (GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
681 GetLastError() == RPC_S_INVALID_NET_ADDR) /* w2k8 */,
682 "LookupPrivilegeNameA didn't fail with RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR: %d\n",
683 GetLastError());
686 struct NameToLUID
688 const char *name;
689 DWORD lowPart;
692 static void test_lookupPrivilegeValue(void)
694 static const struct NameToLUID privs[] = {
695 { "SeCreateTokenPrivilege", SE_CREATE_TOKEN_PRIVILEGE },
696 { "SeAssignPrimaryTokenPrivilege", SE_ASSIGNPRIMARYTOKEN_PRIVILEGE },
697 { "SeLockMemoryPrivilege", SE_LOCK_MEMORY_PRIVILEGE },
698 { "SeIncreaseQuotaPrivilege", SE_INCREASE_QUOTA_PRIVILEGE },
699 { "SeMachineAccountPrivilege", SE_MACHINE_ACCOUNT_PRIVILEGE },
700 { "SeTcbPrivilege", SE_TCB_PRIVILEGE },
701 { "SeSecurityPrivilege", SE_SECURITY_PRIVILEGE },
702 { "SeTakeOwnershipPrivilege", SE_TAKE_OWNERSHIP_PRIVILEGE },
703 { "SeLoadDriverPrivilege", SE_LOAD_DRIVER_PRIVILEGE },
704 { "SeSystemProfilePrivilege", SE_SYSTEM_PROFILE_PRIVILEGE },
705 { "SeSystemtimePrivilege", SE_SYSTEMTIME_PRIVILEGE },
706 { "SeProfileSingleProcessPrivilege", SE_PROF_SINGLE_PROCESS_PRIVILEGE },
707 { "SeIncreaseBasePriorityPrivilege", SE_INC_BASE_PRIORITY_PRIVILEGE },
708 { "SeCreatePagefilePrivilege", SE_CREATE_PAGEFILE_PRIVILEGE },
709 { "SeCreatePermanentPrivilege", SE_CREATE_PERMANENT_PRIVILEGE },
710 { "SeBackupPrivilege", SE_BACKUP_PRIVILEGE },
711 { "SeRestorePrivilege", SE_RESTORE_PRIVILEGE },
712 { "SeShutdownPrivilege", SE_SHUTDOWN_PRIVILEGE },
713 { "SeDebugPrivilege", SE_DEBUG_PRIVILEGE },
714 { "SeAuditPrivilege", SE_AUDIT_PRIVILEGE },
715 { "SeSystemEnvironmentPrivilege", SE_SYSTEM_ENVIRONMENT_PRIVILEGE },
716 { "SeChangeNotifyPrivilege", SE_CHANGE_NOTIFY_PRIVILEGE },
717 { "SeRemoteShutdownPrivilege", SE_REMOTE_SHUTDOWN_PRIVILEGE },
718 { "SeUndockPrivilege", SE_UNDOCK_PRIVILEGE },
719 { "SeSyncAgentPrivilege", SE_SYNC_AGENT_PRIVILEGE },
720 { "SeEnableDelegationPrivilege", SE_ENABLE_DELEGATION_PRIVILEGE },
721 { "SeManageVolumePrivilege", SE_MANAGE_VOLUME_PRIVILEGE },
722 { "SeImpersonatePrivilege", SE_IMPERSONATE_PRIVILEGE },
723 { "SeCreateGlobalPrivilege", SE_CREATE_GLOBAL_PRIVILEGE },
725 BOOL (WINAPI *pLookupPrivilegeValueA)(LPCSTR, LPCSTR, PLUID);
726 unsigned int i;
727 LUID luid;
728 BOOL ret;
730 /* check whether it's available first */
731 pLookupPrivilegeValueA = (void*)GetProcAddress(hmod, "LookupPrivilegeValueA");
732 if (!pLookupPrivilegeValueA) return;
733 ret = pLookupPrivilegeValueA(NULL, "SeCreateTokenPrivilege", &luid);
734 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
735 return;
737 /* check a bogus system name */
738 ret = pLookupPrivilegeValueA("b0gu5.Nam3", "SeCreateTokenPrivilege", &luid);
739 ok( !ret && (GetLastError() == RPC_S_SERVER_UNAVAILABLE ||
740 GetLastError() == RPC_S_INVALID_NET_ADDR) /* w2k8 */,
741 "LookupPrivilegeValueA didn't fail with RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR: %d\n",
742 GetLastError());
743 /* check a NULL string */
744 ret = pLookupPrivilegeValueA(NULL, 0, &luid);
745 ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
746 "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n",
747 GetLastError());
748 /* check a bogus privilege name */
749 ret = pLookupPrivilegeValueA(NULL, "SeBogusPrivilege", &luid);
750 ok( !ret && GetLastError() == ERROR_NO_SUCH_PRIVILEGE,
751 "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %d\n",
752 GetLastError());
753 /* check case insensitive */
754 ret = pLookupPrivilegeValueA(NULL, "sEcREATEtOKENpRIVILEGE", &luid);
755 ok( ret,
756 "LookupPrivilegeValueA(NULL, sEcREATEtOKENpRIVILEGE, &luid) failed: %d\n",
757 GetLastError());
758 for (i = 0; i < ARRAY_SIZE(privs); i++)
760 /* Not all privileges are implemented on all Windows versions, so
761 * don't worry if the call fails
763 if (pLookupPrivilegeValueA(NULL, privs[i].name, &luid))
765 ok(luid.LowPart == privs[i].lowPart,
766 "LookupPrivilegeValueA returned an invalid LUID for %s\n",
767 privs[i].name);
772 static void test_FileSecurity(void)
774 char wintmpdir [MAX_PATH];
775 char path [MAX_PATH];
776 char file [MAX_PATH];
777 HANDLE fh, token;
778 DWORD sdSize, retSize, rc, granted, priv_set_len;
779 PRIVILEGE_SET priv_set;
780 BOOL status;
781 BYTE *sd;
782 GENERIC_MAPPING mapping = { FILE_READ_DATA, FILE_WRITE_DATA, FILE_EXECUTE, FILE_ALL_ACCESS };
783 const SECURITY_INFORMATION request = OWNER_SECURITY_INFORMATION
784 | GROUP_SECURITY_INFORMATION
785 | DACL_SECURITY_INFORMATION;
787 if (!pSetFileSecurityA) {
788 win_skip ("SetFileSecurity is not available\n");
789 return;
792 if (!GetTempPathA (sizeof (wintmpdir), wintmpdir)) {
793 win_skip ("GetTempPathA failed\n");
794 return;
797 /* Create a temporary directory and in it a temporary file */
798 strcat (strcpy (path, wintmpdir), "rary");
799 SetLastError(0xdeadbeef);
800 rc = CreateDirectoryA (path, NULL);
801 ok (rc || GetLastError() == ERROR_ALREADY_EXISTS, "CreateDirectoryA "
802 "failed for '%s' with %d\n", path, GetLastError());
804 strcat (strcpy (file, path), "\\ess");
805 SetLastError(0xdeadbeef);
806 fh = CreateFileA (file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
807 ok (fh != INVALID_HANDLE_VALUE, "CreateFileA "
808 "failed for '%s' with %d\n", file, GetLastError());
809 CloseHandle (fh);
811 /* For the temporary file ... */
813 /* Get size needed */
814 retSize = 0;
815 SetLastError(0xdeadbeef);
816 rc = GetFileSecurityA (file, request, NULL, 0, &retSize);
817 if (!rc && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) {
818 win_skip("GetFileSecurityA is not implemented\n");
819 goto cleanup;
821 ok (!rc, "GetFileSecurityA "
822 "was expected to fail for '%s'\n", file);
823 ok (GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetFileSecurityA "
824 "returned %d; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError());
825 ok (retSize > sizeof (SECURITY_DESCRIPTOR), "GetFileSecurityA returned size %d\n", retSize);
827 sdSize = retSize;
828 sd = HeapAlloc (GetProcessHeap (), 0, sdSize);
830 /* Get security descriptor for real */
831 retSize = -1;
832 SetLastError(0xdeadbeef);
833 rc = GetFileSecurityA (file, request, sd, sdSize, &retSize);
834 ok (rc, "GetFileSecurityA "
835 "was not expected to fail '%s': %d\n", file, GetLastError());
836 ok (retSize == sdSize ||
837 broken(retSize == 0), /* NT4 */
838 "GetFileSecurityA returned size %d; expected %d\n", retSize, sdSize);
840 /* Use it to set security descriptor */
841 SetLastError(0xdeadbeef);
842 rc = pSetFileSecurityA (file, request, sd);
843 ok (rc, "SetFileSecurityA "
844 "was not expected to fail '%s': %d\n", file, GetLastError());
846 HeapFree (GetProcessHeap (), 0, sd);
848 /* Repeat for the temporary directory ... */
850 /* Get size needed */
851 retSize = 0;
852 SetLastError(0xdeadbeef);
853 rc = GetFileSecurityA (path, request, NULL, 0, &retSize);
854 ok (!rc, "GetFileSecurityA "
855 "was expected to fail for '%s'\n", path);
856 ok (GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetFileSecurityA "
857 "returned %d; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError());
858 ok (retSize > sizeof (SECURITY_DESCRIPTOR), "GetFileSecurityA returned size %d\n", retSize);
860 sdSize = retSize;
861 sd = HeapAlloc (GetProcessHeap (), 0, sdSize);
863 /* Get security descriptor for real */
864 retSize = -1;
865 SetLastError(0xdeadbeef);
866 rc = GetFileSecurityA (path, request, sd, sdSize, &retSize);
867 ok (rc, "GetFileSecurityA "
868 "was not expected to fail '%s': %d\n", path, GetLastError());
869 ok (retSize == sdSize ||
870 broken(retSize == 0), /* NT4 */
871 "GetFileSecurityA returned size %d; expected %d\n", retSize, sdSize);
873 /* Use it to set security descriptor */
874 SetLastError(0xdeadbeef);
875 rc = pSetFileSecurityA (path, request, sd);
876 ok (rc, "SetFileSecurityA "
877 "was not expected to fail '%s': %d\n", path, GetLastError());
878 HeapFree (GetProcessHeap (), 0, sd);
880 /* Old test */
881 strcpy (wintmpdir, "\\Should not exist");
882 SetLastError(0xdeadbeef);
883 rc = GetFileSecurityA (wintmpdir, OWNER_SECURITY_INFORMATION, NULL, 0, &sdSize);
884 ok (!rc, "GetFileSecurityA should fail for not existing directories/files\n");
885 ok (GetLastError() == ERROR_FILE_NOT_FOUND,
886 "last error ERROR_FILE_NOT_FOUND expected, got %d\n", GetLastError());
888 cleanup:
889 /* Remove temporary file and directory */
890 DeleteFileA(file);
891 RemoveDirectoryA(path);
893 /* Test file access permissions for a file with FILE_ATTRIBUTE_ARCHIVE */
894 SetLastError(0xdeadbeef);
895 rc = GetTempPathA(sizeof(wintmpdir), wintmpdir);
896 ok(rc, "GetTempPath error %d\n", GetLastError());
898 SetLastError(0xdeadbeef);
899 rc = GetTempFileNameA(wintmpdir, "tmp", 0, file);
900 ok(rc, "GetTempFileName error %d\n", GetLastError());
902 rc = GetFileAttributesA(file);
903 rc &= ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|FILE_ATTRIBUTE_COMPRESSED);
904 ok(rc == FILE_ATTRIBUTE_ARCHIVE, "expected FILE_ATTRIBUTE_ARCHIVE got %#x\n", rc);
906 rc = GetFileSecurityA(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
907 NULL, 0, &sdSize);
908 ok(!rc, "GetFileSecurity should fail\n");
909 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
910 "expected ERROR_INSUFFICIENT_BUFFER got %d\n", GetLastError());
911 ok(sdSize > sizeof(SECURITY_DESCRIPTOR), "got sd size %d\n", sdSize);
913 sd = HeapAlloc(GetProcessHeap (), 0, sdSize);
914 retSize = 0xdeadbeef;
915 SetLastError(0xdeadbeef);
916 rc = GetFileSecurityA(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
917 sd, sdSize, &retSize);
918 ok(rc, "GetFileSecurity error %d\n", GetLastError());
919 ok(retSize == sdSize || broken(retSize == 0) /* NT4 */, "expected %d, got %d\n", sdSize, retSize);
921 SetLastError(0xdeadbeef);
922 rc = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &token);
923 ok(!rc, "OpenThreadToken should fail\n");
924 ok(GetLastError() == ERROR_NO_TOKEN, "expected ERROR_NO_TOKEN, got %d\n", GetLastError());
926 SetLastError(0xdeadbeef);
927 rc = ImpersonateSelf(SecurityIdentification);
928 ok(rc, "ImpersonateSelf error %d\n", GetLastError());
930 SetLastError(0xdeadbeef);
931 rc = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &token);
932 ok(rc, "OpenThreadToken error %d\n", GetLastError());
934 SetLastError(0xdeadbeef);
935 rc = RevertToSelf();
936 ok(rc, "RevertToSelf error %d\n", GetLastError());
938 priv_set_len = sizeof(priv_set);
939 granted = 0xdeadbeef;
940 status = 0xdeadbeef;
941 SetLastError(0xdeadbeef);
942 rc = AccessCheck(sd, token, FILE_READ_DATA, &mapping, &priv_set, &priv_set_len, &granted, &status);
943 ok(rc, "AccessCheck error %d\n", GetLastError());
944 ok(status == 1, "expected 1, got %d\n", status);
945 ok(granted == FILE_READ_DATA, "expected FILE_READ_DATA, got %#x\n", granted);
947 granted = 0xdeadbeef;
948 status = 0xdeadbeef;
949 SetLastError(0xdeadbeef);
950 rc = AccessCheck(sd, token, FILE_WRITE_DATA, &mapping, &priv_set, &priv_set_len, &granted, &status);
951 ok(rc, "AccessCheck error %d\n", GetLastError());
952 ok(status == 1, "expected 1, got %d\n", status);
953 ok(granted == FILE_WRITE_DATA, "expected FILE_WRITE_DATA, got %#x\n", granted);
955 granted = 0xdeadbeef;
956 status = 0xdeadbeef;
957 SetLastError(0xdeadbeef);
958 rc = AccessCheck(sd, token, FILE_EXECUTE, &mapping, &priv_set, &priv_set_len, &granted, &status);
959 ok(rc, "AccessCheck error %d\n", GetLastError());
960 ok(status == 1, "expected 1, got %d\n", status);
961 ok(granted == FILE_EXECUTE, "expected FILE_EXECUTE, got %#x\n", granted);
963 granted = 0xdeadbeef;
964 status = 0xdeadbeef;
965 SetLastError(0xdeadbeef);
966 rc = AccessCheck(sd, token, DELETE, &mapping, &priv_set, &priv_set_len, &granted, &status);
967 ok(rc, "AccessCheck error %d\n", GetLastError());
968 ok(status == 1, "expected 1, got %d\n", status);
969 ok(granted == DELETE, "expected DELETE, got %#x\n", granted);
971 granted = 0xdeadbeef;
972 status = 0xdeadbeef;
973 SetLastError(0xdeadbeef);
974 rc = AccessCheck(sd, token, FILE_DELETE_CHILD, &mapping, &priv_set, &priv_set_len, &granted, &status);
975 ok(rc, "AccessCheck error %d\n", GetLastError());
976 ok(status == 1, "expected 1, got %d\n", status);
977 ok(granted == FILE_DELETE_CHILD, "expected FILE_DELETE_CHILD, got %#x\n", granted);
979 granted = 0xdeadbeef;
980 status = 0xdeadbeef;
981 SetLastError(0xdeadbeef);
982 rc = AccessCheck(sd, token, 0x1ff, &mapping, &priv_set, &priv_set_len, &granted, &status);
983 ok(rc, "AccessCheck error %d\n", GetLastError());
984 ok(status == 1, "expected 1, got %d\n", status);
985 ok(granted == 0x1ff, "expected 0x1ff, got %#x\n", granted);
987 granted = 0xdeadbeef;
988 status = 0xdeadbeef;
989 SetLastError(0xdeadbeef);
990 rc = AccessCheck(sd, token, FILE_ALL_ACCESS, &mapping, &priv_set, &priv_set_len, &granted, &status);
991 ok(rc, "AccessCheck error %d\n", GetLastError());
992 ok(status == 1, "expected 1, got %d\n", status);
993 ok(granted == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", granted);
995 SetLastError(0xdeadbeef);
996 rc = AccessCheck(sd, token, 0xffffffff, &mapping, &priv_set, &priv_set_len, &granted, &status);
997 ok(!rc, "AccessCheck should fail\n");
998 ok(GetLastError() == ERROR_GENERIC_NOT_MAPPED, "expected ERROR_GENERIC_NOT_MAPPED, got %d\n", GetLastError());
1000 /* Test file access permissions for a file with FILE_ATTRIBUTE_READONLY */
1001 SetLastError(0xdeadbeef);
1002 fh = CreateFileA(file, FILE_READ_DATA, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
1003 ok(fh != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
1004 retSize = 0xdeadbeef;
1005 SetLastError(0xdeadbeef);
1006 rc = WriteFile(fh, "1", 1, &retSize, NULL);
1007 ok(!rc, "WriteFile should fail\n");
1008 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1009 ok(retSize == 0, "expected 0, got %d\n", retSize);
1010 CloseHandle(fh);
1012 rc = GetFileAttributesA(file);
1013 rc &= ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|FILE_ATTRIBUTE_COMPRESSED);
1014 todo_wine
1015 ok(rc == (FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY),
1016 "expected FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY got %#x\n", rc);
1018 SetLastError(0xdeadbeef);
1019 rc = SetFileAttributesA(file, FILE_ATTRIBUTE_ARCHIVE);
1020 ok(rc, "SetFileAttributes error %d\n", GetLastError());
1021 SetLastError(0xdeadbeef);
1022 rc = DeleteFileA(file);
1023 ok(rc, "DeleteFile error %d\n", GetLastError());
1025 SetLastError(0xdeadbeef);
1026 fh = CreateFileA(file, FILE_READ_DATA, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
1027 ok(fh != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
1028 retSize = 0xdeadbeef;
1029 SetLastError(0xdeadbeef);
1030 rc = WriteFile(fh, "1", 1, &retSize, NULL);
1031 ok(!rc, "WriteFile should fail\n");
1032 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1033 ok(retSize == 0, "expected 0, got %d\n", retSize);
1034 CloseHandle(fh);
1036 rc = GetFileAttributesA(file);
1037 rc &= ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|FILE_ATTRIBUTE_COMPRESSED);
1038 ok(rc == (FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY),
1039 "expected FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY got %#x\n", rc);
1041 retSize = 0xdeadbeef;
1042 SetLastError(0xdeadbeef);
1043 rc = GetFileSecurityA(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
1044 sd, sdSize, &retSize);
1045 ok(rc, "GetFileSecurity error %d\n", GetLastError());
1046 ok(retSize == sdSize || broken(retSize == 0) /* NT4 */, "expected %d, got %d\n", sdSize, retSize);
1048 priv_set_len = sizeof(priv_set);
1049 granted = 0xdeadbeef;
1050 status = 0xdeadbeef;
1051 SetLastError(0xdeadbeef);
1052 rc = AccessCheck(sd, token, FILE_READ_DATA, &mapping, &priv_set, &priv_set_len, &granted, &status);
1053 ok(rc, "AccessCheck error %d\n", GetLastError());
1054 ok(status == 1, "expected 1, got %d\n", status);
1055 ok(granted == FILE_READ_DATA, "expected FILE_READ_DATA, got %#x\n", granted);
1057 granted = 0xdeadbeef;
1058 status = 0xdeadbeef;
1059 SetLastError(0xdeadbeef);
1060 rc = AccessCheck(sd, token, FILE_WRITE_DATA, &mapping, &priv_set, &priv_set_len, &granted, &status);
1061 ok(rc, "AccessCheck error %d\n", GetLastError());
1062 todo_wine {
1063 ok(status == 1, "expected 1, got %d\n", status);
1064 ok(granted == FILE_WRITE_DATA, "expected FILE_WRITE_DATA, got %#x\n", granted);
1066 granted = 0xdeadbeef;
1067 status = 0xdeadbeef;
1068 SetLastError(0xdeadbeef);
1069 rc = AccessCheck(sd, token, FILE_EXECUTE, &mapping, &priv_set, &priv_set_len, &granted, &status);
1070 ok(rc, "AccessCheck error %d\n", GetLastError());
1071 ok(status == 1, "expected 1, got %d\n", status);
1072 ok(granted == FILE_EXECUTE, "expected FILE_EXECUTE, got %#x\n", granted);
1074 granted = 0xdeadbeef;
1075 status = 0xdeadbeef;
1076 SetLastError(0xdeadbeef);
1077 rc = AccessCheck(sd, token, DELETE, &mapping, &priv_set, &priv_set_len, &granted, &status);
1078 ok(rc, "AccessCheck error %d\n", GetLastError());
1079 todo_wine {
1080 ok(status == 1, "expected 1, got %d\n", status);
1081 ok(granted == DELETE, "expected DELETE, got %#x\n", granted);
1083 granted = 0xdeadbeef;
1084 status = 0xdeadbeef;
1085 SetLastError(0xdeadbeef);
1086 rc = AccessCheck(sd, token, FILE_DELETE_CHILD, &mapping, &priv_set, &priv_set_len, &granted, &status);
1087 ok(rc, "AccessCheck error %d\n", GetLastError());
1088 todo_wine {
1089 ok(status == 1, "expected 1, got %d\n", status);
1090 ok(granted == FILE_DELETE_CHILD, "expected FILE_DELETE_CHILD, got %#x\n", granted);
1092 granted = 0xdeadbeef;
1093 status = 0xdeadbeef;
1094 SetLastError(0xdeadbeef);
1095 rc = AccessCheck(sd, token, 0x1ff, &mapping, &priv_set, &priv_set_len, &granted, &status);
1096 ok(rc, "AccessCheck error %d\n", GetLastError());
1097 todo_wine {
1098 ok(status == 1, "expected 1, got %d\n", status);
1099 ok(granted == 0x1ff, "expected 0x1ff, got %#x\n", granted);
1101 granted = 0xdeadbeef;
1102 status = 0xdeadbeef;
1103 SetLastError(0xdeadbeef);
1104 rc = AccessCheck(sd, token, FILE_ALL_ACCESS, &mapping, &priv_set, &priv_set_len, &granted, &status);
1105 ok(rc, "AccessCheck error %d\n", GetLastError());
1106 todo_wine {
1107 ok(status == 1, "expected 1, got %d\n", status);
1108 ok(granted == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", granted);
1110 SetLastError(0xdeadbeef);
1111 rc = DeleteFileA(file);
1112 ok(!rc, "DeleteFile should fail\n");
1113 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1114 SetLastError(0xdeadbeef);
1115 rc = SetFileAttributesA(file, FILE_ATTRIBUTE_ARCHIVE);
1116 ok(rc, "SetFileAttributes error %d\n", GetLastError());
1117 SetLastError(0xdeadbeef);
1118 rc = DeleteFileA(file);
1119 ok(rc, "DeleteFile error %d\n", GetLastError());
1121 CloseHandle(token);
1122 HeapFree(GetProcessHeap(), 0, sd);
1125 static void test_AccessCheck(void)
1127 PSID EveryoneSid = NULL, AdminSid = NULL, UsersSid = NULL;
1128 PACL Acl = NULL;
1129 SECURITY_DESCRIPTOR *SecurityDescriptor = NULL;
1130 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
1131 SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
1132 GENERIC_MAPPING Mapping = { KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS };
1133 ACCESS_MASK Access;
1134 BOOL AccessStatus;
1135 HANDLE Token;
1136 HANDLE ProcessToken;
1137 BOOL ret;
1138 DWORD PrivSetLen;
1139 PRIVILEGE_SET *PrivSet;
1140 BOOL res;
1141 HMODULE NtDllModule;
1142 BOOLEAN Enabled;
1143 DWORD err;
1144 NTSTATUS ntret, ntAccessStatus;
1146 NtDllModule = GetModuleHandleA("ntdll.dll");
1147 if (!NtDllModule)
1149 skip("not running on NT, skipping test\n");
1150 return;
1152 pRtlAdjustPrivilege = (void *)GetProcAddress(NtDllModule, "RtlAdjustPrivilege");
1153 if (!pRtlAdjustPrivilege)
1155 win_skip("missing RtlAdjustPrivilege, skipping test\n");
1156 return;
1159 Acl = HeapAlloc(GetProcessHeap(), 0, 256);
1160 res = InitializeAcl(Acl, 256, ACL_REVISION);
1161 if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1163 skip("ACLs not implemented - skipping tests\n");
1164 HeapFree(GetProcessHeap(), 0, Acl);
1165 return;
1167 ok(res, "InitializeAcl failed with error %d\n", GetLastError());
1169 res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
1170 ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
1172 res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
1173 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminSid);
1174 ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
1176 res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
1177 DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid);
1178 ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
1180 SecurityDescriptor = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
1182 res = InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
1183 ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
1185 res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
1186 ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
1188 PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
1189 PrivSet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, PrivSetLen);
1190 PrivSet->PrivilegeCount = 16;
1192 res = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &ProcessToken);
1193 ok(res, "OpenProcessToken failed with error %d\n", GetLastError());
1195 pRtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, FALSE, TRUE, &Enabled);
1197 res = DuplicateToken(ProcessToken, SecurityImpersonation, &Token);
1198 ok(res, "DuplicateToken failed with error %d\n", GetLastError());
1200 /* SD without owner/group */
1201 SetLastError(0xdeadbeef);
1202 Access = AccessStatus = 0x1abe11ed;
1203 ret = AccessCheck(SecurityDescriptor, Token, KEY_QUERY_VALUE, &Mapping,
1204 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1205 err = GetLastError();
1206 ok(!ret && err == ERROR_INVALID_SECURITY_DESCR, "AccessCheck should have "
1207 "failed with ERROR_INVALID_SECURITY_DESCR, instead of %d\n", err);
1208 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1209 "Access and/or AccessStatus were changed!\n");
1211 /* Set owner and group */
1212 res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE);
1213 ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
1214 res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, TRUE);
1215 ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
1217 /* Generic access mask */
1218 SetLastError(0xdeadbeef);
1219 Access = AccessStatus = 0x1abe11ed;
1220 ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1221 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1222 err = GetLastError();
1223 ok(!ret && err == ERROR_GENERIC_NOT_MAPPED, "AccessCheck should have failed "
1224 "with ERROR_GENERIC_NOT_MAPPED, instead of %d\n", err);
1225 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1226 "Access and/or AccessStatus were changed!\n");
1228 /* Generic access mask - no privilegeset buffer */
1229 SetLastError(0xdeadbeef);
1230 Access = AccessStatus = 0x1abe11ed;
1231 ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1232 NULL, &PrivSetLen, &Access, &AccessStatus);
1233 err = GetLastError();
1234 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have failed "
1235 "with ERROR_NOACCESS, instead of %d\n", err);
1236 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1237 "Access and/or AccessStatus were changed!\n");
1239 /* Generic access mask - no returnlength */
1240 SetLastError(0xdeadbeef);
1241 Access = AccessStatus = 0x1abe11ed;
1242 ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1243 PrivSet, NULL, &Access, &AccessStatus);
1244 err = GetLastError();
1245 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have failed "
1246 "with ERROR_NOACCESS, instead of %d\n", err);
1247 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1248 "Access and/or AccessStatus were changed!\n");
1250 /* Generic access mask - no privilegeset buffer, no returnlength */
1251 SetLastError(0xdeadbeef);
1252 Access = AccessStatus = 0x1abe11ed;
1253 ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1254 NULL, NULL, &Access, &AccessStatus);
1255 err = GetLastError();
1256 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have failed "
1257 "with ERROR_NOACCESS, instead of %d\n", err);
1258 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1259 "Access and/or AccessStatus were changed!\n");
1261 /* sd with no dacl present */
1262 Access = AccessStatus = 0x1abe11ed;
1263 ret = SetSecurityDescriptorDacl(SecurityDescriptor, FALSE, NULL, FALSE);
1264 ok(ret, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
1265 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1266 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1267 ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1268 ok(AccessStatus && (Access == KEY_READ),
1269 "AccessCheck failed to grant access with error %d\n",
1270 GetLastError());
1272 /* sd with no dacl present - no privilegeset buffer */
1273 SetLastError(0xdeadbeef);
1274 Access = AccessStatus = 0x1abe11ed;
1275 ret = AccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1276 NULL, &PrivSetLen, &Access, &AccessStatus);
1277 err = GetLastError();
1278 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have failed "
1279 "with ERROR_NOACCESS, instead of %d\n", err);
1280 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1281 "Access and/or AccessStatus were changed!\n");
1283 if(pNtAccessCheck)
1285 DWORD ntPrivSetLen = sizeof(PRIVILEGE_SET);
1287 /* Generic access mask - no privilegeset buffer */
1288 SetLastError(0xdeadbeef);
1289 Access = ntAccessStatus = 0x1abe11ed;
1290 ntret = pNtAccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1291 NULL, &ntPrivSetLen, &Access, &ntAccessStatus);
1292 err = GetLastError();
1293 ok(ntret == STATUS_ACCESS_VIOLATION,
1294 "NtAccessCheck should have failed with STATUS_ACCESS_VIOLATION, got %x\n", ntret);
1295 ok(err == 0xdeadbeef,
1296 "NtAccessCheck shouldn't set last error, got %d\n", err);
1297 ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed,
1298 "Access and/or AccessStatus were changed!\n");
1299 ok(ntPrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", ntPrivSetLen);
1301 /* Generic access mask - no returnlength */
1302 SetLastError(0xdeadbeef);
1303 Access = ntAccessStatus = 0x1abe11ed;
1304 ntret = pNtAccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1305 PrivSet, NULL, &Access, &ntAccessStatus);
1306 err = GetLastError();
1307 ok(ntret == STATUS_ACCESS_VIOLATION,
1308 "NtAccessCheck should have failed with STATUS_ACCESS_VIOLATION, got %x\n", ntret);
1309 ok(err == 0xdeadbeef,
1310 "NtAccessCheck shouldn't set last error, got %d\n", err);
1311 ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed,
1312 "Access and/or AccessStatus were changed!\n");
1314 /* Generic access mask - no privilegeset buffer, no returnlength */
1315 SetLastError(0xdeadbeef);
1316 Access = ntAccessStatus = 0x1abe11ed;
1317 ntret = pNtAccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1318 NULL, NULL, &Access, &ntAccessStatus);
1319 err = GetLastError();
1320 ok(ntret == STATUS_ACCESS_VIOLATION,
1321 "NtAccessCheck should have failed with STATUS_ACCESS_VIOLATION, got %x\n", ntret);
1322 ok(err == 0xdeadbeef,
1323 "NtAccessCheck shouldn't set last error, got %d\n", err);
1324 ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed,
1325 "Access and/or AccessStatus were changed!\n");
1327 /* Generic access mask - zero returnlength */
1328 SetLastError(0xdeadbeef);
1329 Access = ntAccessStatus = 0x1abe11ed;
1330 ntPrivSetLen = 0;
1331 ntret = pNtAccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1332 PrivSet, &ntPrivSetLen, &Access, &ntAccessStatus);
1333 err = GetLastError();
1334 ok(ntret == STATUS_GENERIC_NOT_MAPPED,
1335 "NtAccessCheck should have failed with STATUS_GENERIC_NOT_MAPPED, got %x\n", ntret);
1336 ok(err == 0xdeadbeef,
1337 "NtAccessCheck shouldn't set last error, got %d\n", err);
1338 ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed,
1339 "Access and/or AccessStatus were changed!\n");
1340 ok(ntPrivSetLen == 0, "PrivSetLen returns %d\n", ntPrivSetLen);
1342 /* Generic access mask - insufficient returnlength */
1343 SetLastError(0xdeadbeef);
1344 Access = ntAccessStatus = 0x1abe11ed;
1345 ntPrivSetLen = sizeof(PRIVILEGE_SET)-1;
1346 ntret = pNtAccessCheck(SecurityDescriptor, Token, GENERIC_READ, &Mapping,
1347 PrivSet, &ntPrivSetLen, &Access, &ntAccessStatus);
1348 err = GetLastError();
1349 ok(ntret == STATUS_GENERIC_NOT_MAPPED,
1350 "NtAccessCheck should have failed with STATUS_GENERIC_NOT_MAPPED, got %x\n", ntret);
1351 ok(err == 0xdeadbeef,
1352 "NtAccessCheck shouldn't set last error, got %d\n", err);
1353 ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed,
1354 "Access and/or AccessStatus were changed!\n");
1355 ok(ntPrivSetLen == sizeof(PRIVILEGE_SET)-1, "PrivSetLen returns %d\n", ntPrivSetLen);
1357 /* Key access mask - zero returnlength */
1358 SetLastError(0xdeadbeef);
1359 Access = ntAccessStatus = 0x1abe11ed;
1360 ntPrivSetLen = 0;
1361 ntret = pNtAccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1362 PrivSet, &ntPrivSetLen, &Access, &ntAccessStatus);
1363 err = GetLastError();
1364 ok(ntret == STATUS_BUFFER_TOO_SMALL,
1365 "NtAccessCheck should have failed with STATUS_BUFFER_TOO_SMALL, got %x\n", ntret);
1366 ok(err == 0xdeadbeef,
1367 "NtAccessCheck shouldn't set last error, got %d\n", err);
1368 ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed,
1369 "Access and/or AccessStatus were changed!\n");
1370 ok(ntPrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", ntPrivSetLen);
1372 /* Key access mask - insufficient returnlength */
1373 SetLastError(0xdeadbeef);
1374 Access = ntAccessStatus = 0x1abe11ed;
1375 ntPrivSetLen = sizeof(PRIVILEGE_SET)-1;
1376 ntret = pNtAccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1377 PrivSet, &ntPrivSetLen, &Access, &ntAccessStatus);
1378 err = GetLastError();
1379 ok(ntret == STATUS_BUFFER_TOO_SMALL,
1380 "NtAccessCheck should have failed with STATUS_BUFFER_TOO_SMALL, got %x\n", ntret);
1381 ok(err == 0xdeadbeef,
1382 "NtAccessCheck shouldn't set last error, got %d\n", err);
1383 ok(Access == 0x1abe11ed && ntAccessStatus == 0x1abe11ed,
1384 "Access and/or AccessStatus were changed!\n");
1385 ok(ntPrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", ntPrivSetLen);
1387 else
1388 win_skip("NtAccessCheck unavailable. Skipping.\n");
1390 /* sd with NULL dacl */
1391 Access = AccessStatus = 0x1abe11ed;
1392 ret = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, NULL, FALSE);
1393 ok(ret, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
1394 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1395 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1396 ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1397 ok(AccessStatus && (Access == KEY_READ),
1398 "AccessCheck failed to grant access with error %d\n",
1399 GetLastError());
1400 ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping,
1401 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1402 ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1403 ok(AccessStatus && (Access == KEY_ALL_ACCESS),
1404 "AccessCheck failed to grant access with error %d\n",
1405 GetLastError());
1407 /* sd with blank dacl */
1408 ret = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
1409 ok(ret, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
1410 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1411 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1412 ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1413 err = GetLastError();
1414 ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed "
1415 "with ERROR_ACCESS_DENIED, instead of %d\n", err);
1416 ok(!Access, "Should have failed to grant any access, got 0x%08x\n", Access);
1418 res = AddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, EveryoneSid);
1419 ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
1421 res = AddAccessDeniedAce(Acl, ACL_REVISION, KEY_SET_VALUE, AdminSid);
1422 ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError());
1424 /* sd with dacl */
1425 Access = AccessStatus = 0x1abe11ed;
1426 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1427 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1428 ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1429 ok(AccessStatus && (Access == KEY_READ),
1430 "AccessCheck failed to grant access with error %d\n",
1431 GetLastError());
1433 ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping,
1434 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1435 ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1436 ok(AccessStatus,
1437 "AccessCheck failed to grant any access with error %d\n",
1438 GetLastError());
1439 trace("AccessCheck with MAXIMUM_ALLOWED got Access 0x%08x\n", Access);
1441 /* Null PrivSet with null PrivSetLen pointer */
1442 SetLastError(0xdeadbeef);
1443 Access = AccessStatus = 0x1abe11ed;
1444 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1445 NULL, NULL, &Access, &AccessStatus);
1446 err = GetLastError();
1447 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have "
1448 "failed with ERROR_NOACCESS, instead of %d\n", err);
1449 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1450 "Access and/or AccessStatus were changed!\n");
1452 /* Null PrivSet with zero PrivSetLen */
1453 SetLastError(0xdeadbeef);
1454 Access = AccessStatus = 0x1abe11ed;
1455 PrivSetLen = 0;
1456 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1457 0, &PrivSetLen, &Access, &AccessStatus);
1458 err = GetLastError();
1459 todo_wine
1460 ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1461 "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err);
1462 todo_wine
1463 ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen);
1464 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1465 "Access and/or AccessStatus were changed!\n");
1467 /* Null PrivSet with insufficient PrivSetLen */
1468 SetLastError(0xdeadbeef);
1469 Access = AccessStatus = 0x1abe11ed;
1470 PrivSetLen = 1;
1471 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1472 0, &PrivSetLen, &Access, &AccessStatus);
1473 err = GetLastError();
1474 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have "
1475 "failed with ERROR_NOACCESS, instead of %d\n", err);
1476 ok(PrivSetLen == 1, "PrivSetLen returns %d\n", PrivSetLen);
1477 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1478 "Access and/or AccessStatus were changed!\n");
1480 /* Null PrivSet with insufficient PrivSetLen */
1481 SetLastError(0xdeadbeef);
1482 Access = AccessStatus = 0x1abe11ed;
1483 PrivSetLen = sizeof(PRIVILEGE_SET) - 1;
1484 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1485 0, &PrivSetLen, &Access, &AccessStatus);
1486 err = GetLastError();
1487 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have "
1488 "failed with ERROR_NOACCESS, instead of %d\n", err);
1489 ok(PrivSetLen == sizeof(PRIVILEGE_SET) - 1, "PrivSetLen returns %d\n", PrivSetLen);
1490 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1491 "Access and/or AccessStatus were changed!\n");
1493 /* Null PrivSet with minimal sufficient PrivSetLen */
1494 SetLastError(0xdeadbeef);
1495 Access = AccessStatus = 0x1abe11ed;
1496 PrivSetLen = sizeof(PRIVILEGE_SET);
1497 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1498 0, &PrivSetLen, &Access, &AccessStatus);
1499 err = GetLastError();
1500 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have "
1501 "failed with ERROR_NOACCESS, instead of %d\n", err);
1502 ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen);
1503 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1504 "Access and/or AccessStatus were changed!\n");
1506 /* Valid PrivSet with zero PrivSetLen */
1507 SetLastError(0xdeadbeef);
1508 Access = AccessStatus = 0x1abe11ed;
1509 PrivSetLen = 0;
1510 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1511 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1512 err = GetLastError();
1513 ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1514 "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err);
1515 ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen);
1516 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1517 "Access and/or AccessStatus were changed!\n");
1519 /* Valid PrivSet with insufficient PrivSetLen */
1520 SetLastError(0xdeadbeef);
1521 Access = AccessStatus = 0x1abe11ed;
1522 PrivSetLen = 1;
1523 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1524 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1525 err = GetLastError();
1526 ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1527 "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err);
1528 ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen);
1529 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1530 "Access and/or AccessStatus were changed!\n");
1532 /* Valid PrivSet with insufficient PrivSetLen */
1533 SetLastError(0xdeadbeef);
1534 Access = AccessStatus = 0x1abe11ed;
1535 PrivSetLen = sizeof(PRIVILEGE_SET) - 1;
1536 PrivSet->PrivilegeCount = 0xdeadbeef;
1537 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1538 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1539 err = GetLastError();
1540 ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1541 "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err);
1542 ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen);
1543 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1544 "Access and/or AccessStatus were changed!\n");
1545 ok(PrivSet->PrivilegeCount == 0xdeadbeef, "buffer contents should not be changed\n");
1547 /* Valid PrivSet with minimal sufficient PrivSetLen */
1548 SetLastError(0xdeadbeef);
1549 Access = AccessStatus = 0x1abe11ed;
1550 PrivSetLen = sizeof(PRIVILEGE_SET);
1551 memset(PrivSet, 0xcc, PrivSetLen);
1552 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1553 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1554 err = GetLastError();
1555 ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1556 ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen);
1557 ok(AccessStatus && (Access == KEY_READ),
1558 "AccessCheck failed to grant access with error %d\n", GetLastError());
1559 ok(PrivSet->PrivilegeCount == 0, "PrivilegeCount returns %d, expects 0\n",
1560 PrivSet->PrivilegeCount);
1562 /* Valid PrivSet with sufficient PrivSetLen */
1563 SetLastError(0xdeadbeef);
1564 Access = AccessStatus = 0x1abe11ed;
1565 PrivSetLen = sizeof(PRIVILEGE_SET) + 1;
1566 memset(PrivSet, 0xcc, PrivSetLen);
1567 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1568 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1569 err = GetLastError();
1570 ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1571 todo_wine
1572 ok(PrivSetLen == sizeof(PRIVILEGE_SET) + 1, "PrivSetLen returns %d\n", PrivSetLen);
1573 ok(AccessStatus && (Access == KEY_READ),
1574 "AccessCheck failed to grant access with error %d\n", GetLastError());
1575 ok(PrivSet->PrivilegeCount == 0, "PrivilegeCount returns %d, expects 0\n",
1576 PrivSet->PrivilegeCount);
1578 PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
1580 /* Null PrivSet with valid PrivSetLen */
1581 SetLastError(0xdeadbeef);
1582 Access = AccessStatus = 0x1abe11ed;
1583 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1584 0, &PrivSetLen, &Access, &AccessStatus);
1585 err = GetLastError();
1586 ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have "
1587 "failed with ERROR_NOACCESS, instead of %d\n", err);
1588 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1589 "Access and/or AccessStatus were changed!\n");
1591 /* Access denied by SD */
1592 SetLastError(0xdeadbeef);
1593 Access = AccessStatus = 0x1abe11ed;
1594 ret = AccessCheck(SecurityDescriptor, Token, KEY_WRITE, &Mapping,
1595 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1596 ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1597 err = GetLastError();
1598 ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed "
1599 "with ERROR_ACCESS_DENIED, instead of %d\n", err);
1600 ok(!Access, "Should have failed to grant any access, got 0x%08x\n", Access);
1602 SetLastError(0xdeadbeef);
1603 PrivSet->PrivilegeCount = 16;
1604 ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping,
1605 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1606 ok(ret && !AccessStatus && GetLastError() == ERROR_PRIVILEGE_NOT_HELD,
1607 "AccessCheck should have failed with ERROR_PRIVILEGE_NOT_HELD, instead of %d\n",
1608 GetLastError());
1610 ret = ImpersonateLoggedOnUser(Token);
1611 ok(ret, "ImpersonateLoggedOnUser failed with error %d\n", GetLastError());
1612 ret = pRtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, TRUE, TRUE, &Enabled);
1613 if (!ret)
1615 /* Valid PrivSet with zero PrivSetLen */
1616 SetLastError(0xdeadbeef);
1617 Access = AccessStatus = 0x1abe11ed;
1618 PrivSetLen = 0;
1619 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1620 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1621 err = GetLastError();
1622 ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1623 "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err);
1624 ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen);
1625 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1626 "Access and/or AccessStatus were changed!\n");
1628 /* Valid PrivSet with insufficient PrivSetLen */
1629 SetLastError(0xdeadbeef);
1630 Access = AccessStatus = 0x1abe11ed;
1631 PrivSetLen = sizeof(PRIVILEGE_SET) - 1;
1632 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1633 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1634 err = GetLastError();
1635 ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have "
1636 "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err);
1637 ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen);
1638 ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed,
1639 "Access and/or AccessStatus were changed!\n");
1641 /* Valid PrivSet with minimal sufficient PrivSetLen */
1642 SetLastError(0xdeadbeef);
1643 Access = AccessStatus = 0x1abe11ed;
1644 PrivSetLen = sizeof(PRIVILEGE_SET);
1645 memset(PrivSet, 0xcc, PrivSetLen);
1646 ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping,
1647 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1648 ok(ret && AccessStatus && GetLastError() == 0xdeadbeef,
1649 "AccessCheck should have succeeded, error %d\n",
1650 GetLastError());
1651 ok(Access == ACCESS_SYSTEM_SECURITY,
1652 "Access should be equal to ACCESS_SYSTEM_SECURITY instead of 0x%08x\n",
1653 Access);
1654 ok(PrivSet->PrivilegeCount == 1, "PrivilegeCount returns %d, expects 1\n",
1655 PrivSet->PrivilegeCount);
1657 /* Valid PrivSet with large PrivSetLen */
1658 SetLastError(0xdeadbeef);
1659 Access = AccessStatus = 0x1abe11ed;
1660 PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]);
1661 memset(PrivSet, 0xcc, PrivSetLen);
1662 ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping,
1663 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1664 ok(ret && AccessStatus && GetLastError() == 0xdeadbeef,
1665 "AccessCheck should have succeeded, error %d\n",
1666 GetLastError());
1667 ok(Access == ACCESS_SYSTEM_SECURITY,
1668 "Access should be equal to ACCESS_SYSTEM_SECURITY instead of 0x%08x\n",
1669 Access);
1670 ok(PrivSet->PrivilegeCount == 1, "PrivilegeCount returns %d, expects 1\n",
1671 PrivSet->PrivilegeCount);
1673 else
1674 trace("Couldn't get SE_SECURITY_PRIVILEGE (0x%08x), skipping ACCESS_SYSTEM_SECURITY test\n",
1675 ret);
1676 ret = RevertToSelf();
1677 ok(ret, "RevertToSelf failed with error %d\n", GetLastError());
1679 /* test INHERIT_ONLY_ACE */
1680 ret = InitializeAcl(Acl, 256, ACL_REVISION);
1681 ok(ret, "InitializeAcl failed with error %d\n", GetLastError());
1683 /* NT doesn't have AddAccessAllowedAceEx. Skipping this call/test doesn't influence
1684 * the next ones.
1686 if (pAddAccessAllowedAceEx)
1688 ret = pAddAccessAllowedAceEx(Acl, ACL_REVISION, INHERIT_ONLY_ACE, KEY_READ, EveryoneSid);
1689 ok(ret, "AddAccessAllowedAceEx failed with error %d\n", GetLastError());
1691 else
1692 win_skip("AddAccessAllowedAceEx is not available\n");
1694 ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping,
1695 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1696 ok(ret, "AccessCheck failed with error %d\n", GetLastError());
1697 err = GetLastError();
1698 ok(!AccessStatus && err == ERROR_ACCESS_DENIED, "AccessCheck should have failed "
1699 "with ERROR_ACCESS_DENIED, instead of %d\n", err);
1700 ok(!Access, "Should have failed to grant any access, got 0x%08x\n", Access);
1702 CloseHandle(Token);
1704 res = DuplicateToken(ProcessToken, SecurityAnonymous, &Token);
1705 ok(res, "DuplicateToken failed with error %d\n", GetLastError());
1707 SetLastError(0xdeadbeef);
1708 ret = AccessCheck(SecurityDescriptor, Token, MAXIMUM_ALLOWED, &Mapping,
1709 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1710 err = GetLastError();
1711 ok(!ret && err == ERROR_BAD_IMPERSONATION_LEVEL, "AccessCheck should have failed "
1712 "with ERROR_BAD_IMPERSONATION_LEVEL, instead of %d\n", err);
1714 CloseHandle(Token);
1716 SetLastError(0xdeadbeef);
1717 ret = AccessCheck(SecurityDescriptor, ProcessToken, KEY_READ, &Mapping,
1718 PrivSet, &PrivSetLen, &Access, &AccessStatus);
1719 err = GetLastError();
1720 ok(!ret && err == ERROR_NO_IMPERSONATION_TOKEN, "AccessCheck should have failed "
1721 "with ERROR_NO_IMPERSONATION_TOKEN, instead of %d\n", err);
1723 CloseHandle(ProcessToken);
1725 if (EveryoneSid)
1726 FreeSid(EveryoneSid);
1727 if (AdminSid)
1728 FreeSid(AdminSid);
1729 if (UsersSid)
1730 FreeSid(UsersSid);
1731 HeapFree(GetProcessHeap(), 0, Acl);
1732 HeapFree(GetProcessHeap(), 0, SecurityDescriptor);
1733 HeapFree(GetProcessHeap(), 0, PrivSet);
1736 /* test GetTokenInformation for the various attributes */
1737 static void test_token_attr(void)
1739 HANDLE Token, ImpersonationToken;
1740 DWORD Size, Size2;
1741 TOKEN_PRIVILEGES *Privileges;
1742 TOKEN_GROUPS *Groups;
1743 TOKEN_USER *User;
1744 TOKEN_DEFAULT_DACL *Dacl;
1745 BOOL ret;
1746 DWORD i, GLE;
1747 LPSTR SidString;
1748 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
1749 ACL *acl;
1751 /* cygwin-like use case */
1752 SetLastError(0xdeadbeef);
1753 ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &Token);
1754 if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
1756 win_skip("OpenProcessToken is not implemented\n");
1757 return;
1759 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1760 if (ret)
1762 DWORD buf[256]; /* GetTokenInformation wants a dword-aligned buffer */
1763 Size = sizeof(buf);
1764 ret = GetTokenInformation(Token, TokenUser,(void*)buf, Size, &Size);
1765 ok(ret, "GetTokenInformation failed with error %d\n", GetLastError());
1766 Size = sizeof(ImpersonationLevel);
1767 ret = GetTokenInformation(Token, TokenImpersonationLevel, &ImpersonationLevel, Size, &Size);
1768 GLE = GetLastError();
1769 ok(!ret && (GLE == ERROR_INVALID_PARAMETER), "GetTokenInformation(TokenImpersonationLevel) on primary token should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GLE);
1770 CloseHandle(Token);
1773 SetLastError(0xdeadbeef);
1774 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &Token);
1775 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
1777 /* groups */
1778 /* insufficient buffer length */
1779 SetLastError(0xdeadbeef);
1780 Size2 = 0;
1781 ret = GetTokenInformation(Token, TokenGroups, NULL, 0, &Size2);
1782 ok(Size2 > 1, "got %d\n", Size2);
1783 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1784 "%d with error %d\n", ret, GetLastError());
1785 Size2 -= 1;
1786 Groups = HeapAlloc(GetProcessHeap(), 0, Size2);
1787 memset(Groups, 0xcc, Size2);
1788 Size = 0;
1789 ret = GetTokenInformation(Token, TokenGroups, Groups, Size2, &Size);
1790 ok(Size > 1, "got %d\n", Size);
1791 ok((!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) || broken(ret) /* wow64 */,
1792 "%d with error %d\n", ret, GetLastError());
1793 if(!ret)
1794 ok(*((BYTE*)Groups) == 0xcc, "buffer altered\n");
1796 HeapFree(GetProcessHeap(), 0, Groups);
1798 SetLastError(0xdeadbeef);
1799 ret = GetTokenInformation(Token, TokenGroups, NULL, 0, &Size);
1800 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1801 "GetTokenInformation(TokenGroups) %s with error %d\n",
1802 ret ? "succeeded" : "failed", GetLastError());
1803 Groups = HeapAlloc(GetProcessHeap(), 0, Size);
1804 SetLastError(0xdeadbeef);
1805 ret = GetTokenInformation(Token, TokenGroups, Groups, Size, &Size);
1806 ok(ret, "GetTokenInformation(TokenGroups) failed with error %d\n", GetLastError());
1807 ok(GetLastError() == 0xdeadbeef,
1808 "GetTokenInformation shouldn't have set last error to %d\n",
1809 GetLastError());
1810 trace("TokenGroups:\n");
1811 for (i = 0; i < Groups->GroupCount; i++)
1813 DWORD NameLength = 255;
1814 CHAR Name[255];
1815 DWORD DomainLength = 255;
1816 CHAR Domain[255];
1817 SID_NAME_USE SidNameUse;
1818 Name[0] = '\0';
1819 Domain[0] = '\0';
1820 ret = LookupAccountSidA(NULL, Groups->Groups[i].Sid, Name, &NameLength, Domain, &DomainLength, &SidNameUse);
1821 if (ret)
1823 ConvertSidToStringSidA(Groups->Groups[i].Sid, &SidString);
1824 trace("%s, %s\\%s use: %d attr: 0x%08x\n", SidString, Domain, Name, SidNameUse, Groups->Groups[i].Attributes);
1825 LocalFree(SidString);
1827 else trace("attr: 0x%08x LookupAccountSid failed with error %d\n", Groups->Groups[i].Attributes, GetLastError());
1829 HeapFree(GetProcessHeap(), 0, Groups);
1831 /* user */
1832 ret = GetTokenInformation(Token, TokenUser, NULL, 0, &Size);
1833 ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1834 "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
1835 User = HeapAlloc(GetProcessHeap(), 0, Size);
1836 ret = GetTokenInformation(Token, TokenUser, User, Size, &Size);
1837 ok(ret,
1838 "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
1840 ConvertSidToStringSidA(User->User.Sid, &SidString);
1841 trace("TokenUser: %s attr: 0x%08x\n", SidString, User->User.Attributes);
1842 LocalFree(SidString);
1843 HeapFree(GetProcessHeap(), 0, User);
1845 /* logon */
1846 ret = GetTokenInformation(Token, TokenLogonSid, NULL, 0, &Size);
1847 if (!ret && (GetLastError() == ERROR_INVALID_PARAMETER))
1848 todo_wine win_skip("TokenLogonSid not supported. Skipping tests\n");
1849 else
1851 ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1852 "GetTokenInformation(TokenLogonSid) failed with error %d\n", GetLastError());
1853 Groups = HeapAlloc(GetProcessHeap(), 0, Size);
1854 ret = GetTokenInformation(Token, TokenLogonSid, Groups, Size, &Size);
1855 ok(ret,
1856 "GetTokenInformation(TokenLogonSid) failed with error %d\n", GetLastError());
1857 if (ret)
1859 ok(Groups->GroupCount == 1, "got %d\n", Groups->GroupCount);
1860 if(Groups->GroupCount == 1)
1862 ConvertSidToStringSidA(Groups->Groups[0].Sid, &SidString);
1863 trace("TokenLogon: %s\n", SidString);
1864 LocalFree(SidString);
1866 /* S-1-5-5-0-XXXXXX */
1867 ret = IsWellKnownSid(Groups->Groups[0].Sid, WinLogonIdsSid);
1868 ok(ret, "Unknown SID\n");
1872 HeapFree(GetProcessHeap(), 0, Groups);
1875 /* privileges */
1876 ret = GetTokenInformation(Token, TokenPrivileges, NULL, 0, &Size);
1877 ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1878 "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError());
1879 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
1880 ret = GetTokenInformation(Token, TokenPrivileges, Privileges, Size, &Size);
1881 ok(ret,
1882 "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError());
1883 trace("TokenPrivileges:\n");
1884 for (i = 0; i < Privileges->PrivilegeCount; i++)
1886 CHAR Name[256];
1887 DWORD NameLen = ARRAY_SIZE(Name);
1888 LookupPrivilegeNameA(NULL, &Privileges->Privileges[i].Luid, Name, &NameLen);
1889 trace("\t%s, 0x%x\n", Name, Privileges->Privileges[i].Attributes);
1891 HeapFree(GetProcessHeap(), 0, Privileges);
1893 ret = DuplicateToken(Token, SecurityAnonymous, &ImpersonationToken);
1894 ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
1896 Size = sizeof(ImpersonationLevel);
1897 ret = GetTokenInformation(ImpersonationToken, TokenImpersonationLevel, &ImpersonationLevel, Size, &Size);
1898 ok(ret, "GetTokenInformation(TokenImpersonationLevel) failed with error %d\n", GetLastError());
1899 ok(ImpersonationLevel == SecurityAnonymous, "ImpersonationLevel should have been SecurityAnonymous instead of %d\n", ImpersonationLevel);
1901 CloseHandle(ImpersonationToken);
1903 /* default dacl */
1904 ret = GetTokenInformation(Token, TokenDefaultDacl, NULL, 0, &Size);
1905 ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1906 "GetTokenInformation(TokenDefaultDacl) failed with error %u\n", GetLastError());
1908 Dacl = HeapAlloc(GetProcessHeap(), 0, Size);
1909 ret = GetTokenInformation(Token, TokenDefaultDacl, Dacl, Size, &Size);
1910 ok(ret, "GetTokenInformation(TokenDefaultDacl) failed with error %u\n", GetLastError());
1912 SetLastError(0xdeadbeef);
1913 ret = SetTokenInformation(Token, TokenDefaultDacl, NULL, 0);
1914 GLE = GetLastError();
1915 ok(!ret, "SetTokenInformation(TokenDefaultDacl) succeeded\n");
1916 ok(GLE == ERROR_BAD_LENGTH, "expected ERROR_BAD_LENGTH got %u\n", GLE);
1918 SetLastError(0xdeadbeef);
1919 ret = SetTokenInformation(Token, TokenDefaultDacl, NULL, Size);
1920 GLE = GetLastError();
1921 ok(!ret, "SetTokenInformation(TokenDefaultDacl) succeeded\n");
1922 ok(GLE == ERROR_NOACCESS, "expected ERROR_NOACCESS got %u\n", GLE);
1924 acl = Dacl->DefaultDacl;
1925 Dacl->DefaultDacl = NULL;
1927 ret = SetTokenInformation(Token, TokenDefaultDacl, Dacl, Size);
1928 ok(ret, "SetTokenInformation(TokenDefaultDacl) succeeded\n");
1930 Size2 = 0;
1931 Dacl->DefaultDacl = (ACL *)0xdeadbeef;
1932 ret = GetTokenInformation(Token, TokenDefaultDacl, Dacl, Size, &Size2);
1933 ok(ret, "GetTokenInformation(TokenDefaultDacl) failed with error %u\n", GetLastError());
1934 ok(Dacl->DefaultDacl == NULL, "expected NULL, got %p\n", Dacl->DefaultDacl);
1935 ok(Size2 == sizeof(TOKEN_DEFAULT_DACL) || broken(Size2 == 2*sizeof(TOKEN_DEFAULT_DACL)), /* WoW64 */
1936 "got %u expected sizeof(TOKEN_DEFAULT_DACL)\n", Size2);
1938 Dacl->DefaultDacl = acl;
1939 ret = SetTokenInformation(Token, TokenDefaultDacl, Dacl, Size);
1940 ok(ret, "SetTokenInformation(TokenDefaultDacl) failed with error %u\n", GetLastError());
1942 if (Size2 == sizeof(TOKEN_DEFAULT_DACL)) {
1943 ret = GetTokenInformation(Token, TokenDefaultDacl, Dacl, Size, &Size2);
1944 ok(ret, "GetTokenInformation(TokenDefaultDacl) failed with error %u\n", GetLastError());
1945 } else
1946 win_skip("TOKEN_DEFAULT_DACL size too small on WoW64\n");
1948 HeapFree(GetProcessHeap(), 0, Dacl);
1949 CloseHandle(Token);
1952 static void test_GetTokenInformation(void)
1954 DWORD is_app_container, size;
1955 HANDLE token;
1956 BOOL ret;
1958 ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
1959 ok(ret, "OpenProcessToken failed: %u\n", GetLastError());
1961 size = 0;
1962 is_app_container = 0xdeadbeef;
1963 ret = GetTokenInformation(token, TokenIsAppContainer, &is_app_container,
1964 sizeof(is_app_container), &size);
1965 ok(ret || broken(GetLastError() == ERROR_INVALID_PARAMETER ||
1966 GetLastError() == ERROR_INVALID_FUNCTION), /* pre-win8 */
1967 "GetTokenInformation failed: %u\n", GetLastError());
1968 if(ret) {
1969 ok(size == sizeof(is_app_container), "size = %u\n", size);
1970 ok(!is_app_container, "is_app_container = %x\n", is_app_container);
1973 CloseHandle(token);
1976 typedef union _MAX_SID
1978 SID sid;
1979 char max[SECURITY_MAX_SID_SIZE];
1980 } MAX_SID;
1982 static void test_sid_str(PSID * sid)
1984 char *str_sid;
1985 BOOL ret = ConvertSidToStringSidA(sid, &str_sid);
1986 ok(ret, "ConvertSidToStringSidA() failed: %d\n", GetLastError());
1987 if (ret)
1989 char account[MAX_PATH], domain[MAX_PATH];
1990 SID_NAME_USE use;
1991 DWORD acc_size = MAX_PATH;
1992 DWORD dom_size = MAX_PATH;
1993 ret = LookupAccountSidA (NULL, sid, account, &acc_size, domain, &dom_size, &use);
1994 ok(ret || GetLastError() == ERROR_NONE_MAPPED,
1995 "LookupAccountSid(%s) failed: %d\n", str_sid, GetLastError());
1996 if (ret)
1997 trace(" %s %s\\%s %d\n", str_sid, domain, account, use);
1998 else if (GetLastError() == ERROR_NONE_MAPPED)
1999 trace(" %s couldn't be mapped\n", str_sid);
2000 LocalFree(str_sid);
2004 static const struct well_known_sid_value
2006 BOOL without_domain;
2007 const char *sid_string;
2008 } well_known_sid_values[] = {
2009 /* 0 */ {TRUE, "S-1-0-0"}, {TRUE, "S-1-1-0"}, {TRUE, "S-1-2-0"}, {TRUE, "S-1-3-0"},
2010 /* 4 */ {TRUE, "S-1-3-1"}, {TRUE, "S-1-3-2"}, {TRUE, "S-1-3-3"}, {TRUE, "S-1-5"},
2011 /* 8 */ {FALSE, "S-1-5-1"}, {TRUE, "S-1-5-2"}, {TRUE, "S-1-5-3"}, {TRUE, "S-1-5-4"},
2012 /* 12 */ {TRUE, "S-1-5-6"}, {TRUE, "S-1-5-7"}, {TRUE, "S-1-5-8"}, {TRUE, "S-1-5-9"},
2013 /* 16 */ {TRUE, "S-1-5-10"}, {TRUE, "S-1-5-11"}, {TRUE, "S-1-5-12"}, {TRUE, "S-1-5-13"},
2014 /* 20 */ {TRUE, "S-1-5-14"}, {FALSE, NULL}, {TRUE, "S-1-5-18"}, {TRUE, "S-1-5-19"},
2015 /* 24 */ {TRUE, "S-1-5-20"}, {TRUE, "S-1-5-32"},
2016 /* 26 */ {FALSE, "S-1-5-32-544"}, {TRUE, "S-1-5-32-545"}, {TRUE, "S-1-5-32-546"},
2017 /* 29 */ {TRUE, "S-1-5-32-547"}, {TRUE, "S-1-5-32-548"}, {TRUE, "S-1-5-32-549"},
2018 /* 32 */ {TRUE, "S-1-5-32-550"}, {TRUE, "S-1-5-32-551"}, {TRUE, "S-1-5-32-552"},
2019 /* 35 */ {TRUE, "S-1-5-32-554"}, {TRUE, "S-1-5-32-555"}, {TRUE, "S-1-5-32-556"},
2020 /* 38 */ {FALSE, "S-1-5-21-12-23-34-45-56-500"}, {FALSE, "S-1-5-21-12-23-34-45-56-501"},
2021 /* 40 */ {FALSE, "S-1-5-21-12-23-34-45-56-502"}, {FALSE, "S-1-5-21-12-23-34-45-56-512"},
2022 /* 42 */ {FALSE, "S-1-5-21-12-23-34-45-56-513"}, {FALSE, "S-1-5-21-12-23-34-45-56-514"},
2023 /* 44 */ {FALSE, "S-1-5-21-12-23-34-45-56-515"}, {FALSE, "S-1-5-21-12-23-34-45-56-516"},
2024 /* 46 */ {FALSE, "S-1-5-21-12-23-34-45-56-517"}, {FALSE, "S-1-5-21-12-23-34-45-56-518"},
2025 /* 48 */ {FALSE, "S-1-5-21-12-23-34-45-56-519"}, {FALSE, "S-1-5-21-12-23-34-45-56-520"},
2026 /* 50 */ {FALSE, "S-1-5-21-12-23-34-45-56-553"},
2027 /* Added in Windows Server 2003 */
2028 /* 51 */ {TRUE, "S-1-5-64-10"}, {TRUE, "S-1-5-64-21"}, {TRUE, "S-1-5-64-14"},
2029 /* 54 */ {TRUE, "S-1-5-15"}, {TRUE, "S-1-5-1000"}, {FALSE, "S-1-5-32-557"},
2030 /* 57 */ {TRUE, "S-1-5-32-558"}, {TRUE, "S-1-5-32-559"}, {TRUE, "S-1-5-32-560"},
2031 /* 60 */ {TRUE, "S-1-5-32-561"}, {TRUE, "S-1-5-32-562"},
2032 /* Added in Windows Vista: */
2033 /* 62 */ {TRUE, "S-1-5-32-568"},
2034 /* 63 */ {TRUE, "S-1-5-17"}, {FALSE, "S-1-5-32-569"}, {TRUE, "S-1-16-0"},
2035 /* 66 */ {TRUE, "S-1-16-4096"}, {TRUE, "S-1-16-8192"}, {TRUE, "S-1-16-12288"},
2036 /* 69 */ {TRUE, "S-1-16-16384"}, {TRUE, "S-1-5-33"}, {TRUE, "S-1-3-4"},
2037 /* 72 */ {FALSE, "S-1-5-21-12-23-34-45-56-571"}, {FALSE, "S-1-5-21-12-23-34-45-56-572"},
2038 /* 74 */ {TRUE, "S-1-5-22"}, {FALSE, "S-1-5-21-12-23-34-45-56-521"}, {TRUE, "S-1-5-32-573"},
2039 /* 77 */ {FALSE, "S-1-5-21-12-23-34-45-56-498"}, {TRUE, "S-1-5-32-574"}, {TRUE, "S-1-16-8448"},
2040 /* 80 */ {FALSE, NULL}, {TRUE, "S-1-2-1"}, {TRUE, "S-1-5-65-1"}, {FALSE, NULL},
2041 /* 84 */ {TRUE, "S-1-15-2-1"},
2044 static void test_CreateWellKnownSid(void)
2046 SID_IDENTIFIER_AUTHORITY ident = { SECURITY_NT_AUTHORITY };
2047 PSID domainsid, sid;
2048 DWORD size, error;
2049 BOOL ret;
2050 unsigned int i;
2052 size = 0;
2053 SetLastError(0xdeadbeef);
2054 ret = CreateWellKnownSid(WinInteractiveSid, NULL, NULL, &size);
2055 error = GetLastError();
2056 ok(!ret, "CreateWellKnownSid succeeded\n");
2057 ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
2058 ok(size, "expected size > 0\n");
2060 SetLastError(0xdeadbeef);
2061 ret = CreateWellKnownSid(WinInteractiveSid, NULL, NULL, &size);
2062 error = GetLastError();
2063 ok(!ret, "CreateWellKnownSid succeeded\n");
2064 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2066 sid = HeapAlloc(GetProcessHeap(), 0, size);
2067 ret = CreateWellKnownSid(WinInteractiveSid, NULL, sid, &size);
2068 ok(ret, "CreateWellKnownSid failed %u\n", GetLastError());
2069 HeapFree(GetProcessHeap(), 0, sid);
2071 /* a domain sid usually have three subauthorities but we test that CreateWellKnownSid doesn't check it */
2072 AllocateAndInitializeSid(&ident, 6, SECURITY_NT_NON_UNIQUE, 12, 23, 34, 45, 56, 0, 0, &domainsid);
2074 for (i = 0; i < ARRAY_SIZE(well_known_sid_values); i++)
2076 const struct well_known_sid_value *value = &well_known_sid_values[i];
2077 char sid_buffer[SECURITY_MAX_SID_SIZE];
2078 LPSTR str;
2079 DWORD cb;
2081 if (value->sid_string == NULL)
2082 continue;
2084 /* some SIDs aren't implemented by all Windows versions - detect it */
2085 cb = sizeof(sid_buffer);
2086 if (!CreateWellKnownSid(i, NULL, sid_buffer, &cb))
2088 skip("Well known SID %u not implemented\n", i);
2089 continue;
2092 cb = sizeof(sid_buffer);
2093 ok(CreateWellKnownSid(i, value->without_domain ? NULL : domainsid, sid_buffer, &cb), "Couldn't create well known sid %u\n", i);
2094 expect_eq(GetSidLengthRequired(*GetSidSubAuthorityCount(sid_buffer)), cb, DWORD, "%d");
2095 ok(IsValidSid(sid_buffer), "The sid is not valid\n");
2096 ok(ConvertSidToStringSidA(sid_buffer, &str), "Couldn't convert SID to string\n");
2097 ok(strcmp(str, value->sid_string) == 0, "%d: SID mismatch - expected %s, got %s\n", i,
2098 value->sid_string, str);
2099 LocalFree(str);
2101 if (value->without_domain)
2103 char buf2[SECURITY_MAX_SID_SIZE];
2104 cb = sizeof(buf2);
2105 ok(CreateWellKnownSid(i, domainsid, buf2, &cb), "Couldn't create well known sid %u with optional domain\n", i);
2106 expect_eq(GetSidLengthRequired(*GetSidSubAuthorityCount(sid_buffer)), cb, DWORD, "%d");
2107 ok(memcmp(buf2, sid_buffer, cb) == 0, "SID create with domain is different than without (%u)\n", i);
2111 FreeSid(domainsid);
2114 static void test_LookupAccountSid(void)
2116 SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
2117 CHAR accountA[MAX_PATH], domainA[MAX_PATH], usernameA[MAX_PATH];
2118 DWORD acc_sizeA, dom_sizeA, user_sizeA;
2119 DWORD real_acc_sizeA, real_dom_sizeA;
2120 WCHAR accountW[MAX_PATH], domainW[MAX_PATH];
2121 LSA_OBJECT_ATTRIBUTES object_attributes;
2122 DWORD acc_sizeW, dom_sizeW;
2123 DWORD real_acc_sizeW, real_dom_sizeW;
2124 PSID pUsersSid = NULL;
2125 SID_NAME_USE use;
2126 BOOL ret;
2127 DWORD error, size, cbti = 0;
2128 MAX_SID max_sid;
2129 CHAR *str_sidA;
2130 int i;
2131 HANDLE hToken;
2132 PTOKEN_USER ptiUser = NULL;
2133 LSA_HANDLE handle;
2134 NTSTATUS status;
2136 /* native windows crashes if account size, domain size, or name use is NULL */
2138 ret = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
2139 DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &pUsersSid);
2140 ok(ret || (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED),
2141 "AllocateAndInitializeSid failed with error %d\n", GetLastError());
2143 /* not running on NT so give up */
2144 if (!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
2145 return;
2147 real_acc_sizeA = MAX_PATH;
2148 real_dom_sizeA = MAX_PATH;
2149 ret = LookupAccountSidA(NULL, pUsersSid, accountA, &real_acc_sizeA, domainA, &real_dom_sizeA, &use);
2150 ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
2152 /* try NULL account */
2153 acc_sizeA = MAX_PATH;
2154 dom_sizeA = MAX_PATH;
2155 ret = LookupAccountSidA(NULL, pUsersSid, NULL, &acc_sizeA, domainA, &dom_sizeA, &use);
2156 ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
2158 /* try NULL domain */
2159 acc_sizeA = MAX_PATH;
2160 dom_sizeA = MAX_PATH;
2161 ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, NULL, &dom_sizeA, &use);
2162 ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
2164 /* try a small account buffer */
2165 acc_sizeA = 1;
2166 dom_sizeA = MAX_PATH;
2167 accountA[0] = 0;
2168 ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
2169 ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n");
2170 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2171 "LookupAccountSidA() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
2173 /* try a 0 sized account buffer */
2174 acc_sizeA = 0;
2175 dom_sizeA = MAX_PATH;
2176 accountA[0] = 0;
2177 LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
2178 /* this can fail or succeed depending on OS version but the size will always be returned */
2179 ok(acc_sizeA == real_acc_sizeA + 1,
2180 "LookupAccountSidA() Expected acc_size = %u, got %u\n",
2181 real_acc_sizeA + 1, acc_sizeA);
2183 /* try a 0 sized account buffer */
2184 acc_sizeA = 0;
2185 dom_sizeA = MAX_PATH;
2186 LookupAccountSidA(NULL, pUsersSid, NULL, &acc_sizeA, domainA, &dom_sizeA, &use);
2187 /* this can fail or succeed depending on OS version but the size will always be returned */
2188 ok(acc_sizeA == real_acc_sizeA + 1,
2189 "LookupAccountSid() Expected acc_size = %u, got %u\n",
2190 real_acc_sizeA + 1, acc_sizeA);
2192 /* try a small domain buffer */
2193 dom_sizeA = 1;
2194 acc_sizeA = MAX_PATH;
2195 accountA[0] = 0;
2196 ret = LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
2197 ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n");
2198 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2199 "LookupAccountSidA() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
2201 /* try a 0 sized domain buffer */
2202 dom_sizeA = 0;
2203 acc_sizeA = MAX_PATH;
2204 accountA[0] = 0;
2205 LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
2206 /* this can fail or succeed depending on OS version but the size will always be returned */
2207 ok(dom_sizeA == real_dom_sizeA + 1,
2208 "LookupAccountSidA() Expected dom_size = %u, got %u\n",
2209 real_dom_sizeA + 1, dom_sizeA);
2211 /* try a 0 sized domain buffer */
2212 dom_sizeA = 0;
2213 acc_sizeA = MAX_PATH;
2214 LookupAccountSidA(NULL, pUsersSid, accountA, &acc_sizeA, NULL, &dom_sizeA, &use);
2215 /* this can fail or succeed depending on OS version but the size will always be returned */
2216 ok(dom_sizeA == real_dom_sizeA + 1,
2217 "LookupAccountSidA() Expected dom_size = %u, got %u\n",
2218 real_dom_sizeA + 1, dom_sizeA);
2220 real_acc_sizeW = MAX_PATH;
2221 real_dom_sizeW = MAX_PATH;
2222 ret = LookupAccountSidW(NULL, pUsersSid, accountW, &real_acc_sizeW, domainW, &real_dom_sizeW, &use);
2223 ok(ret, "LookupAccountSidW() Expected TRUE, got FALSE\n");
2225 /* try an invalid system name */
2226 real_acc_sizeA = MAX_PATH;
2227 real_dom_sizeA = MAX_PATH;
2228 ret = LookupAccountSidA("deepthought", pUsersSid, accountA, &real_acc_sizeA, domainA, &real_dom_sizeA, &use);
2229 ok(!ret, "LookupAccountSidA() Expected FALSE got TRUE\n");
2230 ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR /* Vista */,
2231 "LookupAccountSidA() Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %u\n", GetLastError());
2233 /* native windows crashes if domainW or accountW is NULL */
2235 /* try a small account buffer */
2236 acc_sizeW = 1;
2237 dom_sizeW = MAX_PATH;
2238 accountW[0] = 0;
2239 ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
2240 ok(!ret, "LookupAccountSidW() Expected FALSE got TRUE\n");
2241 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2242 "LookupAccountSidW() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
2244 /* try a 0 sized account buffer */
2245 acc_sizeW = 0;
2246 dom_sizeW = MAX_PATH;
2247 accountW[0] = 0;
2248 LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
2249 /* this can fail or succeed depending on OS version but the size will always be returned */
2250 ok(acc_sizeW == real_acc_sizeW + 1,
2251 "LookupAccountSidW() Expected acc_size = %u, got %u\n",
2252 real_acc_sizeW + 1, acc_sizeW);
2254 /* try a 0 sized account buffer */
2255 acc_sizeW = 0;
2256 dom_sizeW = MAX_PATH;
2257 LookupAccountSidW(NULL, pUsersSid, NULL, &acc_sizeW, domainW, &dom_sizeW, &use);
2258 /* this can fail or succeed depending on OS version but the size will always be returned */
2259 ok(acc_sizeW == real_acc_sizeW + 1,
2260 "LookupAccountSidW() Expected acc_size = %u, got %u\n",
2261 real_acc_sizeW + 1, acc_sizeW);
2263 /* try a small domain buffer */
2264 dom_sizeW = 1;
2265 acc_sizeW = MAX_PATH;
2266 accountW[0] = 0;
2267 ret = LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
2268 ok(!ret, "LookupAccountSidW() Expected FALSE got TRUE\n");
2269 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2270 "LookupAccountSidW() Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
2272 /* try a 0 sized domain buffer */
2273 dom_sizeW = 0;
2274 acc_sizeW = MAX_PATH;
2275 accountW[0] = 0;
2276 LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, domainW, &dom_sizeW, &use);
2277 /* this can fail or succeed depending on OS version but the size will always be returned */
2278 ok(dom_sizeW == real_dom_sizeW + 1,
2279 "LookupAccountSidW() Expected dom_size = %u, got %u\n",
2280 real_dom_sizeW + 1, dom_sizeW);
2282 /* try a 0 sized domain buffer */
2283 dom_sizeW = 0;
2284 acc_sizeW = MAX_PATH;
2285 LookupAccountSidW(NULL, pUsersSid, accountW, &acc_sizeW, NULL, &dom_sizeW, &use);
2286 /* this can fail or succeed depending on OS version but the size will always be returned */
2287 ok(dom_sizeW == real_dom_sizeW + 1,
2288 "LookupAccountSidW() Expected dom_size = %u, got %u\n",
2289 real_dom_sizeW + 1, dom_sizeW);
2291 acc_sizeW = dom_sizeW = use = 0;
2292 SetLastError(0xdeadbeef);
2293 ret = LookupAccountSidW(NULL, pUsersSid, NULL, &acc_sizeW, NULL, &dom_sizeW, &use);
2294 error = GetLastError();
2295 ok(!ret, "LookupAccountSidW failed %u\n", GetLastError());
2296 ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
2297 ok(acc_sizeW, "expected non-zero account size\n");
2298 ok(dom_sizeW, "expected non-zero domain size\n");
2299 ok(!use, "expected zero use %u\n", use);
2301 FreeSid(pUsersSid);
2303 /* Test LookupAccountSid with Sid retrieved from token information.
2304 This assumes this process is running under the account of the current user.*/
2305 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_DUPLICATE, &hToken);
2306 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
2307 ret = GetTokenInformation(hToken, TokenUser, NULL, 0, &cbti);
2308 ok(!ret, "GetTokenInformation failed with error %d\n", GetLastError());
2309 ptiUser = HeapAlloc(GetProcessHeap(), 0, cbti);
2310 if (GetTokenInformation(hToken, TokenUser, ptiUser, cbti, &cbti))
2312 acc_sizeA = dom_sizeA = MAX_PATH;
2313 ret = LookupAccountSidA(NULL, ptiUser->User.Sid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use);
2314 ok(ret, "LookupAccountSidA() Expected TRUE, got FALSE\n");
2315 user_sizeA = MAX_PATH;
2316 ret = GetUserNameA(usernameA , &user_sizeA);
2317 ok(ret, "GetUserNameA() Expected TRUE, got FALSE\n");
2318 ok(lstrcmpA(usernameA, accountA) == 0, "LookupAccountSidA() Expected account name: %s got: %s\n", usernameA, accountA );
2320 HeapFree(GetProcessHeap(), 0, ptiUser);
2322 trace("Well Known SIDs:\n");
2323 for (i = 0; i <= 60; i++)
2325 size = SECURITY_MAX_SID_SIZE;
2326 if (CreateWellKnownSid(i, NULL, &max_sid.sid, &size))
2328 if (ConvertSidToStringSidA(&max_sid.sid, &str_sidA))
2330 acc_sizeA = MAX_PATH;
2331 dom_sizeA = MAX_PATH;
2332 if (LookupAccountSidA(NULL, &max_sid.sid, accountA, &acc_sizeA, domainA, &dom_sizeA, &use))
2333 trace(" %d: %s %s\\%s %d\n", i, str_sidA, domainA, accountA, use);
2334 LocalFree(str_sidA);
2337 else
2339 if (GetLastError() != ERROR_INVALID_PARAMETER)
2340 trace(" CreateWellKnownSid(%d) failed: %d\n", i, GetLastError());
2341 else
2342 trace(" %d: not supported\n", i);
2346 ZeroMemory(&object_attributes, sizeof(object_attributes));
2347 object_attributes.Length = sizeof(object_attributes);
2349 status = LsaOpenPolicy( NULL, &object_attributes, POLICY_ALL_ACCESS, &handle);
2350 ok(status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED,
2351 "LsaOpenPolicy(POLICY_ALL_ACCESS) returned 0x%08x\n", status);
2353 /* try a more restricted access mask if necessary */
2354 if (status == STATUS_ACCESS_DENIED) {
2355 trace("LsaOpenPolicy(POLICY_ALL_ACCESS) failed, trying POLICY_VIEW_LOCAL_INFORMATION\n");
2356 status = LsaOpenPolicy( NULL, &object_attributes, POLICY_VIEW_LOCAL_INFORMATION, &handle);
2357 ok(status == STATUS_SUCCESS, "LsaOpenPolicy(POLICY_VIEW_LOCAL_INFORMATION) returned 0x%08x\n", status);
2360 if (status == STATUS_SUCCESS)
2362 PPOLICY_ACCOUNT_DOMAIN_INFO info;
2363 status = LsaQueryInformationPolicy(handle, PolicyAccountDomainInformation, (PVOID*)&info);
2364 ok(status == STATUS_SUCCESS, "LsaQueryInformationPolicy() failed, returned 0x%08x\n", status);
2365 if (status == STATUS_SUCCESS)
2367 ok(info->DomainSid!=0, "LsaQueryInformationPolicy(PolicyAccountDomainInformation) missing SID\n");
2368 if (info->DomainSid)
2370 int count = *GetSidSubAuthorityCount(info->DomainSid);
2371 CopySid(GetSidLengthRequired(count), &max_sid, info->DomainSid);
2372 test_sid_str((PSID)&max_sid.sid);
2373 max_sid.sid.SubAuthority[count] = DOMAIN_USER_RID_ADMIN;
2374 max_sid.sid.SubAuthorityCount = count + 1;
2375 test_sid_str((PSID)&max_sid.sid);
2376 max_sid.sid.SubAuthority[count] = DOMAIN_USER_RID_GUEST;
2377 test_sid_str((PSID)&max_sid.sid);
2378 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_ADMINS;
2379 test_sid_str((PSID)&max_sid.sid);
2380 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_USERS;
2381 test_sid_str((PSID)&max_sid.sid);
2382 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_GUESTS;
2383 test_sid_str((PSID)&max_sid.sid);
2384 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_COMPUTERS;
2385 test_sid_str((PSID)&max_sid.sid);
2386 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_CONTROLLERS;
2387 test_sid_str((PSID)&max_sid.sid);
2388 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_CERT_ADMINS;
2389 test_sid_str((PSID)&max_sid.sid);
2390 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_SCHEMA_ADMINS;
2391 test_sid_str((PSID)&max_sid.sid);
2392 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_ENTERPRISE_ADMINS;
2393 test_sid_str((PSID)&max_sid.sid);
2394 max_sid.sid.SubAuthority[count] = DOMAIN_GROUP_RID_POLICY_ADMINS;
2395 test_sid_str((PSID)&max_sid.sid);
2396 max_sid.sid.SubAuthority[count] = DOMAIN_ALIAS_RID_RAS_SERVERS;
2397 test_sid_str((PSID)&max_sid.sid);
2398 max_sid.sid.SubAuthority[count] = 1000; /* first user account */
2399 test_sid_str((PSID)&max_sid.sid);
2402 LsaFreeMemory(info);
2405 status = LsaClose(handle);
2406 ok(status == STATUS_SUCCESS, "LsaClose() failed, returned 0x%08x\n", status);
2410 static BOOL get_sid_info(PSID psid, LPSTR *user, LPSTR *dom)
2412 static CHAR account[UNLEN + 1];
2413 static CHAR domain[UNLEN + 1];
2414 DWORD size, dom_size;
2415 SID_NAME_USE use;
2417 *user = account;
2418 *dom = domain;
2420 size = dom_size = UNLEN + 1;
2421 account[0] = '\0';
2422 domain[0] = '\0';
2423 SetLastError(0xdeadbeef);
2424 return LookupAccountSidA(NULL, psid, account, &size, domain, &dom_size, &use);
2427 static void check_wellknown_name(const char* name, WELL_KNOWN_SID_TYPE result)
2429 SID_IDENTIFIER_AUTHORITY ident = { SECURITY_NT_AUTHORITY };
2430 PSID domainsid = NULL;
2431 char wk_sid[SECURITY_MAX_SID_SIZE];
2432 DWORD cb;
2434 DWORD sid_size, domain_size;
2435 SID_NAME_USE sid_use;
2436 LPSTR domain, account, sid_domain, wk_domain, wk_account;
2437 PSID psid;
2438 BOOL ret ,ret2;
2440 sid_size = 0;
2441 domain_size = 0;
2442 ret = LookupAccountNameA(NULL, name, NULL, &sid_size, NULL, &domain_size, &sid_use);
2443 ok(!ret, " %s Should have failed to lookup account name\n", name);
2444 psid = HeapAlloc(GetProcessHeap(),0,sid_size);
2445 domain = HeapAlloc(GetProcessHeap(),0,domain_size);
2446 ret = LookupAccountNameA(NULL, name, psid, &sid_size, domain, &domain_size, &sid_use);
2448 if (!result)
2450 ok(!ret, " %s Should have failed to lookup account name\n",name);
2451 goto cleanup;
2454 AllocateAndInitializeSid(&ident, 6, SECURITY_NT_NON_UNIQUE, 12, 23, 34, 45, 56, 0, 0, &domainsid);
2455 cb = sizeof(wk_sid);
2456 if (!CreateWellKnownSid(result, domainsid, wk_sid, &cb))
2458 win_skip("SID %i is not available on the system\n",result);
2459 goto cleanup;
2462 ret2 = get_sid_info(wk_sid, &wk_account, &wk_domain);
2463 if (!ret2 && GetLastError() == ERROR_NONE_MAPPED)
2465 win_skip("CreateWellKnownSid() succeeded but the account '%s' is not present (W2K)\n", name);
2466 goto cleanup;
2469 get_sid_info(psid, &account, &sid_domain);
2471 ok(ret, "Failed to lookup account name %s\n",name);
2472 ok(sid_size != 0, "sid_size was zero\n");
2474 ok(EqualSid(psid,wk_sid),"%s Sid %s fails to match well known sid %s!\n",
2475 name, debugstr_sid(psid), debugstr_sid(wk_sid));
2477 ok(!lstrcmpA(account, wk_account), "Expected %s , got %s\n", account, wk_account);
2478 ok(!lstrcmpA(domain, wk_domain), "Expected %s, got %s\n", wk_domain, domain);
2479 ok(sid_use == SidTypeWellKnownGroup , "Expected Use (5), got %d\n", sid_use);
2481 cleanup:
2482 FreeSid(domainsid);
2483 HeapFree(GetProcessHeap(),0,psid);
2484 HeapFree(GetProcessHeap(),0,domain);
2487 static void test_LookupAccountName(void)
2489 DWORD sid_size, domain_size, user_size;
2490 DWORD sid_save, domain_save;
2491 CHAR user_name[UNLEN + 1];
2492 CHAR computer_name[UNLEN + 1];
2493 SID_NAME_USE sid_use;
2494 LPSTR domain, account, sid_dom;
2495 PSID psid;
2496 BOOL ret;
2498 /* native crashes if (assuming all other parameters correct):
2499 * - peUse is NULL
2500 * - Sid is NULL and cbSid is > 0
2501 * - cbSid or cchReferencedDomainName are NULL
2502 * - ReferencedDomainName is NULL and cchReferencedDomainName is the correct size
2505 user_size = UNLEN + 1;
2506 SetLastError(0xdeadbeef);
2507 ret = GetUserNameA(user_name, &user_size);
2508 ok(ret, "Failed to get user name : %d\n", GetLastError());
2510 /* get sizes */
2511 sid_size = 0;
2512 domain_size = 0;
2513 sid_use = 0xcafebabe;
2514 SetLastError(0xdeadbeef);
2515 ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, NULL, &domain_size, &sid_use);
2516 if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
2518 win_skip("LookupAccountNameA is not implemented\n");
2519 return;
2521 ok(!ret, "Expected 0, got %d\n", ret);
2522 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2523 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2524 ok(sid_size != 0, "Expected non-zero sid size\n");
2525 ok(domain_size != 0, "Expected non-zero domain size\n");
2526 ok(sid_use == (SID_NAME_USE)0xcafebabe, "Expected 0xcafebabe, got %d\n", sid_use);
2528 sid_save = sid_size;
2529 domain_save = domain_size;
2531 psid = HeapAlloc(GetProcessHeap(), 0, sid_size);
2532 domain = HeapAlloc(GetProcessHeap(), 0, domain_size);
2534 /* try valid account name */
2535 ret = LookupAccountNameA(NULL, user_name, psid, &sid_size, domain, &domain_size, &sid_use);
2536 get_sid_info(psid, &account, &sid_dom);
2537 ok(ret, "Failed to lookup account name\n");
2538 ok(sid_size == GetLengthSid(psid), "Expected %d, got %d\n", GetLengthSid(psid), sid_size);
2539 ok(!lstrcmpA(account, user_name), "Expected %s, got %s\n", user_name, account);
2540 ok(!lstrcmpiA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
2541 ok(domain_size == domain_save - 1, "Expected %d, got %d\n", domain_save - 1, domain_size);
2542 ok(strlen(domain) == domain_size, "Expected %d, got %d\n", lstrlenA(domain), domain_size);
2543 ok(sid_use == SidTypeUser, "Expected SidTypeUser (%d), got %d\n", SidTypeUser, sid_use);
2544 domain_size = domain_save;
2545 sid_size = sid_save;
2547 if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH)
2549 skip("Non-English locale (test with hardcoded 'Everyone')\n");
2551 else
2553 ret = LookupAccountNameA(NULL, "Everyone", psid, &sid_size, domain, &domain_size, &sid_use);
2554 get_sid_info(psid, &account, &sid_dom);
2555 ok(ret, "Failed to lookup account name\n");
2556 ok(sid_size != 0, "sid_size was zero\n");
2557 ok(!lstrcmpA(account, "Everyone"), "Expected Everyone, got %s\n", account);
2558 ok(!lstrcmpiA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
2559 ok(domain_size == 0, "Expected 0, got %d\n", domain_size);
2560 ok(strlen(domain) == domain_size, "Expected %d, got %d\n", lstrlenA(domain), domain_size);
2561 ok(sid_use == SidTypeWellKnownGroup, "Expected SidTypeWellKnownGroup (%d), got %d\n", SidTypeWellKnownGroup, sid_use);
2562 domain_size = domain_save;
2565 /* NULL Sid with zero sid size */
2566 SetLastError(0xdeadbeef);
2567 sid_size = 0;
2568 ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, domain, &domain_size, &sid_use);
2569 ok(!ret, "Expected 0, got %d\n", ret);
2570 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2571 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2572 ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size);
2573 ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
2575 /* try cchReferencedDomainName - 1 */
2576 SetLastError(0xdeadbeef);
2577 domain_size--;
2578 ret = LookupAccountNameA(NULL, user_name, NULL, &sid_size, domain, &domain_size, &sid_use);
2579 ok(!ret, "Expected 0, got %d\n", ret);
2580 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2581 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2582 ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size);
2583 ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
2585 /* NULL ReferencedDomainName with zero domain name size */
2586 SetLastError(0xdeadbeef);
2587 domain_size = 0;
2588 ret = LookupAccountNameA(NULL, user_name, psid, &sid_size, NULL, &domain_size, &sid_use);
2589 ok(!ret, "Expected 0, got %d\n", ret);
2590 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2591 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2592 ok(sid_size == sid_save, "Expected %d, got %d\n", sid_save, sid_size);
2593 ok(domain_size == domain_save, "Expected %d, got %d\n", domain_save, domain_size);
2595 HeapFree(GetProcessHeap(), 0, psid);
2596 HeapFree(GetProcessHeap(), 0, domain);
2598 /* get sizes for NULL account name */
2599 sid_size = 0;
2600 domain_size = 0;
2601 sid_use = 0xcafebabe;
2602 SetLastError(0xdeadbeef);
2603 ret = LookupAccountNameA(NULL, NULL, NULL, &sid_size, NULL, &domain_size, &sid_use);
2604 if (!ret && GetLastError() == ERROR_NONE_MAPPED)
2605 win_skip("NULL account name doesn't work on NT4\n");
2606 else
2608 ok(!ret, "Expected 0, got %d\n", ret);
2609 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2610 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2611 ok(sid_size != 0, "Expected non-zero sid size\n");
2612 ok(domain_size != 0, "Expected non-zero domain size\n");
2613 ok(sid_use == (SID_NAME_USE)0xcafebabe, "Expected 0xcafebabe, got %d\n", sid_use);
2615 psid = HeapAlloc(GetProcessHeap(), 0, sid_size);
2616 domain = HeapAlloc(GetProcessHeap(), 0, domain_size);
2618 /* try NULL account name */
2619 ret = LookupAccountNameA(NULL, NULL, psid, &sid_size, domain, &domain_size, &sid_use);
2620 get_sid_info(psid, &account, &sid_dom);
2621 ok(ret, "Failed to lookup account name\n");
2622 /* Using a fixed string will not work on different locales */
2623 ok(!lstrcmpiA(account, domain),
2624 "Got %s for account and %s for domain, these should be the same\n", account, domain);
2625 ok(sid_use == SidTypeDomain, "Expected SidTypeDomain (%d), got %d\n", SidTypeDomain, sid_use);
2627 HeapFree(GetProcessHeap(), 0, psid);
2628 HeapFree(GetProcessHeap(), 0, domain);
2631 /* try an invalid account name */
2632 SetLastError(0xdeadbeef);
2633 sid_size = 0;
2634 domain_size = 0;
2635 ret = LookupAccountNameA(NULL, "oogabooga", NULL, &sid_size, NULL, &domain_size, &sid_use);
2636 ok(!ret, "Expected 0, got %d\n", ret);
2637 ok(GetLastError() == ERROR_NONE_MAPPED ||
2638 broken(GetLastError() == ERROR_TRUSTED_RELATIONSHIP_FAILURE),
2639 "Expected ERROR_NONE_MAPPED, got %d\n", GetLastError());
2640 ok(sid_size == 0, "Expected 0, got %d\n", sid_size);
2641 ok(domain_size == 0, "Expected 0, got %d\n", domain_size);
2643 /* try an invalid system name */
2644 SetLastError(0xdeadbeef);
2645 sid_size = 0;
2646 domain_size = 0;
2647 ret = LookupAccountNameA("deepthought", NULL, NULL, &sid_size, NULL, &domain_size, &sid_use);
2648 ok(!ret, "Expected 0, got %d\n", ret);
2649 ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR /* Vista */,
2650 "Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %d\n", GetLastError());
2651 ok(sid_size == 0, "Expected 0, got %d\n", sid_size);
2652 ok(domain_size == 0, "Expected 0, got %d\n", domain_size);
2654 /* try with the computer name as the account name */
2655 domain_size = sizeof(computer_name);
2656 GetComputerNameA(computer_name, &domain_size);
2657 sid_size = 0;
2658 domain_size = 0;
2659 ret = LookupAccountNameA(NULL, computer_name, NULL, &sid_size, NULL, &domain_size, &sid_use);
2660 ok(!ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
2661 GetLastError() == ERROR_NONE_MAPPED /* in a domain */ ||
2662 broken(GetLastError() == ERROR_TRUSTED_DOMAIN_FAILURE) ||
2663 broken(GetLastError() == ERROR_TRUSTED_RELATIONSHIP_FAILURE)),
2664 "LookupAccountNameA failed: %d\n", GetLastError());
2665 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2667 psid = HeapAlloc(GetProcessHeap(), 0, sid_size);
2668 domain = HeapAlloc(GetProcessHeap(), 0, domain_size);
2669 ret = LookupAccountNameA(NULL, computer_name, psid, &sid_size, domain, &domain_size, &sid_use);
2670 ok(ret, "LookupAccountNameA failed: %d\n", GetLastError());
2671 ok(sid_use == SidTypeDomain ||
2672 (sid_use == SidTypeUser && ! strcmp(computer_name, user_name)), "expected SidTypeDomain for %s, got %d\n", computer_name, sid_use);
2673 HeapFree(GetProcessHeap(), 0, domain);
2674 HeapFree(GetProcessHeap(), 0, psid);
2677 /* Well Known names */
2678 if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH)
2680 skip("Non-English locale (skipping well known name creation tests)\n");
2681 return;
2684 check_wellknown_name("LocalService", WinLocalServiceSid);
2685 check_wellknown_name("Local Service", WinLocalServiceSid);
2686 /* 2 spaces */
2687 check_wellknown_name("Local Service", 0);
2688 check_wellknown_name("NetworkService", WinNetworkServiceSid);
2689 check_wellknown_name("Network Service", WinNetworkServiceSid);
2691 /* example of some names where the spaces are not optional */
2692 check_wellknown_name("Terminal Server User", WinTerminalServerSid);
2693 check_wellknown_name("TerminalServer User", 0);
2694 check_wellknown_name("TerminalServerUser", 0);
2695 check_wellknown_name("Terminal ServerUser", 0);
2697 check_wellknown_name("enterprise domain controllers",WinEnterpriseControllersSid);
2698 check_wellknown_name("enterprisedomain controllers", 0);
2699 check_wellknown_name("enterprise domaincontrollers", 0);
2700 check_wellknown_name("enterprisedomaincontrollers", 0);
2702 /* case insensitivity */
2703 check_wellknown_name("lOCAlServICE", WinLocalServiceSid);
2705 /* fully qualified account names */
2706 check_wellknown_name("NT AUTHORITY\\LocalService", WinLocalServiceSid);
2707 check_wellknown_name("nt authority\\Network Service", WinNetworkServiceSid);
2708 check_wellknown_name("nt authority test\\Network Service", 0);
2709 check_wellknown_name("Dummy\\Network Service", 0);
2710 check_wellknown_name("ntauthority\\Network Service", 0);
2713 static void test_security_descriptor(void)
2715 SECURITY_DESCRIPTOR sd, *sd_rel, *sd_rel2, *sd_abs;
2716 char buf[8192];
2717 DWORD size, size_dacl, size_sacl, size_owner, size_group;
2718 BOOL isDefault, isPresent, ret;
2719 PACL pacl, dacl, sacl;
2720 PSID psid, owner, group;
2722 SetLastError(0xdeadbeef);
2723 ret = InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
2724 if (ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2726 win_skip("InitializeSecurityDescriptor is not implemented\n");
2727 return;
2730 ok(GetSecurityDescriptorOwner(&sd, &psid, &isDefault), "GetSecurityDescriptorOwner failed\n");
2731 expect_eq(psid, NULL, PSID, "%p");
2732 expect_eq(isDefault, FALSE, BOOL, "%d");
2733 sd.Control |= SE_DACL_PRESENT | SE_SACL_PRESENT;
2735 SetLastError(0xdeadbeef);
2736 size = 5;
2737 expect_eq(MakeSelfRelativeSD(&sd, buf, &size), FALSE, BOOL, "%d");
2738 expect_eq(GetLastError(), ERROR_INSUFFICIENT_BUFFER, DWORD, "%u");
2739 ok(size > 5, "Size not increased\n");
2740 if (size <= 8192)
2742 expect_eq(MakeSelfRelativeSD(&sd, buf, &size), TRUE, BOOL, "%d");
2743 ok(GetSecurityDescriptorOwner(&sd, &psid, &isDefault), "GetSecurityDescriptorOwner failed\n");
2744 expect_eq(psid, NULL, PSID, "%p");
2745 expect_eq(isDefault, FALSE, BOOL, "%d");
2746 ok(GetSecurityDescriptorGroup(&sd, &psid, &isDefault), "GetSecurityDescriptorGroup failed\n");
2747 expect_eq(psid, NULL, PSID, "%p");
2748 expect_eq(isDefault, FALSE, BOOL, "%d");
2749 ok(GetSecurityDescriptorDacl(&sd, &isPresent, &pacl, &isDefault), "GetSecurityDescriptorDacl failed\n");
2750 expect_eq(isPresent, TRUE, BOOL, "%d");
2751 expect_eq(psid, NULL, PSID, "%p");
2752 expect_eq(isDefault, FALSE, BOOL, "%d");
2753 ok(GetSecurityDescriptorSacl(&sd, &isPresent, &pacl, &isDefault), "GetSecurityDescriptorSacl failed\n");
2754 expect_eq(isPresent, TRUE, BOOL, "%d");
2755 expect_eq(psid, NULL, PSID, "%p");
2756 expect_eq(isDefault, FALSE, BOOL, "%d");
2759 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA(
2760 "O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)"
2761 "(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)"
2762 "(AU;NPSA;0x12019f;;;SU)", SDDL_REVISION_1, (void **)&sd_rel, NULL);
2763 ok(ret, "got %u\n", GetLastError());
2765 size = 0;
2766 ret = MakeSelfRelativeSD(sd_rel, NULL, &size);
2767 todo_wine ok(!ret && GetLastError() == ERROR_BAD_DESCRIPTOR_FORMAT, "got %u\n", GetLastError());
2769 /* convert to absolute form */
2770 size = size_dacl = size_sacl = size_owner = size_group = 0;
2771 ret = MakeAbsoluteSD(sd_rel, NULL, &size, NULL, &size_dacl, NULL, &size_sacl, NULL, &size_owner, NULL,
2772 &size_group);
2773 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2775 sd_abs = HeapAlloc(GetProcessHeap(), 0, size + size_dacl + size_sacl + size_owner + size_group);
2776 dacl = (PACL)(sd_abs + 1);
2777 sacl = (PACL)((char *)dacl + size_dacl);
2778 owner = (PSID)((char *)sacl + size_sacl);
2779 group = (PSID)((char *)owner + size_owner);
2780 ret = MakeAbsoluteSD(sd_rel, sd_abs, &size, dacl, &size_dacl, sacl, &size_sacl, owner, &size_owner,
2781 group, &size_group);
2782 ok(ret, "got %u\n", GetLastError());
2784 size = 0;
2785 ret = MakeSelfRelativeSD(sd_abs, NULL, &size);
2786 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2787 ok(size == 184, "got %u\n", size);
2789 size += 4;
2790 sd_rel2 = HeapAlloc(GetProcessHeap(), 0, size);
2791 ret = MakeSelfRelativeSD(sd_abs, sd_rel2, &size);
2792 ok(ret, "got %u\n", GetLastError());
2793 ok(size == 188, "got %u\n", size);
2795 HeapFree(GetProcessHeap(), 0, sd_abs);
2796 HeapFree(GetProcessHeap(), 0, sd_rel2);
2797 LocalFree(sd_rel);
2800 #define TEST_GRANTED_ACCESS(a,b) test_granted_access(a,b,0,__LINE__)
2801 #define TEST_GRANTED_ACCESS2(a,b,c) test_granted_access(a,b,c,__LINE__)
2802 static void test_granted_access(HANDLE handle, ACCESS_MASK access,
2803 ACCESS_MASK alt, int line)
2805 OBJECT_BASIC_INFORMATION obj_info;
2806 NTSTATUS status;
2808 if (!pNtQueryObject)
2810 skip_(__FILE__, line)("Not NT platform - skipping tests\n");
2811 return;
2814 status = pNtQueryObject( handle, ObjectBasicInformation, &obj_info,
2815 sizeof(obj_info), NULL );
2816 ok_(__FILE__, line)(!status, "NtQueryObject with err: %08x\n", status);
2817 if (alt)
2818 ok_(__FILE__, line)(obj_info.GrantedAccess == access ||
2819 obj_info.GrantedAccess == alt, "Granted access should be 0x%08x "
2820 "or 0x%08x, instead of 0x%08x\n", access, alt, obj_info.GrantedAccess);
2821 else
2822 ok_(__FILE__, line)(obj_info.GrantedAccess == access, "Granted access should "
2823 "be 0x%08x, instead of 0x%08x\n", access, obj_info.GrantedAccess);
2826 #define CHECK_SET_SECURITY(o,i,e) \
2827 do{ \
2828 BOOL res_; \
2829 DWORD err; \
2830 SetLastError( 0xdeadbeef ); \
2831 res_ = SetKernelObjectSecurity( o, i, SecurityDescriptor ); \
2832 err = GetLastError(); \
2833 if (e == ERROR_SUCCESS) \
2834 ok(res_, "SetKernelObjectSecurity failed with %d\n", err); \
2835 else \
2836 ok(!res_ && err == e, "SetKernelObjectSecurity should have failed " \
2837 "with %s, instead of %d\n", #e, err); \
2838 }while(0)
2840 static void test_process_security(void)
2842 BOOL res;
2843 PTOKEN_USER user;
2844 PTOKEN_OWNER owner;
2845 PTOKEN_PRIMARY_GROUP group;
2846 PSID AdminSid = NULL, UsersSid = NULL, UserSid = NULL;
2847 PACL Acl = NULL, ThreadAcl = NULL;
2848 SECURITY_DESCRIPTOR *SecurityDescriptor = NULL, *ThreadSecurityDescriptor = NULL;
2849 char buffer[MAX_PATH], account[MAX_PATH], domain[MAX_PATH];
2850 PROCESS_INFORMATION info;
2851 STARTUPINFOA startup;
2852 SECURITY_ATTRIBUTES psa, tsa;
2853 HANDLE token, event;
2854 DWORD size, acc_size, dom_size, ret;
2855 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
2856 PSID EveryoneSid = NULL;
2857 SID_NAME_USE use;
2859 Acl = HeapAlloc(GetProcessHeap(), 0, 256);
2860 res = InitializeAcl(Acl, 256, ACL_REVISION);
2861 if (!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2863 win_skip("ACLs not implemented - skipping tests\n");
2864 HeapFree(GetProcessHeap(), 0, Acl);
2865 return;
2867 ok(res, "InitializeAcl failed with error %d\n", GetLastError());
2869 res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
2870 ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
2872 /* get owner from the token we might be running as a user not admin */
2873 res = OpenProcessToken( GetCurrentProcess(), MAXIMUM_ALLOWED, &token );
2874 ok(res, "OpenProcessToken failed with error %d\n", GetLastError());
2875 if (!res)
2877 HeapFree(GetProcessHeap(), 0, Acl);
2878 return;
2881 res = GetTokenInformation( token, TokenOwner, NULL, 0, &size );
2882 ok(!res, "Expected failure, got %d\n", res);
2883 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2884 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2886 owner = HeapAlloc(GetProcessHeap(), 0, size);
2887 res = GetTokenInformation( token, TokenOwner, owner, size, &size );
2888 ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
2889 AdminSid = owner->Owner;
2890 test_sid_str(AdminSid);
2892 res = GetTokenInformation( token, TokenPrimaryGroup, NULL, 0, &size );
2893 ok(!res, "Expected failure, got %d\n", res);
2894 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2895 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2897 group = HeapAlloc(GetProcessHeap(), 0, size);
2898 res = GetTokenInformation( token, TokenPrimaryGroup, group, size, &size );
2899 ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
2900 UsersSid = group->PrimaryGroup;
2901 test_sid_str(UsersSid);
2903 acc_size = sizeof(account);
2904 dom_size = sizeof(domain);
2905 ret = LookupAccountSidA( NULL, UsersSid, account, &acc_size, domain, &dom_size, &use );
2906 ok(ret, "LookupAccountSid failed with %d\n", ret);
2907 ok(use == SidTypeGroup, "expect SidTypeGroup, got %d\n", use);
2908 if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH)
2909 skip("Non-English locale (test with hardcoded 'None')\n");
2910 else
2911 ok(!strcmp(account, "None"), "expect None, got %s\n", account);
2913 res = GetTokenInformation( token, TokenUser, NULL, 0, &size );
2914 ok(!res, "Expected failure, got %d\n", res);
2915 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
2916 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2918 user = HeapAlloc(GetProcessHeap(), 0, size);
2919 res = GetTokenInformation( token, TokenUser, user, size, &size );
2920 ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
2921 UserSid = user->User.Sid;
2922 test_sid_str(UserSid);
2923 ok(EqualPrefixSid(UsersSid, UserSid), "TokenPrimaryGroup Sid and TokenUser Sid don't match.\n");
2925 CloseHandle( token );
2926 if (!res)
2928 HeapFree(GetProcessHeap(), 0, group);
2929 HeapFree(GetProcessHeap(), 0, owner);
2930 HeapFree(GetProcessHeap(), 0, user);
2931 HeapFree(GetProcessHeap(), 0, Acl);
2932 return;
2935 res = AddAccessDeniedAce(Acl, ACL_REVISION, PROCESS_VM_READ, AdminSid);
2936 ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError());
2937 res = AddAccessAllowedAce(Acl, ACL_REVISION, PROCESS_ALL_ACCESS, AdminSid);
2938 ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
2940 SecurityDescriptor = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
2941 res = InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
2942 ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
2944 event = CreateEventA( NULL, TRUE, TRUE, "test_event" );
2945 ok(event != NULL, "CreateEvent %d\n", GetLastError());
2947 SecurityDescriptor->Revision = 0;
2948 CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_UNKNOWN_REVISION );
2949 SecurityDescriptor->Revision = SECURITY_DESCRIPTOR_REVISION;
2951 CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR );
2952 CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR );
2953 CHECK_SET_SECURITY( event, SACL_SECURITY_INFORMATION, ERROR_ACCESS_DENIED );
2954 CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
2955 /* NULL DACL is valid and means that everyone has access */
2956 SecurityDescriptor->Control |= SE_DACL_PRESENT;
2957 CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
2959 /* Set owner and group and dacl */
2960 res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE);
2961 ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
2962 CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_SUCCESS );
2963 test_owner_equal( event, AdminSid, __LINE__ );
2965 res = SetSecurityDescriptorGroup(SecurityDescriptor, EveryoneSid, FALSE);
2966 ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
2967 CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_SUCCESS );
2968 test_group_equal( event, EveryoneSid, __LINE__ );
2970 res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
2971 ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
2972 CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
2973 /* setting a dacl should not change the owner or group */
2974 test_owner_equal( event, AdminSid, __LINE__ );
2975 test_group_equal( event, EveryoneSid, __LINE__ );
2977 /* Test again with a different SID in case the previous SID also happens to
2978 * be the one that is incorrectly replacing the group. */
2979 res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, FALSE);
2980 ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
2981 CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_SUCCESS );
2982 test_group_equal( event, UsersSid, __LINE__ );
2984 res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
2985 ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
2986 CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
2987 test_group_equal( event, UsersSid, __LINE__ );
2989 sprintf(buffer, "%s security test", myARGV[0]);
2990 memset(&startup, 0, sizeof(startup));
2991 startup.cb = sizeof(startup);
2992 startup.dwFlags = STARTF_USESHOWWINDOW;
2993 startup.wShowWindow = SW_SHOWNORMAL;
2995 psa.nLength = sizeof(psa);
2996 psa.lpSecurityDescriptor = SecurityDescriptor;
2997 psa.bInheritHandle = TRUE;
2999 ThreadSecurityDescriptor = HeapAlloc( GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH );
3000 res = InitializeSecurityDescriptor( ThreadSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
3001 ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
3003 ThreadAcl = HeapAlloc( GetProcessHeap(), 0, 256 );
3004 res = InitializeAcl( ThreadAcl, 256, ACL_REVISION );
3005 ok(res, "InitializeAcl failed with error %d\n", GetLastError());
3006 res = AddAccessDeniedAce( ThreadAcl, ACL_REVISION, THREAD_SET_THREAD_TOKEN, AdminSid );
3007 ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError() );
3008 res = AddAccessAllowedAce( ThreadAcl, ACL_REVISION, THREAD_ALL_ACCESS, AdminSid );
3009 ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
3011 res = SetSecurityDescriptorOwner( ThreadSecurityDescriptor, AdminSid, FALSE );
3012 ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
3013 res = SetSecurityDescriptorGroup( ThreadSecurityDescriptor, UsersSid, FALSE );
3014 ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
3015 res = SetSecurityDescriptorDacl( ThreadSecurityDescriptor, TRUE, ThreadAcl, FALSE );
3016 ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
3018 tsa.nLength = sizeof(tsa);
3019 tsa.lpSecurityDescriptor = ThreadSecurityDescriptor;
3020 tsa.bInheritHandle = TRUE;
3022 /* Doesn't matter what ACL say we should get full access for ourselves */
3023 res = CreateProcessA( NULL, buffer, &psa, &tsa, FALSE, 0, NULL, NULL, &startup, &info );
3024 ok(res, "CreateProcess with err:%d\n", GetLastError());
3025 TEST_GRANTED_ACCESS2( info.hProcess, PROCESS_ALL_ACCESS_NT4,
3026 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
3027 TEST_GRANTED_ACCESS2( info.hThread, THREAD_ALL_ACCESS_NT4,
3028 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
3029 wait_child_process( info.hProcess );
3031 FreeSid(EveryoneSid);
3032 CloseHandle( info.hProcess );
3033 CloseHandle( info.hThread );
3034 CloseHandle( event );
3035 HeapFree(GetProcessHeap(), 0, group);
3036 HeapFree(GetProcessHeap(), 0, owner);
3037 HeapFree(GetProcessHeap(), 0, user);
3038 HeapFree(GetProcessHeap(), 0, Acl);
3039 HeapFree(GetProcessHeap(), 0, SecurityDescriptor);
3040 HeapFree(GetProcessHeap(), 0, ThreadAcl);
3041 HeapFree(GetProcessHeap(), 0, ThreadSecurityDescriptor);
3044 static void test_process_security_child(void)
3046 HANDLE handle, handle1;
3047 BOOL ret;
3048 DWORD err;
3050 handle = OpenProcess( PROCESS_TERMINATE, FALSE, GetCurrentProcessId() );
3051 ok(handle != NULL, "OpenProcess(PROCESS_TERMINATE) with err:%d\n", GetLastError());
3052 TEST_GRANTED_ACCESS( handle, PROCESS_TERMINATE );
3054 ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
3055 &handle1, 0, TRUE, DUPLICATE_SAME_ACCESS );
3056 ok(ret, "duplicating handle err:%d\n", GetLastError());
3057 TEST_GRANTED_ACCESS( handle1, PROCESS_TERMINATE );
3059 CloseHandle( handle1 );
3061 SetLastError( 0xdeadbeef );
3062 ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
3063 &handle1, PROCESS_ALL_ACCESS, TRUE, 0 );
3064 err = GetLastError();
3065 ok(!ret && err == ERROR_ACCESS_DENIED, "duplicating handle should have failed "
3066 "with STATUS_ACCESS_DENIED, instead of err:%d\n", err);
3068 CloseHandle( handle );
3070 /* These two should fail - they are denied by ACL */
3071 handle = OpenProcess( PROCESS_VM_READ, FALSE, GetCurrentProcessId() );
3072 ok(handle == NULL, "OpenProcess(PROCESS_VM_READ) should have failed\n");
3073 handle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId() );
3074 ok(handle == NULL, "OpenProcess(PROCESS_ALL_ACCESS) should have failed\n");
3076 /* Documented privilege elevation */
3077 ret = DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
3078 &handle, 0, TRUE, DUPLICATE_SAME_ACCESS );
3079 ok(ret, "duplicating handle err:%d\n", GetLastError());
3080 TEST_GRANTED_ACCESS2( handle, PROCESS_ALL_ACCESS_NT4,
3081 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
3083 CloseHandle( handle );
3085 /* Same only explicitly asking for all access rights */
3086 ret = DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(),
3087 &handle, PROCESS_ALL_ACCESS, TRUE, 0 );
3088 ok(ret, "duplicating handle err:%d\n", GetLastError());
3089 TEST_GRANTED_ACCESS2( handle, PROCESS_ALL_ACCESS_NT4,
3090 PROCESS_ALL_ACCESS | PROCESS_QUERY_LIMITED_INFORMATION );
3091 ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
3092 &handle1, PROCESS_VM_READ, TRUE, 0 );
3093 ok(ret, "duplicating handle err:%d\n", GetLastError());
3094 TEST_GRANTED_ACCESS( handle1, PROCESS_VM_READ );
3095 CloseHandle( handle1 );
3096 CloseHandle( handle );
3098 /* Test thread security */
3099 handle = OpenThread( THREAD_TERMINATE, FALSE, GetCurrentThreadId() );
3100 ok(handle != NULL, "OpenThread(THREAD_TERMINATE) with err:%d\n", GetLastError());
3101 TEST_GRANTED_ACCESS( handle, PROCESS_TERMINATE );
3102 CloseHandle( handle );
3104 handle = OpenThread( THREAD_SET_THREAD_TOKEN, FALSE, GetCurrentThreadId() );
3105 ok(handle == NULL, "OpenThread(THREAD_SET_THREAD_TOKEN) should have failed\n");
3108 static void test_impersonation_level(void)
3110 HANDLE Token, ProcessToken;
3111 HANDLE Token2;
3112 DWORD Size;
3113 TOKEN_PRIVILEGES *Privileges;
3114 TOKEN_USER *User;
3115 PRIVILEGE_SET *PrivilegeSet;
3116 BOOL AccessGranted;
3117 BOOL ret;
3118 HKEY hkey;
3119 DWORD error;
3121 if( !pDuplicateTokenEx ) {
3122 win_skip("DuplicateTokenEx is not available\n");
3123 return;
3125 SetLastError(0xdeadbeef);
3126 ret = ImpersonateSelf(SecurityAnonymous);
3127 if(!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
3129 win_skip("ImpersonateSelf is not implemented\n");
3130 return;
3132 ok(ret, "ImpersonateSelf(SecurityAnonymous) failed with error %d\n", GetLastError());
3133 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
3134 ok(!ret, "OpenThreadToken should have failed\n");
3135 error = GetLastError();
3136 ok(error == ERROR_CANT_OPEN_ANONYMOUS, "OpenThreadToken on anonymous token should have returned ERROR_CANT_OPEN_ANONYMOUS instead of %d\n", error);
3137 /* can't perform access check when opening object against an anonymous impersonation token */
3138 todo_wine {
3139 error = RegOpenKeyExA(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
3140 ok(error == ERROR_INVALID_HANDLE || error == ERROR_CANT_OPEN_ANONYMOUS || error == ERROR_BAD_IMPERSONATION_LEVEL,
3141 "RegOpenKeyEx failed with %d\n", error);
3143 RevertToSelf();
3145 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &ProcessToken);
3146 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
3148 ret = pDuplicateTokenEx(ProcessToken,
3149 TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE, NULL,
3150 SecurityAnonymous, TokenImpersonation, &Token);
3151 ok(ret, "DuplicateTokenEx failed with error %d\n", GetLastError());
3152 /* can't increase the impersonation level */
3153 ret = DuplicateToken(Token, SecurityIdentification, &Token2);
3154 error = GetLastError();
3155 ok(!ret && error == ERROR_BAD_IMPERSONATION_LEVEL,
3156 "Duplicating a token and increasing the impersonation level should have failed with ERROR_BAD_IMPERSONATION_LEVEL instead of %d\n", error);
3157 /* we can query anything from an anonymous token, including the user */
3158 ret = GetTokenInformation(Token, TokenUser, NULL, 0, &Size);
3159 error = GetLastError();
3160 ok(!ret && error == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenUser) should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", error);
3161 User = HeapAlloc(GetProcessHeap(), 0, Size);
3162 ret = GetTokenInformation(Token, TokenUser, User, Size, &Size);
3163 ok(ret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
3164 HeapFree(GetProcessHeap(), 0, User);
3166 /* PrivilegeCheck fails with SecurityAnonymous level */
3167 ret = GetTokenInformation(Token, TokenPrivileges, NULL, 0, &Size);
3168 error = GetLastError();
3169 ok(!ret && error == ERROR_INSUFFICIENT_BUFFER, "GetTokenInformation(TokenPrivileges) should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", error);
3170 Privileges = HeapAlloc(GetProcessHeap(), 0, Size);
3171 ret = GetTokenInformation(Token, TokenPrivileges, Privileges, Size, &Size);
3172 ok(ret, "GetTokenInformation(TokenPrivileges) failed with error %d\n", GetLastError());
3174 PrivilegeSet = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(PRIVILEGE_SET, Privilege[Privileges->PrivilegeCount]));
3175 PrivilegeSet->PrivilegeCount = Privileges->PrivilegeCount;
3176 memcpy(PrivilegeSet->Privilege, Privileges->Privileges, PrivilegeSet->PrivilegeCount * sizeof(PrivilegeSet->Privilege[0]));
3177 PrivilegeSet->Control = PRIVILEGE_SET_ALL_NECESSARY;
3178 HeapFree(GetProcessHeap(), 0, Privileges);
3180 ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
3181 error = GetLastError();
3182 ok(!ret && error == ERROR_BAD_IMPERSONATION_LEVEL, "PrivilegeCheck for SecurityAnonymous token should have failed with ERROR_BAD_IMPERSONATION_LEVEL instead of %d\n", error);
3184 CloseHandle(Token);
3186 ret = ImpersonateSelf(SecurityIdentification);
3187 ok(ret, "ImpersonateSelf(SecurityIdentification) failed with error %d\n", GetLastError());
3188 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
3189 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
3191 /* can't perform access check when opening object against an identification impersonation token */
3192 error = RegOpenKeyExA(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
3193 todo_wine {
3194 ok(error == ERROR_INVALID_HANDLE || error == ERROR_BAD_IMPERSONATION_LEVEL || error == ERROR_ACCESS_DENIED,
3195 "RegOpenKeyEx should have failed with ERROR_INVALID_HANDLE, ERROR_BAD_IMPERSONATION_LEVEL or ERROR_ACCESS_DENIED instead of %d\n", error);
3197 ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
3198 ok(ret, "PrivilegeCheck for SecurityIdentification failed with error %d\n", GetLastError());
3199 CloseHandle(Token);
3200 RevertToSelf();
3202 ret = ImpersonateSelf(SecurityImpersonation);
3203 ok(ret, "ImpersonateSelf(SecurityImpersonation) failed with error %d\n", GetLastError());
3204 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
3205 ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
3206 error = RegOpenKeyExA(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
3207 ok(error == ERROR_SUCCESS, "RegOpenKeyEx should have succeeded instead of failing with %d\n", error);
3208 RegCloseKey(hkey);
3209 ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
3210 ok(ret, "PrivilegeCheck for SecurityImpersonation failed with error %d\n", GetLastError());
3211 RevertToSelf();
3213 CloseHandle(Token);
3214 CloseHandle(ProcessToken);
3216 HeapFree(GetProcessHeap(), 0, PrivilegeSet);
3219 static void test_SetEntriesInAclW(void)
3221 DWORD res;
3222 PSID EveryoneSid = NULL, UsersSid = NULL;
3223 PACL OldAcl = NULL, NewAcl;
3224 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
3225 SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
3226 EXPLICIT_ACCESSW ExplicitAccess;
3227 static const WCHAR wszEveryone[] = {'E','v','e','r','y','o','n','e',0};
3228 static const WCHAR wszCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'};
3230 if (!pSetEntriesInAclW)
3232 win_skip("SetEntriesInAclW is not available\n");
3233 return;
3236 NewAcl = (PACL)0xdeadbeef;
3237 res = pSetEntriesInAclW(0, NULL, NULL, &NewAcl);
3238 if(res == ERROR_CALL_NOT_IMPLEMENTED)
3240 win_skip("SetEntriesInAclW is not implemented\n");
3241 return;
3243 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
3244 ok(NewAcl == NULL ||
3245 broken(NewAcl != NULL), /* NT4 */
3246 "NewAcl=%p, expected NULL\n", NewAcl);
3247 LocalFree(NewAcl);
3249 OldAcl = HeapAlloc(GetProcessHeap(), 0, 256);
3250 res = InitializeAcl(OldAcl, 256, ACL_REVISION);
3251 if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
3253 win_skip("ACLs not implemented - skipping tests\n");
3254 HeapFree(GetProcessHeap(), 0, OldAcl);
3255 return;
3257 ok(res, "InitializeAcl failed with error %d\n", GetLastError());
3259 res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
3260 ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
3262 res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
3263 DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid);
3264 ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
3266 res = AddAccessAllowedAce(OldAcl, ACL_REVISION, KEY_READ, UsersSid);
3267 ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
3269 ExplicitAccess.grfAccessPermissions = KEY_WRITE;
3270 ExplicitAccess.grfAccessMode = GRANT_ACCESS;
3271 ExplicitAccess.grfInheritance = NO_INHERITANCE;
3272 ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
3273 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
3274 ExplicitAccess.Trustee.ptstrName = EveryoneSid;
3275 ExplicitAccess.Trustee.MultipleTrusteeOperation = 0xDEADBEEF;
3276 ExplicitAccess.Trustee.pMultipleTrustee = (PVOID)0xDEADBEEF;
3277 res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3278 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
3279 ok(NewAcl != NULL, "returned acl was NULL\n");
3280 LocalFree(NewAcl);
3282 ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3283 ExplicitAccess.Trustee.pMultipleTrustee = NULL;
3284 ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3285 res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3286 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
3287 ok(NewAcl != NULL, "returned acl was NULL\n");
3288 LocalFree(NewAcl);
3290 if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH)
3292 skip("Non-English locale (test with hardcoded 'Everyone')\n");
3294 else
3296 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3297 ExplicitAccess.Trustee.ptstrName = (LPWSTR)wszEveryone;
3298 res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3299 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
3300 ok(NewAcl != NULL, "returned acl was NULL\n");
3301 LocalFree(NewAcl);
3303 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_BAD_FORM;
3304 res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3305 ok(res == ERROR_INVALID_PARAMETER ||
3306 broken(res == ERROR_NOT_SUPPORTED), /* NT4 */
3307 "SetEntriesInAclW failed: %u\n", res);
3308 ok(NewAcl == NULL ||
3309 broken(NewAcl != NULL), /* NT4 */
3310 "returned acl wasn't NULL: %p\n", NewAcl);
3312 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3313 ExplicitAccess.Trustee.MultipleTrusteeOperation = TRUSTEE_IS_IMPERSONATE;
3314 res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3315 ok(res == ERROR_INVALID_PARAMETER ||
3316 broken(res == ERROR_NOT_SUPPORTED), /* NT4 */
3317 "SetEntriesInAclW failed: %u\n", res);
3318 ok(NewAcl == NULL ||
3319 broken(NewAcl != NULL), /* NT4 */
3320 "returned acl wasn't NULL: %p\n", NewAcl);
3322 ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3323 ExplicitAccess.grfAccessMode = SET_ACCESS;
3324 res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3325 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
3326 ok(NewAcl != NULL, "returned acl was NULL\n");
3327 LocalFree(NewAcl);
3330 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3331 ExplicitAccess.Trustee.ptstrName = (LPWSTR)wszCurrentUser;
3332 res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3333 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
3334 ok(NewAcl != NULL, "returned acl was NULL\n");
3335 LocalFree(NewAcl);
3337 ExplicitAccess.grfAccessMode = REVOKE_ACCESS;
3338 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
3339 ExplicitAccess.Trustee.ptstrName = UsersSid;
3340 res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
3341 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
3342 ok(NewAcl != NULL, "returned acl was NULL\n");
3343 LocalFree(NewAcl);
3345 FreeSid(UsersSid);
3346 FreeSid(EveryoneSid);
3347 HeapFree(GetProcessHeap(), 0, OldAcl);
3350 static void test_SetEntriesInAclA(void)
3352 DWORD res;
3353 PSID EveryoneSid = NULL, UsersSid = NULL;
3354 PACL OldAcl = NULL, NewAcl;
3355 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
3356 SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
3357 EXPLICIT_ACCESSA ExplicitAccess;
3358 static const CHAR szEveryone[] = {'E','v','e','r','y','o','n','e',0};
3359 static const CHAR szCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'};
3361 NewAcl = (PACL)0xdeadbeef;
3362 res = SetEntriesInAclA(0, NULL, NULL, &NewAcl);
3363 if(res == ERROR_CALL_NOT_IMPLEMENTED)
3365 win_skip("SetEntriesInAclA is not implemented\n");
3366 return;
3368 ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res);
3369 ok(NewAcl == NULL ||
3370 broken(NewAcl != NULL), /* NT4 */
3371 "NewAcl=%p, expected NULL\n", NewAcl);
3372 LocalFree(NewAcl);
3374 OldAcl = HeapAlloc(GetProcessHeap(), 0, 256);
3375 res = InitializeAcl(OldAcl, 256, ACL_REVISION);
3376 if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
3378 win_skip("ACLs not implemented - skipping tests\n");
3379 HeapFree(GetProcessHeap(), 0, OldAcl);
3380 return;
3382 ok(res, "InitializeAcl failed with error %d\n", GetLastError());
3384 res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
3385 ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
3387 res = AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
3388 DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &UsersSid);
3389 ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
3391 res = AddAccessAllowedAce(OldAcl, ACL_REVISION, KEY_READ, UsersSid);
3392 ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
3394 ExplicitAccess.grfAccessPermissions = KEY_WRITE;
3395 ExplicitAccess.grfAccessMode = GRANT_ACCESS;
3396 ExplicitAccess.grfInheritance = NO_INHERITANCE;
3397 ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
3398 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
3399 ExplicitAccess.Trustee.ptstrName = EveryoneSid;
3400 ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3401 ExplicitAccess.Trustee.pMultipleTrustee = NULL;
3402 res = SetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3403 ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res);
3404 ok(NewAcl != NULL, "returned acl was NULL\n");
3405 LocalFree(NewAcl);
3407 ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
3408 ExplicitAccess.Trustee.pMultipleTrustee = NULL;
3409 ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3410 res = SetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3411 ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res);
3412 ok(NewAcl != NULL, "returned acl was NULL\n");
3413 LocalFree(NewAcl);
3415 if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH)
3417 skip("Non-English locale (test with hardcoded 'Everyone')\n");
3419 else
3421 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3422 ExplicitAccess.Trustee.ptstrName = (LPSTR)szEveryone;
3423 res = SetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3424 ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res);
3425 ok(NewAcl != NULL, "returned acl was NULL\n");
3426 LocalFree(NewAcl);
3428 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_BAD_FORM;
3429 res = SetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3430 ok(res == ERROR_INVALID_PARAMETER ||
3431 broken(res == ERROR_NOT_SUPPORTED), /* NT4 */
3432 "SetEntriesInAclA failed: %u\n", res);
3433 ok(NewAcl == NULL ||
3434 broken(NewAcl != NULL), /* NT4 */
3435 "returned acl wasn't NULL: %p\n", NewAcl);
3437 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3438 ExplicitAccess.Trustee.MultipleTrusteeOperation = TRUSTEE_IS_IMPERSONATE;
3439 res = SetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3440 ok(res == ERROR_INVALID_PARAMETER ||
3441 broken(res == ERROR_NOT_SUPPORTED), /* NT4 */
3442 "SetEntriesInAclA failed: %u\n", res);
3443 ok(NewAcl == NULL ||
3444 broken(NewAcl != NULL), /* NT4 */
3445 "returned acl wasn't NULL: %p\n", NewAcl);
3447 ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
3448 ExplicitAccess.grfAccessMode = SET_ACCESS;
3449 res = SetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3450 ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res);
3451 ok(NewAcl != NULL, "returned acl was NULL\n");
3452 LocalFree(NewAcl);
3455 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
3456 ExplicitAccess.Trustee.ptstrName = (LPSTR)szCurrentUser;
3457 res = SetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3458 ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res);
3459 ok(NewAcl != NULL, "returned acl was NULL\n");
3460 LocalFree(NewAcl);
3462 ExplicitAccess.grfAccessMode = REVOKE_ACCESS;
3463 ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
3464 ExplicitAccess.Trustee.ptstrName = UsersSid;
3465 res = SetEntriesInAclA(1, &ExplicitAccess, OldAcl, &NewAcl);
3466 ok(res == ERROR_SUCCESS, "SetEntriesInAclA failed: %u\n", res);
3467 ok(NewAcl != NULL, "returned acl was NULL\n");
3468 LocalFree(NewAcl);
3470 FreeSid(UsersSid);
3471 FreeSid(EveryoneSid);
3472 HeapFree(GetProcessHeap(), 0, OldAcl);
3475 /* helper function for test_CreateDirectoryA */
3476 static void get_nt_pathW(const char *name, UNICODE_STRING *nameW)
3478 UNICODE_STRING strW;
3479 ANSI_STRING str;
3480 NTSTATUS status;
3481 BOOLEAN ret;
3483 pRtlInitAnsiString(&str, name);
3485 status = pRtlAnsiStringToUnicodeString(&strW, &str, TRUE);
3486 ok(!status, "RtlAnsiStringToUnicodeString failed with %08x\n", status);
3488 ret = pRtlDosPathNameToNtPathName_U(strW.Buffer, nameW, NULL, NULL);
3489 ok(ret, "RtlDosPathNameToNtPathName_U failed\n");
3491 pRtlFreeUnicodeString(&strW);
3494 static void test_inherited_dacl(PACL dacl, PSID admin_sid, PSID user_sid, DWORD flags, DWORD mask,
3495 BOOL todo_count, BOOL todo_sid, BOOL todo_flags, int line)
3497 ACL_SIZE_INFORMATION acl_size;
3498 ACCESS_ALLOWED_ACE *ace;
3499 BOOL bret;
3501 bret = GetAclInformation(dacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3502 ok_(__FILE__, line)(bret, "GetAclInformation failed\n");
3504 todo_wine_if (todo_count)
3505 ok_(__FILE__, line)(acl_size.AceCount == 2,
3506 "GetAclInformation returned unexpected entry count (%d != 2)\n",
3507 acl_size.AceCount);
3509 if (acl_size.AceCount > 0)
3511 bret = GetAce(dacl, 0, (VOID **)&ace);
3512 ok_(__FILE__, line)(bret, "Failed to get Current User ACE\n");
3514 bret = EqualSid(&ace->SidStart, user_sid);
3515 todo_wine_if (todo_sid)
3516 ok_(__FILE__, line)(bret, "Current User ACE (%s) != Current User SID (%s)\n", debugstr_sid(&ace->SidStart), debugstr_sid(user_sid));
3518 todo_wine_if (todo_flags)
3519 ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags,
3520 "Current User ACE has unexpected flags (0x%x != 0x%x)\n",
3521 ((ACE_HEADER *)ace)->AceFlags, flags);
3523 ok_(__FILE__, line)(ace->Mask == mask,
3524 "Current User ACE has unexpected mask (0x%x != 0x%x)\n",
3525 ace->Mask, mask);
3527 if (acl_size.AceCount > 1)
3529 bret = GetAce(dacl, 1, (VOID **)&ace);
3530 ok_(__FILE__, line)(bret, "Failed to get Administators Group ACE\n");
3532 bret = EqualSid(&ace->SidStart, admin_sid);
3533 todo_wine_if (todo_sid)
3534 ok_(__FILE__, line)(bret, "Administators Group ACE (%s) != Administators Group SID (%s)\n", debugstr_sid(&ace->SidStart), debugstr_sid(admin_sid));
3536 todo_wine_if (todo_flags)
3537 ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags,
3538 "Administators Group ACE has unexpected flags (0x%x != 0x%x)\n",
3539 ((ACE_HEADER *)ace)->AceFlags, flags);
3541 ok_(__FILE__, line)(ace->Mask == mask,
3542 "Administators Group ACE has unexpected mask (0x%x != 0x%x)\n",
3543 ace->Mask, mask);
3547 static void test_CreateDirectoryA(void)
3549 char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], *user;
3550 DWORD sid_size = sizeof(admin_ptr), user_size;
3551 PSID admin_sid = (PSID) admin_ptr, user_sid;
3552 char sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
3553 PSECURITY_DESCRIPTOR pSD = &sd;
3554 ACL_SIZE_INFORMATION acl_size;
3555 UNICODE_STRING tmpfileW;
3556 SECURITY_ATTRIBUTES sa;
3557 OBJECT_ATTRIBUTES attr;
3558 char tmpfile[MAX_PATH];
3559 char tmpdir[MAX_PATH];
3560 HANDLE token, hTemp;
3561 IO_STATUS_BLOCK io;
3562 struct _SID *owner;
3563 BOOL bret = TRUE;
3564 NTSTATUS status;
3565 DWORD error;
3566 PACL pDacl;
3568 if (!pGetNamedSecurityInfoA)
3570 win_skip("Required functions are not available\n");
3571 return;
3574 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
3576 if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE;
3577 else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE;
3579 if (!bret)
3581 win_skip("Failed to get current user token\n");
3582 return;
3584 bret = GetTokenInformation(token, TokenUser, NULL, 0, &user_size);
3585 ok(!bret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
3586 "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
3587 user = HeapAlloc(GetProcessHeap(), 0, user_size);
3588 bret = GetTokenInformation(token, TokenUser, user, user_size, &user_size);
3589 ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
3590 CloseHandle( token );
3591 user_sid = ((TOKEN_USER *)user)->User.Sid;
3593 sa.nLength = sizeof(sa);
3594 sa.lpSecurityDescriptor = pSD;
3595 sa.bInheritHandle = TRUE;
3596 InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
3597 CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size);
3598 pDacl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
3599 bret = InitializeAcl(pDacl, 100, ACL_REVISION);
3600 ok(bret, "Failed to initialize ACL.\n");
3601 bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
3602 GENERIC_ALL, user_sid);
3603 ok(bret, "Failed to add Current User to ACL.\n");
3604 bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
3605 GENERIC_ALL, admin_sid);
3606 ok(bret, "Failed to add Administrator Group to ACL.\n");
3607 bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
3608 ok(bret, "Failed to add ACL to security descriptor.\n");
3610 GetTempPathA(MAX_PATH, tmpdir);
3611 lstrcatA(tmpdir, "Please Remove Me");
3612 bret = CreateDirectoryA(tmpdir, &sa);
3613 ok(bret == TRUE, "CreateDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
3614 HeapFree(GetProcessHeap(), 0, pDacl);
3616 SetLastError(0xdeadbeef);
3617 error = pGetNamedSecurityInfoA(tmpdir, SE_FILE_OBJECT,
3618 OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, (PSID*)&owner,
3619 NULL, &pDacl, NULL, &pSD);
3620 if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
3622 win_skip("GetNamedSecurityInfoA is not implemented\n");
3623 goto done;
3625 ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
3626 test_inherited_dacl(pDacl, admin_sid, user_sid, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
3627 0x1f01ff, FALSE, TRUE, FALSE, __LINE__);
3628 LocalFree(pSD);
3630 /* Test inheritance of ACLs in CreateFile without security descriptor */
3631 strcpy(tmpfile, tmpdir);
3632 lstrcatA(tmpfile, "/tmpfile");
3634 hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
3635 CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, NULL);
3636 ok(hTemp != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError());
3638 error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
3639 OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3640 (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3641 ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
3642 test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
3643 0x1f01ff, TRUE, TRUE, TRUE, __LINE__);
3644 LocalFree(pSD);
3645 CloseHandle(hTemp);
3647 /* Test inheritance of ACLs in CreateFile with security descriptor -
3648 * When a security descriptor is set, then inheritance doesn't take effect */
3649 pSD = &sd;
3650 InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
3651 pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
3652 bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
3653 ok(bret, "Failed to initialize ACL\n");
3654 bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
3655 ok(bret, "Failed to add ACL to security descriptor\n");
3657 strcpy(tmpfile, tmpdir);
3658 lstrcatA(tmpfile, "/tmpfile");
3660 sa.nLength = sizeof(sa);
3661 sa.lpSecurityDescriptor = pSD;
3662 sa.bInheritHandle = TRUE;
3663 hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, &sa,
3664 CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, NULL);
3665 ok(hTemp != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError());
3666 HeapFree(GetProcessHeap(), 0, pDacl);
3668 error = GetSecurityInfo(hTemp, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3669 (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3670 ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
3671 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3672 ok(bret, "GetAclInformation failed\n");
3673 todo_wine
3674 ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
3675 acl_size.AceCount);
3676 LocalFree(pSD);
3678 error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
3679 OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3680 (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3681 todo_wine
3682 ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
3683 if (error == ERROR_SUCCESS)
3685 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3686 ok(bret, "GetAclInformation failed\n");
3687 todo_wine
3688 ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
3689 acl_size.AceCount);
3690 LocalFree(pSD);
3692 CloseHandle(hTemp);
3694 /* Test inheritance of ACLs in NtCreateFile without security descriptor */
3695 strcpy(tmpfile, tmpdir);
3696 lstrcatA(tmpfile, "/tmpfile");
3697 get_nt_pathW(tmpfile, &tmpfileW);
3699 attr.Length = sizeof(attr);
3700 attr.RootDirectory = 0;
3701 attr.ObjectName = &tmpfileW;
3702 attr.Attributes = OBJ_CASE_INSENSITIVE;
3703 attr.SecurityDescriptor = NULL;
3704 attr.SecurityQualityOfService = NULL;
3706 status = pNtCreateFile(&hTemp, GENERIC_WRITE | DELETE, &attr, &io, NULL, 0,
3707 FILE_SHARE_READ, FILE_CREATE, FILE_DELETE_ON_CLOSE, NULL, 0);
3708 ok(!status, "NtCreateFile failed with %08x\n", status);
3709 pRtlFreeUnicodeString(&tmpfileW);
3711 error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
3712 OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3713 (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3714 ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
3715 test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
3716 0x1f01ff, TRUE, TRUE, TRUE, __LINE__);
3717 LocalFree(pSD);
3718 CloseHandle(hTemp);
3720 /* Test inheritance of ACLs in NtCreateFile with security descriptor -
3721 * When a security descriptor is set, then inheritance doesn't take effect */
3722 pSD = &sd;
3723 InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
3724 pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
3725 bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
3726 ok(bret, "Failed to initialize ACL\n");
3727 bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
3728 ok(bret, "Failed to add ACL to security descriptor\n");
3730 strcpy(tmpfile, tmpdir);
3731 lstrcatA(tmpfile, "/tmpfile");
3732 get_nt_pathW(tmpfile, &tmpfileW);
3734 attr.Length = sizeof(attr);
3735 attr.RootDirectory = 0;
3736 attr.ObjectName = &tmpfileW;
3737 attr.Attributes = OBJ_CASE_INSENSITIVE;
3738 attr.SecurityDescriptor = pSD;
3739 attr.SecurityQualityOfService = NULL;
3741 status = pNtCreateFile(&hTemp, GENERIC_WRITE | DELETE, &attr, &io, NULL, 0,
3742 FILE_SHARE_READ, FILE_CREATE, FILE_DELETE_ON_CLOSE, NULL, 0);
3743 ok(!status, "NtCreateFile failed with %08x\n", status);
3744 pRtlFreeUnicodeString(&tmpfileW);
3745 HeapFree(GetProcessHeap(), 0, pDacl);
3747 error = GetSecurityInfo(hTemp, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3748 (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3749 ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
3750 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3751 ok(bret, "GetAclInformation failed\n");
3752 todo_wine
3753 ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
3754 acl_size.AceCount);
3755 LocalFree(pSD);
3757 error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
3758 OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
3759 (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
3760 todo_wine
3761 ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
3762 if (error == ERROR_SUCCESS)
3764 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3765 ok(bret, "GetAclInformation failed\n");
3766 todo_wine
3767 ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
3768 acl_size.AceCount);
3769 LocalFree(pSD);
3771 CloseHandle(hTemp);
3773 done:
3774 HeapFree(GetProcessHeap(), 0, user);
3775 bret = RemoveDirectoryA(tmpdir);
3776 ok(bret == TRUE, "RemoveDirectoryA should always succeed\n");
3779 static void test_GetNamedSecurityInfoA(void)
3781 char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], *user;
3782 char system_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES];
3783 char users_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES];
3784 SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
3785 PSID admin_sid = (PSID) admin_ptr, users_sid = (PSID) users_ptr;
3786 PSID system_sid = (PSID) system_ptr, user_sid, localsys_sid;
3787 DWORD sid_size = sizeof(admin_ptr), user_size;
3788 char invalid_path[] = "/an invalid file path";
3789 int users_ace_id = -1, admins_ace_id = -1, i;
3790 char software_key[] = "MACHINE\\Software";
3791 char sd[SECURITY_DESCRIPTOR_MIN_LENGTH+sizeof(void*)];
3792 SECURITY_DESCRIPTOR_CONTROL control;
3793 ACL_SIZE_INFORMATION acl_size;
3794 CHAR windows_dir[MAX_PATH];
3795 PSECURITY_DESCRIPTOR pSD;
3796 ACCESS_ALLOWED_ACE *ace;
3797 BOOL bret = TRUE, isNT4;
3798 char tmpfile[MAX_PATH];
3799 DWORD error, revision;
3800 BOOL owner_defaulted;
3801 BOOL group_defaulted;
3802 BOOL dacl_defaulted;
3803 HANDLE token, hTemp, h;
3804 PSID owner, group;
3805 BOOL dacl_present;
3806 PACL pDacl;
3807 BYTE flags;
3808 NTSTATUS status;
3810 if (!pSetNamedSecurityInfoA || !pGetNamedSecurityInfoA)
3812 win_skip("Required functions are not available\n");
3813 return;
3816 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
3818 if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE;
3819 else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE;
3821 if (!bret)
3823 win_skip("Failed to get current user token\n");
3824 return;
3826 bret = GetTokenInformation(token, TokenUser, NULL, 0, &user_size);
3827 ok(!bret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
3828 "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
3829 user = HeapAlloc(GetProcessHeap(), 0, user_size);
3830 bret = GetTokenInformation(token, TokenUser, user, user_size, &user_size);
3831 ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
3832 CloseHandle( token );
3833 user_sid = ((TOKEN_USER *)user)->User.Sid;
3835 bret = GetWindowsDirectoryA(windows_dir, MAX_PATH);
3836 ok(bret, "GetWindowsDirectory failed with error %d\n", GetLastError());
3838 SetLastError(0xdeadbeef);
3839 error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,
3840 OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
3841 NULL, NULL, NULL, NULL, &pSD);
3842 if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
3844 win_skip("GetNamedSecurityInfoA is not implemented\n");
3845 HeapFree(GetProcessHeap(), 0, user);
3846 return;
3848 ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
3850 bret = GetSecurityDescriptorControl(pSD, &control, &revision);
3851 ok(bret, "GetSecurityDescriptorControl failed with error %d\n", GetLastError());
3852 ok((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == (SE_SELF_RELATIVE|SE_DACL_PRESENT) ||
3853 broken((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT), /* NT4 */
3854 "control (0x%x) doesn't have (SE_SELF_RELATIVE|SE_DACL_PRESENT) flags set\n", control);
3855 ok(revision == SECURITY_DESCRIPTOR_REVISION1, "revision was %d instead of 1\n", revision);
3857 isNT4 = (control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT;
3859 bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted);
3860 ok(bret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
3861 ok(owner != NULL, "owner should not be NULL\n");
3863 bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted);
3864 ok(bret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
3865 ok(group != NULL, "group should not be NULL\n");
3866 LocalFree(pSD);
3869 /* NULL descriptor tests */
3870 if(isNT4)
3872 win_skip("NT4 does not support GetNamedSecutityInfo with a NULL descriptor\n");
3873 HeapFree(GetProcessHeap(), 0, user);
3874 return;
3877 error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,
3878 NULL, NULL, NULL, NULL, NULL);
3879 ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error);
3881 pDacl = NULL;
3882 error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,
3883 NULL, NULL, &pDacl, NULL, &pSD);
3884 ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
3885 ok(pDacl != NULL, "DACL should not be NULL\n");
3886 LocalFree(pSD);
3888 error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,OWNER_SECURITY_INFORMATION,
3889 NULL, NULL, &pDacl, NULL, NULL);
3890 ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error);
3892 /* Test behavior of SetNamedSecurityInfo with an invalid path */
3893 SetLastError(0xdeadbeef);
3894 error = pSetNamedSecurityInfoA(invalid_path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL,
3895 NULL, NULL, NULL);
3896 ok(error == ERROR_FILE_NOT_FOUND, "Unexpected error returned: 0x%x\n", error);
3897 ok(GetLastError() == 0xdeadbeef, "Expected last error to remain unchanged.\n");
3899 /* Create security descriptor information and test that it comes back the same */
3900 pSD = &sd;
3901 pDacl = HeapAlloc(GetProcessHeap(), 0, 100);
3902 InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
3903 CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size);
3904 bret = InitializeAcl(pDacl, 100, ACL_REVISION);
3905 ok(bret, "Failed to initialize ACL.\n");
3906 bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
3907 ok(bret, "Failed to add Current User to ACL.\n");
3908 bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, admin_sid);
3909 ok(bret, "Failed to add Administrator Group to ACL.\n");
3910 bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
3911 ok(bret, "Failed to add ACL to security descriptor.\n");
3912 GetTempFileNameA(".", "foo", 0, tmpfile);
3913 hTemp = CreateFileA(tmpfile, WRITE_DAC|GENERIC_WRITE, FILE_SHARE_DELETE|FILE_SHARE_READ,
3914 NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
3915 SetLastError(0xdeadbeef);
3916 error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL,
3917 NULL, pDacl, NULL);
3918 HeapFree(GetProcessHeap(), 0, pDacl);
3919 if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
3921 win_skip("SetNamedSecurityInfoA is not implemented\n");
3922 HeapFree(GetProcessHeap(), 0, user);
3923 CloseHandle(hTemp);
3924 return;
3926 ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error);
3927 SetLastError(0xdeadbeef);
3928 error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
3929 NULL, NULL, &pDacl, NULL, &pSD);
3930 if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
3932 win_skip("GetNamedSecurityInfoA is not implemented\n");
3933 HeapFree(GetProcessHeap(), 0, user);
3934 CloseHandle(hTemp);
3935 return;
3937 ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
3939 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3940 ok(bret, "GetAclInformation failed\n");
3941 if (acl_size.AceCount > 0)
3943 bret = GetAce(pDacl, 0, (VOID **)&ace);
3944 ok(bret, "Failed to get Current User ACE.\n");
3945 bret = EqualSid(&ace->SidStart, user_sid);
3946 todo_wine ok(bret, "Current User ACE (%s) != Current User SID (%s).\n",
3947 debugstr_sid(&ace->SidStart), debugstr_sid(user_sid));
3948 ok(((ACE_HEADER *)ace)->AceFlags == 0,
3949 "Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
3950 ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
3951 ace->Mask);
3953 if (acl_size.AceCount > 1)
3955 bret = GetAce(pDacl, 1, (VOID **)&ace);
3956 ok(bret, "Failed to get Administators Group ACE.\n");
3957 bret = EqualSid(&ace->SidStart, admin_sid);
3958 todo_wine ok(bret || broken(!bret) /* win2k */,
3959 "Administators Group ACE (%s) != Administators Group SID (%s).\n",
3960 debugstr_sid(&ace->SidStart), debugstr_sid(admin_sid));
3961 ok(((ACE_HEADER *)ace)->AceFlags == 0,
3962 "Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
3963 ok(ace->Mask == 0x1f01ff || broken(ace->Mask == GENERIC_ALL) /* win2k */,
3964 "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
3966 LocalFree(pSD);
3968 /* show that setting empty DACL is not removing all file permissions */
3969 pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
3970 bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
3971 ok(bret, "Failed to initialize ACL.\n");
3972 error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
3973 NULL, NULL, pDacl, NULL);
3974 ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error);
3975 HeapFree(GetProcessHeap(), 0, pDacl);
3977 error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
3978 NULL, NULL, &pDacl, NULL, &pSD);
3979 ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
3981 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
3982 ok(bret, "GetAclInformation failed\n");
3983 if (acl_size.AceCount > 0)
3985 bret = GetAce(pDacl, 0, (VOID **)&ace);
3986 ok(bret, "Failed to get ACE.\n");
3987 todo_wine ok(((ACE_HEADER *)ace)->AceFlags & INHERITED_ACE,
3988 "ACE has unexpected flags: 0x%x\n", ((ACE_HEADER *)ace)->AceFlags);
3990 LocalFree(pSD);
3992 h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
3993 NULL, OPEN_EXISTING, 0, NULL);
3994 ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
3995 CloseHandle(h);
3997 /* test setting NULL DACL */
3998 error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
3999 DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL);
4000 ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error);
4002 error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
4003 NULL, NULL, &pDacl, NULL, &pSD);
4004 ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
4005 todo_wine ok(!pDacl, "pDacl != NULL\n");
4006 LocalFree(pSD);
4008 h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4009 NULL, OPEN_EXISTING, 0, NULL);
4010 ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
4011 CloseHandle(h);
4013 /* NtSetSecurityObject doesn't inherit DACL entries */
4014 pSD = sd+sizeof(void*)-((ULONG_PTR)sd)%sizeof(void*);
4015 InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
4016 pDacl = HeapAlloc(GetProcessHeap(), 0, 100);
4017 bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
4018 ok(bret, "Failed to initialize ACL.\n");
4019 bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
4020 ok(bret, "Failed to add ACL to security descriptor.\n");
4021 status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
4022 ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
4024 h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4025 NULL, OPEN_EXISTING, 0, NULL);
4026 ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
4027 CloseHandle(h);
4029 pSetSecurityDescriptorControl(pSD, SE_DACL_AUTO_INHERIT_REQ, SE_DACL_AUTO_INHERIT_REQ);
4030 status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
4031 ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
4033 h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4034 NULL, OPEN_EXISTING, 0, NULL);
4035 ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
4036 CloseHandle(h);
4038 pSetSecurityDescriptorControl(pSD, SE_DACL_AUTO_INHERIT_REQ|SE_DACL_AUTO_INHERITED,
4039 SE_DACL_AUTO_INHERIT_REQ|SE_DACL_AUTO_INHERITED);
4040 status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
4041 ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
4043 h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4044 NULL, OPEN_EXISTING, 0, NULL);
4045 ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
4046 CloseHandle(h);
4048 /* test if DACL is properly mapped to permission */
4049 bret = InitializeAcl(pDacl, 100, ACL_REVISION);
4050 ok(bret, "Failed to initialize ACL.\n");
4051 bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
4052 ok(bret, "Failed to add Current User to ACL.\n");
4053 bret = pAddAccessDeniedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
4054 ok(bret, "Failed to add Current User to ACL.\n");
4055 bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
4056 ok(bret, "Failed to add ACL to security descriptor.\n");
4057 status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
4058 ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
4060 h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4061 NULL, OPEN_EXISTING, 0, NULL);
4062 ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
4063 CloseHandle(h);
4065 bret = InitializeAcl(pDacl, 100, ACL_REVISION);
4066 ok(bret, "Failed to initialize ACL.\n");
4067 bret = pAddAccessDeniedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
4068 ok(bret, "Failed to add Current User to ACL.\n");
4069 bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
4070 ok(bret, "Failed to add Current User to ACL.\n");
4071 bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
4072 ok(bret, "Failed to add ACL to security descriptor.\n");
4073 status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
4074 ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
4076 h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
4077 NULL, OPEN_EXISTING, 0, NULL);
4078 ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
4079 HeapFree(GetProcessHeap(), 0, pDacl);
4080 HeapFree(GetProcessHeap(), 0, user);
4081 CloseHandle(hTemp);
4083 /* Test querying the ownership of a built-in registry key */
4084 sid_size = sizeof(system_ptr);
4085 CreateWellKnownSid(WinLocalSystemSid, NULL, system_sid, &sid_size);
4086 error = pGetNamedSecurityInfoA(software_key, SE_REGISTRY_KEY,
4087 OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION,
4088 NULL, NULL, NULL, NULL, &pSD);
4089 ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
4091 bret = AllocateAndInitializeSid(&SIDAuthNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &localsys_sid);
4092 ok(bret, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
4094 bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted);
4095 ok(bret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
4096 ok(owner != NULL, "owner should not be NULL\n");
4097 ok(EqualSid(owner, admin_sid) || EqualSid(owner, localsys_sid),
4098 "MACHINE\\Software owner SID (%s) != Administrators SID (%s) or Local System Sid (%s).\n",
4099 debugstr_sid(owner), debugstr_sid(admin_sid), debugstr_sid(localsys_sid));
4101 bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted);
4102 ok(bret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
4103 ok(group != NULL, "group should not be NULL\n");
4104 ok(EqualSid(group, admin_sid) || broken(EqualSid(group, system_sid)) /* before Win7 */
4105 || broken(((SID*)group)->SubAuthority[0] == SECURITY_NT_NON_UNIQUE) /* Vista */,
4106 "MACHINE\\Software group SID (%s) != Local System SID (%s or %s)\n",
4107 debugstr_sid(group), debugstr_sid(admin_sid), debugstr_sid(system_sid));
4108 LocalFree(pSD);
4110 /* Test querying the DACL of a built-in registry key */
4111 sid_size = sizeof(users_ptr);
4112 CreateWellKnownSid(WinBuiltinUsersSid, NULL, users_sid, &sid_size);
4113 error = pGetNamedSecurityInfoA(software_key, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION,
4114 NULL, NULL, NULL, NULL, &pSD);
4115 ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
4117 bret = GetSecurityDescriptorDacl(pSD, &dacl_present, &pDacl, &dacl_defaulted);
4118 ok(bret, "GetSecurityDescriptorDacl failed with error %d\n", GetLastError());
4119 ok(dacl_present, "DACL should be present\n");
4120 ok(pDacl && IsValidAcl(pDacl), "GetSecurityDescriptorDacl returned invalid DACL.\n");
4121 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
4122 ok(bret, "GetAclInformation failed\n");
4123 ok(acl_size.AceCount != 0, "GetAclInformation returned no ACLs\n");
4124 for (i=0; i<acl_size.AceCount; i++)
4126 bret = GetAce(pDacl, i, (VOID **)&ace);
4127 ok(bret, "Failed to get ACE %d.\n", i);
4128 bret = EqualSid(&ace->SidStart, users_sid);
4129 if (bret) users_ace_id = i;
4130 bret = EqualSid(&ace->SidStart, admin_sid);
4131 if (bret) admins_ace_id = i;
4133 ok(users_ace_id != -1 || broken(users_ace_id == -1) /* win2k */,
4134 "Builtin Users ACE not found.\n");
4135 if (users_ace_id != -1)
4137 bret = GetAce(pDacl, users_ace_id, (VOID **)&ace);
4138 ok(bret, "Failed to get Builtin Users ACE.\n");
4139 flags = ((ACE_HEADER *)ace)->AceFlags;
4140 ok(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE)
4141 || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* w2k8 */
4142 || broken(flags == (CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* win 10 wow64 */
4143 || broken(flags == CONTAINER_INHERIT_ACE), /* win 10 */
4144 "Builtin Users ACE has unexpected flags (0x%x != 0x%x)\n", flags,
4145 INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE);
4146 ok(ace->Mask == GENERIC_READ
4147 || broken(ace->Mask == KEY_READ), /* win 10 */
4148 "Builtin Users ACE has unexpected mask (0x%x != 0x%x)\n",
4149 ace->Mask, GENERIC_READ);
4151 ok(admins_ace_id != -1, "Builtin Admins ACE not found.\n");
4152 if (admins_ace_id != -1)
4154 bret = GetAce(pDacl, admins_ace_id, (VOID **)&ace);
4155 ok(bret, "Failed to get Builtin Admins ACE.\n");
4156 flags = ((ACE_HEADER *)ace)->AceFlags;
4157 ok(flags == 0x0
4158 || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* w2k8 */
4159 || broken(flags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)) /* win7 */
4160 || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE)) /* win8+ */
4161 || broken(flags == (CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* win 10 wow64 */
4162 || broken(flags == CONTAINER_INHERIT_ACE), /* win 10 */
4163 "Builtin Admins ACE has unexpected flags (0x%x != 0x0)\n", flags);
4164 ok(ace->Mask == KEY_ALL_ACCESS || broken(ace->Mask == GENERIC_ALL) /* w2k8 */,
4165 "Builtin Admins ACE has unexpected mask (0x%x != 0x%x)\n", ace->Mask, KEY_ALL_ACCESS);
4168 FreeSid(localsys_sid);
4169 LocalFree(pSD);
4172 static void test_ConvertStringSecurityDescriptor(void)
4174 BOOL ret;
4175 PSECURITY_DESCRIPTOR pSD;
4176 static const WCHAR Blank[] = { 0 };
4177 unsigned int i;
4178 ULONG size;
4179 ACL *acl;
4180 static const struct
4182 const char *sidstring;
4183 DWORD revision;
4184 BOOL ret;
4185 DWORD GLE;
4186 DWORD altGLE;
4187 } cssd[] =
4189 { "D:(A;;GA;;;WD)", 0xdeadbeef, FALSE, ERROR_UNKNOWN_REVISION },
4190 /* test ACE string type */
4191 { "D:(A;;GA;;;WD)", SDDL_REVISION_1, TRUE },
4192 { "D:(D;;GA;;;WD)", SDDL_REVISION_1, TRUE },
4193 { "ERROR:(D;;GA;;;WD)", SDDL_REVISION_1, FALSE, ERROR_INVALID_PARAMETER },
4194 /* test ACE string with spaces */
4195 { " D:(D;;GA;;;WD)", SDDL_REVISION_1, TRUE },
4196 { "D: (D;;GA;;;WD)", SDDL_REVISION_1, TRUE },
4197 { "D:( D;;GA;;;WD)", SDDL_REVISION_1, TRUE },
4198 { "D:(D ;;GA;;;WD)", SDDL_REVISION_1, FALSE, RPC_S_INVALID_STRING_UUID, ERROR_INVALID_ACL }, /* Vista+ */
4199 { "D:(D; ;GA;;;WD)", SDDL_REVISION_1, TRUE },
4200 { "D:(D;; GA;;;WD)", SDDL_REVISION_1, TRUE },
4201 { "D:(D;;GA ;;;WD)", SDDL_REVISION_1, FALSE, ERROR_INVALID_ACL },
4202 { "D:(D;;GA; ;;WD)", SDDL_REVISION_1, TRUE },
4203 { "D:(D;;GA;; ;WD)", SDDL_REVISION_1, TRUE },
4204 { "D:(D;;GA;;; WD)", SDDL_REVISION_1, TRUE },
4205 { "D:(D;;GA;;;WD )", SDDL_REVISION_1, TRUE },
4206 /* test ACE string access rights */
4207 { "D:(A;;GA;;;WD)", SDDL_REVISION_1, TRUE },
4208 { "D:(A;;GRGWGX;;;WD)", SDDL_REVISION_1, TRUE },
4209 { "D:(A;;RCSDWDWO;;;WD)", SDDL_REVISION_1, TRUE },
4210 { "D:(A;;RPWPCCDCLCSWLODTCR;;;WD)", SDDL_REVISION_1, TRUE },
4211 { "D:(A;;FAFRFWFX;;;WD)", SDDL_REVISION_1, TRUE },
4212 { "D:(A;;KAKRKWKX;;;WD)", SDDL_REVISION_1, TRUE },
4213 { "D:(A;;0xFFFFFFFF;;;WD)", SDDL_REVISION_1, TRUE },
4214 { "S:(AU;;0xFFFFFFFF;;;WD)", SDDL_REVISION_1, TRUE },
4215 /* test ACE string access right error case */
4216 { "D:(A;;ROB;;;WD)", SDDL_REVISION_1, FALSE, ERROR_INVALID_ACL },
4217 /* test behaviour with empty strings */
4218 { "", SDDL_REVISION_1, TRUE },
4219 /* test ACE string SID */
4220 { "D:(D;;GA;;;S-1-0-0)", SDDL_REVISION_1, TRUE },
4221 { "D:(D;;GA;;;Nonexistent account)", SDDL_REVISION_1, FALSE, ERROR_INVALID_ACL, ERROR_INVALID_SID } /* W2K */
4224 for (i = 0; i < ARRAY_SIZE(cssd); i++)
4226 DWORD GLE;
4228 SetLastError(0xdeadbeef);
4229 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA(
4230 cssd[i].sidstring, cssd[i].revision, &pSD, NULL);
4231 GLE = GetLastError();
4232 ok(ret == cssd[i].ret, "(%02u) Expected %s (%d)\n", i, cssd[i].ret ? "success" : "failure", GLE);
4233 if (!cssd[i].ret)
4234 ok(GLE == cssd[i].GLE ||
4235 (cssd[i].altGLE && GLE == cssd[i].altGLE),
4236 "(%02u) Unexpected last error %d\n", i, GLE);
4237 if (ret)
4238 LocalFree(pSD);
4241 /* test behaviour with NULL parameters */
4242 SetLastError(0xdeadbeef);
4243 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA(
4244 NULL, 0xdeadbeef, &pSD, NULL);
4245 todo_wine
4246 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4247 "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
4248 GetLastError());
4250 SetLastError(0xdeadbeef);
4251 ret = pConvertStringSecurityDescriptorToSecurityDescriptorW(
4252 NULL, 0xdeadbeef, &pSD, NULL);
4253 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4254 "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
4255 GetLastError());
4257 SetLastError(0xdeadbeef);
4258 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA(
4259 "D:(A;;ROB;;;WD)", 0xdeadbeef, NULL, NULL);
4260 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4261 "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
4262 GetLastError());
4264 SetLastError(0xdeadbeef);
4265 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA(
4266 "D:(A;;ROB;;;WD)", SDDL_REVISION_1, NULL, NULL);
4267 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4268 "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n",
4269 GetLastError());
4271 /* test behaviour with empty strings */
4272 SetLastError(0xdeadbeef);
4273 ret = pConvertStringSecurityDescriptorToSecurityDescriptorW(
4274 Blank, SDDL_REVISION_1, &pSD, NULL);
4275 ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
4276 LocalFree(pSD);
4278 SetLastError(0xdeadbeef);
4279 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA(
4280 "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);
4281 ok(ret || broken(!ret && GetLastError() == ERROR_INVALID_DATATYPE) /* win2k */,
4282 "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %u\n", GetLastError());
4283 if (ret) LocalFree(pSD);
4285 /* empty DACL */
4286 size = 0;
4287 SetLastError(0xdeadbeef);
4288 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA("D:", SDDL_REVISION_1, &pSD, &size);
4289 ok(ret, "unexpected error %u\n", GetLastError());
4290 ok(size == sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sizeof(ACL), "got %u\n", size);
4291 acl = (ACL *)((char *)pSD + sizeof(SECURITY_DESCRIPTOR_RELATIVE));
4292 ok(acl->AclRevision == ACL_REVISION, "got %u\n", acl->AclRevision);
4293 ok(!acl->Sbz1, "got %u\n", acl->Sbz1);
4294 ok(acl->AclSize == sizeof(*acl), "got %u\n", acl->AclSize);
4295 ok(!acl->AceCount, "got %u\n", acl->AceCount);
4296 ok(!acl->Sbz2, "got %u\n", acl->Sbz2);
4297 LocalFree(pSD);
4299 /* empty SACL */
4300 size = 0;
4301 SetLastError(0xdeadbeef);
4302 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA("S:", SDDL_REVISION_1, &pSD, &size);
4303 ok(ret, "unexpected error %u\n", GetLastError());
4304 ok(size == sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sizeof(ACL), "got %u\n", size);
4305 acl = (ACL *)((char *)pSD + sizeof(SECURITY_DESCRIPTOR_RELATIVE));
4306 ok(!acl->Sbz1, "got %u\n", acl->Sbz1);
4307 ok(acl->AclSize == sizeof(*acl), "got %u\n", acl->AclSize);
4308 ok(!acl->AceCount, "got %u\n", acl->AceCount);
4309 ok(!acl->Sbz2, "got %u\n", acl->Sbz2);
4310 LocalFree(pSD);
4313 static void test_ConvertSecurityDescriptorToString(void)
4315 SECURITY_DESCRIPTOR desc;
4316 SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION;
4317 LPSTR string;
4318 DWORD size;
4319 PSID psid, psid2;
4320 PACL pacl;
4321 char sid_buf[256];
4322 char acl_buf[8192];
4323 ULONG len;
4325 if (!pConvertSecurityDescriptorToStringSecurityDescriptorA)
4327 win_skip("ConvertSecurityDescriptorToStringSecurityDescriptor is not available\n");
4328 return;
4331 /* It seems Windows XP adds an extra character to the length of the string for each ACE in an ACL. We
4332 * don't replicate this feature so we only test len >= strlen+1. */
4333 #define CHECK_RESULT_AND_FREE(exp_str) \
4334 ok(strcmp(string, (exp_str)) == 0, "String mismatch (expected \"%s\", got \"%s\")\n", (exp_str), string); \
4335 ok(len >= (strlen(exp_str) + 1), "Length mismatch (expected %d, got %d)\n", lstrlenA(exp_str) + 1, len); \
4336 LocalFree(string);
4338 #define CHECK_ONE_OF_AND_FREE(exp_str1, exp_str2) \
4339 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); \
4340 ok(len >= (strlen(exp_str1) + 1) || len >= (strlen(exp_str2) + 1), "Length mismatch (expected %d or %d, got %d)\n", lstrlenA(exp_str1) + 1, lstrlenA(exp_str2) + 1, len); \
4341 LocalFree(string);
4343 InitializeSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION);
4344 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4345 CHECK_RESULT_AND_FREE("");
4347 size = 4096;
4348 CreateWellKnownSid(WinLocalSid, NULL, sid_buf, &size);
4349 SetSecurityDescriptorOwner(&desc, sid_buf, FALSE);
4350 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4351 CHECK_RESULT_AND_FREE("O:S-1-2-0");
4353 SetSecurityDescriptorOwner(&desc, sid_buf, TRUE);
4354 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4355 CHECK_RESULT_AND_FREE("O:S-1-2-0");
4357 size = sizeof(sid_buf);
4358 CreateWellKnownSid(WinLocalSystemSid, NULL, sid_buf, &size);
4359 SetSecurityDescriptorOwner(&desc, sid_buf, TRUE);
4360 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4361 CHECK_RESULT_AND_FREE("O:SY");
4363 ConvertStringSidToSidA("S-1-5-21-93476-23408-4576", &psid);
4364 SetSecurityDescriptorGroup(&desc, psid, TRUE);
4365 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4366 CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576");
4368 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, GROUP_SECURITY_INFORMATION, &string, &len), "Conversion failed\n");
4369 CHECK_RESULT_AND_FREE("G:S-1-5-21-93476-23408-4576");
4371 pacl = (PACL)acl_buf;
4372 InitializeAcl(pacl, sizeof(acl_buf), ACL_REVISION);
4373 SetSecurityDescriptorDacl(&desc, TRUE, pacl, TRUE);
4374 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4375 CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:");
4377 SetSecurityDescriptorDacl(&desc, TRUE, pacl, FALSE);
4378 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4379 CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:");
4381 ConvertStringSidToSidA("S-1-5-6", &psid2);
4382 pAddAccessAllowedAceEx(pacl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, 0xf0000000, psid2);
4383 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4384 CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)");
4386 pAddAccessAllowedAceEx(pacl, ACL_REVISION, INHERIT_ONLY_ACE|INHERITED_ACE, 0x00000003, psid2);
4387 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4388 CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)");
4390 pAddAccessDeniedAceEx(pacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE, 0xffffffff, psid);
4391 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4392 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)");
4395 pacl = (PACL)acl_buf;
4396 InitializeAcl(pacl, sizeof(acl_buf), ACL_REVISION);
4397 SetSecurityDescriptorSacl(&desc, TRUE, pacl, FALSE);
4398 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4399 CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:");
4401 /* fails in win2k */
4402 SetSecurityDescriptorDacl(&desc, TRUE, NULL, FALSE);
4403 pAddAuditAccessAceEx(pacl, ACL_REVISION, VALID_INHERIT_FLAGS, KEY_READ|KEY_WRITE, psid2, TRUE, TRUE);
4404 if (pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len))
4406 CHECK_ONE_OF_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)", /* XP */
4407 "O:SYG:S-1-5-21-93476-23408-4576D:NO_ACCESS_CONTROLS:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)" /* Vista */);
4410 /* fails in win2k */
4411 pAddAuditAccessAceEx(pacl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, FILE_GENERIC_READ|FILE_GENERIC_WRITE, psid2, TRUE, FALSE);
4412 if (pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len))
4414 CHECK_ONE_OF_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)", /* XP */
4415 "O:SYG:S-1-5-21-93476-23408-4576D:NO_ACCESS_CONTROLS:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)" /* Vista */);
4418 LocalFree(psid2);
4419 LocalFree(psid);
4422 static void test_SetSecurityDescriptorControl (PSECURITY_DESCRIPTOR sec)
4424 SECURITY_DESCRIPTOR_CONTROL ref;
4425 SECURITY_DESCRIPTOR_CONTROL test;
4427 SECURITY_DESCRIPTOR_CONTROL const mutable
4428 = SE_DACL_AUTO_INHERIT_REQ | SE_SACL_AUTO_INHERIT_REQ
4429 | SE_DACL_AUTO_INHERITED | SE_SACL_AUTO_INHERITED
4430 | SE_DACL_PROTECTED | SE_SACL_PROTECTED
4431 | 0x00000040 | 0x00000080 /* not defined in winnt.h */
4433 SECURITY_DESCRIPTOR_CONTROL const immutable
4434 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
4435 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
4436 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
4437 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
4440 int bit;
4441 DWORD dwRevision;
4442 LPCSTR fmt = "Expected error %s, got %u\n";
4444 GetSecurityDescriptorControl (sec, &ref, &dwRevision);
4446 /* The mutable bits are mutable regardless of the truth of
4447 SE_DACL_PRESENT and/or SE_SACL_PRESENT */
4449 /* Check call barfs if any bit-of-interest is immutable */
4450 for (bit = 0; bit < 16; ++bit)
4452 SECURITY_DESCRIPTOR_CONTROL const bitOfInterest = 1 << bit;
4453 SECURITY_DESCRIPTOR_CONTROL setOrClear = ref & bitOfInterest;
4455 SECURITY_DESCRIPTOR_CONTROL ctrl;
4457 DWORD dwExpect = (bitOfInterest & immutable)
4458 ? ERROR_INVALID_PARAMETER : 0xbebecaca;
4459 LPCSTR strExpect = (bitOfInterest & immutable)
4460 ? "ERROR_INVALID_PARAMETER" : "0xbebecaca";
4462 ctrl = (bitOfInterest & mutable) ? ref + bitOfInterest : ref;
4463 setOrClear ^= bitOfInterest;
4464 SetLastError (0xbebecaca);
4465 pSetSecurityDescriptorControl (sec, bitOfInterest, setOrClear);
4466 ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ());
4467 GetSecurityDescriptorControl(sec, &test, &dwRevision);
4468 expect_eq(test, ctrl, int, "%x");
4470 setOrClear ^= bitOfInterest;
4471 SetLastError (0xbebecaca);
4472 pSetSecurityDescriptorControl (sec, bitOfInterest, setOrClear);
4473 ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ());
4474 GetSecurityDescriptorControl (sec, &test, &dwRevision);
4475 expect_eq(test, ref, int, "%x");
4478 /* Check call barfs if any bit-to-set is immutable
4479 even when not a bit-of-interest */
4480 for (bit = 0; bit < 16; ++bit)
4482 SECURITY_DESCRIPTOR_CONTROL const bitsOfInterest = mutable;
4483 SECURITY_DESCRIPTOR_CONTROL setOrClear = ref & bitsOfInterest;
4485 SECURITY_DESCRIPTOR_CONTROL ctrl;
4487 DWORD dwExpect = ((1 << bit) & immutable)
4488 ? ERROR_INVALID_PARAMETER : 0xbebecaca;
4489 LPCSTR strExpect = ((1 << bit) & immutable)
4490 ? "ERROR_INVALID_PARAMETER" : "0xbebecaca";
4492 ctrl = ((1 << bit) & immutable) ? test : ref | mutable;
4493 setOrClear ^= bitsOfInterest;
4494 SetLastError (0xbebecaca);
4495 pSetSecurityDescriptorControl (sec, bitsOfInterest, setOrClear | (1 << bit));
4496 ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ());
4497 GetSecurityDescriptorControl(sec, &test, &dwRevision);
4498 expect_eq(test, ctrl, int, "%x");
4500 ctrl = ((1 << bit) & immutable) ? test : ref | (1 << bit);
4501 setOrClear ^= bitsOfInterest;
4502 SetLastError (0xbebecaca);
4503 pSetSecurityDescriptorControl (sec, bitsOfInterest, setOrClear | (1 << bit));
4504 ok (GetLastError () == dwExpect, fmt, strExpect, GetLastError ());
4505 GetSecurityDescriptorControl(sec, &test, &dwRevision);
4506 expect_eq(test, ctrl, int, "%x");
4510 static void test_PrivateObjectSecurity(void)
4512 SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION;
4513 SECURITY_DESCRIPTOR_CONTROL ctrl;
4514 PSECURITY_DESCRIPTOR sec;
4515 DWORD dwDescSize;
4516 DWORD dwRevision;
4517 DWORD retSize;
4518 LPSTR string;
4519 ULONG len;
4520 PSECURITY_DESCRIPTOR buf;
4521 BOOL ret;
4523 ok(ConvertStringSecurityDescriptorToSecurityDescriptorA(
4524 "O:SY"
4525 "G:S-1-5-21-93476-23408-4576"
4526 "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)"
4527 "(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
4528 "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)",
4529 SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n");
4531 test_SetSecurityDescriptorControl(sec);
4533 LocalFree(sec);
4535 ok(ConvertStringSecurityDescriptorToSecurityDescriptorA(
4536 "O:SY"
4537 "G:S-1-5-21-93476-23408-4576",
4538 SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n");
4540 test_SetSecurityDescriptorControl(sec);
4542 LocalFree(sec);
4544 ok(ConvertStringSecurityDescriptorToSecurityDescriptorA(
4545 "O:SY"
4546 "G:S-1-5-21-93476-23408-4576"
4547 "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
4548 "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)", SDDL_REVISION_1, &sec, &dwDescSize), "Creating descriptor failed\n");
4549 buf = HeapAlloc(GetProcessHeap(), 0, dwDescSize);
4550 pSetSecurityDescriptorControl(sec, SE_DACL_PROTECTED, SE_DACL_PROTECTED);
4551 GetSecurityDescriptorControl(sec, &ctrl, &dwRevision);
4552 expect_eq(ctrl, 0x9014, int, "%x");
4554 ret = GetPrivateObjectSecurity(sec, GROUP_SECURITY_INFORMATION, buf, dwDescSize, &retSize);
4555 ok(ret, "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError());
4556 ok(retSize <= dwDescSize, "Buffer too small (%d vs %d)\n", retSize, dwDescSize);
4557 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4558 CHECK_RESULT_AND_FREE("G:S-1-5-21-93476-23408-4576");
4559 GetSecurityDescriptorControl(buf, &ctrl, &dwRevision);
4560 expect_eq(ctrl, 0x8000, int, "%x");
4562 ret = GetPrivateObjectSecurity(sec, GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, buf, dwDescSize, &retSize);
4563 ok(ret, "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError());
4564 ok(retSize <= dwDescSize, "Buffer too small (%d vs %d)\n", retSize, dwDescSize);
4565 ret = pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len);
4566 ok(ret, "Conversion failed err=%u\n", GetLastError());
4567 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)",
4568 "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 */
4569 GetSecurityDescriptorControl(buf, &ctrl, &dwRevision);
4570 expect_eq(ctrl & (~ SE_DACL_PROTECTED), 0x8004, int, "%x");
4572 ret = GetPrivateObjectSecurity(sec, sec_info, buf, dwDescSize, &retSize);
4573 ok(ret, "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError());
4574 ok(retSize == dwDescSize, "Buffer too small (%d vs %d)\n", retSize, dwDescSize);
4575 ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
4576 CHECK_ONE_OF_AND_FREE("O:SY"
4577 "G:S-1-5-21-93476-23408-4576"
4578 "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
4579 "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)",
4580 "O:SY"
4581 "G:S-1-5-21-93476-23408-4576"
4582 "D:P(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
4583 "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)"); /* Win7 */
4584 GetSecurityDescriptorControl(buf, &ctrl, &dwRevision);
4585 expect_eq(ctrl & (~ SE_DACL_PROTECTED), 0x8014, int, "%x");
4587 SetLastError(0xdeadbeef);
4588 ok(GetPrivateObjectSecurity(sec, sec_info, buf, 5, &retSize) == FALSE, "GetPrivateObjectSecurity should have failed\n");
4589 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected error ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
4591 LocalFree(sec);
4592 HeapFree(GetProcessHeap(), 0, buf);
4594 #undef CHECK_RESULT_AND_FREE
4595 #undef CHECK_ONE_OF_AND_FREE
4597 static void test_InitializeAcl(void)
4599 char buffer[256];
4600 PACL pAcl = (PACL)buffer;
4601 BOOL ret;
4603 SetLastError(0xdeadbeef);
4604 ret = InitializeAcl(pAcl, sizeof(ACL) - 1, ACL_REVISION);
4605 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
4607 win_skip("InitializeAcl is not implemented\n");
4608 return;
4611 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InitializeAcl with too small a buffer should have failed with ERROR_INSUFFICIENT_BUFFER instead of %d\n", GetLastError());
4613 SetLastError(0xdeadbeef);
4614 ret = InitializeAcl(pAcl, 0xffffffff, ACL_REVISION);
4615 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl with too large a buffer should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
4617 SetLastError(0xdeadbeef);
4618 ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION1);
4619 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl(ACL_REVISION1) should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
4621 ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION2);
4622 ok(ret, "InitializeAcl(ACL_REVISION2) failed with error %d\n", GetLastError());
4624 ret = IsValidAcl(pAcl);
4625 ok(ret, "IsValidAcl failed with error %d\n", GetLastError());
4627 ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION3);
4628 ok(ret, "InitializeAcl(ACL_REVISION3) failed with error %d\n", GetLastError());
4630 ret = IsValidAcl(pAcl);
4631 ok(ret, "IsValidAcl failed with error %d\n", GetLastError());
4633 SetLastError(0xdeadbeef);
4634 ret = InitializeAcl(pAcl, sizeof(buffer), ACL_REVISION4);
4635 if (GetLastError() != ERROR_INVALID_PARAMETER)
4637 ok(ret, "InitializeAcl(ACL_REVISION4) failed with error %d\n", GetLastError());
4639 ret = IsValidAcl(pAcl);
4640 ok(ret, "IsValidAcl failed with error %d\n", GetLastError());
4642 else
4643 win_skip("ACL_REVISION4 is not implemented on NT4\n");
4645 SetLastError(0xdeadbeef);
4646 ret = InitializeAcl(pAcl, sizeof(buffer), -1);
4647 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "InitializeAcl(-1) failed with error %d\n", GetLastError());
4650 static void test_GetSecurityInfo(void)
4652 char domain_users_ptr[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
4653 char b[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
4654 char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], dacl[100];
4655 PSID domain_users_sid = (PSID) domain_users_ptr, domain_sid;
4656 SID_IDENTIFIER_AUTHORITY sia = { SECURITY_NT_AUTHORITY };
4657 int domain_users_ace_id = -1, admins_ace_id = -1, i;
4658 DWORD sid_size = sizeof(admin_ptr), l = sizeof(b);
4659 PSID admin_sid = (PSID) admin_ptr, user_sid;
4660 char sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
4661 BOOL owner_defaulted, group_defaulted;
4662 BOOL dacl_defaulted, dacl_present;
4663 ACL_SIZE_INFORMATION acl_size;
4664 PSECURITY_DESCRIPTOR pSD;
4665 ACCESS_ALLOWED_ACE *ace;
4666 HANDLE token, obj;
4667 PSID owner, group;
4668 BOOL bret = TRUE;
4669 PACL pDacl;
4670 BYTE flags;
4671 DWORD ret;
4673 if (!pSetSecurityInfo)
4675 win_skip("[Get|Set]SecurityInfo is not available\n");
4676 return;
4679 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
4681 if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE;
4682 else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE;
4684 if (!bret)
4686 win_skip("Failed to get current user token\n");
4687 return;
4689 bret = GetTokenInformation(token, TokenUser, b, l, &l);
4690 ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
4691 CloseHandle( token );
4692 user_sid = ((TOKEN_USER *)b)->User.Sid;
4694 /* Create something. Files have lots of associated security info. */
4695 obj = CreateFileA(myARGV[0], GENERIC_READ|WRITE_DAC, FILE_SHARE_READ, NULL,
4696 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
4697 if (obj == INVALID_HANDLE_VALUE)
4699 skip("Couldn't create an object for GetSecurityInfo test\n");
4700 return;
4703 ret = GetSecurityInfo(obj, SE_FILE_OBJECT,
4704 OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
4705 &owner, &group, &pDacl, NULL, &pSD);
4706 if (ret == ERROR_CALL_NOT_IMPLEMENTED)
4708 win_skip("GetSecurityInfo is not implemented\n");
4709 CloseHandle(obj);
4710 return;
4712 ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret);
4713 ok(pSD != NULL, "GetSecurityInfo\n");
4714 ok(owner != NULL, "GetSecurityInfo\n");
4715 ok(group != NULL, "GetSecurityInfo\n");
4716 if (pDacl != NULL)
4717 ok(IsValidAcl(pDacl), "GetSecurityInfo\n");
4718 else
4719 win_skip("No ACL information returned\n");
4721 LocalFree(pSD);
4723 /* If we don't ask for the security descriptor, Windows will still give us
4724 the other stuff, leaving us no way to free it. */
4725 ret = GetSecurityInfo(obj, SE_FILE_OBJECT,
4726 OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
4727 &owner, &group, &pDacl, NULL, NULL);
4728 ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret);
4729 ok(owner != NULL, "GetSecurityInfo\n");
4730 ok(group != NULL, "GetSecurityInfo\n");
4731 if (pDacl != NULL)
4732 ok(IsValidAcl(pDacl), "GetSecurityInfo\n");
4733 else
4734 win_skip("No ACL information returned\n");
4736 /* Create security descriptor information and test that it comes back the same */
4737 pSD = &sd;
4738 pDacl = (PACL)&dacl;
4739 InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
4740 CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size);
4741 bret = InitializeAcl(pDacl, sizeof(dacl), ACL_REVISION);
4742 ok(bret, "Failed to initialize ACL.\n");
4743 bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
4744 ok(bret, "Failed to add Current User to ACL.\n");
4745 bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, admin_sid);
4746 ok(bret, "Failed to add Administrator Group to ACL.\n");
4747 bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
4748 ok(bret, "Failed to add ACL to security descriptor.\n");
4749 ret = pSetSecurityInfo(obj, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
4750 NULL, NULL, pDacl, NULL);
4751 ok(ret == ERROR_SUCCESS, "SetSecurityInfo returned %d\n", ret);
4752 ret = GetSecurityInfo(obj, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
4753 NULL, NULL, &pDacl, NULL, &pSD);
4754 ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret);
4755 ok(pDacl && IsValidAcl(pDacl), "GetSecurityInfo returned invalid DACL.\n");
4756 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
4757 ok(bret, "GetAclInformation failed\n");
4758 if (acl_size.AceCount > 0)
4760 bret = GetAce(pDacl, 0, (VOID **)&ace);
4761 ok(bret, "Failed to get Current User ACE.\n");
4762 bret = EqualSid(&ace->SidStart, user_sid);
4763 todo_wine ok(bret, "Current User ACE (%s) != Current User SID (%s).\n",
4764 debugstr_sid(&ace->SidStart), debugstr_sid(user_sid));
4765 ok(((ACE_HEADER *)ace)->AceFlags == 0,
4766 "Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
4767 ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
4768 ace->Mask);
4770 if (acl_size.AceCount > 1)
4772 bret = GetAce(pDacl, 1, (VOID **)&ace);
4773 ok(bret, "Failed to get Administators Group ACE.\n");
4774 bret = EqualSid(&ace->SidStart, admin_sid);
4775 todo_wine ok(bret, "Administators Group ACE (%s) != Administators Group SID (%s).\n", debugstr_sid(&ace->SidStart), debugstr_sid(admin_sid));
4776 ok(((ACE_HEADER *)ace)->AceFlags == 0,
4777 "Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
4778 ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n",
4779 ace->Mask);
4781 LocalFree(pSD);
4782 CloseHandle(obj);
4784 /* Obtain the "domain users" SID from the user SID */
4785 if (!AllocateAndInitializeSid(&sia, 4, *GetSidSubAuthority(user_sid, 0),
4786 *GetSidSubAuthority(user_sid, 1),
4787 *GetSidSubAuthority(user_sid, 2),
4788 *GetSidSubAuthority(user_sid, 3), 0, 0, 0, 0, &domain_sid))
4790 win_skip("Failed to get current domain SID\n");
4791 return;
4793 sid_size = sizeof(domain_users_ptr);
4794 CreateWellKnownSid(WinAccountDomainUsersSid, domain_sid, domain_users_sid, &sid_size);
4795 FreeSid(domain_sid);
4797 /* Test querying the ownership of a process */
4798 ret = GetSecurityInfo(GetCurrentProcess(), SE_KERNEL_OBJECT,
4799 OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION,
4800 NULL, NULL, NULL, NULL, &pSD);
4801 ok(!ret, "GetNamedSecurityInfo failed with error %d\n", ret);
4803 bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted);
4804 ok(bret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
4805 ok(owner != NULL, "owner should not be NULL\n");
4806 ok(EqualSid(owner, admin_sid) || EqualSid(owner, user_sid),
4807 "Process owner SID != Administrators SID.\n");
4809 bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted);
4810 ok(bret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
4811 ok(group != NULL, "group should not be NULL\n");
4812 ok(EqualSid(group, domain_users_sid), "Process group SID != Domain Users SID.\n");
4813 LocalFree(pSD);
4815 /* Test querying the DACL of a process */
4816 ret = GetSecurityInfo(GetCurrentProcess(), SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
4817 NULL, NULL, NULL, NULL, &pSD);
4818 ok(!ret, "GetSecurityInfo failed with error %d\n", ret);
4820 bret = GetSecurityDescriptorDacl(pSD, &dacl_present, &pDacl, &dacl_defaulted);
4821 ok(bret, "GetSecurityDescriptorDacl failed with error %d\n", GetLastError());
4822 ok(dacl_present, "DACL should be present\n");
4823 ok(pDacl && IsValidAcl(pDacl), "GetSecurityDescriptorDacl returned invalid DACL.\n");
4824 bret = GetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
4825 ok(bret, "GetAclInformation failed\n");
4826 ok(acl_size.AceCount != 0, "GetAclInformation returned no ACLs\n");
4827 for (i=0; i<acl_size.AceCount; i++)
4829 bret = GetAce(pDacl, i, (VOID **)&ace);
4830 ok(bret, "Failed to get ACE %d.\n", i);
4831 bret = EqualSid(&ace->SidStart, domain_users_sid);
4832 if (bret) domain_users_ace_id = i;
4833 bret = EqualSid(&ace->SidStart, admin_sid);
4834 if (bret) admins_ace_id = i;
4836 ok(domain_users_ace_id != -1 || broken(domain_users_ace_id == -1) /* win2k */,
4837 "Domain Users ACE not found.\n");
4838 if (domain_users_ace_id != -1)
4840 bret = GetAce(pDacl, domain_users_ace_id, (VOID **)&ace);
4841 ok(bret, "Failed to get Domain Users ACE.\n");
4842 flags = ((ACE_HEADER *)ace)->AceFlags;
4843 ok(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE),
4844 "Domain Users ACE has unexpected flags (0x%x != 0x%x)\n", flags,
4845 INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE);
4846 ok(ace->Mask == GENERIC_READ, "Domain Users ACE has unexpected mask (0x%x != 0x%x)\n",
4847 ace->Mask, GENERIC_READ);
4849 ok(admins_ace_id != -1 || broken(admins_ace_id == -1) /* xp */,
4850 "Builtin Admins ACE not found.\n");
4851 if (admins_ace_id != -1)
4853 bret = GetAce(pDacl, admins_ace_id, (VOID **)&ace);
4854 ok(bret, "Failed to get Builtin Admins ACE.\n");
4855 flags = ((ACE_HEADER *)ace)->AceFlags;
4856 ok(flags == 0x0, "Builtin Admins ACE has unexpected flags (0x%x != 0x0)\n", flags);
4857 ok(ace->Mask == PROCESS_ALL_ACCESS || broken(ace->Mask == 0x1f0fff) /* win2k */,
4858 "Builtin Admins ACE has unexpected mask (0x%x != 0x%x)\n", ace->Mask, PROCESS_ALL_ACCESS);
4860 LocalFree(pSD);
4863 static void test_GetSidSubAuthority(void)
4865 PSID psid = NULL;
4867 /* Note: on windows passing in an invalid index like -1, lets GetSidSubAuthority return 0x05000000 but
4868 still GetLastError returns ERROR_SUCCESS then. We don't test these unlikely cornercases here for now */
4869 ok(ConvertStringSidToSidA("S-1-5-21-93476-23408-4576",&psid),"ConvertStringSidToSidA failed\n");
4870 ok(IsValidSid(psid),"Sid is not valid\n");
4871 SetLastError(0xbebecaca);
4872 ok(*GetSidSubAuthorityCount(psid) == 4,"GetSidSubAuthorityCount gave %d expected 4\n", *GetSidSubAuthorityCount(psid));
4873 ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
4874 SetLastError(0xbebecaca);
4875 ok(*GetSidSubAuthority(psid,0) == 21,"GetSidSubAuthority gave %d expected 21\n", *GetSidSubAuthority(psid,0));
4876 ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
4877 SetLastError(0xbebecaca);
4878 ok(*GetSidSubAuthority(psid,1) == 93476,"GetSidSubAuthority gave %d expected 93476\n", *GetSidSubAuthority(psid,1));
4879 ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
4880 SetLastError(0xbebecaca);
4881 ok(GetSidSubAuthority(psid,4) != NULL,"Expected out of bounds GetSidSubAuthority to return a non-NULL pointer\n");
4882 ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
4883 LocalFree(psid);
4886 static void test_CheckTokenMembership(void)
4888 PTOKEN_GROUPS token_groups;
4889 DWORD size;
4890 HANDLE process_token, token;
4891 BOOL is_member;
4892 BOOL ret;
4893 DWORD i;
4895 if (!pCheckTokenMembership)
4897 win_skip("CheckTokenMembership is not available\n");
4898 return;
4900 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &process_token);
4901 ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
4903 ret = DuplicateToken(process_token, SecurityImpersonation, &token);
4904 ok(ret, "DuplicateToken failed with error %d\n", GetLastError());
4906 /* groups */
4907 ret = GetTokenInformation(token, TokenGroups, NULL, 0, &size);
4908 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
4909 "GetTokenInformation(TokenGroups) %s with error %d\n",
4910 ret ? "succeeded" : "failed", GetLastError());
4911 token_groups = HeapAlloc(GetProcessHeap(), 0, size);
4912 ret = GetTokenInformation(token, TokenGroups, token_groups, size, &size);
4913 ok(ret, "GetTokenInformation(TokenGroups) failed with error %d\n", GetLastError());
4915 for (i = 0; i < token_groups->GroupCount; i++)
4917 if (token_groups->Groups[i].Attributes & SE_GROUP_ENABLED)
4918 break;
4921 if (i == token_groups->GroupCount)
4923 HeapFree(GetProcessHeap(), 0, token_groups);
4924 CloseHandle(token);
4925 skip("user not a member of any group\n");
4926 return;
4929 is_member = FALSE;
4930 ret = pCheckTokenMembership(token, token_groups->Groups[i].Sid, &is_member);
4931 ok(ret, "CheckTokenMembership failed with error %d\n", GetLastError());
4932 ok(is_member, "CheckTokenMembership should have detected sid as member\n");
4934 is_member = FALSE;
4935 ret = pCheckTokenMembership(NULL, token_groups->Groups[i].Sid, &is_member);
4936 ok(ret, "CheckTokenMembership failed with error %d\n", GetLastError());
4937 ok(is_member, "CheckTokenMembership should have detected sid as member\n");
4939 is_member = TRUE;
4940 SetLastError(0xdeadbeef);
4941 ret = pCheckTokenMembership(process_token, token_groups->Groups[i].Sid, &is_member);
4942 ok(!ret && GetLastError() == ERROR_NO_IMPERSONATION_TOKEN,
4943 "CheckTokenMembership with process token %s with error %d\n",
4944 ret ? "succeeded" : "failed", GetLastError());
4945 ok(!is_member, "CheckTokenMembership should have cleared is_member\n");
4947 HeapFree(GetProcessHeap(), 0, token_groups);
4948 CloseHandle(token);
4949 CloseHandle(process_token);
4952 static void test_EqualSid(void)
4954 PSID sid1, sid2;
4955 BOOL ret;
4956 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
4957 SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
4959 SetLastError(0xdeadbeef);
4960 ret = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
4961 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid1);
4962 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
4964 win_skip("AllocateAndInitializeSid is not implemented\n");
4965 return;
4967 ok(ret, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
4968 ok(GetLastError() == 0xdeadbeef,
4969 "AllocateAndInitializeSid shouldn't have set last error to %d\n",
4970 GetLastError());
4972 ret = AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID,
4973 0, 0, 0, 0, 0, 0, 0, &sid2);
4974 ok(ret, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
4976 SetLastError(0xdeadbeef);
4977 ret = EqualSid(sid1, sid2);
4978 ok(!ret, "World and domain admins sids shouldn't have been equal\n");
4979 ok(GetLastError() == ERROR_SUCCESS ||
4980 broken(GetLastError() == 0xdeadbeef), /* NT4 */
4981 "EqualSid should have set last error to ERROR_SUCCESS instead of %d\n",
4982 GetLastError());
4984 SetLastError(0xdeadbeef);
4985 sid2 = FreeSid(sid2);
4986 ok(!sid2, "FreeSid should have returned NULL instead of %p\n", sid2);
4987 ok(GetLastError() == 0xdeadbeef,
4988 "FreeSid shouldn't have set last error to %d\n",
4989 GetLastError());
4991 ret = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
4992 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid2);
4993 ok(ret, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
4995 SetLastError(0xdeadbeef);
4996 ret = EqualSid(sid1, sid2);
4997 ok(ret, "Same sids should have been equal %s != %s\n",
4998 debugstr_sid(sid1), debugstr_sid(sid2));
4999 ok(GetLastError() == ERROR_SUCCESS ||
5000 broken(GetLastError() == 0xdeadbeef), /* NT4 */
5001 "EqualSid should have set last error to ERROR_SUCCESS instead of %d\n",
5002 GetLastError());
5004 ((SID *)sid2)->Revision = 2;
5005 SetLastError(0xdeadbeef);
5006 ret = EqualSid(sid1, sid2);
5007 ok(!ret, "EqualSid with invalid sid should have returned FALSE\n");
5008 ok(GetLastError() == ERROR_SUCCESS ||
5009 broken(GetLastError() == 0xdeadbeef), /* NT4 */
5010 "EqualSid should have set last error to ERROR_SUCCESS instead of %d\n",
5011 GetLastError());
5012 ((SID *)sid2)->Revision = SID_REVISION;
5014 FreeSid(sid1);
5015 FreeSid(sid2);
5018 static void test_GetUserNameA(void)
5020 char buffer[UNLEN + 1], filler[UNLEN + 1];
5021 DWORD required_len, buffer_len;
5022 BOOL ret;
5024 /* Test crashes on Windows. */
5025 if (0)
5027 SetLastError(0xdeadbeef);
5028 GetUserNameA(NULL, NULL);
5031 SetLastError(0xdeadbeef);
5032 required_len = 0;
5033 ret = GetUserNameA(NULL, &required_len);
5034 ok(ret == FALSE, "GetUserNameA returned %d\n", ret);
5035 ok(required_len != 0, "Outputted buffer length was %u\n", required_len);
5036 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
5038 SetLastError(0xdeadbeef);
5039 required_len = 1;
5040 ret = GetUserNameA(NULL, &required_len);
5041 ok(ret == FALSE, "GetUserNameA returned %d\n", ret);
5042 ok(required_len != 0 && required_len != 1, "Outputted buffer length was %u\n", required_len);
5043 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
5045 /* Tests crashes on Windows. */
5046 if (0)
5048 SetLastError(0xdeadbeef);
5049 required_len = UNLEN + 1;
5050 GetUserNameA(NULL, &required_len);
5052 SetLastError(0xdeadbeef);
5053 GetUserNameA(buffer, NULL);
5056 memset(filler, 'x', sizeof(filler));
5058 /* Note that GetUserNameA on XP and newer outputs the number of bytes
5059 * required for a Unicode string, which affects a test in the next block. */
5060 SetLastError(0xdeadbeef);
5061 memcpy(buffer, filler, sizeof(filler));
5062 required_len = 0;
5063 ret = GetUserNameA(buffer, &required_len);
5064 ok(ret == FALSE, "GetUserNameA returned %d\n", ret);
5065 ok(!memcmp(buffer, filler, sizeof(filler)), "Output buffer was altered\n");
5066 ok(required_len != 0, "Outputted buffer length was %u\n", required_len);
5067 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
5069 SetLastError(0xdeadbeef);
5070 memcpy(buffer, filler, sizeof(filler));
5071 buffer_len = required_len;
5072 ret = GetUserNameA(buffer, &buffer_len);
5073 ok(ret == TRUE, "GetUserNameA returned %d, last error %u\n", ret, GetLastError());
5074 ok(memcmp(buffer, filler, sizeof(filler)) != 0, "Output buffer was untouched\n");
5075 ok(buffer_len == required_len ||
5076 broken(buffer_len == required_len / sizeof(WCHAR)), /* XP+ */
5077 "Outputted buffer length was %u\n", buffer_len);
5078 ok(GetLastError() == 0xdeadbeef, "Last error was %u\n", GetLastError());
5080 /* Use the reported buffer size from the last GetUserNameA call and pass
5081 * a length that is one less than the required value. */
5082 SetLastError(0xdeadbeef);
5083 memcpy(buffer, filler, sizeof(filler));
5084 buffer_len--;
5085 ret = GetUserNameA(buffer, &buffer_len);
5086 ok(ret == FALSE, "GetUserNameA returned %d\n", ret);
5087 ok(!memcmp(buffer, filler, sizeof(filler)), "Output buffer was untouched\n");
5088 ok(buffer_len == required_len, "Outputted buffer length was %u\n", buffer_len);
5089 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
5092 static void test_GetUserNameW(void)
5094 WCHAR buffer[UNLEN + 1], filler[UNLEN + 1];
5095 DWORD required_len, buffer_len;
5096 BOOL ret;
5098 /* Test crashes on Windows. */
5099 if (0)
5101 SetLastError(0xdeadbeef);
5102 GetUserNameW(NULL, NULL);
5105 SetLastError(0xdeadbeef);
5106 required_len = 0;
5107 ret = GetUserNameW(NULL, &required_len);
5108 ok(ret == FALSE, "GetUserNameW returned %d\n", ret);
5109 ok(required_len != 0, "Outputted buffer length was %u\n", required_len);
5110 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
5112 SetLastError(0xdeadbeef);
5113 required_len = 1;
5114 ret = GetUserNameW(NULL, &required_len);
5115 ok(ret == FALSE, "GetUserNameW returned %d\n", ret);
5116 ok(required_len != 0 && required_len != 1, "Outputted buffer length was %u\n", required_len);
5117 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
5119 /* Tests crash on Windows. */
5120 if (0)
5122 SetLastError(0xdeadbeef);
5123 required_len = UNLEN + 1;
5124 GetUserNameW(NULL, &required_len);
5126 SetLastError(0xdeadbeef);
5127 GetUserNameW(buffer, NULL);
5130 memset(filler, 'x', sizeof(filler));
5132 SetLastError(0xdeadbeef);
5133 memcpy(buffer, filler, sizeof(filler));
5134 required_len = 0;
5135 ret = GetUserNameW(buffer, &required_len);
5136 ok(ret == FALSE, "GetUserNameW returned %d\n", ret);
5137 ok(!memcmp(buffer, filler, sizeof(filler)), "Output buffer was altered\n");
5138 ok(required_len != 0, "Outputted buffer length was %u\n", required_len);
5139 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
5141 SetLastError(0xdeadbeef);
5142 memcpy(buffer, filler, sizeof(filler));
5143 buffer_len = required_len;
5144 ret = GetUserNameW(buffer, &buffer_len);
5145 ok(ret == TRUE, "GetUserNameW returned %d, last error %u\n", ret, GetLastError());
5146 ok(memcmp(buffer, filler, sizeof(filler)) != 0, "Output buffer was untouched\n");
5147 ok(buffer_len == required_len, "Outputted buffer length was %u\n", buffer_len);
5148 ok(GetLastError() == 0xdeadbeef, "Last error was %u\n", GetLastError());
5150 /* GetUserNameW on XP and newer writes a truncated portion of the username string to the buffer. */
5151 SetLastError(0xdeadbeef);
5152 memcpy(buffer, filler, sizeof(filler));
5153 buffer_len--;
5154 ret = GetUserNameW(buffer, &buffer_len);
5155 ok(ret == FALSE, "GetUserNameW returned %d\n", ret);
5156 ok(!memcmp(buffer, filler, sizeof(filler)) ||
5157 broken(memcmp(buffer, filler, sizeof(filler)) != 0), /* XP+ */
5158 "Output buffer was altered\n");
5159 ok(buffer_len == required_len, "Outputted buffer length was %u\n", buffer_len);
5160 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Last error was %u\n", GetLastError());
5163 static void test_CreateRestrictedToken(void)
5165 HANDLE process_token, token, r_token;
5166 PTOKEN_GROUPS token_groups, groups2;
5167 LUID_AND_ATTRIBUTES lattr;
5168 SID_AND_ATTRIBUTES sattr;
5169 SECURITY_IMPERSONATION_LEVEL level;
5170 SID *removed_sid = NULL;
5171 char privs_buffer[1000];
5172 TOKEN_PRIVILEGES *privs = (TOKEN_PRIVILEGES *)privs_buffer;
5173 PRIVILEGE_SET priv_set;
5174 TOKEN_TYPE type;
5175 BOOL is_member;
5176 DWORD size;
5177 LUID luid = { 0, 0 };
5178 BOOL ret;
5179 DWORD i;
5181 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &process_token);
5182 ok(ret, "got error %d\n", GetLastError());
5184 ret = DuplicateTokenEx(process_token, TOKEN_DUPLICATE|TOKEN_ADJUST_GROUPS|TOKEN_QUERY,
5185 NULL, SecurityImpersonation, TokenImpersonation, &token);
5186 ok(ret, "got error %d\n", GetLastError());
5188 ret = GetTokenInformation(token, TokenGroups, NULL, 0, &size);
5189 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
5190 "got %d with error %d\n", ret, GetLastError());
5191 token_groups = HeapAlloc(GetProcessHeap(), 0, size);
5192 ret = GetTokenInformation(token, TokenGroups, token_groups, size, &size);
5193 ok(ret, "got error %d\n", GetLastError());
5195 for (i = 0; i < token_groups->GroupCount; i++)
5197 if (token_groups->Groups[i].Attributes & SE_GROUP_ENABLED)
5199 removed_sid = token_groups->Groups[i].Sid;
5200 break;
5203 ok(!!removed_sid, "user is not a member of any group\n");
5205 is_member = FALSE;
5206 ret = pCheckTokenMembership(token, removed_sid, &is_member);
5207 ok(ret, "got error %d\n", GetLastError());
5208 ok(is_member, "not a member\n");
5210 sattr.Sid = removed_sid;
5211 sattr.Attributes = 0;
5212 r_token = NULL;
5213 ret = CreateRestrictedToken(token, 0, 1, &sattr, 0, NULL, 0, NULL, &r_token);
5214 ok(ret, "got error %d\n", GetLastError());
5216 is_member = TRUE;
5217 ret = pCheckTokenMembership(r_token, removed_sid, &is_member);
5218 ok(ret, "got error %d\n", GetLastError());
5219 ok(!is_member, "not a member\n");
5221 ret = GetTokenInformation(r_token, TokenGroups, NULL, 0, &size);
5222 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n",
5223 ret, GetLastError());
5224 groups2 = HeapAlloc(GetProcessHeap(), 0, size);
5225 ret = GetTokenInformation(r_token, TokenGroups, groups2, size, &size);
5226 ok(ret, "got error %d\n", GetLastError());
5228 for (i = 0; i < groups2->GroupCount; i++)
5230 if (EqualSid(groups2->Groups[i].Sid, removed_sid))
5232 DWORD attr = groups2->Groups[i].Attributes;
5233 ok(attr & SE_GROUP_USE_FOR_DENY_ONLY, "got wrong attributes %#x\n", attr);
5234 ok(!(attr & SE_GROUP_ENABLED), "got wrong attributes %#x\n", attr);
5235 break;
5239 HeapFree(GetProcessHeap(), 0, groups2);
5241 size = sizeof(type);
5242 ret = GetTokenInformation(r_token, TokenType, &type, size, &size);
5243 ok(ret, "got error %d\n", GetLastError());
5244 ok(type == TokenImpersonation, "got type %u\n", type);
5246 size = sizeof(level);
5247 ret = GetTokenInformation(r_token, TokenImpersonationLevel, &level, size, &size);
5248 ok(ret, "got error %d\n", GetLastError());
5249 ok(level == SecurityImpersonation, "got level %u\n", type);
5251 CloseHandle(r_token);
5253 r_token = NULL;
5254 ret = CreateRestrictedToken(process_token, 0, 1, &sattr, 0, NULL, 0, NULL, &r_token);
5255 ok(ret, "got error %u\n", GetLastError());
5257 size = sizeof(type);
5258 ret = GetTokenInformation(r_token, TokenType, &type, size, &size);
5259 ok(ret, "got error %u\n", GetLastError());
5260 ok(type == TokenPrimary, "got type %u\n", type);
5262 CloseHandle(r_token);
5264 ret = GetTokenInformation(token, TokenPrivileges, privs, sizeof(privs_buffer), &size);
5265 ok(ret, "got error %u\n", GetLastError());
5267 for (i = 0; i < privs->PrivilegeCount; i++)
5269 if (privs->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED)
5271 luid = privs->Privileges[i].Luid;
5272 break;
5275 ok(i < privs->PrivilegeCount, "user has no privileges\n");
5277 lattr.Luid = luid;
5278 lattr.Attributes = 0;
5279 r_token = NULL;
5280 ret = CreateRestrictedToken(token, 0, 0, NULL, 1, &lattr, 0, NULL, &r_token);
5281 ok(ret, "got error %u\n", GetLastError());
5283 priv_set.PrivilegeCount = 1;
5284 priv_set.Control = 0;
5285 priv_set.Privilege[0].Luid = luid;
5286 priv_set.Privilege[0].Attributes = 0;
5287 ret = PrivilegeCheck(r_token, &priv_set, &is_member);
5288 ok(ret, "got error %u\n", GetLastError());
5289 ok(!is_member, "privilege should not be enabled\n");
5291 ret = GetTokenInformation(r_token, TokenPrivileges, privs, sizeof(privs_buffer), &size);
5292 ok(ret, "got error %u\n", GetLastError());
5294 is_member = FALSE;
5295 for (i = 0; i < privs->PrivilegeCount; i++)
5297 if (!memcmp(&privs->Privileges[i].Luid, &luid, sizeof(luid)))
5298 is_member = TRUE;
5300 ok(!is_member, "disabled privilege should not be present\n");
5302 CloseHandle(r_token);
5304 removed_sid->SubAuthority[0] = 0xdeadbeef;
5305 lattr.Luid.LowPart = 0xdeadbeef;
5306 r_token = NULL;
5307 ret = CreateRestrictedToken(token, 0, 1, &sattr, 1, &lattr, 0, NULL, &r_token);
5308 ok(ret, "got error %u\n", GetLastError());
5309 CloseHandle(r_token);
5311 HeapFree(GetProcessHeap(), 0, token_groups);
5312 CloseHandle(token);
5313 CloseHandle(process_token);
5316 static void validate_default_security_descriptor(SECURITY_DESCRIPTOR *sd)
5318 BOOL ret, present, defaulted;
5319 ACL *acl;
5320 void *sid;
5322 ret = IsValidSecurityDescriptor(sd);
5323 ok(ret, "security descriptor is not valid\n");
5325 present = -1;
5326 defaulted = -1;
5327 acl = (void *)0xdeadbeef;
5328 SetLastError(0xdeadbeef);
5329 ret = GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted);
5330 ok(ret, "GetSecurityDescriptorDacl error %d\n", GetLastError());
5331 todo_wine
5332 ok(present == 1, "acl is not present\n");
5333 todo_wine
5334 ok(acl != (void *)0xdeadbeef && acl != NULL, "acl pointer is not set\n");
5335 ok(defaulted == 0, "defaulted is set to TRUE\n");
5337 defaulted = -1;
5338 sid = (void *)0xdeadbeef;
5339 SetLastError(0xdeadbeef);
5340 ret = GetSecurityDescriptorOwner(sd, &sid, &defaulted);
5341 ok(ret, "GetSecurityDescriptorOwner error %d\n", GetLastError());
5342 todo_wine
5343 ok(sid != (void *)0xdeadbeef && sid != NULL, "sid pointer is not set\n");
5344 ok(defaulted == 0, "defaulted is set to TRUE\n");
5346 defaulted = -1;
5347 sid = (void *)0xdeadbeef;
5348 SetLastError(0xdeadbeef);
5349 ret = GetSecurityDescriptorGroup(sd, &sid, &defaulted);
5350 ok(ret, "GetSecurityDescriptorGroup error %d\n", GetLastError());
5351 todo_wine
5352 ok(sid != (void *)0xdeadbeef && sid != NULL, "sid pointer is not set\n");
5353 ok(defaulted == 0, "defaulted is set to TRUE\n");
5356 static void test_default_handle_security(HANDLE token, HANDLE handle, GENERIC_MAPPING *mapping)
5358 DWORD ret, granted, priv_set_len;
5359 BOOL status;
5360 PRIVILEGE_SET priv_set;
5361 SECURITY_DESCRIPTOR *sd;
5363 sd = test_get_security_descriptor(handle, __LINE__);
5364 validate_default_security_descriptor(sd);
5366 priv_set_len = sizeof(priv_set);
5367 granted = 0xdeadbeef;
5368 status = 0xdeadbeef;
5369 SetLastError(0xdeadbeef);
5370 ret = AccessCheck(sd, token, MAXIMUM_ALLOWED, mapping, &priv_set, &priv_set_len, &granted, &status);
5371 todo_wine {
5372 ok(ret, "AccessCheck error %d\n", GetLastError());
5373 ok(status == 1, "expected 1, got %d\n", status);
5374 ok(granted == mapping->GenericAll, "expected all access %#x, got %#x\n", mapping->GenericAll, granted);
5376 priv_set_len = sizeof(priv_set);
5377 granted = 0xdeadbeef;
5378 status = 0xdeadbeef;
5379 SetLastError(0xdeadbeef);
5380 ret = AccessCheck(sd, token, 0, mapping, &priv_set, &priv_set_len, &granted, &status);
5381 todo_wine {
5382 ok(ret, "AccessCheck error %d\n", GetLastError());
5383 ok(status == 0 || broken(status == 1) /* NT4 */, "expected 0, got %d\n", status);
5384 ok(granted == 0 || broken(granted == mapping->GenericRead) /* NT4 */, "expected 0, got %#x\n", granted);
5386 priv_set_len = sizeof(priv_set);
5387 granted = 0xdeadbeef;
5388 status = 0xdeadbeef;
5389 SetLastError(0xdeadbeef);
5390 ret = AccessCheck(sd, token, ACCESS_SYSTEM_SECURITY, mapping, &priv_set, &priv_set_len, &granted, &status);
5391 todo_wine {
5392 ok(ret, "AccessCheck error %d\n", GetLastError());
5393 ok(status == 0, "expected 0, got %d\n", status);
5394 ok(granted == 0, "expected 0, got %#x\n", granted);
5396 priv_set_len = sizeof(priv_set);
5397 granted = 0xdeadbeef;
5398 status = 0xdeadbeef;
5399 SetLastError(0xdeadbeef);
5400 ret = AccessCheck(sd, token, mapping->GenericRead, mapping, &priv_set, &priv_set_len, &granted, &status);
5401 todo_wine {
5402 ok(ret, "AccessCheck error %d\n", GetLastError());
5403 ok(status == 1, "expected 1, got %d\n", status);
5404 ok(granted == mapping->GenericRead, "expected read access %#x, got %#x\n", mapping->GenericRead, granted);
5406 priv_set_len = sizeof(priv_set);
5407 granted = 0xdeadbeef;
5408 status = 0xdeadbeef;
5409 SetLastError(0xdeadbeef);
5410 ret = AccessCheck(sd, token, mapping->GenericWrite, mapping, &priv_set, &priv_set_len, &granted, &status);
5411 todo_wine {
5412 ok(ret, "AccessCheck error %d\n", GetLastError());
5413 ok(status == 1, "expected 1, got %d\n", status);
5414 ok(granted == mapping->GenericWrite, "expected write access %#x, got %#x\n", mapping->GenericWrite, granted);
5416 priv_set_len = sizeof(priv_set);
5417 granted = 0xdeadbeef;
5418 status = 0xdeadbeef;
5419 SetLastError(0xdeadbeef);
5420 ret = AccessCheck(sd, token, mapping->GenericExecute, mapping, &priv_set, &priv_set_len, &granted, &status);
5421 todo_wine {
5422 ok(ret, "AccessCheck error %d\n", GetLastError());
5423 ok(status == 1, "expected 1, got %d\n", status);
5424 ok(granted == mapping->GenericExecute, "expected execute access %#x, got %#x\n", mapping->GenericExecute, granted);
5426 HeapFree(GetProcessHeap(), 0, sd);
5429 static ACCESS_MASK get_obj_access(HANDLE obj)
5431 OBJECT_BASIC_INFORMATION info;
5432 NTSTATUS status;
5434 if (!pNtQueryObject) return 0;
5436 status = pNtQueryObject(obj, ObjectBasicInformation, &info, sizeof(info), NULL);
5437 ok(!status, "NtQueryObject error %#x\n", status);
5439 return info.GrantedAccess;
5442 static void test_mutex_security(HANDLE token)
5444 DWORD ret, i, access;
5445 HANDLE mutex, dup;
5446 GENERIC_MAPPING mapping = { STANDARD_RIGHTS_READ | MUTANT_QUERY_STATE | SYNCHRONIZE,
5447 STANDARD_RIGHTS_WRITE | MUTEX_MODIFY_STATE | SYNCHRONIZE,
5448 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
5449 STANDARD_RIGHTS_ALL | MUTEX_ALL_ACCESS };
5450 static const struct
5452 int generic, mapped;
5453 } map[] =
5455 { 0, 0 },
5456 { GENERIC_READ, STANDARD_RIGHTS_READ | MUTANT_QUERY_STATE },
5457 { GENERIC_WRITE, STANDARD_RIGHTS_WRITE },
5458 { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
5459 { GENERIC_ALL, STANDARD_RIGHTS_ALL | MUTANT_QUERY_STATE }
5462 SetLastError(0xdeadbeef);
5463 mutex = OpenMutexA(0, FALSE, "WineTestMutex");
5464 ok(!mutex, "mutex should not exist\n");
5465 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
5467 SetLastError(0xdeadbeef);
5468 mutex = CreateMutexA(NULL, FALSE, "WineTestMutex");
5469 ok(mutex != 0, "CreateMutex error %d\n", GetLastError());
5471 access = get_obj_access(mutex);
5472 ok(access == MUTANT_ALL_ACCESS, "expected MUTANT_ALL_ACCESS, got %#x\n", access);
5474 for (i = 0; i < ARRAY_SIZE(map); i++)
5476 SetLastError( 0xdeadbeef );
5477 ret = DuplicateHandle(GetCurrentProcess(), mutex, GetCurrentProcess(), &dup,
5478 map[i].generic, FALSE, 0);
5479 ok(ret, "DuplicateHandle error %d\n", GetLastError());
5481 access = get_obj_access(dup);
5482 ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
5484 CloseHandle(dup);
5486 SetLastError(0xdeadbeef);
5487 dup = OpenMutexA(0, FALSE, "WineTestMutex");
5488 todo_wine
5489 ok(!dup, "OpenMutex should fail\n");
5490 todo_wine
5491 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError());
5494 test_default_handle_security(token, mutex, &mapping);
5496 CloseHandle (mutex);
5499 static void test_event_security(HANDLE token)
5501 DWORD ret, i, access;
5502 HANDLE event, dup;
5503 GENERIC_MAPPING mapping = { STANDARD_RIGHTS_READ | EVENT_QUERY_STATE | SYNCHRONIZE,
5504 STANDARD_RIGHTS_WRITE | EVENT_MODIFY_STATE | SYNCHRONIZE,
5505 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
5506 STANDARD_RIGHTS_ALL | EVENT_ALL_ACCESS };
5507 static const struct
5509 int generic, mapped;
5510 } map[] =
5512 { 0, 0 },
5513 { GENERIC_READ, STANDARD_RIGHTS_READ | EVENT_QUERY_STATE },
5514 { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | EVENT_MODIFY_STATE },
5515 { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
5516 { GENERIC_ALL, STANDARD_RIGHTS_ALL | EVENT_QUERY_STATE | EVENT_MODIFY_STATE }
5519 SetLastError(0xdeadbeef);
5520 event = OpenEventA(0, FALSE, "WineTestEvent");
5521 ok(!event, "event should not exist\n");
5522 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
5524 SetLastError(0xdeadbeef);
5525 event = CreateEventA(NULL, FALSE, FALSE, "WineTestEvent");
5526 ok(event != 0, "CreateEvent error %d\n", GetLastError());
5528 access = get_obj_access(event);
5529 ok(access == EVENT_ALL_ACCESS, "expected EVENT_ALL_ACCESS, got %#x\n", access);
5531 for (i = 0; i < ARRAY_SIZE(map); i++)
5533 SetLastError( 0xdeadbeef );
5534 ret = DuplicateHandle(GetCurrentProcess(), event, GetCurrentProcess(), &dup,
5535 map[i].generic, FALSE, 0);
5536 ok(ret, "DuplicateHandle error %d\n", GetLastError());
5538 access = get_obj_access(dup);
5539 ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
5541 CloseHandle(dup);
5543 SetLastError(0xdeadbeef);
5544 dup = OpenEventA(0, FALSE, "WineTestEvent");
5545 todo_wine
5546 ok(!dup, "OpenEvent should fail\n");
5547 todo_wine
5548 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError());
5551 test_default_handle_security(token, event, &mapping);
5553 CloseHandle(event);
5556 static void test_semaphore_security(HANDLE token)
5558 DWORD ret, i, access;
5559 HANDLE sem, dup;
5560 GENERIC_MAPPING mapping = { STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE,
5561 STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE,
5562 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
5563 STANDARD_RIGHTS_ALL | SEMAPHORE_ALL_ACCESS };
5564 static const struct
5566 int generic, mapped;
5567 } map[] =
5569 { 0, 0 },
5570 { GENERIC_READ, STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE },
5571 { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE },
5572 { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
5573 { GENERIC_ALL, STANDARD_RIGHTS_ALL | SEMAPHORE_QUERY_STATE | SEMAPHORE_MODIFY_STATE }
5576 SetLastError(0xdeadbeef);
5577 sem = OpenSemaphoreA(0, FALSE, "WineTestSemaphore");
5578 ok(!sem, "semaphore should not exist\n");
5579 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
5581 SetLastError(0xdeadbeef);
5582 sem = CreateSemaphoreA(NULL, 0, 10, "WineTestSemaphore");
5583 ok(sem != 0, "CreateSemaphore error %d\n", GetLastError());
5585 access = get_obj_access(sem);
5586 ok(access == SEMAPHORE_ALL_ACCESS, "expected SEMAPHORE_ALL_ACCESS, got %#x\n", access);
5588 for (i = 0; i < ARRAY_SIZE(map); i++)
5590 SetLastError( 0xdeadbeef );
5591 ret = DuplicateHandle(GetCurrentProcess(), sem, GetCurrentProcess(), &dup,
5592 map[i].generic, FALSE, 0);
5593 ok(ret, "DuplicateHandle error %d\n", GetLastError());
5595 access = get_obj_access(dup);
5596 ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
5598 CloseHandle(dup);
5601 test_default_handle_security(token, sem, &mapping);
5603 CloseHandle(sem);
5606 #define WINE_TEST_PIPE "\\\\.\\pipe\\WineTestPipe"
5607 static void test_named_pipe_security(HANDLE token)
5609 DWORD ret, i, access;
5610 HANDLE pipe, file, dup;
5611 GENERIC_MAPPING mapping = { FILE_GENERIC_READ,
5612 FILE_GENERIC_WRITE,
5613 FILE_GENERIC_EXECUTE,
5614 STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS };
5615 static const struct
5617 int generic, mapped;
5618 } map[] =
5620 { 0, 0 },
5621 { GENERIC_READ, FILE_GENERIC_READ },
5622 { GENERIC_WRITE, FILE_GENERIC_WRITE },
5623 { GENERIC_EXECUTE, FILE_GENERIC_EXECUTE },
5624 { GENERIC_ALL, STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS }
5626 static const struct
5628 DWORD open_mode;
5629 DWORD access;
5630 } creation_access[] =
5632 { PIPE_ACCESS_INBOUND, FILE_GENERIC_READ },
5633 { PIPE_ACCESS_OUTBOUND, FILE_GENERIC_WRITE },
5634 { PIPE_ACCESS_DUPLEX, FILE_GENERIC_READ|FILE_GENERIC_WRITE },
5635 { PIPE_ACCESS_INBOUND|WRITE_DAC, FILE_GENERIC_READ|WRITE_DAC },
5636 { PIPE_ACCESS_INBOUND|WRITE_OWNER, FILE_GENERIC_READ|WRITE_OWNER }
5637 /* ACCESS_SYSTEM_SECURITY is also valid, but will fail with ERROR_PRIVILEGE_NOT_HELD */
5640 /* Test the different security access options for pipes */
5641 for (i = 0; i < ARRAY_SIZE(creation_access); i++)
5643 SetLastError(0xdeadbeef);
5644 pipe = CreateNamedPipeA(WINE_TEST_PIPE, creation_access[i].open_mode,
5645 PIPE_TYPE_BYTE | PIPE_NOWAIT, PIPE_UNLIMITED_INSTANCES, 0, 0,
5646 NMPWAIT_USE_DEFAULT_WAIT, NULL);
5647 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe(0x%x) error %d\n",
5648 creation_access[i].open_mode, GetLastError());
5649 access = get_obj_access(pipe);
5650 ok(access == creation_access[i].access,
5651 "CreateNamedPipeA(0x%x) pipe expected access 0x%x (got 0x%x)\n",
5652 creation_access[i].open_mode, creation_access[i].access, access);
5653 CloseHandle(pipe);
5656 SetLastError(0xdeadbeef);
5657 pipe = CreateNamedPipeA(WINE_TEST_PIPE, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,
5658 PIPE_TYPE_BYTE | PIPE_NOWAIT, PIPE_UNLIMITED_INSTANCES,
5659 0, 0, NMPWAIT_USE_DEFAULT_WAIT, NULL);
5660 ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe error %d\n", GetLastError());
5662 test_default_handle_security(token, pipe, &mapping);
5664 SetLastError(0xdeadbeef);
5665 file = CreateFileA(WINE_TEST_PIPE, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, 0, 0);
5666 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
5668 access = get_obj_access(file);
5669 ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", access);
5671 for (i = 0; i < ARRAY_SIZE(map); i++)
5673 SetLastError( 0xdeadbeef );
5674 ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup,
5675 map[i].generic, FALSE, 0);
5676 ok(ret, "DuplicateHandle error %d\n", GetLastError());
5678 access = get_obj_access(dup);
5679 ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
5681 CloseHandle(dup);
5684 CloseHandle(file);
5685 CloseHandle(pipe);
5687 SetLastError(0xdeadbeef);
5688 file = CreateFileA("\\\\.\\pipe\\", FILE_ALL_ACCESS, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
5689 ok(file != INVALID_HANDLE_VALUE || broken(file == INVALID_HANDLE_VALUE) /* before Vista */, "CreateFile error %d\n", GetLastError());
5691 if (file != INVALID_HANDLE_VALUE)
5693 access = get_obj_access(file);
5694 ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", access);
5696 for (i = 0; i < ARRAY_SIZE(map); i++)
5698 SetLastError( 0xdeadbeef );
5699 ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup,
5700 map[i].generic, FALSE, 0);
5701 ok(ret, "DuplicateHandle error %d\n", GetLastError());
5703 access = get_obj_access(dup);
5704 ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
5705 CloseHandle(dup);
5709 CloseHandle(file);
5712 static void test_file_security(HANDLE token)
5714 DWORD ret, i, access, bytes;
5715 HANDLE file, dup;
5716 static const struct
5718 int generic, mapped;
5719 } map[] =
5721 { 0, 0 },
5722 { GENERIC_READ, FILE_GENERIC_READ },
5723 { GENERIC_WRITE, FILE_GENERIC_WRITE },
5724 { GENERIC_EXECUTE, FILE_GENERIC_EXECUTE },
5725 { GENERIC_ALL, STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS }
5727 char temp_path[MAX_PATH];
5728 char file_name[MAX_PATH];
5729 char buf[16];
5731 GetTempPathA(MAX_PATH, temp_path);
5732 GetTempFileNameA(temp_path, "tmp", 0, file_name);
5734 /* file */
5735 SetLastError(0xdeadbeef);
5736 file = CreateFileA(file_name, GENERIC_ALL, 0, NULL, CREATE_ALWAYS, 0, NULL);
5737 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
5739 access = get_obj_access(file);
5740 ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", access);
5742 for (i = 0; i < ARRAY_SIZE(map); i++)
5744 SetLastError( 0xdeadbeef );
5745 ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup,
5746 map[i].generic, FALSE, 0);
5747 ok(ret, "DuplicateHandle error %d\n", GetLastError());
5749 access = get_obj_access(dup);
5750 ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
5752 CloseHandle(dup);
5755 CloseHandle(file);
5757 SetLastError(0xdeadbeef);
5758 file = CreateFileA(file_name, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
5759 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
5761 access = get_obj_access(file);
5762 ok(access == (FILE_READ_ATTRIBUTES | SYNCHRONIZE), "expected FILE_READ_ATTRIBUTES | SYNCHRONIZE, got %#x\n", access);
5764 bytes = 0xdeadbeef;
5765 SetLastError(0xdeadbeef);
5766 ret = ReadFile(file, buf, sizeof(buf), &bytes, NULL);
5767 ok(!ret, "ReadFile should fail\n");
5768 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
5769 ok(bytes == 0, "expected 0, got %u\n", bytes);
5771 CloseHandle(file);
5773 SetLastError(0xdeadbeef);
5774 file = CreateFileA(file_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
5775 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
5777 access = get_obj_access(file);
5778 ok(access == (FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES), "expected FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES, got %#x\n", access);
5780 bytes = 0xdeadbeef;
5781 SetLastError(0xdeadbeef);
5782 ret = ReadFile(file, buf, sizeof(buf), &bytes, NULL);
5783 ok(!ret, "ReadFile should fail\n");
5784 ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
5785 ok(bytes == 0, "expected 0, got %u\n", bytes);
5787 CloseHandle(file);
5788 DeleteFileA(file_name);
5790 /* directory */
5791 SetLastError(0xdeadbeef);
5792 file = CreateFileA(temp_path, GENERIC_ALL, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
5793 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
5795 access = get_obj_access(file);
5796 ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", access);
5798 for (i = 0; i < ARRAY_SIZE(map); i++)
5800 SetLastError( 0xdeadbeef );
5801 ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup,
5802 map[i].generic, FALSE, 0);
5803 ok(ret, "DuplicateHandle error %d\n", GetLastError());
5805 access = get_obj_access(dup);
5806 ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
5808 CloseHandle(dup);
5811 CloseHandle(file);
5813 SetLastError(0xdeadbeef);
5814 file = CreateFileA(temp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
5815 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
5817 access = get_obj_access(file);
5818 ok(access == (FILE_READ_ATTRIBUTES | SYNCHRONIZE), "expected FILE_READ_ATTRIBUTES | SYNCHRONIZE, got %#x\n", access);
5820 CloseHandle(file);
5822 SetLastError(0xdeadbeef);
5823 file = CreateFileA(temp_path, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
5824 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
5826 access = get_obj_access(file);
5827 ok(access == (FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES), "expected FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES, got %#x\n", access);
5829 CloseHandle(file);
5832 static void test_filemap_security(void)
5834 char temp_path[MAX_PATH];
5835 char file_name[MAX_PATH];
5836 DWORD ret, i, access;
5837 HANDLE file, mapping, dup, created_mapping;
5838 static const struct
5840 int generic, mapped;
5841 BOOL open_only;
5842 } map[] =
5844 { 0, 0 },
5845 { GENERIC_READ, STANDARD_RIGHTS_READ | SECTION_QUERY | SECTION_MAP_READ },
5846 { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | SECTION_MAP_WRITE },
5847 { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SECTION_MAP_EXECUTE },
5848 { GENERIC_ALL, STANDARD_RIGHTS_REQUIRED | SECTION_ALL_ACCESS },
5849 { SECTION_MAP_READ | SECTION_MAP_WRITE, SECTION_MAP_READ | SECTION_MAP_WRITE },
5850 { SECTION_MAP_WRITE, SECTION_MAP_WRITE },
5851 { SECTION_MAP_READ | SECTION_QUERY, SECTION_MAP_READ | SECTION_QUERY },
5852 { SECTION_QUERY, SECTION_MAP_READ, TRUE },
5853 { SECTION_QUERY | SECTION_MAP_READ, SECTION_QUERY | SECTION_MAP_READ }
5855 static const struct
5857 int prot, mapped;
5858 } prot_map[] =
5860 { 0, 0 },
5861 { PAGE_NOACCESS, 0 },
5862 { PAGE_READONLY, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ },
5863 { PAGE_READWRITE, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE },
5864 { PAGE_WRITECOPY, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ },
5865 { PAGE_EXECUTE, 0 },
5866 { PAGE_EXECUTE_READ, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE },
5867 { PAGE_EXECUTE_READWRITE, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE },
5868 { PAGE_EXECUTE_WRITECOPY, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE }
5871 GetTempPathA(MAX_PATH, temp_path);
5872 GetTempFileNameA(temp_path, "tmp", 0, file_name);
5874 SetLastError(0xdeadbeef);
5875 file = CreateFileA(file_name, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, CREATE_ALWAYS, 0, 0);
5876 ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
5877 SetFilePointer(file, 4096, NULL, FILE_BEGIN);
5878 SetEndOfFile(file);
5880 for (i = 0; i < ARRAY_SIZE(prot_map); i++)
5882 if (map[i].open_only) continue;
5884 SetLastError(0xdeadbeef);
5885 mapping = CreateFileMappingW(file, NULL, prot_map[i].prot, 0, 4096, NULL);
5886 if (prot_map[i].mapped)
5888 if (!mapping)
5890 /* NT4 and win2k don't support EXEC on file mappings */
5891 if (prot_map[i].prot == PAGE_EXECUTE_READ || prot_map[i].prot == PAGE_EXECUTE_READWRITE || prot_map[i].prot == PAGE_EXECUTE_WRITECOPY)
5893 win_skip("CreateFileMapping doesn't support PAGE_EXECUTE protection\n");
5894 continue;
5897 ok(mapping != 0, "CreateFileMapping(%04x) error %d\n", prot_map[i].prot, GetLastError());
5899 else
5901 ok(!mapping, "CreateFileMapping(%04x) should fail\n", prot_map[i].prot);
5902 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
5903 continue;
5906 access = get_obj_access(mapping);
5907 ok(access == prot_map[i].mapped, "%d: expected %#x, got %#x\n", i, prot_map[i].mapped, access);
5909 CloseHandle(mapping);
5912 SetLastError(0xdeadbeef);
5913 mapping = CreateFileMappingW(file, NULL, PAGE_EXECUTE_READWRITE, 0, 4096, NULL);
5914 if (!mapping)
5916 /* NT4 and win2k don't support EXEC on file mappings */
5917 win_skip("CreateFileMapping doesn't support PAGE_EXECUTE protection\n");
5918 CloseHandle(file);
5919 DeleteFileA(file_name);
5920 return;
5922 ok(mapping != 0, "CreateFileMapping error %d\n", GetLastError());
5924 access = get_obj_access(mapping);
5925 ok(access == (STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE),
5926 "expected STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE, got %#x\n", access);
5928 for (i = 0; i < ARRAY_SIZE(map); i++)
5930 if (map[i].open_only) continue;
5932 SetLastError( 0xdeadbeef );
5933 ret = DuplicateHandle(GetCurrentProcess(), mapping, GetCurrentProcess(), &dup,
5934 map[i].generic, FALSE, 0);
5935 ok(ret, "DuplicateHandle error %d\n", GetLastError());
5937 access = get_obj_access(dup);
5938 ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
5940 CloseHandle(dup);
5943 CloseHandle(mapping);
5944 CloseHandle(file);
5945 DeleteFileA(file_name);
5947 created_mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 0x1000,
5948 "Wine Test Open Mapping");
5949 ok(created_mapping != NULL, "CreateFileMapping failed with error %u\n", GetLastError());
5951 for (i = 0; i < ARRAY_SIZE(map); i++)
5953 if (!map[i].generic) continue;
5955 mapping = OpenFileMappingA(map[i].generic, FALSE, "Wine Test Open Mapping");
5956 ok(mapping != NULL, "OpenFileMapping failed with error %d\n", GetLastError());
5957 access = get_obj_access(mapping);
5958 ok(access == map[i].mapped, "%d: unexpected access flags %#x, expected %#x\n",
5959 i, access, map[i].mapped);
5960 CloseHandle(mapping);
5963 CloseHandle(created_mapping);
5966 static void test_thread_security(void)
5968 DWORD ret, i, access;
5969 HANDLE thread, dup;
5970 static const struct
5972 int generic, mapped;
5973 } map[] =
5975 { 0, 0 },
5976 { GENERIC_READ, STANDARD_RIGHTS_READ | THREAD_QUERY_INFORMATION | THREAD_GET_CONTEXT },
5977 { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | THREAD_SET_INFORMATION | THREAD_SET_CONTEXT | THREAD_TERMINATE | THREAD_SUSPEND_RESUME | 0x4 },
5978 { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
5979 { GENERIC_ALL, THREAD_ALL_ACCESS_NT4 }
5982 SetLastError(0xdeadbeef);
5983 thread = CreateThread(NULL, 0, (void *)0xdeadbeef, NULL, CREATE_SUSPENDED, &ret);
5984 ok(thread != 0, "CreateThread error %d\n", GetLastError());
5986 access = get_obj_access(thread);
5987 ok(access == THREAD_ALL_ACCESS_NT4 || access == THREAD_ALL_ACCESS_VISTA, "expected THREAD_ALL_ACCESS, got %#x\n", access);
5989 for (i = 0; i < ARRAY_SIZE(map); i++)
5991 SetLastError( 0xdeadbeef );
5992 ret = DuplicateHandle(GetCurrentProcess(), thread, GetCurrentProcess(), &dup,
5993 map[i].generic, FALSE, 0);
5994 ok(ret, "DuplicateHandle error %d\n", GetLastError());
5996 access = get_obj_access(dup);
5997 switch (map[i].generic)
5999 case GENERIC_READ:
6000 case GENERIC_EXECUTE:
6001 ok(access == map[i].mapped ||
6002 access == (map[i].mapped | THREAD_QUERY_LIMITED_INFORMATION) /* Vista+ */ ||
6003 access == (map[i].mapped | THREAD_QUERY_LIMITED_INFORMATION | THREAD_RESUME) /* win8 */,
6004 "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6005 break;
6006 case GENERIC_WRITE:
6007 ok(access == map[i].mapped ||
6008 access == (map[i].mapped | THREAD_SET_LIMITED_INFORMATION) /* Vista+ */ ||
6009 access == (map[i].mapped | THREAD_SET_LIMITED_INFORMATION | THREAD_RESUME) /* win8 */,
6010 "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6011 break;
6012 case GENERIC_ALL:
6013 ok(access == map[i].mapped || access == THREAD_ALL_ACCESS_VISTA,
6014 "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6015 break;
6016 default:
6017 ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6018 break;
6021 CloseHandle(dup);
6024 SetLastError( 0xdeadbeef );
6025 ret = DuplicateHandle(GetCurrentProcess(), thread, GetCurrentProcess(), &dup,
6026 THREAD_QUERY_INFORMATION, FALSE, 0);
6027 ok(ret, "DuplicateHandle error %d\n", GetLastError());
6028 access = get_obj_access(dup);
6029 ok(access == (THREAD_QUERY_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION) /* Vista+ */ ||
6030 access == THREAD_QUERY_INFORMATION /* before Vista */,
6031 "expected THREAD_QUERY_INFORMATION|THREAD_QUERY_LIMITED_INFORMATION, got %#x\n", access);
6032 CloseHandle(dup);
6034 TerminateThread(thread, 0);
6035 CloseHandle(thread);
6038 static void test_process_access(void)
6040 DWORD ret, i, access;
6041 HANDLE process, dup;
6042 STARTUPINFOA sti;
6043 PROCESS_INFORMATION pi;
6044 char cmdline[] = "winver.exe";
6045 static const struct
6047 int generic, mapped;
6048 } map[] =
6050 { 0, 0 },
6051 { GENERIC_READ, STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ },
6052 { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION | PROCESS_SUSPEND_RESUME |
6053 PROCESS_VM_WRITE | PROCESS_DUP_HANDLE | PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION },
6054 { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
6055 { GENERIC_ALL, PROCESS_ALL_ACCESS_NT4 }
6058 memset(&sti, 0, sizeof(sti));
6059 sti.cb = sizeof(sti);
6060 SetLastError(0xdeadbeef);
6061 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &sti, &pi);
6062 ok(ret, "CreateProcess() error %d\n", GetLastError());
6064 CloseHandle(pi.hThread);
6065 process = pi.hProcess;
6067 access = get_obj_access(process);
6068 ok(access == PROCESS_ALL_ACCESS_NT4 || access == PROCESS_ALL_ACCESS_VISTA, "expected PROCESS_ALL_ACCESS, got %#x\n", access);
6070 for (i = 0; i < ARRAY_SIZE(map); i++)
6072 SetLastError( 0xdeadbeef );
6073 ret = DuplicateHandle(GetCurrentProcess(), process, GetCurrentProcess(), &dup,
6074 map[i].generic, FALSE, 0);
6075 ok(ret, "DuplicateHandle error %d\n", GetLastError());
6077 access = get_obj_access(dup);
6078 switch (map[i].generic)
6080 case GENERIC_READ:
6081 ok(access == map[i].mapped || access == (map[i].mapped | PROCESS_QUERY_LIMITED_INFORMATION) /* Vista+ */,
6082 "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6083 break;
6084 case GENERIC_WRITE:
6085 ok(access == map[i].mapped ||
6086 access == (map[i].mapped | PROCESS_TERMINATE) /* before Vista */ ||
6087 access == (map[i].mapped | PROCESS_SET_LIMITED_INFORMATION) /* win8 */ ||
6088 access == (map[i].mapped | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_SET_LIMITED_INFORMATION) /* Win10 Anniversary Update */,
6089 "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6090 break;
6091 case GENERIC_EXECUTE:
6092 ok(access == map[i].mapped || access == (map[i].mapped | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE) /* Vista+ */,
6093 "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6094 break;
6095 case GENERIC_ALL:
6096 ok(access == map[i].mapped || access == PROCESS_ALL_ACCESS_VISTA,
6097 "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6098 break;
6099 default:
6100 ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
6101 break;
6104 CloseHandle(dup);
6107 SetLastError( 0xdeadbeef );
6108 ret = DuplicateHandle(GetCurrentProcess(), process, GetCurrentProcess(), &dup,
6109 PROCESS_QUERY_INFORMATION, FALSE, 0);
6110 ok(ret, "DuplicateHandle error %d\n", GetLastError());
6111 access = get_obj_access(dup);
6112 ok(access == (PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION) /* Vista+ */ ||
6113 access == PROCESS_QUERY_INFORMATION /* before Vista */,
6114 "expected PROCESS_QUERY_INFORMATION|PROCESS_QUERY_LIMITED_INFORMATION, got %#x\n", access);
6115 CloseHandle(dup);
6117 TerminateProcess(process, 0);
6118 CloseHandle(process);
6121 static BOOL validate_impersonation_token(HANDLE token, DWORD *token_type)
6123 DWORD ret, needed;
6124 TOKEN_TYPE type;
6125 SECURITY_IMPERSONATION_LEVEL sil;
6127 type = 0xdeadbeef;
6128 needed = 0;
6129 SetLastError(0xdeadbeef);
6130 ret = GetTokenInformation(token, TokenType, &type, sizeof(type), &needed);
6131 ok(ret, "GetTokenInformation error %d\n", GetLastError());
6132 ok(needed == sizeof(type), "GetTokenInformation should return required buffer length\n");
6133 ok(type == TokenPrimary || type == TokenImpersonation, "expected TokenPrimary or TokenImpersonation, got %d\n", type);
6135 *token_type = type;
6136 if (type != TokenImpersonation) return FALSE;
6138 needed = 0;
6139 SetLastError(0xdeadbeef);
6140 ret = GetTokenInformation(token, TokenImpersonationLevel, &sil, sizeof(sil), &needed);
6141 ok(ret, "GetTokenInformation error %d\n", GetLastError());
6142 ok(needed == sizeof(sil), "GetTokenInformation should return required buffer length\n");
6143 ok(sil == SecurityImpersonation, "expected SecurityImpersonation, got %d\n", sil);
6145 needed = 0xdeadbeef;
6146 SetLastError(0xdeadbeef);
6147 ret = GetTokenInformation(token, TokenDefaultDacl, NULL, 0, &needed);
6148 ok(!ret, "GetTokenInformation should fail\n");
6149 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
6150 ok(needed != 0xdeadbeef, "GetTokenInformation should return required buffer length\n");
6151 ok(needed > sizeof(TOKEN_DEFAULT_DACL), "GetTokenInformation returned empty default DACL\n");
6153 needed = 0xdeadbeef;
6154 SetLastError(0xdeadbeef);
6155 ret = GetTokenInformation(token, TokenOwner, NULL, 0, &needed);
6156 ok(!ret, "GetTokenInformation should fail\n");
6157 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
6158 ok(needed != 0xdeadbeef, "GetTokenInformation should return required buffer length\n");
6159 ok(needed > sizeof(TOKEN_OWNER), "GetTokenInformation returned empty token owner\n");
6161 needed = 0xdeadbeef;
6162 SetLastError(0xdeadbeef);
6163 ret = GetTokenInformation(token, TokenPrimaryGroup, NULL, 0, &needed);
6164 ok(!ret, "GetTokenInformation should fail\n");
6165 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
6166 ok(needed != 0xdeadbeef, "GetTokenInformation should return required buffer length\n");
6167 ok(needed > sizeof(TOKEN_PRIMARY_GROUP), "GetTokenInformation returned empty token primary group\n");
6169 return TRUE;
6172 static void test_kernel_objects_security(void)
6174 HANDLE token, process_token;
6175 DWORD ret, token_type;
6177 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_QUERY, &process_token);
6178 ok(ret, "OpenProcessToken error %d\n", GetLastError());
6180 ret = validate_impersonation_token(process_token, &token_type);
6181 ok(token_type == TokenPrimary, "expected TokenPrimary, got %d\n", token_type);
6182 ok(!ret, "access token should not be an impersonation token\n");
6184 ret = DuplicateToken(process_token, SecurityImpersonation, &token);
6185 ok(ret, "DuplicateToken error %d\n", GetLastError());
6187 ret = validate_impersonation_token(token, &token_type);
6188 ok(ret, "access token should be a valid impersonation token\n");
6189 ok(token_type == TokenImpersonation, "expected TokenImpersonation, got %d\n", token_type);
6191 test_mutex_security(token);
6192 test_event_security(token);
6193 test_named_pipe_security(token);
6194 test_semaphore_security(token);
6195 test_file_security(token);
6196 test_filemap_security();
6197 test_thread_security();
6198 test_process_access();
6199 /* FIXME: test other kernel object types */
6201 CloseHandle(process_token);
6202 CloseHandle(token);
6205 static void test_TokenIntegrityLevel(void)
6207 TOKEN_MANDATORY_LABEL *tml;
6208 BYTE buffer[64]; /* using max. 28 byte in win7 x64 */
6209 HANDLE token;
6210 DWORD size;
6211 DWORD res;
6212 static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
6213 {SECURITY_MANDATORY_HIGH_RID}};
6214 static SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
6215 {SECURITY_MANDATORY_MEDIUM_RID}};
6217 SetLastError(0xdeadbeef);
6218 res = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
6219 ok(res, "got %d with %d (expected TRUE)\n", res, GetLastError());
6221 SetLastError(0xdeadbeef);
6222 res = GetTokenInformation(token, TokenIntegrityLevel, buffer, sizeof(buffer), &size);
6224 /* not supported before Vista */
6225 if (!res && ((GetLastError() == ERROR_INVALID_PARAMETER) || GetLastError() == ERROR_INVALID_FUNCTION))
6227 win_skip("TokenIntegrityLevel not supported\n");
6228 CloseHandle(token);
6229 return;
6232 ok(res, "got %u with %u (expected TRUE)\n", res, GetLastError());
6233 if (!res)
6235 CloseHandle(token);
6236 return;
6239 tml = (TOKEN_MANDATORY_LABEL*) buffer;
6240 ok(tml->Label.Attributes == (SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED),
6241 "got 0x%x (expected 0x%x)\n", tml->Label.Attributes, (SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED));
6243 ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level),
6244 "got %s (expected %s or %s)\n", debugstr_sid(tml->Label.Sid),
6245 debugstr_sid(&medium_level), debugstr_sid(&high_level));
6247 CloseHandle(token);
6250 static void test_default_dacl_owner_sid(void)
6252 HANDLE handle;
6253 BOOL ret, defaulted, present, found;
6254 DWORD size, index;
6255 SECURITY_DESCRIPTOR *sd;
6256 SECURITY_ATTRIBUTES sa;
6257 PSID owner;
6258 ACL *dacl;
6259 ACCESS_ALLOWED_ACE *ace;
6261 sd = HeapAlloc( GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH );
6262 ret = InitializeSecurityDescriptor( sd, SECURITY_DESCRIPTOR_REVISION );
6263 ok( ret, "error %u\n", GetLastError() );
6265 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
6266 sa.lpSecurityDescriptor = sd;
6267 sa.bInheritHandle = FALSE;
6268 handle = CreateEventA( &sa, TRUE, TRUE, "test_event" );
6269 ok( handle != NULL, "error %u\n", GetLastError() );
6271 size = 0;
6272 ret = GetKernelObjectSecurity( handle, OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, NULL, 0, &size );
6273 ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "error %u\n", GetLastError() );
6275 sd = HeapAlloc( GetProcessHeap(), 0, size );
6276 ret = GetKernelObjectSecurity( handle, OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, sd, size, &size );
6277 ok( ret, "error %u\n", GetLastError() );
6279 owner = (void *)0xdeadbeef;
6280 defaulted = TRUE;
6281 ret = GetSecurityDescriptorOwner( sd, &owner, &defaulted );
6282 ok( ret, "error %u\n", GetLastError() );
6283 ok( owner != (void *)0xdeadbeef, "owner not set\n" );
6284 ok( !defaulted, "owner defaulted\n" );
6286 dacl = (void *)0xdeadbeef;
6287 present = FALSE;
6288 defaulted = TRUE;
6289 ret = GetSecurityDescriptorDacl( sd, &present, &dacl, &defaulted );
6290 ok( ret, "error %u\n", GetLastError() );
6291 ok( present, "dacl not present\n" );
6292 ok( dacl != (void *)0xdeadbeef, "dacl not set\n" );
6293 ok( !defaulted, "dacl defaulted\n" );
6295 index = 0;
6296 found = FALSE;
6297 while (GetAce( dacl, index++, (void **)&ace ))
6299 if (EqualSid( &ace->SidStart, owner )) found = TRUE;
6301 ok( found, "owner sid not found in dacl\n" );
6303 HeapFree( GetProcessHeap(), 0, sa.lpSecurityDescriptor );
6304 HeapFree( GetProcessHeap(), 0, sd );
6305 CloseHandle( handle );
6308 static void test_AdjustTokenPrivileges(void)
6310 TOKEN_PRIVILEGES tp;
6311 HANDLE token;
6312 DWORD len;
6313 LUID luid;
6314 BOOL ret;
6316 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
6317 return;
6319 if (!LookupPrivilegeValueA(NULL, SE_BACKUP_NAME, &luid))
6321 CloseHandle(token);
6322 return;
6325 tp.PrivilegeCount = 1;
6326 tp.Privileges[0].Luid = luid;
6327 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
6329 len = 0xdeadbeef;
6330 ret = AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, &len);
6331 ok(ret, "got %d\n", ret);
6332 ok(len == 0xdeadbeef, "got length %d\n", len);
6334 /* revert */
6335 tp.PrivilegeCount = 1;
6336 tp.Privileges[0].Luid = luid;
6337 tp.Privileges[0].Attributes = 0;
6338 ret = AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
6339 ok(ret, "got %d\n", ret);
6341 CloseHandle(token);
6344 static void test_AddAce(void)
6346 static SID const sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
6348 char acl_buf[1024], ace_buf[256];
6349 ACCESS_ALLOWED_ACE *ace = (ACCESS_ALLOWED_ACE*)ace_buf;
6350 PACL acl = (PACL)acl_buf;
6351 BOOL ret;
6353 memset(ace, 0, sizeof(ace_buf));
6354 ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
6355 ace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD)+sizeof(SID);
6356 memcpy(&ace->SidStart, &sidWorld, sizeof(sidWorld));
6358 ret = InitializeAcl(acl, sizeof(acl_buf), ACL_REVISION2);
6359 ok(ret, "InitializeAcl failed: %d\n", GetLastError());
6361 ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize);
6362 ok(ret, "AddAce failed: %d\n", GetLastError());
6363 ret = AddAce(acl, ACL_REVISION2, MAXDWORD, ace, ace->Header.AceSize);
6364 ok(ret, "AddAce failed: %d\n", GetLastError());
6365 ret = AddAce(acl, ACL_REVISION3, MAXDWORD, ace, ace->Header.AceSize);
6366 ok(ret, "AddAce failed: %d\n", GetLastError());
6367 ok(acl->AclRevision == ACL_REVISION3, "acl->AclRevision = %d\n", acl->AclRevision);
6368 ret = AddAce(acl, ACL_REVISION4, MAXDWORD, ace, ace->Header.AceSize);
6369 ok(ret, "AddAce failed: %d\n", GetLastError());
6370 ok(acl->AclRevision == ACL_REVISION4, "acl->AclRevision = %d\n", acl->AclRevision);
6371 ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize);
6372 ok(ret, "AddAce failed: %d\n", GetLastError());
6373 ok(acl->AclRevision == ACL_REVISION4, "acl->AclRevision = %d\n", acl->AclRevision);
6374 ret = AddAce(acl, ACL_REVISION2, MAXDWORD, ace, ace->Header.AceSize);
6375 ok(ret, "AddAce failed: %d\n", GetLastError());
6377 ret = AddAce(acl, MIN_ACL_REVISION-1, MAXDWORD, ace, ace->Header.AceSize);
6378 ok(ret, "AddAce failed: %d\n", GetLastError());
6379 /* next test succeededs but corrupts ACL */
6380 ret = AddAce(acl, MAX_ACL_REVISION+1, MAXDWORD, ace, ace->Header.AceSize);
6381 ok(ret, "AddAce failed: %d\n", GetLastError());
6382 ok(acl->AclRevision == MAX_ACL_REVISION+1, "acl->AclRevision = %d\n", acl->AclRevision);
6383 SetLastError(0xdeadbeef);
6384 ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize);
6385 ok(!ret, "AddAce succeeded\n");
6386 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError() = %d\n", GetLastError());
6389 static void test_AddMandatoryAce(void)
6391 static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
6392 {SECURITY_MANDATORY_LOW_RID}};
6393 static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
6394 {SECURITY_MANDATORY_MEDIUM_RID}};
6395 static SID_IDENTIFIER_AUTHORITY sia_world = {SECURITY_WORLD_SID_AUTHORITY};
6396 char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
6397 SECURITY_DESCRIPTOR *sd2, *sd = (SECURITY_DESCRIPTOR *)&buffer_sd;
6398 BOOL defaulted, present, ret;
6399 ACL_SIZE_INFORMATION acl_size_info;
6400 SYSTEM_MANDATORY_LABEL_ACE *ace;
6401 char buffer_acl[256];
6402 ACL *acl = (ACL *)&buffer_acl;
6403 SECURITY_ATTRIBUTES sa;
6404 DWORD size;
6405 HANDLE handle;
6406 SID *everyone;
6407 ACL *sacl;
6409 if (!pAddMandatoryAce)
6411 win_skip("AddMandatoryAce not supported, skipping test\n");
6412 return;
6415 ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
6416 ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
6418 sa.nLength = sizeof(sa);
6419 sa.lpSecurityDescriptor = sd;
6420 sa.bInheritHandle = FALSE;
6422 handle = CreateEventA(&sa, TRUE, TRUE, "test_event");
6423 ok(handle != NULL, "CreateEventA failed with error %u\n", GetLastError());
6425 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6426 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6427 "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
6429 sd2 = HeapAlloc(GetProcessHeap(), 0, size);
6430 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6431 ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
6433 sacl = (void *)0xdeadbeef;
6434 present = TRUE;
6435 ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6436 ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6437 ok(!present, "SACL is present\n");
6438 ok(sacl == (void *)0xdeadbeef, "SACL is set\n");
6440 HeapFree(GetProcessHeap(), 0, sd2);
6441 CloseHandle(handle);
6443 memset(buffer_acl, 0, sizeof(buffer_acl));
6444 ret = InitializeAcl(acl, 256, ACL_REVISION);
6445 ok(ret, "InitializeAcl failed with %u\n", GetLastError());
6447 SetLastError(0xdeadbeef);
6448 ret = pAddMandatoryAce(acl, ACL_REVISION, 0, 0x1234, &low_level);
6449 ok(!ret, "AddMandatoryAce succeeded\n");
6450 ok(GetLastError() == ERROR_INVALID_PARAMETER,
6451 "Expected ERROR_INVALID_PARAMETER got %u\n", GetLastError());
6453 ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level);
6454 ok(ret, "AddMandatoryAce failed with %u\n", GetLastError());
6456 ret = GetAce(acl, 0, (void **)&ace);
6457 ok(ret, "got error %u\n", GetLastError());
6458 ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "got type %#x\n", ace->Header.AceType);
6459 ok(!ace->Header.AceFlags, "got flags %#x\n", ace->Header.AceFlags);
6460 ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "got mask %#x\n", ace->Mask);
6461 ok(EqualSid(&ace->SidStart, &low_level), "wrong sid\n");
6463 SetLastError(0xdeadbeef);
6464 ret = GetAce(acl, 1, (void **)&ace);
6465 ok(!ret, "expected failure\n");
6466 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError());
6468 ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
6469 ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6471 handle = CreateEventA(&sa, TRUE, TRUE, "test_event");
6472 ok(handle != NULL, "CreateEventA failed with error %u\n", GetLastError());
6474 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6475 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6476 "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
6478 sd2 = HeapAlloc(GetProcessHeap(), 0, size);
6479 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6480 ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
6482 sacl = (void *)0xdeadbeef;
6483 present = FALSE;
6484 defaulted = TRUE;
6485 ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6486 ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6487 ok(present, "SACL not present\n");
6488 ok(sacl != (void *)0xdeadbeef, "SACL not set\n");
6489 ok(!defaulted, "SACL defaulted\n");
6490 ret = GetAclInformation(sacl, &acl_size_info, sizeof(acl_size_info), AclSizeInformation);
6491 ok(ret, "GetAclInformation failed with error %u\n", GetLastError());
6492 ok(acl_size_info.AceCount == 1, "SACL contains an unexpected ACE count %u\n", acl_size_info.AceCount);
6494 ret = GetAce(sacl, 0, (void **)&ace);
6495 ok(ret, "GetAce failed with error %u\n", GetLastError());
6496 ok (ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType);
6497 ok(!ace->Header.AceFlags, "Unexpected ACE flags %#x\n", ace->Header.AceFlags);
6498 ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "Unexpected ACE mask %#x\n", ace->Mask);
6499 ok(EqualSid(&ace->SidStart, &low_level), "Expected low integrity level\n");
6501 HeapFree(GetProcessHeap(), 0, sd2);
6503 ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level);
6504 ok(ret, "AddMandatoryAce failed with error %u\n", GetLastError());
6506 ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
6507 ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
6509 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6510 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6511 "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
6513 sd2 = HeapAlloc(GetProcessHeap(), 0, size);
6514 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6515 ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
6517 sacl = (void *)0xdeadbeef;
6518 present = FALSE;
6519 defaulted = TRUE;
6520 ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6521 ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6522 ok(present, "SACL not present\n");
6523 ok(sacl != (void *)0xdeadbeef, "SACL not set\n");
6524 ok(sacl->AceCount == 2, "Expected 2 ACEs, got %d\n", sacl->AceCount);
6525 ok(!defaulted, "SACL defaulted\n");
6527 ret = GetAce(acl, 0, (void **)&ace);
6528 ok(ret, "got error %u\n", GetLastError());
6529 ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "got type %#x\n", ace->Header.AceType);
6530 ok(!ace->Header.AceFlags, "got flags %#x\n", ace->Header.AceFlags);
6531 ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "got mask %#x\n", ace->Mask);
6532 ok(EqualSid(&ace->SidStart, &low_level), "wrong sid\n");
6534 ret = GetAce(acl, 1, (void **)&ace);
6535 ok(ret, "got error %u\n", GetLastError());
6536 ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "got type %#x\n", ace->Header.AceType);
6537 ok(!ace->Header.AceFlags, "got flags %#x\n", ace->Header.AceFlags);
6538 ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, "got mask %#x\n", ace->Mask);
6539 ok(EqualSid(&ace->SidStart, &medium_level), "wrong sid\n");
6541 SetLastError(0xdeadbeef);
6542 ret = GetAce(acl, 2, (void **)&ace);
6543 ok(!ret, "expected failure\n");
6544 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError());
6546 HeapFree(GetProcessHeap(), 0, sd2);
6548 ret = SetSecurityDescriptorSacl(sd, FALSE, NULL, FALSE);
6549 ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6551 ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
6552 ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
6554 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6555 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6556 "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
6558 sd2 = HeapAlloc(GetProcessHeap(), 0, size);
6559 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6560 ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
6562 sacl = (void *)0xdeadbeef;
6563 present = FALSE;
6564 defaulted = TRUE;
6565 ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6566 ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6567 ok(present, "SACL not present\n");
6568 ok(sacl && sacl != (void *)0xdeadbeef, "SACL not set\n");
6569 ok(!defaulted, "SACL defaulted\n");
6570 ok(!sacl->AceCount, "SACL contains an unexpected ACE count %u\n", sacl->AceCount);
6572 HeapFree(GetProcessHeap(), 0, sd2);
6574 ret = InitializeAcl(acl, 256, ACL_REVISION);
6575 ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
6577 ret = pAddMandatoryAce(acl, ACL_REVISION3, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level);
6578 ok(ret, "AddMandatoryAce failed with error %u\n", GetLastError());
6580 ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
6581 ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6583 ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
6584 ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
6586 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6587 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6588 "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
6590 sd2 = HeapAlloc(GetProcessHeap(), 0, size);
6591 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6592 ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
6594 sacl = (void *)0xdeadbeef;
6595 present = FALSE;
6596 defaulted = TRUE;
6597 ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6598 ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6599 ok(present, "SACL not present\n");
6600 ok(sacl != (void *)0xdeadbeef, "SACL not set\n");
6601 ok(sacl->AclRevision == ACL_REVISION3, "Expected revision 3, got %d\n", sacl->AclRevision);
6602 ok(!defaulted, "SACL defaulted\n");
6604 HeapFree(GetProcessHeap(), 0, sd2);
6606 ret = InitializeAcl(acl, 256, ACL_REVISION);
6607 ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
6609 ret = AllocateAndInitializeSid(&sia_world, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, (void **)&everyone);
6610 ok(ret, "AllocateAndInitializeSid failed with error %u\n", GetLastError());
6612 ret = AddAccessAllowedAce(acl, ACL_REVISION, KEY_READ, everyone);
6613 ok(ret, "AddAccessAllowedAce failed with error %u\n", GetLastError());
6615 ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
6616 ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6618 ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
6619 ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
6621 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6622 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6623 "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
6625 sd2 = HeapAlloc(GetProcessHeap(), 0, size);
6626 ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
6627 ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
6629 sacl = (void *)0xdeadbeef;
6630 present = FALSE;
6631 defaulted = TRUE;
6632 ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
6633 ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6634 ok(present, "SACL not present\n");
6635 ok(sacl && sacl != (void *)0xdeadbeef, "SACL not set\n");
6636 ok(!defaulted, "SACL defaulted\n");
6637 ok(!sacl->AceCount, "SACL contains an unexpected ACE count %u\n", sacl->AceCount);
6639 FreeSid(everyone);
6640 HeapFree(GetProcessHeap(), 0, sd2);
6641 CloseHandle(handle);
6644 static void test_system_security_access(void)
6646 static const WCHAR testkeyW[] =
6647 {'S','O','F','T','W','A','R','E','\\','W','i','n','e','\\','S','A','C','L','t','e','s','t',0};
6648 LONG res;
6649 HKEY hkey;
6650 PSECURITY_DESCRIPTOR sd;
6651 ACL *sacl;
6652 DWORD err, len = 128;
6653 TOKEN_PRIVILEGES priv, *priv_prev;
6654 HANDLE token;
6655 LUID luid;
6656 BOOL ret;
6658 if (!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &token )) return;
6659 if (!LookupPrivilegeValueA( NULL, SE_SECURITY_NAME, &luid ))
6661 CloseHandle( token );
6662 return;
6665 /* ACCESS_SYSTEM_SECURITY requires special privilege */
6666 res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ|ACCESS_SYSTEM_SECURITY, NULL, &hkey, NULL );
6667 if (res == ERROR_ACCESS_DENIED)
6669 skip( "unprivileged user\n" );
6670 CloseHandle( token );
6671 return;
6673 todo_wine ok( res == ERROR_PRIVILEGE_NOT_HELD, "got %d\n", res );
6675 priv.PrivilegeCount = 1;
6676 priv.Privileges[0].Luid = luid;
6677 priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
6679 priv_prev = HeapAlloc( GetProcessHeap(), 0, len );
6680 ret = AdjustTokenPrivileges( token, FALSE, &priv, len, priv_prev, &len );
6681 ok( ret, "got %u\n", GetLastError());
6683 res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ|ACCESS_SYSTEM_SECURITY, NULL, &hkey, NULL );
6684 if (res == ERROR_PRIVILEGE_NOT_HELD)
6686 win_skip( "privilege not held\n" );
6687 HeapFree( GetProcessHeap(), 0, priv_prev );
6688 CloseHandle( token );
6689 return;
6691 ok( !res, "got %d\n", res );
6693 /* restore privileges */
6694 ret = AdjustTokenPrivileges( token, FALSE, priv_prev, 0, NULL, NULL );
6695 ok( ret, "got %u\n", GetLastError() );
6696 HeapFree( GetProcessHeap(), 0, priv_prev );
6698 /* privilege is checked on access */
6699 err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
6700 todo_wine ok( err == ERROR_PRIVILEGE_NOT_HELD || err == ERROR_ACCESS_DENIED, "got %u\n", err );
6701 if (err == ERROR_SUCCESS)
6702 LocalFree( sd );
6704 priv.PrivilegeCount = 1;
6705 priv.Privileges[0].Luid = luid;
6706 priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
6708 priv_prev = HeapAlloc( GetProcessHeap(), 0, len );
6709 ret = AdjustTokenPrivileges( token, FALSE, &priv, len, priv_prev, &len );
6710 ok( ret, "got %u\n", GetLastError());
6712 err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
6713 ok( err == ERROR_SUCCESS, "got %u\n", err );
6714 RegCloseKey( hkey );
6715 LocalFree( sd );
6717 /* handle created without ACCESS_SYSTEM_SECURITY, privilege held */
6718 res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ, NULL, &hkey, NULL );
6719 ok( res == ERROR_SUCCESS, "got %d\n", res );
6721 sd = NULL;
6722 err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
6723 todo_wine ok( err == ERROR_SUCCESS, "got %u\n", err );
6724 RegCloseKey( hkey );
6725 LocalFree( sd );
6727 /* restore privileges */
6728 ret = AdjustTokenPrivileges( token, FALSE, priv_prev, 0, NULL, NULL );
6729 ok( ret, "got %u\n", GetLastError() );
6730 HeapFree( GetProcessHeap(), 0, priv_prev );
6732 /* handle created without ACCESS_SYSTEM_SECURITY, privilege not held */
6733 res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ, NULL, &hkey, NULL );
6734 ok( res == ERROR_SUCCESS, "got %d\n", res );
6736 err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
6737 ok( err == ERROR_PRIVILEGE_NOT_HELD || err == ERROR_ACCESS_DENIED, "got %u\n", err );
6738 RegCloseKey( hkey );
6740 res = RegDeleteKeyW( HKEY_LOCAL_MACHINE, testkeyW );
6741 ok( !res, "got %d\n", res );
6742 CloseHandle( token );
6745 static void test_GetWindowsAccountDomainSid(void)
6747 char *user, buffer1[SECURITY_MAX_SID_SIZE], buffer2[SECURITY_MAX_SID_SIZE];
6748 SID_IDENTIFIER_AUTHORITY domain_ident = { SECURITY_NT_AUTHORITY };
6749 PSID domain_sid = (PSID *)&buffer1;
6750 PSID domain_sid2 = (PSID *)&buffer2;
6751 DWORD sid_size;
6752 PSID user_sid;
6753 HANDLE token;
6754 BOOL bret = TRUE;
6755 int i;
6757 if (!pGetWindowsAccountDomainSid)
6759 win_skip("GetWindowsAccountDomainSid not available\n");
6760 return;
6763 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
6765 if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE;
6766 else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE;
6768 if (!bret)
6770 win_skip("Failed to get current user token\n");
6771 return;
6774 bret = GetTokenInformation(token, TokenUser, NULL, 0, &sid_size);
6775 ok(!bret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6776 "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
6777 user = HeapAlloc(GetProcessHeap(), 0, sid_size);
6778 bret = GetTokenInformation(token, TokenUser, user, sid_size, &sid_size);
6779 ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
6780 CloseHandle(token);
6781 user_sid = ((TOKEN_USER *)user)->User.Sid;
6783 SetLastError(0xdeadbeef);
6784 bret = pGetWindowsAccountDomainSid(0, 0, 0);
6785 ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
6786 ok(GetLastError() == ERROR_INVALID_SID, "expected ERROR_INVALID_SID, got %d\n", GetLastError());
6788 SetLastError(0xdeadbeef);
6789 bret = pGetWindowsAccountDomainSid(user_sid, 0, 0);
6790 ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
6791 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
6793 sid_size = SECURITY_MAX_SID_SIZE;
6794 SetLastError(0xdeadbeef);
6795 bret = pGetWindowsAccountDomainSid(user_sid, 0, &sid_size);
6796 ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
6797 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
6798 ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size);
6800 SetLastError(0xdeadbeef);
6801 bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, 0);
6802 ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
6803 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
6805 sid_size = 1;
6806 SetLastError(0xdeadbeef);
6807 bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, &sid_size);
6808 ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
6809 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
6810 ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size);
6812 sid_size = SECURITY_MAX_SID_SIZE;
6813 bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, &sid_size);
6814 ok(bret, "GetWindowsAccountDomainSid failed with error %d\n", GetLastError());
6815 ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size);
6816 InitializeSid(domain_sid2, &domain_ident, 4);
6817 for (i = 0; i < 4; i++)
6818 *GetSidSubAuthority(domain_sid2, i) = *GetSidSubAuthority(user_sid, i);
6819 ok(EqualSid(domain_sid, domain_sid2), "unexpected domain sid %s != %s\n",
6820 debugstr_sid(domain_sid), debugstr_sid(domain_sid2));
6822 HeapFree(GetProcessHeap(), 0, user);
6825 static void test_GetSidIdentifierAuthority(void)
6827 char buffer[SECURITY_MAX_SID_SIZE];
6828 PSID authority_sid = (PSID *)buffer;
6829 PSID_IDENTIFIER_AUTHORITY id;
6830 BOOL ret;
6832 if (!pGetSidIdentifierAuthority)
6834 win_skip("GetSidIdentifierAuthority not available\n");
6835 return;
6838 memset(buffer, 0xcc, sizeof(buffer));
6839 ret = IsValidSid(authority_sid);
6840 ok(!ret, "expected FALSE, got %u\n", ret);
6842 SetLastError(0xdeadbeef);
6843 id = GetSidIdentifierAuthority(authority_sid);
6844 ok(id != NULL, "got NULL pointer as identifier authority\n");
6845 ok(GetLastError() == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", GetLastError());
6847 SetLastError(0xdeadbeef);
6848 id = GetSidIdentifierAuthority(NULL);
6849 ok(id != NULL, "got NULL pointer as identifier authority\n");
6850 ok(GetLastError() == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", GetLastError());
6853 static void test_pseudo_tokens(void)
6855 TOKEN_STATISTICS statistics1, statistics2;
6856 HANDLE token;
6857 DWORD retlen;
6858 BOOL ret;
6860 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
6861 ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
6862 memset(&statistics1, 0x11, sizeof(statistics1));
6863 ret = GetTokenInformation(token, TokenStatistics, &statistics1, sizeof(statistics1), &retlen);
6864 ok(ret, "GetTokenInformation failed with %u\n", GetLastError());
6865 CloseHandle(token);
6867 /* test GetCurrentProcessToken() */
6868 SetLastError(0xdeadbeef);
6869 memset(&statistics2, 0x22, sizeof(statistics2));
6870 ret = GetTokenInformation(GetCurrentProcessToken(), TokenStatistics,
6871 &statistics2, sizeof(statistics2), &retlen);
6872 ok(ret || broken(GetLastError() == ERROR_INVALID_HANDLE),
6873 "GetTokenInformation failed with %u\n", GetLastError());
6874 if (ret)
6875 ok(!memcmp(&statistics1, &statistics2, sizeof(statistics1)), "Token statistics do not match\n");
6876 else
6877 win_skip("CurrentProcessToken not supported, skipping test\n");
6879 /* test GetCurrentThreadEffectiveToken() */
6880 SetLastError(0xdeadbeef);
6881 memset(&statistics2, 0x22, sizeof(statistics2));
6882 ret = GetTokenInformation(GetCurrentThreadEffectiveToken(), TokenStatistics,
6883 &statistics2, sizeof(statistics2), &retlen);
6884 ok(ret || broken(GetLastError() == ERROR_INVALID_HANDLE),
6885 "GetTokenInformation failed with %u\n", GetLastError());
6886 if (ret)
6887 ok(!memcmp(&statistics1, &statistics2, sizeof(statistics1)), "Token statistics do not match\n");
6888 else
6889 win_skip("CurrentThreadEffectiveToken not supported, skipping test\n");
6891 SetLastError(0xdeadbeef);
6892 ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &token);
6893 ok(!ret, "OpenThreadToken should have failed\n");
6894 ok(GetLastError() == ERROR_NO_TOKEN, "Expected ERROR_NO_TOKEN, got %u\n", GetLastError());
6896 /* test GetCurrentThreadToken() */
6897 SetLastError(0xdeadbeef);
6898 ret = GetTokenInformation(GetCurrentThreadToken(), TokenStatistics,
6899 &statistics2, sizeof(statistics2), &retlen);
6900 todo_wine ok(GetLastError() == ERROR_NO_TOKEN || broken(GetLastError() == ERROR_INVALID_HANDLE),
6901 "Expected ERROR_NO_TOKEN, got %u\n", GetLastError());
6904 static void test_maximum_allowed(void)
6906 HANDLE (WINAPI *pCreateEventExA)(SECURITY_ATTRIBUTES *, LPCSTR, DWORD, DWORD);
6907 char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH], buffer_acl[256];
6908 SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)&buffer_sd;
6909 SECURITY_ATTRIBUTES sa;
6910 ACL *acl = (ACL *)&buffer_acl;
6911 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
6912 ACCESS_MASK mask;
6913 HANDLE handle;
6914 BOOL ret;
6916 pCreateEventExA = (void *)GetProcAddress(hkernel32, "CreateEventExA");
6917 if (!pCreateEventExA)
6919 win_skip("CreateEventExA is not available\n");
6920 return;
6923 ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
6924 ok(ret, "InitializeSecurityDescriptor failed with %u\n", GetLastError());
6925 memset(buffer_acl, 0, sizeof(buffer_acl));
6926 ret = InitializeAcl(acl, 256, ACL_REVISION);
6927 ok(ret, "InitializeAcl failed with %u\n", GetLastError());
6928 ret = SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE);
6929 ok(ret, "SetSecurityDescriptorDacl failed with %u\n", GetLastError());
6931 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
6932 sa.lpSecurityDescriptor = sd;
6933 sa.bInheritHandle = FALSE;
6935 handle = pCreateEventExA(&sa, NULL, 0, MAXIMUM_ALLOWED | 0x4);
6936 ok(handle != NULL, "CreateEventExA failed with error %u\n", GetLastError());
6937 mask = get_obj_access(handle);
6938 ok(mask == EVENT_ALL_ACCESS, "Expected %x, got %x\n", EVENT_ALL_ACCESS, mask);
6939 CloseHandle(handle);
6942 static void test_token_label(void)
6944 static SID medium_sid = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
6945 {SECURITY_MANDATORY_MEDIUM_RID}};
6946 static SID high_sid = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
6947 {SECURITY_MANDATORY_HIGH_RID}};
6948 SECURITY_DESCRIPTOR_CONTROL control;
6949 SYSTEM_MANDATORY_LABEL_ACE *ace;
6950 BOOL ret, present, defaulted;
6951 SECURITY_DESCRIPTOR *sd;
6952 ACL *sacl = NULL, *dacl;
6953 DWORD size, revision;
6954 HANDLE token;
6955 char *str;
6956 SID *sid;
6958 if (!pAddMandatoryAce)
6960 win_skip("Mandatory integrity control is not supported.\n");
6961 return;
6964 ret = OpenProcessToken(GetCurrentProcess(), READ_CONTROL | WRITE_OWNER, &token);
6965 ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
6967 ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
6968 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
6969 "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
6971 sd = HeapAlloc(GetProcessHeap(), 0, size);
6972 ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size);
6973 ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
6975 ret = GetSecurityDescriptorControl(sd, &control, &revision);
6976 ok(ret, "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
6977 todo_wine ok(control == (SE_SELF_RELATIVE | SE_SACL_AUTO_INHERITED | SE_SACL_PRESENT),
6978 "Unexpected security descriptor control %#x\n", control);
6979 ok(revision == 1, "Unexpected security descriptor revision %u\n", revision);
6981 sid = (void *)0xdeadbeef;
6982 defaulted = TRUE;
6983 ret = GetSecurityDescriptorOwner(sd, (void **)&sid, &defaulted);
6984 ok(ret, "GetSecurityDescriptorOwner failed with error %u\n", GetLastError());
6985 ok(!sid, "Owner present\n");
6986 ok(!defaulted, "Owner defaulted\n");
6988 sid = (void *)0xdeadbeef;
6989 defaulted = TRUE;
6990 ret = GetSecurityDescriptorGroup(sd, (void **)&sid, &defaulted);
6991 ok(ret, "GetSecurityDescriptorGroup failed with error %u\n", GetLastError());
6992 ok(!sid, "Group present\n");
6993 ok(!defaulted, "Group defaulted\n");
6995 ret = GetSecurityDescriptorSacl(sd, &present, &sacl, &defaulted);
6996 ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
6997 ok(present, "No SACL in the security descriptor\n");
6998 ok(!!sacl, "NULL SACL in the security descriptor\n");
6999 ok(!defaulted, "SACL defaulted\n");
7000 ok(sacl->AceCount == 1, "SACL contains an unexpected ACE count %u\n", sacl->AceCount);
7002 ret = GetAce(sacl, 0, (void **)&ace);
7003 ok(ret, "GetAce failed with error %u\n", GetLastError());
7005 ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
7006 "Unexpected ACE type %#x\n", ace->Header.AceType);
7007 ok(!ace->Header.AceFlags, "Unexpected ACE flags %#x\n", ace->Header.AceFlags);
7008 ok(ace->Header.AceSize, "Unexpected ACE size %u\n", ace->Header.AceSize);
7009 ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "Unexpected ACE mask %#x\n", ace->Mask);
7011 sid = (SID *)&ace->SidStart;
7012 ConvertSidToStringSidA(sid, &str);
7013 ok(EqualSid(sid, &medium_sid) || EqualSid(sid, &high_sid), "Got unexpected SID %s\n", str);
7014 LocalFree(str);
7016 ret = GetSecurityDescriptorDacl(sd, &present, &dacl, &defaulted);
7017 ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
7018 todo_wine ok(!present, "DACL present\n");
7020 HeapFree(GetProcessHeap(), 0, sd);
7021 CloseHandle(token);
7024 static void test_token_security_descriptor(void)
7026 static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
7027 {SECURITY_MANDATORY_LOW_RID}};
7028 char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
7029 SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)&buffer_sd, *sd2;
7030 char buffer_acl[256], buffer[MAX_PATH];
7031 ACL *acl = (ACL *)&buffer_acl, *acl2, *acl_child;
7032 BOOL defaulted, present, ret, found;
7033 HANDLE token, token2, token3;
7034 EXPLICIT_ACCESSW exp_access;
7035 PROCESS_INFORMATION info;
7036 DWORD size, index, retd;
7037 ACCESS_ALLOWED_ACE *ace;
7038 SECURITY_ATTRIBUTES sa;
7039 STARTUPINFOA startup;
7040 PSID psid;
7042 if (!pDuplicateTokenEx || !pAddAccessAllowedAceEx || !pSetEntriesInAclW)
7044 win_skip("Some functions not available\n");
7045 return;
7048 /* Test whether we can create tokens with security descriptors */
7049 ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
7050 ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
7052 ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
7053 ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
7055 memset(buffer_acl, 0, sizeof(buffer_acl));
7056 ret = InitializeAcl(acl, 256, ACL_REVISION);
7057 ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
7059 ret = ConvertStringSidToSidA("S-1-5-6", &psid);
7060 ok(ret, "ConvertStringSidToSidA failed with error %u\n", GetLastError());
7062 ret = pAddAccessAllowedAceEx(acl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, GENERIC_ALL, psid);
7063 ok(ret, "AddAccessAllowedAceEx failed with error %u\n", GetLastError());
7065 ret = SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE);
7066 ok(ret, "SetSecurityDescriptorDacl failed with error %u\n", GetLastError());
7068 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
7069 sa.lpSecurityDescriptor = sd;
7070 sa.bInheritHandle = FALSE;
7072 ret = pDuplicateTokenEx(token, MAXIMUM_ALLOWED, &sa, SecurityImpersonation, TokenImpersonation, &token2);
7073 ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
7075 ret = GetKernelObjectSecurity(token2, DACL_SECURITY_INFORMATION, NULL, 0, &size);
7076 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7077 "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
7079 sd2 = HeapAlloc(GetProcessHeap(), 0, size);
7080 ret = GetKernelObjectSecurity(token2, DACL_SECURITY_INFORMATION, sd2, size, &size);
7081 ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7083 acl2 = (void *)0xdeadbeef;
7084 present = FALSE;
7085 defaulted = TRUE;
7086 ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted);
7087 ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
7088 ok(present, "acl2 not present\n");
7089 ok(acl2 != (void *)0xdeadbeef, "acl2 not set\n");
7090 ok(acl2->AceCount == 1, "Expected 1 ACE, got %d\n", acl2->AceCount);
7091 ok(!defaulted, "acl2 defaulted\n");
7093 ret = GetAce(acl2, 0, (void **)&ace);
7094 ok(ret, "GetAce failed with error %u\n", GetLastError());
7095 ok(ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType);
7096 ok(EqualSid(&ace->SidStart, psid), "Expected access allowed ACE\n");
7097 ok(ace->Header.AceFlags == NO_PROPAGATE_INHERIT_ACE,
7098 "Expected NO_PROPAGATE_INHERIT_ACE as flags, got %x\n", ace->Header.AceFlags);
7100 HeapFree(GetProcessHeap(), 0, sd2);
7102 /* Duplicate token without security attributes.
7103 * Tokens do not inherit the security descriptor in DuplicateToken. */
7104 ret = pDuplicateTokenEx(token2, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenImpersonation, &token3);
7105 ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
7107 ret = GetKernelObjectSecurity(token3, DACL_SECURITY_INFORMATION, NULL, 0, &size);
7108 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7109 "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
7111 sd2 = HeapAlloc(GetProcessHeap(), 0, size);
7112 ret = GetKernelObjectSecurity(token3, DACL_SECURITY_INFORMATION, sd2, size, &size);
7113 ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7115 acl2 = (void *)0xdeadbeef;
7116 present = FALSE;
7117 defaulted = TRUE;
7118 ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted);
7119 ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
7120 todo_wine
7121 ok(present, "DACL not present\n");
7123 if (present)
7125 ok(acl2 != (void *)0xdeadbeef, "DACL not set\n");
7126 ok(!defaulted, "DACL defaulted\n");
7128 index = 0;
7129 found = FALSE;
7130 while (GetAce(acl2, index++, (void **)&ace))
7132 if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE && EqualSid(&ace->SidStart, psid))
7133 found = TRUE;
7135 ok(!found, "Access allowed ACE was inherited\n");
7138 HeapFree(GetProcessHeap(), 0, sd2);
7140 /* When creating a child process, the process does inherit the token of
7141 * the parent but not the DACL of the token */
7142 ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, NULL, 0, &size);
7143 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7144 "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
7146 sd2 = HeapAlloc(GetProcessHeap(), 0, size);
7147 ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd2, size, &size);
7148 ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7150 acl2 = (void *)0xdeadbeef;
7151 present = FALSE;
7152 defaulted = TRUE;
7153 ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted);
7154 ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
7155 ok(present, "DACL not present\n");
7156 ok(acl2 != (void *)0xdeadbeef, "DACL not set\n");
7157 ok(!defaulted, "DACL defaulted\n");
7159 exp_access.grfAccessPermissions = GENERIC_ALL;
7160 exp_access.grfAccessMode = GRANT_ACCESS;
7161 exp_access.grfInheritance = NO_PROPAGATE_INHERIT_ACE;
7162 exp_access.Trustee.pMultipleTrustee = NULL;
7163 exp_access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
7164 exp_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
7165 exp_access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
7166 exp_access.Trustee.ptstrName = (void*)psid;
7168 retd = pSetEntriesInAclW(1, &exp_access, acl2, &acl_child);
7169 ok(retd == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", retd);
7171 memset(sd, 0, sizeof(buffer_sd));
7172 ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
7173 ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
7175 ret = SetSecurityDescriptorDacl(sd, TRUE, acl_child, FALSE);
7176 ok(ret, "SetSecurityDescriptorDacl failed with error %u\n", GetLastError());
7178 ret = SetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd);
7179 ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
7181 /* The security label is also not inherited */
7182 if (pAddMandatoryAce)
7184 ret = InitializeAcl(acl, 256, ACL_REVISION);
7185 ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
7187 ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level);
7188 ok(ret, "AddMandatoryAce failed with error %u\n", GetLastError());
7190 memset(sd, 0, sizeof(buffer_sd));
7191 ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
7192 ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
7194 ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
7195 ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
7197 ret = SetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd);
7198 ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
7200 else
7201 win_skip("SYSTEM_MANDATORY_LABEL not supported\n");
7203 /* Start child process with our modified token */
7204 memset(&startup, 0, sizeof(startup));
7205 startup.cb = sizeof(startup);
7206 startup.dwFlags = STARTF_USESHOWWINDOW;
7207 startup.wShowWindow = SW_SHOWNORMAL;
7209 sprintf(buffer, "%s security test_token_sd", myARGV[0]);
7210 ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info);
7211 ok(ret, "CreateProcess failed with error %u\n", GetLastError());
7212 wait_child_process(info.hProcess);
7213 CloseHandle(info.hProcess);
7214 CloseHandle(info.hThread);
7216 LocalFree(acl_child);
7217 HeapFree(GetProcessHeap(), 0, sd2);
7218 LocalFree(psid);
7220 CloseHandle(token3);
7221 CloseHandle(token2);
7222 CloseHandle(token);
7225 static void test_child_token_sd(void)
7227 static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
7228 {SECURITY_MANDATORY_LOW_RID}};
7229 SYSTEM_MANDATORY_LABEL_ACE *ace_label;
7230 BOOL ret, present, defaulted;
7231 ACCESS_ALLOWED_ACE *acc_ace;
7232 SECURITY_DESCRIPTOR *sd;
7233 DWORD size, i;
7234 HANDLE token;
7235 PSID psid;
7236 ACL *acl;
7238 ret = ConvertStringSidToSidA("S-1-5-6", &psid);
7239 ok(ret, "ConvertStringSidToSidA failed with error %u\n", GetLastError());
7241 ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
7242 ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
7244 ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, NULL, 0, &size);
7245 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7246 "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
7248 sd = HeapAlloc(GetProcessHeap(), 0, size);
7249 ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd, size, &size);
7250 ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7252 acl = NULL;
7253 present = FALSE;
7254 defaulted = TRUE;
7255 ret = GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted);
7256 ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
7257 ok(present, "DACL not present\n");
7258 ok(acl && acl != (void *)0xdeadbeef, "Got invalid DACL\n");
7259 ok(!defaulted, "DACL defaulted\n");
7261 ok(acl->AceCount, "Expected at least one ACE\n");
7262 for (i = 0; i < acl->AceCount; i++)
7264 ret = GetAce(acl, i, (void **)&acc_ace);
7265 ok(ret, "GetAce failed with error %u\n", GetLastError());
7266 ok(acc_ace->Header.AceType != ACCESS_ALLOWED_ACE_TYPE || !EqualSid(&acc_ace->SidStart, psid),
7267 "ACE inherited from the parent\n");
7270 LocalFree(psid);
7271 HeapFree(GetProcessHeap(), 0, sd);
7273 if (!pAddMandatoryAce)
7275 win_skip("SYSTEM_MANDATORY_LABEL not supported\n");
7276 return;
7279 ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
7280 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
7281 "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
7283 sd = HeapAlloc(GetProcessHeap(), 0, size);
7284 ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size);
7285 ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
7287 acl = NULL;
7288 present = FALSE;
7289 defaulted = TRUE;
7290 ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted);
7291 ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
7292 ok(present, "SACL not present\n");
7293 ok(acl && acl != (void *)0xdeadbeef, "Got invalid SACL\n");
7294 ok(!defaulted, "SACL defaulted\n");
7295 ok(acl->AceCount == 1, "Expected exactly one ACE\n");
7296 ret = GetAce(acl, 0, (void **)&ace_label);
7297 ok(ret, "GetAce failed with error %u\n", GetLastError());
7298 ok(ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
7299 "Unexpected ACE type %#x\n", ace_label->Header.AceType);
7300 ok(!EqualSid(&ace_label->SidStart, &low_level),
7301 "Low integrity level should not have been inherited\n");
7303 HeapFree(GetProcessHeap(), 0, sd);
7306 static void test_GetExplicitEntriesFromAclW(void)
7308 static const WCHAR wszCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'};
7309 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
7310 SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
7311 PSID everyone_sid = NULL, users_sid = NULL;
7312 EXPLICIT_ACCESSW access;
7313 EXPLICIT_ACCESSW *access2;
7314 PACL new_acl, old_acl = NULL;
7315 ULONG count;
7316 DWORD res;
7318 if (!pGetExplicitEntriesFromAclW)
7320 win_skip("GetExplicitEntriesFromAclW is not available\n");
7321 return;
7324 if (!pSetEntriesInAclW)
7326 win_skip("SetEntriesInAclW is not available\n");
7327 return;
7330 old_acl = HeapAlloc(GetProcessHeap(), 0, 256);
7331 res = InitializeAcl(old_acl, 256, ACL_REVISION);
7332 if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
7334 win_skip("ACLs not implemented - skipping tests\n");
7335 HeapFree(GetProcessHeap(), 0, old_acl);
7336 return;
7338 ok(res, "InitializeAcl failed with error %d\n", GetLastError());
7340 res = AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyone_sid);
7341 ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
7343 res = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
7344 DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &users_sid);
7345 ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
7347 res = AddAccessAllowedAce(old_acl, ACL_REVISION, KEY_READ, users_sid);
7348 ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
7350 access2 = NULL;
7351 res = pGetExplicitEntriesFromAclW(old_acl, &count, &access2);
7352 ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
7353 ok(count == 1, "Expected count == 1, got %d\n", count);
7354 ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
7355 ok(access2[0].grfAccessPermissions == KEY_READ, "Expected KEY_READ, got %d\n", access2[0].grfAccessPermissions);
7356 ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
7357 ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
7358 ok(EqualSid(access2[0].Trustee.ptstrName, users_sid), "Expected equal SIDs\n");
7359 LocalFree(access2);
7361 access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
7362 access.Trustee.pMultipleTrustee = NULL;
7364 access.grfAccessPermissions = KEY_WRITE;
7365 access.grfAccessMode = GRANT_ACCESS;
7366 access.grfInheritance = NO_INHERITANCE;
7367 access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
7368 access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
7369 access.Trustee.ptstrName = everyone_sid;
7370 res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
7371 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
7372 ok(new_acl != NULL, "returned acl was NULL\n");
7374 access2 = NULL;
7375 res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
7376 ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
7377 ok(count == 2, "Expected count == 2, got %d\n", count);
7378 ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
7379 ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions);
7380 ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
7381 "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
7382 ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
7383 ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
7384 ok(EqualSid(access2[0].Trustee.ptstrName, everyone_sid), "Expected equal SIDs\n");
7385 LocalFree(access2);
7386 LocalFree(new_acl);
7388 access.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
7389 res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
7390 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
7391 ok(new_acl != NULL, "returned acl was NULL\n");
7393 access2 = NULL;
7394 res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
7395 ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
7396 ok(count == 2, "Expected count == 2, got %d\n", count);
7397 ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
7398 ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions);
7399 ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
7400 "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
7401 ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
7402 ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
7403 ok(EqualSid(access2[0].Trustee.ptstrName, everyone_sid), "Expected equal SIDs\n");
7404 LocalFree(access2);
7405 LocalFree(new_acl);
7407 access.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
7408 access.Trustee.ptstrName = (LPWSTR)wszCurrentUser;
7409 res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
7410 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
7411 ok(new_acl != NULL, "returned acl was NULL\n");
7413 access2 = NULL;
7414 res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
7415 ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
7416 ok(count == 2, "Expected count == 2, got %d\n", count);
7417 ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
7418 ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions);
7419 ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
7420 "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
7421 ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
7422 ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
7423 LocalFree(access2);
7424 LocalFree(new_acl);
7426 access.grfAccessMode = REVOKE_ACCESS;
7427 access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
7428 access.Trustee.ptstrName = users_sid;
7429 res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
7430 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
7431 ok(new_acl != NULL, "returned acl was NULL\n");
7433 access2 = (void *)0xdeadbeef;
7434 res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
7435 ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
7436 ok(count == 0, "Expected count == 0, got %d\n", count);
7437 ok(access2 == NULL, "access2 was not NULL\n");
7438 LocalFree(new_acl);
7440 /* Make the ACL both Allow and Deny Everyone. */
7441 res = AddAccessAllowedAce(old_acl, ACL_REVISION, KEY_READ, everyone_sid);
7442 ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
7443 res = AddAccessDeniedAce(old_acl, ACL_REVISION, KEY_WRITE, everyone_sid);
7444 ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError());
7445 /* Revoke Everyone. */
7446 access.Trustee.ptstrName = everyone_sid;
7447 access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
7448 access.grfAccessPermissions = 0;
7449 new_acl = NULL;
7450 res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
7451 ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
7452 ok(new_acl != NULL, "returned acl was NULL\n");
7453 /* Deny Everyone should remain (along with Grant Users from earlier). */
7454 access2 = NULL;
7455 res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
7456 ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
7457 ok(count == 2, "Expected count == 2, got %d\n", count);
7458 ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
7459 ok(access2[0].grfAccessPermissions == KEY_READ , "Expected KEY_READ, got %d\n", access2[0].grfAccessPermissions);
7460 ok(EqualSid(access2[0].Trustee.ptstrName, users_sid), "Expected equal SIDs\n");
7461 ok(access2[1].grfAccessMode == DENY_ACCESS, "Expected DENY_ACCESS, got %d\n", access2[1].grfAccessMode);
7462 ok(access2[1].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[1].grfAccessPermissions);
7463 ok(EqualSid(access2[1].Trustee.ptstrName, everyone_sid), "Expected equal SIDs\n");
7464 LocalFree(access2);
7466 FreeSid(users_sid);
7467 FreeSid(everyone_sid);
7468 HeapFree(GetProcessHeap(), 0, old_acl);
7471 static void test_BuildSecurityDescriptorW(void)
7473 SECURITY_DESCRIPTOR old_sd, *new_sd, *rel_sd;
7474 ULONG new_sd_size;
7475 DWORD buf_size;
7476 char buf[1024];
7477 BOOL success;
7478 DWORD ret;
7480 InitializeSecurityDescriptor(&old_sd, SECURITY_DESCRIPTOR_REVISION);
7482 buf_size = sizeof(buf);
7483 rel_sd = (SECURITY_DESCRIPTOR *)buf;
7484 success = MakeSelfRelativeSD(&old_sd, rel_sd, &buf_size);
7485 ok(success, "MakeSelfRelativeSD failed with %u\n", GetLastError());
7487 new_sd = NULL;
7488 new_sd_size = 0;
7489 ret = BuildSecurityDescriptorW(NULL, NULL, 0, NULL, 0, NULL, NULL, &new_sd_size, (void **)&new_sd);
7490 ok(ret == ERROR_SUCCESS, "BuildSecurityDescriptor failed with %u\n", ret);
7491 ok(new_sd != NULL, "expected new_sd != NULL\n");
7492 LocalFree(new_sd);
7494 new_sd = (void *)0xdeadbeef;
7495 ret = BuildSecurityDescriptorW(NULL, NULL, 0, NULL, 0, NULL, &old_sd, &new_sd_size, (void **)&new_sd);
7496 ok(ret == ERROR_INVALID_SECURITY_DESCR, "expected ERROR_INVALID_SECURITY_DESCR, got %u\n", ret);
7497 ok(new_sd == (void *)0xdeadbeef, "expected new_sd == 0xdeadbeef, got %p\n", new_sd);
7499 new_sd = NULL;
7500 new_sd_size = 0;
7501 ret = BuildSecurityDescriptorW(NULL, NULL, 0, NULL, 0, NULL, rel_sd, &new_sd_size, (void **)&new_sd);
7502 ok(ret == ERROR_SUCCESS, "BuildSecurityDescriptor failed with %u\n", ret);
7503 ok(new_sd != NULL, "expected new_sd != NULL\n");
7504 LocalFree(new_sd);
7507 static void test_EqualDomainSid(void)
7509 SID_IDENTIFIER_AUTHORITY ident = { SECURITY_NT_AUTHORITY };
7510 char sid_buffer[SECURITY_MAX_SID_SIZE], sid_buffer2[SECURITY_MAX_SID_SIZE];
7511 PSID domainsid, sid = sid_buffer, sid2 = sid_buffer2;
7512 DWORD size;
7513 BOOL ret, equal;
7514 unsigned int i;
7516 if (!pEqualDomainSid)
7518 win_skip("EqualDomainSid not available\n");
7519 return;
7522 ret = AllocateAndInitializeSid(&ident, 6, SECURITY_NT_NON_UNIQUE, 12, 23, 34, 45, 56, 0, 0, &domainsid);
7523 ok(ret, "AllocateAndInitializeSid error %u\n", GetLastError());
7525 SetLastError(0xdeadbeef);
7526 ret = pEqualDomainSid(NULL, NULL, NULL);
7527 ok(!ret, "got %d\n", ret);
7528 ok(GetLastError() == ERROR_INVALID_SID, "got %u\n", GetLastError());
7530 SetLastError(0xdeadbeef);
7531 ret = pEqualDomainSid(domainsid, domainsid, NULL);
7532 ok(!ret, "got %d\n", ret);
7533 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u\n", GetLastError());
7535 for (i = 0; i < ARRAY_SIZE(well_known_sid_values); i++)
7537 SID *pisid = sid;
7539 size = sizeof(sid_buffer);
7540 if (!CreateWellKnownSid(i, NULL, sid, &size))
7542 trace("Well known SID %u not supported\n", i);
7543 continue;
7546 equal = 0xdeadbeef;
7547 SetLastError(0xdeadbeef);
7548 ret = pEqualDomainSid(sid, domainsid, &equal);
7549 if (pisid->SubAuthority[0] != SECURITY_BUILTIN_DOMAIN_RID)
7551 ok(!ret, "%u: got %d\n", i, ret);
7552 ok(GetLastError() == ERROR_NON_DOMAIN_SID, "%u: got %u\n", i, GetLastError());
7553 ok(equal == 0xdeadbeef, "%u: got %d\n", i, equal);
7554 continue;
7557 ok(ret, "%u: got %d\n", i, ret);
7558 ok(GetLastError() == 0, "%u: got %u\n", i, GetLastError());
7559 ok(equal == 0, "%u: got %d\n", i, equal);
7561 size = sizeof(sid_buffer2);
7562 ret = CreateWellKnownSid(i, well_known_sid_values[i].without_domain ? NULL : domainsid, sid2, &size);
7563 ok(ret, "%u: CreateWellKnownSid error %u\n", i, GetLastError());
7565 equal = 0xdeadbeef;
7566 SetLastError(0xdeadbeef);
7567 ret = pEqualDomainSid(sid, sid2, &equal);
7568 ok(ret, "%u: got %d\n", i, ret);
7569 ok(GetLastError() == 0, "%u: got %u\n", i, GetLastError());
7570 ok(equal == 1, "%u: got %d\n", i, equal);
7573 FreeSid(domainsid);
7576 static DWORD WINAPI duplicate_handle_access_thread(void *arg)
7578 HANDLE event = arg, event2;
7579 BOOL ret;
7581 event2 = OpenEventA(SYNCHRONIZE, FALSE, "test_dup");
7582 ok(!!event2, "got error %u\n", GetLastError());
7583 CloseHandle(event2);
7585 event2 = OpenEventA(EVENT_MODIFY_STATE, FALSE, "test_dup");
7586 ok(!!event2, "got error %u\n", GetLastError());
7587 CloseHandle(event2);
7589 ret = DuplicateHandle(GetCurrentProcess(), event, GetCurrentProcess(),
7590 &event2, EVENT_MODIFY_STATE, FALSE, 0);
7591 ok(ret, "got error %u\n", GetLastError());
7592 CloseHandle(event2);
7594 return 0;
7597 static void test_duplicate_handle_access(void)
7599 char acl_buffer[200], everyone_sid_buffer[100], local_sid_buffer[100], cmdline[300];
7600 HANDLE token, restricted, impersonation, all_event, sync_event, event2, thread;
7601 SECURITY_ATTRIBUTES sa = {.nLength = sizeof(sa)};
7602 SID *everyone_sid = (SID *)everyone_sid_buffer;
7603 SID *local_sid = (SID *)local_sid_buffer;
7604 ACL *acl = (ACL *)acl_buffer;
7605 SID_AND_ATTRIBUTES sid_attr;
7606 SECURITY_DESCRIPTOR sd;
7607 PROCESS_INFORMATION pi;
7608 STARTUPINFOA si = {0};
7609 DWORD size;
7610 BOOL ret;
7612 /* DuplicateHandle() validates access against the calling thread's token and
7613 * the target process's token. It does *not* validate access against the
7614 * calling process's token, even if the calling thread is not impersonating.
7617 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, &token);
7618 ok(ret, "got error %u\n", GetLastError());
7620 size = sizeof(everyone_sid_buffer);
7621 ret = CreateWellKnownSid(WinWorldSid, NULL, everyone_sid, &size);
7622 ok(ret, "got error %u\n", GetLastError());
7623 size = sizeof(local_sid_buffer);
7624 ret = CreateWellKnownSid(WinLocalSid, NULL, local_sid, &size);
7625 ok(ret, "got error %u\n", GetLastError());
7627 InitializeAcl(acl, sizeof(acl_buffer), ACL_REVISION);
7628 ret = AddAccessAllowedAce(acl, ACL_REVISION, SYNCHRONIZE, everyone_sid);
7629 ok(ret, "got error %u\n", GetLastError());
7630 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
7631 ret = AddAccessAllowedAce(acl, ACL_REVISION, EVENT_MODIFY_STATE, local_sid);
7632 ok(ret, "got error %u\n", GetLastError());
7633 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
7634 ret = SetSecurityDescriptorDacl(&sd, TRUE, acl, FALSE);
7635 ok(ret, "got error %u\n", GetLastError());
7636 sa.lpSecurityDescriptor = &sd;
7638 sid_attr.Sid = local_sid;
7639 sid_attr.Attributes = 0;
7640 ret = CreateRestrictedToken(token, 0, 1, &sid_attr, 0, NULL, 0, NULL, &restricted);
7641 ok(ret, "got error %u\n", GetLastError());
7642 ret = DuplicateTokenEx(restricted, TOKEN_IMPERSONATE, NULL,
7643 SecurityImpersonation, TokenImpersonation, &impersonation);
7644 ok(ret, "got error %u\n", GetLastError());
7646 all_event = CreateEventA(&sa, TRUE, TRUE, "test_dup");
7647 ok(!!all_event, "got error %u\n", GetLastError());
7648 sync_event = OpenEventA(SYNCHRONIZE, FALSE, "test_dup");
7649 ok(!!sync_event, "got error %u\n", GetLastError());
7651 event2 = OpenEventA(SYNCHRONIZE, FALSE, "test_dup");
7652 ok(!!event2, "got error %u\n", GetLastError());
7653 CloseHandle(event2);
7655 event2 = OpenEventA(EVENT_MODIFY_STATE, FALSE, "test_dup");
7656 ok(!!event2, "got error %u\n", GetLastError());
7657 CloseHandle(event2);
7659 ret = DuplicateHandle(GetCurrentProcess(), all_event, GetCurrentProcess(), &event2, EVENT_MODIFY_STATE, FALSE, 0);
7660 ok(ret, "got error %u\n", GetLastError());
7661 CloseHandle(event2);
7663 ret = DuplicateHandle(GetCurrentProcess(), sync_event, GetCurrentProcess(), &event2, EVENT_MODIFY_STATE, FALSE, 0);
7664 ok(ret, "got error %u\n", GetLastError());
7665 CloseHandle(event2);
7667 ret = SetThreadToken(NULL, impersonation);
7668 ok(ret, "got error %u\n", GetLastError());
7670 thread = CreateThread(NULL, 0, duplicate_handle_access_thread, sync_event, 0, NULL);
7671 ret = WaitForSingleObject(thread, 1000);
7672 ok(!ret, "wait failed\n");
7674 event2 = OpenEventA(SYNCHRONIZE, FALSE, "test_dup");
7675 ok(!!event2, "got error %u\n", GetLastError());
7676 CloseHandle(event2);
7678 SetLastError(0xdeadbeef);
7679 event2 = OpenEventA(EVENT_MODIFY_STATE, FALSE, "test_dup");
7680 ok(!event2, "expected failure\n");
7681 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
7683 ret = DuplicateHandle(GetCurrentProcess(), all_event, GetCurrentProcess(), &event2, EVENT_MODIFY_STATE, FALSE, 0);
7684 ok(ret, "got error %u\n", GetLastError());
7685 CloseHandle(event2);
7687 SetLastError(0xdeadbeef);
7688 ret = DuplicateHandle(GetCurrentProcess(), sync_event, GetCurrentProcess(), &event2, EVENT_MODIFY_STATE, FALSE, 0);
7689 ok(!ret, "expected failure\n");
7690 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
7692 ret = RevertToSelf();
7693 ok(ret, "got error %u\n", GetLastError());
7695 sprintf(cmdline, "%s security duplicate %Iu %u %Iu", myARGV[0],
7696 (ULONG_PTR)sync_event, GetCurrentProcessId(), (ULONG_PTR)impersonation );
7697 ret = CreateProcessAsUserA(restricted, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
7698 ok(ret, "got error %u\n", GetLastError());
7700 ret = DuplicateHandle(GetCurrentProcess(), all_event, pi.hProcess, &event2, EVENT_MODIFY_STATE, FALSE, 0);
7701 ok(ret, "got error %u\n", GetLastError());
7703 SetLastError(0xdeadbeef);
7704 ret = DuplicateHandle(GetCurrentProcess(), sync_event, pi.hProcess, &event2, EVENT_MODIFY_STATE, FALSE, 0);
7705 ok(!ret, "expected failure\n");
7706 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
7708 ret = WaitForSingleObject(pi.hProcess, 1000);
7709 ok(!ret, "wait failed\n");
7711 CloseHandle(impersonation);
7712 CloseHandle(restricted);
7713 CloseHandle(token);
7714 CloseHandle(sync_event);
7715 CloseHandle(all_event);
7718 static void test_duplicate_handle_access_child(void)
7720 HANDLE event, event2, process, token;
7721 BOOL ret;
7723 event = (HANDLE)(ULONG_PTR)_atoi64(myARGV[3]);
7724 process = OpenProcess(PROCESS_DUP_HANDLE, FALSE, atoi(myARGV[4]));
7725 ok(!!process, "failed to open process, error %u\n", GetLastError());
7727 event2 = OpenEventA(SYNCHRONIZE, FALSE, "test_dup");
7728 ok(!!event2, "got error %u\n", GetLastError());
7729 CloseHandle(event2);
7731 SetLastError(0xdeadbeef);
7732 event2 = OpenEventA(EVENT_MODIFY_STATE, FALSE, "test_dup");
7733 ok(!event2, "expected failure\n");
7734 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
7736 ret = DuplicateHandle(process, event, process, &event2, EVENT_MODIFY_STATE, FALSE, 0);
7737 ok(ret, "got error %u\n", GetLastError());
7739 SetLastError(0xdeadbeef);
7740 ret = DuplicateHandle(process, event, GetCurrentProcess(), &event2, EVENT_MODIFY_STATE, FALSE, 0);
7741 ok(!ret, "expected failure\n");
7742 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
7744 ret = DuplicateHandle(process, (HANDLE)(ULONG_PTR)_atoi64(myARGV[5]),
7745 GetCurrentProcess(), &token, 0, FALSE, DUPLICATE_SAME_ACCESS);
7746 ok(ret, "failed to retrieve token, error %u\n", GetLastError());
7747 ret = SetThreadToken(NULL, token);
7748 ok(ret, "failed to set thread token, error %u\n", GetLastError());
7750 SetLastError(0xdeadbeef);
7751 ret = DuplicateHandle(process, event, process, &event2, EVENT_MODIFY_STATE, FALSE, 0);
7752 ok(!ret, "expected failure\n");
7753 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
7755 SetLastError(0xdeadbeef);
7756 ret = DuplicateHandle(process, event, GetCurrentProcess(), &event2, EVENT_MODIFY_STATE, FALSE, 0);
7757 ok(!ret, "expected failure\n");
7758 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
7760 ret = RevertToSelf();
7761 ok(ret, "failed to revert, error %u\n", GetLastError());
7762 CloseHandle(token);
7763 CloseHandle(process);
7766 #define join_process(a) join_process_(__LINE__, a)
7767 static void join_process_(int line, const PROCESS_INFORMATION *pi)
7769 DWORD ret = WaitForSingleObject(pi->hProcess, 1000);
7770 ok_(__FILE__, line)(!ret, "wait failed\n");
7771 CloseHandle(pi->hProcess);
7772 CloseHandle(pi->hThread);
7775 static void test_create_process_token(void)
7777 char cmdline[300], acl_buffer[200], sid_buffer[100];
7778 SECURITY_ATTRIBUTES sa = {.nLength = sizeof(sa)};
7779 ACL *acl = (ACL *)acl_buffer;
7780 SID *sid = (SID *)sid_buffer;
7781 SID_AND_ATTRIBUTES sid_attr;
7782 HANDLE event, token, token2;
7783 PROCESS_INFORMATION pi;
7784 SECURITY_DESCRIPTOR sd;
7785 STARTUPINFOA si = {0};
7786 DWORD size;
7787 BOOL ret;
7789 size = sizeof(sid_buffer);
7790 ret = CreateWellKnownSid(WinLocalSid, NULL, sid, &size);
7791 ok(ret, "got error %u\n", GetLastError());
7792 ret = InitializeAcl(acl, sizeof(acl_buffer), ACL_REVISION);
7793 ok(ret, "got error %u\n", GetLastError());
7794 ret = AddAccessAllowedAce(acl, ACL_REVISION, EVENT_MODIFY_STATE, sid);
7795 ok(ret, "got error %u\n", GetLastError());
7796 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
7797 ret = SetSecurityDescriptorDacl(&sd, TRUE, acl, FALSE);
7798 ok(ret, "got error %u\n", GetLastError());
7799 sa.lpSecurityDescriptor = &sd;
7800 event = CreateEventA(&sa, TRUE, TRUE, "test_event");
7801 ok(!!event, "got error %u\n", GetLastError());
7803 sprintf(cmdline, "%s security restricted 0", myARGV[0]);
7805 ret = CreateProcessAsUserA(NULL, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
7806 ok(ret, "got error %u\n", GetLastError());
7807 join_process(&pi);
7809 ret = CreateProcessAsUserA(GetCurrentProcessToken(), NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
7810 todo_wine ok(!ret, "expected failure\n");
7811 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got error %u\n", GetLastError());
7812 if (ret) join_process(&pi);
7814 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, &token);
7815 ok(ret, "got error %u\n", GetLastError());
7816 ret = CreateProcessAsUserA(token, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
7817 ok(ret || broken(GetLastError() == ERROR_ACCESS_DENIED) /* < 7 */, "got error %u\n", GetLastError());
7818 if (ret) join_process(&pi);
7819 CloseHandle(token);
7821 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
7822 ok(ret, "got error %u\n", GetLastError());
7823 ret = CreateProcessAsUserA(token, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
7824 ok(!ret, "expected failure\n");
7825 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
7826 CloseHandle(token);
7828 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ASSIGN_PRIMARY, &token);
7829 ok(ret, "got error %u\n", GetLastError());
7830 ret = CreateProcessAsUserA(token, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
7831 ok(!ret, "expected failure\n");
7832 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
7833 CloseHandle(token);
7835 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE, &token);
7836 ok(ret, "got error %u\n", GetLastError());
7838 ret = DuplicateTokenEx(token, TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, NULL,
7839 SecurityImpersonation, TokenImpersonation, &token2);
7840 ok(ret, "got error %u\n", GetLastError());
7841 ret = CreateProcessAsUserA(token2, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
7842 ok(ret || broken(GetLastError() == ERROR_BAD_TOKEN_TYPE) /* < 7 */, "got error %u\n", GetLastError());
7843 if (ret) join_process(&pi);
7844 CloseHandle(token2);
7846 sprintf(cmdline, "%s security restricted 1", myARGV[0]);
7847 sid_attr.Sid = sid;
7848 sid_attr.Attributes = 0;
7849 ret = CreateRestrictedToken(token, 0, 1, &sid_attr, 0, NULL, 0, NULL, &token2);
7850 ok(ret, "got error %u\n", GetLastError());
7851 ret = CreateProcessAsUserA(token2, NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
7852 ok(ret, "got error %u\n", GetLastError());
7853 join_process(&pi);
7854 CloseHandle(token2);
7856 CloseHandle(token);
7858 CloseHandle(event);
7861 static void test_create_process_token_child(void)
7863 HANDLE event;
7865 SetLastError(0xdeadbeef);
7866 event = OpenEventA(EVENT_MODIFY_STATE, FALSE, "test_event");
7867 if (!atoi(myARGV[3]))
7869 ok(!!event, "got error %u\n", GetLastError());
7870 CloseHandle(event);
7872 else
7874 ok(!event, "expected failure\n");
7875 ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
7879 static void test_pseudo_handle_security(void)
7881 char buffer[200];
7882 PSECURITY_DESCRIPTOR sd = buffer, sd_ptr;
7883 unsigned int i;
7884 DWORD size;
7885 BOOL ret;
7887 static const HKEY keys[] =
7889 HKEY_CLASSES_ROOT,
7890 HKEY_CURRENT_USER,
7891 HKEY_LOCAL_MACHINE,
7892 HKEY_USERS,
7893 HKEY_PERFORMANCE_DATA,
7894 HKEY_CURRENT_CONFIG,
7895 HKEY_DYN_DATA,
7898 ret = GetKernelObjectSecurity(GetCurrentProcess(), OWNER_SECURITY_INFORMATION, &sd, sizeof(buffer), &size);
7899 ok(ret, "got error %u\n", GetLastError());
7901 ret = GetKernelObjectSecurity(GetCurrentThread(), OWNER_SECURITY_INFORMATION, &sd, sizeof(buffer), &size);
7902 ok(ret, "got error %u\n", GetLastError());
7904 for (i = 0; i < ARRAY_SIZE(keys); ++i)
7906 SetLastError(0xdeadbeef);
7907 ret = GetKernelObjectSecurity(keys[i], OWNER_SECURITY_INFORMATION, &sd, sizeof(buffer), &size);
7908 ok(!ret, "key %p: expected failure\n", keys[i]);
7909 ok(GetLastError() == ERROR_INVALID_HANDLE, "key %p: got error %u\n", keys[i], GetLastError());
7911 ret = GetSecurityInfo(keys[i], SE_REGISTRY_KEY,
7912 DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &sd_ptr);
7913 if (keys[i] == HKEY_PERFORMANCE_DATA)
7914 todo_wine ok(ret == ERROR_INVALID_HANDLE, "key %p: got error %u\n", keys[i], ret);
7915 else if (keys[i] == HKEY_DYN_DATA)
7916 todo_wine ok(ret == ERROR_CALL_NOT_IMPLEMENTED || broken(ret == ERROR_INVALID_HANDLE) /* <7 */,
7917 "key %p: got error %u\n", keys[i], ret);
7918 else
7919 ok(!ret, "key %p: got error %u\n", keys[i], ret);
7920 LocalFree(sd_ptr);
7922 ret = GetSecurityInfo(keys[i], SE_KERNEL_OBJECT,
7923 DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &sd_ptr);
7924 ok(ret == ERROR_INVALID_HANDLE, "key %p: got error %u\n", keys[i], ret);
7928 static void test_duplicate_token(void)
7930 HANDLE token, token2;
7931 BOOL ret;
7933 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT, &token);
7934 ok(ret, "got error %u\n", GetLastError());
7936 ret = DuplicateToken(token, SecurityAnonymous, &token2);
7937 ok(ret, "got error %u\n", GetLastError());
7938 TEST_GRANTED_ACCESS(token2, TOKEN_QUERY | TOKEN_IMPERSONATE);
7939 CloseHandle(token2);
7941 ret = DuplicateTokenEx(token, 0, NULL, SecurityAnonymous, TokenPrimary, &token2);
7942 ok(ret, "got error %u\n", GetLastError());
7943 TEST_GRANTED_ACCESS(token2, TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT);
7944 CloseHandle(token2);
7946 ret = DuplicateTokenEx(token, MAXIMUM_ALLOWED, NULL, SecurityAnonymous, TokenPrimary, &token2);
7947 ok(ret, "got error %u\n", GetLastError());
7948 TEST_GRANTED_ACCESS(token2, TOKEN_ALL_ACCESS);
7949 CloseHandle(token2);
7951 ret = DuplicateTokenEx(token, TOKEN_QUERY_SOURCE, NULL, SecurityAnonymous, TokenPrimary, &token2);
7952 ok(ret, "got error %u\n", GetLastError());
7953 TEST_GRANTED_ACCESS(token2, TOKEN_QUERY_SOURCE);
7954 CloseHandle(token2);
7956 CloseHandle(token);
7959 static void test_GetKernelObjectSecurity(void)
7961 /* Basic tests for parameter validation. */
7963 SECURITY_DESCRIPTOR_CONTROL control;
7964 DWORD size, ret_size, revision;
7965 BOOL ret, present, defaulted;
7966 PSECURITY_DESCRIPTOR sd;
7967 PSID sid;
7968 ACL *acl;
7970 SetLastError(0xdeadbeef);
7971 size = 0xdeadbeef;
7972 ret = GetKernelObjectSecurity(NULL, OWNER_SECURITY_INFORMATION, NULL, 0, &size);
7973 ok(!ret, "expected failure\n");
7974 ok(GetLastError() == ERROR_INVALID_HANDLE, "got error %u\n", GetLastError());
7975 ok(size == 0xdeadbeef, "got size %u\n", size);
7977 SetLastError(0xdeadbeef);
7978 ret = GetKernelObjectSecurity(GetCurrentProcess(), OWNER_SECURITY_INFORMATION, NULL, 0, NULL);
7979 ok(!ret, "expected failure\n");
7980 ok(GetLastError() == ERROR_NOACCESS, "got error %u\n", GetLastError());
7982 SetLastError(0xdeadbeef);
7983 size = 0xdeadbeef;
7984 ret = GetKernelObjectSecurity(GetCurrentProcess(), OWNER_SECURITY_INFORMATION, NULL, 0, &size);
7985 ok(!ret, "expected failure\n");
7986 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %u\n", GetLastError());
7987 ok(size > 0 && size != 0xdeadbeef, "got size 0\n");
7989 sd = malloc(size + 1);
7991 SetLastError(0xdeadbeef);
7992 ret = GetKernelObjectSecurity(GetCurrentProcess(), OWNER_SECURITY_INFORMATION, sd, size - 1, &ret_size);
7993 ok(!ret, "expected failure\n");
7994 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %u\n", GetLastError());
7995 ok(ret_size == size, "expected size %u, got %u\n", size, ret_size);
7997 SetLastError(0xdeadbeef);
7998 ret = GetKernelObjectSecurity(GetCurrentProcess(), OWNER_SECURITY_INFORMATION, sd, size + 1, &ret_size);
7999 ok(ret, "expected success\n");
8000 ok(GetLastError() == 0xdeadbeef, "got error %u\n", GetLastError());
8001 ok(ret_size == size, "expected size %u, got %u\n", size, ret_size);
8003 free(sd);
8005 /* Calling the function with flags not defined succeeds and yields an empty
8006 * descriptor. */
8008 SetLastError(0xdeadbeef);
8009 ret = GetKernelObjectSecurity(GetCurrentProcess(), 0x100000, NULL, 0, &size);
8010 ok(!ret, "expected failure\n");
8011 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %u\n", GetLastError());
8013 sd = malloc(size);
8014 SetLastError(0xdeadbeef);
8015 ret = GetKernelObjectSecurity(GetCurrentProcess(), 0x100000, sd, size, &ret_size);
8016 ok(ret, "expected success\n");
8017 ok(GetLastError() == 0xdeadbeef, "got error %u\n", GetLastError());
8018 ok(ret_size == size, "expected size %u, got %u\n", size, ret_size);
8020 ret = GetSecurityDescriptorControl(sd, &control, &revision);
8021 ok(ret, "got error %u\n", GetLastError());
8022 todo_wine ok(control == SE_SELF_RELATIVE, "got control %#x\n", control);
8023 ok(revision == SECURITY_DESCRIPTOR_REVISION1, "got revision %u\n", revision);
8025 ret = GetSecurityDescriptorOwner(sd, &sid, &defaulted);
8026 ok(ret, "got error %u\n", GetLastError());
8027 ok(!sid, "expected no owner SID\n");
8028 ok(!defaulted, "expected owner not defaulted\n");
8030 ret = GetSecurityDescriptorGroup(sd, &sid, &defaulted);
8031 ok(ret, "got error %u\n", GetLastError());
8032 ok(!sid, "expected no group SID\n");
8033 ok(!defaulted, "expected group not defaulted\n");
8035 ret = GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted);
8036 ok(ret, "got error %u\n", GetLastError());
8037 todo_wine ok(!present, "expected no DACL present\n");
8038 /* the descriptor is defaulted only on Windows >= 7 */
8040 ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted);
8041 ok(ret, "got error %u\n", GetLastError());
8042 ok(!present, "expected no SACL present\n");
8043 /* the descriptor is defaulted only on Windows >= 7 */
8045 free(sd);
8048 static void check_different_token(HANDLE token1, HANDLE token2)
8050 TOKEN_STATISTICS stats1, stats2;
8051 DWORD size;
8052 BOOL ret;
8054 ret = GetTokenInformation(token1, TokenStatistics, &stats1, sizeof(stats1), &size);
8055 ok(ret, "got error %u\n", GetLastError());
8056 ret = GetTokenInformation(token2, TokenStatistics, &stats2, sizeof(stats2), &size);
8057 ok(ret, "got error %u\n", GetLastError());
8059 ok(memcmp(&stats1.TokenId, &stats2.TokenId, sizeof(LUID)), "expected different IDs\n");
8062 static void test_elevation(void)
8064 TOKEN_LINKED_TOKEN linked, linked2;
8065 DWORD orig_type, type, size;
8066 TOKEN_ELEVATION elevation;
8067 HANDLE token, token2;
8068 BOOL ret;
8070 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | READ_CONTROL | TOKEN_DUPLICATE
8071 | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_DEFAULT, &token);
8072 ok(ret, "got error %u\n", GetLastError());
8074 ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size);
8075 ok(ret, "got error %u\n", GetLastError());
8076 orig_type = type;
8077 ret = GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &size);
8078 ok(ret, "got error %u\n", GetLastError());
8079 ret = GetTokenInformation(token, TokenLinkedToken, &linked, sizeof(linked), &size);
8080 if (!ret && GetLastError() == ERROR_NO_SUCH_LOGON_SESSION) /* fails on w2008s64 */
8082 win_skip("Failed to get linked token.\n");
8083 CloseHandle(token);
8084 return;
8086 ok(ret, "got error %u\n", GetLastError());
8088 if (type == TokenElevationTypeDefault)
8090 ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated);
8091 ok(!linked.LinkedToken, "expected no linked token\n");
8093 else if (type == TokenElevationTypeLimited)
8095 ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated);
8096 ok(!!linked.LinkedToken, "expected a linked token\n");
8098 TEST_GRANTED_ACCESS(linked.LinkedToken, TOKEN_ALL_ACCESS);
8099 ret = GetTokenInformation(linked.LinkedToken, TokenElevationType, &type, sizeof(type), &size);
8100 ok(ret, "got error %u\n", GetLastError());
8101 ok(type == TokenElevationTypeFull, "got type %#x\n", type);
8102 ret = GetTokenInformation(linked.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size);
8103 ok(ret, "got error %u\n", GetLastError());
8104 ok(elevation.TokenIsElevated == TRUE, "got elevation %#x\n", elevation.TokenIsElevated);
8106 /* Asking for the linked token again gives us a different token. */
8107 ret = GetTokenInformation(token, TokenLinkedToken, &linked2, sizeof(linked2), &size);
8108 ok(ret, "got error %u\n", GetLastError());
8110 ret = GetTokenInformation(linked2.LinkedToken, TokenElevationType, &type, sizeof(type), &size);
8111 ok(ret, "got error %u\n", GetLastError());
8112 ok(type == TokenElevationTypeFull, "got type %#x\n", type);
8113 ret = GetTokenInformation(linked2.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size);
8114 ok(ret, "got error %u\n", GetLastError());
8115 ok(elevation.TokenIsElevated == TRUE, "got elevation %#x\n", elevation.TokenIsElevated);
8117 check_different_token(linked.LinkedToken, linked2.LinkedToken);
8119 CloseHandle(linked2.LinkedToken);
8121 /* Asking for the linked token's linked token gives us a new limited token. */
8122 ret = GetTokenInformation(linked.LinkedToken, TokenLinkedToken, &linked2, sizeof(linked2), &size);
8123 ok(ret, "got error %u\n", GetLastError());
8125 ret = GetTokenInformation(linked2.LinkedToken, TokenElevationType, &type, sizeof(type), &size);
8126 ok(ret, "got error %u\n", GetLastError());
8127 ok(type == TokenElevationTypeLimited, "got type %#x\n", type);
8128 ret = GetTokenInformation(linked2.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size);
8129 ok(ret, "got error %u\n", GetLastError());
8130 ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated);
8132 check_different_token(token, linked2.LinkedToken);
8134 CloseHandle(linked2.LinkedToken);
8136 CloseHandle(linked.LinkedToken);
8138 type = TokenElevationTypeLimited;
8139 ret = SetTokenInformation(token, TokenElevationType, &type, sizeof(type));
8140 ok(!ret, "expected failure\n");
8141 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError());
8143 elevation.TokenIsElevated = FALSE;
8144 ret = SetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation));
8145 ok(!ret, "expected failure\n");
8146 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError());
8148 else
8150 ok(elevation.TokenIsElevated == TRUE, "got elevation %#x\n", elevation.TokenIsElevated);
8151 ok(!!linked.LinkedToken, "expected a linked token\n");
8153 TEST_GRANTED_ACCESS(linked.LinkedToken, TOKEN_ALL_ACCESS);
8154 ret = GetTokenInformation(linked.LinkedToken, TokenElevationType, &type, sizeof(type), &size);
8155 ok(ret, "got error %u\n", GetLastError());
8156 ok(type == TokenElevationTypeLimited, "got type %#x\n", type);
8157 ret = GetTokenInformation(linked.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size);
8158 ok(ret, "got error %u\n", GetLastError());
8159 ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated);
8161 /* Asking for the linked token again gives us a different token. */
8162 ret = GetTokenInformation(token, TokenLinkedToken, &linked2, sizeof(linked2), &size);
8163 ok(ret, "got error %u\n", GetLastError());
8165 ret = GetTokenInformation(linked2.LinkedToken, TokenElevationType, &type, sizeof(type), &size);
8166 ok(ret, "got error %u\n", GetLastError());
8167 ok(type == TokenElevationTypeLimited, "got type %#x\n", type);
8168 ret = GetTokenInformation(linked2.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size);
8169 ok(ret, "got error %u\n", GetLastError());
8170 ok(elevation.TokenIsElevated == FALSE, "got elevation %#x\n", elevation.TokenIsElevated);
8172 check_different_token(linked.LinkedToken, linked2.LinkedToken);
8174 CloseHandle(linked2.LinkedToken);
8176 /* Asking for the linked token's linked token gives us a new elevated token. */
8177 ret = GetTokenInformation(linked.LinkedToken, TokenLinkedToken, &linked2, sizeof(linked2), &size);
8178 ok(ret, "got error %u\n", GetLastError());
8180 ret = GetTokenInformation(linked2.LinkedToken, TokenElevationType, &type, sizeof(type), &size);
8181 ok(ret, "got error %u\n", GetLastError());
8182 ok(type == TokenElevationTypeFull, "got type %#x\n", type);
8183 ret = GetTokenInformation(linked2.LinkedToken, TokenElevation, &elevation, sizeof(elevation), &size);
8184 ok(ret, "got error %u\n", GetLastError());
8185 ok(elevation.TokenIsElevated == TRUE, "got elevation %#x\n", elevation.TokenIsElevated);
8187 check_different_token(token, linked2.LinkedToken);
8189 CloseHandle(linked2.LinkedToken);
8191 CloseHandle(linked.LinkedToken);
8193 type = TokenElevationTypeLimited;
8194 ret = SetTokenInformation(token, TokenElevationType, &type, sizeof(type));
8195 ok(!ret, "expected failure\n");
8196 todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError());
8198 elevation.TokenIsElevated = FALSE;
8199 ret = SetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation));
8200 ok(!ret, "expected failure\n");
8201 todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError());
8204 ret = DuplicateTokenEx(token, TOKEN_ALL_ACCESS, NULL, SecurityAnonymous, TokenPrimary, &token2);
8205 ok(ret, "got error %u\n", GetLastError());
8206 ret = GetTokenInformation(token2, TokenElevationType, &type, sizeof(type), &size);
8207 ok(ret, "got error %u\n", GetLastError());
8208 ok(type == orig_type, "expected same type\n");
8209 ret = GetTokenInformation(token2, TokenElevation, &elevation, sizeof(elevation), &size);
8210 ok(ret, "got error %u\n", GetLastError());
8211 ok(elevation.TokenIsElevated == (type == TokenElevationTypeFull), "got elevation %#x\n", elevation.TokenIsElevated);
8212 ret = GetTokenInformation(token2, TokenLinkedToken, &linked, sizeof(linked), &size);
8213 ok(ret, "got error %u\n", GetLastError());
8214 if (type == TokenElevationTypeDefault)
8215 ok(!linked.LinkedToken, "expected no linked token\n");
8216 else
8217 ok(!!linked.LinkedToken, "expected a linked token\n");
8218 CloseHandle(linked.LinkedToken);
8219 CloseHandle(token2);
8221 ret = CreateRestrictedToken(token, 0, 0, NULL, 0, NULL, 0, NULL, &token2);
8222 ok(ret, "got error %u\n", GetLastError());
8223 ret = GetTokenInformation(token2, TokenElevationType, &type, sizeof(type), &size);
8224 ok(ret, "got error %u\n", GetLastError());
8225 ok(type == orig_type, "expected same type\n");
8226 ret = GetTokenInformation(token2, TokenElevation, &elevation, sizeof(elevation), &size);
8227 ok(ret, "got error %u\n", GetLastError());
8228 ok(elevation.TokenIsElevated == (type == TokenElevationTypeFull), "got elevation %#x\n", elevation.TokenIsElevated);
8229 ret = GetTokenInformation(token2, TokenLinkedToken, &linked, sizeof(linked), &size);
8230 ok(ret, "got error %u\n", GetLastError());
8231 if (type == TokenElevationTypeDefault)
8232 ok(!linked.LinkedToken, "expected no linked token\n");
8233 else
8234 ok(!!linked.LinkedToken, "expected a linked token\n");
8235 CloseHandle(linked.LinkedToken);
8236 CloseHandle(token2);
8238 if (type != TokenElevationTypeDefault)
8240 char prev_privs_buffer[128], acl_buffer[256], prev_acl_buffer[256];
8241 TOKEN_PRIVILEGES privs, *prev_privs = (TOKEN_PRIVILEGES *)prev_privs_buffer;
8242 TOKEN_DEFAULT_DACL *prev_acl = (TOKEN_DEFAULT_DACL *)prev_acl_buffer;
8243 TOKEN_DEFAULT_DACL *ret_acl = (TOKEN_DEFAULT_DACL *)acl_buffer;
8244 TOKEN_DEFAULT_DACL default_acl;
8245 PRIVILEGE_SET priv_set;
8246 BOOL ret, is_member;
8247 DWORD size;
8248 ACL acl;
8250 /* Linked tokens do not preserve privilege modifications. */
8252 privs.PrivilegeCount = 1;
8253 ret = LookupPrivilegeValueA(NULL, "SeChangeNotifyPrivilege", &privs.Privileges[0].Luid);
8254 ok(ret, "got error %u\n", GetLastError());
8255 privs.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED;
8256 ret = AdjustTokenPrivileges(token, FALSE, &privs, sizeof(prev_privs_buffer), prev_privs, &size);
8257 ok(ret, "got error %u\n", GetLastError());
8259 priv_set.PrivilegeCount = 1;
8260 priv_set.Control = 0;
8261 priv_set.Privilege[0] = privs.Privileges[0];
8262 ret = PrivilegeCheck(token, &priv_set, &is_member);
8263 ok(ret, "got error %u\n", GetLastError());
8264 ok(!is_member, "not a member\n");
8266 ret = GetTokenInformation(token, TokenLinkedToken, &linked, sizeof(linked), &size);
8267 ok(ret, "got error %u\n", GetLastError());
8269 ret = PrivilegeCheck(linked.LinkedToken, &priv_set, &is_member);
8270 ok(ret, "got error %u\n", GetLastError());
8271 ok(is_member, "not a member\n");
8273 CloseHandle(linked.LinkedToken);
8275 ret = AdjustTokenPrivileges(token, FALSE, prev_privs, 0, NULL, NULL);
8276 ok(ret, "got error %u\n", GetLastError());
8278 /* Linked tokens do not preserve default DACL modifications. */
8280 ret = GetTokenInformation(token, TokenDefaultDacl, prev_acl, sizeof(prev_acl_buffer), &size);
8281 ok(ret, "got error %u\n", GetLastError());
8282 ok(prev_acl->DefaultDacl->AceCount, "expected non-empty default DACL\n");
8284 InitializeAcl(&acl, sizeof(acl), ACL_REVISION);
8285 default_acl.DefaultDacl = &acl;
8286 ret = SetTokenInformation(token, TokenDefaultDacl, &default_acl, sizeof(default_acl));
8287 ok(ret, "got error %u\n", GetLastError());
8289 ret = GetTokenInformation(token, TokenDefaultDacl, ret_acl, sizeof(acl_buffer), &size);
8290 ok(ret, "got error %u\n", GetLastError());
8291 ok(!ret_acl->DefaultDacl->AceCount, "expected empty default DACL\n");
8293 ret = GetTokenInformation(token, TokenLinkedToken, &linked, sizeof(linked), &size);
8294 ok(ret, "got error %u\n", GetLastError());
8296 ret = GetTokenInformation(linked.LinkedToken, TokenDefaultDacl, ret_acl, sizeof(acl_buffer), &size);
8297 ok(ret, "got error %u\n", GetLastError());
8298 ok(ret_acl->DefaultDacl->AceCount, "expected non-empty default DACL\n");
8300 CloseHandle(linked.LinkedToken);
8302 ret = SetTokenInformation(token, TokenDefaultDacl, prev_acl, sizeof(*prev_acl));
8303 ok(ret, "got error %u\n", GetLastError());
8306 CloseHandle(token);
8309 START_TEST(security)
8311 init();
8312 if (!hmod) return;
8314 if (myARGC >= 3)
8316 if (!strcmp(myARGV[2], "test_token_sd"))
8317 test_child_token_sd();
8318 else if (!strcmp(myARGV[2], "test"))
8319 test_process_security_child();
8320 else if (!strcmp(myARGV[2], "duplicate"))
8321 test_duplicate_handle_access_child();
8322 else if (!strcmp(myARGV[2], "restricted"))
8323 test_create_process_token_child();
8324 return;
8326 test_kernel_objects_security();
8327 test_ConvertStringSidToSid();
8328 test_trustee();
8329 test_allocateLuid();
8330 test_lookupPrivilegeName();
8331 test_lookupPrivilegeValue();
8332 test_CreateWellKnownSid();
8333 test_FileSecurity();
8334 test_AccessCheck();
8335 test_token_attr();
8336 test_GetTokenInformation();
8337 test_LookupAccountSid();
8338 test_LookupAccountName();
8339 test_security_descriptor();
8340 test_process_security();
8341 test_impersonation_level();
8342 test_SetEntriesInAclW();
8343 test_SetEntriesInAclA();
8344 test_CreateDirectoryA();
8345 test_GetNamedSecurityInfoA();
8346 test_ConvertStringSecurityDescriptor();
8347 test_ConvertSecurityDescriptorToString();
8348 test_PrivateObjectSecurity();
8349 test_InitializeAcl();
8350 test_GetWindowsAccountDomainSid();
8351 test_EqualDomainSid();
8352 test_GetSecurityInfo();
8353 test_GetSidSubAuthority();
8354 test_CheckTokenMembership();
8355 test_EqualSid();
8356 test_GetUserNameA();
8357 test_GetUserNameW();
8358 test_CreateRestrictedToken();
8359 test_TokenIntegrityLevel();
8360 test_default_dacl_owner_sid();
8361 test_AdjustTokenPrivileges();
8362 test_AddAce();
8363 test_AddMandatoryAce();
8364 test_system_security_access();
8365 test_GetSidIdentifierAuthority();
8366 test_pseudo_tokens();
8367 test_maximum_allowed();
8368 test_token_label();
8369 test_GetExplicitEntriesFromAclW();
8370 test_BuildSecurityDescriptorW();
8371 test_duplicate_handle_access();
8372 test_create_process_token();
8373 test_pseudo_handle_security();
8374 test_duplicate_token();
8375 test_GetKernelObjectSecurity();
8376 test_elevation();
8378 /* Must be the last test, modifies process token */
8379 test_token_security_descriptor();