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

📄 dispatch.c

📁 driver wdk
💻 C
字号:
//++
// File Name:
//		dispatch.c
//
// Contents:
//		Dispatch routines for parallel driver
//--

//
// Driver-specific header files
//
#include "Ave2k.h"
#include "channel2.h"
#include "AudioCtrl.h"
void StopVideo(PDEVICE_EXTENSION pDE);
ULONG SetOSD(PDEVICE_EXTENSION pDE, int nMode, unsigned char *pName, unsigned char *pHanLib);
//
// Forward declarations of local routines
//
// (None)

//
// If the compiler can handle it, save space
// by making various routines pageable
//    
#ifdef ALLOC_PRAGMA
#pragma alloc_text( page, Ave2kDispatchOpenClose )
#pragma alloc_text( page, Ave2kDispatchWrite )
#endif //ALLOC_PRAGMA

//++
// Function:
//		Ave2kDispatchOpenClose
//
// Description:
//		This function dispatches CreateFile and
//		CloseHandle requests from Win32
//
// Arguments:
//		Pointer to Device object
//		Pointer to IRP for this request
//
// Return Value:
//		This function returns STATUS_XXX
//--
#if _WIN32_WINNT==0x0400
NTSTATUS
Ave2kDispatchOpenClose(
	IN PDEVICE_OBJECT pDO,
	IN PIRP Irp
	)
{
	PDEVICE_EXTENSION pDE=(PDEVICE_EXTENSION)pDO->DeviceExtension;
	PIO_STACK_LOCATION IrpStack =
	   IoGetCurrentIrpStackLocation( Irp );

	Irp->IoStatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = 0;
	IoCompleteRequest( Irp, IO_NO_INCREMENT );

	if(IrpStack->MajorFunction == IRP_MJ_CLOSE){
		StopVideo(pDE);
		DisableAllDataChannel(pDE);
		if(pDE->ExtraFunctions&0x02)
			SetOSD(pDE, 0, NULL, NULL);
	}
	return STATUS_SUCCESS;
}
#else
NTSTATUS
Ave2kDispatchOpenClose(
	IN PDEVICE_OBJECT pDO,
	IN PIRP Irp
	)
{
  	NTSTATUS status=STATUS_SUCCESS;
	PDEVICE_EXTENSION pDE = (PDEVICE_EXTENSION)pDO->DeviceExtension;
	PIO_STACK_LOCATION IrpStack =
	IoGetCurrentIrpStackLocation( Irp );
	if(IrpStack->MajorFunction == IRP_MJ_CREATE)
	{
	 if(pDE->Occupyed==FALSE)
	 {
      pDE->Occupyed=TRUE; 	  
	  Irp->IoStatus.Status = STATUS_SUCCESS;
	  Irp->IoStatus.Information = 0;
	  status=STATUS_SUCCESS;
     }
	 else //only one application can access the device
	 {
      Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
	  Irp->IoStatus.Information = 0;
	  status=STATUS_UNSUCCESSFUL;
	 }
	}
	else
	{
	  pDE->Occupyed=FALSE;
	  Irp->IoStatus.Status = STATUS_SUCCESS;
	  Irp->IoStatus.Information = 0;
	  status=STATUS_SUCCESS;
	  StopVideo(pDE);
	  DisableAllDataChannel(pDE);
	  if(pDE->ExtraFunctions&0x02)
		SetOSD(pDE, 0, NULL, NULL);
     }
	IoCompleteRequest( Irp, IO_NO_INCREMENT );
	return status;
}
#endif

//++
// Function:
//		Ave2kDispatchWrite
//
// Description:
//		This function dispatches WriteFile
//		requests from Win32
//
// Arguments:
//		Pointer to Device object
//		Pointer to IRP for this request
//
// Return Value:
//		This function returns STATUS_XXX
//--
NTSTATUS 
Ave2kDispatchWrite(
	IN PDEVICE_OBJECT pDO,
	IN PIRP Irp
	)
{
	PIO_STACK_LOCATION IrpStack = 
				IoGetCurrentIrpStackLocation( Irp );

	//
	// Check for zero-length transfers
	//
		Irp->IoStatus.Status = STATUS_SUCCESS;
		Irp->IoStatus.Information = 0;
		IoCompleteRequest( Irp, IO_NO_INCREMENT );
		return STATUS_SUCCESS;
}

//++
// Function:
//		Ave2kDispatchRead
//
// Description:
//		This function dispatches ReadFile
//		requests from Win32
//
// Arguments:
//		Pointer to Device object
//		Pointer to IRP for this request
//
// Return Value:
//		This function returns STATUS_XXX
//--
NTSTATUS 
Ave2kDispatchRead(
	IN PDEVICE_OBJECT pDO,
	IN PIRP Irp
	)
{
	UCHAR Channel;
	KIRQL OldIrql;
	PDEVICE_EXTENSION pDE=(PDEVICE_EXTENSION)pDO->DeviceExtension;
	PIO_STACK_LOCATION IrpStack = 
				IoGetCurrentIrpStackLocation( Irp );
	ULONG BufLen;

	//
	// Check for zero-length transfers
	//
	if( IrpStack->Parameters.Read.Length == 0 ) {
		Irp->IoStatus.Status = STATUS_SUCCESS;
		Irp->IoStatus.Information = 0;
		IoCompleteRequest( Irp, IO_NO_INCREMENT );
		return STATUS_SUCCESS;
	}

	if( IrpStack->Parameters.Read.Length != 2324 &&
         IrpStack->Parameters.Read.Length != sizeof(AUDIOSTREAMSECTOR)){
		Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
		Irp->IoStatus.Information = 0;
		IoCompleteRequest( Irp, IO_NO_INCREMENT );
		return STATUS_SUCCESS;
	}
	
	Channel = *(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
	if(Channel != 0 &&
		Channel != 1)
	{
		Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
		Irp->IoStatus.Information = 0;
		IoCompleteRequest( Irp, IO_NO_INCREMENT );
		return STATUS_SUCCESS;
	}

	if(Channel == 0){
		KeAcquireSpinLock(&pDE->ReadLock, &OldIrql);
		ASSERT(pDE->ReadIrpDataBuffer==NULL);
#ifdef USING_DIRECT_IO
		pDE->ReadIrpDataBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
#else
		pDE->ReadIrpDataBuffer = pIrp->AssociatedIrp.SystemBuffer;  //Using buffered I/O
#endif
		IrpStack = IoGetCurrentIrpStackLocation( Irp );
		BufLen=IrpStack->Parameters.Read.Length;
		if(AudioDespListRead(pDE, BufLen, 0)){
			Irp->IoStatus.Status = STATUS_SUCCESS;
			Irp->IoStatus.Information = IrpStack->Parameters.Read.Length; //sizeof(AUDIOSTREAMSECTOR);
			IoCompleteRequest(Irp,IO_NO_INCREMENT);
			pDE->ReadIrpDataBuffer=NULL;
			KeReleaseSpinLock(&pDE->ReadLock, OldIrql);
			return STATUS_SUCCESS;
		}
		else{
			//Use standard device queue
			IoMarkIrpPending( Irp );
			IoStartPacket( pDO, Irp, 0, Ave2kCancelIrp);
			KeReleaseSpinLock(&pDE->ReadLock, OldIrql);
			ErrorRecover(pDE, 0);
		}
	}
	else{
		KeAcquireSpinLock(&pDE->ReadLock2, &OldIrql);
		ASSERT(pDE->CurrentAlternateIrpBuffer==NULL);
#ifdef USING_DIRECT_IO
		pDE->CurrentAlternateIrpBuffer=
		         MmGetSystemAddressForMdl(Irp->MdlAddress);
#else
		pDE->CurrentAlternateIrpBuffer=
	              Irp->AssociatedIrp.SystemBuffer;  //Using buffered I/O
#endif
		IrpStack = IoGetCurrentIrpStackLocation( Irp );
		BufLen=IrpStack->Parameters.Read.Length;
		if(AudioDespListRead(pDE, BufLen, 1))
		{
			Irp->IoStatus.Status = STATUS_SUCCESS;
			Irp->IoStatus.Information = IrpStack->Parameters.Read.Length; //sizeof(AUDIOSTREAMSECTOR);
			IoCompleteRequest(Irp,IO_NO_INCREMENT);
			pDE->CurrentAlternateIrpBuffer=NULL;
			KeReleaseSpinLock(&pDE->ReadLock2, OldIrql);
			return STATUS_SUCCESS;
		}
		else{
			IoMarkIrpPending(Irp);
			Ave2kChannel2StartPacket(pDO, Irp, Ave2kCancelChannel2Irp);
			KeReleaseSpinLock(&pDE->ReadLock2, OldIrql);
			ErrorRecover(pDE, 1);
		}
	}
	return STATUS_PENDING;
}


//++
// Function:
//		Ave2kCleanupDeviceQueue
//
// Description:
//		This function removes any IRPs associated
//		with a given File object from a specific
//		Device Queue. It then cancels these IRPs.
//
//		This function is called from PASSIVE_LEVEL
//		but it spends time at DISPATCH_LEVEL while
//		it holds the Cancel spin lock.
//
// Arguments:
//		Pointer to Device Queue object
//		Pointer to File object
//
// Return Value:
//		(None)
//--
static VOID
Ave2kCleanupDeviceQueue(
	IN PKDEVICE_QUEUE DeviceQueue,
	IN PFILE_OBJECT FileObject
	)
{
	KIRQL OldIrql;
	PIRP CancelIrp;
	PIRP RequeueIrp;
 
	PIO_STACK_LOCATION CancelIrpStack;

	LIST_ENTRY CancelList;
	LIST_ENTRY RequeueList;
	PLIST_ENTRY ListHead;
	PKDEVICE_QUEUE_ENTRY QueueEntry;
	
	//
	// Prepare the two work lists
	//
	InitializeListHead( &CancelList );
	InitializeListHead( &RequeueList );

	//
	// This work must be done under the protection
	// of the Cancel spin lock...
	//
	IoAcquireCancelSpinLock( &OldIrql );

	//
	// See if there's actually any work
	// to do. If not, quit right now.
	//
	if( IsListEmpty( &DeviceQueue->DeviceListHead ))
	{
		IoReleaseCancelSpinLock( OldIrql );
		return;
	}

	//
	// Loop until every IRP has been removed from
	// the Device Queue. Decide whether each one
	// should be canceled or not. (At the end of
	// this loop, the Device Queue will have been
	// emptied; hence its state will be Not Busy.)
	//
	while(( QueueEntry = 
				KeRemoveDeviceQueue(
							DeviceQueue ))
									!= NULL )
	{
		CancelIrp = 
			CONTAINING_RECORD(
				QueueEntry,
				IRP,
				Tail.Overlay.DeviceQueueEntry );

		KdPrint(( "\tRemoving IRP %8x from Device Queue\n", CancelIrp ));

		CancelIrpStack = 
			IoGetCurrentIrpStackLocation( CancelIrp );

		//
		// If the IRP's File object is the same as
		// the one in the IRP_MJ_CLEANUP IRP, set 
		// the IRP's CancelXxx fields and put the 
		// IRP in a holding queue of IRPs to be 
		// completed.
		//
		if( CancelIrpStack->FileObject == FileObject )
		{
			CancelIrp->Cancel		 = TRUE;
			CancelIrp->CancelIrql	 = OldIrql;
			CancelIrp->CancelRoutine = NULL;

			KdPrint(( "\tAdding IRP %8x to CancelList\n", CancelIrp ));

			InsertTailList(
				&CancelList,
				&CancelIrp->Tail.Overlay.ListEntry );
		}

		//
		// Else, put it in a holding queue of IRP's
		// to be requeued... 
		//
		else
		{
			KdPrint(( "\tAdding IRP %8x to RequeueList\n", CancelIrp ));

			InsertTailList(
				&RequeueList,
				&CancelIrp->Tail.Overlay.ListEntry );
		}
	}

	//
	// Run the holding queue of IRP's to be requeued
	// and put them back in the Device Queue object
	//
	while( !IsListEmpty( &RequeueList ))
	{
		ListHead = RemoveHeadList( &RequeueList );
		RequeueIrp = 
			CONTAINING_RECORD(
				ListHead,
				IRP,
				Tail.Overlay.ListEntry );

		//
		// Requeue the IRP. If this is the first
		// reinsertion, the Device Queue will be
		// Not Busy. Hence, it will take two calls 
		// to get the insertion to work.
		//

		KdPrint(( "\tRequeuing IRP %8x to Device Queue\n", RequeueIrp ));

		if( !KeInsertDeviceQueue(
				DeviceQueue,
				&RequeueIrp->
					Tail.Overlay.DeviceQueueEntry ))
		{
			KeInsertDeviceQueue(
				DeviceQueue,
				&RequeueIrp->
					Tail.Overlay.DeviceQueueEntry );
		}
	}

	//
	// Then release the Cancel spin lock
	//
	IoReleaseCancelSpinLock( OldIrql );

	//
	// Run the length of the holding queue and 
	// complete every IRP that we found in it.
	//
	while( !IsListEmpty( &CancelList ))
	{
		ListHead = RemoveHeadList( &CancelList );
		CancelIrp = 
			CONTAINING_RECORD(
				ListHead,
				IRP,
				Tail.Overlay.ListEntry );

		KdPrint(( "\tCancelling IRP %8x to Device Queue\n", CancelIrp ));
		
		CancelIrp->IoStatus.Status = STATUS_CANCELLED;
		CancelIrp->IoStatus.Information = 0;

		IoCompleteRequest( 
			CancelIrp, 
			IO_NO_INCREMENT );
	}
}

//++
// Function:
//		Ave2kDispatchCleanup
//
// Description:
//		This function processes 
//		IRP_MJ_CLEANUP requests
//
// Arguments:
//		Pointer to Device object
//		Pointer to IRP for this request
//
// Return Value:
//		This function returns STATUS_XXX
//--
NTSTATUS
Ave2kDispatchCleanup(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp
	)
{
	PIO_STACK_LOCATION CleanupIrpStack = 
			IoGetCurrentIrpStackLocation( Irp );

	PDEVICE_EXTENSION DeviceExtension = 
			DeviceObject->DeviceExtension;

	KdPrint(( "Ave2kDispatchCleanup: IRP %8x\n", Irp ));

	//
	// Remove any pending IRP_MJ_READ IRPs 
	// from the Device Queue.
	//
	Ave2kCleanupDeviceQueue(
		&DeviceObject->DeviceQueue,
		CleanupIrpStack->FileObject );

	Ave2kCleanupDeviceQueue(
		&DeviceExtension->AlternateIrpQueue,
		CleanupIrpStack->FileObject );
	//
	// Complete the IRP_MJ_CLEANUP IRP itself...
	//
	Irp->IoStatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = 0;
	IoCompleteRequest( Irp, IO_NO_INCREMENT );
	return STATUS_SUCCESS;
}

⌨️ 快捷键说明

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