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);
/* 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);
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);
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) {
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);
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");
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 */
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 );
#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
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;
#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;
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 );
}
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);
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);
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;
"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);
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",
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);
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);
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);
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);
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);
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);
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,
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 */,
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 */
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",
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,
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",
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);
}
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},
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);
}
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();
test_AdjustTokenPrivileges();
test_AddAce();
test_system_security_access();
+ test_GetSidIdentifierAuthority();
+ test_pseudo_tokens();
}