Thanks Tim,
I will try to reduce and explain the relevant code to a minimal.
I have a “DriverEntry.cpp” which includes “Driver.h”
Driver.h has the declararion of the Csamp functions and also the declaration of the DeviceExtention.
In AddDevice I do the init of the queue and the spin lock etc. See above code which I aleady posted.
The CsampXXX code is taken 1:1 from here:
https://github.com/microsoft/Windows-driver-samples/blob/main/general/cancel/sys/cancel.cpp
typedef struct _DEVICE_EXTENSION {
ULONG flags; // flags
LONG handles; // # open handles
PDEVICE_OBJECT DeviceObject; // device object this extension belongs to
PDEVICE_OBJECT LowerDeviceObject; // next lower driver in same stack
PDEVICE_OBJECT Pdo; // the PDO
PDRIVER_OBJECT DriverObject; // our own driver object
IO_REMOVE_LOCK RemoveLock; // removal control locking structure
UNICODE_STRING devname; // name of this device
DEVSTATE state; // current state of device
DEVSTATE prevstate; // state prior to removal query
DEVICE_POWER_STATE devpower; // current device power state
SYSTEM_POWER_STATE syspower; // current system power state
DEVICE_CAPABILITIES devcaps; // copy of most recent device capabilities
LIST_ENTRY PendingIrpQueue;
// SpinLock to protect access to the queue
KSPIN_LOCK QueueLock;
IO_CSQ CancelSafeQueue;
KSEMAPHORE IrpQueueSemaphore;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
…
VOID
CsampInsertIrp(
_In_ PIO_CSQ Csq,
_In_ PIRP Irp
);
VOID
CsampRemoveIrp(
_In_ PIO_CSQ Csq,
_In_ PIRP Irp
);
PIRP
CsampPeekNextIrp(
_In_ PIO_CSQ Csq,
_In_ PIRP Irp,
_In_ PVOID PeekContext
);
_IRQL_raises_(DISPATCH_LEVEL)
_IRQL_requires_max_(DISPATCH_LEVEL)
_Acquires_lock_(CONTAINING_RECORD(Csq, DEVICE_EXTENSION, CancelSafeQueue)->QueueLock)
VOID
CsampAcquireLock(
_In_ PIO_CSQ Csq,
_Out_ _At_(*Irql, _Post_ _IRQL_saves_) PKIRQL Irql
);
_IRQL_requires_(DISPATCH_LEVEL)
_Releases_lock_(CONTAINING_RECORD(Csq, DEVICE_EXTENSION, CancelSafeQueue)->QueueLock)
VOID
CsampReleaseLock(
_In_ PIO_CSQ Csq,
_In_ _IRQL_restores_ KIRQL Irql
);
VOID
CsampCompleteCanceledIrp(
_In_ PIO_CSQ pCsq,
_In_ PIRP Irp
);
In DriverEntry.cpp my functions look like this:
VOID CsampInsertIrp(
_In_ PIO_CSQ Csq,
_In_ PIRP Irp
)
{
PDEVICE_EXTENSION devExtension;
//BREAK_ONCE;
devExtension = CONTAINING_RECORD(Csq,
DEVICE_EXTENSION, CancelSafeQueue);
InsertTailList(&devExtension->PendingIrpQueue,
&Irp->Tail.Overlay.ListEntry);
}
VOID CsampRemoveIrp(
_In_ PIO_CSQ Csq,
_In_ PIRP Irp
)
{
UNREFERENCED_PARAMETER(Csq);
//BREAK_ONCE;
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
}
PIRP CsampPeekNextIrp(
_In_ PIO_CSQ Csq,
_In_ PIRP Irp,
_In_ PVOID PeekContext
)
{
PDEVICE_EXTENSION devExtension;
PIRP nextIrp = NULL;
PLIST_ENTRY nextEntry;
PLIST_ENTRY listHead;
PIO_STACK_LOCATION irpStack;
//BREAK_ONCE;
devExtension = CONTAINING_RECORD(Csq,
DEVICE_EXTENSION, CancelSafeQueue);
listHead = &devExtension->PendingIrpQueue;
//
// If the IRP is NULL, we will start peeking from the listhead, else
// we will start from that IRP onwards. This is done under the
// assumption that new IRPs are always inserted at the tail.
//
if (Irp == NULL) {
nextEntry = listHead->Flink;
}
else {
nextEntry = Irp->Tail.Overlay.ListEntry.Flink;
}
while (nextEntry != listHead) {
nextIrp = CONTAINING_RECORD(nextEntry, IRP, Tail.Overlay.ListEntry);
irpStack = IoGetCurrentIrpStackLocation(nextIrp);
//
// If context is present, continue until you find a matching one.
// Else you break out as you got next one.
//
if (PeekContext) {
if (irpStack->FileObject == (PFILE_OBJECT)PeekContext) {
break;
}
}
else {
break;
}
nextIrp = NULL;
nextEntry = nextEntry->Flink;
}
return nextIrp;
}
_IRQL_raises_(DISPATCH_LEVEL)
_IRQL_requires_max_(DISPATCH_LEVEL)
_Acquires_lock_(CONTAINING_RECORD(Csq, DEVICE_EXTENSION, CancelSafeQueue)->QueueLock)
VOID CsampAcquireLock(
_In_ PIO_CSQ Csq,
_Out_ _At_(*Irql, _Post_ _IRQL_saves_) PKIRQL Irql
)
{
PDEVICE_EXTENSION devExtension;
//BREAK_ONCE;
devExtension = CONTAINING_RECORD(Csq,
DEVICE_EXTENSION, CancelSafeQueue);
//
// Suppressing because the address below csq is valid since it's
// part of DEVICE_EXTENSION structure.
//
#pragma prefast(suppress: __WARNING_BUFFER_UNDERFLOW, "Underflow using expression 'devExtension->QueueLock'")
KeAcquireSpinLock(&devExtension->QueueLock, Irql);
}
//
// CsampReleaseLock modifies the execution level of the current processor.
//
// KeReleaseSpinLock assumes we already hold the spin lock and are therefore
// running at Dispatch level. It will use the Irql parameter saved in a
// previous call to KeAcquireSpinLock to return the thread back to it's original
// execution level.
//
// The annotations reflect these changes and requirments.
//
_IRQL_requires_(DISPATCH_LEVEL)
_Releases_lock_(CONTAINING_RECORD(Csq, DEVICE_EXTENSION, CancelSafeQueue)->QueueLock)
VOID CsampReleaseLock(
_In_ PIO_CSQ Csq,
_In_ _IRQL_restores_ KIRQL Irql
)
{
PDEVICE_EXTENSION devExtension;
//BREAK_ONCE;
devExtension = CONTAINING_RECORD(Csq,
DEVICE_EXTENSION, CancelSafeQueue);
//
// Suppressing because the address below csq is valid since it's
// part of DEVICE_EXTENSION structure.
//
#pragma prefast(suppress: __WARNING_BUFFER_UNDERFLOW, "Underflow using expression 'devExtension->QueueLock'")
KeReleaseSpinLock(&devExtension->QueueLock, Irql);
}
VOID CsampCompleteCanceledIrp(
_In_ PIO_CSQ pCsq,
_In_ PIRP Irp
)
{
UNREFERENCED_PARAMETER(pCsq);
//BREAK_ONCE;
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
In DriverEntry.cpp my PnpDispatch looks like this:
NTSTATUS DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{ // DispatchPnp
PAGED_CODE();
KOUT(("\nPnp*[%X] ",DeviceObject));
PCOMMON_EXTENSION pcx = (PCOMMON_EXTENSION) DeviceObject->DeviceExtension;
//DbgPrintEx(DPFLTR_IHVAUDIO_ID, 0, "%s %X %d\n", __FUNCTION__, pcx, pcx->flags);
if (pcx->flags & ISPDO)
return DispatchPnpPdo(DeviceObject, Irp);
else
return DispatchPnpFdo(DeviceObject, Irp);
}
Now from within the DispatchPnPFdo I get the call to HandleStartDevice, // IRP_MN_START_DEVICE
Here I pass my DeviceObject into my part of CODE where I hande the USB stuff: cusbcom
In cusbcom I hold a pointer to the DeviceObject from “DispatchPnp”.
I hope this will help enough to understand what I’m doing.
Regards,
K. Weller