ole32: Add ManualResetEvent implementation.

This commit is contained in:
David Hedberg 2011-05-30 12:45:31 +02:00 committed by Alexandre Julliard
parent 66db40e891
commit a0980b47c8
2 changed files with 177 additions and 0 deletions

View File

@ -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.
*/

View File

@ -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();