Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3196 lines
95 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1997 - 1999
  3. Module Name:
  4. usbscn9x.c
  5. Abstract:
  6. Environment:
  7. kernel mode only
  8. Notes:
  9. Revision History:
  10. --*/
  11. #include <wdm.h>
  12. #include <stdio.h>
  13. #include <usbscan.h>
  14. #include <usbd_api.h>
  15. #include "private.h"
  16. #include <initguid.h>
  17. #include <wiaintfc.h>
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text(PAGE, DriverEntry)
  20. #pragma alloc_text(PAGE, USPnpAddDevice)
  21. #pragma alloc_text(PAGE, USPnp)
  22. #pragma alloc_text(PAGE, USCreateSymbolicLink)
  23. #pragma alloc_text(PAGE, USDestroySymbolicLink)
  24. #pragma alloc_text(PAGE, USGetUSBDeviceDescriptor)
  25. #pragma alloc_text(PAGE, USConfigureDevice)
  26. #pragma alloc_text(PAGE, USUnConfigureDevice)
  27. #pragma alloc_text(PAGE, USUnload)
  28. #endif
  29. // Globals
  30. ULONG NextDeviceInstance = 0;
  31. #if DBG
  32. ULONG USBSCAN_DebugTraceLevel = MIN_TRACE;
  33. ULONG USBSCAN_PnPTest = 0;
  34. #endif
  35. NTSTATUS
  36. DriverEntry(
  37. IN PDRIVER_OBJECT pDriverObject,
  38. IN PUNICODE_STRING pRegistryPath
  39. )
  40. {
  41. /*++
  42. Routine Description:
  43. Installable driver initialization entry point.
  44. This is where the driver is called when the driver is being loaded
  45. by the I/O system.
  46. Arguments:
  47. DriverObject - pointer to the driver object
  48. RegistryPath - pointer to a unicode string representing the path
  49. to driver-specific key in the registry
  50. Return Value:
  51. STATUS_SUCCESS if successful,
  52. STATUS_UNSUCCESSFUL otherwise
  53. -- */
  54. PAGED_CODE();
  55. DebugTrace((MIN_TRACE | TRACE_FLAG_PROC),("DriverEntry called. Driver reg=%wZ\n",pRegistryPath));
  56. #if DBG
  57. MyDebugInit(pRegistryPath);
  58. #endif // DBG
  59. pDriverObject -> MajorFunction[IRP_MJ_READ] = USRead;
  60. pDriverObject -> MajorFunction[IRP_MJ_WRITE] = USWrite;
  61. pDriverObject -> MajorFunction[IRP_MJ_DEVICE_CONTROL] = USDeviceControl;
  62. pDriverObject -> MajorFunction[IRP_MJ_CREATE] = USOpen;
  63. pDriverObject -> MajorFunction[IRP_MJ_CLOSE] = USClose;
  64. pDriverObject -> MajorFunction[IRP_MJ_PNP_POWER] = USPnp;
  65. pDriverObject -> MajorFunction[IRP_MJ_FLUSH_BUFFERS] = USFlush;
  66. pDriverObject -> MajorFunction[IRP_MJ_POWER] = USPower;
  67. pDriverObject -> MajorFunction[IRP_MJ_SYSTEM_CONTROL] = USPnp;
  68. pDriverObject -> DriverExtension -> AddDevice = USPnpAddDevice;
  69. pDriverObject -> DriverUnload = USUnload;
  70. return STATUS_SUCCESS;
  71. }
  72. NTSTATUS
  73. USPnpAddDevice(
  74. IN PDRIVER_OBJECT pDriverObject,
  75. IN OUT PDEVICE_OBJECT pPhysicalDeviceObject
  76. )
  77. /*++
  78. Routine Description:
  79. This routine is called to create a new instance of the device.
  80. Arguments:
  81. pDriverObject - pointer to the driver object for this instance of SS
  82. pPhysicalDeviceObject - pointer to the device object that represents the scanner
  83. on the scsi bus.
  84. Return Value:
  85. STATUS_SUCCESS if successful,
  86. STATUS_UNSUCCESSFUL otherwise
  87. --*/
  88. {
  89. UCHAR aName[64];
  90. ANSI_STRING ansiName;
  91. UNICODE_STRING uName;
  92. PDEVICE_OBJECT pDeviceObject = NULL;
  93. NTSTATUS Status;
  94. PUSBSCAN_DEVICE_EXTENSION pde;
  95. PAGED_CODE();
  96. DebugTrace(TRACE_PROC_ENTER,("USPnpAddDevice: Enter..\n"));
  97. //
  98. // Create the Functional Device Object (FDO) for this device.
  99. //
  100. sprintf(aName,"\\Device\\Usbscan%d",NextDeviceInstance);
  101. RtlInitAnsiString(&ansiName, aName);
  102. //
  103. // Show device object name.
  104. //
  105. DebugTrace(TRACE_STATUS,("USPnpAddDevice: Create device object %s\n", aName));
  106. //
  107. // Allocates Unicode string.
  108. //
  109. Status = RtlAnsiStringToUnicodeString(&uName, &ansiName, TRUE);
  110. if(STATUS_SUCCESS != Status){
  111. DebugTrace(TRACE_CRITICAL,("USPnpAddDevice: ERROR!! Can't alloc buffer for Unicode\n"));
  112. DEBUG_BREAKPOINT();
  113. Status = STATUS_INSUFFICIENT_RESOURCES;
  114. goto USPnpAddDevice_return;
  115. }
  116. //
  117. // Create device object for this scanner.
  118. //
  119. Status = IoCreateDevice(pDriverObject,
  120. sizeof(USBSCAN_DEVICE_EXTENSION),
  121. &uName,
  122. FILE_DEVICE_SCANNER,
  123. 0,
  124. FALSE,
  125. &pDeviceObject);
  126. if (!NT_SUCCESS(Status)) {
  127. DebugTrace(TRACE_ERROR,("USPnpAddDevice: ERROR!! Can't create device object\n"));
  128. DEBUG_BREAKPOINT();
  129. goto USPnpAddDevice_return;
  130. }
  131. //
  132. // Device object was successfully created.
  133. // Free Unicode string used for device creation.
  134. //
  135. RtlFreeUnicodeString(&uName);
  136. uName.Buffer = NULL;
  137. //
  138. // Initialize Device Extension.
  139. //
  140. pde = (PUSBSCAN_DEVICE_EXTENSION)(pDeviceObject -> DeviceExtension);
  141. RtlZeroMemory(pde, sizeof(USBSCAN_DEVICE_EXTENSION));
  142. //
  143. // Save own device object.
  144. //
  145. pde -> pOwnDeviceObject = pDeviceObject;
  146. //
  147. // Initialize PendingIoEvent. Set the number of pending i/o requests for this device to 1.
  148. // When this number falls to zero, it is okay to remove, or stop the device.
  149. //
  150. pde -> PendingIoCount = 0;
  151. pde -> Stopped = FALSE;
  152. KeInitializeEvent(&pde -> PendingIoEvent, NotificationEvent, FALSE);
  153. //
  154. // Indicate that IRPs should include MDLs.
  155. //
  156. pDeviceObject->Flags |= DO_DIRECT_IO;
  157. //
  158. // indicate our power code is pagable
  159. //
  160. pDeviceObject->Flags |= DO_POWER_PAGABLE;
  161. //
  162. // Attach our new FDO to the PDO (Physical Device Object).
  163. //
  164. pde -> pStackDeviceObject = IoAttachDeviceToDeviceStack(pDeviceObject,
  165. pPhysicalDeviceObject);
  166. if (NULL == pde -> pStackDeviceObject) {
  167. DebugTrace(TRACE_ERROR,("USPnpAddDevice: ERROR!! Cannot attach FDO to PDO.\n"));
  168. DEBUG_BREAKPOINT();
  169. IoDeleteDevice( pDeviceObject );
  170. Status = STATUS_NOT_SUPPORTED;
  171. goto USPnpAddDevice_return;
  172. }
  173. //
  174. // Remember the PDO in our device extension.
  175. //
  176. pde -> pPhysicalDeviceObject = pPhysicalDeviceObject;
  177. //
  178. // Remember the DeviceInstance number.
  179. //
  180. pde -> DeviceInstance = NextDeviceInstance;
  181. //
  182. // Handle exporting interface
  183. //
  184. Status = UsbScanHandleInterface(
  185. pPhysicalDeviceObject,
  186. &pde->InterfaceNameString,
  187. TRUE
  188. );
  189. //
  190. // Each time AddDevice gets called, we advance the global DeviceInstance variable.
  191. //
  192. NextDeviceInstance++;
  193. //
  194. // Set initial device power state as online.
  195. //
  196. pde -> CurrentDevicePowerState = PowerDeviceD0;
  197. //
  198. // Initialize spinlock.
  199. //
  200. KeInitializeSpinLock(&pde->SpinLock);
  201. //
  202. // Initialize wake state.
  203. //
  204. USInitializeWakeState(pde);
  205. //
  206. // Will see device capability on START_DEVICE.
  207. //
  208. pde -> bEnabledForWakeup = FALSE;
  209. //
  210. // Finish initializing.
  211. //
  212. pDeviceObject -> Flags &= ~DO_DEVICE_INITIALIZING;
  213. USPnpAddDevice_return:
  214. if(NULL != uName.Buffer){
  215. RtlFreeUnicodeString(&uName);
  216. }
  217. DebugTrace(TRACE_PROC_LEAVE,("USPnpAddDevice: Leaving.. Status = 0x%x\n", Status));
  218. return Status;
  219. } // end USAddDevice()
  220. NTSTATUS USPnp(
  221. IN PDEVICE_OBJECT pDeviceObject,
  222. IN PIRP pIrp
  223. )
  224. /*++
  225. Routine Description:
  226. This routine handles all PNP irps.
  227. Arguments:
  228. pDeviceObject - represents a scanner device
  229. pIrp - PNP irp
  230. Return Value:
  231. STATUS_SUCCESS if successful,
  232. STATUS_UNSUCCESSFUL otherwise
  233. --*/
  234. {
  235. NTSTATUS Status;
  236. PUSBSCAN_DEVICE_EXTENSION pde;
  237. PIO_STACK_LOCATION pIrpStack;
  238. KEVENT event;
  239. PDEVICE_CAPABILITIES pCaps;
  240. LONG bTemp;
  241. POWER_STATE PowerState;
  242. PAGED_CODE();
  243. DebugTrace(TRACE_PROC_ENTER,("USPnp: Enter..\n"));
  244. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  245. pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
  246. Status = pIrp -> IoStatus.Status;
  247. // DbgPrint("USPnP: Major=0x%x, Minor=0x%x\n",
  248. // pIrpStack -> MajorFunction,
  249. // pIrpStack->MinorFunction);
  250. switch (pIrpStack -> MajorFunction) {
  251. case IRP_MJ_SYSTEM_CONTROL:
  252. DebugTrace(TRACE_STATUS,("USPnp: IRP_MJ_SYSTEM_CONTROL\n"));
  253. //
  254. // Simply passing down the IRP.
  255. //
  256. DebugTrace(TRACE_STATUS,("USPnp: Simply passing down the IRP\n"));
  257. IoCopyCurrentIrpStackLocationToNext( pIrp );
  258. Status = IoCallDriver(pde -> pStackDeviceObject, pIrp);
  259. break;
  260. case IRP_MJ_PNP:
  261. DebugTrace(TRACE_STATUS,("USPnp: IRP_MJ_PNP\n"));
  262. switch (pIrpStack->MinorFunction) {
  263. case IRP_MN_QUERY_CAPABILITIES:
  264. DebugTrace(TRACE_STATUS,("USPnp: IRP_MJ_QUERY_CAPS\n"));
  265. //
  266. // Call downlevel driver first to fill capabilities structure
  267. // Then add our specific capabilities
  268. //
  269. DebugTrace(TRACE_STATUS,("USPnp: Call down to get capabilities\n"));
  270. pIrp->IoStatus.Status = STATUS_SUCCESS;
  271. Status = USCallNextDriverSynch(pde, pIrp);
  272. if(!NT_SUCCESS(Status)){
  273. DebugTrace(TRACE_ERROR,("USPnp: ERROR!! Call down failed. Status=0x%x\n", Status));
  274. IoCompleteRequest( pIrp, IO_NO_INCREMENT );
  275. goto USPnP_return;
  276. }
  277. //
  278. // Set SurpriseRemoval OK
  279. //
  280. pCaps = pIrpStack -> Parameters.DeviceCapabilities.Capabilities;
  281. pCaps->SurpriseRemovalOK = TRUE;
  282. pCaps->Removable = TRUE;
  283. //
  284. // Setup remote wakeup state.
  285. //
  286. DebugTrace(TRACE_STATUS,("USPnp: DeviceState[PowerSystemUnspecified]=0x%x.\n",pCaps->DeviceState[PowerSystemUnspecified]));
  287. DebugTrace(TRACE_STATUS,("USPnp: DeviceState[PowerSystemWorking] =0x%x.\n",pCaps->DeviceState[PowerSystemWorking]));
  288. DebugTrace(TRACE_STATUS,("USPnp: DeviceState[PowerSystemSleeping1] =0x%x.\n",pCaps->DeviceState[PowerSystemSleeping1]));
  289. DebugTrace(TRACE_STATUS,("USPnp: DeviceState[PowerSystemSleeping2] =0x%x.\n",pCaps->DeviceState[PowerSystemSleeping2]));
  290. DebugTrace(TRACE_STATUS,("USPnp: DeviceState[PowerSystemSleeping3] =0x%x.\n",pCaps->DeviceState[PowerSystemSleeping3]));
  291. DebugTrace(TRACE_STATUS,("USPnp: DeviceState[PowerSystemHibernate] =0x%x.\n",pCaps->DeviceState[PowerSystemHibernate]));
  292. DebugTrace(TRACE_STATUS,("USPnp: DeviceState[PowerSystemShutdown] =0x%x.\n",pCaps->DeviceState[PowerSystemShutdown]));
  293. DebugTrace(TRACE_STATUS,("USPnp: DeviceState[PowerSystemMaximum] =0x%x.\n",pCaps->DeviceState[PowerSystemMaximum]));
  294. DebugTrace(TRACE_STATUS,("USPnp: Lower stack set DeviceWake(0x%x) SystemWake(0x%x)\n.", pCaps->DeviceWake, pCaps->SystemWake));
  295. //
  296. // Set returning status.
  297. //
  298. Status = STATUS_SUCCESS;
  299. pIrp -> IoStatus.Status = Status;
  300. pIrp -> IoStatus.Information = 0;
  301. IoCompleteRequest( pIrp, IO_NO_INCREMENT );
  302. goto USPnP_return;
  303. break;
  304. case IRP_MN_START_DEVICE:
  305. DebugTrace(TRACE_STATUS,("USPnp: IRP_MJ_START_DEVICE\n"));
  306. pde -> Stopped = FALSE;
  307. USIncrementIoCount(pDeviceObject);
  308. //
  309. // First, let the port driver start the device.
  310. //
  311. Status = USCallNextDriverSynch(pde, pIrp);
  312. if(!NT_SUCCESS(Status)){
  313. //
  314. // Lower layer failed to start device.
  315. //
  316. DebugTrace(TRACE_ERROR,("USPnp: ERROR!! Lower layer failed to start device. Status=0x%x\n", Status));
  317. break;
  318. }
  319. //
  320. // The port driver has started the device. It is time for
  321. // us to do some initialization and create symbolic links
  322. // for the device.
  323. //
  324. // Get the device descriptor and save it in our
  325. // device extension.
  326. //
  327. Status = USGetUSBDeviceDescriptor(pDeviceObject);
  328. if(!NT_SUCCESS(Status)){
  329. //
  330. // GetDescriptor failed.
  331. //
  332. DebugTrace(TRACE_ERROR,("USPnp: ERROR!! Cannot get DeviceDescriptor.\n"));
  333. DEBUG_BREAKPOINT();
  334. break;
  335. }
  336. //
  337. // Configure the device.
  338. //
  339. Status = USConfigureDevice(pDeviceObject);
  340. #if DBG
  341. //DEBUG_BREAKPOINT();
  342. if (USBSCAN_PnPTest) {
  343. Status = STATUS_UNSUCCESSFUL;
  344. }
  345. #endif
  346. if (!NT_SUCCESS(Status)) {
  347. DebugTrace(TRACE_ERROR,("USPnp: ERROR!! Can't configure the device.\n"));
  348. DEBUG_BREAKPOINT();
  349. break;
  350. }
  351. //
  352. // Create the symbolic link for this device.
  353. //
  354. Status = USCreateSymbolicLink( pde );
  355. #if DBG
  356. //DEBUG_BREAKPOINT();
  357. if (USBSCAN_PnPTest) {
  358. Status = STATUS_UNSUCCESSFUL;
  359. }
  360. #endif
  361. if (!NT_SUCCESS(Status)) {
  362. DebugTrace(TRACE_ERROR, ("USPnp: ERROR!! Can't create symbolic link.\n"));
  363. DEBUG_BREAKPOINT();
  364. break;
  365. }
  366. //
  367. // Initialize the synchronize read event. This event is used the serialze
  368. // i/o requests to the read pipe if the request size is NOT a usb packet multiple.
  369. //
  370. {
  371. ULONG i;
  372. for(i = 0; i < pde->NumberOfPipes; i++){
  373. if( (pde->PipeInfo[i].PipeType == UsbdPipeTypeBulk)
  374. && (pde->PipeInfo[i].EndpointAddress & BULKIN_FLAG) )
  375. {
  376. DebugTrace(TRACE_STATUS,("USPnp: Initializing event for Pipe[%d]\n", i));
  377. KeInitializeEvent(&pde -> ReadPipeBuffer[i].ReadSyncEvent, SynchronizationEvent, TRUE);
  378. }
  379. }
  380. }
  381. //
  382. // Get device capability.
  383. //
  384. Status = USGetDeviceCapability(pde);
  385. if(!NT_SUCCESS(Status)){
  386. DebugTrace(TRACE_ERROR, ("USPnp: ERROR!! Unable to get Capability of this device. Status=0x%x.\n", Status));
  387. break;
  388. } // if(!NT_SUCCESS(Status))
  389. //
  390. // Arm for wake if device is capable.
  391. //
  392. if(TRUE == pde->bEnabledForWakeup){
  393. PowerState.SystemState = pde -> DeviceCapabilities.SystemWake;
  394. USArmForWake(pde, PowerState);
  395. } // if(TRUE == pde->bEnabledForWakeup)
  396. //
  397. // Indicate device is now ready.
  398. //
  399. pde -> AcceptingRequests = TRUE;
  400. //
  401. // Set return status.
  402. //
  403. pIrp -> IoStatus.Status = Status;
  404. pIrp -> IoStatus.Information = 0;
  405. IoCompleteRequest( pIrp, IO_NO_INCREMENT );
  406. goto USPnP_return;
  407. case IRP_MN_REMOVE_DEVICE:
  408. DebugTrace(TRACE_STATUS,("USPnp: IRP_MN_REMOVE_DEVICE\n"));
  409. //
  410. // Prohivit further request.
  411. //
  412. bTemp = (LONG)InterlockedExchange((PULONG)&(pde -> AcceptingRequests),
  413. (LONG)FALSE );
  414. //
  415. // Wait for any io requests pending in our driver to
  416. // complete before proceeding the remove.
  417. //
  418. if (!pde -> Stopped ) {
  419. USDecrementIoCount(pDeviceObject);
  420. }
  421. //
  422. // Disarm remote wakeup.
  423. //
  424. USDisarmWake(pde);
  425. KeWaitForSingleObject(&pde -> PendingIoEvent,
  426. Suspended,
  427. KernelMode,
  428. FALSE,NULL);
  429. //
  430. // Is this device stopped/removed before?
  431. //
  432. if (bTemp) {
  433. //
  434. // Delete symbolic link.
  435. //
  436. USDestroySymbolicLink( pde );
  437. //
  438. // Abort all pipes.
  439. //
  440. USCancelPipe(pDeviceObject, NULL, ALL_PIPE, TRUE);
  441. }
  442. //
  443. // Disable device interface.
  444. //
  445. UsbScanHandleInterface(pde->pPhysicalDeviceObject,
  446. &pde->InterfaceNameString,
  447. FALSE);
  448. //
  449. // Forward remove message to lower driver.
  450. //
  451. IoCopyCurrentIrpStackLocationToNext(pIrp);
  452. Status = IoCallDriver(pde -> pStackDeviceObject, pIrp);
  453. //
  454. // Free allocated memory.
  455. //
  456. if (pde -> pDeviceDescriptor) {
  457. USFreePool(pde -> pDeviceDescriptor);
  458. pde -> pDeviceDescriptor = NULL;
  459. }
  460. if (pde -> pConfigurationDescriptor) {
  461. USFreePool(pde -> pConfigurationDescriptor);
  462. pde -> pConfigurationDescriptor = NULL;
  463. }
  464. //
  465. // Free allocated buffer(s)
  466. //
  467. {
  468. ULONG i;
  469. for(i = 0; i < pde->NumberOfPipes; i++){
  470. if(pde->ReadPipeBuffer[i].pStartBuffer){
  471. USFreePool(pde->ReadPipeBuffer[i].pStartBuffer);
  472. pde->ReadPipeBuffer[i].pStartBuffer = NULL;
  473. pde->ReadPipeBuffer[i].pBuffer = NULL;
  474. }
  475. }
  476. }
  477. //
  478. // Detatch device object from stack.
  479. //
  480. IoDetachDevice(pde -> pStackDeviceObject);
  481. //
  482. // Delete device object
  483. //
  484. IoDeleteDevice (pDeviceObject);
  485. pDeviceObject = NULL;
  486. DebugTrace(TRACE_STATUS,("USPnp: IRP_MN_REMOVE_DEVICE complete\n"));
  487. goto USPnP_return;
  488. case IRP_MN_STOP_DEVICE:
  489. DebugTrace(TRACE_STATUS,("USPnp: IRP_MN_STOP_DEVICE\n"));
  490. //
  491. // Indicate device is stopped.
  492. //
  493. pde -> Stopped = TRUE;
  494. if (pde -> AcceptingRequests) {
  495. //
  496. // Disarm remote wakeup.
  497. //
  498. USDisarmWake(pde);
  499. //
  500. // No more requests are allowed.
  501. //
  502. pde -> AcceptingRequests = FALSE;
  503. //
  504. // Delete symbolic link.
  505. //
  506. USDestroySymbolicLink( pde );
  507. //
  508. // Abort all pipes.
  509. //
  510. USCancelPipe(pDeviceObject, NULL, ALL_PIPE, TRUE);
  511. //
  512. // Set device into unconfigured state.
  513. //
  514. USUnConfigureDevice(pDeviceObject);
  515. } //(pde -> AcceptingRequests)
  516. #ifndef _CHICAGO_
  517. //
  518. // Disable device interface.
  519. //
  520. if (pde->InterfaceNameString.Buffer != NULL) {
  521. IoSetDeviceInterfaceState(&pde->InterfaceNameString,FALSE);
  522. }
  523. #endif // _CHICAGO_
  524. //
  525. // Let the port driver stop the device.
  526. //
  527. IoCopyCurrentIrpStackLocationToNext(pIrp);
  528. Status = IoCallDriver(pde -> pStackDeviceObject, pIrp);
  529. //
  530. // wait for any io requests pending in our driver to
  531. // complete before finishing the remove
  532. //
  533. USDecrementIoCount(pDeviceObject);
  534. KeWaitForSingleObject(&pde -> PendingIoEvent, Suspended, KernelMode,
  535. FALSE,NULL);
  536. ASSERT(pde -> pDeviceDescriptor);
  537. ASSERT(pde -> pConfigurationDescriptor);
  538. if (pde -> pDeviceDescriptor) {
  539. USFreePool(pde -> pDeviceDescriptor);
  540. pde -> pDeviceDescriptor = NULL;
  541. }
  542. if (pde -> pConfigurationDescriptor) {
  543. USFreePool(pde -> pConfigurationDescriptor);
  544. pde -> pConfigurationDescriptor = NULL;
  545. }
  546. //
  547. // Free allocated buffer(s)
  548. //
  549. {
  550. ULONG i;
  551. for(i = 0; i < pde->NumberOfPipes; i++){
  552. if(pde->ReadPipeBuffer[i].pBuffer){
  553. USFreePool(pde->ReadPipeBuffer[i].pBuffer);
  554. pde->ReadPipeBuffer[i].pBuffer = NULL;
  555. }
  556. }
  557. }
  558. goto USPnP_return;
  559. case IRP_MN_QUERY_INTERFACE:
  560. DebugTrace(TRACE_STATUS,("USPnp: IRP_MN_QUERY_INTERFACE\n"));
  561. break;
  562. case IRP_MN_QUERY_RESOURCES:
  563. DebugTrace(TRACE_STATUS,("USPnp: IRP_MN_QUERY_RESOURCES\n"));
  564. break;
  565. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  566. DebugTrace(TRACE_STATUS,("USPnp: IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n"));
  567. break;
  568. case IRP_MN_QUERY_DEVICE_TEXT:
  569. DebugTrace(TRACE_STATUS,("USPnp: IRP_MN_QUERY_DEVICE_TEXT\n"));
  570. break;
  571. // case IRP_MN_QUERY_LEGACY_BUS_INFORMATION:
  572. // DebugTrace(TRACE_STATUS,("USPnp: IRP_MN_QUERY_LEGACY_BUS_INFORMATION\n"));
  573. // break;
  574. case IRP_MN_QUERY_STOP_DEVICE:
  575. DebugTrace(TRACE_STATUS,("USPnp: IRP_MN_QUERY_STOP_DEVICE\n"));
  576. break;
  577. case IRP_MN_QUERY_REMOVE_DEVICE:
  578. DebugTrace(TRACE_STATUS,("USPnp: IRP_MN_QUERY_REMOVE_DEVICE\n"));
  579. break;
  580. case IRP_MN_CANCEL_STOP_DEVICE:
  581. DebugTrace(TRACE_STATUS,("USPnp: IRP_MN_CANCEL_STOP_DEVICE\n"));
  582. break;
  583. case IRP_MN_CANCEL_REMOVE_DEVICE:
  584. DebugTrace(TRACE_STATUS,("USPnp: IRP_MN_CANCEL_REMOVE_DEVICE\n"));
  585. break;
  586. case IRP_MN_QUERY_DEVICE_RELATIONS:
  587. DebugTrace(TRACE_STATUS,("USPnp: IRP_MN_QUERY_DEVICE_RELATIONS\n"));
  588. break;
  589. case IRP_MN_SURPRISE_REMOVAL:
  590. DebugTrace(TRACE_STATUS,("USPnp: IRP_MN_SURPRISE_REMOVAL\n"));
  591. //
  592. // Indicate interface is stopped
  593. //
  594. UsbScanHandleInterface(pde->pPhysicalDeviceObject,
  595. &pde->InterfaceNameString,
  596. FALSE);
  597. break;
  598. default:
  599. DebugTrace(TRACE_STATUS,("USPnp: Minor PNP message. MinorFunction = 0x%x\n",pIrpStack->MinorFunction));
  600. break;
  601. } /* case MinorFunction, MajorFunction == IRP_MJ_PNP_POWER */
  602. //
  603. // Passing down IRP
  604. //
  605. IoCopyCurrentIrpStackLocationToNext(pIrp);
  606. Status = IoCallDriver(pde -> pStackDeviceObject, pIrp);
  607. DebugTrace(TRACE_STATUS,("USPnp: Passed Pnp Irp down, status = %x\n", Status));
  608. if(!NT_SUCCESS(Status)){
  609. DebugTrace(TRACE_WARNING,("USPnp: WARNING!! IRP Status failed, status = %x\n", Status));
  610. // DEBUG_BREAKPOINT();
  611. }
  612. break; // IRP_MJ_PNP
  613. default:
  614. DebugTrace(TRACE_STATUS,("USPnp: Major PNP IOCTL not handled\n"));
  615. Status = STATUS_INVALID_PARAMETER;
  616. pIrp -> IoStatus.Status = Status;
  617. IoCompleteRequest( pIrp, IO_NO_INCREMENT );
  618. goto USPnP_return;
  619. } /* case MajorFunction */
  620. USPnP_return:
  621. DebugTrace(TRACE_PROC_LEAVE,("USPnP: Leaving.. Status = 0x%x\n", Status));
  622. return Status;
  623. } // end USPnp()
  624. NTSTATUS
  625. USCreateSymbolicLink(
  626. PUSBSCAN_DEVICE_EXTENSION pde
  627. )
  628. /*++
  629. Routine Description:
  630. This routine create the symbolic link for the device.
  631. Arguments:
  632. pde - pointer to device extension
  633. Return Value:
  634. STATUS_SUCCESS if successful,
  635. STATUS_UNSUCCESSFUL otherwise
  636. --*/
  637. {
  638. NTSTATUS Status;
  639. UNICODE_STRING uName;
  640. UNICODE_STRING uName2;
  641. ANSI_STRING ansiName;
  642. CHAR aName[32];
  643. HANDLE hSwKey;
  644. PAGED_CODE();
  645. DebugTrace(TRACE_PROC_ENTER,("USCreateSymbolicLink: Enter..\n"));
  646. //
  647. // Initialize
  648. //
  649. Status = STATUS_SUCCESS;
  650. RtlZeroMemory(&uName, sizeof(UNICODE_STRING));
  651. RtlZeroMemory(&uName2, sizeof(UNICODE_STRING));
  652. RtlZeroMemory(&ansiName, sizeof(ANSI_STRING));
  653. hSwKey = NULL;
  654. //
  655. // Create the symbolic link for this device.
  656. //
  657. sprintf(aName,"\\Device\\Usbscan%d",pde -> DeviceInstance);
  658. RtlInitAnsiString(&ansiName, aName);
  659. Status = RtlAnsiStringToUnicodeString(&uName, &ansiName, TRUE);
  660. if(STATUS_SUCCESS != Status){
  661. DebugTrace(TRACE_CRITICAL,("USCreateSymbolicLink: ERROR!! Cannot allocate buffer for Unicode srting\n"));
  662. DEBUG_BREAKPOINT();
  663. Status = STATUS_INSUFFICIENT_RESOURCES;
  664. goto USCreateSymbolicLink_return;
  665. }
  666. sprintf(aName,"\\DosDevices\\Usbscan%d",pde -> DeviceInstance);
  667. RtlInitAnsiString(&ansiName, aName);
  668. Status = RtlAnsiStringToUnicodeString(&(pde -> SymbolicLinkName), &ansiName, TRUE);
  669. if(STATUS_SUCCESS != Status){
  670. DebugTrace(TRACE_CRITICAL,("USCreateSymbolicLink: ERROR!! Cannot allocate buffer for Unicode srting\n"));
  671. DEBUG_BREAKPOINT();
  672. Status = STATUS_INSUFFICIENT_RESOURCES;
  673. goto USCreateSymbolicLink_return;
  674. }
  675. //
  676. // Create Sympolic link.
  677. //
  678. Status = IoCreateSymbolicLink( &(pde -> SymbolicLinkName), &uName );
  679. RtlFreeUnicodeString( &uName );
  680. uName.Buffer = NULL;
  681. if (STATUS_SUCCESS != Status ) {
  682. DebugTrace(TRACE_ERROR,("USCreateSymbolicLink: ERROR!! Cannot create symbolic link.\n"));
  683. DEBUG_BREAKPOINT();
  684. Status = STATUS_NOT_SUPPORTED;
  685. goto USCreateSymbolicLink_return;
  686. }
  687. //
  688. // Now, stuff the symbolic link into the CreateFileName key so that STI can find the device.
  689. //
  690. IoOpenDeviceRegistryKey( pde -> pPhysicalDeviceObject,
  691. PLUGPLAY_REGKEY_DRIVER, KEY_WRITE, &hSwKey);
  692. //
  693. // Create CreateFile name. ("\\.\UsbscanX")
  694. //
  695. RtlInitUnicodeString(&uName,USBSCAN_REG_CREATEFILE); // L"CreateFileName"
  696. sprintf(aName, "%s%d", USBSCAN_OBJECTNAME_A, pde -> DeviceInstance); // "\\\\.\\Usbscan%d"
  697. RtlInitAnsiString(&ansiName, aName);
  698. Status = RtlAnsiStringToUnicodeString(&uName2, &ansiName, TRUE);
  699. if(STATUS_SUCCESS != Status){
  700. DebugTrace(TRACE_CRITICAL,("USCreateSymbolicLink: ERROR!! Cannot allocate buffer for Unicode srting\n"));
  701. DEBUG_BREAKPOINT();
  702. Status = STATUS_INSUFFICIENT_RESOURCES;
  703. goto USCreateSymbolicLink_return;
  704. }
  705. //
  706. // Set CreateFile name to the registry.
  707. //
  708. ZwSetValueKey(hSwKey,&uName,0,REG_SZ,uName2.Buffer,uName2.Length);
  709. //
  710. // uName is not allocated. Just zero it.
  711. //
  712. RtlZeroMemory(&uName, sizeof(UNICODE_STRING));
  713. USCreateSymbolicLink_return:
  714. if(NULL != hSwKey){
  715. ZwClose(hSwKey);
  716. }
  717. if(NULL != uName.Buffer){
  718. RtlFreeUnicodeString( &uName );
  719. }
  720. if(NULL != uName2.Buffer){
  721. RtlFreeUnicodeString( &uName2 );
  722. }
  723. DebugTrace(TRACE_PROC_LEAVE,("USCreateSymbolicLink: Leaving.. Status = 0x%x\n", Status));
  724. return Status;
  725. } // end USCreateSymbolicLink()
  726. NTSTATUS
  727. USDestroySymbolicLink(
  728. PUSBSCAN_DEVICE_EXTENSION pde
  729. )
  730. /*++
  731. Routine Description:
  732. This routine removes the symbolic link for the device.
  733. Arguments:
  734. pde - pointer to device extension
  735. Return Value:
  736. STATUS_SUCCESS if successful,
  737. STATUS_UNSUCCESSFUL otherwise
  738. --*/
  739. {
  740. UNICODE_STRING uName;
  741. UNICODE_STRING uName2;
  742. UNICODE_STRING uNumber;
  743. ANSI_STRING ansiName;
  744. CHAR aName[32];
  745. HANDLE hSwKey;
  746. WCHAR wsCreateFileName[64];
  747. ULONG ulBufLength, ulRetLength;
  748. NTSTATUS Status;
  749. PVOID pvNumber;
  750. ULONG ulNumber;
  751. const WCHAR wcsObjectName[] = USBSCAN_OBJECTNAME_W; // L"\\\\.\\Usbscan"
  752. ULONG uiObjectNameLen = wcslen(wcsObjectName) * sizeof(WCHAR) ;
  753. PAGED_CODE();
  754. DebugTrace(TRACE_PROC_ENTER,("USDestroySymbolicLink: Enter..\n"));
  755. //
  756. // Delete the symbolic link to this device.
  757. //
  758. IoDeleteSymbolicLink( &(pde -> SymbolicLinkName) );
  759. //
  760. // Remove the CreateFile name from the s/w key, if it's created by this device object.
  761. //
  762. Status = IoOpenDeviceRegistryKey( pde -> pPhysicalDeviceObject,
  763. PLUGPLAY_REGKEY_DRIVER,
  764. KEY_ALL_ACCESS,
  765. &hSwKey);
  766. if(STATUS_SUCCESS != Status){
  767. DebugTrace(TRACE_ERROR,("USDestroySymbolicLink: ERROR!! IoOpenDeviceRegistryKey Failed\n"));
  768. DEBUG_BREAKPOINT();
  769. goto USDestroySymbolicLink_return;
  770. }
  771. RtlInitUnicodeString(&uName,USBSCAN_REG_CREATEFILE); // L"CreateFileName"
  772. memset(aName, 0, sizeof(aName));
  773. RtlInitAnsiString(&ansiName, aName);
  774. Status = RtlAnsiStringToUnicodeString(&uName2, &ansiName, TRUE);
  775. if(STATUS_SUCCESS != Status){
  776. DebugTrace(TRACE_CRITICAL,("USDestroySymbolicLink: ERROR!! Cannot allocate buffer for Unicode srting\n"));
  777. DEBUG_BREAKPOINT();
  778. Status = STATUS_INSUFFICIENT_RESOURCES;
  779. goto USDestroySymbolicLink_return;
  780. }
  781. //
  782. // Check if this CreateFile name is created by this device object.
  783. //
  784. //
  785. // Query CreateFile name from the registry.
  786. //
  787. ulBufLength = sizeof(wsCreateFileName);
  788. Status = ZwQueryValueKey(hSwKey,
  789. &uName,
  790. KeyValuePartialInformation,
  791. (PVOID)wsCreateFileName,
  792. ulBufLength,
  793. &ulRetLength);
  794. if(STATUS_SUCCESS != Status){
  795. DebugTrace(TRACE_ERROR,("USDestroySymbolicLink: ERROR!! Cannot query registry.\n"));
  796. RtlFreeUnicodeString( &uName2 );
  797. uName2.Buffer = NULL;
  798. goto USDestroySymbolicLink_return;
  799. }
  800. if (NULL != wsCreateFileName){
  801. DebugTrace(TRACE_STATUS,("USDestroySymbolicLink: CreateFileName=%ws, DeviceInstance=%d.\n",
  802. ((PKEY_VALUE_PARTIAL_INFORMATION)wsCreateFileName)->Data,
  803. pde -> DeviceInstance));
  804. //
  805. // Get instance number of CreteFile name.
  806. //
  807. pvNumber = wcsstr((const wchar_t *)((PKEY_VALUE_PARTIAL_INFORMATION)wsCreateFileName)->Data, wcsObjectName);
  808. if(NULL != pvNumber){
  809. //
  810. // Move pointer forward. (sizeof(L"\\\\.\\Usbscan") == 22)
  811. //
  812. // if( ((PKEY_VALUE_PARTIAL_INFORMATION)wsCreateFileName)->DataLength > sizeof(wcsObjectName) ){
  813. // (PCHAR)pvNumber += sizeof(wcsObjectName);
  814. if( ((PKEY_VALUE_PARTIAL_INFORMATION)wsCreateFileName)->DataLength > uiObjectNameLen ){
  815. (PCHAR)pvNumber += uiObjectNameLen;
  816. } else {
  817. DebugTrace(TRACE_ERROR,("USDestroySymbolicLink: ERROR!! CreateFile name too short.\n"));
  818. RtlFreeUnicodeString( &uName2 );
  819. uName2.Buffer = NULL;
  820. ZwClose(hSwKey);
  821. goto USDestroySymbolicLink_return;
  822. }
  823. //
  824. // Translate X of UsbscanX to integer.
  825. //
  826. RtlInitUnicodeString(&uNumber, pvNumber);
  827. Status = RtlUnicodeStringToInteger(&uNumber,
  828. 10,
  829. &ulNumber);
  830. if(STATUS_SUCCESS != Status){
  831. DebugTrace(TRACE_ERROR,("USDestroySymbolicLink: ERROR!! RtlUnicodeStringToInteger failed.\n"));
  832. RtlFreeUnicodeString( &uName2 );
  833. uName2.Buffer = NULL;
  834. ZwClose(hSwKey);
  835. goto USDestroySymbolicLink_return;
  836. }
  837. //
  838. // See if this CreateFile name is made by this instance.
  839. //
  840. if(ulNumber == pde -> DeviceInstance){
  841. //
  842. // Delete CreateFile name in the registry.
  843. //
  844. DebugTrace(TRACE_STATUS,("USDestroySymbolicLink: Deleting %ws%d\n",
  845. wcsObjectName,
  846. ulNumber));
  847. ZwSetValueKey(hSwKey,&uName,0,REG_SZ,uName2.Buffer,uName2.Length);
  848. } else {
  849. //
  850. // CreateFile name is created by other instance.
  851. //
  852. DebugTrace(TRACE_STATUS,("USDestroySymbolicLink: CreateFile name is created by other instance.\n"));
  853. }
  854. } else { // (NULL != pvNumber)
  855. //
  856. // "Usbscan" was not found in CreateFile name.
  857. //
  858. DebugTrace(TRACE_WARNING,("USDestroySymbolicLink: WARNING!! Didn't find \"Usbscan\" in CreateFileName\n"));
  859. }
  860. } else { // (NULL != wsCreateFileName)
  861. //
  862. // Query CreateFile name returned NULL.
  863. //
  864. DebugTrace(TRACE_WARNING,("USDestroySymbolicLink: WARNING!! CreateFileName=NULL\n"));
  865. }
  866. //
  867. // Free allocated memory.
  868. //
  869. RtlFreeUnicodeString( &uName2 );
  870. //
  871. // Close registry.
  872. //
  873. ZwClose(hSwKey);
  874. USDestroySymbolicLink_return:
  875. //
  876. // Free allocated string buffer in DeviceObject.
  877. //
  878. RtlFreeUnicodeString( &(pde -> SymbolicLinkName) );
  879. DebugTrace(TRACE_PROC_LEAVE,("USDestroySymbolicLink: Leaving.. Status = 0x%x\n",Status));
  880. return Status;
  881. } // end USDestroySymbolicLink()
  882. NTSTATUS
  883. USGetUSBDeviceDescriptor(
  884. IN PDEVICE_OBJECT pDeviceObject
  885. )
  886. /*++
  887. Routine Description:
  888. Retrieves the USB device descriptor and stores it in the device
  889. extension. This descriptor contains product info and
  890. endpoint 0 (default pipe) info.
  891. Arguments:
  892. pDeviceObject - pointer to device object
  893. Return Value:
  894. STATUS_SUCCESS if successful,
  895. STATUS_UNSUCCESSFUL otherwise
  896. --*/
  897. {
  898. PUSBSCAN_DEVICE_EXTENSION pde;
  899. NTSTATUS Status;
  900. PUSB_DEVICE_DESCRIPTOR pDeviceDescriptor;
  901. PURB pUrb;
  902. ULONG siz;
  903. PAGED_CODE();
  904. DebugTrace(TRACE_PROC_ENTER,("USGetUSBDeviceDescriptor: Enter..\n"));
  905. pde = pDeviceObject->DeviceExtension;
  906. //
  907. // Allocate pool for URB.
  908. //
  909. pUrb = USAllocatePool(NonPagedPool,
  910. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
  911. if (NULL == pUrb) {
  912. DebugTrace(TRACE_CRITICAL,("USGetUSBDeviceDescriptor: ERROR!! cannot allocated URB\n"));
  913. DEBUG_BREAKPOINT();
  914. Status = STATUS_INSUFFICIENT_RESOURCES;
  915. goto USGetUSBDeviceDescriptor_return;
  916. }
  917. //
  918. // Allocate pool for Descriptor.
  919. //
  920. siz = sizeof(USB_DEVICE_DESCRIPTOR);
  921. pDeviceDescriptor = USAllocatePool(NonPagedPool, siz);
  922. if (NULL == pDeviceDescriptor) {
  923. DebugTrace(TRACE_CRITICAL,("USGetUSBDeviceDescriptor: ERROR!! cannot allocated device descriptor\n"));
  924. DEBUG_BREAKPOINT();
  925. USFreePool(pUrb);
  926. pUrb = NULL;
  927. Status = STATUS_INSUFFICIENT_RESOURCES;
  928. goto USGetUSBDeviceDescriptor_return;
  929. }
  930. //
  931. // Do Macro to set parameter for GetDescriptor to URB.
  932. //
  933. UsbBuildGetDescriptorRequest(pUrb,
  934. (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  935. USB_DEVICE_DESCRIPTOR_TYPE,
  936. 0,
  937. 0,
  938. pDeviceDescriptor,
  939. NULL,
  940. siz,
  941. NULL);
  942. //
  943. // Call down.
  944. //
  945. Status = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  946. #if DBG
  947. //DEBUG_BREAKPOINT();
  948. if (USBSCAN_PnPTest) {
  949. Status = STATUS_UNSUCCESSFUL;
  950. }
  951. #endif
  952. if (STATUS_SUCCESS == Status) {
  953. //
  954. // Show device descriptor.
  955. //
  956. DebugTrace(TRACE_DEVICE_DATA,("USGetUSBDeviceDescriptor: Device Descriptor = %x, len %x\n",
  957. pDeviceDescriptor,
  958. pUrb->UrbControlDescriptorRequest.TransferBufferLength));
  959. DebugTrace(TRACE_DEVICE_DATA,("USGetUSBDeviceDescriptor: USBSCAN Device Descriptor:\n"));
  960. DebugTrace(TRACE_DEVICE_DATA,("USGetUSBDeviceDescriptor: -------------------------\n"));
  961. DebugTrace(TRACE_DEVICE_DATA,("USGetUSBDeviceDescriptor: bLength %d\n", pDeviceDescriptor -> bLength));
  962. DebugTrace(TRACE_DEVICE_DATA,("USGetUSBDeviceDescriptor: bDescriptorType 0x%x\n", pDeviceDescriptor -> bDescriptorType));
  963. DebugTrace(TRACE_DEVICE_DATA,("USGetUSBDeviceDescriptor: bcdUSB 0x%x\n", pDeviceDescriptor -> bcdUSB));
  964. DebugTrace(TRACE_DEVICE_DATA,("USGetUSBDeviceDescriptor: bDeviceClass 0x%x\n", pDeviceDescriptor -> bDeviceClass));
  965. DebugTrace(TRACE_DEVICE_DATA,("USGetUSBDeviceDescriptor: bDeviceSubClass 0x%x\n", pDeviceDescriptor -> bDeviceSubClass));
  966. DebugTrace(TRACE_DEVICE_DATA,("USGetUSBDeviceDescriptor: bDeviceProtocol 0x%x\n", pDeviceDescriptor -> bDeviceProtocol));
  967. DebugTrace(TRACE_DEVICE_DATA,("USGetUSBDeviceDescriptor: bMaxPacketSize0 0x%x\n", pDeviceDescriptor -> bMaxPacketSize0));
  968. DebugTrace(TRACE_DEVICE_DATA,("USGetUSBDeviceDescriptor: idVendor 0x%x\n", pDeviceDescriptor -> idVendor));
  969. DebugTrace(TRACE_DEVICE_DATA,("USGetUSBDeviceDescriptor: idProduct 0x%x\n", pDeviceDescriptor -> idProduct));
  970. DebugTrace(TRACE_DEVICE_DATA,("USGetUSBDeviceDescriptor: bcdDevice 0x%x\n", pDeviceDescriptor -> bcdDevice));
  971. DebugTrace(TRACE_DEVICE_DATA,("USGetUSBDeviceDescriptor: iManufacturer 0x%x\n", pDeviceDescriptor -> iManufacturer));
  972. DebugTrace(TRACE_DEVICE_DATA,("USGetUSBDeviceDescriptor: iProduct 0x%x\n", pDeviceDescriptor -> iProduct));
  973. DebugTrace(TRACE_DEVICE_DATA,("USGetUSBDeviceDescriptor: iSerialNumber 0x%x\n", pDeviceDescriptor -> iSerialNumber));
  974. DebugTrace(TRACE_DEVICE_DATA,("USGetUSBDeviceDescriptor: bNumConfigurations 0x%x\n", pDeviceDescriptor -> bNumConfigurations));
  975. //
  976. // Save pointer to device descriptor in our device extension
  977. //
  978. pde -> pDeviceDescriptor = pDeviceDescriptor;
  979. } else { // (STATUS_SUCCESS == Status)
  980. //
  981. // Error returned from lower driver.
  982. //
  983. DebugTrace(TRACE_ERROR,("USGetUSBDeviceDescriptor: ERROR!! Cannot get device descriptor. (%x)\n", Status));
  984. USFreePool(pDeviceDescriptor);
  985. pDeviceDescriptor = NULL;
  986. } // (STATUS_SUCCESS == Status)
  987. USFreePool(pUrb);
  988. pUrb = NULL;
  989. USGetUSBDeviceDescriptor_return:
  990. DebugTrace(TRACE_PROC_LEAVE,("USGetUSBDeviceDescriptor: Leaving.. Status = 0x%x\n", Status));
  991. return Status;
  992. } // end USGetUSBDeviceDescriptor()
  993. NTSTATUS
  994. USDeferIrpCompletion(
  995. IN PDEVICE_OBJECT pDeviceObject,
  996. IN PIRP pIrp,
  997. IN PVOID Context
  998. )
  999. /*++
  1000. Routine Description:
  1001. This routine is called when the port driver completes an IRP.
  1002. Arguments:
  1003. pDeviceObject - Pointer to the device object for the class device.
  1004. pIrp - Irp completed.
  1005. Context - Driver defined context.
  1006. Return Value:
  1007. The function value is the final status from the operation.
  1008. --*/
  1009. {
  1010. PKEVENT pEvent = Context;
  1011. DebugTrace(TRACE_PROC_ENTER,("USDeferIrpCompletion: Enter..\n"));
  1012. KeSetEvent(pEvent, 1, FALSE);
  1013. DebugTrace(TRACE_PROC_LEAVE,("USDeferIrpCompletion: Leaving.. Status = STATUS_MORE_PROCESSING_REQUIRED\n"));
  1014. return STATUS_MORE_PROCESSING_REQUIRED;
  1015. } // end USDeferIrpCompletion()
  1016. VOID
  1017. USIncrementIoCount(
  1018. IN PDEVICE_OBJECT pDeviceObject
  1019. )
  1020. /*++
  1021. Routine Description:
  1022. Arguments:
  1023. Return Value:
  1024. --*/
  1025. {
  1026. PUSBSCAN_DEVICE_EXTENSION pde;
  1027. DebugTrace(TRACE_PROC_ENTER,("USIncrementIoCount: Enter..\n"));
  1028. pde = (PUSBSCAN_DEVICE_EXTENSION)(pDeviceObject -> DeviceExtension);
  1029. ASSERT((LONG)pde -> PendingIoCount >= 0);
  1030. InterlockedIncrement(&pde -> PendingIoCount);
  1031. DebugTrace(TRACE_PROC_LEAVE,("USIncrementIoCount: Leaving.. IoCount=0x%x, Status=VOID\n", pde -> PendingIoCount));
  1032. } // end USIncrementIoCount()
  1033. LONG
  1034. USDecrementIoCount(
  1035. IN PDEVICE_OBJECT pDeviceObject
  1036. )
  1037. /*++
  1038. Routine Description:
  1039. Arguments:
  1040. Return Value:
  1041. --*/
  1042. {
  1043. PUSBSCAN_DEVICE_EXTENSION pde;
  1044. LONG ioCount;
  1045. DebugTrace(TRACE_PROC_ENTER,("USDecrementIoCount: Enter..\n"));
  1046. pde = (PUSBSCAN_DEVICE_EXTENSION)(pDeviceObject -> DeviceExtension);
  1047. ASSERT(pde ->PendingIoCount >= 1);
  1048. ioCount = InterlockedDecrement(&pde -> PendingIoCount);
  1049. if (0 == ioCount) {
  1050. KeSetEvent(&pde -> PendingIoEvent,
  1051. 1,
  1052. FALSE);
  1053. }
  1054. DebugTrace(TRACE_PROC_LEAVE,("USDecrementIoCount: Leaving.. IoCount(=Ret)=0x%x\n", ioCount));
  1055. return ioCount;
  1056. } // end USDecrementIoCount()
  1057. NTSTATUS
  1058. USBSCAN_CallUSBD(
  1059. IN PDEVICE_OBJECT pDeviceObject,
  1060. IN PURB pUrb
  1061. )
  1062. /*++
  1063. Routine Description:
  1064. Passes a URB to the USBD class driver
  1065. Arguments:
  1066. pDeviceObject - pointer to the device object
  1067. pUrb - pointer to Urb request block
  1068. Return Value:
  1069. STATUS_SUCCESS if successful,
  1070. STATUS_UNSUCCESSFUL otherwise
  1071. --*/
  1072. {
  1073. NTSTATUS Status;
  1074. PUSBSCAN_DEVICE_EXTENSION pde;
  1075. PIRP pIrp;
  1076. KEVENT eventTimeout;
  1077. IO_STATUS_BLOCK ioStatus;
  1078. PIO_STACK_LOCATION pNextStack;
  1079. LARGE_INTEGER Timeout;
  1080. KEVENT eventSync;
  1081. DebugTrace(TRACE_PROC_ENTER,("USBSCAN_CallUSBD: Enter..\n"));
  1082. pde = pDeviceObject -> DeviceExtension;
  1083. //
  1084. // issue a synchronous request
  1085. //
  1086. KeInitializeEvent(&eventTimeout, NotificationEvent, FALSE);
  1087. KeInitializeEvent(&eventSync, SynchronizationEvent, FALSE);
  1088. pIrp = IoBuildDeviceIoControlRequest(
  1089. IOCTL_INTERNAL_USB_SUBMIT_URB,
  1090. pde -> pStackDeviceObject,
  1091. NULL,
  1092. 0,
  1093. NULL,
  1094. 0,
  1095. TRUE, /* INTERNAL */
  1096. &eventTimeout,
  1097. &ioStatus);
  1098. if(NULL == pIrp){
  1099. DebugTrace(TRACE_CRITICAL,("USBSCAN_CallUSBD: ERROR!! cannot allocated IRP\n"));
  1100. Status = STATUS_INSUFFICIENT_RESOURCES;
  1101. goto USBSCAN_CallUSBD_return;
  1102. }
  1103. //
  1104. // Call the class driver to perform the operation. If the returned status
  1105. // is PENDING, wait for the request to complete.
  1106. //
  1107. pNextStack = IoGetNextIrpStackLocation(pIrp);
  1108. ASSERT(pNextStack != NULL);
  1109. //
  1110. // pass the URB to the USB driver stack
  1111. //
  1112. pNextStack -> Parameters.Others.Argument1 = pUrb;
  1113. //
  1114. // Set completion routine
  1115. //
  1116. IoSetCompletionRoutine(pIrp,
  1117. USDeferIrpCompletion,
  1118. &eventSync,
  1119. TRUE,
  1120. TRUE,
  1121. TRUE);
  1122. DebugTrace(TRACE_STATUS,("USBSCAN_CallUSBD: calling USBD\n"));
  1123. Status = IoCallDriver(pde -> pStackDeviceObject, pIrp);
  1124. DebugTrace(TRACE_STATUS,("USBSCAN_CallUSBD: return from IoCallDriver USBD %x\n", Status));
  1125. if (Status == STATUS_PENDING) {
  1126. DebugTrace(TRACE_STATUS,("USBSCAN_CallUSBD: Wait for single object\n"));
  1127. //
  1128. // Set timeout in case bad device not responding.
  1129. //
  1130. Timeout = RtlConvertLongToLargeInteger(-10*1000*1000*(USBSCAN_TIMEOUT_OTHER));
  1131. Status = KeWaitForSingleObject(
  1132. &eventSync,
  1133. Suspended,
  1134. KernelMode,
  1135. FALSE,
  1136. &Timeout);
  1137. if(STATUS_TIMEOUT == Status){
  1138. NTSTATUS LocalStatus;
  1139. DebugTrace(TRACE_ERROR,("USBSCAN_CallUSBD: ERROR!! call timeout. Now canceling IRP...\n"));
  1140. //
  1141. // Cancel IRP.
  1142. //
  1143. IoCancelIrp(pIrp);
  1144. //
  1145. // Make sure the IRP gets completed.
  1146. //
  1147. LocalStatus = KeWaitForSingleObject(&eventSync,
  1148. Suspended,
  1149. KernelMode,
  1150. FALSE,
  1151. NULL);
  1152. DebugTrace(TRACE_STATUS,("USBSCAN_CallUSBD: Canceled status = 0x%x.\n", LocalStatus));
  1153. } else {
  1154. DebugTrace(TRACE_STATUS,("USBSCAN_CallUSBD: Wait for single object, returned 0x%x\n", Status));
  1155. }
  1156. } // if (Status == STATUS_PENDING)
  1157. //
  1158. // Free the IRP.
  1159. //
  1160. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  1161. USBSCAN_CallUSBD_return:
  1162. DebugTrace(TRACE_PROC_LEAVE, ("USBSCAN_CallUSBD: Leaving.. URB Status = 0x%x, Status = 0x%x\n",
  1163. pUrb -> UrbHeader.Status,
  1164. Status));
  1165. return Status;
  1166. } // end USBSCAN_CallUSBD()
  1167. NTSTATUS
  1168. USConfigureDevice(
  1169. IN PDEVICE_OBJECT pDeviceObject
  1170. )
  1171. /*++
  1172. Routine Description:
  1173. Initializes a given instance of the device on the USB and selects the
  1174. configuration.
  1175. Arguments:
  1176. pDeviceObject - pointer to the device object
  1177. Return Value:
  1178. STATUS_SUCCESS if successful,
  1179. STATUS_UNSUCCESSFUL otherwise
  1180. --*/
  1181. {
  1182. NTSTATUS Status;
  1183. PUSBSCAN_DEVICE_EXTENSION pde;
  1184. PURB pUrb;
  1185. ULONG siz;
  1186. PUSB_CONFIGURATION_DESCRIPTOR pConfigurationDescriptor;
  1187. PUSB_INTERFACE_DESCRIPTOR pInterfaceDescriptor;
  1188. PUSB_ENDPOINT_DESCRIPTOR pEndpointDescriptor;
  1189. PUSB_COMMON_DESCRIPTOR pCommonDescriptor;
  1190. PUSBD_INTERFACE_INFORMATION pInterface;
  1191. UCHAR AlternateSetting;
  1192. UCHAR InterfaceNumber;
  1193. USHORT length;
  1194. ULONG i;
  1195. PAGED_CODE();
  1196. DebugTrace(TRACE_PROC_ENTER,("USConfigureDevice: Enter..\n"));
  1197. //
  1198. // Initialize local variable.
  1199. //
  1200. pConfigurationDescriptor = NULL;
  1201. pInterfaceDescriptor = NULL;
  1202. pEndpointDescriptor = NULL;
  1203. pCommonDescriptor = NULL;
  1204. pInterface = NULL;
  1205. pUrb = NULL;
  1206. siz = 0;
  1207. AlternateSetting = 0;
  1208. InterfaceNumber = 0;
  1209. length = 0;
  1210. pde = pDeviceObject -> DeviceExtension;
  1211. Status = STATUS_UNSUCCESSFUL;
  1212. //
  1213. // First configure the device
  1214. //
  1215. pUrb = USAllocatePool(NonPagedPool,
  1216. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
  1217. if (NULL == pUrb) {
  1218. DebugTrace(TRACE_CRITICAL,("USConfigureDevice: ERROR!! Can't allocate control descriptor URB.\n"));
  1219. DEBUG_BREAKPOINT();
  1220. Status = STATUS_INSUFFICIENT_RESOURCES;
  1221. goto USConfigureDevice_return;
  1222. }
  1223. siz = sizeof(USB_CONFIGURATION_DESCRIPTOR);
  1224. get_config_descriptor_retry:
  1225. pConfigurationDescriptor = USAllocatePool(NonPagedPool, siz);
  1226. if (NULL == pConfigurationDescriptor) {
  1227. DebugTrace(TRACE_CRITICAL,("USConfigureDevice: ERROR!! Can't allocate configuration descriptor.\n"));
  1228. DEBUG_BREAKPOINT();
  1229. USFreePool(pUrb);
  1230. pUrb = NULL;
  1231. Status = STATUS_INSUFFICIENT_RESOURCES;
  1232. goto USConfigureDevice_return;
  1233. }
  1234. //
  1235. // Initialize buffers by 0
  1236. //
  1237. RtlZeroMemory(pConfigurationDescriptor, siz);
  1238. RtlZeroMemory(pUrb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
  1239. UsbBuildGetDescriptorRequest(pUrb,
  1240. (USHORT)sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  1241. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  1242. 0,
  1243. 0,
  1244. pConfigurationDescriptor,
  1245. NULL,
  1246. siz,
  1247. NULL);
  1248. Status = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  1249. DebugTrace(TRACE_STATUS,("USConfigureDevice: URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE Status = %x\n", Status));
  1250. DebugTrace(TRACE_STATUS,("USConfigureDevice: Configuration Descriptor = %x, len = %x\n",
  1251. pConfigurationDescriptor,
  1252. pUrb -> UrbControlDescriptorRequest.TransferBufferLength));
  1253. //
  1254. // if we got some data see if it was enough.
  1255. //
  1256. // NOTE: we may get an error in URB because of buffer overrun
  1257. //
  1258. if ( (pUrb -> UrbControlDescriptorRequest.TransferBufferLength > 0) &&
  1259. (pConfigurationDescriptor -> wTotalLength > siz)) {
  1260. DebugTrace(TRACE_WARNING,("USConfigureDevice: WARNING!! Data is incomplete. Fetch descriptor again...\n"));
  1261. siz = pConfigurationDescriptor -> wTotalLength;
  1262. USFreePool(pConfigurationDescriptor);
  1263. pConfigurationDescriptor = NULL;
  1264. goto get_config_descriptor_retry;
  1265. }
  1266. USFreePool(pUrb);
  1267. pUrb = NULL;
  1268. //
  1269. // We have the configuration descriptor for the configuration
  1270. // we want. Save it in our device extension.
  1271. //
  1272. pde -> pConfigurationDescriptor = pConfigurationDescriptor;
  1273. //
  1274. // Now we issue the select configuration command to get
  1275. // the pipes associated with this configuration.
  1276. //
  1277. pUrb = USCreateConfigurationRequest(pConfigurationDescriptor, &length);
  1278. if (NULL == pUrb) {
  1279. DebugTrace(TRACE_CRITICAL,("USConfigureDevice: ERROR!! Can't allocate select configuration urb.\n"));
  1280. DEBUG_BREAKPOINT();
  1281. Status = STATUS_INSUFFICIENT_RESOURCES;
  1282. goto USConfigureDevice_return;
  1283. }
  1284. //
  1285. // Get the Interface descriptors.
  1286. //
  1287. pInterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(pConfigurationDescriptor,
  1288. pConfigurationDescriptor,
  1289. -1,
  1290. 0,
  1291. -1,
  1292. -1,
  1293. -1);
  1294. if(NULL == pInterfaceDescriptor){
  1295. DebugTrace(TRACE_CRITICAL,("USConfigureDevice: ERROR!! Can't get Interface descriptor.\n"));
  1296. USFreePool(pUrb);
  1297. pUrb = NULL;
  1298. Status = STATUS_UNSUCCESSFUL;
  1299. goto USConfigureDevice_return;
  1300. }
  1301. //
  1302. // Get the Endpoint descriptors.
  1303. //
  1304. pCommonDescriptor = USBD_ParseDescriptors(pConfigurationDescriptor,
  1305. pConfigurationDescriptor->wTotalLength,
  1306. pInterfaceDescriptor,
  1307. USB_ENDPOINT_DESCRIPTOR_TYPE);
  1308. if(NULL == pCommonDescriptor){
  1309. DebugTrace(TRACE_CRITICAL,("USConfigureDevice: ERROR!! Can't get Endpoint descriptor.\n"));
  1310. Status = STATUS_UNSUCCESSFUL;
  1311. goto USConfigureDevice_return;
  1312. }
  1313. ASSERT(USB_ENDPOINT_DESCRIPTOR_TYPE == pCommonDescriptor->bDescriptorType);
  1314. pEndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)pCommonDescriptor;
  1315. //
  1316. // save these pointers is our device extension.
  1317. //
  1318. pde -> pInterfaceDescriptor = pInterfaceDescriptor;
  1319. pde -> pEndpointDescriptor = pEndpointDescriptor;
  1320. //
  1321. // Set the max transfer size for each BULK endpoint to 64K.
  1322. // Also, search through the set of endpoints and find the pipe index for our
  1323. // bulk-in, interrupt, and optionally bulk-out pipes.
  1324. //
  1325. pde -> IndexBulkIn = -1;
  1326. pde -> IndexBulkOut = -1;
  1327. pde -> IndexInterrupt = -1;
  1328. pInterface = &(pUrb -> UrbSelectConfiguration.Interface);
  1329. for (i=0; i < pInterfaceDescriptor -> bNumEndpoints; i++) {
  1330. DebugTrace(TRACE_DEVICE_DATA,("USConfigureDevice: End point[%d] descriptor\n", i));
  1331. DebugTrace(TRACE_DEVICE_DATA,("USConfigureDevice: bLength : 0x%X\n", pEndpointDescriptor[i].bLength));
  1332. DebugTrace(TRACE_DEVICE_DATA,("USConfigureDevice: bDescriptorType : 0x%X\n", pEndpointDescriptor[i].bDescriptorType));
  1333. DebugTrace(TRACE_DEVICE_DATA,("USConfigureDevice: bEndpointAddress : 0x%X\n", pEndpointDescriptor[i].bEndpointAddress));
  1334. DebugTrace(TRACE_DEVICE_DATA,("USConfigureDevice: bmAttributes : 0x%X\n", pEndpointDescriptor[i].bmAttributes));
  1335. DebugTrace(TRACE_DEVICE_DATA,("USConfigureDevice: wMaxPacketSize : 0x%X\n", pEndpointDescriptor[i].wMaxPacketSize));
  1336. DebugTrace(TRACE_DEVICE_DATA,("USConfigureDevice: bInterval : 0x%X\n", pEndpointDescriptor[i].bInterval));
  1337. DebugTrace(TRACE_DEVICE_DATA,("USConfigureDevice: \n"));
  1338. if (USB_ENDPOINT_TYPE_BULK == pEndpointDescriptor[i].bmAttributes) {
  1339. pInterface -> Pipes[i].MaximumTransferSize = 64*1024;
  1340. if (pEndpointDescriptor[i].bEndpointAddress & BULKIN_FLAG) { // if input endpoint
  1341. pde -> IndexBulkIn = i;
  1342. } else {
  1343. pde -> IndexBulkOut = i;
  1344. }
  1345. } else if (USB_ENDPOINT_TYPE_INTERRUPT == pEndpointDescriptor[i].bmAttributes) {
  1346. pde -> IndexInterrupt = i;
  1347. }
  1348. }
  1349. //
  1350. // Select the default configuration.
  1351. //
  1352. UsbBuildSelectConfigurationRequest(pUrb, length, pConfigurationDescriptor);
  1353. Status = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  1354. if (STATUS_SUCCESS != Status) {
  1355. DebugTrace(TRACE_ERROR,("USConfigureDevice: ERROR!! Selecting default configuration. Status = %x\n", Status));
  1356. USFreePool(pUrb);
  1357. pUrb = NULL;
  1358. Status = STATUS_IO_DEVICE_ERROR;
  1359. goto USConfigureDevice_return;
  1360. }
  1361. //
  1362. // Save the configuration handle in our device extension.
  1363. //
  1364. pde -> ConfigurationHandle = pUrb -> UrbSelectConfiguration.ConfigurationHandle;
  1365. //
  1366. // Insure that this device won't overflow our PipeInfo structure.
  1367. //
  1368. if (pInterfaceDescriptor -> bNumEndpoints > MAX_NUM_PIPES) {
  1369. DebugTrace(TRACE_ERROR,("USConfigureDevice: ERROR!! Too many endpoints for this driver! # endpoints = %d\n",
  1370. pInterfaceDescriptor -> bNumEndpoints));
  1371. // DEBUG_BREAKPOINT();
  1372. USFreePool(pUrb);
  1373. pUrb = NULL;
  1374. Status = STATUS_INSUFFICIENT_RESOURCES;
  1375. goto USConfigureDevice_return;
  1376. }
  1377. //
  1378. // Save pipe configurations in our device extension
  1379. //
  1380. pde -> NumberOfPipes = pInterfaceDescriptor -> bNumEndpoints;
  1381. for (i=0; i < pInterfaceDescriptor -> bNumEndpoints; i++) {
  1382. pde -> PipeInfo[i] = pInterface -> Pipes[i];
  1383. DebugTrace(TRACE_DEVICE_DATA,("USConfigureDevice: Pipe[%d] information\n", i));
  1384. DebugTrace(TRACE_DEVICE_DATA,("USConfigureDevice: MaximumPacketSize : 0x%X\n", pde -> PipeInfo[i].MaximumPacketSize));
  1385. DebugTrace(TRACE_DEVICE_DATA,("USConfigureDevice: EndpointAddress : 0x%X\n", pde -> PipeInfo[i].EndpointAddress));
  1386. DebugTrace(TRACE_DEVICE_DATA,("USConfigureDevice: Interval : 0x%X\n", pde -> PipeInfo[i].Interval));
  1387. DebugTrace(TRACE_DEVICE_DATA,("USConfigureDevice: PipeType : 0x%X\n", pde -> PipeInfo[i].PipeType));
  1388. DebugTrace(TRACE_DEVICE_DATA,("USConfigureDevice: PipeHandle : 0x%X\n", pde -> PipeInfo[i].PipeHandle));
  1389. //
  1390. // Initialize the read pipe buffer if type is Bulk-In.
  1391. //
  1392. if( (pde->PipeInfo[i].PipeType == UsbdPipeTypeBulk)
  1393. && (pde->PipeInfo[i].EndpointAddress & BULKIN_FLAG) )
  1394. {
  1395. DebugTrace(TRACE_STATUS,("USConfigureDevice: Alocates buffer for Pipe[%d]\n", i));
  1396. pde -> ReadPipeBuffer[i].RemainingData = 0;
  1397. pde -> ReadPipeBuffer[i].pBuffer = USAllocatePool(NonPagedPool, 2 * (pde -> PipeInfo[i].MaximumPacketSize));
  1398. if (NULL == pde -> ReadPipeBuffer[i].pBuffer) {
  1399. DebugTrace(TRACE_CRITICAL,("USConfigureDevice: Cannot allocate bulk-in buffer.\n"));
  1400. DEBUG_BREAKPOINT();
  1401. Status = STATUS_INSUFFICIENT_RESOURCES;
  1402. USFreePool(pUrb);
  1403. pUrb = NULL;
  1404. goto USConfigureDevice_return;
  1405. }
  1406. pde -> ReadPipeBuffer[i].pStartBuffer = pde -> ReadPipeBuffer[i].pBuffer;
  1407. } else {
  1408. pde -> ReadPipeBuffer[i].pBuffer = NULL;
  1409. }
  1410. }
  1411. USFreePool(pUrb);
  1412. pUrb = NULL;
  1413. USConfigureDevice_return:
  1414. DebugTrace(TRACE_PROC_LEAVE,("USConfigureDevice: Leaving.. Status = %x\n", Status));
  1415. return Status;
  1416. } // USConfigureDevice()
  1417. NTSTATUS
  1418. USUnConfigureDevice(
  1419. IN PDEVICE_OBJECT pDeviceObject
  1420. )
  1421. /*++
  1422. Routine Description:
  1423. Arguments:
  1424. pDeviceObject - pointer to the device object
  1425. Return Value:
  1426. STATUS_SUCCESS if successful,
  1427. STATUS_UNSUCCESSFUL otherwise
  1428. --*/
  1429. {
  1430. NTSTATUS Status;
  1431. PURB pUrb;
  1432. ULONG siz;
  1433. PAGED_CODE();
  1434. DebugTrace(TRACE_PROC_ENTER,("USUnConfigureDevice: Enter..\n"));
  1435. siz = sizeof(struct _URB_SELECT_CONFIGURATION);
  1436. pUrb = USAllocatePool(NonPagedPool, siz);
  1437. if (NULL == pUrb) {
  1438. DebugTrace(TRACE_CRITICAL,("USUnConfigureDevice: ERROR!! cannot allocated URB\n"));
  1439. DEBUG_BREAKPOINT();
  1440. Status = STATUS_INSUFFICIENT_RESOURCES;
  1441. goto USUnConfigureDevice_return;
  1442. }
  1443. RtlZeroMemory(pUrb, siz);
  1444. //
  1445. // Send the select configuration urb with a NULL pointer for the configuration
  1446. // handle, this closes the configuration and puts the device in the 'unconfigured'
  1447. // state.
  1448. //
  1449. UsbBuildSelectConfigurationRequest(pUrb, (USHORT)siz, NULL);
  1450. Status = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  1451. DebugTrace(TRACE_STATUS,("USUnConfigureDevice: Device Configuration Closed status = %x usb status = %x.\n",
  1452. Status, pUrb->UrbHeader.Status));
  1453. USFreePool(pUrb);
  1454. pUrb = NULL;
  1455. USUnConfigureDevice_return:
  1456. DebugTrace(TRACE_PROC_LEAVE,("USUnConfigureDevice: Leaving.. Status = %x\n", Status));
  1457. return Status;
  1458. } // USUnConfigureDevice()
  1459. NTSTATUS
  1460. USGetDeviceCapability(
  1461. IN PUSBSCAN_DEVICE_EXTENSION pde
  1462. )
  1463. /*++
  1464. Routine Description:
  1465. Arguments:
  1466. pDeviceObject - pointer to the device object
  1467. Return Value:
  1468. STATUS_SUCCESS if successful,
  1469. STATUS_UNSUCCESSFUL otherwise
  1470. --*/
  1471. {
  1472. NTSTATUS Status;
  1473. PIRP pIrp;
  1474. PIO_STACK_LOCATION pIrpStack;
  1475. KEVENT Event;
  1476. PAGED_CODE();
  1477. DebugTrace(TRACE_PROC_ENTER,("USGetDeviceCapability: Enter..\n"));
  1478. //
  1479. // Initialize local.
  1480. //
  1481. Status = STATUS_SUCCESS;
  1482. pIrp = NULL;
  1483. pIrpStack = NULL;
  1484. //
  1485. // Allocate Irp.
  1486. //
  1487. pIrp = IoAllocateIrp(pde->pStackDeviceObject->StackSize, FALSE);
  1488. if(NULL == pIrp){
  1489. DebugTrace(TRACE_WARNING,("USUnConfigureDevice: ERROR!! Unable to allocate Irp.\n"));
  1490. Status = STATUS_INSUFFICIENT_RESOURCES;
  1491. goto USGetDeviceCapability_return;
  1492. } // if(NULL == pIrp)
  1493. //
  1494. // Get next stack location of the allocated IRP.
  1495. //
  1496. pIrpStack = IoGetNextIrpStackLocation(pIrp);
  1497. ASSERT(NULL != pIrpStack);
  1498. //
  1499. // Initialize required fields.
  1500. //
  1501. RtlZeroMemory(&pde->DeviceCapabilities, sizeof(DEVICE_CAPABILITIES));
  1502. pde->DeviceCapabilities.Size = sizeof(DEVICE_CAPABILITIES);
  1503. pde->DeviceCapabilities.Version = 1;
  1504. pde->DeviceCapabilities.Address = -1;
  1505. pde->DeviceCapabilities.UINumber = -1;
  1506. //
  1507. // Set required parameters.
  1508. //
  1509. pIrpStack->MajorFunction = IRP_MJ_PNP;
  1510. pIrpStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
  1511. pIrpStack->Parameters.DeviceCapabilities.Capabilities = &pde->DeviceCapabilities;
  1512. pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  1513. pIrp->IoStatus.Information = 0;
  1514. //
  1515. // Initialize synchronization.
  1516. //
  1517. KeInitializeEvent(&Event,
  1518. SynchronizationEvent,
  1519. FALSE);
  1520. //
  1521. // Set completion routine
  1522. //
  1523. IoSetCompletionRoutine(pIrp,
  1524. USDeferIrpCompletion,
  1525. &Event,
  1526. TRUE,
  1527. TRUE,
  1528. TRUE);
  1529. //
  1530. // Call down
  1531. //
  1532. Status = IoCallDriver(pde -> pStackDeviceObject, pIrp);
  1533. if(Status == STATUS_PENDING){
  1534. //
  1535. // Waiting for the completion.
  1536. //
  1537. DebugTrace(TRACE_STATUS,("USGetDeviceCapability: STATUS_PENDING. Wait for completion.\n"));
  1538. KeWaitForSingleObject(&Event,
  1539. Executive,
  1540. KernelMode,
  1541. FALSE,
  1542. NULL);
  1543. Status = pIrp -> IoStatus.Status;
  1544. } // if(Status == STATUS_PENDING)
  1545. //
  1546. // See if device is capable for remote wake.
  1547. //
  1548. if(NT_SUCCESS(Status)){
  1549. if(PowerDeviceD0 != pde->DeviceCapabilities.DeviceWake){
  1550. //
  1551. // Remote wake isn't supported on this device.
  1552. //
  1553. pde->bEnabledForWakeup = TRUE;
  1554. } // if(PowerDeviceD0 == pCaps->DeviceWake)
  1555. } // if(NT_SUCCESS(Status))
  1556. //
  1557. // Free allocated Irp.
  1558. //
  1559. IoFreeIrp(pIrp);
  1560. pIrp = NULL;
  1561. USGetDeviceCapability_return:
  1562. DebugTrace(TRACE_PROC_LEAVE,("USGetDeviceCapability: Leaving.. Status = %x\n", Status));
  1563. return Status;
  1564. } // USGetDeviceCapability()
  1565. VOID
  1566. USUnload(
  1567. IN PDRIVER_OBJECT pDriverObject
  1568. )
  1569. /*++
  1570. Routine Description:
  1571. Unload routine. The routine is called when the driver is unloaded.
  1572. Release every resource allocated in relation with the driver object.
  1573. Arguments:
  1574. pDriverObject - pointer to the driver object
  1575. Return Value:
  1576. None
  1577. -- */
  1578. {
  1579. PAGED_CODE();
  1580. DebugTrace((MIN_TRACE | TRACE_FLAG_PROC),("UsbScanUnload(0x%X);\n", pDriverObject));
  1581. } // end USUnload()
  1582. NTSTATUS
  1583. USCallNextDriverSynch(
  1584. IN PUSBSCAN_DEVICE_EXTENSION pde,
  1585. IN PIRP pIrp
  1586. )
  1587. /*++
  1588. Routine Description:
  1589. Calls lower driver and waits for result
  1590. Arguments:
  1591. DeviceExtension - pointer to device extension
  1592. Irp - pointer to IRP
  1593. Return Value:
  1594. none.
  1595. --*/
  1596. {
  1597. KEVENT Event;
  1598. PIO_STACK_LOCATION IrpStack;
  1599. NTSTATUS Status;
  1600. DebugTrace(TRACE_PROC_ENTER,("USCallNextDriverSynch: Enter..\n"));
  1601. IrpStack = IoGetCurrentIrpStackLocation(pIrp);
  1602. //
  1603. // Copy IRP stack to the next.
  1604. //
  1605. IoCopyCurrentIrpStackLocationToNext(pIrp);
  1606. //
  1607. // Initialize synchronizing event.
  1608. //
  1609. KeInitializeEvent(&Event,
  1610. SynchronizationEvent,
  1611. FALSE);
  1612. //
  1613. // Set completion routine
  1614. //
  1615. IoSetCompletionRoutine(pIrp,
  1616. USDeferIrpCompletion,
  1617. &Event,
  1618. TRUE,
  1619. TRUE,
  1620. TRUE);
  1621. //
  1622. // Call down
  1623. //
  1624. Status = IoCallDriver(pde -> pStackDeviceObject, pIrp);
  1625. if (Status == STATUS_PENDING) {
  1626. //
  1627. // Waiting for the completion.
  1628. //
  1629. DebugTrace(TRACE_STATUS,("USCallNextDriverSynch: STATUS_PENDING. Wait for event.\n"));
  1630. KeWaitForSingleObject(&Event,
  1631. Executive,
  1632. KernelMode,
  1633. FALSE,
  1634. NULL);
  1635. Status = pIrp -> IoStatus.Status;
  1636. }
  1637. //
  1638. // Return
  1639. //
  1640. DebugTrace(TRACE_PROC_LEAVE,("USCallNextDriverSynch: Leaving.. Status = %x\n", Status));
  1641. return (Status);
  1642. }
  1643. NTSTATUS
  1644. UsbScanHandleInterface(
  1645. PDEVICE_OBJECT DeviceObject,
  1646. PUNICODE_STRING InterfaceName,
  1647. BOOLEAN Create
  1648. )
  1649. /*++
  1650. Routine Description:
  1651. Arguments:
  1652. DeviceObject - Supplies the device object.
  1653. Return Value:
  1654. None.
  1655. --*/
  1656. {
  1657. NTSTATUS Status;
  1658. DebugTrace(TRACE_PROC_ENTER,("UsbScanHandleInterface: Enter..\n"));
  1659. Status = STATUS_SUCCESS;
  1660. #ifndef _CHICAGO_
  1661. if (Create) {
  1662. Status=IoRegisterDeviceInterface(
  1663. DeviceObject,
  1664. &GUID_DEVINTERFACE_IMAGE,
  1665. NULL,
  1666. InterfaceName
  1667. );
  1668. DebugTrace(TRACE_STATUS,("Called IoRegisterDeviceInterface . Returned=0x%X\n",Status));
  1669. if (NT_SUCCESS(Status)) {
  1670. IoSetDeviceInterfaceState(
  1671. InterfaceName,
  1672. TRUE
  1673. );
  1674. DebugTrace(TRACE_STATUS,("Called IoSetDeviceInterfaceState(TRUE) . \n"));
  1675. }
  1676. } else {
  1677. if (InterfaceName->Buffer != NULL) {
  1678. Status = IoSetDeviceInterfaceState(
  1679. InterfaceName,
  1680. FALSE
  1681. );
  1682. RtlFreeUnicodeString(
  1683. InterfaceName
  1684. );
  1685. InterfaceName->Buffer = NULL;
  1686. }
  1687. }
  1688. #endif // !_CHICAGO_
  1689. DebugTrace(TRACE_PROC_LEAVE,("IoRegisterDeviceInterface: Leaving... Status=0x%X\n",Status));
  1690. return Status;
  1691. }
  1692. BOOLEAN
  1693. USArmForWake(
  1694. PUSBSCAN_DEVICE_EXTENSION pde,
  1695. POWER_STATE SystemState
  1696. )
  1697. /*++
  1698. Routine Description:
  1699. Arm device for remote wakeup.
  1700. Arguments:
  1701. pde - pointer to device extension
  1702. Return Value:
  1703. STATUS_SUCCESS if successful,
  1704. --*/
  1705. {
  1706. BOOLEAN bRet;
  1707. LONG OldWakeState;
  1708. NTSTATUS status;
  1709. DebugTrace(TRACE_PROC_ENTER,("USArmForWake: Enter..\n"));
  1710. //
  1711. // Initialize local.
  1712. //
  1713. bRet = FALSE;
  1714. status = STATUS_SUCCESS;
  1715. OldWakeState = WAKESTATE_DISARMED;
  1716. //
  1717. // See if device/system supports wakeup.
  1718. //
  1719. if(TRUE != pde->bEnabledForWakeup){
  1720. DebugTrace(TRACE_STATUS,("USArmForWake: This device or system doesn't support RemoteWake.\n"));
  1721. bRet = FALSE;
  1722. goto USArmForWake_return;
  1723. } // if(TRUE != pde->bEnabledForWakeup)
  1724. //
  1725. // Make sure about curent state.
  1726. //
  1727. while(1){
  1728. // Try to move us into the arming state
  1729. OldWakeState = InterlockedCompareExchange(&pde->WakeState,
  1730. WAKESTATE_WAITING,
  1731. WAKESTATE_DISARMED);
  1732. if(WAKESTATE_DISARMED == OldWakeState){
  1733. break;
  1734. } // if(OldWakeState == WAKESTATE_DISARMED)
  1735. if( (WAKESTATE_ARMED == OldWakeState)
  1736. || (WAKESTATE_WAITING == OldWakeState) )
  1737. {
  1738. // The device is already armed.
  1739. DebugTrace(TRACE_STATUS,("USArmForWake: Device is already armed for wake\n"));
  1740. bRet = TRUE;
  1741. goto USArmForWake_return;
  1742. }
  1743. // Wait for the previous wait-wake IRP to finish
  1744. DebugTrace(TRACE_STATUS,("USArmForWake: Wait for previous wake IRP to complete.\n"));
  1745. USDisarmWake(pde);
  1746. } // while(1)
  1747. // The state just got moved to WAKESTATE_WAITING. First ensure the previous
  1748. // WaitWake IRP has finished
  1749. KeWaitForSingleObject(&pde->WakeCompletedEvent,
  1750. Executive,
  1751. KernelMode,
  1752. FALSE,
  1753. NULL);
  1754. //
  1755. // Request the power IRP, STATUS_PENDING is success
  1756. //
  1757. status = PoRequestPowerIrp(pde->pStackDeviceObject,
  1758. IRP_MN_WAIT_WAKE,
  1759. SystemState,
  1760. USWaitWakePoCompletionRoutine,
  1761. (PVOID)pde,
  1762. NULL );
  1763. if(!NT_SUCCESS(status)){
  1764. //
  1765. // IRP_MN_WAIT_WAKE didn't succeed. Possiblly lower stack doesn't support.
  1766. //
  1767. DebugTrace(TRACE_WARNING,("USArmForWake: WARNING!! IRP_MN_WAIT_WAKE failed. Statust=0x%x.\n", status));
  1768. pde->WakeState = WAKESTATE_DISARMED;
  1769. KeSetEvent(&pde->WakeCompletedEvent,
  1770. IO_NO_INCREMENT,
  1771. FALSE);
  1772. } // if(!NT_SUCCESS(status))
  1773. bRet = (status == STATUS_PENDING);
  1774. USArmForWake_return:
  1775. DebugTrace(TRACE_PROC_LEAVE,("USArmForWake: Leaving.. Ret=0x%x\n", bRet));
  1776. return bRet;
  1777. } // USArmForWake()
  1778. VOID
  1779. USDisarmWake(
  1780. PUSBSCAN_DEVICE_EXTENSION pde
  1781. )
  1782. {
  1783. LONG oldWakeState;
  1784. DebugTrace(TRACE_PROC_ENTER,("USDisarmWake: Enter...\n"));
  1785. //
  1786. // See if device/system supports wakeup.
  1787. //
  1788. if(TRUE != pde->bEnabledForWakeup){
  1789. DebugTrace(TRACE_STATUS,("USDisarmWake: This device or system doesn't support RemoteWake.\n"));
  1790. goto USDisarmWake_return;
  1791. } // if(TRUE != pde->bEnabledForWakeup)
  1792. // Go from WAKESTATE_WAITING to WAKESTATE_WAITING_CANCELLED, or
  1793. // WAKESTATE_ARMED to WAKESTATE_ARMING_CANCELLED, or
  1794. // stay in WAKESTATE_DISARMED or WAKESTATE_COMPLETING
  1795. oldWakeState = MyInterlockedOr(&pde->SpinLock,
  1796. &pde->WakeState,
  1797. 1);
  1798. if(WAKESTATE_ARMED == oldWakeState){
  1799. DebugTrace(TRACE_STATUS,("USDisarmWake: Currently armed, canceling WaitWakeIRP...\n"));
  1800. ASSERT(NULL != pde->pWakeIrp);
  1801. IoCancelIrp(pde->pWakeIrp);
  1802. //
  1803. // Now that we�fve cancelled the IRP, try to give back ownership
  1804. // to the completion routine by restoring the WAKESTATE_ARMED state
  1805. //
  1806. //
  1807. // Note: Check again here to make sure there's no "Dangerous moment"
  1808. //
  1809. oldWakeState = InterlockedCompareExchange(&pde->WakeState,
  1810. WAKESTATE_ARMED,
  1811. WAKESTATE_ARMING_CANCELLED);
  1812. if(WAKESTATE_COMPLETING == oldWakeState){
  1813. //
  1814. // We didn�ft give back control of IRP in time, so we own it now.
  1815. //
  1816. IoCompleteRequest(pde->pWakeIrp, IO_NO_INCREMENT);
  1817. } // if(WAKESTATE_COMPLETING == oldWakeState)
  1818. } // if(WAKESTATE_ARMED == oldWakeState)
  1819. USDisarmWake_return:
  1820. DebugTrace(TRACE_PROC_LEAVE,("USDisarmWake: Leaving.. Ret=VOID.\n"));
  1821. } // USDisarmWake()
  1822. VOID
  1823. USWaitWakePoCompletionRoutine(
  1824. PDEVICE_OBJECT pDeviceObject,
  1825. UCHAR MinorFunction,
  1826. POWER_STATE State,
  1827. PVOID pContext,
  1828. PIO_STATUS_BLOCK pIoStatus
  1829. )
  1830. /*++
  1831. Routine Description:
  1832. Completion routine for WaitWait IRP.
  1833. --*/
  1834. {
  1835. PUSBSCAN_DEVICE_EXTENSION pde;
  1836. DebugTrace(TRACE_PROC_ENTER,("USWaitWakePoCompletionRoutine: Enter...\n"));
  1837. pde = (PUSBSCAN_DEVICE_EXTENSION) pContext;
  1838. //
  1839. // WaitWakeIRP has been freed.
  1840. //
  1841. pde->pWakeIrp = NULL;
  1842. pde->WakeState = WAKESTATE_DISARMED;
  1843. //
  1844. // Adjust synchronization event so another Wait-Wake can get queued
  1845. //
  1846. KeSetEvent(&pde->WakeCompletedEvent,
  1847. IO_NO_INCREMENT,
  1848. FALSE);
  1849. if(NT_SUCCESS(pIoStatus->Status)){
  1850. DebugTrace(TRACE_STATUS,("USWaitWakePoCompletionRoutine: Wakeup succeeded. Queue rearm callback.\n"));
  1851. //
  1852. // WaitWakeIRP has been completed successfully. Rearming for next wakeup.
  1853. //
  1854. USQueuePassiveLevelCallback(pde->pOwnDeviceObject,
  1855. USPassiveLevelReArmCallbackWorker);
  1856. } else if( (STATUS_UNSUCCESSFUL == pIoStatus->Status)
  1857. || (STATUS_NOT_IMPLEMENTED == pIoStatus->Status)
  1858. || (STATUS_POWER_STATE_INVALID == pIoStatus->Status)
  1859. || (STATUS_NOT_SUPPORTED == pIoStatus->Status) )
  1860. {
  1861. //
  1862. // Remote wakeup isn't supported on this bus/device.
  1863. //
  1864. DebugTrace(TRACE_STATUS,("USWaitWakePoCompletionRoutine: RemoteWake isn't supported. Ret=VOID.\n"));
  1865. pde -> bEnabledForWakeup = FALSE;
  1866. } else {
  1867. DebugTrace(TRACE_STATUS,("USWaitWakePoCompletionRoutine: Wakeup didn't succeed.(0x%x).\n", pIoStatus->Status));
  1868. }
  1869. DebugTrace(TRACE_PROC_LEAVE,("USWaitWakePoCompletionRoutine: Leaving.. Ret=VOID.\n"));
  1870. return;
  1871. } // USWaitWakePoCompletionRoutine()
  1872. VOID
  1873. USInitializeWakeState(
  1874. PUSBSCAN_DEVICE_EXTENSION pde
  1875. )
  1876. /*++
  1877. Routine Description:
  1878. Initialize wake state.
  1879. Arguments:
  1880. pde - pointer to device extension
  1881. Return Value:
  1882. none.
  1883. --*/
  1884. {
  1885. pde->WakeState = WAKESTATE_DISARMED;
  1886. pde->pWakeIrp = NULL;
  1887. //
  1888. // Initialize event for sync.
  1889. //
  1890. KeInitializeEvent(&pde->WakeCompletedEvent,
  1891. SynchronizationEvent,
  1892. TRUE);
  1893. } // USArmDevice()
  1894. VOID
  1895. USQueuePassiveLevelCallback(
  1896. IN PDEVICE_OBJECT pDeviceObject,
  1897. IN PIO_WORKITEM_ROUTINE pCallbackFunction
  1898. )
  1899. /*++
  1900. Routine Description:
  1901. This routine queues a passive level callback if it's called
  1902. at DISPATCH_LEVEL otherwise calls the worker routine directly.
  1903. Arguments:
  1904. DeviceObject - pointer to a device extenion.
  1905. CallbackFunction - Function to invoke when at PASSIVE_LEVEL.
  1906. Return Value:
  1907. --*/
  1908. {
  1909. PIO_WORKITEM item;
  1910. DebugTrace(TRACE_PROC_ENTER,("USQueuePassiveLevelCallback: Enter...\n"));
  1911. //
  1912. // If the current IRQL level is not DISPATCH_LEVEL, we will call the
  1913. // CallbackFunction directly without queuing a workitem.
  1914. //
  1915. if(KeGetCurrentIrql() != DISPATCH_LEVEL) {
  1916. (*pCallbackFunction)(pDeviceObject, NULL);
  1917. } else { // if(KeGetCurrentIrql() != DISPATCH_LEVEL)
  1918. //
  1919. // Allocate a workitem and queue it for passive level processing.
  1920. //
  1921. item = IoAllocateWorkItem(pDeviceObject);
  1922. if(NULL != item){
  1923. IoQueueWorkItem(item,
  1924. pCallbackFunction,
  1925. DelayedWorkQueue,
  1926. item
  1927. );
  1928. } else { // if(NULL != item)
  1929. DebugTrace(TRACE_WARNING,("USQueuePassiveLevelCallback: WARNING!! IoAllocateWorkItem() failed, running out of resource.\n"));
  1930. } // else(NULL != item)
  1931. } // else(KeGetCurrentIrql() != DISPATCH_LEVEL)
  1932. DebugTrace(TRACE_PROC_LEAVE,("USQueuePassiveLevelCallback: Leaving.. Ret=VOID.\n"));
  1933. } // USQueuePassiveLevelCallback()
  1934. VOID
  1935. USPassiveLevelReArmCallbackWorker(
  1936. IN PDEVICE_OBJECT pDeviceObject,
  1937. IN PVOID pContext
  1938. )
  1939. {
  1940. PUSBSCAN_DEVICE_EXTENSION pde;
  1941. POWER_STATE PowerState;
  1942. PAGED_CODE();
  1943. DebugTrace(TRACE_PROC_ENTER,("USPassiveLevelReArmCallbackWorker: Enter...\n"));
  1944. pde = pDeviceObject->DeviceExtension;
  1945. //
  1946. // Rearm for wake.
  1947. //
  1948. PowerState.SystemState = pde -> DeviceCapabilities.SystemWake;
  1949. USArmForWake(pde, PowerState);
  1950. if(NULL != pContext){
  1951. IoFreeWorkItem((PIO_WORKITEM)pContext);
  1952. } // if(Context)
  1953. DebugTrace(TRACE_PROC_LEAVE,("USPassiveLevelReArmCallbackWorker: Leaving.. Ret=VOID.\n"));
  1954. } // USPassiveLevelReArmCallbackWorker()
  1955. LONG
  1956. MyInterlockedOr(
  1957. PKSPIN_LOCK pSpinLock,
  1958. LONG volatile *Destination,
  1959. LONG Value
  1960. )
  1961. {
  1962. KIRQL OldIrql;
  1963. LONG lOldValue;
  1964. //
  1965. // Acquire spinlock to access shared resource, going into IRQL_DISPATCH_LEVEL.
  1966. //
  1967. KeAcquireSpinLock(pSpinLock, &OldIrql);
  1968. //
  1969. // Save old value;
  1970. //
  1971. lOldValue = *Destination;
  1972. //
  1973. // Or Value to the destination.
  1974. //
  1975. *Destination |= Value;
  1976. //
  1977. // Release spinlock and return to the original IRQL.
  1978. //
  1979. KeReleaseSpinLock(pSpinLock, OldIrql);
  1980. //
  1981. // Return original value.
  1982. //
  1983. return lOldValue;
  1984. } // MyInterlockedOr()
  1985. NTSTATUS
  1986. UsbScanReadDeviceRegistry(
  1987. IN PUSBSCAN_DEVICE_EXTENSION pExtension,
  1988. IN PCWSTR pKeyName,
  1989. OUT PVOID *ppvData
  1990. )
  1991. /*++
  1992. Routine Description:
  1993. This routine open registry for this device and query a value specified
  1994. by key name. This routine allocate non-paged memory and return its pointer.
  1995. Caller must free returned pointer.
  1996. Arguments:
  1997. pExtension - pointer to device extension
  1998. pKeyName - pointer to a wide string specify key name
  1999. ppvData - pointer to the queried data pointer allocated by this routine
  2000. Return Value:
  2001. STATUS_SUCCESS - if success,
  2002. STATUS_INVALID_PARAMETER - if passed argument is invalid,
  2003. --*/
  2004. {
  2005. NTSTATUS Status;
  2006. HANDLE hRegKey;
  2007. PVOID pvBuffer;
  2008. ULONG DataSize;
  2009. PVOID pvRetData;
  2010. UNICODE_STRING unicodeKeyName;
  2011. PAGED_CODE();
  2012. DebugTrace(TRACE_PROC_ENTER, ("UsbScanReadDeviceRegistry: Entering...\n"));
  2013. //
  2014. // Initialize status
  2015. //
  2016. Status = STATUS_SUCCESS;
  2017. hRegKey = NULL;
  2018. pvBuffer = NULL;
  2019. pvRetData = NULL;
  2020. DataSize = 0;
  2021. //
  2022. // Check the arguments
  2023. //
  2024. if( (NULL == pExtension)
  2025. || (NULL == pKeyName)
  2026. || (NULL == ppvData) )
  2027. {
  2028. DebugTrace(TRACE_ERROR, ("UsbScanReadDeviceRegistry: ERROR!! Invalid argument.\n"));
  2029. Status = STATUS_INVALID_PARAMETER;
  2030. goto UsbScanReadDeviceRegistry_return;
  2031. }
  2032. //
  2033. // Open device registry.
  2034. //
  2035. Status = IoOpenDeviceRegistryKey(pExtension->pPhysicalDeviceObject,
  2036. PLUGPLAY_REGKEY_DRIVER,
  2037. KEY_ALL_ACCESS,
  2038. &hRegKey);
  2039. if(!NT_SUCCESS(Status)){
  2040. DebugTrace(TRACE_ERROR, ("UsbScanReadDeviceRegistry: ERROR!! IoOpenDeviceRegistryKey failed.\n"));
  2041. goto UsbScanReadDeviceRegistry_return;
  2042. }
  2043. //
  2044. // Query required size.
  2045. //
  2046. RtlInitUnicodeString(&unicodeKeyName, pKeyName);
  2047. Status = ZwQueryValueKey(hRegKey,
  2048. &unicodeKeyName,
  2049. KeyValuePartialInformation,
  2050. NULL,
  2051. 0,
  2052. &DataSize);
  2053. if(0 == DataSize){
  2054. if(STATUS_OBJECT_NAME_NOT_FOUND == Status){
  2055. DebugTrace(TRACE_STATUS, ("UsbScanReadDeviceRegistry: Reg-key \"%wZ\" doesn't exist.\n", &unicodeKeyName));
  2056. } else {
  2057. DebugTrace(TRACE_ERROR, ("UsbScanReadDeviceRegistry: ERROR!! Cannot retrieve reqired data size of %wZ. Status=0x%x\n",
  2058. &unicodeKeyName ,
  2059. Status));
  2060. }
  2061. goto UsbScanReadDeviceRegistry_return;
  2062. }
  2063. //
  2064. // Allocate memory for temp buffer. size +2 for NULL.
  2065. //
  2066. pvBuffer = USAllocatePool(NonPagedPool, DataSize+2);
  2067. if(NULL == pvBuffer){
  2068. DebugTrace(TRACE_CRITICAL, ("UsbScanReadDeviceRegistry: ERROR!! Buffer allocate failed.\n"));
  2069. Status = STATUS_INSUFFICIENT_RESOURCES;
  2070. goto UsbScanReadDeviceRegistry_return;
  2071. }
  2072. RtlZeroMemory(pvBuffer, DataSize+sizeof(WCHAR));
  2073. //
  2074. // Query specified value.
  2075. //
  2076. DebugTrace(TRACE_STATUS, ("UsbScanReadDeviceRegistry: Query \"%wZ\".\n", &unicodeKeyName));
  2077. Status = ZwQueryValueKey(hRegKey,
  2078. &unicodeKeyName,
  2079. KeyValuePartialInformation,
  2080. pvBuffer,
  2081. DataSize,
  2082. &DataSize);
  2083. if(!NT_SUCCESS(Status)){
  2084. DebugTrace(TRACE_ERROR, ("UsbScanReadDeviceRegistry: ERROR!! ZwQueryValueKey failed. Status=0x%x\n", Status));
  2085. goto UsbScanReadDeviceRegistry_return;
  2086. }
  2087. UsbScanReadDeviceRegistry_return:
  2088. if(!NT_SUCCESS(Status)){
  2089. //
  2090. // This routine failed.
  2091. //
  2092. if(pvRetData){
  2093. USFreePool(pvRetData);
  2094. }
  2095. *ppvData = NULL;
  2096. } else {
  2097. //
  2098. // This routine succeeded.
  2099. //
  2100. *ppvData = pvBuffer;
  2101. }
  2102. //
  2103. // Clean-up.
  2104. //
  2105. if(hRegKey){
  2106. ZwClose(hRegKey);
  2107. }
  2108. DebugTrace(TRACE_PROC_LEAVE, ("UsbScanReadDeviceRegistry: Leaving... Status=0x%x\n", Status));
  2109. return Status;
  2110. }
  2111. NTSTATUS
  2112. UsbScanWriteDeviceRegistry(
  2113. IN PUSBSCAN_DEVICE_EXTENSION pExtension,
  2114. IN PCWSTR pKeyName,
  2115. IN ULONG Type,
  2116. IN PVOID pvData,
  2117. IN ULONG DataSize
  2118. )
  2119. /*++
  2120. Routine Description:
  2121. This routine open registry for this device and set a value specified
  2122. by key name.
  2123. Arguments:
  2124. pExtension - pointer to device extension
  2125. pKeyName - pointer to a wide string specify key name
  2126. Type - specifies the type of data to be written
  2127. pvData - pointer to a caller allocated buffer containing data
  2128. DataSize - specifies the size in bytes of the data buffer
  2129. Return Value:
  2130. STATUS_SUCCESS - if success,
  2131. STATUS_INVALID_PARAMETER - if passed argument is invalid,
  2132. --*/
  2133. {
  2134. NTSTATUS Status;
  2135. HANDLE hRegKey;
  2136. UNICODE_STRING unicodeKeyName;
  2137. PAGED_CODE();
  2138. DebugTrace(TRACE_PROC_ENTER, ("UsbScanWriteDeviceRegistry: Entering...\n"));
  2139. //
  2140. // Initialize status
  2141. //
  2142. Status = STATUS_SUCCESS;
  2143. hRegKey = NULL;
  2144. //
  2145. // Check the arguments
  2146. //
  2147. if( (NULL == pExtension)
  2148. || (NULL == pKeyName)
  2149. || (NULL == pvData)
  2150. || (0 == DataSize) )
  2151. {
  2152. DebugTrace(TRACE_ERROR, ("UsbScanWriteDeviceRegistry: ERROR!! Invalid argument.\n"));
  2153. Status = STATUS_INVALID_PARAMETER;
  2154. goto UsbScanWriteDeviceRegistry_return;
  2155. }
  2156. //
  2157. // Open device registry.
  2158. //
  2159. Status = IoOpenDeviceRegistryKey(pExtension->pPhysicalDeviceObject,
  2160. PLUGPLAY_REGKEY_DRIVER,
  2161. KEY_ALL_ACCESS,
  2162. &hRegKey);
  2163. if(!NT_SUCCESS(Status)){
  2164. DebugTrace(TRACE_ERROR, ("UsbScanWriteDeviceRegistry: ERROR!! IoOpenDeviceRegistryKey failed.\n"));
  2165. goto UsbScanWriteDeviceRegistry_return;
  2166. }
  2167. //
  2168. // Set specified value.
  2169. //
  2170. RtlInitUnicodeString(&unicodeKeyName, pKeyName);
  2171. DebugTrace(TRACE_STATUS, ("UsbScanWriteDeviceRegistry: Setting \"%wZ\".\n", &unicodeKeyName));
  2172. Status = ZwSetValueKey(hRegKey,
  2173. &unicodeKeyName,
  2174. 0,
  2175. Type,
  2176. pvData,
  2177. DataSize);
  2178. if(!NT_SUCCESS(Status)){
  2179. DebugTrace(TRACE_ERROR, ("UsbScanWriteDeviceRegistry: ERROR!! ZwSetValueKey failed. Status = 0x%x\n", Status));
  2180. goto UsbScanWriteDeviceRegistry_return;
  2181. }
  2182. UsbScanWriteDeviceRegistry_return:
  2183. //
  2184. // Clean-up.
  2185. //
  2186. if(hRegKey){
  2187. ZwClose(hRegKey);
  2188. }
  2189. DebugTrace(TRACE_PROC_LEAVE, ("UsbScanWriteDeviceRegistry: Leaving... Status=0x%x\n", Status));
  2190. return Status;
  2191. } // UsbScanWriteDeviceRegistry()
  2192. PURB
  2193. USCreateConfigurationRequest(
  2194. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
  2195. IN OUT PUSHORT Siz
  2196. )
  2197. /*++
  2198. Routine Description:
  2199. Arguments:
  2200. Return Value:
  2201. Pointer to initailized select_configuration urb.
  2202. --*/
  2203. {
  2204. PURB urb = NULL;
  2205. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
  2206. PUSBD_INTERFACE_LIST_ENTRY interfaceList, tmp;
  2207. LONG numberOfInterfaces, interfaceNumber, i;
  2208. PAGED_CODE();
  2209. DebugTrace(TRACE_PROC_ENTER, ("USCreateConfigurationRequest: Entering...\n"));
  2210. //
  2211. // build a request structure and call the new api
  2212. //
  2213. numberOfInterfaces = ConfigurationDescriptor->bNumInterfaces;
  2214. tmp = interfaceList = USAllocatePool(PagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (numberOfInterfaces+1));
  2215. //
  2216. // just grab the first alt setting we find for each interface
  2217. //
  2218. i = interfaceNumber = 0;
  2219. while (i< numberOfInterfaces) {
  2220. interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor,
  2221. ConfigurationDescriptor,
  2222. -1,
  2223. 0, // assume alt setting zero here
  2224. -1,
  2225. -1,
  2226. -1);
  2227. ASSERT(interfaceDescriptor != NULL);
  2228. if (interfaceDescriptor) {
  2229. interfaceList->InterfaceDescriptor =
  2230. interfaceDescriptor;
  2231. interfaceList++;
  2232. i++;
  2233. } else {
  2234. // could not find the requested interface descriptor
  2235. // bail, we will prorblay crash somewhere in the
  2236. // client driver.
  2237. goto USCreateConfigurationRequest_return;
  2238. }
  2239. interfaceNumber++;
  2240. }
  2241. //
  2242. // terminate the list
  2243. //
  2244. interfaceList->InterfaceDescriptor = NULL;
  2245. urb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor, tmp);
  2246. USCreateConfigurationRequest_return:
  2247. ExFreePool(tmp);
  2248. if (urb) {
  2249. *Siz = urb->UrbHeader.Length;
  2250. }
  2251. DebugTrace(TRACE_PROC_LEAVE, ("USCreateConfigurationRequest: Leaving... Ret=0x%x\n", urb));
  2252. return urb;
  2253. } // USCreateConfigurationRequest()
  2254. VOID
  2255. UsbScanLogError(
  2256. IN PDRIVER_OBJECT DriverObject,
  2257. IN PDEVICE_OBJECT DeviceObject OPTIONAL,
  2258. IN ULONG SequenceNumber,
  2259. IN UCHAR MajorFunctionCode,
  2260. IN UCHAR RetryCount,
  2261. IN ULONG UniqueErrorValue,
  2262. IN NTSTATUS FinalStatus,
  2263. IN NTSTATUS SpecificIOStatus
  2264. )
  2265. /*++
  2266. Routine Description:
  2267. This routine allocates an error log entry, copies the supplied data
  2268. to it, and requests that it be written to the error log file.
  2269. Arguments:
  2270. DriverObject - Supplies a pointer to the driver object for the
  2271. device.
  2272. DeviceObject - Supplies a pointer to the device object associated
  2273. with the device that had the error, early in
  2274. initialization, one may not yet exist.
  2275. SequenceNumber - Supplies a ulong value that is unique to an IRP over
  2276. the life of the irp in this driver - 0 generally
  2277. means an error not associated with an irp.
  2278. MajorFunctionCode - Supplies the major function code of the irp if there
  2279. is an error associated with it.
  2280. RetryCount - Supplies the number of times a particular operation
  2281. has been retried.
  2282. UniqueErrorValue - Supplies a unique long word that identifies the
  2283. particular call to this function.
  2284. FinalStatus - Supplies the final status given to the irp that was
  2285. associated with this error. If this log entry is
  2286. being made during one of the retries this value
  2287. will be STATUS_SUCCESS.
  2288. SpecificIOStatus - Supplies the IO status for this particular error.
  2289. Return Value:
  2290. None.
  2291. --*/
  2292. {
  2293. PIO_ERROR_LOG_PACKET ErrorLogEntry;
  2294. PVOID ObjectToUse;
  2295. SHORT DumpToAllocate;
  2296. if (ARGUMENT_PRESENT(DeviceObject)) {
  2297. ObjectToUse = DeviceObject;
  2298. } else {
  2299. ObjectToUse = DriverObject;
  2300. }
  2301. DumpToAllocate = 0;
  2302. ErrorLogEntry = IoAllocateErrorLogEntry(ObjectToUse,
  2303. (UCHAR) (sizeof(IO_ERROR_LOG_PACKET) + DumpToAllocate));
  2304. if (!ErrorLogEntry) {
  2305. return;
  2306. }
  2307. ErrorLogEntry->ErrorCode = SpecificIOStatus;
  2308. ErrorLogEntry->SequenceNumber = SequenceNumber;
  2309. ErrorLogEntry->MajorFunctionCode = MajorFunctionCode;
  2310. ErrorLogEntry->RetryCount = RetryCount;
  2311. ErrorLogEntry->UniqueErrorValue = UniqueErrorValue;
  2312. ErrorLogEntry->FinalStatus = FinalStatus;
  2313. ErrorLogEntry->DumpDataSize = DumpToAllocate;
  2314. if (DumpToAllocate) {
  2315. // If needed - add more to parameter list and move memory here
  2316. //RtlCopyMemory(ErrorLogEntry->DumpData, &P1, sizeof(PHYSICAL_ADDRESS));
  2317. }
  2318. IoWriteErrorLogEntry(ErrorLogEntry);
  2319. }
  2320. #ifdef ORIGINAL_POOLTRACK
  2321. int NumberOfAllocate = 0;
  2322. PVOID
  2323. USAllocatePool(
  2324. IN POOL_TYPE PoolType,
  2325. IN ULONG ulNumberOfBytes
  2326. )
  2327. /*++
  2328. Routine Description:
  2329. Wrapper for pool allocation. Use tag to avoid heap corruption.
  2330. Arguments:
  2331. PoolType - type of pool memory to allocate
  2332. ulNumberOfBytes - number of bytes to allocate
  2333. Return Value:
  2334. Pointer to the allocated memory
  2335. --*/
  2336. {
  2337. PVOID pvRet;
  2338. DebugTrace(TRACE_PROC_ENTER,("USAllocatePool: Enter.. Size = %d\n", ulNumberOfBytes));
  2339. pvRet = ExAllocatePoolWithTag(PoolType,
  2340. ulNumberOfBytes,
  2341. TAG_USBSCAN);
  2342. NumberOfAllocate++;
  2343. DebugTrace(TRACE_PROC_LEAVE,("USAllocatePool: Leaving.. pvRet = %x, Count=%d\n", pvRet, NumberOfAllocate));
  2344. return pvRet;
  2345. }
  2346. VOID
  2347. USFreePool(
  2348. IN PVOID pvAddress
  2349. )
  2350. /*++
  2351. Routine Description:
  2352. Wrapper for pool free. Check tag to avoid heap corruption
  2353. Arguments:
  2354. pvAddress - Pointer to the allocated memory
  2355. Return Value:
  2356. none.
  2357. --*/
  2358. {
  2359. ULONG ulTag;
  2360. DebugTrace(TRACE_PROC_ENTER,("USFreePool: Enter..\n"));
  2361. ulTag = *((PULONG)pvAddress-1);
  2362. if( (TAG_USBSCAN == ulTag) || (TAG_USBD == ulTag) ){
  2363. DebugTrace(TRACE_STATUS,("USFreePool: Free memory. tag = %c%c%c%c\n",
  2364. ((PUCHAR)&ulTag)[0],
  2365. ((PUCHAR)&ulTag)[1],
  2366. ((PUCHAR)&ulTag)[2],
  2367. ((PUCHAR)&ulTag)[3] ))
  2368. } else {
  2369. DebugTrace(TRACE_WARNING,("USFreePool: WARNING!! Free memory. tag = %c%c%c%c\n",
  2370. ((PUCHAR)&ulTag)[0],
  2371. ((PUCHAR)&ulTag)[1],
  2372. ((PUCHAR)&ulTag)[2],
  2373. ((PUCHAR)&ulTag)[3] ))
  2374. }
  2375. ExFreePool(pvAddress);
  2376. NumberOfAllocate--;
  2377. DebugTrace(TRACE_PROC_LEAVE,("USFreePool: Leaving.. Status = VOID, Count=%d\n", NumberOfAllocate));
  2378. }
  2379. #endif // ORIGINAL_POOLTRACK