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.

3584 lines
113 KiB

  1. /*++
  2. Copyright (c) 1997-1998 Microsoft Corporation
  3. Module Name:
  4. USBPRINT.c
  5. Abstract:
  6. Device driver for USB printers
  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) 1996 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 5-4-96 : created
  17. --*/
  18. #define DRIVER
  19. //Windows includes
  20. #include "wdm.h"
  21. #include "ntddpar.h"
  22. #include "initguid.h"
  23. #include "wdmguid.h"
  24. NTSTATUS
  25. USBPRINT_SystemControl(
  26. IN PDEVICE_OBJECT DeviceObject,
  27. IN PIRP Irp
  28. );
  29. #ifdef ALLOC_PRAGMA
  30. #pragma alloc_text(PAGE, USBPRINT_SystemControl)
  31. #endif
  32. #include "stdarg.h"
  33. #include "stdio.h"
  34. //USB includes
  35. #include <usb.h>
  36. #include <usbdrivr.h>
  37. #include "usbdlib.h"
  38. //My includes
  39. #include "usbprint.h"
  40. #include "deviceid.h"
  41. //
  42. // Global pointer to Driver Object
  43. //
  44. PDRIVER_OBJECT USBPRINT_DriverObject;
  45. int iGMessageLevel;
  46. PFREE_PORTS pGPortList;
  47. HANDLE GLogHandle;
  48. NTSTATUS QueryDeviceRelations(PDEVICE_OBJECT DeviceObject,PIRP Irp,DEVICE_RELATION_TYPE,BOOL *pbComplete);
  49. NTSTATUS GetPortNumber(HANDLE hInterfaceKey,ULONG *ulPortNumber);
  50. NTSTATUS ProduceQueriedID(PDEVICE_EXTENSION deviceExtension,PIO_STACK_LOCATION irpStack,PIRP Irp,PDEVICE_OBJECT DeviceObject);
  51. int iGetMessageLevel();
  52. NTSTATUS USBPRINT_ProcessChildPowerIrp(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);
  53. NTSTATUS USBPRINT_ProcessFdoPowerIrp(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);
  54. NTSTATUS InitFreePorts( PFREE_PORTS * pHead );
  55. NTSTATUS bAddPortInUseItem(PFREE_PORTS * pFreePorts,ULONG iPortNumber );
  56. NTSTATUS LoadPortsUsed(GUID *pPrinterGuid,PFREE_PORTS * pPortList,WCHAR *wcBaseName);
  57. void ClearFreePorts(PFREE_PORTS * pHead);
  58. NTSTATUS LoadPortsUsed(GUID *pPrinterGuid,PFREE_PORTS * pPortList,WCHAR *wcBaseName);
  59. void vClaimPortNumber(ULONG ulPortNumber,HANDLE hInterfaceKey,PFREE_PORTS * pPortsUsed);
  60. NTSTATUS GetNewPortNumber(PFREE_PORTS * pFreePorts, ULONG *pulPortNumber);
  61. BOOL bDeleteIfRecyclable(HANDLE hInterfaceKey);
  62. NTSTATUS SetValueToZero(HANDLE hRegKey,PUNICODE_STRING ValueName);
  63. USBPRINT_GetDeviceID(PDEVICE_OBJECT ParentDeviceObject);
  64. void WritePortDescription(PDEVICE_EXTENSION deviceExtension);
  65. void vOpenLogFile(IN HANDLE *pHandle);
  66. void vWriteToLogFile(IN HANDLE *pHandle,IN CHAR *pszString);
  67. void vCloseLogFile(IN HANDLE *pHandle);
  68. NTSYSAPI
  69. NTSTATUS
  70. NTAPI
  71. ZwDeleteValueKey(
  72. IN HANDLE KeyHandle,
  73. IN PUNICODE_STRING ValueName
  74. );
  75. NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
  76. /*++
  77. Routine Description:
  78. Installable driver initialization entry point.
  79. This entry point is called directly by the I/O system.
  80. Arguments:
  81. DriverObject - pointer to the driver object
  82. RegistryPath - pointer to a unicode string representing the path
  83. to driver-specific key in the registry
  84. Return Value:
  85. STATUS_SUCCESS if successful,
  86. STATUS_UNSUCCESSFUL otherwise
  87. --*/
  88. {
  89. NTSTATUS ntStatus = STATUS_SUCCESS;
  90. PDEVICE_OBJECT deviceObject = NULL;
  91. USBPRINT_DriverObject = DriverObject;
  92. //
  93. // Create dispatch points for device control, create, close.
  94. //
  95. DriverObject->MajorFunction[IRP_MJ_CREATE] = USBPRINT_Create;
  96. DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBPRINT_Close;
  97. DriverObject->DriverUnload = USBPRINT_Unload;
  98. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBPRINT_ProcessIOCTL;
  99. DriverObject->MajorFunction[IRP_MJ_WRITE] = USBPRINT_Write;
  100. DriverObject->MajorFunction[IRP_MJ_READ] = USBPRINT_Read;
  101. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = USBPRINT_SystemControl;
  102. DriverObject->MajorFunction[IRP_MJ_PNP] = USBPRINT_Dispatch;
  103. DriverObject->MajorFunction[IRP_MJ_POWER] = USBPRINT_ProcessPowerIrp;
  104. DriverObject->DriverExtension->AddDevice = USBPRINT_PnPAddDevice;
  105. iGMessageLevel=iGetMessageLevel();
  106. USBPRINT_KdPrint2 (("USBPRINT.SYS: entering (USBPRINT) DriverEntry\n"));
  107. USBPRINT_KdPrint2 (("USBPRINT.SYS: MessageLevel=%d\n",iGMessageLevel));
  108. USBPRINT_KdPrint2 (("USBPRINT.SYS: About to load ports\n"));
  109. pGPortList = NULL;
  110. ntStatus=InitFreePorts(&pGPortList);
  111. if(NT_SUCCESS(ntStatus) && pGPortList!=NULL)
  112. {
  113. ntStatus=LoadPortsUsed((GUID *)&USBPRINT_GUID,&pGPortList,USB_BASE_NAME);
  114. if(!NT_SUCCESS(ntStatus))
  115. {
  116. USBPRINT_KdPrint1 (("USBPRINT.SYS: DriverInit: Unable to load used ports; error=%u\n", ntStatus));
  117. }
  118. }
  119. else
  120. {
  121. USBPRINT_KdPrint1 (("USBPRINT.SYS: exiting (USBPRINT) DriverEntry (%x)\n", ntStatus));
  122. if(NT_SUCCESS(ntStatus))
  123. {
  124. ntStatus=STATUS_INSUFFICIENT_RESOURCES;
  125. }
  126. }
  127. USBPRINT_KdPrint2 (("USBPRINT.SYS: exiting (USBPRINT) DriverEntry (%x)\n", ntStatus));
  128. if ( !NT_SUCCESS(ntStatus))
  129. ClearFreePorts(&pGPortList);
  130. return ntStatus;
  131. }
  132. /*********************************************
  133. * Message Levels:
  134. * 0 == None, except critical, about to crash the machine failures
  135. * 1 == Error messages only
  136. * 2 == Informative messages
  137. * 3 == Verbose informative messages
  138. ******************************************************/
  139. int iGetMessageLevel()
  140. {
  141. OBJECT_ATTRIBUTES rObjectAttribs;
  142. HANDLE hRegHandle;
  143. UNICODE_STRING KeyName;
  144. UNICODE_STRING ValueName;
  145. ULONG ulSizeUsed;
  146. PKEY_VALUE_PARTIAL_INFORMATION pValueStruct;
  147. NTSTATUS ntStatus;
  148. int iReturn;
  149. RtlInitUnicodeString(&KeyName,L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\USBPRINT");
  150. RtlInitUnicodeString(&ValueName,L"DriverMessageLevel");
  151. InitializeObjectAttributes(&rObjectAttribs,&KeyName,OBJ_CASE_INSENSITIVE,NULL,NULL);
  152. ntStatus=ZwOpenKey(&hRegHandle,KEY_QUERY_VALUE,&rObjectAttribs);
  153. if(NT_SUCCESS(ntStatus))
  154. {
  155. ulSizeUsed=sizeof(KEY_VALUE_PARTIAL_INFORMATION)+sizeof(ULONG); //this is a byte to much. Oh well
  156. pValueStruct=ExAllocatePoolWithTag(NonPagedPool,ulSizeUsed, USBP_TAG);
  157. if(pValueStruct==NULL)
  158. {
  159. USBPRINT_KdPrint0(("'USBPRINT.SYS: iGetMessageLevel; Unable to allocate memory\n"));
  160. ZwClose(hRegHandle);
  161. return 1;
  162. }
  163. ntStatus=ZwQueryValueKey(hRegHandle,&ValueName,KeyValuePartialInformation,pValueStruct,ulSizeUsed,&ulSizeUsed);
  164. if(!NT_SUCCESS(ntStatus))
  165. {
  166. USBPRINT_KdPrint3(("Failed to Query value Key\n"));
  167. iReturn=1;
  168. }
  169. else
  170. {
  171. iReturn=(int)*((ULONG *)(pValueStruct->Data));
  172. }
  173. ExFreePool(pValueStruct);
  174. ZwClose(hRegHandle);
  175. }
  176. else
  177. {
  178. iReturn=1;
  179. }
  180. return iReturn;
  181. } /*end iGetMessageLevel*/
  182. NTSTATUS
  183. USBPRINT_PoRequestCompletion(
  184. IN PDEVICE_OBJECT DeviceObject,
  185. IN UCHAR MinorFunction,
  186. IN POWER_STATE PowerState,
  187. IN PVOID Context,
  188. IN PIO_STATUS_BLOCK IoStatus
  189. )
  190. /*++
  191. Routine Description:
  192. This routine is called when the port driver completes an IRP.
  193. Arguments:
  194. DeviceObject - Pointer to the device object for the class device.
  195. Context - Driver defined context.
  196. Return Value:
  197. The function value is the final status from the operation.
  198. --*/
  199. {
  200. PIRP irp;
  201. PDEVICE_EXTENSION deviceExtension;
  202. PDEVICE_OBJECT deviceObject = Context;
  203. NTSTATUS ntStatus;
  204. deviceExtension = deviceObject->DeviceExtension;
  205. irp = deviceExtension->PowerIrp;
  206. USBPRINT_KdPrint2(("USBPRINT_PoRequestCompletion\n"));
  207. PoStartNextPowerIrp(irp);
  208. IoCopyCurrentIrpStackLocationToNext(irp);
  209. ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject,
  210. irp);
  211. USBPRINT_DecrementIoCount(deviceObject);
  212. return ntStatus;
  213. }
  214. NTSTATUS
  215. USBPRINT_PowerIrp_Complete(
  216. IN PDEVICE_OBJECT NullDeviceObject,
  217. IN PIRP Irp,
  218. IN PVOID Context
  219. )
  220. /*++
  221. Routine Description:
  222. This routine is called when the port driver completes an IRP.
  223. Arguments:
  224. DeviceObject - Pointer to the device object for the class device.
  225. Irp - Irp completed.
  226. Context - Driver defined context.
  227. Return Value:
  228. The function value is the final status from the operation.
  229. --*/
  230. {
  231. NTSTATUS ntStatus = STATUS_SUCCESS;
  232. PDEVICE_OBJECT deviceObject;
  233. PIO_STACK_LOCATION irpStack;
  234. PDEVICE_EXTENSION deviceExtension;
  235. USBPRINT_KdPrint2(("USBPRINT.SYS: enter USBPRINT_PowerIrp_Complete\n"));
  236. deviceObject = (PDEVICE_OBJECT) Context;
  237. deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
  238. if (Irp->PendingReturned) {
  239. IoMarkIrpPending(Irp);
  240. }
  241. irpStack = IoGetCurrentIrpStackLocation (Irp);
  242. ASSERT(irpStack->MajorFunction == IRP_MJ_POWER);
  243. ASSERT(irpStack->MinorFunction == IRP_MN_SET_POWER);
  244. ASSERT(irpStack->Parameters.Power.Type==DevicePowerState);
  245. ASSERT(irpStack->Parameters.Power.State.DeviceState==PowerDeviceD0);
  246. deviceExtension->CurrentDevicePowerState = PowerDeviceD0;
  247. deviceExtension->bD0IrpPending=FALSE;
  248. // if (deviceExtension->Interface)
  249. // ExFreePool(deviceExtension->Interface);
  250. // ntStatus=USBPRINT_ConfigureDevice(deviceObject);
  251. // ntStatus = USBPRINT_BuildPipeList(deviceObject);
  252. // if(!NT_SUCCESS(ntStatus))
  253. // USBPRINT_KdPrint1(("USBPRINT.SYS : Unable to reconfigure device after wakeup. Error %x\n",ntStatus));
  254. Irp->IoStatus.Status = ntStatus;
  255. USBPRINT_DecrementIoCount(deviceObject);
  256. return ntStatus;
  257. }
  258. NTSTATUS
  259. USBPRINT_SetDevicePowerState(
  260. IN PDEVICE_OBJECT DeviceObject,
  261. IN DEVICE_POWER_STATE DeviceState,
  262. IN PBOOLEAN HookIt
  263. )
  264. /*++
  265. Routine Description:
  266. Arguments:
  267. DeviceObject - Pointer to the device object for the class device.
  268. Irp - Irp completed.
  269. DeviceState - Device specific power state to set the device in to.
  270. Return Value:
  271. --*/
  272. {
  273. NTSTATUS ntStatus = STATUS_SUCCESS;
  274. PDEVICE_EXTENSION deviceExtension;
  275. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  276. switch (DeviceState) {
  277. case PowerDeviceD3:
  278. //
  279. // device will be going OFF, save any state now.
  280. //
  281. USBPRINT_KdPrint2(("USBPRINT.SYS: PowerDeviceD3 (OFF)*******************************/*dd\n"));
  282. deviceExtension->CurrentDevicePowerState = DeviceState;
  283. break;
  284. case PowerDeviceD1:
  285. case PowerDeviceD2:
  286. //
  287. // power states D1,D2 translate to USB suspend
  288. USBPRINT_KdPrint2(("USBPRINT.SYS: PowerDeviceD1/D2 (SUSPEND)*******************************/*dd\n"));
  289. deviceExtension->CurrentDevicePowerState = DeviceState;
  290. break;
  291. case PowerDeviceD0:
  292. USBPRINT_KdPrint2(("USBPRINT.SYS: PowerDeviceD0 (ON)*******************************/*dd\n"));
  293. //
  294. // finish the rest in the completion routine
  295. //
  296. *HookIt = TRUE;
  297. // pass on to PDO
  298. break;
  299. default:
  300. USBPRINT_KdPrint1(("USBPRINT.SYS: Bogus DeviceState = %x\n", DeviceState));
  301. }
  302. return ntStatus;
  303. }
  304. NTSTATUS
  305. USBPRINT_DeferIrpCompletion(
  306. IN PDEVICE_OBJECT DeviceObject,
  307. IN PIRP Irp,
  308. IN PVOID Context
  309. )
  310. /*++
  311. Routine Description:
  312. This routine is called when the port driver completes an IRP.
  313. Arguments:
  314. DeviceObject - Pointer to the device object for the class device.
  315. Irp - Irp completed.
  316. Context - Driver defined context.
  317. Return Value:
  318. The function value is the final status from the operation.
  319. --*/
  320. {
  321. PKEVENT event = Context;
  322. KeSetEvent(event,1,FALSE);
  323. return STATUS_MORE_PROCESSING_REQUIRED;
  324. }
  325. NTSTATUS
  326. USBPRINT_QueryCapabilities(
  327. IN PDEVICE_OBJECT PdoDeviceObject,
  328. IN PDEVICE_CAPABILITIES DeviceCapabilities
  329. )
  330. /*++
  331. Routine Description:
  332. This routine reads or write config space.
  333. Arguments:
  334. DeviceObject - Physical DeviceObject for this USB controller.
  335. Return Value:
  336. None.
  337. --*/
  338. {
  339. PIO_STACK_LOCATION nextStack;
  340. PIRP irp;
  341. NTSTATUS ntStatus;
  342. KEVENT event;
  343. PAGED_CODE();
  344. irp = IoAllocateIrp(PdoDeviceObject->StackSize, FALSE);
  345. if (!irp) {
  346. return STATUS_INSUFFICIENT_RESOURCES;
  347. }
  348. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  349. nextStack = IoGetNextIrpStackLocation(irp);
  350. ASSERT(nextStack != NULL);
  351. nextStack->MajorFunction= IRP_MJ_PNP;
  352. nextStack->MinorFunction= IRP_MN_QUERY_CAPABILITIES;
  353. KeInitializeEvent(&event, NotificationEvent, FALSE);
  354. IoSetCompletionRoutine(irp,
  355. USBPRINT_DeferIrpCompletion,
  356. &event,
  357. TRUE,
  358. TRUE,
  359. TRUE);
  360. //this is different from the latest version of busdd.doc
  361. nextStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities;
  362. ntStatus = IoCallDriver(PdoDeviceObject,
  363. irp);
  364. USBPRINT_KdPrint3(("USBPRINT.SYS: ntStatus from IoCallDriver to PCI = 0x%x\n", ntStatus));
  365. if (ntStatus == STATUS_PENDING) {
  366. // wait for irp to complete
  367. KeWaitForSingleObject(
  368. &event,
  369. Suspended,
  370. KernelMode,
  371. FALSE,
  372. NULL);
  373. }
  374. #if DBG
  375. if (!NT_SUCCESS(ntStatus)) {
  376. // failed? this is probably a bug
  377. USBPRINT_KdPrint1(("USBPRINT.SYS: QueryCapabilities failed, why?\n"));
  378. }
  379. #endif
  380. IoFreeIrp(irp);
  381. return STATUS_SUCCESS;
  382. }
  383. NTSTATUS
  384. USBPRINT_ProcessPowerIrp(
  385. IN PDEVICE_OBJECT DeviceObject,
  386. IN PIRP Irp
  387. )
  388. {
  389. PDEVICE_EXTENSION deviceExtension;
  390. BOOLEAN hookIt = FALSE;
  391. NTSTATUS ntStatus;
  392. USBPRINT_KdPrint2(("USBPRINT.SYS: /*****************************************************************IRP_MJ_POWER\n"));
  393. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  394. if(deviceExtension->IsChildDevice)
  395. ntStatus=USBPRINT_ProcessChildPowerIrp(DeviceObject,Irp);
  396. else
  397. ntStatus=USBPRINT_ProcessFdoPowerIrp(DeviceObject,Irp);
  398. USBPRINT_KdPrint3(("USBPRINT.SYS: /*****************************************************************Leaving power IRP_MJ_POWER\n"));
  399. return ntStatus;
  400. } /*end function USBPRINT_ProcessPowerIrp*/
  401. NTSTATUS
  402. USBPRINT_ProcessChildPowerIrp(
  403. IN PDEVICE_OBJECT DeviceObject,
  404. IN PIRP Irp
  405. )
  406. {
  407. PIO_STACK_LOCATION irpStack;
  408. NTSTATUS ntStatus;
  409. PCHILD_DEVICE_EXTENSION pDeviceExtension;
  410. USBPRINT_KdPrint2(("USBPRINT.SYS: IRP_MJ_POWER for child PDO\n"));
  411. pDeviceExtension=(PCHILD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
  412. irpStack=IoGetCurrentIrpStackLocation(Irp);
  413. switch(irpStack->MinorFunction)
  414. {
  415. case IRP_MN_SET_POWER:
  416. USBPRINT_KdPrint3(("USBPRINT.SYS: IRP_MJ_POWER, IRP_MN_SET_POWER\n"));
  417. ntStatus=STATUS_SUCCESS;
  418. break;
  419. case IRP_MN_QUERY_POWER:
  420. USBPRINT_KdPrint3(("USBPRINT.SYS: IRP_MJ_POWER, IRP_MN_QUERY_POWER\n"));
  421. ntStatus=STATUS_SUCCESS;
  422. break;
  423. default:
  424. ntStatus = Irp->IoStatus.Status;
  425. } /*end switch irpStack->MinorFunction*/
  426. PoStartNextPowerIrp(Irp);
  427. Irp->IoStatus.Status=ntStatus;
  428. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  429. return ntStatus;
  430. } /*end function USBPRINT_ProcessChildPowerIrp*/
  431. NTSTATUS
  432. USBPRINT_ProcessFdoPowerIrp(
  433. IN PDEVICE_OBJECT DeviceObject,
  434. IN PIRP Irp
  435. )
  436. /*++
  437. Routine Description:
  438. Process the Power IRPs sent to the PDO for this device.
  439. Arguments:
  440. DeviceObject - pointer to a hcd device object (FDO)
  441. Irp - pointer to an I/O Request Packet
  442. Return Value:
  443. NT status code
  444. --*/
  445. {
  446. PIO_STACK_LOCATION irpStack;
  447. NTSTATUS ntStatus = STATUS_SUCCESS;
  448. PDEVICE_EXTENSION deviceExtension;
  449. BOOLEAN hookIt = FALSE;
  450. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  451. if(deviceExtension->IsChildDevice)
  452. {
  453. USBPRINT_KdPrint1(("USBPRINT.SYS Is child device inside fdo function. Error!*/\n"));
  454. }
  455. irpStack = IoGetCurrentIrpStackLocation (Irp);
  456. USBPRINT_IncrementIoCount(DeviceObject);
  457. switch(irpStack->MinorFunction)
  458. {
  459. case IRP_MN_SET_POWER:
  460. {
  461. switch(irpStack->Parameters.Power.Type)
  462. {
  463. case SystemPowerState:
  464. //
  465. // find the device power state equivalent to the given system state
  466. //
  467. {
  468. POWER_STATE powerState;
  469. USBPRINT_KdPrint3(("USBPRINT.SYS: Set Power, SystemPowerState (%d)\n",
  470. irpStack->Parameters.Power.State.SystemState));
  471. powerState.DeviceState = deviceExtension->DeviceCapabilities.DeviceState[irpStack->Parameters.Power.State.SystemState];
  472. //
  473. // are we already in this state?
  474. //
  475. if(powerState.DeviceState != deviceExtension->CurrentDevicePowerState)
  476. {
  477. // No,
  478. // request that we be put into this state
  479. //Don't touch the Irp any more after this. It could complete at any time
  480. deviceExtension->PowerIrp = Irp;
  481. IoMarkIrpPending(Irp);
  482. ntStatus = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject,
  483. IRP_MN_SET_POWER,
  484. powerState,
  485. USBPRINT_PoRequestCompletion,
  486. DeviceObject,
  487. NULL);
  488. hookIt = TRUE;
  489. }
  490. else
  491. {
  492. // Yes,
  493. // just pass it on
  494. PoStartNextPowerIrp(Irp);
  495. IoCopyCurrentIrpStackLocationToNext(Irp);
  496. ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject,
  497. Irp);
  498. }
  499. }
  500. break;
  501. case DevicePowerState:
  502. ntStatus = USBPRINT_SetDevicePowerState(DeviceObject,
  503. irpStack->Parameters.Power.State.DeviceState,
  504. &hookIt);
  505. PoStartNextPowerIrp(Irp);
  506. IoCopyCurrentIrpStackLocationToNext(Irp);
  507. if(hookIt)
  508. {
  509. USBPRINT_KdPrint2(("USBPRINT.SYS: Set PowerIrp Completion Routine\n"));
  510. IoSetCompletionRoutine(Irp,USBPRINT_PowerIrp_Complete,DeviceObject,TRUE,TRUE,TRUE);
  511. }
  512. ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject,Irp);
  513. break;
  514. } /* switch irpStack->Parameters.Power.Type */
  515. }
  516. break; /* IRP_MN_SET_POWER */
  517. default:
  518. USBPRINT_KdPrint1(("USBPRINT.SYS: UNKNOWN POWER MESSAGE (%x)\n", irpStack->MinorFunction));
  519. //
  520. // All unahndled PnP messages are passed on to the PDO
  521. //
  522. PoStartNextPowerIrp(Irp);
  523. IoCopyCurrentIrpStackLocationToNext(Irp);
  524. ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject,
  525. Irp);
  526. } /* irpStack->MinorFunction */
  527. if( !hookIt )
  528. USBPRINT_DecrementIoCount(DeviceObject);
  529. return ntStatus;
  530. } /*end function ProcessFdoPowerIrp*/
  531. NTSTATUS
  532. USBPRINT_Dispatch(
  533. IN PDEVICE_OBJECT DeviceObject,
  534. IN PIRP Irp
  535. )
  536. /*++
  537. Routine Description:
  538. Process the IRPs sent to this device.
  539. Arguments:
  540. DeviceObject - pointer to a device object
  541. Irp - pointer to an I/O Request Packet
  542. Return Value:
  543. --*/
  544. {
  545. PIO_STACK_LOCATION irpStack;
  546. PDEVICE_EXTENSION deviceExtension;
  547. NTSTATUS ntStatus = STATUS_SUCCESS;
  548. PDEVICE_OBJECT stackDeviceObject;
  549. BOOL bHandled=FALSE;
  550. //Irp->IoStatus.Status = STATUS_SUCCESS;
  551. //Irp->IoStatus.Information = 0;
  552. //
  553. // Get a pointer to the current location in the Irp. This is where
  554. // the function codes and parameters are located.
  555. //
  556. irpStack = IoGetCurrentIrpStackLocation (Irp);
  557. //
  558. // Get a pointer to the device extension
  559. //
  560. deviceExtension = DeviceObject->DeviceExtension;
  561. stackDeviceObject = deviceExtension->TopOfStackDeviceObject;
  562. #ifdef MYDEBUG
  563. DbgPrint("USBPRINT_Dispatch entry for pnp event %d\n", irpStack->MinorFunction);
  564. ASSERT(irpStack->MajorFunction == IRP_MJ_PNP);
  565. #endif
  566. USBPRINT_IncrementIoCount(DeviceObject);
  567. switch (irpStack->MinorFunction)
  568. {
  569. case IRP_MN_START_DEVICE:
  570. {
  571. if(deviceExtension->IsChildDevice==FALSE)
  572. {
  573. KEVENT event;
  574. USBPRINT_KdPrint2 (("USBPRINT.SYS: IRP_MN_START_DEVICE\n"));
  575. KeInitializeEvent(&event, NotificationEvent, FALSE);
  576. IoCopyCurrentIrpStackLocationToNext(Irp);
  577. IoSetCompletionRoutine(Irp,USBPRINT_DeferIrpCompletion,&event,TRUE,TRUE,TRUE);
  578. ntStatus = IoCallDriver(stackDeviceObject,Irp);
  579. if (ntStatus == STATUS_PENDING)
  580. {
  581. KeWaitForSingleObject(&event,Suspended,KernelMode,FALSE,NULL);
  582. ntStatus = Irp->IoStatus.Status;
  583. }
  584. if ( NT_SUCCESS(ntStatus) ) {
  585. //
  586. // You start the device after everyone below you have started it
  587. //
  588. Irp->IoStatus.Status = ntStatus = USBPRINT_StartDevice(DeviceObject);
  589. }
  590. } /*end if not child*/
  591. else
  592. {
  593. ntStatus = Irp->IoStatus.Status = STATUS_SUCCESS;
  594. }
  595. bHandled = TRUE;
  596. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  597. USBPRINT_DecrementIoCount(DeviceObject);
  598. } //end case IRP_MN_START_DEVICE
  599. break;
  600. case IRP_MN_STOP_DEVICE:
  601. if(deviceExtension->IsChildDevice)
  602. {
  603. Irp->IoStatus.Status = STATUS_SUCCESS;
  604. ntStatus=STATUS_SUCCESS;
  605. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  606. }
  607. else
  608. {
  609. USBPRINT_KdPrint2 (("USBPRINT.SYS: IRP_MN_STOP_DEVICE\n"));
  610. //
  611. // You stop the device first and then let everyone below you deal with it
  612. //
  613. ntStatus = USBPRINT_StopDevice(DeviceObject);
  614. ASSERT(NT_SUCCESS(ntStatus));
  615. //
  616. // We want to stop the device anyway ..
  617. //
  618. Irp->IoStatus.Status = STATUS_SUCCESS;
  619. IoSkipCurrentIrpStackLocation(Irp);
  620. ntStatus = IoCallDriver(stackDeviceObject,Irp);
  621. }
  622. bHandled = TRUE;
  623. USBPRINT_DecrementIoCount(DeviceObject);
  624. break;
  625. case IRP_MN_SURPRISE_REMOVAL:
  626. if(deviceExtension->IsChildDevice)
  627. {
  628. Irp->IoStatus.Status = STATUS_SUCCESS;
  629. ntStatus=STATUS_SUCCESS;
  630. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  631. }
  632. else
  633. {
  634. USBPRINT_KdPrint2(("USBPRINT.SYS: Surprise Remove"));
  635. ntStatus = USBPRINT_StopDevice(DeviceObject);
  636. ASSERT(NT_SUCCESS(ntStatus));
  637. Irp->IoStatus.Status=STATUS_SUCCESS;
  638. deviceExtension->AcceptingRequests=FALSE;
  639. IoSkipCurrentIrpStackLocation(Irp);
  640. ntStatus = IoCallDriver(stackDeviceObject,Irp);
  641. } /*end else NOT child device*/
  642. bHandled = TRUE;
  643. USBPRINT_DecrementIoCount(DeviceObject);
  644. break;
  645. case IRP_MN_REMOVE_DEVICE:
  646. if(deviceExtension->IsChildDevice==FALSE)
  647. {
  648. USBPRINT_KdPrint2 (("USBPRINT.SYS: IRP_MN_REMOVE_DEVICE\n"));
  649. // match the inc at the begining of the dispatch routine
  650. USBPRINT_DecrementIoCount(DeviceObject);
  651. ntStatus = USBPRINT_StopDevice(DeviceObject);
  652. ASSERT(NT_SUCCESS(ntStatus));
  653. Irp->IoStatus.Status=STATUS_SUCCESS;
  654. //
  655. // ounce this flag is set no irps will be pased
  656. // down the stack to lower drivers
  657. //
  658. deviceExtension->AcceptingRequests = FALSE;
  659. if(deviceExtension->bChildDeviceHere)
  660. {
  661. deviceExtension->bChildDeviceHere=FALSE;
  662. IoDeleteDevice(deviceExtension->ChildDevice);
  663. USBPRINT_KdPrint3(("USBPRINT.SYS: Deleted child device\n"));
  664. }
  665. if (NT_SUCCESS(ntStatus))
  666. {
  667. LONG pendingIoCount;
  668. USBPRINT_KdPrint3(("USBPRINT.SYS: About to copy current IrpStackLocation\n"));
  669. IoCopyCurrentIrpStackLocationToNext(Irp);
  670. ntStatus = IoCallDriver(stackDeviceObject,Irp);
  671. // Irp->IoStatus.Information = 0;
  672. //
  673. // final decrement will trigger the remove
  674. //
  675. pendingIoCount = USBPRINT_DecrementIoCount(DeviceObject);
  676. {
  677. NTSTATUS status;
  678. // wait for any io request pending in our driver to
  679. // complete for finishing the remove
  680. status = KeWaitForSingleObject(&deviceExtension->RemoveEvent,Suspended,KernelMode,FALSE,NULL);
  681. // TRAP();
  682. } /*end of non-controled code block*/
  683. //
  684. // Delete the link and FDO we created
  685. //
  686. USBPRINT_RemoveDevice(DeviceObject);
  687. USBPRINT_KdPrint3 (("USBPRINT.SYS: Detaching from %08X\n",deviceExtension->TopOfStackDeviceObject));
  688. IoDetachDevice(deviceExtension->TopOfStackDeviceObject);
  689. USBPRINT_KdPrint3 (("USBPRINT.SYS: Deleting %08X\n",DeviceObject));
  690. IoDeleteDevice (DeviceObject);
  691. } /*end if NT_SUCCESS(ntStatus)*/
  692. } /*end if IsChildDevice==FALSE*/
  693. else
  694. {
  695. USBPRINT_DecrementIoCount(DeviceObject);
  696. Irp->IoStatus.Status = STATUS_SUCCESS;
  697. ntStatus=STATUS_SUCCESS;
  698. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  699. }
  700. bHandled = TRUE;
  701. break; //case IRP_MN_REMOVE_DEVICE
  702. case IRP_MN_QUERY_CAPABILITIES:
  703. {
  704. if(deviceExtension->IsChildDevice==FALSE) //if it's the parent, pass down the irp, and set SurpriseRemovalOK on the way back up
  705. {
  706. KEVENT event;
  707. KeInitializeEvent(&event, NotificationEvent, FALSE);
  708. IoCopyCurrentIrpStackLocationToNext(Irp);
  709. IoSetCompletionRoutine(Irp,USBPRINT_DeferIrpCompletion,&event,TRUE,TRUE,TRUE);
  710. ntStatus = IoCallDriver(stackDeviceObject,Irp);
  711. if (ntStatus == STATUS_PENDING)
  712. {
  713. KeWaitForSingleObject(&event,Suspended,KernelMode,FALSE,NULL);
  714. ntStatus = Irp->IoStatus.Status;
  715. }
  716. if ( NT_SUCCESS(ntStatus) )
  717. irpStack->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = TRUE;
  718. // get device wake for selective suspend
  719. deviceExtension->DeviceWake = irpStack->Parameters.DeviceCapabilities.Capabilities->DeviceWake;
  720. }
  721. else
  722. {
  723. irpStack->Parameters.DeviceCapabilities.Capabilities->RawDeviceOK = TRUE;
  724. irpStack->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = TRUE;
  725. Irp->IoStatus.Status = STATUS_SUCCESS;
  726. ntStatus=STATUS_SUCCESS;
  727. }
  728. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  729. bHandled = TRUE;
  730. USBPRINT_DecrementIoCount(DeviceObject);
  731. }
  732. break;
  733. case IRP_MN_QUERY_DEVICE_TEXT:
  734. USBPRINT_KdPrint2 (("USBPRINT.SYS: IRP_MN_QUERY_DEVICE_TEXT\n"));
  735. if(deviceExtension->IsChildDevice==TRUE)
  736. {
  737. PCHILD_DEVICE_EXTENSION pChildDeviceExtension=(PCHILD_DEVICE_EXTENSION)deviceExtension;
  738. PDEVICE_EXTENSION pParentExtension=pChildDeviceExtension->ParentDeviceObject->DeviceExtension;
  739. USBPRINT_KdPrint2(("USBPRINT.SYS: Is child PDO, will complete locally\n"));
  740. switch(irpStack->Parameters.QueryDeviceText.DeviceTextType)
  741. {
  742. case DeviceTextDescription:
  743. {
  744. ANSI_STRING AnsiTextString;
  745. UNICODE_STRING UnicodeDeviceText;
  746. RtlInitAnsiString(&AnsiTextString,pParentExtension->DeviceIdString);
  747. ntStatus=RtlAnsiStringToUnicodeString(&UnicodeDeviceText,&AnsiTextString,TRUE);
  748. USBPRINT_KdPrint2(("USBPRINT.SYS: QUERY_DEVICE_TEXT, DeviceID=%s\n",pParentExtension->DeviceIdString));
  749. if(NT_SUCCESS(ntStatus))
  750. Irp->IoStatus.Information=(ULONG_PTR)UnicodeDeviceText.Buffer;
  751. }
  752. break;
  753. default:
  754. ntStatus=Irp->IoStatus.Status;
  755. }
  756. bHandled=TRUE;
  757. USBPRINT_DecrementIoCount(DeviceObject);
  758. Irp->IoStatus.Status = ntStatus;
  759. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  760. }
  761. break;
  762. case IRP_MN_QUERY_BUS_INFORMATION:
  763. if(deviceExtension->IsChildDevice==TRUE)
  764. {
  765. PPNP_BUS_INFORMATION pBusInfo = ExAllocatePool( PagedPool, sizeof(PNP_BUS_INFORMATION) );
  766. USBPRINT_KdPrint2(("USBPRINT.SYS: IRP_MN_QUERY_BUS_INFORMATION\n"));
  767. if( pBusInfo )
  768. {
  769. pBusInfo->BusTypeGuid = GUID_BUS_TYPE_USBPRINT;
  770. pBusInfo->LegacyBusType = PNPBus;
  771. pBusInfo->BusNumber = 0;
  772. ntStatus = STATUS_SUCCESS;
  773. Irp->IoStatus.Information = (ULONG_PTR)pBusInfo;
  774. }
  775. else
  776. {
  777. ntStatus = STATUS_NO_MEMORY;
  778. }
  779. bHandled = TRUE;
  780. USBPRINT_DecrementIoCount(DeviceObject);
  781. Irp->IoStatus.Status = ntStatus;
  782. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  783. }
  784. break;
  785. case IRP_MN_QUERY_ID:
  786. {
  787. USBPRINT_KdPrint2 (("USBPRINT.SYS: IRP_MN_QUERY_ID\n"));
  788. if(deviceExtension->IsChildDevice==TRUE)
  789. {
  790. USBPRINT_KdPrint2(("USBPRINT.SYS: Is child PDO, will complete locally\n"));
  791. ntStatus=ProduceQueriedID(deviceExtension,irpStack,Irp,DeviceObject);
  792. bHandled = TRUE;
  793. USBPRINT_DecrementIoCount(DeviceObject);
  794. Irp->IoStatus.Status = ntStatus;
  795. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  796. } /*end if child PDO*/
  797. } /*end case QUERY_ID*/
  798. break;
  799. case IRP_MN_QUERY_DEVICE_RELATIONS:
  800. USBPRINT_KdPrint2 (("USBPRINT.SYS: IRP_MN_QUERY_DEVICE_RELATIONS\n"));
  801. ntStatus=QueryDeviceRelations(DeviceObject,Irp,irpStack->Parameters.QueryDeviceRelations.Type,&bHandled);
  802. if ( bHandled )
  803. USBPRINT_DecrementIoCount(DeviceObject);
  804. break;
  805. case IRP_MN_QUERY_STOP_DEVICE:
  806. case IRP_MN_CANCEL_STOP_DEVICE:
  807. case IRP_MN_QUERY_REMOVE_DEVICE:
  808. case IRP_MN_CANCEL_REMOVE_DEVICE:
  809. if(deviceExtension->IsChildDevice)
  810. {
  811. Irp->IoStatus.Status = STATUS_SUCCESS;
  812. ntStatus=STATUS_SUCCESS;
  813. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  814. }
  815. else
  816. {
  817. ntStatus = Irp->IoStatus.Status = STATUS_SUCCESS;
  818. IoSkipCurrentIrpStackLocation(Irp);
  819. ntStatus = IoCallDriver(stackDeviceObject,Irp);
  820. }
  821. USBPRINT_DecrementIoCount(DeviceObject);
  822. bHandled = TRUE;
  823. break;
  824. } /* end IRP_MN swich inside IRP_MJ_PNP case */
  825. if(!bHandled)
  826. {
  827. if(deviceExtension->IsChildDevice==TRUE)
  828. {
  829. USBPRINT_KdPrint3(("USBPRINT.SYS: unsupported child pnp IRP\n"));
  830. ntStatus = Irp->IoStatus.Status;
  831. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  832. } /*end if child device*/
  833. else
  834. {
  835. IoSkipCurrentIrpStackLocation(Irp);
  836. ntStatus = IoCallDriver(stackDeviceObject,Irp);
  837. }
  838. USBPRINT_DecrementIoCount(DeviceObject);
  839. } /*end if !bHandled*/
  840. #ifdef MYDEBUG
  841. DbgPrint("Returning %d\n", ntStatus);
  842. #endif
  843. return ntStatus;
  844. } /*end function USBPRINT_Dispatch*/
  845. NTSTATUS
  846. USBPRINT_SystemControl(
  847. IN PDEVICE_OBJECT DeviceObject,
  848. IN PIRP Irp
  849. )
  850. /*++
  851. Routine Description:
  852. Process the IRPs sent to this device.
  853. Arguments:
  854. DeviceObject - pointer to a device object
  855. Irp - pointer to an I/O Request Packet
  856. Return Value:
  857. --*/
  858. {
  859. PDEVICE_EXTENSION deviceExtension;
  860. NTSTATUS ntStatus;
  861. PDEVICE_OBJECT stackDeviceObject;
  862. PAGED_CODE();
  863. //
  864. // Get a pointer to the device extension
  865. //
  866. deviceExtension = DeviceObject->DeviceExtension;
  867. stackDeviceObject = deviceExtension->TopOfStackDeviceObject;
  868. USBPRINT_IncrementIoCount(DeviceObject);
  869. if(deviceExtension->IsChildDevice==TRUE)
  870. {
  871. USBPRINT_KdPrint3(("USBPRINT.SYS: unsupported child SystemControl IRP\n"));
  872. ntStatus = Irp->IoStatus.Status;
  873. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  874. } /*end if child device*/
  875. else
  876. {
  877. IoSkipCurrentIrpStackLocation(Irp);
  878. ntStatus = IoCallDriver(stackDeviceObject,Irp);
  879. }
  880. USBPRINT_DecrementIoCount(DeviceObject);
  881. return ntStatus;
  882. }
  883. NTSTATUS QueryDeviceRelations(PDEVICE_OBJECT DeviceObject,PIRP Irp,DEVICE_RELATION_TYPE RelationType,BOOL *pbComplete)
  884. {
  885. PIO_STACK_LOCATION irpSp;
  886. NTSTATUS ntStatus;
  887. PDEVICE_EXTENSION pExtension;
  888. PDEVICE_RELATIONS pRelations;
  889. *pbComplete=FALSE;
  890. pExtension=(PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
  891. ntStatus=Irp->IoStatus.Status;
  892. irpSp=IoGetCurrentIrpStackLocation(Irp);
  893. if(!pExtension->IsChildDevice)
  894. {
  895. USBPRINT_KdPrint2 (("USBPRINT.SYS: Parent QueryDeviceRelations\n"));
  896. if(RelationType==BusRelations)
  897. {
  898. *pbComplete=TRUE;
  899. pRelations=(PDEVICE_RELATIONS)ExAllocatePoolWithTag(NonPagedPool,sizeof(DEVICE_RELATIONS), USBP_TAG);
  900. if(pRelations!=NULL)
  901. {
  902. //Some drivers check for pre-existing children and preserve them. This would happen if there is a filter driver above us, but we're not REALLY a bus driver
  903. pRelations->Objects[0]=pExtension->ChildDevice;
  904. pRelations->Count = 1;
  905. ObReferenceObject(pExtension->ChildDevice);
  906. Irp->IoStatus.Information=(ULONG_PTR)pRelations;
  907. Irp->IoStatus.Status = STATUS_SUCCESS;
  908. IoCopyCurrentIrpStackLocationToNext(Irp);
  909. ntStatus = IoCallDriver(pExtension->TopOfStackDeviceObject,Irp);
  910. } /*end !NULL*/
  911. else
  912. {
  913. ntStatus=STATUS_NO_MEMORY;
  914. Irp->IoStatus.Status = ntStatus;
  915. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  916. }
  917. //Port info will be written to the registry in the IRP_MN_QUERY_ID case. It can't be used before then anyway
  918. } /*end if BusRelations*/
  919. } else {
  920. USBPRINT_KdPrint2 (("USBPRINT.SYS: Child QueryDeviceRelations\n"));
  921. if(RelationType==TargetDeviceRelation)
  922. {
  923. *pbComplete=TRUE;
  924. pRelations=(PDEVICE_RELATIONS)ExAllocatePoolWithTag(NonPagedPool,sizeof(DEVICE_RELATIONS), USBP_TAG);
  925. if(pRelations!=NULL)
  926. {
  927. pRelations->Count = 1;
  928. pRelations->Objects[0]=DeviceObject;
  929. ObReferenceObject(DeviceObject);
  930. Irp->IoStatus.Information=(ULONG_PTR)pRelations;
  931. ntStatus = STATUS_SUCCESS;
  932. Irp->IoStatus.Status = ntStatus;
  933. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  934. } /*end !NULL*/
  935. else
  936. {
  937. ntStatus=STATUS_NO_MEMORY;
  938. Irp->IoStatus.Status = ntStatus;
  939. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  940. }
  941. //Port info will be written to the registry in the IRP_MN_QUERY_ID case. It can't be used before then anyway
  942. } /*end if BusRelations*/
  943. }
  944. return ntStatus;
  945. }
  946. VOID
  947. USBPRINT_Unload(
  948. IN PDRIVER_OBJECT DriverObject
  949. )
  950. /*++
  951. Routine Description:
  952. Free all the allocated resources, etc.
  953. Arguments:
  954. DriverObject - pointer to a driver object
  955. Return Value:
  956. --*/
  957. {
  958. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_Unload\n"));
  959. if(pGPortList!=NULL)
  960. {
  961. ClearFreePorts(&pGPortList);
  962. }
  963. // if(pPortsUsed!=NULL)
  964. // ExFreePool(pPortsUsed);
  965. //
  966. // Free any global resources allocated
  967. // in DriverEntry
  968. //
  969. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_Unload\n"));
  970. }
  971. NTSTATUS
  972. USBPRINT_StartDevice(
  973. IN PDEVICE_OBJECT DeviceObject
  974. )
  975. /*++
  976. Routine Description:
  977. Initializes a given instance of the device on the USB.
  978. All we do here is get the device descriptor and store it
  979. Arguments:
  980. DeviceObject - pointer to the device object for this instance of a printer
  981. Return Value:
  982. NT status code
  983. --*/
  984. {
  985. PDEVICE_EXTENSION deviceExtension;
  986. NTSTATUS ntStatus;
  987. UNICODE_STRING KeyName;
  988. PUSB_DEVICE_DESCRIPTOR deviceDescriptor = NULL;
  989. PURB urb=NULL;
  990. ULONG siz;
  991. ULONG dwVidPid;
  992. PDEVICE_OBJECT NewDevice;
  993. LARGE_INTEGER timeOut;
  994. PCHILD_DEVICE_EXTENSION pChildExtension;
  995. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_StartDevice\n"));
  996. deviceExtension = DeviceObject->DeviceExtension;
  997. ntStatus = USBPRINT_ConfigureDevice(DeviceObject);
  998. if(NT_SUCCESS(ntStatus))
  999. {
  1000. urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), USBP_TAG);
  1001. }
  1002. else
  1003. {
  1004. USBPRINT_KdPrint1(("USBPRINT.SYS: USBPRINT_ConfigureDevice Failed\n"));
  1005. urb=NULL;
  1006. }
  1007. if (urb)
  1008. {
  1009. siz = sizeof(USB_DEVICE_DESCRIPTOR);
  1010. deviceDescriptor = ExAllocatePoolWithTag(NonPagedPool,siz, USBP_TAG);
  1011. if (deviceDescriptor)
  1012. {
  1013. UsbBuildGetDescriptorRequest(urb,
  1014. (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  1015. USB_DEVICE_DESCRIPTOR_TYPE,
  1016. 0,
  1017. 0,
  1018. deviceDescriptor,
  1019. NULL,
  1020. siz,
  1021. NULL);
  1022. timeOut.QuadPart = FAILURE_TIMEOUT;
  1023. ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
  1024. if (NT_SUCCESS(ntStatus))
  1025. {
  1026. USBPRINT_KdPrint3 (("USBPRINT.SYS: Device Descriptor = %x, len %x\n",
  1027. deviceDescriptor,
  1028. urb->UrbControlDescriptorRequest.TransferBufferLength));
  1029. USBPRINT_KdPrint3 (("USBPRINT.SYS: USBPRINT Device Descriptor:\n"));
  1030. USBPRINT_KdPrint3 (("USBPRINT.SYS: -------------------------\n"));
  1031. USBPRINT_KdPrint3 (("USBPRINT.SYS: bLength %d\n", deviceDescriptor->bLength));
  1032. USBPRINT_KdPrint3 (("USBPRINT.SYS: bDescriptorType 0x%x\n", deviceDescriptor->bDescriptorType));
  1033. USBPRINT_KdPrint3 (("USBPRINT.SYS: bcdUSB 0x%x\n", deviceDescriptor->bcdUSB));
  1034. USBPRINT_KdPrint3 (("USBPRINT.SYS: bDeviceClass 0x%x\n", deviceDescriptor->bDeviceClass));
  1035. USBPRINT_KdPrint3 (("USBPRINT.SYS: bDeviceSubClass 0x%x\n", deviceDescriptor->bDeviceSubClass));
  1036. USBPRINT_KdPrint3 (("USBPRINT.SYS: bDeviceProtocol 0x%x\n", deviceDescriptor->bDeviceProtocol));
  1037. USBPRINT_KdPrint3 (("USBPRINT.SYS: bMaxPacketSize0 0x%x\n", deviceDescriptor->bMaxPacketSize0));
  1038. USBPRINT_KdPrint3 (("USBPRINT.SYS: idVendor 0x%x\n", deviceDescriptor->idVendor));
  1039. USBPRINT_KdPrint3 (("USBPRINT.SYS: idProduct 0x%x\n", deviceDescriptor->idProduct));
  1040. USBPRINT_KdPrint3 (("USBPRINT.SYS: bcdDevice 0x%x\n", deviceDescriptor->bcdDevice));
  1041. USBPRINT_KdPrint3 (("USBPRINT.SYS: iManufacturer 0x%x\n", deviceDescriptor->iManufacturer));
  1042. USBPRINT_KdPrint3 (("USBPRINT.SYS: iProduct 0x%x\n", deviceDescriptor->iProduct));
  1043. USBPRINT_KdPrint3 (("USBPRINT.SYS: iSerialNumber 0x%x\n", deviceDescriptor->iSerialNumber));
  1044. USBPRINT_KdPrint3 (("USBPRINT.SYS: bNumConfigurations 0x%x\n", deviceDescriptor->bNumConfigurations));
  1045. dwVidPid=deviceDescriptor->idVendor;
  1046. dwVidPid<<=16;
  1047. dwVidPid+=deviceDescriptor->idProduct;
  1048. USBPRINT_KdPrint3 (("USBPRINT.SYS: Math OK\n"));
  1049. }
  1050. else
  1051. {
  1052. USBPRINT_KdPrint1(("USBPRINT.SYS: Get Device Descriptor failed\n"));
  1053. ntStatus=STATUS_DEVICE_CONFIGURATION_ERROR;
  1054. }
  1055. }
  1056. else
  1057. {
  1058. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1059. USBPRINT_KdPrint1(("USBPRINT.SYS: Insufficient resources to allocate device descriptor in StartDevice\n"));
  1060. }
  1061. if (NT_SUCCESS(ntStatus))
  1062. {
  1063. deviceExtension->DeviceDescriptor = deviceDescriptor;
  1064. } else if (deviceDescriptor)
  1065. {
  1066. ExFreePool(deviceDescriptor);
  1067. }
  1068. ExFreePool(urb);
  1069. }
  1070. else
  1071. {
  1072. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1073. USBPRINT_KdPrint1(("USBPRINT.SYS: Insufficient resources to allocate urb in StartDevice\n"));
  1074. }
  1075. if(deviceExtension->bChildDeviceHere==FALSE)
  1076. {
  1077. if(NT_SUCCESS(ntStatus))
  1078. {
  1079. ntStatus=IoCreateDevice(USBPRINT_DriverObject,
  1080. sizeof(CHILD_DEVICE_EXTENSION),
  1081. NULL,
  1082. FILE_DEVICE_PARALLEL_PORT,
  1083. FILE_AUTOGENERATED_DEVICE_NAME,
  1084. TRUE,
  1085. &NewDevice);
  1086. }
  1087. if(NT_SUCCESS(ntStatus))
  1088. {
  1089. USBPRINT_KdPrint3(("USBPRINT.SYS: IoCreateDevice succeeded for child device\n"));
  1090. NewDevice->Flags|=DO_POWER_PAGABLE;
  1091. pChildExtension=NewDevice->DeviceExtension;
  1092. pChildExtension->ParentDeviceObject=DeviceObject;
  1093. deviceExtension->ChildDevice=NewDevice;
  1094. deviceExtension->bChildDeviceHere=TRUE;
  1095. pChildExtension->IsChildDevice=TRUE;
  1096. pChildExtension->ulInstanceNumber=deviceExtension->ulInstanceNumber;
  1097. }
  1098. else
  1099. {
  1100. USBPRINT_KdPrint1(("USBPRINT.SYS: IoCreateDevice failed for child device\n"));
  1101. }
  1102. } /*end if we need to make a child device*/
  1103. if(NT_SUCCESS(ntStatus))
  1104. {
  1105. USBPRINT_GetDeviceID(DeviceObject);
  1106. WritePortDescription(deviceExtension);
  1107. ntStatus=IoSetDeviceInterfaceState(&(deviceExtension->DeviceLinkName),TRUE);
  1108. }
  1109. if (NT_SUCCESS(ntStatus))
  1110. {
  1111. ntStatus = USBPRINT_BuildPipeList(DeviceObject);
  1112. if(!deviceExtension->IsChildDevice)
  1113. {
  1114. USBPRINT_FdoSubmitIdleRequestIrp(deviceExtension);
  1115. }
  1116. }
  1117. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_StartDevice (%x)\n", ntStatus));
  1118. return ntStatus;
  1119. }
  1120. void WritePortDescription(PDEVICE_EXTENSION deviceExtension)
  1121. {
  1122. UNICODE_STRING ValueName;
  1123. ANSI_STRING AnsiTextString;
  1124. UNICODE_STRING Description;
  1125. UNICODE_STRING BaseName,BaseValueName;
  1126. RtlInitUnicodeString(&ValueName,L"Port Description");
  1127. RtlInitAnsiString(&AnsiTextString,deviceExtension->DeviceIdString);
  1128. RtlAnsiStringToUnicodeString(&Description,&AnsiTextString,TRUE);
  1129. ZwSetValueKey(deviceExtension->hInterfaceKey,&ValueName,0,REG_SZ,Description.Buffer,Description.Length+2);
  1130. RtlFreeUnicodeString(&Description);
  1131. RtlInitUnicodeString(&BaseName,L"USB");
  1132. RtlInitUnicodeString(&BaseValueName,L"Base Name");
  1133. ZwSetValueKey(deviceExtension->hInterfaceKey,&BaseValueName,0,REG_SZ,BaseName.Buffer,BaseName.Length+2);
  1134. }
  1135. NTSTATUS
  1136. USBPRINT_RemoveDevice(
  1137. IN PDEVICE_OBJECT DeviceObject
  1138. )
  1139. /*++
  1140. Routine Description:
  1141. Stops a given instance of printer
  1142. Arguments:
  1143. DeviceObject - pointer to the device object for this instance of the (parent) printer object
  1144. Return Value:
  1145. NT status code
  1146. --*/
  1147. {
  1148. PDEVICE_EXTENSION deviceExtension;
  1149. NTSTATUS ntStatus = STATUS_SUCCESS;
  1150. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_RemoveDevice\n"));
  1151. deviceExtension = DeviceObject->DeviceExtension;
  1152. ZwClose(deviceExtension->hInterfaceKey);
  1153. USBPRINT_KdPrint2(("USBPRINT.SYS: Closeing interface key in RemoveDevice\n"));
  1154. ntStatus=IoSetDeviceInterfaceState(&(deviceExtension->DeviceLinkName),FALSE);
  1155. if(!NT_SUCCESS(ntStatus))
  1156. {
  1157. USBPRINT_KdPrint1 (("USBPRINT.SYS: ioSetDeviceInterface to false failed\n"));
  1158. }
  1159. RtlFreeUnicodeString(&(deviceExtension->DeviceLinkName));
  1160. //
  1161. // Free device descriptor structure
  1162. //
  1163. if (deviceExtension->DeviceDescriptor) {
  1164. ExFreePool(deviceExtension->DeviceDescriptor);
  1165. }
  1166. //
  1167. // Free up any interface structures
  1168. //
  1169. if (deviceExtension->Interface) {
  1170. ExFreePool(deviceExtension->Interface);
  1171. }
  1172. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_RemoveDevice (%x)\n", ntStatus));
  1173. return ntStatus;
  1174. }
  1175. NTSTATUS
  1176. USBPRINT_StopDevice(
  1177. IN PDEVICE_OBJECT DeviceObject
  1178. )
  1179. /*++
  1180. Routine Description:
  1181. Stops a given instance of a printer on the USB, this is only
  1182. stuff we need to do if the device is still present.
  1183. Arguments:
  1184. DeviceObject - pointer to the device object for this printer
  1185. Return Value:
  1186. NT status code
  1187. --*/
  1188. {
  1189. PDEVICE_EXTENSION deviceExtension;
  1190. NTSTATUS ntStatus = STATUS_SUCCESS;
  1191. PURB urb;
  1192. ULONG siz;
  1193. LARGE_INTEGER timeOut;
  1194. timeOut.QuadPart = FAILURE_TIMEOUT;
  1195. USBPRINT_KdPrint3 (("USBPRINT.SYS: enter USBPRINT_StopDevice\n"));
  1196. deviceExtension = DeviceObject->DeviceExtension;
  1197. //
  1198. // Send the select configuration urb with a NULL pointer for the configuration
  1199. // handle, this closes the configuration and puts the device in the 'unconfigured'
  1200. // state.
  1201. //
  1202. siz = sizeof(struct _URB_SELECT_CONFIGURATION);
  1203. urb = ExAllocatePoolWithTag(NonPagedPool,siz, USBP_TAG);
  1204. if (urb) {
  1205. NTSTATUS status;
  1206. UsbBuildSelectConfigurationRequest(urb,
  1207. (USHORT) siz,
  1208. NULL);
  1209. status = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
  1210. USBPRINT_KdPrint3 (("USBPRINT.SYS: Device Configuration Closed status = %x usb status = %x.\n",
  1211. status, urb->UrbHeader.Status));
  1212. ExFreePool(urb);
  1213. } else {
  1214. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1215. }
  1216. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_StopDevice (%x)\n", ntStatus));
  1217. return ntStatus;
  1218. }
  1219. NTSTATUS
  1220. USBPRINT_PnPAddDevice(
  1221. IN PDRIVER_OBJECT DriverObject,
  1222. IN PDEVICE_OBJECT PhysicalDeviceObject
  1223. )
  1224. /*++
  1225. Routine Description:
  1226. This routine is called to create a new instance of the device
  1227. Arguments:
  1228. DriverObject - pointer to the driver object for this instance of USBPRINT
  1229. PhysicalDeviceObject - pointer to a device object created by the bus
  1230. Return Value:
  1231. STATUS_SUCCESS if successful,
  1232. STATUS_UNSUCCESSFUL otherwise
  1233. --*/
  1234. {
  1235. NTSTATUS ntStatus = STATUS_SUCCESS;
  1236. PDEVICE_OBJECT deviceObject = NULL;
  1237. PDEVICE_EXTENSION deviceExtension;
  1238. USBD_VERSION_INFORMATION versionInformation;
  1239. ULONG ulPortNumber;
  1240. GUID * pPrinterGuid;
  1241. static ULONG instance = 0;
  1242. //UNICODE_STRING deviceLinkUnicodeString;
  1243. HANDLE hInterfaceKey;
  1244. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_PnPAddDevice\n"));
  1245. //
  1246. // create our funtional device object (FDO)
  1247. //
  1248. ntStatus =
  1249. USBPRINT_CreateDeviceObject(DriverObject, &deviceObject);
  1250. if (NT_SUCCESS(ntStatus)) {
  1251. deviceExtension = deviceObject->DeviceExtension;
  1252. //
  1253. // we support direct io for read/write
  1254. //
  1255. deviceObject->Flags |= DO_DIRECT_IO;
  1256. deviceObject->Flags |= DO_POWER_PAGABLE;
  1257. //** initialize our device extension
  1258. //
  1259. // remember the Physical device Object
  1260. //
  1261. deviceExtension->PhysicalDeviceObject=PhysicalDeviceObject;
  1262. // init selective suspend stuff
  1263. deviceExtension->PendingIdleIrp = NULL;
  1264. deviceExtension->IdleCallbackInfo = NULL;
  1265. deviceExtension->OpenCnt=0;
  1266. deviceExtension->bD0IrpPending=FALSE;
  1267. KeInitializeSpinLock(&(deviceExtension->WakeSpinLock));
  1268. //
  1269. // Attach to the PDO
  1270. //
  1271. deviceExtension->TopOfStackDeviceObject=IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);
  1272. if(deviceExtension->TopOfStackDeviceObject==NULL)
  1273. {
  1274. USBPRINT_KdPrint1(("USBPRINT.SYS: IoAttachDeviceToDeviceStack failed\n"));
  1275. }
  1276. else
  1277. {
  1278. USBPRINT_KdPrint3(("USBPRINT.SYS: IoAttachDeviceToDeviceStack worked\n"));
  1279. }
  1280. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  1281. USBPRINT_KdPrint3(("'USBPRINT.SYS: Before ioRegisterDeviceInterface\n"));
  1282. pPrinterGuid=(GUID *)&USBPRINT_GUID;
  1283. ntStatus=IoRegisterDeviceInterface(PhysicalDeviceObject,pPrinterGuid,NULL,&(deviceExtension->DeviceLinkName));
  1284. if(!NT_SUCCESS(ntStatus))
  1285. {
  1286. USBPRINT_KdPrint1(("'USBPRINT.SYS: ioRegisterDeviceInterface failed\n"));
  1287. goto AddDeviceFailure;
  1288. }
  1289. ntStatus=IoOpenDeviceInterfaceRegistryKey(&(deviceExtension->DeviceLinkName),KEY_ALL_ACCESS,&hInterfaceKey);
  1290. USBPRINT_KdPrint2(("USBPRINT.SYS: Opened Device Interface reg key in AddDevice\n"));
  1291. // moved to RemoveDevice RtlFreeUnicodeString(&deviceLinkUnicodeString);
  1292. if(!NT_SUCCESS(ntStatus))
  1293. {
  1294. USBPRINT_KdPrint1(("USBPRINT.SYS: IoOpenDeviceInterfaceRegistryKey failed\n"));
  1295. goto AddDeviceFailure;
  1296. }
  1297. USBPRINT_KdPrint3(("USBPRINT.SYS: IoOpenDeviceInterfaceRegistryKey succeeded\n"));
  1298. deviceExtension->hInterfaceKey=hInterfaceKey;
  1299. ntStatus=GetPortNumber(hInterfaceKey,&ulPortNumber);
  1300. if(!NT_SUCCESS(ntStatus))
  1301. {
  1302. USBPRINT_KdPrint1(("USBPRINT.SYS: GetPortNumber failed\n"));
  1303. goto AddDeviceFailure;
  1304. }
  1305. deviceExtension->ulInstanceNumber=ulPortNumber;
  1306. USBPRINT_KdPrint2(("USBPRINT.SYS: Allocated port # %u\n",ulPortNumber));
  1307. /* ntStatus=IoSetDeviceInterfaceState(&(deviceExtension->DeviceLinkName),TRUE);
  1308. if(NT_SUCCESS(ntStatus))
  1309. {
  1310. USBPRINT_KdPrint3(("USBPRINT.SYS: IoSetDeviceInterfaceState worked\n"));
  1311. }
  1312. else
  1313. {
  1314. USBPRINT_KdPrint1(("USBPRINT.SYS: IoSetDeviceInterfaceState did not work\n"));
  1315. goto AddDeviceFailure;
  1316. }
  1317. */
  1318. USBPRINT_QueryCapabilities(PhysicalDeviceObject,
  1319. &deviceExtension->DeviceCapabilities);
  1320. //
  1321. // display the device caps
  1322. //
  1323. #if DBG
  1324. {
  1325. ULONG i;
  1326. USBPRINT_KdPrint3(("USBPRINT.SYS: >>>>>> DeviceCaps\n"));
  1327. USBPRINT_KdPrint3(("USBPRINT.SYS: SystemWake = (%d)\n",
  1328. deviceExtension->DeviceCapabilities.SystemWake));
  1329. USBPRINT_KdPrint3(("USBPRINT.SYS: DeviceWake = (D%d)\n",
  1330. deviceExtension->DeviceCapabilities.DeviceWake-1));
  1331. for (i=PowerSystemUnspecified; i< PowerSystemMaximum; i++) {
  1332. USBPRINT_KdPrint3(("USBPRINT.SYS: Device State Map: sysstate %d = devstate 0x%x\n", i,
  1333. deviceExtension->DeviceCapabilities.DeviceState[i]));
  1334. }
  1335. USBPRINT_KdPrint3(("USBPRINT.SYS: '<<<<<<<<DeviceCaps\n"));
  1336. }
  1337. #endif
  1338. //
  1339. // transition to zero signals the event
  1340. //
  1341. USBPRINT_IncrementIoCount(deviceObject);
  1342. }
  1343. USBD_GetUSBDIVersion(&versionInformation);
  1344. AddDeviceFailure:
  1345. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_PnPAddDevice (%x)\n", ntStatus));
  1346. return ntStatus;
  1347. }
  1348. NTSTATUS
  1349. USBPRINT_CreateDeviceObject(
  1350. IN PDRIVER_OBJECT DriverObject,
  1351. IN PDEVICE_OBJECT *DeviceObject
  1352. )
  1353. /*++
  1354. Routine Description:
  1355. Creates a Functional DeviceObject
  1356. Arguments:
  1357. DriverObject - pointer to the driver object for device
  1358. DeviceObject - pointer to DeviceObject pointer to return
  1359. created device object.
  1360. Instance - instnace of the device create.
  1361. Return Value:
  1362. STATUS_SUCCESS if successful,
  1363. STATUS_UNSUCCESSFUL otherwise
  1364. --*/
  1365. {
  1366. NTSTATUS ntStatus;
  1367. PDEVICE_EXTENSION deviceExtension;
  1368. ULONG instance;
  1369. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_CreateDeviceObject\n"));
  1370. //
  1371. // This driver supports up to 9 instances
  1372. //
  1373. ntStatus = IoCreateDevice (DriverObject,
  1374. sizeof (DEVICE_EXTENSION),
  1375. NULL,
  1376. FILE_DEVICE_UNKNOWN,
  1377. 0,
  1378. FALSE,
  1379. DeviceObject);
  1380. //
  1381. // Initialize our device extension
  1382. //
  1383. deviceExtension = (PDEVICE_EXTENSION) ((*DeviceObject)->DeviceExtension);
  1384. deviceExtension->IsChildDevice=FALSE;
  1385. deviceExtension->ResetWorkItemPending=0; //init to "no workitem pending"
  1386. deviceExtension->bChildDeviceHere=FALSE;
  1387. deviceExtension->DeviceDescriptor = NULL;
  1388. deviceExtension->Interface = NULL;
  1389. deviceExtension->ConfigurationHandle = NULL;
  1390. deviceExtension->AcceptingRequests = TRUE;
  1391. deviceExtension->PendingIoCount = 0;
  1392. deviceExtension->DeviceCapabilities.Size = sizeof(DEVICE_CAPABILITIES);
  1393. deviceExtension->DeviceCapabilities.Version = DEVICE_CAPABILITY_VERSION;
  1394. deviceExtension->DeviceCapabilities.Address = (ULONG) -1;
  1395. deviceExtension->DeviceCapabilities.UINumber= (ULONG) -1;
  1396. deviceExtension->DeviceCapabilities.DeviceState[PowerSystemWorking] = PowerDeviceD0;
  1397. deviceExtension->DeviceCapabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD3;
  1398. deviceExtension->DeviceCapabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD3;
  1399. deviceExtension->DeviceCapabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
  1400. deviceExtension->DeviceCapabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
  1401. deviceExtension->DeviceCapabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
  1402. KeInitializeEvent(&deviceExtension->RemoveEvent, NotificationEvent, FALSE);
  1403. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_CreateDeviceObject (%x)\n", ntStatus));
  1404. return ntStatus;
  1405. }
  1406. NTSTATUS
  1407. USBPRINT_CallUSBD(
  1408. IN PDEVICE_OBJECT DeviceObject,
  1409. IN PURB Urb,
  1410. IN PLARGE_INTEGER pTimeout
  1411. )
  1412. /*++
  1413. Routine Description:
  1414. Passes a URB to the USBD class driver
  1415. Arguments:
  1416. DeviceObject - pointer to the device object for this printer
  1417. Urb - pointer to Urb request block
  1418. Return Value:
  1419. STATUS_SUCCESS if successful,
  1420. STATUS_UNSUCCESSFUL otherwise
  1421. --*/
  1422. {
  1423. NTSTATUS ntStatus, status = STATUS_SUCCESS;
  1424. PDEVICE_EXTENSION deviceExtension;
  1425. PIRP irp;
  1426. KEVENT event;
  1427. PIO_STACK_LOCATION nextStack;
  1428. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_CallUSBD\n"));
  1429. deviceExtension = DeviceObject->DeviceExtension;
  1430. //
  1431. // issue a synchronous request
  1432. //
  1433. KeInitializeEvent(&event, NotificationEvent, FALSE);
  1434. if ( (irp = IoAllocateIrp(deviceExtension->TopOfStackDeviceObject->StackSize,
  1435. FALSE)) == NULL )
  1436. return STATUS_INSUFFICIENT_RESOURCES;
  1437. //
  1438. // Call the class driver to perform the operation. If the returned status
  1439. // is PENDING, wait for the request to complete.
  1440. //
  1441. nextStack = IoGetNextIrpStackLocation(irp);
  1442. ASSERT(nextStack != NULL);
  1443. //
  1444. // pass the URB to the USB driver stack
  1445. //
  1446. nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1447. nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  1448. nextStack->Parameters.Others.Argument1 = Urb;
  1449. IoSetCompletionRoutine(irp,
  1450. USBPRINT_DeferIrpCompletion,
  1451. &event,
  1452. TRUE,
  1453. TRUE,
  1454. TRUE);
  1455. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
  1456. irp);
  1457. if ( ntStatus == STATUS_PENDING )
  1458. {
  1459. status = KeWaitForSingleObject(&event,Suspended,KernelMode,FALSE,pTimeout);
  1460. //
  1461. // If the request timed out cancel the request
  1462. // and wait for it to complete
  1463. //
  1464. if ( status == STATUS_TIMEOUT ) {
  1465. #ifdef MYDEBUG
  1466. DbgPrint("Call_USBD: Cancelling IRP %X because of timeout\n", irp);
  1467. #endif
  1468. IoCancelIrp(irp);
  1469. KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
  1470. }
  1471. ntStatus = irp->IoStatus.Status;
  1472. }
  1473. IoFreeIrp(irp);
  1474. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_CallUSBD (%x)\n", ntStatus));
  1475. USBPRINT_KdPrint3 (("USBPRINT.SYS: About to return from CallUSBD, status=%x\n", ntStatus));
  1476. return ntStatus;
  1477. }
  1478. NTSTATUS
  1479. USBPRINT_ConfigureDevice(
  1480. IN PDEVICE_OBJECT DeviceObject
  1481. )
  1482. /*++
  1483. Routine Description:
  1484. Initializes a given instance of the device on the USB and selects the configuration.
  1485. Arguments:
  1486. DeviceObject - pointer to the device object for this printer devcice.
  1487. Return Value:
  1488. NT status code
  1489. --*/
  1490. {
  1491. PDEVICE_EXTENSION deviceExtension;
  1492. NTSTATUS ntStatus;
  1493. PURB urb;
  1494. ULONG siz;
  1495. PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL;
  1496. LARGE_INTEGER timeOut;
  1497. int tries=0;
  1498. timeOut.QuadPart = FAILURE_TIMEOUT;
  1499. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_ConfigureDevice\n"));
  1500. deviceExtension = DeviceObject->DeviceExtension;
  1501. //
  1502. // first configure the device
  1503. //
  1504. urb = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), USBP_TAG);
  1505. if (urb)
  1506. {
  1507. siz = sizeof(USB_CONFIGURATION_DESCRIPTOR)+256;
  1508. get_config_descriptor_retry:
  1509. configurationDescriptor = ExAllocatePoolWithTag(NonPagedPool,siz, USBP_TAG);
  1510. if (configurationDescriptor)
  1511. {
  1512. UsbBuildGetDescriptorRequest(urb,
  1513. (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  1514. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  1515. 0,
  1516. 0,
  1517. configurationDescriptor,
  1518. NULL,
  1519. siz,
  1520. NULL);
  1521. ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
  1522. if(!NT_SUCCESS(ntStatus))
  1523. {
  1524. USBPRINT_KdPrint1 (("USBPRINT.SYS: Get Configuration descriptor failed\n"));
  1525. }
  1526. else
  1527. {
  1528. //
  1529. // if we got some data see if it was enough.
  1530. //
  1531. // NOTE: we may get an error in URB because of buffer overrun
  1532. if (urb->UrbControlDescriptorRequest.TransferBufferLength>0 &&configurationDescriptor->wTotalLength > siz)
  1533. {
  1534. #define MAX_MEM_FOR_DESCRIPTOR 1024 * 25
  1535. if((siz>MAX_MEM_FOR_DESCRIPTOR)||((tries++)==10))
  1536. {
  1537. USBPRINT_KdPrint3 (("USBPRINT.SYS: ConfigureDevice, this device appears to be lying to us about descriptor size\n"));
  1538. ExFreePool(configurationDescriptor);
  1539. configurationDescriptor = NULL;
  1540. ntStatus=STATUS_DEVICE_CONFIGURATION_ERROR;
  1541. }
  1542. else
  1543. {
  1544. siz = configurationDescriptor->wTotalLength;
  1545. ExFreePool(configurationDescriptor);
  1546. configurationDescriptor = NULL;
  1547. goto get_config_descriptor_retry;
  1548. }
  1549. } //end if not big enough
  1550. } //end else we got some sort of descriptor
  1551. USBPRINT_KdPrint3 (("USBPRINT.SYS: Configuration Descriptor = %x, len %x\n",
  1552. configurationDescriptor,
  1553. urb->UrbControlDescriptorRequest.TransferBufferLength));
  1554. }
  1555. else
  1556. {
  1557. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1558. USBPRINT_KdPrint1(("USBPRINT.SYS: Insufficient resources to allocate configuration descriptor in ConfigureDevice\n"));
  1559. }
  1560. ExFreePool(urb);
  1561. }
  1562. else
  1563. {
  1564. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1565. }
  1566. if (configurationDescriptor)
  1567. {
  1568. USBPRINT_KdPrint2(("USBPRINT.SYS: ConfigureDevice, We have a configuration descriptor!\n"));
  1569. //
  1570. // We have the configuration descriptor for the configuration
  1571. // we want.
  1572. //
  1573. // Now we issue the select configuration command to get
  1574. // the pipes associated with this configuration.
  1575. //
  1576. if(NT_SUCCESS(ntStatus))
  1577. {
  1578. ntStatus = USBPRINT_SelectInterface(DeviceObject,configurationDescriptor);
  1579. }
  1580. ExFreePool(configurationDescriptor);
  1581. }
  1582. else
  1583. {
  1584. USBPRINT_KdPrint1(("USBPRINT.SYS: ConfigureDevice, No Configuration descriptor.\n"));
  1585. }
  1586. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_ConfigureDevice (%x)\n", ntStatus));
  1587. return ntStatus;
  1588. }
  1589. NTSTATUS USBPRINT_SelectInterface(IN PDEVICE_OBJECT DeviceObject,IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
  1590. /*++
  1591. Routine Description:
  1592. Initializes a printer with multiple interfaces
  1593. Arguments:
  1594. DeviceObject - pointer to the device object for this printer
  1595. ConfigurationDescriptor - pointer to the USB configuration
  1596. descriptor containing the interface and endpoint
  1597. descriptors.
  1598. Return Value:
  1599. NT status code
  1600. --*/
  1601. {
  1602. PDEVICE_EXTENSION deviceExtension;
  1603. NTSTATUS ntStatus;
  1604. PURB urb = NULL;
  1605. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor = NULL;
  1606. PUSBD_INTERFACE_INFORMATION Interface = NULL;
  1607. USBD_INTERFACE_LIST_ENTRY InterfaceList[2];
  1608. LARGE_INTEGER timeOut;
  1609. timeOut.QuadPart = FAILURE_TIMEOUT;
  1610. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_SelectInterface\n"));
  1611. deviceExtension = DeviceObject->DeviceExtension;
  1612. //starting at offset 0, search for an alternate interface with protocol code 2; Ignore InterfaceNumber, AlternateSetting, InterfaceClass, InterfaceSubClass
  1613. interfaceDescriptor=USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor,ConfigurationDescriptor,-1,-1,-1,-1,2);
  1614. if(!interfaceDescriptor)
  1615. {
  1616. USBPRINT_KdPrint3 (("USBPRINT.SYS: First ParseConfigurationDescriptorEx failed\n"));
  1617. interfaceDescriptor=USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor,ConfigurationDescriptor,-1,-1,-1,-1,1);
  1618. if(!interfaceDescriptor)
  1619. {
  1620. USBPRINT_KdPrint1 (("USBPRINT.SYS: second ParseConfigurationDescriptorEx failed\n"));
  1621. ntStatus=STATUS_DEVICE_CONFIGURATION_ERROR;
  1622. }
  1623. else
  1624. {
  1625. USBPRINT_KdPrint3 (("USBPRINT.SYS: second ParseConfigurationDescriptorEx success\n"));
  1626. deviceExtension->bReadSupported=FALSE;
  1627. } /*end second ParseConfigDescriptor worked*/
  1628. }
  1629. else
  1630. {
  1631. deviceExtension->bReadSupported=TRUE;
  1632. USBPRINT_KdPrint3 (("USBPRINT.SYS: First ParseConfigurationDescriptorEx success\n"));
  1633. }
  1634. if(interfaceDescriptor)
  1635. {
  1636. InterfaceList[0].InterfaceDescriptor=interfaceDescriptor;
  1637. InterfaceList[1].InterfaceDescriptor=NULL;
  1638. urb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor,InterfaceList);
  1639. if (urb)
  1640. {
  1641. Interface = InterfaceList[0].Interface;
  1642. ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
  1643. }
  1644. else
  1645. {
  1646. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1647. USBPRINT_KdPrint1 (("USBPRINT.SYS: CreateConfigurationRequest failed\n"));
  1648. }
  1649. } //end found good interface
  1650. else
  1651. {
  1652. USBPRINT_KdPrint1 (("USBPRINT.SYS: failed to locate apropriate interface\n"));
  1653. } //end no interface
  1654. if (NT_SUCCESS(ntStatus))
  1655. {
  1656. //
  1657. // Save the configuration handle for this device
  1658. //
  1659. USBPRINT_KdPrint3 (("USBPRINT.SYS: SelectInterface, Inside good config case\n"));
  1660. deviceExtension->ConfigurationHandle = urb->UrbSelectConfiguration.ConfigurationHandle;
  1661. deviceExtension->Interface = ExAllocatePoolWithTag(NonPagedPool,Interface->Length, USBP_TAG);
  1662. if (deviceExtension->Interface)
  1663. {
  1664. ULONG j;
  1665. //
  1666. // save a copy of the interface information returned
  1667. //
  1668. RtlCopyMemory(deviceExtension->Interface, Interface, Interface->Length);
  1669. //
  1670. // Dump the interface to the debugger
  1671. //
  1672. USBPRINT_KdPrint3 (("USBPRINT.SYS: ---------\n"));
  1673. USBPRINT_KdPrint3 (("USBPRINT.SYS: NumberOfPipes 0x%x\n", deviceExtension->Interface->NumberOfPipes));
  1674. USBPRINT_KdPrint3 (("USBPRINT.SYS: Length 0x%x\n", deviceExtension->Interface->Length));
  1675. USBPRINT_KdPrint3 (("USBPRINT.SYS: Alt Setting 0x%x\n", deviceExtension->Interface->AlternateSetting));
  1676. USBPRINT_KdPrint3 (("USBPRINT.SYS: Interface Number 0x%x\n", deviceExtension->Interface->InterfaceNumber));
  1677. USBPRINT_KdPrint3 (("USBPRINT.SYS: Class, subclass, protocol 0x%x 0x%x 0x%x\n",
  1678. deviceExtension->Interface->Class,
  1679. deviceExtension->Interface->SubClass,
  1680. deviceExtension->Interface->Protocol));
  1681. // Dump the pipe info
  1682. for (j=0; j<Interface->NumberOfPipes; j++)
  1683. {
  1684. PUSBD_PIPE_INFORMATION pipeInformation;
  1685. pipeInformation = &deviceExtension->Interface->Pipes[j];
  1686. USBPRINT_KdPrint3 (("USBPRINT.SYS: ---------\n"));
  1687. USBPRINT_KdPrint3 (("USBPRINT.SYS: PipeType 0x%x\n", pipeInformation->PipeType));
  1688. USBPRINT_KdPrint3 (("USBPRINT.SYS: EndpointAddress 0x%x\n", pipeInformation->EndpointAddress));
  1689. USBPRINT_KdPrint3 (("USBPRINT.SYS: MaxPacketSize 0x%x\n", pipeInformation->MaximumPacketSize));
  1690. USBPRINT_KdPrint3 (("USBPRINT.SYS: Interval 0x%x\n", pipeInformation->Interval));
  1691. USBPRINT_KdPrint3 (("USBPRINT.SYS: Handle 0x%x\n", pipeInformation->PipeHandle));
  1692. USBPRINT_KdPrint3 (("USBPRINT.SYS: MaximumTransferSize 0x%x\n", pipeInformation->MaximumTransferSize));
  1693. }
  1694. USBPRINT_KdPrint3 (("USBPRINT.SYS: ---------\n"));
  1695. } /*end if interface Alloc OK*/
  1696. else
  1697. {
  1698. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1699. USBPRINT_KdPrint1 (("USBPRINT.SYS: Alloc failed in SelectInterface\n"));
  1700. }
  1701. }
  1702. if (urb)
  1703. {
  1704. ExFreePool(urb);
  1705. }
  1706. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_SelectInterface (%x)\n", ntStatus));
  1707. return ntStatus;
  1708. }
  1709. NTSTATUS
  1710. USBPRINT_BuildPipeList(
  1711. IN PDEVICE_OBJECT DeviceObject
  1712. )
  1713. /*++
  1714. Routine Description:
  1715. Arguments:
  1716. DeviceObject - pointer to the device object for this printer
  1717. devcice.
  1718. Return Value:
  1719. NT status code
  1720. --*/
  1721. {
  1722. PDEVICE_EXTENSION deviceExtension;
  1723. ULONG i;
  1724. WCHAR Name[] = L"\\PIPE00";
  1725. PUSBD_INTERFACE_INFORMATION InterfaceDescriptor;
  1726. BOOL bFoundWritePipe=FALSE,bFoundReadPipe=FALSE,bNeedReadPipe=FALSE;
  1727. deviceExtension = DeviceObject->DeviceExtension;
  1728. InterfaceDescriptor = deviceExtension->Interface;
  1729. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_BuildPipeList\n"));
  1730. deviceExtension = DeviceObject->DeviceExtension;
  1731. if(InterfaceDescriptor->Protocol==2)
  1732. bNeedReadPipe=TRUE;
  1733. else
  1734. bNeedReadPipe=FALSE;
  1735. for (i=0; i<InterfaceDescriptor->NumberOfPipes; i++) {
  1736. USBPRINT_KdPrint3 (("USBPRINT.SYS: about to look at endpoint with address 0x%x)\n",InterfaceDescriptor->Pipes[i].EndpointAddress));
  1737. if(((InterfaceDescriptor->Pipes[i].EndpointAddress)&0x80)==0) //if bit 7 is 0, it's an OUT endpoint
  1738. {
  1739. if(bFoundWritePipe==TRUE)
  1740. {
  1741. USBPRINT_KdPrint1 (("USBPRINT.SYS: Warning!! Multiple OUT pipes detected on printer. Defaulting to first pipe\n"));
  1742. } /*end if we've already found a write pipe*/
  1743. else
  1744. {
  1745. USBPRINT_KdPrint3 (("USBPRINT.SYS: Found write pipe\n"));
  1746. deviceExtension->pWritePipe=&(InterfaceDescriptor->Pipes[i]);
  1747. bFoundWritePipe=TRUE;
  1748. } /*else we haven't seen an OUT endpont before*/
  1749. } /*end if it's an OUT endpoint*/
  1750. else
  1751. {
  1752. if(!bNeedReadPipe)
  1753. {
  1754. USBPRINT_KdPrint1 (("USBPRINT.SYS: Warning!! unexpected IN pipe (not specified in protocol field)\n"));
  1755. } /*end if we don't need a read pipe, but we found one*/
  1756. else if(bFoundReadPipe)
  1757. {
  1758. USBPRINT_KdPrint1 (("USBPRINT.SYS: Warning!! Multiple IN pipes detected on printer. Defaulting to first pipe\n"));
  1759. } /*end if we've already found a read pipe*/
  1760. else
  1761. {
  1762. USBPRINT_KdPrint3 (("USBPRINT.SYS: Found read pipe\n"));
  1763. deviceExtension->pReadPipe=&(InterfaceDescriptor->Pipes[i]);
  1764. bFoundReadPipe=TRUE;
  1765. } /*end else we're supposed to have an IN pipe, and this is the first one we've seen*/
  1766. } /*end else it's an IN endpoint*/
  1767. } /*end for*/
  1768. if((bNeedReadPipe==TRUE)&&(bFoundReadPipe==FALSE))
  1769. {
  1770. USBPRINT_KdPrint1 (("USBPRINT.SYS: Warning!! IN pipe was specified in protocol field, but was not found\n"));
  1771. } /*end if we needed a read pipe, and didn't find one*/
  1772. deviceExtension->bReadPipeExists=bFoundReadPipe;
  1773. return STATUS_SUCCESS;
  1774. } /*end function BuildPipeList*/
  1775. NTSTATUS
  1776. USBPRINT_ResetPipe(
  1777. IN PDEVICE_OBJECT DeviceObject,
  1778. IN PUSBD_PIPE_INFORMATION Pipe,
  1779. IN BOOLEAN IsoClearStall
  1780. )
  1781. /*++
  1782. Routine Description:
  1783. Reset a given USB pipe.
  1784. NOTES:
  1785. This will reset the host to Data0 and should also reset the device
  1786. to Data0 for Bulk and Interrupt pipes.
  1787. For Iso pipes this will set the virgin state of pipe so that ASAP
  1788. transfers begin with the current bus frame instead of the next frame
  1789. after the last transfer occurred.
  1790. Arguments:
  1791. Return Value:
  1792. --*/
  1793. {
  1794. NTSTATUS ntStatus;
  1795. PURB urb;
  1796. LARGE_INTEGER timeOut;
  1797. timeOut.QuadPart = FAILURE_TIMEOUT;
  1798. USBPRINT_KdPrint2 (("USBPRINT.SYS: Entering Reset Pipe; pipe # %x\n", Pipe));
  1799. urb = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct _URB_PIPE_REQUEST), USBP_TAG);
  1800. if (urb) {
  1801. urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_PIPE_REQUEST);
  1802. urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
  1803. urb->UrbPipeRequest.PipeHandle =
  1804. Pipe->PipeHandle;
  1805. ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
  1806. if(!NT_SUCCESS(ntStatus))
  1807. {
  1808. USBPRINT_KdPrint1(("USBPRINT.SYS: CallUSBD failed in ResetPipe\n"));
  1809. }
  1810. else
  1811. {
  1812. USBPRINT_KdPrint3(("USBPRINT.SYS: CallUSBD Succeeded in ResetPipe\n"));
  1813. }
  1814. ExFreePool(urb);
  1815. } else {
  1816. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1817. }
  1818. //
  1819. // Memphis RESET_PIPE will send a Clear-Feature Endpoint Stall to
  1820. // reset the data toggle of non-Iso pipes as part of a RESET_PIPE
  1821. // request. It does not do this for Iso pipes as Iso pipes do not use
  1822. // the data toggle (all Iso packets are Data0). However, we also use
  1823. // the Clear-Feature Endpoint Stall request in our device firmware to
  1824. // reset data buffer points inside the device so we explicitly send
  1825. // this request to the device for Iso pipes if desired.
  1826. //
  1827. if (NT_SUCCESS(ntStatus) && IsoClearStall &&
  1828. (Pipe->PipeType == UsbdPipeTypeIsochronous)) {
  1829. urb = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct _URB_CONTROL_FEATURE_REQUEST), USBP_TAG);
  1830. if (urb) {
  1831. UsbBuildFeatureRequest(urb,
  1832. URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT,
  1833. USB_FEATURE_ENDPOINT_STALL,
  1834. Pipe->EndpointAddress,
  1835. NULL);
  1836. ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
  1837. ExFreePool(urb);
  1838. } else {
  1839. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1840. }
  1841. }
  1842. return ntStatus;
  1843. }
  1844. LONG
  1845. USBPRINT_DecrementIoCount(
  1846. IN PDEVICE_OBJECT DeviceObject
  1847. )
  1848. /*++
  1849. Routine Description:
  1850. Arguments:
  1851. Return Value:
  1852. --*/
  1853. {
  1854. PDEVICE_EXTENSION deviceExtension;
  1855. LONG ioCount=0;
  1856. deviceExtension = DeviceObject->DeviceExtension;
  1857. if(!(deviceExtension->IsChildDevice))
  1858. {
  1859. ioCount = InterlockedDecrement(&deviceExtension->PendingIoCount);
  1860. #ifdef MYDEBUG
  1861. DbgPrint("USBPRINT_DecrementIoCount -- IoCount %d\n", deviceExtension->PendingIoCount);
  1862. #endif
  1863. USBPRINT_KdPrint3 (("USBPRINT.SYS: Pending io count = %x\n", ioCount));
  1864. if (ioCount==0) {
  1865. KeSetEvent(&deviceExtension->RemoveEvent,
  1866. 1,
  1867. FALSE);
  1868. }
  1869. } /*end if ! child device*/
  1870. return ioCount;
  1871. }
  1872. VOID
  1873. USBPRINT_IncrementIoCount(
  1874. IN PDEVICE_OBJECT DeviceObject
  1875. )
  1876. /*++
  1877. Routine Description:
  1878. Arguments:
  1879. Return Value:
  1880. --*/
  1881. {
  1882. PDEVICE_EXTENSION deviceExtension;
  1883. deviceExtension = DeviceObject->DeviceExtension;
  1884. if(!(deviceExtension->IsChildDevice))
  1885. {
  1886. InterlockedIncrement(&deviceExtension->PendingIoCount);
  1887. #ifdef MYDEBUG
  1888. DbgPrint("USBPRINT_IncrementIoCount -- IoCount %d\n", deviceExtension->PendingIoCount);
  1889. #endif
  1890. //
  1891. // Everytime iocount goes to 0 we set this event
  1892. // so we must cleat it when we have a new io
  1893. //
  1894. KeClearEvent(&deviceExtension->RemoveEvent);
  1895. }
  1896. }
  1897. NTSTATUS
  1898. USBPRINT_ReconfigureDevice(
  1899. IN PDEVICE_OBJECT DeviceObject
  1900. )
  1901. /*++
  1902. Routine Description:
  1903. Initializes a given instance of the device on the USB and selects the
  1904. configuration.
  1905. Arguments:
  1906. DeviceObject - pointer to the device object for this printer
  1907. Return Value:
  1908. NT status code
  1909. --*/
  1910. {
  1911. PDEVICE_EXTENSION deviceExtension;
  1912. NTSTATUS ntStatus = STATUS_SUCCESS;
  1913. PUSBD_INTERFACE_INFORMATION InterfaceDescriptor;
  1914. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_ReconfigureDevice\n"));
  1915. deviceExtension = DeviceObject->DeviceExtension;
  1916. if (NT_SUCCESS(ntStatus)) {
  1917. ntStatus = USBPRINT_ConfigureDevice(DeviceObject);
  1918. }
  1919. //
  1920. // new InterfaceDescriptor structure is now set up
  1921. //
  1922. InterfaceDescriptor = deviceExtension->Interface;
  1923. //
  1924. // set up the pipe handles again
  1925. //
  1926. return ntStatus;
  1927. }
  1928. NTSTATUS LoadPortsUsed(GUID *pPrinterGuid,PFREE_PORTS * pPortList,WCHAR *wcBaseName)
  1929. {
  1930. NTSTATUS ReturnStatus=STATUS_SUCCESS,Result=STATUS_SUCCESS;
  1931. PWSTR pDeviceList;
  1932. PWSTR pWalk;
  1933. UNICODE_STRING wNumberValueName,wBaseValueName,wLinkName;
  1934. ULONG ulPortNum;
  1935. ULONG ulBaseNameSizeIn,ulBaseNameSizeOut,ulPortNumSizeIn,ulPortNumSizeOut;
  1936. PKEY_VALUE_PARTIAL_INFORMATION pBaseValueStruct,pNumberValueStruct;
  1937. HANDLE hInterfaceKey;
  1938. BOOL bFoundUsbPort;
  1939. Result=IoGetDeviceInterfaces(pPrinterGuid,NULL,DEVICE_INTERFACE_INCLUDE_NONACTIVE,&pDeviceList);
  1940. if(Result==STATUS_SUCCESS)
  1941. {
  1942. RtlInitUnicodeString(&wNumberValueName,PORT_NUM_VALUE_NAME);
  1943. RtlInitUnicodeString(&wBaseValueName,PORT_BASE_NAME);
  1944. pWalk=pDeviceList;
  1945. ulBaseNameSizeIn=sizeof(KEY_VALUE_PARTIAL_INFORMATION)+((wcslen(wcBaseName)+1)*sizeof(WCHAR)); //this is a byte to much. Oh well
  1946. ulPortNumSizeIn=sizeof(KEY_VALUE_PARTIAL_INFORMATION)+sizeof(ULONG);
  1947. pBaseValueStruct=ExAllocatePoolWithTag(NonPagedPool,ulBaseNameSizeIn, USBP_TAG);
  1948. pNumberValueStruct=ExAllocatePoolWithTag(NonPagedPool,ulPortNumSizeIn, USBP_TAG);
  1949. if((pBaseValueStruct!=NULL)&&(pNumberValueStruct!=NULL))
  1950. {
  1951. while( *pWalk!=0 && NT_SUCCESS(ReturnStatus) )
  1952. {
  1953. RtlInitUnicodeString(&wLinkName,pWalk);
  1954. Result=IoOpenDeviceInterfaceRegistryKey(&wLinkName,KEY_ALL_ACCESS,&hInterfaceKey);
  1955. if(NT_SUCCESS(Result))
  1956. {
  1957. //The following is: If there is not a value, or there is a value that matches what we expect, then set bFoundUsbPort to true
  1958. bFoundUsbPort=TRUE;
  1959. Result=ZwQueryValueKey(hInterfaceKey,&wBaseValueName,KeyValuePartialInformation,pBaseValueStruct,ulBaseNameSizeIn,&ulBaseNameSizeOut);
  1960. if(NT_SUCCESS(Result))
  1961. {
  1962. if(wcscmp(wcBaseName,(WCHAR *)(pBaseValueStruct->Data))!=0)
  1963. bFoundUsbPort=FALSE;
  1964. }//end if Query OK
  1965. else if(STATUS_OBJECT_NAME_NOT_FOUND!=Result)
  1966. {
  1967. bFoundUsbPort=FALSE;
  1968. }
  1969. if(bFoundUsbPort)
  1970. {
  1971. Result=ZwQueryValueKey(hInterfaceKey,&wNumberValueName,KeyValuePartialInformation,pNumberValueStruct,ulPortNumSizeIn,&ulPortNumSizeOut);
  1972. if(NT_SUCCESS(Result))
  1973. {
  1974. ulPortNum=*((ULONG *)(pNumberValueStruct->Data));
  1975. if(!bDeleteIfRecyclable(hInterfaceKey))
  1976. {
  1977. USBPRINT_KdPrint2(("USBPRINT.SYS: Adding port number\n"));
  1978. ReturnStatus=bAddPortInUseItem(pPortList,ulPortNum);
  1979. if(!NT_SUCCESS(ReturnStatus))
  1980. {
  1981. USBPRINT_KdPrint1(("USBPRINT.SYS: Unable to add port %u to port list\n",ulPortNum));
  1982. USBPRINT_KdPrint1(("USBPRINT.SYS: Failing out of LoadPortsUsed due to ntstatus failure %d\n",ReturnStatus));
  1983. } //end if AddPortInUse failed
  1984. } //end if port not deleted
  1985. else
  1986. {
  1987. // ReturnStatus=STATUS_INVALID_PARAMETER;
  1988. USBPRINT_KdPrint1(("USBPRINT.SYS: Invalid port number %u\n",ulPortNum));
  1989. }
  1990. } //end if Query Port Number OK
  1991. //no else. If there's no port number, we ignore this interface
  1992. } //End if bFoundUSbPort
  1993. ZwClose(hInterfaceKey);
  1994. } //end if OpenReg ok
  1995. pWalk=pWalk+wcslen(pWalk)+1;
  1996. } //end while
  1997. } //end ExAllocatePool OK
  1998. else
  1999. {
  2000. USBPRINT_KdPrint1(("USBPRINT.SYS: Unable to allocate memory"));
  2001. ReturnStatus=STATUS_INSUFFICIENT_RESOURCES;
  2002. } /*end else ExAllocatePool failed*/
  2003. if(pBaseValueStruct!=NULL)
  2004. ExFreePool(pBaseValueStruct);
  2005. if(pNumberValueStruct!=NULL)
  2006. ExFreePool(pNumberValueStruct);
  2007. ExFreePool(pDeviceList);
  2008. } /*end if IoGetDeviceInterfaces success*/
  2009. else
  2010. {
  2011. USBPRINT_KdPrint1(("USBPRINT.SYS: IoGetDeviceInterfaces failed"));
  2012. ReturnStatus=Result; //do some error translation here?
  2013. }
  2014. return ReturnStatus;
  2015. } /*end function LoadPortsUsed*/
  2016. NTSTATUS GetPortNumber(HANDLE hInterfaceKey,
  2017. ULONG *ulReturnNumber)
  2018. {
  2019. ULONG ulPortNumber,ulSizeUsed;
  2020. NTSTATUS ntStatus=STATUS_SUCCESS;
  2021. UNICODE_STRING uncValueName;
  2022. PKEY_VALUE_PARTIAL_INFORMATION pValueStruct;
  2023. ulSizeUsed=sizeof(KEY_VALUE_PARTIAL_INFORMATION)+sizeof(ULONG); //this is a byte to much. Oh well
  2024. pValueStruct=ExAllocatePoolWithTag(PagedPool,ulSizeUsed, USBP_TAG);
  2025. if(pValueStruct==NULL)
  2026. return STATUS_INSUFFICIENT_RESOURCES;
  2027. RtlInitUnicodeString(&uncValueName,PORT_NUM_VALUE_NAME);
  2028. ntStatus=ZwQueryValueKey(hInterfaceKey,&uncValueName,KeyValuePartialInformation,(PVOID)pValueStruct,ulSizeUsed,&ulSizeUsed);
  2029. if(!NT_SUCCESS(ntStatus))
  2030. {
  2031. USBPRINT_KdPrint2(("USBPRINT.SYS: GetPortNumber; ZwQueryValueKey failed\n"));
  2032. switch(ntStatus)
  2033. {
  2034. case STATUS_BUFFER_OVERFLOW:
  2035. USBPRINT_KdPrint2(("USBPRINT.SYS: GetPortNumber zwQueryValueKey returned STATUS_BUFFER_OVERFLOW\n"));
  2036. break;
  2037. case STATUS_INVALID_PARAMETER:
  2038. USBPRINT_KdPrint2(("USBPRINT.SYS: GetPortNumber zwQueryValueKey returned STATUS_INVALID_PARAMETER\n"));
  2039. break;
  2040. case STATUS_OBJECT_NAME_NOT_FOUND:
  2041. USBPRINT_KdPrint2(("USBPRINT.SYS: GetPortNumber zwQueryValueKey returned STATUS_OBJECT_NAME_NOT_FOUND\n"));
  2042. break;
  2043. default:
  2044. USBPRINT_KdPrint2(("USBPRINT.SYS: GetPortNumber zwQueryValueKey returned unkown error\n"));
  2045. }
  2046. ntStatus=GetNewPortNumber(&pGPortList,&ulPortNumber);
  2047. }
  2048. else
  2049. {
  2050. ulPortNumber=*((ULONG *)&(pValueStruct->Data));
  2051. if(ulPortNumber==0) //zero is a placeholder for "not there" which we use because win9x is missing the zwDeleteValueKey api
  2052. ntStatus=GetNewPortNumber(&pGPortList,&ulPortNumber);
  2053. else
  2054. vClaimPortNumber(ulPortNumber,hInterfaceKey,&pGPortList);
  2055. }
  2056. if(!NT_SUCCESS(ntStatus))
  2057. {
  2058. USBPRINT_KdPrint1(("USBPRINT.SYS: GetPortNumber; failed to allocate new port number\n"));
  2059. }
  2060. else
  2061. {
  2062. *ulReturnNumber=ulPortNumber;
  2063. USBPRINT_KdPrint3(("USBPRINT.SYS: GetPortNumber; Inside \"write back to reg\" case, ulPortNumber==%d\n",ulPortNumber));
  2064. USBPRINT_KdPrint3(("USBPRINT.SYS: GetPortNumber; Before ntstatys=success\n"));
  2065. ntStatus=STATUS_SUCCESS;
  2066. USBPRINT_KdPrint3(("USBPRINT.SYS: GetPortNumber; Before ZwSetValueKey\n"));
  2067. ntStatus=ZwSetValueKey(hInterfaceKey,&uncValueName,0,REG_DWORD,&ulPortNumber,sizeof(ulPortNumber));
  2068. if(!NT_SUCCESS(ntStatus))
  2069. {
  2070. USBPRINT_KdPrint1(("USBPRINT.SYS: GetPortNumber; Unable to set value key\n"));
  2071. }
  2072. else
  2073. {
  2074. *ulReturnNumber=ulPortNumber;
  2075. }
  2076. }
  2077. ExFreePool(pValueStruct);
  2078. return ntStatus;
  2079. } /*end function GetPortNumber*/
  2080. USBPRINT_GetDeviceID(PDEVICE_OBJECT ParentDeviceObject)
  2081. {
  2082. UCHAR *p1284Id;
  2083. NTSTATUS ntStatus;
  2084. int iReturnSize;
  2085. PDEVICE_EXTENSION pParentExtension;
  2086. pParentExtension=ParentDeviceObject->DeviceExtension;
  2087. USBPRINT_KdPrint1 (("USBPRINT.SYS: GetDeviceID enter\n")); /*dd*/
  2088. p1284Id=ExAllocatePoolWithTag(NonPagedPool,MAX_ID_SIZE, USBP_TAG);
  2089. if(p1284Id==NULL)
  2090. {
  2091. pParentExtension->bBadDeviceID=TRUE;
  2092. USBPRINT_KdPrint1 (("USBPRINT.SYS: Memory Allocation failed in GetDeviceID\n"));
  2093. sprintf(pParentExtension->DeviceIdString,BOGUS_PNP_ID);
  2094. }
  2095. else
  2096. {
  2097. iReturnSize=USBPRINT_Get1284Id(ParentDeviceObject,p1284Id,MAX_ID_SIZE-ID_OVERHEAD); //
  2098. if(iReturnSize==-1)
  2099. {
  2100. pParentExtension->bBadDeviceID=TRUE;
  2101. USBPRINT_KdPrint1 (("USBPRINT.SYS: Get1284Id Failed\n"));
  2102. sprintf(pParentExtension->DeviceIdString,BOGUS_PNP_ID);
  2103. } /*end if Get1284 failed*/
  2104. else
  2105. {
  2106. USBPRINT_KdPrint3 (("USBPRINT.SYS: Get1284Id Succeeded\n"));
  2107. USBPRINT_KdPrint2 (("USBPRINT.SYS: 1284 ID == %s\n",(p1284Id+2)));
  2108. ntStatus=ParPnpGetId(p1284Id+2,BusQueryDeviceID,pParentExtension->DeviceIdString);
  2109. USBPRINT_KdPrint3 (("USBPRINT.SYS: After call to ParPnpGetId"));
  2110. if(!NT_SUCCESS(ntStatus))
  2111. {
  2112. USBPRINT_KdPrint1 (("USBPRINT.SYS: ParPnpGetId failed, error== 0x%0X\n",ntStatus));
  2113. sprintf(pParentExtension->DeviceIdString,BOGUS_PNP_ID);
  2114. pParentExtension->bBadDeviceID=TRUE;
  2115. }
  2116. else
  2117. {
  2118. USBPRINT_KdPrint3 (("USBPRINT.SYS: After ParPnpGetID\n"));
  2119. USBPRINT_KdPrint2 (("USBPRINT.SYS: DeviceIdString=%s\n",pParentExtension->DeviceIdString));
  2120. }
  2121. } /*end if the request didn't fail*/
  2122. ExFreePool(p1284Id);
  2123. }
  2124. USBPRINT_KdPrint2 (("USBPRINT.SYS: GetDeviceID exit\n"));
  2125. } /*end function USBPRINT_GetDeviceID*/
  2126. NTSTATUS ProduceQueriedID(PDEVICE_EXTENSION deviceExtension,PIO_STACK_LOCATION irpStack,PIRP Irp,PDEVICE_OBJECT DeviceObject)
  2127. {
  2128. PDEVICE_EXTENSION pParentExtension;
  2129. NTSTATUS ntStatus=STATUS_SUCCESS;
  2130. WCHAR wTempString1[30];
  2131. PWSTR pWalk;
  2132. HANDLE hChildRegKey;
  2133. UCHAR *pRawString,*pTempString;
  2134. UNICODE_STRING UnicodeDeviceId;
  2135. UNICODE_STRING uncPortValueName;
  2136. ANSI_STRING AnsiIdString;
  2137. PCHILD_DEVICE_EXTENSION pChildExtension;
  2138. int iReturnSize;
  2139. int iFirstLen,iSecondLen, iTotalLen;
  2140. pChildExtension=(PCHILD_DEVICE_EXTENSION)deviceExtension;
  2141. pParentExtension=pChildExtension->ParentDeviceObject->DeviceExtension;
  2142. USBPRINT_KdPrint1(("USBPRINT.SYS: head of ProduceQueriedID\n")); /*dd*/
  2143. pRawString=ExAllocatePool(NonPagedPool,MAX_ID_SIZE);
  2144. pTempString=ExAllocatePool(NonPagedPool,MAX_ID_SIZE);
  2145. if((pTempString==NULL)||(pRawString==NULL))
  2146. {
  2147. USBPRINT_KdPrint1 (("USBPRINT.SYS: BusQueryDeviceIDs; No memory. Failing\n"));
  2148. ntStatus=STATUS_NO_MEMORY;
  2149. iReturnSize=-1;
  2150. }
  2151. else
  2152. {
  2153. if(pParentExtension->DeviceIdString[0]!=0)
  2154. {
  2155. switch(irpStack->Parameters.QueryId.IdType)
  2156. {
  2157. case BusQueryDeviceID:
  2158. USBPRINT_KdPrint1 (("USBPRINT.SYS: Received BusQueryDeviceID message\n"));
  2159. sprintf(pRawString,"USBPRINT\\%s",pParentExtension->DeviceIdString); //this sprintf safe.. DeviceIDString guaranteed to be 15 less than RawString
  2160. FixupDeviceId((PUCHAR)pRawString);
  2161. RtlInitAnsiString(&AnsiIdString,pRawString);
  2162. if(!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeDeviceId,&AnsiIdString,TRUE))) //Make a unicode string out of this
  2163. {
  2164. USBPRINT_KdPrint1 (("USBPRINT.SYS: RtlAnsiStringToUnicodeString failed\n"));
  2165. ntStatus=STATUS_NO_MEMORY;
  2166. iReturnSize=-1;
  2167. Irp->IoStatus.Information=0;
  2168. break;
  2169. }
  2170. ntStatus=STATUS_SUCCESS;
  2171. Irp->IoStatus.Information=(ULONG_PTR)UnicodeDeviceId.Buffer;
  2172. USBPRINT_KdPrint1(("USBPRINT.SYS: returing DeviceID\n")); /*dd*/
  2173. break;
  2174. case BusQueryInstanceID:
  2175. USBPRINT_KdPrint2 (("USBPRINT.SYS: Received BusQueryInstanceID message\n"));
  2176. USBPRINT_KdPrint2 (("USBPRINT.SYS: returning instance %u\n",pChildExtension->ulInstanceNumber));
  2177. sprintf(pRawString,"USB%03u",pChildExtension->ulInstanceNumber);
  2178. USBPRINT_KdPrint2 (("USBPRINT.SYS: RawString=%s\n",pRawString));
  2179. RtlInitAnsiString(&AnsiIdString,pRawString);
  2180. if(!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeDeviceId,&AnsiIdString,TRUE))) //Make a unicode string out of this
  2181. {
  2182. ntStatus=STATUS_NO_MEMORY;
  2183. iReturnSize=-1;
  2184. Irp->IoStatus.Information=0;
  2185. break;
  2186. }
  2187. ntStatus=STATUS_SUCCESS;
  2188. Irp->IoStatus.Information=(ULONG_PTR)UnicodeDeviceId.Buffer;
  2189. break;
  2190. case BusQueryHardwareIDs:
  2191. USBPRINT_KdPrint2 (("USBPRINT.SYS: Received BusQueryHardwareIDs message\n"));
  2192. #ifndef WIN9XBUILD
  2193. USBPRINT_KdPrint2 (("USBPRINT.SYS: inside IF NT\n"));
  2194. ntStatus=IoOpenDeviceRegistryKey(DeviceObject,PLUGPLAY_REGKEY_DEVICE,KEY_ALL_ACCESS,&hChildRegKey);
  2195. #else
  2196. USBPRINT_KdPrint2 (("USBPRINT.SYS: inside not NT\n"));
  2197. ntStatus=IoOpenDeviceRegistryKey(pParentExtension->PhysicalDeviceObject,PLUGPLAY_REGKEY_DEVICE,KEY_ALL_ACCESS,&hChildRegKey);
  2198. #endif
  2199. if(!NT_SUCCESS(ntStatus))
  2200. {
  2201. USBPRINT_KdPrint1 (("USBPRINT.SYS: BusQueryHardwareIDs; IoOpenDeviceRegistryKey failed\n"));
  2202. break;
  2203. }
  2204. swprintf(wTempString1,L"USB%03u",pChildExtension->ulInstanceNumber);
  2205. RtlInitUnicodeString(&uncPortValueName,L"PortName");
  2206. ntStatus=ZwSetValueKey(hChildRegKey,&uncPortValueName,0,REG_SZ,wTempString1,(wcslen(wTempString1)+1)*sizeof(WCHAR));
  2207. if(!NT_SUCCESS(ntStatus))
  2208. {
  2209. USBPRINT_KdPrint1 (("USBPRINT.SYS: BusQueryHardwareIDs; ZwSetValueKey failed\n"));
  2210. }
  2211. else
  2212. {
  2213. USBPRINT_KdPrint3 (("USBPRINT.SYS: BusQueryHardwareIDs; ZwSetValueKey worked, wcslen(wTempString1)==%u\n",wcslen(wTempString1)));
  2214. ntStatus=STATUS_SUCCESS;
  2215. }
  2216. ZwClose(hChildRegKey);
  2217. if(pParentExtension->DeviceIdString[0]==0)
  2218. {
  2219. ntStatus=STATUS_NOT_FOUND;
  2220. USBPRINT_KdPrint2 (("USBPRINT.SYS: BusQueryCompatibleIDs; DeviceIdString is null. Can't continue\n"));
  2221. break;
  2222. }
  2223. ntStatus=ParPnpGetId(pParentExtension->DeviceIdString,irpStack->Parameters.QueryId.IdType,pRawString);
  2224. if(!NT_SUCCESS(ntStatus))
  2225. {
  2226. USBPRINT_KdPrint1 (("USBPRINT.SYS: BusQueryDeviceIDs; ParPnpGetID failed\n"));
  2227. break;
  2228. }
  2229. if((strlen(pRawString)+ID_OVERHEAD)*2>MAX_ID_SIZE)
  2230. {
  2231. ntStatus=STATUS_NO_MEMORY;
  2232. USBPRINT_KdPrint1 (("USBPRINT.SYS: BusQueryDeviceIDs; ID's to long. Failing\n"));
  2233. iReturnSize=-1;
  2234. break;
  2235. }
  2236. sprintf(pTempString,"USBPRINT\\%s",pRawString);
  2237. iFirstLen=strlen(pTempString);
  2238. *(pTempString+iFirstLen)=' '; //make the old null be a space so that RtlInitAnsiString will step past it
  2239. *(pTempString+iFirstLen+1)='\0'; //add an extra null at the end of the string
  2240. strcat(pTempString,pRawString);
  2241. iTotalLen=strlen(pTempString);
  2242. #ifdef USBPRINT_LIE_ABOUT_LPT
  2243. *(pTempString+iTotalLen)=' ';
  2244. *(pTempString+iTotalLen+1)='\0';
  2245. iSecondLen=iTotalLen;
  2246. strcat(pTempString,"LPTENUM\\");
  2247. strcat(pTempString,pRawString);
  2248. iTotalLen=strlen(pTempString);
  2249. #endif
  2250. *(pTempString+iTotalLen)=' ';
  2251. *(pTempString+iTotalLen+1)='\0';
  2252. FixupDeviceId((PUCHAR)pTempString);
  2253. RtlInitAnsiString(&AnsiIdString,pTempString); //make a counted ansi string
  2254. if(!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeDeviceId,&AnsiIdString,TRUE))) //Make a unicode string out of this
  2255. {
  2256. ntStatus=STATUS_NO_MEMORY;
  2257. iReturnSize=-1;
  2258. Irp->IoStatus.Information=0;
  2259. break;
  2260. }
  2261. pWalk = UnicodeDeviceId.Buffer+iFirstLen; //Set a pointer to the beginning of the string
  2262. *pWalk=L'\0'; //set the space to be a unicode null
  2263. #ifdef USBPRINT_LIE_ABOUT_LPT
  2264. pWalk = UnicodeDeviceId.Buffer+iSecondLen; //Set a pointer to the beginning of the string
  2265. *pWalk=L'\0'; //set the space to be a unicode null
  2266. #endif
  2267. pWalk = UnicodeDeviceId.Buffer+iTotalLen; //set a pointer to the space at the end of the total string
  2268. *pWalk=L'\0'; //set the space to be a unicode null, so that we now have a double unicode null.
  2269. Irp->IoStatus.Information = (ULONG_PTR)UnicodeDeviceId.Buffer;
  2270. break;
  2271. case BusQueryCompatibleIDs:
  2272. USBPRINT_KdPrint2 (("USBPRINT.SYS: Received BusQueryCompatibleIDs message\n"));
  2273. Irp->IoStatus.Information = (ULONG_PTR) NULL; //(ULONG_PTR)UnicodeDeviceId.Buffer;
  2274. break;
  2275. default:
  2276. {
  2277. USBPRINT_KdPrint2 (("USBPRINT.SYS: Received unkown BusQuery message\n"));
  2278. ntStatus = Irp->IoStatus.Status;
  2279. }
  2280. } /*end switch ID type*/
  2281. } /*end no 1284 ID*/
  2282. else
  2283. {
  2284. ntStatus=STATUS_NOT_FOUND;
  2285. }
  2286. }
  2287. if(pTempString!=NULL)
  2288. ExFreePool(pTempString);
  2289. if(pRawString!=NULL)
  2290. ExFreePool(pRawString);
  2291. return ntStatus;
  2292. } /*End function QueryID*/
  2293. //
  2294. // Function: bAddPortInUseItem
  2295. //
  2296. // Description : iPortNumber is removed from the free ports list structure.
  2297. //
  2298. // Parameters: IN\OUT pFreePorts - is the beginning of the list and on return will contain the beginning of the list.
  2299. // pFreePorts may change during the call.
  2300. // IN iPortNumber - the port number that is in use.
  2301. //
  2302. // Returns: NTSTATUS value - STATUS_NO_MEMORY
  2303. // - STATUS_SUCCESS
  2304. //
  2305. NTSTATUS bAddPortInUseItem(PFREE_PORTS * pFreePorts,ULONG iPortNumber )
  2306. {
  2307. NTSTATUS ntstatus = STATUS_SUCCESS;
  2308. PFREE_PORTS pBefore = *pFreePorts;
  2309. PFREE_PORTS pHead = *pFreePorts;
  2310. PFREE_PORTS pNewBlock = NULL;
  2311. USBPRINT_KdPrint2 ((" USBPRINT.SYS: Head of bAddPortInUseItem\n"));
  2312. //
  2313. // Traverse the FREE_PORT structure to remove the port number from the list.
  2314. // Note - This function will not be needed to be called by anyone else other than LoadPortsUsed
  2315. // as the GetNewPortNumber will do this functionality automatically.
  2316. //
  2317. while( *pFreePorts )
  2318. {
  2319. if( iPortNumber >= (*pFreePorts)->iBottomOfRange && iPortNumber <= (*pFreePorts)->iTopOfRange )
  2320. {
  2321. // We're where we want to be - so decide what to do...
  2322. if( iPortNumber == (*pFreePorts)->iBottomOfRange )
  2323. {
  2324. if( (++((*pFreePorts)->iBottomOfRange)) > (*pFreePorts)->iTopOfRange )
  2325. {
  2326. // Case of the Port Number being the first and only element in the first block.
  2327. if( *pFreePorts == pHead )
  2328. {
  2329. pHead = (*pFreePorts)->pNextBlock;
  2330. }
  2331. else // Case of the Port Number being the first element in another block.
  2332. {
  2333. pBefore->pNextBlock = (*pFreePorts)->pNextBlock;
  2334. }
  2335. ExFreePool( *pFreePorts );
  2336. }
  2337. }
  2338. else
  2339. {
  2340. if( iPortNumber == (*pFreePorts)->iTopOfRange )
  2341. { // Deletion case handled in the above case, so just need to decrement.
  2342. ((*pFreePorts)->iTopOfRange)--;
  2343. }
  2344. else // Otherwise we're in the middle of the block and we need to split it.
  2345. {
  2346. pNewBlock = ExAllocatePoolWithTag( NonPagedPool, sizeof(FREE_PORTS), USBP_TAG);
  2347. if( !pNewBlock )
  2348. {
  2349. ntstatus = STATUS_NO_MEMORY;
  2350. goto Cleanup;
  2351. }
  2352. pNewBlock->iTopOfRange = (*pFreePorts)->iTopOfRange;
  2353. (*pFreePorts)->iTopOfRange = iPortNumber - 1;
  2354. pNewBlock->iBottomOfRange = iPortNumber + 1;
  2355. pNewBlock->pNextBlock = (*pFreePorts)->pNextBlock;
  2356. (*pFreePorts)->pNextBlock = pNewBlock;
  2357. }
  2358. }
  2359. break;
  2360. }
  2361. else
  2362. {
  2363. if( iPortNumber < (*pFreePorts)->iBottomOfRange )
  2364. { // The port number has already been used - not in the free list.
  2365. USBPRINT_KdPrint2 ((" USBPRINT.SYS: Port number %n is allocated already from free list.\n", iPortNumber));
  2366. break;
  2367. }
  2368. pBefore = *pFreePorts;
  2369. *pFreePorts = (*pFreePorts)->pNextBlock;
  2370. }
  2371. }
  2372. if( NULL == *pFreePorts )
  2373. {
  2374. ntstatus = STATUS_INVALID_PARAMETER;
  2375. // Assert this as we could never allocate a port number that is not in the initial ranges 1-999
  2376. // - but if we assert here, we have run off the end of the port allocation numbers.
  2377. ASSERT( *pFreePorts );
  2378. }
  2379. Cleanup:
  2380. *pFreePorts = pHead;
  2381. return ntstatus;
  2382. } /*end function bAddPortInUseItem*/
  2383. void vClaimPortNumber(ULONG ulPortNumber,HANDLE hInterfaceKey,PFREE_PORTS * pPortsUsed)
  2384. {
  2385. UNICODE_STRING wRecycle;
  2386. WCHAR *pName;
  2387. pName=L"RECYCLABLE";
  2388. RtlInitUnicodeString(&wRecycle,pName);
  2389. #if WIN95_BUILD==1
  2390. SetValueToZero(hInterfaceKey,&wRecycle);
  2391. #else
  2392. ZwDeleteValueKey(hInterfaceKey,&wRecycle);
  2393. #endif
  2394. // Do we need to fail out gracefully from the below?
  2395. // The func doesn't have a return, but we could fail a mem alloc inside the below call!!
  2396. // bAddPortInUseItem(pPortsUsed,ulPortNumber);
  2397. } /*end function vClaimPortNumber*/
  2398. NTSTATUS GetNewPortNumber(PFREE_PORTS * pFreePorts, ULONG *pulPortNumber)
  2399. {
  2400. NTSTATUS ntstatus = STATUS_SUCCESS;
  2401. PFREE_PORTS pTemp = *pFreePorts;
  2402. USBPRINT_KdPrint2 (("USBPRINT.SYS: Head of GetNewPortNumber\n"));
  2403. if( NULL == *pFreePorts )
  2404. {
  2405. // If the pFreePorts list is empty - try to reconstruct it.
  2406. ntstatus=InitFreePorts(pFreePorts);
  2407. if(NT_SUCCESS(ntstatus))
  2408. ntstatus=LoadPortsUsed((GUID *)&USBPRINT_GUID,pFreePorts,USB_BASE_NAME);
  2409. if( NULL == *pFreePorts && NT_SUCCESS(ntstatus))
  2410. {
  2411. ntstatus=STATUS_INVALID_PORT_HANDLE;
  2412. }
  2413. if(!NT_SUCCESS(ntstatus))
  2414. {
  2415. *pulPortNumber = 0;
  2416. goto Cleanup;
  2417. }
  2418. }
  2419. *pulPortNumber = (*pFreePorts)->iBottomOfRange;
  2420. if( (++((*pFreePorts)->iBottomOfRange)) > (*pFreePorts)->iTopOfRange )
  2421. {
  2422. // Case of the Port Number being the first and only element in the first block.
  2423. *pFreePorts = (*pFreePorts)->pNextBlock;
  2424. ExFreePool( pTemp );
  2425. }
  2426. Cleanup:
  2427. return ntstatus;
  2428. } /*end function GetNewPortNumber*/
  2429. BOOL bDeleteIfRecyclable(HANDLE hRegKey)
  2430. {
  2431. BOOL bReturn=FALSE;
  2432. UNICODE_STRING wcValueName;
  2433. NTSTATUS ntStatus;
  2434. USBPRINT_KdPrint2 (("USBPRINT.SYS: Head of bDeleteifRecyclable\n"));
  2435. RtlInitUnicodeString(&wcValueName,L"recyclable");
  2436. #if WIN95_BUILD==1
  2437. ntStatus=SetValueToZero(hRegKey,&wcValueName);
  2438. #else
  2439. ntStatus=ZwDeleteValueKey(hRegKey,&wcValueName);
  2440. #endif
  2441. if(NT_SUCCESS(ntStatus))
  2442. {
  2443. RtlInitUnicodeString(&wcValueName,L"Port Number");
  2444. #if WIN95_BUILD==1
  2445. ntStatus=SetValueToZero(hRegKey,&wcValueName);
  2446. #else
  2447. ntStatus=ZwDeleteValueKey(hRegKey,&wcValueName);
  2448. #endif
  2449. if(NT_SUCCESS(ntStatus))
  2450. bReturn=TRUE;
  2451. } // end function bDeleteIfRecyclable
  2452. if(bReturn)
  2453. {
  2454. USBPRINT_KdPrint3 (("USBPRINT.SYS: bDeleteIfRecyclable, returning TRUE\n"));
  2455. }
  2456. else
  2457. {
  2458. USBPRINT_KdPrint3 (("USBPRINT.SYS: bDeleteIfRecyclable, returning FALSE\n"));
  2459. }
  2460. return bReturn;
  2461. } //End function bDeleteIfRecycable
  2462. //
  2463. // Initialises the free ports structure list.
  2464. // pHead must be NULL or a valid pointer to a FREE_PORTS structure.
  2465. //
  2466. NTSTATUS InitFreePorts( PFREE_PORTS * pHead )
  2467. {
  2468. PFREE_PORTS pNext = *pHead;
  2469. NTSTATUS ntstatus = STATUS_SUCCESS;
  2470. while(pNext)
  2471. {
  2472. pNext = (*pHead)->pNextBlock;
  2473. ExFreePool(*pHead);
  2474. *pHead = pNext;
  2475. }
  2476. //
  2477. // Any old list will be cleared from memory and pHead will be NULL
  2478. //
  2479. *pHead = ExAllocatePoolWithTag(NonPagedPool, sizeof(FREE_PORTS), USBP_TAG);
  2480. if( *pHead )
  2481. {
  2482. (*pHead)->iBottomOfRange = MIN_PORT_NUMBER;
  2483. (*pHead)->iTopOfRange = MAX_PORT_NUMBER;
  2484. (*pHead)->pNextBlock = NULL;
  2485. }
  2486. else
  2487. ntstatus = STATUS_NO_MEMORY;
  2488. return ntstatus;
  2489. }
  2490. void ClearFreePorts( PFREE_PORTS * pHead )
  2491. {
  2492. PFREE_PORTS pTemp = *pHead;
  2493. while( *pHead )
  2494. {
  2495. *pHead = (*pHead)->pNextBlock;
  2496. ExFreePool( pTemp );
  2497. pTemp = *pHead;
  2498. }
  2499. }
  2500. /********************************************************
  2501. * SetValueToZero. Sets and interger reg key to zero.
  2502. * Returns failure if reg key does not exist, or if
  2503. * The key already is set to zero. Mimics ZwDeleteValueKey
  2504. * (which is not currently avaiable on Milinium) by
  2505. * useing the value 0 to mean deleted
  2506. **************************************************************/
  2507. NTSTATUS SetValueToZero(HANDLE hRegKey,PUNICODE_STRING ValueName)
  2508. {
  2509. PKEY_VALUE_PARTIAL_INFORMATION pValueStruct;
  2510. NTSTATUS ReturnCode;
  2511. ULONG dwZero=0;
  2512. ULONG ulSizeUsed;
  2513. NTSTATUS ntStatus;
  2514. int iValue;
  2515. ulSizeUsed=sizeof(KEY_VALUE_PARTIAL_INFORMATION)+sizeof(ULONG); //this is a byte to much. Oh well
  2516. pValueStruct=ExAllocatePool(NonPagedPool,ulSizeUsed);
  2517. if(pValueStruct==NULL)
  2518. {
  2519. USBPRINT_KdPrint1(("USBPRINT.SYS: SetValueToZero; Unable to allocate memory\n"));
  2520. return STATUS_NO_MEMORY;
  2521. }
  2522. ntStatus=ZwQueryValueKey(hRegKey,ValueName,KeyValuePartialInformation,pValueStruct,ulSizeUsed,&ulSizeUsed);
  2523. if(!NT_SUCCESS(ntStatus))
  2524. {
  2525. USBPRINT_KdPrint3(("Failed to Query value Key\n"));
  2526. ExFreePool(pValueStruct);
  2527. return STATUS_OBJECT_NAME_NOT_FOUND;
  2528. }
  2529. iValue=(int)*((ULONG *)(pValueStruct->Data));
  2530. ExFreePool(pValueStruct);
  2531. if(iValue==0)
  2532. return STATUS_OBJECT_NAME_NOT_FOUND;
  2533. //if we make it to here, the value exists, and is nonzero
  2534. ReturnCode=ZwSetValueKey(hRegKey,ValueName,0,REG_DWORD,&dwZero,sizeof(dwZero));
  2535. return ReturnCode;
  2536. } /*end function SetValueToZero*/
  2537. VOID
  2538. USBPRINT_FdoIdleNotificationCallback(IN PDEVICE_EXTENSION DevExt)
  2539. /*++
  2540. Routine Description:
  2541. Called when it is time to idle out USB printer
  2542. --*/
  2543. {
  2544. POWER_STATE powerState;
  2545. NTSTATUS ntStatus;
  2546. USBPRINT_KdPrint1(("USB Printer (%08X) going idle\n", DevExt));
  2547. if(!DevExt->AcceptingRequests || DevExt->OpenCnt)
  2548. {
  2549. // Don't idle this printer if the printer is not accepting requests
  2550. USBPRINT_KdPrint1(("USB Printer (%08X) not accepting requests, abort idle\n", DevExt));
  2551. return;
  2552. }
  2553. powerState.DeviceState = DevExt->DeviceWake;
  2554. // request new device power state, wait wake Irp will be posted on request
  2555. PoRequestPowerIrp(DevExt->PhysicalDeviceObject,
  2556. IRP_MN_SET_POWER,
  2557. powerState,
  2558. NULL,
  2559. NULL,
  2560. NULL);
  2561. } // USBPRINT_FdoIdleNotificationCallback
  2562. NTSTATUS
  2563. USBPRINT_FdoIdleNotificationRequestComplete(
  2564. PDEVICE_OBJECT DeviceObject,
  2565. PIRP Irp,
  2566. PDEVICE_EXTENSION DevExt
  2567. )
  2568. /*++
  2569. Routine Description:
  2570. Completion routine for the Idle request IRP for the USB printer device
  2571. --*/
  2572. {
  2573. NTSTATUS ntStatus;
  2574. PUSB_IDLE_CALLBACK_INFO idleCallbackInfo;
  2575. //
  2576. // DeviceObject is NULL because we sent the irp
  2577. //
  2578. UNREFERENCED_PARAMETER(DeviceObject);
  2579. USBPRINT_KdPrint1(("Idle notification IRP for USB Printer (%08X) completed (%08X)\n",
  2580. DevExt, Irp->IoStatus.Status));
  2581. // save completion status in device extension
  2582. idleCallbackInfo = DevExt->IdleCallbackInfo;
  2583. DevExt->IdleCallbackInfo = NULL;
  2584. DevExt->PendingIdleIrp = NULL;
  2585. // free up callback info
  2586. if(idleCallbackInfo)
  2587. {
  2588. ExFreePool(idleCallbackInfo);
  2589. }
  2590. ntStatus = Irp->IoStatus.Status;
  2591. return ntStatus;
  2592. } // USBPRINT_FdoIdleNotificationRequestComplete
  2593. NTSTATUS
  2594. USBPRINT_FdoSubmitIdleRequestIrp(IN PDEVICE_EXTENSION DevExt)
  2595. /*++
  2596. Routine Description:
  2597. Called when all handles to the USB printer are closed. This function allocates
  2598. an idle request IOCTL IRP and passes it to the parent's PDO.
  2599. --*/
  2600. {
  2601. PIRP irp = NULL;
  2602. NTSTATUS ntStatus = STATUS_SUCCESS;
  2603. PUSB_IDLE_CALLBACK_INFO idleCallbackInfo = NULL;
  2604. USBPRINT_KdPrint1(("USBPRINT_FdoSubmitIdleRequestIrp (%08X)\n", DevExt));
  2605. // if we have an Irp pending, don't bother to send another
  2606. if(DevExt->PendingIdleIrp || DevExt->CurrentDevicePowerState == DevExt->DeviceWake)
  2607. return ntStatus;
  2608. idleCallbackInfo = ExAllocatePoolWithTag(NonPagedPool,
  2609. sizeof(struct _USB_IDLE_CALLBACK_INFO), USBP_TAG);
  2610. if (idleCallbackInfo)
  2611. {
  2612. idleCallbackInfo->IdleCallback = USBPRINT_FdoIdleNotificationCallback;
  2613. idleCallbackInfo->IdleContext = (PVOID)DevExt;
  2614. DevExt->IdleCallbackInfo = idleCallbackInfo;
  2615. irp = IoBuildDeviceIoControlRequest(
  2616. IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION,
  2617. DevExt->PhysicalDeviceObject,
  2618. idleCallbackInfo,
  2619. sizeof(struct _USB_IDLE_CALLBACK_INFO),
  2620. NULL,
  2621. 0,
  2622. TRUE, /* INTERNAL */
  2623. NULL,
  2624. NULL);
  2625. if (irp == NULL)
  2626. {
  2627. ExFreePool(idleCallbackInfo);
  2628. return STATUS_INSUFFICIENT_RESOURCES;
  2629. }
  2630. IoSetCompletionRoutine(irp,
  2631. USBPRINT_FdoIdleNotificationRequestComplete,
  2632. DevExt,
  2633. TRUE,
  2634. TRUE,
  2635. TRUE);
  2636. ntStatus = IoCallDriver(DevExt->PhysicalDeviceObject, irp);
  2637. if(ntStatus == STATUS_PENDING)
  2638. {
  2639. // Successfully posted an Idle IRP.
  2640. DevExt->PendingIdleIrp = irp;
  2641. }
  2642. }
  2643. return ntStatus;
  2644. } // USBPRINT_FdoSubmitIdleRequestIrp
  2645. VOID
  2646. USBPRINT_FdoRequestWake(IN PDEVICE_EXTENSION DevExt)
  2647. /*++
  2648. Routine Description:
  2649. Called when we want to wake up the device after an idle request
  2650. --*/
  2651. {
  2652. POWER_STATE powerState;
  2653. KIRQL OldIrql;
  2654. BOOL bExit=FALSE;
  2655. USBPRINT_KdPrint1(("USBPRINT: USB Printer (%08X) waking up\n", DevExt));
  2656. KeAcquireSpinLock(&(DevExt->WakeSpinLock),&OldIrql);
  2657. if(!DevExt->AcceptingRequests || DevExt->CurrentDevicePowerState == PowerDeviceD0 || DevExt->bD0IrpPending)
  2658. {
  2659. // Don't wake this printer if it's not accepting requests or we're already at power state D0
  2660. if(!DevExt->AcceptingRequests)
  2661. USBPRINT_KdPrint1(("USBPRINT: USB Printer (%08X) not accepting requests, abort wake\n", DevExt));
  2662. if(DevExt->CurrentDevicePowerState == PowerDeviceD0)
  2663. USBPRINT_KdPrint1(("USBPRINT: USB Printer (%08X) already at D0, abort wake\n", DevExt));
  2664. if(DevExt->bD0IrpPending == TRUE)
  2665. USBPRINT_KdPrint1(("USBPRINT: USB Printer (%08X) already has D0 irp pending, abort wake\n", DevExt));
  2666. bExit=TRUE;
  2667. }
  2668. else
  2669. DevExt->bD0IrpPending=TRUE;
  2670. KeReleaseSpinLock(&(DevExt->WakeSpinLock),OldIrql);
  2671. if(bExit)
  2672. return;
  2673. powerState.DeviceState = PowerDeviceD0;
  2674. // request new device power state, wake up the device
  2675. PoRequestPowerIrp(DevExt->PhysicalDeviceObject,
  2676. IRP_MN_SET_POWER,
  2677. powerState,
  2678. NULL,
  2679. NULL,
  2680. NULL);
  2681. } // USBPRINT_FdoRequestWake
  2682. void vOpenLogFile(HANDLE *pHandle)
  2683. {
  2684. NTSTATUS ntStatus;
  2685. OBJECT_ATTRIBUTES FileAttributes;
  2686. IO_STATUS_BLOCK StatusBlock;
  2687. UNICODE_STRING PathName;
  2688. RtlInitUnicodeString(&PathName,L"\\??\\C:\\USBPRINT.LOG");
  2689. InitializeObjectAttributes(&FileAttributes,&PathName,0,NULL,NULL);
  2690. ntStatus=ZwCreateFile(pHandle,
  2691. GENERIC_WRITE,
  2692. &FileAttributes,
  2693. &StatusBlock,
  2694. 0,
  2695. 0,
  2696. FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
  2697. FILE_OPEN_IF,
  2698. FILE_NON_DIRECTORY_FILE|FILE_WRITE_THROUGH|FILE_SYNCHRONOUS_IO_NONALERT,
  2699. NULL,
  2700. 0);
  2701. if(!NT_SUCCESS(ntStatus))
  2702. {
  2703. USBPRINT_KdPrint1(("USBPRINT: Unable to open C:\\USBPRINT.LOG"));
  2704. }
  2705. else
  2706. {
  2707. USBPRINT_KdPrint1(("USBPRINT: Opened logfile C:\\USBPRINT.LOG")); /*dd*/
  2708. }
  2709. }
  2710. void vWriteToLogFile(HANDLE *pHandle,IN CHAR *pszString)
  2711. {
  2712. HANDLE hFileHandle;
  2713. ULONG BufferSize;
  2714. NTSTATUS ntStatus;
  2715. IO_STATUS_BLOCK StatusBlock;
  2716. LARGE_INTEGER WriteOffset;
  2717. WriteOffset.LowPart=FILE_WRITE_TO_END_OF_FILE;
  2718. WriteOffset.HighPart=-1;
  2719. BufferSize=strlen(pszString);
  2720. ntStatus=ZwWriteFile(*pHandle,
  2721. NULL,
  2722. NULL,
  2723. NULL,
  2724. &StatusBlock,
  2725. pszString,
  2726. BufferSize,
  2727. &WriteOffset,
  2728. NULL);
  2729. if(!NT_SUCCESS(ntStatus))
  2730. {
  2731. USBPRINT_KdPrint1(("USBPRINT: Unable to write to log file C:\\USBPRINT.LOG"));
  2732. }
  2733. else
  2734. {
  2735. USBPRINT_KdPrint1(("USBPRINT: write to log file C:\\USBPRINT.LOG")); /*dd*/
  2736. }
  2737. } /*end function vWriteToLog*/
  2738. void vCloseLogFile(IN HANDLE *pHandle)
  2739. {
  2740. ZwClose(*pHandle);
  2741. } /*end function vCloseLogFile*/