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