mirror of
https://github.com/reactos/wine.git
synced 2024-11-25 12:49:45 +00:00
ole32: Add ManualResetEvent implementation.
This commit is contained in:
parent
66db40e891
commit
a0980b47c8
@ -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.
|
||||
*/
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user