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 );
|
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.@]
|
* CoRevokeClassObject [OLE32.@]
|
||||||
*
|
*
|
||||||
@ -2510,6 +2620,9 @@ HRESULT WINAPI CoCreateInstance(
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsEqualCLSID(rclsid, &CLSID_ManualResetEvent))
|
||||||
|
return ManualResetEvent_Construct(pUnkOuter, iid, ppv);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get a class factory to construct the object we want.
|
* Get a class factory to construct the object we want.
|
||||||
*/
|
*/
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "wine/test.h"
|
#include "wine/test.h"
|
||||||
|
|
||||||
DEFINE_GUID(CLSID_StdGlobalInterfaceTable,0x00000323,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
|
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 */
|
/* functions that are not present on all versions of Windows */
|
||||||
static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
|
static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
|
||||||
@ -2836,6 +2837,68 @@ static void test_globalinterfacetable(void)
|
|||||||
IGlobalInterfaceTable_Release(git);
|
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 const char *debugstr_iid(REFIID riid)
|
||||||
{
|
{
|
||||||
static char name[256];
|
static char name[256];
|
||||||
@ -3120,6 +3183,7 @@ START_TEST(marshal)
|
|||||||
test_local_server();
|
test_local_server();
|
||||||
|
|
||||||
test_globalinterfacetable();
|
test_globalinterfacetable();
|
||||||
|
test_manualresetevent();
|
||||||
|
|
||||||
/* must be last test as channel hooks can't be unregistered */
|
/* must be last test as channel hooks can't be unregistered */
|
||||||
test_channel_hook();
|
test_channel_hook();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user