Commit 15a0b7fa authored by Rob Shearman's avatar Rob Shearman Committed by Alexandre Julliard

ole32: Don't keep the local server named pipe open for a single-use object.

parent 7ba4b816
...@@ -1622,6 +1622,7 @@ HRESULT WINAPI CoRegisterClassObject( ...@@ -1622,6 +1622,7 @@ HRESULT WINAPI CoRegisterClassObject(
hr = RPC_StartLocalServer(&newClass->classIdentifier, hr = RPC_StartLocalServer(&newClass->classIdentifier,
newClass->pMarshaledData, newClass->pMarshaledData,
flags & (REGCLS_MULTIPLEUSE|REGCLS_MULTI_SEPARATE),
&newClass->RpcRegistration); &newClass->RpcRegistration);
} }
return S_OK; return S_OK;
......
...@@ -221,7 +221,7 @@ HRESULT RPC_CreateServerChannel(IRpcChannelBuffer **chan); ...@@ -221,7 +221,7 @@ HRESULT RPC_CreateServerChannel(IRpcChannelBuffer **chan);
void RPC_ExecuteCall(struct dispatch_params *params); void RPC_ExecuteCall(struct dispatch_params *params);
HRESULT RPC_RegisterInterface(REFIID riid); HRESULT RPC_RegisterInterface(REFIID riid);
void RPC_UnregisterInterface(REFIID riid); void RPC_UnregisterInterface(REFIID riid);
HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, void **registration); HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, BOOL multi_use, void **registration);
void RPC_StopLocalServer(void *registration); void RPC_StopLocalServer(void *registration);
HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv); HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv);
HRESULT RPC_RegisterChannelHook(REFGUID rguid, IChannelHook *hook); HRESULT RPC_RegisterChannelHook(REFGUID rguid, IChannelHook *hook);
......
...@@ -1732,6 +1732,7 @@ struct local_server_params ...@@ -1732,6 +1732,7 @@ struct local_server_params
CLSID clsid; CLSID clsid;
IStream *stream; IStream *stream;
HANDLE ready_event; HANDLE ready_event;
BOOL multi_use;
HANDLE pipe; HANDLE pipe;
}; };
...@@ -1749,6 +1750,7 @@ static DWORD WINAPI local_server_thread(LPVOID param) ...@@ -1749,6 +1750,7 @@ static DWORD WINAPI local_server_thread(LPVOID param)
LARGE_INTEGER seekto; LARGE_INTEGER seekto;
ULARGE_INTEGER newpos; ULARGE_INTEGER newpos;
ULONG res; ULONG res;
BOOL multi_use = lsp->multi_use;
TRACE("Starting threader for %s.\n",debugstr_guid(&lsp->clsid)); TRACE("Starting threader for %s.\n",debugstr_guid(&lsp->clsid));
...@@ -1817,13 +1819,20 @@ static DWORD WINAPI local_server_thread(LPVOID param) ...@@ -1817,13 +1819,20 @@ static DWORD WINAPI local_server_thread(LPVOID param)
DisconnectNamedPipe(hPipe); DisconnectNamedPipe(hPipe);
TRACE("done marshalling IClassFactory\n"); TRACE("done marshalling IClassFactory\n");
if (!multi_use)
{
TRACE("single use object, shutting down pipe %s\n", debugstr_w(pipefn));
CloseHandle(hPipe);
break;
}
} }
IStream_Release(pStm); IStream_Release(pStm);
return 0; return 0;
} }
/* starts listening for a local server */ /* starts listening for a local server */
HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, void **registration) HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, BOOL multi_use, void **registration)
{ {
DWORD tid; DWORD tid;
HANDLE thread, ready_event; HANDLE thread, ready_event;
...@@ -1833,6 +1842,7 @@ HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, void **registratio ...@@ -1833,6 +1842,7 @@ HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, void **registratio
lsp->stream = stream; lsp->stream = stream;
IStream_AddRef(stream); IStream_AddRef(stream);
lsp->ready_event = ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); lsp->ready_event = ready_event = CreateEventW(NULL, FALSE, FALSE, NULL);
lsp->multi_use = multi_use;
thread = CreateThread(NULL, 0, local_server_thread, lsp, 0, &tid); thread = CreateThread(NULL, 0, local_server_thread, lsp, 0, &tid);
if (!thread) if (!thread)
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#define CONST_VTABLE #define CONST_VTABLE
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h>
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
...@@ -50,6 +51,14 @@ static const IID IID_IWineTest = ...@@ -50,6 +51,14 @@ static const IID IID_IWineTest =
#define EXTENTID_WineTest IID_IWineTest #define EXTENTID_WineTest IID_IWineTest
#define CLSID_WineTest IID_IWineTest #define CLSID_WineTest IID_IWineTest
static const CLSID CLSID_WineOOPTest =
{
0x5201163f,
0x8164,
0x4fd0,
{0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
}; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
static void test_cocreateinstance_proxy(void) static void test_cocreateinstance_proxy(void)
{ {
IUnknown *pProxy; IUnknown *pProxy;
...@@ -2152,6 +2161,11 @@ static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance( ...@@ -2152,6 +2161,11 @@ static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance(
REFIID riid, REFIID riid,
LPVOID *ppvObj) LPVOID *ppvObj)
{ {
if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown))
{
*ppvObj = iface;
return S_OK;
}
return CLASS_E_CLASSNOTAVAILABLE; return CLASS_E_CLASSNOTAVAILABLE;
} }
...@@ -2177,19 +2191,72 @@ static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl = ...@@ -2177,19 +2191,72 @@ static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl }; static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl };
static void test_register_local_server(void)
{
DWORD cookie;
HRESULT hr;
HANDLE ready_event;
HANDLE quit_event;
DWORD wait;
heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
ok_ole_success(hr, CoRegisterClassObject);
ready_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Ready Event");
SetEvent(ready_event);
quit_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
do
{
wait = MsgWaitForMultipleObjects(1, &quit_event, FALSE, INFINITE, QS_ALLINPUT);
if (wait == WAIT_OBJECT_0+1)
{
MSG msg;
BOOL ret = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
if (ret)
{
trace("Message 0x%x\n", msg.message);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
while (wait == WAIT_OBJECT_0+1);
hr = CoRevokeClassObject(cookie);
ok_ole_success(hr, CoRevokeClassObject);
}
static HANDLE create_target_process(const char *arg)
{
char **argv;
char cmdline[MAX_PATH];
PROCESS_INFORMATION pi;
STARTUPINFO si = { 0 };
si.cb = sizeof(si);
winetest_get_mainargs( &argv );
sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
ok(CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
&si, &pi) != 0, "error: %u\n", GetLastError());
ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError());
return pi.hProcess;
}
/* tests functions commonly used by out of process COM servers */ /* tests functions commonly used by out of process COM servers */
static void test_local_server(void) static void test_local_server(void)
{ {
static const CLSID CLSID_WineOOPTest = {
0x5201163f,
0x8164,
0x4fd0,
{0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
}; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
DWORD cookie; DWORD cookie;
HRESULT hr; HRESULT hr;
IClassFactory * cf; IClassFactory * cf;
DWORD ret; DWORD ret;
HANDLE process;
HANDLE quit_event;
HANDLE ready_event;
heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL); heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
...@@ -2249,6 +2316,28 @@ static void test_local_server(void) ...@@ -2249,6 +2316,28 @@ static void test_local_server(void)
ok_ole_success(hr, CoRevokeClassObject); ok_ole_success(hr, CoRevokeClassObject);
CloseHandle(heventShutdown); CloseHandle(heventShutdown);
process = create_target_process("-Embedding");
ok(process != NULL, "couldn't start local server process, error was %d\n", GetLastError());
ready_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Ready Event");
WaitForSingleObject(ready_event, 1000);
CloseHandle(ready_event);
hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IClassFactory, (void **)&cf);
ok_ole_success(hr, CoCreateInstance);
IClassFactory_Release(cf);
hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IClassFactory, (void **)&cf);
ok(hr == REGDB_E_CLASSNOTREG, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
quit_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
SetEvent(quit_event);
WaitForSingleObject(process, INFINITE);
CloseHandle(quit_event);
CloseHandle(process);
} }
struct git_params struct git_params
...@@ -2532,8 +2621,21 @@ START_TEST(marshal) ...@@ -2532,8 +2621,21 @@ START_TEST(marshal)
{ {
WNDCLASS wndclass; WNDCLASS wndclass;
HMODULE hOle32 = GetModuleHandle("ole32"); HMODULE hOle32 = GetModuleHandle("ole32");
int argc;
char **argv;
if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"))) goto no_test; if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"))) goto no_test;
argc = winetest_get_mainargs( &argv );
if (argc > 2 && (!strcmp(argv[2], "-Embedding")))
{
pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
test_register_local_server();
CoUninitialize();
return;
}
/* register a window class used in several tests */ /* register a window class used in several tests */
memset(&wndclass, 0, sizeof(wndclass)); memset(&wndclass, 0, sizeof(wndclass));
wndclass.lpfnWndProc = window_proc; wndclass.lpfnWndProc = window_proc;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment