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.

811 lines
17 KiB

  1. /***************************************************************************
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. pnp.C
  5. Abstract:
  6. PnP Routines for Smartcard Driver Utility Library
  7. Environment:
  8. Kernel Mode Only
  9. Notes:
  10. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  11. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  12. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  13. PURPOSE.
  14. Copyright (c) 2001 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 05/14/2002 : created
  17. Authors:
  18. Randy Aull
  19. ****************************************************************************/
  20. #include "pch.h"
  21. #include "pnp.h"
  22. #include "irplist.h"
  23. #include "scutil.h"
  24. #include "scpriv.h"
  25. PNPSTATE
  26. SetPnPState(
  27. PSCUTIL_EXTENSION pExt,
  28. PNPSTATE State
  29. )
  30. {
  31. PNPSTATE prevState;
  32. prevState = pExt->PrevState;
  33. pExt->PrevState = pExt->PnPState;
  34. pExt->PnPState = State;
  35. return prevState;
  36. }
  37. NTSTATUS
  38. ScUtilDefaultPnpHandler(
  39. PDEVICE_OBJECT DeviceObject,
  40. PIRP Irp
  41. )
  42. /*++
  43. Routine Description:
  44. Passes IRP_MJ_PNP to next lower driver
  45. Arguments:
  46. Return Value:
  47. --*/
  48. {
  49. PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
  50. NTSTATUS status = STATUS_SUCCESS;
  51. __try
  52. {
  53. SmartcardDebug( DEBUG_TRACE, ("ScUtilDefaultPnpHandler Enter\n"));
  54. IoSkipCurrentIrpStackLocation(Irp);
  55. ASSERT(pExt->LowerDeviceObject);
  56. status = IoCallDriver(pExt->LowerDeviceObject, Irp);
  57. }
  58. __finally
  59. {
  60. SmartcardDebug( DEBUG_TRACE, ("ScUtilDefaultPnpHandler Exit : 0x%x\n",status ));
  61. }
  62. return status;
  63. }
  64. NTSTATUS
  65. ScUtil_PnP(
  66. PDEVICE_OBJECT DeviceObject,
  67. PIRP Irp
  68. )
  69. {
  70. NTSTATUS status = STATUS_UNSUCCESSFUL;
  71. PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
  72. PIO_STACK_LOCATION irpStack;
  73. BOOLEAN deviceRemoved = FALSE;
  74. PSMARTCARD_EXTENSION smartcardExtension = pExt->SmartcardExtension;
  75. ASSERT(pExt);
  76. PAGED_CODE();
  77. __try
  78. {
  79. SmartcardDebug(DEBUG_TRACE,
  80. ("Enter: ScUtil_PnP\n"));
  81. status = IoAcquireRemoveLock(pExt->RemoveLock,
  82. Irp);
  83. if (!NT_SUCCESS(status)) {
  84. Irp->IoStatus.Information = 0;
  85. Irp->IoStatus.Status = status;
  86. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  87. __leave;
  88. }
  89. irpStack = IoGetCurrentIrpStackLocation(Irp);
  90. switch (irpStack->MinorFunction) {
  91. case IRP_MN_START_DEVICE:
  92. SmartcardDebug( DEBUG_DRIVER, ("ScUtil_PnP: IRP_MN_START_DEVICE \n"));
  93. SetPnPState(pExt,
  94. DEVICE_STATE_STARTING);
  95. status = ScUtil_ForwardAndWait(DeviceObject,
  96. Irp);
  97. if (NT_SUCCESS(status)) {
  98. status = ScUtilStartDevice(DeviceObject,
  99. Irp);
  100. }
  101. break;
  102. case IRP_MN_QUERY_REMOVE_DEVICE:
  103. SmartcardDebug( DEBUG_DRIVER, ("ScUtil_PnP: IRP_MN_QUERY_REMOVE_DEVICE\n"));
  104. status = ScUtilQueryRemoveDevice(DeviceObject,
  105. Irp);
  106. if (!NT_SUCCESS(status)) {
  107. break;
  108. }
  109. Irp->IoStatus.Status = STATUS_SUCCESS;
  110. status = ScUtilDefaultPnpHandler(DeviceObject,
  111. Irp);
  112. __leave;
  113. case IRP_MN_REMOVE_DEVICE:
  114. SmartcardDebug( DEBUG_DRIVER, ("ScUtil_PnP: IRP_MN_REMOVE_DEVICE\n"));
  115. status = ScUtilRemoveDevice(DeviceObject,
  116. Irp);
  117. if (NT_SUCCESS(status)) {
  118. deviceRemoved = TRUE;
  119. __leave;
  120. }
  121. break;
  122. case IRP_MN_SURPRISE_REMOVAL:
  123. SmartcardDebug( DEBUG_DRIVER, ("ScUtil_PnP: IRP_MN_SUPRISE_REMOVE\n"));
  124. status = ScUtilSurpriseRemoval(DeviceObject,
  125. Irp);
  126. if (!NT_SUCCESS(status)) {
  127. break;
  128. }
  129. Irp->IoStatus.Status = STATUS_SUCCESS;
  130. status = ScUtilDefaultPnpHandler(DeviceObject,
  131. Irp);
  132. __leave;
  133. case IRP_MN_CANCEL_REMOVE_DEVICE:
  134. SmartcardDebug( DEBUG_DRIVER, ("ScUtil_PnP: IRP_MN_CANCEL_REMOVE_DEVICE\n"));
  135. status = ScUtil_ForwardAndWait(DeviceObject,
  136. Irp);
  137. if (NT_SUCCESS(status)) {
  138. status = ScUtilCancelRemoveDevice(DeviceObject,
  139. Irp);
  140. }
  141. break;
  142. case IRP_MN_STOP_DEVICE:
  143. SmartcardDebug( DEBUG_DRIVER, ("ScUtil_PnP: IRP_MN_STOP_DEVICE\n"));
  144. status = ScUtilStopDevice(DeviceObject,
  145. Irp);
  146. if (NT_SUCCESS(status)) {
  147. Irp->IoStatus.Status = STATUS_SUCCESS;
  148. status = ScUtilDefaultPnpHandler(DeviceObject,
  149. Irp);
  150. __leave;
  151. }
  152. break;
  153. case IRP_MN_QUERY_STOP_DEVICE:
  154. SmartcardDebug( DEBUG_DRIVER, ("ScUtil_PnP: IRP_MN_QUERY_STOP_DEVICE\n"));
  155. status = ScUtilQueryStopDevice(DeviceObject,
  156. Irp);
  157. if (!NT_SUCCESS(status)) {
  158. break;
  159. }
  160. Irp->IoStatus.Status = STATUS_SUCCESS;
  161. status = ScUtilDefaultPnpHandler(DeviceObject,
  162. Irp);
  163. __leave; // We don't need to complete this so just skip it.
  164. case IRP_MN_CANCEL_STOP_DEVICE:
  165. SmartcardDebug( DEBUG_DRIVER, ("ScUtil_PnP: IRP_MN_CANCEL_STOP_DEVICE\n"));
  166. // Lower drivers must handle this irp first
  167. status = ScUtil_ForwardAndWait(DeviceObject,
  168. Irp);
  169. if (NT_SUCCESS(status)) {
  170. status = ScUtilCancelStopDevice(DeviceObject,
  171. Irp);
  172. }
  173. break;
  174. case IRP_MN_QUERY_CAPABILITIES:
  175. SmartcardDebug( DEBUG_DRIVER, ("ScUtil_PnP: IRP_MN_QUERY_CAPABILITIES\n"));
  176. status = ScUtil_ForwardAndWait(DeviceObject,
  177. Irp);
  178. if (NT_SUCCESS(status)) {
  179. pExt->DeviceCapabilities = *irpStack->Parameters.DeviceCapabilities.Capabilities;
  180. }
  181. break;
  182. default:
  183. SmartcardDebug( DEBUG_DRIVER, ("ScUtil_PnP: IRP_MN_...%lx\n", irpStack->MinorFunction ));
  184. status = ScUtilDefaultPnpHandler(DeviceObject,
  185. Irp);
  186. __leave; // We don't need to complete this so just skip it.
  187. }
  188. Irp->IoStatus.Status = status;
  189. IoCompleteRequest(Irp,
  190. IO_NO_INCREMENT);
  191. }
  192. __finally
  193. {
  194. if (deviceRemoved == FALSE) {
  195. IoReleaseRemoveLock(pExt->RemoveLock,
  196. Irp);
  197. }
  198. SmartcardDebug(DEBUG_TRACE,
  199. ("Exit: ScUtil_PnP (0x%x)\n", status));
  200. }
  201. return status;
  202. }
  203. NTSTATUS
  204. ScUtilStartDevice(
  205. PDEVICE_OBJECT DeviceObject,
  206. PIRP Irp
  207. )
  208. /*++
  209. Routine Description:
  210. Handles the IRP_MN_START_DEVICE
  211. Gets the usb descriptors from the reader and configures it.
  212. Also starts "polling" the interrupt pipe
  213. Arguments:
  214. Return Value:
  215. --*/
  216. {
  217. NTSTATUS status = STATUS_UNSUCCESSFUL;
  218. PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
  219. __try
  220. {
  221. SmartcardDebug( DEBUG_TRACE, ("ScUtilStartDevice Enter\n" ));
  222. status = pExt->StartDevice(DeviceObject,
  223. Irp);
  224. if (!NT_SUCCESS(status)) {
  225. SetPnPState(pExt,
  226. DEVICE_STATE_START_FAILURE);
  227. __leave;
  228. }
  229. SetPnPState(pExt,
  230. DEVICE_STATE_START_SUCCESS);
  231. StartIoctls(pExt);
  232. IncIoCount(pExt);
  233. status = IoSetDeviceInterfaceState(&pExt->DeviceName,
  234. TRUE);
  235. }
  236. __finally
  237. {
  238. SmartcardDebug( DEBUG_TRACE, ("ScUtilStartDevice Exit : 0x%x\n", status ));
  239. }
  240. return status;
  241. }
  242. NTSTATUS
  243. ScUtilStopDevice(
  244. PDEVICE_OBJECT DeviceObject,
  245. PIRP Irp
  246. )
  247. /*++
  248. Routine Description:
  249. Handles IRP_MN_STOP_DEVICE
  250. Stops "polling" the interrupt pipe and frees resources allocated in StartDevice
  251. Arguments:
  252. Return Value:
  253. --*/
  254. {
  255. NTSTATUS status = STATUS_UNSUCCESSFUL;
  256. PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
  257. __try
  258. {
  259. SmartcardDebug( DEBUG_TRACE, ("ScUtilStopDevice Enter\n" ));
  260. if (!DeviceObject) {
  261. __leave;
  262. }
  263. pExt->StopDevice(DeviceObject,
  264. Irp);
  265. }
  266. __finally
  267. {
  268. SmartcardDebug( DEBUG_TRACE, ("ScUtilStopDevice Exit : 0x%x\n", status ));
  269. }
  270. return status;
  271. }
  272. NTSTATUS
  273. ScUtilQueryRemoveDevice(
  274. PDEVICE_OBJECT DeviceObject,
  275. PIRP Irp
  276. )
  277. /*++
  278. Routine Description:
  279. Handles IRP_MN_QUERY_REMOVE
  280. Disables the reader and prepares it for the IRP_MN_REMOVE
  281. Arguments:
  282. Return Value:
  283. --*/
  284. {
  285. NTSTATUS status = STATUS_SUCCESS;
  286. PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
  287. __try
  288. {
  289. SmartcardDebug( DEBUG_TRACE, ("ScUtilQueryRemoveDevice Enter\n" ));
  290. // check if the reader has been opened
  291. if (pExt->ReaderOpen) {
  292. status = STATUS_UNSUCCESSFUL;
  293. __leave;
  294. }
  295. SetPnPState(pExt,
  296. DEVICE_STATE_REMOVING);
  297. StopIoctls(pExt);
  298. }
  299. __finally
  300. {
  301. SmartcardDebug( DEBUG_TRACE, ("ScUtilQueryRemoveDevice Exit : 0x%x\n", status ));
  302. }
  303. return status;
  304. }
  305. NTSTATUS
  306. ScUtilCancelRemoveDevice(
  307. PDEVICE_OBJECT DeviceObject,
  308. PIRP Irp
  309. )
  310. /*++
  311. Routine Description:
  312. handles IRP_MN_CANCEL_REMOVE
  313. undoes actions in QueryRemove
  314. Arguments:
  315. Return Value:
  316. STATUS_SUCCESS
  317. --*/
  318. {
  319. NTSTATUS status = STATUS_UNSUCCESSFUL;
  320. PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
  321. __try
  322. {
  323. SmartcardDebug( DEBUG_TRACE, ("ScUtilCancelRemoveDevice Enter\n" ));
  324. if (pExt->PnPState != DEVICE_STATE_REMOVING) {
  325. status = STATUS_SUCCESS;
  326. __leave;
  327. }
  328. if (pExt->PrevState == DEVICE_STATE_START_SUCCESS) {
  329. StartIoctls(pExt);
  330. }
  331. SetPnPState(pExt,
  332. pExt->PrevState);
  333. status = STATUS_SUCCESS;
  334. }
  335. __finally
  336. {
  337. SmartcardDebug( DEBUG_TRACE, ("ScUtilCancelRemoveDevice Exit : 0x%x\n", status ));
  338. }
  339. return status;
  340. }
  341. NTSTATUS
  342. ScUtilRemoveDevice(
  343. PDEVICE_OBJECT DeviceObject,
  344. PIRP Irp
  345. )
  346. /*++
  347. Routine Description:
  348. handles IRP_MN_REMOVE_DEVICE
  349. stops and unloads the device.
  350. Arguments:
  351. Return Value:
  352. --*/
  353. {
  354. NTSTATUS status = STATUS_UNSUCCESSFUL;
  355. PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
  356. __try
  357. {
  358. SmartcardDebug( DEBUG_TRACE, ("ScUtilRemoveDevice Enter\n" ));
  359. if (pExt->PnPState != DEVICE_STATE_SUPRISE_REMOVING) {
  360. FailIoctls(pExt);
  361. status = IoSetDeviceInterfaceState(&pExt->DeviceName,
  362. FALSE);
  363. if (pExt->FreeResources) {
  364. pExt->FreeResources(DeviceObject,
  365. Irp);
  366. }
  367. }
  368. IoReleaseRemoveLockAndWait(pExt->RemoveLock,
  369. Irp);
  370. SetPnPState(pExt,
  371. DEVICE_STATE_REMOVED);
  372. Irp->IoStatus.Status = STATUS_SUCCESS;
  373. IoSkipCurrentIrpStackLocation (Irp);
  374. status = IoCallDriver (pExt->LowerDeviceObject, Irp);
  375. pExt->RemoveDevice(DeviceObject,
  376. Irp);
  377. // delete the symbolic link
  378. if( pExt->DeviceName.Buffer != NULL ) {
  379. RtlFreeUnicodeString(&pExt->DeviceName);
  380. pExt->DeviceName.Buffer = NULL;
  381. }
  382. if( pExt->SmartcardExtension->OsData != NULL ) {
  383. SmartcardExit(pExt->SmartcardExtension);
  384. }
  385. if (pExt->SmartcardExtension->ReaderExtension != NULL) {
  386. ExFreePool(pExt->SmartcardExtension->ReaderExtension);
  387. pExt->SmartcardExtension->ReaderExtension = NULL;
  388. }
  389. // Detach from the usb driver
  390. if (pExt->LowerDeviceObject) {
  391. IoDetachDevice(pExt->LowerDeviceObject);
  392. pExt->LowerDeviceObject = NULL;
  393. }
  394. ExFreePool(pExt);
  395. // delete the device object
  396. IoDeleteDevice(DeviceObject);
  397. }
  398. __finally
  399. {
  400. SmartcardDebug( DEBUG_TRACE, ("ScUtilRemoveDevice Exit : 0x%x\n", status ));
  401. }
  402. return status;
  403. }
  404. NTSTATUS
  405. ScUtilSurpriseRemoval(
  406. PDEVICE_OBJECT DeviceObject,
  407. PIRP Irp
  408. )
  409. /*++
  410. Routine Description:
  411. handles IRP_MN_SUPRISE_REMOVE
  412. Does the same as QueryRemove
  413. Arguments:
  414. Return Value:
  415. --*/
  416. {
  417. NTSTATUS status = STATUS_UNSUCCESSFUL;
  418. PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
  419. __try
  420. {
  421. SmartcardDebug( DEBUG_TRACE, ("ScUtilSurpriseRemoval Enter\n" ));
  422. FailIoctls(pExt);
  423. SetPnPState(pExt,
  424. DEVICE_STATE_REMOVING);
  425. status = IoSetDeviceInterfaceState(&pExt->DeviceName,
  426. FALSE);
  427. if (pExt->FreeResources) {
  428. pExt->FreeResources(DeviceObject,
  429. Irp);
  430. }
  431. status = STATUS_SUCCESS;
  432. }
  433. __finally
  434. {
  435. SmartcardDebug( DEBUG_TRACE, ("ScUtilSurpriseRemoval Exit : 0x%x\n", status ));
  436. }
  437. return status;
  438. }
  439. NTSTATUS
  440. ScUtilQueryStopDevice(
  441. PDEVICE_OBJECT DeviceObject,
  442. PIRP Irp
  443. )
  444. /*++
  445. Routine Description:
  446. handles IRP_MN_QUERY_STOP
  447. Stops interrupt "polling" and waits for I/O to complete
  448. Arguments:
  449. Return Value:
  450. --*/
  451. {
  452. NTSTATUS status = STATUS_UNSUCCESSFUL;
  453. PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
  454. __try
  455. {
  456. SmartcardDebug( DEBUG_TRACE, ("ScUtilQueryStopDevice Enter\n"));
  457. if (!NT_SUCCESS(status)) {
  458. __leave;
  459. }
  460. SetPnPState(pExt,
  461. DEVICE_STATE_STOPPING);
  462. StopIoctls(pExt);
  463. DecIoCount(pExt);
  464. // Wait for all IO to complete before stopping
  465. status = KeWaitForSingleObject(&pExt->OkToStop,
  466. Executive,
  467. KernelMode,
  468. FALSE,
  469. NULL);
  470. if (!NT_SUCCESS(status)) {
  471. __leave;
  472. }
  473. }
  474. __finally
  475. {
  476. SmartcardDebug( DEBUG_TRACE, ("ScUtilQueryStopDevice Exit : 0x%x\n", status ));
  477. }
  478. return status;
  479. }
  480. NTSTATUS
  481. ScUtilCancelStopDevice(
  482. PDEVICE_OBJECT DeviceObject,
  483. PIRP Irp
  484. )
  485. /*++
  486. Routine Description:
  487. Restarts Interrupt polling
  488. Arguments:
  489. Return Value:
  490. --*/
  491. {
  492. NTSTATUS status = STATUS_UNSUCCESSFUL;
  493. PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
  494. __try
  495. {
  496. SmartcardDebug( DEBUG_TRACE, ("ScUtilCancelStopDevice Enter\n"));
  497. SetPnPState(pExt,
  498. pExt->PrevState);
  499. IncIoCount(pExt);
  500. StartIoctls(pExt);
  501. status = STATUS_SUCCESS;
  502. }
  503. __finally
  504. {
  505. SmartcardDebug( DEBUG_TRACE, ("ScUtilCancelStopDevice Exit : 0x%x\n", status ));
  506. }
  507. return status;
  508. }