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.

760 lines
17 KiB

  1. /***************************************************************************
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. SCUTIL.C
  5. Abstract:
  6. 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. VOID
  22. IncIoCount(
  23. PSCUTIL_EXTENSION pExt
  24. )
  25. {
  26. ULONG count;
  27. count = InterlockedIncrement(&pExt->IoCount);
  28. KeClearEvent(&pExt->OkToStop);
  29. }
  30. VOID
  31. DecIoCount(
  32. PSCUTIL_EXTENSION pExt
  33. )
  34. {
  35. ULONG count;
  36. count = InterlockedDecrement(&pExt->IoCount);
  37. if (count == 0) {
  38. KeSetEvent(&pExt->OkToStop,
  39. 0,
  40. FALSE);
  41. }
  42. }
  43. VOID
  44. StartIoctls(
  45. PSCUTIL_EXTENSION pExt
  46. )
  47. {
  48. LIST_ENTRY head;
  49. InterlockedExchange(&pExt->IoctlQueueState,
  50. PASS_IOCTLS);
  51. pExt->RestartIoctls = TRUE;
  52. // Now drain the queued list
  53. InitializeListHead(&head);
  54. IrpList_Drain(&pExt->PendingIrpQueue,
  55. &head);
  56. while (!IsListEmpty(&head)) {
  57. PLIST_ENTRY ple;
  58. PIRP pIrp;
  59. ple = RemoveHeadList(&head);
  60. pIrp = CONTAINING_RECORD(ple, IRP, Tail.Overlay.ListEntry);
  61. IncIoCount(pExt);
  62. SmartcardDeviceControl(pExt->SmartcardExtension,
  63. pIrp);
  64. DecIoCount(pExt);
  65. IoReleaseRemoveLock(pExt->RemoveLock,
  66. pIrp);
  67. }
  68. }
  69. VOID
  70. StopIoctls(
  71. PSCUTIL_EXTENSION pExt
  72. )
  73. {
  74. InterlockedExchange(&pExt->IoctlQueueState,
  75. QUEUE_IOCTLS);
  76. }
  77. VOID
  78. FailIoctls(
  79. PSCUTIL_EXTENSION pExt
  80. )
  81. {
  82. LIST_ENTRY head;
  83. InterlockedExchange(&pExt->IoctlQueueState,
  84. FAIL_IOCTLS);
  85. InitializeListHead(&head);
  86. IrpList_Drain(&pExt->PendingIrpQueue,
  87. &head);
  88. while (!IsListEmpty(&head)) {
  89. PLIST_ENTRY ple;
  90. PIRP pIrp;
  91. ple = RemoveHeadList(&head);
  92. pIrp = CONTAINING_RECORD(ple, IRP, Tail.Overlay.ListEntry);
  93. IoReleaseRemoveLock(pExt->RemoveLock,
  94. pIrp);
  95. pIrp->IoStatus.Information = 0;
  96. pIrp->IoStatus.Status = STATUS_DELETE_PENDING;
  97. IoCompleteRequest(pIrp,
  98. IO_NO_INCREMENT);
  99. }
  100. }
  101. QUEUE_STATE
  102. GetIoctlQueueState(
  103. PSCUTIL_EXTENSION pExt
  104. )
  105. {
  106. return InterlockedCompareExchange(&pExt->IoctlQueueState,
  107. PASS_IOCTLS,
  108. INVALID_STATE);
  109. }
  110. NTSTATUS
  111. ScUtil_SystemControl(
  112. PDEVICE_OBJECT DeviceObject,
  113. PIRP Irp
  114. )
  115. /*++
  116. Routine Description:
  117. forwards IRP_MJ_SYSTEM_CONTROL
  118. Arguments:
  119. Return Value:
  120. --*/
  121. {
  122. PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
  123. NTSTATUS status = STATUS_SUCCESS;
  124. __try
  125. {
  126. SmartcardDebug( DEBUG_TRACE, ("ScUtilSystemControl Enter\n"));
  127. IoSkipCurrentIrpStackLocation(Irp);
  128. status = IoCallDriver(pExt->LowerDeviceObject, Irp);
  129. }
  130. __finally
  131. {
  132. SmartcardDebug( DEBUG_TRACE, ("ScUtilSystemControl Exit : 0x%x\n",status ));
  133. }
  134. return status;
  135. }
  136. NTSTATUS
  137. OnRequestComplete(
  138. PDEVICE_OBJECT DeviceObject,
  139. PIRP Irp,
  140. PKEVENT Event
  141. )
  142. /*++
  143. Routine Description:
  144. Completion routine for UsbScForwardAndWait
  145. Arguments:
  146. Return Value:
  147. --*/
  148. {
  149. NTSTATUS status = STATUS_SUCCESS;
  150. __try
  151. {
  152. SmartcardDebug( DEBUG_TRACE, ("OnRequestComplete Enter\n"));
  153. KeSetEvent(Event,
  154. 0,
  155. FALSE);
  156. status = STATUS_MORE_PROCESSING_REQUIRED;
  157. }
  158. __finally
  159. {
  160. SmartcardDebug( DEBUG_TRACE, ("OnRequestComplete Exit : 0x%x\n",status ));
  161. }
  162. return status;
  163. }
  164. NTSTATUS
  165. ScUtil_ForwardAndWait(
  166. PDEVICE_OBJECT DeviceObject,
  167. PIRP Irp
  168. )
  169. /*++
  170. Routine Description:
  171. Sends an irp down the stack and waits for its completion.
  172. Arguments:
  173. Return Value:
  174. --*/
  175. {
  176. KEVENT event;
  177. PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
  178. NTSTATUS status = STATUS_UNSUCCESSFUL;
  179. __try
  180. {
  181. SmartcardDebug( DEBUG_TRACE, ("ScUtilForwardAndWait Enter\n"));
  182. KeInitializeEvent(&event,
  183. NotificationEvent,
  184. FALSE);
  185. IoCopyCurrentIrpStackLocationToNext(Irp);
  186. IoSetCompletionRoutine(Irp,
  187. (PIO_COMPLETION_ROUTINE) OnRequestComplete,
  188. (PVOID) &event,
  189. TRUE,
  190. TRUE,
  191. TRUE);
  192. ASSERT(pExt->LowerDeviceObject);
  193. IoCallDriver(pExt->LowerDeviceObject,
  194. Irp);
  195. KeWaitForSingleObject(&event,
  196. Executive,
  197. KernelMode,
  198. FALSE,
  199. NULL);
  200. status = Irp->IoStatus.Status;
  201. }
  202. __finally
  203. {
  204. SmartcardDebug( DEBUG_TRACE, ("ScUtilForwardAndWait Exit : 0x%x\n",status));
  205. }
  206. return status;
  207. }
  208. NTSTATUS
  209. ScUtil_Cancel(
  210. PDEVICE_OBJECT DeviceObject,
  211. PIRP Irp
  212. )
  213. {
  214. PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
  215. NTSTATUS status = STATUS_SUCCESS;
  216. KIRQL irql;
  217. __try
  218. {
  219. SmartcardDebug( DEBUG_TRACE, ("ScUtil_Cancel Enter\n"));
  220. Irp->IoStatus.Information = 0;
  221. Irp->IoStatus.Status = STATUS_CANCELLED;
  222. KeAcquireSpinLock(&pExt->SmartcardExtension->OsData->SpinLock,
  223. &irql);
  224. pExt->SmartcardExtension->OsData->NotificationIrp = NULL;
  225. KeReleaseSpinLock(&pExt->SmartcardExtension->OsData->SpinLock,
  226. irql);
  227. IoReleaseCancelSpinLock(Irp->CancelIrql);
  228. IoReleaseRemoveLock(pExt->RemoveLock,
  229. Irp);
  230. IoCompleteRequest(
  231. Irp,
  232. IO_NO_INCREMENT);
  233. }
  234. __finally
  235. {
  236. SmartcardDebug( DEBUG_TRACE, ("ScUtil_Cancel Exit : 0x%x\n",status ));
  237. }
  238. return status;
  239. }
  240. NTSTATUS
  241. ScUtil_CancelTrackingIrp(
  242. PSCUTIL_EXTENSION pExt
  243. )
  244. {
  245. NTSTATUS status = STATUS_UNSUCCESSFUL;
  246. PSMARTCARD_EXTENSION pSmartcardExtension = pExt->SmartcardExtension;
  247. PIRP notificationIrp = NULL;
  248. KIRQL irql;
  249. KIRQL cancelIrql;
  250. __try
  251. {
  252. SmartcardDebug(DEBUG_TRACE,
  253. ("Enter: ScUtil_CancelTrackingIrp\n"));
  254. IoAcquireCancelSpinLock(&cancelIrql);
  255. // cancel pending notification irps
  256. KeAcquireSpinLock(&pSmartcardExtension->OsData->SpinLock,
  257. &irql);
  258. if ( pSmartcardExtension->OsData->NotificationIrp ) {
  259. // reset the cancel function so that it won't be called anymore
  260. IoSetCancelRoutine(pSmartcardExtension->OsData->NotificationIrp,
  261. NULL);
  262. pSmartcardExtension->OsData->NotificationIrp->CancelIrql = cancelIrql;
  263. notificationIrp = pSmartcardExtension->OsData->NotificationIrp;
  264. pSmartcardExtension->OsData->NotificationIrp = NULL;
  265. }
  266. KeReleaseSpinLock(&pSmartcardExtension->OsData->SpinLock,
  267. irql);
  268. if (notificationIrp) {
  269. IoSetCancelRoutine(notificationIrp,
  270. NULL);
  271. }
  272. IoReleaseCancelSpinLock(cancelIrql);
  273. if (notificationIrp) {
  274. notificationIrp->IoStatus.Information = 0;
  275. notificationIrp->IoStatus.Status = STATUS_CANCELLED;
  276. status = STATUS_CANCELLED;
  277. IoReleaseRemoveLock(pExt->RemoveLock,
  278. notificationIrp);
  279. IoCompleteRequest(notificationIrp,
  280. IO_NO_INCREMENT);
  281. }
  282. }
  283. __finally
  284. {
  285. SmartcardDebug(DEBUG_TRACE,
  286. ("Exit: ScUtil_CancelTrackingIrp (0x%x)\n", status));
  287. }
  288. return status;
  289. }
  290. NTSTATUS
  291. ScUtil_Initialize(
  292. SCUTIL_HANDLE *UtilHandle,
  293. PDEVICE_OBJECT PhysicalDeviceObject,
  294. PDEVICE_OBJECT LowerDeviceObject,
  295. PSMARTCARD_EXTENSION SmartcardExtension,
  296. PIO_REMOVE_LOCK RemoveLock,
  297. PNP_CALLBACK StartDevice,
  298. PNP_CALLBACK StopDevice,
  299. PNP_CALLBACK RemoveDevice,
  300. PNP_CALLBACK FreeResources,
  301. POWER_CALLBACK SetPowerState
  302. )
  303. {
  304. NTSTATUS status = STATUS_UNSUCCESSFUL;
  305. PSCUTIL_EXTENSION pExt = (PSCUTIL_EXTENSION) ExAllocatePool(NonPagedPool,
  306. sizeof(SCUTIL_EXTENSION));
  307. *UtilHandle = pExt;
  308. PAGED_CODE();
  309. __try
  310. {
  311. SmartcardDebug(DEBUG_TRACE,
  312. ("Enter: ScUtil_Initialize\n"));
  313. pExt->LowerDeviceObject = LowerDeviceObject;
  314. pExt->PhysicalDeviceObject = PhysicalDeviceObject;
  315. pExt->SmartcardExtension = SmartcardExtension;
  316. pExt->RemoveLock = RemoveLock;
  317. pExt->StartDevice = StartDevice;
  318. pExt->StopDevice = StopDevice;
  319. pExt->RemoveDevice = RemoveDevice;
  320. pExt->FreeResources = FreeResources;
  321. pExt->SetPowerState = SetPowerState;
  322. IoInitializeRemoveLock(RemoveLock,
  323. 'LUCS',
  324. 0,
  325. 20);
  326. KeInitializeEvent(&pExt->OkToStop,
  327. NotificationEvent,
  328. TRUE);
  329. pExt->IoCount = 0;
  330. pExt->ReaderOpen = 0;
  331. pExt->PowerState = PowerDeviceUnspecified;
  332. IrpList_Init(&pExt->PendingIrpQueue,
  333. IrpList_CancelRoutine,
  334. NULL);
  335. pExt->RestartIoctls = FALSE;
  336. SetPnPState(pExt,
  337. DEVICE_STATE_INITIALIZED);
  338. // register our new device
  339. status = IoRegisterDeviceInterface(PhysicalDeviceObject,
  340. &SmartCardReaderGuid,
  341. NULL,
  342. &pExt->DeviceName);
  343. }
  344. __finally
  345. {
  346. SmartcardDebug(DEBUG_TRACE,
  347. ("Exit: ScUtil_Initialize (0x%x)\n", status));
  348. }
  349. return status;
  350. }
  351. NTSTATUS
  352. ScUtil_DeviceIOControl(
  353. PDEVICE_OBJECT DeviceObject,
  354. PIRP Irp
  355. )
  356. {
  357. NTSTATUS status = STATUS_UNSUCCESSFUL;
  358. PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
  359. QUEUE_STATE state;
  360. BOOLEAN complete = FALSE;
  361. ASSERT(pExt);
  362. __try
  363. {
  364. SmartcardDebug(DEBUG_TRACE,
  365. ("Enter: ScUtil_DeviceIOControl\n"));
  366. status = IoAcquireRemoveLock(pExt->RemoveLock,
  367. Irp);
  368. if (!NT_SUCCESS(status)) {
  369. // the device has been removed. Fail the call
  370. status = STATUS_DEVICE_REMOVED;
  371. complete = TRUE;
  372. __leave;
  373. }
  374. state = GetIoctlQueueState(pExt);
  375. if ( state == QUEUE_IOCTLS) {
  376. //
  377. // Need to queue Irp
  378. //
  379. status = IrpList_EnqueueEx(&pExt->PendingIrpQueue,
  380. Irp,
  381. TRUE);
  382. if (!NT_SUCCESS(status)) {
  383. // the irp couldn't be queued.
  384. IoReleaseRemoveLock(pExt->RemoveLock,
  385. Irp);
  386. complete = TRUE;
  387. }
  388. __leave;
  389. } else if (state == FAIL_IOCTLS) {
  390. status = STATUS_DEVICE_REMOVED;
  391. complete = TRUE;
  392. __leave;
  393. }
  394. IncIoCount(pExt);
  395. status = SmartcardDeviceControl(pExt->SmartcardExtension,
  396. Irp);
  397. IoReleaseRemoveLock(pExt->RemoveLock,
  398. Irp);
  399. DecIoCount(pExt);
  400. }
  401. __finally
  402. {
  403. if (complete) {
  404. Irp->IoStatus.Information = 0;
  405. Irp->IoStatus.Status = status;
  406. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  407. }
  408. SmartcardDebug(DEBUG_TRACE,
  409. ("Exit: ScUtil_DeviceIOControl (0x%x)\n", status));
  410. }
  411. return status;
  412. }
  413. NTSTATUS
  414. ScUtil_Cleanup(
  415. PDEVICE_OBJECT DeviceObject,
  416. PIRP Irp
  417. )
  418. {
  419. NTSTATUS status = STATUS_UNSUCCESSFUL;
  420. PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
  421. PSMARTCARD_EXTENSION pSmartcardExtension = pExt->SmartcardExtension;
  422. KIRQL cancelIrql;
  423. ASSERT(pExt);
  424. __try
  425. {
  426. SmartcardDebug(DEBUG_TRACE,
  427. ("Enter: ScUtil_Cleanup\n"));
  428. ScUtil_CancelTrackingIrp(pExt);
  429. Irp->IoStatus.Information = 0;
  430. Irp->IoStatus.Status = STATUS_SUCCESS;
  431. IoCompleteRequest(Irp,
  432. IO_NO_INCREMENT);
  433. status = STATUS_SUCCESS;
  434. }
  435. __finally
  436. {
  437. SmartcardDebug(DEBUG_TRACE,
  438. ("Exit: ScUtil_Cleanup (0x%x)\n", status));
  439. }
  440. return status;
  441. }
  442. NTSTATUS
  443. ScUtil_UnloadDriver(
  444. PDRIVER_OBJECT DriverObject
  445. )
  446. {
  447. NTSTATUS status = STATUS_UNSUCCESSFUL;
  448. PAGED_CODE();
  449. __try
  450. {
  451. SmartcardDebug(DEBUG_TRACE,
  452. ("Enter: ScUtil_UnloadDriver\n"));
  453. }
  454. __finally
  455. {
  456. SmartcardDebug(DEBUG_TRACE,
  457. ("Exit: ScUtil_UnloadDriver (0x%x)\n", status));
  458. }
  459. return status;
  460. }
  461. NTSTATUS
  462. ScUtil_CreateClose(
  463. PDEVICE_OBJECT DeviceObject,
  464. PIRP Irp
  465. )
  466. {
  467. NTSTATUS status = STATUS_UNSUCCESSFUL;
  468. PSCUTIL_EXTENSION pExt = *((PSCUTIL_EXTENSION*) DeviceObject->DeviceExtension);
  469. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
  470. ASSERT(pExt);
  471. PAGED_CODE();
  472. __try
  473. {
  474. SmartcardDebug(DEBUG_TRACE,
  475. ("Enter: ScUtil_CreateClose\n"));
  476. if ( pIrpStack->MajorFunction == IRP_MJ_CREATE ) {
  477. status = IoAcquireRemoveLock(pExt->RemoveLock,
  478. DeviceObject);
  479. if (!NT_SUCCESS(status)) {
  480. status = STATUS_DEVICE_REMOVED;
  481. __leave;
  482. }
  483. // test if the device has been opened already
  484. if ( InterlockedCompareExchange(&pExt->ReaderOpen,
  485. 1,
  486. 0) == 0 ) {
  487. //
  488. //
  489. } else {
  490. // the device is already in use
  491. status = STATUS_UNSUCCESSFUL;
  492. // release the lock
  493. IoReleaseRemoveLock(pExt->RemoveLock,
  494. DeviceObject);
  495. }
  496. } else {
  497. if (InterlockedCompareExchange(&pExt->ReaderOpen,
  498. 0,
  499. 1) == 1) {
  500. IoReleaseRemoveLock(pExt->RemoveLock,
  501. DeviceObject);
  502. }
  503. }
  504. }
  505. __finally
  506. {
  507. Irp->IoStatus.Status = status;
  508. Irp->IoStatus.Information = 0;
  509. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  510. SmartcardDebug(DEBUG_TRACE,
  511. ("Exit: ScUtil_CreateClose (0x%x)\n", status));
  512. }
  513. return status;
  514. }