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.

2657 lines
80 KiB

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