Source code of Windows XP (NT5)
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.

3574 lines
109 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. if(NT_SUCCESS(ntStatus))
  749. Irp->IoStatus.Information=(ULONG_PTR)UnicodeDeviceText.Buffer;
  750. }
  751. break;
  752. default:
  753. ntStatus=Irp->IoStatus.Status;
  754. }
  755. bHandled=TRUE;
  756. USBPRINT_DecrementIoCount(DeviceObject);
  757. Irp->IoStatus.Status = ntStatus;
  758. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  759. }
  760. break;
  761. case IRP_MN_QUERY_BUS_INFORMATION:
  762. if(deviceExtension->IsChildDevice==TRUE)
  763. {
  764. PPNP_BUS_INFORMATION pBusInfo = ExAllocatePool( PagedPool, sizeof(PNP_BUS_INFORMATION) );
  765. USBPRINT_KdPrint2(("USBPRINT.SYS: IRP_MN_QUERY_BUS_INFORMATION\n"));
  766. if( pBusInfo )
  767. {
  768. pBusInfo->BusTypeGuid = GUID_BUS_TYPE_USBPRINT;
  769. pBusInfo->LegacyBusType = PNPBus;
  770. pBusInfo->BusNumber = 0;
  771. ntStatus = STATUS_SUCCESS;
  772. Irp->IoStatus.Information = (ULONG_PTR)pBusInfo;
  773. }
  774. else
  775. {
  776. ntStatus = STATUS_NO_MEMORY;
  777. }
  778. bHandled = TRUE;
  779. USBPRINT_DecrementIoCount(DeviceObject);
  780. Irp->IoStatus.Status = ntStatus;
  781. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  782. }
  783. break;
  784. case IRP_MN_QUERY_ID:
  785. {
  786. USBPRINT_KdPrint2 (("USBPRINT.SYS: IRP_MN_QUERY_ID\n"));
  787. if(deviceExtension->IsChildDevice==TRUE)
  788. {
  789. USBPRINT_KdPrint2(("USBPRINT.SYS: Is child PDO, will complete locally\n"));
  790. ntStatus=ProduceQueriedID(deviceExtension,irpStack,Irp,DeviceObject);
  791. bHandled = TRUE;
  792. USBPRINT_DecrementIoCount(DeviceObject);
  793. Irp->IoStatus.Status = ntStatus;
  794. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  795. } /*end if child PDO*/
  796. } /*end case QUERY_ID*/
  797. break;
  798. case IRP_MN_QUERY_DEVICE_RELATIONS:
  799. USBPRINT_KdPrint2 (("USBPRINT.SYS: IRP_MN_QUERY_DEVICE_RELATIONS\n"));
  800. ntStatus=QueryDeviceRelations(DeviceObject,Irp,irpStack->Parameters.QueryDeviceRelations.Type,&bHandled);
  801. if ( bHandled )
  802. USBPRINT_DecrementIoCount(DeviceObject);
  803. break;
  804. case IRP_MN_QUERY_STOP_DEVICE:
  805. case IRP_MN_CANCEL_STOP_DEVICE:
  806. case IRP_MN_QUERY_REMOVE_DEVICE:
  807. case IRP_MN_CANCEL_REMOVE_DEVICE:
  808. if(deviceExtension->IsChildDevice)
  809. {
  810. Irp->IoStatus.Status = STATUS_SUCCESS;
  811. ntStatus=STATUS_SUCCESS;
  812. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  813. }
  814. else
  815. {
  816. ntStatus = Irp->IoStatus.Status = STATUS_SUCCESS;
  817. IoSkipCurrentIrpStackLocation(Irp);
  818. ntStatus = IoCallDriver(stackDeviceObject,Irp);
  819. }
  820. USBPRINT_DecrementIoCount(DeviceObject);
  821. bHandled = TRUE;
  822. break;
  823. } /* end IRP_MN swich inside IRP_MJ_PNP case */
  824. if(!bHandled)
  825. {
  826. if(deviceExtension->IsChildDevice==TRUE)
  827. {
  828. USBPRINT_KdPrint3(("USBPRINT.SYS: unsupported child pnp IRP\n"));
  829. ntStatus = Irp->IoStatus.Status;
  830. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  831. } /*end if child device*/
  832. else
  833. {
  834. IoSkipCurrentIrpStackLocation(Irp);
  835. ntStatus = IoCallDriver(stackDeviceObject,Irp);
  836. }
  837. USBPRINT_DecrementIoCount(DeviceObject);
  838. } /*end if !bHandled*/
  839. #ifdef MYDEBUG
  840. DbgPrint("Returning %d\n", ntStatus);
  841. #endif
  842. return ntStatus;
  843. } /*end function USBPRINT_Dispatch*/
  844. NTSTATUS
  845. USBPRINT_SystemControl(
  846. IN PDEVICE_OBJECT DeviceObject,
  847. IN PIRP Irp
  848. )
  849. /*++
  850. Routine Description:
  851. Process the IRPs sent to this device.
  852. Arguments:
  853. DeviceObject - pointer to a device object
  854. Irp - pointer to an I/O Request Packet
  855. Return Value:
  856. --*/
  857. {
  858. PDEVICE_EXTENSION deviceExtension;
  859. NTSTATUS ntStatus;
  860. PDEVICE_OBJECT stackDeviceObject;
  861. PAGED_CODE();
  862. //
  863. // Get a pointer to the device extension
  864. //
  865. deviceExtension = DeviceObject->DeviceExtension;
  866. stackDeviceObject = deviceExtension->TopOfStackDeviceObject;
  867. USBPRINT_IncrementIoCount(DeviceObject);
  868. if(deviceExtension->IsChildDevice==TRUE)
  869. {
  870. USBPRINT_KdPrint3(("USBPRINT.SYS: unsupported child SystemControl IRP\n"));
  871. ntStatus = Irp->IoStatus.Status;
  872. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  873. } /*end if child device*/
  874. else
  875. {
  876. IoSkipCurrentIrpStackLocation(Irp);
  877. ntStatus = IoCallDriver(stackDeviceObject,Irp);
  878. }
  879. USBPRINT_DecrementIoCount(DeviceObject);
  880. return ntStatus;
  881. }
  882. NTSTATUS QueryDeviceRelations(PDEVICE_OBJECT DeviceObject,PIRP Irp,DEVICE_RELATION_TYPE RelationType,BOOL *pbComplete)
  883. {
  884. PIO_STACK_LOCATION irpSp;
  885. NTSTATUS ntStatus;
  886. PDEVICE_EXTENSION pExtension;
  887. PDEVICE_RELATIONS pRelations;
  888. *pbComplete=FALSE;
  889. pExtension=(PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
  890. ntStatus=Irp->IoStatus.Status;
  891. irpSp=IoGetCurrentIrpStackLocation(Irp);
  892. if(!pExtension->IsChildDevice)
  893. {
  894. USBPRINT_KdPrint2 (("USBPRINT.SYS: Parent QueryDeviceRelations\n"));
  895. if(RelationType==BusRelations)
  896. {
  897. *pbComplete=TRUE;
  898. pRelations=(PDEVICE_RELATIONS)ExAllocatePoolWithTag(NonPagedPool,sizeof(DEVICE_RELATIONS), USBP_TAG);
  899. if(pRelations!=NULL)
  900. {
  901. //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
  902. pRelations->Objects[0]=pExtension->ChildDevice;
  903. pRelations->Count = 1;
  904. ObReferenceObject(pExtension->ChildDevice);
  905. Irp->IoStatus.Information=(ULONG_PTR)pRelations;
  906. Irp->IoStatus.Status = STATUS_SUCCESS;
  907. IoCopyCurrentIrpStackLocationToNext(Irp);
  908. ntStatus = IoCallDriver(pExtension->TopOfStackDeviceObject,Irp);
  909. } /*end !NULL*/
  910. else
  911. {
  912. ntStatus=STATUS_NO_MEMORY;
  913. Irp->IoStatus.Status = ntStatus;
  914. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  915. }
  916. //Port info will be written to the registry in the IRP_MN_QUERY_ID case. It can't be used before then anyway
  917. } /*end if BusRelations*/
  918. } else {
  919. USBPRINT_KdPrint2 (("USBPRINT.SYS: Child QueryDeviceRelations\n"));
  920. if(RelationType==TargetDeviceRelation)
  921. {
  922. *pbComplete=TRUE;
  923. pRelations=(PDEVICE_RELATIONS)ExAllocatePoolWithTag(NonPagedPool,sizeof(DEVICE_RELATIONS), USBP_TAG);
  924. if(pRelations!=NULL)
  925. {
  926. pRelations->Count = 1;
  927. pRelations->Objects[0]=DeviceObject;
  928. ObReferenceObject(DeviceObject);
  929. Irp->IoStatus.Information=(ULONG_PTR)pRelations;
  930. ntStatus = STATUS_SUCCESS;
  931. Irp->IoStatus.Status = ntStatus;
  932. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  933. } /*end !NULL*/
  934. else
  935. {
  936. ntStatus=STATUS_NO_MEMORY;
  937. Irp->IoStatus.Status = ntStatus;
  938. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  939. }
  940. //Port info will be written to the registry in the IRP_MN_QUERY_ID case. It can't be used before then anyway
  941. } /*end if BusRelations*/
  942. }
  943. return ntStatus;
  944. }
  945. VOID
  946. USBPRINT_Unload(
  947. IN PDRIVER_OBJECT DriverObject
  948. )
  949. /*++
  950. Routine Description:
  951. Free all the allocated resources, etc.
  952. Arguments:
  953. DriverObject - pointer to a driver object
  954. Return Value:
  955. --*/
  956. {
  957. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_Unload\n"));
  958. if(pGPortList!=NULL)
  959. {
  960. ClearFreePorts(&pGPortList);
  961. }
  962. // if(pPortsUsed!=NULL)
  963. // ExFreePool(pPortsUsed);
  964. //
  965. // Free any global resources allocated
  966. // in DriverEntry
  967. //
  968. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_Unload\n"));
  969. }
  970. NTSTATUS
  971. USBPRINT_StartDevice(
  972. IN PDEVICE_OBJECT DeviceObject
  973. )
  974. /*++
  975. Routine Description:
  976. Initializes a given instance of the device on the USB.
  977. All we do here is get the device descriptor and store it
  978. Arguments:
  979. DeviceObject - pointer to the device object for this instance of a printer
  980. Return Value:
  981. NT status code
  982. --*/
  983. {
  984. PDEVICE_EXTENSION deviceExtension;
  985. NTSTATUS ntStatus;
  986. UNICODE_STRING KeyName;
  987. PUSB_DEVICE_DESCRIPTOR deviceDescriptor = NULL;
  988. PURB urb=NULL;
  989. ULONG siz;
  990. ULONG dwVidPid;
  991. PDEVICE_OBJECT NewDevice;
  992. LARGE_INTEGER timeOut;
  993. PCHILD_DEVICE_EXTENSION pChildExtension;
  994. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_StartDevice\n"));
  995. deviceExtension = DeviceObject->DeviceExtension;
  996. ntStatus = USBPRINT_ConfigureDevice(DeviceObject);
  997. if(NT_SUCCESS(ntStatus))
  998. {
  999. urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), USBP_TAG);
  1000. }
  1001. else
  1002. {
  1003. USBPRINT_KdPrint1(("USBPRINT.SYS: USBPRINT_ConfigureDevice Failed\n"));
  1004. urb=NULL;
  1005. }
  1006. if (urb)
  1007. {
  1008. siz = sizeof(USB_DEVICE_DESCRIPTOR);
  1009. deviceDescriptor = ExAllocatePoolWithTag(NonPagedPool,siz, USBP_TAG);
  1010. if (deviceDescriptor)
  1011. {
  1012. UsbBuildGetDescriptorRequest(urb,
  1013. (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  1014. USB_DEVICE_DESCRIPTOR_TYPE,
  1015. 0,
  1016. 0,
  1017. deviceDescriptor,
  1018. NULL,
  1019. siz,
  1020. NULL);
  1021. timeOut.QuadPart = FAILURE_TIMEOUT;
  1022. ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
  1023. if (NT_SUCCESS(ntStatus))
  1024. {
  1025. USBPRINT_KdPrint3 (("USBPRINT.SYS: Device Descriptor = %x, len %x\n",
  1026. deviceDescriptor,
  1027. urb->UrbControlDescriptorRequest.TransferBufferLength));
  1028. USBPRINT_KdPrint3 (("USBPRINT.SYS: USBPRINT Device Descriptor:\n"));
  1029. USBPRINT_KdPrint3 (("USBPRINT.SYS: -------------------------\n"));
  1030. USBPRINT_KdPrint3 (("USBPRINT.SYS: bLength %d\n", deviceDescriptor->bLength));
  1031. USBPRINT_KdPrint3 (("USBPRINT.SYS: bDescriptorType 0x%x\n", deviceDescriptor->bDescriptorType));
  1032. USBPRINT_KdPrint3 (("USBPRINT.SYS: bcdUSB 0x%x\n", deviceDescriptor->bcdUSB));
  1033. USBPRINT_KdPrint3 (("USBPRINT.SYS: bDeviceClass 0x%x\n", deviceDescriptor->bDeviceClass));
  1034. USBPRINT_KdPrint3 (("USBPRINT.SYS: bDeviceSubClass 0x%x\n", deviceDescriptor->bDeviceSubClass));
  1035. USBPRINT_KdPrint3 (("USBPRINT.SYS: bDeviceProtocol 0x%x\n", deviceDescriptor->bDeviceProtocol));
  1036. USBPRINT_KdPrint3 (("USBPRINT.SYS: bMaxPacketSize0 0x%x\n", deviceDescriptor->bMaxPacketSize0));
  1037. USBPRINT_KdPrint3 (("USBPRINT.SYS: idVendor 0x%x\n", deviceDescriptor->idVendor));
  1038. USBPRINT_KdPrint3 (("USBPRINT.SYS: idProduct 0x%x\n", deviceDescriptor->idProduct));
  1039. USBPRINT_KdPrint3 (("USBPRINT.SYS: bcdDevice 0x%x\n", deviceDescriptor->bcdDevice));
  1040. USBPRINT_KdPrint3 (("USBPRINT.SYS: iManufacturer 0x%x\n", deviceDescriptor->iManufacturer));
  1041. USBPRINT_KdPrint3 (("USBPRINT.SYS: iProduct 0x%x\n", deviceDescriptor->iProduct));
  1042. USBPRINT_KdPrint3 (("USBPRINT.SYS: iSerialNumber 0x%x\n", deviceDescriptor->iSerialNumber));
  1043. USBPRINT_KdPrint3 (("USBPRINT.SYS: bNumConfigurations 0x%x\n", deviceDescriptor->bNumConfigurations));
  1044. dwVidPid=deviceDescriptor->idVendor;
  1045. dwVidPid<<=16;
  1046. dwVidPid+=deviceDescriptor->idProduct;
  1047. USBPRINT_KdPrint3 (("USBPRINT.SYS: Math OK\n"));
  1048. }
  1049. else
  1050. {
  1051. USBPRINT_KdPrint1(("USBPRINT.SYS: Get Device Descriptor failed\n"));
  1052. ntStatus=STATUS_DEVICE_CONFIGURATION_ERROR;
  1053. }
  1054. }
  1055. else
  1056. {
  1057. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1058. USBPRINT_KdPrint1(("USBPRINT.SYS: Insufficient resources to allocate device descriptor in StartDevice\n"));
  1059. }
  1060. if (NT_SUCCESS(ntStatus))
  1061. {
  1062. deviceExtension->DeviceDescriptor = deviceDescriptor;
  1063. } else if (deviceDescriptor)
  1064. {
  1065. ExFreePool(deviceDescriptor);
  1066. }
  1067. ExFreePool(urb);
  1068. }
  1069. else
  1070. {
  1071. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1072. USBPRINT_KdPrint1(("USBPRINT.SYS: Insufficient resources to allocate urb in StartDevice\n"));
  1073. }
  1074. if(deviceExtension->bChildDeviceHere==FALSE)
  1075. {
  1076. if(NT_SUCCESS(ntStatus))
  1077. {
  1078. ntStatus=IoCreateDevice(USBPRINT_DriverObject,
  1079. sizeof(CHILD_DEVICE_EXTENSION),
  1080. NULL,
  1081. FILE_DEVICE_PARALLEL_PORT,
  1082. FILE_AUTOGENERATED_DEVICE_NAME,
  1083. TRUE,
  1084. &NewDevice);
  1085. }
  1086. if(NT_SUCCESS(ntStatus))
  1087. {
  1088. USBPRINT_KdPrint3(("USBPRINT.SYS: IoCreateDevice succeeded for child device\n"));
  1089. NewDevice->Flags|=DO_POWER_PAGABLE;
  1090. pChildExtension=NewDevice->DeviceExtension;
  1091. pChildExtension->ParentDeviceObject=DeviceObject;
  1092. deviceExtension->ChildDevice=NewDevice;
  1093. deviceExtension->bChildDeviceHere=TRUE;
  1094. pChildExtension->IsChildDevice=TRUE;
  1095. pChildExtension->ulInstanceNumber=deviceExtension->ulInstanceNumber;
  1096. }
  1097. else
  1098. {
  1099. USBPRINT_KdPrint1(("USBPRINT.SYS: IoCreateDevice failed for child device\n"));
  1100. }
  1101. } /*end if we need to make a child device*/
  1102. if(NT_SUCCESS(ntStatus))
  1103. {
  1104. USBPRINT_GetDeviceID(DeviceObject);
  1105. WritePortDescription(deviceExtension);
  1106. ntStatus=IoSetDeviceInterfaceState(&(deviceExtension->DeviceLinkName),TRUE);
  1107. }
  1108. if (NT_SUCCESS(ntStatus))
  1109. {
  1110. ntStatus = USBPRINT_BuildPipeList(DeviceObject);
  1111. if(!deviceExtension->IsChildDevice)
  1112. {
  1113. USBPRINT_FdoSubmitIdleRequestIrp(deviceExtension);
  1114. }
  1115. }
  1116. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_StartDevice (%x)\n", ntStatus));
  1117. return ntStatus;
  1118. }
  1119. void WritePortDescription(PDEVICE_EXTENSION deviceExtension)
  1120. {
  1121. UNICODE_STRING ValueName;
  1122. ANSI_STRING AnsiTextString;
  1123. UNICODE_STRING Description;
  1124. UNICODE_STRING BaseName,BaseValueName;
  1125. RtlInitUnicodeString(&ValueName,L"Port Description");
  1126. RtlInitAnsiString(&AnsiTextString,deviceExtension->DeviceIdString);
  1127. RtlAnsiStringToUnicodeString(&Description,&AnsiTextString,TRUE);
  1128. ZwSetValueKey(deviceExtension->hInterfaceKey,&ValueName,0,REG_SZ,Description.Buffer,Description.Length+2);
  1129. RtlFreeUnicodeString(&Description);
  1130. RtlInitUnicodeString(&BaseName,L"USB");
  1131. RtlInitUnicodeString(&BaseValueName,L"Base Name");
  1132. ZwSetValueKey(deviceExtension->hInterfaceKey,&BaseValueName,0,REG_SZ,BaseName.Buffer,BaseName.Length+2);
  1133. }
  1134. NTSTATUS
  1135. USBPRINT_RemoveDevice(
  1136. IN PDEVICE_OBJECT DeviceObject
  1137. )
  1138. /*++
  1139. Routine Description:
  1140. Stops a given instance of printer
  1141. Arguments:
  1142. DeviceObject - pointer to the device object for this instance of the (parent) printer object
  1143. Return Value:
  1144. NT status code
  1145. --*/
  1146. {
  1147. PDEVICE_EXTENSION deviceExtension;
  1148. NTSTATUS ntStatus = STATUS_SUCCESS;
  1149. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_RemoveDevice\n"));
  1150. deviceExtension = DeviceObject->DeviceExtension;
  1151. ZwClose(deviceExtension->hInterfaceKey);
  1152. USBPRINT_KdPrint2(("USBPRINT.SYS: Closeing interface key in RemoveDevice\n"));
  1153. ntStatus=IoSetDeviceInterfaceState(&(deviceExtension->DeviceLinkName),FALSE);
  1154. if(!NT_SUCCESS(ntStatus))
  1155. {
  1156. USBPRINT_KdPrint1 (("USBPRINT.SYS: ioSetDeviceInterface to false failed\n"));
  1157. }
  1158. RtlFreeUnicodeString(&(deviceExtension->DeviceLinkName));
  1159. //
  1160. // Free device descriptor structure
  1161. //
  1162. if (deviceExtension->DeviceDescriptor) {
  1163. ExFreePool(deviceExtension->DeviceDescriptor);
  1164. }
  1165. //
  1166. // Free up any interface structures
  1167. //
  1168. if (deviceExtension->Interface) {
  1169. ExFreePool(deviceExtension->Interface);
  1170. }
  1171. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_RemoveDevice (%x)\n", ntStatus));
  1172. return ntStatus;
  1173. }
  1174. NTSTATUS
  1175. USBPRINT_StopDevice(
  1176. IN PDEVICE_OBJECT DeviceObject
  1177. )
  1178. /*++
  1179. Routine Description:
  1180. Stops a given instance of a printer on the USB, this is only
  1181. stuff we need to do if the device is still present.
  1182. Arguments:
  1183. DeviceObject - pointer to the device object for this printer
  1184. Return Value:
  1185. NT status code
  1186. --*/
  1187. {
  1188. PDEVICE_EXTENSION deviceExtension;
  1189. NTSTATUS ntStatus = STATUS_SUCCESS;
  1190. PURB urb;
  1191. ULONG siz;
  1192. LARGE_INTEGER timeOut;
  1193. timeOut.QuadPart = FAILURE_TIMEOUT;
  1194. USBPRINT_KdPrint3 (("USBPRINT.SYS: enter USBPRINT_StopDevice\n"));
  1195. deviceExtension = DeviceObject->DeviceExtension;
  1196. //
  1197. // Send the select configuration urb with a NULL pointer for the configuration
  1198. // handle, this closes the configuration and puts the device in the 'unconfigured'
  1199. // state.
  1200. //
  1201. siz = sizeof(struct _URB_SELECT_CONFIGURATION);
  1202. urb = ExAllocatePoolWithTag(NonPagedPool,siz, USBP_TAG);
  1203. if (urb) {
  1204. NTSTATUS status;
  1205. UsbBuildSelectConfigurationRequest(urb,
  1206. (USHORT) siz,
  1207. NULL);
  1208. status = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
  1209. USBPRINT_KdPrint3 (("USBPRINT.SYS: Device Configuration Closed status = %x usb status = %x.\n",
  1210. status, urb->UrbHeader.Status));
  1211. ExFreePool(urb);
  1212. } else {
  1213. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1214. }
  1215. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_StopDevice (%x)\n", ntStatus));
  1216. return ntStatus;
  1217. }
  1218. NTSTATUS
  1219. USBPRINT_PnPAddDevice(
  1220. IN PDRIVER_OBJECT DriverObject,
  1221. IN PDEVICE_OBJECT PhysicalDeviceObject
  1222. )
  1223. /*++
  1224. Routine Description:
  1225. This routine is called to create a new instance of the device
  1226. Arguments:
  1227. DriverObject - pointer to the driver object for this instance of USBPRINT
  1228. PhysicalDeviceObject - pointer to a device object created by the bus
  1229. Return Value:
  1230. STATUS_SUCCESS if successful,
  1231. STATUS_UNSUCCESSFUL otherwise
  1232. --*/
  1233. {
  1234. NTSTATUS ntStatus = STATUS_SUCCESS;
  1235. PDEVICE_OBJECT deviceObject = NULL;
  1236. PDEVICE_EXTENSION deviceExtension;
  1237. USBD_VERSION_INFORMATION versionInformation;
  1238. ULONG ulPortNumber;
  1239. GUID * pPrinterGuid;
  1240. static ULONG instance = 0;
  1241. //UNICODE_STRING deviceLinkUnicodeString;
  1242. HANDLE hInterfaceKey;
  1243. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_PnPAddDevice\n"));
  1244. //
  1245. // create our funtional device object (FDO)
  1246. //
  1247. ntStatus =
  1248. USBPRINT_CreateDeviceObject(DriverObject, &deviceObject);
  1249. if (NT_SUCCESS(ntStatus)) {
  1250. deviceExtension = deviceObject->DeviceExtension;
  1251. //
  1252. // we support direct io for read/write
  1253. //
  1254. deviceObject->Flags |= DO_DIRECT_IO;
  1255. deviceObject->Flags |= DO_POWER_PAGABLE;
  1256. //** initialize our device extension
  1257. //
  1258. // remember the Physical device Object
  1259. //
  1260. deviceExtension->PhysicalDeviceObject=PhysicalDeviceObject;
  1261. // init selective suspend stuff
  1262. deviceExtension->PendingIdleIrp = NULL;
  1263. deviceExtension->IdleCallbackInfo = NULL;
  1264. deviceExtension->OpenCnt=0;
  1265. deviceExtension->bD0IrpPending=FALSE;
  1266. KeInitializeSpinLock(&(deviceExtension->WakeSpinLock));
  1267. //
  1268. // Attach to the PDO
  1269. //
  1270. deviceExtension->TopOfStackDeviceObject=IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);
  1271. if(deviceExtension->TopOfStackDeviceObject==NULL)
  1272. {
  1273. USBPRINT_KdPrint1(("USBPRINT.SYS: IoAttachDeviceToDeviceStack failed\n"));
  1274. }
  1275. else
  1276. {
  1277. USBPRINT_KdPrint3(("USBPRINT.SYS: IoAttachDeviceToDeviceStack worked\n"));
  1278. }
  1279. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  1280. USBPRINT_KdPrint3(("'USBPRINT.SYS: Before ioRegisterDeviceInterface\n"));
  1281. pPrinterGuid=(GUID *)&USBPRINT_GUID;
  1282. ntStatus=IoRegisterDeviceInterface(PhysicalDeviceObject,pPrinterGuid,NULL,&(deviceExtension->DeviceLinkName));
  1283. if(!NT_SUCCESS(ntStatus))
  1284. {
  1285. USBPRINT_KdPrint1(("'USBPRINT.SYS: ioRegisterDeviceInterface failed\n"));
  1286. goto AddDeviceFailure;
  1287. }
  1288. ntStatus=IoOpenDeviceInterfaceRegistryKey(&(deviceExtension->DeviceLinkName),KEY_ALL_ACCESS,&hInterfaceKey);
  1289. USBPRINT_KdPrint2(("USBPRINT.SYS: Opened Device Interface reg key in AddDevice\n"));
  1290. // moved to RemoveDevice RtlFreeUnicodeString(&deviceLinkUnicodeString);
  1291. if(!NT_SUCCESS(ntStatus))
  1292. {
  1293. USBPRINT_KdPrint1(("USBPRINT.SYS: IoOpenDeviceInterfaceRegistryKey failed\n"));
  1294. goto AddDeviceFailure;
  1295. }
  1296. USBPRINT_KdPrint3(("USBPRINT.SYS: IoOpenDeviceInterfaceRegistryKey succeeded\n"));
  1297. deviceExtension->hInterfaceKey=hInterfaceKey;
  1298. ntStatus=GetPortNumber(hInterfaceKey,&ulPortNumber);
  1299. if(!NT_SUCCESS(ntStatus))
  1300. {
  1301. USBPRINT_KdPrint1(("USBPRINT.SYS: GetPortNumber failed\n"));
  1302. goto AddDeviceFailure;
  1303. }
  1304. deviceExtension->ulInstanceNumber=ulPortNumber;
  1305. USBPRINT_KdPrint2(("USBPRINT.SYS: Allocated port # %u\n",ulPortNumber));
  1306. /* ntStatus=IoSetDeviceInterfaceState(&(deviceExtension->DeviceLinkName),TRUE);
  1307. if(NT_SUCCESS(ntStatus))
  1308. {
  1309. USBPRINT_KdPrint3(("USBPRINT.SYS: IoSetDeviceInterfaceState worked\n"));
  1310. }
  1311. else
  1312. {
  1313. USBPRINT_KdPrint1(("USBPRINT.SYS: IoSetDeviceInterfaceState did not work\n"));
  1314. goto AddDeviceFailure;
  1315. }
  1316. */
  1317. USBPRINT_QueryCapabilities(PhysicalDeviceObject,
  1318. &deviceExtension->DeviceCapabilities);
  1319. //
  1320. // display the device caps
  1321. //
  1322. #if DBG
  1323. {
  1324. ULONG i;
  1325. USBPRINT_KdPrint3(("USBPRINT.SYS: >>>>>> DeviceCaps\n"));
  1326. USBPRINT_KdPrint3(("USBPRINT.SYS: SystemWake = (%d)\n",
  1327. deviceExtension->DeviceCapabilities.SystemWake));
  1328. USBPRINT_KdPrint3(("USBPRINT.SYS: DeviceWake = (D%d)\n",
  1329. deviceExtension->DeviceCapabilities.DeviceWake-1));
  1330. for (i=PowerSystemUnspecified; i< PowerSystemMaximum; i++) {
  1331. USBPRINT_KdPrint3(("USBPRINT.SYS: Device State Map: sysstate %d = devstate 0x%x\n", i,
  1332. deviceExtension->DeviceCapabilities.DeviceState[i]));
  1333. }
  1334. USBPRINT_KdPrint3(("USBPRINT.SYS: '<<<<<<<<DeviceCaps\n"));
  1335. }
  1336. #endif
  1337. //
  1338. // transition to zero signals the event
  1339. //
  1340. USBPRINT_IncrementIoCount(deviceObject);
  1341. }
  1342. USBD_GetUSBDIVersion(&versionInformation);
  1343. AddDeviceFailure:
  1344. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_PnPAddDevice (%x)\n", ntStatus));
  1345. return ntStatus;
  1346. }
  1347. NTSTATUS
  1348. USBPRINT_CreateDeviceObject(
  1349. IN PDRIVER_OBJECT DriverObject,
  1350. IN PDEVICE_OBJECT *DeviceObject
  1351. )
  1352. /*++
  1353. Routine Description:
  1354. Creates a Functional DeviceObject
  1355. Arguments:
  1356. DriverObject - pointer to the driver object for device
  1357. DeviceObject - pointer to DeviceObject pointer to return
  1358. created device object.
  1359. Instance - instnace of the device create.
  1360. Return Value:
  1361. STATUS_SUCCESS if successful,
  1362. STATUS_UNSUCCESSFUL otherwise
  1363. --*/
  1364. {
  1365. NTSTATUS ntStatus;
  1366. PDEVICE_EXTENSION deviceExtension;
  1367. ULONG instance;
  1368. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_CreateDeviceObject\n"));
  1369. //
  1370. // This driver supports up to 9 instances
  1371. //
  1372. ntStatus = IoCreateDevice (DriverObject,
  1373. sizeof (DEVICE_EXTENSION),
  1374. NULL,
  1375. FILE_DEVICE_UNKNOWN,
  1376. 0,
  1377. FALSE,
  1378. DeviceObject);
  1379. //
  1380. // Initialize our device extension
  1381. //
  1382. deviceExtension = (PDEVICE_EXTENSION) ((*DeviceObject)->DeviceExtension);
  1383. deviceExtension->IsChildDevice=FALSE;
  1384. deviceExtension->ResetWorkItemPending=0; //init to "no workitem pending"
  1385. deviceExtension->bChildDeviceHere=FALSE;
  1386. deviceExtension->DeviceDescriptor = NULL;
  1387. deviceExtension->Interface = NULL;
  1388. deviceExtension->ConfigurationHandle = NULL;
  1389. deviceExtension->AcceptingRequests = TRUE;
  1390. deviceExtension->PendingIoCount = 0;
  1391. deviceExtension->DeviceCapabilities.Size = sizeof(DEVICE_CAPABILITIES);
  1392. deviceExtension->DeviceCapabilities.Version = DEVICE_CAPABILITY_VERSION;
  1393. deviceExtension->DeviceCapabilities.Address = (ULONG) -1;
  1394. deviceExtension->DeviceCapabilities.UINumber= (ULONG) -1;
  1395. deviceExtension->DeviceCapabilities.DeviceState[PowerSystemWorking] = PowerDeviceD0;
  1396. deviceExtension->DeviceCapabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD3;
  1397. deviceExtension->DeviceCapabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD3;
  1398. deviceExtension->DeviceCapabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
  1399. deviceExtension->DeviceCapabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
  1400. deviceExtension->DeviceCapabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
  1401. KeInitializeEvent(&deviceExtension->RemoveEvent, NotificationEvent, FALSE);
  1402. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_CreateDeviceObject (%x)\n", ntStatus));
  1403. return ntStatus;
  1404. }
  1405. NTSTATUS
  1406. USBPRINT_CallUSBD(
  1407. IN PDEVICE_OBJECT DeviceObject,
  1408. IN PURB Urb,
  1409. IN PLARGE_INTEGER pTimeout
  1410. )
  1411. /*++
  1412. Routine Description:
  1413. Passes a URB to the USBD class driver
  1414. Arguments:
  1415. DeviceObject - pointer to the device object for this printer
  1416. Urb - pointer to Urb request block
  1417. Return Value:
  1418. STATUS_SUCCESS if successful,
  1419. STATUS_UNSUCCESSFUL otherwise
  1420. --*/
  1421. {
  1422. NTSTATUS ntStatus, status = STATUS_SUCCESS;
  1423. PDEVICE_EXTENSION deviceExtension;
  1424. PIRP irp;
  1425. KEVENT event;
  1426. PIO_STACK_LOCATION nextStack;
  1427. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_CallUSBD\n"));
  1428. deviceExtension = DeviceObject->DeviceExtension;
  1429. //
  1430. // issue a synchronous request
  1431. //
  1432. KeInitializeEvent(&event, NotificationEvent, FALSE);
  1433. if ( (irp = IoAllocateIrp(deviceExtension->TopOfStackDeviceObject->StackSize,
  1434. FALSE)) == NULL )
  1435. return STATUS_INSUFFICIENT_RESOURCES;
  1436. //
  1437. // Call the class driver to perform the operation. If the returned status
  1438. // is PENDING, wait for the request to complete.
  1439. //
  1440. nextStack = IoGetNextIrpStackLocation(irp);
  1441. ASSERT(nextStack != NULL);
  1442. //
  1443. // pass the URB to the USB driver stack
  1444. //
  1445. nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1446. nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  1447. nextStack->Parameters.Others.Argument1 = Urb;
  1448. IoSetCompletionRoutine(irp,
  1449. USBPRINT_DeferIrpCompletion,
  1450. &event,
  1451. TRUE,
  1452. TRUE,
  1453. TRUE);
  1454. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
  1455. irp);
  1456. if ( ntStatus == STATUS_PENDING )
  1457. {
  1458. status = KeWaitForSingleObject(&event,Suspended,KernelMode,FALSE,pTimeout);
  1459. //
  1460. // If the request timed out cancel the request
  1461. // and wait for it to complete
  1462. //
  1463. if ( status == STATUS_TIMEOUT ) {
  1464. #ifdef MYDEBUG
  1465. DbgPrint("Call_USBD: Cancelling IRP %X because of timeout\n", irp);
  1466. #endif
  1467. IoCancelIrp(irp);
  1468. KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
  1469. }
  1470. ntStatus = irp->IoStatus.Status;
  1471. }
  1472. IoFreeIrp(irp);
  1473. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_CallUSBD (%x)\n", ntStatus));
  1474. USBPRINT_KdPrint3 (("USBPRINT.SYS: About to return from CallUSBD, status=%x\n", ntStatus));
  1475. return ntStatus;
  1476. }
  1477. NTSTATUS
  1478. USBPRINT_ConfigureDevice(
  1479. IN PDEVICE_OBJECT DeviceObject
  1480. )
  1481. /*++
  1482. Routine Description:
  1483. Initializes a given instance of the device on the USB and selects the configuration.
  1484. Arguments:
  1485. DeviceObject - pointer to the device object for this printer devcice.
  1486. Return Value:
  1487. NT status code
  1488. --*/
  1489. {
  1490. PDEVICE_EXTENSION deviceExtension;
  1491. NTSTATUS ntStatus;
  1492. PURB urb;
  1493. ULONG siz;
  1494. PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL;
  1495. LARGE_INTEGER timeOut;
  1496. timeOut.QuadPart = FAILURE_TIMEOUT;
  1497. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_ConfigureDevice\n"));
  1498. deviceExtension = DeviceObject->DeviceExtension;
  1499. //
  1500. // first configure the device
  1501. //
  1502. urb = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), USBP_TAG);
  1503. if (urb)
  1504. {
  1505. siz = sizeof(USB_CONFIGURATION_DESCRIPTOR)+256;
  1506. get_config_descriptor_retry:
  1507. configurationDescriptor = ExAllocatePoolWithTag(NonPagedPool,siz, USBP_TAG);
  1508. if (configurationDescriptor)
  1509. {
  1510. UsbBuildGetDescriptorRequest(urb,
  1511. (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  1512. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  1513. 0,
  1514. 0,
  1515. configurationDescriptor,
  1516. NULL,
  1517. siz,
  1518. NULL);
  1519. ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
  1520. if(!NT_SUCCESS(ntStatus))
  1521. {
  1522. USBPRINT_KdPrint1 (("USBPRINT.SYS: Get Configuration descriptor failed\n"));
  1523. }
  1524. else
  1525. {
  1526. //
  1527. // if we got some data see if it was enough.
  1528. //
  1529. // NOTE: we may get an error in URB because of buffer overrun
  1530. if (urb->UrbControlDescriptorRequest.TransferBufferLength>0 &&configurationDescriptor->wTotalLength > siz)
  1531. {
  1532. siz = configurationDescriptor->wTotalLength;
  1533. ExFreePool(configurationDescriptor);
  1534. configurationDescriptor = NULL;
  1535. goto get_config_descriptor_retry;
  1536. }
  1537. }
  1538. USBPRINT_KdPrint3 (("USBPRINT.SYS: Configuration Descriptor = %x, len %x\n",
  1539. configurationDescriptor,
  1540. urb->UrbControlDescriptorRequest.TransferBufferLength));
  1541. }
  1542. else
  1543. {
  1544. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1545. USBPRINT_KdPrint1(("USBPRINT.SYS: Insufficient resources to allocate configuration descriptor in ConfigureDevice\n"));
  1546. }
  1547. ExFreePool(urb);
  1548. }
  1549. else
  1550. {
  1551. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1552. }
  1553. if (configurationDescriptor)
  1554. {
  1555. USBPRINT_KdPrint2(("USBPRINT.SYS: ConfigureDevice, We have a configuration descriptor!\n"));
  1556. //
  1557. // We have the configuration descriptor for the configuration
  1558. // we want.
  1559. //
  1560. // Now we issue the select configuration command to get
  1561. // the pipes associated with this configuration.
  1562. //
  1563. if(NT_SUCCESS(ntStatus))
  1564. {
  1565. ntStatus = USBPRINT_SelectInterface(DeviceObject,configurationDescriptor);
  1566. }
  1567. ExFreePool(configurationDescriptor);
  1568. }
  1569. else
  1570. {
  1571. USBPRINT_KdPrint1(("USBPRINT.SYS: ConfigureDevice, No Configuration descriptor.\n"));
  1572. }
  1573. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_ConfigureDevice (%x)\n", ntStatus));
  1574. return ntStatus;
  1575. }
  1576. NTSTATUS USBPRINT_SelectInterface(IN PDEVICE_OBJECT DeviceObject,IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
  1577. /*++
  1578. Routine Description:
  1579. Initializes a printer with multiple interfaces
  1580. Arguments:
  1581. DeviceObject - pointer to the device object for this printer
  1582. ConfigurationDescriptor - pointer to the USB configuration
  1583. descriptor containing the interface and endpoint
  1584. descriptors.
  1585. Return Value:
  1586. NT status code
  1587. --*/
  1588. {
  1589. PDEVICE_EXTENSION deviceExtension;
  1590. NTSTATUS ntStatus;
  1591. PURB urb = NULL;
  1592. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor = NULL;
  1593. PUSBD_INTERFACE_INFORMATION Interface = NULL;
  1594. USBD_INTERFACE_LIST_ENTRY InterfaceList[2];
  1595. LARGE_INTEGER timeOut;
  1596. timeOut.QuadPart = FAILURE_TIMEOUT;
  1597. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_SelectInterface\n"));
  1598. deviceExtension = DeviceObject->DeviceExtension;
  1599. //starting at offset 0, search for an alternate interface with protocol code 2; Ignore InterfaceNumber, AlternateSetting, InterfaceClass, InterfaceSubClass
  1600. interfaceDescriptor=USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor,ConfigurationDescriptor,-1,-1,-1,-1,2);
  1601. if(!interfaceDescriptor)
  1602. {
  1603. USBPRINT_KdPrint3 (("USBPRINT.SYS: First ParseConfigurationDescriptorEx failed\n"));
  1604. interfaceDescriptor=USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor,ConfigurationDescriptor,-1,-1,-1,-1,1);
  1605. if(!interfaceDescriptor)
  1606. {
  1607. USBPRINT_KdPrint1 (("USBPRINT.SYS: second ParseConfigurationDescriptorEx failed\n"));
  1608. ntStatus=STATUS_DEVICE_CONFIGURATION_ERROR;
  1609. }
  1610. else
  1611. {
  1612. USBPRINT_KdPrint3 (("USBPRINT.SYS: second ParseConfigurationDescriptorEx success\n"));
  1613. deviceExtension->bReadSupported=FALSE;
  1614. } /*end second ParseConfigDescriptor worked*/
  1615. }
  1616. else
  1617. {
  1618. deviceExtension->bReadSupported=TRUE;
  1619. USBPRINT_KdPrint3 (("USBPRINT.SYS: First ParseConfigurationDescriptorEx success\n"));
  1620. }
  1621. if(interfaceDescriptor)
  1622. {
  1623. InterfaceList[0].InterfaceDescriptor=interfaceDescriptor;
  1624. InterfaceList[1].InterfaceDescriptor=NULL;
  1625. urb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor,InterfaceList);
  1626. if (urb)
  1627. {
  1628. Interface = InterfaceList[0].Interface;
  1629. ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
  1630. }
  1631. else
  1632. {
  1633. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1634. USBPRINT_KdPrint1 (("USBPRINT.SYS: CreateConfigurationRequest failed\n"));
  1635. }
  1636. } //end found good interface
  1637. else
  1638. {
  1639. USBPRINT_KdPrint1 (("USBPRINT.SYS: failed to locate apropriate interface\n"));
  1640. } //end no interface
  1641. if (NT_SUCCESS(ntStatus))
  1642. {
  1643. //
  1644. // Save the configuration handle for this device
  1645. //
  1646. USBPRINT_KdPrint3 (("USBPRINT.SYS: SelectInterface, Inside good config case\n"));
  1647. deviceExtension->ConfigurationHandle = urb->UrbSelectConfiguration.ConfigurationHandle;
  1648. deviceExtension->Interface = ExAllocatePoolWithTag(NonPagedPool,Interface->Length, USBP_TAG);
  1649. if (deviceExtension->Interface)
  1650. {
  1651. ULONG j;
  1652. //
  1653. // save a copy of the interface information returned
  1654. //
  1655. RtlCopyMemory(deviceExtension->Interface, Interface, Interface->Length);
  1656. //
  1657. // Dump the interface to the debugger
  1658. //
  1659. USBPRINT_KdPrint3 (("USBPRINT.SYS: ---------\n"));
  1660. USBPRINT_KdPrint3 (("USBPRINT.SYS: NumberOfPipes 0x%x\n", deviceExtension->Interface->NumberOfPipes));
  1661. USBPRINT_KdPrint3 (("USBPRINT.SYS: Length 0x%x\n", deviceExtension->Interface->Length));
  1662. USBPRINT_KdPrint3 (("USBPRINT.SYS: Alt Setting 0x%x\n", deviceExtension->Interface->AlternateSetting));
  1663. USBPRINT_KdPrint3 (("USBPRINT.SYS: Interface Number 0x%x\n", deviceExtension->Interface->InterfaceNumber));
  1664. USBPRINT_KdPrint3 (("USBPRINT.SYS: Class, subclass, protocol 0x%x 0x%x 0x%x\n",
  1665. deviceExtension->Interface->Class,
  1666. deviceExtension->Interface->SubClass,
  1667. deviceExtension->Interface->Protocol));
  1668. // Dump the pipe info
  1669. for (j=0; j<Interface->NumberOfPipes; j++)
  1670. {
  1671. PUSBD_PIPE_INFORMATION pipeInformation;
  1672. pipeInformation = &deviceExtension->Interface->Pipes[j];
  1673. USBPRINT_KdPrint3 (("USBPRINT.SYS: ---------\n"));
  1674. USBPRINT_KdPrint3 (("USBPRINT.SYS: PipeType 0x%x\n", pipeInformation->PipeType));
  1675. USBPRINT_KdPrint3 (("USBPRINT.SYS: EndpointAddress 0x%x\n", pipeInformation->EndpointAddress));
  1676. USBPRINT_KdPrint3 (("USBPRINT.SYS: MaxPacketSize 0x%x\n", pipeInformation->MaximumPacketSize));
  1677. USBPRINT_KdPrint3 (("USBPRINT.SYS: Interval 0x%x\n", pipeInformation->Interval));
  1678. USBPRINT_KdPrint3 (("USBPRINT.SYS: Handle 0x%x\n", pipeInformation->PipeHandle));
  1679. USBPRINT_KdPrint3 (("USBPRINT.SYS: MaximumTransferSize 0x%x\n", pipeInformation->MaximumTransferSize));
  1680. }
  1681. USBPRINT_KdPrint3 (("USBPRINT.SYS: ---------\n"));
  1682. } /*end if interface Alloc OK*/
  1683. else
  1684. {
  1685. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1686. USBPRINT_KdPrint1 (("USBPRINT.SYS: Alloc failed in SelectInterface\n"));
  1687. }
  1688. }
  1689. if (urb)
  1690. {
  1691. ExFreePool(urb);
  1692. }
  1693. USBPRINT_KdPrint2 (("USBPRINT.SYS: exit USBPRINT_SelectInterface (%x)\n", ntStatus));
  1694. return ntStatus;
  1695. }
  1696. NTSTATUS
  1697. USBPRINT_BuildPipeList(
  1698. IN PDEVICE_OBJECT DeviceObject
  1699. )
  1700. /*++
  1701. Routine Description:
  1702. Arguments:
  1703. DeviceObject - pointer to the device object for this printer
  1704. devcice.
  1705. Return Value:
  1706. NT status code
  1707. --*/
  1708. {
  1709. PDEVICE_EXTENSION deviceExtension;
  1710. ULONG i;
  1711. WCHAR Name[] = L"\\PIPE00";
  1712. PUSBD_INTERFACE_INFORMATION InterfaceDescriptor;
  1713. BOOL bFoundWritePipe=FALSE,bFoundReadPipe=FALSE,bNeedReadPipe=FALSE;
  1714. deviceExtension = DeviceObject->DeviceExtension;
  1715. InterfaceDescriptor = deviceExtension->Interface;
  1716. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_BuildPipeList\n"));
  1717. deviceExtension = DeviceObject->DeviceExtension;
  1718. if(InterfaceDescriptor->Protocol==2)
  1719. bNeedReadPipe=TRUE;
  1720. else
  1721. bNeedReadPipe=FALSE;
  1722. for (i=0; i<InterfaceDescriptor->NumberOfPipes; i++) {
  1723. USBPRINT_KdPrint3 (("USBPRINT.SYS: about to look at endpoint with address 0x%x)\n",InterfaceDescriptor->Pipes[i].EndpointAddress));
  1724. if(((InterfaceDescriptor->Pipes[i].EndpointAddress)&0x80)==0) //if bit 7 is 0, it's an OUT endpoint
  1725. {
  1726. if(bFoundWritePipe==TRUE)
  1727. {
  1728. USBPRINT_KdPrint1 (("USBPRINT.SYS: Warning!! Multiple OUT pipes detected on printer. Defaulting to first pipe\n"));
  1729. } /*end if we've already found a write pipe*/
  1730. else
  1731. {
  1732. USBPRINT_KdPrint3 (("USBPRINT.SYS: Found write pipe\n"));
  1733. deviceExtension->pWritePipe=&(InterfaceDescriptor->Pipes[i]);
  1734. bFoundWritePipe=TRUE;
  1735. } /*else we haven't seen an OUT endpont before*/
  1736. } /*end if it's an OUT endpoint*/
  1737. else
  1738. {
  1739. if(!bNeedReadPipe)
  1740. {
  1741. USBPRINT_KdPrint1 (("USBPRINT.SYS: Warning!! unexpected IN pipe (not specified in protocol field)\n"));
  1742. } /*end if we don't need a read pipe, but we found one*/
  1743. else if(bFoundReadPipe)
  1744. {
  1745. USBPRINT_KdPrint1 (("USBPRINT.SYS: Warning!! Multiple IN pipes detected on printer. Defaulting to first pipe\n"));
  1746. } /*end if we've already found a read pipe*/
  1747. else
  1748. {
  1749. USBPRINT_KdPrint3 (("USBPRINT.SYS: Found read pipe\n"));
  1750. deviceExtension->pReadPipe=&(InterfaceDescriptor->Pipes[i]);
  1751. bFoundReadPipe=TRUE;
  1752. } /*end else we're supposed to have an IN pipe, and this is the first one we've seen*/
  1753. } /*end else it's an IN endpoint*/
  1754. } /*end for*/
  1755. if((bNeedReadPipe==TRUE)&&(bFoundReadPipe==FALSE))
  1756. {
  1757. USBPRINT_KdPrint1 (("USBPRINT.SYS: Warning!! IN pipe was specified in protocol field, but was not found\n"));
  1758. } /*end if we needed a read pipe, and didn't find one*/
  1759. deviceExtension->bReadPipeExists=bFoundReadPipe;
  1760. return STATUS_SUCCESS;
  1761. } /*end function BuildPipeList*/
  1762. NTSTATUS
  1763. USBPRINT_ResetPipe(
  1764. IN PDEVICE_OBJECT DeviceObject,
  1765. IN PUSBD_PIPE_INFORMATION Pipe,
  1766. IN BOOLEAN IsoClearStall
  1767. )
  1768. /*++
  1769. Routine Description:
  1770. Reset a given USB pipe.
  1771. NOTES:
  1772. This will reset the host to Data0 and should also reset the device
  1773. to Data0 for Bulk and Interrupt pipes.
  1774. For Iso pipes this will set the virgin state of pipe so that ASAP
  1775. transfers begin with the current bus frame instead of the next frame
  1776. after the last transfer occurred.
  1777. Arguments:
  1778. Return Value:
  1779. --*/
  1780. {
  1781. NTSTATUS ntStatus;
  1782. PURB urb;
  1783. LARGE_INTEGER timeOut;
  1784. timeOut.QuadPart = FAILURE_TIMEOUT;
  1785. USBPRINT_KdPrint2 (("USBPRINT.SYS: Entering Reset Pipe; pipe # %x\n", Pipe));
  1786. urb = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct _URB_PIPE_REQUEST), USBP_TAG);
  1787. if (urb) {
  1788. urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_PIPE_REQUEST);
  1789. urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
  1790. urb->UrbPipeRequest.PipeHandle =
  1791. Pipe->PipeHandle;
  1792. ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
  1793. if(!NT_SUCCESS(ntStatus))
  1794. {
  1795. USBPRINT_KdPrint1(("USBPRINT.SYS: CallUSBD failed in ResetPipe\n"));
  1796. }
  1797. else
  1798. {
  1799. USBPRINT_KdPrint3(("USBPRINT.SYS: CallUSBD Succeeded in ResetPipe\n"));
  1800. }
  1801. ExFreePool(urb);
  1802. } else {
  1803. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1804. }
  1805. //
  1806. // Memphis RESET_PIPE will send a Clear-Feature Endpoint Stall to
  1807. // reset the data toggle of non-Iso pipes as part of a RESET_PIPE
  1808. // request. It does not do this for Iso pipes as Iso pipes do not use
  1809. // the data toggle (all Iso packets are Data0). However, we also use
  1810. // the Clear-Feature Endpoint Stall request in our device firmware to
  1811. // reset data buffer points inside the device so we explicitly send
  1812. // this request to the device for Iso pipes if desired.
  1813. //
  1814. if (NT_SUCCESS(ntStatus) && IsoClearStall &&
  1815. (Pipe->PipeType == UsbdPipeTypeIsochronous)) {
  1816. urb = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct _URB_CONTROL_FEATURE_REQUEST), USBP_TAG);
  1817. if (urb) {
  1818. UsbBuildFeatureRequest(urb,
  1819. URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT,
  1820. USB_FEATURE_ENDPOINT_STALL,
  1821. Pipe->EndpointAddress,
  1822. NULL);
  1823. ntStatus = USBPRINT_CallUSBD(DeviceObject, urb, &timeOut);
  1824. ExFreePool(urb);
  1825. } else {
  1826. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1827. }
  1828. }
  1829. return ntStatus;
  1830. }
  1831. LONG
  1832. USBPRINT_DecrementIoCount(
  1833. IN PDEVICE_OBJECT DeviceObject
  1834. )
  1835. /*++
  1836. Routine Description:
  1837. Arguments:
  1838. Return Value:
  1839. --*/
  1840. {
  1841. PDEVICE_EXTENSION deviceExtension;
  1842. LONG ioCount=0;
  1843. deviceExtension = DeviceObject->DeviceExtension;
  1844. if(!(deviceExtension->IsChildDevice))
  1845. {
  1846. ioCount = InterlockedDecrement(&deviceExtension->PendingIoCount);
  1847. #ifdef MYDEBUG
  1848. DbgPrint("USBPRINT_DecrementIoCount -- IoCount %d\n", deviceExtension->PendingIoCount);
  1849. #endif
  1850. USBPRINT_KdPrint3 (("USBPRINT.SYS: Pending io count = %x\n", ioCount));
  1851. if (ioCount==0) {
  1852. KeSetEvent(&deviceExtension->RemoveEvent,
  1853. 1,
  1854. FALSE);
  1855. }
  1856. } /*end if ! child device*/
  1857. return ioCount;
  1858. }
  1859. VOID
  1860. USBPRINT_IncrementIoCount(
  1861. IN PDEVICE_OBJECT DeviceObject
  1862. )
  1863. /*++
  1864. Routine Description:
  1865. Arguments:
  1866. Return Value:
  1867. --*/
  1868. {
  1869. PDEVICE_EXTENSION deviceExtension;
  1870. deviceExtension = DeviceObject->DeviceExtension;
  1871. if(!(deviceExtension->IsChildDevice))
  1872. {
  1873. InterlockedIncrement(&deviceExtension->PendingIoCount);
  1874. #ifdef MYDEBUG
  1875. DbgPrint("USBPRINT_IncrementIoCount -- IoCount %d\n", deviceExtension->PendingIoCount);
  1876. #endif
  1877. //
  1878. // Everytime iocount goes to 0 we set this event
  1879. // so we must cleat it when we have a new io
  1880. //
  1881. KeClearEvent(&deviceExtension->RemoveEvent);
  1882. }
  1883. }
  1884. NTSTATUS
  1885. USBPRINT_ReconfigureDevice(
  1886. IN PDEVICE_OBJECT DeviceObject
  1887. )
  1888. /*++
  1889. Routine Description:
  1890. Initializes a given instance of the device on the USB and selects the
  1891. configuration.
  1892. Arguments:
  1893. DeviceObject - pointer to the device object for this printer
  1894. Return Value:
  1895. NT status code
  1896. --*/
  1897. {
  1898. PDEVICE_EXTENSION deviceExtension;
  1899. NTSTATUS ntStatus = STATUS_SUCCESS;
  1900. PUSBD_INTERFACE_INFORMATION InterfaceDescriptor;
  1901. USBPRINT_KdPrint2 (("USBPRINT.SYS: enter USBPRINT_ReconfigureDevice\n"));
  1902. deviceExtension = DeviceObject->DeviceExtension;
  1903. if (NT_SUCCESS(ntStatus)) {
  1904. ntStatus = USBPRINT_ConfigureDevice(DeviceObject);
  1905. }
  1906. //
  1907. // new InterfaceDescriptor structure is now set up
  1908. //
  1909. InterfaceDescriptor = deviceExtension->Interface;
  1910. //
  1911. // set up the pipe handles again
  1912. //
  1913. return ntStatus;
  1914. }
  1915. NTSTATUS LoadPortsUsed(GUID *pPrinterGuid,PFREE_PORTS * pPortList,WCHAR *wcBaseName)
  1916. {
  1917. NTSTATUS ReturnStatus=STATUS_SUCCESS,Result=STATUS_SUCCESS;
  1918. PWSTR pDeviceList;
  1919. PWSTR pWalk;
  1920. UNICODE_STRING wNumberValueName,wBaseValueName,wLinkName;
  1921. ULONG ulPortNum;
  1922. ULONG ulBaseNameSizeIn,ulBaseNameSizeOut,ulPortNumSizeIn,ulPortNumSizeOut;
  1923. PKEY_VALUE_PARTIAL_INFORMATION pBaseValueStruct,pNumberValueStruct;
  1924. HANDLE hInterfaceKey;
  1925. BOOL bFoundUsbPort;
  1926. Result=IoGetDeviceInterfaces(pPrinterGuid,NULL,DEVICE_INTERFACE_INCLUDE_NONACTIVE,&pDeviceList);
  1927. if(Result==STATUS_SUCCESS)
  1928. {
  1929. RtlInitUnicodeString(&wNumberValueName,PORT_NUM_VALUE_NAME);
  1930. RtlInitUnicodeString(&wBaseValueName,PORT_BASE_NAME);
  1931. pWalk=pDeviceList;
  1932. ulBaseNameSizeIn=sizeof(KEY_VALUE_PARTIAL_INFORMATION)+((wcslen(wcBaseName)+1)*sizeof(WCHAR)); //this is a byte to much. Oh well
  1933. ulPortNumSizeIn=sizeof(KEY_VALUE_PARTIAL_INFORMATION)+sizeof(ULONG);
  1934. pBaseValueStruct=ExAllocatePoolWithTag(NonPagedPool,ulBaseNameSizeIn, USBP_TAG);
  1935. pNumberValueStruct=ExAllocatePoolWithTag(NonPagedPool,ulPortNumSizeIn, USBP_TAG);
  1936. if((pBaseValueStruct!=NULL)&&(pNumberValueStruct!=NULL))
  1937. {
  1938. while( *pWalk!=0 && NT_SUCCESS(ReturnStatus) )
  1939. {
  1940. RtlInitUnicodeString(&wLinkName,pWalk);
  1941. Result=IoOpenDeviceInterfaceRegistryKey(&wLinkName,KEY_ALL_ACCESS,&hInterfaceKey);
  1942. if(NT_SUCCESS(Result))
  1943. {
  1944. //The following is: If there is not a value, or there is a value that matches what we expect, then set bFoundUsbPort to true
  1945. bFoundUsbPort=TRUE;
  1946. Result=ZwQueryValueKey(hInterfaceKey,&wBaseValueName,KeyValuePartialInformation,pBaseValueStruct,ulBaseNameSizeIn,&ulBaseNameSizeOut);
  1947. if(NT_SUCCESS(Result))
  1948. {
  1949. if(wcscmp(wcBaseName,(WCHAR *)(pBaseValueStruct->Data))!=0)
  1950. bFoundUsbPort=FALSE;
  1951. }//end if Query OK
  1952. else if(STATUS_OBJECT_NAME_NOT_FOUND!=Result)
  1953. {
  1954. bFoundUsbPort=FALSE;
  1955. }
  1956. if(bFoundUsbPort)
  1957. {
  1958. Result=ZwQueryValueKey(hInterfaceKey,&wNumberValueName,KeyValuePartialInformation,pNumberValueStruct,ulPortNumSizeIn,&ulPortNumSizeOut);
  1959. if(NT_SUCCESS(Result))
  1960. {
  1961. ulPortNum=*((ULONG *)(pNumberValueStruct->Data));
  1962. if(!bDeleteIfRecyclable(hInterfaceKey))
  1963. {
  1964. USBPRINT_KdPrint2(("USBPRINT.SYS: Adding port number\n"));
  1965. ReturnStatus=bAddPortInUseItem(pPortList,ulPortNum);
  1966. if(!NT_SUCCESS(ReturnStatus))
  1967. {
  1968. USBPRINT_KdPrint1(("USBPRINT.SYS: Unable to add port %u to port list\n",ulPortNum));
  1969. USBPRINT_KdPrint1(("USBPRINT.SYS: Failing out of LoadPortsUsed due to ntstatus failure %d\n",ReturnStatus));
  1970. } //end if AddPortInUse failed
  1971. } //end if port not deleted
  1972. else
  1973. {
  1974. // ReturnStatus=STATUS_INVALID_PARAMETER;
  1975. USBPRINT_KdPrint1(("USBPRINT.SYS: Invalid port number %u\n",ulPortNum));
  1976. }
  1977. } //end if Query Port Number OK
  1978. //no else. If there's no port number, we ignore this interface
  1979. } //End if bFoundUSbPort
  1980. ZwClose(hInterfaceKey);
  1981. } //end if OpenReg ok
  1982. pWalk=pWalk+wcslen(pWalk)+1;
  1983. } //end while
  1984. } //end ExAllocatePool OK
  1985. else
  1986. {
  1987. USBPRINT_KdPrint1(("USBPRINT.SYS: Unable to allocate memory"));
  1988. ReturnStatus=STATUS_INSUFFICIENT_RESOURCES;
  1989. } /*end else ExAllocatePool failed*/
  1990. if(pBaseValueStruct!=NULL)
  1991. ExFreePool(pBaseValueStruct);
  1992. if(pNumberValueStruct!=NULL)
  1993. ExFreePool(pNumberValueStruct);
  1994. ExFreePool(pDeviceList);
  1995. } /*end if IoGetDeviceInterfaces success*/
  1996. else
  1997. {
  1998. USBPRINT_KdPrint1(("USBPRINT.SYS: IoGetDeviceInterfaces failed"));
  1999. ReturnStatus=Result; //do some error translation here?
  2000. }
  2001. return ReturnStatus;
  2002. } /*end function LoadPortsUsed*/
  2003. NTSTATUS GetPortNumber(HANDLE hInterfaceKey,
  2004. ULONG *ulReturnNumber)
  2005. {
  2006. ULONG ulPortNumber,ulSizeUsed;
  2007. NTSTATUS ntStatus=STATUS_SUCCESS;
  2008. UNICODE_STRING uncValueName;
  2009. PKEY_VALUE_PARTIAL_INFORMATION pValueStruct;
  2010. ulSizeUsed=sizeof(KEY_VALUE_PARTIAL_INFORMATION)+sizeof(ULONG); //this is a byte to much. Oh well
  2011. pValueStruct=ExAllocatePoolWithTag(PagedPool,ulSizeUsed, USBP_TAG);
  2012. if(pValueStruct==NULL)
  2013. return STATUS_INSUFFICIENT_RESOURCES;
  2014. RtlInitUnicodeString(&uncValueName,PORT_NUM_VALUE_NAME);
  2015. ntStatus=ZwQueryValueKey(hInterfaceKey,&uncValueName,KeyValuePartialInformation,(PVOID)pValueStruct,ulSizeUsed,&ulSizeUsed);
  2016. if(!NT_SUCCESS(ntStatus))
  2017. {
  2018. USBPRINT_KdPrint2(("USBPRINT.SYS: GetPortNumber; ZwQueryValueKey failed\n"));
  2019. switch(ntStatus)
  2020. {
  2021. case STATUS_BUFFER_OVERFLOW:
  2022. USBPRINT_KdPrint2(("USBPRINT.SYS: GetPortNumber zwQueryValueKey returned STATUS_BUFFER_OVERFLOW\n"));
  2023. break;
  2024. case STATUS_INVALID_PARAMETER:
  2025. USBPRINT_KdPrint2(("USBPRINT.SYS: GetPortNumber zwQueryValueKey returned STATUS_INVALID_PARAMETER\n"));
  2026. break;
  2027. case STATUS_OBJECT_NAME_NOT_FOUND:
  2028. USBPRINT_KdPrint2(("USBPRINT.SYS: GetPortNumber zwQueryValueKey returned STATUS_OBJECT_NAME_NOT_FOUND\n"));
  2029. break;
  2030. default:
  2031. USBPRINT_KdPrint2(("USBPRINT.SYS: GetPortNumber zwQueryValueKey returned unkown error\n"));
  2032. }
  2033. ntStatus=GetNewPortNumber(&pGPortList,&ulPortNumber);
  2034. }
  2035. else
  2036. {
  2037. ulPortNumber=*((ULONG *)&(pValueStruct->Data));
  2038. if(ulPortNumber==0) //zero is a placeholder for "not there" which we use because win9x is missing the zwDeleteValueKey api
  2039. ntStatus=GetNewPortNumber(&pGPortList,&ulPortNumber);
  2040. else
  2041. vClaimPortNumber(ulPortNumber,hInterfaceKey,&pGPortList);
  2042. }
  2043. if(!NT_SUCCESS(ntStatus))
  2044. {
  2045. USBPRINT_KdPrint1(("USBPRINT.SYS: GetPortNumber; failed to allocate new port number\n"));
  2046. }
  2047. else
  2048. {
  2049. *ulReturnNumber=ulPortNumber;
  2050. USBPRINT_KdPrint3(("USBPRINT.SYS: GetPortNumber; Inside \"write back to reg\" case, ulPortNumber==%d\n",ulPortNumber));
  2051. USBPRINT_KdPrint3(("USBPRINT.SYS: GetPortNumber; Before ntstatys=success\n"));
  2052. ntStatus=STATUS_SUCCESS;
  2053. USBPRINT_KdPrint3(("USBPRINT.SYS: GetPortNumber; Before ZwSetValueKey\n"));
  2054. ntStatus=ZwSetValueKey(hInterfaceKey,&uncValueName,0,REG_DWORD,&ulPortNumber,sizeof(ulPortNumber));
  2055. if(!NT_SUCCESS(ntStatus))
  2056. {
  2057. USBPRINT_KdPrint1(("USBPRINT.SYS: GetPortNumber; Unable to set value key\n"));
  2058. }
  2059. else
  2060. {
  2061. *ulReturnNumber=ulPortNumber;
  2062. }
  2063. }
  2064. ExFreePool(pValueStruct);
  2065. return ntStatus;
  2066. } /*end function GetPortNumber*/
  2067. USBPRINT_GetDeviceID(PDEVICE_OBJECT ParentDeviceObject)
  2068. {
  2069. UCHAR *p1284Id;
  2070. NTSTATUS ntStatus;
  2071. int iReturnSize;
  2072. PDEVICE_EXTENSION pParentExtension;
  2073. pParentExtension=ParentDeviceObject->DeviceExtension;
  2074. USBPRINT_KdPrint2 (("USBPRINT.SYS: GetDeviceID enter\n"));
  2075. p1284Id=ExAllocatePoolWithTag(NonPagedPool,MAX_ID_SIZE, USBP_TAG);
  2076. if(p1284Id==NULL)
  2077. {
  2078. ntStatus=STATUS_NO_MEMORY;
  2079. }
  2080. else
  2081. {
  2082. iReturnSize=USBPRINT_Get1284Id(ParentDeviceObject,p1284Id,MAX_ID_SIZE-ID_OVERHEAD); //
  2083. if(iReturnSize==-1)
  2084. {
  2085. pParentExtension->bBadDeviceID=TRUE;
  2086. USBPRINT_KdPrint1 (("USBPRINT.SYS: Get1284Id Failed\n"));
  2087. ntStatus=STATUS_NOT_SUPPORTED;
  2088. pParentExtension->DeviceIdString[0]=0;
  2089. } /*end if Get1284 failed*/
  2090. else
  2091. {
  2092. USBPRINT_KdPrint3 (("USBPRINT.SYS: Get1284Id Succeeded\n"));
  2093. USBPRINT_KdPrint2 (("USBPRINT.SYS: 1284 ID == %s\n",(p1284Id+2)));
  2094. ntStatus=ParPnpGetId(p1284Id+2,BusQueryDeviceID,pParentExtension->DeviceIdString);
  2095. USBPRINT_KdPrint3 (("USBPRINT.SYS: After call to ParPnpGetId"));
  2096. if(!NT_SUCCESS(ntStatus))
  2097. {
  2098. iReturnSize=-1;
  2099. USBPRINT_KdPrint1 (("USBPRINT.SYS: ParPnpGetId failed, error==%d, %u\n",ntStatus,ntStatus));
  2100. pParentExtension->bBadDeviceID=TRUE;
  2101. }
  2102. else
  2103. {
  2104. USBPRINT_KdPrint3 (("USBPRINT.SYS: After ParPnpGetID\n"));
  2105. USBPRINT_KdPrint2 (("USBPRINT.SYS: DeviceIdString=%s\n",pParentExtension->DeviceIdString));
  2106. }
  2107. } /*end if the request didn't fail*/
  2108. ExFreePool(p1284Id);
  2109. }
  2110. USBPRINT_KdPrint2 (("USBPRINT.SYS: GetDeviceID exit\n"));
  2111. } /*end function USBPRINT_GetDeviceID*/
  2112. NTSTATUS ProduceQueriedID(PDEVICE_EXTENSION deviceExtension,PIO_STACK_LOCATION irpStack,PIRP Irp,PDEVICE_OBJECT DeviceObject)
  2113. {
  2114. PDEVICE_EXTENSION pParentExtension;
  2115. NTSTATUS ntStatus=STATUS_SUCCESS;
  2116. WCHAR wTempString1[30];
  2117. PWSTR pWalk;
  2118. HANDLE hChildRegKey;
  2119. UCHAR *pRawString,*pTempString;
  2120. UNICODE_STRING UnicodeDeviceId;
  2121. UNICODE_STRING uncPortValueName;
  2122. ANSI_STRING AnsiIdString;
  2123. PCHILD_DEVICE_EXTENSION pChildExtension;
  2124. int iReturnSize;
  2125. int iFirstLen,iSecondLen, iTotalLen;
  2126. pChildExtension=(PCHILD_DEVICE_EXTENSION)deviceExtension;
  2127. pParentExtension=pChildExtension->ParentDeviceObject->DeviceExtension;
  2128. if(pParentExtension->bBadDeviceID==TRUE)
  2129. {
  2130. USBPRINT_KdPrint2(("USBPRINT.SYS: About to error out of ProduceQueriedID with STATUS_NOT_FOUND\n"));
  2131. return STATUS_NOT_FOUND;
  2132. }
  2133. pRawString=ExAllocatePool(NonPagedPool,MAX_ID_SIZE);
  2134. pTempString=ExAllocatePool(NonPagedPool,MAX_ID_SIZE);
  2135. if((pTempString==NULL)||(pRawString==NULL))
  2136. {
  2137. USBPRINT_KdPrint1 (("USBPRINT.SYS: BusQueryDeviceIDs; No memory. Failing\n"));
  2138. ntStatus=STATUS_NO_MEMORY;
  2139. iReturnSize=-1;
  2140. }
  2141. else
  2142. {
  2143. if(pParentExtension->DeviceIdString[0]!=0)
  2144. {
  2145. switch(irpStack->Parameters.QueryId.IdType)
  2146. {
  2147. case BusQueryDeviceID:
  2148. USBPRINT_KdPrint2 (("USBPRINT.SYS: Received BusQueryDeviceID message\n"));
  2149. sprintf(pRawString,"USBPRINT\\%s",pParentExtension->DeviceIdString); //this sprintf safe.. DeviceIDString guaranteed to be 15 less than RawString
  2150. USBPRINT_KdPrint2 (("USBPRINT.SYS: ID before fixup=%s\n",pRawString));
  2151. FixupDeviceId((PUCHAR)pRawString);
  2152. USBPRINT_KdPrint2 (("USBPRINT.SYS: ID after fixup=%s\n",pRawString));
  2153. RtlInitAnsiString(&AnsiIdString,pRawString);
  2154. if(!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeDeviceId,&AnsiIdString,TRUE))) //Make a unicode string out of this
  2155. {
  2156. ntStatus=STATUS_NO_MEMORY;
  2157. iReturnSize=-1;
  2158. Irp->IoStatus.Information=0;
  2159. break;
  2160. }
  2161. ntStatus=STATUS_SUCCESS;
  2162. Irp->IoStatus.Information=(ULONG_PTR)UnicodeDeviceId.Buffer;
  2163. USBPRINT_KdPrint2(("USBPRINT.SYS: __________________________________returing DeviceID\n"));
  2164. break;
  2165. case BusQueryInstanceID:
  2166. USBPRINT_KdPrint2 (("USBPRINT.SYS: Received BusQueryInstanceID message\n"));
  2167. USBPRINT_KdPrint2 (("USBPRINT.SYS: returning instance %u\n",pChildExtension->ulInstanceNumber));
  2168. sprintf(pRawString,"USB%03u",pChildExtension->ulInstanceNumber);
  2169. USBPRINT_KdPrint2 (("USBPRINT.SYS: RawString=%s\n",pRawString));
  2170. RtlInitAnsiString(&AnsiIdString,pRawString);
  2171. if(!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeDeviceId,&AnsiIdString,TRUE))) //Make a unicode string out of this
  2172. {
  2173. ntStatus=STATUS_NO_MEMORY;
  2174. iReturnSize=-1;
  2175. Irp->IoStatus.Information=0;
  2176. break;
  2177. }
  2178. ntStatus=STATUS_SUCCESS;
  2179. Irp->IoStatus.Information=(ULONG_PTR)UnicodeDeviceId.Buffer;
  2180. break;
  2181. case BusQueryHardwareIDs:
  2182. USBPRINT_KdPrint2 (("USBPRINT.SYS: Received BusQueryHardwareIDs message\n"));
  2183. #ifndef WIN9XBUILD
  2184. USBPRINT_KdPrint2 (("USBPRINT.SYS: inside IF NT\n"));
  2185. ntStatus=IoOpenDeviceRegistryKey(DeviceObject,PLUGPLAY_REGKEY_DEVICE,KEY_ALL_ACCESS,&hChildRegKey);
  2186. #else
  2187. USBPRINT_KdPrint2 (("USBPRINT.SYS: inside not NT\n"));
  2188. ntStatus=IoOpenDeviceRegistryKey(pParentExtension->PhysicalDeviceObject,PLUGPLAY_REGKEY_DEVICE,KEY_ALL_ACCESS,&hChildRegKey);
  2189. #endif
  2190. if(!NT_SUCCESS(ntStatus))
  2191. {
  2192. USBPRINT_KdPrint1 (("USBPRINT.SYS: BusQueryHardwareIDs; IoOpenDeviceRegistryKey failed\n"));
  2193. break;
  2194. }
  2195. swprintf(wTempString1,L"USB%03u",pChildExtension->ulInstanceNumber);
  2196. RtlInitUnicodeString(&uncPortValueName,L"PortName");
  2197. ntStatus=ZwSetValueKey(hChildRegKey,&uncPortValueName,0,REG_SZ,wTempString1,(wcslen(wTempString1)+1)*sizeof(WCHAR));
  2198. if(!NT_SUCCESS(ntStatus))
  2199. {
  2200. USBPRINT_KdPrint1 (("USBPRINT.SYS: BusQueryHardwareIDs; ZwSetValueKey failed\n"));
  2201. }
  2202. else
  2203. {
  2204. USBPRINT_KdPrint3 (("USBPRINT.SYS: BusQueryHardwareIDs; ZwSetValueKey worked, wcslen(wTempString1)==%u\n",wcslen(wTempString1)));
  2205. ntStatus=STATUS_SUCCESS;
  2206. }
  2207. ZwClose(hChildRegKey);
  2208. if(pParentExtension->DeviceIdString[0]==0)
  2209. {
  2210. ntStatus=STATUS_NOT_FOUND;
  2211. USBPRINT_KdPrint2 (("USBPRINT.SYS: BusQueryCompatibleIDs; DeviceIdString is null. Can't continue\n"));
  2212. break;
  2213. }
  2214. ntStatus=ParPnpGetId(pParentExtension->DeviceIdString,irpStack->Parameters.QueryId.IdType,pRawString);
  2215. if(!NT_SUCCESS(ntStatus))
  2216. {
  2217. USBPRINT_KdPrint1 (("USBPRINT.SYS: BusQueryDeviceIDs; ParPnpGetID failed\n"));
  2218. break;
  2219. }
  2220. if((strlen(pRawString)+ID_OVERHEAD)*2>MAX_ID_SIZE)
  2221. {
  2222. ntStatus=STATUS_NO_MEMORY;
  2223. USBPRINT_KdPrint1 (("USBPRINT.SYS: BusQueryDeviceIDs; ID's to long. Failing\n"));
  2224. iReturnSize=-1;
  2225. break;
  2226. }
  2227. FixupDeviceId((PUCHAR)pRawString);
  2228. sprintf(pTempString,"USBPRINT\\%s",pRawString);
  2229. iFirstLen=strlen(pTempString);
  2230. *(pTempString+iFirstLen)=' '; //make the old null be a space so that RtlInitAnsiString will step past it
  2231. *(pTempString+iFirstLen+1)='\0'; //add an extra null at the end of the string
  2232. strcat(pTempString,pRawString);
  2233. iTotalLen=strlen(pTempString);
  2234. #ifdef USBPRINT_LIE_ABOUT_LPT
  2235. *(pTempString+iTotalLen)=' ';
  2236. *(pTempString+iTotalLen+1)='\0';
  2237. iSecondLen=iTotalLen;
  2238. strcat(pTempString,"LPTENUM\\");
  2239. strcat(pTempString,pRawString);
  2240. iTotalLen=strlen(pTempString);
  2241. #endif
  2242. *(pTempString+iTotalLen)=' ';
  2243. *(pTempString+iTotalLen+1)='\0';
  2244. USBPRINT_KdPrint2 (("USBPRINT.SYS: Hardware ID before fixup=%s\n",pRawString));
  2245. USBPRINT_KdPrint2 (("USBPRINT.SYS: Hardware ID after fixup=%s\n",pRawString));
  2246. RtlInitAnsiString(&AnsiIdString,pTempString); //make a counted ansi string
  2247. if(!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeDeviceId,&AnsiIdString,TRUE))) //Make a unicode string out of this
  2248. {
  2249. ntStatus=STATUS_NO_MEMORY;
  2250. iReturnSize=-1;
  2251. Irp->IoStatus.Information=0;
  2252. break;
  2253. }
  2254. pWalk = UnicodeDeviceId.Buffer+iFirstLen; //Set a pointer to the beginning of the string
  2255. *pWalk=L'\0'; //set the space to be a unicode null
  2256. #ifdef USBPRINT_LIE_ABOUT_LPT
  2257. pWalk = UnicodeDeviceId.Buffer+iSecondLen; //Set a pointer to the beginning of the string
  2258. *pWalk=L'\0'; //set the space to be a unicode null
  2259. #endif
  2260. pWalk = UnicodeDeviceId.Buffer+iTotalLen; //set a pointer to the space at the end of the total string
  2261. *pWalk=L'\0'; //set the space to be a unicode null, so that we now have a double unicode null.
  2262. Irp->IoStatus.Information = (ULONG_PTR)UnicodeDeviceId.Buffer;
  2263. break;
  2264. case BusQueryCompatibleIDs:
  2265. Irp->IoStatus.Information = (ULONG_PTR) NULL; //(ULONG_PTR)UnicodeDeviceId.Buffer;
  2266. break;
  2267. default:
  2268. ntStatus = Irp->IoStatus.Status;
  2269. } /*end switch ID type*/
  2270. } /*end no 1284 ID*/
  2271. else
  2272. {
  2273. ntStatus=STATUS_NOT_FOUND;
  2274. }
  2275. }
  2276. if(pTempString!=NULL)
  2277. ExFreePool(pTempString);
  2278. if(pRawString!=NULL)
  2279. ExFreePool(pRawString);
  2280. return ntStatus;
  2281. } /*End function QueryID*/
  2282. //
  2283. // Function: bAddPortInUseItem
  2284. //
  2285. // Description : iPortNumber is removed from the free ports list structure.
  2286. //
  2287. // Parameters: IN\OUT pFreePorts - is the beginning of the list and on return will contain the beginning of the list.
  2288. // pFreePorts may change during the call.
  2289. // IN iPortNumber - the port number that is in use.
  2290. //
  2291. // Returns: NTSTATUS value - STATUS_NO_MEMORY
  2292. // - STATUS_SUCCESS
  2293. //
  2294. NTSTATUS bAddPortInUseItem(PFREE_PORTS * pFreePorts,ULONG iPortNumber )
  2295. {
  2296. NTSTATUS ntstatus = STATUS_SUCCESS;
  2297. PFREE_PORTS pBefore = *pFreePorts;
  2298. PFREE_PORTS pHead = *pFreePorts;
  2299. PFREE_PORTS pNewBlock = NULL;
  2300. USBPRINT_KdPrint2 ((" USBPRINT.SYS: Head of bAddPortInUseItem\n"));
  2301. //
  2302. // Traverse the FREE_PORT structure to remove the port number from the list.
  2303. // Note - This function will not be needed to be called by anyone else other than LoadPortsUsed
  2304. // as the GetNewPortNumber will do this functionality automatically.
  2305. //
  2306. while( *pFreePorts )
  2307. {
  2308. if( iPortNumber >= (*pFreePorts)->iBottomOfRange && iPortNumber <= (*pFreePorts)->iTopOfRange )
  2309. {
  2310. // We're where we want to be - so decide what to do...
  2311. if( iPortNumber == (*pFreePorts)->iBottomOfRange )
  2312. {
  2313. if( (++((*pFreePorts)->iBottomOfRange)) > (*pFreePorts)->iTopOfRange )
  2314. {
  2315. // Case of the Port Number being the first and only element in the first block.
  2316. if( *pFreePorts == pHead )
  2317. {
  2318. pHead = (*pFreePorts)->pNextBlock;
  2319. }
  2320. else // Case of the Port Number being the first element in another block.
  2321. {
  2322. pBefore->pNextBlock = (*pFreePorts)->pNextBlock;
  2323. }
  2324. ExFreePool( *pFreePorts );
  2325. }
  2326. }
  2327. else
  2328. {
  2329. if( iPortNumber == (*pFreePorts)->iTopOfRange )
  2330. { // Deletion case handled in the above case, so just need to decrement.
  2331. ((*pFreePorts)->iTopOfRange)--;
  2332. }
  2333. else // Otherwise we're in the middle of the block and we need to split it.
  2334. {
  2335. pNewBlock = ExAllocatePoolWithTag( NonPagedPool, sizeof(FREE_PORTS), USBP_TAG);
  2336. if( !pNewBlock )
  2337. {
  2338. ntstatus = STATUS_NO_MEMORY;
  2339. goto Cleanup;
  2340. }
  2341. pNewBlock->iTopOfRange = (*pFreePorts)->iTopOfRange;
  2342. (*pFreePorts)->iTopOfRange = iPortNumber - 1;
  2343. pNewBlock->iBottomOfRange = iPortNumber + 1;
  2344. pNewBlock->pNextBlock = (*pFreePorts)->pNextBlock;
  2345. (*pFreePorts)->pNextBlock = pNewBlock;
  2346. }
  2347. }
  2348. break;
  2349. }
  2350. else
  2351. {
  2352. if( iPortNumber < (*pFreePorts)->iBottomOfRange )
  2353. { // The port number has already been used - not in the free list.
  2354. USBPRINT_KdPrint2 ((" USBPRINT.SYS: Port number %n is allocated already from free list.\n", iPortNumber));
  2355. break;
  2356. }
  2357. pBefore = *pFreePorts;
  2358. *pFreePorts = (*pFreePorts)->pNextBlock;
  2359. }
  2360. }
  2361. if( NULL == *pFreePorts )
  2362. {
  2363. ntstatus = STATUS_INVALID_PARAMETER;
  2364. // Assert this as we could never allocate a port number that is not in the initial ranges 1-999
  2365. // - but if we assert here, we have run off the end of the port allocation numbers.
  2366. ASSERT( *pFreePorts );
  2367. }
  2368. Cleanup:
  2369. *pFreePorts = pHead;
  2370. return ntstatus;
  2371. } /*end function bAddPortInUseItem*/
  2372. void vClaimPortNumber(ULONG ulPortNumber,HANDLE hInterfaceKey,PFREE_PORTS * pPortsUsed)
  2373. {
  2374. UNICODE_STRING wRecycle;
  2375. WCHAR *pName;
  2376. pName=L"RECYCLABLE";
  2377. RtlInitUnicodeString(&wRecycle,pName);
  2378. #if WIN95_BUILD==1
  2379. SetValueToZero(hInterfaceKey,&wRecycle);
  2380. #else
  2381. ZwDeleteValueKey(hInterfaceKey,&wRecycle);
  2382. #endif
  2383. // Do we need to fail out gracefully from the below?
  2384. // The func doesn't have a return, but we could fail a mem alloc inside the below call!!
  2385. // bAddPortInUseItem(pPortsUsed,ulPortNumber);
  2386. } /*end function vClaimPortNumber*/
  2387. NTSTATUS GetNewPortNumber(PFREE_PORTS * pFreePorts, ULONG *pulPortNumber)
  2388. {
  2389. NTSTATUS ntstatus = STATUS_SUCCESS;
  2390. PFREE_PORTS pTemp = *pFreePorts;
  2391. USBPRINT_KdPrint2 (("USBPRINT.SYS: Head of GetNewPortNumber\n"));
  2392. if( NULL == *pFreePorts )
  2393. {
  2394. // If the pFreePorts list is empty - try to reconstruct it.
  2395. ntstatus=InitFreePorts(pFreePorts);
  2396. if(NT_SUCCESS(ntstatus))
  2397. ntstatus=LoadPortsUsed((GUID *)&USBPRINT_GUID,pFreePorts,USB_BASE_NAME);
  2398. if( NULL == *pFreePorts && NT_SUCCESS(ntstatus))
  2399. {
  2400. ntstatus=STATUS_INVALID_PORT_HANDLE;
  2401. }
  2402. if(!NT_SUCCESS(ntstatus))
  2403. {
  2404. *pulPortNumber = 0;
  2405. goto Cleanup;
  2406. }
  2407. }
  2408. *pulPortNumber = (*pFreePorts)->iBottomOfRange;
  2409. if( (++((*pFreePorts)->iBottomOfRange)) > (*pFreePorts)->iTopOfRange )
  2410. {
  2411. // Case of the Port Number being the first and only element in the first block.
  2412. *pFreePorts = (*pFreePorts)->pNextBlock;
  2413. ExFreePool( pTemp );
  2414. }
  2415. Cleanup:
  2416. return ntstatus;
  2417. } /*end function GetNewPortNumber*/
  2418. BOOL bDeleteIfRecyclable(HANDLE hRegKey)
  2419. {
  2420. BOOL bReturn=FALSE;
  2421. UNICODE_STRING wcValueName;
  2422. NTSTATUS ntStatus;
  2423. USBPRINT_KdPrint2 (("USBPRINT.SYS: Head of bDeleteifRecyclable\n"));
  2424. RtlInitUnicodeString(&wcValueName,L"recyclable");
  2425. #if WIN95_BUILD==1
  2426. ntStatus=SetValueToZero(hRegKey,&wcValueName);
  2427. #else
  2428. ntStatus=ZwDeleteValueKey(hRegKey,&wcValueName);
  2429. #endif
  2430. if(NT_SUCCESS(ntStatus))
  2431. {
  2432. RtlInitUnicodeString(&wcValueName,L"Port Number");
  2433. #if WIN95_BUILD==1
  2434. ntStatus=SetValueToZero(hRegKey,&wcValueName);
  2435. #else
  2436. ntStatus=ZwDeleteValueKey(hRegKey,&wcValueName);
  2437. #endif
  2438. if(NT_SUCCESS(ntStatus))
  2439. bReturn=TRUE;
  2440. } // end function bDeleteIfRecyclable
  2441. if(bReturn)
  2442. {
  2443. USBPRINT_KdPrint3 (("USBPRINT.SYS: bDeleteIfRecyclable, returning TRUE\n"));
  2444. }
  2445. else
  2446. {
  2447. USBPRINT_KdPrint3 (("USBPRINT.SYS: bDeleteIfRecyclable, returning FALSE\n"));
  2448. }
  2449. return bReturn;
  2450. } //End function bDeleteIfRecycable
  2451. //
  2452. // Initialises the free ports structure list.
  2453. // pHead must be NULL or a valid pointer to a FREE_PORTS structure.
  2454. //
  2455. NTSTATUS InitFreePorts( PFREE_PORTS * pHead )
  2456. {
  2457. PFREE_PORTS pNext = *pHead;
  2458. NTSTATUS ntstatus = STATUS_SUCCESS;
  2459. while(pNext)
  2460. {
  2461. pNext = (*pHead)->pNextBlock;
  2462. ExFreePool(*pHead);
  2463. *pHead = pNext;
  2464. }
  2465. //
  2466. // Any old list will be cleared from memory and pHead will be NULL
  2467. //
  2468. *pHead = ExAllocatePoolWithTag(NonPagedPool, sizeof(FREE_PORTS), USBP_TAG);
  2469. if( *pHead )
  2470. {
  2471. (*pHead)->iBottomOfRange = MIN_PORT_NUMBER;
  2472. (*pHead)->iTopOfRange = MAX_PORT_NUMBER;
  2473. (*pHead)->pNextBlock = NULL;
  2474. }
  2475. else
  2476. ntstatus = STATUS_NO_MEMORY;
  2477. return ntstatus;
  2478. }
  2479. void ClearFreePorts( PFREE_PORTS * pHead )
  2480. {
  2481. PFREE_PORTS pTemp = *pHead;
  2482. while( *pHead )
  2483. {
  2484. *pHead = (*pHead)->pNextBlock;
  2485. ExFreePool( pTemp );
  2486. pTemp = *pHead;
  2487. }
  2488. }
  2489. /********************************************************
  2490. * SetValueToZero. Sets and interger reg key to zero.
  2491. * Returns failure if reg key does not exist, or if
  2492. * The key already is set to zero. Mimics ZwDeleteValueKey
  2493. * (which is not currently avaiable on Milinium) by
  2494. * useing the value 0 to mean deleted
  2495. **************************************************************/
  2496. NTSTATUS SetValueToZero(HANDLE hRegKey,PUNICODE_STRING ValueName)
  2497. {
  2498. PKEY_VALUE_PARTIAL_INFORMATION pValueStruct;
  2499. NTSTATUS ReturnCode;
  2500. ULONG dwZero=0;
  2501. ULONG ulSizeUsed;
  2502. NTSTATUS ntStatus;
  2503. int iValue;
  2504. ulSizeUsed=sizeof(KEY_VALUE_PARTIAL_INFORMATION)+sizeof(ULONG); //this is a byte to much. Oh well
  2505. pValueStruct=ExAllocatePool(NonPagedPool,ulSizeUsed);
  2506. if(pValueStruct==NULL)
  2507. {
  2508. USBPRINT_KdPrint1(("USBPRINT.SYS: SetValueToZero; Unable to allocate memory\n"));
  2509. return STATUS_NO_MEMORY;
  2510. }
  2511. ntStatus=ZwQueryValueKey(hRegKey,ValueName,KeyValuePartialInformation,pValueStruct,ulSizeUsed,&ulSizeUsed);
  2512. if(!NT_SUCCESS(ntStatus))
  2513. {
  2514. USBPRINT_KdPrint3(("Failed to Query value Key\n"));
  2515. ExFreePool(pValueStruct);
  2516. return STATUS_OBJECT_NAME_NOT_FOUND;
  2517. }
  2518. iValue=(int)*((ULONG *)(pValueStruct->Data));
  2519. ExFreePool(pValueStruct);
  2520. if(iValue==0)
  2521. return STATUS_OBJECT_NAME_NOT_FOUND;
  2522. //if we make it to here, the value exists, and is nonzero
  2523. ReturnCode=ZwSetValueKey(hRegKey,ValueName,0,REG_DWORD,&dwZero,sizeof(dwZero));
  2524. return ReturnCode;
  2525. } /*end function SetValueToZero*/
  2526. VOID
  2527. USBPRINT_FdoIdleNotificationCallback(IN PDEVICE_EXTENSION DevExt)
  2528. /*++
  2529. Routine Description:
  2530. Called when it is time to idle out USB printer
  2531. --*/
  2532. {
  2533. POWER_STATE powerState;
  2534. NTSTATUS ntStatus;
  2535. USBPRINT_KdPrint1(("USB Printer (%08X) going idle\n", DevExt));
  2536. if(!DevExt->AcceptingRequests || DevExt->OpenCnt)
  2537. {
  2538. // Don't idle this printer if the printer is not accepting requests
  2539. USBPRINT_KdPrint1(("USB Printer (%08X) not accepting requests, abort idle\n", DevExt));
  2540. return;
  2541. }
  2542. powerState.DeviceState = DevExt->DeviceWake;
  2543. // request new device power state, wait wake Irp will be posted on request
  2544. PoRequestPowerIrp(DevExt->PhysicalDeviceObject,
  2545. IRP_MN_SET_POWER,
  2546. powerState,
  2547. NULL,
  2548. NULL,
  2549. NULL);
  2550. } // USBPRINT_FdoIdleNotificationCallback
  2551. NTSTATUS
  2552. USBPRINT_FdoIdleNotificationRequestComplete(
  2553. PDEVICE_OBJECT DeviceObject,
  2554. PIRP Irp,
  2555. PDEVICE_EXTENSION DevExt
  2556. )
  2557. /*++
  2558. Routine Description:
  2559. Completion routine for the Idle request IRP for the USB printer device
  2560. --*/
  2561. {
  2562. NTSTATUS ntStatus;
  2563. PUSB_IDLE_CALLBACK_INFO idleCallbackInfo;
  2564. //
  2565. // DeviceObject is NULL because we sent the irp
  2566. //
  2567. UNREFERENCED_PARAMETER(DeviceObject);
  2568. USBPRINT_KdPrint1(("Idle notification IRP for USB Printer (%08X) completed (%08X)\n",
  2569. DevExt, Irp->IoStatus.Status));
  2570. // save completion status in device extension
  2571. idleCallbackInfo = DevExt->IdleCallbackInfo;
  2572. DevExt->IdleCallbackInfo = NULL;
  2573. DevExt->PendingIdleIrp = NULL;
  2574. // free up callback info
  2575. if(idleCallbackInfo)
  2576. {
  2577. ExFreePool(idleCallbackInfo);
  2578. }
  2579. ntStatus = Irp->IoStatus.Status;
  2580. return ntStatus;
  2581. } // USBPRINT_FdoIdleNotificationRequestComplete
  2582. NTSTATUS
  2583. USBPRINT_FdoSubmitIdleRequestIrp(IN PDEVICE_EXTENSION DevExt)
  2584. /*++
  2585. Routine Description:
  2586. Called when all handles to the USB printer are closed. This function allocates
  2587. an idle request IOCTL IRP and passes it to the parent's PDO.
  2588. --*/
  2589. {
  2590. PIRP irp = NULL;
  2591. NTSTATUS ntStatus = STATUS_SUCCESS;
  2592. PUSB_IDLE_CALLBACK_INFO idleCallbackInfo = NULL;
  2593. USBPRINT_KdPrint1(("USBPRINT_FdoSubmitIdleRequestIrp (%08X)\n", DevExt));
  2594. // if we have an Irp pending, don't bother to send another
  2595. if(DevExt->PendingIdleIrp || DevExt->CurrentDevicePowerState == DevExt->DeviceWake)
  2596. return ntStatus;
  2597. idleCallbackInfo = ExAllocatePoolWithTag(NonPagedPool,
  2598. sizeof(struct _USB_IDLE_CALLBACK_INFO), USBP_TAG);
  2599. if (idleCallbackInfo)
  2600. {
  2601. idleCallbackInfo->IdleCallback = USBPRINT_FdoIdleNotificationCallback;
  2602. idleCallbackInfo->IdleContext = (PVOID)DevExt;
  2603. DevExt->IdleCallbackInfo = idleCallbackInfo;
  2604. irp = IoBuildDeviceIoControlRequest(
  2605. IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION,
  2606. DevExt->PhysicalDeviceObject,
  2607. idleCallbackInfo,
  2608. sizeof(struct _USB_IDLE_CALLBACK_INFO),
  2609. NULL,
  2610. 0,
  2611. TRUE, /* INTERNAL */
  2612. NULL,
  2613. NULL);
  2614. if (irp == NULL)
  2615. {
  2616. ExFreePool(idleCallbackInfo);
  2617. return STATUS_INSUFFICIENT_RESOURCES;
  2618. }
  2619. IoSetCompletionRoutine(irp,
  2620. USBPRINT_FdoIdleNotificationRequestComplete,
  2621. DevExt,
  2622. TRUE,
  2623. TRUE,
  2624. TRUE);
  2625. ntStatus = IoCallDriver(DevExt->PhysicalDeviceObject, irp);
  2626. if(ntStatus == STATUS_PENDING)
  2627. {
  2628. // Successfully posted an Idle IRP.
  2629. DevExt->PendingIdleIrp = irp;
  2630. }
  2631. }
  2632. return ntStatus;
  2633. } // USBPRINT_FdoSubmitIdleRequestIrp
  2634. VOID
  2635. USBPRINT_FdoRequestWake(IN PDEVICE_EXTENSION DevExt)
  2636. /*++
  2637. Routine Description:
  2638. Called when we want to wake up the device after an idle request
  2639. --*/
  2640. {
  2641. POWER_STATE powerState;
  2642. KIRQL OldIrql;
  2643. BOOL bExit=FALSE;
  2644. USBPRINT_KdPrint1(("USBPRINT: USB Printer (%08X) waking up\n", DevExt));
  2645. KeAcquireSpinLock(&(DevExt->WakeSpinLock),&OldIrql);
  2646. if(!DevExt->AcceptingRequests || DevExt->CurrentDevicePowerState == PowerDeviceD0 || DevExt->bD0IrpPending)
  2647. {
  2648. // Don't wake this printer if it's not accepting requests or we're already at power state D0
  2649. if(!DevExt->AcceptingRequests)
  2650. USBPRINT_KdPrint1(("USBPRINT: USB Printer (%08X) not accepting requests, abort wake\n", DevExt));
  2651. if(DevExt->CurrentDevicePowerState == PowerDeviceD0)
  2652. USBPRINT_KdPrint1(("USBPRINT: USB Printer (%08X) already at D0, abort wake\n", DevExt));
  2653. if(DevExt->bD0IrpPending == TRUE)
  2654. USBPRINT_KdPrint1(("USBPRINT: USB Printer (%08X) already has D0 irp pending, abort wake\n", DevExt));
  2655. bExit=TRUE;
  2656. }
  2657. else
  2658. DevExt->bD0IrpPending=TRUE;
  2659. KeReleaseSpinLock(&(DevExt->WakeSpinLock),OldIrql);
  2660. if(bExit)
  2661. return;
  2662. powerState.DeviceState = PowerDeviceD0;
  2663. // request new device power state, wake up the device
  2664. PoRequestPowerIrp(DevExt->PhysicalDeviceObject,
  2665. IRP_MN_SET_POWER,
  2666. powerState,
  2667. NULL,
  2668. NULL,
  2669. NULL);
  2670. } // USBPRINT_FdoRequestWake
  2671. void vOpenLogFile(HANDLE *pHandle)
  2672. {
  2673. NTSTATUS ntStatus;
  2674. OBJECT_ATTRIBUTES FileAttributes;
  2675. IO_STATUS_BLOCK StatusBlock;
  2676. UNICODE_STRING PathName;
  2677. RtlInitUnicodeString(&PathName,L"\\??\\C:\\USBPRINT.LOG");
  2678. InitializeObjectAttributes(&FileAttributes,&PathName,0,NULL,NULL);
  2679. ntStatus=ZwCreateFile(pHandle,
  2680. GENERIC_WRITE,
  2681. &FileAttributes,
  2682. &StatusBlock,
  2683. 0,
  2684. 0,
  2685. FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
  2686. FILE_OPEN_IF,
  2687. FILE_NON_DIRECTORY_FILE|FILE_WRITE_THROUGH|FILE_SYNCHRONOUS_IO_NONALERT,
  2688. NULL,
  2689. 0);
  2690. if(!NT_SUCCESS(ntStatus))
  2691. {
  2692. USBPRINT_KdPrint1(("USBPRINT: Unable to open C:\\USBPRINT.LOG"));
  2693. }
  2694. else
  2695. {
  2696. USBPRINT_KdPrint1(("USBPRINT: Opened logfile C:\\USBPRINT.LOG")); /*dd*/
  2697. }
  2698. }
  2699. void vWriteToLogFile(HANDLE *pHandle,IN CHAR *pszString)
  2700. {
  2701. HANDLE hFileHandle;
  2702. ULONG BufferSize;
  2703. NTSTATUS ntStatus;
  2704. IO_STATUS_BLOCK StatusBlock;
  2705. LARGE_INTEGER WriteOffset;
  2706. WriteOffset.LowPart=FILE_WRITE_TO_END_OF_FILE;
  2707. WriteOffset.HighPart=-1;
  2708. BufferSize=strlen(pszString);
  2709. ntStatus=ZwWriteFile(*pHandle,
  2710. NULL,
  2711. NULL,
  2712. NULL,
  2713. &StatusBlock,
  2714. pszString,
  2715. BufferSize,
  2716. &WriteOffset,
  2717. NULL);
  2718. if(!NT_SUCCESS(ntStatus))
  2719. {
  2720. USBPRINT_KdPrint1(("USBPRINT: Unable to write to log file C:\\USBPRINT.LOG"));
  2721. }
  2722. else
  2723. {
  2724. USBPRINT_KdPrint1(("USBPRINT: write to log file C:\\USBPRINT.LOG")); /*dd*/
  2725. }
  2726. } /*end function vWriteToLog*/
  2727. void vCloseLogFile(IN HANDLE *pHandle)
  2728. {
  2729. ZwClose(*pHandle);
  2730. } /*end function vCloseLogFile*/