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.

5028 lines
155 KiB

  1. /*++
  2. Copyright (c) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. USBMASS.C
  5. Abstract:
  6. This source file contains the DriverEntry() and AddDevice() entry points
  7. for the USBSTOR driver and the dispatch routines which handle:
  8. IRP_MJ_POWER
  9. IRP_MJ_SYSTEM_CONTROL
  10. IRP_MJ_PNP
  11. Environment:
  12. kernel mode
  13. Revision History:
  14. 06-01-98 : started rewrite
  15. --*/
  16. //*****************************************************************************
  17. // I N C L U D E S
  18. //*****************************************************************************
  19. #include <ntddk.h>
  20. #include <usbdi.h>
  21. #include <usbdlib.h>
  22. #include <initguid.h>
  23. #include <usbbusif.h>
  24. #include <stdio.h>
  25. #include "usbmass.h"
  26. //*****************************************************************************
  27. // L O C A L F U N C T I O N P R O T O T Y P E S
  28. //*****************************************************************************
  29. NTSTATUS
  30. USBSTOR_GetBusInterface (
  31. IN PDEVICE_OBJECT DeviceObject,
  32. IN PUSB_BUS_INTERFACE_USBDI_V1 BusInterface
  33. );
  34. #ifdef ALLOC_PRAGMA
  35. #pragma alloc_text(PAGE, DriverEntry)
  36. #pragma alloc_text(PAGE, USBSTOR_Unload)
  37. #pragma alloc_text(PAGE, USBSTOR_AddDevice)
  38. #pragma alloc_text(PAGE, USBSTOR_QueryFdoParams)
  39. #pragma alloc_text(PAGE, USBSTOR_QueryGlobalFdoParams)
  40. #pragma alloc_text(PAGE, USBSTOR_Power)
  41. #pragma alloc_text(PAGE, USBSTOR_FdoSetPower)
  42. #pragma alloc_text(PAGE, USBSTOR_SystemControl)
  43. #pragma alloc_text(PAGE, USBSTOR_Pnp)
  44. #pragma alloc_text(PAGE, USBSTOR_FdoStartDevice)
  45. #pragma alloc_text(PAGE, USBSTOR_GetDescriptors)
  46. #pragma alloc_text(PAGE, USBSTOR_GetStringDescriptors)
  47. #pragma alloc_text(PAGE, USBSTOR_AdjustConfigurationDescriptor)
  48. #pragma alloc_text(PAGE, USBSTOR_GetPipes)
  49. #pragma alloc_text(PAGE, USBSTOR_CreateChildPDO)
  50. #pragma alloc_text(PAGE, USBSTOR_FdoStopDevice)
  51. #pragma alloc_text(PAGE, USBSTOR_FdoRemoveDevice)
  52. #pragma alloc_text(PAGE, USBSTOR_FdoQueryStopRemoveDevice)
  53. #pragma alloc_text(PAGE, USBSTOR_FdoCancelStopRemoveDevice)
  54. #pragma alloc_text(PAGE, USBSTOR_FdoQueryDeviceRelations)
  55. #pragma alloc_text(PAGE, USBSTOR_FdoQueryCapabilities)
  56. #pragma alloc_text(PAGE, USBSTOR_PdoStartDevice)
  57. #pragma alloc_text(PAGE, USBSTOR_PdoRemoveDevice)
  58. #pragma alloc_text(PAGE, USBSTOR_PdoQueryID)
  59. #pragma alloc_text(PAGE, USBSTOR_PdoDeviceTypeString)
  60. #pragma alloc_text(PAGE, USBSTOR_PdoGenericTypeString)
  61. #pragma alloc_text(PAGE, CopyField)
  62. #pragma alloc_text(PAGE, USBSTOR_StringArrayToMultiSz)
  63. #pragma alloc_text(PAGE, USBSTOR_PdoQueryDeviceId)
  64. #pragma alloc_text(PAGE, USBSTOR_PdoQueryHardwareIds)
  65. #pragma alloc_text(PAGE, USBSTOR_PdoQueryCompatibleIds)
  66. #pragma alloc_text(PAGE, USBSTOR_PdoQueryDeviceText)
  67. #pragma alloc_text(PAGE, USBSTOR_PdoBusQueryInstanceId)
  68. #pragma alloc_text(PAGE, USBSTOR_PdoQueryDeviceRelations)
  69. #pragma alloc_text(PAGE, USBSTOR_PdoQueryCapabilities)
  70. #pragma alloc_text(PAGE, USBSTOR_SyncPassDownIrp)
  71. #pragma alloc_text(PAGE, USBSTOR_SyncSendUsbRequest)
  72. #pragma alloc_text(PAGE, USBSTOR_GetDescriptor)
  73. #pragma alloc_text(PAGE, USBSTOR_GetMaxLun)
  74. #pragma alloc_text(PAGE, USBSTOR_SelectConfiguration)
  75. #pragma alloc_text(PAGE, USBSTOR_UnConfigure)
  76. #pragma alloc_text(PAGE, USBSTOR_ResetPipe)
  77. #pragma alloc_text(PAGE, USBSTOR_AbortPipe)
  78. #pragma alloc_text(PAGE, USBSTOR_GetBusInterface)
  79. #endif
  80. //******************************************************************************
  81. //
  82. // DriverEntry()
  83. //
  84. //******************************************************************************
  85. NTSTATUS
  86. DriverEntry (
  87. IN PDRIVER_OBJECT DriverObject,
  88. IN PUNICODE_STRING RegistryPath
  89. )
  90. {
  91. PAGED_CODE();
  92. #if DBG
  93. // Query the registry for global parameters
  94. //
  95. USBSTOR_QueryGlobalParams();
  96. #endif
  97. DBGPRINT(2, ("enter: DriverEntry\n"));
  98. DBGFBRK(DBGF_BRK_DRIVERENTRY);
  99. LOGINIT();
  100. //
  101. // Initialize the Driver Object with the driver's entry points
  102. //
  103. //
  104. // USBMASS.C
  105. //
  106. DriverObject->DriverUnload = USBSTOR_Unload;
  107. DriverObject->DriverExtension->AddDevice = USBSTOR_AddDevice;
  108. //
  109. // OCRW.C
  110. //
  111. DriverObject->MajorFunction[IRP_MJ_CREATE] = USBSTOR_Create;
  112. DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBSTOR_Close;
  113. DriverObject->MajorFunction[IRP_MJ_READ] = USBSTOR_ReadWrite;
  114. DriverObject->MajorFunction[IRP_MJ_WRITE] = USBSTOR_ReadWrite;
  115. //
  116. // SCSI.C
  117. //
  118. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBSTOR_DeviceControl;
  119. DriverObject->MajorFunction[IRP_MJ_SCSI] = USBSTOR_Scsi;
  120. DriverObject->DriverStartIo = USBSTOR_StartIo;
  121. //
  122. // USBMASS.C
  123. //
  124. DriverObject->MajorFunction[IRP_MJ_POWER] = USBSTOR_Power;
  125. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = USBSTOR_SystemControl;
  126. DriverObject->MajorFunction[IRP_MJ_PNP] = USBSTOR_Pnp;
  127. DBGPRINT(2, ("exit: DriverEntry\n"));
  128. return STATUS_SUCCESS;
  129. }
  130. //******************************************************************************
  131. //
  132. // USBSTOR_Unload()
  133. //
  134. //******************************************************************************
  135. VOID
  136. USBSTOR_Unload (
  137. IN PDRIVER_OBJECT DriverObject
  138. )
  139. {
  140. PAGED_CODE();
  141. DBGPRINT(2, ("enter: USBSTOR_Unload\n"));
  142. LOGENTRY('UNLD', DriverObject, 0, 0);
  143. DBGFBRK(DBGF_BRK_UNLOAD);
  144. LOGUNINIT();
  145. DBGPRINT(2, ("exit: USBSTOR_Unload\n"));
  146. }
  147. //******************************************************************************
  148. //
  149. // USBSTOR_AddDevice()
  150. //
  151. //******************************************************************************
  152. NTSTATUS
  153. USBSTOR_AddDevice (
  154. IN PDRIVER_OBJECT DriverObject,
  155. IN PDEVICE_OBJECT PhysicalDeviceObject
  156. )
  157. {
  158. PDEVICE_OBJECT deviceObject;
  159. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  160. NTSTATUS ntStatus;
  161. PAGED_CODE();
  162. DBGPRINT(2, ("enter: USBSTOR_AddDevice\n"));
  163. LOGENTRY('ADDD', DriverObject, PhysicalDeviceObject, 0);
  164. DBGFBRK(DBGF_BRK_ADDDEVICE);
  165. // Create the FDO
  166. //
  167. ntStatus = IoCreateDevice(DriverObject,
  168. sizeof(FDO_DEVICE_EXTENSION),
  169. NULL,
  170. FILE_DEVICE_BUS_EXTENDER,
  171. (FILE_AUTOGENERATED_DEVICE_NAME |
  172. FILE_DEVICE_SECURE_OPEN),
  173. FALSE,
  174. &deviceObject);
  175. if (!NT_SUCCESS(ntStatus))
  176. {
  177. return ntStatus;
  178. }
  179. // StartIo should not be called recursively and should be deferred until
  180. // the previous StartIo call returns to the IO manager. This will prevent
  181. // a recursive stack overflow death if a device error occurs when there
  182. // are many requests queued on the device queue.
  183. //
  184. IoSetStartIoAttributes(deviceObject,
  185. TRUE, // DeferredStartIo
  186. FALSE // NonCancelable
  187. );
  188. // Initialize the FDO DeviceExtension
  189. //
  190. fdoDeviceExtension = deviceObject->DeviceExtension;
  191. // Set all DeviceExtension pointers to NULL and all variable to zero
  192. //
  193. RtlZeroMemory(fdoDeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
  194. // Tag this as the FDO on top of the USB PDO
  195. //
  196. fdoDeviceExtension->Type = USBSTOR_DO_TYPE_FDO;
  197. // Store a back point to the DeviceObject to which the DeviceExtension
  198. // is attached.
  199. //
  200. fdoDeviceExtension->FdoDeviceObject = deviceObject;
  201. // Remember our PDO
  202. //
  203. fdoDeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
  204. // Attach the FDO we created to the top of the PDO stack
  205. //
  206. fdoDeviceExtension->StackDeviceObject = IoAttachDeviceToDeviceStack(
  207. deviceObject,
  208. PhysicalDeviceObject);
  209. ASSERT(fdoDeviceExtension->StackDeviceObject != NULL);
  210. // Initialize the list of child PDOs
  211. //
  212. InitializeListHead(&fdoDeviceExtension->ChildPDOs);
  213. // Initialize to one in AddDevice, decrement by one in REMOVE_DEVICE
  214. //
  215. fdoDeviceExtension->PendingIoCount = 1;
  216. // Initialize the event which is set when OpenCount is decremented to zero.
  217. //
  218. KeInitializeEvent(&fdoDeviceExtension->RemoveEvent,
  219. SynchronizationEvent,
  220. FALSE);
  221. // Set the initial system and device power states
  222. //
  223. fdoDeviceExtension->SystemPowerState = PowerSystemWorking;
  224. fdoDeviceExtension->DevicePowerState = PowerDeviceD0;
  225. KeInitializeEvent(&fdoDeviceExtension->PowerDownEvent,
  226. SynchronizationEvent,
  227. FALSE);
  228. // Initialize the spinlock which protects the PDO DeviceFlags
  229. //
  230. KeInitializeSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock);
  231. KeInitializeEvent(&fdoDeviceExtension->CancelEvent,
  232. SynchronizationEvent,
  233. FALSE);
  234. // Initialize timeout timer
  235. //
  236. IoInitializeTimer(deviceObject, USBSTOR_TimerTick, NULL);
  237. USBSTOR_QueryFdoParams(deviceObject);
  238. fdoDeviceExtension->LastSenseWasReset = TRUE;
  239. deviceObject->Flags |= DO_DIRECT_IO;
  240. deviceObject->Flags |= DO_POWER_PAGABLE;
  241. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  242. DBGPRINT(2, ("exit: USBSTOR_AddDevice\n"));
  243. LOGENTRY('addd', deviceObject, fdoDeviceExtension,
  244. fdoDeviceExtension->StackDeviceObject);
  245. // Fail AddDevice if IoAttachDeviceToDeviceStack() failed.
  246. //
  247. if (fdoDeviceExtension->StackDeviceObject == NULL)
  248. {
  249. return STATUS_UNSUCCESSFUL;
  250. }
  251. else
  252. {
  253. return STATUS_SUCCESS;
  254. }
  255. }
  256. //******************************************************************************
  257. //
  258. // USBSTOR_QueryFdoParams()
  259. //
  260. // This is called at AddDevice() time when the FDO is being created to query
  261. // device parameters from the registry.
  262. //
  263. //******************************************************************************
  264. VOID
  265. USBSTOR_QueryFdoParams (
  266. IN PDEVICE_OBJECT DeviceObject
  267. )
  268. {
  269. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  270. RTL_QUERY_REGISTRY_TABLE paramTable[3];
  271. ULONG driverFlags;
  272. ULONG nonRemovable;
  273. HANDLE handle;
  274. NTSTATUS ntStatus;
  275. PAGED_CODE();
  276. DBGPRINT(2, ("enter: USBSTOR_QueryFdoParams\n"));
  277. fdoDeviceExtension = DeviceObject->DeviceExtension;
  278. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  279. // Set the default value in case the registry key does not exist.
  280. // Currently the flags are only used to specify the device protocol:
  281. // {Bulk-Only, Control/Bulk/Interrupt, Control/Bulk}
  282. //
  283. // If the driver is loaded during textmode setup then the registry key
  284. // will not yet exist. That should be the only case in which the registry
  285. // key does not exist. In this case DeviceProtocolUnspecified will be
  286. // treated as DeviceProtocolCB. If that causes the first request to fail
  287. // then we will switch to DeviceProtocolBulkOnly.
  288. //
  289. driverFlags = DeviceProtocolUnspecified;
  290. nonRemovable = 0;
  291. ntStatus = IoOpenDeviceRegistryKey(
  292. fdoDeviceExtension->PhysicalDeviceObject,
  293. PLUGPLAY_REGKEY_DRIVER,
  294. STANDARD_RIGHTS_ALL,
  295. &handle);
  296. if (NT_SUCCESS(ntStatus))
  297. {
  298. RtlZeroMemory (&paramTable[0], sizeof(paramTable));
  299. paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  300. paramTable[0].Name = L"DriverFlags";
  301. paramTable[0].EntryContext = &driverFlags;
  302. paramTable[0].DefaultType = REG_BINARY;
  303. paramTable[0].DefaultData = &driverFlags;
  304. paramTable[0].DefaultLength = sizeof(ULONG);
  305. paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
  306. paramTable[1].Name = L"NonRemovable";
  307. paramTable[1].EntryContext = &nonRemovable;
  308. paramTable[1].DefaultType = REG_BINARY;
  309. paramTable[1].DefaultData = &nonRemovable;
  310. paramTable[1].DefaultLength = sizeof(ULONG);
  311. RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  312. (PCWSTR)handle,
  313. &paramTable[0],
  314. NULL, // Context
  315. NULL); // Environment
  316. ZwClose(handle);
  317. }
  318. if (driverFlags >= DeviceProtocolLast)
  319. {
  320. driverFlags = DeviceProtocolUnspecified;
  321. }
  322. fdoDeviceExtension->DriverFlags = driverFlags;
  323. fdoDeviceExtension->NonRemovable = nonRemovable;
  324. DBGPRINT(2, ("deviceFlags %08X\n", driverFlags));
  325. DBGPRINT(2, ("nonRemovable %08X\n", nonRemovable));
  326. DBGPRINT(2, ("exit: USBSTOR_QueryFdoParams\n"));
  327. }
  328. //******************************************************************************
  329. //
  330. // USBSTOR_QueryGlobalFdoParams()
  331. //
  332. // This is called at START_DEVICE time to query device parameters from
  333. // the registry from a globabl key which is not device instance
  334. // specific.
  335. //
  336. // It assumes that a valid Device Descriptor has already been retrieved
  337. // from the device so the device idVendor and idProduct are already
  338. // known.
  339. //
  340. //******************************************************************************
  341. VOID
  342. USBSTOR_QueryGlobalFdoParams (
  343. IN PDEVICE_OBJECT DeviceObject
  344. )
  345. {
  346. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  347. WCHAR path[] = L"usbstor\\vvvvpppp";
  348. USHORT idVendor;
  349. USHORT idProduct;
  350. ULONG i;
  351. static WCHAR NibbleW[] = {'0','1','2','3','4','5','6','7',
  352. '8','9','a','b','c','d','e','f'};
  353. ULONG driverFlags;
  354. RTL_QUERY_REGISTRY_TABLE paramTable[2];
  355. NTSTATUS ntStatus;
  356. PAGED_CODE();
  357. DBGPRINT(2, ("enter: USBSTOR_QueryGlobalFdoParams\n"));
  358. fdoDeviceExtension = DeviceObject->DeviceExtension;
  359. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  360. // If we already know what the device protocol is then skip reading
  361. // the global setting from the registry.
  362. //
  363. if (fdoDeviceExtension->DriverFlags == DeviceProtocolUnspecified)
  364. {
  365. // Build the registry path string for the device
  366. //
  367. idVendor = fdoDeviceExtension->DeviceDescriptor->idVendor;
  368. idProduct = fdoDeviceExtension->DeviceDescriptor->idProduct;
  369. i = sizeof("usbstor\\") - 1;
  370. path[i++] = NibbleW[idVendor >> 12];
  371. path[i++] = NibbleW[(idVendor >> 8) & 0x000f];
  372. path[i++] = NibbleW[(idVendor >> 4) & 0x000f];
  373. path[i++] = NibbleW[idVendor & 0x000f];
  374. path[i++] = NibbleW[idProduct >> 12];
  375. path[i++] = NibbleW[(idProduct >> 8) & 0x000f];
  376. path[i++] = NibbleW[(idProduct >> 4) & 0x000f];
  377. path[i++] = NibbleW[idProduct & 0x000f];
  378. // Set the default value
  379. //
  380. driverFlags = DeviceProtocolUnspecified;
  381. // Intialize the registry query table
  382. //
  383. RtlZeroMemory (&paramTable[0], sizeof(paramTable));
  384. paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  385. paramTable[0].Name = L"DriverFlags";
  386. paramTable[0].EntryContext = &driverFlags;
  387. paramTable[0].DefaultType = REG_BINARY;
  388. paramTable[0].DefaultData = &driverFlags;
  389. paramTable[0].DefaultLength = sizeof(ULONG);
  390. ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
  391. path,
  392. &paramTable[0],
  393. NULL, // Context
  394. NULL); // Environment
  395. if (NT_SUCCESS(ntStatus) && driverFlags < DeviceProtocolLast)
  396. {
  397. fdoDeviceExtension->DriverFlags = driverFlags;
  398. }
  399. DBGPRINT(2, ("driverFlags %08X\n", driverFlags));
  400. }
  401. DBGPRINT(2, ("exit: USBSTOR_QueryGlobalFdoParams\n"));
  402. }
  403. //******************************************************************************
  404. //
  405. // USBSTOR_Power()
  406. //
  407. // Dispatch routine which handles IRP_MJ_POWER
  408. //
  409. //******************************************************************************
  410. NTSTATUS
  411. USBSTOR_Power (
  412. IN PDEVICE_OBJECT DeviceObject,
  413. IN PIRP Irp
  414. )
  415. {
  416. PDEVICE_EXTENSION deviceExtension;
  417. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  418. PIO_STACK_LOCATION irpStack;
  419. NTSTATUS ntStatus;
  420. PAGED_CODE();
  421. deviceExtension = DeviceObject->DeviceExtension;
  422. irpStack = IoGetCurrentIrpStackLocation(Irp);
  423. DBGPRINT(2, ("enter: USBSTOR_Power %s %08X %08X %s\n",
  424. (deviceExtension->Type == USBSTOR_DO_TYPE_FDO) ?
  425. "FDO" : "PDO",
  426. DeviceObject,
  427. Irp,
  428. PowerMinorFunctionString(irpStack->MinorFunction)));
  429. LOGENTRY('POWR', DeviceObject, Irp, irpStack->MinorFunction);
  430. if (irpStack->MinorFunction == IRP_MN_SET_POWER)
  431. {
  432. DBGPRINT(2, ("%s IRP_MN_SET_POWER %s\n",
  433. (deviceExtension->Type == USBSTOR_DO_TYPE_FDO) ?
  434. "FDO" : "PDO",
  435. (irpStack->Parameters.Power.Type == SystemPowerState) ?
  436. PowerSystemStateString(irpStack->Parameters.Power.State.SystemState) :
  437. PowerDeviceStateString(irpStack->Parameters.Power.State.DeviceState)));
  438. }
  439. if (deviceExtension->Type == USBSTOR_DO_TYPE_FDO)
  440. {
  441. // This is an FDO attached to the USB PDO.
  442. //
  443. fdoDeviceExtension = (PFDO_DEVICE_EXTENSION)deviceExtension;
  444. if (irpStack->MinorFunction == IRP_MN_SET_POWER)
  445. {
  446. // Handle powering the FDO down and up...
  447. //
  448. ntStatus = USBSTOR_FdoSetPower(DeviceObject,
  449. Irp);
  450. }
  451. else
  452. {
  453. // No special processing for IRP_MN_QUERY_POWER, IRP_MN_WAIT_WAKE,
  454. // or IRP_MN_POWER_SEQUENCE at this time. Just pass the request
  455. // down to the next lower driver now.
  456. //
  457. PoStartNextPowerIrp(Irp);
  458. IoSkipCurrentIrpStackLocation(Irp);
  459. ntStatus = PoCallDriver(fdoDeviceExtension->StackDeviceObject,
  460. Irp);
  461. }
  462. }
  463. else
  464. {
  465. // This is a PDO enumerated by our FDO.
  466. if (irpStack->MinorFunction == IRP_MN_SET_POWER)
  467. {
  468. // Handle powering the PDO down and up...
  469. //
  470. ntStatus = USBSTOR_PdoSetPower(DeviceObject,
  471. Irp);
  472. }
  473. else
  474. {
  475. if (irpStack->MinorFunction == IRP_MN_QUERY_POWER)
  476. {
  477. // Always return SUCCESS for IRP_MN_QUERY_POWER for the PDO.
  478. //
  479. ntStatus = STATUS_SUCCESS;
  480. Irp->IoStatus.Status = ntStatus;
  481. }
  482. else
  483. {
  484. // No special processing for IRP_MN_WAIT_WAKE or
  485. // IRP_MN_POWER_SEQUENCE. Just complete the request
  486. // now without changing the status.
  487. //
  488. ntStatus = Irp->IoStatus.Status;
  489. }
  490. PoStartNextPowerIrp(Irp);
  491. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  492. }
  493. }
  494. DBGPRINT(2, ("exit: USBSTOR_Power %08X\n", ntStatus));
  495. LOGENTRY('powr', ntStatus, 0, 0);
  496. return ntStatus;
  497. }
  498. //******************************************************************************
  499. //
  500. // USBSTOR_FdoSetPower()
  501. //
  502. // Dispatch routine which handles IRP_MJ_POWER, IRP_MN_SET_POWER for the FDO
  503. //
  504. //******************************************************************************
  505. NTSTATUS
  506. USBSTOR_FdoSetPower (
  507. IN PDEVICE_OBJECT DeviceObject,
  508. IN PIRP Irp
  509. )
  510. {
  511. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  512. PIO_STACK_LOCATION irpStack;
  513. POWER_STATE_TYPE powerType;
  514. POWER_STATE powerState;
  515. POWER_STATE newState;
  516. BOOLEAN passRequest;
  517. NTSTATUS ntStatus;
  518. PAGED_CODE();
  519. fdoDeviceExtension = DeviceObject->DeviceExtension;
  520. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  521. // Get our Irp parameters
  522. //
  523. irpStack = IoGetCurrentIrpStackLocation(Irp);
  524. powerType = irpStack->Parameters.Power.Type;
  525. powerState = irpStack->Parameters.Power.State;
  526. DBGPRINT(2, ("enter: USBSTOR_FdoSetPower %08X %s\n",
  527. DeviceObject,
  528. (powerType == SystemPowerState) ?
  529. PowerSystemStateString(powerState.SystemState) :
  530. PowerDeviceStateString(powerState.DeviceState)));
  531. LOGENTRY('FDSP', DeviceObject, Irp, irpStack->MinorFunction);
  532. // Pass the request down here, unless we request a device state power
  533. // Irp, in which case we pass the request down in our completion routine.
  534. //
  535. passRequest = TRUE;
  536. if (powerType == SystemPowerState)
  537. {
  538. // Remember the current system state.
  539. //
  540. fdoDeviceExtension->SystemPowerState = powerState.SystemState;
  541. // Map the new system state to a new device state
  542. //
  543. if (powerState.SystemState != PowerSystemWorking)
  544. {
  545. newState.DeviceState = PowerDeviceD3;
  546. }
  547. else
  548. {
  549. newState.DeviceState = PowerDeviceD0;
  550. }
  551. // If the new device state is different than the current device
  552. // state, request a device state power Irp.
  553. //
  554. if (fdoDeviceExtension->DevicePowerState != newState.DeviceState)
  555. {
  556. DBGPRINT(2, ("Requesting power Irp %08X %08X from %s to %s\n",
  557. DeviceObject, Irp,
  558. PowerDeviceStateString(fdoDeviceExtension->DevicePowerState),
  559. PowerDeviceStateString(newState.DeviceState)));
  560. ASSERT(fdoDeviceExtension->CurrentPowerIrp == NULL);
  561. fdoDeviceExtension->CurrentPowerIrp = Irp;
  562. ntStatus = PoRequestPowerIrp(fdoDeviceExtension->PhysicalDeviceObject,
  563. IRP_MN_SET_POWER,
  564. newState,
  565. USBSTOR_FdoSetPowerCompletion,
  566. DeviceObject,
  567. NULL);
  568. passRequest = FALSE;
  569. }
  570. }
  571. else if (powerType == DevicePowerState)
  572. {
  573. POWER_STATE oldState;
  574. DBGPRINT(2, ("Received power Irp %08X %08X from %s to %s\n",
  575. DeviceObject, Irp,
  576. PowerDeviceStateString(fdoDeviceExtension->DevicePowerState),
  577. PowerDeviceStateString(powerState.DeviceState)));
  578. // Update the current device state.
  579. //
  580. oldState.DeviceState = fdoDeviceExtension->DevicePowerState;
  581. fdoDeviceExtension->DevicePowerState = powerState.DeviceState;
  582. if (oldState.DeviceState == PowerDeviceD0 &&
  583. powerState.DeviceState > PowerDeviceD0)
  584. {
  585. // Powering down. Stick this Irp in the device queue and
  586. // then wait. When USBSTOR_StartIo() pulls this Irp out
  587. // of the device queue, we'll know that no transfer requests
  588. // are active at that time and then this power Irp can be
  589. // passed down the stack.
  590. ULONG zero;
  591. DBGPRINT(2, ("FDO Powering Down\n"));
  592. LOGENTRY('PWRD', DeviceObject, Irp, 0);
  593. zero = 0; // Front of the queue please
  594. IoStartPacket(DeviceObject,
  595. Irp,
  596. &zero,
  597. NULL);
  598. KeWaitForSingleObject(&fdoDeviceExtension->PowerDownEvent,
  599. Executive,
  600. KernelMode,
  601. FALSE,
  602. NULL);
  603. }
  604. else if (oldState.DeviceState > PowerDeviceD0 &&
  605. powerState.DeviceState == PowerDeviceD0)
  606. {
  607. DBGPRINT(2, ("PDO Powering Up\n"));
  608. LOGENTRY('PWRU', DeviceObject, Irp, 0);
  609. IoCopyCurrentIrpStackLocationToNext(Irp);
  610. IoSetCompletionRoutine(Irp,
  611. USBSTOR_FdoSetPowerD0Completion,
  612. NULL,
  613. TRUE,
  614. TRUE,
  615. TRUE);
  616. ntStatus = PoCallDriver(fdoDeviceExtension->StackDeviceObject,
  617. Irp);
  618. passRequest = FALSE;
  619. }
  620. }
  621. if (passRequest)
  622. {
  623. //
  624. // Pass the request down to the next lower driver
  625. //
  626. PoStartNextPowerIrp(Irp);
  627. IoSkipCurrentIrpStackLocation(Irp);
  628. ntStatus = PoCallDriver(fdoDeviceExtension->StackDeviceObject,
  629. Irp);
  630. }
  631. DBGPRINT(2, ("exit: USBSTOR_FdoSetPower %08X\n", ntStatus));
  632. LOGENTRY('fdsp', ntStatus, 0, 0);
  633. return ntStatus;
  634. }
  635. //******************************************************************************
  636. //
  637. // USBSTOR_FdoSetPowerCompletion()
  638. //
  639. // Completion routine for PoRequestPowerIrp() in USBSTOR_FdoSetPower.
  640. //
  641. // The purpose of this routine is to block passing down the SystemPowerState
  642. // Irp until the requested DevicePowerState Irp completes.
  643. //
  644. //******************************************************************************
  645. VOID
  646. USBSTOR_FdoSetPowerCompletion(
  647. IN PDEVICE_OBJECT PdoDeviceObject,
  648. IN UCHAR MinorFunction,
  649. IN POWER_STATE PowerState,
  650. IN PVOID Context,
  651. IN PIO_STATUS_BLOCK IoStatus
  652. )
  653. {
  654. PDEVICE_OBJECT fdoDeviceObject;
  655. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  656. PIRP irp;
  657. NTSTATUS ntStatus;
  658. fdoDeviceObject = (PDEVICE_OBJECT)Context;
  659. fdoDeviceExtension = fdoDeviceObject->DeviceExtension;
  660. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  661. ASSERT(fdoDeviceExtension->CurrentPowerIrp != NULL);
  662. irp = fdoDeviceExtension->CurrentPowerIrp;
  663. fdoDeviceExtension->CurrentPowerIrp = NULL;
  664. #if DBG
  665. {
  666. PIO_STACK_LOCATION irpStack;
  667. SYSTEM_POWER_STATE systemState;
  668. irpStack = IoGetCurrentIrpStackLocation(irp);
  669. systemState = irpStack->Parameters.Power.State.SystemState;
  670. ntStatus = IoStatus->Status;
  671. DBGPRINT(2, ("USBSTOR_FdoSetPowerCompletion %08X %08X %s %08X\n",
  672. fdoDeviceObject, irp,
  673. PowerSystemStateString(systemState),
  674. ntStatus));
  675. LOGENTRY('fspc', fdoDeviceObject, systemState, ntStatus);
  676. }
  677. #endif
  678. // The requested DevicePowerState Irp has completed.
  679. // Now pass down the SystemPowerState Irp which requested the
  680. // DevicePowerState Irp.
  681. PoStartNextPowerIrp(irp);
  682. IoCopyCurrentIrpStackLocationToNext(irp);
  683. // Mark the Irp pending since USBSTOR_FdoSetPower() would have
  684. // originally returned STATUS_PENDING after calling PoRequestPowerIrp().
  685. //
  686. IoMarkIrpPending(irp);
  687. ntStatus = PoCallDriver(fdoDeviceExtension->StackDeviceObject,
  688. irp);
  689. }
  690. //******************************************************************************
  691. //
  692. // USBSTOR_FdoSetPowerD0Completion()
  693. //
  694. // Completion routine used by USBSTOR_FdoSetPower when passing down a
  695. // IRP_MN_SET_POWER DevicePowerState PowerDeviceD0 Irp for the FDO.
  696. //
  697. // The purpose of this routine is to delay unblocking the device queue
  698. // until after the DevicePowerState PowerDeviceD0 Irp completes.
  699. //
  700. //******************************************************************************
  701. NTSTATUS
  702. USBSTOR_FdoSetPowerD0Completion (
  703. IN PDEVICE_OBJECT DeviceObject,
  704. IN PIRP Irp,
  705. IN PVOID NotUsed
  706. )
  707. {
  708. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  709. PIO_STACK_LOCATION irpStack;
  710. DEVICE_POWER_STATE deviceState;
  711. KIRQL irql;
  712. NTSTATUS ntStatus;
  713. fdoDeviceExtension = DeviceObject->DeviceExtension;
  714. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  715. irpStack = IoGetCurrentIrpStackLocation(Irp);
  716. deviceState = irpStack->Parameters.Power.State.DeviceState;
  717. ASSERT(deviceState == PowerDeviceD0);
  718. ntStatus = Irp->IoStatus.Status;
  719. DBGPRINT(2, ("USBSTOR_FdoSetPowerD0Completion %08X %08X %s %08X\n",
  720. DeviceObject, Irp,
  721. PowerDeviceStateString(deviceState),
  722. ntStatus));
  723. LOGENTRY('fs0c', DeviceObject, deviceState, ntStatus);
  724. // Powering up. Unblock the device queue which was left blocked
  725. // after USBSTOR_StartIo() passed down the power down Irp.
  726. KeRaiseIrql(DISPATCH_LEVEL, &irql);
  727. {
  728. IoStartNextPacket(DeviceObject, TRUE);
  729. }
  730. KeLowerIrql(irql);
  731. PoStartNextPowerIrp(Irp);
  732. return ntStatus;
  733. }
  734. //******************************************************************************
  735. //
  736. // USBSTOR_PdoSetPower()
  737. //
  738. // Dispatch routine which handles IRP_MJ_POWER, IRP_MN_SET_POWER for the PDO
  739. //
  740. //******************************************************************************
  741. NTSTATUS
  742. USBSTOR_PdoSetPower (
  743. IN PDEVICE_OBJECT DeviceObject,
  744. IN PIRP Irp
  745. )
  746. {
  747. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  748. PIO_STACK_LOCATION irpStack;
  749. POWER_STATE_TYPE powerType;
  750. POWER_STATE powerState;
  751. BOOLEAN completeRequest;
  752. NTSTATUS ntStatus;
  753. pdoDeviceExtension = DeviceObject->DeviceExtension;
  754. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  755. // Get our Irp parameters
  756. //
  757. irpStack = IoGetCurrentIrpStackLocation(Irp);
  758. powerType = irpStack->Parameters.Power.Type;
  759. powerState = irpStack->Parameters.Power.State;
  760. DBGPRINT(2, ("enter: USBSTOR_PdoSetPower %08X %s\n",
  761. DeviceObject,
  762. (powerType == SystemPowerState) ?
  763. PowerSystemStateString(powerState.SystemState) :
  764. PowerDeviceStateString(powerState.DeviceState)));
  765. LOGENTRY('PDSP', DeviceObject, Irp, irpStack->MinorFunction);
  766. // Complete the request here and now with success, unless we are powering
  767. // up or down and need to wait before completing the request later.
  768. //
  769. completeRequest = TRUE;
  770. ntStatus = STATUS_SUCCESS;
  771. if (powerType == SystemPowerState)
  772. {
  773. POWER_STATE newState;
  774. // Update the current system state.
  775. //
  776. pdoDeviceExtension->SystemPowerState = powerState.SystemState;
  777. // Map the new system state to a new device state
  778. //
  779. if (powerState.SystemState != PowerSystemWorking)
  780. {
  781. newState.DeviceState = PowerDeviceD3;
  782. }
  783. else
  784. {
  785. newState.DeviceState = PowerDeviceD0;
  786. }
  787. // If the new device state is different than the current device
  788. // state, request a device state power Irp.
  789. //
  790. if (pdoDeviceExtension->DevicePowerState != newState.DeviceState)
  791. {
  792. DBGPRINT(2, ("Requesting power Irp %08X %08X from %s to %s\n",
  793. DeviceObject, Irp,
  794. PowerDeviceStateString(pdoDeviceExtension->DevicePowerState),
  795. PowerDeviceStateString(newState.DeviceState)));
  796. ASSERT(pdoDeviceExtension->CurrentPowerIrp == NULL);
  797. pdoDeviceExtension->CurrentPowerIrp = Irp;
  798. ntStatus = PoRequestPowerIrp(DeviceObject,
  799. IRP_MN_SET_POWER,
  800. newState,
  801. USBSTOR_PdoSetPowerCompletion,
  802. NULL,
  803. NULL);
  804. ASSERT(ntStatus == STATUS_PENDING);
  805. // If PoRequestPowerIrp() failed to allocate a DevicePowerState Irp
  806. // then we need to complete the SystemPowerState Irp now.
  807. //
  808. if (!NT_SUCCESS(ntStatus))
  809. {
  810. completeRequest = TRUE;
  811. pdoDeviceExtension->CurrentPowerIrp = NULL;
  812. }
  813. else
  814. {
  815. completeRequest = FALSE;
  816. }
  817. }
  818. }
  819. else if (powerType == DevicePowerState)
  820. {
  821. POWER_STATE oldState;
  822. DBGPRINT(2, ("Received power Irp %08X %08X from %s to %s\n",
  823. DeviceObject, Irp,
  824. PowerDeviceStateString(pdoDeviceExtension->DevicePowerState),
  825. PowerDeviceStateString(powerState.DeviceState)));
  826. // Update the current device state.
  827. //
  828. oldState.DeviceState = pdoDeviceExtension->DevicePowerState;
  829. pdoDeviceExtension->DevicePowerState = powerState.DeviceState;
  830. if (oldState.DeviceState == PowerDeviceD0 &&
  831. powerState.DeviceState > PowerDeviceD0)
  832. {
  833. // Powering down.
  834. DBGPRINT(2, ("PDO Powering Down\n"));
  835. LOGENTRY('pwrd', DeviceObject, Irp, 0);
  836. }
  837. else if (oldState.DeviceState > PowerDeviceD0 &&
  838. powerState.DeviceState == PowerDeviceD0)
  839. {
  840. // Powering up.
  841. DBGPRINT(2, ("PDO Powering Up\n"));
  842. LOGENTRY('pwru', DeviceObject, Irp, 0);
  843. }
  844. }
  845. if (completeRequest)
  846. {
  847. Irp->IoStatus.Status = ntStatus;
  848. PoStartNextPowerIrp(Irp);
  849. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  850. }
  851. DBGPRINT(2, ("exit: USBSTOR_PdoSetPower %08X\n", ntStatus));
  852. LOGENTRY('pdsp', ntStatus, 0, 0);
  853. return ntStatus;
  854. }
  855. //******************************************************************************
  856. //
  857. // USBSTOR_PdoSetPowerCompletion()
  858. //
  859. // Completion routine for PoRequestPowerIrp() in USBSTOR_PdoSetPower.
  860. //
  861. // The purpose of this routine is to block completing the SystemPowerState
  862. // Irp until the requested DevicePowerState Irp completes.
  863. //
  864. //******************************************************************************
  865. VOID
  866. USBSTOR_PdoSetPowerCompletion(
  867. IN PDEVICE_OBJECT DeviceObject,
  868. IN UCHAR MinorFunction,
  869. IN POWER_STATE PowerState,
  870. IN PVOID Context,
  871. IN PIO_STATUS_BLOCK IoStatus
  872. )
  873. {
  874. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  875. PIRP irp;
  876. pdoDeviceExtension = DeviceObject->DeviceExtension;
  877. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  878. ASSERT(pdoDeviceExtension->CurrentPowerIrp != NULL);
  879. irp = pdoDeviceExtension->CurrentPowerIrp;
  880. pdoDeviceExtension->CurrentPowerIrp = NULL;
  881. #if DBG
  882. {
  883. PIO_STACK_LOCATION irpStack;
  884. SYSTEM_POWER_STATE systemState;
  885. NTSTATUS ntStatus;
  886. irpStack = IoGetCurrentIrpStackLocation(irp);
  887. systemState = irpStack->Parameters.Power.State.SystemState;
  888. ntStatus = IoStatus->Status;
  889. DBGPRINT(2, ("USBSTOR_PdoSetPowerCompletion %08X %08X %s %08X\n",
  890. DeviceObject, irp,
  891. PowerSystemStateString(systemState),
  892. ntStatus));
  893. LOGENTRY('pspc', DeviceObject, systemState, ntStatus);
  894. }
  895. #endif
  896. // The requested DevicePowerState Irp has completed.
  897. // Now complete the SystemPowerState Irp which requested the
  898. // DevicePowerState Irp.
  899. // Mark the Irp pending since USBSTOR_PdoSetPower() would have
  900. // originally returned STATUS_PENDING after calling PoRequestPowerIrp().
  901. //
  902. IoMarkIrpPending(irp);
  903. irp->IoStatus.Status = STATUS_SUCCESS;
  904. PoStartNextPowerIrp(irp);
  905. IoCompleteRequest(irp, IO_NO_INCREMENT);
  906. }
  907. //******************************************************************************
  908. //
  909. // USBSTOR_SystemControl()
  910. //
  911. // Dispatch routine which handles IRP_MJ_SYSTEM_CONTROL
  912. //
  913. //******************************************************************************
  914. NTSTATUS
  915. USBSTOR_SystemControl (
  916. IN PDEVICE_OBJECT DeviceObject,
  917. IN PIRP Irp
  918. )
  919. {
  920. PDEVICE_EXTENSION deviceExtension;
  921. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  922. PIO_STACK_LOCATION irpStack;
  923. NTSTATUS ntStatus;
  924. PAGED_CODE();
  925. deviceExtension = DeviceObject->DeviceExtension;
  926. irpStack = IoGetCurrentIrpStackLocation(Irp);
  927. DBGPRINT(2, ("enter: USBSTOR_SystemControl %2X\n", irpStack->MinorFunction));
  928. LOGENTRY('SYSC', DeviceObject, Irp, irpStack->MinorFunction);
  929. if (deviceExtension->Type == USBSTOR_DO_TYPE_FDO)
  930. {
  931. // This is an FDO attached to the USB PDO.
  932. //
  933. fdoDeviceExtension = DeviceObject->DeviceExtension;
  934. switch (irpStack->MinorFunction)
  935. {
  936. //
  937. // XXXXX Need to handle any of these?
  938. //
  939. default:
  940. //
  941. // Pass the request down to the next lower driver
  942. //
  943. IoSkipCurrentIrpStackLocation(Irp);
  944. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  945. Irp);
  946. break;
  947. }
  948. }
  949. else
  950. {
  951. // This is a PDO enumerated by our FDO.
  952. ntStatus = Irp->IoStatus.Status;
  953. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  954. }
  955. DBGPRINT(2, ("exit: USBSTOR_SystemControl %08X\n", ntStatus));
  956. LOGENTRY('sysc', ntStatus, 0, 0);
  957. return ntStatus;
  958. }
  959. //******************************************************************************
  960. //
  961. // USBSTOR_Pnp()
  962. //
  963. // Dispatch routine which handles IRP_MJ_PNP
  964. //
  965. //******************************************************************************
  966. NTSTATUS
  967. USBSTOR_Pnp (
  968. IN PDEVICE_OBJECT DeviceObject,
  969. IN PIRP Irp
  970. )
  971. {
  972. PDEVICE_EXTENSION deviceExtension;
  973. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  974. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  975. PIO_STACK_LOCATION irpStack;
  976. NTSTATUS ntStatus;
  977. PAGED_CODE();
  978. deviceExtension = DeviceObject->DeviceExtension;
  979. irpStack = IoGetCurrentIrpStackLocation(Irp);
  980. DBGPRINT(2, ("enter: USBSTOR_Pnp %s\n",
  981. PnPMinorFunctionString(irpStack->MinorFunction)));
  982. LOGENTRY('PNP ', DeviceObject, Irp, irpStack->MinorFunction);
  983. if (deviceExtension->Type == USBSTOR_DO_TYPE_FDO)
  984. {
  985. // This is an FDO attached to the USB PDO.
  986. // We have some real work to do.
  987. //
  988. fdoDeviceExtension = DeviceObject->DeviceExtension;
  989. switch (irpStack->MinorFunction)
  990. {
  991. case IRP_MN_START_DEVICE:
  992. ntStatus = USBSTOR_FdoStartDevice(DeviceObject, Irp);
  993. break;
  994. case IRP_MN_STOP_DEVICE:
  995. ntStatus = USBSTOR_FdoStopDevice(DeviceObject, Irp);
  996. break;
  997. case IRP_MN_REMOVE_DEVICE:
  998. ntStatus = USBSTOR_FdoRemoveDevice(DeviceObject, Irp);
  999. break;
  1000. case IRP_MN_QUERY_STOP_DEVICE:
  1001. case IRP_MN_QUERY_REMOVE_DEVICE:
  1002. ntStatus = USBSTOR_FdoQueryStopRemoveDevice(DeviceObject, Irp);
  1003. break;
  1004. case IRP_MN_CANCEL_STOP_DEVICE:
  1005. case IRP_MN_CANCEL_REMOVE_DEVICE:
  1006. ntStatus = USBSTOR_FdoCancelStopRemoveDevice(DeviceObject, Irp);
  1007. break;
  1008. case IRP_MN_QUERY_DEVICE_RELATIONS:
  1009. ntStatus = USBSTOR_FdoQueryDeviceRelations(DeviceObject, Irp);
  1010. break;
  1011. case IRP_MN_QUERY_CAPABILITIES:
  1012. ntStatus = USBSTOR_FdoQueryCapabilities(DeviceObject, Irp);
  1013. break;
  1014. case IRP_MN_SURPRISE_REMOVAL:
  1015. //
  1016. // The documentation says to set the status before passing the
  1017. // Irp down the stack
  1018. //
  1019. Irp->IoStatus.Status = STATUS_SUCCESS;
  1020. // nothing else special yet, just fall through to default
  1021. default:
  1022. //
  1023. // Pass the request down to the next lower driver
  1024. //
  1025. IoSkipCurrentIrpStackLocation(Irp);
  1026. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  1027. Irp);
  1028. break;
  1029. }
  1030. }
  1031. else
  1032. {
  1033. // This is a PDO enumerated by our FDO.
  1034. // We don't have too much to do.
  1035. //
  1036. pdoDeviceExtension = DeviceObject->DeviceExtension;
  1037. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  1038. switch (irpStack->MinorFunction)
  1039. {
  1040. case IRP_MN_START_DEVICE:
  1041. ntStatus = USBSTOR_PdoStartDevice(DeviceObject, Irp);
  1042. break;
  1043. case IRP_MN_QUERY_ID:
  1044. ntStatus = USBSTOR_PdoQueryID(DeviceObject, Irp);
  1045. break;
  1046. case IRP_MN_QUERY_DEVICE_TEXT:
  1047. ntStatus = USBSTOR_PdoQueryDeviceText(DeviceObject, Irp);
  1048. break;
  1049. case IRP_MN_QUERY_DEVICE_RELATIONS:
  1050. ntStatus = USBSTOR_PdoQueryDeviceRelations(DeviceObject, Irp);
  1051. break;
  1052. case IRP_MN_QUERY_CAPABILITIES:
  1053. ntStatus = USBSTOR_PdoQueryCapabilities(DeviceObject, Irp);
  1054. break;
  1055. case IRP_MN_REMOVE_DEVICE:
  1056. ntStatus = USBSTOR_PdoRemoveDevice(DeviceObject, Irp);
  1057. break;
  1058. case IRP_MN_SURPRISE_REMOVAL:
  1059. case IRP_MN_STOP_DEVICE:
  1060. case IRP_MN_QUERY_STOP_DEVICE:
  1061. case IRP_MN_QUERY_REMOVE_DEVICE:
  1062. case IRP_MN_CANCEL_STOP_DEVICE:
  1063. case IRP_MN_CANCEL_REMOVE_DEVICE:
  1064. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  1065. // We have no value add for IRP_MN_QUERY_PNP_DEVICE_STATE
  1066. // at the moment. At some point we might have reason to
  1067. // return PNP_DEVICE_REMOVED or PNP_DEVICE_FAILED.
  1068. DBGPRINT(2, ("Succeeding PnP for Child PDO %s\n",
  1069. PnPMinorFunctionString(irpStack->MinorFunction)));
  1070. ntStatus = STATUS_SUCCESS;
  1071. Irp->IoStatus.Status = ntStatus;
  1072. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1073. break;
  1074. default:
  1075. DBGPRINT(2, ("Unhandled PnP Irp for Child PDO %s\n",
  1076. PnPMinorFunctionString(irpStack->MinorFunction)));
  1077. ntStatus = Irp->IoStatus.Status;
  1078. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1079. break;
  1080. }
  1081. }
  1082. DBGPRINT(2, ("exit: USBSTOR_Pnp %08X\n", ntStatus));
  1083. LOGENTRY('pnp ', ntStatus, 0, 0);
  1084. return ntStatus;
  1085. }
  1086. //******************************************************************************
  1087. //
  1088. // USBSTOR_FdoStartDevice()
  1089. //
  1090. // This routine handles IRP_MJ_PNP, IRP_MN_START_DEVICE for the FDO
  1091. //
  1092. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  1093. // system thread.
  1094. //
  1095. // This IRP must be handled first by the underlying bus driver for a device
  1096. // and then by each higher driver in the device stack.
  1097. //
  1098. //******************************************************************************
  1099. NTSTATUS
  1100. USBSTOR_FdoStartDevice (
  1101. IN PDEVICE_OBJECT DeviceObject,
  1102. IN PIRP Irp
  1103. )
  1104. {
  1105. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1106. USB_BUS_INTERFACE_USBDI_V1 busInterface;
  1107. NTSTATUS ntStatus;
  1108. PAGED_CODE();
  1109. DBGPRINT(2, ("enter: USBSTOR_FdoStartDevice\n"));
  1110. DBGFBRK(DBGF_BRK_STARTDEVICE);
  1111. LOGENTRY('STRT', DeviceObject, Irp, 0);
  1112. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1113. // Pass IRP_MN_START_DEVICE Irp down the stack first before we do anything.
  1114. //
  1115. ntStatus = USBSTOR_SyncPassDownIrp(DeviceObject,
  1116. Irp);
  1117. if (!NT_SUCCESS(ntStatus))
  1118. {
  1119. DBGPRINT(1, ("Lower driver failed IRP_MN_START_DEVICE\n"));
  1120. goto USBSTOR_FdoStartDeviceDone;
  1121. }
  1122. // Allocate Reset Pipe / Reset Port IoWorkItem
  1123. //
  1124. if (fdoDeviceExtension->IoWorkItem == NULL)
  1125. {
  1126. fdoDeviceExtension->IoWorkItem = IoAllocateWorkItem(DeviceObject);
  1127. if (fdoDeviceExtension->IoWorkItem == NULL)
  1128. {
  1129. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1130. goto USBSTOR_FdoStartDeviceDone;
  1131. }
  1132. }
  1133. // If this is the first time the device as been started, retrieve the
  1134. // Device and Configuration Descriptors from the device.
  1135. //
  1136. if (fdoDeviceExtension->DeviceDescriptor == NULL)
  1137. {
  1138. ntStatus = USBSTOR_GetDescriptors(DeviceObject);
  1139. if (!NT_SUCCESS(ntStatus))
  1140. {
  1141. goto USBSTOR_FdoStartDeviceDone;
  1142. }
  1143. // Query any registry parameters that are global to all
  1144. // instances of this device.
  1145. //
  1146. USBSTOR_QueryGlobalFdoParams(DeviceObject);
  1147. }
  1148. // Now configure the device
  1149. //
  1150. ntStatus = USBSTOR_SelectConfiguration(DeviceObject);
  1151. if (!NT_SUCCESS(ntStatus))
  1152. {
  1153. DBGPRINT(1, ("Configure device failed\n"));
  1154. goto USBSTOR_FdoStartDeviceDone;
  1155. }
  1156. // If the driver is loaded during textmode setup then the registry
  1157. // value won't exist yet to indicate what type of device this is. If
  1158. // the Interface Descriptor indicates that the device is a Bulk-Only
  1159. // device then believe it.
  1160. //
  1161. if ((fdoDeviceExtension->InterfaceDescriptor->bInterfaceClass ==
  1162. USB_DEVICE_CLASS_STORAGE) &&
  1163. (fdoDeviceExtension->InterfaceDescriptor->bInterfaceProtocol ==
  1164. USBSTOR_PROTOCOL_BULK_ONLY) &&
  1165. (fdoDeviceExtension->DriverFlags == DeviceProtocolUnspecified))
  1166. {
  1167. fdoDeviceExtension->DriverFlags = DeviceProtocolBulkOnly;
  1168. }
  1169. // Find the bulk and interrupt pipes we'll use in this configuration.
  1170. //
  1171. ntStatus = USBSTOR_GetPipes(DeviceObject);
  1172. if (!NT_SUCCESS(ntStatus))
  1173. {
  1174. goto USBSTOR_FdoStartDeviceDone;
  1175. }
  1176. // Enable hacks for certain revs of the Y-E Data USB Floppy
  1177. //
  1178. if (fdoDeviceExtension->DeviceDescriptor->idVendor == 0x057B &&
  1179. fdoDeviceExtension->DeviceDescriptor->idProduct == 0x0000 &&
  1180. fdoDeviceExtension->DeviceDescriptor->bcdDevice < 0x0128)
  1181. {
  1182. SET_FLAG(fdoDeviceExtension->DeviceHackFlags, DHF_FORCE_REQUEST_SENSE);
  1183. #if 0
  1184. SET_FLAG(fdoDeviceExtension->DeviceHackFlags, DHF_TUR_START_UNIT);
  1185. SET_FLAG(fdoDeviceExtension->DeviceHackFlags, DHF_MEDIUM_CHANGE_RESET);
  1186. #endif
  1187. }
  1188. // Start timeout timer
  1189. //
  1190. IoStartTimer(DeviceObject);
  1191. // Everything looks good so far, go ahead and create the list of
  1192. // child PDOs if this is the first time we have been started and
  1193. // the list is empty.
  1194. //
  1195. if (IsListEmpty(&fdoDeviceExtension->ChildPDOs))
  1196. {
  1197. UCHAR maxLun;
  1198. UCHAR lun;
  1199. maxLun = 0;
  1200. // Only check devices which claim to be USB Mass Storage Class
  1201. // Bulk-Only spec compliant for Multiple LUN support.
  1202. //
  1203. if ((fdoDeviceExtension->InterfaceDescriptor->bInterfaceClass ==
  1204. USB_DEVICE_CLASS_STORAGE) &&
  1205. (fdoDeviceExtension->InterfaceDescriptor->bInterfaceProtocol ==
  1206. USBSTOR_PROTOCOL_BULK_ONLY))
  1207. {
  1208. // See if the device supports Multiple LUNs
  1209. //
  1210. ntStatus = USBSTOR_GetMaxLun(DeviceObject,
  1211. &maxLun);
  1212. if (NT_SUCCESS(ntStatus))
  1213. {
  1214. DBGPRINT(1, ("GetMaxLun returned %02x\n", maxLun));
  1215. // We need to provide a unique InstanceID for each logical unit.
  1216. // We use the device USB SerialNumber string as part of the
  1217. // unique InstanceID. Without a device USB SerialNumber string
  1218. // we can't support multiple logical units on the device.
  1219. //
  1220. // The Bulk-Only USB Mass Storage class specification requires
  1221. // a SerialNumber string so if the device does not have one it
  1222. // is not really spec compliant anyway.
  1223. //
  1224. if (fdoDeviceExtension->SerialNumber == NULL)
  1225. {
  1226. DBGPRINT(1, ("Multiple Lun but no SerialNumber!\n"));
  1227. maxLun = 0;
  1228. }
  1229. }
  1230. }
  1231. for (lun = 0; lun <= maxLun; lun++)
  1232. {
  1233. ntStatus = USBSTOR_CreateChildPDO(DeviceObject, lun);
  1234. if (!NT_SUCCESS(ntStatus))
  1235. {
  1236. DBGPRINT(1, ("Create Child PDO %d failed\n", lun));
  1237. goto USBSTOR_FdoStartDeviceDone;
  1238. }
  1239. }
  1240. }
  1241. if (NT_SUCCESS(USBSTOR_GetBusInterface(DeviceObject, &busInterface)))
  1242. {
  1243. fdoDeviceExtension->DeviceIsHighSpeed =
  1244. busInterface.IsDeviceHighSpeed(busInterface.BusContext);
  1245. DBGPRINT(1, ("DeviceIsHighSpeed: %s\n",
  1246. fdoDeviceExtension->DeviceIsHighSpeed ? "TRUE" : "FALSE"));
  1247. }
  1248. else
  1249. {
  1250. fdoDeviceExtension->DeviceIsHighSpeed = FALSE;
  1251. }
  1252. USBSTOR_FdoStartDeviceDone:
  1253. // Must complete request since completion routine returned
  1254. // STATUS_MORE_PROCESSING_REQUIRED
  1255. //
  1256. Irp->IoStatus.Status = ntStatus;
  1257. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1258. DBGPRINT(2, ("exit: USBSTOR_FdoStartDevice %08X\n", ntStatus));
  1259. LOGENTRY('strt', ntStatus, 0, 0);
  1260. return ntStatus;
  1261. }
  1262. //******************************************************************************
  1263. //
  1264. // USBSTOR_GetDescriptors()
  1265. //
  1266. // This routine is called at START_DEVICE time for the FDO to retrieve the
  1267. // Device and Configurations descriptors from the device and store them in
  1268. // the device extension.
  1269. //
  1270. //******************************************************************************
  1271. NTSTATUS
  1272. USBSTOR_GetDescriptors (
  1273. IN PDEVICE_OBJECT DeviceObject
  1274. )
  1275. {
  1276. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1277. PUCHAR descriptor;
  1278. ULONG descriptorLength;
  1279. NTSTATUS ntStatus;
  1280. PAGED_CODE();
  1281. DBGPRINT(2, ("enter: USBSTOR_GetDescriptors\n"));
  1282. LOGENTRY('GDSC', DeviceObject, 0, 0);
  1283. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1284. //
  1285. // Get Device Descriptor
  1286. //
  1287. ntStatus = USBSTOR_GetDescriptor(DeviceObject,
  1288. USB_RECIPIENT_DEVICE,
  1289. USB_DEVICE_DESCRIPTOR_TYPE,
  1290. 0, // Index
  1291. 0, // LanguageId
  1292. 2, // RetryCount
  1293. sizeof(USB_DEVICE_DESCRIPTOR),
  1294. &descriptor);
  1295. if (!NT_SUCCESS(ntStatus))
  1296. {
  1297. DBGPRINT(1, ("Get Device Descriptor failed\n"));
  1298. goto USBSTOR_GetDescriptorsDone;
  1299. }
  1300. ASSERT(fdoDeviceExtension->DeviceDescriptor == NULL);
  1301. fdoDeviceExtension->DeviceDescriptor = (PUSB_DEVICE_DESCRIPTOR)descriptor;
  1302. //
  1303. // Get Configuration Descriptor (just the Configuration Descriptor)
  1304. //
  1305. ntStatus = USBSTOR_GetDescriptor(DeviceObject,
  1306. USB_RECIPIENT_DEVICE,
  1307. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  1308. 0, // Index
  1309. 0, // LanguageId
  1310. 2, // RetryCount
  1311. sizeof(USB_CONFIGURATION_DESCRIPTOR),
  1312. &descriptor);
  1313. if (!NT_SUCCESS(ntStatus))
  1314. {
  1315. DBGPRINT(1, ("Get Configuration Descriptor failed (1)\n"));
  1316. goto USBSTOR_GetDescriptorsDone;
  1317. }
  1318. descriptorLength = ((PUSB_CONFIGURATION_DESCRIPTOR)descriptor)->wTotalLength;
  1319. ExFreePool(descriptor);
  1320. if (descriptorLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))
  1321. {
  1322. ntStatus = STATUS_DEVICE_DATA_ERROR;
  1323. DBGPRINT(1, ("Get Configuration Descriptor failed (2)\n"));
  1324. goto USBSTOR_GetDescriptorsDone;
  1325. }
  1326. //
  1327. // Get Configuration Descriptor (and Interface and Endpoint Descriptors)
  1328. //
  1329. ntStatus = USBSTOR_GetDescriptor(DeviceObject,
  1330. USB_RECIPIENT_DEVICE,
  1331. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  1332. 0, // Index
  1333. 0, // LanguageId
  1334. 2, // RetryCount
  1335. descriptorLength,
  1336. &descriptor);
  1337. if (!NT_SUCCESS(ntStatus))
  1338. {
  1339. DBGPRINT(1, ("Get Configuration Descriptor failed (3)\n"));
  1340. goto USBSTOR_GetDescriptorsDone;
  1341. }
  1342. ASSERT(fdoDeviceExtension->ConfigurationDescriptor == NULL);
  1343. fdoDeviceExtension->ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)descriptor;
  1344. //
  1345. // Get the Serial Number String Descriptor, if there is one
  1346. //
  1347. if (fdoDeviceExtension->DeviceDescriptor->iSerialNumber)
  1348. {
  1349. USBSTOR_GetStringDescriptors(DeviceObject);
  1350. }
  1351. #if DBG
  1352. DumpDeviceDesc(fdoDeviceExtension->DeviceDescriptor);
  1353. DumpConfigDesc(fdoDeviceExtension->ConfigurationDescriptor);
  1354. #endif
  1355. USBSTOR_GetDescriptorsDone:
  1356. DBGPRINT(2, ("exit: USBSTOR_GetDescriptors %08X\n", ntStatus));
  1357. LOGENTRY('gdsc', ntStatus, 0, 0);
  1358. return ntStatus;
  1359. }
  1360. //******************************************************************************
  1361. //
  1362. // USBSTOR_GetStringDescriptors()
  1363. //
  1364. // This routine is called at START_DEVICE time for the FDO to retrieve the
  1365. // Serial Number string descriptor from the device and store it in
  1366. // the device extension.
  1367. //
  1368. //******************************************************************************
  1369. USBSTOR_GetStringDescriptors (
  1370. IN PDEVICE_OBJECT DeviceObject
  1371. )
  1372. {
  1373. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1374. PUCHAR descriptor;
  1375. ULONG descriptorLength;
  1376. USHORT languageId;
  1377. ULONG i, numIds;
  1378. NTSTATUS ntStatus;
  1379. PAGED_CODE();
  1380. DBGPRINT(2, ("enter: USBSTOR_GetStringDescriptors\n"));
  1381. LOGENTRY('GSDC', DeviceObject, 0, 0);
  1382. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1383. //
  1384. // Get the list of Language IDs (descriptor header only)
  1385. //
  1386. ntStatus = USBSTOR_GetDescriptor(DeviceObject,
  1387. USB_RECIPIENT_DEVICE,
  1388. USB_STRING_DESCRIPTOR_TYPE,
  1389. 0, // Index
  1390. 0, // LanguageId
  1391. 2, // RetryCount
  1392. sizeof(USB_COMMON_DESCRIPTOR),
  1393. &descriptor);
  1394. if (!NT_SUCCESS(ntStatus))
  1395. {
  1396. DBGPRINT(1, ("Get Language IDs failed (1) %08X\n", ntStatus));
  1397. goto USBSTOR_GetStringDescriptorsDone;
  1398. }
  1399. descriptorLength = ((PUSB_COMMON_DESCRIPTOR)descriptor)->bLength;
  1400. ExFreePool(descriptor);
  1401. if ((descriptorLength < sizeof(USB_COMMON_DESCRIPTOR) + sizeof(USHORT)) ||
  1402. (descriptorLength & 1))
  1403. {
  1404. ntStatus = STATUS_DEVICE_DATA_ERROR;
  1405. DBGPRINT(1, ("Get Language IDs failed (2) %d\n", descriptorLength));
  1406. goto USBSTOR_GetStringDescriptorsDone;
  1407. }
  1408. //
  1409. // Get the list of Language IDs (complete descriptor)
  1410. //
  1411. ntStatus = USBSTOR_GetDescriptor(DeviceObject,
  1412. USB_RECIPIENT_DEVICE,
  1413. USB_STRING_DESCRIPTOR_TYPE,
  1414. 0, // Index
  1415. 0, // LanguageId
  1416. 2, // RetryCount
  1417. descriptorLength,
  1418. &descriptor);
  1419. if (!NT_SUCCESS(ntStatus))
  1420. {
  1421. DBGPRINT(1, ("Get Language IDs failed (3) %08X\n", ntStatus));
  1422. goto USBSTOR_GetStringDescriptorsDone;
  1423. }
  1424. // Search the list of LanguageIDs for US-English (0x0409). If we find
  1425. // it in the list, that's the LanguageID we'll use. Else just default
  1426. // to the first LanguageID in the list.
  1427. numIds = (descriptorLength - sizeof(USB_COMMON_DESCRIPTOR)) / sizeof(USHORT);
  1428. languageId = ((PUSHORT)descriptor)[1];
  1429. for (i = 2; i <= numIds; i++)
  1430. {
  1431. if (((PUSHORT)descriptor)[i] == 0x0409)
  1432. {
  1433. languageId = 0x0409;
  1434. break;
  1435. }
  1436. }
  1437. ExFreePool(descriptor);
  1438. //
  1439. // Get the Serial Number (descriptor header only)
  1440. //
  1441. ntStatus = USBSTOR_GetDescriptor(DeviceObject,
  1442. USB_RECIPIENT_DEVICE,
  1443. USB_STRING_DESCRIPTOR_TYPE,
  1444. fdoDeviceExtension->DeviceDescriptor->iSerialNumber,
  1445. languageId,
  1446. 2, // RetryCount
  1447. sizeof(USB_COMMON_DESCRIPTOR),
  1448. &descriptor);
  1449. if (!NT_SUCCESS(ntStatus))
  1450. {
  1451. DBGPRINT(1, ("Get Serial Number failed (1) %08X\n", ntStatus));
  1452. goto USBSTOR_GetStringDescriptorsDone;
  1453. }
  1454. descriptorLength = ((PUSB_COMMON_DESCRIPTOR)descriptor)->bLength;
  1455. ExFreePool(descriptor);
  1456. if ((descriptorLength < sizeof(USB_COMMON_DESCRIPTOR) + sizeof(USHORT)) ||
  1457. (descriptorLength & 1))
  1458. {
  1459. ntStatus = STATUS_DEVICE_DATA_ERROR;
  1460. DBGPRINT(1, ("Get Serial Number failed (2) %d\n", descriptorLength));
  1461. goto USBSTOR_GetStringDescriptorsDone;
  1462. }
  1463. //
  1464. // Get the Serial Number (complete descriptor)
  1465. //
  1466. ntStatus = USBSTOR_GetDescriptor(DeviceObject,
  1467. USB_RECIPIENT_DEVICE,
  1468. USB_STRING_DESCRIPTOR_TYPE,
  1469. fdoDeviceExtension->DeviceDescriptor->iSerialNumber,
  1470. languageId,
  1471. 2, // RetryCount
  1472. descriptorLength,
  1473. &descriptor);
  1474. if (!NT_SUCCESS(ntStatus))
  1475. {
  1476. DBGPRINT(1, ("Get Serial Number failed (3) %08X\n", ntStatus));
  1477. goto USBSTOR_GetStringDescriptorsDone;
  1478. }
  1479. ASSERT(fdoDeviceExtension->SerialNumber == NULL);
  1480. fdoDeviceExtension->SerialNumber = (PUSB_STRING_DESCRIPTOR)descriptor;
  1481. USBSTOR_GetStringDescriptorsDone:
  1482. DBGPRINT(2, ("exit: USBSTOR_GetStringDescriptors %08X %08X\n",
  1483. ntStatus, fdoDeviceExtension->SerialNumber));
  1484. LOGENTRY('gdsc', ntStatus, 0, 0);
  1485. return ntStatus;
  1486. }
  1487. //******************************************************************************
  1488. //
  1489. // USBSTOR_AdjustConfigurationDescriptor()
  1490. //
  1491. // This routine is called at START_DEVICE time for the FDO to adjust the
  1492. // Configuration Descriptor, if necessary.
  1493. //
  1494. // Removes Endpoint Descriptors we won't use. The Configuration Descriptor
  1495. // is modified in place.
  1496. //
  1497. //******************************************************************************
  1498. VOID
  1499. USBSTOR_AdjustConfigurationDescriptor (
  1500. IN PDEVICE_OBJECT DeviceObject,
  1501. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc,
  1502. OUT PUSB_INTERFACE_DESCRIPTOR *InterfaceDesc,
  1503. OUT PLONG BulkInIndex,
  1504. OUT PLONG BulkOutIndex,
  1505. OUT PLONG InterruptInIndex
  1506. )
  1507. {
  1508. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1509. PUCHAR descEnd;
  1510. PUSB_COMMON_DESCRIPTOR commonDesc;
  1511. PUSB_INTERFACE_DESCRIPTOR interfaceDesc;
  1512. PUSB_ENDPOINT_DESCRIPTOR endpointDesc;
  1513. LONG endpointIndex;
  1514. BOOLEAN removeEndpoint;
  1515. PAGED_CODE();
  1516. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1517. descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength;
  1518. commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc;
  1519. interfaceDesc = NULL;
  1520. *BulkInIndex = -1;
  1521. *BulkOutIndex = -1;
  1522. *InterruptInIndex = -1;
  1523. endpointIndex = 0;
  1524. while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd &&
  1525. (PUCHAR)commonDesc + commonDesc->bLength <= descEnd)
  1526. {
  1527. // Is this an Interface Descriptor?
  1528. //
  1529. if ((commonDesc->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) &&
  1530. (commonDesc->bLength == sizeof(USB_INTERFACE_DESCRIPTOR)))
  1531. {
  1532. // Only bother looking at the first Interface Descriptor
  1533. //
  1534. if (interfaceDesc != NULL)
  1535. {
  1536. break;
  1537. }
  1538. // Remember the first Interface Descriptor we have seen
  1539. //
  1540. interfaceDesc = (PUSB_INTERFACE_DESCRIPTOR)commonDesc;
  1541. }
  1542. // Is this an Endpoint Descriptor?
  1543. //
  1544. if ((commonDesc->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE) &&
  1545. (commonDesc->bLength == sizeof(USB_ENDPOINT_DESCRIPTOR)) &&
  1546. (interfaceDesc != NULL))
  1547. {
  1548. endpointDesc = (PUSB_ENDPOINT_DESCRIPTOR)commonDesc;
  1549. #if 0
  1550. removeEndpoint = TRUE;
  1551. #else
  1552. // There is currently a bug in the composite parent driver
  1553. // that doesn't handle the case where the number of
  1554. // endpoints in an Interface Descriptor differs from the
  1555. // Interface Descriptor originally returned by the deivce.
  1556. // Until that bug is fixed avoid the bug by not stripping
  1557. // out endpoints that won't be used.
  1558. //
  1559. removeEndpoint = FALSE;
  1560. #endif
  1561. if (((endpointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) ==
  1562. USB_ENDPOINT_TYPE_BULK) &&
  1563. (USB_ENDPOINT_DIRECTION_IN(endpointDesc->bEndpointAddress)))
  1564. {
  1565. if (*BulkInIndex == -1)
  1566. {
  1567. *BulkInIndex = endpointIndex;
  1568. removeEndpoint = FALSE;
  1569. }
  1570. }
  1571. else if (((endpointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) ==
  1572. USB_ENDPOINT_TYPE_BULK) &&
  1573. (USB_ENDPOINT_DIRECTION_OUT(endpointDesc->bEndpointAddress)))
  1574. {
  1575. if (*BulkOutIndex == -1)
  1576. {
  1577. *BulkOutIndex = endpointIndex;
  1578. removeEndpoint = FALSE;
  1579. }
  1580. }
  1581. else if (((endpointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) ==
  1582. USB_ENDPOINT_TYPE_INTERRUPT) &&
  1583. (USB_ENDPOINT_DIRECTION_IN(endpointDesc->bEndpointAddress)))
  1584. {
  1585. // Only keep the Interrupt endpoint if we know for sure
  1586. // that the device is a CBI device. Don't trust the
  1587. // bInterfaceProtocol value of the device. Devices can lie.
  1588. //
  1589. if ((*InterruptInIndex == -1) &&
  1590. (fdoDeviceExtension->DriverFlags == DeviceProtocolCBI))
  1591. {
  1592. *InterruptInIndex = endpointIndex;
  1593. removeEndpoint = FALSE;
  1594. }
  1595. }
  1596. if (removeEndpoint)
  1597. {
  1598. // Remove this endpoint, we won't use it.
  1599. //
  1600. DBGPRINT(1, ("Removing Endpoint addr %02X, attr %02X\n",
  1601. endpointDesc->bEndpointAddress,
  1602. endpointDesc->bmAttributes));
  1603. RtlMoveMemory(endpointDesc,
  1604. endpointDesc + 1,
  1605. descEnd - (PUCHAR)(endpointDesc + 1));
  1606. ConfigDesc->wTotalLength -= sizeof(USB_ENDPOINT_DESCRIPTOR);
  1607. interfaceDesc->bNumEndpoints -= 1;
  1608. descEnd -= sizeof(USB_ENDPOINT_DESCRIPTOR);
  1609. continue;
  1610. }
  1611. else
  1612. {
  1613. DBGPRINT(1, ("Keeping Endpoint addr %02X, attr %02X\n",
  1614. endpointDesc->bEndpointAddress,
  1615. endpointDesc->bmAttributes));
  1616. endpointIndex++;
  1617. }
  1618. }
  1619. // Advance past this descriptor
  1620. //
  1621. (PUCHAR)commonDesc += commonDesc->bLength;
  1622. }
  1623. ASSERT(*BulkInIndex != -1);
  1624. ASSERT(*BulkOutIndex != -1);
  1625. ASSERT((*InterruptInIndex != -1) ==
  1626. (fdoDeviceExtension->DriverFlags == DeviceProtocolCBI));
  1627. *InterfaceDesc = interfaceDesc;
  1628. }
  1629. //******************************************************************************
  1630. //
  1631. // USBSTOR_GetPipes()
  1632. //
  1633. // This routine is called at START_DEVICE time find the Bulk IN, Bulk OUT,
  1634. // and Interrupt IN endpoints for the device.
  1635. //
  1636. //******************************************************************************
  1637. NTSTATUS
  1638. USBSTOR_GetPipes (
  1639. IN PDEVICE_OBJECT DeviceObject
  1640. )
  1641. {
  1642. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1643. PUSBD_PIPE_INFORMATION pipe;
  1644. ULONG i;
  1645. NTSTATUS ntStatus;
  1646. PAGED_CODE();
  1647. DBGPRINT(2, ("enter: USBSTOR_GetPipes\n"));
  1648. LOGENTRY('GPIP', DeviceObject, 0, 0);
  1649. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1650. fdoDeviceExtension->BulkInPipe = NULL;
  1651. fdoDeviceExtension->BulkOutPipe = NULL;
  1652. fdoDeviceExtension->InterruptInPipe = NULL;
  1653. // Find the Bulk IN, Bulk OUT, and Interrupt IN endpoints.
  1654. //
  1655. for (i=0; i<fdoDeviceExtension->InterfaceInfo->NumberOfPipes; i++)
  1656. {
  1657. pipe = &fdoDeviceExtension->InterfaceInfo->Pipes[i];
  1658. if (pipe->PipeType == UsbdPipeTypeBulk)
  1659. {
  1660. if (USBD_PIPE_DIRECTION_IN(pipe) &&
  1661. fdoDeviceExtension->BulkInPipe == NULL)
  1662. {
  1663. fdoDeviceExtension->BulkInPipe = pipe;
  1664. }
  1665. else if (!USBD_PIPE_DIRECTION_IN(pipe) &&
  1666. fdoDeviceExtension->BulkOutPipe == NULL)
  1667. {
  1668. fdoDeviceExtension->BulkOutPipe = pipe;
  1669. }
  1670. }
  1671. else if (pipe->PipeType == UsbdPipeTypeInterrupt)
  1672. {
  1673. if (USBD_PIPE_DIRECTION_IN(pipe) &&
  1674. fdoDeviceExtension->InterruptInPipe == NULL &&
  1675. fdoDeviceExtension->DriverFlags == DeviceProtocolCBI)
  1676. {
  1677. fdoDeviceExtension->InterruptInPipe = pipe;
  1678. }
  1679. }
  1680. }
  1681. ntStatus = STATUS_SUCCESS;
  1682. if (fdoDeviceExtension->BulkInPipe == NULL)
  1683. {
  1684. DBGPRINT(1, ("Missing Bulk IN pipe\n"));
  1685. ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
  1686. }
  1687. if (fdoDeviceExtension->BulkOutPipe == NULL)
  1688. {
  1689. DBGPRINT(1, ("Missing Bulk OUT pipe\n"));
  1690. ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
  1691. }
  1692. DBGPRINT(2, ("exit: USBSTOR_GetPipes %08X\n", ntStatus));
  1693. LOGENTRY('gpip', ntStatus, fdoDeviceExtension->BulkInPipe,
  1694. fdoDeviceExtension->BulkOutPipe);
  1695. return ntStatus;
  1696. }
  1697. //******************************************************************************
  1698. //
  1699. // USBSTOR_CreateChildPDO()
  1700. //
  1701. // This routine is called during START_DEVICE of the FDO to create the
  1702. // child PDO. This is only called the first time the FDO is started,
  1703. // after the device has its USB configuration selected.
  1704. //
  1705. //******************************************************************************
  1706. NTSTATUS
  1707. USBSTOR_CreateChildPDO (
  1708. IN PDEVICE_OBJECT FdoDeviceObject,
  1709. IN UCHAR Lun
  1710. )
  1711. {
  1712. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1713. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  1714. PDEVICE_OBJECT pdoDeviceObject;
  1715. NTSTATUS ntStatus;
  1716. PAGED_CODE();
  1717. DBGPRINT(2, ("enter: USBSTOR_CreateChildPDO %d\n", Lun));
  1718. LOGENTRY('CCPD', FdoDeviceObject, Lun, 0);
  1719. fdoDeviceExtension = FdoDeviceObject->DeviceExtension;
  1720. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  1721. // Create the PDO
  1722. //
  1723. ntStatus = IoCreateDevice(FdoDeviceObject->DriverObject,
  1724. sizeof(PDO_DEVICE_EXTENSION),
  1725. NULL,
  1726. FILE_DEVICE_MASS_STORAGE,
  1727. (FILE_AUTOGENERATED_DEVICE_NAME |
  1728. FILE_DEVICE_SECURE_OPEN),
  1729. FALSE,
  1730. &pdoDeviceObject);
  1731. if (!NT_SUCCESS(ntStatus))
  1732. {
  1733. return ntStatus;
  1734. }
  1735. // The PDO and the FDO are effectively at the same stack level.
  1736. // Irps directed at the PDO will sometimes be passed down with
  1737. // IoCallDriver() to the FDO->StackDeviceObject.
  1738. //
  1739. pdoDeviceObject->StackSize = FdoDeviceObject->StackSize;
  1740. // Initialize the PDO DeviceExtension
  1741. //
  1742. pdoDeviceExtension = pdoDeviceObject->DeviceExtension;
  1743. // Set all DeviceExtension pointers to NULL and all variable to zero
  1744. //
  1745. RtlZeroMemory(pdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
  1746. // Tag this as a PDO which is the child of an FDO
  1747. //
  1748. pdoDeviceExtension->Type = USBSTOR_DO_TYPE_PDO;
  1749. // Point back to our own DeviceObject
  1750. //
  1751. pdoDeviceExtension->PdoDeviceObject = pdoDeviceObject;
  1752. // Remember the PDO's parent FDO
  1753. //
  1754. pdoDeviceExtension->ParentFDO = FdoDeviceObject;
  1755. // Set the initial system and device power states
  1756. //
  1757. pdoDeviceExtension->SystemPowerState = PowerSystemWorking;
  1758. pdoDeviceExtension->DevicePowerState = PowerDeviceD0;
  1759. // Initialize the PDO's PnP device state
  1760. //
  1761. pdoDeviceExtension->DeviceState = DeviceStateCreated;
  1762. // Add the child PDO we just created to the parent's list of child PDOs
  1763. //
  1764. InsertTailList(&fdoDeviceExtension->ChildPDOs,
  1765. &pdoDeviceExtension->ListEntry);
  1766. pdoDeviceObject->Flags |= DO_DIRECT_IO;
  1767. pdoDeviceObject->Flags |= DO_POWER_PAGABLE;
  1768. pdoDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  1769. pdoDeviceExtension->LUN = Lun;
  1770. // Get the Inquiry Data from the device
  1771. //
  1772. ntStatus = USBSTOR_GetInquiryData(pdoDeviceObject);
  1773. // If the device is a DIRECT_ACCESS_DEVICE, see if it is a floppy
  1774. //
  1775. if (NT_SUCCESS(ntStatus))
  1776. {
  1777. PINQUIRYDATA inquiryData;
  1778. inquiryData = (PINQUIRYDATA)pdoDeviceExtension->InquiryDataBuffer;
  1779. if (inquiryData->DeviceType == DIRECT_ACCESS_DEVICE)
  1780. {
  1781. pdoDeviceExtension->IsFloppy = USBSTOR_IsFloppyDevice(pdoDeviceObject);
  1782. }
  1783. }
  1784. DBGPRINT(2, ("exit: USBSTOR_CreateChildPDO %08X\n", ntStatus));
  1785. LOGENTRY('ccpd', FdoDeviceObject, pdoDeviceObject, ntStatus);
  1786. return ntStatus;
  1787. }
  1788. //******************************************************************************
  1789. //
  1790. // USBSTOR_FdoStopDevice()
  1791. //
  1792. // This routine handles IRP_MJ_PNP, IRP_MN_STOP_DEVICE for the FDO
  1793. //
  1794. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  1795. // system thread.
  1796. //
  1797. // The PnP Manager only sends this IRP if a prior IRP_MN_QUERY_STOP_DEVICE
  1798. // completed successfully.
  1799. //
  1800. // This IRP is handled first by the driver at the top of the device stack and
  1801. // then by each lower driver in the attachment chain.
  1802. //
  1803. // A driver must set Irp->IoStatus.Status to STATUS_SUCCESS. A driver must
  1804. // not fail this IRP. If a driver cannot release the device's hardware
  1805. // resources, it can fail a query-stop IRP, but once it succeeds the query-stop
  1806. // request it must succeed the stop request.
  1807. //
  1808. //******************************************************************************
  1809. NTSTATUS
  1810. USBSTOR_FdoStopDevice (
  1811. IN PDEVICE_OBJECT DeviceObject,
  1812. IN PIRP Irp
  1813. )
  1814. {
  1815. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1816. NTSTATUS ntStatus;
  1817. PAGED_CODE();
  1818. DBGPRINT(2, ("enter: USBSTOR_FdoStopDevice\n"));
  1819. LOGENTRY('STOP', DeviceObject, Irp, 0);
  1820. DBGFBRK(DBGF_BRK_STOPDEVICE);
  1821. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1822. // Release the device resources allocated during IRP_MN_START_DEVICE
  1823. //
  1824. // Stop the timeout timer
  1825. //
  1826. IoStopTimer(DeviceObject);
  1827. // Unconfigure the device
  1828. //
  1829. ntStatus = USBSTOR_UnConfigure(DeviceObject);
  1830. // The documentation says to set the status before passing the
  1831. // Irp down the stack
  1832. //
  1833. Irp->IoStatus.Status = STATUS_SUCCESS;
  1834. // Pass the IRP_MN_STOP_DEVICE Irp down the stack.
  1835. //
  1836. IoSkipCurrentIrpStackLocation(Irp);
  1837. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  1838. Irp);
  1839. DBGPRINT(2, ("exit: USBSTOR_FdoStopDevice %08X\n", ntStatus));
  1840. LOGENTRY('stop', ntStatus, 0, 0);
  1841. return ntStatus;
  1842. }
  1843. //******************************************************************************
  1844. //
  1845. // USBSTOR_FdoRemoveDevice()
  1846. //
  1847. // This routine handles IRP_MJ_PNP, IRP_MN_REMOVE_DEVICE for the FDO
  1848. //
  1849. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  1850. // system thread.
  1851. //
  1852. // This IRP is handled first by the driver at the top of the device stack and
  1853. // then by each lower driver in the attachment chain.
  1854. //
  1855. // A driver must set Irp->IoStatus.Status to STATUS_SUCCESS. Drivers must not
  1856. // fail this IRP.
  1857. //
  1858. //******************************************************************************
  1859. NTSTATUS
  1860. USBSTOR_FdoRemoveDevice (
  1861. IN PDEVICE_OBJECT DeviceObject,
  1862. IN PIRP Irp
  1863. )
  1864. {
  1865. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1866. NTSTATUS ntStatus;
  1867. PAGED_CODE();
  1868. DBGPRINT(2, ("enter: USBSTOR_FdoRemoveDevice\n"));
  1869. LOGENTRY('REMV', DeviceObject, Irp, 0);
  1870. DBGFBRK(DBGF_BRK_REMOVEDEVICE);
  1871. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1872. // Decrement by one to match the initial one in AddDevice
  1873. //
  1874. DECREMENT_PENDING_IO_COUNT(fdoDeviceExtension);
  1875. LOGENTRY('rem1', DeviceObject, 0, 0);
  1876. // Wait for all pending requests to complete
  1877. //
  1878. KeWaitForSingleObject(&fdoDeviceExtension->RemoveEvent,
  1879. Executive,
  1880. KernelMode,
  1881. FALSE,
  1882. NULL);
  1883. LOGENTRY('rem2', DeviceObject, 0, 0);
  1884. // The child PDOs should have received REMOVE_DEVICE before the FDO.
  1885. // Go ahead and delete them now.
  1886. //
  1887. while (!IsListEmpty(&fdoDeviceExtension->ChildPDOs))
  1888. {
  1889. PLIST_ENTRY listEntry;
  1890. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  1891. listEntry = RemoveTailList(&fdoDeviceExtension->ChildPDOs);
  1892. pdoDeviceExtension = CONTAINING_RECORD(listEntry,
  1893. PDO_DEVICE_EXTENSION,
  1894. ListEntry);
  1895. ASSERT(pdoDeviceExtension->DeviceState == DeviceStateCreated ||
  1896. pdoDeviceExtension->DeviceState == DeviceStateRemoved);
  1897. LOGENTRY('remc', DeviceObject, pdoDeviceExtension->PdoDeviceObject, 0);
  1898. IoDeleteDevice(pdoDeviceExtension->PdoDeviceObject);
  1899. }
  1900. // Free everything that was allocated during IRP_MN_START_DEVICE
  1901. //
  1902. if (fdoDeviceExtension->IoWorkItem != NULL)
  1903. {
  1904. IoFreeWorkItem(fdoDeviceExtension->IoWorkItem);
  1905. }
  1906. if (fdoDeviceExtension->DeviceDescriptor != NULL)
  1907. {
  1908. ExFreePool(fdoDeviceExtension->DeviceDescriptor);
  1909. }
  1910. if (fdoDeviceExtension->ConfigurationDescriptor != NULL)
  1911. {
  1912. ExFreePool(fdoDeviceExtension->ConfigurationDescriptor);
  1913. }
  1914. if (fdoDeviceExtension->SerialNumber != NULL)
  1915. {
  1916. ExFreePool(fdoDeviceExtension->SerialNumber);
  1917. }
  1918. if (fdoDeviceExtension->InterfaceInfo != NULL)
  1919. {
  1920. ExFreePool(fdoDeviceExtension->InterfaceInfo);
  1921. }
  1922. // The documentation says to set the status before passing the Irp down
  1923. //
  1924. Irp->IoStatus.Status = STATUS_SUCCESS;
  1925. // Pass the IRP_MN_REMOVE_DEVICE Irp down the stack.
  1926. //
  1927. IoSkipCurrentIrpStackLocation(Irp);
  1928. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  1929. Irp);
  1930. LOGENTRY('rem3', DeviceObject, 0, 0);
  1931. // Free everything that was allocated during AddDevice
  1932. //
  1933. IoDetachDevice(fdoDeviceExtension->StackDeviceObject);
  1934. IoDeleteDevice(DeviceObject);
  1935. DBGPRINT(2, ("exit: USBSTOR_FdoRemoveDevice %08X\n", ntStatus));
  1936. LOGENTRY('remv', ntStatus, 0, 0);
  1937. return ntStatus;
  1938. }
  1939. //******************************************************************************
  1940. //
  1941. // USBSTOR_FdoQueryStopRemoveDevice()
  1942. //
  1943. // This routine handles IRP_MJ_PNP, IRP_MN_QUERY_STOP_DEVICE and
  1944. // IRP_MN_QUERY_REMOVE_DEVICE for the FDO.
  1945. //
  1946. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  1947. // system thread.
  1948. //
  1949. // This IRP is handled first by the driver at the top of the device stack and
  1950. // then by each lower driver in the attachment chain.
  1951. //
  1952. //******************************************************************************
  1953. NTSTATUS
  1954. USBSTOR_FdoQueryStopRemoveDevice (
  1955. IN PDEVICE_OBJECT DeviceObject,
  1956. IN PIRP Irp
  1957. )
  1958. {
  1959. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1960. NTSTATUS ntStatus;
  1961. PAGED_CODE();
  1962. DBGPRINT(2, ("enter: USBSTOR_FdoQueryStopRemoveDevice\n"));
  1963. LOGENTRY('QSRD', DeviceObject, Irp, 0);
  1964. DBGFBRK(DBGF_BRK_QUERYSTOPDEVICE);
  1965. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1966. // The documentation says to set the status before passing the Irp down
  1967. //
  1968. Irp->IoStatus.Status = STATUS_SUCCESS;
  1969. // Pass the IRP_MN_QUERY_STOP/REMOVE_DEVICE Irp down the stack.
  1970. //
  1971. IoSkipCurrentIrpStackLocation(Irp);
  1972. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  1973. Irp);
  1974. DBGPRINT(2, ("exit: USBSTOR_FdoQueryStopRemoveDevice %08X\n", ntStatus));
  1975. LOGENTRY('qsrd', ntStatus, 0, 0);
  1976. return ntStatus;
  1977. }
  1978. //******************************************************************************
  1979. //
  1980. // USBSTOR_FdoCancelStopRemoveDevice()
  1981. //
  1982. // This routine handles IRP_MJ_PNP, IRP_MN_CANCEL_STOP_DEVICE and
  1983. // IRP_MN_CANCEL_REMOVE_DEVICE for the FDO.
  1984. //
  1985. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  1986. // system thread.
  1987. //
  1988. // This IRP must be handled first by the underlying bus driver for a device
  1989. // and then by each higher driver in the device stack.
  1990. //
  1991. //******************************************************************************
  1992. NTSTATUS
  1993. USBSTOR_FdoCancelStopRemoveDevice (
  1994. IN PDEVICE_OBJECT DeviceObject,
  1995. IN PIRP Irp
  1996. )
  1997. {
  1998. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1999. NTSTATUS ntStatus;
  2000. PAGED_CODE();
  2001. DBGPRINT(2, ("enter: USBSTOR_FdoCancelStopRemoveDevice\n"));
  2002. LOGENTRY('CSRD', DeviceObject, Irp, 0);
  2003. DBGFBRK(DBGF_BRK_CANCELSTOPDEVICE);
  2004. fdoDeviceExtension = DeviceObject->DeviceExtension;
  2005. // The documentation says to set the status before passing the Irp down
  2006. //
  2007. Irp->IoStatus.Status = STATUS_SUCCESS;
  2008. // Pass the IRP_MN_CANCEL_STOP/REMOVE_DEVICE Irp down the stack.
  2009. //
  2010. ntStatus = USBSTOR_SyncPassDownIrp(DeviceObject,
  2011. Irp);
  2012. if (!NT_SUCCESS(ntStatus))
  2013. {
  2014. DBGPRINT(1, ("Lower driver failed IRP_MN_CANCEL_STOP/REMOVE_DEVICE\n"));
  2015. goto USBSTOR_CancelStopRemoveDeviceDone;
  2016. }
  2017. USBSTOR_CancelStopRemoveDeviceDone:
  2018. // Must complete request since completion routine returned
  2019. // STATUS_MORE_PROCESSING_REQUIRED
  2020. //
  2021. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2022. DBGPRINT(2, ("exit: USBSTOR_FdoCancelStopRemoveDevice %08X\n", ntStatus));
  2023. LOGENTRY('csrd', ntStatus, 0, 0);
  2024. return ntStatus;
  2025. }
  2026. //******************************************************************************
  2027. //
  2028. // USBSTOR_FdoQueryDeviceRelations()
  2029. //
  2030. // This routine handles IRP_MJ_PNP, IRP_MN_QUERY_DEVICE_RELATIONS for the FDO.
  2031. //
  2032. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  2033. // an arbitrary thread.
  2034. //
  2035. //******************************************************************************
  2036. NTSTATUS
  2037. USBSTOR_FdoQueryDeviceRelations (
  2038. IN PDEVICE_OBJECT DeviceObject,
  2039. IN PIRP Irp
  2040. )
  2041. {
  2042. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  2043. PIO_STACK_LOCATION irpStack;
  2044. DEVICE_RELATION_TYPE relationType;
  2045. NTSTATUS ntStatus;
  2046. PAGED_CODE();
  2047. fdoDeviceExtension = DeviceObject->DeviceExtension;
  2048. irpStack = IoGetCurrentIrpStackLocation(Irp);
  2049. relationType = irpStack->Parameters.QueryDeviceRelations.Type;
  2050. DBGPRINT(2, ("enter: USBSTOR_FdoQueryDeviceRelations %d\n",
  2051. relationType));
  2052. LOGENTRY('FQDR', DeviceObject, Irp, relationType);
  2053. switch (relationType)
  2054. {
  2055. case BusRelations:
  2056. if (!IsListEmpty(&fdoDeviceExtension->ChildPDOs))
  2057. {
  2058. // If we have children to return, add them to the existing
  2059. // relation list, if there is one, else create and add them
  2060. // to a new relation list.
  2061. //
  2062. // Then in either case, pass the request down the driver stack.
  2063. //
  2064. PDEVICE_RELATIONS oldRelations;
  2065. PDEVICE_RELATIONS newRelations;
  2066. PLIST_ENTRY listHead;
  2067. PLIST_ENTRY listEntry;
  2068. ULONG oldCount;
  2069. ULONG childCount;
  2070. ULONG index;
  2071. listHead = &fdoDeviceExtension->ChildPDOs;
  2072. // How many children?
  2073. //
  2074. for (listEntry = listHead->Flink, childCount = 0;
  2075. listEntry != listHead;
  2076. listEntry = listEntry->Flink, childCount++)
  2077. ;
  2078. oldRelations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
  2079. if (oldRelations)
  2080. {
  2081. // Add our children to the existing relation list.
  2082. oldCount = oldRelations->Count;
  2083. // A DEVICE_RELATIONS structure has room for one
  2084. // PDEVICE_OBJECT to start with, so subtract that
  2085. // out of the size we allocate.
  2086. //
  2087. newRelations = ExAllocatePoolWithTag(
  2088. PagedPool,
  2089. sizeof(DEVICE_RELATIONS) +
  2090. sizeof(PDEVICE_OBJECT) *
  2091. (oldCount + childCount - 1),
  2092. POOL_TAG);
  2093. if (newRelations)
  2094. {
  2095. // Copy the existing relation list
  2096. //
  2097. for (index = 0; index < oldCount; index++)
  2098. {
  2099. newRelations->Objects[index] =
  2100. oldRelations->Objects[index];
  2101. }
  2102. }
  2103. // Now we're done the the existing relation list, free it
  2104. //
  2105. ExFreePool(oldRelations);
  2106. }
  2107. else
  2108. {
  2109. // Create a new relation list for our children
  2110. newRelations = ExAllocatePoolWithTag(
  2111. PagedPool,
  2112. sizeof(DEVICE_RELATIONS) +
  2113. sizeof(PDEVICE_OBJECT) *
  2114. (childCount - 1),
  2115. POOL_TAG);
  2116. oldCount = 0;
  2117. index = 0;
  2118. }
  2119. if (newRelations)
  2120. {
  2121. newRelations->Count = oldCount + childCount;
  2122. // Add our child relations at the end of the list
  2123. //
  2124. for (listEntry = listHead->Flink;
  2125. listEntry != listHead;
  2126. listEntry = listEntry->Flink)
  2127. {
  2128. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2129. pdoDeviceExtension = CONTAINING_RECORD(
  2130. listEntry,
  2131. PDO_DEVICE_EXTENSION,
  2132. ListEntry);
  2133. newRelations->Objects[index++] =
  2134. pdoDeviceExtension->PdoDeviceObject;
  2135. ObReferenceObject(pdoDeviceExtension->PdoDeviceObject);
  2136. DBGPRINT(2, ("returning ChildPDO %08X\n",
  2137. pdoDeviceExtension->PdoDeviceObject));
  2138. }
  2139. ASSERT(index == oldCount + childCount);
  2140. ntStatus = STATUS_SUCCESS;
  2141. Irp->IoStatus.Status = ntStatus;
  2142. Irp->IoStatus.Information = (ULONG_PTR)newRelations;
  2143. }
  2144. else
  2145. {
  2146. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  2147. Irp->IoStatus.Status = ntStatus;
  2148. Irp->IoStatus.Information = 0;
  2149. }
  2150. }
  2151. else
  2152. {
  2153. // If we don't have a child to return, just pass the request
  2154. // down without doing anything.
  2155. //
  2156. ntStatus = STATUS_SUCCESS;
  2157. }
  2158. break;
  2159. case EjectionRelations:
  2160. case PowerRelations:
  2161. case RemovalRelations:
  2162. case TargetDeviceRelation:
  2163. default:
  2164. //
  2165. // Pass the request down the driver stack without doing anything.
  2166. //
  2167. ntStatus = STATUS_SUCCESS;
  2168. break;
  2169. }
  2170. if (NT_SUCCESS(ntStatus))
  2171. {
  2172. // Pass the Irp down the driver stack if successful so far.
  2173. //
  2174. IoSkipCurrentIrpStackLocation(Irp);
  2175. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  2176. Irp);
  2177. }
  2178. else
  2179. {
  2180. // Unsuccessful, just complete the request now.
  2181. //
  2182. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2183. }
  2184. DBGPRINT(2, ("exit: USBSTOR_FdoQueryDeviceRelations %08X\n", ntStatus));
  2185. LOGENTRY('fqdr', ntStatus, 0, 0);
  2186. return ntStatus;
  2187. }
  2188. //******************************************************************************
  2189. //
  2190. // USBSTOR_FdoQueryCapabilities()
  2191. //
  2192. // This routine handles IRP_MJ_PNP, IRP_MN_QUERY_CAPABILITIES for the FDO.
  2193. //
  2194. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  2195. // an arbitrary thread.
  2196. //
  2197. //******************************************************************************
  2198. NTSTATUS
  2199. USBSTOR_FdoQueryCapabilities (
  2200. IN PDEVICE_OBJECT DeviceObject,
  2201. IN PIRP Irp
  2202. )
  2203. {
  2204. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  2205. PIO_STACK_LOCATION irpStack;
  2206. PDEVICE_CAPABILITIES deviceCapabilities;
  2207. NTSTATUS ntStatus;
  2208. PAGED_CODE();
  2209. fdoDeviceExtension = DeviceObject->DeviceExtension;
  2210. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  2211. DBGPRINT(2, ("enter: USBSTOR_FdoQueryCapabilities\n"));
  2212. LOGENTRY('FQCP', DeviceObject, Irp, 0);
  2213. irpStack = IoGetCurrentIrpStackLocation(Irp);
  2214. deviceCapabilities = irpStack->Parameters.DeviceCapabilities.Capabilities;
  2215. // Pass IRP_MN_QUERY_CAPABILITIES Irp down the stack first before we do
  2216. // anything.
  2217. //
  2218. ntStatus = USBSTOR_SyncPassDownIrp(DeviceObject,
  2219. Irp);
  2220. if (!NT_SUCCESS(ntStatus))
  2221. {
  2222. DBGPRINT(1, ("Lower driver failed IRP_MN_QUERY_CAPABILITIES\n"));
  2223. }
  2224. else
  2225. {
  2226. if (fdoDeviceExtension->NonRemovable)
  2227. {
  2228. deviceCapabilities->Removable = FALSE;
  2229. }
  2230. }
  2231. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2232. DBGPRINT(2, ("exit: USBSTOR_FdoQueryCapabilities %08X\n", ntStatus));
  2233. LOGENTRY('fqcp', ntStatus, 0, 0);
  2234. return ntStatus;
  2235. }
  2236. //******************************************************************************
  2237. //
  2238. // USBSTOR_PdoStartDevice()
  2239. //
  2240. // This routine handles IRP_MJ_PNP, IRP_MN_START_DEVICE for the PDO
  2241. //
  2242. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  2243. // system thread.
  2244. //
  2245. //******************************************************************************
  2246. NTSTATUS
  2247. USBSTOR_PdoStartDevice (
  2248. IN PDEVICE_OBJECT DeviceObject,
  2249. IN PIRP Irp
  2250. )
  2251. {
  2252. NTSTATUS ntStatus;
  2253. PAGED_CODE();
  2254. DBGPRINT(2, ("enter: USBSTOR_PdoStartDevice\n"));
  2255. ntStatus = STATUS_SUCCESS;
  2256. Irp->IoStatus.Status = ntStatus;
  2257. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2258. DBGPRINT(2, ("exit: USBSTOR_PdoStartDevice %08X\n", ntStatus));
  2259. LOGENTRY('pstr', ntStatus, 0, 0);
  2260. return ntStatus;
  2261. }
  2262. //******************************************************************************
  2263. //
  2264. // USBSTOR_PdoRemoveDevice()
  2265. //
  2266. // This routine handles IRP_MJ_PNP, IRP_MN_REMOVE_DEVICE for the PDO
  2267. //
  2268. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  2269. // system thread.
  2270. //
  2271. //******************************************************************************
  2272. NTSTATUS
  2273. USBSTOR_PdoRemoveDevice (
  2274. IN PDEVICE_OBJECT DeviceObject,
  2275. IN PIRP Irp
  2276. )
  2277. {
  2278. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2279. NTSTATUS ntStatus;
  2280. PAGED_CODE();
  2281. DBGPRINT(2, ("enter: USBSTOR_PdoRemoveDevice\n"));
  2282. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2283. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2284. pdoDeviceExtension->Claimed = FALSE;
  2285. ntStatus = STATUS_SUCCESS;
  2286. Irp->IoStatus.Status = ntStatus;
  2287. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2288. DBGPRINT(2, ("exit: USBSTOR_PdoRemoveDevice %08X\n", ntStatus));
  2289. LOGENTRY('prmd', ntStatus, 0, 0);
  2290. return ntStatus;
  2291. }
  2292. //******************************************************************************
  2293. //
  2294. // USBSTOR_PdoQueryID()
  2295. //
  2296. // This routine handles IRP_MJ_PNP, IRP_MN_QUERY_ID for the PDO.
  2297. //
  2298. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  2299. // an arbitrary thread.
  2300. //
  2301. //******************************************************************************
  2302. NTSTATUS
  2303. USBSTOR_PdoQueryID (
  2304. IN PDEVICE_OBJECT DeviceObject,
  2305. IN PIRP Irp
  2306. )
  2307. {
  2308. PIO_STACK_LOCATION irpStack;
  2309. UNICODE_STRING unicodeStr;
  2310. BOOLEAN multiStrings;
  2311. NTSTATUS ntStatus;
  2312. PAGED_CODE();
  2313. DBGPRINT(2, ("enter: USBSTOR_PdoQueryID\n"));
  2314. LOGENTRY('PQID', DeviceObject, Irp, 0);
  2315. irpStack = IoGetCurrentIrpStackLocation(Irp);
  2316. // Initialize return value to NULL
  2317. //
  2318. RtlInitUnicodeString(&unicodeStr, NULL);
  2319. switch (irpStack->Parameters.QueryId.IdType)
  2320. {
  2321. case BusQueryDeviceID:
  2322. ntStatus = USBSTOR_PdoQueryDeviceId(
  2323. DeviceObject,
  2324. &unicodeStr);
  2325. multiStrings = FALSE;
  2326. break;
  2327. case BusQueryHardwareIDs:
  2328. ntStatus = USBSTOR_PdoQueryHardwareIds(
  2329. DeviceObject,
  2330. &unicodeStr);
  2331. multiStrings = TRUE;
  2332. break;
  2333. case BusQueryCompatibleIDs:
  2334. ntStatus = USBSTOR_PdoQueryCompatibleIds(
  2335. DeviceObject,
  2336. &unicodeStr);
  2337. multiStrings = TRUE;
  2338. break;
  2339. case BusQueryInstanceID:
  2340. ntStatus = USBSTOR_PdoBusQueryInstanceId(
  2341. DeviceObject,
  2342. &unicodeStr);
  2343. multiStrings = FALSE;
  2344. break;
  2345. default:
  2346. ntStatus = STATUS_NOT_SUPPORTED;
  2347. break;
  2348. }
  2349. if (NT_SUCCESS(ntStatus) && unicodeStr.Buffer)
  2350. {
  2351. PWCHAR idString;
  2352. //
  2353. // fix up all invalid characters
  2354. //
  2355. idString = unicodeStr.Buffer;
  2356. while (*idString)
  2357. {
  2358. if ((*idString <= L' ') ||
  2359. (*idString > (WCHAR)0x7F) ||
  2360. (*idString == L','))
  2361. {
  2362. *idString = L'_';
  2363. }
  2364. idString++;
  2365. if ((*idString == L'\0') && multiStrings)
  2366. {
  2367. idString++;
  2368. }
  2369. }
  2370. Irp->IoStatus.Information = (ULONG_PTR)unicodeStr.Buffer;
  2371. }
  2372. else
  2373. {
  2374. Irp->IoStatus.Information = (ULONG_PTR)NULL;
  2375. }
  2376. Irp->IoStatus.Status = ntStatus;
  2377. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2378. DBGPRINT(2, ("exit: USBSTOR_PdoQueryID %08X\n", ntStatus));
  2379. LOGENTRY('pqid', ntStatus, 0, 0);
  2380. return ntStatus;
  2381. }
  2382. //******************************************************************************
  2383. //
  2384. // USBSTOR_PdoDeviceTypeString()
  2385. //
  2386. // This routine returns a device type string for the PDO.
  2387. //
  2388. //******************************************************************************
  2389. PCHAR
  2390. USBSTOR_PdoDeviceTypeString (
  2391. IN PDEVICE_OBJECT DeviceObject
  2392. )
  2393. {
  2394. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2395. PINQUIRYDATA inquiryData;
  2396. PAGED_CODE();
  2397. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2398. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2399. inquiryData = (PINQUIRYDATA)pdoDeviceExtension->InquiryDataBuffer;
  2400. switch (inquiryData->DeviceType)
  2401. {
  2402. case DIRECT_ACCESS_DEVICE:
  2403. return pdoDeviceExtension->IsFloppy ? "SFloppy" : "Disk";
  2404. case WRITE_ONCE_READ_MULTIPLE_DEVICE:
  2405. return "Worm";
  2406. case READ_ONLY_DIRECT_ACCESS_DEVICE:
  2407. return "CdRom";
  2408. case OPTICAL_DEVICE:
  2409. return "Optical";
  2410. case MEDIUM_CHANGER:
  2411. return "Changer";
  2412. case SEQUENTIAL_ACCESS_DEVICE:
  2413. return "Sequential";
  2414. default:
  2415. return "Other";
  2416. }
  2417. }
  2418. //******************************************************************************
  2419. //
  2420. // USBSTOR_PdoGenericTypeString()
  2421. //
  2422. // This routine returns a device type string for the PDO.
  2423. //
  2424. //******************************************************************************
  2425. PCHAR
  2426. USBSTOR_PdoGenericTypeString (
  2427. IN PDEVICE_OBJECT DeviceObject
  2428. )
  2429. {
  2430. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2431. PINQUIRYDATA inquiryData;
  2432. PAGED_CODE();
  2433. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2434. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2435. inquiryData = (PINQUIRYDATA)pdoDeviceExtension->InquiryDataBuffer;
  2436. switch (inquiryData->DeviceType)
  2437. {
  2438. case DIRECT_ACCESS_DEVICE:
  2439. return pdoDeviceExtension->IsFloppy ? "GenSFloppy" : "GenDisk";
  2440. case WRITE_ONCE_READ_MULTIPLE_DEVICE:
  2441. return "GenWorm";
  2442. case READ_ONLY_DIRECT_ACCESS_DEVICE:
  2443. return "GenCdRom";
  2444. case OPTICAL_DEVICE:
  2445. return "GenOptical";
  2446. case MEDIUM_CHANGER:
  2447. return "GenChanger";
  2448. case SEQUENTIAL_ACCESS_DEVICE:
  2449. return "GenSequential";
  2450. default:
  2451. return "UsbstorOther";
  2452. }
  2453. }
  2454. //******************************************************************************
  2455. //
  2456. // CopyField()
  2457. //
  2458. // This routine will copy Count string bytes from Source to Destination.
  2459. // If it finds a nul byte in the Source it will translate that and any
  2460. // subsequent bytes into Change. It will also replace spaces with the
  2461. // specified Change character.
  2462. //
  2463. //******************************************************************************
  2464. VOID
  2465. CopyField (
  2466. IN PUCHAR Destination,
  2467. IN PUCHAR Source,
  2468. IN ULONG Count,
  2469. IN UCHAR Change
  2470. )
  2471. {
  2472. ULONG i;
  2473. BOOLEAN pastEnd;
  2474. PAGED_CODE();
  2475. pastEnd = FALSE;
  2476. for (i = 0; i < Count; i++)
  2477. {
  2478. if (!pastEnd)
  2479. {
  2480. if (Source[i] == 0)
  2481. {
  2482. pastEnd = TRUE;
  2483. Destination[i] = Change;
  2484. } else if (Source[i] == ' ')
  2485. {
  2486. Destination[i] = Change;
  2487. } else
  2488. {
  2489. Destination[i] = Source[i];
  2490. }
  2491. }
  2492. else
  2493. {
  2494. Destination[i] = Change;
  2495. }
  2496. }
  2497. return;
  2498. }
  2499. //******************************************************************************
  2500. //
  2501. // USBSTOR_StringArrayToMultiSz()
  2502. //
  2503. // This routine will take a null terminated array of ascii strings and merge
  2504. // them together into a unicode multi-string block.
  2505. //
  2506. // This routine allocates memory for the string buffer - it is the caller's
  2507. // responsibility to free it.
  2508. //
  2509. //******************************************************************************
  2510. NTSTATUS
  2511. USBSTOR_StringArrayToMultiSz(
  2512. PUNICODE_STRING MultiString,
  2513. PCSTR StringArray[]
  2514. )
  2515. {
  2516. ANSI_STRING ansiEntry;
  2517. UNICODE_STRING unicodeEntry;
  2518. UCHAR i;
  2519. NTSTATUS ntStatus;
  2520. PAGED_CODE();
  2521. DBGPRINT(2, ("enter: USBSTOR_StringArrayToMultiSz %08X %08X\n",
  2522. MultiString, StringArray));
  2523. // Make sure we aren't going to leak any memory
  2524. //
  2525. ASSERT(MultiString->Buffer == NULL);
  2526. RtlInitUnicodeString(MultiString, NULL);
  2527. // First add up the sizes of the converted ascii strings to determine
  2528. // how big the multisz will be.
  2529. //
  2530. for (i = 0; StringArray[i] != NULL; i++)
  2531. {
  2532. RtlInitAnsiString(&ansiEntry, StringArray[i]);
  2533. MultiString->Length += (USHORT)RtlAnsiStringToUnicodeSize(&ansiEntry);
  2534. }
  2535. ASSERT(MultiString->Length != 0);
  2536. // Add room for the double NULL terminator
  2537. //
  2538. MultiString->MaximumLength = MultiString->Length + sizeof(UNICODE_NULL);
  2539. // Now allocate a buffer for the multisz
  2540. //
  2541. MultiString->Buffer = ExAllocatePoolWithTag(PagedPool,
  2542. MultiString->MaximumLength,
  2543. POOL_TAG);
  2544. if (MultiString->Buffer == NULL)
  2545. {
  2546. return STATUS_INSUFFICIENT_RESOURCES;
  2547. }
  2548. RtlZeroMemory(MultiString->Buffer, MultiString->MaximumLength);
  2549. unicodeEntry = *MultiString;
  2550. // Now convert each ascii string in the array into a unicode string
  2551. // in the multisz
  2552. //
  2553. for (i = 0; StringArray[i] != NULL; i++)
  2554. {
  2555. RtlInitAnsiString(&ansiEntry, StringArray[i]);
  2556. ntStatus = RtlAnsiStringToUnicodeString(&unicodeEntry,
  2557. &ansiEntry,
  2558. FALSE);
  2559. // Since we're not allocating any memory the only failure possible
  2560. // is if this function is bad
  2561. ASSERT(NT_SUCCESS(ntStatus));
  2562. // Push the buffer location up and reduce the maximum count
  2563. //
  2564. ((PSTR) unicodeEntry.Buffer) += unicodeEntry.Length + sizeof(WCHAR);
  2565. unicodeEntry.MaximumLength -= unicodeEntry.Length + sizeof(WCHAR);
  2566. };
  2567. DBGPRINT(2, ("exit: USBSTOR_StringArrayToMultiSz\n"));
  2568. return STATUS_SUCCESS;
  2569. }
  2570. //******************************************************************************
  2571. //
  2572. // USBSTOR_PdoQueryDeviceId()
  2573. //
  2574. // This routine handles IRP_MN_QUERY_ID BusQueryDeviceID for the PDO.
  2575. //
  2576. //******************************************************************************
  2577. NTSTATUS
  2578. USBSTOR_PdoQueryDeviceId (
  2579. IN PDEVICE_OBJECT DeviceObject,
  2580. OUT PUNICODE_STRING UnicodeString
  2581. )
  2582. {
  2583. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2584. PINQUIRYDATA inquiryData;
  2585. UCHAR buffer[128];
  2586. PUCHAR rawIdString;
  2587. ANSI_STRING ansiIdString;
  2588. ULONG whichString;
  2589. NTSTATUS ntStatus;
  2590. PAGED_CODE();
  2591. DBGPRINT(2, ("enter: USBSTOR_PdoQueryDeviceId\n"));
  2592. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2593. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2594. inquiryData = (PINQUIRYDATA)pdoDeviceExtension->InquiryDataBuffer;
  2595. RtlZeroMemory(buffer, sizeof(buffer));
  2596. rawIdString = USBSTOR_PdoDeviceTypeString(DeviceObject);
  2597. sprintf(buffer, "USBSTOR\\%s", rawIdString);
  2598. rawIdString = buffer + strlen(buffer);
  2599. for (whichString = 0; whichString < 3; whichString++)
  2600. {
  2601. PUCHAR headerString;
  2602. PUCHAR sourceString;
  2603. ULONG sourceStringLength;
  2604. ULONG i;
  2605. switch (whichString)
  2606. {
  2607. //
  2608. // Vendor Id
  2609. //
  2610. case 0:
  2611. sourceString = inquiryData->VendorId;
  2612. sourceStringLength = sizeof(inquiryData->VendorId);
  2613. headerString = "Ven";
  2614. break;
  2615. //
  2616. // Product Id
  2617. //
  2618. case 1:
  2619. sourceString = inquiryData->ProductId;
  2620. sourceStringLength = sizeof(inquiryData->ProductId);
  2621. headerString = "Prod";
  2622. break;
  2623. //
  2624. // Product Revision Level
  2625. //
  2626. case 2:
  2627. sourceString = inquiryData->ProductRevisionLevel;
  2628. sourceStringLength = sizeof(inquiryData->ProductRevisionLevel);
  2629. headerString = "Rev";
  2630. break;
  2631. }
  2632. //
  2633. // Start at the end of the source string and back up until we find a
  2634. // non-space, non-null character.
  2635. //
  2636. for (; sourceStringLength > 0; sourceStringLength--)
  2637. {
  2638. if((sourceString[sourceStringLength - 1] != ' ') &&
  2639. (sourceString[sourceStringLength - 1] != '\0'))
  2640. {
  2641. break;
  2642. }
  2643. }
  2644. //
  2645. // Throw the header string into the block
  2646. //
  2647. sprintf(rawIdString, "&%s_", headerString);
  2648. rawIdString += strlen(headerString) + 2;
  2649. //
  2650. // Spew the string into the device id
  2651. //
  2652. for(i = 0; i < sourceStringLength; i++)
  2653. {
  2654. *rawIdString = (sourceString[i] != ' ') ? (sourceString[i]) :
  2655. ('_');
  2656. rawIdString++;
  2657. }
  2658. }
  2659. RtlInitAnsiString(&ansiIdString, buffer);
  2660. ntStatus = RtlAnsiStringToUnicodeString(UnicodeString, &ansiIdString, TRUE);
  2661. DBGPRINT(2, ("exit: USBSTOR_PdoQueryDeviceId %08X\n", ntStatus));
  2662. return ntStatus;
  2663. }
  2664. //******************************************************************************
  2665. //
  2666. // USBSTOR_PdoQueryHardwareIds()
  2667. //
  2668. // This routine handles IRP_MN_QUERY_ID BusQueryHardwareIDs for the PDO.
  2669. //
  2670. //******************************************************************************
  2671. #define NUMBER_HARDWARE_STRINGS 7
  2672. NTSTATUS
  2673. USBSTOR_PdoQueryHardwareIds (
  2674. IN PDEVICE_OBJECT DeviceObject,
  2675. OUT PUNICODE_STRING UnicodeString
  2676. )
  2677. {
  2678. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2679. PINQUIRYDATA inquiryData;
  2680. PUCHAR devTypeString;
  2681. PUCHAR genTypeString;
  2682. ULONG i;
  2683. PSTR strings[NUMBER_HARDWARE_STRINGS + 1];
  2684. UCHAR scratch[128];
  2685. NTSTATUS ntStatus;
  2686. PAGED_CODE();
  2687. DBGPRINT(2, ("enter: USBSTOR_PdoQueryHardwareIds\n"));
  2688. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2689. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2690. inquiryData = (PINQUIRYDATA)pdoDeviceExtension->InquiryDataBuffer;
  2691. devTypeString = USBSTOR_PdoDeviceTypeString(DeviceObject);
  2692. genTypeString = USBSTOR_PdoGenericTypeString(DeviceObject);
  2693. ntStatus = STATUS_SUCCESS;
  2694. RtlZeroMemory(strings, sizeof(strings));
  2695. for (i = 0; i < NUMBER_HARDWARE_STRINGS; i++)
  2696. {
  2697. RtlZeroMemory(scratch, sizeof(scratch));
  2698. // First build each string in the scratch buffer
  2699. //
  2700. switch (i)
  2701. {
  2702. //
  2703. // Bus + Dev Type + Vendor + Product + Revision
  2704. //
  2705. case 0:
  2706. sprintf(scratch, "USBSTOR\\%s", devTypeString);
  2707. CopyField(scratch + strlen(scratch),
  2708. inquiryData->VendorId,
  2709. 8,
  2710. '_');
  2711. CopyField(scratch + strlen(scratch),
  2712. inquiryData->ProductId,
  2713. 16,
  2714. '_');
  2715. CopyField(scratch + strlen(scratch),
  2716. inquiryData->ProductRevisionLevel,
  2717. 4,
  2718. '_');
  2719. break;
  2720. //
  2721. // Bus + Dev Type + Vendor + Product
  2722. //
  2723. case 1:
  2724. sprintf(scratch, "USBSTOR\\%s", devTypeString);
  2725. CopyField(scratch + strlen(scratch),
  2726. inquiryData->VendorId,
  2727. 8,
  2728. '_');
  2729. CopyField(scratch + strlen(scratch),
  2730. inquiryData->ProductId,
  2731. 16,
  2732. '_');
  2733. break;
  2734. //
  2735. // Bus + Dev Type + Vendor
  2736. //
  2737. case 2:
  2738. sprintf(scratch, "USBSTOR\\%s", devTypeString);
  2739. CopyField(scratch + strlen(scratch),
  2740. inquiryData->VendorId,
  2741. 8,
  2742. '_');
  2743. break;
  2744. //
  2745. // Bus + Vendor + Product + Revision[0]
  2746. //
  2747. case 3:
  2748. sprintf(scratch, "USBSTOR\\");
  2749. //
  2750. // Fall through to the next set.
  2751. //
  2752. //
  2753. // Vendor + Product + Revision[0] (win9x)
  2754. //
  2755. case 4:
  2756. CopyField(scratch + strlen(scratch),
  2757. inquiryData->VendorId,
  2758. 8,
  2759. '_');
  2760. CopyField(scratch + strlen(scratch),
  2761. inquiryData->ProductId,
  2762. 16,
  2763. '_');
  2764. CopyField(scratch + strlen(scratch),
  2765. inquiryData->ProductRevisionLevel,
  2766. 1,
  2767. '_');
  2768. break;
  2769. //
  2770. // Bus + Generic Type
  2771. //
  2772. case 5:
  2773. sprintf(scratch, "USBSTOR\\%s", genTypeString);
  2774. break;
  2775. //
  2776. // Generic Type
  2777. //
  2778. case 6:
  2779. sprintf(scratch, "%s", genTypeString);
  2780. break;
  2781. default:
  2782. ASSERT(FALSE);
  2783. break;
  2784. }
  2785. // Now allocate a tmp buffer for this string and copy the scratch
  2786. // buffer to the tmp buffer
  2787. //
  2788. if (strlen(scratch) != 0)
  2789. {
  2790. strings[i] = ExAllocatePoolWithTag(
  2791. PagedPool,
  2792. strlen(scratch) + sizeof(UCHAR),
  2793. POOL_TAG);
  2794. if (strings[i] == NULL)
  2795. {
  2796. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  2797. break;
  2798. }
  2799. else
  2800. {
  2801. strcpy(strings[i], scratch);
  2802. }
  2803. }
  2804. }
  2805. if (NT_SUCCESS(ntStatus))
  2806. {
  2807. // Now convert the array of stings to one Unicode MultiSz
  2808. //
  2809. ntStatus = USBSTOR_StringArrayToMultiSz(UnicodeString, strings);
  2810. }
  2811. // Now free up the tmp buffers for each string
  2812. //
  2813. for (i = 0; i < NUMBER_HARDWARE_STRINGS; i++)
  2814. {
  2815. if (strings[i])
  2816. {
  2817. ExFreePool(strings[i]);
  2818. }
  2819. }
  2820. DBGPRINT(2, ("exit: USBSTOR_PdoQueryHardwareIds %08X\n", ntStatus));
  2821. return ntStatus;
  2822. }
  2823. //******************************************************************************
  2824. //
  2825. // USBSTOR_PdoQueryCompatibleIds()
  2826. //
  2827. // This routine handles IRP_MN_QUERY_ID BusQueryCompatibleIDs for the PDO.
  2828. //
  2829. //******************************************************************************
  2830. NTSTATUS
  2831. USBSTOR_PdoQueryCompatibleIds (
  2832. IN PDEVICE_OBJECT DeviceObject,
  2833. OUT PUNICODE_STRING UnicodeString
  2834. )
  2835. {
  2836. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2837. PINQUIRYDATA inquiryData;
  2838. PUCHAR devTypeString;
  2839. UCHAR s[sizeof("USBSTOR\\DEVICE_TYPE_GOES_HERE")];
  2840. PSTR strings[] = {s, "USBSTOR\\RAW", NULL};
  2841. NTSTATUS ntStatus;
  2842. PAGED_CODE();
  2843. DBGPRINT(2, ("enter: USBSTOR_PdoQueryCompatibleIds\n"));
  2844. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2845. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2846. inquiryData = (PINQUIRYDATA)pdoDeviceExtension->InquiryDataBuffer;
  2847. devTypeString = USBSTOR_PdoDeviceTypeString(DeviceObject);
  2848. sprintf(s, "USBSTOR\\%s", devTypeString);
  2849. ntStatus = USBSTOR_StringArrayToMultiSz(UnicodeString, strings);
  2850. DBGPRINT(2, ("exit: USBSTOR_PdoQueryCompatibleIds %08X\n", ntStatus));
  2851. return ntStatus;
  2852. }
  2853. //******************************************************************************
  2854. //
  2855. // USBSTOR_PdoQueryDeviceText()
  2856. //
  2857. // This routine handles IRP_MJ_PNP, IRP_MN_QUERY_DEVICE_TEXT for the PDO.
  2858. //
  2859. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  2860. // an arbitrary thread.
  2861. //
  2862. //******************************************************************************
  2863. NTSTATUS
  2864. USBSTOR_PdoQueryDeviceText (
  2865. IN PDEVICE_OBJECT DeviceObject,
  2866. IN PIRP Irp
  2867. )
  2868. {
  2869. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2870. PINQUIRYDATA inquiryData;
  2871. PIO_STACK_LOCATION irpStack;
  2872. DEVICE_TEXT_TYPE textType;
  2873. UCHAR ansiBuffer[256];
  2874. ANSI_STRING ansiText;
  2875. UNICODE_STRING unicodeText;
  2876. NTSTATUS ntStatus;
  2877. PAGED_CODE();
  2878. DBGPRINT(2, ("enter: USBSTOR_PdoQueryDeviceText\n"));
  2879. LOGENTRY('PQDT', DeviceObject, Irp, 0);
  2880. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2881. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2882. inquiryData = (PINQUIRYDATA)pdoDeviceExtension->InquiryDataBuffer;
  2883. irpStack = IoGetCurrentIrpStackLocation(Irp);
  2884. textType = irpStack->Parameters.QueryDeviceText.DeviceTextType;
  2885. if (textType == DeviceTextDescription)
  2886. {
  2887. PUCHAR c;
  2888. LONG i;
  2889. RtlZeroMemory(ansiBuffer, sizeof(ansiBuffer));
  2890. RtlCopyMemory(ansiBuffer,
  2891. inquiryData->VendorId,
  2892. sizeof(inquiryData->VendorId));
  2893. c = ansiBuffer;
  2894. for (i = sizeof(inquiryData->VendorId)-1; i >= 0; i--)
  2895. {
  2896. if((c[i] != '\0') &&
  2897. (c[i] != ' '))
  2898. {
  2899. i++;
  2900. break;
  2901. }
  2902. }
  2903. c += i;
  2904. *c++ = ' ';
  2905. RtlCopyMemory(c,
  2906. inquiryData->ProductId,
  2907. sizeof(inquiryData->ProductId));
  2908. for (i = sizeof(inquiryData->ProductId)-1; i >= 0; i--)
  2909. {
  2910. if((c[i] != '\0') &&
  2911. (c[i] != ' '))
  2912. {
  2913. i++;
  2914. break;
  2915. }
  2916. }
  2917. c += i;
  2918. *c++ = ' ';
  2919. sprintf(c, "USB Device");
  2920. RtlInitAnsiString(&ansiText, ansiBuffer);
  2921. ntStatus = RtlAnsiStringToUnicodeString(&unicodeText,
  2922. &ansiText,
  2923. TRUE);
  2924. if (NT_SUCCESS(ntStatus))
  2925. {
  2926. Irp->IoStatus.Information = (ULONG_PTR)unicodeText.Buffer;
  2927. }
  2928. else
  2929. {
  2930. Irp->IoStatus.Information = (ULONG_PTR)NULL;
  2931. }
  2932. }
  2933. else
  2934. {
  2935. // If a device does not provide description or location information,
  2936. // the device's underlying bus driver completes the IRP without
  2937. // modifying Irp->IoStatus.Status or Ipr->IoStatus.Information.
  2938. //
  2939. ntStatus = Irp->IoStatus.Status;
  2940. }
  2941. Irp->IoStatus.Status = ntStatus;
  2942. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2943. DBGPRINT(2, ("exit: USBSTOR_PdoQueryDeviceText %08X\n", ntStatus));
  2944. LOGENTRY('pqdt', ntStatus, 0, 0);
  2945. return ntStatus;
  2946. }
  2947. //******************************************************************************
  2948. //
  2949. // USBSTOR_PdoBusQueryInstanceId()
  2950. //
  2951. // This routine handles IRP_MN_QUERY_ID BusQueryInstanceID for the PDO.
  2952. //
  2953. //******************************************************************************
  2954. NTSTATUS
  2955. USBSTOR_PdoBusQueryInstanceId (
  2956. IN PDEVICE_OBJECT DeviceObject,
  2957. OUT PUNICODE_STRING UnicodeString
  2958. )
  2959. {
  2960. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2961. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  2962. USHORT length;
  2963. NTSTATUS ntStatus;
  2964. PAGED_CODE();
  2965. DBGPRINT(2, ("enter: USBSTOR_PdoBusQueryInstanceId\n"));
  2966. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2967. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2968. fdoDeviceExtension = pdoDeviceExtension->ParentFDO->DeviceExtension;
  2969. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  2970. if (fdoDeviceExtension->SerialNumber == NULL)
  2971. {
  2972. // If we set DEVICE_CAPABILITIES.UniqueID = 0 in response to a
  2973. // IRP_MN_QUERY_CAPABILITIES, we can return a NULL ID in response
  2974. // to a BusQueryInstanceID.
  2975. //
  2976. ntStatus = STATUS_SUCCESS;
  2977. }
  2978. else
  2979. {
  2980. // Return an NULL-terminated InstanceId string with the format:
  2981. // <USB Device SerialNumberString> + '&' + <LUN value in hex>
  2982. //
  2983. length = fdoDeviceExtension->SerialNumber->bLength -
  2984. sizeof(USB_COMMON_DESCRIPTOR) +
  2985. 3 * sizeof(WCHAR);
  2986. UnicodeString->Buffer = ExAllocatePoolWithTag(
  2987. PagedPool,
  2988. length,
  2989. POOL_TAG);
  2990. if (UnicodeString->Buffer == NULL)
  2991. {
  2992. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  2993. }
  2994. else
  2995. {
  2996. UnicodeString->Length = length - sizeof(WCHAR);
  2997. UnicodeString->MaximumLength = length;
  2998. // Copy the USB Device SerialNumberString
  2999. //
  3000. RtlCopyMemory(UnicodeString->Buffer,
  3001. &fdoDeviceExtension->SerialNumber->bString[0],
  3002. length - 3 * sizeof(WCHAR));
  3003. // Append a '&'
  3004. //
  3005. UnicodeString->Buffer[length/sizeof(WCHAR) - 3] = (WCHAR)'&';
  3006. // Append the LUN value in hex
  3007. //
  3008. if (pdoDeviceExtension->LUN <= 9)
  3009. {
  3010. UnicodeString->Buffer[length/sizeof(WCHAR) - 2] =
  3011. (WCHAR)('0' + pdoDeviceExtension->LUN);
  3012. }
  3013. else
  3014. {
  3015. UnicodeString->Buffer[length/sizeof(WCHAR) - 2] =
  3016. (WCHAR)('A' + pdoDeviceExtension->LUN - 0xA);
  3017. }
  3018. UnicodeString->Buffer[length/sizeof(WCHAR) - 1] =
  3019. UNICODE_NULL;
  3020. ntStatus = STATUS_SUCCESS;
  3021. }
  3022. }
  3023. DBGPRINT(2, ("exit: USBSTOR_PdoBusQueryInstanceId %08X\n", ntStatus));
  3024. return ntStatus;
  3025. }
  3026. //******************************************************************************
  3027. //
  3028. // USBSTOR_PdoQueryDeviceRelations()
  3029. //
  3030. // This routine handles IRP_MJ_PNP, IRP_MN_QUERY_DEVICE_RELATIONS for the PDO.
  3031. //
  3032. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  3033. // an arbitrary thread.
  3034. //
  3035. //******************************************************************************
  3036. NTSTATUS
  3037. USBSTOR_PdoQueryDeviceRelations (
  3038. IN PDEVICE_OBJECT DeviceObject,
  3039. IN PIRP Irp
  3040. )
  3041. {
  3042. PIO_STACK_LOCATION irpStack;
  3043. DEVICE_RELATION_TYPE relationType;
  3044. PDEVICE_RELATIONS newRelations;
  3045. NTSTATUS ntStatus;
  3046. PAGED_CODE();
  3047. irpStack = IoGetCurrentIrpStackLocation(Irp);
  3048. relationType = irpStack->Parameters.QueryDeviceRelations.Type;
  3049. DBGPRINT(2, ("enter: USBSTOR_PdoQueryDeviceRelations %d\n",
  3050. relationType));
  3051. LOGENTRY('PQDR', DeviceObject, Irp, relationType);
  3052. switch (relationType)
  3053. {
  3054. case TargetDeviceRelation:
  3055. //
  3056. // Return a relation list containing ourself.
  3057. //
  3058. newRelations = ExAllocatePoolWithTag(
  3059. PagedPool,
  3060. sizeof(DEVICE_RELATIONS),
  3061. POOL_TAG);
  3062. if (newRelations)
  3063. {
  3064. newRelations->Count = 1;
  3065. newRelations->Objects[0] = DeviceObject;
  3066. ObReferenceObject(DeviceObject);
  3067. ntStatus = STATUS_SUCCESS;
  3068. Irp->IoStatus.Status = ntStatus;
  3069. Irp->IoStatus.Information = (ULONG_PTR)newRelations;
  3070. }
  3071. else
  3072. {
  3073. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3074. Irp->IoStatus.Status = ntStatus;
  3075. Irp->IoStatus.Information = 0;
  3076. }
  3077. break;
  3078. case BusRelations:
  3079. case EjectionRelations:
  3080. case PowerRelations:
  3081. case RemovalRelations:
  3082. default:
  3083. //
  3084. // Just complete the request with it's current status
  3085. //
  3086. ntStatus = Irp->IoStatus.Status;
  3087. break;
  3088. }
  3089. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  3090. DBGPRINT(2, ("exit: USBSTOR_PdoQueryDeviceRelations %08X\n", ntStatus));
  3091. LOGENTRY('pqdr', ntStatus, 0, 0);
  3092. return ntStatus;
  3093. }
  3094. //******************************************************************************
  3095. //
  3096. // USBSTOR_PdoQueryCapabilities()
  3097. //
  3098. // This routine handles IRP_MJ_PNP, IRP_MN_QUERY_CAPABILITIES for the PDO.
  3099. //
  3100. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  3101. // an arbitrary thread.
  3102. //
  3103. //******************************************************************************
  3104. NTSTATUS
  3105. USBSTOR_PdoQueryCapabilities (
  3106. IN PDEVICE_OBJECT DeviceObject,
  3107. IN PIRP Irp
  3108. )
  3109. {
  3110. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  3111. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3112. PIO_STACK_LOCATION irpStack;
  3113. PDEVICE_CAPABILITIES deviceCapabilities;
  3114. NTSTATUS ntStatus;
  3115. PAGED_CODE();
  3116. pdoDeviceExtension = DeviceObject->DeviceExtension;
  3117. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  3118. fdoDeviceExtension = pdoDeviceExtension->ParentFDO->DeviceExtension;
  3119. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3120. DBGPRINT(2, ("enter: USBSTOR_PdoQueryCapabilities\n"));
  3121. LOGENTRY('PQCP', DeviceObject, Irp, 0);
  3122. irpStack = IoGetCurrentIrpStackLocation(Irp);
  3123. deviceCapabilities = irpStack->Parameters.DeviceCapabilities.Capabilities;
  3124. // Pass IRP_MN_QUERY_CAPABILITIES Irp down the stack first before we do
  3125. // anything.
  3126. //
  3127. ntStatus = USBSTOR_SyncPassDownIrp(pdoDeviceExtension->ParentFDO,
  3128. Irp);
  3129. if (!NT_SUCCESS(ntStatus))
  3130. {
  3131. DBGPRINT(1, ("Lower driver failed IRP_MN_QUERY_CAPABILITIES\n"));
  3132. }
  3133. else
  3134. {
  3135. if (fdoDeviceExtension->SerialNumber == NULL)
  3136. {
  3137. deviceCapabilities->UniqueID = FALSE;
  3138. }
  3139. deviceCapabilities->Removable = FALSE;
  3140. }
  3141. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  3142. DBGPRINT(2, ("exit: USBSTOR_PdoQueryCapabilities %08X\n", ntStatus));
  3143. LOGENTRY('pqcp', ntStatus, 0, 0);
  3144. return ntStatus;
  3145. }
  3146. //******************************************************************************
  3147. //
  3148. // USBSTOR_SyncPassDownIrp()
  3149. //
  3150. //******************************************************************************
  3151. NTSTATUS
  3152. USBSTOR_SyncPassDownIrp (
  3153. IN PDEVICE_OBJECT DeviceObject,
  3154. IN PIRP Irp
  3155. )
  3156. {
  3157. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3158. NTSTATUS ntStatus;
  3159. KEVENT localevent;
  3160. PAGED_CODE();
  3161. DBGPRINT(2, ("enter: USBSTOR_SyncPassDownIrp\n"));
  3162. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3163. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3164. // Initialize the event we'll wait on
  3165. //
  3166. KeInitializeEvent(&localevent,
  3167. SynchronizationEvent,
  3168. FALSE);
  3169. // Copy down Irp params for the next driver
  3170. //
  3171. IoCopyCurrentIrpStackLocationToNext(Irp);
  3172. // Set the completion routine, which will signal the event
  3173. //
  3174. IoSetCompletionRoutine(Irp,
  3175. USBSTOR_SyncCompletionRoutine,
  3176. &localevent,
  3177. TRUE, // InvokeOnSuccess
  3178. TRUE, // InvokeOnError
  3179. TRUE); // InvokeOnCancel
  3180. // Pass the Irp down the stack
  3181. //
  3182. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  3183. Irp);
  3184. // If the request is pending, block until it completes
  3185. //
  3186. if (ntStatus == STATUS_PENDING)
  3187. {
  3188. KeWaitForSingleObject(&localevent,
  3189. Executive,
  3190. KernelMode,
  3191. FALSE,
  3192. NULL);
  3193. ntStatus = Irp->IoStatus.Status;
  3194. }
  3195. DBGPRINT(2, ("exit: USBSTOR_SyncPassDownIrp %08X\n", ntStatus));
  3196. return ntStatus;
  3197. }
  3198. //******************************************************************************
  3199. //
  3200. // USBSTOR_SyncCompletionRoutine()
  3201. //
  3202. // Completion routine used by USBSTOR_SyncPassDownIrp and
  3203. // USBSTOR_SyncSendUsbRequest
  3204. //
  3205. // If the Irp is one we allocated ourself, DeviceObject is NULL.
  3206. //
  3207. //******************************************************************************
  3208. NTSTATUS
  3209. USBSTOR_SyncCompletionRoutine (
  3210. IN PDEVICE_OBJECT DeviceObject,
  3211. IN PIRP Irp,
  3212. IN PVOID Context
  3213. )
  3214. {
  3215. PKEVENT kevent;
  3216. LOGENTRY('SCR ', DeviceObject, Irp, Irp->IoStatus.Status);
  3217. kevent = (PKEVENT)Context;
  3218. KeSetEvent(kevent,
  3219. IO_NO_INCREMENT,
  3220. FALSE);
  3221. return STATUS_MORE_PROCESSING_REQUIRED;
  3222. }
  3223. //******************************************************************************
  3224. //
  3225. // USBSTOR_SyncSendUsbRequest()
  3226. //
  3227. // Must be called at IRQL PASSIVE_LEVEL
  3228. //
  3229. //******************************************************************************
  3230. NTSTATUS
  3231. USBSTOR_SyncSendUsbRequest (
  3232. IN PDEVICE_OBJECT DeviceObject,
  3233. IN PURB Urb
  3234. )
  3235. {
  3236. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3237. KEVENT localevent;
  3238. PIRP irp;
  3239. PIO_STACK_LOCATION nextStack;
  3240. NTSTATUS ntStatus;
  3241. PAGED_CODE();
  3242. DBGPRINT(3, ("enter: USBSTOR_SyncSendUsbRequest\n"));
  3243. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3244. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3245. // Initialize the event we'll wait on
  3246. //
  3247. KeInitializeEvent(&localevent,
  3248. SynchronizationEvent,
  3249. FALSE);
  3250. // Allocate the Irp
  3251. //
  3252. irp = IoAllocateIrp(fdoDeviceExtension->StackDeviceObject->StackSize, FALSE);
  3253. LOGENTRY('SSUR', DeviceObject, irp, Urb);
  3254. if (irp == NULL)
  3255. {
  3256. return STATUS_INSUFFICIENT_RESOURCES;
  3257. }
  3258. // Set the Irp parameters
  3259. //
  3260. nextStack = IoGetNextIrpStackLocation(irp);
  3261. nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  3262. nextStack->Parameters.DeviceIoControl.IoControlCode =
  3263. IOCTL_INTERNAL_USB_SUBMIT_URB;
  3264. nextStack->Parameters.Others.Argument1 = Urb;
  3265. // Set the completion routine, which will signal the event
  3266. //
  3267. IoSetCompletionRoutine(irp,
  3268. USBSTOR_SyncCompletionRoutine,
  3269. &localevent,
  3270. TRUE, // InvokeOnSuccess
  3271. TRUE, // InvokeOnError
  3272. TRUE); // InvokeOnCancel
  3273. // Pass the Irp & Urb down the stack
  3274. //
  3275. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  3276. irp);
  3277. // If the request is pending, block until it completes
  3278. //
  3279. if (ntStatus == STATUS_PENDING)
  3280. {
  3281. LARGE_INTEGER timeout;
  3282. // Specify a timeout of 5 seconds to wait for this call to complete.
  3283. //
  3284. timeout.QuadPart = -10000 * 5000;
  3285. ntStatus = KeWaitForSingleObject(&localevent,
  3286. Executive,
  3287. KernelMode,
  3288. FALSE,
  3289. &timeout);
  3290. if (ntStatus == STATUS_TIMEOUT)
  3291. {
  3292. ntStatus = STATUS_IO_TIMEOUT;
  3293. // Cancel the Irp we just sent.
  3294. //
  3295. IoCancelIrp(irp);
  3296. // And wait until the cancel completes
  3297. //
  3298. KeWaitForSingleObject(&localevent,
  3299. Executive,
  3300. KernelMode,
  3301. FALSE,
  3302. NULL);
  3303. }
  3304. else
  3305. {
  3306. ntStatus = irp->IoStatus.Status;
  3307. }
  3308. }
  3309. // Done with the Irp, now free it.
  3310. //
  3311. IoFreeIrp(irp);
  3312. LOGENTRY('ssur', ntStatus, Urb, Urb->UrbHeader.Status);
  3313. DBGPRINT(3, ("exit: USBSTOR_SyncSendUsbRequest %08X\n", ntStatus));
  3314. return ntStatus;
  3315. }
  3316. //******************************************************************************
  3317. //
  3318. // USBSTOR_GetDescriptor()
  3319. //
  3320. // Must be called at IRQL PASSIVE_LEVEL
  3321. //
  3322. //******************************************************************************
  3323. NTSTATUS
  3324. USBSTOR_GetDescriptor (
  3325. IN PDEVICE_OBJECT DeviceObject,
  3326. IN UCHAR Recipient,
  3327. IN UCHAR DescriptorType,
  3328. IN UCHAR Index,
  3329. IN USHORT LanguageId,
  3330. IN ULONG RetryCount,
  3331. IN ULONG DescriptorLength,
  3332. OUT PUCHAR *Descriptor
  3333. )
  3334. {
  3335. USHORT function;
  3336. PURB urb;
  3337. NTSTATUS ntStatus;
  3338. PAGED_CODE();
  3339. DBGPRINT(2, ("enter: USBSTOR_GetDescriptor\n"));
  3340. *Descriptor = NULL;
  3341. // Set the URB function based on Recipient {Device, Interface, Endpoint}
  3342. //
  3343. switch (Recipient)
  3344. {
  3345. case USB_RECIPIENT_DEVICE:
  3346. function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
  3347. break;
  3348. case USB_RECIPIENT_INTERFACE:
  3349. function = URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE;
  3350. break;
  3351. case USB_RECIPIENT_ENDPOINT:
  3352. function = URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT;
  3353. break;
  3354. default:
  3355. return STATUS_INVALID_PARAMETER;
  3356. }
  3357. // Allocate a descriptor buffer
  3358. //
  3359. *Descriptor = ExAllocatePoolWithTag(NonPagedPool,
  3360. DescriptorLength,
  3361. POOL_TAG);
  3362. if (*Descriptor != NULL)
  3363. {
  3364. // Allocate a URB for the Get Descriptor request
  3365. //
  3366. urb = ExAllocatePoolWithTag(NonPagedPool,
  3367. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  3368. POOL_TAG);
  3369. if (urb != NULL)
  3370. {
  3371. do
  3372. {
  3373. // Initialize the URB
  3374. //
  3375. urb->UrbHeader.Function = function;
  3376. urb->UrbHeader.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
  3377. urb->UrbControlDescriptorRequest.TransferBufferLength = DescriptorLength;
  3378. urb->UrbControlDescriptorRequest.TransferBuffer = *Descriptor;
  3379. urb->UrbControlDescriptorRequest.TransferBufferMDL = NULL;
  3380. urb->UrbControlDescriptorRequest.UrbLink = NULL;
  3381. urb->UrbControlDescriptorRequest.DescriptorType = DescriptorType;
  3382. urb->UrbControlDescriptorRequest.Index = Index;
  3383. urb->UrbControlDescriptorRequest.LanguageId = LanguageId;
  3384. // Send the URB down the stack
  3385. //
  3386. ntStatus = USBSTOR_SyncSendUsbRequest(DeviceObject,
  3387. urb);
  3388. if (NT_SUCCESS(ntStatus))
  3389. {
  3390. // No error, make sure the length and type are correct
  3391. //
  3392. if ((DescriptorLength ==
  3393. urb->UrbControlDescriptorRequest.TransferBufferLength) &&
  3394. (DescriptorType ==
  3395. ((PUSB_COMMON_DESCRIPTOR)*Descriptor)->bDescriptorType))
  3396. {
  3397. // The length and type are correct, all done
  3398. //
  3399. break;
  3400. }
  3401. else
  3402. {
  3403. // No error, but the length or type is incorrect
  3404. //
  3405. ntStatus = STATUS_DEVICE_DATA_ERROR;
  3406. }
  3407. }
  3408. } while (RetryCount-- > 0);
  3409. ExFreePool(urb);
  3410. }
  3411. else
  3412. {
  3413. // Failed to allocate the URB
  3414. //
  3415. ExFreePool(*Descriptor);
  3416. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3417. }
  3418. }
  3419. else
  3420. {
  3421. // Failed to allocate the descriptor buffer
  3422. //
  3423. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3424. }
  3425. if (!NT_SUCCESS(ntStatus))
  3426. {
  3427. if (*Descriptor != NULL)
  3428. {
  3429. ExFreePool(*Descriptor);
  3430. *Descriptor = NULL;
  3431. }
  3432. }
  3433. DBGPRINT(2, ("exit: USBSTOR_GetDescriptor %08X\n", ntStatus));
  3434. return ntStatus;
  3435. }
  3436. //******************************************************************************
  3437. //
  3438. // USBSTOR_GetMaxLun()
  3439. //
  3440. // Must be called at IRQL PASSIVE_LEVEL
  3441. //
  3442. //******************************************************************************
  3443. NTSTATUS
  3444. USBSTOR_GetMaxLun (
  3445. IN PDEVICE_OBJECT DeviceObject,
  3446. OUT PUCHAR MaxLun
  3447. )
  3448. {
  3449. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3450. PUCHAR maxLunBuf;
  3451. ULONG retryCount;
  3452. PURB urb;
  3453. NTSTATUS ntStatus;
  3454. PAGED_CODE();
  3455. DBGPRINT(2, ("enter: USBSTOR_GetMaxLun\n"));
  3456. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3457. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3458. // Return zero unless we successfully return a non-zero value
  3459. //
  3460. *MaxLun = 0;
  3461. // Allocate a URB for the Get Max LUN request, plus an extra byte at
  3462. // the end for the transfer buffer.
  3463. //
  3464. urb = ExAllocatePoolWithTag(NonPagedPool,
  3465. sizeof(URB) + 1,
  3466. POOL_TAG);
  3467. if (urb != NULL)
  3468. {
  3469. // Get a pointer to the transfer buffer, which is the byte immediately
  3470. // after the end of the URB.
  3471. //
  3472. maxLunBuf = (PUCHAR)(urb + 1);
  3473. retryCount = 2;
  3474. do
  3475. {
  3476. // Initialize the Control Transfer URB, all fields default to zero
  3477. //
  3478. RtlZeroMemory(urb, sizeof(URB) + 1);
  3479. CLASS_URB(urb).Hdr.Length = sizeof(CLASS_URB(urb));
  3480. CLASS_URB(urb).Hdr.Function = URB_FUNCTION_CLASS_INTERFACE;
  3481. CLASS_URB(urb).TransferFlags = USBD_TRANSFER_DIRECTION_IN;
  3482. CLASS_URB(urb).TransferBufferLength = 1;
  3483. CLASS_URB(urb).TransferBuffer = maxLunBuf;
  3484. // CLASS_URB(urb).TransferBufferMDL is already zero
  3485. // CLASS_URB(urb).RequestTypeReservedBits is already zero
  3486. CLASS_URB(urb).Request = BULK_ONLY_GET_MAX_LUN;
  3487. // CLASS_URB(urb).Value is already zero
  3488. // Target the request at the proper interface on the device
  3489. //
  3490. CLASS_URB(urb).Index = fdoDeviceExtension->InterfaceInfo->InterfaceNumber;
  3491. // Send the URB down the stack
  3492. //
  3493. ntStatus = USBSTOR_SyncSendUsbRequest(DeviceObject,
  3494. urb);
  3495. if (NT_SUCCESS(ntStatus))
  3496. {
  3497. // No error, make sure the length is correct
  3498. //
  3499. if (CLASS_URB(urb).TransferBufferLength == 1)
  3500. {
  3501. // The length is correct, return the value if it looks ok
  3502. //
  3503. if (*maxLunBuf <= BULK_ONLY_MAXIMUM_LUN)
  3504. {
  3505. *MaxLun = *maxLunBuf;
  3506. }
  3507. else
  3508. {
  3509. ntStatus = STATUS_DEVICE_DATA_ERROR;
  3510. }
  3511. break;
  3512. }
  3513. else
  3514. {
  3515. // No error, but the length or type is incorrect
  3516. //
  3517. ntStatus = STATUS_DEVICE_DATA_ERROR;
  3518. }
  3519. }
  3520. else if (USBD_STATUS(CLASS_URB(urb).Hdr.Status) ==
  3521. USBD_STATUS(USBD_STATUS_STALL_PID))
  3522. {
  3523. // Some devices which do not support the Get Max LUN request
  3524. // get confused and will STALL a CBW on the Bulk endpoint
  3525. // it if immediately follows the Get Max LUN request.
  3526. //
  3527. // It should never be necessary to send a Clear_Feature
  3528. // Endpoint_Stall for Control EP0, but doing so appears to
  3529. // be one way to unconfuse devices which are confused by the
  3530. // Get Max LUN request.
  3531. // Initialize the Control Transfer URB, all fields default to zero
  3532. //
  3533. RtlZeroMemory(urb, sizeof(URB));
  3534. FEATURE_URB(urb).Hdr.Length = sizeof(FEATURE_URB(urb));
  3535. FEATURE_URB(urb).Hdr.Function = URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT;
  3536. FEATURE_URB(urb).FeatureSelector = USB_FEATURE_ENDPOINT_STALL;
  3537. // FEATURE_URB(urb).Index is already zero
  3538. // Send the URB down the stack
  3539. //
  3540. USBSTOR_SyncSendUsbRequest(DeviceObject,
  3541. urb);
  3542. }
  3543. } while (retryCount-- > 0);
  3544. ExFreePool(urb);
  3545. }
  3546. else
  3547. {
  3548. // Failed to allocate the URB
  3549. //
  3550. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3551. }
  3552. DBGPRINT(2, ("exit: USBSTOR_GetMaxLun %08X\n", ntStatus));
  3553. return ntStatus;
  3554. }
  3555. //******************************************************************************
  3556. //
  3557. // USBSTOR_SelectConfiguration()
  3558. //
  3559. // Must be called at IRQL PASSIVE_LEVEL
  3560. //
  3561. //******************************************************************************
  3562. NTSTATUS
  3563. USBSTOR_SelectConfiguration (
  3564. IN PDEVICE_OBJECT DeviceObject
  3565. )
  3566. {
  3567. PURB urb;
  3568. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3569. PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
  3570. PUSBD_INTERFACE_LIST_ENTRY interfaceList;
  3571. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
  3572. PUSBD_INTERFACE_INFORMATION interfaceInfo;
  3573. LONG i;
  3574. LONG bulkInIndex;
  3575. LONG bulkOutIndex;
  3576. LONG interruptInIndex;
  3577. NTSTATUS ntStatus;
  3578. PAGED_CODE();
  3579. DBGPRINT(2, ("enter: USBSTOR_SelectConfiguration\n"));
  3580. LOGENTRY('SCON', DeviceObject, 0, 0);
  3581. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3582. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3583. configurationDescriptor = fdoDeviceExtension->ConfigurationDescriptor;
  3584. // Allocate storage for an Inteface List to use as an input/output
  3585. // parameter to USBD_CreateConfigurationRequestEx().
  3586. //
  3587. interfaceList = ExAllocatePoolWithTag(
  3588. PagedPool,
  3589. sizeof(USBD_INTERFACE_LIST_ENTRY) * 2,
  3590. POOL_TAG);
  3591. if (interfaceList)
  3592. {
  3593. // Mutate configuration descriptor to suit our wishes
  3594. //
  3595. USBSTOR_AdjustConfigurationDescriptor(
  3596. DeviceObject,
  3597. fdoDeviceExtension->ConfigurationDescriptor,
  3598. &interfaceDescriptor,
  3599. &bulkInIndex,
  3600. &bulkOutIndex,
  3601. &interruptInIndex);
  3602. // Save the Interface Descriptor pointer so we don't have
  3603. // to parse the Configuration Descriptor again in case we
  3604. // want to look at it.
  3605. //
  3606. fdoDeviceExtension->InterfaceDescriptor = interfaceDescriptor;
  3607. if (interfaceDescriptor)
  3608. {
  3609. // Add the single Interface Descriptor we care about to the
  3610. // interface list, then terminate the list.
  3611. //
  3612. interfaceList[0].InterfaceDescriptor = interfaceDescriptor;
  3613. interfaceList[1].InterfaceDescriptor = NULL;
  3614. // USBD will fail a SELECT_CONFIGURATION request if the Config
  3615. // Descriptor bNumInterfaces does not match the number of interfaces
  3616. // in the SELECT_CONFIGURATION request. Since we are ignoring
  3617. // any interfaces other than the first interface, set the Config
  3618. // Descriptor bNumInterfaces to 1.
  3619. //
  3620. // This is only necessary in case this driver is loaded for an
  3621. // entire multiple interface device and not as a single interface
  3622. // child of the composite parent driver.
  3623. //
  3624. configurationDescriptor->bNumInterfaces = 1;
  3625. // Create a SELECT_CONFIGURATION URB, turning the Interface
  3626. // Descriptors in the interfaceList into USBD_INTERFACE_INFORMATION
  3627. // structures in the URB.
  3628. //
  3629. urb = USBD_CreateConfigurationRequestEx(
  3630. configurationDescriptor,
  3631. interfaceList
  3632. );
  3633. if (urb)
  3634. {
  3635. // Now issue the USB request to set the Configuration
  3636. //
  3637. ntStatus = USBSTOR_SyncSendUsbRequest(DeviceObject,
  3638. urb);
  3639. if (NT_SUCCESS(ntStatus))
  3640. {
  3641. // Save the configuration handle for this device in
  3642. // the Device Extension.
  3643. //
  3644. fdoDeviceExtension->ConfigurationHandle =
  3645. urb->UrbSelectConfiguration.ConfigurationHandle;
  3646. interfaceInfo = &urb->UrbSelectConfiguration.Interface;
  3647. // Save a copy of the interface information returned
  3648. // by the SELECT_CONFIGURATION request in the Device
  3649. // Extension. This gives us a list of PIPE_INFORMATION
  3650. // structures for each pipe opened in this configuration.
  3651. //
  3652. ASSERT(fdoDeviceExtension->InterfaceInfo == NULL);
  3653. fdoDeviceExtension->InterfaceInfo =
  3654. ExAllocatePoolWithTag(NonPagedPool,
  3655. interfaceInfo->Length,
  3656. POOL_TAG);
  3657. if (fdoDeviceExtension->InterfaceInfo)
  3658. {
  3659. RtlCopyMemory(fdoDeviceExtension->InterfaceInfo,
  3660. interfaceInfo,
  3661. interfaceInfo->Length);
  3662. }
  3663. else
  3664. {
  3665. // Could not allocate a copy of interface information
  3666. //
  3667. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3668. }
  3669. }
  3670. if (NT_SUCCESS(ntStatus))
  3671. {
  3672. // Reuse the SELECT_CONFIGURATION request URB as a
  3673. // SELECT_INTERFACE request URB and send down a request to
  3674. // select the default alternate interface setting that is
  3675. // currently in effect. The point of this seemingly
  3676. // useless request is to make sure the endpoint
  3677. // MaximumTransferSize values are in effect.
  3678. //
  3679. // When USBHUB is loaded as a composite parent for a
  3680. // multiple interface device it ignores SELECT_CONFIGURATION
  3681. // requests from child device drivers. In particular the
  3682. // MaximumTransferSize values of child driver SELECT_CONFIGURATION
  3683. // requests are ignored and the default 4KB value remains
  3684. // in effect. The composite parent driver will respect the
  3685. // MaximumTransferSize values of child driver SELECT_INTERFACE
  3686. // requests.
  3687. //
  3688. ASSERT(GET_SELECT_INTERFACE_REQUEST_SIZE(fdoDeviceExtension->InterfaceInfo->NumberOfPipes) <
  3689. GET_SELECT_CONFIGURATION_REQUEST_SIZE(1, fdoDeviceExtension->InterfaceInfo->NumberOfPipes));
  3690. RtlZeroMemory(urb, GET_SELECT_INTERFACE_REQUEST_SIZE(fdoDeviceExtension->InterfaceInfo->NumberOfPipes));
  3691. urb->UrbSelectInterface.Hdr.Length =
  3692. (USHORT)GET_SELECT_INTERFACE_REQUEST_SIZE(fdoDeviceExtension->InterfaceInfo->NumberOfPipes);
  3693. urb->UrbSelectInterface.Hdr.Function =
  3694. URB_FUNCTION_SELECT_INTERFACE;
  3695. urb->UrbSelectInterface.ConfigurationHandle =
  3696. fdoDeviceExtension->ConfigurationHandle;
  3697. interfaceInfo = &urb->UrbSelectInterface.Interface;
  3698. RtlCopyMemory(interfaceInfo,
  3699. fdoDeviceExtension->InterfaceInfo,
  3700. fdoDeviceExtension->InterfaceInfo->Length);
  3701. // Override the USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE
  3702. // for all pipes.
  3703. //
  3704. for (i=0; i<(LONG)interfaceInfo->NumberOfPipes; i++)
  3705. {
  3706. if (i == bulkInIndex || i == bulkOutIndex)
  3707. {
  3708. interfaceInfo->Pipes[i].MaximumTransferSize =
  3709. USBSTOR_MAX_TRANSFER_SIZE;
  3710. DBGPRINT(1, ("Set pipe %d MaximumTransferSize to %X\n",
  3711. i,
  3712. interfaceInfo->Pipes[i].MaximumTransferSize));
  3713. }
  3714. else if (i == interruptInIndex)
  3715. {
  3716. interfaceInfo->Pipes[i].MaximumTransferSize =
  3717. sizeof(USHORT);
  3718. DBGPRINT(1, ("Set pipe %d MaximumTransferSize to %X\n",
  3719. i,
  3720. interfaceInfo->Pipes[i].MaximumTransferSize));
  3721. }
  3722. }
  3723. // Now issue the USB request to set the Interface
  3724. //
  3725. ntStatus = USBSTOR_SyncSendUsbRequest(DeviceObject,
  3726. urb);
  3727. if (NT_SUCCESS(ntStatus))
  3728. {
  3729. ASSERT(interfaceInfo->Length ==
  3730. fdoDeviceExtension->InterfaceInfo->Length);
  3731. RtlCopyMemory(fdoDeviceExtension->InterfaceInfo,
  3732. interfaceInfo,
  3733. fdoDeviceExtension->InterfaceInfo->Length);
  3734. }
  3735. }
  3736. // Done with the URB
  3737. //
  3738. ExFreePool(urb);
  3739. }
  3740. else
  3741. {
  3742. // Could not allocate urb
  3743. //
  3744. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3745. }
  3746. }
  3747. else
  3748. {
  3749. // Did not parse an Interface Descriptor out of the Configuration
  3750. // Descriptor, the Configuration Descriptor must be bad.
  3751. //
  3752. ntStatus = STATUS_UNSUCCESSFUL;
  3753. }
  3754. // Done with the interface list
  3755. //
  3756. ExFreePool(interfaceList);
  3757. }
  3758. else
  3759. {
  3760. // Could not allocate Interface List
  3761. //
  3762. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3763. }
  3764. DBGPRINT(2, ("exit: USBSTOR_SelectConfiguration %08X\n", ntStatus));
  3765. LOGENTRY('scon', ntStatus, 0, 0);
  3766. return ntStatus;
  3767. }
  3768. //******************************************************************************
  3769. //
  3770. // USBSTOR_UnConfigure()
  3771. //
  3772. // Must be called at IRQL PASSIVE_LEVEL
  3773. //
  3774. //******************************************************************************
  3775. NTSTATUS
  3776. USBSTOR_UnConfigure (
  3777. IN PDEVICE_OBJECT DeviceObject
  3778. )
  3779. {
  3780. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3781. NTSTATUS ntStatus;
  3782. PURB urb;
  3783. ULONG ulSize;
  3784. PAGED_CODE();
  3785. DBGPRINT(2, ("enter: USBSTOR_UnConfigure\n"));
  3786. LOGENTRY('UCON', DeviceObject, 0, 0);
  3787. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3788. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3789. // Allocate a URB for the SELECT_CONFIGURATION request. As we are
  3790. // unconfiguring the device, the request needs no pipe and interface
  3791. // information structures.
  3792. //
  3793. ulSize = sizeof(struct _URB_SELECT_CONFIGURATION) -
  3794. sizeof(USBD_INTERFACE_INFORMATION);
  3795. urb = ExAllocatePoolWithTag(NonPagedPool, ulSize, POOL_TAG);
  3796. if (urb)
  3797. {
  3798. // Initialize the URB. A NULL Configuration Descriptor indicates
  3799. // that the device should be unconfigured.
  3800. //
  3801. UsbBuildSelectConfigurationRequest(urb,
  3802. (USHORT)ulSize,
  3803. NULL);
  3804. // Now issue the USB request to set the Configuration
  3805. //
  3806. ntStatus = USBSTOR_SyncSendUsbRequest(DeviceObject,
  3807. urb);
  3808. // Done with the URB now.
  3809. //
  3810. ExFreePool(urb);
  3811. fdoDeviceExtension->ConfigurationHandle = 0;
  3812. // Free the copy of the interface information that was allocated in
  3813. // USBSTOR_SelectConfiguration().
  3814. //
  3815. if (fdoDeviceExtension->InterfaceInfo != NULL)
  3816. {
  3817. ExFreePool(fdoDeviceExtension->InterfaceInfo);
  3818. fdoDeviceExtension->InterfaceInfo = NULL;
  3819. }
  3820. }
  3821. else
  3822. {
  3823. // Could not allocate the URB.
  3824. //
  3825. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3826. }
  3827. DBGPRINT(2, ("exit: USBSTOR_UnConfigure %08X\n", ntStatus));
  3828. LOGENTRY('ucon', ntStatus, 0, 0);
  3829. return ntStatus;
  3830. }
  3831. //******************************************************************************
  3832. //
  3833. // USBSTOR_ResetPipe()
  3834. //
  3835. // This will reset the host pipe to Data0 and should also reset the device
  3836. // endpoint to Data0 for Bulk and Interrupt pipes by issuing a Clear_Feature
  3837. // Endpoint_Stall to the device endpoint.
  3838. //
  3839. // Must be called at IRQL PASSIVE_LEVEL
  3840. //
  3841. //******************************************************************************
  3842. NTSTATUS
  3843. USBSTOR_ResetPipe (
  3844. IN PDEVICE_OBJECT DeviceObject,
  3845. IN USBD_PIPE_HANDLE Pipe
  3846. )
  3847. {
  3848. PURB urb;
  3849. NTSTATUS ntStatus;
  3850. PAGED_CODE();
  3851. DBGPRINT(2, ("enter: USBSTOR_ResetPipe\n"));
  3852. LOGENTRY('RESP', DeviceObject, Pipe, 0);
  3853. // Allocate URB for RESET_PIPE request
  3854. //
  3855. urb = ExAllocatePoolWithTag(NonPagedPool,
  3856. sizeof(struct _URB_PIPE_REQUEST),
  3857. POOL_TAG);
  3858. if (urb != NULL)
  3859. {
  3860. // Initialize RESET_PIPE request URB
  3861. //
  3862. urb->UrbHeader.Length = sizeof (struct _URB_PIPE_REQUEST);
  3863. urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
  3864. urb->UrbPipeRequest.PipeHandle = Pipe;
  3865. // Submit RESET_PIPE request URB
  3866. //
  3867. ntStatus = USBSTOR_SyncSendUsbRequest(DeviceObject, urb);
  3868. // Done with URB for RESET_PIPE request, free it
  3869. //
  3870. ExFreePool(urb);
  3871. }
  3872. else
  3873. {
  3874. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3875. }
  3876. DBGPRINT(2, ("exit: USBSTOR_ResetPipe %08X\n", ntStatus));
  3877. LOGENTRY('resp', ntStatus, 0, 0);
  3878. return ntStatus;
  3879. }
  3880. //******************************************************************************
  3881. //
  3882. // USBSTOR_AbortPipe()
  3883. //
  3884. // Must be called at IRQL PASSIVE_LEVEL
  3885. //
  3886. //******************************************************************************
  3887. NTSTATUS
  3888. USBSTOR_AbortPipe (
  3889. IN PDEVICE_OBJECT DeviceObject,
  3890. IN USBD_PIPE_HANDLE Pipe
  3891. )
  3892. {
  3893. PURB urb;
  3894. NTSTATUS ntStatus;
  3895. PAGED_CODE();
  3896. DBGPRINT(2, ("enter: USBSTOR_AbortPipe\n"));
  3897. LOGENTRY('ABRT', DeviceObject, Pipe, 0);
  3898. // Allocate URB for ABORT_PIPE request
  3899. //
  3900. urb = ExAllocatePoolWithTag(NonPagedPool,
  3901. sizeof(struct _URB_PIPE_REQUEST),
  3902. POOL_TAG);
  3903. if (urb != NULL)
  3904. {
  3905. // Initialize ABORT_PIPE request URB
  3906. //
  3907. urb->UrbHeader.Length = sizeof (struct _URB_PIPE_REQUEST);
  3908. urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
  3909. urb->UrbPipeRequest.PipeHandle = Pipe;
  3910. // Submit ABORT_PIPE request URB
  3911. //
  3912. ntStatus = USBSTOR_SyncSendUsbRequest(DeviceObject, urb);
  3913. // Done with URB for ABORT_PIPE request, free it
  3914. //
  3915. ExFreePool(urb);
  3916. }
  3917. else
  3918. {
  3919. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3920. }
  3921. DBGPRINT(2, ("exit: USBSTOR_AbortPipe %08X\n", ntStatus));
  3922. LOGENTRY('abrt', ntStatus, 0, 0);
  3923. return ntStatus;
  3924. }
  3925. //******************************************************************************
  3926. //
  3927. // USBSTOR_GetBusInterface()
  3928. //
  3929. // Must be called at IRQL PASSIVE_LEVEL
  3930. //
  3931. //******************************************************************************
  3932. NTSTATUS
  3933. USBSTOR_GetBusInterface (
  3934. IN PDEVICE_OBJECT DeviceObject,
  3935. IN PUSB_BUS_INTERFACE_USBDI_V1 BusInterface
  3936. )
  3937. {
  3938. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3939. PIRP irp;
  3940. KEVENT localevent;
  3941. PIO_STACK_LOCATION nextStack;
  3942. NTSTATUS ntStatus;
  3943. PAGED_CODE();
  3944. DBGPRINT(1, ("enter: USBSTOR_GetBusInterface\n"));
  3945. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3946. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3947. RtlZeroMemory(BusInterface, sizeof(*BusInterface));
  3948. // Allocate the Irp
  3949. //
  3950. irp = IoAllocateIrp((CCHAR)(fdoDeviceExtension->StackDeviceObject->StackSize),
  3951. FALSE);
  3952. if (irp == NULL)
  3953. {
  3954. return STATUS_INSUFFICIENT_RESOURCES;
  3955. }
  3956. // Initialize the event we'll wait on.
  3957. //
  3958. KeInitializeEvent(&localevent,
  3959. SynchronizationEvent,
  3960. FALSE);
  3961. // Set the Irp parameters
  3962. //
  3963. nextStack = IoGetNextIrpStackLocation(irp);
  3964. nextStack->MajorFunction = IRP_MJ_PNP;
  3965. nextStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
  3966. nextStack->Parameters.QueryInterface.Interface =
  3967. (PINTERFACE)BusInterface;
  3968. nextStack->Parameters.QueryInterface.InterfaceSpecificData =
  3969. NULL;
  3970. nextStack->Parameters.QueryInterface.InterfaceType =
  3971. &USB_BUS_INTERFACE_USBDI_GUID;
  3972. nextStack->Parameters.QueryInterface.Size =
  3973. sizeof(*BusInterface);
  3974. nextStack->Parameters.QueryInterface.Version =
  3975. USB_BUSIF_USBDI_VERSION_1;
  3976. // Set the completion routine, which will signal the event
  3977. //
  3978. IoSetCompletionRoutineEx(DeviceObject,
  3979. irp,
  3980. USBSTOR_SyncCompletionRoutine,
  3981. &localevent,
  3982. TRUE, // InvokeOnSuccess
  3983. TRUE, // InvokeOnError
  3984. TRUE); // InvokeOnCancel
  3985. // All PnP IRP's need the Status field initialized to STATUS_NOT_SUPPORTED
  3986. //
  3987. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  3988. // Pass the Irp down the stack
  3989. //
  3990. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  3991. irp);
  3992. // If the request is pending, block until it completes
  3993. //
  3994. if (ntStatus == STATUS_PENDING)
  3995. {
  3996. KeWaitForSingleObject(&localevent,
  3997. Executive,
  3998. KernelMode,
  3999. FALSE,
  4000. NULL);
  4001. ntStatus = irp->IoStatus.Status;
  4002. }
  4003. IoFreeIrp(irp);
  4004. if (NT_SUCCESS(ntStatus))
  4005. {
  4006. ASSERT(BusInterface->Version == USB_BUSIF_USBDI_VERSION_1);
  4007. ASSERT(BusInterface->Size == sizeof(*BusInterface));
  4008. }
  4009. DBGPRINT(1, ("exit: USBSTOR_GetBusInterface %08X\n", ntStatus));
  4010. return ntStatus;
  4011. }