David Hedberg : ole32: Add ManualResetEvent implementation.
Alexandre Julliard
julliard at winehq.org
Mon May 30 12:41:18 CDT 2011
Module: wine
Branch: master
Commit: a0980b47c8840ae1952c3561923e02ca1ff3b376
URL: http://source.winehq.org/git/wine.git/?a=commit;h=a0980b47c8840ae1952c3561923e02ca1ff3b376
Author: David Hedberg <dhedberg at 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();
More information about the wine-cvs
mailing list