#include "ntstatus.h"
#define WIN32_NO_STATUS
+#define WIN32_LEAN_AND_MEAN
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
+#include "wine/winternl.h"
#include "aclapi.h"
#include "winnt.h"
#include "sddl.h"
#include "wine/test.h"
+#ifndef PROCESS_QUERY_LIMITED_INFORMATION
+#define PROCESS_QUERY_LIMITED_INFORMATION 0x1000
+#endif
+
/* PROCESS_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
#define PROCESS_ALL_ACCESS_NT4 (PROCESS_ALL_ACCESS & ~0xf000)
+#define PROCESS_ALL_ACCESS_VISTA (PROCESS_ALL_ACCESS | 0xf000)
#ifndef EVENT_QUERY_STATE
#define EVENT_QUERY_STATE 0x0001
#endif
-/* copied from Wine winternl.h - not included in the Windows SDK */
-typedef enum _OBJECT_INFORMATION_CLASS {
- ObjectBasicInformation,
- ObjectNameInformation,
- ObjectTypeInformation,
- ObjectAllInformation,
- ObjectDataInformation
-} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;
-
-typedef struct _OBJECT_BASIC_INFORMATION {
- ULONG Attributes;
- ACCESS_MASK GrantedAccess;
- ULONG HandleCount;
- ULONG PointerCount;
- ULONG PagedPoolUsage;
- ULONG NonPagedPoolUsage;
- ULONG Reserved[3];
- ULONG NameInformationLength;
- ULONG TypeInformationLength;
- ULONG SecurityDescriptorLength;
- LARGE_INTEGER CreateTime;
-} OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION;
+#ifndef SEMAPHORE_QUERY_STATE
+#define SEMAPHORE_QUERY_STATE 0x0001
+#endif
+
+#ifndef THREAD_SET_LIMITED_INFORMATION
+#define THREAD_SET_LIMITED_INFORMATION 0x0400
+#define THREAD_QUERY_LIMITED_INFORMATION 0x0800
+#endif
+
+#define THREAD_ALL_ACCESS_NT4 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff)
+#define THREAD_ALL_ACCESS_VISTA (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xffff)
#define expect_eq(expr, value, type, format) { type ret_ = expr; ok((value) == ret_, #expr " expected " format " got " format "\n", (value), (ret_)); }
static DWORD (WINAPI *pGetNamedSecurityInfoA)(LPSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION,
PSID*, PSID*, PACL*, PACL*,
PSECURITY_DESCRIPTOR*);
-static DWORD (WINAPI *pSetNamedSecurityInfoA)(LPTSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION,
+static DWORD (WINAPI *pSetNamedSecurityInfoA)(LPSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION,
PSID, PSID, PACL, PACL);
static PDWORD (WINAPI *pGetSidSubAuthority)(PSID, DWORD);
static PUCHAR (WINAPI *pGetSidSubAuthorityCount)(PSID);
PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE);
static BOOL (WINAPI *pGetAclInformation)(PACL,LPVOID,DWORD,ACL_INFORMATION_CLASS);
static BOOL (WINAPI *pGetAce)(PACL,DWORD,LPVOID*);
+static NTSTATUS (WINAPI *pNtSetSecurityObject)(HANDLE,SECURITY_INFORMATION,PSECURITY_DESCRIPTOR);
+static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG);
+static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)(LPCWSTR,PUNICODE_STRING,PWSTR*,CURDIR*);
+static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING,PCANSI_STRING,BOOLEAN);
+static BOOL (WINAPI *pGetWindowsAccountDomainSid)(PSID,PSID,DWORD*);
+static void (WINAPI *pRtlInitAnsiString)(PANSI_STRING,PCSZ);
+static NTSTATUS (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
static HMODULE hmod;
static int myARGC;
hntdll = GetModuleHandleA("ntdll.dll");
pNtQueryObject = (void *)GetProcAddress( hntdll, "NtQueryObject" );
pNtAccessCheck = (void *)GetProcAddress( hntdll, "NtAccessCheck" );
-
- hmod = GetModuleHandle("advapi32.dll");
+ pNtSetSecurityObject = (void *)GetProcAddress(hntdll, "NtSetSecurityObject");
+ pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile");
+ pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
+ pRtlAnsiStringToUnicodeString = (void *)GetProcAddress(hntdll, "RtlAnsiStringToUnicodeString");
+ pRtlInitAnsiString = (void *)GetProcAddress(hntdll, "RtlInitAnsiString");
+ pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
+
+ hmod = GetModuleHandleA("advapi32.dll");
pAddAccessAllowedAceEx = (void *)GetProcAddress(hmod, "AddAccessAllowedAceEx");
pAddAccessDeniedAceEx = (void *)GetProcAddress(hmod, "AddAccessDeniedAceEx");
pAddAuditAccessAceEx = (void *)GetProcAddress(hmod, "AddAuditAccessAceEx");
pConvertStringSidToSidA = (void *)GetProcAddress(hmod, "ConvertStringSidToSidA");
pGetAclInformation = (void *)GetProcAddress(hmod, "GetAclInformation");
pGetAce = (void *)GetProcAddress(hmod, "GetAce");
+ pGetWindowsAccountDomainSid = (void *)GetProcAddress(hmod, "GetWindowsAccountDomainSid");
myARGC = winetest_get_mainargs( &myARGV );
}
+static SECURITY_DESCRIPTOR* test_get_security_descriptor(HANDLE handle, int line)
+{
+ /* use HeapFree(GetProcessHeap(), 0, sd); when done */
+ DWORD ret, length, needed;
+ SECURITY_DESCRIPTOR *sd;
+
+ needed = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = GetKernelObjectSecurity(handle, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ NULL, 0, &needed);
+ ok_(__FILE__, line)(!ret, "GetKernelObjectSecurity should fail\n");
+ ok_(__FILE__, line)(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ ok_(__FILE__, line)(needed != 0xdeadbeef, "GetKernelObjectSecurity should return required buffer length\n");
+
+ length = needed;
+ sd = HeapAlloc(GetProcessHeap(), 0, length);
+
+ needed = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = GetKernelObjectSecurity(handle, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ sd, length, &needed);
+ ok_(__FILE__, line)(ret, "GetKernelObjectSecurity error %d\n", GetLastError());
+ ok_(__FILE__, line)(needed == length || needed == 0 /* file, pipe */, "GetKernelObjectSecurity should return %u instead of %u\n", length, needed);
+ return sd;
+}
+
+static void test_owner_equal(HANDLE Handle, PSID expected, int line)
+{
+ BOOL res;
+ SECURITY_DESCRIPTOR *queriedSD = NULL;
+ PSID owner;
+ BOOL owner_defaulted;
+
+ queriedSD = test_get_security_descriptor( Handle, line );
+
+ res = GetSecurityDescriptorOwner(queriedSD, &owner, &owner_defaulted);
+ ok_(__FILE__, line)(res, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
+
+ ok_(__FILE__, line)(EqualSid(owner, expected), "Owner SIDs are not equal\n");
+ ok_(__FILE__, line)(!owner_defaulted, "Defaulted is true\n");
+
+ HeapFree(GetProcessHeap(), 0, queriedSD);
+}
+
+static void test_group_equal(HANDLE Handle, PSID expected, int line)
+{
+ BOOL res;
+ SECURITY_DESCRIPTOR *queriedSD = NULL;
+ PSID group;
+ BOOL group_defaulted;
+
+ queriedSD = test_get_security_descriptor( Handle, line );
+
+ res = GetSecurityDescriptorGroup(queriedSD, &group, &group_defaulted);
+ ok_(__FILE__, line)(res, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
+
+ ok_(__FILE__, line)(EqualSid(group, expected), "Group SIDs are not equal\n");
+ ok_(__FILE__, line)(!group_defaulted, "Defaulted is true\n");
+
+ HeapFree(GetProcessHeap(), 0, queriedSD);
+}
+
static void test_sid(void)
{
struct sidRef refs[] = {
GUID ObjectType = {0x12345678, 0x1234, 0x5678, {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}};
GUID InheritedObjectType = {0x23456789, 0x2345, 0x6786, {0x2, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}};
GUID ZeroGuid;
- OBJECTS_AND_NAME_ oan;
+ OBJECTS_AND_NAME_A oan;
OBJECTS_AND_SID oas;
- TRUSTEE trustee;
+ TRUSTEEA trustee;
PSID psid;
char szObjectTypeName[] = "ObjectTypeName";
char szInheritedObjectTypeName[] = "InheritedObjectTypeName";
ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
- ok(trustee.ptstrName == (LPTSTR)&oan, "ptstrName wrong\n");
+ ok(trustee.ptstrName == (LPSTR)&oan, "ptstrName wrong\n");
ok(oan.ObjectsPresent == (ACE_OBJECT_TYPE_PRESENT | ACE_INHERITED_OBJECT_TYPE_PRESENT), "ObjectsPresent wrong\n");
ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
ok(trustee.MultipleTrusteeOperation == NO_MULTIPLE_TRUSTEE, "MultipleTrusteeOperation wrong\n");
ok(trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_NAME, "TrusteeForm wrong\n");
ok(trustee.TrusteeType == TRUSTEE_IS_UNKNOWN, "TrusteeType wrong\n");
- ok(trustee.ptstrName == (LPTSTR)&oan, "ptstrName wrong\n");
+ ok(trustee.ptstrName == (LPSTR)&oan, "ptstrName wrong\n");
ok(oan.ObjectsPresent == ACE_OBJECT_TYPE_PRESENT, "ObjectsPresent wrong\n");
ok(oan.ObjectType == SE_KERNEL_OBJECT, "ObjectType wrong\n");
/* Test file access permissions for a file with FILE_ATTRIBUTE_ARCHIVE */
SetLastError(0xdeadbeef);
- rc = GetTempPath(sizeof(wintmpdir), wintmpdir);
+ rc = GetTempPathA(sizeof(wintmpdir), wintmpdir);
ok(rc, "GetTempPath error %d\n", GetLastError());
SetLastError(0xdeadbeef);
- rc = GetTempFileName(wintmpdir, "tmp", 0, file);
+ rc = GetTempFileNameA(wintmpdir, "tmp", 0, file);
ok(rc, "GetTempFileName error %d\n", GetLastError());
- rc = GetFileAttributes(file);
- rc &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
+ rc = GetFileAttributesA(file);
+ rc &= ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|FILE_ATTRIBUTE_COMPRESSED);
ok(rc == FILE_ATTRIBUTE_ARCHIVE, "expected FILE_ATTRIBUTE_ARCHIVE got %#x\n", rc);
- retSize = 0xdeadbeef;
- rc = GetFileSecurity(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
- NULL, 0, &sdSize);
+ rc = GetFileSecurityA(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
+ NULL, 0, &sdSize);
ok(!rc, "GetFileSecurity should fail\n");
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
"expected ERROR_INSUFFICIENT_BUFFER got %d\n", GetLastError());
sd = HeapAlloc(GetProcessHeap (), 0, sdSize);
retSize = 0xdeadbeef;
SetLastError(0xdeadbeef);
- rc = GetFileSecurity(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
- sd, sdSize, &retSize);
+ rc = GetFileSecurityA(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
+ sd, sdSize, &retSize);
ok(rc, "GetFileSecurity error %d\n", GetLastError());
ok(retSize == sdSize || broken(retSize == 0) /* NT4 */, "expected %d, got %d\n", sdSize, retSize);
/* Test file access permissions for a file with FILE_ATTRIBUTE_READONLY */
SetLastError(0xdeadbeef);
- fh = CreateFile(file, FILE_READ_DATA, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
+ fh = CreateFileA(file, FILE_READ_DATA, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
ok(fh != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
retSize = 0xdeadbeef;
SetLastError(0xdeadbeef);
ok(retSize == 0, "expected 0, got %d\n", retSize);
CloseHandle(fh);
- rc = GetFileAttributes(file);
- rc &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
+ rc = GetFileAttributesA(file);
+ rc &= ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|FILE_ATTRIBUTE_COMPRESSED);
todo_wine
ok(rc == (FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY),
"expected FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY got %#x\n", rc);
SetLastError(0xdeadbeef);
- rc = SetFileAttributes(file, FILE_ATTRIBUTE_ARCHIVE);
+ rc = SetFileAttributesA(file, FILE_ATTRIBUTE_ARCHIVE);
ok(rc, "SetFileAttributes error %d\n", GetLastError());
SetLastError(0xdeadbeef);
- rc = DeleteFile(file);
+ rc = DeleteFileA(file);
ok(rc, "DeleteFile error %d\n", GetLastError());
SetLastError(0xdeadbeef);
- fh = CreateFile(file, FILE_READ_DATA, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
+ fh = CreateFileA(file, FILE_READ_DATA, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
ok(fh != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
retSize = 0xdeadbeef;
SetLastError(0xdeadbeef);
ok(retSize == 0, "expected 0, got %d\n", retSize);
CloseHandle(fh);
- rc = GetFileAttributes(file);
- rc &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
+ rc = GetFileAttributesA(file);
+ rc &= ~(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED|FILE_ATTRIBUTE_COMPRESSED);
ok(rc == (FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY),
"expected FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY got %#x\n", rc);
retSize = 0xdeadbeef;
SetLastError(0xdeadbeef);
- rc = GetFileSecurity(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
- sd, sdSize, &retSize);
+ rc = GetFileSecurityA(file, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
+ sd, sdSize, &retSize);
ok(rc, "GetFileSecurity error %d\n", GetLastError());
ok(retSize == sdSize || broken(retSize == 0) /* NT4 */, "expected %d, got %d\n", sdSize, retSize);
ok(granted == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", granted);
}
SetLastError(0xdeadbeef);
- rc = DeleteFile(file);
+ rc = DeleteFileA(file);
ok(!rc, "DeleteFile should fail\n");
ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
SetLastError(0xdeadbeef);
- rc = SetFileAttributes(file, FILE_ATTRIBUTE_ARCHIVE);
+ rc = SetFileAttributesA(file, FILE_ATTRIBUTE_ARCHIVE);
ok(rc, "SetFileAttributes error %d\n", GetLastError());
SetLastError(0xdeadbeef);
- rc = DeleteFile(file);
+ rc = DeleteFileA(file);
ok(rc, "DeleteFile error %d\n", GetLastError());
CloseHandle(token);
DWORD err;
NTSTATUS ntret, ntAccessStatus;
- NtDllModule = GetModuleHandle("ntdll.dll");
+ NtDllModule = GetModuleHandleA("ntdll.dll");
if (!NtDllModule)
{
skip("not running on NT, skipping test\n");
for (i = 0; i < Groups->GroupCount; i++)
{
DWORD NameLength = 255;
- TCHAR Name[255];
+ CHAR Name[255];
DWORD DomainLength = 255;
- TCHAR Domain[255];
+ CHAR Domain[255];
SID_NAME_USE SidNameUse;
Name[0] = '\0';
Domain[0] = '\0';
- ret = LookupAccountSid(NULL, Groups->Groups[i].Sid, Name, &NameLength, Domain, &DomainLength, &SidNameUse);
+ ret = LookupAccountSidA(NULL, Groups->Groups[i].Sid, Name, &NameLength, Domain, &DomainLength, &SidNameUse);
if (ret)
{
pConvertSidToStringSidA(Groups->Groups[i].Sid, &SidString);
trace("TokenPrivileges:\n");
for (i = 0; i < Privileges->PrivilegeCount; i++)
{
- TCHAR Name[256];
+ CHAR Name[256];
DWORD NameLen = sizeof(Name)/sizeof(Name[0]);
- LookupPrivilegeName(NULL, &Privileges->Privileges[i].Luid, Name, &NameLen);
+ LookupPrivilegeNameA(NULL, &Privileges->Privileges[i].Luid, Name, &NameLen);
trace("\t%s, 0x%x\n", Name, Privileges->Privileges[i].Attributes);
}
HeapFree(GetProcessHeap(), 0, Privileges);
SID_NAME_USE use;
DWORD acc_size = MAX_PATH;
DWORD dom_size = MAX_PATH;
- ret = LookupAccountSid(NULL, sid, account, &acc_size, domain, &dom_size, &use);
- ok(ret || (!ret && (GetLastError() == ERROR_NONE_MAPPED)),
+ ret = LookupAccountSidA (NULL, sid, account, &acc_size, domain, &dom_size, &use);
+ ok(ret || GetLastError() == ERROR_NONE_MAPPED,
"LookupAccountSid(%s) failed: %d\n", str_sid, GetLastError());
if (ret)
trace(" %s %s\\%s %d\n", str_sid, domain, account, use);
/* 69 */ {TRUE, "S-1-16-16384"}, {TRUE, "S-1-5-33"}, {TRUE, "S-1-3-4"},
/* 72 */ {FALSE, "S-1-5-21-12-23-34-45-56-571"}, {FALSE, "S-1-5-21-12-23-34-45-56-572"},
/* 74 */ {TRUE, "S-1-5-22"}, {FALSE, "S-1-5-21-12-23-34-45-56-521"}, {TRUE, "S-1-5-32-573"},
-/* 77 */ {FALSE, "S-1-5-21-12-23-34-45-56-498"}, {TRUE, "S-1-5-32-574"}, {TRUE, "S-1-16-8448"}
+/* 77 */ {FALSE, "S-1-5-21-12-23-34-45-56-498"}, {TRUE, "S-1-5-32-574"}, {TRUE, "S-1-16-8448"},
+/* 80 */ {FALSE, NULL}, {TRUE, "S-1-2-1"}, {TRUE, "S-1-5-65-1"}, {FALSE, NULL},
+/* 84 */ {TRUE, "S-1-15-2-1"},
};
static void test_CreateWellKnownSid(void)
if (value->sid_string == NULL)
continue;
- if (i > WinAccountRasAndIasServersSid)
+ /* some SIDs aren't implemented by all Windows versions - detect it */
+ cb = sizeof(sid_buffer);
+ if (!pCreateWellKnownSid(i, NULL, sid_buffer, &cb))
{
- /* These SIDs aren't implemented by all Windows versions - detect it and break the loop */
- cb = sizeof(sid_buffer);
- if (!pCreateWellKnownSid(i, domainsid, sid_buffer, &cb))
- {
- skip("Well known SIDs starting from %u are not implemented\n", i);
- break;
- }
+ skip("Well known SID %u not implemented\n", i);
+ continue;
}
cb = sizeof(sid_buffer);
ok(EqualSid(psid,wk_sid),"(%s) Sids fail to match well known sid!\n",name);
- ok(!lstrcmp(account, wk_account), "Expected %s , got %s\n", account, wk_account);
- ok(!lstrcmp(domain, wk_domain), "Expected %s, got %s\n", wk_domain, domain);
+ ok(!lstrcmpA(account, wk_account), "Expected %s , got %s\n", account, wk_account);
+ ok(!lstrcmpA(domain, wk_domain), "Expected %s, got %s\n", wk_domain, domain);
ok(sid_use == SidTypeWellKnownGroup , "Expected Use (5), got %d\n", sid_use);
cleanup:
get_sid_info(psid, &account, &sid_dom);
ok(ret, "Failed to lookup account name\n");
ok(sid_size == GetLengthSid(psid), "Expected %d, got %d\n", GetLengthSid(psid), sid_size);
- ok(!lstrcmp(account, user_name), "Expected %s, got %s\n", user_name, account);
- ok(!lstrcmp(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
+ ok(!lstrcmpA(account, user_name), "Expected %s, got %s\n", user_name, account);
+ ok(!lstrcmpiA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
ok(domain_size == domain_save - 1, "Expected %d, got %d\n", domain_save - 1, domain_size);
- ok(strlen(domain) == domain_size, "Expected %d, got %d\n", lstrlen(domain), domain_size);
+ ok(strlen(domain) == domain_size, "Expected %d, got %d\n", lstrlenA(domain), domain_size);
ok(sid_use == SidTypeUser, "Expected SidTypeUser (%d), got %d\n", SidTypeUser, sid_use);
domain_size = domain_save;
sid_size = sid_save;
get_sid_info(psid, &account, &sid_dom);
ok(ret, "Failed to lookup account name\n");
ok(sid_size != 0, "sid_size was zero\n");
- ok(!lstrcmp(account, "Everyone"), "Expected Everyone, got %s\n", account);
- ok(!lstrcmp(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
+ ok(!lstrcmpA(account, "Everyone"), "Expected Everyone, got %s\n", account);
+ ok(!lstrcmpiA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain);
ok(domain_size == 0, "Expected 0, got %d\n", domain_size);
- ok(strlen(domain) == domain_size, "Expected %d, got %d\n", lstrlen(domain), domain_size);
+ ok(strlen(domain) == domain_size, "Expected %d, got %d\n", lstrlenA(domain), domain_size);
ok(sid_use == SidTypeWellKnownGroup, "Expected SidTypeWellKnownGroup (%d), got %d\n", SidTypeWellKnownGroup, sid_use);
domain_size = domain_save;
}
get_sid_info(psid, &account, &sid_dom);
ok(ret, "Failed to lookup account name\n");
/* Using a fixed string will not work on different locales */
- ok(!lstrcmp(account, domain),
- "Got %s for account and %s for domain, these should be the same\n",
- account, domain);
+ ok(!lstrcmpiA(account, domain),
+ "Got %s for account and %s for domain, these should be the same\n", account, domain);
ok(sid_use == SidTypeDomain, "Expected SidTypeDomain (%d), got %d\n", SidTypeDomain, sid_use);
HeapFree(GetProcessHeap(), 0, psid);
static void test_process_security(void)
{
BOOL res;
+ PTOKEN_USER user;
PTOKEN_OWNER owner;
PTOKEN_PRIMARY_GROUP group;
- PSID AdminSid = NULL, UsersSid = NULL;
- PACL Acl = NULL;
- SECURITY_DESCRIPTOR *SecurityDescriptor = NULL;
- char buffer[MAX_PATH];
+ PSID AdminSid = NULL, UsersSid = NULL, UserSid = NULL;
+ PACL Acl = NULL, ThreadAcl = NULL;
+ SECURITY_DESCRIPTOR *SecurityDescriptor = NULL, *ThreadSecurityDescriptor = NULL;
+ char buffer[MAX_PATH], account[MAX_PATH], domain[MAX_PATH];
PROCESS_INFORMATION info;
STARTUPINFOA startup;
- SECURITY_ATTRIBUTES psa;
+ SECURITY_ATTRIBUTES psa, tsa;
HANDLE token, event;
- DWORD size;
+ DWORD size, acc_size, dom_size, ret;
+ SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
+ PSID EveryoneSid = NULL;
+ SID_NAME_USE use;
Acl = HeapAlloc(GetProcessHeap(), 0, 256);
res = InitializeAcl(Acl, 256, ACL_REVISION);
}
ok(res, "InitializeAcl failed with error %d\n", GetLastError());
+ res = AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
+ ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
+
/* get owner from the token we might be running as a user not admin */
res = OpenProcessToken( GetCurrentProcess(), MAXIMUM_ALLOWED, &token );
ok(res, "OpenProcessToken failed with error %d\n", GetLastError());
owner = HeapAlloc(GetProcessHeap(), 0, size);
res = GetTokenInformation( token, TokenOwner, owner, size, &size );
ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
- AdminSid = ((TOKEN_OWNER*)owner)->Owner;
+ AdminSid = owner->Owner;
+ test_sid_str(AdminSid);
res = GetTokenInformation( token, TokenPrimaryGroup, NULL, 0, &size );
ok(!res, "Expected failure, got %d\n", res);
group = HeapAlloc(GetProcessHeap(), 0, size);
res = GetTokenInformation( token, TokenPrimaryGroup, group, size, &size );
ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
- UsersSid = ((TOKEN_PRIMARY_GROUP*)group)->PrimaryGroup;
+ UsersSid = group->PrimaryGroup;
+ test_sid_str(UsersSid);
+
+ acc_size = sizeof(account);
+ dom_size = sizeof(domain);
+ ret = LookupAccountSidA( NULL, UsersSid, account, &acc_size, domain, &dom_size, &use );
+ ok(ret, "LookupAccountSid failed with %d\n", ret);
+ ok(use == SidTypeGroup, "expect SidTypeGroup, got %d\n", use);
+ ok(!strcmp(account, "None"), "expect None, got %s\n", account);
+
+ res = GetTokenInformation( token, TokenUser, NULL, 0, &size );
+ ok(!res, "Expected failure, got %d\n", res);
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+
+ user = HeapAlloc(GetProcessHeap(), 0, size);
+ res = GetTokenInformation( token, TokenUser, user, size, &size );
+ ok(res, "GetTokenInformation failed with error %d\n", GetLastError());
+ UserSid = user->User.Sid;
+ test_sid_str(UserSid);
+ ok(EqualPrefixSid(UsersSid, UserSid), "TokenPrimaryGroup Sid and TokenUser Sid don't match.\n");
CloseHandle( token );
if (!res)
{
HeapFree(GetProcessHeap(), 0, group);
HeapFree(GetProcessHeap(), 0, owner);
+ HeapFree(GetProcessHeap(), 0, user);
HeapFree(GetProcessHeap(), 0, Acl);
return;
}
res = InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
- event = CreateEvent( NULL, TRUE, TRUE, "test_event" );
+ event = CreateEventA( NULL, TRUE, TRUE, "test_event" );
ok(event != NULL, "CreateEvent %d\n", GetLastError());
SecurityDescriptor->Revision = 0;
CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_INVALID_SECURITY_DESCR );
CHECK_SET_SECURITY( event, SACL_SECURITY_INFORMATION, ERROR_ACCESS_DENIED );
CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
- /* NULL DACL is valid and means default DACL from token */
+ /* NULL DACL is valid and means that everyone has access */
SecurityDescriptor->Control |= SE_DACL_PRESENT;
CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
res = SetSecurityDescriptorOwner(SecurityDescriptor, AdminSid, FALSE);
ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
CHECK_SET_SECURITY( event, OWNER_SECURITY_INFORMATION, ERROR_SUCCESS );
+ test_owner_equal( event, AdminSid, __LINE__ );
+
+ res = SetSecurityDescriptorGroup(SecurityDescriptor, EveryoneSid, FALSE);
+ ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
+ CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_SUCCESS );
+ test_group_equal( event, EveryoneSid, __LINE__ );
+
+ res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
+ ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
+ CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
+ /* setting a dacl should not change the owner or group */
+ test_owner_equal( event, AdminSid, __LINE__ );
+ test_group_equal( event, EveryoneSid, __LINE__ );
+
+ /* Test again with a different SID in case the previous SID also happens to
+ * be the one that is incorrectly replacing the group. */
res = SetSecurityDescriptorGroup(SecurityDescriptor, UsersSid, FALSE);
ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
CHECK_SET_SECURITY( event, GROUP_SECURITY_INFORMATION, ERROR_SUCCESS );
+ test_group_equal( event, UsersSid, __LINE__ );
+
res = SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
CHECK_SET_SECURITY( event, DACL_SECURITY_INFORMATION, ERROR_SUCCESS );
+ test_group_equal( event, UsersSid, __LINE__ );
sprintf(buffer, "%s tests/security.c test", myARGV[0]);
memset(&startup, 0, sizeof(startup));
psa.lpSecurityDescriptor = SecurityDescriptor;
psa.bInheritHandle = TRUE;
+ ThreadSecurityDescriptor = HeapAlloc( GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH );
+ res = InitializeSecurityDescriptor( ThreadSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
+ ok(res, "InitializeSecurityDescriptor failed with error %d\n", GetLastError());
+
+ ThreadAcl = HeapAlloc( GetProcessHeap(), 0, 256 );
+ res = InitializeAcl( ThreadAcl, 256, ACL_REVISION );
+ ok(res, "InitializeAcl failed with error %d\n", GetLastError());
+ res = AddAccessDeniedAce( ThreadAcl, ACL_REVISION, THREAD_SET_THREAD_TOKEN, AdminSid );
+ ok(res, "AddAccessDeniedAce failed with error %d\n", GetLastError() );
+ res = AddAccessAllowedAce( ThreadAcl, ACL_REVISION, THREAD_ALL_ACCESS, AdminSid );
+ ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
+
+ res = SetSecurityDescriptorOwner( ThreadSecurityDescriptor, AdminSid, FALSE );
+ ok(res, "SetSecurityDescriptorOwner failed with error %d\n", GetLastError());
+ res = SetSecurityDescriptorGroup( ThreadSecurityDescriptor, UsersSid, FALSE );
+ ok(res, "SetSecurityDescriptorGroup failed with error %d\n", GetLastError());
+ res = SetSecurityDescriptorDacl( ThreadSecurityDescriptor, TRUE, ThreadAcl, FALSE );
+ ok(res, "SetSecurityDescriptorDacl failed with error %d\n", GetLastError());
+
+ tsa.nLength = sizeof(tsa);
+ tsa.lpSecurityDescriptor = ThreadSecurityDescriptor;
+ tsa.bInheritHandle = TRUE;
+
/* Doesn't matter what ACL say we should get full access for ourselves */
- res = CreateProcessA( NULL, buffer, &psa, NULL, FALSE, 0, NULL, NULL, &startup, &info );
+ res = CreateProcessA( NULL, buffer, &psa, &tsa, FALSE, 0, NULL, NULL, &startup, &info );
ok(res, "CreateProcess with err:%d\n", GetLastError());
TEST_GRANTED_ACCESS2( info.hProcess, PROCESS_ALL_ACCESS_NT4,
STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
+ TEST_GRANTED_ACCESS2( info.hThread, THREAD_ALL_ACCESS_NT4,
+ STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL );
winetest_wait_child_process( info.hProcess );
+ FreeSid(EveryoneSid);
CloseHandle( info.hProcess );
CloseHandle( info.hThread );
CloseHandle( event );
HeapFree(GetProcessHeap(), 0, group);
HeapFree(GetProcessHeap(), 0, owner);
+ HeapFree(GetProcessHeap(), 0, user);
HeapFree(GetProcessHeap(), 0, Acl);
HeapFree(GetProcessHeap(), 0, SecurityDescriptor);
+ HeapFree(GetProcessHeap(), 0, ThreadAcl);
+ HeapFree(GetProcessHeap(), 0, ThreadSecurityDescriptor);
}
static void test_process_security_child(void)
ret = DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(),
&handle1, PROCESS_ALL_ACCESS, TRUE, 0 );
err = GetLastError();
- todo_wine
ok(!ret && err == ERROR_ACCESS_DENIED, "duplicating handle should have failed "
"with STATUS_ACCESS_DENIED, instead of err:%d\n", err);
/* These two should fail - they are denied by ACL */
handle = OpenProcess( PROCESS_VM_READ, FALSE, GetCurrentProcessId() );
- todo_wine
ok(handle == NULL, "OpenProcess(PROCESS_VM_READ) should have failed\n");
handle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId() );
- todo_wine
ok(handle == NULL, "OpenProcess(PROCESS_ALL_ACCESS) should have failed\n");
/* Documented privilege elevation */
TEST_GRANTED_ACCESS( handle1, PROCESS_VM_READ );
CloseHandle( handle1 );
CloseHandle( handle );
+
+ /* Test thread security */
+ handle = OpenThread( THREAD_TERMINATE, FALSE, GetCurrentThreadId() );
+ ok(handle != NULL, "OpenThread(THREAD_TERMINATE) with err:%d\n", GetLastError());
+ TEST_GRANTED_ACCESS( handle, PROCESS_TERMINATE );
+ CloseHandle( handle );
+
+ handle = OpenThread( THREAD_SET_THREAD_TOKEN, FALSE, GetCurrentThreadId() );
+ ok(handle == NULL, "OpenThread(THREAD_SET_THREAD_TOKEN) should have failed\n");
}
static void test_impersonation_level(void)
ok(error == ERROR_CANT_OPEN_ANONYMOUS, "OpenThreadToken on anonymous token should have returned ERROR_CANT_OPEN_ANONYMOUS instead of %d\n", error);
/* can't perform access check when opening object against an anonymous impersonation token */
todo_wine {
- error = RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
- ok(error == ERROR_INVALID_HANDLE || error == ERROR_CANT_OPEN_ANONYMOUS,
- "RegOpenKeyEx should have failed with ERROR_INVALID_HANDLE or ERROR_CANT_OPEN_ANONYMOUS instead of %d\n", error);
+ error = RegOpenKeyExA(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
+ ok(error == ERROR_INVALID_HANDLE || error == ERROR_CANT_OPEN_ANONYMOUS || error == ERROR_BAD_IMPERSONATION_LEVEL,
+ "RegOpenKeyEx failed with %d\n", error);
}
RevertToSelf();
ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
/* can't perform access check when opening object against an identification impersonation token */
- error = RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
+ error = RegOpenKeyExA(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
todo_wine {
ok(error == ERROR_INVALID_HANDLE || error == ERROR_BAD_IMPERSONATION_LEVEL,
"RegOpenKeyEx should have failed with ERROR_INVALID_HANDLE or ERROR_BAD_IMPERSONATION_LEVEL instead of %d\n", error);
ok(ret, "ImpersonateSelf(SecurityImpersonation) failed with error %d\n", GetLastError());
ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY_SOURCE | TOKEN_IMPERSONATE | TOKEN_ADJUST_DEFAULT, TRUE, &Token);
ok(ret, "OpenThreadToken failed with error %d\n", GetLastError());
- error = RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
+ error = RegOpenKeyExA(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
ok(error == ERROR_SUCCESS, "RegOpenKeyEx should have succeeded instead of failing with %d\n", error);
RegCloseKey(hkey);
ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
PACL OldAcl = NULL, NewAcl;
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
- EXPLICIT_ACCESS ExplicitAccess;
+ EXPLICIT_ACCESSA ExplicitAccess;
static const CHAR szEveryone[] = {'E','v','e','r','y','o','n','e',0};
static const CHAR szCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'};
HeapFree(GetProcessHeap(), 0, OldAcl);
}
-static void test_GetNamedSecurityInfoA(void)
+/* helper function for test_CreateDirectoryA */
+static void get_nt_pathW(const char *name, UNICODE_STRING *nameW)
+{
+ UNICODE_STRING strW;
+ ANSI_STRING str;
+ NTSTATUS status;
+ BOOLEAN ret;
+
+ pRtlInitAnsiString(&str, name);
+
+ status = pRtlAnsiStringToUnicodeString(&strW, &str, TRUE);
+ ok(!status, "RtlAnsiStringToUnicodeString failed with %08x\n", status);
+
+ ret = pRtlDosPathNameToNtPathName_U(strW.Buffer, nameW, NULL, NULL);
+ ok(ret, "RtlDosPathNameToNtPathName_U failed\n");
+
+ pRtlFreeUnicodeString(&strW);
+}
+
+static void test_inherited_dacl(PACL dacl, PSID admin_sid, PSID user_sid, DWORD flags, DWORD mask,
+ BOOL todo_count, BOOL todo_sid, BOOL todo_flags, int line)
+{
+ ACL_SIZE_INFORMATION acl_size;
+ ACCESS_ALLOWED_ACE *ace;
+ BOOL bret;
+
+ bret = pGetAclInformation(dacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok_(__FILE__, line)(bret, "GetAclInformation failed\n");
+
+ if (todo_count)
+ todo_wine
+ ok_(__FILE__, line)(acl_size.AceCount == 2,
+ "GetAclInformation returned unexpected entry count (%d != 2)\n",
+ acl_size.AceCount);
+ else
+ ok_(__FILE__, line)(acl_size.AceCount == 2,
+ "GetAclInformation returned unexpected entry count (%d != 2)\n",
+ acl_size.AceCount);
+
+ if (acl_size.AceCount > 0)
+ {
+ bret = pGetAce(dacl, 0, (VOID **)&ace);
+ ok_(__FILE__, line)(bret, "Failed to get Current User ACE\n");
+
+ bret = EqualSid(&ace->SidStart, user_sid);
+ if (todo_sid)
+ todo_wine
+ ok_(__FILE__, line)(bret, "Current User ACE != Current User SID\n");
+ else
+ ok_(__FILE__, line)(bret, "Current User ACE != Current User SID\n");
+
+ if (todo_flags)
+ todo_wine
+ ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags,
+ "Current User ACE has unexpected flags (0x%x != 0x%x)\n",
+ ((ACE_HEADER *)ace)->AceFlags, flags);
+ else
+ ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags,
+ "Current User ACE has unexpected flags (0x%x != 0x%x)\n",
+ ((ACE_HEADER *)ace)->AceFlags, flags);
+
+ ok_(__FILE__, line)(ace->Mask == mask,
+ "Current User ACE has unexpected mask (0x%x != 0x%x)\n",
+ ace->Mask, mask);
+ }
+ if (acl_size.AceCount > 1)
+ {
+ bret = pGetAce(dacl, 1, (VOID **)&ace);
+ ok_(__FILE__, line)(bret, "Failed to get Administators Group ACE\n");
+
+ bret = EqualSid(&ace->SidStart, admin_sid);
+ if (todo_sid)
+ todo_wine
+ ok_(__FILE__, line)(bret, "Administators Group ACE != Administators Group SID\n");
+ else
+ ok_(__FILE__, line)(bret, "Administators Group ACE != Administators Group SID\n");
+
+ if (todo_flags)
+ todo_wine
+ ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags,
+ "Administators Group ACE has unexpected flags (0x%x != 0x%x)\n",
+ ((ACE_HEADER *)ace)->AceFlags, flags);
+ else
+ ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags,
+ "Administators Group ACE has unexpected flags (0x%x != 0x%x)\n",
+ ((ACE_HEADER *)ace)->AceFlags, flags);
+
+ ok_(__FILE__, line)(ace->Mask == mask,
+ "Administators Group ACE has unexpected mask (0x%x != 0x%x)\n",
+ ace->Mask, mask);
+ }
+}
+
+static void test_CreateDirectoryA(void)
{
- char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], dacl[100], *user;
+ char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], *user;
DWORD sid_size = sizeof(admin_ptr), user_size;
- char invalid_path[] = "/an invalid file path";
PSID admin_sid = (PSID) admin_ptr, user_sid;
char sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
- SECURITY_DESCRIPTOR_CONTROL control;
+ PSECURITY_DESCRIPTOR pSD = &sd;
ACL_SIZE_INFORMATION acl_size;
- CHAR windows_dir[MAX_PATH];
- PSECURITY_DESCRIPTOR pSD;
- ACCESS_ALLOWED_ACE *ace;
- BOOL bret = TRUE, isNT4;
+ UNICODE_STRING tmpfileW;
+ SECURITY_ATTRIBUTES sa;
+ OBJECT_ATTRIBUTES attr;
char tmpfile[MAX_PATH];
- DWORD error, revision;
- BOOL owner_defaulted;
- BOOL group_defaulted;
+ char tmpdir[MAX_PATH];
HANDLE token, hTemp;
- PSID owner, group;
+ IO_STATUS_BLOCK io;
+ struct _SID *owner;
+ BOOL bret = TRUE;
+ NTSTATUS status;
+ DWORD error;
PACL pDacl;
- if (!pSetNamedSecurityInfoA || !pGetNamedSecurityInfoA || !pCreateWellKnownSid)
+ if (!pGetSecurityInfo || !pGetNamedSecurityInfoA || !pCreateWellKnownSid)
{
win_skip("Required functions are not available\n");
return;
CloseHandle( token );
user_sid = ((TOKEN_USER *)user)->User.Sid;
- bret = GetWindowsDirectoryA(windows_dir, MAX_PATH);
- ok(bret, "GetWindowsDirectory failed with error %d\n", GetLastError());
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = pSD;
+ sa.bInheritHandle = TRUE;
+ InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
+ pCreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size);
+ pDacl = HeapAlloc(GetProcessHeap(), 0, 100);
+ bret = InitializeAcl(pDacl, 100, ACL_REVISION);
+ ok(bret, "Failed to initialize ACL.\n");
+ bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
+ GENERIC_ALL, user_sid);
+ ok(bret, "Failed to add Current User to ACL.\n");
+ bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
+ GENERIC_ALL, admin_sid);
+ ok(bret, "Failed to add Administrator Group to ACL.\n");
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+ ok(bret, "Failed to add ACL to security desciptor.\n");
+
+ GetTempPathA(MAX_PATH, tmpdir);
+ lstrcatA(tmpdir, "Please Remove Me");
+ bret = CreateDirectoryA(tmpdir, &sa);
+ ok(bret == TRUE, "CreateDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
+ HeapFree(GetProcessHeap(), 0, pDacl);
SetLastError(0xdeadbeef);
- error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,
- OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
- NULL, NULL, NULL, NULL, &pSD);
+ error = pGetNamedSecurityInfoA(tmpdir, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, (PSID*)&owner,
+ NULL, &pDacl, NULL, &pSD);
if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
{
win_skip("GetNamedSecurityInfoA is not implemented\n");
- HeapFree(GetProcessHeap(), 0, user);
- return;
+ goto done;
}
ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
+ test_inherited_dacl(pDacl, admin_sid, user_sid, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
+ 0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
+ LocalFree(pSD);
- bret = GetSecurityDescriptorControl(pSD, &control, &revision);
- ok(bret, "GetSecurityDescriptorControl failed with error %d\n", GetLastError());
- ok((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == (SE_SELF_RELATIVE|SE_DACL_PRESENT) ||
- broken((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT), /* NT4 */
- "control (0x%x) doesn't have (SE_SELF_RELATIVE|SE_DACL_PRESENT) flags set\n", control);
- ok(revision == SECURITY_DESCRIPTOR_REVISION1, "revision was %d instead of 1\n", revision);
+ /* Test inheritance of ACLs in CreateFile without security descriptor */
+ strcpy(tmpfile, tmpdir);
+ lstrcatA(tmpfile, "/tmpfile");
- isNT4 = (control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT;
+ hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
+ CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ ok(hTemp != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError());
- bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted);
- ok(bret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
- ok(owner != NULL, "owner should not be NULL\n");
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
+ test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
+ 0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
+ LocalFree(pSD);
+ CloseHandle(hTemp);
- bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted);
- ok(bret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
- ok(group != NULL, "group should not be NULL\n");
+ /* Test inheritance of ACLs in CreateFile with security descriptor -
+ * When a security descriptor is set, then inheritance doesn't take effect */
+ pSD = &sd;
+ InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
+ pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
+ bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
+ ok(bret, "Failed to initialize ACL\n");
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+ ok(bret, "Failed to add ACL to security desciptor\n");
+
+ strcpy(tmpfile, tmpdir);
+ lstrcatA(tmpfile, "/tmpfile");
+
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = pSD;
+ sa.bInheritHandle = TRUE;
+ hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, &sa,
+ CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ ok(hTemp != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError());
+ HeapFree(GetProcessHeap(), 0, pDacl);
+
+ error = pGetSecurityInfo(hTemp, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
+ bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok(bret, "GetAclInformation failed\n");
+ ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
+ acl_size.AceCount);
LocalFree(pSD);
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
+ bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok(bret, "GetAclInformation failed\n");
+ ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
+ acl_size.AceCount);
+ LocalFree(pSD);
+ CloseHandle(hTemp);
- /* NULL descriptor tests */
- if(isNT4)
- {
- win_skip("NT4 does not support GetNamedSecutityInfo with a NULL descriptor\n");
- HeapFree(GetProcessHeap(), 0, user);
- return;
- }
+ /* Test inheritance of ACLs in NtCreateFile without security descriptor */
+ strcpy(tmpfile, tmpdir);
+ lstrcatA(tmpfile, "/tmpfile");
+ get_nt_pathW(tmpfile, &tmpfileW);
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = &tmpfileW;
+ attr.Attributes = OBJ_CASE_INSENSITIVE;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+
+ status = pNtCreateFile(&hTemp, GENERIC_WRITE | DELETE, &attr, &io, NULL, 0,
+ FILE_SHARE_READ, FILE_CREATE, FILE_DELETE_ON_CLOSE, NULL, 0);
+ ok(!status, "NtCreateFile failed with %08x\n", status);
+ pRtlFreeUnicodeString(&tmpfileW);
+
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
+ test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
+ 0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
+ LocalFree(pSD);
+ CloseHandle(hTemp);
- error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,
- NULL, NULL, NULL, NULL, NULL);
- ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error);
+ /* Test inheritance of ACLs in NtCreateFile with security descriptor -
+ * When a security descriptor is set, then inheritance doesn't take effect */
+ pSD = &sd;
+ InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
+ pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
+ bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
+ ok(bret, "Failed to initialize ACL\n");
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+ ok(bret, "Failed to add ACL to security desciptor\n");
+
+ strcpy(tmpfile, tmpdir);
+ lstrcatA(tmpfile, "/tmpfile");
+ get_nt_pathW(tmpfile, &tmpfileW);
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = &tmpfileW;
+ attr.Attributes = OBJ_CASE_INSENSITIVE;
+ attr.SecurityDescriptor = pSD;
+ attr.SecurityQualityOfService = NULL;
+
+ status = pNtCreateFile(&hTemp, GENERIC_WRITE | DELETE, &attr, &io, NULL, 0,
+ FILE_SHARE_READ, FILE_CREATE, FILE_DELETE_ON_CLOSE, NULL, 0);
+ ok(!status, "NtCreateFile failed with %08x\n", status);
+ pRtlFreeUnicodeString(&tmpfileW);
+ HeapFree(GetProcessHeap(), 0, pDacl);
+
+ error = pGetSecurityInfo(hTemp, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
+ bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok(bret, "GetAclInformation failed\n");
+ todo_wine
+ ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
+ acl_size.AceCount);
+ LocalFree(pSD);
- error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,
- NULL, NULL, &pDacl, NULL, NULL);
- ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
- ok(pDacl != NULL, "DACL should not be NULL\n");
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
+ bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok(bret, "GetAclInformation failed\n");
+ todo_wine
+ ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
+ acl_size.AceCount);
+ LocalFree(pSD);
+ CloseHandle(hTemp);
- error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,OWNER_SECURITY_INFORMATION,
- NULL, NULL, &pDacl, NULL, NULL);
- ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error);
+ /* Test inheritance of ACLs in CreateDirectory without security descriptor */
+ strcpy(tmpfile, tmpdir);
+ lstrcatA(tmpfile, "/tmpdir");
+ bret = CreateDirectoryA(tmpfile, NULL);
+ ok(bret == TRUE, "CreateDirectoryA failed with error %u\n", GetLastError());
+
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
+ test_inherited_dacl(pDacl, admin_sid, user_sid,
+ OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERITED_ACE,
+ 0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
+ LocalFree(pSD);
+ bret = RemoveDirectoryA(tmpfile);
+ ok(bret == TRUE, "RemoveDirectoryA failed with error %u\n", GetLastError());
+
+ /* Test inheritance of ACLs in CreateDirectory with security descriptor */
+ pSD = &sd;
+ InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
+ pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
+ bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
+ ok(bret, "Failed to initialize ACL\n");
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+ ok(bret, "Failed to add ACL to security desciptor\n");
+
+ strcpy(tmpfile, tmpdir);
+ lstrcatA(tmpfile, "/tmpdir1");
+
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = pSD;
+ sa.bInheritHandle = TRUE;
+ bret = CreateDirectoryA(tmpfile, &sa);
+ ok(bret == TRUE, "CreateDirectoryA failed with error %u\n", GetLastError());
+ HeapFree(GetProcessHeap(), 0, pDacl);
+
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
+ bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok(bret, "GetAclInformation failed\n");
+ ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
+ acl_size.AceCount);
+ LocalFree(pSD);
- /* Test behavior of SetNamedSecurityInfo with an invalid path */
SetLastError(0xdeadbeef);
- error = pSetNamedSecurityInfoA(invalid_path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL,
- NULL, NULL, NULL);
- ok(error == ERROR_FILE_NOT_FOUND, "Unexpected error returned: 0x%x\n", error);
- ok(GetLastError() == 0xdeadbeef, "Expected last error to remain unchanged.\n");
+ bret = RemoveDirectoryA(tmpfile);
+ error = GetLastError();
+ ok(bret == FALSE, "RemoveDirectoryA unexpected succeeded\n");
+ ok(error == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %u\n", error);
- /* Create security descriptor information and test that it comes back the same */
pSD = &sd;
- pDacl = (PACL)&dacl;
InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
- pCreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size);
- bret = InitializeAcl(pDacl, sizeof(dacl), ACL_REVISION);
+ pDacl = HeapAlloc(GetProcessHeap(), 0, 100);
+ bret = InitializeAcl(pDacl, 100, ACL_REVISION);
ok(bret, "Failed to initialize ACL.\n");
bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
- HeapFree(GetProcessHeap(), 0, user);
ok(bret, "Failed to add Current User to ACL.\n");
- bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, admin_sid);
- ok(bret, "Failed to add Administrator Group to ACL.\n");
bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
ok(bret, "Failed to add ACL to security desciptor.\n");
- GetTempFileNameA(".", "foo", 0, tmpfile);
- hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING,
- FILE_FLAG_DELETE_ON_CLOSE, NULL);
- SetLastError(0xdeadbeef);
error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL,
NULL, pDacl, NULL);
- if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
- {
- win_skip("SetNamedSecurityInfoA is not implemented\n");
- CloseHandle(hTemp);
- return;
- }
- ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error);
- SetLastError(0xdeadbeef);
- error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
- NULL, NULL, &pDacl, NULL, &pSD);
- if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
- {
- win_skip("GetNamedSecurityInfoA is not implemented\n");
- return;
- }
- ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
-
+ ok(error == ERROR_SUCCESS, "SetNamedSecurityInfoA failed with error %u\n", error);
+ HeapFree(GetProcessHeap(), 0, pDacl);
+
+ bret = RemoveDirectoryA(tmpfile);
+ ok(bret == TRUE, "RemoveDirectoryA failed with error %u\n", GetLastError());
+
+ /* Test inheritance of ACLs in NtCreateFile(..., FILE_DIRECTORY_FILE, ...) without security descriptor */
+ strcpy(tmpfile, tmpdir);
+ lstrcatA(tmpfile, "/tmpdir");
+ get_nt_pathW(tmpfile, &tmpfileW);
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = &tmpfileW;
+ attr.Attributes = OBJ_CASE_INSENSITIVE;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+
+ status = pNtCreateFile(&hTemp, GENERIC_READ | DELETE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ, FILE_CREATE, FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE, NULL, 0);
+ ok(!status, "NtCreateFile failed with %08x\n", status);
+ RtlFreeUnicodeString(&tmpfileW);
+
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
+ test_inherited_dacl(pDacl, admin_sid, user_sid,
+ OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERITED_ACE,
+ 0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
+ LocalFree(pSD);
+ CloseHandle(hTemp);
+
+ /* Test inheritance of ACLs in NtCreateFile(..., FILE_DIRECTORY_FILE, ...) with security descriptor */
+ pSD = &sd;
+ InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
+ pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
+ bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
+ ok(bret, "Failed to initialize ACL\n");
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+ ok(bret, "Failed to add ACL to security desciptor\n");
+
+ strcpy(tmpfile, tmpdir);
+ lstrcatA(tmpfile, "/tmpdir2");
+ get_nt_pathW(tmpfile, &tmpfileW);
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = &tmpfileW;
+ attr.Attributes = OBJ_CASE_INSENSITIVE;
+ attr.SecurityDescriptor = pSD;
+ attr.SecurityQualityOfService = NULL;
+
+ status = pNtCreateFile(&hTemp, GENERIC_READ | DELETE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ, FILE_CREATE, FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE, NULL, 0);
+ ok(!status, "NtCreateFile failed with %08x\n", status);
+ RtlFreeUnicodeString(&tmpfileW);
+ HeapFree(GetProcessHeap(), 0, pDacl);
+
+ error = pGetSecurityInfo(hTemp, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
+ bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok(bret, "GetAclInformation failed\n");
+ todo_wine
+ ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
+ acl_size.AceCount);
+ LocalFree(pSD);
+
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ (PSID *)&owner, NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
+ bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok(bret, "GetAclInformation failed\n");
+ todo_wine
+ ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
+ acl_size.AceCount);
+ LocalFree(pSD);
+ CloseHandle(hTemp);
+
+done:
+ HeapFree(GetProcessHeap(), 0, user);
+ bret = RemoveDirectoryA(tmpdir);
+ ok(bret == TRUE, "RemoveDirectoryA should always succeed\n");
+}
+
+static void test_GetNamedSecurityInfoA(void)
+{
+ char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], *user;
+ char system_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES];
+ char users_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES];
+ PSID admin_sid = (PSID) admin_ptr, users_sid = (PSID) users_ptr;
+ PSID system_sid = (PSID) system_ptr, user_sid;
+ DWORD sid_size = sizeof(admin_ptr), user_size;
+ char invalid_path[] = "/an invalid file path";
+ int users_ace_id = -1, admins_ace_id = -1, i;
+ char software_key[] = "MACHINE\\Software";
+ char sd[SECURITY_DESCRIPTOR_MIN_LENGTH+sizeof(void*)];
+ SECURITY_DESCRIPTOR_CONTROL control;
+ ACL_SIZE_INFORMATION acl_size;
+ CHAR windows_dir[MAX_PATH];
+ PSECURITY_DESCRIPTOR pSD;
+ ACCESS_ALLOWED_ACE *ace;
+ BOOL bret = TRUE, isNT4;
+ char tmpfile[MAX_PATH];
+ DWORD error, revision;
+ BOOL owner_defaulted;
+ BOOL group_defaulted;
+ BOOL dacl_defaulted;
+ HANDLE token, hTemp, h;
+ PSID owner, group;
+ BOOL dacl_present;
+ PACL pDacl;
+ BYTE flags;
+ NTSTATUS status;
+
+ if (!pSetNamedSecurityInfoA || !pGetNamedSecurityInfoA || !pCreateWellKnownSid)
+ {
+ win_skip("Required functions are not available\n");
+ return;
+ }
+
+ if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
+ {
+ if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE;
+ else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE;
+ }
+ if (!bret)
+ {
+ win_skip("Failed to get current user token\n");
+ return;
+ }
+ bret = GetTokenInformation(token, TokenUser, NULL, 0, &user_size);
+ ok(!bret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
+ "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
+ user = HeapAlloc(GetProcessHeap(), 0, user_size);
+ bret = GetTokenInformation(token, TokenUser, user, user_size, &user_size);
+ ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
+ CloseHandle( token );
+ user_sid = ((TOKEN_USER *)user)->User.Sid;
+
+ bret = GetWindowsDirectoryA(windows_dir, MAX_PATH);
+ ok(bret, "GetWindowsDirectory failed with error %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,
+ NULL, NULL, NULL, NULL, &pSD);
+ if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
+ {
+ win_skip("GetNamedSecurityInfoA is not implemented\n");
+ HeapFree(GetProcessHeap(), 0, user);
+ return;
+ }
+ ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
+
+ bret = GetSecurityDescriptorControl(pSD, &control, &revision);
+ ok(bret, "GetSecurityDescriptorControl failed with error %d\n", GetLastError());
+ ok((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == (SE_SELF_RELATIVE|SE_DACL_PRESENT) ||
+ broken((control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT), /* NT4 */
+ "control (0x%x) doesn't have (SE_SELF_RELATIVE|SE_DACL_PRESENT) flags set\n", control);
+ ok(revision == SECURITY_DESCRIPTOR_REVISION1, "revision was %d instead of 1\n", revision);
+
+ isNT4 = (control & (SE_SELF_RELATIVE|SE_DACL_PRESENT)) == SE_DACL_PRESENT;
+
+ bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted);
+ ok(bret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
+ ok(owner != NULL, "owner should not be NULL\n");
+
+ bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted);
+ ok(bret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
+ ok(group != NULL, "group should not be NULL\n");
+ LocalFree(pSD);
+
+
+ /* NULL descriptor tests */
+ if(isNT4)
+ {
+ win_skip("NT4 does not support GetNamedSecutityInfo with a NULL descriptor\n");
+ HeapFree(GetProcessHeap(), 0, user);
+ return;
+ }
+
+ error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,
+ NULL, NULL, NULL, NULL, NULL);
+ ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error);
+
+ pDacl = NULL;
+ error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,
+ NULL, NULL, &pDacl, NULL, &pSD);
+ ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
+ ok(pDacl != NULL, "DACL should not be NULL\n");
+ LocalFree(pSD);
+
+ error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,OWNER_SECURITY_INFORMATION,
+ NULL, NULL, &pDacl, NULL, NULL);
+ ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error);
+
+ /* Test behavior of SetNamedSecurityInfo with an invalid path */
+ SetLastError(0xdeadbeef);
+ error = pSetNamedSecurityInfoA(invalid_path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL,
+ NULL, NULL, NULL);
+ ok(error == ERROR_FILE_NOT_FOUND, "Unexpected error returned: 0x%x\n", error);
+ ok(GetLastError() == 0xdeadbeef, "Expected last error to remain unchanged.\n");
+
+ /* Create security descriptor information and test that it comes back the same */
+ pSD = &sd;
+ pDacl = HeapAlloc(GetProcessHeap(), 0, 100);
+ InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
+ pCreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size);
+ bret = InitializeAcl(pDacl, 100, ACL_REVISION);
+ ok(bret, "Failed to initialize ACL.\n");
+ bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
+ ok(bret, "Failed to add Current User to ACL.\n");
+ bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, admin_sid);
+ ok(bret, "Failed to add Administrator Group to ACL.\n");
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+ ok(bret, "Failed to add ACL to security desciptor.\n");
+ GetTempFileNameA(".", "foo", 0, tmpfile);
+ hTemp = CreateFileA(tmpfile, WRITE_DAC|GENERIC_WRITE, FILE_SHARE_DELETE|FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ SetLastError(0xdeadbeef);
+ error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL,
+ NULL, pDacl, NULL);
+ HeapFree(GetProcessHeap(), 0, pDacl);
+ if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
+ {
+ win_skip("SetNamedSecurityInfoA is not implemented\n");
+ HeapFree(GetProcessHeap(), 0, user);
+ CloseHandle(hTemp);
+ return;
+ }
+ ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error);
+ SetLastError(0xdeadbeef);
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
+ NULL, NULL, &pDacl, NULL, &pSD);
+ if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
+ {
+ win_skip("GetNamedSecurityInfoA is not implemented\n");
+ HeapFree(GetProcessHeap(), 0, user);
+ CloseHandle(hTemp);
+ return;
+ }
+ ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
+
bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
ok(bret, "GetAclInformation failed\n");
if (acl_size.AceCount > 0)
bret = pGetAce(pDacl, 0, (VOID **)&ace);
ok(bret, "Failed to get Current User ACE.\n");
bret = EqualSid(&ace->SidStart, user_sid);
- todo_wine ok(bret, "Current User ACE != Current User SID.\n");
+ ok(bret, "Current User ACE != Current User SID.\n");
ok(((ACE_HEADER *)ace)->AceFlags == 0,
"Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
- ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
- ace->Mask);
+ ok(ace->Mask == 0x1f01ff,
+ "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
}
if (acl_size.AceCount > 1)
{
bret = pGetAce(pDacl, 1, (VOID **)&ace);
ok(bret, "Failed to get Administators Group ACE.\n");
bret = EqualSid(&ace->SidStart, admin_sid);
- todo_wine ok(bret || broken(!bret) /* win2k */,
- "Administators Group ACE != Administators Group SID.\n");
+ ok(bret || broken(!bret) /* win2k */, "Administators Group ACE != Administators Group SID.\n");
ok(((ACE_HEADER *)ace)->AceFlags == 0,
"Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
ok(ace->Mask == 0x1f01ff || broken(ace->Mask == GENERIC_ALL) /* win2k */,
"Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
}
LocalFree(pSD);
+
+ /* show that setting empty DACL is not removing all file permissions */
+ pDacl = HeapAlloc(GetProcessHeap(), 0, sizeof(ACL));
+ bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
+ ok(bret, "Failed to initialize ACL.\n");
+ error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
+ NULL, NULL, pDacl, NULL);
+ ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error);
+ HeapFree(GetProcessHeap(), 0, pDacl);
+
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
+ NULL, NULL, &pDacl, NULL, &pSD);
+ ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
+
+ bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok(bret, "GetAclInformation failed\n");
+ if (acl_size.AceCount > 0)
+ {
+ bret = pGetAce(pDacl, 0, (VOID **)&ace);
+ ok(bret, "Failed to get ACE.\n");
+ ok(((ACE_HEADER *)ace)->AceFlags & INHERITED_ACE,
+ "ACE has unexpected flags: 0x%x\n", ((ACE_HEADER *)ace)->AceFlags);
+ }
+ LocalFree(pSD);
+
+ h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+ CloseHandle(h);
+
+ /* test setting NULL DACL */
+ error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL);
+ ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error);
+
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
+ NULL, NULL, &pDacl, NULL, &pSD);
+ ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
+ todo_wine ok(!pDacl, "pDacl != NULL\n");
+ LocalFree(pSD);
+
+ h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+ CloseHandle(h);
+
+ /* NtSetSecurityObject doesn't inherit DACL entries */
+ pSD = sd+sizeof(void*)-((ULONG_PTR)sd)%sizeof(void*);
+ InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
+ pDacl = HeapAlloc(GetProcessHeap(), 0, 100);
+ bret = InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION);
+ ok(bret, "Failed to initialize ACL.\n");
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+ ok(bret, "Failed to add ACL to security desciptor.\n");
+ status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
+ ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
+
+ h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+ CloseHandle(h);
+
+ pSetSecurityDescriptorControl(pSD, SE_DACL_AUTO_INHERIT_REQ, SE_DACL_AUTO_INHERIT_REQ);
+ status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
+ ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
+
+ h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+ CloseHandle(h);
+
+ pSetSecurityDescriptorControl(pSD, SE_DACL_AUTO_INHERIT_REQ|SE_DACL_AUTO_INHERITED,
+ SE_DACL_AUTO_INHERIT_REQ|SE_DACL_AUTO_INHERITED);
+ status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
+ ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
+
+ h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+ CloseHandle(h);
+
+ /* test if DACL is properly mapped to permission */
+ bret = InitializeAcl(pDacl, 100, ACL_REVISION);
+ ok(bret, "Failed to initialize ACL.\n");
+ bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
+ ok(bret, "Failed to add Current User to ACL.\n");
+ bret = pAddAccessDeniedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
+ ok(bret, "Failed to add Current User to ACL.\n");
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+ ok(bret, "Failed to add ACL to security desciptor.\n");
+ status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
+ ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
+
+ h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ ok(h != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+ CloseHandle(h);
+
+ bret = InitializeAcl(pDacl, 100, ACL_REVISION);
+ ok(bret, "Failed to initialize ACL.\n");
+ bret = pAddAccessDeniedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
+ ok(bret, "Failed to add Current User to ACL.\n");
+ bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
+ ok(bret, "Failed to add Current User to ACL.\n");
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+ ok(bret, "Failed to add ACL to security desciptor.\n");
+ status = pNtSetSecurityObject(hTemp, DACL_SECURITY_INFORMATION, pSD);
+ ok(status == ERROR_SUCCESS, "NtSetSecurityObject returned %x\n", status);
+
+ h = CreateFileA(tmpfile, GENERIC_READ, FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ ok(h == INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+ HeapFree(GetProcessHeap(), 0, pDacl);
+ HeapFree(GetProcessHeap(), 0, user);
CloseHandle(hTemp);
+
+ /* Test querying the ownership of a built-in registry key */
+ sid_size = sizeof(system_ptr);
+ pCreateWellKnownSid(WinLocalSystemSid, NULL, system_sid, &sid_size);
+ error = pGetNamedSecurityInfoA(software_key, SE_REGISTRY_KEY,
+ OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION,
+ NULL, NULL, NULL, NULL, &pSD);
+ ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
+
+ bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted);
+ ok(bret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
+ ok(owner != NULL, "owner should not be NULL\n");
+ ok(EqualSid(owner, admin_sid), "MACHINE\\Software owner SID != Administrators SID.\n");
+
+ bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted);
+ ok(bret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
+ ok(group != NULL, "group should not be NULL\n");
+ ok(EqualSid(group, admin_sid) || broken(EqualSid(group, system_sid)) /* before Win7 */
+ || broken(((SID*)group)->SubAuthority[0] == SECURITY_NT_NON_UNIQUE) /* Vista */,
+ "MACHINE\\Software group SID != Local System SID.\n");
+ LocalFree(pSD);
+
+ /* Test querying the DACL of a built-in registry key */
+ sid_size = sizeof(users_ptr);
+ pCreateWellKnownSid(WinBuiltinUsersSid, NULL, users_sid, &sid_size);
+ error = pGetNamedSecurityInfoA(software_key, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION,
+ NULL, NULL, NULL, NULL, &pSD);
+ ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
+
+ bret = GetSecurityDescriptorDacl(pSD, &dacl_present, &pDacl, &dacl_defaulted);
+ ok(bret, "GetSecurityDescriptorDacl failed with error %d\n", GetLastError());
+ ok(dacl_present, "DACL should be present\n");
+ ok(pDacl && IsValidAcl(pDacl), "GetSecurityDescriptorDacl returned invalid DACL.\n");
+ bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok(bret, "GetAclInformation failed\n");
+ ok(acl_size.AceCount != 0, "GetAclInformation returned no ACLs\n");
+ for (i=0; i<acl_size.AceCount; i++)
+ {
+ bret = pGetAce(pDacl, i, (VOID **)&ace);
+ ok(bret, "Failed to get ACE %d.\n", i);
+ bret = EqualSid(&ace->SidStart, users_sid);
+ if (bret) users_ace_id = i;
+ bret = EqualSid(&ace->SidStart, admin_sid);
+ if (bret) admins_ace_id = i;
+ }
+ ok(users_ace_id != -1 || broken(users_ace_id == -1) /* win2k */,
+ "Bultin Users ACE not found.\n");
+ if (users_ace_id != -1)
+ {
+ bret = pGetAce(pDacl, users_ace_id, (VOID **)&ace);
+ ok(bret, "Failed to get Builtin Users ACE.\n");
+ flags = ((ACE_HEADER *)ace)->AceFlags;
+ ok(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE)
+ || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* w2k8 */,
+ "Builtin Users ACE has unexpected flags (0x%x != 0x%x)\n", flags,
+ INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE);
+ ok(ace->Mask == GENERIC_READ, "Builtin Users ACE has unexpected mask (0x%x != 0x%x)\n",
+ ace->Mask, GENERIC_READ);
+ }
+ ok(admins_ace_id != -1, "Bultin Admins ACE not found.\n");
+ if (admins_ace_id != -1)
+ {
+ bret = pGetAce(pDacl, admins_ace_id, (VOID **)&ace);
+ ok(bret, "Failed to get Builtin Admins ACE.\n");
+ flags = ((ACE_HEADER *)ace)->AceFlags;
+ ok(flags == 0x0
+ || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* w2k8 */
+ || broken(flags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)), /* win7 */
+ "Builtin Admins ACE has unexpected flags (0x%x != 0x0)\n", flags);
+ ok(ace->Mask == KEY_ALL_ACCESS || broken(ace->Mask == GENERIC_ALL) /* w2k8 */,
+ "Builtin Admins ACE has unexpected mask (0x%x != 0x%x)\n", ace->Mask, KEY_ALL_ACCESS);
+ }
+ LocalFree(pSD);
}
static void test_ConvertStringSecurityDescriptor(void)
Blank, SDDL_REVISION_1, &pSD, NULL);
ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError());
LocalFree(pSD);
+
+ SetLastError(0xdeadbeef);
+ ret = pConvertStringSecurityDescriptorToSecurityDescriptorA(
+ "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);
+ ok(ret || broken(!ret && GetLastError() == ERROR_INVALID_DATATYPE) /* win2k */,
+ "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %u\n", GetLastError());
+ if (ret) LocalFree(pSD);
}
static void test_ConvertSecurityDescriptorToString(void)
* don't replicate this feature so we only test len >= strlen+1. */
#define CHECK_RESULT_AND_FREE(exp_str) \
ok(strcmp(string, (exp_str)) == 0, "String mismatch (expected \"%s\", got \"%s\")\n", (exp_str), string); \
- ok(len >= (strlen(exp_str) + 1), "Length mismatch (expected %d, got %d)\n", lstrlen(exp_str) + 1, len); \
+ ok(len >= (strlen(exp_str) + 1), "Length mismatch (expected %d, got %d)\n", lstrlenA(exp_str) + 1, len); \
LocalFree(string);
#define CHECK_ONE_OF_AND_FREE(exp_str1, exp_str2) \
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); \
- ok(len >= (strlen(exp_str1) + 1) || len >= (strlen(exp_str2) + 1), "Length mismatch (expected %d or %d, got %d)\n", lstrlen(exp_str1) + 1, lstrlen(exp_str2) + 1, len); \
+ ok(len >= (strlen(exp_str1) + 1) || len >= (strlen(exp_str2) + 1), "Length mismatch (expected %d or %d, got %d)\n", lstrlenA(exp_str1) + 1, lstrlenA(exp_str2) + 1, len); \
LocalFree(string);
InitializeSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION);
static void test_GetSecurityInfo(void)
{
+ char domain_users_ptr[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
char b[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], dacl[100];
+ PSID domain_users_sid = (PSID) domain_users_ptr, domain_sid;
+ SID_IDENTIFIER_AUTHORITY sia = { SECURITY_NT_AUTHORITY };
+ int domain_users_ace_id = -1, admins_ace_id = -1, i;
DWORD sid_size = sizeof(admin_ptr), l = sizeof(b);
PSID admin_sid = (PSID) admin_ptr, user_sid;
char sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
+ BOOL owner_defaulted, group_defaulted;
+ BOOL dacl_defaulted, dacl_present;
ACL_SIZE_INFORMATION acl_size;
PSECURITY_DESCRIPTOR pSD;
ACCESS_ALLOWED_ACE *ace;
PSID owner, group;
BOOL bret = TRUE;
PACL pDacl;
+ BYTE flags;
DWORD ret;
if (!pGetSecurityInfo || !pSetSecurityInfo)
win_skip("Failed to get current user token\n");
return;
}
- GetTokenInformation(token, TokenUser, b, l, &l);
+ bret = GetTokenInformation(token, TokenUser, b, l, &l);
+ ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
CloseHandle( token );
user_sid = ((TOKEN_USER *)b)->User.Sid;
/* Create something. Files have lots of associated security info. */
- obj = CreateFile(myARGV[0], GENERIC_READ|WRITE_DAC, FILE_SHARE_READ, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ obj = CreateFileA(myARGV[0], GENERIC_READ|WRITE_DAC, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (obj == INVALID_HANDLE_VALUE)
{
skip("Couldn't create an object for GetSecurityInfo test\n");
NULL, NULL, pDacl, NULL);
ok(ret == ERROR_SUCCESS, "SetSecurityInfo returned %d\n", ret);
ret = pGetSecurityInfo(obj, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
- NULL, NULL, &pDacl, NULL, NULL);
+ NULL, NULL, &pDacl, NULL, &pSD);
ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret);
ok(pDacl && IsValidAcl(pDacl), "GetSecurityInfo returned invalid DACL.\n");
bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
bret = pGetAce(pDacl, 0, (VOID **)&ace);
ok(bret, "Failed to get Current User ACE.\n");
bret = EqualSid(&ace->SidStart, user_sid);
- todo_wine ok(bret, "Current User ACE != Current User SID.\n");
+ ok(bret, "Current User ACE != Current User SID.\n");
ok(((ACE_HEADER *)ace)->AceFlags == 0,
"Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
- ace->Mask);
+ ace->Mask);
}
if (acl_size.AceCount > 1)
{
bret = pGetAce(pDacl, 1, (VOID **)&ace);
ok(bret, "Failed to get Administators Group ACE.\n");
bret = EqualSid(&ace->SidStart, admin_sid);
- todo_wine ok(bret, "Administators Group ACE != Administators Group SID.\n");
+ ok(bret, "Administators Group ACE != Administators Group SID.\n");
ok(((ACE_HEADER *)ace)->AceFlags == 0,
"Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
- ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n",
- ace->Mask);
+ ok(ace->Mask == 0x1f01ff,
+ "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
}
+ LocalFree(pSD);
CloseHandle(obj);
-}
-
-static void test_GetSidSubAuthority(void)
-{
- PSID psid = NULL;
- if (!pGetSidSubAuthority || !pConvertStringSidToSidA || !pIsValidSid || !pGetSidSubAuthorityCount)
+ /* Obtain the "domain users" SID from the user SID */
+ if (!AllocateAndInitializeSid(&sia, 4, *GetSidSubAuthority(user_sid, 0),
+ *GetSidSubAuthority(user_sid, 1),
+ *GetSidSubAuthority(user_sid, 2),
+ *GetSidSubAuthority(user_sid, 3), 0, 0, 0, 0, &domain_sid))
{
- win_skip("Some functions not available\n");
+ win_skip("Failed to get current domain SID\n");
return;
}
- /* Note: on windows passing in an invalid index like -1, lets GetSidSubAuthority return 0x05000000 but
- still GetLastError returns ERROR_SUCCESS then. We don't test these unlikely cornercases here for now */
- ok(pConvertStringSidToSidA("S-1-5-21-93476-23408-4576",&psid),"ConvertStringSidToSidA failed\n");
- ok(pIsValidSid(psid),"Sid is not valid\n");
- SetLastError(0xbebecaca);
- ok(*pGetSidSubAuthorityCount(psid) == 4,"GetSidSubAuthorityCount gave %d expected 4\n",*pGetSidSubAuthorityCount(psid));
- ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
- SetLastError(0xbebecaca);
- ok(*pGetSidSubAuthority(psid,0) == 21,"GetSidSubAuthority gave %d expected 21\n",*pGetSidSubAuthority(psid,0));
- ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
- SetLastError(0xbebecaca);
- ok(*pGetSidSubAuthority(psid,1) == 93476,"GetSidSubAuthority gave %d expected 93476\n",*pGetSidSubAuthority(psid,1));
- ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
+ sid_size = sizeof(domain_users_ptr);
+ pCreateWellKnownSid(WinAccountDomainUsersSid, domain_sid, domain_users_sid, &sid_size);
+ FreeSid(domain_sid);
+
+ /* Test querying the ownership of a process */
+ ret = pGetSecurityInfo(GetCurrentProcess(), SE_KERNEL_OBJECT,
+ OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION,
+ NULL, NULL, NULL, NULL, &pSD);
+ ok(!ret, "GetNamedSecurityInfo failed with error %d\n", ret);
+
+ bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted);
+ ok(bret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError());
+ ok(owner != NULL, "owner should not be NULL\n");
+ ok(EqualSid(owner, admin_sid) || EqualSid(owner, user_sid),
+ "Process owner SID != Administrators SID.\n");
+
+ bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted);
+ ok(bret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError());
+ ok(group != NULL, "group should not be NULL\n");
+ ok(EqualSid(group, domain_users_sid), "Process group SID != Domain Users SID.\n");
+ LocalFree(pSD);
+
+ /* Test querying the DACL of a process */
+ ret = pGetSecurityInfo(GetCurrentProcess(), SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
+ NULL, NULL, NULL, NULL, &pSD);
+ ok(!ret, "GetSecurityInfo failed with error %d\n", ret);
+
+ bret = GetSecurityDescriptorDacl(pSD, &dacl_present, &pDacl, &dacl_defaulted);
+ ok(bret, "GetSecurityDescriptorDacl failed with error %d\n", GetLastError());
+ ok(dacl_present, "DACL should be present\n");
+ ok(pDacl && IsValidAcl(pDacl), "GetSecurityDescriptorDacl returned invalid DACL.\n");
+ bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok(bret, "GetAclInformation failed\n");
+ ok(acl_size.AceCount != 0, "GetAclInformation returned no ACLs\n");
+ for (i=0; i<acl_size.AceCount; i++)
+ {
+ bret = pGetAce(pDacl, i, (VOID **)&ace);
+ ok(bret, "Failed to get ACE %d.\n", i);
+ bret = EqualSid(&ace->SidStart, domain_users_sid);
+ if (bret) domain_users_ace_id = i;
+ bret = EqualSid(&ace->SidStart, admin_sid);
+ if (bret) admins_ace_id = i;
+ }
+ ok(domain_users_ace_id != -1 || broken(domain_users_ace_id == -1) /* win2k */,
+ "Domain Users ACE not found.\n");
+ if (domain_users_ace_id != -1)
+ {
+ bret = pGetAce(pDacl, domain_users_ace_id, (VOID **)&ace);
+ ok(bret, "Failed to get Domain Users ACE.\n");
+ flags = ((ACE_HEADER *)ace)->AceFlags;
+ ok(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE),
+ "Domain Users ACE has unexpected flags (0x%x != 0x%x)\n", flags,
+ INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE);
+ ok(ace->Mask == GENERIC_READ, "Domain Users ACE has unexpected mask (0x%x != 0x%x)\n",
+ ace->Mask, GENERIC_READ);
+ }
+ ok(admins_ace_id != -1 || broken(admins_ace_id == -1) /* xp */,
+ "Builtin Admins ACE not found.\n");
+ if (admins_ace_id != -1)
+ {
+ bret = pGetAce(pDacl, admins_ace_id, (VOID **)&ace);
+ ok(bret, "Failed to get Builtin Admins ACE.\n");
+ flags = ((ACE_HEADER *)ace)->AceFlags;
+ ok(flags == 0x0, "Builtin Admins ACE has unexpected flags (0x%x != 0x0)\n", flags);
+ ok(ace->Mask == PROCESS_ALL_ACCESS || broken(ace->Mask == 0x1f0fff) /* win2k */,
+ "Builtin Admins ACE has unexpected mask (0x%x != 0x%x)\n", ace->Mask, PROCESS_ALL_ACCESS);
+ }
+ LocalFree(pSD);
+}
+
+static void test_GetSidSubAuthority(void)
+{
+ PSID psid = NULL;
+
+ if (!pGetSidSubAuthority || !pConvertStringSidToSidA || !pIsValidSid || !pGetSidSubAuthorityCount)
+ {
+ win_skip("Some functions not available\n");
+ return;
+ }
+ /* Note: on windows passing in an invalid index like -1, lets GetSidSubAuthority return 0x05000000 but
+ still GetLastError returns ERROR_SUCCESS then. We don't test these unlikely cornercases here for now */
+ ok(pConvertStringSidToSidA("S-1-5-21-93476-23408-4576",&psid),"ConvertStringSidToSidA failed\n");
+ ok(pIsValidSid(psid),"Sid is not valid\n");
+ SetLastError(0xbebecaca);
+ ok(*pGetSidSubAuthorityCount(psid) == 4,"GetSidSubAuthorityCount gave %d expected 4\n",*pGetSidSubAuthorityCount(psid));
+ ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
+ SetLastError(0xbebecaca);
+ ok(*pGetSidSubAuthority(psid,0) == 21,"GetSidSubAuthority gave %d expected 21\n",*pGetSidSubAuthority(psid,0));
+ ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
+ SetLastError(0xbebecaca);
+ ok(*pGetSidSubAuthority(psid,1) == 93476,"GetSidSubAuthority gave %d expected 93476\n",*pGetSidSubAuthority(psid,1));
+ ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
SetLastError(0xbebecaca);
ok(pGetSidSubAuthority(psid,4) != NULL,"Expected out of bounds GetSidSubAuthority to return a non-NULL pointer\n");
ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
HANDLE process_token, token, r_token;
PTOKEN_GROUPS token_groups, groups2;
SID_AND_ATTRIBUTES sattr;
+ SECURITY_IMPERSONATION_LEVEL level;
+ TOKEN_TYPE type;
BOOL is_member;
DWORD size;
BOOL ret;
sattr.Attributes = 0;
r_token = NULL;
ret = pCreateRestrictedToken(token, 0, 1, &sattr, 0, NULL, 0, NULL, &r_token);
- todo_wine ok(ret, "got error %d\n", GetLastError());
+ ok(ret, "got error %d\n", GetLastError());
if (ret)
{
is_member = TRUE;
ret = pCheckTokenMembership(r_token, token_groups->Groups[i].Sid, &is_member);
ok(ret, "got error %d\n", GetLastError());
- ok(!is_member, "not a member\n");
+ todo_wine ok(!is_member, "not a member\n");
ret = GetTokenInformation(r_token, TokenGroups, NULL, 0, &size);
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n",
break;
}
- ok(groups2->Groups[j].Attributes & SE_GROUP_USE_FOR_DENY_ONLY,
+ todo_wine ok(groups2->Groups[j].Attributes & SE_GROUP_USE_FOR_DENY_ONLY,
"got wrong attributes\n");
- ok((groups2->Groups[j].Attributes & SE_GROUP_ENABLED) == 0,
+ todo_wine ok((groups2->Groups[j].Attributes & SE_GROUP_ENABLED) == 0,
"got wrong attributes\n");
HeapFree(GetProcessHeap(), 0, groups2);
+
+ size = sizeof(type);
+ ret = GetTokenInformation(r_token, TokenType, &type, size, &size);
+ ok(ret, "got error %d\n", GetLastError());
+ ok(type == TokenImpersonation, "got type %u\n", type);
+
+ size = sizeof(level);
+ ret = GetTokenInformation(r_token, TokenImpersonationLevel, &level, size, &size);
+ ok(ret, "got error %d\n", GetLastError());
+ ok(level == SecurityImpersonation, "got level %u\n", type);
}
HeapFree(GetProcessHeap(), 0, token_groups);
static void test_default_handle_security(HANDLE token, HANDLE handle, GENERIC_MAPPING *mapping)
{
- DWORD ret, length, needed, granted, priv_set_len;
+ DWORD ret, granted, priv_set_len;
BOOL status;
PRIVILEGE_SET priv_set;
SECURITY_DESCRIPTOR *sd;
- needed = 0xdeadbeef;
- SetLastError(0xdeadbeef);
- ret = GetKernelObjectSecurity(handle, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
- NULL, 0, &needed);
- ok(!ret, "GetKernelObjectSecurity should fail\n");
- ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
- ok(needed != 0xdeadbeef, "GetKernelObjectSecurity should return required buffer length\n");
-
- length = needed;
- sd = HeapAlloc(GetProcessHeap(), 0, length);
-
- needed = 0xdeadbeef;
- SetLastError(0xdeadbeef);
- ret = GetKernelObjectSecurity(handle, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
- sd, length, &needed);
- ok(ret, "GetKernelObjectSecurity error %d\n", GetLastError());
- ok(needed == length || needed == 0 /* file, pipe */, "GetKernelObjectSecurity should return %u instead of %u\n", length, needed);
-
+ sd = test_get_security_descriptor(handle, __LINE__);
validate_default_security_descriptor(sd);
priv_set_len = sizeof(priv_set);
HeapFree(GetProcessHeap(), 0, sd);
}
+static ACCESS_MASK get_obj_access(HANDLE obj)
+{
+ OBJECT_BASIC_INFORMATION info;
+ NTSTATUS status;
+
+ if (!pNtQueryObject) return 0;
+
+ status = pNtQueryObject(obj, ObjectBasicInformation, &info, sizeof(info), NULL);
+ ok(!status, "NtQueryObject error %#x\n", status);
+
+ return info.GrantedAccess;
+}
+
static void test_mutex_security(HANDLE token)
{
- HANDLE mutex;
+ DWORD ret, i, access;
+ HANDLE mutex, dup;
GENERIC_MAPPING mapping = { STANDARD_RIGHTS_READ | MUTANT_QUERY_STATE | SYNCHRONIZE,
STANDARD_RIGHTS_WRITE | MUTEX_MODIFY_STATE | SYNCHRONIZE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
STANDARD_RIGHTS_ALL | MUTEX_ALL_ACCESS };
+ static const struct
+ {
+ int generic, mapped;
+ } map[] =
+ {
+ { 0, 0 },
+ { GENERIC_READ, STANDARD_RIGHTS_READ | MUTANT_QUERY_STATE },
+ { GENERIC_WRITE, STANDARD_RIGHTS_WRITE },
+ { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
+ { GENERIC_ALL, STANDARD_RIGHTS_ALL | MUTANT_QUERY_STATE }
+ };
SetLastError(0xdeadbeef);
- mutex = OpenMutex(0, FALSE, "WineTestMutex");
+ mutex = OpenMutexA(0, FALSE, "WineTestMutex");
ok(!mutex, "mutex should not exist\n");
ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef);
- mutex = CreateMutex(NULL, FALSE, "WineTestMutex");
+ mutex = CreateMutexA(NULL, FALSE, "WineTestMutex");
ok(mutex != 0, "CreateMutex error %d\n", GetLastError());
+ access = get_obj_access(mutex);
+ ok(access == MUTANT_ALL_ACCESS, "expected MUTANT_ALL_ACCESS, got %#x\n", access);
+
+ for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
+ {
+ SetLastError( 0xdeadbeef );
+ ret = DuplicateHandle(GetCurrentProcess(), mutex, GetCurrentProcess(), &dup,
+ map[i].generic, FALSE, 0);
+ ok(ret, "DuplicateHandle error %d\n", GetLastError());
+
+ access = get_obj_access(dup);
+ ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+
+ CloseHandle(dup);
+
+ SetLastError(0xdeadbeef);
+ dup = OpenMutexA(0, FALSE, "WineTestMutex");
+todo_wine
+ ok(!dup, "OpenMutex should fail\n");
+todo_wine
+ ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError());
+ }
+
test_default_handle_security(token, mutex, &mapping);
CloseHandle (mutex);
static void test_event_security(HANDLE token)
{
- HANDLE event;
+ DWORD ret, i, access;
+ HANDLE event, dup;
GENERIC_MAPPING mapping = { STANDARD_RIGHTS_READ | EVENT_QUERY_STATE | SYNCHRONIZE,
STANDARD_RIGHTS_WRITE | EVENT_MODIFY_STATE | SYNCHRONIZE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
STANDARD_RIGHTS_ALL | EVENT_ALL_ACCESS };
+ static const struct
+ {
+ int generic, mapped;
+ } map[] =
+ {
+ { 0, 0 },
+ { GENERIC_READ, STANDARD_RIGHTS_READ | EVENT_QUERY_STATE },
+ { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | EVENT_MODIFY_STATE },
+ { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
+ { GENERIC_ALL, STANDARD_RIGHTS_ALL | EVENT_QUERY_STATE | EVENT_MODIFY_STATE }
+ };
SetLastError(0xdeadbeef);
- event = OpenEvent(0, FALSE, "WineTestEvent");
+ event = OpenEventA(0, FALSE, "WineTestEvent");
ok(!event, "event should not exist\n");
ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef);
- event = CreateEvent(NULL, FALSE, FALSE, "WineTestEvent");
+ event = CreateEventA(NULL, FALSE, FALSE, "WineTestEvent");
ok(event != 0, "CreateEvent error %d\n", GetLastError());
+ access = get_obj_access(event);
+ ok(access == EVENT_ALL_ACCESS, "expected EVENT_ALL_ACCESS, got %#x\n", access);
+
+ for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
+ {
+ SetLastError( 0xdeadbeef );
+ ret = DuplicateHandle(GetCurrentProcess(), event, GetCurrentProcess(), &dup,
+ map[i].generic, FALSE, 0);
+ ok(ret, "DuplicateHandle error %d\n", GetLastError());
+
+ access = get_obj_access(dup);
+ ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+
+ CloseHandle(dup);
+
+ SetLastError(0xdeadbeef);
+ dup = OpenEventA(0, FALSE, "WineTestEvent");
+todo_wine
+ ok(!dup, "OpenEvent should fail\n");
+todo_wine
+ ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError());
+ }
+
test_default_handle_security(token, event, &mapping);
CloseHandle(event);
}
+static void test_semaphore_security(HANDLE token)
+{
+ DWORD ret, i, access;
+ HANDLE sem, dup;
+ GENERIC_MAPPING mapping = { STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE,
+ STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE,
+ STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
+ STANDARD_RIGHTS_ALL | SEMAPHORE_ALL_ACCESS };
+ static const struct
+ {
+ int generic, mapped;
+ } map[] =
+ {
+ { 0, 0 },
+ { GENERIC_READ, STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE },
+ { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE },
+ { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
+ { GENERIC_ALL, STANDARD_RIGHTS_ALL | SEMAPHORE_QUERY_STATE | SEMAPHORE_MODIFY_STATE }
+ };
+
+ SetLastError(0xdeadbeef);
+ sem = OpenSemaphoreA(0, FALSE, "WineTestSemaphore");
+ ok(!sem, "semaphore should not exist\n");
+ ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ sem = CreateSemaphoreA(NULL, 0, 10, "WineTestSemaphore");
+ ok(sem != 0, "CreateSemaphore error %d\n", GetLastError());
+
+ access = get_obj_access(sem);
+ ok(access == SEMAPHORE_ALL_ACCESS, "expected SEMAPHORE_ALL_ACCESS, got %#x\n", access);
+
+ for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
+ {
+ SetLastError( 0xdeadbeef );
+ ret = DuplicateHandle(GetCurrentProcess(), sem, GetCurrentProcess(), &dup,
+ map[i].generic, FALSE, 0);
+ ok(ret, "DuplicateHandle error %d\n", GetLastError());
+
+ access = get_obj_access(dup);
+ ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+
+ CloseHandle(dup);
+ }
+
+ test_default_handle_security(token, sem, &mapping);
+
+ CloseHandle(sem);
+}
+
#define WINE_TEST_PIPE "\\\\.\\pipe\\WineTestPipe"
static void test_named_pipe_security(HANDLE token)
{
- HANDLE pipe, file;
+ DWORD ret, i, access;
+ HANDLE pipe, file, dup;
GENERIC_MAPPING mapping = { FILE_GENERIC_READ,
FILE_GENERIC_WRITE,
FILE_GENERIC_EXECUTE,
STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS };
+ static const struct
+ {
+ int todo, generic, mapped;
+ } map[] =
+ {
+ { 0, 0, 0 },
+ { 1, GENERIC_READ, FILE_GENERIC_READ },
+ { 1, GENERIC_WRITE, FILE_GENERIC_WRITE },
+ { 1, GENERIC_EXECUTE, FILE_GENERIC_EXECUTE },
+ { 1, GENERIC_ALL, STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS }
+ };
+ static const struct
+ {
+ DWORD open_mode;
+ DWORD access;
+ } creation_access[] =
+ {
+ { PIPE_ACCESS_INBOUND, FILE_GENERIC_READ },
+ { PIPE_ACCESS_OUTBOUND, FILE_GENERIC_WRITE },
+ { PIPE_ACCESS_DUPLEX, FILE_GENERIC_READ|FILE_GENERIC_WRITE },
+ { PIPE_ACCESS_INBOUND|WRITE_DAC, FILE_GENERIC_READ|WRITE_DAC },
+ { PIPE_ACCESS_INBOUND|WRITE_OWNER, FILE_GENERIC_READ|WRITE_OWNER }
+ /* ACCESS_SYSTEM_SECURITY is also valid, but will fail with ERROR_PRIVILEGE_NOT_HELD */
+ };
+
+ /* Test the different security access options for pipes */
+ for (i = 0; i < sizeof(creation_access)/sizeof(creation_access[0]); i++)
+ {
+ SetLastError(0xdeadbeef);
+ pipe = CreateNamedPipeA(WINE_TEST_PIPE, creation_access[i].open_mode,
+ PIPE_TYPE_BYTE | PIPE_NOWAIT, PIPE_UNLIMITED_INSTANCES, 0, 0,
+ NMPWAIT_USE_DEFAULT_WAIT, NULL);
+ ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe(0x%x) error %d\n",
+ creation_access[i].open_mode, GetLastError());
+ access = get_obj_access(pipe);
+ ok(access == creation_access[i].access,
+ "CreateNamedPipeA(0x%x) pipe expected access 0x%x (got 0x%x)\n",
+ creation_access[i].open_mode, creation_access[i].access, access);
+ CloseHandle(pipe);
+ }
SetLastError(0xdeadbeef);
- pipe = CreateNamedPipe(WINE_TEST_PIPE, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,
- PIPE_TYPE_BYTE | PIPE_NOWAIT, PIPE_UNLIMITED_INSTANCES,
- 0, 0, NMPWAIT_USE_DEFAULT_WAIT, NULL);
+ pipe = CreateNamedPipeA(WINE_TEST_PIPE, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,
+ PIPE_TYPE_BYTE | PIPE_NOWAIT, PIPE_UNLIMITED_INSTANCES,
+ 0, 0, NMPWAIT_USE_DEFAULT_WAIT, NULL);
ok(pipe != INVALID_HANDLE_VALUE, "CreateNamedPipe error %d\n", GetLastError());
test_default_handle_security(token, pipe, &mapping);
SetLastError(0xdeadbeef);
- file = CreateFile(WINE_TEST_PIPE, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, 0, 0);
+ file = CreateFileA(WINE_TEST_PIPE, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, 0, 0);
ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
- CloseHandle(file);
+ access = get_obj_access(file);
+ ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", access);
+
+ for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
+ {
+ SetLastError( 0xdeadbeef );
+ ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup,
+ map[i].generic, FALSE, 0);
+ ok(ret, "DuplicateHandle error %d\n", GetLastError());
+
+ access = get_obj_access(dup);
+ ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+
+ CloseHandle(dup);
+ }
+
+ CloseHandle(file);
CloseHandle(pipe);
SetLastError(0xdeadbeef);
- file = CreateFile("\\\\.\\pipe\\", FILE_ALL_ACCESS, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
+ file = CreateFileA("\\\\.\\pipe\\", FILE_ALL_ACCESS, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
ok(file != INVALID_HANDLE_VALUE || broken(file == INVALID_HANDLE_VALUE) /* before Vista */, "CreateFile error %d\n", GetLastError());
+
+ if (file != INVALID_HANDLE_VALUE)
+ {
+ access = get_obj_access(file);
+ ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", access);
+
+ for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
+ {
+ SetLastError( 0xdeadbeef );
+ ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup,
+ map[i].generic, FALSE, 0);
+ ok(ret, "DuplicateHandle error %d\n", GetLastError());
+
+ access = get_obj_access(dup);
+ if (map[i].todo)
+todo_wine
+ ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+ else
+ ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+
+ CloseHandle(dup);
+ }
+ }
+
+ CloseHandle(file);
+}
+
+static void test_file_security(HANDLE token)
+{
+ DWORD ret, i, access, bytes;
+ HANDLE file, dup;
+ static const struct
+ {
+ int generic, mapped;
+ } map[] =
+ {
+ { 0, 0 },
+ { GENERIC_READ, FILE_GENERIC_READ },
+ { GENERIC_WRITE, FILE_GENERIC_WRITE },
+ { GENERIC_EXECUTE, FILE_GENERIC_EXECUTE },
+ { GENERIC_ALL, STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS }
+ };
+ char temp_path[MAX_PATH];
+ char file_name[MAX_PATH];
+ char buf[16];
+
+ GetTempPathA(MAX_PATH, temp_path);
+ GetTempFileNameA(temp_path, "tmp", 0, file_name);
+
+ /* file */
+ SetLastError(0xdeadbeef);
+ file = CreateFileA(file_name, GENERIC_ALL, 0, NULL, CREATE_ALWAYS, 0, NULL);
+ ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+
+ access = get_obj_access(file);
+ ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", access);
+
+ for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
+ {
+ SetLastError( 0xdeadbeef );
+ ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup,
+ map[i].generic, FALSE, 0);
+ ok(ret, "DuplicateHandle error %d\n", GetLastError());
+
+ access = get_obj_access(dup);
+ ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+
+ CloseHandle(dup);
+ }
+
+ CloseHandle(file);
+
+ SetLastError(0xdeadbeef);
+ file = CreateFileA(file_name, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
+ ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+
+ access = get_obj_access(file);
+todo_wine
+ ok(access == (FILE_READ_ATTRIBUTES | SYNCHRONIZE), "expected FILE_READ_ATTRIBUTES | SYNCHRONIZE, got %#x\n", access);
+
+ bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(file, buf, sizeof(buf), &bytes, NULL);
+ ok(!ret, "ReadFile should fail\n");
+ ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
+ ok(bytes == 0, "expected 0, got %u\n", bytes);
+
+ CloseHandle(file);
+
+ SetLastError(0xdeadbeef);
+ file = CreateFileA(file_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
+ ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+
+ access = get_obj_access(file);
+todo_wine
+ ok(access == (FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES), "expected FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES, got %#x\n", access);
+
+ bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(file, buf, sizeof(buf), &bytes, NULL);
+ ok(!ret, "ReadFile should fail\n");
+ ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
+ ok(bytes == 0, "expected 0, got %u\n", bytes);
+
+ CloseHandle(file);
+ DeleteFileA(file_name);
+
+ /* directory */
+ SetLastError(0xdeadbeef);
+ file = CreateFileA(temp_path, GENERIC_ALL, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
+ ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+
+ access = get_obj_access(file);
+ ok(access == FILE_ALL_ACCESS, "expected FILE_ALL_ACCESS, got %#x\n", access);
+
+ for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
+ {
+ SetLastError( 0xdeadbeef );
+ ret = DuplicateHandle(GetCurrentProcess(), file, GetCurrentProcess(), &dup,
+ map[i].generic, FALSE, 0);
+ ok(ret, "DuplicateHandle error %d\n", GetLastError());
+
+ access = get_obj_access(dup);
+ ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+
+ CloseHandle(dup);
+ }
+
+ CloseHandle(file);
+
+ SetLastError(0xdeadbeef);
+ file = CreateFileA(temp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
+ ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+
+ access = get_obj_access(file);
+todo_wine
+ ok(access == (FILE_READ_ATTRIBUTES | SYNCHRONIZE), "expected FILE_READ_ATTRIBUTES | SYNCHRONIZE, got %#x\n", access);
+
+ CloseHandle(file);
+
+ SetLastError(0xdeadbeef);
+ file = CreateFileA(temp_path, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
+ ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+
+ access = get_obj_access(file);
+todo_wine
+ ok(access == (FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES), "expected FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES, got %#x\n", access);
+
+ CloseHandle(file);
+}
+
+static void test_filemap_security(void)
+{
+ char temp_path[MAX_PATH];
+ char file_name[MAX_PATH];
+ DWORD ret, i, access;
+ HANDLE file, mapping, dup;
+ static const struct
+ {
+ int generic, mapped;
+ } map[] =
+ {
+ { 0, 0 },
+ { GENERIC_READ, STANDARD_RIGHTS_READ | SECTION_QUERY | SECTION_MAP_READ },
+ { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | SECTION_MAP_WRITE },
+ { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SECTION_MAP_EXECUTE },
+ { GENERIC_ALL, STANDARD_RIGHTS_REQUIRED | SECTION_ALL_ACCESS }
+ };
+ static const struct
+ {
+ int prot, mapped;
+ } prot_map[] =
+ {
+ { 0, 0 },
+ { PAGE_NOACCESS, 0 },
+ { PAGE_READONLY, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ },
+ { PAGE_READWRITE, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE },
+ { PAGE_WRITECOPY, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ },
+ { PAGE_EXECUTE, 0 },
+ { PAGE_EXECUTE_READ, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE },
+ { PAGE_EXECUTE_READWRITE, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE },
+ { PAGE_EXECUTE_WRITECOPY, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE }
+ };
+
+ GetTempPathA(MAX_PATH, temp_path);
+ GetTempFileNameA(temp_path, "tmp", 0, file_name);
+
+ SetLastError(0xdeadbeef);
+ file = CreateFileA(file_name, GENERIC_READ|GENERIC_WRITE|GENERIC_EXECUTE, 0, NULL, CREATE_ALWAYS, 0, 0);
+ ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+ SetFilePointer(file, 4096, NULL, FILE_BEGIN);
+ SetEndOfFile(file);
+
+ for (i = 0; i < sizeof(prot_map)/sizeof(prot_map[0]); i++)
+ {
+ SetLastError(0xdeadbeef);
+ mapping = CreateFileMappingW(file, NULL, prot_map[i].prot, 0, 4096, NULL);
+ if (prot_map[i].mapped)
+ {
+ if (!mapping)
+ {
+ /* NT4 and win2k don't support EXEC on file mappings */
+ if (prot_map[i].prot == PAGE_EXECUTE_READ || prot_map[i].prot == PAGE_EXECUTE_READWRITE || prot_map[i].prot == PAGE_EXECUTE_WRITECOPY)
+ {
+ win_skip("CreateFileMapping doesn't support PAGE_EXECUTE protection\n");
+ continue;
+ }
+ }
+ ok(mapping != 0, "CreateFileMapping(%04x) error %d\n", prot_map[i].prot, GetLastError());
+ }
+ else
+ {
+ ok(!mapping, "CreateFileMapping(%04x) should fail\n", prot_map[i].prot);
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+ continue;
+ }
+
+ access = get_obj_access(mapping);
+ ok(access == prot_map[i].mapped, "%d: expected %#x, got %#x\n", i, prot_map[i].mapped, access);
+
+ CloseHandle(mapping);
+ }
+
+ SetLastError(0xdeadbeef);
+ mapping = CreateFileMappingW(file, NULL, PAGE_EXECUTE_READWRITE, 0, 4096, NULL);
+ if (!mapping)
+ {
+ /* NT4 and win2k don't support EXEC on file mappings */
+ win_skip("CreateFileMapping doesn't support PAGE_EXECUTE protection\n");
+ CloseHandle(file);
+ DeleteFileA(file_name);
+ return;
+ }
+ ok(mapping != 0, "CreateFileMapping error %d\n", GetLastError());
+
+ access = get_obj_access(mapping);
+ ok(access == (STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE),
+ "expected STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE, got %#x\n", access);
+
+ for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
+ {
+ SetLastError( 0xdeadbeef );
+ ret = DuplicateHandle(GetCurrentProcess(), mapping, GetCurrentProcess(), &dup,
+ map[i].generic, FALSE, 0);
+ ok(ret, "DuplicateHandle error %d\n", GetLastError());
+
+ access = get_obj_access(dup);
+ ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+
+ CloseHandle(dup);
+ }
+
+ CloseHandle(mapping);
CloseHandle(file);
+ DeleteFileA(file_name);
+}
+
+static void test_thread_security(void)
+{
+ DWORD ret, i, access;
+ HANDLE thread, dup;
+ static const struct
+ {
+ int generic, mapped;
+ } map[] =
+ {
+ { 0, 0 },
+ { GENERIC_READ, STANDARD_RIGHTS_READ | THREAD_QUERY_INFORMATION | THREAD_GET_CONTEXT },
+ { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | THREAD_SET_INFORMATION | THREAD_SET_CONTEXT | THREAD_TERMINATE | THREAD_SUSPEND_RESUME | 0x4 },
+ { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
+ { GENERIC_ALL, THREAD_ALL_ACCESS_NT4 }
+ };
+
+ SetLastError(0xdeadbeef);
+ thread = CreateThread(NULL, 0, (void *)0xdeadbeef, NULL, CREATE_SUSPENDED, &ret);
+ ok(thread != 0, "CreateThread error %d\n", GetLastError());
+
+ access = get_obj_access(thread);
+ ok(access == THREAD_ALL_ACCESS_NT4 || access == THREAD_ALL_ACCESS_VISTA, "expected THREAD_ALL_ACCESS, got %#x\n", access);
+
+ for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
+ {
+ SetLastError( 0xdeadbeef );
+ ret = DuplicateHandle(GetCurrentProcess(), thread, GetCurrentProcess(), &dup,
+ map[i].generic, FALSE, 0);
+ ok(ret, "DuplicateHandle error %d\n", GetLastError());
+
+ access = get_obj_access(dup);
+ switch (map[i].generic)
+ {
+ case GENERIC_READ:
+ case GENERIC_EXECUTE:
+ ok(access == map[i].mapped ||
+ access == (map[i].mapped | THREAD_QUERY_LIMITED_INFORMATION) /* Vista+ */ ||
+ access == (map[i].mapped | THREAD_QUERY_LIMITED_INFORMATION | THREAD_RESUME) /* win8 */,
+ "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+ break;
+ case GENERIC_WRITE:
+todo_wine
+ ok(access == map[i].mapped ||
+ access == (map[i].mapped | THREAD_SET_LIMITED_INFORMATION) /* Vista+ */ ||
+ access == (map[i].mapped | THREAD_SET_LIMITED_INFORMATION | THREAD_RESUME) /* win8 */,
+ "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+ break;
+ case GENERIC_ALL:
+ ok(access == map[i].mapped || access == THREAD_ALL_ACCESS_VISTA,
+ "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+ break;
+ default:
+ ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+ break;
+ }
+
+ CloseHandle(dup);
+ }
+
+ SetLastError( 0xdeadbeef );
+ ret = DuplicateHandle(GetCurrentProcess(), thread, GetCurrentProcess(), &dup,
+ THREAD_QUERY_INFORMATION, FALSE, 0);
+ ok(ret, "DuplicateHandle error %d\n", GetLastError());
+ access = get_obj_access(dup);
+ ok(access == (THREAD_QUERY_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION) /* Vista+ */ ||
+ access == THREAD_QUERY_INFORMATION /* before Vista */,
+ "expected THREAD_QUERY_INFORMATION|THREAD_QUERY_LIMITED_INFORMATION, got %#x\n", access);
+ CloseHandle(dup);
+
+ TerminateThread(thread, 0);
+ CloseHandle(thread);
+}
+
+static void test_process_access(void)
+{
+ DWORD ret, i, access;
+ HANDLE process, dup;
+ STARTUPINFOA sti;
+ PROCESS_INFORMATION pi;
+ char cmdline[] = "winver.exe";
+ static const struct
+ {
+ int generic, mapped;
+ } map[] =
+ {
+ { 0, 0 },
+ { GENERIC_READ, STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ },
+ { GENERIC_WRITE, STANDARD_RIGHTS_WRITE | PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION | PROCESS_SUSPEND_RESUME |
+ PROCESS_VM_WRITE | PROCESS_DUP_HANDLE | PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION },
+ { GENERIC_EXECUTE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE },
+ { GENERIC_ALL, PROCESS_ALL_ACCESS_NT4 }
+ };
+
+ memset(&sti, 0, sizeof(sti));
+ sti.cb = sizeof(sti);
+ SetLastError(0xdeadbeef);
+ ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &sti, &pi);
+ ok(ret, "CreateProcess() error %d\n", GetLastError());
+
+ CloseHandle(pi.hThread);
+ process = pi.hProcess;
+
+ access = get_obj_access(process);
+ ok(access == PROCESS_ALL_ACCESS_NT4 || access == PROCESS_ALL_ACCESS_VISTA, "expected PROCESS_ALL_ACCESS, got %#x\n", access);
+
+ for (i = 0; i < sizeof(map)/sizeof(map[0]); i++)
+ {
+ SetLastError( 0xdeadbeef );
+ ret = DuplicateHandle(GetCurrentProcess(), process, GetCurrentProcess(), &dup,
+ map[i].generic, FALSE, 0);
+ ok(ret, "DuplicateHandle error %d\n", GetLastError());
+
+ access = get_obj_access(dup);
+ switch (map[i].generic)
+ {
+ case GENERIC_READ:
+ ok(access == map[i].mapped || access == (map[i].mapped | PROCESS_QUERY_LIMITED_INFORMATION) /* Vista+ */,
+ "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+ break;
+ case GENERIC_WRITE:
+ ok(access == map[i].mapped ||
+ access == (map[i].mapped | PROCESS_TERMINATE) /* before Vista */ ||
+ access == (map[i].mapped | PROCESS_SET_LIMITED_INFORMATION) /* win8 */,
+ "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+ break;
+ case GENERIC_EXECUTE:
+ ok(access == map[i].mapped || access == (map[i].mapped | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE) /* Vista+ */,
+ "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+ break;
+ case GENERIC_ALL:
+ ok(access == map[i].mapped || access == PROCESS_ALL_ACCESS_VISTA,
+ "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+ break;
+ default:
+ ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
+ break;
+ }
+
+ CloseHandle(dup);
+ }
+
+ SetLastError( 0xdeadbeef );
+ ret = DuplicateHandle(GetCurrentProcess(), process, GetCurrentProcess(), &dup,
+ PROCESS_QUERY_INFORMATION, FALSE, 0);
+ ok(ret, "DuplicateHandle error %d\n", GetLastError());
+ access = get_obj_access(dup);
+ ok(access == (PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION) /* Vista+ */ ||
+ access == PROCESS_QUERY_INFORMATION /* before Vista */,
+ "expected PROCESS_QUERY_INFORMATION|PROCESS_QUERY_LIMITED_INFORMATION, got %#x\n", access);
+ CloseHandle(dup);
+
+ TerminateProcess(process, 0);
+ CloseHandle(process);
}
static BOOL validate_impersonation_token(HANDLE token, DWORD *token_type)
test_mutex_security(token);
test_event_security(token);
test_named_pipe_security(token);
+ test_semaphore_security(token);
+ test_file_security(token);
+ test_filemap_security();
+ test_thread_security();
+ test_process_access();
/* FIXME: test other kernel object types */
CloseHandle(process_token);
CloseHandle(token);
}
+static void test_default_dacl_owner_sid(void)
+{
+ HANDLE handle;
+ BOOL ret, defaulted, present, found;
+ DWORD size, index;
+ SECURITY_DESCRIPTOR *sd;
+ SECURITY_ATTRIBUTES sa;
+ PSID owner;
+ ACL *dacl;
+ ACCESS_ALLOWED_ACE *ace;
+
+ sd = HeapAlloc( GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH );
+ ret = InitializeSecurityDescriptor( sd, SECURITY_DESCRIPTOR_REVISION );
+ ok( ret, "error %u\n", GetLastError() );
+
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = sd;
+ sa.bInheritHandle = FALSE;
+ handle = CreateEventA( &sa, TRUE, TRUE, "test_event" );
+ ok( handle != NULL, "error %u\n", GetLastError() );
+
+ size = 0;
+ ret = GetKernelObjectSecurity( handle, OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, NULL, 0, &size );
+ ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "error %u\n", GetLastError() );
+
+ sd = HeapAlloc( GetProcessHeap(), 0, size );
+ ret = GetKernelObjectSecurity( handle, OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, sd, size, &size );
+ ok( ret, "error %u\n", GetLastError() );
+
+ owner = (void *)0xdeadbeef;
+ defaulted = TRUE;
+ ret = GetSecurityDescriptorOwner( sd, &owner, &defaulted );
+ ok( ret, "error %u\n", GetLastError() );
+ ok( owner != (void *)0xdeadbeef, "owner not set\n" );
+ ok( !defaulted, "owner defaulted\n" );
+
+ dacl = (void *)0xdeadbeef;
+ present = FALSE;
+ defaulted = TRUE;
+ ret = GetSecurityDescriptorDacl( sd, &present, &dacl, &defaulted );
+ ok( ret, "error %u\n", GetLastError() );
+ ok( present, "dacl not present\n" );
+ ok( dacl != (void *)0xdeadbeef, "dacl not set\n" );
+ ok( !defaulted, "dacl defaulted\n" );
+
+ index = 0;
+ found = FALSE;
+ while (pGetAce( dacl, index++, (void **)&ace ))
+ {
+ if (EqualSid( &ace->SidStart, owner )) found = TRUE;
+ }
+ ok( found, "owner sid not found in dacl\n" );
+
+ HeapFree( GetProcessHeap(), 0, sa.lpSecurityDescriptor );
+ HeapFree( GetProcessHeap(), 0, sd );
+ CloseHandle( handle );
+}
+
+static void test_AdjustTokenPrivileges(void)
+{
+ TOKEN_PRIVILEGES tp, prev;
+ HANDLE token;
+ DWORD len;
+ LUID luid;
+ BOOL ret;
+
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
+ return;
+
+ if (!LookupPrivilegeValueA(NULL, SE_BACKUP_NAME, &luid))
+ {
+ CloseHandle(token);
+ return;
+ }
+
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Luid = luid;
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ len = 0xdeadbeef;
+ ret = AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, &len);
+ ok(ret, "got %d\n", ret);
+ ok(len == 0xdeadbeef, "got length %d\n", len);
+
+ /* revert */
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Luid = luid;
+ tp.Privileges[0].Attributes = 0;
+ AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &prev, NULL);
+
+ CloseHandle(token);
+}
+
+static void test_AddAce(void)
+{
+ static SID const sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
+
+ char acl_buf[1024], ace_buf[256];
+ ACCESS_ALLOWED_ACE *ace = (ACCESS_ALLOWED_ACE*)ace_buf;
+ PACL acl = (PACL)acl_buf;
+ BOOL ret;
+
+ memset(ace, 0, sizeof(ace_buf));
+ ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
+ ace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD)+sizeof(SID);
+ memcpy(&ace->SidStart, &sidWorld, sizeof(sidWorld));
+
+ ret = InitializeAcl(acl, sizeof(acl_buf), ACL_REVISION2);
+ ok(ret, "InitializeAcl failed: %d\n", GetLastError());
+
+ ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize);
+ ok(ret, "AddAce failed: %d\n", GetLastError());
+ ret = AddAce(acl, ACL_REVISION2, MAXDWORD, ace, ace->Header.AceSize);
+ ok(ret, "AddAce failed: %d\n", GetLastError());
+ ret = AddAce(acl, ACL_REVISION3, MAXDWORD, ace, ace->Header.AceSize);
+ ok(ret, "AddAce failed: %d\n", GetLastError());
+ ok(acl->AclRevision == ACL_REVISION3, "acl->AclRevision = %d\n", acl->AclRevision);
+ ret = AddAce(acl, ACL_REVISION4, MAXDWORD, ace, ace->Header.AceSize);
+ ok(ret, "AddAce failed: %d\n", GetLastError());
+ ok(acl->AclRevision == ACL_REVISION4, "acl->AclRevision = %d\n", acl->AclRevision);
+ ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize);
+ ok(ret, "AddAce failed: %d\n", GetLastError());
+ ok(acl->AclRevision == ACL_REVISION4, "acl->AclRevision = %d\n", acl->AclRevision);
+ ret = AddAce(acl, ACL_REVISION2, MAXDWORD, ace, ace->Header.AceSize);
+ ok(ret, "AddAce failed: %d\n", GetLastError());
+
+ ret = AddAce(acl, MIN_ACL_REVISION-1, MAXDWORD, ace, ace->Header.AceSize);
+ ok(ret, "AddAce failed: %d\n", GetLastError());
+ /* next test succeededs but corrupts ACL */
+ ret = AddAce(acl, MAX_ACL_REVISION+1, MAXDWORD, ace, ace->Header.AceSize);
+ ok(ret, "AddAce failed: %d\n", GetLastError());
+ ok(acl->AclRevision == MAX_ACL_REVISION+1, "acl->AclRevision = %d\n", acl->AclRevision);
+ SetLastError(0xdeadbeef);
+ ret = AddAce(acl, ACL_REVISION1, MAXDWORD, ace, ace->Header.AceSize);
+ ok(!ret, "AddAce succeeded\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError() = %d\n", GetLastError());
+}
+
+static void test_system_security_access(void)
+{
+ static const WCHAR testkeyW[] =
+ {'S','O','F','T','W','A','R','E','\\','W','i','n','e','\\','S','A','C','L','t','e','s','t',0};
+ LONG res;
+ HKEY hkey;
+ PSECURITY_DESCRIPTOR sd;
+ ACL *sacl;
+ DWORD err, len = 128;
+ TOKEN_PRIVILEGES priv, *priv_prev;
+ HANDLE token;
+ LUID luid;
+ BOOL ret;
+
+ if (!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &token )) return;
+ if (!LookupPrivilegeValueA( NULL, SE_SECURITY_NAME, &luid ))
+ {
+ CloseHandle( token );
+ return;
+ }
+
+ /* ACCESS_SYSTEM_SECURITY requires special privilege */
+ res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ|ACCESS_SYSTEM_SECURITY, NULL, &hkey, NULL );
+ if (res == ERROR_ACCESS_DENIED)
+ {
+ skip( "unprivileged user\n" );
+ CloseHandle( token );
+ return;
+ }
+ todo_wine ok( res == ERROR_PRIVILEGE_NOT_HELD, "got %d\n", res );
+
+ priv.PrivilegeCount = 1;
+ priv.Privileges[0].Luid = luid;
+ priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ priv_prev = HeapAlloc( GetProcessHeap(), 0, len );
+ ret = AdjustTokenPrivileges( token, FALSE, &priv, len, priv_prev, &len );
+ ok( ret, "got %u\n", GetLastError());
+
+ res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ|ACCESS_SYSTEM_SECURITY, NULL, &hkey, NULL );
+ if (res == ERROR_PRIVILEGE_NOT_HELD)
+ {
+ win_skip( "privilege not held\n" );
+ HeapFree( GetProcessHeap(), 0, priv_prev );
+ CloseHandle( token );
+ return;
+ }
+ ok( !res, "got %d\n", res );
+
+ /* restore privileges */
+ ret = AdjustTokenPrivileges( token, FALSE, priv_prev, 0, NULL, NULL );
+ ok( ret, "got %u\n", GetLastError() );
+ HeapFree( GetProcessHeap(), 0, priv_prev );
+
+ /* privilege is checked on access */
+ err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
+ todo_wine ok( err == ERROR_PRIVILEGE_NOT_HELD, "got %u\n", err );
+
+ priv.PrivilegeCount = 1;
+ priv.Privileges[0].Luid = luid;
+ priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ priv_prev = HeapAlloc( GetProcessHeap(), 0, len );
+ ret = AdjustTokenPrivileges( token, FALSE, &priv, len, priv_prev, &len );
+ ok( ret, "got %u\n", GetLastError());
+
+ err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
+ ok( err == ERROR_SUCCESS, "got %u\n", err );
+ RegCloseKey( hkey );
+ LocalFree( sd );
+
+ /* handle created without ACCESS_SYSTEM_SECURITY, privilege held */
+ res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ, NULL, &hkey, NULL );
+ ok( res == ERROR_SUCCESS, "got %d\n", res );
+
+ sd = NULL;
+ err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
+ todo_wine ok( err == ERROR_SUCCESS, "got %u\n", err );
+ RegCloseKey( hkey );
+ LocalFree( sd );
+
+ /* restore privileges */
+ ret = AdjustTokenPrivileges( token, FALSE, priv_prev, 0, NULL, NULL );
+ ok( ret, "got %u\n", GetLastError() );
+ HeapFree( GetProcessHeap(), 0, priv_prev );
+
+ /* handle created without ACCESS_SYSTEM_SECURITY, privilege not held */
+ res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ, NULL, &hkey, NULL );
+ ok( res == ERROR_SUCCESS, "got %d\n", res );
+
+ err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd );
+ todo_wine ok( err == ERROR_PRIVILEGE_NOT_HELD, "got %u\n", err );
+ RegCloseKey( hkey );
+
+ res = RegDeleteKeyW( HKEY_LOCAL_MACHINE, testkeyW );
+ ok( !res, "got %d\n", res );
+ CloseHandle( token );
+}
+
+static void test_GetWindowsAccountDomainSid(void)
+{
+ char *user, buffer1[SECURITY_MAX_SID_SIZE], buffer2[SECURITY_MAX_SID_SIZE];
+ SID_IDENTIFIER_AUTHORITY domain_ident = { SECURITY_NT_AUTHORITY };
+ PSID domain_sid = (PSID *)&buffer1;
+ PSID domain_sid2 = (PSID *)&buffer2;
+ DWORD sid_size;
+ PSID user_sid;
+ HANDLE token;
+ BOOL bret = TRUE;
+ int i;
+
+ if (!pGetWindowsAccountDomainSid)
+ {
+ win_skip("GetWindowsAccountDomainSid not available\n");
+ return;
+ }
+
+ if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
+ {
+ if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE;
+ else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE;
+ }
+ if (!bret)
+ {
+ win_skip("Failed to get current user token\n");
+ return;
+ }
+
+ bret = GetTokenInformation(token, TokenUser, NULL, 0, &sid_size);
+ ok(!bret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
+ user = HeapAlloc(GetProcessHeap(), 0, sid_size);
+ bret = GetTokenInformation(token, TokenUser, user, sid_size, &sid_size);
+ ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
+ CloseHandle(token);
+ user_sid = ((TOKEN_USER *)user)->User.Sid;
+
+ SetLastError(0xdeadbeef);
+ bret = pGetWindowsAccountDomainSid(0, 0, 0);
+ ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
+ ok(GetLastError() == ERROR_INVALID_SID, "expected ERROR_INVALID_SID, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ bret = pGetWindowsAccountDomainSid(user_sid, 0, 0);
+ ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ sid_size = SECURITY_MAX_SID_SIZE;
+ SetLastError(0xdeadbeef);
+ bret = pGetWindowsAccountDomainSid(user_sid, 0, &sid_size);
+ ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+ ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size);
+
+ SetLastError(0xdeadbeef);
+ bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, 0);
+ ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ sid_size = 1;
+ SetLastError(0xdeadbeef);
+ bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, &sid_size);
+ ok(!bret, "GetWindowsAccountDomainSid succeeded\n");
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+ ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size);
+
+ sid_size = SECURITY_MAX_SID_SIZE;
+ bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, &sid_size);
+ ok(bret, "GetWindowsAccountDomainSid failed with error %d\n", GetLastError());
+ ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size);
+ InitializeSid(domain_sid2, &domain_ident, 4);
+ for (i = 0; i < 4; i++)
+ *GetSidSubAuthority(domain_sid2, i) = *GetSidSubAuthority(user_sid, i);
+ ok(EqualSid(domain_sid, domain_sid2), "unexpected domain sid\n");
+
+ HeapFree(GetProcessHeap(), 0, user);
+}
+
START_TEST(security)
{
init();
test_impersonation_level();
test_SetEntriesInAclW();
test_SetEntriesInAclA();
+ test_CreateDirectoryA();
test_GetNamedSecurityInfoA();
test_ConvertStringSecurityDescriptor();
test_ConvertSecurityDescriptorToString();
test_PrivateObjectSecurity();
test_acls();
+ test_GetWindowsAccountDomainSid();
test_GetSecurityInfo();
test_GetSidSubAuthority();
test_CheckTokenMembership();
test_GetUserNameW();
test_CreateRestrictedToken();
test_TokenIntegrityLevel();
+ test_default_dacl_owner_sid();
+ test_AdjustTokenPrivileges();
+ test_AddAce();
+ test_system_security_access();
}