📄 dispatch.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 + -