/*++

Copyright (c) 1992-1993  Microsoft Corporation

Module Name:

	irps.c

Abstract:


Author:

	Thomas Dimitri (tommyd) 08-May-1992

--*/

#include "asyncall.h"
#include "globals.h"

VOID
AsyncCancelQueued(
	PDEVICE_OBJECT	DeviceObject,
	PIRP			Irp)
{
	DbgTracef(0, ("RASHUB: IRP 0x%.8x is being cancelled.\n", Irp));

	// Mark this Irp as cancelled
	Irp->IoStatus.Status = STATUS_CANCELLED;
	Irp->IoStatus.Information = 0;

	// Take off our own list
	RemoveEntryList(&Irp->Tail.Overlay.ListEntry);

	// Release cancel spin lock which the IO system acquired??
	IoReleaseCancelSpinLock(Irp->CancelIrql);

	IoCompleteRequest(
		Irp,
		IO_NETWORK_INCREMENT);
}

VOID
AsyncCancelAllQueued(
	PLIST_ENTRY		QueueToCancel)
{
	KIRQL		oldIrql;
	PLIST_ENTRY	headOfList;
	PIRP		pIrp;

	//
	// We are pigs here using the global spin lock
	// but this is called so infrequently, we can
	// be pigs
	//
	IoAcquireCancelSpinLock(&oldIrql);

	//
	// Run through entire list until it is empty
	//
	for (;;) {

		if (IsListEmpty(QueueToCancel)) {
			break;
		}

		//
		// pick off the head of the list
		//
		headOfList = RemoveHeadList(QueueToCancel);

		pIrp = CONTAINING_RECORD(
				headOfList,
				IRP,
				Tail.Overlay.ListEntry);

		//
		// Disable the cancel routine
		//
		IoSetCancelRoutine(
			pIrp,
			NULL);

		//
		// Mark this irp as cancelled
		//
		pIrp->Cancel = TRUE;
		pIrp->IoStatus.Status = STATUS_CANCELLED;
		pIrp->IoStatus.Information = 0;

		//
		// We must release the spin lock before calling completing the irp
		//
		IoReleaseCancelSpinLock(oldIrql);

		DbgTracef(0, ("RASHUB: Cancelling a request\n"));

		IoCompleteRequest(
			pIrp,
			IO_NETWORK_INCREMENT);

		DbgTracef(0, ("RASHUB: Done cancelling a request\n"));

		//
		// Acquire it again before looking at the list
		//
		IoAcquireCancelSpinLock(&oldIrql);

	}

	IoReleaseCancelSpinLock(oldIrql);

}


VOID
AsyncQueueIrp(
	PLIST_ENTRY		Queue,
	PIRP			Irp)
{
	KIRQL		oldIrql;

	//
	// We are pigs here using the global spin lock
	//
	IoAcquireCancelSpinLock(&oldIrql);

	//
	// Mark the irp as pending and return from this ioctl
	//
	Irp->IoStatus.Status = STATUS_PENDING;
	IoMarkIrpPending(Irp);

	//
	// Queue up the irp at the end
	//
	InsertTailList(
		Queue,
		&Irp->Tail.Overlay.ListEntry);

	//
	// Set the cancel routine (also the purge routine)
	//
	IoSetCancelRoutine(
		Irp,
		AsyncCancelQueued);

	IoReleaseCancelSpinLock(oldIrql);

}


BOOLEAN
TryToCompleteDDCDIrp(
	PASYNC_INFO		pInfo)
	
/*++

Routine Description:


Arguments:


Return Value:


--*/

{

	KIRQL				oldIrql;
	PLIST_ENTRY			headOfList;
	PIRP				pIrp;

	IoAcquireCancelSpinLock(&oldIrql);

	if (IsListEmpty(&pInfo->DDCDQueue)) {
		IoReleaseCancelSpinLock(oldIrql);
		return((BOOLEAN)FALSE);
	}

	headOfList = RemoveHeadList(&pInfo->DDCDQueue);

	pIrp = CONTAINING_RECORD(
				headOfList,
				IRP,
				Tail.Overlay.ListEntry);

	IoSetCancelRoutine(
			pIrp,
			NULL);

	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;

	IoReleaseCancelSpinLock(oldIrql);

	IoCompleteRequest(
			pIrp,
			IO_NETWORK_INCREMENT);

	return((BOOLEAN)TRUE);

}