⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 driverentry.cpp

📁 The PCI Local bus concept was developed to break the PC data I/O bottleneck and clearly opens the d
💻 CPP
📖 第 1 页 / 共 2 页
字号:

/*

Function name:

	AllowRequests

Routine Description:

	Begin accepting new requests to the queue.

Arguments:

	pdq -  Address of queue object

Return Value:

*/
VOID AllowRequests(PDEVQUEUE pdq)
{
	KdPrint(("SIWDM - AllowRequests\n"));

	pdq->abortstatus = STATUS_SUCCESS;
}

/*

Function name:

	AreRequestsBeingAborted

Routine Description:

	Determine if new requests to the queue are being rejected.

Arguments:

	pdq -  Address of queue object

Return Value:

	STATUS_SUCCESS  if successful
	ntStatus code otherwise.

*/
NTSTATUS AreRequestsBeingAborted(PDEVQUEUE pdq)
{
	KdPrint(("SIWDM - AreRequestsBeingAborted\n"));

	return pdq->abortstatus;
}

/*

Function name:

	CancelRequests

Routine Description:

	Handles cancellation of an Irp.  Should be called from a cancel routine while
	still owning the spin lock.

Arguments:

	pdq -  Address of queue object

	Irp - that is being cancelled

Return Value:

*/
VOID CancelRequest(PDEVQUEUE pdq, PIRP Irp)
{
	KIRQL oldirql = Irp->CancelIrql;

	KdPrint(("SIWDM - Entering CancelRequests\n"));

	IoReleaseCancelSpinLock(DISPATCH_LEVEL);
	KeAcquireSpinLockAtDpcLevel(&pdq->lock);
	RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
	KeReleaseSpinLock(&pdq->lock, oldirql);

	Irp->IoStatus.Status = STATUS_CANCELLED;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);

	KdPrint(("SIWDM - Exiting CancelRequests\n"));
}

/*

Function name:

	CheckBusyAndStall

Routine Description:

	Stalls the queue if no Irps are being processed.

Arguments:

	pdq -  Address of queue object

Return Value:

	TRUE if queue busy.
	FALSE if queue empty.
*/
BOOLEAN CheckBusyAndStall(PDEVQUEUE pdq)
{
	KIRQL oldirql;

	KdPrint(("SIWDM - Entering CheckBusyAndStall\n"));

	KeAcquireSpinLock(&pdq->lock, &oldirql);
	BOOLEAN busy = pdq->CurrentIrp != NULL;

	if (!busy)
		InterlockedIncrement(&pdq->stallcount);

	KeReleaseSpinLock(&pdq->lock, oldirql);

	KdPrint(("SIWDM - Exiting CheckBusyAndStall\n"));

	return busy;
}

/*

Function name:

	CleanupRequests

Routine Description:

	Completes the requests for a given file object.

Arguments:

	pdq -  Address of queue object

	fop - Pointer to the file object, NULL completes all requests on the queue.

	ntStatus - Status to which complete requests

Return Value:

*/
VOID CleanupRequests(PDEVQUEUE pdq, PFILE_OBJECT fop, NTSTATUS status)
{
	LIST_ENTRY cancellist;
	KIRQL oldirql;
	PLIST_ENTRY first = &pdq->head;
	PLIST_ENTRY next;

	KdPrint(("SIWDM - Entering CleanupRequests\n"));

	InitializeListHead(&cancellist);
	KeAcquireSpinLock(&pdq->lock, &oldirql);

	for(next=first->Flink;next!=first; )
	{
		PIRP Irp = CONTAINING_RECORD(next, IRP, Tail.Overlay.ListEntry);
		PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
		PLIST_ENTRY current = next;

		next = next->Flink;

		if(fop && stack->FileObject != fop)
			continue;

		if(!IoSetCancelRoutine(Irp, NULL))
			continue;
		RemoveEntryList(current);
		InsertTailList(&cancellist, current);
	}

	KeReleaseSpinLock(&pdq->lock, oldirql);

	while(!IsListEmpty(&cancellist))
	{
		next = RemoveHeadList(&cancellist);
		PIRP Irp = CONTAINING_RECORD(next, IRP, Tail.Overlay.ListEntry);
		Irp->IoStatus.Status = status;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
	}

	KdPrint(("SIWDM - Exiting CleanupRequests\n"));
}

/*

Function name:

	GetCurrentIrp

Routine Description:

	Determines the current Irp for the queue

Arguments:

	pdq -  Address of queue object

Return Value:

	A pointer to an Irp

*/
PIRP GetCurrentIrp(PDEVQUEUE pdq)
{
	KdPrint(("SIWDM - GetCurrentIrp\n"));

	return pdq->CurrentIrp;
}

/*

Function name:

	InitializeQueue

Routine Description:

	Initializes the queue and sets the StartIo routine.

Arguments:

	pdq -  Address of queue object

	StartIo - Addres of the StartIo routine

Return Value:

*/
VOID InitializeQueue(PDEVQUEUE pdq, PDRIVER_STARTIO StartIo)
{
	KdPrint(("SIWDM - Entering InitializeQueue\n"));

	InitializeListHead(&pdq->head);
	KeInitializeSpinLock(&pdq->lock);
	pdq->StartIo = StartIo;
	pdq->stallcount = 1;
	pdq->CurrentIrp = NULL;
	KeInitializeEvent(&pdq->evStop, NotificationEvent, FALSE);
	pdq->abortstatus = (NTSTATUS) 0;
	pdq->notify = NULL;
	pdq->notifycontext = 0;

	KdPrint(("SIWDM - Exiting InitializeQueue\n"));
}

/*

Function name:

	RestartRequests

Routine Description:

	Restarts a stalled queue.

Arguments:

	pdq -  Address of queue object

	fdo - Address of the device object

Return Value:

*/
VOID RestartRequests(PDEVQUEUE pdq, PDEVICE_OBJECT fdo)
{
	KdPrint(("SIWDM - Entering RestartRequests\n"));

	if(InterlockedDecrement(&pdq->stallcount) > 0)
		return;

	StartNextPacket(pdq, fdo);

	KdPrint(("SIWDM - Exiting RestartRequests\n"));
}

/*

Function name:

	StallRequests

Routine Description:

	Stalls requests in the queue.

Arguments:

	pdq -  Address of queue object

Return Value:

*/
VOID StallRequests(PDEVQUEUE pdq)
{
	KdPrint(("SIWDM - StallRequests\n"));

	InterlockedIncrement(&pdq->stallcount);
}

/*

Function name:

	StallRequestsAndNotify

Routine Description:

	Stalls requests in the queue and notifies when current Irp is complete.

Arguments:

	pdq -  Address of queue object

	notify - Address of the notify function.

	context - arguement passed to notify function.

Return Value:

	STATUS_SUCCESS if stalled
	STATUS_PENDING if waiting for IRP to complete
	STATUS_INVALID_DEVICE_REQUEST if call already pending for queue

*/
NTSTATUS StallRequestsAndNotify(PDEVQUEUE pdq, PQNOTIFYFUNC notify, PVOID context)
{
	NTSTATUS ntStatus;
	KIRQL oldirql;

	KdPrint(("SIWDM - Entering StallRequestsAndNotify\n"));

	KeAcquireSpinLock(&pdq->lock, &oldirql);

	if(pdq->notify)
		ntStatus = STATUS_INVALID_DEVICE_REQUEST;
	else
	{
		InterlockedIncrement(&pdq->stallcount);

		if(pdq->CurrentIrp)
		{
			pdq->notify = notify;
			pdq->notifycontext = context;
			ntStatus = STATUS_PENDING;
		}
		else
			ntStatus = STATUS_SUCCESS;
	}

	KeReleaseSpinLock(&pdq->lock, oldirql);

	KdPrint(("SIWDM - Exiting StallRequestsAndNotify\n"));

	return ntStatus;
}

/*

Function name:

	StartNextPacket

Routine Description:

	Starts the next packet in the queue.

Arguments:

	pdq -  Address of queue object

	fdo - Address of the device object

Return Value:

	Address of the Irp with which the device was busy.

*/
PIRP StartNextPacket(PDEVQUEUE pdq, PDEVICE_OBJECT fdo)
{
	KIRQL oldirql;

	KdPrint(("SIWDM - Entering StartNextPacket\n"));

	KeAcquireSpinLock(&pdq->lock, &oldirql);
	PIRP CurrentIrp = (PIRP) InterlockedExchangePointer(&pdq->CurrentIrp, NULL);

	if(CurrentIrp)
		KeSetEvent(&pdq->evStop, 0, FALSE);

	PQNOTIFYFUNC notify = pdq->notify;
	PVOID notifycontext = pdq->notifycontext;
	pdq->notify = NULL;

	while(!pdq->stallcount && !pdq->abortstatus && !IsListEmpty(&pdq->head))
	{
		PLIST_ENTRY next = RemoveHeadList(&pdq->head);
		PIRP Irp = CONTAINING_RECORD(next, IRP, Tail.Overlay.ListEntry);

		if(!IoSetCancelRoutine(Irp, NULL))
		{
			InitializeListHead(&Irp->Tail.Overlay.ListEntry);
			continue;
		}

		pdq->CurrentIrp = Irp;
		KeReleaseSpinLockFromDpcLevel(&pdq->lock);
		(*pdq->StartIo)(fdo, Irp);
		KeLowerIrql(oldirql);

		return CurrentIrp;
	}

	KeReleaseSpinLock(&pdq->lock, oldirql);

	if(notify)
		(*notify)(notifycontext);

	KdPrint(("SIWDM - Exiting StartNextPacket\n"));

	return CurrentIrp;
}

/*

Function name:

	StartPacket

Routine Description:

	Sends the Irp to the StartIo routine or places the Irp in the queue.

Arguments:

	pdq -  Address of queue object

	fdo - Address of the device object

	Irp - Irp that starts the queue or is being placed in the queue.

	cancel - Cancel routine for active Irps

Return Value:

*/
VOID StartPacket(PDEVQUEUE pdq, PDEVICE_OBJECT fdo, PIRP Irp, PDRIVER_CANCEL cancel)
{
	KIRQL oldirql;
	KeAcquireSpinLock(&pdq->lock, &oldirql);
	NTSTATUS abortstatus = pdq->abortstatus;

	KdPrint(("SIWDM - Entering StartPacket\n"));

	if(abortstatus)
	{
		KeReleaseSpinLock(&pdq->lock, oldirql);
		Irp->IoStatus.Status = abortstatus;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
	}
	else if(pdq->CurrentIrp || pdq->stallcount)
	{
		IoSetCancelRoutine(Irp, cancel);

		if(Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
		{
			KeReleaseSpinLock(&pdq->lock, oldirql);
			Irp->IoStatus.Status = STATUS_CANCELLED;
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
		}
		else
		{
			InsertTailList(&pdq->head, &Irp->Tail.Overlay.ListEntry);
			KeReleaseSpinLock(&pdq->lock, oldirql);
		}
	}
	else
	{
		pdq->CurrentIrp = Irp;
		KeReleaseSpinLock(&pdq->lock, DISPATCH_LEVEL);
		(*pdq->StartIo)(fdo, Irp);
		KeLowerIrql(oldirql);
	}

	KdPrint(("SIWDM - Exiting StartPacket\n"));
}

/*

Function name:

	WaitForCurrentIrp

Routine Description:

	Waits for the current Irp to finish.

Arguments:

	pdq -  Address of queue object

Return Value:

*/
VOID WaitForCurrentIrp(PDEVQUEUE pdq)
{
	KdPrint(("SIWDM - Entering WaitForCurrentIrp\n"));

	KeClearEvent(&pdq->evStop);
	
	KIRQL oldirql;
	KeAcquireSpinLock(&pdq->lock, &oldirql);
	BOOLEAN mustwait = pdq->CurrentIrp != NULL;
	KeReleaseSpinLock(&pdq->lock, oldirql);

	if(mustwait)
		KeWaitForSingleObject(&pdq->evStop, Executive, KernelMode, FALSE, NULL);

	KdPrint(("SIWDM - Exiting WaitForCurrentIrp\n"));
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -