selfreg.c was copied from dlls/msi/tests and load_resource was copied from dlls/setupapi/tests/install.c.
Two of the tests are marked todo because Wine currently doesn't support the UnregisterOCXs command, only RegisterOCXs.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56209
-- v8: advpack: Ignore lines that begin with '@' in (Un)RegisterOCXs sections.
From: Alex Henrie alexhenrie24@gmail.com
selfreg.c was copied from dlls/msi/tests and load_resource was copied from dlls/setupapi/tests/install.c.
Two of the tests are marked todo because Wine currently doesn't support the UnregisterOCXs command, only RegisterOCXs.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56209 --- dlls/advpack/install.c | 8 +++ dlls/advpack/tests/Makefile.in | 6 +- dlls/advpack/tests/install.c | 98 ++++++++++++++++++++++++++++++++- dlls/advpack/tests/selfreg.c | 42 ++++++++++++++ dlls/advpack/tests/selfreg.spec | 2 + 5 files changed, 152 insertions(+), 4 deletions(-) create mode 100644 dlls/advpack/tests/selfreg.c create mode 100644 dlls/advpack/tests/selfreg.spec
diff --git a/dlls/advpack/install.c b/dlls/advpack/install.c index b32a6f4c972..81ceebbe7aa 100644 --- a/dlls/advpack/install.c +++ b/dlls/advpack/install.c @@ -128,6 +128,14 @@ static HRESULT register_ocxs_callback(HINF hinf, PCWSTR field, const void *arg) if (!SetupGetStringFieldW(&context, 1, buffer, ARRAY_SIZE(buffer), NULL)) continue;
+ /* RegisterOCXs and UnRegisterOCXs sections can include lines that start with an at sign and + * do not have any discernable or documented effect */ + if (buffer[0] == '@') + { + FIXME("Ignoring inf line %s\n", debugstr_w(buffer)); + continue; + } + hm = LoadLibraryExW(buffer, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (hm) { diff --git a/dlls/advpack/tests/Makefile.in b/dlls/advpack/tests/Makefile.in index 084d67955ce..f52c656ed06 100644 --- a/dlls/advpack/tests/Makefile.in +++ b/dlls/advpack/tests/Makefile.in @@ -1,7 +1,9 @@ TESTDLL = advpack.dll -IMPORTS = cabinet advapi32 advpack +IMPORTS = cabinet advapi32 advpack user32
SOURCES = \ advpack.c \ files.c \ - install.c + install.c \ + selfreg.c \ + selfreg.spec diff --git a/dlls/advpack/tests/install.c b/dlls/advpack/tests/install.c index bdf02c5a397..4d28f22df6c 100644 --- a/dlls/advpack/tests/install.c +++ b/dlls/advpack/tests/install.c @@ -26,7 +26,7 @@ static HMODULE hAdvPack; /* function pointers */ static HRESULT (WINAPI *pRunSetupCommand)(HWND, LPCSTR, LPCSTR, LPCSTR, LPCSTR, HANDLE*, DWORD, LPVOID); -static HRESULT (WINAPI *pLaunchINFSection)(HWND, HINSTANCE, LPSTR, INT); +static INT (WINAPI *pLaunchINFSection)(HWND, HINSTANCE, LPSTR, INT); static HRESULT (WINAPI *pLaunchINFSectionEx)(HWND, HINSTANCE, LPSTR, INT);
static char CURR_DIR[MAX_PATH]; @@ -55,6 +55,24 @@ static BOOL is_spapi_err(DWORD err) return (((err & SPAPI_MASK) ^ SPAPI_PREFIX) == 0); }
+static void load_resource(const char *name, const char *filename) +{ + DWORD written; + HANDLE file; + HRSRC res; + void *ptr; + + file = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); + ok(file != INVALID_HANDLE_VALUE, "file creation failed, at %s, error %ld\n", filename, GetLastError()); + + res = FindResourceA(NULL, name, "TESTDLL"); + ok(res != 0, "couldn't find resource\n"); + ptr = LockResource(LoadResource(GetModuleHandleA(NULL), res)); + WriteFile(file, ptr, SizeofResource(GetModuleHandleA(NULL), res), &written, NULL); + ok(written == SizeofResource(GetModuleHandleA(NULL), res), "couldn't write resource\n"); + CloseHandle(file); +} + static void create_inf_file(LPCSTR filename) { DWORD dwNumberOfBytesWritten; @@ -66,7 +84,29 @@ static void create_inf_file(LPCSTR filename) "Signature="$Chicago$"\n" "AdvancedINF=2.5\n" "[DefaultInstall]\n" - "CheckAdminRights=1\n"; + "CheckAdminRights=1\n" + + "[OcxInstallGood]\n" + "RegisterOCXs=GoodOCX\n" + "[OcxUninstallGood]\n" + "UnregisterOCXs=GoodOCX\n" + "[GoodOCX]\n" + "winetest_selfreg.ocx\n" + + "[OcxInstallAtGood]\n" + "RegisterOCXs=AtGoodOCX\n" + "[AtGoodOCX]\n" + "@winetest_selfreg.ocx\n" + + "[OcxInstallBad]\n" + "RegisterOCXs=BadOCXsToRegister\n" + "[BadOCXsToRegister]\n" + "nonexistent.ocx\n" + + "[OcxInstallAtBad]\n" + "RegisterOCXs=AtBadOCX\n" + "[AtBadOCX]\n" + "@nonexistent.ocx\n";
WriteFile(hf, data, sizeof(data) - 1, &dwNumberOfBytesWritten, NULL); CloseHandle(hf); @@ -262,6 +302,59 @@ static void test_LaunchINFSectionEx(void) DeleteFileA("test.inf"); }
+static LRESULT CALLBACK hide_window_hook(int code, WPARAM wparam, LPARAM lparam) +{ + if (code == HCBT_CREATEWND) + { + /* Suppress the "Error registering the OCX" dialog */ + return 1; + } + + return CallNextHookEx(NULL, code, wparam, lparam); +} + +static void test_RegisterOCXs(void) +{ + static char install_good_section[] = "test.inf,OcxInstallGood,4,0"; + static char uninstall_good_section[] = "test.inf,OcxUninstallGood,4,0"; + static char install_at_good_section[] = "test.inf,OcxInstallAtGood,4,0"; + static char install_bad_section[] = "test.inf,OcxInstallBad,4,0"; + static char install_at_bad_section[] = "test.inf,OcxInstallAtBad,4,0"; + HHOOK hook; + HKEY key; + INT res; + + load_resource("selfreg.dll", "winetest_selfreg.ocx"); + create_inf_file("test.inf"); + + res = pLaunchINFSection(NULL, NULL, install_good_section, 0); + ok(res == 0, "Expected 0, got %d\n", res); + res = RegOpenKeyA(HKEY_CLASSES_ROOT, "selfreg_test", &key); + ok(res == 0, "Expected 0, got %d\n", res); + RegCloseKey(key); + + res = pLaunchINFSection(NULL, NULL, uninstall_good_section, 0); + ok(res == 0, "Expected 0, got %d\n", res); + res = RegOpenKeyA(HKEY_CLASSES_ROOT, "selfreg_test", &key); + todo_wine ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res); + + res = pLaunchINFSection(NULL, NULL, install_at_good_section, 0); + ok(res == 0, "Expected 0, got %d\n", res); + res = RegOpenKeyA(HKEY_CLASSES_ROOT, "selfreg_test", &key); + todo_wine ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res); + + hook = SetWindowsHookExW(WH_CBT, hide_window_hook, NULL, GetCurrentThreadId()); + res = pLaunchINFSection(NULL, NULL, install_bad_section, 0); + ok(res == 1, "Expected 1, got %d\n", res); + UnhookWindowsHookEx(hook); + + res = pLaunchINFSection(NULL, NULL, install_at_bad_section, 0); + ok(res == 0, "Expected 0, got %d\n", res); + + DeleteFileA("winetest_selfreg.ocx"); + DeleteFileA("test.inf"); +} + START_TEST(install) { DWORD len; @@ -289,6 +382,7 @@ START_TEST(install) test_RunSetupCommand(); test_LaunchINFSection(); test_LaunchINFSectionEx(); + test_RegisterOCXs();
FreeLibrary(hAdvPack); SetCurrentDirectoryA(prev_path); diff --git a/dlls/advpack/tests/selfreg.c b/dlls/advpack/tests/selfreg.c new file mode 100644 index 00000000000..2f5e6f48ef1 --- /dev/null +++ b/dlls/advpack/tests/selfreg.c @@ -0,0 +1,42 @@ +/* + * DLL for testing self-registration + * + * Copyright 2018 Zebediah Figura + * + * 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 + */ + +#if 0 +#pragma makedep testdll +#endif + +#include <stdarg.h> +#include <windef.h> +#include <winbase.h> +#include <winreg.h> + +HRESULT WINAPI DllRegisterServer(void) +{ + HKEY key; + RegCreateKeyA(HKEY_CLASSES_ROOT, "selfreg_test", &key); + RegCloseKey(key); + return S_OK; +} + +HRESULT WINAPI DllUnregisterServer(void) +{ + RegDeleteKeyA(HKEY_CLASSES_ROOT, "selfreg_test"); + return S_OK; +} diff --git a/dlls/advpack/tests/selfreg.spec b/dlls/advpack/tests/selfreg.spec new file mode 100644 index 00000000000..0f9b07355f7 --- /dev/null +++ b/dlls/advpack/tests/selfreg.spec @@ -0,0 +1,2 @@ +@ stdcall -private DllRegisterServer() +@ stdcall -private DllUnregisterServer()
On Mon Sep 29 20:47:34 2025 +0000, Alexandre Julliard wrote:
A more convincing test would be to use a proper OCX and check whether it gets registered.
I have now added a test that shows that DllRegisterServer is called if the OCX file exists, but it is not called if `@` is prepended to the OCX's filename.