mirror of
https://github.com/reactos/reactos.git
synced 2025-03-10 10:14:44 +00:00

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
297 lines
5.5 KiB
C++
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
|