From: Mike Kozelkov augenzi@etersoft.ru
--- dlls/urlmon/tests/Makefile.in | 3 +- dlls/urlmon/tests/zone_id.c | 561 ++++++++++++++++++++++++++++++++++ 2 files changed, 563 insertions(+), 1 deletion(-) create mode 100644 dlls/urlmon/tests/zone_id.c
diff --git a/dlls/urlmon/tests/Makefile.in b/dlls/urlmon/tests/Makefile.in index 797a3434e1f..ed3cacd02fd 100644 --- a/dlls/urlmon/tests/Makefile.in +++ b/dlls/urlmon/tests/Makefile.in @@ -8,4 +8,5 @@ SOURCES = \ sec_mgr.c \ stream.c \ uri.c \ - url.c + url.c \ + zone_id.c diff --git a/dlls/urlmon/tests/zone_id.c b/dlls/urlmon/tests/zone_id.c new file mode 100644 index 00000000000..01b9cce98c5 --- /dev/null +++ b/dlls/urlmon/tests/zone_id.c @@ -0,0 +1,561 @@ +/* + * Copyright 2025 Mike Kozelkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#define CONST_VTABLE + +#include <wine/test.h> + +#include "windows.h" +#include "urlmon.h" + +#define UNINIT_TEST(str) "uninitialized: " str +#define ZONE_TEST(str) "zone_identifier: " str +#define FILE_TEST(str) "persist_file: " str + +#define URLZONE_CUSTOM1 URLZONE_UNTRUSTED + 1 +#define URLZONE_CUSTOM2 URLZONE_USER_MAX + 1 + +#define TMP_PATH_LEN 2 * MAX_PATH + +typedef struct _zone_id_op_test { + URLZONE id; + HRESULT hres; +} zone_id_op_test; + +typedef struct _zone_id_test { + zone_id_op_test set; + zone_id_op_test get; +} zone_id_test; + +static const zone_id_test zone_id_tests[] = { + { + { URLZONE_INVALID, E_INVALIDARG }, + { URLZONE_UNTRUSTED, E_ACCESSDENIED } + }, + { + { URLZONE_LOCAL_MACHINE, S_OK }, + { URLZONE_LOCAL_MACHINE, S_OK } + }, + { + { URLZONE_INTRANET, S_OK }, + { URLZONE_INTRANET, S_OK } + }, + { + { URLZONE_TRUSTED, S_OK }, + { URLZONE_TRUSTED, S_OK } + }, + { + { URLZONE_INTERNET, S_OK }, + { URLZONE_INTERNET, S_OK } + }, + { + { URLZONE_UNTRUSTED, S_OK }, + { URLZONE_UNTRUSTED, S_OK } + }, + { + { URLZONE_CUSTOM1, E_INVALIDARG }, + { URLZONE_UNTRUSTED, E_ACCESSDENIED } + }, + { + { URLZONE_USER_MIN, E_INVALIDARG }, + { URLZONE_UNTRUSTED, E_ACCESSDENIED } + }, + { + { URLZONE_USER_MAX, E_INVALIDARG }, + { URLZONE_UNTRUSTED, E_ACCESSDENIED } + }, + { + { URLZONE_CUSTOM2, E_INVALIDARG }, + { URLZONE_UNTRUSTED, E_ACCESSDENIED } + } +}; + +typedef struct _get_cur_file_test { + LPCWSTR name; + HRESULT hres; +} get_cur_file_test; + +typedef struct load_file_test { + LPCWSTR name; + DWORD mode; + HRESULT hres; +} load_file_test; + +typedef struct _save_file_test { + LPCWSTR name; + BOOL remember; + HRESULT hres; +} save_file_test; + + +typedef struct _persist_file_test { + zone_id_op_test set; + HRESULT is_dirty_before_save; + save_file_test save; + HRESULT is_dirty_after_save; + get_cur_file_test cur_file; + HRESULT is_dirty_before_load; + load_file_test load; + HRESULT is_dirty_after_load; + zone_id_op_test get; +} persist_file_test; + +static const persist_file_test persist_file_tests[] = { + { + { URLZONE_UNTRUSTED, S_OK }, + S_OK, + { NULL, FALSE, E_INVALIDARG }, + S_OK, + { NULL, E_NOTIMPL }, + S_OK, + { NULL, 0, E_INVALIDARG }, + S_OK, + { URLZONE_UNTRUSTED, __HRESULT_FROM_WIN32(ERROR_NOT_FOUND) }, + }, + { + { URLZONE_INTERNET, S_OK }, + S_OK, + { L"00000000-0000-0000-0000-000000000000", FALSE, S_OK }, + S_OK, + { NULL, E_NOTIMPL }, + S_OK, + { L"00000000-0000-0000-0000-000000000000", STGM_READWRITE | STGM_SHARE_DENY_NONE, S_OK }, + S_OK, + { URLZONE_INTERNET, S_OK }, + }, + { + { URLZONE_LOCAL_MACHINE, S_OK }, + S_OK, + { L"00000000-0000-0000-0000-000000000000", TRUE, S_OK }, + S_OK, + { NULL, E_NOTIMPL }, + S_OK, + { L"00000000-0000-0000-0000-000000000000", STGM_READWRITE | STGM_SHARE_DENY_NONE, S_OK }, + S_OK, + { URLZONE_LOCAL_MACHINE, S_OK }, + }, + { + { URLZONE_TRUSTED, S_OK }, + S_OK, + { NULL, FALSE, S_OK }, + S_OK, + { NULL, E_NOTIMPL }, + S_OK, + { L"00000000-0000-0000-0000-000000000000", STGM_READWRITE | STGM_SHARE_DENY_NONE, S_OK }, + S_OK, + { URLZONE_TRUSTED, S_OK }, + }, + { + { URLZONE_INTRANET, S_OK }, + S_OK, + { NULL, TRUE, S_OK }, + S_OK, + { NULL, E_NOTIMPL }, + S_OK, + { L"00000000-0000-0000-0000-000000000000", STGM_READWRITE | STGM_SHARE_DENY_NONE, S_OK }, + S_OK, + { URLZONE_INTRANET, S_OK }, + }, + { + { URLZONE_INTERNET, S_OK }, + S_OK, + { L"11111111-1111-1111-1111-111111111111", FALSE, S_OK }, + S_OK, + { NULL, E_NOTIMPL }, + S_OK, + { L"11111111-1111-1111-1111-111111111111", STGM_READWRITE | STGM_SHARE_DENY_NONE, S_OK }, + S_OK, + { URLZONE_INTERNET, S_OK } + }, + { + { URLZONE_LOCAL_MACHINE, S_OK }, + S_OK, + { L"00000000-0000-0000-0000-000000000000", TRUE, S_OK }, + S_OK, + { NULL, E_NOTIMPL }, + S_OK, + { NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, __HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) }, + S_OK, + { URLZONE_UNTRUSTED, __HRESULT_FROM_WIN32(ERROR_NOT_FOUND) }, + }, + { + { URLZONE_LOCAL_MACHINE, S_OK }, + S_OK, + { L"00000000-0000-0000-0000-000000000000", TRUE, S_OK }, + S_OK, + { NULL, E_NOTIMPL }, + S_OK, + { L"00000000-0000-0000-0000-000000000000", STGM_READ | STGM_SHARE_EXCLUSIVE, S_OK }, + S_OK, + { URLZONE_LOCAL_MACHINE, S_OK }, + }, +}; + + +static void test_Uninitialized(void) +{ + const zone_id_op_test get = { URLZONE_UNTRUSTED, HRESULT_FROM_WIN32(ERROR_NOT_FOUND) }; + const zone_id_op_test set = { URLZONE_INTERNET, S_OK }; + const get_cur_file_test get_cur_file = { NULL, E_NOTIMPL }; + const load_file_test load = { NULL, STGM_READ, E_INVALIDARG }; + const save_file_test save = { NULL, FALSE, E_INVALIDARG }; + IUnknown *unk; + IZoneIdentifier *zone_id; + IPersistFile *persist_file; + HRESULT hres; + DWORD zone; + CLSID clsid; + LPWSTR file_name; + + hres = CoCreateInstance(&CLSID_PersistentZoneIdentifier, NULL, + CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&unk); + ok(hres == S_OK, UNINIT_TEST("failed to obtain IUnknown iface: 0x%08lx\n"), hres); + + hres = IUnknown_QueryInterface(unk, &IID_IZoneIdentifier, (void**)&zone_id); + ok(hres == S_OK, UNINIT_TEST("failed to obtain IZoneIdentifier iface: 0x%08lx\n"), hres); + + hres = IUnknown_QueryInterface(unk, &IID_IPersistFile, (void**)&persist_file); + ok(hres == S_OK, UNINIT_TEST("failed to obtain IPersistFile iface: 0x%08lx\n"), hres); + + hres = IZoneIdentifier_GetId(zone_id, &zone); + ok(hres == get.hres, + UNINIT_TEST("unexpected get zone id result: 0x%08lx, expected result: 0x%08lx\n"), + hres, get.hres); + ok(zone == get.id, + UNINIT_TEST("unexpected default zone: 0x%08lx, expected zone: 0x%08x\n"), zone, get.id); + + hres = IPersistFile_GetClassID(persist_file, &clsid); + ok(hres == S_OK, + UNINIT_TEST("unexpected get class id result: 0x%08lx, expected result: 0x%08lx\n"), + hres, S_OK); + ok(IsEqualCLSID(&clsid, &CLSID_PersistentZoneIdentifier), + UNINIT_TEST("unexpected class id: %s, expected class id: %s\n"), + debugstr_guid(&clsid), debugstr_guid(&CLSID_PersistentZoneIdentifier)); + + hres = IPersistFile_GetCurFile(persist_file, &file_name); + ok(hres == get_cur_file.hres, + UNINIT_TEST("unexpected get current file result: 0x%08lx, expected result: 0x%08lx\n"), + hres, get_cur_file.hres); + ok(!lstrcmpW(file_name, get_cur_file.name), + UNINIT_TEST("unexpected current file name: %s, expected file name: %s\n"), + debugstr_w(file_name), debugstr_w(get_cur_file.name)); + if (hres == S_OK || hres == S_FALSE) + CoTaskMemFree(file_name); + + hres = IPersistFile_IsDirty(persist_file); + ok(hres == S_OK, + UNINIT_TEST("unexpected change object state: 0x%08lx, expected state: 0x%08lx\n"), hres, S_OK); + + hres = IZoneIdentifier_SetId(zone_id, set.id); + ok(hres == set.hres, + UNINIT_TEST("unexpected set zone id result: 0x%08lx, expected result: 0x%08lx\n"), + hres, set.hres); + + hres = IPersistFile_IsDirty(persist_file); + ok(hres == S_OK, + UNINIT_TEST("unexpected change object state after set zone: 0x%08lx, expected state: 0x%08lx\n"), + hres, S_OK); + + hres = IPersistFile_Save(persist_file, save.name, save.remember); + ok(hres == save.hres, + UNINIT_TEST("unexpected save result: 0x%08lx, expected result: 0x%08lx\n"), hres, save.hres); + + hres = IPersistFile_Load(persist_file, load.name, load.mode); + ok(hres == load.hres, + UNINIT_TEST("unexpected load result: 0x%08lx, expected result: 0x%08lx\n"), hres, load.hres); +} + +static void test_IZoneIdentifier(void) +{ + const zone_id_op_test get_removed = { URLZONE_UNTRUSTED, HRESULT_FROM_WIN32(ERROR_NOT_FOUND)}; + IUnknown *unk; + IZoneIdentifier *zone_id; + zone_id_op_test set; + zone_id_op_test get; + HRESULT hres; + DWORD i; + DWORD zone; + + hres = CoCreateInstance(&CLSID_PersistentZoneIdentifier, NULL, + CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&unk); + ok(hres == S_OK, ZONE_TEST("failed to obtain IUnknown iface: 0x%08lx\n"), hres); + + hres = IUnknown_QueryInterface(unk, &IID_IZoneIdentifier, (void**)&zone_id); + ok(hres == S_OK, ZONE_TEST("failed to obtain IZoneIdentifier iface: 0x%08lx\n"), hres); + + for(i = 0; i < ARRAY_SIZE(zone_id_tests); ++i) + { + set = zone_id_tests[i].set; + get = zone_id_tests[i].get; + + hres = IZoneIdentifier_SetId(zone_id, set.id); + ok(hres == set.hres, + ZONE_TEST("unexpected set zone id result: 0x%08lx, expected result: 0x%08lx\n"), + hres, set.hres); + + hres = IZoneIdentifier_GetId(zone_id, &zone); + ok(hres == get.hres, + ZONE_TEST("unexpected get zone id result: 0x%08lx, expected result: 0x%08lx\n"), + hres, get.hres); + ok(zone == get.id, + ZONE_TEST("unexpected zone id: 0x%08lx, expected zone: 0x%08x\n"), zone, get.id); + } + + hres = IZoneIdentifier_Remove(zone_id); + ok(hres == S_OK, + ZONE_TEST("unexpected remove zone id result: 0x%08lx, expected result: 0x%08lx\n"), + hres, S_OK); + + hres = IZoneIdentifier_GetId(zone_id, &zone); + ok(hres == get_removed.hres, + ZONE_TEST("unexpected get zone id result after remove: 0x%08lx, expected result: 0x%08lx\n"), + hres, get_removed.hres); + ok(zone == get_removed.id, + ZONE_TEST("unexpected zone id after remove: 0x%08lx, expected zone: 0x%08x\n"), + zone, get_removed.id); +} + +static void remove_dir(const WCHAR* dir_path) +{ + WCHAR files_mask[TMP_PATH_LEN]; + WCHAR file_path[TMP_PATH_LEN]; + HANDLE hfiles; + WIN32_FIND_DATAW file_data; + + wsprintfW(files_mask, L"%s\*-*-*-*", dir_path); + + hfiles = FindFirstFileW(files_mask, &file_data); + if (hfiles != INVALID_HANDLE_VALUE) + do { + wsprintfW(file_path, L"%s\%s", dir_path, file_data.cFileName); + DeleteFileW(file_path); + } while(FindNextFileW(hfiles, &file_data)); + + RemoveDirectoryW(dir_path); +} + +static void test_IPersistFile(void) +{ + IUnknown *unk; + IZoneIdentifier *zone_id_save; + IZoneIdentifier *zone_id_load; + IPersistFile *persist_file_save; + IPersistFile *persist_file_load; + HRESULT hres; + WCHAR tmp_dir[TMP_PATH_LEN]; + WCHAR sub_dir [] = L"PersistentZoneIdentifier"; + WCHAR tmp_file_path[TMP_PATH_LEN]; + WCHAR *file_path; + HANDLE hfile; + DWORD zone; + LPWSTR file_name; + DWORD i; + persist_file_test test; + + hres = CoCreateInstance(&CLSID_PersistentZoneIdentifier, NULL, + CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&unk); + ok(hres == S_OK, FILE_TEST("failed to obtain IUnknown save iface: 0x%08lx\n"), hres); + + hres = IUnknown_QueryInterface(unk, &IID_IZoneIdentifier, (void**)&zone_id_save); + ok(hres == S_OK, FILE_TEST("failed to obtain IZoneIdentifier save iface: 0x%08lx\n"), hres); + + hres = IUnknown_QueryInterface(unk, &IID_IPersistFile, (void**)&persist_file_save); + ok(hres == S_OK, FILE_TEST("failed to obtain IPersistFile save iface: 0x%08lx\n"), hres); + + hres = CoCreateInstance(&CLSID_PersistentZoneIdentifier, NULL, + CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&unk); + ok(hres == S_OK, FILE_TEST("failed to obtain IUnknown load iface: 0x%08lx\n"), hres); + + hres = IUnknown_QueryInterface(unk, &IID_IZoneIdentifier, (void**)&zone_id_load); + ok(hres == S_OK, FILE_TEST("failed to obtain IZoneIdentifier load iface: 0x%08lx\n"), hres); + + hres = IUnknown_QueryInterface(unk, &IID_IPersistFile, (void**)&persist_file_load); + ok(hres == S_OK, FILE_TEST("failed to obtain IPersistFile load iface: 0x%08lx\n"), hres); + + hres = IZoneIdentifier_Remove(zone_id_save); + ok(hres == S_OK, + FILE_TEST("unexpected remove zone id result: 0x%08lx, expected result: 0x%08lx\n"), + hres, S_OK); + + if (!GetTempPathW(sizeof(tmp_dir), tmp_dir)) + { + skip("Cannot get temporary directory path\n"); + return; + } + + if (lstrcatW(tmp_dir, sub_dir) != tmp_dir) + { + skip("Cannot get temporary subdirectory path\n"); + return; + } + + if (!CreateDirectoryW(tmp_dir, NULL)) + { + skip("Cannot create temporary directory\n"); + return; + } + + for (i = 0; i < ARRAY_SIZE(persist_file_tests); ++i) { + file_name = NULL; + file_path = NULL; + + test = persist_file_tests[i]; + hres = IZoneIdentifier_SetId(zone_id_save, test.set.id); + ok(hres == test.set.hres, + FILE_TEST("unexpected set zone id result: 0x%08lx, expected result: 0x%08lx\n"), + hres, test.set.hres); + + hres = IPersistFile_IsDirty(persist_file_save); + ok(hres == test.is_dirty_before_save, + FILE_TEST("unexpected change object state before save: 0x%08lx, expected state: 0x%08lx\n"), + hres, test.is_dirty_before_save); + + if (test.save.name) + { + wsprintfW(tmp_file_path, L"%s\%s", tmp_dir, test.save.name); + file_path = tmp_file_path; + } + else + file_path = (WCHAR *)test.save.name; + + if (file_path) + { + hfile = CreateFileW(file_path, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hfile == INVALID_HANDLE_VALUE) + { + skip("Failed to create file %s, error: 0x%08lx\n", debugstr_w(file_path), + GetLastError()); + continue; + } + CloseHandle(hfile); + } + + hres = IPersistFile_Save(persist_file_save, file_path, test.save.remember); + ok(hres == test.save.hres, + FILE_TEST("unexpected save result: 0x%08lx, expected result: 0x%08lx\n"), + hres, test.save.hres); + + hres = IPersistFile_IsDirty(persist_file_save); + ok(hres == test.is_dirty_after_save, + FILE_TEST("unexpected change object state after save: 0x%08lx, expected state: 0x%08lx\n"), + hres, test.is_dirty_after_save); + + if (test.cur_file.name && test.cur_file.hres == S_OK) + { + wsprintfW(tmp_file_path, L"%s\%s", tmp_dir, test.cur_file.name); + file_path = tmp_file_path; + } + else + file_path = (WCHAR *)test.cur_file.name; + + hres = IPersistFile_GetCurFile(persist_file_save, &file_name); + ok(hres == test.cur_file.hres, + FILE_TEST("unexpected get current file result: 0x%08lx, expected result: 0x%08lx\n"), + hres, test.cur_file.hres); + ok(!lstrcmpW(file_name, file_path), + FILE_TEST("unexpected current file name: %s, expected file name: %s\n"), + debugstr_w(file_name), debugstr_w(file_path)); + + if (hres == S_OK || hres == S_FALSE) + CoTaskMemFree(file_name); + + hres = IZoneIdentifier_Remove(zone_id_load); + ok(hres == S_OK, + FILE_TEST("unexpected remove zone id result: 0x%08lx, expected result: 0x%08lx\n"), + hres, S_OK); + + hres = IPersistFile_IsDirty(persist_file_load); + ok(hres == test.is_dirty_before_load, + FILE_TEST("unexpected change object state before load: 0x%08lx, expected state: 0x%08lx\n"), + hres, test.is_dirty_before_load); + + if (test.load.name) + { + wsprintfW(tmp_file_path, L"%s\%s", tmp_dir, test.load.name); + file_path = tmp_file_path; + } + else + file_path = (WCHAR *)test.load.name; + + hres = IPersistFile_Load(persist_file_load, file_path, test.load.mode); + ok(hres == test.load.hres, + FILE_TEST("unexpected load result: 0x%08lx, expected result: 0x%08lx\n"), + hres, test.load.hres); + + hres = IPersistFile_Load(persist_file_save, file_path, test.load.mode); + + hres = IPersistFile_IsDirty(persist_file_load); + ok(hres == test.is_dirty_after_load, + FILE_TEST("unexpected change object state after load: 0x%08lx, expected state: 0x%08lx\n"), + hres, test.is_dirty_after_load); + + hres = IZoneIdentifier_GetId(zone_id_load, &zone); + + /* GetId checks after expected Load falure shouldn't be marked as todo_wine */ + if (test.get.hres == __HRESULT_FROM_WIN32(ERROR_NOT_FOUND)) + { + ok(hres == test.get.hres, + FILE_TEST("unexpected get zone id result after load: 0x%08lx, expected result: 0x%08lx\n"), + hres, test.get.hres); + ok(zone == test.get.id, + FILE_TEST("unexpected zone id after load: 0x%08lx, expected zone: 0x%08x\n"), + zone, test.get.id); + + } + else + { + todo_wine ok(hres == test.get.hres, + FILE_TEST("unexpected get zone id result after load: 0x%08lx, expected result: 0x%08lx\n"), + hres, test.get.hres); + todo_wine ok(zone == test.get.id, + FILE_TEST("unexpected zone id after load: 0x%08lx, expected zone: 0x%08x\n"), + zone, test.get.id); + } + + if (test.save.name) + { + wsprintfW(tmp_file_path, L"%s\%s", tmp_dir, test.save.name); + file_path = tmp_file_path; + } + else + file_path = (WCHAR *)test.save.name; + + if (file_path) + DeleteFileW(file_path); + + } + + remove_dir(tmp_dir); + +} + + +START_TEST(zone_id) +{ + + CoInitialize(NULL); + + test_Uninitialized(); + test_IZoneIdentifier(); + test_IPersistFile(); + + CoUninitialize(); + +}