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