Module: wine Branch: master Commit: a0980b47c8840ae1952c3561923e02ca1ff3b376 URL: http://source.winehq.org/git/wine.git/?a=commit;h=a0980b47c8840ae1952c356192...
Author: David Hedberg dhedberg@codeweavers.com Date: Mon May 30 12:45:31 2011 +0200
ole32: Add ManualResetEvent implementation.
---
dlls/ole32/compobj.c | 113 ++++++++++++++++++++++++++++++++++++++++++++ dlls/ole32/tests/marshal.c | 64 +++++++++++++++++++++++++ 2 files changed, 177 insertions(+), 0 deletions(-)
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 0aa3aee..28e5da1 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -458,6 +458,116 @@ static void COM_RevokeAllClasses(const struct apartment *apt) LeaveCriticalSection( &csRegisteredClassList ); }
+/****************************************************************************** + * Implementation of the manual reset event object. (CLSID_ManualResetEvent) + */ + +typedef struct ManualResetEvent { + ISynchronize ISynchronize_iface; + LONG ref; + HANDLE event; +} MREImpl; + +static inline MREImpl *impl_from_ISynchronize(ISynchronize *iface) +{ + return CONTAINING_RECORD(iface, MREImpl, ISynchronize_iface); +} + +static HRESULT WINAPI ISynchronize_fnQueryInterface(ISynchronize *iface, REFIID riid, void **ppv) +{ + MREImpl *This = impl_from_ISynchronize(iface); + TRACE("%p (%s, %p)\n", This, debugstr_guid(riid), ppv); + + *ppv = NULL; + if(IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_ISynchronize)) + *ppv = This; + else + ERR("Unknown interface %s requested.\n", debugstr_guid(riid)); + + if(*ppv) + { + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG WINAPI ISynchronize_fnAddRef(ISynchronize *iface) +{ + MREImpl *This = impl_from_ISynchronize(iface); + LONG ref = InterlockedIncrement(&This->ref); + TRACE("%p - ref %d\n", This, ref); + + return ref; +} + +static ULONG WINAPI ISynchronize_fnRelease(ISynchronize *iface) +{ + MREImpl *This = impl_from_ISynchronize(iface); + LONG ref = InterlockedDecrement(&This->ref); + TRACE("%p - ref %d\n", This, ref); + + if(!ref) + { + CloseHandle(This->event); + HeapFree(GetProcessHeap(), 0, This); + } + + return ref; +} + +static HRESULT WINAPI ISynchronize_fnWait(ISynchronize *iface, DWORD dwFlags, DWORD dwMilliseconds) +{ + MREImpl *This = impl_from_ISynchronize(iface); + UINT index; + TRACE("%p (%08x, %08x)\n", This, dwFlags, dwMilliseconds); + return CoWaitForMultipleHandles(dwFlags, dwMilliseconds, 1, &This->event, &index); +} + +static HRESULT WINAPI ISynchronize_fnSignal(ISynchronize *iface) +{ + MREImpl *This = impl_from_ISynchronize(iface); + TRACE("%p\n", This); + SetEvent(This->event); + return S_OK; +} + +static HRESULT WINAPI ISynchronize_fnReset(ISynchronize *iface) +{ + MREImpl *This = impl_from_ISynchronize(iface); + TRACE("%p\n", This); + ResetEvent(This->event); + return S_OK; +} + +static ISynchronizeVtbl vt_ISynchronize = { + ISynchronize_fnQueryInterface, + ISynchronize_fnAddRef, + ISynchronize_fnRelease, + ISynchronize_fnWait, + ISynchronize_fnSignal, + ISynchronize_fnReset +}; + +static HRESULT ManualResetEvent_Construct(IUnknown *punkouter, REFIID iid, void **ppv) +{ + MREImpl *This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MREImpl)); + HRESULT hr; + + if(punkouter) + FIXME("Aggregation not implemented.\n"); + + This->ref = 1; + This->ISynchronize_iface.lpVtbl = &vt_ISynchronize; + This->event = CreateEventW(NULL, TRUE, FALSE, NULL); + + hr = ISynchronize_QueryInterface(&This->ISynchronize_iface, iid, ppv); + ISynchronize_Release(&This->ISynchronize_iface); + return hr; +} + /*********************************************************************** * CoRevokeClassObject [OLE32.@] * @@ -2510,6 +2620,9 @@ HRESULT WINAPI CoCreateInstance( return S_OK; }
+ if (IsEqualCLSID(rclsid, &CLSID_ManualResetEvent)) + return ManualResetEvent_Construct(pUnkOuter, iid, ppv); + /* * Get a class factory to construct the object we want. */ diff --git a/dlls/ole32/tests/marshal.c b/dlls/ole32/tests/marshal.c index 86a8f0f..87b2006 100644 --- a/dlls/ole32/tests/marshal.c +++ b/dlls/ole32/tests/marshal.c @@ -36,6 +36,7 @@ #include "wine/test.h"
DEFINE_GUID(CLSID_StdGlobalInterfaceTable,0x00000323,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46); +DEFINE_GUID(CLSID_ManualResetEvent, 0x0000032c,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
/* functions that are not present on all versions of Windows */ static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit); @@ -2836,6 +2837,68 @@ static void test_globalinterfacetable(void) IGlobalInterfaceTable_Release(git); }
+static void test_manualresetevent(void) +{ + ISynchronize *psync1, *psync2; + IUnknown *punk; + LONG ref; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&punk); + ok(hr == S_OK, "Got 0x%08x\n", hr); + ok(!!punk, "Got NULL.\n"); + IUnknown_Release(punk); + + hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_ISynchronize, (void**)&psync1); + ok(hr == S_OK, "Got 0x%08x\n", hr); + ok(!!psync1, "Got NULL.\n"); + + hr = ISynchronize_Wait(psync1, 0, 5); + ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr); + + hr = ISynchronize_Reset(psync1); + ok(hr == S_OK, "Got 0x%08x\n", hr); + hr = ISynchronize_Signal(psync1); + ok(hr == S_OK, "Got 0x%08x\n", hr); + hr = ISynchronize_Wait(psync1, 0, 5); + ok(hr == S_OK, "Got 0x%08x\n", hr); + hr = ISynchronize_Wait(psync1, 0, 5); + ok(hr == S_OK, "Got 0x%08x\n", hr); + hr = ISynchronize_Reset(psync1); + ok(hr == S_OK, "Got 0x%08x\n", hr); + hr = ISynchronize_Wait(psync1, 0, 5); + ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr); + + hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_ISynchronize, (void**)&psync2); + ok(hr == S_OK, "Got 0x%08x\n", hr); + ok(!!psync2, "Got NULL.\n"); + ok(psync1 != psync2, "psync1 == psync2.\n"); + hr = ISynchronize_Wait(psync2, 0, 5); + ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr); + + hr = ISynchronize_Reset(psync1); + ok(hr == S_OK, "Got 0x%08x\n", hr); + hr = ISynchronize_Reset(psync2); + ok(hr == S_OK, "Got 0x%08x\n", hr); + hr = ISynchronize_Signal(psync1); + ok(hr == S_OK, "Got 0x%08x\n", hr); + hr = ISynchronize_Wait(psync2, 0, 5); + ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr); + + ref = ISynchronize_AddRef(psync1); + ok(ref == 2, "Got ref: %d\n", ref); + ref = ISynchronize_AddRef(psync1); + ok(ref == 3, "Got ref: %d\n", ref); + ref = ISynchronize_Release(psync1); + ok(ref == 2, "Got nonzero ref: %d\n", ref); + ref = ISynchronize_Release(psync2); + ok(!ref, "Got nonzero ref: %d\n", ref); + ref = ISynchronize_Release(psync1); + ok(ref == 1, "Got nonzero ref: %d\n", ref); + ref = ISynchronize_Release(psync1); + ok(!ref, "Got nonzero ref: %d\n", ref); +} + static const char *debugstr_iid(REFIID riid) { static char name[256]; @@ -3120,6 +3183,7 @@ START_TEST(marshal) test_local_server();
test_globalinterfacetable(); + test_manualresetevent();
/* must be last test as channel hooks can't be unregistered */ test_channel_hook();