From 490190e205634b1526ea93f9297d247e6d3f9fd2 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sat, 5 Oct 2013 10:38:32 +0000 Subject: [PATCH] [ADVAPI32_WINETEST] * Sync with Wine 1.7.1. CORE-7469 svn path=/trunk/; revision=60531 --- rostests/winetests/advapi32/CMakeLists.txt | 9 +- rostests/winetests/advapi32/crypt.c | 18 +- rostests/winetests/advapi32/eventlog.c | 7 +- rostests/winetests/advapi32/lsa.c | 59 +++- rostests/winetests/advapi32/registry.c | 301 ++++++++++++++++++++- rostests/winetests/advapi32/security.c | 174 +++++++++++- rostests/winetests/advapi32/service.c | 59 +++- rostests/winetests/advapi32/testlist.c | 5 +- 8 files changed, 594 insertions(+), 38 deletions(-) diff --git a/rostests/winetests/advapi32/CMakeLists.txt b/rostests/winetests/advapi32/CMakeLists.txt index bfaa2f9f4b2..333048659ba 100644 --- a/rostests/winetests/advapi32/CMakeLists.txt +++ b/rostests/winetests/advapi32/CMakeLists.txt @@ -1,8 +1,4 @@ -add_definitions( - -D__ROS_LONG64__ - -D_DLL -D__USE_CRTIMP) - list(APPEND SOURCE cred.c crypt.c @@ -18,9 +14,6 @@ list(APPEND SOURCE testlist.c) add_executable(advapi32_winetest ${SOURCE}) - -target_link_libraries(advapi32_winetest uuid) - set_module_type(advapi32_winetest win32cui) -add_importlibs(advapi32_winetest advapi32 ole32 msvcrt kernel32 ntdll) +add_importlibs(advapi32_winetest advapi32 ole32 msvcrt kernel32) add_cd_file(TARGET advapi32_winetest DESTINATION reactos/bin FOR all) diff --git a/rostests/winetests/advapi32/crypt.c b/rostests/winetests/advapi32/crypt.c index 4820d279e61..768dd3be344 100644 --- a/rostests/winetests/advapi32/crypt.c +++ b/rostests/winetests/advapi32/crypt.c @@ -146,6 +146,13 @@ static void clean_up_environment(void) pCryptReleaseContext(hProv, 0); pCryptAcquireContextA(&hProv, szKeySet, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET); } + + /* Remove container "wine_test_bad_keyset" */ + if (pCryptAcquireContextA(&hProv, szBadKeySet, szRsaBaseProv, PROV_RSA_FULL, 0)) + { + pCryptReleaseContext(hProv, 0); + pCryptAcquireContextA(&hProv, szBadKeySet, szRsaBaseProv, PROV_RSA_FULL, CRYPT_DELETEKEYSET); + } } static void test_acquire_context(void) @@ -561,7 +568,16 @@ static void test_enum_providers(void) if (!(provider = LocalAlloc(LMEM_ZEROINIT, providerLen))) return; - providerLen = 0xdeadbeef; + providerLen = -1; + result = pCryptEnumProvidersA(dwIndex, NULL, 0, &type, provider, &providerLen); + ok(result, "expected TRUE, got %d\n", result); + ok(type==dwType, "expected %d, got %d\n", dwType, type); + if (pszProvName) + ok(!strcmp(pszProvName, provider), "expected %s, got %s\n", pszProvName, provider); + ok(cbName==providerLen, "expected %d, got %d\n", cbName, providerLen); + + providerLen = -1000; + provider[0] = 0; result = pCryptEnumProvidersA(dwIndex, NULL, 0, &type, provider, &providerLen); ok(result, "expected TRUE, got %d\n", result); ok(type==dwType, "expected %d, got %d\n", dwType, type); diff --git a/rostests/winetests/advapi32/eventlog.c b/rostests/winetests/advapi32/eventlog.c index 543b41cbaf8..b0283544c5b 100644 --- a/rostests/winetests/advapi32/eventlog.c +++ b/rostests/winetests/advapi32/eventlog.c @@ -637,7 +637,6 @@ static BOOL create_new_eventlog(void) /* First create our eventlog */ lret = RegOpenKeyA(HKEY_LOCAL_MACHINE, eventlogsvc, &key); - /* FIXME: Wine stops here */ if (lret != ERROR_SUCCESS) { skip("Could not open the EventLog service registry key\n"); @@ -832,11 +831,13 @@ static void test_readwrite(void) SetLastError(0xdeadbeef); ret = GetNumberOfEventLogRecords(handle, &count); ok(ret, "Expected GetNumberOfEventLogRecords success : %d\n", GetLastError()); + todo_wine ok(count == (i + 1), "Expected %d records, got %d\n", i + 1, count); oldest = 0xdeadbeef; ret = GetOldestEventLogRecord(handle, &oldest); ok(ret, "Expected GetOldestEventLogRecord success : %d\n", GetLastError()); + todo_wine ok(oldest == 1 || (oldest > 1 && oldest != 0xdeadbeef), /* Vista SP1+, W2K8 and Win7 */ "Expected oldest to be 1 or higher, got %d\n", oldest); @@ -855,6 +856,7 @@ static void test_readwrite(void) count = 0xdeadbeef; ret = GetNumberOfEventLogRecords(handle, &count); ok(ret, "Expected success\n"); + todo_wine ok(count == i, "Expected %d records, got %d\n", i, count); CloseEventLog(handle); @@ -1083,6 +1085,7 @@ static void test_autocreation(void) lstrcatA(eventlogfile, ".evtx"); } + todo_wine ok(GetFileAttributesA(eventlogfile) != INVALID_FILE_ATTRIBUTES, "Expected an eventlog file\n"); @@ -1109,14 +1112,12 @@ static void cleanup_eventlog(void) RegDeleteValueA(key, "Sources"); RegCloseKey(key); lret = RegDeleteKeyA(HKEY_LOCAL_MACHINE, winesvc); - todo_wine ok(lret == ERROR_SUCCESS, "Could not delete the registry tree : %d\n", lret); /* A handle to the eventlog is locked by services.exe. We can only * delete the eventlog file after reboot. */ bret = MoveFileExA(eventlogfile, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); - todo_wine ok(bret, "Expected MoveFileEx to succeed: %d\n", GetLastError()); } diff --git a/rostests/winetests/advapi32/lsa.c b/rostests/winetests/advapi32/lsa.c index e5b84c7526e..420b89c14f2 100644 --- a/rostests/winetests/advapi32/lsa.c +++ b/rostests/winetests/advapi32/lsa.c @@ -23,6 +23,8 @@ #include "ntstatus.h" #define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H #include "windef.h" #include "winbase.h" #include "winreg.h" @@ -43,6 +45,7 @@ static NTSTATUS (WINAPI *pLsaOpenPolicy)(PLSA_UNICODE_STRING,PLSA_OBJECT_ATTRIBU static NTSTATUS (WINAPI *pLsaQueryInformationPolicy)(LSA_HANDLE,POLICY_INFORMATION_CLASS,PVOID*); static BOOL (WINAPI *pConvertSidToStringSidA)(PSID,LPSTR*); static NTSTATUS (WINAPI *pLsaLookupNames2)(LSA_HANDLE,ULONG,ULONG,PLSA_UNICODE_STRING,PLSA_REFERENCED_DOMAIN_LIST*,PLSA_TRANSLATED_SID2*); +static NTSTATUS (WINAPI *pLsaLookupSids)(LSA_HANDLE,ULONG,PSID*,LSA_REFERENCED_DOMAIN_LIST**,LSA_TRANSLATED_NAME**); static BOOL init(void) { @@ -55,6 +58,7 @@ static BOOL init(void) pLsaQueryInformationPolicy = (void*)GetProcAddress(hadvapi32, "LsaQueryInformationPolicy"); pConvertSidToStringSidA = (void*)GetProcAddress(hadvapi32, "ConvertSidToStringSidA"); pLsaLookupNames2 = (void*)GetProcAddress(hadvapi32, "LsaLookupNames2"); + pLsaLookupSids = (void*)GetProcAddress(hadvapi32, "LsaLookupSids"); if (pLsaClose && pLsaEnumerateAccountRights && pLsaFreeMemory && pLsaOpenPolicy && pLsaQueryInformationPolicy && pConvertSidToStringSidA) return TRUE; @@ -253,7 +257,8 @@ static void test_LsaLookupNames2(void) return; } - if (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH) + if ((PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) != LANG_ENGLISH) || + (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH)) { skip("Non-English locale (skipping LsaLookupNames2 tests)\n"); return; @@ -351,6 +356,57 @@ static void test_LsaLookupNames2(void) ok(status == STATUS_SUCCESS, "LsaClose() failed, returned 0x%08x\n", status); } +static void test_LsaLookupSids(void) +{ + LSA_REFERENCED_DOMAIN_LIST *list; + LSA_OBJECT_ATTRIBUTES attrs; + LSA_TRANSLATED_NAME *names; + LSA_HANDLE policy; + TOKEN_USER *user; + NTSTATUS status; + HANDLE token; + DWORD size; + BOOL ret; + + memset(&attrs, 0, sizeof(attrs)); + attrs.Length = sizeof(attrs); + + status = pLsaOpenPolicy(NULL, &attrs, POLICY_LOOKUP_NAMES, &policy); + ok(status == STATUS_SUCCESS, "got 0x%08x\n", status); + + ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token); + ok(ret, "got %d\n", ret); + + ret = GetTokenInformation(token, TokenUser, NULL, 0, &size); + ok(!ret, "gotr %d\n", ret); + + user = HeapAlloc(GetProcessHeap(), 0, size); + ret = GetTokenInformation(token, TokenUser, user, size, &size); + ok(ret, "got %d\n", ret); + + status = pLsaLookupSids(policy, 1, &user->User.Sid, &list, &names); + ok(status == STATUS_SUCCESS, "got 0x%08x\n", status); + + ok(list->Entries > 0, "got %d\n", list->Entries); + if (list->Entries) + { + ok((char*)list->Domains - (char*)list > 0, "%p, %p\n", list, list->Domains); + ok((char*)list->Domains[0].Sid - (char*)list->Domains > 0, "%p, %p\n", list->Domains, list->Domains[0].Sid); + ok(list->Domains[0].Name.MaximumLength > list->Domains[0].Name.Length, "got %d, %d\n", list->Domains[0].Name.MaximumLength, + list->Domains[0].Name.Length); + } + + pLsaFreeMemory(names); + pLsaFreeMemory(list); + + HeapFree(GetProcessHeap(), 0, user); + + CloseHandle(token); + + status = pLsaClose(policy); + ok(status == STATUS_SUCCESS, "got 0x%08x\n", status); +} + START_TEST(lsa) { if (!init()) { @@ -360,4 +416,5 @@ START_TEST(lsa) test_lsa(); test_LsaLookupNames2(); + test_LsaLookupSids(); } diff --git a/rostests/winetests/advapi32/registry.c b/rostests/winetests/advapi32/registry.c index 9ee5ab4ac89..6ec84ee1037 100644 --- a/rostests/winetests/advapi32/registry.c +++ b/rostests/winetests/advapi32/registry.c @@ -19,6 +19,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#define WIN32_NO_STATUS +#define WIN32_LEAN_AND_MEAN + #include #include #include @@ -31,11 +34,14 @@ #include "winerror.h" #include "aclapi.h" +#define IS_HKCR(hk) ((UINT_PTR)hk > 0 && ((UINT_PTR)hk & 3) == 2) + static HKEY hkey_main; static DWORD GLE; static const char * sTestpath1 = "%LONGSYSTEMVAR%\\subdir1"; 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); @@ -143,6 +149,7 @@ static DWORD delete_key( HKEY hkey ) char name[MAX_PATH]; DWORD ret; + if ((ret = RegOpenKeyExA( hkey, "", 0, KEY_ENUMERATE_SUB_KEYS, &hkey ))) return ret; while (!(ret = RegEnumKeyA(hkey, 0, name, sizeof(name)))) { HKEY tmp; @@ -155,6 +162,7 @@ static DWORD delete_key( HKEY hkey ) } if (ret != ERROR_NO_MORE_ITEMS) return ret; RegDeleteKeyA( hkey, "" ); + RegCloseKey(hkey); return 0; } @@ -823,7 +831,8 @@ static void test_get_value(void) /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ (not allowed without RRF_NOEXPAND) */ ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ, NULL, NULL, NULL); - ok(ret == ERROR_INVALID_PARAMETER, "ret=%d\n", ret); + /* before win8: ERROR_INVALID_PARAMETER, win8: ERROR_UNSUPPORTED_TYPE */ + ok(ret == ERROR_INVALID_PARAMETER || ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret); /* Query REG_EXPAND_SZ using RRF_RT_ANY */ buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf); @@ -946,6 +955,39 @@ static void test_reg_open_key(void) "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret); RegCloseKey(hkResult); + /* check special HKEYs on 64bit + * only the lower 4 bytes of the supplied key are used + */ + if (ptr_size == 64) + { + /* HKEY_CURRENT_USER */ + ret = RegOpenKeyA(UlongToHandle(HandleToUlong(HKEY_CURRENT_USER)), "Software", &hkResult); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); + ok(hkResult != NULL, "expected hkResult != NULL\n"); + RegCloseKey(hkResult); + + ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_CURRENT_USER) | (ULONG64)1 << 32), "Software", &hkResult); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); + ok(hkResult != NULL, "expected hkResult != NULL\n"); + RegCloseKey(hkResult); + + ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_CURRENT_USER) | (ULONG64)0xdeadbeef << 32), "Software", &hkResult); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); + ok(hkResult != NULL, "expected hkResult != NULL\n"); + RegCloseKey(hkResult); + + ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_CURRENT_USER) | (ULONG64)0xffffffff << 32), "Software", &hkResult); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); + ok(hkResult != NULL, "expected hkResult != NULL\n"); + RegCloseKey(hkResult); + + /* HKEY_LOCAL_MACHINE */ + ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_LOCAL_MACHINE) | (ULONG64)0xdeadbeef << 32), "Software", &hkResult); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); + ok(hkResult != NULL, "expected hkResult != NULL\n"); + RegCloseKey(hkResult); + } + /* Try using WOW64 flags when opening a key with a DACL set to verify that * the registry access check is performed correctly. Redirection isn't * being tested, so the tests don't care about whether the process is @@ -1797,8 +1839,6 @@ static void test_symlinks(void) pRtlFreeUnicodeString( &target_str ); } -static const DWORD ptr_size = 8 * sizeof(void*); - static DWORD get_key_value( HKEY root, const char *name, DWORD flags ) { HKEY key; @@ -2085,6 +2125,7 @@ static void test_classesroot(void) skip("not enough privileges to add a user class\n"); return; } + ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey); /* try to open that key in hkcr */ res = RegOpenKeyExA( HKEY_CLASSES_ROOT, "WineTestCls", 0, @@ -2092,6 +2133,7 @@ static void test_classesroot(void) todo_wine ok(res == ERROR_SUCCESS || broken(res == ERROR_FILE_NOT_FOUND /* WinNT */), "test key not found in hkcr: %d\n", res); + todo_wine ok(IS_HKCR(hkcr), "hkcr mask not set in %p\n", hkcr); if (res) { skip("HKCR key merging not supported\n"); @@ -2123,16 +2165,16 @@ static void test_classesroot(void) ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); /* try to find the value in user's classes */ - res = RegQueryValueExA(hkcr, "val0", NULL, &type, (LPBYTE)buffer, &size); + res = RegQueryValueExA(hkey, "val0", NULL, &type, (LPBYTE)buffer, &size); ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res); ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer ); /* modify the value in user's classes */ - res = RegSetValueExA(hkcr, "val0", 0, REG_SZ, (const BYTE *)"user", sizeof("user")); + res = RegSetValueExA(hkey, "val0", 0, REG_SZ, (const BYTE *)"user", sizeof("user")); ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); /* check if the value is also modified in hkcr */ - res = RegQueryValueExA(hkey, "val0", NULL, &type, (LPBYTE)buffer, &size); + res = RegQueryValueExA(hkcr, "val0", NULL, &type, (LPBYTE)buffer, &size); ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError()); ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer ); @@ -2155,12 +2197,14 @@ static void test_classesroot(void) skip("not enough privileges to add a system class\n"); return; } + ok(!IS_HKCR(hklm), "hkcr mask set in %p\n", hklm); /* try to open that key in hkcr */ res = RegOpenKeyExA( HKEY_CLASSES_ROOT, "WineTestCls", 0, KEY_QUERY_VALUE|KEY_SET_VALUE, &hkcr ); ok(res == ERROR_SUCCESS, "test key not found in hkcr: %d\n", res); + ok(IS_HKCR(hkcr), "hkcr mask not set in %p\n", hkcr); if (res) { delete_key( hklm ); @@ -2181,19 +2225,21 @@ static void test_classesroot(void) res = RegSetValueExA(hkcr, "val2", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr")); ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); - /* check that the value is not modified in hklm classes */ + /* check that the value is modified in hklm classes */ res = RegQueryValueExA(hklm, "val2", NULL, &type, (LPBYTE)buffer, &size); ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError()); - ok(!strcmp( buffer, "hklm" ), "value set to '%s'\n", buffer ); + ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer ); if (RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", 0, NULL, 0, KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hkey, NULL )) return; + ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey); /* try to open that key in hkcr */ res = RegOpenKeyExA( HKEY_CLASSES_ROOT, "WineTestCls", 0, KEY_QUERY_VALUE|KEY_SET_VALUE, &hkcr ); ok(res == ERROR_SUCCESS, "test key not found in hkcr: %d\n", res); + ok(IS_HKCR(hkcr), "hkcr mask not set in %p\n", hkcr); /* set a value in user's classes */ res = RegSetValueExA(hkey, "val2", 0, REG_SZ, (const BYTE *)"user", sizeof("user")); @@ -2231,9 +2277,11 @@ static void test_classesroot(void) /* create a subkey in hklm */ if (RegCreateKeyExA( hklm, "subkey1", 0, NULL, 0, KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hklmsub1, NULL )) return; + ok(!IS_HKCR(hklmsub1), "hkcr mask set in %p\n", hklmsub1); /* try to open that subkey in hkcr */ res = RegOpenKeyExA( hkcr, "subkey1", 0, KEY_QUERY_VALUE|KEY_SET_VALUE, &hkcrsub1 ); ok(res == ERROR_SUCCESS, "test key not found in hkcr: %d\n", res); + ok(IS_HKCR(hkcrsub1), "hkcr mask not set in %p\n", hkcrsub1); /* set a value in hklm classes */ res = RegSetValueExA(hklmsub1, "subval1", 0, REG_SZ, (const BYTE *)"hklm", sizeof("hklm")); @@ -2256,6 +2304,7 @@ static void test_classesroot(void) /* create a subkey in user's classes */ if (RegCreateKeyExA( hkey, "subkey1", 0, NULL, 0, KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hkeysub1, NULL )) return; + ok(!IS_HKCR(hkeysub1), "hkcr mask set in %p\n", hkeysub1); /* set a value in user's classes */ res = RegSetValueExA(hkeysub1, "subval1", 0, REG_SZ, (const BYTE *)"user", sizeof("user")); @@ -2293,6 +2342,7 @@ static void test_classesroot(void) /* new subkey in hkcr */ if (RegCreateKeyExA( hkcr, "subkey2", 0, NULL, 0, KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hkcrsub2, NULL )) return; + ok(IS_HKCR(hkcrsub2), "hkcr mask not set in %p\n", hkcrsub2); res = RegSetValueExA(hkcrsub2, "subval1", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr")); ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); @@ -2302,12 +2352,37 @@ static void test_classesroot(void) hklmsub2 = 0; res = RegOpenKeyExA( hklm, "subkey2", 0, KEY_QUERY_VALUE|KEY_SET_VALUE, &hklmsub2 ); ok(res == ERROR_SUCCESS, "test key not found in hklm: %d\n", res); + ok(!IS_HKCR(hklmsub2), "hkcr mask set in %p\n", hklmsub2); /* check that the value is present in hklm */ res = RegQueryValueExA(hklmsub2, "subval1", NULL, &type, (LPBYTE)buffer, &size); ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res); ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer ); + /* cleanup */ + RegCloseKey( hkeysub1 ); + RegCloseKey( hklmsub1 ); + + /* delete subkey1 from hkcr (should point at user's classes) */ + res = RegDeleteKey(hkcr, "subkey1"); + ok(res == ERROR_SUCCESS, "RegDeleteKey failed: %d\n", res); + + /* confirm key was removed in hkey but not hklm */ + res = RegOpenKeyExA(hkey, "subkey1", 0, KEY_READ, &hkeysub1); + ok(res == ERROR_FILE_NOT_FOUND, "test key found in user's classes: %d\n", res); + res = RegOpenKeyExA(hklm, "subkey1", 0, KEY_READ, &hklmsub1); + ok(res == ERROR_SUCCESS, "test key not found in hklm: %d\n", res); + ok(!IS_HKCR(hklmsub1), "hkcr mask set in %p\n", hklmsub1); + + /* delete subkey1 from hkcr again (which should now point at hklm) */ + res = RegDeleteKey(hkcr, "subkey1"); + ok(res == ERROR_SUCCESS, "RegDeleteKey failed: %d\n", res); + + /* confirm hkey was removed in hklm */ + RegCloseKey( hklmsub1 ); + res = RegOpenKeyExA(hklm, "subkey1", 0, KEY_READ, &hklmsub1); + ok(res == ERROR_FILE_NOT_FOUND, "test key found in hklm: %d\n", res); + /* final cleanup */ delete_key( hkey ); delete_key( hklm ); @@ -2327,6 +2402,214 @@ static void test_classesroot(void) RegCloseKey( hkcrsub2 ); } +static void test_classesroot_enum(void) +{ + HKEY hkcu=0, hklm=0, hkcr=0, hkcusub[2]={0}, hklmsub[2]={0}; + DWORD size; + static CHAR buffer[2]; + LONG res; + + /* prepare initial testing env in HKCU */ + if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", &hkcu )) + { + delete_key( hkcu ); + RegCloseKey( hkcu ); + } + res = RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", 0, NULL, 0, + KEY_SET_VALUE|KEY_ENUMERATE_SUB_KEYS, NULL, &hkcu, NULL ); + + if (res != ERROR_SUCCESS) + { + skip("failed to add a user class\n"); + return; + } + + res = RegOpenKeyA( HKEY_CLASSES_ROOT, "WineTestCls", &hkcr ); + todo_wine ok(res == ERROR_SUCCESS || + broken(res == ERROR_FILE_NOT_FOUND /* WinNT */), + "test key not found in hkcr: %d\n", res); + if (res) + { + skip("HKCR key merging not supported\n"); + delete_key( hkcu ); + RegCloseKey( hkcu ); + return; + } + + res = RegSetValueExA( hkcu, "X", 0, REG_SZ, (const BYTE *) "AA", 3 ); + ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", res); + res = RegSetValueExA( hkcu, "Y", 0, REG_SZ, (const BYTE *) "B", 2 ); + ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", res); + res = RegCreateKeyA( hkcu, "A", &hkcusub[0] ); + ok(res == ERROR_SUCCESS, "RegCreateKeyA failed: %d\n", res); + res = RegCreateKeyA( hkcu, "B", &hkcusub[1] ); + ok(res == ERROR_SUCCESS, "RegCreateKeyA failed: %d\n", res); + + /* test on values in HKCU */ + size = sizeof(buffer); + res = RegEnumValueA( hkcr, 0, buffer, &size, NULL, NULL, NULL, NULL ); + ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res ); + ok(!strcmp( buffer, "X" ), "expected 'X', got '%s'\n", buffer); + size = sizeof(buffer); + res = RegEnumValueA( hkcr, 1, buffer, &size, NULL, NULL, NULL, NULL ); + ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res ); + ok(!strcmp( buffer, "Y" ), "expected 'Y', got '%s'\n", buffer); + size = sizeof(buffer); + res = RegEnumValueA( hkcr, 2, buffer, &size, NULL, NULL, NULL, NULL ); + ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res ); + + res = RegEnumKeyA( hkcr, 0, buffer, size ); + ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res ); + ok(!strcmp( buffer, "A" ), "expected 'A', got '%s'\n", buffer); + res = RegEnumKeyA( hkcr, 1, buffer, size ); + ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res ); + ok(!strcmp( buffer, "B" ), "expected 'B', got '%s'\n", buffer); + res = RegEnumKeyA( hkcr, 2, buffer, size ); + ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res ); + + /* prepare test env in HKLM */ + if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Classes\\WineTestCls", &hklm )) + { + delete_key( hklm ); + RegCloseKey( hklm ); + } + + res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\WineTestCls", 0, NULL, 0, + KEY_SET_VALUE|KEY_ENUMERATE_SUB_KEYS, NULL, &hklm, NULL ); + + if (res == ERROR_ACCESS_DENIED) + { + RegCloseKey( hkcusub[0] ); + RegCloseKey( hkcusub[1] ); + delete_key( hkcu ); + RegCloseKey( hkcu ); + RegCloseKey( hkcr ); + skip("not enough privileges to add a system class\n"); + return; + } + + res = RegSetValueExA( hklm, "X", 0, REG_SZ, (const BYTE *) "AB", 3 ); + ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", res); + res = RegSetValueExA( hklm, "Z", 0, REG_SZ, (const BYTE *) "C", 2 ); + ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", res); + res = RegCreateKeyA( hklm, "A", &hklmsub[0] ); + ok(res == ERROR_SUCCESS, "RegCreateKeyA failed: %d\n", res); + res = RegCreateKeyA( hklm, "C", &hklmsub[1] ); + ok(res == ERROR_SUCCESS, "RegCreateKeyA failed: %d\n", res); + + /* test on values/keys in both HKCU and HKLM */ + size = sizeof(buffer); + res = RegEnumValueA( hkcr, 0, buffer, &size, NULL, NULL, NULL, NULL ); + ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res ); + ok(!strcmp( buffer, "X" ), "expected 'X', got '%s'\n", buffer); + size = sizeof(buffer); + res = RegEnumValueA( hkcr, 1, buffer, &size, NULL, NULL, NULL, NULL ); + ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res ); + ok(!strcmp( buffer, "Y" ), "expected 'Y', got '%s'\n", buffer); + size = sizeof(buffer); + res = RegEnumValueA( hkcr, 2, buffer, &size, NULL, NULL, NULL, NULL ); + ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res ); + ok(!strcmp( buffer, "Z" ), "expected 'Z', got '%s'\n", buffer); + size = sizeof(buffer); + res = RegEnumValueA( hkcr, 3, buffer, &size, NULL, NULL, NULL, NULL ); + ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res ); + + res = RegEnumKeyA( hkcr, 0, buffer, size ); + ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res ); + ok(!strcmp( buffer, "A" ), "expected 'A', got '%s'\n", buffer); + res = RegEnumKeyA( hkcr, 1, buffer, size ); + ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res ); + ok(!strcmp( buffer, "B" ), "expected 'B', got '%s'\n", buffer); + res = RegEnumKeyA( hkcr, 2, buffer, size ); + ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res ); + ok(!strcmp( buffer, "C" ), "expected 'C', got '%s'\n", buffer); + res = RegEnumKeyA( hkcr, 3, buffer, size ); + ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res ); + + /* delete values/keys from HKCU to test only on HKLM */ + RegCloseKey( hkcusub[0] ); + RegCloseKey( hkcusub[1] ); + delete_key( hkcu ); + RegCloseKey( hkcu ); + + size = sizeof(buffer); + res = RegEnumValueA( hkcr, 0, buffer, &size, NULL, NULL, NULL, NULL ); + ok(res == ERROR_KEY_DELETED || + res == ERROR_NO_SYSTEM_RESOURCES, /* Windows XP */ + "expected ERROR_KEY_DELETED, got %d\n", res); + size = sizeof(buffer); + res = RegEnumKeyA( hkcr, 0, buffer, size ); + ok(res == ERROR_KEY_DELETED || + res == ERROR_NO_SYSTEM_RESOURCES, /* Windows XP */ + "expected ERROR_KEY_DELETED, got %d\n", res); + + /* reopen HKCR handle */ + RegCloseKey( hkcr ); + res = RegOpenKeyA( HKEY_CLASSES_ROOT, "WineTestCls", &hkcr ); + ok(res == ERROR_SUCCESS, "test key not found in hkcr: %d\n", res); + if (res) goto cleanup; + + /* test on values/keys in HKLM */ + size = sizeof(buffer); + res = RegEnumValueA( hkcr, 0, buffer, &size, NULL, NULL, NULL, NULL ); + ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res ); + ok(!strcmp( buffer, "X" ), "expected 'X', got '%s'\n", buffer); + size = sizeof(buffer); + res = RegEnumValueA( hkcr, 1, buffer, &size, NULL, NULL, NULL, NULL ); + ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res ); + ok(!strcmp( buffer, "Z" ), "expected 'Z', got '%s'\n", buffer); + size = sizeof(buffer); + res = RegEnumValueA( hkcr, 2, buffer, &size, NULL, NULL, NULL, NULL ); + ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res ); + + res = RegEnumKeyA( hkcr, 0, buffer, size ); + ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res ); + ok(!strcmp( buffer, "A" ), "expected 'A', got '%s'\n", buffer); + res = RegEnumKeyA( hkcr, 1, buffer, size ); + ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res ); + ok(!strcmp( buffer, "C" ), "expected 'C', got '%s'\n", buffer); + res = RegEnumKeyA( hkcr, 2, buffer, size ); + ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res ); + +cleanup: + RegCloseKey( hklmsub[0] ); + RegCloseKey( hklmsub[1] ); + delete_key( hklm ); + RegCloseKey( hklm ); + RegCloseKey( hkcr ); +} + +static void test_classesroot_mask(void) +{ + HKEY hkey; + LSTATUS res; + + res = RegOpenKeyA( HKEY_CLASSES_ROOT, "CLSID", &hkey ); + ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %d\n", res); + todo_wine ok(IS_HKCR(hkey), "hkcr mask not set in %p\n", hkey); + RegCloseKey( hkey ); + + res = RegOpenKeyA( HKEY_CURRENT_USER, "Software", &hkey ); + ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %d\n", res); + ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey); + RegCloseKey( hkey ); + + res = RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software", &hkey ); + ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %d\n", res); + ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey); + RegCloseKey( hkey ); + + res = RegOpenKeyA( HKEY_USERS, ".Default", &hkey ); + ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %d\n", res); + ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey); + RegCloseKey( hkey ); + + res = RegOpenKeyA( HKEY_CURRENT_CONFIG, "Software", &hkey ); + ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %d\n", res); + ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey); + RegCloseKey( hkey ); +} + static void test_deleted_key(void) { HKEY hkey, hkey2; @@ -2420,6 +2703,8 @@ START_TEST(registry) test_symlinks(); test_redirection(); test_classesroot(); + test_classesroot_enum(); + test_classesroot_mask(); /* SaveKey/LoadKey require the SE_BACKUP_NAME privilege to be set */ if (set_privileges(SE_BACKUP_NAME, TRUE) && diff --git a/rostests/winetests/advapi32/security.c b/rostests/winetests/advapi32/security.c index 09e0fcd6894..c1945e11428 100644 --- a/rostests/winetests/advapi32/security.c +++ b/rostests/winetests/advapi32/security.c @@ -24,6 +24,7 @@ #include "ntstatus.h" #define WIN32_NO_STATUS +#define WIN32_LEAN_AND_MEAN #include "windef.h" #include "winbase.h" #include "winerror.h" @@ -3007,10 +3008,15 @@ static void test_SetEntriesInAclA(void) static void test_GetNamedSecurityInfoA(void) { - char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], dacl[100], *user; + char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], *user; + char system_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES]; + char users_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES]; + PSID admin_sid = (PSID) admin_ptr, users_sid = (PSID) users_ptr; + PSID system_sid = (PSID) system_ptr, user_sid; DWORD sid_size = sizeof(admin_ptr), user_size; char invalid_path[] = "/an invalid file path"; - PSID admin_sid = (PSID) admin_ptr, user_sid; + int users_ace_id = -1, admins_ace_id = -1, i; + char software_key[] = "MACHINE\\Software"; char sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; SECURITY_DESCRIPTOR_CONTROL control; ACL_SIZE_INFORMATION acl_size; @@ -3022,9 +3028,12 @@ static void test_GetNamedSecurityInfoA(void) DWORD error, revision; BOOL owner_defaulted; BOOL group_defaulted; + BOOL dacl_defaulted; HANDLE token, hTemp; PSID owner, group; + BOOL dacl_present; PACL pDacl; + BYTE flags; if (!pSetNamedSecurityInfoA || !pGetNamedSecurityInfoA || !pCreateWellKnownSid) { @@ -3115,13 +3124,12 @@ static void test_GetNamedSecurityInfoA(void) /* Create security descriptor information and test that it comes back the same */ pSD = &sd; - pDacl = (PACL)&dacl; + pDacl = HeapAlloc(GetProcessHeap(), 0, 100); InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); pCreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size); - bret = InitializeAcl(pDacl, sizeof(dacl), ACL_REVISION); + bret = InitializeAcl(pDacl, 100, ACL_REVISION); ok(bret, "Failed to initialize ACL.\n"); bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid); - HeapFree(GetProcessHeap(), 0, user); ok(bret, "Failed to add Current User to ACL.\n"); bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, admin_sid); ok(bret, "Failed to add Administrator Group to ACL.\n"); @@ -3133,9 +3141,11 @@ static void test_GetNamedSecurityInfoA(void) SetLastError(0xdeadbeef); error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pDacl, NULL); + HeapFree(GetProcessHeap(), 0, pDacl); if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) { win_skip("SetNamedSecurityInfoA is not implemented\n"); + HeapFree(GetProcessHeap(), 0, user); CloseHandle(hTemp); return; } @@ -3146,6 +3156,8 @@ static void test_GetNamedSecurityInfoA(void) if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) { win_skip("GetNamedSecurityInfoA is not implemented\n"); + HeapFree(GetProcessHeap(), 0, user); + CloseHandle(hTemp); return; } ok(!error, "GetNamedSecurityInfo failed with error %d\n", error); @@ -3176,7 +3188,80 @@ static void test_GetNamedSecurityInfoA(void) "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask); } LocalFree(pSD); + HeapFree(GetProcessHeap(), 0, user); CloseHandle(hTemp); + + /* Test querying the ownership of a built-in registry key */ + sid_size = sizeof(system_ptr); + pCreateWellKnownSid(WinLocalSystemSid, NULL, system_sid, &sid_size); + error = pGetNamedSecurityInfoA(software_key, SE_REGISTRY_KEY, + OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION, + NULL, NULL, NULL, NULL, &pSD); + ok(!error, "GetNamedSecurityInfo failed with error %d\n", error); + + bret = GetSecurityDescriptorOwner(pSD, &owner, &owner_defaulted); + ok(bret, "GetSecurityDescriptorOwner failed with error %d\n", GetLastError()); + ok(owner != NULL, "owner should not be NULL\n"); + ok(EqualSid(owner, admin_sid), "MACHINE\\Software owner SID != Administrators SID.\n"); + + bret = GetSecurityDescriptorGroup(pSD, &group, &group_defaulted); + ok(bret, "GetSecurityDescriptorGroup failed with error %d\n", GetLastError()); + ok(group != NULL, "group should not be NULL\n"); + ok(EqualSid(group, admin_sid) || broken(EqualSid(group, system_sid)) /* before Win7 */ + || broken(((SID*)group)->SubAuthority[0] == SECURITY_NT_NON_UNIQUE) /* Vista */, + "MACHINE\\Software group SID != Local System SID.\n"); + LocalFree(pSD); + + /* Test querying the DACL of a built-in registry key */ + sid_size = sizeof(users_ptr); + pCreateWellKnownSid(WinBuiltinUsersSid, NULL, users_sid, &sid_size); + error = pGetNamedSecurityInfoA(software_key, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, + NULL, NULL, NULL, NULL, &pSD); + ok(!error, "GetNamedSecurityInfo failed with error %d\n", error); + + bret = GetSecurityDescriptorDacl(pSD, &dacl_present, &pDacl, &dacl_defaulted); + ok(bret, "GetSecurityDescriptorDacl failed with error %d\n", GetLastError()); + ok(dacl_present, "DACL should be present\n"); + ok(pDacl && IsValidAcl(pDacl), "GetSecurityDescriptorDacl returned invalid DACL.\n"); + bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation); + ok(bret, "GetAclInformation failed\n"); + ok(acl_size.AceCount != 0, "GetAclInformation returned no ACLs\n"); + for (i=0; iSidStart, users_sid); + if (bret) users_ace_id = i; + bret = EqualSid(&ace->SidStart, admin_sid); + if (bret) admins_ace_id = i; + } + ok(users_ace_id != -1 || broken(users_ace_id == -1) /* win2k */, + "Bultin Users ACE not found.\n"); + if (users_ace_id != -1) + { + bret = pGetAce(pDacl, users_ace_id, (VOID **)&ace); + ok(bret, "Failed to get Builtin Users ACE.\n"); + flags = ((ACE_HEADER *)ace)->AceFlags; + ok(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE) + || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* w2k8 */, + "Builtin Users ACE has unexpected flags (0x%x != 0x%x)\n", flags, + INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE); + ok(ace->Mask == GENERIC_READ, "Builtin Users ACE has unexpected mask (0x%x != 0x%x)\n", + ace->Mask, GENERIC_READ); + } + ok(admins_ace_id != -1, "Bultin Admins ACE not found.\n"); + if (admins_ace_id != -1) + { + bret = pGetAce(pDacl, admins_ace_id, (VOID **)&ace); + ok(bret, "Failed to get Builtin Admins ACE.\n"); + flags = ((ACE_HEADER *)ace)->AceFlags; + ok(flags == 0x0 + || broken(flags == (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|INHERITED_ACE)) /* w2k8 */, + "Builtin Admins ACE has unexpected flags (0x%x != 0x0)\n", flags); + ok(ace->Mask == KEY_ALL_ACCESS || broken(ace->Mask == GENERIC_ALL) /* w2k8 */, + "Builtin Admins ACE has unexpected mask (0x%x != 0x%x)\n", ace->Mask, KEY_ALL_ACCESS); + } + LocalFree(pSD); } static void test_ConvertStringSecurityDescriptor(void) @@ -4077,6 +4162,8 @@ static void test_CreateRestrictedToken(void) HANDLE process_token, token, r_token; PTOKEN_GROUPS token_groups, groups2; SID_AND_ATTRIBUTES sattr; + SECURITY_IMPERSONATION_LEVEL level; + TOKEN_TYPE type; BOOL is_member; DWORD size; BOOL ret; @@ -4127,7 +4214,7 @@ static void test_CreateRestrictedToken(void) sattr.Attributes = 0; r_token = NULL; ret = pCreateRestrictedToken(token, 0, 1, &sattr, 0, NULL, 0, NULL, &r_token); - todo_wine ok(ret, "got error %d\n", GetLastError()); + ok(ret, "got error %d\n", GetLastError()); if (ret) { @@ -4135,7 +4222,7 @@ static void test_CreateRestrictedToken(void) is_member = TRUE; ret = pCheckTokenMembership(r_token, token_groups->Groups[i].Sid, &is_member); ok(ret, "got error %d\n", GetLastError()); - ok(!is_member, "not a member\n"); + todo_wine ok(!is_member, "not a member\n"); ret = GetTokenInformation(r_token, TokenGroups, NULL, 0, &size); ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n", @@ -4150,12 +4237,22 @@ static void test_CreateRestrictedToken(void) break; } - ok(groups2->Groups[j].Attributes & SE_GROUP_USE_FOR_DENY_ONLY, + todo_wine ok(groups2->Groups[j].Attributes & SE_GROUP_USE_FOR_DENY_ONLY, "got wrong attributes\n"); - ok((groups2->Groups[j].Attributes & SE_GROUP_ENABLED) == 0, + todo_wine ok((groups2->Groups[j].Attributes & SE_GROUP_ENABLED) == 0, "got wrong attributes\n"); HeapFree(GetProcessHeap(), 0, groups2); + + size = sizeof(type); + ret = GetTokenInformation(r_token, TokenType, &type, size, &size); + ok(ret, "got error %d\n", GetLastError()); + ok(type == TokenImpersonation, "got type %u\n", type); + + size = sizeof(level); + ret = GetTokenInformation(r_token, TokenImpersonationLevel, &level, size, &size); + ok(ret, "got error %d\n", GetLastError()); + ok(level == SecurityImpersonation, "got level %u\n", type); } HeapFree(GetProcessHeap(), 0, token_groups); @@ -4497,6 +4594,64 @@ static void test_TokenIntegrityLevel(void) CloseHandle(token); } +static void test_default_dacl_owner_sid(void) +{ + HANDLE handle; + BOOL ret, defaulted, present, found; + DWORD size, index; + SECURITY_DESCRIPTOR *sd; + SECURITY_ATTRIBUTES sa; + PSID owner; + ACL *dacl; + ACCESS_ALLOWED_ACE *ace; + + sd = HeapAlloc( GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH ); + ret = InitializeSecurityDescriptor( sd, SECURITY_DESCRIPTOR_REVISION ); + ok( ret, "error %u\n", GetLastError() ); + + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = sd; + sa.bInheritHandle = FALSE; + handle = CreateEvent( &sa, TRUE, TRUE, "test_event" ); + ok( handle != NULL, "error %u\n", GetLastError() ); + + size = 0; + ret = GetKernelObjectSecurity( handle, OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, NULL, 0, &size ); + ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "error %u\n", GetLastError() ); + + sd = HeapAlloc( GetProcessHeap(), 0, size ); + ret = GetKernelObjectSecurity( handle, OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, sd, size, &size ); + ok( ret, "error %u\n", GetLastError() ); + + owner = (void *)0xdeadbeef; + defaulted = TRUE; + ret = GetSecurityDescriptorOwner( sd, &owner, &defaulted ); + ok( ret, "error %u\n", GetLastError() ); + ok( owner != (void *)0xdeadbeef, "owner not set\n" ); + todo_wine ok( !defaulted, "owner defaulted\n" ); + + dacl = (void *)0xdeadbeef; + present = FALSE; + defaulted = TRUE; + ret = GetSecurityDescriptorDacl( sd, &present, &dacl, &defaulted ); + ok( ret, "error %u\n", GetLastError() ); + ok( present, "dacl not present\n" ); + ok( dacl != (void *)0xdeadbeef, "dacl not set\n" ); + todo_wine ok( !defaulted, "dacl defaulted\n" ); + + index = 0; + found = FALSE; + while (pGetAce( dacl, index++, (void **)&ace )) + { + if (EqualSid( &ace->SidStart, owner )) found = TRUE; + } + ok( found, "owner sid not found in dacl\n" ); + + HeapFree( GetProcessHeap(), 0, sa.lpSecurityDescriptor ); + HeapFree( GetProcessHeap(), 0, sd ); + CloseHandle( handle ); +} + START_TEST(security) { init(); @@ -4535,4 +4690,5 @@ START_TEST(security) test_GetUserNameW(); test_CreateRestrictedToken(); test_TokenIntegrityLevel(); + test_default_dacl_owner_sid(); } diff --git a/rostests/winetests/advapi32/service.c b/rostests/winetests/advapi32/service.c index 3b066e03694..bbfe01ddb91 100644 --- a/rostests/winetests/advapi32/service.c +++ b/rostests/winetests/advapi32/service.c @@ -18,6 +18,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#define WIN32_NO_STATUS +#define WIN32_LEAN_AND_MEAN + #include #include @@ -48,6 +51,8 @@ static BOOL (WINAPI *pQueryServiceConfig2A)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD static BOOL (WINAPI *pQueryServiceConfig2W)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD); static BOOL (WINAPI *pQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD); +static BOOL (WINAPI *pQueryServiceObjectSecurity)(SC_HANDLE, SECURITY_INFORMATION, + PSECURITY_DESCRIPTOR, DWORD, LPDWORD); static void init_function_pointers(void) { @@ -60,6 +65,7 @@ static void init_function_pointers(void) pQueryServiceConfig2A= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2A"); pQueryServiceConfig2W= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2W"); pQueryServiceStatusEx= (void*)GetProcAddress(hadvapi32, "QueryServiceStatusEx"); + pQueryServiceObjectSecurity = (void*)GetProcAddress(hadvapi32, "QueryServiceObjectSecurity"); } static void test_open_scm(void) @@ -1756,7 +1762,7 @@ static void test_close(void) static void test_sequence(void) { SC_HANDLE scm_handle, svc_handle; - BOOL ret; + BOOL ret, is_nt4; QUERY_SERVICE_CONFIGA *config; DWORD given, needed; static const CHAR servicename [] = "Winetest"; @@ -1780,6 +1786,9 @@ static void test_sequence(void) ok(scm_handle != NULL, "Could not get a handle to the manager: %d\n", GetLastError()); if (!scm_handle) return; + svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ); + is_nt4=(svc_handle == NULL && GetLastError() == ERROR_INVALID_PARAMETER); + CloseServiceHandle(svc_handle); /* Create a dummy service */ SetLastError(0xdeadbeef); @@ -1817,12 +1826,54 @@ static void test_sequence(void) PSID sidOwner, sidGroup; PACL dacl, sacl; PSECURITY_DESCRIPTOR pSD; - HRESULT retval = pGetSecurityInfo(svc_handle,SE_SERVICE,DACL_SECURITY_INFORMATION,&sidOwner,&sidGroup,&dacl,&sacl,&pSD); - todo_wine ok(ERROR_SUCCESS == retval, "Expected GetSecurityInfo to succeed: result %d\n",retval); + DWORD error, n1, n2; + HRESULT retval; + BOOL bret; + + /* Test using GetSecurityInfo to obtain security information */ + retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, &sidOwner, + &sidGroup, &dacl, &sacl, &pSD); + LocalFree(pSD); + ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval); + retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL, + NULL, NULL, NULL, &pSD); + LocalFree(pSD); + ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval); + if (!is_nt4) + { + retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL, + NULL, &dacl, NULL, NULL); + ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval); + SetLastError(0xdeadbeef); + retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL, + NULL, NULL, NULL, NULL); + error = GetLastError(); + ok(retval == ERROR_INVALID_PARAMETER, "Expected GetSecurityInfo to fail: result %d\n", retval); + ok(error == 0xdeadbeef, "Unexpected last error %d\n", error); + } + else + win_skip("A NULL security descriptor in GetSecurityInfo results in an exception on NT4.\n"); + + /* Test using QueryServiceObjectSecurity to obtain security information */ + SetLastError(0xdeadbeef); + bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, NULL, 0, &n1); + error = GetLastError(); + ok(!bret, "Expected QueryServiceObjectSecurity to fail: result %d\n", bret); + ok(error == ERROR_INSUFFICIENT_BUFFER || + broken(error == ERROR_INVALID_ADDRESS) || broken(error == ERROR_INVALID_PARAMETER), + "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", error); + if (error != ERROR_INSUFFICIENT_BUFFER) n1 = 1024; + pSD = LocalAlloc(0, n1); + bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, pSD, n1, &n2); + ok(bret, "Expected QueryServiceObjectSecurity to succeed: result %d\n", bret); + LocalFree(pSD); } } - if (!svc_handle) return; + if (!svc_handle) { + CloseServiceHandle(scm_handle); + return; + } /* TODO: * Before we do a QueryServiceConfig we should check the registry. This will make sure diff --git a/rostests/winetests/advapi32/testlist.c b/rostests/winetests/advapi32/testlist.c index 9722479c9be..bd8e8187d75 100644 --- a/rostests/winetests/advapi32/testlist.c +++ b/rostests/winetests/advapi32/testlist.c @@ -1,10 +1,7 @@ /* Automatically generated file; DO NOT EDIT!! */ -#define WIN32_LEAN_AND_MEAN -#include - #define STANDALONE -#include "wine/test.h" +#include extern void func_cred(void); extern void func_crypt(void); -- 2.17.1