You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
706 lines
19 KiB
706 lines
19 KiB
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ocrw.c
|
|
|
|
Abstract:
|
|
|
|
read/write io code for printing
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Notes:
|
|
|
|
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
|
|
PURPOSE.
|
|
|
|
Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
|
|
|
|
|
|
Revision History:
|
|
|
|
5-4-96 : created
|
|
|
|
--*/
|
|
|
|
#define DRIVER
|
|
|
|
#include "wdm.h"
|
|
#include "stdarg.h"
|
|
#include "stdio.h"
|
|
|
|
#include <usb.h>
|
|
#include <usbdrivr.h>
|
|
#include "usbdlib.h"
|
|
#include "usbprint.h"
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
//
|
|
// USBPRINT_CompletionStop()
|
|
//
|
|
// IO Completion Routine which just stops further completion of the Irp
|
|
//
|
|
//******************************************************************************
|
|
|
|
NTSTATUS
|
|
USBPRINT_CompletionStop (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
)
|
|
{
|
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
|
}
|
|
|
|
|
|
|
|
PURB
|
|
USBPRINT_BuildAsyncRequest(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PUSBD_PIPE_INFORMATION PipeHandle,
|
|
IN BOOLEAN Read
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - pointer to the device extension for this instance of the
|
|
printer
|
|
|
|
Irp -
|
|
|
|
PipeHandle -
|
|
|
|
Return Value:
|
|
|
|
initialized async urb.
|
|
|
|
--*/
|
|
{
|
|
ULONG siz;
|
|
ULONG length;
|
|
PURB urb = NULL;
|
|
|
|
USBPRINT_KdPrint3 (("USBPRINT.SYS: handle = 0x%x\n", PipeHandle));
|
|
|
|
if ( Irp->MdlAddress == NULL )
|
|
return NULL;
|
|
|
|
length = MmGetMdlByteCount(Irp->MdlAddress);
|
|
|
|
USBPRINT_KdPrint3 (("USBPRINT.SYS: length = 0x%x\n", length));
|
|
|
|
siz = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
|
|
urb = ExAllocatePoolWithTag(NonPagedPool, siz, USBP_TAG);
|
|
|
|
USBPRINT_KdPrint3 (("USBPRINT.SYS: siz = 0x%x urb 0x%x\n", siz, urb));
|
|
|
|
if (urb) {
|
|
RtlZeroMemory(urb, siz);
|
|
|
|
urb->UrbBulkOrInterruptTransfer.Hdr.Length = (USHORT) siz;
|
|
urb->UrbBulkOrInterruptTransfer.Hdr.Function =
|
|
URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
|
|
urb->UrbBulkOrInterruptTransfer.PipeHandle =
|
|
PipeHandle->PipeHandle;
|
|
urb->UrbBulkOrInterruptTransfer.TransferFlags =
|
|
Read ? USBD_TRANSFER_DIRECTION_IN : 0;
|
|
|
|
// short packet is not treated as an error.
|
|
urb->UrbBulkOrInterruptTransfer.TransferFlags |=
|
|
USBD_SHORT_TRANSFER_OK;
|
|
|
|
//
|
|
// no linkage for now
|
|
//
|
|
|
|
urb->UrbBulkOrInterruptTransfer.UrbLink = NULL;
|
|
|
|
urb->UrbBulkOrInterruptTransfer.TransferBufferMDL =
|
|
Irp->MdlAddress;
|
|
urb->UrbBulkOrInterruptTransfer.TransferBufferLength =
|
|
length;
|
|
|
|
USBPRINT_KdPrint3 (("USBPRINT.SYS: Init async urb Length = 0x%x buf = 0x%x, mdlBuff=0x%x\n",
|
|
urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
|
|
urb->UrbBulkOrInterruptTransfer.TransferBuffer,
|
|
urb->UrbBulkOrInterruptTransfer.TransferBufferMDL));
|
|
}
|
|
|
|
USBPRINT_KdPrint3 (("USBPRINT.SYS: exit USBPRINT_BuildAsyncRequest\n"));
|
|
|
|
return urb;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
USBPRINT_AsyncReadWrite_Complete(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Pointer to the device object for the USBPRINT device.
|
|
|
|
Irp - Irp completed.
|
|
|
|
Context - Driver defined context.
|
|
|
|
Return Value:
|
|
|
|
The function value is the final status from the operation.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
PURB urb;
|
|
PUSBPRINT_RW_CONTEXT context = Context;
|
|
PDEVICE_OBJECT deviceObject;
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
PUSBPRINT_WORKITEM_CONTEXT pResetWorkItemObj;
|
|
LONG ResetPending;
|
|
|
|
//Always mark irp pending in dispatch routine now
|
|
// if (Irp->PendingReturned) {
|
|
// IoMarkIrpPending(Irp);
|
|
// }
|
|
|
|
urb = context->Urb;
|
|
deviceObject = context->DeviceObject;
|
|
deviceExtension=deviceObject->DeviceExtension;
|
|
|
|
USBPRINT_KdPrint2 (("USBPRINT.SYS: Async Completion: Length %d, Status 0x%08X\n",
|
|
urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
|
|
urb->UrbHeader.Status));
|
|
|
|
|
|
//ASSERT(urb->UrbHeader.Status==0);
|
|
|
|
ntStatus=urb->UrbHeader.Status;
|
|
|
|
//
|
|
// set the length based on the TransferBufferLength
|
|
// value in the URB
|
|
//
|
|
Irp->IoStatus.Information =
|
|
urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
|
|
|
|
|
|
if((!NT_SUCCESS(ntStatus))&&(ntStatus!=STATUS_CANCELLED)&&(ntStatus!=STATUS_DEVICE_NOT_CONNECTED)&&(ntStatus!=STATUS_DELETE_PENDING))
|
|
{ //We've got an error, and it's not "not connected" or "cancelled", we need to reset the connection
|
|
ResetPending=InterlockedCompareExchange(&deviceExtension->ResetWorkItemPending,
|
|
1,
|
|
0); //Check to see if ResetWorkItem is 0, if so, set it to 1, and start a Reset
|
|
if(!ResetPending)
|
|
{
|
|
pResetWorkItemObj=ExAllocatePoolWithTag(NonPagedPool,sizeof(USBPRINT_WORKITEM_CONTEXT),USBP_TAG);
|
|
if(pResetWorkItemObj)
|
|
{
|
|
pResetWorkItemObj->ioWorkItem=IoAllocateWorkItem(DeviceObject);
|
|
if(pResetWorkItemObj==NULL)
|
|
{
|
|
USBPRINT_KdPrint1 (("USBPRINT.SYS: Unable to allocate IoAllocateWorkItem in ReadWrite_Complete\n"));
|
|
ExFreePool(pResetWorkItemObj);
|
|
pResetWorkItemObj=NULL;
|
|
}
|
|
} //if ALloc RestWorkItem OK
|
|
else
|
|
{
|
|
USBPRINT_KdPrint1 (("USBPRINT.SYS: Unable to allocate WorkItemObj in ReadWrite_Complete\n"));
|
|
}
|
|
if(pResetWorkItemObj)
|
|
{
|
|
pResetWorkItemObj->irp=Irp;
|
|
pResetWorkItemObj->deviceObject=DeviceObject;
|
|
if(context->IsWrite)
|
|
pResetWorkItemObj->pPipeInfo=deviceExtension->pWritePipe;
|
|
else
|
|
pResetWorkItemObj->pPipeInfo=deviceExtension->pReadPipe;
|
|
|
|
USBPRINT_IncrementIoCount(deviceObject);
|
|
IoQueueWorkItem(pResetWorkItemObj->ioWorkItem,
|
|
USBPRINT_ResetWorkItem,
|
|
DelayedWorkQueue,
|
|
pResetWorkItemObj);
|
|
ntStatus=STATUS_MORE_PROCESSING_REQUIRED;
|
|
//Leave the IRP pending until the reset is complete. This way we won't get flooded with irp's we're not
|
|
//prepaired to deal with. The Reset WorkItem completes the IRP when it's done.
|
|
} //end if the allocs went OK
|
|
} //end if ! Reset Pending
|
|
} //end if we need to reset
|
|
|
|
USBPRINT_DecrementIoCount(deviceObject); //still +1 on the IO count after this, leaving one for the workitem to decrement
|
|
|
|
ExFreePool(context);
|
|
ExFreePool(urb);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS USBPRINT_ResetWorkItem(IN PDEVICE_OBJECT deviceObject, IN PVOID Context)
|
|
{
|
|
|
|
PUSBPRINT_WORKITEM_CONTEXT pResetWorkItemObj;
|
|
PDEVICE_EXTENSION DeviceExtension;
|
|
NTSTATUS ntStatus;
|
|
ULONG portStatus;
|
|
PDEVICE_OBJECT devObj;
|
|
|
|
|
|
USBPRINT_KdPrint2(("USBPRINT.SYS: Entering USBPRINT_ResetWorkItem\n"));
|
|
pResetWorkItemObj=(PUSBPRINT_WORKITEM_CONTEXT)Context;
|
|
DeviceExtension=pResetWorkItemObj->deviceObject->DeviceExtension;
|
|
ntStatus=USBPRINT_ResetPipe(pResetWorkItemObj->deviceObject,pResetWorkItemObj->pPipeInfo,FALSE);
|
|
IoCompleteRequest(pResetWorkItemObj->irp,IO_NO_INCREMENT);
|
|
IoFreeWorkItem(pResetWorkItemObj->ioWorkItem);
|
|
|
|
// save off work item device object before freeing work item
|
|
devObj = pResetWorkItemObj->deviceObject;
|
|
|
|
ExFreePool(pResetWorkItemObj);
|
|
InterlockedExchange(&(DeviceExtension->ResetWorkItemPending),0);
|
|
USBPRINT_DecrementIoCount(devObj);
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPRINT_Read(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - pointer to the device object for this instance of a printer.
|
|
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
PUSBD_PIPE_INFORMATION pipeHandle = NULL;
|
|
PFILE_OBJECT fileObject;
|
|
PIO_STACK_LOCATION irpStack, nextStack;
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
PURB urb;
|
|
PUSBPRINT_RW_CONTEXT context = NULL;
|
|
|
|
USBPRINT_KdPrint3 (("USBPRINT.SYS: /*dd enter USBPRINT_Read\n\n\n\n\n\n"));
|
|
USBPRINT_KdPrint3 (("USBPRINT.SYS: /*dd **************************************************************************\n"));
|
|
|
|
USBPRINT_IncrementIoCount(DeviceObject);
|
|
|
|
deviceExtension = DeviceObject->DeviceExtension;
|
|
|
|
if (deviceExtension->IsChildDevice == TRUE)
|
|
{
|
|
ntStatus = STATUS_NOT_SUPPORTED;
|
|
Irp->IoStatus.Status = ntStatus;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest (Irp,IO_NO_INCREMENT);
|
|
USBPRINT_DecrementIoCount(DeviceObject);
|
|
return ntStatus;
|
|
}
|
|
|
|
if (deviceExtension->AcceptingRequests == FALSE)
|
|
{
|
|
ntStatus = STATUS_DELETE_PENDING;
|
|
Irp->IoStatus.Status = ntStatus;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest (Irp,IO_NO_INCREMENT);
|
|
USBPRINT_DecrementIoCount(DeviceObject);
|
|
return ntStatus;
|
|
}
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation (Irp);
|
|
fileObject = irpStack->FileObject;
|
|
|
|
pipeHandle = deviceExtension->pReadPipe;
|
|
|
|
if (!pipeHandle) {
|
|
ntStatus = STATUS_INVALID_HANDLE;
|
|
goto USBPRINT_Read_Reject;
|
|
}
|
|
|
|
//
|
|
// submit the Read request to USB
|
|
//
|
|
|
|
switch (pipeHandle->PipeType) {
|
|
case UsbdPipeTypeInterrupt:
|
|
case UsbdPipeTypeBulk:
|
|
urb = USBPRINT_BuildAsyncRequest(DeviceObject,
|
|
Irp,
|
|
pipeHandle,
|
|
TRUE);
|
|
if (urb) {
|
|
context = ExAllocatePoolWithTag(NonPagedPool, sizeof(USBPRINT_RW_CONTEXT), USBP_TAG);
|
|
|
|
if ( !context )
|
|
ExFreePool(urb);
|
|
}
|
|
|
|
if (urb && context) {
|
|
context->Urb = urb;
|
|
context->DeviceObject = DeviceObject;
|
|
context->IsWrite=FALSE;
|
|
|
|
nextStack = IoGetNextIrpStackLocation(Irp);
|
|
ASSERT(nextStack != NULL);
|
|
ASSERT(DeviceObject->StackSize>1);
|
|
|
|
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
|
|
nextStack->Parameters.Others.Argument1 = urb;
|
|
nextStack->Parameters.DeviceIoControl.IoControlCode =
|
|
IOCTL_INTERNAL_USB_SUBMIT_URB;
|
|
|
|
IoSetCompletionRoutine(Irp,
|
|
USBPRINT_AsyncReadWrite_Complete,
|
|
context,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
|
|
USBPRINT_KdPrint3 (("USBPRINT.SYS: IRP = 0x%x current = 0x%x next = 0x%x\n",
|
|
Irp, irpStack, nextStack));
|
|
|
|
// start perf timer here if needed
|
|
|
|
IoMarkIrpPending(Irp);
|
|
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
|
|
Irp);
|
|
ntStatus=STATUS_PENDING;
|
|
goto USBPRINT_Read_Done;
|
|
}
|
|
else
|
|
{
|
|
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
break;
|
|
default:
|
|
ntStatus = STATUS_INVALID_PARAMETER;
|
|
TRAP();
|
|
}
|
|
|
|
USBPRINT_Read_Reject:
|
|
|
|
USBPRINT_DecrementIoCount(DeviceObject);
|
|
Irp->IoStatus.Status = ntStatus;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest (Irp,
|
|
IO_NO_INCREMENT
|
|
);
|
|
|
|
USBPRINT_Read_Done:
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPRINT_Write(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function services WRITE requests for this device (probably from the user mode USB port monitor)
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - pointer to the device object for this printer
|
|
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
PUSBD_PIPE_INFORMATION pipeHandle = NULL;
|
|
PFILE_OBJECT fileObject;
|
|
PIO_STACK_LOCATION irpStack, nextStack;
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
PURB urb;
|
|
PUSBPRINT_RW_CONTEXT context = NULL;
|
|
|
|
USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_Write (foo)\n"));
|
|
|
|
USBPRINT_IncrementIoCount(DeviceObject);
|
|
|
|
deviceExtension = DeviceObject->DeviceExtension;
|
|
|
|
if (deviceExtension->IsChildDevice == TRUE)
|
|
{
|
|
USBPRINT_KdPrint1 (("USBPRINT.SYS: failure because bChildDevice=TRUE\n"));
|
|
ntStatus = STATUS_NOT_SUPPORTED;
|
|
Irp->IoStatus.Status = ntStatus;
|
|
Irp->IoStatus.Information = 0;
|
|
USBPRINT_DecrementIoCount(DeviceObject);
|
|
IoCompleteRequest (Irp,IO_NO_INCREMENT);
|
|
return ntStatus;
|
|
}
|
|
if (deviceExtension->AcceptingRequests == FALSE)
|
|
{
|
|
USBPRINT_KdPrint1 (("USBPRINT.SYS: failure because AcceptingRequests=FALSE\n"));
|
|
ntStatus = STATUS_DELETE_PENDING;
|
|
Irp->IoStatus.Status = ntStatus;
|
|
Irp->IoStatus.Information = 0;
|
|
USBPRINT_DecrementIoCount(DeviceObject);
|
|
IoCompleteRequest (Irp,IO_NO_INCREMENT);
|
|
return ntStatus;
|
|
}
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation (Irp);
|
|
|
|
|
|
fileObject = irpStack->FileObject;
|
|
|
|
// MmProbeAndLockPages(Irp->MdlAddress,
|
|
// KernelMode,
|
|
// IoReadAccess);
|
|
|
|
pipeHandle = deviceExtension->pWritePipe;
|
|
if (!pipeHandle)
|
|
{
|
|
USBPRINT_KdPrint1 (("USBPRINT.SYS: failure because pipe is bad\n"));
|
|
ntStatus = STATUS_INVALID_HANDLE;
|
|
goto USBPRINT_Write_Reject;
|
|
}
|
|
|
|
//
|
|
// submit the write request to USB
|
|
//
|
|
|
|
switch (pipeHandle->PipeType)
|
|
{
|
|
case UsbdPipeTypeInterrupt:
|
|
case UsbdPipeTypeBulk:
|
|
urb = USBPRINT_BuildAsyncRequest(DeviceObject,
|
|
Irp,
|
|
pipeHandle,
|
|
FALSE);
|
|
|
|
if (urb)
|
|
{
|
|
context = ExAllocatePoolWithTag(NonPagedPool, sizeof(USBPRINT_RW_CONTEXT), USBP_TAG);
|
|
|
|
if(!context)
|
|
ExFreePool(urb);
|
|
|
|
}
|
|
|
|
if (urb && context)
|
|
{
|
|
context->Urb = urb;
|
|
context->DeviceObject = DeviceObject;
|
|
context->IsWrite=TRUE;
|
|
|
|
nextStack = IoGetNextIrpStackLocation(Irp);
|
|
ASSERT(nextStack != NULL);
|
|
ASSERT(DeviceObject->StackSize>1);
|
|
|
|
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
|
|
nextStack->Parameters.Others.Argument1 = urb;
|
|
nextStack->Parameters.DeviceIoControl.IoControlCode =
|
|
IOCTL_INTERNAL_USB_SUBMIT_URB;
|
|
|
|
IoSetCompletionRoutine(Irp,
|
|
USBPRINT_AsyncReadWrite_Complete,
|
|
context,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
|
|
USBPRINT_KdPrint3 (("USBPRINT.SYS: IRP = 0x%x current = 0x%x next = 0x%x\n",Irp, irpStack, nextStack));
|
|
|
|
IoMarkIrpPending(Irp);
|
|
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,Irp);
|
|
ntStatus=STATUS_PENDING;
|
|
goto USBPRINT_Write_Done;
|
|
}
|
|
else
|
|
{
|
|
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
break;
|
|
default:
|
|
ntStatus = STATUS_INVALID_PARAMETER;
|
|
TRAP();
|
|
}
|
|
|
|
USBPRINT_Write_Reject:
|
|
|
|
USBPRINT_DecrementIoCount(DeviceObject);
|
|
Irp->IoStatus.Status = ntStatus;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest (Irp,
|
|
IO_NO_INCREMENT
|
|
);
|
|
|
|
USBPRINT_Write_Done:
|
|
USBPRINT_KdPrint3 (("USBPRINT.SYS: Write Done, status= 0x%08X\n",ntStatus));
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPRINT_Close(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - pointer to the device object for this printer
|
|
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
PFILE_OBJECT fileObject;
|
|
PIO_STACK_LOCATION irpStack;
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
PUSBD_PIPE_INFORMATION pipeHandle = NULL;
|
|
|
|
USBPRINT_KdPrint2 (("USBPRINT.SYS: entering USBPRINT_Close\n"));
|
|
|
|
USBPRINT_IncrementIoCount(DeviceObject);
|
|
|
|
deviceExtension = DeviceObject->DeviceExtension;
|
|
irpStack = IoGetCurrentIrpStackLocation (Irp);
|
|
fileObject = irpStack->FileObject;
|
|
|
|
if (fileObject->FsContext)
|
|
{
|
|
// closing pipe handle
|
|
pipeHandle = fileObject->FsContext;
|
|
USBPRINT_KdPrint3 (("USBPRINT.SYS: closing pipe %x\n", pipeHandle));
|
|
|
|
}
|
|
deviceExtension->OpenCnt--;
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
|
|
ntStatus = Irp->IoStatus.Status;
|
|
|
|
IoCompleteRequest (Irp,IO_NO_INCREMENT);
|
|
|
|
USBPRINT_DecrementIoCount(DeviceObject);
|
|
|
|
if(!deviceExtension->IsChildDevice)
|
|
{
|
|
USBPRINT_FdoSubmitIdleRequestIrp(deviceExtension);
|
|
}
|
|
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
USBPRINT_Create(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
//
|
|
// Entry point for CreateFile calls
|
|
// user mode apps open device interfaces via
|
|
// SetupDiEnumDeviceInterfaces
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - pointer to the device object for this printer.
|
|
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
PFILE_OBJECT fileObject;
|
|
PIO_STACK_LOCATION irpStack;
|
|
PDEVICE_EXTENSION deviceExtension;
|
|
|
|
USBPRINT_KdPrint2 (("USBPRINT.SYS: entering USBPRINT_Create\n"));
|
|
USBPRINT_IncrementIoCount(DeviceObject);
|
|
deviceExtension = DeviceObject->DeviceExtension;
|
|
if (deviceExtension->IsChildDevice==TRUE) {
|
|
ntStatus = STATUS_NOT_SUPPORTED;
|
|
Irp->IoStatus.Status = ntStatus;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest (Irp,IO_NO_INCREMENT);
|
|
USBPRINT_DecrementIoCount(DeviceObject);
|
|
return ntStatus;
|
|
}
|
|
if (deviceExtension->AcceptingRequests == FALSE) {
|
|
ntStatus = STATUS_DELETE_PENDING;
|
|
Irp->IoStatus.Status = ntStatus;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest (Irp,IO_NO_INCREMENT);
|
|
USBPRINT_DecrementIoCount(DeviceObject);
|
|
return ntStatus;
|
|
}
|
|
|
|
USBPRINT_FdoRequestWake(deviceExtension);
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation (Irp);
|
|
fileObject = irpStack->FileObject;
|
|
// fscontext is null for device
|
|
fileObject->FsContext = NULL;
|
|
deviceExtension->OpenCnt++;
|
|
ntStatus = STATUS_SUCCESS;
|
|
Irp->IoStatus.Status = ntStatus;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest (Irp,IO_NO_INCREMENT);
|
|
USBPRINT_DecrementIoCount(DeviceObject);
|
|
USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_Create %x\n", ntStatus));
|
|
return ntStatus;
|
|
}
|
|
|
|
|