From: Amine Khaldi Date: Sun, 6 Mar 2016 16:43:16 +0000 (+0000) Subject: [ADVAPI32_WINETEST] Sync with Wine Staging 1.9.4. CORE-10912 X-Git-Tag: ReactOS-0.4.1~253 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=bab6d16d7c466a0e67ff0dc9dab8ccad4351e213 [ADVAPI32_WINETEST] Sync with Wine Staging 1.9.4. CORE-10912 svn path=/trunk/; revision=70962 --- diff --git a/rostests/winetests/advapi32/crypt.c b/rostests/winetests/advapi32/crypt.c index ebae143f005..84a54a13e53 100644 --- a/rostests/winetests/advapi32/crypt.c +++ b/rostests/winetests/advapi32/crypt.c @@ -961,7 +961,13 @@ static void test_machine_guid(void) { restoreGuid = TRUE; r = RegDeleteValueA(key, "MachineGuid"); - ok(!r, "RegDeleteValueA failed: %d\n", r); + ok(!r || broken(r == ERROR_ACCESS_DENIED) /*win8*/, "RegDeleteValueA failed: %d\n", r); + if (r == ERROR_ACCESS_DENIED) + { + skip("broken virtualization on HKLM\\Software\\Microsoft\\Cryptography\n"); + RegCloseKey(key); + return; + } } else ok(r == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", diff --git a/rostests/winetests/advapi32/eventlog.c b/rostests/winetests/advapi32/eventlog.c index 1e483482df5..3ca59c39887 100644 --- a/rostests/winetests/advapi32/eventlog.c +++ b/rostests/winetests/advapi32/eventlog.c @@ -487,7 +487,7 @@ static void test_read(void) ok(!ret, "Expected failure\n"); ok(read == 0, "Expected no bytes read\n"); ok(needed > sizeof(EVENTLOGRECORD), "Expected the needed buffersize to be bigger than sizeof(EVENTLOGRECORD)\n"); - ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); /* Read the first record */ toread = needed; diff --git a/rostests/winetests/advapi32/registry.c b/rostests/winetests/advapi32/registry.c index 7d16cb38f83..407c18bc9a8 100644 --- a/rostests/winetests/advapi32/registry.c +++ b/rostests/winetests/advapi32/registry.c @@ -44,7 +44,8 @@ static const char * sTestpath2 = "%FOO%\\subdir1"; static const DWORD ptr_size = 8 * sizeof(void*); static DWORD (WINAPI *pRegGetValueA)(HKEY,LPCSTR,LPCSTR,DWORD,LPDWORD,PVOID,LPDWORD); -static DWORD (WINAPI *pRegDeleteTreeA)(HKEY,LPCSTR); +static LONG (WINAPI *pRegCopyTreeA)(HKEY,const char *,HKEY); +static LONG (WINAPI *pRegDeleteTreeA)(HKEY,const char *); static DWORD (WINAPI *pRegDeleteKeyExA)(HKEY,LPCSTR,REGSAM,DWORD); static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL); static NTSTATUS (WINAPI * pNtDeleteKey)(HANDLE); @@ -138,6 +139,7 @@ static void InitFunctionPtrs(void) /* This function was introduced with Windows 2003 SP1 */ ADVAPI32_GET_PROC(RegGetValueA); + ADVAPI32_GET_PROC(RegCopyTreeA); ADVAPI32_GET_PROC(RegDeleteTreeA); ADVAPI32_GET_PROC(RegDeleteKeyExA); ADVAPI32_GET_PROC(RegDeleteKeyValueA); @@ -1343,6 +1345,13 @@ static void test_reg_create_key(void) RegDeleteKeyA(hkey1, ""); RegCloseKey(hkey1); + /* System\CurrentControlSet\Control\Video should be non-volatile */ + ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\Video\\Wine", + 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL); + ok(ret == ERROR_SUCCESS, "RegCreateKeyExA failed with error %d\n", ret); + RegDeleteKeyA(hkey1, ""); + RegCloseKey(hkey1); + /* WOW64 flags - open an existing key */ hkey1 = NULL; ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0, KEY_READ|KEY_WOW64_32KEY, NULL, &hkey1, NULL); @@ -2082,10 +2091,106 @@ static void test_string_termination(void) RegCloseKey(subkey); } +static void test_reg_copy_tree(void) +{ + HKEY src, dst, subkey; + CHAR buffer[MAX_PATH]; + DWORD dwsize, type; + LONG size, ret; + + if (!pRegCopyTreeA) + { + win_skip("Skipping RegCopyTreeA tests, function not present\n"); + return; + } + + ret = RegCreateKeyA(hkey_main, "src", &src); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + ret = RegCreateKeyA(hkey_main, "dst", &dst); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + + /* Copy nonexistent subkey */ + ret = pRegCopyTreeA(src, "nonexistent_subkey", dst); + ok(ret == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", ret); + + /* Create test keys and values */ + ret = RegSetValueA(src, NULL, REG_SZ, "data", 4); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + ret = RegSetValueExA(src, "value", 0, REG_SZ, (const BYTE *)"data2", 5); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + + ret = RegCreateKeyA(src, "subkey2", &subkey); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + ret = RegSetValueA(subkey, NULL, REG_SZ, "data3", 5); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + ret = RegSetValueExA(subkey, "value", 0, REG_SZ, (const BYTE *)"data4", 5); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + ret = RegCloseKey(subkey); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + + ret = RegCreateKeyA(src, "subkey3", &subkey); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + ret = RegCloseKey(subkey); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + + /* Copy subkey */ + ret = pRegCopyTreeA(src, "subkey2", dst); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + + size = MAX_PATH; + ret = RegQueryValueA(dst, NULL, buffer, &size); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + ok(!strcmp(buffer, "data3"), "Expected 'data3', got '%s'\n", buffer); + + dwsize = MAX_PATH; + ret = RegQueryValueExA(dst, "value", NULL, &type, (BYTE *)buffer, &dwsize); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + ok(type == REG_SZ, "Expected REG_SZ, got %u\n", type); + ok(!strcmp(buffer, "data4"), "Expected 'data4', got '%s'\n", buffer); + + /* Copy full tree */ + ret = pRegCopyTreeA(src, NULL, dst); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + + size = MAX_PATH; + ret = RegQueryValueA(dst, NULL, buffer, &size); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + ok(!strcmp(buffer, "data"), "Expected 'data', got '%s'\n", buffer); + + dwsize = MAX_PATH; + ret = RegQueryValueExA(dst, "value", NULL, &type, (BYTE *)buffer, &dwsize); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + ok(type == REG_SZ, "Expected REG_SZ, got %u\n", type); + ok(!strcmp(buffer, "data2"), "Expected 'data2', got '%s'\n", buffer); + + ret = RegOpenKeyA(dst, "subkey2", &subkey); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + size = MAX_PATH; + ret = RegQueryValueA(subkey, NULL, buffer, &size); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + ok(!strcmp(buffer, "data3"), "Expected 'data3', got '%s'\n", buffer); + dwsize = MAX_PATH; + ret = RegQueryValueExA(subkey, "value", NULL, &type, (BYTE *)buffer, &dwsize); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + ok(type == REG_SZ, "Expected REG_SZ, got %u\n", type); + ok(!strcmp(buffer, "data4"), "Expected 'data4', got '%s'\n", buffer); + ret = RegCloseKey(subkey); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + + ret = RegOpenKeyA(dst, "subkey3", &subkey); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + ret = RegCloseKey(subkey); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + + delete_key(src); + delete_key(dst); +} + static void test_reg_delete_tree(void) { CHAR buffer[MAX_PATH]; HKEY subkey, subkey2; + DWORD dwsize, type; LONG size, ret; if(!pRegDeleteTreeA) { @@ -2131,7 +2236,9 @@ static void test_reg_delete_tree(void) ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); ret = RegCloseKey(subkey2); ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); - ret = RegSetValueA(subkey, "value", REG_SZ, "data2", 5); + ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4); + ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); + ret = RegSetValueExA(subkey, "value", 0, REG_SZ, (const BYTE *)"data2", 5); ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); ret = pRegDeleteTreeA(subkey, NULL); ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); @@ -2146,8 +2253,8 @@ static void test_reg_delete_tree(void) ok(ret == ERROR_SUCCESS, "Default value of subkey is not present\n"); ok(!buffer[0], "Expected length 0 got length %u(%s)\n", lstrlenA(buffer), buffer); - size = MAX_PATH; - ok(RegQueryValueA(subkey, "value", buffer, &size), + dwsize = MAX_PATH; + ok(RegQueryValueExA(subkey, "value", NULL, &type, (BYTE *)buffer, &dwsize), "Value is still present\n"); ret = pRegDeleteTreeA(hkey_main, "not-here"); @@ -3281,6 +3388,18 @@ static void test_delete_key_value(void) RegCloseKey(subkey); } +static void test_RegOpenCurrentUser(void) +{ + HKEY key; + LONG ret; + + key = HKEY_CURRENT_USER; + ret = RegOpenCurrentUser(KEY_READ, &key); + ok(!ret, "got %d, error %d\n", ret, GetLastError()); + ok(key != HKEY_CURRENT_USER, "got %p\n", key); + RegCloseKey(key); +} + START_TEST(registry) { /* Load pointers for functions that are not available in all Windows versions */ @@ -3305,16 +3424,16 @@ START_TEST(registry) test_classesroot(); test_classesroot_enum(); test_classesroot_mask(); - test_reg_save_key(); test_reg_load_key(); test_reg_unload_key(); - + test_reg_copy_tree(); test_reg_delete_tree(); test_rw_order(); test_deleted_key(); test_delete_value(); test_delete_key_value(); + test_RegOpenCurrentUser(); /* cleanup */ delete_key( hkey_main ); diff --git a/rostests/winetests/advapi32/security.c b/rostests/winetests/advapi32/security.c index 1c88ceafc81..e99cfd71204 100644 --- a/rostests/winetests/advapi32/security.c +++ b/rostests/winetests/advapi32/security.c @@ -39,6 +39,11 @@ #include "wine/test.h" +/* FIXME: Inspect */ +#define GetCurrentProcessToken() ((HANDLE)~(ULONG_PTR)3) +#define GetCurrentThreadToken() ((HANDLE)~(ULONG_PTR)4) +#define GetCurrentThreadEffectiveToken() ((HANDLE)~(ULONG_PTR)5) + #ifndef PROCESS_QUERY_LIMITED_INFORMATION #define PROCESS_QUERY_LIMITED_INFORMATION 0x1000 #endif @@ -135,6 +140,7 @@ static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING,PCANSI_S static BOOL (WINAPI *pGetWindowsAccountDomainSid)(PSID,PSID,DWORD*); static void (WINAPI *pRtlInitAnsiString)(PANSI_STRING,PCSZ); static NTSTATUS (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING); +static PSID_IDENTIFIER_AUTHORITY (WINAPI *pGetSidIdentifierAuthority)(PSID); static HMODULE hmod; static int myARGC; @@ -148,6 +154,35 @@ struct strsid_entry #define STRSID_OK 0 #define STRSID_OPT 1 +#define SID_SLOTS 4 +static char debugsid_str[SID_SLOTS][256]; +static int debugsid_index = 0; +static const char* debugstr_sid(PSID sid) +{ + LPSTR sidstr; + DWORD le = GetLastError(); + char* res = debugsid_str[debugsid_index]; + debugsid_index = (debugsid_index + 1) % SID_SLOTS; + if (!pConvertSidToStringSidA) + strcpy(res, "missing ConvertSidToStringSidA"); + else if (!pConvertSidToStringSidA(sid, &sidstr)) + sprintf(res, "ConvertSidToStringSidA failed le=%u", GetLastError()); + else if (strlen(sidstr) > sizeof(*debugsid_str) - 1) + { + memcpy(res, sidstr, sizeof(*debugsid_str) - 4); + strcpy(res + sizeof(*debugsid_str) - 4, "..."); + LocalFree(sidstr); + } + else + { + strcpy(res, sidstr); + LocalFree(sidstr); + } + /* Restore the last error in case ConvertSidToStringSidA() modified it */ + SetLastError(le); + return res; +} + struct sidRef { SID_IDENTIFIER_AUTHORITY auth; @@ -199,6 +234,7 @@ static void init(void) pGetAclInformation = (void *)GetProcAddress(hmod, "GetAclInformation"); pGetAce = (void *)GetProcAddress(hmod, "GetAce"); pGetWindowsAccountDomainSid = (void *)GetProcAddress(hmod, "GetWindowsAccountDomainSid"); + pGetSidIdentifierAuthority = (void *)GetProcAddress(hmod, "GetSidIdentifierAuthority"); myARGC = winetest_get_mainargs( &myARGV ); } @@ -241,7 +277,8 @@ static void test_owner_equal(HANDLE Handle, PSID expected, int 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)(EqualSid(owner, expected), "Owner SIDs are not equal %s != %s\n", + debugstr_sid(owner), debugstr_sid(expected)); ok_(__FILE__, line)(!owner_defaulted, "Defaulted is true\n"); HeapFree(GetProcessHeap(), 0, queriedSD); @@ -259,7 +296,8 @@ static void test_group_equal(HANDLE Handle, PSID expected, int 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)(EqualSid(group, expected), "Group SIDs are not equal %s != %s\n", + debugstr_sid(group), debugstr_sid(expected)); ok_(__FILE__, line)(!group_defaulted, "Defaulted is true\n"); HeapFree(GetProcessHeap(), 0, queriedSD); @@ -1381,6 +1419,158 @@ static void test_AccessCheck(void) GetLastError()); trace("AccessCheck with MAXIMUM_ALLOWED got Access 0x%08x\n", Access); + /* Null PrivSet with null PrivSetLen pointer */ + SetLastError(0xdeadbeef); + Access = AccessStatus = 0x1abe11ed; + ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, + NULL, NULL, &Access, &AccessStatus); + err = GetLastError(); + ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have " + "failed with ERROR_NOACCESS, instead of %d\n", err); + ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, + "Access and/or AccessStatus were changed!\n"); + + /* Null PrivSet with zero PrivSetLen */ + SetLastError(0xdeadbeef); + Access = AccessStatus = 0x1abe11ed; + PrivSetLen = 0; + ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, + 0, &PrivSetLen, &Access, &AccessStatus); + err = GetLastError(); + ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have " + "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err); + ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen); + ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, + "Access and/or AccessStatus were changed!\n"); + + /* Null PrivSet with insufficient PrivSetLen */ + SetLastError(0xdeadbeef); + Access = AccessStatus = 0x1abe11ed; + PrivSetLen = 1; + ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, + 0, &PrivSetLen, &Access, &AccessStatus); + err = GetLastError(); + ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have " + "failed with ERROR_NOACCESS, instead of %d\n", err); + ok(PrivSetLen == 1, "PrivSetLen returns %d\n", PrivSetLen); + ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, + "Access and/or AccessStatus were changed!\n"); + + /* Null PrivSet with insufficient PrivSetLen */ + SetLastError(0xdeadbeef); + Access = AccessStatus = 0x1abe11ed; + PrivSetLen = sizeof(PRIVILEGE_SET) - 1; + ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, + 0, &PrivSetLen, &Access, &AccessStatus); + err = GetLastError(); + ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have " + "failed with ERROR_NOACCESS, instead of %d\n", err); + ok(PrivSetLen == sizeof(PRIVILEGE_SET) - 1, "PrivSetLen returns %d\n", PrivSetLen); + ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, + "Access and/or AccessStatus were changed!\n"); + + /* Null PrivSet with minimal sufficient PrivSetLen */ + SetLastError(0xdeadbeef); + Access = AccessStatus = 0x1abe11ed; + PrivSetLen = sizeof(PRIVILEGE_SET); + ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, + 0, &PrivSetLen, &Access, &AccessStatus); + err = GetLastError(); + ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have " + "failed with ERROR_NOACCESS, instead of %d\n", err); + ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen); + ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, + "Access and/or AccessStatus were changed!\n"); + + /* Valid PrivSet with zero PrivSetLen */ + SetLastError(0xdeadbeef); + Access = AccessStatus = 0x1abe11ed; + PrivSetLen = 0; + ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, + PrivSet, &PrivSetLen, &Access, &AccessStatus); + err = GetLastError(); + ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have " + "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err); + ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen); + ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, + "Access and/or AccessStatus were changed!\n"); + + /* Valid PrivSet with insufficient PrivSetLen */ + SetLastError(0xdeadbeef); + Access = AccessStatus = 0x1abe11ed; + PrivSetLen = 1; + ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, + PrivSet, &PrivSetLen, &Access, &AccessStatus); + err = GetLastError(); +todo_wine + ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have " + "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err); +todo_wine + ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen); + ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, + "Access and/or AccessStatus were changed!\n"); + + /* Valid PrivSet with insufficient PrivSetLen */ + SetLastError(0xdeadbeef); + Access = AccessStatus = 0x1abe11ed; + PrivSetLen = sizeof(PRIVILEGE_SET) - 1; + ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, + PrivSet, &PrivSetLen, &Access, &AccessStatus); + err = GetLastError(); +todo_wine + ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have " + "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err); +todo_wine + ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen); +todo_wine + ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, + "Access and/or AccessStatus were changed!\n"); + + /* Valid PrivSet with minimal sufficient PrivSetLen */ + SetLastError(0xdeadbeef); + Access = AccessStatus = 0x1abe11ed; + PrivSetLen = sizeof(PRIVILEGE_SET); + memset(PrivSet, 0xcc, PrivSetLen); + ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, + PrivSet, &PrivSetLen, &Access, &AccessStatus); + err = GetLastError(); + ok(ret, "AccessCheck failed with error %d\n", GetLastError()); +todo_wine + ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen); + ok(AccessStatus && (Access == KEY_READ), + "AccessCheck failed to grant access with error %d\n", GetLastError()); + ok(PrivSet->PrivilegeCount == 0, "PrivilegeCount returns %d, expects 0\n", + PrivSet->PrivilegeCount); + + /* Valid PrivSet with sufficient PrivSetLen */ + SetLastError(0xdeadbeef); + Access = AccessStatus = 0x1abe11ed; + PrivSetLen = sizeof(PRIVILEGE_SET) + 1; + memset(PrivSet, 0xcc, PrivSetLen); + ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, + PrivSet, &PrivSetLen, &Access, &AccessStatus); + err = GetLastError(); + ok(ret, "AccessCheck failed with error %d\n", GetLastError()); +todo_wine + ok(PrivSetLen == sizeof(PRIVILEGE_SET) + 1, "PrivSetLen returns %d\n", PrivSetLen); + ok(AccessStatus && (Access == KEY_READ), + "AccessCheck failed to grant access with error %d\n", GetLastError()); + ok(PrivSet->PrivilegeCount == 0, "PrivilegeCount returns %d, expects 0\n", + PrivSet->PrivilegeCount); + + PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]); + + /* Null PrivSet with valid PrivSetLen */ + SetLastError(0xdeadbeef); + Access = AccessStatus = 0x1abe11ed; + ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, + 0, &PrivSetLen, &Access, &AccessStatus); + err = GetLastError(); + ok(!ret && err == ERROR_NOACCESS, "AccessCheck should have " + "failed with ERROR_NOACCESS, instead of %d\n", err); + ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, + "Access and/or AccessStatus were changed!\n"); + /* Access denied by SD */ SetLastError(0xdeadbeef); Access = AccessStatus = 0x1abe11ed; @@ -1392,7 +1582,7 @@ static void test_AccessCheck(void) "with ERROR_ACCESS_DENIED, instead of %d\n", err); ok(!Access, "Should have failed to grant any access, got 0x%08x\n", Access); - SetLastError(0); + SetLastError(0xdeadbeef); PrivSet->PrivilegeCount = 16; ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); @@ -1405,16 +1595,66 @@ static void test_AccessCheck(void) ret = pRtlAdjustPrivilege(SE_SECURITY_PRIVILEGE, TRUE, TRUE, &Enabled); if (!ret) { - SetLastError(0); - PrivSet->PrivilegeCount = 16; + /* Valid PrivSet with zero PrivSetLen */ + SetLastError(0xdeadbeef); + Access = AccessStatus = 0x1abe11ed; + PrivSetLen = 0; + ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, + PrivSet, &PrivSetLen, &Access, &AccessStatus); + err = GetLastError(); + ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have " + "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err); + ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen); + ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, + "Access and/or AccessStatus were changed!\n"); + + /* Valid PrivSet with insufficient PrivSetLen */ + SetLastError(0xdeadbeef); + Access = AccessStatus = 0x1abe11ed; + PrivSetLen = sizeof(PRIVILEGE_SET) - 1; + ret = AccessCheck(SecurityDescriptor, Token, KEY_READ, &Mapping, + PrivSet, &PrivSetLen, &Access, &AccessStatus); + err = GetLastError(); + todo_wine + ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "AccessCheck should have " + "failed with ERROR_INSUFFICIENT_BUFFER, instead of %d\n", err); + todo_wine + ok(PrivSetLen == sizeof(PRIVILEGE_SET), "PrivSetLen returns %d\n", PrivSetLen); + todo_wine + ok(Access == 0x1abe11ed && AccessStatus == 0x1abe11ed, + "Access and/or AccessStatus were changed!\n"); + + /* Valid PrivSet with minimal sufficient PrivSetLen */ + SetLastError(0xdeadbeef); + Access = AccessStatus = 0x1abe11ed; + PrivSetLen = sizeof(PRIVILEGE_SET); + memset(PrivSet, 0xcc, PrivSetLen); ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping, PrivSet, &PrivSetLen, &Access, &AccessStatus); - ok(ret && AccessStatus && GetLastError() == 0, + ok(ret && AccessStatus && GetLastError() == 0xdeadbeef, "AccessCheck should have succeeded, error %d\n", GetLastError()); ok(Access == ACCESS_SYSTEM_SECURITY, "Access should be equal to ACCESS_SYSTEM_SECURITY instead of 0x%08x\n", Access); + ok(PrivSet->PrivilegeCount == 1, "PrivilegeCount returns %d, expects 1\n", + PrivSet->PrivilegeCount); + + /* Valid PrivSet with large PrivSetLen */ + SetLastError(0xdeadbeef); + Access = AccessStatus = 0x1abe11ed; + PrivSetLen = FIELD_OFFSET(PRIVILEGE_SET, Privilege[16]); + memset(PrivSet, 0xcc, PrivSetLen); + ret = AccessCheck(SecurityDescriptor, Token, ACCESS_SYSTEM_SECURITY, &Mapping, + PrivSet, &PrivSetLen, &Access, &AccessStatus); + ok(ret && AccessStatus && GetLastError() == 0xdeadbeef, + "AccessCheck should have succeeded, error %d\n", + GetLastError()); + ok(Access == ACCESS_SYSTEM_SECURITY, + "Access should be equal to ACCESS_SYSTEM_SECURITY instead of 0x%08x\n", + Access); + ok(PrivSet->PrivilegeCount == 1, "PrivilegeCount returns %d, expects 1\n", + PrivSet->PrivilegeCount); } else trace("Couldn't get SE_SECURITY_PRIVILEGE (0x%08x), skipping ACCESS_SYSTEM_SECURITY test\n", @@ -2187,7 +2427,8 @@ static void check_wellknown_name(const char* name, WELL_KNOWN_SID_TYPE result) ok(ret, "Failed to lookup account name %s\n",name); ok(sid_size != 0, "sid_size was zero\n"); - ok(EqualSid(psid,wk_sid),"(%s) Sids fail to match well known sid!\n",name); + ok(EqualSid(psid,wk_sid),"%s Sid %s fails to match well known sid %s!\n", + name, debugstr_sid(psid), debugstr_sid(wk_sid)); 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); @@ -3186,12 +3427,7 @@ static void test_inherited_dacl(PACL dacl, PSID admin_sid, PSID user_sid, DWORD 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 + todo_wine_if (todo_count) ok_(__FILE__, line)(acl_size.AceCount == 2, "GetAclInformation returned unexpected entry count (%d != 2)\n", acl_size.AceCount); @@ -3202,18 +3438,10 @@ static void test_inherited_dacl(PACL dacl, PSID admin_sid, PSID user_sid, DWORD 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"); + todo_wine_if (todo_sid) + ok_(__FILE__, line)(bret, "Current User ACE (%s) != Current User SID (%s)\n", debugstr_sid(&ace->SidStart), debugstr_sid(user_sid)); - 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 + todo_wine_if (todo_flags) ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags, "Current User ACE has unexpected flags (0x%x != 0x%x)\n", ((ACE_HEADER *)ace)->AceFlags, flags); @@ -3228,18 +3456,10 @@ static void test_inherited_dacl(PACL dacl, PSID admin_sid, PSID user_sid, DWORD 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"); + todo_wine_if (todo_sid) + ok_(__FILE__, line)(bret, "Administators Group ACE (%s) != Administators Group SID (%s)\n", debugstr_sid(&ace->SidStart), debugstr_sid(admin_sid)); - 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 + todo_wine_if (todo_flags) ok_(__FILE__, line)(((ACE_HEADER *)ace)->AceFlags == flags, "Administators Group ACE has unexpected flags (0x%x != 0x%x)\n", ((ACE_HEADER *)ace)->AceFlags, flags); @@ -3451,7 +3671,6 @@ static void test_CreateDirectoryA(void) 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); @@ -3510,6 +3729,7 @@ static void test_CreateDirectoryA(void) 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); @@ -3785,7 +4005,8 @@ static void test_GetNamedSecurityInfoA(void) 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(bret, "Current User ACE (%s) != Current User SID (%s).\n", + debugstr_sid(&ace->SidStart), debugstr_sid(user_sid)); ok(((ACE_HEADER *)ace)->AceFlags == 0, "Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags); ok(ace->Mask == 0x1f01ff, @@ -3796,7 +4017,8 @@ static void test_GetNamedSecurityInfoA(void) 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(bret || broken(!bret) /* win2k */, "Administators Group ACE (%s) != Administators Group SID (%s).\n", + debugstr_sid(&ace->SidStart), debugstr_sid(admin_sid)); 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 */, @@ -3930,14 +4152,15 @@ static void test_GetNamedSecurityInfoA(void) 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"); + ok(EqualSid(owner, admin_sid), "MACHINE\\Software owner SID (%s) != Administrators SID (%s).\n", debugstr_sid(owner), debugstr_sid(admin_sid)); 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"); + "MACHINE\\Software group SID (%s) != Local System SID (%s or %s)\n", + debugstr_sid(group), debugstr_sid(admin_sid), debugstr_sid(system_sid)); LocalFree(pSD); /* Test querying the DACL of a built-in registry key */ @@ -4579,7 +4802,7 @@ static void test_GetSecurityInfo(void) 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(bret, "Current User ACE (%s) != Current User SID (%s).\n", debugstr_sid(&ace->SidStart), debugstr_sid(user_sid)); 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", @@ -4590,7 +4813,7 @@ static void test_GetSecurityInfo(void) 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(bret, "Administators Group ACE (%s) != Administators Group SID (%s).\n", debugstr_sid(&ace->SidStart), debugstr_sid(admin_sid)); ok(((ACE_HEADER *)ace)->AceFlags == 0, "Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags); ok(ace->Mask == 0x1f01ff, @@ -4817,7 +5040,8 @@ static void test_EqualSid(void) SetLastError(0xdeadbeef); ret = EqualSid(sid1, sid2); - ok(ret, "Same sids should have been equal\n"); + ok(ret, "Same sids should have been equal %s != %s\n", + debugstr_sid(sid1), debugstr_sid(sid2)); ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef), /* NT4 */ "EqualSid should have set last error to ERROR_SUCCESS instead of %d\n", @@ -5472,11 +5696,8 @@ static void test_named_pipe_security(HANDLE token) 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); + todo_wine_if (map[i].todo) + ok(access == map[i].mapped, "%d: expected %#x, got %#x\n", i, map[i].mapped, access); CloseHandle(dup); } @@ -5961,7 +6182,6 @@ static void test_TokenIntegrityLevel(void) HANDLE token; DWORD size; DWORD res; - char *sidname = NULL; static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, {SECURITY_MANDATORY_HIGH_RID}}; static SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY}, @@ -5993,14 +6213,10 @@ static void test_TokenIntegrityLevel(void) ok(tml->Label.Attributes == (SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED), "got 0x%x (expected 0x%x)\n", tml->Label.Attributes, (SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED)); - SetLastError(0xdeadbeef); - res = pConvertSidToStringSidA(tml->Label.Sid, &sidname); - ok(res, "got %u and %u\n", res, GetLastError()); - ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level), - "got %s (expected 'S-1-16-8192' or 'S-1-16-12288')\n", sidname); + "got %s (expected %s or %s)\n", debugstr_sid(tml->Label.Sid), + debugstr_sid(&medium_level), debugstr_sid(&high_level)); - LocalFree(sidname); CloseHandle(token); } @@ -6315,11 +6531,91 @@ static void test_GetWindowsAccountDomainSid(void) 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"); + ok(EqualSid(domain_sid, domain_sid2), "unexpected domain sid %s != %s\n", + debugstr_sid(domain_sid), debugstr_sid(domain_sid2)); HeapFree(GetProcessHeap(), 0, user); } +static void test_GetSidIdentifierAuthority(void) +{ + char buffer[SECURITY_MAX_SID_SIZE]; + PSID authority_sid = (PSID *)buffer; + PSID_IDENTIFIER_AUTHORITY id; + BOOL ret; + + if (!pGetSidIdentifierAuthority) + { + win_skip("GetSidIdentifierAuthority not available\n"); + return; + } + + memset(buffer, 0xcc, sizeof(buffer)); + ret = IsValidSid(authority_sid); + ok(!ret, "expected FALSE, got %u\n", ret); + + SetLastError(0xdeadbeef); + id = GetSidIdentifierAuthority(authority_sid); + ok(id != NULL, "got NULL pointer as identifier authority\n"); + ok(GetLastError() == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + id = GetSidIdentifierAuthority(NULL); + ok(id != NULL, "got NULL pointer as identifier authority\n"); + ok(GetLastError() == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", GetLastError()); +} + +static void test_pseudo_tokens(void) +{ + TOKEN_STATISTICS statistics1, statistics2; + HANDLE token; + DWORD retlen; + BOOL ret; + + ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token); + ok(ret, "OpenProcessToken failed with error %u\n", GetLastError()); + memset(&statistics1, 0x11, sizeof(statistics1)); + ret = GetTokenInformation(token, TokenStatistics, &statistics1, sizeof(statistics1), &retlen); + ok(ret, "GetTokenInformation failed with %u\n", GetLastError()); + CloseHandle(token); + + /* test GetCurrentProcessToken() */ + SetLastError(0xdeadbeef); + memset(&statistics2, 0x22, sizeof(statistics2)); + ret = GetTokenInformation(GetCurrentProcessToken(), TokenStatistics, + &statistics2, sizeof(statistics2), &retlen); + ok(ret || broken(GetLastError() == ERROR_INVALID_HANDLE), + "GetTokenInformation failed with %u\n", GetLastError()); + if (ret) + ok(!memcmp(&statistics1, &statistics2, sizeof(statistics1)), "Token statistics do not match\n"); + else + win_skip("CurrentProcessToken not supported, skipping test\n"); + + /* test GetCurrentThreadEffectiveToken() */ + SetLastError(0xdeadbeef); + memset(&statistics2, 0x22, sizeof(statistics2)); + ret = GetTokenInformation(GetCurrentThreadEffectiveToken(), TokenStatistics, + &statistics2, sizeof(statistics2), &retlen); + ok(ret || broken(GetLastError() == ERROR_INVALID_HANDLE), + "GetTokenInformation failed with %u\n", GetLastError()); + if (ret) + ok(!memcmp(&statistics1, &statistics2, sizeof(statistics1)), "Token statistics do not match\n"); + else + win_skip("CurrentThreadEffectiveToken not supported, skipping test\n"); + + SetLastError(0xdeadbeef); + ret = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &token); + ok(!ret, "OpenThreadToken should have failed\n"); + ok(GetLastError() == ERROR_NO_TOKEN, "Expected ERROR_NO_TOKEN, got %u\n", GetLastError()); + + /* test GetCurrentThreadToken() */ + SetLastError(0xdeadbeef); + ret = GetTokenInformation(GetCurrentThreadToken(), TokenStatistics, + &statistics2, sizeof(statistics2), &retlen); + todo_wine ok(GetLastError() == ERROR_NO_TOKEN || broken(GetLastError() == ERROR_INVALID_HANDLE), + "Expected ERROR_NO_TOKEN, got %u\n", GetLastError()); +} + START_TEST(security) { init(); @@ -6364,4 +6660,6 @@ START_TEST(security) test_AdjustTokenPrivileges(); test_AddAce(); test_system_security_access(); + test_GetSidIdentifierAuthority(); + test_pseudo_tokens(); }