Leaked source code of windows server 2003
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

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. ocrw.c
  5. Abstract:
  6. read/write io code for printing
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  11. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  12. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  13. PURPOSE.
  14. Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 5-4-96 : created
  17. --*/
  18. #define DRIVER
  19. #include "wdm.h"
  20. #include "stdarg.h"
  21. #include "stdio.h"
  22. #include <usb.h>
  23. #include <usbdrivr.h>
  24. #include "usbdlib.h"
  25. #include "usbprint.h"
  26. //******************************************************************************
  27. //
  28. // USBPRINT_CompletionStop()
  29. //
  30. // IO Completion Routine which just stops further completion of the Irp
  31. //
  32. //******************************************************************************
  33. NTSTATUS
  34. USBPRINT_CompletionStop (
  35. IN PDEVICE_OBJECT DeviceObject,
  36. IN PIRP Irp,
  37. IN PVOID Context
  38. )
  39. {
  40. return STATUS_MORE_PROCESSING_REQUIRED;
  41. }
  42. PURB
  43. USBPRINT_BuildAsyncRequest(
  44. IN PDEVICE_OBJECT DeviceObject,
  45. IN PIRP Irp,
  46. IN PUSBD_PIPE_INFORMATION PipeHandle,
  47. IN BOOLEAN Read
  48. )
  49. /*++
  50. Routine Description:
  51. Arguments:
  52. DeviceObject - pointer to the device extension for this instance of the
  53. printer
  54. Irp -
  55. PipeHandle -
  56. Return Value:
  57. initialized async urb.
  58. --*/
  59. {
  60. ULONG siz;
  61. ULONG length;
  62. PURB urb = NULL;
  63. USBPRINT_KdPrint3 (("USBPRINT.SYS: handle = 0x%x\n", PipeHandle));
  64. if ( Irp->MdlAddress == NULL )
  65. return NULL;
  66. length = MmGetMdlByteCount(Irp->MdlAddress);
  67. USBPRINT_KdPrint3 (("USBPRINT.SYS: length = 0x%x\n", length));
  68. siz = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
  69. urb = ExAllocatePoolWithTag(NonPagedPool, siz, USBP_TAG);
  70. USBPRINT_KdPrint3 (("USBPRINT.SYS: siz = 0x%x urb 0x%x\n", siz, urb));
  71. if (urb) {
  72. RtlZeroMemory(urb, siz);
  73. urb->UrbBulkOrInterruptTransfer.Hdr.Length = (USHORT) siz;
  74. urb->UrbBulkOrInterruptTransfer.Hdr.Function =
  75. URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
  76. urb->UrbBulkOrInterruptTransfer.PipeHandle =
  77. PipeHandle->PipeHandle;
  78. urb->UrbBulkOrInterruptTransfer.TransferFlags =
  79. Read ? USBD_TRANSFER_DIRECTION_IN : 0;
  80. // short packet is not treated as an error.
  81. urb->UrbBulkOrInterruptTransfer.TransferFlags |=
  82. USBD_SHORT_TRANSFER_OK;
  83. //
  84. // no linkage for now
  85. //
  86. urb->UrbBulkOrInterruptTransfer.UrbLink = NULL;
  87. urb->UrbBulkOrInterruptTransfer.TransferBufferMDL =
  88. Irp->MdlAddress;
  89. urb->UrbBulkOrInterruptTransfer.TransferBufferLength =
  90. length;
  91. USBPRINT_KdPrint3 (("USBPRINT.SYS: Init async urb Length = 0x%x buf = 0x%x, mdlBuff=0x%x\n",
  92. urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
  93. urb->UrbBulkOrInterruptTransfer.TransferBuffer,
  94. urb->UrbBulkOrInterruptTransfer.TransferBufferMDL));
  95. }
  96. USBPRINT_KdPrint3 (("USBPRINT.SYS: exit USBPRINT_BuildAsyncRequest\n"));
  97. return urb;
  98. }
  99. NTSTATUS
  100. USBPRINT_AsyncReadWrite_Complete(
  101. IN PDEVICE_OBJECT DeviceObject,
  102. IN PIRP Irp,
  103. IN PVOID Context
  104. )
  105. /*++
  106. Routine Description:
  107. Arguments:
  108. DeviceObject - Pointer to the device object for the USBPRINT device.
  109. Irp - Irp completed.
  110. Context - Driver defined context.
  111. Return Value:
  112. The function value is the final status from the operation.
  113. --*/
  114. {
  115. NTSTATUS ntStatus = STATUS_SUCCESS;
  116. PURB urb;
  117. PUSBPRINT_RW_CONTEXT context = Context;
  118. PDEVICE_OBJECT deviceObject;
  119. PDEVICE_EXTENSION deviceExtension;
  120. PUSBPRINT_WORKITEM_CONTEXT pResetWorkItemObj;
  121. LONG ResetPending;
  122. //Always mark irp pending in dispatch routine now
  123. // if (Irp->PendingReturned) {
  124. // IoMarkIrpPending(Irp);
  125. // }
  126. urb = context->Urb;
  127. deviceObject = context->DeviceObject;
  128. deviceExtension=deviceObject->DeviceExtension;
  129. USBPRINT_KdPrint2 (("USBPRINT.SYS: Async Completion: Length %d, Status 0x%08X\n",
  130. urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
  131. urb->UrbHeader.Status));
  132. //ASSERT(urb->UrbHeader.Status==0);
  133. ntStatus=urb->UrbHeader.Status;
  134. //
  135. // set the length based on the TransferBufferLength
  136. // value in the URB
  137. //
  138. Irp->IoStatus.Information =
  139. urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
  140. if((!NT_SUCCESS(ntStatus))&&(ntStatus!=STATUS_CANCELLED)&&(ntStatus!=STATUS_DEVICE_NOT_CONNECTED)&&(ntStatus!=STATUS_DELETE_PENDING))
  141. { //We've got an error, and it's not "not connected" or "cancelled", we need to reset the connection
  142. ResetPending=InterlockedCompareExchange(&deviceExtension->ResetWorkItemPending,
  143. 1,
  144. 0); //Check to see if ResetWorkItem is 0, if so, set it to 1, and start a Reset
  145. if(!ResetPending)
  146. {
  147. pResetWorkItemObj=ExAllocatePoolWithTag(NonPagedPool,sizeof(USBPRINT_WORKITEM_CONTEXT),USBP_TAG);
  148. if(pResetWorkItemObj)
  149. {
  150. pResetWorkItemObj->ioWorkItem=IoAllocateWorkItem(DeviceObject);
  151. if(pResetWorkItemObj==NULL)
  152. {
  153. USBPRINT_KdPrint1 (("USBPRINT.SYS: Unable to allocate IoAllocateWorkItem in ReadWrite_Complete\n"));
  154. ExFreePool(pResetWorkItemObj);
  155. pResetWorkItemObj=NULL;
  156. }
  157. } //if ALloc RestWorkItem OK
  158. else
  159. {
  160. USBPRINT_KdPrint1 (("USBPRINT.SYS: Unable to allocate WorkItemObj in ReadWrite_Complete\n"));
  161. }
  162. if(pResetWorkItemObj)
  163. {
  164. pResetWorkItemObj->irp=Irp;
  165. pResetWorkItemObj->deviceObject=DeviceObject;
  166. if(context->IsWrite)
  167. pResetWorkItemObj->pPipeInfo=deviceExtension->pWritePipe;
  168. else
  169. pResetWorkItemObj->pPipeInfo=deviceExtension->pReadPipe;
  170. USBPRINT_IncrementIoCount(deviceObject);
  171. IoQueueWorkItem(pResetWorkItemObj->ioWorkItem,
  172. USBPRINT_ResetWorkItem,
  173. DelayedWorkQueue,
  174. pResetWorkItemObj);
  175. ntStatus=STATUS_MORE_PROCESSING_REQUIRED;
  176. //Leave the IRP pending until the reset is complete. This way we won't get flooded with irp's we're not
  177. //prepaired to deal with. The Reset WorkItem completes the IRP when it's done.
  178. } //end if the allocs went OK
  179. } //end if ! Reset Pending
  180. } //end if we need to reset
  181. USBPRINT_DecrementIoCount(deviceObject); //still +1 on the IO count after this, leaving one for the workitem to decrement
  182. ExFreePool(context);
  183. ExFreePool(urb);
  184. return ntStatus;
  185. }
  186. NTSTATUS USBPRINT_ResetWorkItem(IN PDEVICE_OBJECT deviceObject, IN PVOID Context)
  187. {
  188. PUSBPRINT_WORKITEM_CONTEXT pResetWorkItemObj;
  189. PDEVICE_EXTENSION DeviceExtension;
  190. NTSTATUS ntStatus;
  191. ULONG portStatus;
  192. PDEVICE_OBJECT devObj;
  193. USBPRINT_KdPrint2(("USBPRINT.SYS: Entering USBPRINT_ResetWorkItem\n"));
  194. pResetWorkItemObj=(PUSBPRINT_WORKITEM_CONTEXT)Context;
  195. DeviceExtension=pResetWorkItemObj->deviceObject->DeviceExtension;
  196. ntStatus=USBPRINT_ResetPipe(pResetWorkItemObj->deviceObject,pResetWorkItemObj->pPipeInfo,FALSE);
  197. IoCompleteRequest(pResetWorkItemObj->irp,IO_NO_INCREMENT);
  198. IoFreeWorkItem(pResetWorkItemObj->ioWorkItem);
  199. // save off work item device object before freeing work item
  200. devObj = pResetWorkItemObj->deviceObject;
  201. ExFreePool(pResetWorkItemObj);
  202. InterlockedExchange(&(DeviceExtension->ResetWorkItemPending),0);
  203. USBPRINT_DecrementIoCount(devObj);
  204. return ntStatus;
  205. }
  206. NTSTATUS
  207. USBPRINT_Read(
  208. IN PDEVICE_OBJECT DeviceObject,
  209. IN PIRP Irp
  210. )
  211. /*++
  212. Routine Description:
  213. Arguments:
  214. DeviceObject - pointer to the device object for this instance of a printer.
  215. Return Value:
  216. NT status code
  217. --*/
  218. {
  219. NTSTATUS ntStatus = STATUS_SUCCESS;
  220. PUSBD_PIPE_INFORMATION pipeHandle = NULL;
  221. PFILE_OBJECT fileObject;
  222. PIO_STACK_LOCATION irpStack, nextStack;
  223. PDEVICE_EXTENSION deviceExtension;
  224. PURB urb;
  225. PUSBPRINT_RW_CONTEXT context = NULL;
  226. USBPRINT_KdPrint3 (("USBPRINT.SYS: /*dd enter USBPRINT_Read\n\n\n\n\n\n"));
  227. USBPRINT_KdPrint3 (("USBPRINT.SYS: /*dd **************************************************************************\n"));
  228. USBPRINT_IncrementIoCount(DeviceObject);
  229. deviceExtension = DeviceObject->DeviceExtension;
  230. if (deviceExtension->IsChildDevice == TRUE)
  231. {
  232. ntStatus = STATUS_NOT_SUPPORTED;
  233. Irp->IoStatus.Status = ntStatus;
  234. Irp->IoStatus.Information = 0;
  235. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  236. USBPRINT_DecrementIoCount(DeviceObject);
  237. return ntStatus;
  238. }
  239. if (deviceExtension->AcceptingRequests == FALSE)
  240. {
  241. ntStatus = STATUS_DELETE_PENDING;
  242. Irp->IoStatus.Status = ntStatus;
  243. Irp->IoStatus.Information = 0;
  244. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  245. USBPRINT_DecrementIoCount(DeviceObject);
  246. return ntStatus;
  247. }
  248. irpStack = IoGetCurrentIrpStackLocation (Irp);
  249. fileObject = irpStack->FileObject;
  250. pipeHandle = deviceExtension->pReadPipe;
  251. if (!pipeHandle) {
  252. ntStatus = STATUS_INVALID_HANDLE;
  253. goto USBPRINT_Read_Reject;
  254. }
  255. //
  256. // submit the Read request to USB
  257. //
  258. switch (pipeHandle->PipeType) {
  259. case UsbdPipeTypeInterrupt:
  260. case UsbdPipeTypeBulk:
  261. urb = USBPRINT_BuildAsyncRequest(DeviceObject,
  262. Irp,
  263. pipeHandle,
  264. TRUE);
  265. if (urb) {
  266. context = ExAllocatePoolWithTag(NonPagedPool, sizeof(USBPRINT_RW_CONTEXT), USBP_TAG);
  267. if ( !context )
  268. ExFreePool(urb);
  269. }
  270. if (urb && context) {
  271. context->Urb = urb;
  272. context->DeviceObject = DeviceObject;
  273. context->IsWrite=FALSE;
  274. nextStack = IoGetNextIrpStackLocation(Irp);
  275. ASSERT(nextStack != NULL);
  276. ASSERT(DeviceObject->StackSize>1);
  277. nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  278. nextStack->Parameters.Others.Argument1 = urb;
  279. nextStack->Parameters.DeviceIoControl.IoControlCode =
  280. IOCTL_INTERNAL_USB_SUBMIT_URB;
  281. IoSetCompletionRoutine(Irp,
  282. USBPRINT_AsyncReadWrite_Complete,
  283. context,
  284. TRUE,
  285. TRUE,
  286. TRUE);
  287. USBPRINT_KdPrint3 (("USBPRINT.SYS: IRP = 0x%x current = 0x%x next = 0x%x\n",
  288. Irp, irpStack, nextStack));
  289. // start perf timer here if needed
  290. IoMarkIrpPending(Irp);
  291. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
  292. Irp);
  293. ntStatus=STATUS_PENDING;
  294. goto USBPRINT_Read_Done;
  295. }
  296. else
  297. {
  298. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  299. }
  300. break;
  301. default:
  302. ntStatus = STATUS_INVALID_PARAMETER;
  303. TRAP();
  304. }
  305. USBPRINT_Read_Reject:
  306. USBPRINT_DecrementIoCount(DeviceObject);
  307. Irp->IoStatus.Status = ntStatus;
  308. Irp->IoStatus.Information = 0;
  309. IoCompleteRequest (Irp,
  310. IO_NO_INCREMENT
  311. );
  312. USBPRINT_Read_Done:
  313. return ntStatus;
  314. }
  315. NTSTATUS
  316. USBPRINT_Write(
  317. IN PDEVICE_OBJECT DeviceObject,
  318. IN PIRP Irp
  319. )
  320. /*++
  321. Routine Description:
  322. This function services WRITE requests for this device (probably from the user mode USB port monitor)
  323. Arguments:
  324. DeviceObject - pointer to the device object for this printer
  325. Return Value:
  326. NT status code
  327. --*/
  328. {
  329. NTSTATUS ntStatus = STATUS_SUCCESS;
  330. PUSBD_PIPE_INFORMATION pipeHandle = NULL;
  331. PFILE_OBJECT fileObject;
  332. PIO_STACK_LOCATION irpStack, nextStack;
  333. PDEVICE_EXTENSION deviceExtension;
  334. PURB urb;
  335. PUSBPRINT_RW_CONTEXT context = NULL;
  336. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_Write (foo)\n"));
  337. USBPRINT_IncrementIoCount(DeviceObject);
  338. deviceExtension = DeviceObject->DeviceExtension;
  339. if (deviceExtension->IsChildDevice == TRUE)
  340. {
  341. USBPRINT_KdPrint1 (("USBPRINT.SYS: failure because bChildDevice=TRUE\n"));
  342. ntStatus = STATUS_NOT_SUPPORTED;
  343. Irp->IoStatus.Status = ntStatus;
  344. Irp->IoStatus.Information = 0;
  345. USBPRINT_DecrementIoCount(DeviceObject);
  346. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  347. return ntStatus;
  348. }
  349. if (deviceExtension->AcceptingRequests == FALSE)
  350. {
  351. USBPRINT_KdPrint1 (("USBPRINT.SYS: failure because AcceptingRequests=FALSE\n"));
  352. ntStatus = STATUS_DELETE_PENDING;
  353. Irp->IoStatus.Status = ntStatus;
  354. Irp->IoStatus.Information = 0;
  355. USBPRINT_DecrementIoCount(DeviceObject);
  356. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  357. return ntStatus;
  358. }
  359. irpStack = IoGetCurrentIrpStackLocation (Irp);
  360. fileObject = irpStack->FileObject;
  361. // MmProbeAndLockPages(Irp->MdlAddress,
  362. // KernelMode,
  363. // IoReadAccess);
  364. pipeHandle = deviceExtension->pWritePipe;
  365. if (!pipeHandle)
  366. {
  367. USBPRINT_KdPrint1 (("USBPRINT.SYS: failure because pipe is bad\n"));
  368. ntStatus = STATUS_INVALID_HANDLE;
  369. goto USBPRINT_Write_Reject;
  370. }
  371. //
  372. // submit the write request to USB
  373. //
  374. switch (pipeHandle->PipeType)
  375. {
  376. case UsbdPipeTypeInterrupt:
  377. case UsbdPipeTypeBulk:
  378. urb = USBPRINT_BuildAsyncRequest(DeviceObject,
  379. Irp,
  380. pipeHandle,
  381. FALSE);
  382. if (urb)
  383. {
  384. context = ExAllocatePoolWithTag(NonPagedPool, sizeof(USBPRINT_RW_CONTEXT), USBP_TAG);
  385. if(!context)
  386. ExFreePool(urb);
  387. }
  388. if (urb && context)
  389. {
  390. context->Urb = urb;
  391. context->DeviceObject = DeviceObject;
  392. context->IsWrite=TRUE;
  393. nextStack = IoGetNextIrpStackLocation(Irp);
  394. ASSERT(nextStack != NULL);
  395. ASSERT(DeviceObject->StackSize>1);
  396. nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  397. nextStack->Parameters.Others.Argument1 = urb;
  398. nextStack->Parameters.DeviceIoControl.IoControlCode =
  399. IOCTL_INTERNAL_USB_SUBMIT_URB;
  400. IoSetCompletionRoutine(Irp,
  401. USBPRINT_AsyncReadWrite_Complete,
  402. context,
  403. TRUE,
  404. TRUE,
  405. TRUE);
  406. USBPRINT_KdPrint3 (("USBPRINT.SYS: IRP = 0x%x current = 0x%x next = 0x%x\n",Irp, irpStack, nextStack));
  407. IoMarkIrpPending(Irp);
  408. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,Irp);
  409. ntStatus=STATUS_PENDING;
  410. goto USBPRINT_Write_Done;
  411. }
  412. else
  413. {
  414. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  415. }
  416. break;
  417. default:
  418. ntStatus = STATUS_INVALID_PARAMETER;
  419. TRAP();
  420. }
  421. USBPRINT_Write_Reject:
  422. USBPRINT_DecrementIoCount(DeviceObject);
  423. Irp->IoStatus.Status = ntStatus;
  424. Irp->IoStatus.Information = 0;
  425. IoCompleteRequest (Irp,
  426. IO_NO_INCREMENT
  427. );
  428. USBPRINT_Write_Done:
  429. USBPRINT_KdPrint3 (("USBPRINT.SYS: Write Done, status= 0x%08X\n",ntStatus));
  430. return ntStatus;
  431. }
  432. NTSTATUS
  433. USBPRINT_Close(
  434. IN PDEVICE_OBJECT DeviceObject,
  435. IN PIRP Irp
  436. )
  437. /*++
  438. Routine Description:
  439. Arguments:
  440. DeviceObject - pointer to the device object for this printer
  441. Return Value:
  442. NT status code
  443. --*/
  444. {
  445. NTSTATUS ntStatus;
  446. PFILE_OBJECT fileObject;
  447. PIO_STACK_LOCATION irpStack;
  448. PDEVICE_EXTENSION deviceExtension;
  449. PUSBD_PIPE_INFORMATION pipeHandle = NULL;
  450. USBPRINT_KdPrint2 (("USBPRINT.SYS: entering USBPRINT_Close\n"));
  451. USBPRINT_IncrementIoCount(DeviceObject);
  452. deviceExtension = DeviceObject->DeviceExtension;
  453. irpStack = IoGetCurrentIrpStackLocation (Irp);
  454. fileObject = irpStack->FileObject;
  455. if (fileObject->FsContext)
  456. {
  457. // closing pipe handle
  458. pipeHandle = fileObject->FsContext;
  459. USBPRINT_KdPrint3 (("USBPRINT.SYS: closing pipe %x\n", pipeHandle));
  460. }
  461. deviceExtension->OpenCnt--;
  462. Irp->IoStatus.Status = STATUS_SUCCESS;
  463. Irp->IoStatus.Information = 0;
  464. ntStatus = Irp->IoStatus.Status;
  465. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  466. USBPRINT_DecrementIoCount(DeviceObject);
  467. if(!deviceExtension->IsChildDevice)
  468. {
  469. USBPRINT_FdoSubmitIdleRequestIrp(deviceExtension);
  470. }
  471. return ntStatus;
  472. }
  473. NTSTATUS
  474. USBPRINT_Create(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
  475. /*++
  476. Routine Description:
  477. //
  478. // Entry point for CreateFile calls
  479. // user mode apps open device interfaces via
  480. // SetupDiEnumDeviceInterfaces
  481. Arguments:
  482. DeviceObject - pointer to the device object for this printer.
  483. Return Value:
  484. NT status code
  485. --*/
  486. {
  487. NTSTATUS ntStatus = STATUS_SUCCESS;
  488. PFILE_OBJECT fileObject;
  489. PIO_STACK_LOCATION irpStack;
  490. PDEVICE_EXTENSION deviceExtension;
  491. USBPRINT_KdPrint2 (("USBPRINT.SYS: entering USBPRINT_Create\n"));
  492. USBPRINT_IncrementIoCount(DeviceObject);
  493. deviceExtension = DeviceObject->DeviceExtension;
  494. if (deviceExtension->IsChildDevice==TRUE) {
  495. ntStatus = STATUS_NOT_SUPPORTED;
  496. Irp->IoStatus.Status = ntStatus;
  497. Irp->IoStatus.Information = 0;
  498. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  499. USBPRINT_DecrementIoCount(DeviceObject);
  500. return ntStatus;
  501. }
  502. if (deviceExtension->AcceptingRequests == FALSE) {
  503. ntStatus = STATUS_DELETE_PENDING;
  504. Irp->IoStatus.Status = ntStatus;
  505. Irp->IoStatus.Information = 0;
  506. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  507. USBPRINT_DecrementIoCount(DeviceObject);
  508. return ntStatus;
  509. }
  510. USBPRINT_FdoRequestWake(deviceExtension);
  511. irpStack = IoGetCurrentIrpStackLocation (Irp);
  512. fileObject = irpStack->FileObject;
  513. // fscontext is null for device
  514. fileObject->FsContext = NULL;
  515. deviceExtension->OpenCnt++;
  516. ntStatus = STATUS_SUCCESS;
  517. Irp->IoStatus.Status = ntStatus;
  518. Irp->IoStatus.Information = 0;
  519. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  520. USBPRINT_DecrementIoCount(DeviceObject);
  521. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_Create %x\n", ntStatus));
  522. return ntStatus;
  523. }