diff --git a/rostests/winetests/advapi32/cred.c b/rostests/winetests/advapi32/cred.c index 7e276d4a4e7..bb5fb4eace8 100644 --- a/rostests/winetests/advapi32/cred.c +++ b/rostests/winetests/advapi32/cred.c @@ -295,7 +295,7 @@ static void test_generic(void) for (i = 0; i < count; i++) { - if (!strcmp(creds[i]->TargetName, TEST_TARGET_NAME)) + if (creds[i]->TargetName && !strcmp(creds[i]->TargetName, TEST_TARGET_NAME)) { ok(creds[i]->Type == CRED_TYPE_GENERIC || creds[i]->Type == CRED_TYPE_DOMAIN_PASSWORD, /* Vista */ @@ -353,7 +353,7 @@ static void test_domain_password(DWORD cred_type) for (i = 0; i < count; i++) { - if (!strcmp(creds[i]->TargetName, TEST_TARGET_NAME)) + if (creds[i]->TargetName && !strcmp(creds[i]->TargetName, TEST_TARGET_NAME)) { ok(creds[i]->Type == cred_type, "expected creds[%d]->Type CRED_TYPE_DOMAIN_PASSWORD but got %d\n", i, creds[i]->Type); ok(!creds[i]->Flags, "expected creds[%d]->Flags 0 but got 0x%x\n", i, creds[i]->Flags); diff --git a/rostests/winetests/advapi32/registry.c b/rostests/winetests/advapi32/registry.c index a90fe7a1016..7d16cb38f83 100644 --- a/rostests/winetests/advapi32/registry.c +++ b/rostests/winetests/advapi32/registry.c @@ -646,6 +646,32 @@ static void test_enum_value(void) ok( !strcmp( value, "Test" ), "value is '%s' instead of Test\n", value ); ok( !strcmp( data, "foobar" ), "data is '%s' instead of foobar\n", data ); + if (pRegGetValueA) /* avoid a crash on Windows 2000 */ + { + /* no value and no val_count parameter */ + data_count = 20; + type = 1234; + strcpy( data, "xxxxxxxxxx" ); + res = RegEnumValueA( test_key, 0, NULL, NULL, NULL, &type, (BYTE*)data, &data_count ); + ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res ); + + /* no value parameter */ + val_count = 20; + data_count = 20; + type = 1234; + strcpy( data, "xxxxxxxxxx" ); + res = RegEnumValueA( test_key, 0, NULL, &val_count, NULL, &type, (BYTE*)data, &data_count ); + ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res ); + + /* no val_count parameter */ + data_count = 20; + type = 1234; + strcpy( value, "xxxxxxxxxx" ); + strcpy( data, "xxxxxxxxxx" ); + res = RegEnumValueA( test_key, 0, value, NULL, NULL, &type, (BYTE*)data, &data_count ); + ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res ); + } + /* Unicode tests */ SetLastError(0xdeadbeef); @@ -713,6 +739,32 @@ static void test_enum_value(void) ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" ); ok( !memcmp( dataW, foobarW, sizeof(foobarW) ), "data is not 'foobar'\n" ); + if (pRegGetValueA) /* avoid a crash on Windows 2000 */ + { + /* no valueW and no val_count parameter */ + data_count = 20; + type = 1234; + memcpy( dataW, xxxW, sizeof(xxxW) ); + res = RegEnumValueW( test_key, 0, NULL, NULL, NULL, &type, (BYTE*)dataW, &data_count ); + ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res ); + + /* no valueW parameter */ + val_count = 20; + data_count = 20; + type = 1234; + memcpy( dataW, xxxW, sizeof(xxxW) ); + res = RegEnumValueW( test_key, 0, NULL, &val_count, NULL, &type, (BYTE*)dataW, &data_count ); + ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res ); + + /* no val_count parameter */ + data_count = 20; + type = 1234; + memcpy( valueW, xxxW, sizeof(xxxW) ); + memcpy( dataW, xxxW, sizeof(xxxW) ); + res = RegEnumValueW( test_key, 0, valueW, NULL, NULL, &type, (BYTE*)dataW, &data_count ); + ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res ); + } + cleanup: RegDeleteKeyA(test_key, ""); RegCloseKey(test_key); @@ -1026,7 +1078,6 @@ static void test_reg_open_key(void) ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */ "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret); ok(hkResult == hkPreserve, "expected hkResult == hkPreserve\n"); - RegCloseKey(hkResult); /* send in NULL hkResult */ ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", NULL); @@ -1052,6 +1103,45 @@ static void test_reg_open_key(void) "expected ERROR_SUCCESS, ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %d\n", ret); RegCloseKey(hkResult); + /* NULL or empty subkey of special root */ + hkResult = NULL; + ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, NULL, 0, KEY_QUERY_VALUE, &hkResult); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); + ok(hkResult == HKEY_CLASSES_ROOT, "expected hkResult == HKEY_CLASSES_ROOT\n"); + + hkResult = NULL; + ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, "", 0, KEY_QUERY_VALUE, &hkResult); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); + ok(hkResult == HKEY_CLASSES_ROOT, "expected hkResult == HKEY_CLASSES_ROOT\n"); + + hkResult = NULL; + ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, "\\", 0, KEY_QUERY_VALUE, &hkResult); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); + ok(hkResult != HKEY_CLASSES_ROOT, "expected hkResult to be a new key\n"); + ok(!RegCloseKey(hkResult), "got invalid hkey\n"); + + /* empty subkey of existing handle */ + hkResult = hkPreserve; + ret = RegOpenKeyExA(hkPreserve, "", 0, KEY_QUERY_VALUE, &hkResult); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); + ok(hkResult != hkPreserve, "expected hkResult != hkPreserve\n"); + ok(!RegCloseKey(hkResult), "got invalid hkey\n"); + + /* NULL subkey of existing handle */ + hkResult = hkPreserve; + ret = RegOpenKeyExA(hkPreserve, NULL, 0, KEY_QUERY_VALUE, &hkResult); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); + ok(hkResult != hkPreserve, "expected hkResult != hkPreserve\n"); + ok(!RegCloseKey(hkResult), "got invalid hkey\n"); + + /* empty subkey of NULL */ + hkResult = hkPreserve; + ret = RegOpenKeyExA(NULL, "", 0, KEY_QUERY_VALUE, &hkResult); + ok(ret == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", ret); + ok(hkResult == hkPreserve, "expected hkResult == hkPreserve\n"); + + RegCloseKey(hkPreserve); + /* WOW64 flags */ hkResult = NULL; ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WOW64_32KEY, &hkResult); @@ -1426,39 +1516,6 @@ static void test_reg_delete_key(void) RegCloseKey(key); } -static void test_reg_save_key(void) -{ - DWORD ret; - - ret = RegSaveKeyA(hkey_main, "saved_key", NULL); - ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); -} - -static void test_reg_load_key(void) -{ - DWORD ret; - HKEY hkHandle; - - ret = RegLoadKeyA(HKEY_LOCAL_MACHINE, "Test", "saved_key"); - ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); - - ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, "Test", &hkHandle); - ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); - - RegCloseKey(hkHandle); -} - -static void test_reg_unload_key(void) -{ - DWORD ret; - - ret = RegUnLoadKeyA(HKEY_LOCAL_MACHINE, "Test"); - ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); - - DeleteFileA("saved_key"); - DeleteFileA("saved_key.LOG"); -} - static BOOL set_privileges(LPCSTR privilege, BOOL set) { TOKEN_PRIVILEGES tp; @@ -1493,6 +1550,66 @@ static BOOL set_privileges(LPCSTR privilege, BOOL set) return TRUE; } +static void test_reg_save_key(void) +{ + DWORD ret; + + if (!set_privileges(SE_BACKUP_NAME, TRUE) || + !set_privileges(SE_RESTORE_NAME, FALSE)) + { + win_skip("Failed to set SE_BACKUP_NAME privileges, skipping tests\n"); + return; + } + + ret = RegSaveKeyA(hkey_main, "saved_key", NULL); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); + + set_privileges(SE_BACKUP_NAME, FALSE); +} + +static void test_reg_load_key(void) +{ + DWORD ret; + HKEY hkHandle; + + if (!set_privileges(SE_RESTORE_NAME, TRUE) || + !set_privileges(SE_BACKUP_NAME, FALSE)) + { + win_skip("Failed to set SE_RESTORE_NAME privileges, skipping tests\n"); + return; + } + + ret = RegLoadKeyA(HKEY_LOCAL_MACHINE, "Test", "saved_key"); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); + + set_privileges(SE_RESTORE_NAME, FALSE); + + ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, "Test", &hkHandle); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); + + RegCloseKey(hkHandle); +} + +static void test_reg_unload_key(void) +{ + DWORD ret; + + if (!set_privileges(SE_RESTORE_NAME, TRUE) || + !set_privileges(SE_BACKUP_NAME, FALSE)) + { + win_skip("Failed to set SE_RESTORE_NAME privileges, skipping tests\n"); + return; + } + + ret = RegUnLoadKeyA(HKEY_LOCAL_MACHINE, "Test"); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); + + set_privileges(SE_RESTORE_NAME, FALSE); + + DeleteFileA("saved_key"); + DeleteFileA("saved_key.LOG"); +} + /* tests that show that RegConnectRegistry and OpenSCManager accept computer names without the \\ prefix (what MSDN says). */ @@ -1716,6 +1833,7 @@ static void test_reg_query_info(void) ok(classbufferW[0] == 0x5555, "classbufferW[0] = 0x%x\n", classbufferW[0]); /* empty key */ + sdlen = 0; ret = RegQueryInfoKeyA(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite); ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); ok(classlen == strlen(subkey_class), "classlen = %u\n", classlen); @@ -1725,10 +1843,11 @@ static void test_reg_query_info(void) ok(values == 0, "values = %u\n", values); ok(maxvaluenamelen == 0, "maxvaluenamelen = %u\n", maxvaluenamelen); ok(maxvaluelen == 0, "maxvaluelen = %u\n", maxvaluelen); - ok(sdlen != 0, "sdlen = %u\n", sdlen); + todo_wine ok(sdlen != 0, "sdlen = %u\n", sdlen); ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %u\n", lastwrite.dwLowDateTime); ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %u\n", lastwrite.dwHighDateTime); + sdlen = 0; ret = RegQueryInfoKeyW(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite); ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); ok(classlen == strlen(subkey_class), "classlen = %u\n", classlen); @@ -1738,7 +1857,7 @@ static void test_reg_query_info(void) ok(values == 0, "values = %u\n", values); ok(maxvaluenamelen == 0, "maxvaluenamelen = %u\n", maxvaluenamelen); ok(maxvaluelen == 0, "maxvaluelen = %u\n", maxvaluelen); - ok(sdlen != 0, "sdlen = %u\n", sdlen); + todo_wine ok(sdlen != 0, "sdlen = %u\n", sdlen); ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %u\n", lastwrite.dwLowDateTime); ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %u\n", lastwrite.dwHighDateTime); @@ -1749,8 +1868,9 @@ static void test_reg_query_info(void) ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); /* with subkey & default value */ + sdlen = 0; ret = RegQueryInfoKeyA(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite); - todo_wine ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); + ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); ok(classlen == strlen(subkey_class), "classlen = %u\n", classlen); ok(subkeys == 1, "subkeys = %u\n", subkeys); ok(maxsubkeylen == strlen("subsubkey"), "maxsubkeylen = %u\n", maxsubkeylen); @@ -1758,10 +1878,11 @@ static void test_reg_query_info(void) ok(values == 1, "values = %u\n", values); ok(maxvaluenamelen == 0, "maxvaluenamelen = %u\n", maxvaluenamelen); ok(maxvaluelen == sizeof("data") * sizeof(WCHAR), "maxvaluelen = %u\n", maxvaluelen); - ok(sdlen != 0, "sdlen = %u\n", sdlen); + todo_wine ok(sdlen != 0, "sdlen = %u\n", sdlen); ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %u\n", lastwrite.dwLowDateTime); ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %u\n", lastwrite.dwHighDateTime); + sdlen = 0; ret = RegQueryInfoKeyW(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite); ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); ok(classlen == strlen(subkey_class), "classlen = %u\n", classlen); @@ -1771,7 +1892,7 @@ static void test_reg_query_info(void) ok(values == 1, "values = %u\n", values); ok(maxvaluenamelen == 0, "maxvaluenamelen = %u\n", maxvaluenamelen); ok(maxvaluelen == sizeof("data") * sizeof(WCHAR), "maxvaluelen = %u\n", maxvaluelen); - ok(sdlen != 0, "sdlen = %u\n", sdlen); + todo_wine ok(sdlen != 0, "sdlen = %u\n", sdlen); ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %u\n", lastwrite.dwLowDateTime); ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %u\n", lastwrite.dwHighDateTime); @@ -1783,7 +1904,7 @@ static void test_reg_query_info(void) /* with named value */ ret = RegQueryInfoKeyA(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite); - todo_wine ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); + ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); ok(values == 3, "values = %u\n", values); ok(maxvaluenamelen == strlen("value one"), "maxvaluenamelen = %u\n", maxvaluenamelen); ok(maxvaluelen == sizeof("second value data") * sizeof(WCHAR), "maxvaluelen = %u\n", maxvaluelen); @@ -1798,7 +1919,7 @@ static void test_reg_query_info(void) memset(classbuffer, 0x55, sizeof(classbuffer)); classlen = 0; ret = RegQueryInfoKeyA(subkey, classbuffer, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - todo_wine ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); + ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); ok(classlen == strlen(subkey_class) /* win2k */ || classlen == 0, "classlen = %u\n", classlen); memset(expectbuffer, 0x55, sizeof(expectbuffer)); @@ -1807,7 +1928,7 @@ static void test_reg_query_info(void) memset(classbufferW, 0x55, sizeof(classbufferW)); classlen = 0; ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - todo_wine ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); + ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); ok(classlen == strlen(subkey_class) /* win2k */ || classlen == 0, "classlen = %u\n", classlen); memset(expectbufferW, 0x55, sizeof(expectbufferW)); @@ -1818,15 +1939,15 @@ static void test_reg_query_info(void) classlen = 1; ret = RegQueryInfoKeyA(subkey, classbuffer, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); ok(ret == ERROR_MORE_DATA, "ret = %d\n", ret); - todo_wine ok(classlen == 0, "classlen = %u\n", classlen); + ok(classlen == 0, "classlen = %u\n", classlen); memset(expectbuffer, 0x55, sizeof(expectbuffer)); expectbuffer[0] = 0; - todo_wine ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)), "classbuffer was modified\n"); + ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)), "classbuffer was modified\n"); memset(classbufferW, 0x55, sizeof(classbufferW)); classlen = 1; ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - todo_wine ok(ret == ERROR_INSUFFICIENT_BUFFER, "ret = %d\n", ret); + ok(ret == ERROR_INSUFFICIENT_BUFFER, "ret = %d\n", ret); ok(classlen == 0 /* win8 */ || classlen == strlen(subkey_class), "classlen = %u\n", classlen); memset(expectbufferW, 0x55, sizeof(expectbufferW)); @@ -1837,19 +1958,19 @@ static void test_reg_query_info(void) classlen = sizeof(subkey_class) - 1; ret = RegQueryInfoKeyA(subkey, classbuffer, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); ok(ret == ERROR_MORE_DATA, "ret = %d\n", ret); - todo_wine ok(classlen == sizeof(subkey_class) - 2, "classlen = %u\n", classlen); + ok(classlen == sizeof(subkey_class) - 2, "classlen = %u\n", classlen); memset(expectbuffer, 0x55, sizeof(expectbuffer)); strcpy(expectbuffer, subkey_class); expectbuffer[sizeof(subkey_class) - 2] = 0; expectbuffer[sizeof(subkey_class) - 1] = 0x55; - todo_wine ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)), + ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)), "classbuffer = %.*s, expected %s\n", (int)sizeof(classbuffer), classbuffer, expectbuffer); memset(classbufferW, 0x55, sizeof(classbufferW)); classlen = sizeof(subkey_class) - 1; ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - todo_wine ok(ret == ERROR_INSUFFICIENT_BUFFER, "ret = %d\n", ret); + ok(ret == ERROR_INSUFFICIENT_BUFFER, "ret = %d\n", ret); ok(classlen == sizeof(subkey_class) - 2 /* win8 */ || classlen == strlen(subkey_class), "classlen = %u\n", classlen); memset(expectbufferW, 0x55, sizeof(expectbufferW)); @@ -3185,17 +3306,9 @@ START_TEST(registry) test_classesroot_enum(); test_classesroot_mask(); - /* SaveKey/LoadKey require the SE_BACKUP_NAME privilege to be set */ - if (set_privileges(SE_BACKUP_NAME, TRUE) && - set_privileges(SE_RESTORE_NAME, TRUE)) - { - test_reg_save_key(); - test_reg_load_key(); - test_reg_unload_key(); - - set_privileges(SE_BACKUP_NAME, FALSE); - set_privileges(SE_RESTORE_NAME, FALSE); - } + test_reg_save_key(); + test_reg_load_key(); + test_reg_unload_key(); test_reg_delete_tree(); test_rw_order(); diff --git a/rostests/winetests/advapi32/security.c b/rostests/winetests/advapi32/security.c index 5043e414090..1c88ceafc81 100644 --- a/rostests/winetests/advapi32/security.c +++ b/rostests/winetests/advapi32/security.c @@ -132,6 +132,9 @@ static NTSTATUS (WINAPI *pNtSetSecurityObject)(HANDLE,SECURITY_INFORMATION,PSECU static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG); static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)(LPCWSTR,PUNICODE_STRING,PWSTR*,CURDIR*); static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING,PCANSI_STRING,BOOLEAN); +static BOOL (WINAPI *pGetWindowsAccountDomainSid)(PSID,PSID,DWORD*); +static void (WINAPI *pRtlInitAnsiString)(PANSI_STRING,PCSZ); +static NTSTATUS (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING); static HMODULE hmod; static int myARGC; @@ -162,6 +165,8 @@ static void init(void) pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile"); pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U"); pRtlAnsiStringToUnicodeString = (void *)GetProcAddress(hntdll, "RtlAnsiStringToUnicodeString"); + pRtlInitAnsiString = (void *)GetProcAddress(hntdll, "RtlInitAnsiString"); + pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString"); hmod = GetModuleHandleA("advapi32.dll"); pAddAccessAllowedAceEx = (void *)GetProcAddress(hmod, "AddAccessAllowedAceEx"); @@ -193,6 +198,7 @@ static void init(void) pConvertStringSidToSidA = (void *)GetProcAddress(hmod, "ConvertStringSidToSidA"); pGetAclInformation = (void *)GetProcAddress(hmod, "GetAclInformation"); pGetAce = (void *)GetProcAddress(hmod, "GetAce"); + pGetWindowsAccountDomainSid = (void *)GetProcAddress(hmod, "GetWindowsAccountDomainSid"); myARGC = winetest_get_mainargs( &myARGV ); } @@ -1683,7 +1689,7 @@ static void test_sid_str(PSID * sid) DWORD acc_size = MAX_PATH; DWORD dom_size = MAX_PATH; ret = LookupAccountSidA (NULL, sid, account, &acc_size, domain, &dom_size, &use); - ok(ret || (!ret && (GetLastError() == ERROR_NONE_MAPPED)), + ok(ret || GetLastError() == ERROR_NONE_MAPPED, "LookupAccountSid(%s) failed: %d\n", str_sid, GetLastError()); if (ret) trace(" %s %s\\%s %d\n", str_sid, domain, account, use); @@ -1728,7 +1734,9 @@ static const struct well_known_sid_value /* 69 */ {TRUE, "S-1-16-16384"}, {TRUE, "S-1-5-33"}, {TRUE, "S-1-3-4"}, /* 72 */ {FALSE, "S-1-5-21-12-23-34-45-56-571"}, {FALSE, "S-1-5-21-12-23-34-45-56-572"}, /* 74 */ {TRUE, "S-1-5-22"}, {FALSE, "S-1-5-21-12-23-34-45-56-521"}, {TRUE, "S-1-5-32-573"}, -/* 77 */ {FALSE, "S-1-5-21-12-23-34-45-56-498"}, {TRUE, "S-1-5-32-574"}, {TRUE, "S-1-16-8448"} +/* 77 */ {FALSE, "S-1-5-21-12-23-34-45-56-498"}, {TRUE, "S-1-5-32-574"}, {TRUE, "S-1-16-8448"}, +/* 80 */ {FALSE, NULL}, {TRUE, "S-1-2-1"}, {TRUE, "S-1-5-65-1"}, {FALSE, NULL}, +/* 84 */ {TRUE, "S-1-15-2-1"}, }; static void test_CreateWellKnownSid(void) @@ -1777,15 +1785,12 @@ static void test_CreateWellKnownSid(void) if (value->sid_string == NULL) continue; - if (i > WinAccountRasAndIasServersSid) + /* some SIDs aren't implemented by all Windows versions - detect it */ + cb = sizeof(sid_buffer); + if (!pCreateWellKnownSid(i, NULL, sid_buffer, &cb)) { - /* These SIDs aren't implemented by all Windows versions - detect it and break the loop */ - cb = sizeof(sid_buffer); - if (!pCreateWellKnownSid(i, domainsid, sid_buffer, &cb)) - { - skip("Well known SIDs starting from %u are not implemented\n", i); - break; - } + skip("Well known SID %u not implemented\n", i); + continue; } cb = sizeof(sid_buffer); @@ -2247,7 +2252,7 @@ static void test_LookupAccountName(void) ok(ret, "Failed to lookup account name\n"); ok(sid_size == GetLengthSid(psid), "Expected %d, got %d\n", GetLengthSid(psid), sid_size); ok(!lstrcmpA(account, user_name), "Expected %s, got %s\n", user_name, account); - ok(!lstrcmpA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain); + ok(!lstrcmpiA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain); ok(domain_size == domain_save - 1, "Expected %d, got %d\n", domain_save - 1, domain_size); ok(strlen(domain) == domain_size, "Expected %d, got %d\n", lstrlenA(domain), domain_size); ok(sid_use == SidTypeUser, "Expected SidTypeUser (%d), got %d\n", SidTypeUser, sid_use); @@ -2265,7 +2270,7 @@ static void test_LookupAccountName(void) ok(ret, "Failed to lookup account name\n"); ok(sid_size != 0, "sid_size was zero\n"); ok(!lstrcmpA(account, "Everyone"), "Expected Everyone, got %s\n", account); - ok(!lstrcmpA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain); + ok(!lstrcmpiA(domain, sid_dom), "Expected %s, got %s\n", sid_dom, domain); ok(domain_size == 0, "Expected 0, got %d\n", domain_size); ok(strlen(domain) == domain_size, "Expected %d, got %d\n", lstrlenA(domain), domain_size); ok(sid_use == SidTypeWellKnownGroup, "Expected SidTypeWellKnownGroup (%d), got %d\n", SidTypeWellKnownGroup, sid_use); @@ -2330,9 +2335,8 @@ static void test_LookupAccountName(void) get_sid_info(psid, &account, &sid_dom); ok(ret, "Failed to lookup account name\n"); /* Using a fixed string will not work on different locales */ - ok(!lstrcmpA(account, domain), - "Got %s for account and %s for domain, these should be the same\n", - account, domain); + ok(!lstrcmpiA(account, domain), + "Got %s for account and %s for domain, these should be the same\n", account, domain); ok(sid_use == SidTypeDomain, "Expected SidTypeDomain (%d), got %d\n", SidTypeDomain, sid_use); HeapFree(GetProcessHeap(), 0, psid); @@ -3160,7 +3164,8 @@ static void get_nt_pathW(const char *name, UNICODE_STRING *nameW) ANSI_STRING str; NTSTATUS status; BOOLEAN ret; - RtlInitAnsiString(&str, name); + + pRtlInitAnsiString(&str, name); status = pRtlAnsiStringToUnicodeString(&strW, &str, TRUE); ok(!status, "RtlAnsiStringToUnicodeString failed with %08x\n", status); @@ -3168,7 +3173,7 @@ static void get_nt_pathW(const char *name, UNICODE_STRING *nameW) ret = pRtlDosPathNameToNtPathName_U(strW.Buffer, nameW, NULL, NULL); ok(ret, "RtlDosPathNameToNtPathName_U failed\n"); - RtlFreeUnicodeString(&strW); + pRtlFreeUnicodeString(&strW); } static void test_inherited_dacl(PACL dacl, PSID admin_sid, PSID user_sid, DWORD flags, DWORD mask, @@ -3402,7 +3407,7 @@ static void test_CreateDirectoryA(void) 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); + pRtlFreeUnicodeString(&tmpfileW); error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, @@ -3437,7 +3442,7 @@ static void test_CreateDirectoryA(void) 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); + pRtlFreeUnicodeString(&tmpfileW); HeapFree(GetProcessHeap(), 0, pDacl); error = pGetSecurityInfo(hTemp, SE_FILE_OBJECT, @@ -3979,7 +3984,8 @@ static void test_GetNamedSecurityInfoA(void) ok(bret, "Failed to get Builtin Admins ACE.\n"); flags = ((ACE_HEADER *)ace)->AceFlags; ok(flags == 0x0 - || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* w2k8 */, + || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* w2k8 */ + || broken(flags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)), /* win7 */ "Builtin Admins ACE has unexpected flags (0x%x != 0x0)\n", flags); ok(ace->Mask == KEY_ALL_ACCESS || broken(ace->Mask == GENERIC_ALL) /* w2k8 */, "Builtin Admins ACE has unexpected mask (0x%x != 0x%x)\n", ace->Mask, KEY_ALL_ACCESS); @@ -4492,7 +4498,8 @@ static void test_GetSecurityInfo(void) win_skip("Failed to get current user token\n"); return; } - GetTokenInformation(token, TokenUser, b, l, &l); + bret = GetTokenInformation(token, TokenUser, b, l, &l); + ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError()); CloseHandle( token ); user_sid = ((TOKEN_USER *)b)->User.Sid; @@ -5767,6 +5774,16 @@ todo_wine CloseHandle(dup); } + SetLastError( 0xdeadbeef ); + ret = DuplicateHandle(GetCurrentProcess(), thread, GetCurrentProcess(), &dup, + THREAD_QUERY_INFORMATION, FALSE, 0); + ok(ret, "DuplicateHandle error %d\n", GetLastError()); + access = get_obj_access(dup); + ok(access == (THREAD_QUERY_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION) /* Vista+ */ || + access == THREAD_QUERY_INFORMATION /* before Vista */, + "expected THREAD_QUERY_INFORMATION|THREAD_QUERY_LIMITED_INFORMATION, got %#x\n", access); + CloseHandle(dup); + TerminateThread(thread, 0); CloseHandle(thread); } @@ -5839,6 +5856,16 @@ static void test_process_access(void) CloseHandle(dup); } + SetLastError( 0xdeadbeef ); + ret = DuplicateHandle(GetCurrentProcess(), process, GetCurrentProcess(), &dup, + PROCESS_QUERY_INFORMATION, FALSE, 0); + ok(ret, "DuplicateHandle error %d\n", GetLastError()); + access = get_obj_access(dup); + ok(access == (PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION) /* Vista+ */ || + access == PROCESS_QUERY_INFORMATION /* before Vista */, + "expected PROCESS_QUERY_INFORMATION|PROCESS_QUERY_LIMITED_INFORMATION, got %#x\n", access); + CloseHandle(dup); + TerminateProcess(process, 0); CloseHandle(process); } @@ -6115,6 +6142,184 @@ static void test_AddAce(void) ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError() = %d\n", GetLastError()); } +static void test_system_security_access(void) +{ + static const WCHAR testkeyW[] = + {'S','O','F','T','W','A','R','E','\\','W','i','n','e','\\','S','A','C','L','t','e','s','t',0}; + LONG res; + HKEY hkey; + PSECURITY_DESCRIPTOR sd; + ACL *sacl; + DWORD err, len = 128; + TOKEN_PRIVILEGES priv, *priv_prev; + HANDLE token; + LUID luid; + BOOL ret; + + if (!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &token )) return; + if (!LookupPrivilegeValueA( NULL, SE_SECURITY_NAME, &luid )) + { + CloseHandle( token ); + return; + } + + /* ACCESS_SYSTEM_SECURITY requires special privilege */ + res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ|ACCESS_SYSTEM_SECURITY, NULL, &hkey, NULL ); + if (res == ERROR_ACCESS_DENIED) + { + skip( "unprivileged user\n" ); + CloseHandle( token ); + return; + } + todo_wine ok( res == ERROR_PRIVILEGE_NOT_HELD, "got %d\n", res ); + + priv.PrivilegeCount = 1; + priv.Privileges[0].Luid = luid; + priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + priv_prev = HeapAlloc( GetProcessHeap(), 0, len ); + ret = AdjustTokenPrivileges( token, FALSE, &priv, len, priv_prev, &len ); + ok( ret, "got %u\n", GetLastError()); + + res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ|ACCESS_SYSTEM_SECURITY, NULL, &hkey, NULL ); + if (res == ERROR_PRIVILEGE_NOT_HELD) + { + win_skip( "privilege not held\n" ); + HeapFree( GetProcessHeap(), 0, priv_prev ); + CloseHandle( token ); + return; + } + ok( !res, "got %d\n", res ); + + /* restore privileges */ + ret = AdjustTokenPrivileges( token, FALSE, priv_prev, 0, NULL, NULL ); + ok( ret, "got %u\n", GetLastError() ); + HeapFree( GetProcessHeap(), 0, priv_prev ); + + /* privilege is checked on access */ + err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd ); + todo_wine ok( err == ERROR_PRIVILEGE_NOT_HELD, "got %u\n", err ); + + priv.PrivilegeCount = 1; + priv.Privileges[0].Luid = luid; + priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + priv_prev = HeapAlloc( GetProcessHeap(), 0, len ); + ret = AdjustTokenPrivileges( token, FALSE, &priv, len, priv_prev, &len ); + ok( ret, "got %u\n", GetLastError()); + + err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd ); + ok( err == ERROR_SUCCESS, "got %u\n", err ); + RegCloseKey( hkey ); + LocalFree( sd ); + + /* handle created without ACCESS_SYSTEM_SECURITY, privilege held */ + res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ, NULL, &hkey, NULL ); + ok( res == ERROR_SUCCESS, "got %d\n", res ); + + sd = NULL; + err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd ); + todo_wine ok( err == ERROR_SUCCESS, "got %u\n", err ); + RegCloseKey( hkey ); + LocalFree( sd ); + + /* restore privileges */ + ret = AdjustTokenPrivileges( token, FALSE, priv_prev, 0, NULL, NULL ); + ok( ret, "got %u\n", GetLastError() ); + HeapFree( GetProcessHeap(), 0, priv_prev ); + + /* handle created without ACCESS_SYSTEM_SECURITY, privilege not held */ + res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, testkeyW, 0, NULL, 0, KEY_READ, NULL, &hkey, NULL ); + ok( res == ERROR_SUCCESS, "got %d\n", res ); + + err = GetSecurityInfo( hkey, SE_REGISTRY_KEY, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &sacl, &sd ); + todo_wine ok( err == ERROR_PRIVILEGE_NOT_HELD, "got %u\n", err ); + RegCloseKey( hkey ); + + res = RegDeleteKeyW( HKEY_LOCAL_MACHINE, testkeyW ); + ok( !res, "got %d\n", res ); + CloseHandle( token ); +} + +static void test_GetWindowsAccountDomainSid(void) +{ + char *user, buffer1[SECURITY_MAX_SID_SIZE], buffer2[SECURITY_MAX_SID_SIZE]; + SID_IDENTIFIER_AUTHORITY domain_ident = { SECURITY_NT_AUTHORITY }; + PSID domain_sid = (PSID *)&buffer1; + PSID domain_sid2 = (PSID *)&buffer2; + DWORD sid_size; + PSID user_sid; + HANDLE token; + BOOL bret = TRUE; + int i; + + if (!pGetWindowsAccountDomainSid) + { + win_skip("GetWindowsAccountDomainSid not available\n"); + return; + } + + if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token)) + { + if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE; + else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE; + } + if (!bret) + { + win_skip("Failed to get current user token\n"); + return; + } + + bret = GetTokenInformation(token, TokenUser, NULL, 0, &sid_size); + ok(!bret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError()); + user = HeapAlloc(GetProcessHeap(), 0, sid_size); + bret = GetTokenInformation(token, TokenUser, user, sid_size, &sid_size); + ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError()); + CloseHandle(token); + user_sid = ((TOKEN_USER *)user)->User.Sid; + + SetLastError(0xdeadbeef); + bret = pGetWindowsAccountDomainSid(0, 0, 0); + ok(!bret, "GetWindowsAccountDomainSid succeeded\n"); + ok(GetLastError() == ERROR_INVALID_SID, "expected ERROR_INVALID_SID, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + bret = pGetWindowsAccountDomainSid(user_sid, 0, 0); + ok(!bret, "GetWindowsAccountDomainSid succeeded\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + sid_size = SECURITY_MAX_SID_SIZE; + SetLastError(0xdeadbeef); + bret = pGetWindowsAccountDomainSid(user_sid, 0, &sid_size); + ok(!bret, "GetWindowsAccountDomainSid succeeded\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size); + + SetLastError(0xdeadbeef); + bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, 0); + ok(!bret, "GetWindowsAccountDomainSid succeeded\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + sid_size = 1; + SetLastError(0xdeadbeef); + bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, &sid_size); + ok(!bret, "GetWindowsAccountDomainSid succeeded\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); + ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size); + + sid_size = SECURITY_MAX_SID_SIZE; + bret = pGetWindowsAccountDomainSid(user_sid, domain_sid, &sid_size); + ok(bret, "GetWindowsAccountDomainSid failed with error %d\n", GetLastError()); + ok(sid_size == GetSidLengthRequired(4), "expected size %d, got %d\n", GetSidLengthRequired(4), sid_size); + InitializeSid(domain_sid2, &domain_ident, 4); + for (i = 0; i < 4; i++) + *GetSidSubAuthority(domain_sid2, i) = *GetSidSubAuthority(user_sid, i); + ok(EqualSid(domain_sid, domain_sid2), "unexpected domain sid\n"); + + HeapFree(GetProcessHeap(), 0, user); +} + START_TEST(security) { init(); @@ -6146,6 +6351,7 @@ START_TEST(security) test_ConvertSecurityDescriptorToString(); test_PrivateObjectSecurity(); test_acls(); + test_GetWindowsAccountDomainSid(); test_GetSecurityInfo(); test_GetSidSubAuthority(); test_CheckTokenMembership(); @@ -6157,4 +6363,5 @@ START_TEST(security) test_default_dacl_owner_sid(); test_AdjustTokenPrivileges(); test_AddAce(); + test_system_security_access(); }