wine-wine/dlls/rtworkq/queue.c

220 lines
5.5 KiB
C
Raw Normal View History

/*
* Copyright 2019-2020 Nikolay Sivov for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#define NONAMELESSUNION
#include "initguid.h"
#include "rtworkq.h"
#include "wine/debug.h"
#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
static LONG platform_lock;
struct async_result
{
RTWQASYNCRESULT result;
LONG refcount;
IUnknown *object;
IUnknown *state;
};
static struct async_result *impl_from_IRtwqAsyncResult(IRtwqAsyncResult *iface)
{
return CONTAINING_RECORD(iface, struct async_result, result.AsyncResult);
}
static HRESULT WINAPI async_result_QueryInterface(IRtwqAsyncResult *iface, REFIID riid, void **obj)
{
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IRtwqAsyncResult) ||
IsEqualIID(riid, &IID_IUnknown))
{
*obj = iface;
IRtwqAsyncResult_AddRef(iface);
return S_OK;
}
*obj = NULL;
WARN("Unsupported interface %s.\n", debugstr_guid(riid));
return E_NOINTERFACE;
}
static ULONG WINAPI async_result_AddRef(IRtwqAsyncResult *iface)
{
struct async_result *result = impl_from_IRtwqAsyncResult(iface);
ULONG refcount = InterlockedIncrement(&result->refcount);
TRACE("%p, %u.\n", iface, refcount);
return refcount;
}
static ULONG WINAPI async_result_Release(IRtwqAsyncResult *iface)
{
struct async_result *result = impl_from_IRtwqAsyncResult(iface);
ULONG refcount = InterlockedDecrement(&result->refcount);
TRACE("%p, %u.\n", iface, refcount);
if (!refcount)
{
if (result->result.pCallback)
IRtwqAsyncCallback_Release(result->result.pCallback);
if (result->object)
IUnknown_Release(result->object);
if (result->state)
IUnknown_Release(result->state);
if (result->result.hEvent)
CloseHandle(result->result.hEvent);
heap_free(result);
RtwqUnlockPlatform();
}
return refcount;
}
static HRESULT WINAPI async_result_GetState(IRtwqAsyncResult *iface, IUnknown **state)
{
struct async_result *result = impl_from_IRtwqAsyncResult(iface);
TRACE("%p, %p.\n", iface, state);
if (!result->state)
return E_POINTER;
*state = result->state;
IUnknown_AddRef(*state);
return S_OK;
}
static HRESULT WINAPI async_result_GetStatus(IRtwqAsyncResult *iface)
{
struct async_result *result = impl_from_IRtwqAsyncResult(iface);
TRACE("%p.\n", iface);
return result->result.hrStatusResult;
}
static HRESULT WINAPI async_result_SetStatus(IRtwqAsyncResult *iface, HRESULT status)
{
struct async_result *result = impl_from_IRtwqAsyncResult(iface);
TRACE("%p, %#x.\n", iface, status);
result->result.hrStatusResult = status;
return S_OK;
}
static HRESULT WINAPI async_result_GetObject(IRtwqAsyncResult *iface, IUnknown **object)
{
struct async_result *result = impl_from_IRtwqAsyncResult(iface);
TRACE("%p, %p.\n", iface, object);
if (!result->object)
return E_POINTER;
*object = result->object;
IUnknown_AddRef(*object);
return S_OK;
}
static IUnknown * WINAPI async_result_GetStateNoAddRef(IRtwqAsyncResult *iface)
{
struct async_result *result = impl_from_IRtwqAsyncResult(iface);
TRACE("%p.\n", iface);
return result->state;
}
static const IRtwqAsyncResultVtbl async_result_vtbl =
{
async_result_QueryInterface,
async_result_AddRef,
async_result_Release,
async_result_GetState,
async_result_GetStatus,
async_result_SetStatus,
async_result_GetObject,
async_result_GetStateNoAddRef,
};
static HRESULT create_async_result(IUnknown *object, IRtwqAsyncCallback *callback, IUnknown *state, IRtwqAsyncResult **out)
{
struct async_result *result;
if (!out)
return E_INVALIDARG;
result = heap_alloc_zero(sizeof(*result));
if (!result)
return E_OUTOFMEMORY;
RtwqLockPlatform();
result->result.AsyncResult.lpVtbl = &async_result_vtbl;
result->refcount = 1;
result->object = object;
if (result->object)
IUnknown_AddRef(result->object);
result->result.pCallback = callback;
if (result->result.pCallback)
IRtwqAsyncCallback_AddRef(result->result.pCallback);
result->state = state;
if (result->state)
IUnknown_AddRef(result->state);
*out = &result->result.AsyncResult;
TRACE("Created async result object %p.\n", *out);
return S_OK;
}
HRESULT WINAPI RtwqCreateAsyncResult(IUnknown *object, IRtwqAsyncCallback *callback, IUnknown *state,
IRtwqAsyncResult **out)
{
TRACE("%p, %p, %p, %p.\n", object, callback, state, out);
return create_async_result(object, callback, state, out);
}
HRESULT WINAPI RtwqLockPlatform(void)
{
InterlockedIncrement(&platform_lock);
return S_OK;
}
HRESULT WINAPI RtwqUnlockPlatform(void)
{
InterlockedDecrement(&platform_lock);
return S_OK;
}