reactos/sdk/lib/drivers/wdf/shared/inc/primitives/um/mxeventum.h

290 lines
4.9 KiB
C
Raw Normal View History

/*++
Copyright (c) Microsoft Corporation
ModuleName:
MxEventUm.h
Abstract:
User mode implementation of event
class defined in MxEvent.h
Author:
Revision History:
--*/
#pragma once
typedef struct {
HANDLE Event;
#if DBG
EVENT_TYPE Type; //tracked to allow ReadState only for notification events
#endif
} MdEvent;
#include "DbgMacros.h"
#include "MxEvent.h"
__inline
MxEvent::MxEvent()
{
CLEAR_DBGFLAG_INITIALIZED;
m_Event.Event = NULL;
}
__inline
MxEvent::~MxEvent()
{
//
// PLEASE NOTE: shared code must not rely of d'tor uninitializing the
// event. d'tor may not be invoked if the event is used in a structure
// which is allocated/deallocated using MxPoolAllocate/Free instead of
// new/delete
//
Uninitialize();
}
_Must_inspect_result_
__inline
NTSTATUS
MxEvent::Initialize(
__in EVENT_TYPE Type,
__in BOOLEAN InitialState
)
{
NTSTATUS status = STATUS_SUCCESS;
HANDLE event;
BOOL bManualReset;
if (NotificationEvent == Type)
{
bManualReset = TRUE;
}
else
{
bManualReset = FALSE;
}
event = CreateEvent(
NULL,
bManualReset,
InitialState ? TRUE : FALSE,
NULL
);
if (NULL == event) {
DWORD err = GetLastError();
status = WinErrorToNtStatus(err);
goto exit;
}
m_Event.Event = event;
#if DBG
m_Event.Type = Type;
#endif
SET_DBGFLAG_INITIALIZED;
exit:
return status;
}
__inline
PVOID
MxEvent::GetEvent(
)
{
ASSERT_DBGFLAG_INITIALIZED;
return m_Event.Event;
}
__inline
VOID
MxEvent::Set(
)
{
ASSERT_DBGFLAG_INITIALIZED;
SetEvent(m_Event.Event);
}
__inline
VOID
MxEvent::SetWithIncrement(
__in KPRIORITY Priority
)
{
UNREFERENCED_PARAMETER(Priority);
ASSERT_DBGFLAG_INITIALIZED;
Set();
}
__inline
VOID
MxEvent::Clear(
)
{
ASSERT_DBGFLAG_INITIALIZED;
ResetEvent(m_Event.Event);
}
__drv_when(Timeout != NULL, _Must_inspect_result_)
__inline
NTSTATUS
MxEvent::WaitFor(
__in KWAIT_REASON WaitReason,
__in KPROCESSOR_MODE WaitMode,
__in BOOLEAN Alertable,
__in_opt PLARGE_INTEGER Timeout
)
/*++
Routine Description:
Waits for the event
Arguments:
WaitReason - Unused (only there to match km definition)
WaitMode - Unuses (only there to match km definition)
Altertable - Whether the wait is alertable
Timout - Timeout in 100 ns units, MUST BE NEGATIVE
(negative implies relative timeout)
Return Value:
Status corresponding to return value of WaitForSingleObjectEx
--*/
{
ASSERT_DBGFLAG_INITIALIZED;
DWORD retVal;
UNREFERENCED_PARAMETER(WaitReason);
UNREFERENCED_PARAMETER(WaitMode);
LONGLONG relativeTimeOut = 0;
LONGLONG timeoutInMs = 0;
DWORD dwTimeout = 0;
if (NULL != Timeout)
{
//
// Make sure that timeout is 0 or -ve (which implies relative timeout)
//
if (Timeout->QuadPart > 0)
{
Mx::MxAssertMsg(
"Absolute wait not supported in user mode",
FALSE
);
return STATUS_INVALID_PARAMETER;
}
//
// Remove the -ve sign
//
if (Timeout->QuadPart < 0)
{
relativeTimeOut = -1 * Timeout->QuadPart;
}
//
// Convert from 100ns units to milliseconds
//
timeoutInMs = (relativeTimeOut / (10 * 1000));
if (timeoutInMs > ULONG_MAX)
{
Mx::MxAssertMsg("Timeout too large", FALSE);
return STATUS_INVALID_PARAMETER;
}
else
{
dwTimeout = (DWORD) timeoutInMs;
}
}
retVal = WaitForSingleObjectEx(
m_Event.Event,
(NULL == Timeout) ? INFINITE : dwTimeout,
Alertable
);
switch(retVal)
{
case WAIT_ABANDONED:
return STATUS_ABANDONED;
case WAIT_OBJECT_0:
return STATUS_SUCCESS;
case WAIT_TIMEOUT:
return STATUS_TIMEOUT;
case WAIT_FAILED:
{
DWORD err = GetLastError();
return WinErrorToNtStatus(err);
}
default:
{
//
// We shoudn't get here
//
Mx::MxAssert(FALSE);
return STATUS_UNSUCCESSFUL;
}
}
}
LONG
__inline
MxEvent::ReadState(
)
{
ASSERT_DBGFLAG_INITIALIZED;
#if DBG
Mx::MxAssert(m_Event.Type == NotificationEvent);
#endif
if (WAIT_OBJECT_0 == WaitForSingleObject(
m_Event.Event,
0
)) {
return 1;
}
else {
return 0;
}
}
__inline
VOID
MxEvent::Uninitialize(
)
{
if (NULL != m_Event.Event) {
CloseHandle(m_Event.Event);
m_Event.Event = NULL;
}
CLEAR_DBGFLAG_INITIALIZED;
}