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.

529 lines
16 KiB

  1. /***************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. Dot4Usb.sys - Lower Filter Driver for Dot4.sys for USB connected
  5. IEEE 1284.4 devices.
  6. File Name:
  7. PnP.c
  8. Abstract:
  9. Plug and Play routines
  10. Environment:
  11. Kernel mode only
  12. Notes:
  13. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  14. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  15. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  16. PURPOSE.
  17. Copyright (c) 2000 Microsoft Corporation. All Rights Reserved.
  18. Revision History:
  19. 01/18/2000 : created
  20. ToDo in this file:
  21. - function cleanup and documentation
  22. - code review
  23. Author(s):
  24. Joby Lafky (JobyL)
  25. Doug Fritz (DFritz)
  26. ****************************************************************************/
  27. #include "pch.h"
  28. NTSTATUS (*PnpDispatchTable[])(PDEVICE_EXTENSION,PIRP) = {
  29. PnpHandleStart, // IRP_MN_START_DEVICE 0x00
  30. PnpHandleQueryRemove, // IRP_MN_QUERY_REMOVE_DEVICE 0x01
  31. PnpHandleRemove, // IRP_MN_REMOVE_DEVICE 0x02
  32. PnpHandleCancelRemove, // IRP_MN_CANCEL_REMOVE_DEVICE 0x03
  33. PnpHandleStop, // IRP_MN_STOP_DEVICE 0x04
  34. PnpHandleQueryStop, // IRP_MN_QUERY_STOP_DEVICE 0x05
  35. PnpHandleCancelStop, // IRP_MN_CANCEL_STOP_DEVICE 0x06
  36. PnpHandleQueryDeviceRelations,// IRP_MN_QUERY_DEVICE_RELATIONS 0x07
  37. PnpDefaultHandler, // IRP_MN_QUERY_INTERFACE 0x08
  38. PnpHandleQueryCapabilities, // IRP_MN_QUERY_CAPABILITIES 0x09
  39. PnpDefaultHandler, // IRP_MN_QUERY_RESOURCES 0x0A
  40. PnpDefaultHandler, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS 0x0B
  41. PnpDefaultHandler, // IRP_MN_QUERY_DEVICE_TEXT 0x0C
  42. PnpDefaultHandler, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS 0x0D
  43. PnpDefaultHandler, // no defined IRP MN code 0x0E
  44. PnpDefaultHandler, // IRP_MN_READ_CONFIG 0x0F
  45. PnpDefaultHandler, // IRP_MN_WRITE_CONFIG 0x10
  46. PnpDefaultHandler, // IRP_MN_EJECT 0x11
  47. PnpDefaultHandler, // IRP_MN_SET_LOCK 0x12
  48. PnpDefaultHandler, // IRP_MN_QUERY_ID 0x13
  49. PnpDefaultHandler, // IRP_MN_QUERY_PNP_DEVICE_STATE 0x14
  50. PnpDefaultHandler, // IRP_MN_QUERY_BUS_INFORMATION 0x15
  51. PnpDefaultHandler, // IRP_MN_DEVICE_USAGE_NOTIFICATION 0x16
  52. PnpHandleSurpriseRemoval, // IRP_MN_SURPRISE_REMOVAL 0x17
  53. };
  54. /************************************************************************/
  55. /* DispatchPnp */
  56. /************************************************************************/
  57. //
  58. // Routine Description:
  59. //
  60. // Dispatch routine for IRP_MJ_PNP IRPs. Redirect IRPs to appropriate
  61. // handlers using the IRP_MN_* value as the key.
  62. //
  63. // Arguments:
  64. //
  65. // DevObj - pointer to DEVICE_OBJECT that is the target of the request
  66. // Irp - pointer to IRP
  67. //
  68. // Return Value:
  69. //
  70. // NTSTATUS
  71. //
  72. // Log:
  73. // 2000-05-03 Code Reviewed - TomGreen, JobyL, DFritz
  74. //
  75. /************************************************************************/
  76. NTSTATUS
  77. DispatchPnp(
  78. IN PDEVICE_OBJECT DevObj,
  79. IN PIRP Irp
  80. )
  81. {
  82. PDEVICE_EXTENSION devExt = DevObj->DeviceExtension;
  83. NTSTATUS status = IoAcquireRemoveLock( &devExt->RemoveLock , Irp );
  84. if( NT_SUCCESS( status ) ) {
  85. // Acquire RemoveLock succeeded
  86. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
  87. ULONG minorFunc = irpSp->MinorFunction;
  88. TR_VERBOSE(("DispatchPnp - RemoveLock acquired - DevObj= %x , Irp= %x", DevObj, Irp));
  89. //
  90. // Call appropriate handler based on PnP IRP_MN_xxx code
  91. //
  92. // note: Handler will complete the IRP
  93. //
  94. if( minorFunc >= arraysize(PnpDispatchTable) ) {
  95. status = PnpDefaultHandler( devExt, Irp );
  96. } else {
  97. status = PnpDispatchTable[ minorFunc ]( devExt, Irp );
  98. }
  99. } else {
  100. // Acquire RemoveLock failed
  101. TR_FAIL(("DispatchPnp - RemoveLock acquire FAILED - DevObj= %x , Irp= %x", DevObj, Irp));
  102. Irp->IoStatus.Status = status;
  103. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  104. }
  105. return status;
  106. }
  107. /************************************************************************/
  108. /* PnpDefaultHandler */
  109. /************************************************************************/
  110. //
  111. // Routine Description:
  112. //
  113. // Default handler for PnP IRPs that this driver does not explicitly handle.
  114. //
  115. // Arguments:
  116. //
  117. // DevExt - pointer to DEVICE_EXTENSION of the DEVICE_OBJECT that is
  118. // the target of the request
  119. // Irp - pointer to IRP
  120. //
  121. // Return Value:
  122. //
  123. // NTSTATUS returned by IoCallDriver
  124. //
  125. // Log:
  126. // 2000-05-03 Code Reviewed - TomGreen, JobyL, DFritz
  127. //
  128. /************************************************************************/
  129. NTSTATUS
  130. PnpDefaultHandler(
  131. IN PDEVICE_EXTENSION DevExt,
  132. IN PIRP Irp
  133. )
  134. {
  135. NTSTATUS status;
  136. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
  137. TR_ENTER(("PnpDefaultHandler - IRP_MN = 0x%02x", irpSp->MinorFunction));
  138. IoSkipCurrentIrpStackLocation( Irp );
  139. status = IoCallDriver( DevExt->LowerDevObj, Irp );
  140. IoReleaseRemoveLock( &DevExt->RemoveLock, Irp );
  141. return status;
  142. }
  143. /************************************************************************/
  144. /* PnpHandleStart */
  145. /************************************************************************/
  146. //
  147. // Routine Description:
  148. //
  149. // Handler for PnP IRP_MN_START_DEVICE.
  150. //
  151. // Arguments:
  152. //
  153. // DevExt - pointer to DEVICE_EXTENSION of the DEVICE_OBJECT that is
  154. // the target of the request
  155. // Irp - pointer to IRP
  156. //
  157. // Return Value:
  158. //
  159. // NTSTATUS
  160. //
  161. // Log:
  162. // 2000-05-03 - Code Reviewed - TomGreen, JobyL, DFritz
  163. // - cleanup required - error handling incorrect, may
  164. // result in driver attempting to use invalid and/or
  165. // uninitialized data
  166. //
  167. /************************************************************************/
  168. NTSTATUS
  169. PnpHandleStart(
  170. IN PDEVICE_EXTENSION DevExt,
  171. IN PIRP Irp
  172. )
  173. {
  174. NTSTATUS status;
  175. TR_ENTER(("PnpHandleStart"));
  176. DevExt->PnpState = STATE_STARTING;
  177. //
  178. // Driver stack below us must successfully start before we handle the Start IRP
  179. //
  180. Irp->IoStatus.Status = STATUS_SUCCESS;
  181. IoCopyCurrentIrpStackLocationToNext( Irp );
  182. status = CallLowerDriverSync( DevExt->DevObj, Irp );
  183. if( NT_SUCCESS(status) ) {
  184. //
  185. // Driver stack below us has successfully started, continue
  186. //
  187. //
  188. // Get a copy of the DEVICE_CAPABILITIES of the stack us and
  189. // save it in our DEVICE_EXTENSION for future reference.
  190. //
  191. status = GetDeviceCapabilities( DevExt );
  192. if( NT_SUCCESS(status) ) {
  193. // get USB descriptor
  194. status = UsbGetDescriptor( DevExt );
  195. if( !NT_SUCCESS(status) ) {
  196. TR_VERBOSE(("call to UsbGetDescriptor FAILED w/status = %x",status));
  197. status = STATUS_SUCCESS; // start anyway
  198. } else {
  199. TR_VERBOSE(("call to UsbGetDescriptor - SUCCESS"));
  200. }
  201. // Configure Device
  202. status = UsbConfigureDevice( DevExt );
  203. if( !NT_SUCCESS(status) ) {
  204. TR_VERBOSE(("call to UsbConfigureDevice FAILED w/status = %x",status));
  205. status = STATUS_SUCCESS; // start anyway
  206. } else {
  207. TR_VERBOSE(("call to UsbConfigureDevice - SUCCESS"));
  208. }
  209. // get 1284 ID - just for kicks :-)
  210. {
  211. UCHAR Buffer[256];
  212. LONG retCode;
  213. RtlZeroMemory(Buffer, sizeof(Buffer));
  214. retCode = UsbGet1284Id(DevExt->DevObj, Buffer, sizeof(Buffer)-1);
  215. TR_VERBOSE(("retCode = %d",retCode));
  216. TR_VERBOSE(("strlen = %d", strlen((PCSTR)&Buffer[2])));
  217. TR_VERBOSE(("1284ID = <%s>",&Buffer[2]));
  218. }
  219. // get Pipes
  220. UsbBuildPipeList( DevExt->DevObj );
  221. // we are now STARTED
  222. DevExt->PnpState = STATE_STARTED;
  223. } else {
  224. DevExt->PnpState = STATE_START_FAILED;
  225. }
  226. } else {
  227. //
  228. // Driver stack below us has FAILED the Start, we fail too
  229. //
  230. DevExt->PnpState = STATE_START_FAILED;
  231. }
  232. Irp->IoStatus.Status = status;
  233. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  234. IoReleaseRemoveLock( &DevExt->RemoveLock, Irp );
  235. return status;
  236. }
  237. NTSTATUS
  238. PnpHandleQueryRemove(
  239. IN PDEVICE_EXTENSION DevExt,
  240. IN PIRP Irp
  241. )
  242. {
  243. NTSTATUS status;
  244. TR_ENTER(("PnpHandleQueryRemove"));
  245. IoSkipCurrentIrpStackLocation( Irp );
  246. status = IoCallDriver( DevExt->LowerDevObj, Irp );
  247. IoReleaseRemoveLock( &DevExt->RemoveLock, Irp );
  248. return status;
  249. }
  250. NTSTATUS
  251. PnpHandleRemove(
  252. IN PDEVICE_EXTENSION DevExt,
  253. IN PIRP Irp
  254. )
  255. {
  256. NTSTATUS status;
  257. KIRQL oldIrql;
  258. TR_ENTER(("PnpHandleRemove"));
  259. DevExt->PnpState = STATE_REMOVED;
  260. UsbStopReadInterruptPipeLoop( DevExt->DevObj ); // stop polling Irp if any
  261. IoSkipCurrentIrpStackLocation( Irp );
  262. status = IoCallDriver( DevExt->LowerDevObj, Irp);
  263. TR_TMP1(("PnpHandleRemove - Calling IoReleaseRemoveLockAndWait"));
  264. IoReleaseRemoveLockAndWait( &DevExt->RemoveLock, Irp );
  265. TR_TMP1(("PnpHandleRemove - Returned from IoReleaseRemoveLockAndWait"));
  266. IoDetachDevice( DevExt->LowerDevObj );
  267. // BUGBUG - verify that code in rest of driver that touches Interface
  268. // locks the extension while using it to prevent this function from
  269. // freeing the interface out from under them causing an AV
  270. KeAcquireSpinLock( &DevExt->SpinLock, &oldIrql );
  271. if( DevExt->Interface ) {
  272. PVOID ptr = DevExt->Interface;
  273. DevExt->Interface = NULL;
  274. KeReleaseSpinLock( &DevExt->SpinLock, oldIrql );
  275. ExFreePool( ptr );
  276. } else {
  277. KeReleaseSpinLock( &DevExt->SpinLock, oldIrql );
  278. }
  279. IoDeleteDevice( DevExt->DevObj );
  280. return status;
  281. }
  282. NTSTATUS
  283. PnpHandleCancelRemove(
  284. IN PDEVICE_EXTENSION DevExt,
  285. IN PIRP Irp
  286. )
  287. {
  288. NTSTATUS status;
  289. TR_ENTER(("PnpHandleCancelRemove"));
  290. IoSkipCurrentIrpStackLocation( Irp );
  291. status = IoCallDriver( DevExt->LowerDevObj, Irp );
  292. IoReleaseRemoveLock( &DevExt->RemoveLock, Irp );
  293. return status;
  294. }
  295. NTSTATUS
  296. PnpHandleStop(
  297. IN PDEVICE_EXTENSION DevExt,
  298. IN PIRP Irp
  299. )
  300. {
  301. NTSTATUS status;
  302. TR_ENTER(("PnpHandleStop"));
  303. if( DevExt->PnpState == STATE_STARTED ) {
  304. DevExt->PnpState = STATE_STOPPED;
  305. }
  306. IoSkipCurrentIrpStackLocation( Irp );
  307. status = IoCallDriver( DevExt->LowerDevObj, Irp );
  308. IoReleaseRemoveLock( &DevExt->RemoveLock, Irp );
  309. return status;
  310. }
  311. NTSTATUS
  312. PnpHandleQueryStop(
  313. IN PDEVICE_EXTENSION DevExt,
  314. IN PIRP Irp
  315. )
  316. {
  317. NTSTATUS status;
  318. TR_ENTER(("PnpHandleQueryStop"));
  319. Irp->IoStatus.Status = STATUS_SUCCESS;
  320. IoSkipCurrentIrpStackLocation( Irp );
  321. status = IoCallDriver( DevExt->LowerDevObj, Irp );
  322. IoReleaseRemoveLock( &DevExt->RemoveLock, Irp );
  323. return status;
  324. }
  325. NTSTATUS
  326. PnpHandleCancelStop(
  327. IN PDEVICE_EXTENSION DevExt,
  328. IN PIRP Irp
  329. )
  330. {
  331. NTSTATUS status;
  332. TR_ENTER(("PnpHandleStop"));
  333. IoSkipCurrentIrpStackLocation( Irp );
  334. status = IoCallDriver( DevExt->LowerDevObj, Irp );
  335. IoReleaseRemoveLock( &DevExt->RemoveLock, Irp );
  336. return status;
  337. }
  338. NTSTATUS
  339. PnpHandleQueryDeviceRelations(
  340. IN PDEVICE_EXTENSION DevExt,
  341. IN PIRP Irp
  342. )
  343. {
  344. NTSTATUS status;
  345. TR_ENTER(("PnpHandleQueryDeviceRelations"));
  346. IoSkipCurrentIrpStackLocation( Irp );
  347. status = IoCallDriver( DevExt->LowerDevObj, Irp );
  348. IoReleaseRemoveLock( &DevExt->RemoveLock, Irp );
  349. return status;
  350. }
  351. NTSTATUS
  352. PnpHandleQueryCapabilities(
  353. IN PDEVICE_EXTENSION DevExt,
  354. IN PIRP Irp
  355. )
  356. {
  357. NTSTATUS status;
  358. TR_ENTER(("PnpHandleQueryCapabilities"));
  359. IoCopyCurrentIrpStackLocationToNext( Irp );
  360. status = CallLowerDriverSync( DevExt->DevObj, Irp );
  361. if( NT_SUCCESS( status ) ) {
  362. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
  363. irpSp->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = TRUE;
  364. }
  365. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  366. IoReleaseRemoveLock( &DevExt->RemoveLock, Irp );
  367. return status;
  368. }
  369. NTSTATUS
  370. PnpHandleSurpriseRemoval(
  371. IN PDEVICE_EXTENSION DevExt,
  372. IN PIRP Irp
  373. )
  374. {
  375. NTSTATUS status;
  376. TR_ENTER(("PnpHandleSurpriseRemoval"));
  377. DevExt->PnpState = STATE_REMOVING;
  378. TR_TMP1(("PnpHandleSurpriseRemoval"));
  379. UsbStopReadInterruptPipeLoop( DevExt->DevObj ); // stop polling Irp if any
  380. IoSkipCurrentIrpStackLocation( Irp );
  381. status = IoCallDriver( DevExt->LowerDevObj, Irp );
  382. IoReleaseRemoveLock( &DevExt->RemoveLock, Irp );
  383. return status;
  384. }
  385. NTSTATUS
  386. GetDeviceCapabilities(
  387. IN PDEVICE_EXTENSION DevExt
  388. )
  389. {
  390. NTSTATUS status;
  391. PIRP irp = IoAllocateIrp(DevExt->LowerDevObj->StackSize, FALSE);
  392. if( irp ) {
  393. PIO_STACK_LOCATION irpSp = IoGetNextIrpStackLocation( irp );
  394. // must initialize DeviceCapabilities before sending...
  395. RtlZeroMemory( &DevExt->DeviceCapabilities, sizeof(DEVICE_CAPABILITIES) );
  396. DevExt->DeviceCapabilities.Size = sizeof(DEVICE_CAPABILITIES);
  397. DevExt->DeviceCapabilities.Version = 1;
  398. DevExt->DeviceCapabilities.Address = (ULONG) -1;
  399. DevExt->DeviceCapabilities.UINumber = (ULONG) -1;
  400. // set up next irp stack location...
  401. irpSp->MajorFunction = IRP_MJ_PNP;
  402. irpSp->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
  403. irpSp->Parameters.DeviceCapabilities.Capabilities = &DevExt->DeviceCapabilities;
  404. // required initial status
  405. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  406. status = IoAcquireRemoveLock( &DevExt->RemoveLock, irp );
  407. if( NT_SUCCESS(status) ) {
  408. status = CallLowerDriverSync( DevExt->DevObj, irp );
  409. IoReleaseRemoveLock( &DevExt->RemoveLock, irp );
  410. } else {
  411. TR_VERBOSE(("We're in the process of being removed - abort"));
  412. status = STATUS_DELETE_PENDING;
  413. }
  414. IoFreeIrp( irp );
  415. } else {
  416. status = STATUS_INSUFFICIENT_RESOURCES;
  417. }
  418. return status;
  419. }