reactos/sdk/lib/drivers/wdf/shared/inc/private/common/fxirpqueue.hpp
Victor Perevertkin 1f377076d7
[WDF] Fix KMDF so it can compile with ReactOS SDK
Not all files are included, but these are necessary to compile cdrom driver.
So far it can only be statically linked with drivers, a proper
implementation requires wdfldr helper driver
2020-11-03 00:06:27 +03:00

297 lines
5.5 KiB
C++

/*++
Copyright (c) Microsoft Corporation
Module Name:
FxIrpQueue.hpp
Abstract:
This module implements a common queue structure for the
driver frameworks built around the Cancel Safe Queues pattern
Author:
Environment:
Both kernel and user mode
Revision History:
--*/
#ifndef _FXIRPQUEUE_H_
#define _FXIRPQUEUE_H_
#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
#include "fxirpkm.hpp"
#else
#include "fxirpum.hpp"
#endif
//
// IRP DriverContext[] entry used.
//
// We use the same entry that the CSQ package does
// which is OK since we can't use CSQ if we implement the
// cancel handler ourselves
//
#define FX_IRP_QUEUE_CSQ_CONTEXT_ENTRY 3
//
// FxIrpQueue entry identifier
//
#define FX_IRP_QUEUE_ENTRY_IDENTIFIER 1
#if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE))
#include "fxirpkm.hpp"
#elif ((FX_CORE_MODE)==(FX_CORE_USER_MODE))
#include "fxirpum.hpp"
#endif
//
// This is the cancel function callback for the IrpQueue to its caller/parent
// This is called holding the lock of the object owning the IrpQueue, and it
// is responsible for completing the IRP.
//
extern "C" {
__drv_functionClass(EVT_IRP_QUEUE_CANCEL)
__drv_requiresIRQL(DISPATCH_LEVEL)
typedef
VOID
EVT_IRP_QUEUE_CANCEL (
__in FxIrpQueue* Queue,
__in MdIrp Irp,
__in PMdIoCsqIrpContext pCsqContext,
__in KIRQL CallerIrql
);
typedef EVT_IRP_QUEUE_CANCEL *PFN_IRP_QUEUE_CANCEL;
}
class FxIrpQueue {
friend VOID GetTriageInfo(VOID);
private:
//
// The Queue
//
LIST_ENTRY m_Queue;
//
// The object whose lock controls the queue.
// Provided by the client object.
//
FxNonPagedObject* m_LockObject;
//
// Callers registered cancel callback
//
PFN_IRP_QUEUE_CANCEL m_CancelCallback;
//
// Count of requests in the Queue
//
LONG m_RequestCount;
public:
FxIrpQueue(
VOID
);
~FxIrpQueue(
VOID
);
VOID
Initialize(
__in FxNonPagedObject* LockObject,
__in PFN_IRP_QUEUE_CANCEL Callback
);
_Must_inspect_result_
NTSTATUS
InsertTailRequest(
__inout MdIrp Irp,
__in_opt PMdIoCsqIrpContext CsqContext,
__out_opt ULONG* pRequestCount
);
_Must_inspect_result_
NTSTATUS
InsertHeadRequest(
__inout MdIrp Irp,
__in_opt PMdIoCsqIrpContext CsqContext,
__out_opt ULONG* pRequestCount
);
MdIrp
GetNextRequest(
__out PMdIoCsqIrpContext* pCsqContext
);
_Must_inspect_result_
NTSTATUS
GetNextRequest(
__in_opt PMdIoCsqIrpContext TagContext,
__in_opt MdFileObject FileObject,
__out FxRequest** ppOutRequest
);
_Must_inspect_result_
NTSTATUS
PeekRequest(
__in_opt PMdIoCsqIrpContext TagContext,
__in_opt MdFileObject FileObject,
__out FxRequest** ppOutRequest
);
MdIrp
RemoveRequest(
__in PMdIoCsqIrpContext Context
);
//
// Return whether the queue is empty
// (for optimizing the non-pending case in the caller)
//
inline
BOOLEAN
IsQueueEmpty() {
if( IsListEmpty(&m_Queue) ) {
ASSERT(m_RequestCount == 0);
return TRUE;
}
else {
ASSERT(m_RequestCount != 0);
return FALSE;
}
}
//
// Return count of queued and driver pending requests.
//
inline
LONG
GetRequestCount() {
return m_RequestCount;
}
BOOLEAN
IsIrpInQueue(
__in PMdIoCsqIrpContext Context
);
private:
//
// Insert an IRP on the cancel list
//
_Must_inspect_result_
NTSTATUS
InsertIrpInQueue(
__inout MdIrp Irp,
__in_opt PMdIoCsqIrpContext Context,
__in BOOLEAN InsertInHead,
__out_opt ULONG* pRequestCount
);
// Do not specify argument names
FX_DECLARE_VF_FUNCTION_P1(
VOID,
VerifyRemoveIrpFromQueueByContext,
__in PMdIoCsqIrpContext
);
//
// Ask to remove an IRP from the cancel list by Context,
// and return NULL if its been cancelled
//
MdIrp
RemoveIrpFromQueueByContext(
__in PMdIoCsqIrpContext Context
);
//
// Remove a request from the head of the queue if PeekContext == NULL,
// or the next request after PeekContext if != NULL
//
MdIrp
RemoveNextIrpFromQueue(
__in_opt PVOID PeekContext,
__out_opt PMdIoCsqIrpContext* pCsqContext
);
//
// Peek an IRP in the queue
//
MdIrp
PeekNextIrpFromQueue(
__in_opt MdIrp Irp,
__in_opt PVOID PeekContext
);
//
// Unconditionally remove the IRP from the list entry
//
inline
VOID
RemoveIrpFromListEntry(
__inout FxIrp* Irp
)
{
PLIST_ENTRY entry = Irp->ListEntry();
RemoveEntryList(entry);
InitializeListHead(entry);
m_RequestCount--;
ASSERT(m_RequestCount >= 0);
}
//
// WDM IRP cancel function
//
static
MdCancelRoutineType
_WdmCancelRoutineInternal;
//
// Lock functions accessed from WDM cancel callback
//
__inline
void
LockFromCancel(
__out PKIRQL PreviousIrql
)
{
m_LockObject->Lock(PreviousIrql);
}
__inline
void
UnlockFromCancel(
__in KIRQL PreviousIrql
)
{
m_LockObject->Unlock(PreviousIrql);
}
};
#endif // _FXIRPQUEUE_H