From a91416131ee83e6fb49a8479c57dd5fd779514df Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Mon, 25 May 2015 18:46:12 +0000 Subject: [PATCH] [ADVAPI32_WINETEST] Sync with Wine Staging 1.7.43. svn path=/trunk/; revision=67915 --- rostests/winetests/advapi32/CMakeLists.txt | 2 +- rostests/winetests/advapi32/security.c | 717 ++++++++++++++++----- rostests/winetests/advapi32/service.c | 141 +++- 3 files changed, 698 insertions(+), 162 deletions(-) diff --git a/rostests/winetests/advapi32/CMakeLists.txt b/rostests/winetests/advapi32/CMakeLists.txt index fd902e77676..f0fad3a6344 100644 --- a/rostests/winetests/advapi32/CMakeLists.txt +++ b/rostests/winetests/advapi32/CMakeLists.txt @@ -22,5 +22,5 @@ if(NOT MSVC) endif() set_module_type(advapi32_winetest win32cui) -add_importlibs(advapi32_winetest advapi32 ole32 msvcrt kernel32) +add_importlibs(advapi32_winetest advapi32 ole32 msvcrt kernel32 ntdll) add_cd_file(TARGET advapi32_winetest DESTINATION reactos/bin FOR all) diff --git a/rostests/winetests/advapi32/security.c b/rostests/winetests/advapi32/security.c index f5c58dd63b0..5043e414090 100644 --- a/rostests/winetests/advapi32/security.c +++ b/rostests/winetests/advapi32/security.c @@ -28,6 +28,7 @@ #include "windef.h" #include "winbase.h" #include "winerror.h" +#include "wine/winternl.h" #include "aclapi.h" #include "winnt.h" #include "sddl.h" @@ -62,29 +63,6 @@ #define THREAD_ALL_ACCESS_NT4 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff) #define THREAD_ALL_ACCESS_VISTA (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xffff) -/* 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; - #define expect_eq(expr, value, type, format) { type ret_ = expr; ok((value) == ret_, #expr " expected " format " got " format "\n", (value), (ret_)); } static BOOL (WINAPI *pAddAccessAllowedAceEx)(PACL, DWORD, DWORD, DWORD, PSID); @@ -150,6 +128,10 @@ static BOOL (WINAPI *pCreateRestrictedToken)(HANDLE, DWORD, DWORD, PSID_AND_ATTR 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 HMODULE hmod; static int myARGC; @@ -176,6 +158,10 @@ static void init(void) hntdll = GetModuleHandleA("ntdll.dll"); pNtQueryObject = (void *)GetProcAddress( hntdll, "NtQueryObject" ); pNtAccessCheck = (void *)GetProcAddress( hntdll, "NtAccessCheck" ); + pNtSetSecurityObject = (void *)GetProcAddress(hntdll, "NtSetSecurityObject"); + pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile"); + pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U"); + pRtlAnsiStringToUnicodeString = (void *)GetProcAddress(hntdll, "RtlAnsiStringToUnicodeString"); hmod = GetModuleHandleA("advapi32.dll"); pAddAccessAllowedAceEx = (void *)GetProcAddress(hmod, "AddAccessAllowedAceEx"); @@ -2531,19 +2517,21 @@ static void test_granted_access(HANDLE handle, ACCESS_MASK access, static void test_process_security(void) { BOOL res; + PTOKEN_USER user; PTOKEN_OWNER owner; PTOKEN_PRIMARY_GROUP group; - PSID AdminSid = NULL, UsersSid = NULL; + PSID AdminSid = NULL, UsersSid = NULL, UserSid = NULL; PACL Acl = NULL, ThreadAcl = NULL; SECURITY_DESCRIPTOR *SecurityDescriptor = NULL, *ThreadSecurityDescriptor = NULL; - char buffer[MAX_PATH]; + char buffer[MAX_PATH], account[MAX_PATH], domain[MAX_PATH]; PROCESS_INFORMATION info; STARTUPINFOA startup; 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); @@ -2575,7 +2563,8 @@ static void test_process_security(void) 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); @@ -2585,13 +2574,34 @@ static void test_process_security(void) 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; } @@ -2698,6 +2708,7 @@ static void test_process_security(void) 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); @@ -3142,6 +3153,98 @@ static void test_SetEntriesInAclA(void) HeapFree(GetProcessHeap(), 0, OldAcl); } +/* 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; + RtlInitAnsiString(&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"); + + RtlFreeUnicodeString(&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], *user; @@ -3150,17 +3253,20 @@ static void test_CreateDirectoryA(void) char sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; PSECURITY_DESCRIPTOR pSD = &sd; ACL_SIZE_INFORMATION acl_size; - ACCESS_ALLOWED_ACE *ace; + UNICODE_STRING tmpfileW; SECURITY_ATTRIBUTES sa; + OBJECT_ATTRIBUTES attr; char tmpfile[MAX_PATH]; char tmpdir[MAX_PATH]; HANDLE token, hTemp; + IO_STATUS_BLOCK io; struct _SID *owner; BOOL bret = TRUE; + NTSTATUS status; DWORD error; PACL pDacl; - if (!pGetNamedSecurityInfoA || !pCreateWellKnownSid) + if (!pGetSecurityInfo || !pGetNamedSecurityInfoA || !pCreateWellKnownSid) { win_skip("Required functions are not available\n"); return; @@ -3218,72 +3324,288 @@ static void test_CreateDirectoryA(void) 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); + + /* Test inheritance of ACLs in CreateFile without security descriptor */ + strcpy(tmpfile, tmpdir); + lstrcatA(tmpfile, "/tmpfile"); + + 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()); + + 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); + /* 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 == 2, "GetAclInformation returned unexpected entry count (%d != 2).\n", + ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n", acl_size.AceCount); - 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); - ok(bret, "Current User ACE != Current User SID.\n"); - ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE), - "Current User ACE has unexpected flags (0x%x != 0x03)\n", - ((ACE_HEADER *)ace)->AceFlags); - 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); - ok(bret, "Administators Group ACE != Administators Group SID.\n"); - ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE), - "Administators Group ACE has unexpected flags (0x%x != 0x03)\n", - ((ACE_HEADER *)ace)->AceFlags); - ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", - ace->Mask); - } LocalFree(pSD); - /* Test inheritance of ACLs */ + 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); + + /* Test inheritance of ACLs in NtCreateFile without security descriptor */ strcpy(tmpfile, tmpdir); lstrcatA(tmpfile, "/tmpfile"); - hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, - FILE_FLAG_DELETE_ON_CLOSE, NULL); + 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); + 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"); + 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); + + /* 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); + 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"); - ok(acl_size.AceCount == 2, "GetAclInformation returned unexpected entry count (%d != 2).\n", + todo_wine + ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n", acl_size.AceCount); - if (acl_size.AceCount > 0) - { - bret = pGetAce(pDacl, 0, (VOID **)&ace); - ok(bret, "Inherited Failed to get Current User ACE.\n"); - bret = EqualSid(&ace->SidStart, user_sid); - ok(bret, "Inherited Current User ACE != Current User SID.\n"); - ok(((ACE_HEADER *)ace)->AceFlags == INHERITED_ACE, - "Inherited Current User ACE has unexpected flags (0x%x != 0x10)\n", ((ACE_HEADER *)ace)->AceFlags); - 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, "Inherited Failed to get Administators Group ACE.\n"); - bret = EqualSid(&ace->SidStart, admin_sid); - ok(bret, "Inherited Administators Group ACE != Administators Group SID.\n"); - ok(((ACE_HEADER *)ace)->AceFlags == INHERITED_ACE, - "Inherited Administators Group ACE has unexpected flags (0x%x != 0x10)\n", ((ACE_HEADER *)ace)->AceFlags); - ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", - ace->Mask); - } + 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); + + /* 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); + + SetLastError(0xdeadbeef); + 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); + + pSD = &sd; + InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_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); + 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"); + error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, + NULL, pDacl, NULL); + 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: @@ -3303,7 +3625,7 @@ static void test_GetNamedSecurityInfoA(void) 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]; + char sd[SECURITY_DESCRIPTOR_MIN_LENGTH+sizeof(void*)]; SECURITY_DESCRIPTOR_CONTROL control; ACL_SIZE_INFORMATION acl_size; CHAR windows_dir[MAX_PATH]; @@ -3315,11 +3637,12 @@ static void test_GetNamedSecurityInfoA(void) BOOL owner_defaulted; BOOL group_defaulted; BOOL dacl_defaulted; - HANDLE token, hTemp; + HANDLE token, hTemp, h; PSID owner, group; BOOL dacl_present; PACL pDacl; BYTE flags; + NTSTATUS status; if (!pSetNamedSecurityInfoA || !pGetNamedSecurityInfoA || !pCreateWellKnownSid) { @@ -3424,8 +3747,8 @@ static void test_GetNamedSecurityInfoA(void) 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); + 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); @@ -3460,8 +3783,8 @@ static void test_GetNamedSecurityInfoA(void) 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) { @@ -3475,47 +3798,18 @@ static void test_GetNamedSecurityInfoA(void) "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask); } LocalFree(pSD); - CloseHandle(hTemp); - /* Create security descriptor with no inheritance 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); + /* 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"); - 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, 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|PROTECTED_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; - } + error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, + NULL, NULL, pDacl, NULL); ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error); - SetLastError(0xdeadbeef); + HeapFree(GetProcessHeap(), 0, pDacl); + 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; - } + NULL, NULL, &pDacl, NULL, &pSD); ok(!error, "GetNamedSecurityInfo failed with error %d\n", error); bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); @@ -3523,26 +3817,100 @@ static void test_GetNamedSecurityInfoA(void) 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); - 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); - } - 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); - 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); + 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); @@ -3728,6 +4096,13 @@ 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) @@ -4201,7 +4576,7 @@ static void test_GetSecurityInfo(void) 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) { @@ -4211,8 +4586,8 @@ static void test_GetSecurityInfo(void) 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); @@ -5695,6 +6070,51 @@ static void test_AdjustTokenPrivileges(void) 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()); +} + START_TEST(security) { init(); @@ -5736,4 +6156,5 @@ START_TEST(security) test_TokenIntegrityLevel(); test_default_dacl_owner_sid(); test_AdjustTokenPrivileges(); + test_AddAce(); } diff --git a/rostests/winetests/advapi32/service.c b/rostests/winetests/advapi32/service.c index e54de7a1ea6..2b533edacad 100644 --- a/rostests/winetests/advapi32/service.c +++ b/rostests/winetests/advapi32/service.c @@ -53,6 +53,7 @@ static BOOL (WINAPI *pQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD); static BOOL (WINAPI *pQueryServiceObjectSecurity)(SC_HANDLE, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, LPDWORD); +static DWORD (WINAPI *pNotifyServiceStatusChangeW)(SC_HANDLE,DWORD,SERVICE_NOTIFYW*); static void init_function_pointers(void) { @@ -66,6 +67,7 @@ static void init_function_pointers(void) pQueryServiceConfig2W= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2W"); pQueryServiceStatusEx= (void*)GetProcAddress(hadvapi32, "QueryServiceStatusEx"); pQueryServiceObjectSecurity = (void*)GetProcAddress(hadvapi32, "QueryServiceObjectSecurity"); + pNotifyServiceStatusChangeW = (void*)GetProcAddress(hadvapi32, "NotifyServiceStatusChangeW"); } static void test_open_scm(void) @@ -2201,6 +2203,75 @@ static DWORD try_start_stop(SC_HANDLE svc_handle, const char* name, DWORD is_nt4 return le1; } +struct notify_data { + SERVICE_NOTIFYW notify; + SC_HANDLE svc; +}; + +static void CALLBACK cb_stopped(void *user) +{ + struct notify_data *data = user; + BOOL br; + + ok(data->notify.dwNotificationStatus == ERROR_SUCCESS, + "Got wrong notification status: %u\n", data->notify.dwNotificationStatus); + ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_STOPPED, + "Got wrong service state: 0x%x\n", data->notify.ServiceStatus.dwCurrentState); + ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_STOPPED, + "Got wrong notification triggered: 0x%x\n", data->notify.dwNotificationTriggered); + + br = StartServiceA(data->svc, 0, NULL); + ok(br, "StartService failed: %u\n", GetLastError()); +} + +static void CALLBACK cb_running(void *user) +{ + struct notify_data *data = user; + BOOL br; + SERVICE_STATUS status; + + ok(data->notify.dwNotificationStatus == ERROR_SUCCESS, + "Got wrong notification status: %u\n", data->notify.dwNotificationStatus); + ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_RUNNING, + "Got wrong service state: 0x%x\n", data->notify.ServiceStatus.dwCurrentState); + ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_RUNNING, + "Got wrong notification triggered: 0x%x\n", data->notify.dwNotificationTriggered); + + br = ControlService(data->svc, SERVICE_CONTROL_STOP, &status); + ok(br, "ControlService failed: %u\n", GetLastError()); +} + +static void test_servicenotify(SC_HANDLE svc) +{ + DWORD dr; + struct notify_data data; + + if(!pNotifyServiceStatusChangeW){ + win_skip("No NotifyServiceStatusChangeW\n"); + return; + } + + memset(&data.notify, 0, sizeof(data.notify)); + data.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE; + data.notify.pfnNotifyCallback = &cb_stopped; + data.notify.pContext = &data; + data.svc = svc; + + dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify); + ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %u\n", dr); + + dr = SleepEx(100, TRUE); + ok(dr == WAIT_IO_COMPLETION, "APC wasn't called\n"); + + data.notify.pfnNotifyCallback = &cb_running; + + dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify); + ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %u\n", dr); + + dr = SleepEx(100, TRUE); + ok(dr == WAIT_IO_COMPLETION, "APC wasn't called\n"); +} + static void test_start_stop(void) { BOOL ret; @@ -2279,17 +2350,12 @@ static void test_start_stop(void) le = try_start_stop(svc_handle, displayname, is_nt4); ok(le == ERROR_SERVICE_REQUEST_TIMEOUT, "%d != ERROR_SERVICE_REQUEST_TIMEOUT\n", le); - /* And finally with a service that plays dead, forcing a timeout. - * This time we will put no quotes. That should work too, even if there are - * spaces in the path. - */ - sprintf(cmd, "%s service sleep", selfname); - displayname = "Winetest Sleep Service"; + /* create a real service and test notifications */ + sprintf(cmd, "%s service serve", selfname); + displayname = "Winetest Service"; ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, cmd, NULL, NULL, NULL, NULL, NULL, displayname); ok(ret, "ChangeServiceConfig() failed le=%u\n", GetLastError()); - - le = try_start_stop(svc_handle, displayname, is_nt4); - ok(le == ERROR_SERVICE_REQUEST_TIMEOUT, "%d != ERROR_SERVICE_REQUEST_TIMEOUT\n", le); + test_servicenotify(svc_handle); cleanup: if (svc_handle) @@ -2394,6 +2460,57 @@ static void test_refcount(void) CloseServiceHandle(scm_handle); } +static DWORD WINAPI ctrl_handler(DWORD ctl, DWORD type, void *data, void *user) +{ + HANDLE evt = user; + + switch(ctl){ + case SERVICE_CONTROL_STOP: + SetEvent(evt); + break; + case SERVICE_CONTROL_INTERROGATE: + return NO_ERROR; + } + + return ERROR_CALL_NOT_IMPLEMENTED; +} + +static void WINAPI service_main(DWORD argc, char **argv) +{ + SERVICE_STATUS_HANDLE st_handle; + SERVICE_STATUS st; + HANDLE evt = CreateEventW(0, FALSE, FALSE, 0); + + st_handle = RegisterServiceCtrlHandlerExA("", &ctrl_handler, evt); + + st.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + st.dwServiceSpecificExitCode = 0; + st.dwCurrentState = SERVICE_RUNNING; + st.dwWin32ExitCode = NO_ERROR; + st.dwWaitHint = 0; + st.dwControlsAccepted = SERVICE_ACCEPT_STOP; + st.dwCheckPoint = 0; + + SetServiceStatus(st_handle, &st); + + WaitForSingleObject(evt, 5000); + + st.dwCurrentState = SERVICE_STOPPED; + + SetServiceStatus(st_handle, &st); +} + +static void run_service(void) +{ + char empty[] = {0}; + SERVICE_TABLE_ENTRYA table[] = { + {empty, &service_main }, + {0, 0} + }; + + StartServiceCtrlDispatcherA(table); +} + START_TEST(service) { SC_HANDLE scm_handle; @@ -2404,10 +2521,8 @@ START_TEST(service) GetFullPathNameA(myARGV[0], sizeof(selfname), selfname, NULL); if (myARGC >= 3) { - if (strcmp(myARGV[2], "sleep") == 0) - /* Cause a service startup timeout */ - Sleep(90000); - /* then, or if myARGV[2] == "exit", just exit */ + if (strcmp(myARGV[2], "serve") == 0) + run_service(); return; } -- 2.17.1