📄 ocrwblk.c
字号:
uval = 0;
umultiplier = 1;
// we're traversing least-to-most significant digits
while( ( (FileName->Buffer[ ix ] >= (WCHAR) '0') &&
(FileName->Buffer[ ix ] <= (WCHAR) '9') ) && ix ) {
uval += (umultiplier *
(ULONG) (FileName->Buffer[ ix ] - (WCHAR) '0'));
ix--;
umultiplier *= 10;
}
}
pipeInfo = &deviceExtension->PipeInfo[ uval ];
}
BULKUSB_KdPrint ( DBGLVL_HIGH, ("Exit BulkUsb_PipeWithName() pipeInfo = 0x%x, ix = %d\n", pipeInfo, uval ));
return pipeInfo;
}
NTSTATUS
BulkUsb_Close(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the dispatch table routine for IRP_MJ_CLOSE.
It handles user mode CloseHandle() calls for a pipe
It closes the File Object for the pipe handle it represents.
Arguments:
DeviceObject - pointer to our FDO (Functional Device Object )
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus;
NTSTATUS actStat;
PFILE_OBJECT fileObject;
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
PUSBD_PIPE_INFORMATION pipeHandle = NULL;
PBULKUSB_PIPEINFO pipeInfo = NULL;
BULKUSB_KdPrint( DBGLVL_DEFAULT,("entering BulkUsb_Close\n"));
BulkUsb_IncrementIoCount(DeviceObject);
deviceExtension = DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation (Irp);
fileObject = irpStack->FileObject;
if (fileObject->FsContext) {
// closing pipe handle
pipeHandle = fileObject->FsContext;
pipeInfo = BulkUsb_PipeWithName( DeviceObject, &fileObject->FileName );
if ( NULL == pipeInfo )
goto done;
if ( pipeInfo->fPipeOpened ) { // set if opened
// may have been aborted
BULKUSB_KdPrint( DBGLVL_DEFAULT,("closing pipe %x\n", pipeHandle));
deviceExtension->OpenPipeCount--;
pipeInfo->fPipeOpened = FALSE;
}
else {
// pipe was already closed; this can only be if we got a sudden REMOVE_DEVICE
BULKUSB_ASSERT( deviceExtension->DeviceRemoved );
BULKUSB_KdPrint( DBGLVL_DEFAULT,("Pipe %x was already closed \n", pipeHandle));
}
}
done:
BulkUsb_DecrementIoCount(DeviceObject);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
// try to power down device if this is the last pipe
actStat = BulkUsb_SelfSuspendOrActivate( DeviceObject, TRUE );
BULKUSB_KdPrint( DBGLVL_DEFAULT,("exit BulkUsb_Close OpenPipeCount = decimal %d, status %x\n",deviceExtension->OpenPipeCount, ntStatus));
return ntStatus;
}
NTSTATUS
BulkUsb_Create(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the dispatch table routine for IRP_MJ_CREATE.
It's the entry point for CreateFile() calls
user mode apps may open "<name genned fron GUID>.\yy"
where yy is the internal pipe id
Arguments:
DeviceObject - pointer to our FDO ( Functional Device Object )
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PFILE_OBJECT fileObject;
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
ULONG i, ix;
NTSTATUS actStat;
PUSBD_INTERFACE_INFORMATION interface;
PUSBD_PIPE_INFORMATION PipeInfo;
PBULKUSB_PIPEINFO ourPipeInfo = NULL;
deviceExtension = DeviceObject->DeviceExtension;
interface = deviceExtension->UsbInterface;
BULKUSB_KdPrint( DBGLVL_DEFAULT,("entering BulkUsb_Create\n"));
BulkUsb_IncrementIoCount(DeviceObject);
// Can't accept a new io request if:
// 1) device is removed,
// 2) has never been started,
// 3) is stopped,
// 4) has a remove request pending,
// 5) has a stop device pending
if ( !BulkUsb_CanAcceptIoRequests( DeviceObject ) ) {
ntStatus = STATUS_DELETE_PENDING;
BULKUSB_KdPrint( DBGLVL_DEFAULT,("ABORTING BulkUsb_Create\n"));
goto done;
}
irpStack = IoGetCurrentIrpStackLocation (Irp);
fileObject = irpStack->FileObject;
// fscontext is null for device
fileObject->FsContext = NULL;
if ( 0 == fileObject->FileName.Length ) // this is the case if opening device as opposed to pipe
goto done; // nothing more to do
ourPipeInfo = BulkUsb_PipeWithName( DeviceObject, &fileObject->FileName );
if ( !ourPipeInfo ) {
ntStatus = STATUS_INVALID_PARAMETER;
goto done;
}
// init status to bad; will set good in below loop on success
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
for (i=0; i<interface->NumberOfPipes; i++) {
PipeInfo = &interface->Pipes[i]; // PUSBD_PIPE_INFORMATION PipeInfo;
if ( ourPipeInfo == &deviceExtension->PipeInfo[i] ) {
//
// found a match
//
BULKUSB_KdPrint( DBGLVL_DEFAULT,("open pipe %d\n", i));
fileObject->FsContext = PipeInfo;
ourPipeInfo->fPipeOpened = TRUE; // set flag for opened
ntStatus = STATUS_SUCCESS;
deviceExtension->OpenPipeCount++;
// try to power up device if its not in D0
actStat = BulkUsb_SelfSuspendOrActivate( DeviceObject, FALSE );
break;
}
}
done:
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
BulkUsb_DecrementIoCount(DeviceObject);
BULKUSB_KdPrint( DBGLVL_DEFAULT,("exit BulkUsb_Create %x\n", ntStatus));
return ntStatus;
}
BOOLEAN
BulkUsb_CancelPendingIo(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Cancels pending IO, as on a sudden IRP_MN_REMOVE_DEVICE
This driver maintains and array of info structs (BULKUSB_RW_CONTEXT)
on self-generated IRPS for staged read/writes; This routine traverses
it and cancels all pending IO irps
Arguments:
DeviceObject - pointer to the device object for this instance of the 82930
device.
Return Value:
TRUE if cancelled any, else FALSE
--*/
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PUCHAR pCon = (PUCHAR) deviceExtension->PendingIoIrps;
ULONG i = 0;
PIRP Irp;
USHORT uDriverCancel = 0; // count cancelled via iocancelirp()
BOOLEAN cRes;
NTSTATUS ntStatus, waitStatus;
// nothing pending
if ( !deviceExtension->PendingIoIrps )
return FALSE;
BULKUSB_KdPrint ( DBGLVL_MAXIMUM, ("enter BulkUsb_CancelPendingIo()\n"));
// the BULKUSB_RW_CONTEXT array is terminated by an entry with a NULL Irp
for ( i = 0; ((PBULKUSB_RW_CONTEXT)pCon)->Irp ; i++ ) {
Irp = ((PBULKUSB_RW_CONTEXT) pCon)->Irp;
//
// Since IoCallDriver has been called on this request, we call IoCancelIrp
// and let our completion routine handle it
//
cRes = IoCancelIrp( Irp );
BULKUSB_KdPrint ( DBGLVL_MAXIMUM, ("BulkUsb_CancelPendingIo() IoCancelIrp() cRes=%d, IRP 0x%x\n", cRes, Irp));
// if cancel call failed, they all will, so dump out
if ( !cRes )
break;
uDriverCancel++; // flag we tried to cancel at least one
// point to next context struct in array
pCon += sizeof( BULKUSB_RW_CONTEXT);
} // end, for
if ( uDriverCancel && cRes ) {
// We only get here if we cancelled at least one and all cancellations were successfull.
// Wait on the event set on last cancel in BulkUsb_AsyncReadWriteComplete();
BULKUSB_KdPrint ( DBGLVL_MAXIMUM, ("BulkUsb_CancelPendingIo() before waiting for StagingDoneEvent()\n" ));
waitStatus = KeWaitForSingleObject(
&deviceExtension->StagingDoneEvent,
Suspended,
KernelMode,
FALSE,
NULL);
BULKUSB_KdPrint ( DBGLVL_MAXIMUM, ("BulkUsb_CancelPendingIo() finished waiting for StagingDoneEvent()\n" ));
}
BULKUSB_KdPrintCond ( DBGLVL_HIGH, uDriverCancel,
("BulkUsb_CancelPendingIo() cancelled %d via IoCancelIrp()\n",uDriverCancel));
return (BOOLEAN) uDriverCancel;
}
NTSTATUS
BulkUsb_AbortPipes(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Called as part of sudden device removal handling.
Cancels any pending transfers for all open pipes.
If any pipes are still open, call USBD with URB_FUNCTION_ABORT_PIPE
Also marks the pipe 'closed' in our saved configuration info.
Arguments:
Ptrs to our FDO
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PURB urb;
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
ULONG i;
PUSBD_INTERFACE_INFORMATION interface;
PBULKUSB_PIPEINFO PipeInfo;
PUCHAR pInf = (PUCHAR ) deviceExtension->PipeInfo;
interface = deviceExtension->UsbInterface;
for (i=0; i<interface->NumberOfPipes; i++) {
PipeInfo = (PBULKUSB_PIPEINFO) pInf; // PBULKUSB_PIPEINFO PipeInfo;
if ( PipeInfo->fPipeOpened ) { // we set this if open, clear if closed
BULKUSB_KdPrint( DBGLVL_HIGH,("BulkUsb_AbortPipes() Aborting open Pipe %d\n", i));
urb = BULKUSB_ExAllocatePool(NonPagedPool,
sizeof(struct _URB_PIPE_REQUEST));
if (urb) {
urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_PIPE_REQUEST);
urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
urb->UrbPipeRequest.PipeHandle =
interface->Pipes[i].PipeHandle;
ntStatus = BulkUsb_CallUSBD(DeviceObject, urb);
BULKUSB_ExFreePool(urb);
} else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
BULKUSB_KdPrint( DBGLVL_HIGH,("BulkUsb_AbortPipes() FAILED urb alloc\n" ));
break;
}
if (!(NT_SUCCESS(ntStatus))) {
// if we failed, dump out
#if DBG
if ( gpDbg )
gpDbg->PipeErrorCount++;
#endif
break;
}
else {
PipeInfo->fPipeOpened = FALSE; // mark the pipe 'closed'
deviceExtension->OpenPipeCount--;
#if DBG
if ( gpDbg )
gpDbg->AbortPipeCount++;
#endif
}
} // end, if pipe open
pInf += sizeof ( BULKUSB_PIPEINFO );
} // end, for all pipes
return ntStatus;
}
BOOLEAN
BulkUsb_CanAcceptIoRequests(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Check device extension status flags;
Can't accept a new io request if device:
1) is removed,
2) has never been started,
3) is stopped,
4) has a remove request pending, or
5) has a stop device pending
Arguments:
DeviceObject - pointer to the device object for this instance of the 82930
device.
Return Value:
return TRUE if can accept new io requests, else FALSE
--*/
{
PDEVICE_EXTENSION deviceExtension;
BOOLEAN fCan = FALSE;
deviceExtension = DeviceObject->DeviceExtension;
//flag set when processing IRP_MN_REMOVE_DEVICE
if ( !deviceExtension->DeviceRemoved &&
// device must be started( enabled )
deviceExtension->DeviceStarted &&
// flag set when driver has answered success to IRP_MN_QUERY_REMOVE_DEVICE
!deviceExtension->RemoveDeviceRequested &&
// flag set when driver has answered success to IRP_MN_QUERY_STOP_DEVICE
!deviceExtension->StopDeviceRequested ){
fCan = TRUE;
}
BULKUSB_KdPrintCond( DBGLVL_MAXIMUM, !fCan, ("**** FALSE return from BulkUsb_CanAcceptIoRequests()!\n"));
return fCan;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -