📄 rwr.c
字号:
if (pRWContext) {
DevIoDecrement(pRWContext->pDevExt);
_FreeRWContext(pRWContext);
}
return ntS;
}
/*********************************************************************
*
* DispatchRW
*
* Function description
* Execute read/write IRPs.
*/
static NTSTATUS _DispatchRW(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, BOOLEAN Read) {
URB * Urb;
ULONG totalLength;
NTSTATUS ntS;
ULONG_PTR virtualAddress;
PFILE_OBJECT fileObject;
DEVICE_EXTENSION * pDevExt;
IO_STACK_LOCATION * irpStack;
USB_RW_CONTEXT * pRWContext;
USBD_PIPE_INFORMATION * pipeInformation;
ULONG stageLength;
Urb = NULL;
pRWContext = NULL;
totalLength = 0;
irpStack = IoGetCurrentIrpStackLocation(Irp);
fileObject = irpStack->FileObject;
pDevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(Irp->MdlAddress);
//
// Assert that device is working
//
if (pDevExt->DeviceState != Working) {
DPRINT(("<usb> error: invalid device state\n"));
ntS = STATUS_INVALID_DEVICE_STATE;
goto OnError;
}
//
// More assertions
//
if (!fileObject) {
DPRINT(("<usb> File Object invalid\n"));
ntS = STATUS_INVALID_HANDLE;
goto OnError;
}
if (!fileObject->FsContext) {
DPRINT(("<usb> error: invalid Fscontext\n"));
ntS = STATUS_INVALID_HANDLE;
goto OnError;
}
pipeInformation = fileObject->FsContext;
if (pipeInformation->PipeType != UsbdPipeTypeBulk) {
DPRINT(("<usb> error: pipe not BULK type\n"));
ntS = STATUS_INVALID_HANDLE;
goto OnError;
}
//
// Get TotalLenght ... What happens if (Irp->MdlAddress == NULL) ??? Error handling ??? (RS)
//
if (Irp->MdlAddress) {
totalLength = MmGetMdlByteCount(Irp->MdlAddress);
}
//
// Assert transfer size is in valid range
//
if (totalLength > BULKUSB_TEST_BOARD_TRANSFER_BUFFER_SIZE) {
DPRINT(("<usb> error: transfer size excesss limit\n"));
ntS = STATUS_INVALID_PARAMETER;
goto OnError;
}
if (totalLength == 0) {
DPRINT(("<usb> transfer is 0 bytes\n"));
ntS = STATUS_SUCCESS;
goto OnError;
}
//
// In read mode, check if there is enough data in our intermediate buffer
// If so, then we are done.
//
if (Read) {
if (_CopyFromBuffer(Irp, pDevExt, (void*)virtualAddress, totalLength)) {
DPRINT(("<usb> Request satisfied from buffer\n"));
Irp->IoStatus.Information = totalLength;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
Irp->IoStatus.Status = STATUS_SUCCESS;
return STATUS_SUCCESS;
}
}
//
// In write mode, output debug info
//
#if DBG
if (!Read) {
int i;
int iMax;
char ac[2000];
char acHex[] = "0123456789ABCDEF";
char * s = ac;
char * pData = (char*)virtualAddress;
iMax = (totalLength < 100) ? totalLength : 100;
for (i = 0; i < iMax; i++) {
unsigned char Data = *(i + pData);
*s++ = ' ';
*s++ = acHex[Data >> 4];
*s++ = acHex[Data & 15];
}
*s = '\0';
DPRINT(("<usb> Writing (%s)\n", ac));
}
#endif
//
// Allocate RWContext
//
pRWContext = (USB_RW_CONTEXT *) _ExAllocatePoolZeroed(NonPagedPool, sizeof(USB_RW_CONTEXT));
if (pRWContext == NULL) {
DPRINT(("<usb> error: allocating USB_RW_CONTEXT\n"));
ntS = STATUS_INSUFFICIENT_RESOURCES;
goto OnError;
}
//
// Allocate URB
//
Urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
if (Urb == NULL) {
DPRINT(("<usb> error: allocating urb\n"));
ntS = STATUS_INSUFFICIENT_RESOURCES;
goto OnError;
}
pRWContext->Urb = Urb;
/* Read uses buffered mode, write uses MDL */
if (Read) {
UsbBuildInterruptOrBulkTransferRequest(Urb,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
pipeInformation->PipeHandle,
&pDevExt->acBuffer[pDevExt->NumBytesInBuffer],
NULL,
BULKUSB_MAX_TRANSFER_SIZE_READ,
USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_IN,
NULL);
} else {
//
// map the portion of user-buffer described by an mdl to another mdl
//
// Allocate MDL
//
MDL * Mdl;
stageLength = (totalLength > BULKUSB_MAX_TRANSFER_SIZE_WRITE ? BULKUSB_MAX_TRANSFER_SIZE_WRITE : totalLength);
Mdl = IoAllocateMdl((PVOID) virtualAddress, totalLength, FALSE, FALSE, NULL);
if (Mdl == NULL) {
DPRINT(("<usb> allocating mdl\n"));
ntS = STATUS_INSUFFICIENT_RESOURCES;
goto OnError;
}
IoBuildPartialMdl(Irp->MdlAddress, Mdl, (PVOID) virtualAddress, stageLength);
pRWContext->Mdl = Mdl;
UsbBuildInterruptOrBulkTransferRequest(Urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
pipeInformation->PipeHandle, NULL, Mdl, stageLength,
/*USBD_SHORT_TRANSFER_OK | */USBD_TRANSFER_DIRECTION_OUT, NULL);
}
// set USB_RW_CONTEXT parameters.
pRWContext->NumRemBytes = totalLength;
pRWContext->NumBytesTransferred = 0;
pRWContext->VirtualAddress = virtualAddress;
pRWContext->pDevExt = pDevExt;
pRWContext->PipeHandle = pipeInformation->PipeHandle;
// always mark IRP pending for safety purpose :)
IoMarkIrpPending(Irp);
DevIoIncrement(pDevExt);
// use the original read/write irp as an internal device control irp
if (Read) {
ntS = _CallUSBD(Irp, pRWContext, _OnReadCompletion);
} else {
ntS = _CallUSBD(Irp, pRWContext, _OnWriteCompletion);
}
if (!NT_SUCCESS(ntS)) {
DPRINT(("<usb> error: DispatchReadWrite::IoCallDriver %x\n", ntS));
// if the device was yanked out, then the pipeInformation field is invalid.
// similarly if the request was cancelled, then we need not invoked reset pipe/device.
if ((ntS != STATUS_CANCELLED) && (ntS != STATUS_DEVICE_NOT_CONNECTED)) {
ntS = ResetPipe(DeviceObject, pipeInformation);
if(!NT_SUCCESS(ntS)) {
DPRINT(("<usb> error: DispatchReadWrite::ResetPipe %x (we now reset device)\n", ntS));
ntS = ResetDevice(DeviceObject);
}
} else {
DPRINT(("<usb> error: operation canceled or device not connected\n"));
}
}
// we return STATUS_PENDING and not the status returned by the lower layer.
return STATUS_PENDING;
//
// Error handling
//
OnError:
_FreeRWContext(pRWContext);
return(CompleteRequest(Irp, ntS, 0));
}
/*********************************************************************
*
* DispatchWrite
*
* Function description
* Execute write IRPs. (Callback for IRP_MJ_WRITE)
*/
NTSTATUS DispatchWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
DPRINT(("<usb> IRP_MJ_WRITE\n"));
return _DispatchRW(DeviceObject, Irp, 0);
}
/*********************************************************************
*
* DispatchRead
*
* Function description
* Execute read IRPs. (Callback for IRP_MJ_READ)
*/
NTSTATUS DispatchRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
DPRINT(("<usb> IRP_MJ_READ\n"));
return _DispatchRW(DeviceObject, Irp, 1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -