diff --git a/base/system/msiexec/msiexec.c b/base/system/msiexec/msiexec.c index 5ebfea78ebf..74f6d515b95 100644 --- a/base/system/msiexec/msiexec.c +++ b/base/system/msiexec/msiexec.c @@ -395,11 +395,30 @@ static DWORD DoUnregServer(void) extern UINT CDECL __wine_msi_call_dll_function(GUID *guid); +static DWORD CALLBACK custom_action_thread(void *arg) +{ + GUID *guid = arg; + return __wine_msi_call_dll_function(guid); +} + static int DoEmbedding(LPCWSTR key) { + HANDLE thread; GUID guid; + UINT r; + + /* We need this to unmarshal streams, and some apps expect it to be present. */ + CoInitializeEx(NULL, COINIT_MULTITHREADED); + CLSIDFromString(key, &guid); - return __wine_msi_call_dll_function(&guid); + thread = CreateThread(NULL, 0, custom_action_thread, &guid, 0, NULL); + WaitForSingleObject(thread, INFINITE); + GetExitCodeThread(thread, &r); + CloseHandle(thread); + + CoUninitialize(); + + return r; } /* diff --git a/dll/win32/msi/custom.c b/dll/win32/msi/custom.c index ffea24278d4..216a9bece8f 100644 --- a/dll/win32/msi/custom.c +++ b/dll/win32/msi/custom.c @@ -485,6 +485,43 @@ static void handle_msi_break(LPCSTR target) static WCHAR ncalrpcW[] = {'n','c','a','l','r','p','c',0}; static WCHAR endpoint_lrpcW[] = {'m','s','i',0}; +#if defined __i386__ && defined _MSC_VER +__declspec(naked) UINT custom_proc_wrapper(MsiCustomActionEntryPoint entry, MSIHANDLE hinst) +{ + __asm + { + push ebp + mov ebp, esp + sub esp, 4 + push [ebp+12] + call [ebp+8] + leave + ret + } +} +#elif defined __i386__ && defined __GNUC__ +/* wrapper for apps that don't declare the thread function correctly */ +extern UINT custom_proc_wrapper( MsiCustomActionEntryPoint entry, MSIHANDLE hinst ); +__ASM_GLOBAL_FUNC(custom_proc_wrapper, + "pushl %ebp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") + "movl %esp,%ebp\n\t" + __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") + "subl $4,%esp\n\t" + "pushl 12(%ebp)\n\t" + "call *8(%ebp)\n\t" + "leave\n\t" + __ASM_CFI(".cfi_def_cfa %esp,4\n\t") + __ASM_CFI(".cfi_same_value %ebp\n\t") + "ret" ) +#else +static UINT custom_proc_wrapper( MsiCustomActionEntryPoint entry, MSIHANDLE hinst ) +{ + return entry(hinst); +} +#endif + UINT CDECL __wine_msi_call_dll_function(const GUID *guid) { MsiCustomActionEntryPoint fn; @@ -495,7 +532,6 @@ UINT CDECL __wine_msi_call_dll_function(const GUID *guid) LPWSTR dll = NULL; LPSTR proc = NULL; HANDLE hModule; - HANDLE thread; INT type; UINT r; @@ -515,9 +551,6 @@ UINT CDECL __wine_msi_call_dll_function(const GUID *guid) } RpcStringFreeW(&binding_str); - /* We need this to unmarshal streams, and some apps expect it to be present. */ - CoInitializeEx(NULL, COINIT_MULTITHREADED); - r = remote_GetActionInfo(guid, &type, &dll, &proc, &remote_package); if (r != ERROR_SUCCESS) return r; @@ -540,9 +573,7 @@ UINT CDECL __wine_msi_call_dll_function(const GUID *guid) __TRY { - thread = CreateThread(NULL, 0, (void *)fn, (void *)(ULONG_PTR) hPackage, 0, NULL); - WaitForSingleObject(thread, INFINITE); - GetExitCodeThread(thread, &r); + r = custom_proc_wrapper(fn, hPackage); } __EXCEPT_PAGE_FAULT { @@ -566,8 +597,6 @@ UINT CDECL __wine_msi_call_dll_function(const GUID *guid) midl_user_free(dll); midl_user_free(proc); - CoUninitialize(); - RpcBindingFree(&rpc_handle); return r;