Source code of Windows XP (NT5)
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.

2482 lines
70 KiB

  1. /*****************************************************************************
  2. @doc INT EXT
  3. ******************************************************************************
  4. * $ProjectName: $
  5. * $ProjectRevision: $
  6. *-----------------------------------------------------------------------------
  7. * $Source: z:/pr/cmbs0/sw/sccmn50m.ms/rcs/sccmnt5.c $
  8. * $Revision: 1.7 $
  9. *-----------------------------------------------------------------------------
  10. * $Author: WFrischauf $
  11. *-----------------------------------------------------------------------------
  12. * History: see EOF
  13. *-----------------------------------------------------------------------------
  14. *
  15. * Copyright OMNIKEY AG
  16. ******************************************************************************/
  17. #include <stdio.h>
  18. #include "sccmn50m.h"
  19. //
  20. // We do not need these functions after init anymore
  21. //
  22. #pragma alloc_text(INIT, DriverEntry)
  23. #pragma alloc_text(PAGEABLE, SCCMN50M_AddDevice)
  24. #pragma alloc_text(PAGEABLE, SCCMN50M_CreateDevice)
  25. #if DBG
  26. #pragma optimize ("", off)
  27. #endif
  28. BOOLEAN DeviceSlot[MAXIMUM_SMARTCARD_READERS];
  29. /*****************************************************************************
  30. Routine Description:
  31. This routine is called at system initialization time to initialize
  32. this driver.
  33. Arguments:
  34. DriverObject - Supplies the driver object.
  35. RegistryPath - Supplies the registry path for this driver.
  36. Return Value:
  37. STATUS_SUCCESS - We could initialize at least one device.
  38. STATUS_NO_SUCH_DEVICE - We could not initialize even one device.
  39. *****************************************************************************/
  40. NTSTATUS
  41. DriverEntry(
  42. IN PDRIVER_OBJECT DriverObject,
  43. IN PUNICODE_STRING RegistryPath
  44. )
  45. {
  46. NTSTATUS status = STATUS_SUCCESS;
  47. ULONG device;
  48. //#if DBG
  49. // SmartcardSetDebugLevel(DEBUG_ALL);
  50. //#endif
  51. SmartcardDebug(
  52. DEBUG_TRACE,
  53. ("%s!DriverEntry: Enter - %s %s\n",
  54. DRIVER_NAME,
  55. __DATE__,
  56. __TIME__)
  57. )
  58. // Initialize the Driver Object with driver's entry points
  59. DriverObject->DriverUnload = SCCMN50M_DriverUnload;
  60. DriverObject->MajorFunction[IRP_MJ_CREATE] = SCCMN50M_CreateClose;
  61. DriverObject->MajorFunction[IRP_MJ_CLOSE] = SCCMN50M_CreateClose;
  62. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = SCCMN50M_Cleanup;
  63. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SCCMN50M_DeviceControl;
  64. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = SCCMN50M_SystemControl;
  65. DriverObject->MajorFunction[IRP_MJ_PNP] = SCCMN50M_PnP;
  66. DriverObject->MajorFunction[IRP_MJ_POWER] = SCCMN50M_Power;
  67. DriverObject->DriverExtension->AddDevice = SCCMN50M_AddDevice;
  68. return status;
  69. }
  70. /*****************************************************************************
  71. Routine Description:
  72. Creates a new device without starting it.
  73. Arguments:
  74. Return Value:
  75. *****************************************************************************/
  76. NTSTATUS
  77. SCCMN50M_AddDevice (
  78. IN PDRIVER_OBJECT DriverObject,
  79. IN PDEVICE_OBJECT PhysicalDeviceObject
  80. )
  81. {
  82. NTSTATUS status;
  83. PDEVICE_OBJECT DeviceObject = NULL;
  84. UCHAR PropertyBuffer[1024];
  85. ULONG ResultLength;
  86. PAGED_CODE();
  87. SmartcardDebug(
  88. DEBUG_TRACE,
  89. ( "%s!AddDevice: Enter\n",
  90. DRIVER_NAME)
  91. );
  92. try
  93. {
  94. PDEVICE_EXTENSION deviceExtension;
  95. // create a device instance
  96. status = SCCMN50M_CreateDevice(
  97. DriverObject,
  98. PhysicalDeviceObject,
  99. &DeviceObject
  100. );
  101. if (status != STATUS_SUCCESS)
  102. {
  103. leave;
  104. }
  105. deviceExtension = DeviceObject->DeviceExtension;
  106. // and attach to the PDO
  107. ATTACHED_DEVICE_OBJECT = IoAttachDeviceToDeviceStack(
  108. DeviceObject,
  109. PhysicalDeviceObject
  110. );
  111. ASSERT(ATTACHED_DEVICE_OBJECT != NULL);
  112. if (ATTACHED_DEVICE_OBJECT == NULL)
  113. {
  114. SmartcardLogError(
  115. DriverObject,
  116. SCCMN50M_CANT_CONNECT_TO_ASSIGNED_PORT,
  117. NULL,
  118. status
  119. );
  120. status = STATUS_UNSUCCESSFUL;
  121. leave;
  122. }
  123. // register our new device
  124. status = IoRegisterDeviceInterface(
  125. PhysicalDeviceObject,
  126. &SmartCardReaderGuid,
  127. NULL,
  128. &deviceExtension->PnPDeviceName
  129. );
  130. ASSERT(status == STATUS_SUCCESS);
  131. DeviceObject->Flags |= DO_BUFFERED_IO;
  132. DeviceObject->Flags |= DO_POWER_PAGABLE;
  133. DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  134. }
  135. finally
  136. {
  137. if (status != STATUS_SUCCESS)
  138. {
  139. SCCMN50M_RemoveDevice(DeviceObject);
  140. }
  141. }
  142. SmartcardDebug(
  143. DEBUG_TRACE,
  144. ( "%s!AddDevice: Exit %x\n",
  145. DRIVER_NAME,
  146. status)
  147. );
  148. return status;
  149. }
  150. /*****************************************************************************
  151. Routine Description:
  152. Trys to read the reader name from the registry
  153. Arguments:
  154. DriverObject context of call
  155. SmartcardExtension ptr to smartcard extension
  156. Return Value:
  157. none
  158. ******************************************************************************/
  159. VOID SCCMN50M_SetVendorAndIfdName(
  160. IN PDEVICE_OBJECT PhysicalDeviceObject,
  161. IN PSMARTCARD_EXTENSION SmartcardExtension
  162. )
  163. {
  164. RTL_QUERY_REGISTRY_TABLE parameters[3];
  165. UNICODE_STRING vendorNameU;
  166. ANSI_STRING vendorNameA;
  167. UNICODE_STRING ifdTypeU;
  168. ANSI_STRING ifdTypeA;
  169. HANDLE regKey = NULL;
  170. RtlZeroMemory (parameters, sizeof(parameters));
  171. RtlZeroMemory (&vendorNameU, sizeof(vendorNameU));
  172. RtlZeroMemory (&vendorNameA, sizeof(vendorNameA));
  173. RtlZeroMemory (&ifdTypeU, sizeof(ifdTypeU));
  174. RtlZeroMemory (&ifdTypeA, sizeof(ifdTypeA));
  175. try
  176. {
  177. //
  178. // try to read the reader name from the registry
  179. // if that does not work, we will use the default
  180. // (hardcoded) name
  181. //
  182. if (IoOpenDeviceRegistryKey(PhysicalDeviceObject,
  183. PLUGPLAY_REGKEY_DEVICE,
  184. KEY_READ,
  185. &regKey) != STATUS_SUCCESS)
  186. {
  187. SmartcardDebug(DEBUG_ERROR,
  188. ("%s!SetVendorAndIfdName: IoOpenDeviceRegistryKey failed\n",DRIVER_NAME));
  189. leave;
  190. }
  191. parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  192. parameters[0].Name = L"VendorName";
  193. parameters[0].EntryContext = &vendorNameU;
  194. parameters[0].DefaultType = REG_SZ;
  195. parameters[0].DefaultData = &vendorNameU;
  196. parameters[0].DefaultLength = 0;
  197. parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
  198. parameters[1].Name = L"IfdType";
  199. parameters[1].EntryContext = &ifdTypeU;
  200. parameters[1].DefaultType = REG_SZ;
  201. parameters[1].DefaultData = &ifdTypeU;
  202. parameters[1].DefaultLength = 0;
  203. if (RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  204. (PWSTR) regKey,
  205. parameters,
  206. NULL,
  207. NULL) != STATUS_SUCCESS)
  208. {
  209. SmartcardDebug(DEBUG_ERROR,
  210. ("%s!SetVendorAndIfdName: RtlQueryRegistryValues failed\n",DRIVER_NAME));
  211. leave;
  212. }
  213. if (RtlUnicodeStringToAnsiString(&vendorNameA,&vendorNameU,TRUE) != STATUS_SUCCESS)
  214. {
  215. SmartcardDebug(DEBUG_ERROR,
  216. ("%s!SetVendorAndIfdName: RtlUnicodeStringToAnsiString failed\n",DRIVER_NAME));
  217. leave;
  218. }
  219. if (RtlUnicodeStringToAnsiString(&ifdTypeA,&ifdTypeU,TRUE) != STATUS_SUCCESS)
  220. {
  221. SmartcardDebug(DEBUG_ERROR,
  222. ("%s!SetVendorAndIfdName: RtlUnicodeStringToAnsiString failed\n",DRIVER_NAME));
  223. leave;
  224. }
  225. if (vendorNameA.Length == 0 ||
  226. vendorNameA.Length > MAXIMUM_ATTR_STRING_LENGTH ||
  227. ifdTypeA.Length == 0 ||
  228. ifdTypeA.Length > MAXIMUM_ATTR_STRING_LENGTH)
  229. {
  230. SmartcardDebug(DEBUG_ERROR,
  231. ("%s!SetVendorAndIfdName: vendor name or ifdtype not found or to long\n",DRIVER_NAME));
  232. leave;
  233. }
  234. RtlCopyMemory(SmartcardExtension->VendorAttr.VendorName.Buffer,
  235. vendorNameA.Buffer,
  236. vendorNameA.Length);
  237. SmartcardExtension->VendorAttr.VendorName.Length = vendorNameA.Length;
  238. RtlCopyMemory(SmartcardExtension->VendorAttr.IfdType.Buffer,
  239. ifdTypeA.Buffer,
  240. ifdTypeA.Length);
  241. SmartcardExtension->VendorAttr.IfdType.Length = ifdTypeA.Length;
  242. SmartcardDebug(DEBUG_DRIVER,
  243. ("%s!SetVendorAndIfdName: overwritting vendor name and ifdtype\n",DRIVER_NAME));
  244. }
  245. finally
  246. {
  247. if (vendorNameU.Buffer != NULL)
  248. {
  249. RtlFreeUnicodeString(&vendorNameU);
  250. }
  251. if (vendorNameA.Buffer != NULL)
  252. {
  253. RtlFreeAnsiString(&vendorNameA);
  254. }
  255. if (ifdTypeU.Buffer != NULL)
  256. {
  257. RtlFreeUnicodeString(&ifdTypeU);
  258. }
  259. if (ifdTypeA.Buffer != NULL)
  260. {
  261. RtlFreeAnsiString(&ifdTypeA);
  262. }
  263. if (regKey != NULL)
  264. {
  265. ZwClose (regKey);
  266. }
  267. }
  268. }
  269. /*****************************************************************************
  270. Routine Description:
  271. This routine creates an object for the physical device specified and
  272. sets up the deviceExtension.
  273. Arguments:
  274. Return Value:
  275. *****************************************************************************/
  276. NTSTATUS
  277. SCCMN50M_CreateDevice(
  278. IN PDRIVER_OBJECT DriverObject,
  279. IN PDEVICE_OBJECT PhysicalDeviceObject,
  280. OUT PDEVICE_OBJECT *DeviceObject
  281. )
  282. {
  283. PDEVICE_EXTENSION deviceExtension;
  284. NTSTATUS status = STATUS_SUCCESS;
  285. ULONG deviceInstance;
  286. PREADER_EXTENSION readerExtension;
  287. PSMARTCARD_EXTENSION smartcardExtension;
  288. UNICODE_STRING DriverID;
  289. RTL_QUERY_REGISTRY_TABLE ParamTable[2];
  290. UNICODE_STRING RegistryPath;
  291. DWORD dwStart;
  292. UNICODE_STRING Tmp;
  293. WCHAR Buffer[64];
  294. // this is a list of our supported data rates
  295. PAGED_CODE();
  296. *DeviceObject = NULL;
  297. for ( deviceInstance = 0;deviceInstance < MAXIMUM_SMARTCARD_READERS;deviceInstance++ )
  298. {
  299. if (DeviceSlot[deviceInstance] == FALSE)
  300. {
  301. DeviceSlot[deviceInstance] = TRUE;
  302. break;
  303. }
  304. }
  305. if (deviceInstance == MAXIMUM_SMARTCARD_READERS)
  306. {
  307. SmartcardLogError(
  308. DriverObject,
  309. SCCMN50M_CANT_CREATE_MORE_DEVICES,
  310. NULL,
  311. 0
  312. );
  313. return STATUS_INSUFFICIENT_RESOURCES;
  314. }
  315. //
  316. // construct the device name
  317. //
  318. DriverID.Buffer = Buffer;
  319. DriverID.MaximumLength = sizeof(Buffer);
  320. DriverID.Length = 0;
  321. RtlInitUnicodeString(&Tmp,CARDMAN_DEVICE_NAME);
  322. RtlCopyUnicodeString(&DriverID,&Tmp);
  323. DriverID.Buffer[(DriverID.Length)/sizeof(WCHAR)-1] = L'0' + (WCHAR)deviceInstance;
  324. // Create the device object
  325. status = IoCreateDevice(
  326. DriverObject,
  327. sizeof(DEVICE_EXTENSION),
  328. &DriverID,
  329. FILE_DEVICE_SMARTCARD,
  330. 0,
  331. FALSE,
  332. DeviceObject
  333. );
  334. if (status != STATUS_SUCCESS)
  335. {
  336. SmartcardLogError(
  337. DriverObject,
  338. SCCMN50M_CANT_CREATE_DEVICE,
  339. NULL,
  340. 0
  341. );
  342. return status;
  343. }
  344. SmartcardDebug(
  345. DEBUG_DRIVER,
  346. ( "%s!CreateDevice: Device created\n",
  347. DRIVER_NAME)
  348. );
  349. // set up the device extension.
  350. deviceExtension = (*DeviceObject)->DeviceExtension;
  351. deviceExtension->DeviceInstance = deviceInstance;
  352. smartcardExtension = &deviceExtension->SmartcardExtension;
  353. // Used for stop / start notification
  354. KeInitializeEvent(
  355. &deviceExtension->ReaderStarted,
  356. NotificationEvent,
  357. FALSE
  358. );
  359. // This event signals that the serial driver has been closed
  360. KeInitializeEvent(
  361. &deviceExtension->SerialCloseDone,
  362. NotificationEvent,
  363. TRUE
  364. );
  365. // Used to keep track of open close calls
  366. KeInitializeEvent(
  367. &deviceExtension->ReaderClosed,
  368. NotificationEvent,
  369. TRUE
  370. );
  371. KeInitializeSpinLock(&deviceExtension->SpinLock);
  372. // Allocate data struct space for smart card reader
  373. smartcardExtension->ReaderExtension = ExAllocatePool(
  374. NonPagedPool,
  375. sizeof(READER_EXTENSION)
  376. );
  377. if (smartcardExtension->ReaderExtension == NULL)
  378. {
  379. SmartcardLogError(
  380. DriverObject,
  381. SCCMN50M_NO_MEMORY,
  382. NULL,
  383. 0
  384. );
  385. return STATUS_INSUFFICIENT_RESOURCES;
  386. }
  387. readerExtension = smartcardExtension->ReaderExtension;
  388. RtlZeroMemory(readerExtension, sizeof(READER_EXTENSION));
  389. // ----------------------------------------------
  390. // initialize mutex
  391. // ----------------------------------------------
  392. KeInitializeMutex(&smartcardExtension->ReaderExtension->CardManIOMutex,0L);
  393. // Write the version of the lib we use to the smartcard extension
  394. smartcardExtension->Version = SMCLIB_VERSION;
  395. smartcardExtension->SmartcardRequest.BufferSize =
  396. smartcardExtension->SmartcardReply.BufferSize = MIN_BUFFER_SIZE;
  397. //
  398. // Now let the lib allocate the buffer for data transmission
  399. // We can either tell the lib how big the buffer should be
  400. // by assigning a value to BufferSize or let the lib
  401. // allocate the default size
  402. //
  403. status = SmartcardInitialize(smartcardExtension);
  404. if (status != STATUS_SUCCESS)
  405. {
  406. SmartcardLogError(
  407. DriverObject,
  408. (smartcardExtension->OsData ? SCCMN50M_WRONG_LIB_VERSION : SCCMN50M_NO_MEMORY),
  409. NULL,
  410. 0
  411. );
  412. return status;
  413. }
  414. // Save deviceObject
  415. smartcardExtension->OsData->DeviceObject = *DeviceObject;
  416. // Set up call back functions
  417. smartcardExtension->ReaderFunction[RDF_TRANSMIT] = SCCMN50M_Transmit;
  418. smartcardExtension->ReaderFunction[RDF_SET_PROTOCOL] = SCCMN50M_SetProtocol;
  419. smartcardExtension->ReaderFunction[RDF_CARD_POWER] = SCCMN50M_CardPower;
  420. smartcardExtension->ReaderFunction[RDF_CARD_TRACKING] = SCCMN50M_CardTracking;
  421. smartcardExtension->ReaderFunction[RDF_IOCTL_VENDOR] = SCCMN50M_IoCtlVendor;
  422. SCCMN50M_InitializeSmartcardExtension(smartcardExtension,deviceInstance);
  423. // try to overwrite with registry values
  424. SCCMN50M_SetVendorAndIfdName(PhysicalDeviceObject, smartcardExtension);
  425. // save the current power state of the reader
  426. readerExtension->ReaderPowerState = PowerReaderWorking;
  427. return STATUS_SUCCESS;
  428. }
  429. /*****************************************************************************
  430. Routine Description:
  431. Open the serial device, start card tracking and register our
  432. device interface. If any of the calls here fails we don't care
  433. to rollback since a stop will be called later which we then
  434. use to clean up.
  435. Arguments:
  436. Return Value:
  437. *****************************************************************************/
  438. NTSTATUS
  439. SCCMN50M_StartDevice(
  440. IN PDEVICE_OBJECT DeviceObject
  441. )
  442. {
  443. NTSTATUS status;
  444. PIRP irp;
  445. SmartcardDebug(
  446. DEBUG_TRACE,
  447. ( "%s!StartDevice: Enter\n",
  448. DRIVER_NAME)
  449. );
  450. irp = IoAllocateIrp(
  451. (CCHAR) (DeviceObject->StackSize + 1),
  452. FALSE
  453. );
  454. ASSERT(irp != NULL);
  455. if (irp == NULL)
  456. {
  457. return STATUS_NO_MEMORY;
  458. }
  459. _try {
  460. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  461. PSMARTCARD_EXTENSION pSmartcardExtension = &deviceExtension->SmartcardExtension;
  462. PIO_STACK_LOCATION irpStack;
  463. HANDLE handle = 0;
  464. IO_STATUS_BLOCK ioStatusBlock;
  465. //
  466. // Open the underlying serial driver.
  467. // This is necessary for two reasons:
  468. // a) The serial driver can't be used without opening it
  469. // b) The call will go through serenum first which informs
  470. // it to stop looking/polling for new devices.
  471. //
  472. irp->UserIosb = &ioStatusBlock;
  473. IoSetNextIrpStackLocation(irp);
  474. irpStack = IoGetCurrentIrpStackLocation(irp);
  475. irpStack->MajorFunction = IRP_MJ_CREATE;
  476. irpStack->Parameters.Create.Options = 0;
  477. irpStack->Parameters.Create.ShareAccess = 0;
  478. irpStack->Parameters.Create.FileAttributes = 0;
  479. irpStack->Parameters.Create.EaLength = 0;
  480. status = SCCMN50M_CallSerialDriver(
  481. ATTACHED_DEVICE_OBJECT,
  482. irp
  483. );
  484. if (status != STATUS_SUCCESS)
  485. {
  486. leave;
  487. }
  488. KeClearEvent(&deviceExtension->SerialCloseDone);
  489. pSmartcardExtension->SmartcardReply.BufferLength = pSmartcardExtension->SmartcardReply.BufferSize;
  490. pSmartcardExtension->SmartcardRequest.BufferLength = 0;
  491. pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERENUM_GET_PORT_NAME;
  492. status = SCCMN50M_SerialIo(pSmartcardExtension);
  493. //
  494. // Channel id which the reader is using,
  495. // in our case the Portnumber
  496. // WCHAR are used. e.g. COM3
  497. pSmartcardExtension->ReaderCapabilities.Channel =
  498. pSmartcardExtension->SmartcardReply.Buffer[6] -'0';
  499. status = SCCMN50M_InitializeCardMan(&deviceExtension->SmartcardExtension);
  500. if (status != STATUS_SUCCESS)
  501. {
  502. leave;
  503. }
  504. status = SCCMN50M_StartCardTracking(deviceExtension);
  505. if (status != STATUS_SUCCESS)
  506. {
  507. leave;
  508. }
  509. status = IoSetDeviceInterfaceState(
  510. &deviceExtension->PnPDeviceName,
  511. TRUE
  512. );
  513. if (status != STATUS_SUCCESS)
  514. {
  515. leave;
  516. }
  517. deviceExtension->IoCount = 0;
  518. KeSetEvent(&deviceExtension->ReaderStarted, 0, FALSE);
  519. SmartcardDebug(DEBUG_DRIVER,
  520. ("%s!Event ReaderStarted was set\n",DRIVER_NAME));
  521. }
  522. _finally {
  523. if (status == STATUS_SHARED_IRQ_BUSY)
  524. {
  525. SmartcardLogError(
  526. DeviceObject,
  527. SCCMN50M_IRQ_BUSY,
  528. NULL,
  529. status
  530. );
  531. }
  532. IoFreeIrp(irp);
  533. }
  534. SmartcardDebug(
  535. DEBUG_TRACE,
  536. ( "%s!StartDevice: Exit\n",
  537. DRIVER_NAME)
  538. );
  539. return status;
  540. }
  541. /*****************************************************************************
  542. Routine Description:
  543. Finishes card tracking requests and closes the connection to the
  544. serial driver.
  545. Arguments:
  546. Return Value:
  547. *****************************************************************************/
  548. VOID
  549. SCCMN50M_StopDevice(
  550. IN PDEVICE_EXTENSION DeviceExtension
  551. )
  552. {
  553. NTSTATUS status;
  554. PUCHAR requestBuffer;
  555. PSMARTCARD_EXTENSION smartcardExtension;
  556. SmartcardDebug(
  557. DEBUG_TRACE,
  558. ( "%s!StopDevice: Enter\n",
  559. DRIVER_NAME)
  560. );
  561. if (KeReadStateEvent(&DeviceExtension->SerialCloseDone) == 0l)
  562. {
  563. smartcardExtension = &DeviceExtension->SmartcardExtension;
  564. SCCMN50M_StopCardTracking(DeviceExtension);
  565. SCCMN50M_CloseSerialDriver (smartcardExtension->OsData->DeviceObject);
  566. // now wait until the connetion to serial is closed
  567. status = KeWaitForSingleObject(
  568. &DeviceExtension->SerialCloseDone,
  569. Executive,
  570. KernelMode,
  571. FALSE,
  572. NULL
  573. );
  574. ASSERT(status == STATUS_SUCCESS);
  575. }
  576. SmartcardDebug(
  577. DEBUG_TRACE,
  578. ( "%s!StopDevice: Exit\n",
  579. DRIVER_NAME)
  580. );
  581. }
  582. NTSTATUS
  583. SCCMN50M_SystemControl(
  584. PDEVICE_OBJECT DeviceObject,
  585. PIRP Irp
  586. )
  587. /*++
  588. --*/
  589. {
  590. PDEVICE_EXTENSION DeviceExtension;
  591. NTSTATUS status = STATUS_SUCCESS;
  592. DeviceExtension = DeviceObject->DeviceExtension;
  593. IoSkipCurrentIrpStackLocation(Irp);
  594. status = IoCallDriver(DeviceExtension->SmartcardExtension.ReaderExtension->AttachedDeviceObject, Irp);
  595. return status;
  596. }
  597. /*****************************************************************************
  598. Routine Description:
  599. This is our IOCTL dispatch function
  600. Arguments:
  601. Return Value:
  602. *****************************************************************************/
  603. NTSTATUS
  604. SCCMN50M_DeviceControl(
  605. PDEVICE_OBJECT DeviceObject,
  606. PIRP Irp
  607. )
  608. {
  609. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  610. NTSTATUS status;
  611. KIRQL irql;
  612. PIO_STACK_LOCATION irpSp;
  613. SmartcardDebug(DEBUG_TRACE,
  614. ("%s!DeviceIoControl: Enter\n",DRIVER_NAME));
  615. irpSp = IoGetCurrentIrpStackLocation(Irp);
  616. PAGED_CODE();
  617. #if DBG
  618. switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
  619. {
  620. case IOCTL_SMARTCARD_EJECT:
  621. SmartcardDebug(DEBUG_IOCTL,
  622. ("%s!DeviceControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_EJECT"));
  623. break;
  624. case IOCTL_SMARTCARD_GET_ATTRIBUTE:
  625. SmartcardDebug(DEBUG_IOCTL,
  626. ("%s!DeviceControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_GET_ATTRIBUTE"));
  627. break;
  628. case IOCTL_SMARTCARD_GET_LAST_ERROR:
  629. SmartcardDebug(DEBUG_IOCTL,
  630. ("%s!DeviceControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_GET_LAST_ERROR"));
  631. break;
  632. case IOCTL_SMARTCARD_GET_STATE:
  633. SmartcardDebug(DEBUG_IOCTL,
  634. ("%s!DeviceControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_GET_STATE"));
  635. break;
  636. case IOCTL_SMARTCARD_IS_ABSENT:
  637. SmartcardDebug(DEBUG_IOCTL,
  638. ("%s!DeviceControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_IS_ABSENT"));
  639. break;
  640. case IOCTL_SMARTCARD_IS_PRESENT:
  641. SmartcardDebug(DEBUG_IOCTL,
  642. ("%s!DeviceControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_IS_PRESENT"));
  643. break;
  644. case IOCTL_SMARTCARD_POWER:
  645. SmartcardDebug(DEBUG_IOCTL,
  646. ("%s!DeviceControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_POWER"));
  647. break;
  648. case IOCTL_SMARTCARD_SET_ATTRIBUTE:
  649. SmartcardDebug(DEBUG_IOCTL,
  650. ("%s!DeviceControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_SET_ATTRIBUTE"));
  651. break;
  652. case IOCTL_SMARTCARD_SET_PROTOCOL:
  653. SmartcardDebug(DEBUG_IOCTL,
  654. ("%s!DeviceControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_SET_PROTOCOL"));
  655. break;
  656. case IOCTL_SMARTCARD_SWALLOW:
  657. SmartcardDebug(DEBUG_IOCTL,
  658. ("%s!DeviceControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_SWALLOW"));
  659. break;
  660. case IOCTL_SMARTCARD_TRANSMIT:
  661. SmartcardDebug(DEBUG_IOCTL,
  662. ("%s!DeviceControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_TRANSMIT"));
  663. break;
  664. default:
  665. SmartcardDebug(DEBUG_IOCTL,
  666. ("%s!DeviceControl: %s\n", DRIVER_NAME, "Vendor specific or unexpected IOCTL"));
  667. break;
  668. }
  669. #endif
  670. if (KeReadStateEvent(&deviceExtension->SerialCloseDone) != 0l)
  671. {
  672. // Device has been removed
  673. // fail the call
  674. status = STATUS_DEVICE_REMOVED;
  675. Irp->IoStatus.Information = 0;
  676. Irp->IoStatus.Status = STATUS_DEVICE_REMOVED;
  677. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  678. return status;
  679. }
  680. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  681. if (deviceExtension->IoCount < 0)
  682. {
  683. SmartcardDebug(DEBUG_DRIVER,
  684. ("%s!waiting for Event ReaderStarted\n",DRIVER_NAME));
  685. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  686. status = KeWaitForSingleObject(
  687. &deviceExtension->ReaderStarted,
  688. Executive,
  689. KernelMode,
  690. FALSE,
  691. NULL
  692. );
  693. ASSERT(status == STATUS_SUCCESS);
  694. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  695. }
  696. ASSERT(deviceExtension->IoCount >= 0);
  697. deviceExtension->IoCount++;
  698. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  699. status = SmartcardAcquireRemoveLock(&deviceExtension->SmartcardExtension);
  700. if (status != STATUS_SUCCESS)
  701. {
  702. // the device has been removed. Fail the call
  703. status = STATUS_DEVICE_REMOVED;
  704. Irp->IoStatus.Information = 0;
  705. Irp->IoStatus.Status = STATUS_DEVICE_REMOVED;
  706. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  707. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  708. deviceExtension->IoCount--;
  709. ASSERT(deviceExtension->IoCount >= 0);
  710. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  711. SmartcardDebug(DEBUG_TRACE,
  712. ("%s!DeviceIoControl: Exit %x\n",DRIVER_NAME,status));
  713. return status;
  714. }
  715. // wait for update thread
  716. KeWaitForSingleObject(
  717. &deviceExtension->SmartcardExtension.ReaderExtension->CardManIOMutex,
  718. Executive,
  719. KernelMode,
  720. FALSE,
  721. NULL
  722. );
  723. status = SCCMN50M_UpdateCurrentState(&(deviceExtension->SmartcardExtension));
  724. status = SmartcardDeviceControl(
  725. &(deviceExtension->SmartcardExtension),
  726. Irp
  727. );
  728. // release for update thread
  729. KeReleaseMutex(
  730. &deviceExtension->SmartcardExtension.ReaderExtension->CardManIOMutex,
  731. FALSE
  732. );
  733. SmartcardReleaseRemoveLock(&deviceExtension->SmartcardExtension);
  734. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  735. deviceExtension->IoCount--;
  736. ASSERT(deviceExtension->IoCount >= 0);
  737. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  738. SmartcardDebug(DEBUG_TRACE,
  739. ("%s!DeviceIoControl: Exit %x\n",DRIVER_NAME,status));
  740. return status;
  741. }
  742. /*****************************************************************************
  743. Routine Description:
  744. This function closes the connection to the serial driver when the reader
  745. has been removed (unplugged). This function runs as a system thread at
  746. IRQL == PASSIVE_LEVEL. It waits for the remove event that is set by
  747. the IoCompletionRoutine
  748. Arguments:
  749. Return Value:
  750. *****************************************************************************/
  751. VOID
  752. SCCMN50M_CloseSerialDriver(
  753. IN PDEVICE_OBJECT DeviceObject
  754. )
  755. {
  756. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  757. NTSTATUS status;
  758. PIRP irp;
  759. PIO_STACK_LOCATION irpStack;
  760. IO_STATUS_BLOCK ioStatusBlock;
  761. SmartcardDebug(
  762. DEBUG_TRACE,
  763. ( "%s!CloseSerialDriver: Enter\n",
  764. DRIVER_NAME)
  765. );
  766. //
  767. // first mark this device as 'gone'.
  768. // This will prevent that someone can re-open the device
  769. //
  770. status = IoSetDeviceInterfaceState(
  771. &deviceExtension->PnPDeviceName,
  772. FALSE
  773. );
  774. irp = IoAllocateIrp(
  775. (CCHAR) (DeviceObject->StackSize + 1),
  776. FALSE
  777. );
  778. ASSERT(irp != NULL);
  779. if (irp)
  780. {
  781. SmartcardDebug(
  782. DEBUG_DRIVER,
  783. ( "%s!CloseSerialDriver: Sending IRP_MJ_CLOSE\n",
  784. DRIVER_NAME)
  785. );
  786. IoSetNextIrpStackLocation(irp);
  787. //
  788. // We send down a close to the serial driver. This close goes
  789. // through serenum first which will trigger it to start looking
  790. // for changes on the com-port. Since our device is gone it will
  791. // call the device removal event of our PnP dispatch.
  792. //
  793. irp->UserIosb = &ioStatusBlock;
  794. irpStack = IoGetCurrentIrpStackLocation( irp );
  795. irpStack->MajorFunction = IRP_MJ_CLOSE;
  796. status = SCCMN50M_CallSerialDriver(
  797. ATTACHED_DEVICE_OBJECT,
  798. irp
  799. );
  800. ASSERT(status == STATUS_SUCCESS);
  801. IoFreeIrp(irp);
  802. }
  803. // now 'signal' that we closed the serial driver
  804. KeSetEvent(&deviceExtension->SerialCloseDone, 0, FALSE);
  805. SmartcardDebug(
  806. DEBUG_TRACE,
  807. ( "%s!CloseSerialDriver: Exit\n",
  808. DRIVER_NAME)
  809. );
  810. }
  811. /*****************************************************************************
  812. Routine Description:
  813. Arguments:
  814. Return Value:
  815. *****************************************************************************/
  816. NTSTATUS
  817. SCCMN50M_IoCompletion (
  818. IN PDEVICE_OBJECT DeviceObject,
  819. IN PIRP Irp,
  820. IN PKEVENT Event
  821. )
  822. {
  823. UNREFERENCED_PARAMETER (DeviceObject);
  824. if (Irp->Cancel)
  825. {
  826. Irp->IoStatus.Status = STATUS_CANCELLED;
  827. }
  828. else
  829. {
  830. Irp->IoStatus.Status = STATUS_MORE_PROCESSING_REQUIRED;
  831. }
  832. KeSetEvent (Event, 0, FALSE);
  833. return STATUS_MORE_PROCESSING_REQUIRED;
  834. }
  835. /*****************************************************************************
  836. Routine Description:
  837. Send an Irp to the serial driver.
  838. Arguments:
  839. Return Value:
  840. *****************************************************************************/
  841. NTSTATUS
  842. SCCMN50M_CallSerialDriver(
  843. IN PDEVICE_OBJECT DeviceObject,
  844. IN PIRP Irp
  845. )
  846. {
  847. NTSTATUS status = STATUS_SUCCESS;
  848. KEVENT Event;
  849. // Copy our stack location to the next.
  850. IoCopyCurrentIrpStackLocationToNext(Irp);
  851. //
  852. // initialize an event for process synchronization. The event is passed
  853. // to our completion routine and will be set when the serial driver is done
  854. //
  855. KeInitializeEvent(
  856. &Event,
  857. NotificationEvent,
  858. FALSE
  859. );
  860. // Our IoCompletionRoutine sets only our event
  861. IoSetCompletionRoutine (
  862. Irp,
  863. SCCMN50M_IoCompletion,
  864. &Event,
  865. TRUE,
  866. TRUE,
  867. TRUE
  868. );
  869. if (IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_POWER)
  870. {
  871. status = PoCallDriver(DeviceObject, Irp);
  872. }
  873. else
  874. {
  875. // Call the serial driver
  876. status = IoCallDriver(DeviceObject, Irp);
  877. }
  878. // Wait until the serial driver has processed the Irp
  879. if (status == STATUS_PENDING)
  880. {
  881. status = KeWaitForSingleObject(
  882. &Event,
  883. Executive,
  884. KernelMode,
  885. FALSE,
  886. NULL
  887. );
  888. ASSERT (STATUS_SUCCESS == status);
  889. status = Irp->IoStatus.Status;
  890. }
  891. return status;
  892. }
  893. /*****************************************************************************
  894. Routine Description:
  895. Arguments:
  896. Return Value:
  897. *****************************************************************************/
  898. NTSTATUS
  899. SCCMN50M_PnP(
  900. IN PDEVICE_OBJECT DeviceObject,
  901. IN PIRP Irp
  902. )
  903. {
  904. PUCHAR requestBuffer;
  905. NTSTATUS status = STATUS_SUCCESS;
  906. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  907. PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
  908. PREADER_EXTENSION readerExtension = smartcardExtension->ReaderExtension;
  909. PDEVICE_OBJECT AttachedDeviceObject;
  910. PIO_STACK_LOCATION irpStack;
  911. IO_STATUS_BLOCK ioStatusBlock;
  912. BOOLEAN deviceRemoved = FALSE, irpSkipped = FALSE;
  913. KIRQL irql;
  914. PDEVICE_CAPABILITIES DeviceCapabilities;
  915. PAGED_CODE();
  916. SmartcardDebug(
  917. DEBUG_TRACE,
  918. ( "%s!PnPDeviceControl: Enter\n",
  919. DRIVER_NAME)
  920. );
  921. status = SmartcardAcquireRemoveLock(smartcardExtension);
  922. ASSERT(status == STATUS_SUCCESS);
  923. if (status != STATUS_SUCCESS)
  924. {
  925. Irp->IoStatus.Information = 0;
  926. Irp->IoStatus.Status = status;
  927. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  928. return status;
  929. }
  930. AttachedDeviceObject = ATTACHED_DEVICE_OBJECT;
  931. irpStack = IoGetCurrentIrpStackLocation(Irp);
  932. // Now look what the PnP manager wants...
  933. switch (irpStack->MinorFunction)
  934. {
  935. case IRP_MN_START_DEVICE:
  936. SmartcardDebug(
  937. DEBUG_DRIVER,
  938. ("%s!PnPDeviceControl: IRP_MN_START_DEVICE\n",
  939. DRIVER_NAME)
  940. );
  941. // We have to call the underlying driver first
  942. status = SCCMN50M_CallSerialDriver(AttachedDeviceObject, Irp);
  943. ASSERT(NT_SUCCESS(status));
  944. if (NT_SUCCESS(status))
  945. {
  946. status = SCCMN50M_StartDevice(DeviceObject);
  947. }
  948. break;
  949. case IRP_MN_QUERY_STOP_DEVICE:
  950. SmartcardDebug(
  951. DEBUG_DRIVER,
  952. ("%s!PnPDeviceControl: IRP_MN_QUERY_STOP_DEVICE\n",
  953. DRIVER_NAME)
  954. );
  955. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  956. if (deviceExtension->IoCount > 0)
  957. {
  958. // we refuse to stop if we have pending io
  959. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  960. status = STATUS_DEVICE_BUSY;
  961. }
  962. else
  963. {
  964. // stop processing requests
  965. deviceExtension->IoCount = -1;
  966. KeClearEvent(&deviceExtension->ReaderStarted);
  967. SmartcardDebug(DEBUG_DRIVER,
  968. ("%s!Event ReaderStarted was cleared\n",DRIVER_NAME));
  969. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  970. status = SCCMN50M_CallSerialDriver(AttachedDeviceObject, Irp);
  971. }
  972. break;
  973. case IRP_MN_CANCEL_STOP_DEVICE:
  974. SmartcardDebug(
  975. DEBUG_DRIVER,
  976. ("%s!PnPDeviceControl: IRP_MN_CANCEL_STOP_DEVICE\n",
  977. DRIVER_NAME)
  978. );
  979. status = SCCMN50M_CallSerialDriver(AttachedDeviceObject, Irp);
  980. if (status == STATUS_SUCCESS)
  981. {
  982. // we can continue to process requests
  983. deviceExtension->IoCount = 0;
  984. KeSetEvent(&deviceExtension->ReaderStarted, 0, FALSE);
  985. SmartcardDebug(DEBUG_DRIVER,
  986. ("%s!Event ReaderStarted was set\n",DRIVER_NAME));
  987. }
  988. break;
  989. case IRP_MN_STOP_DEVICE:
  990. SmartcardDebug(
  991. DEBUG_DRIVER,
  992. ("%s!PnPDeviceControl: IRP_MN_STOP_DEVICE\n",
  993. DRIVER_NAME)
  994. );
  995. SCCMN50M_StopDevice(deviceExtension);
  996. //
  997. // we don't do anything since a stop is only used
  998. // to reconfigure hw-resources like interrupts and io-ports
  999. //
  1000. status = SCCMN50M_CallSerialDriver(AttachedDeviceObject, Irp);
  1001. break;
  1002. case IRP_MN_QUERY_REMOVE_DEVICE:
  1003. SmartcardDebug(
  1004. DEBUG_DRIVER,
  1005. ("%s!PnPDeviceControl: IRP_MN_QUERY_REMOVE_DEVICE\n",
  1006. DRIVER_NAME)
  1007. );
  1008. // disable the interface (and ignore possible errors)
  1009. IoSetDeviceInterfaceState(&deviceExtension->PnPDeviceName,
  1010. FALSE);
  1011. // now look if someone is currently connected to us
  1012. if (KeReadStateEvent(&deviceExtension->ReaderClosed) == 0l)
  1013. {
  1014. //
  1015. // someone is connected, fail the call
  1016. // we will enable the device interface in
  1017. // IRP_MN_CANCEL_REMOVE_DEVICE again
  1018. //
  1019. status = STATUS_UNSUCCESSFUL;
  1020. break;
  1021. }
  1022. // pass the call to the next driver in the stack
  1023. status = SCCMN50M_CallSerialDriver(AttachedDeviceObject, Irp);
  1024. break;
  1025. case IRP_MN_CANCEL_REMOVE_DEVICE:
  1026. SmartcardDebug(
  1027. DEBUG_DRIVER,
  1028. ("%s!PnPDeviceControl: IRP_MN_CANCEL_REMOVE_DEVICE\n",
  1029. DRIVER_NAME)
  1030. );
  1031. status = SCCMN50M_CallSerialDriver(AttachedDeviceObject, Irp);
  1032. if (status == STATUS_SUCCESS)
  1033. {
  1034. status = IoSetDeviceInterfaceState(&deviceExtension->PnPDeviceName,
  1035. TRUE);
  1036. ASSERT(status == STATUS_SUCCESS);
  1037. }
  1038. break;
  1039. case IRP_MN_REMOVE_DEVICE:
  1040. SmartcardDebug(
  1041. DEBUG_DRIVER,
  1042. ("%s!PnPDeviceControl: IRP_MN_REMOVE_DEVICE\n",
  1043. DRIVER_NAME)
  1044. );
  1045. SCCMN50M_RemoveDevice(DeviceObject);
  1046. status = SCCMN50M_CallSerialDriver(AttachedDeviceObject, Irp);
  1047. deviceRemoved = TRUE;
  1048. break;
  1049. // ---------------------
  1050. // IRP_MN_QUERY_CAPABILITIES
  1051. // ---------------------
  1052. case IRP_MN_QUERY_CAPABILITIES:
  1053. SmartcardDebug(
  1054. DEBUG_DRIVER,
  1055. ("%s!PnPDeviceControl: IRP_MN_QUERY_CAPABILITIES\n",
  1056. DRIVER_NAME));
  1057. //
  1058. // Get the packet.
  1059. //
  1060. DeviceCapabilities=irpStack->Parameters.DeviceCapabilities.Capabilities;
  1061. if (DeviceCapabilities->Version == 1 &&
  1062. DeviceCapabilities->Size == sizeof(DEVICE_CAPABILITIES))
  1063. {
  1064. //
  1065. // Set the capabilities.
  1066. //
  1067. // We cannot wake the system.
  1068. DeviceCapabilities->SystemWake = PowerSystemUnspecified;
  1069. DeviceCapabilities->DeviceWake = PowerDeviceUnspecified;
  1070. // We have no latencies
  1071. DeviceCapabilities->D1Latency = 0;
  1072. DeviceCapabilities->D2Latency = 0;
  1073. DeviceCapabilities->D3Latency = 0;
  1074. // No locking or ejection
  1075. DeviceCapabilities->LockSupported = FALSE;
  1076. DeviceCapabilities->EjectSupported = FALSE;
  1077. // Device can be physically removed.
  1078. DeviceCapabilities->Removable = TRUE;
  1079. // No docking device
  1080. DeviceCapabilities->DockDevice = FALSE;
  1081. // Device can not be removed any time
  1082. // it has a removable media
  1083. DeviceCapabilities->SurpriseRemovalOK = FALSE;
  1084. }
  1085. //
  1086. // Pass the IRP down
  1087. //
  1088. status = SCCMN50M_CallSerialDriver(AttachedDeviceObject, Irp);
  1089. break; // end, case IRP_MN_QUERY_CAPABILITIES
  1090. default:
  1091. #if DBG
  1092. switch (irpStack->MinorFunction)
  1093. {
  1094. case IRP_MN_QUERY_DEVICE_RELATIONS :
  1095. // This is an Irp that is only useful for underlying drivers
  1096. SmartcardDebug(
  1097. DEBUG_DRIVER,
  1098. ("%s!PnPDeviceControl: IRP_MN_QUERY_DEVICE_RELATIONS\n",
  1099. DRIVER_NAME));
  1100. break;
  1101. case IRP_MN_QUERY_INTERFACE :
  1102. // This is an Irp that is only useful for underlying drivers
  1103. SmartcardDebug(
  1104. DEBUG_DRIVER,
  1105. ("%s!PnPDeviceControl: IRP_MN_QUERY_INTERFACE\n",
  1106. DRIVER_NAME));
  1107. break;
  1108. case IRP_MN_QUERY_CAPABILITIES :
  1109. // This is an Irp that is only useful for underlying drivers
  1110. SmartcardDebug(
  1111. DEBUG_DRIVER,
  1112. ("%s!PnPDeviceControl: IRP_MN_QUERY_CAPABILITIES\n",
  1113. DRIVER_NAME));
  1114. break;
  1115. case IRP_MN_QUERY_RESOURCES :
  1116. // This is an Irp that is only useful for underlying drivers
  1117. SmartcardDebug(
  1118. DEBUG_DRIVER,
  1119. ("%s!PnPDeviceControl: IRP_MN_QUERY_RESOURCES\n",
  1120. DRIVER_NAME));
  1121. break;
  1122. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS :
  1123. // This is an Irp that is only useful for underlying drivers
  1124. SmartcardDebug(
  1125. DEBUG_DRIVER,
  1126. ("%s!PnPDeviceControl: IRP_MN_QUERY_RESOURCE_REQUIEREMENTS\n",
  1127. DRIVER_NAME));
  1128. break;
  1129. case IRP_MN_QUERY_DEVICE_TEXT :
  1130. // This is an Irp that is only useful for underlying drivers
  1131. SmartcardDebug(
  1132. DEBUG_DRIVER,
  1133. ("%s!PnPDeviceControl: IRP_MN_QUERY_DEVICE_TEXT\n",
  1134. DRIVER_NAME));
  1135. break;
  1136. case IRP_MN_FILTER_RESOURCE_REQUIREMENTS :
  1137. // This is an Irp that is only useful for underlying drivers
  1138. SmartcardDebug(
  1139. DEBUG_DRIVER,
  1140. ("%s!PnPDeviceControl: IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n",
  1141. DRIVER_NAME));
  1142. break;
  1143. default :
  1144. case IRP_MN_READ_CONFIG :
  1145. // This is an Irp that is only useful for underlying drivers
  1146. SmartcardDebug(
  1147. DEBUG_DRIVER,
  1148. ("%s!PnPDeviceControl: IRP_MN_READ_CONFIG\n",
  1149. DRIVER_NAME));
  1150. break;
  1151. // This is an Irp that is only useful for underlying drivers
  1152. SmartcardDebug(
  1153. DEBUG_DRIVER,
  1154. ("%s!PnPDeviceControl: IRP_MN_...%lx\n",
  1155. DRIVER_NAME,
  1156. irpStack->MinorFunction));
  1157. break;
  1158. }
  1159. #endif
  1160. IoSkipCurrentIrpStackLocation(Irp);
  1161. status = IoCallDriver(AttachedDeviceObject, Irp);
  1162. irpSkipped = TRUE;
  1163. break;
  1164. }
  1165. if (irpSkipped == FALSE)
  1166. {
  1167. Irp->IoStatus.Status = status;
  1168. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1169. }
  1170. if (deviceRemoved == FALSE)
  1171. {
  1172. SmartcardReleaseRemoveLock(smartcardExtension);
  1173. }
  1174. SmartcardDebug(
  1175. DEBUG_TRACE,
  1176. ( "%s!PnPDeviceControl: Exit %lx\n",
  1177. DRIVER_NAME,
  1178. status)
  1179. );
  1180. return status;
  1181. }
  1182. /*****************************************************************************
  1183. Routine Description:
  1184. This function is called when the underlying stacks
  1185. completed the power transition.
  1186. Arguments:
  1187. Return Value:
  1188. *****************************************************************************/
  1189. VOID
  1190. SCCMN50M_SystemPowerCompletion(
  1191. IN PDEVICE_OBJECT DeviceObject,
  1192. IN UCHAR MinorFunction,
  1193. IN POWER_STATE PowerState,
  1194. IN PKEVENT Event,
  1195. IN PIO_STATUS_BLOCK IoStatus
  1196. )
  1197. {
  1198. UNREFERENCED_PARAMETER (DeviceObject);
  1199. UNREFERENCED_PARAMETER (MinorFunction);
  1200. UNREFERENCED_PARAMETER (PowerState);
  1201. UNREFERENCED_PARAMETER (IoStatus);
  1202. KeSetEvent(Event, 0, FALSE);
  1203. }
  1204. /*****************************************************************************
  1205. Routine Description:
  1206. This routine is called after the underlying stack powered
  1207. UP the serial port, so it can be used again.
  1208. Arguments:
  1209. Return Value:
  1210. *****************************************************************************/
  1211. NTSTATUS
  1212. SCCMN50M_DevicePowerCompletion (
  1213. IN PDEVICE_OBJECT DeviceObject,
  1214. IN PIRP Irp,
  1215. IN PSMARTCARD_EXTENSION SmartcardExtension
  1216. )
  1217. {
  1218. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1219. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1220. UCHAR pbAtrBuffer[MAXIMUM_ATR_LENGTH];
  1221. ULONG ulAtrLength;
  1222. ULONG ulOldState;
  1223. NTSTATUS status;
  1224. SmartcardDebug(DEBUG_TRACE,
  1225. ("%s!DevicePowerCompletion: Enter\n",DRIVER_NAME));
  1226. // We have to remember the old card state because
  1227. // it is overwritten by SCCMN50M_InitializeCardMan
  1228. ulOldState=SmartcardExtension->ReaderExtension->ulOldCardState;
  1229. status = SCCMN50M_InitializeCardMan(SmartcardExtension);
  1230. // Set back the previous state
  1231. SmartcardExtension->ReaderExtension->ulOldCardState = ulOldState;
  1232. if (status != STATUS_SUCCESS)
  1233. {
  1234. SmartcardDebug(DEBUG_DRIVER,
  1235. ("%s!InitializeCardMan failed ! %lx\n",DRIVER_NAME,status));
  1236. }
  1237. //
  1238. // We issue a power request in because
  1239. // we powered down the card before
  1240. //
  1241. //SmartcardExtension->MinorIoControlCode = SCARD_COLD_RESET;
  1242. //status = SCCMN50M_PowerOn (SmartcardExtension,&ulAtrLength,pbAtrBuffer,sizeof(pbAtrBuffer));
  1243. //
  1244. // If a card was present before power down or now there is
  1245. // a card in the reader, we complete any pending card monitor
  1246. // request, since we do not really know what card is now in the
  1247. // reader.
  1248. //
  1249. if (SmartcardExtension->ReaderExtension->CardPresent ||
  1250. SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT)
  1251. {
  1252. deviceExtension->SmartcardExtension.ReaderExtension->ulOldCardState = UNKNOWN;
  1253. deviceExtension->SmartcardExtension.ReaderExtension->ulNewCardState = UNKNOWN;
  1254. }
  1255. status = SCCMN50M_StartCardTracking(deviceExtension);
  1256. if (status != STATUS_SUCCESS)
  1257. {
  1258. SmartcardDebug(DEBUG_ERROR,
  1259. ("%s!StartCardTracking failed ! %lx\n",DRIVER_NAME,status));
  1260. }
  1261. // save the current power state of the reader
  1262. SmartcardExtension->ReaderExtension->ReaderPowerState = PowerReaderWorking;
  1263. SmartcardReleaseRemoveLock(SmartcardExtension);
  1264. // inform the power manager of our state.
  1265. PoSetPowerState (DeviceObject,
  1266. DevicePowerState,
  1267. irpStack->Parameters.Power.State);
  1268. PoStartNextPowerIrp(Irp);
  1269. // signal that we can process ioctls again
  1270. deviceExtension->IoCount = 0;
  1271. KeSetEvent(&deviceExtension->ReaderStarted, 0, FALSE);
  1272. SmartcardDebug(DEBUG_DRIVER,
  1273. ("%s!Event ReaderStarted was set\n",DRIVER_NAME));
  1274. SmartcardDebug(DEBUG_TRACE,
  1275. ("%s!DevicePowerCompletion: Exit\n",DRIVER_NAME));
  1276. return STATUS_SUCCESS;
  1277. }
  1278. /*****************************************************************************
  1279. Routine Description:
  1280. The power dispatch routine.
  1281. This driver is the power policy owner of the device stack,
  1282. because this driver knows about the connected reader.
  1283. Therefor this driver will translate system power states
  1284. to device power states.
  1285. Arguments:
  1286. DeviceObject - pointer to a device object.
  1287. Irp - pointer to an I/O Request Packet.
  1288. Return Value:
  1289. NT status code
  1290. *****************************************************************************/
  1291. typedef enum _ACTION
  1292. {
  1293. Undefined = 0,
  1294. SkipRequest,
  1295. WaitForCompletion,
  1296. CompleteRequest,
  1297. MarkPending
  1298. } ACTION;
  1299. NTSTATUS
  1300. SCCMN50M_Power (
  1301. IN PDEVICE_OBJECT DeviceObject,
  1302. IN PIRP Irp
  1303. )
  1304. {
  1305. NTSTATUS status = STATUS_SUCCESS;
  1306. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1307. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1308. PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
  1309. PDEVICE_OBJECT AttachedDeviceObject;
  1310. POWER_STATE powerState;
  1311. ACTION action = SkipRequest;
  1312. KEVENT event;
  1313. PAGED_CODE();
  1314. SmartcardDebug(
  1315. DEBUG_TRACE,
  1316. ("%s!Power: Enter\n",
  1317. DRIVER_NAME)
  1318. );
  1319. status = SmartcardAcquireRemoveLock(smartcardExtension);
  1320. ASSERT(status == STATUS_SUCCESS);
  1321. if (!NT_SUCCESS(status))
  1322. {
  1323. PoStartNextPowerIrp(Irp);
  1324. Irp->IoStatus.Status = status;
  1325. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1326. return status;
  1327. }
  1328. AttachedDeviceObject = ATTACHED_DEVICE_OBJECT;
  1329. if (irpStack->Parameters.Power.Type == DevicePowerState &&
  1330. irpStack->MinorFunction == IRP_MN_SET_POWER)
  1331. {
  1332. switch (irpStack->Parameters.Power.State.DeviceState)
  1333. {
  1334. case PowerDeviceD0:
  1335. // Turn on the reader
  1336. SmartcardDebug(
  1337. DEBUG_DRIVER,
  1338. ("%s!Power: PowerDevice D0\n",
  1339. DRIVER_NAME)
  1340. );
  1341. //
  1342. // First, we send down the request to the bus, in order
  1343. // to power on the port. When the request completes,
  1344. // we turn on the reader
  1345. //
  1346. IoCopyCurrentIrpStackLocationToNext(Irp);
  1347. IoSetCompletionRoutine (
  1348. Irp,
  1349. SCCMN50M_DevicePowerCompletion,
  1350. smartcardExtension,
  1351. TRUE,
  1352. TRUE,
  1353. TRUE
  1354. );
  1355. action = WaitForCompletion;
  1356. break;
  1357. case PowerDeviceD3:
  1358. SCCMN50M_StopCardTracking(deviceExtension);
  1359. // Turn off the reader
  1360. SmartcardDebug(
  1361. DEBUG_DRIVER,
  1362. ("%s!Power: PowerDevice D3\n",
  1363. DRIVER_NAME)
  1364. );
  1365. PoSetPowerState (
  1366. DeviceObject,
  1367. DevicePowerState,
  1368. irpStack->Parameters.Power.State
  1369. );
  1370. // save the current card state
  1371. smartcardExtension->ReaderExtension->CardPresent = smartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT;
  1372. if (smartcardExtension->ReaderExtension->CardPresent)
  1373. {
  1374. smartcardExtension->MinorIoControlCode = SCARD_POWER_DOWN;
  1375. status = SCCMN50M_PowerOff(smartcardExtension);
  1376. ASSERT(status == STATUS_SUCCESS);
  1377. }
  1378. // save the current power state of the reader
  1379. smartcardExtension->ReaderExtension->ReaderPowerState = PowerReaderOff;
  1380. action = SkipRequest;
  1381. break;
  1382. default:
  1383. action = SkipRequest;
  1384. break;
  1385. }
  1386. }
  1387. if (irpStack->Parameters.Power.Type == SystemPowerState)
  1388. {
  1389. //
  1390. // The system wants to change the power state.
  1391. // We need to translate the system power state to
  1392. // a corresponding device power state.
  1393. //
  1394. POWER_STATE_TYPE powerType = DevicePowerState;
  1395. ASSERT(smartcardExtension->ReaderExtension->ReaderPowerState !=
  1396. PowerReaderUnspecified);
  1397. switch (irpStack->MinorFunction)
  1398. {
  1399. KIRQL irql;
  1400. case IRP_MN_QUERY_POWER:
  1401. SmartcardDebug(
  1402. DEBUG_DRIVER,
  1403. ("%s!Power: Query Power\n",
  1404. DRIVER_NAME)
  1405. );
  1406. switch (irpStack->Parameters.Power.State.SystemState)
  1407. {
  1408. case PowerSystemMaximum:
  1409. case PowerSystemWorking:
  1410. case PowerSystemSleeping1:
  1411. case PowerSystemSleeping2:
  1412. action = SkipRequest;
  1413. break;
  1414. case PowerSystemSleeping3:
  1415. case PowerSystemHibernate:
  1416. case PowerSystemShutdown:
  1417. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  1418. if (deviceExtension->IoCount == 0)
  1419. {
  1420. // Block any further ioctls
  1421. deviceExtension->IoCount = -1;
  1422. KeClearEvent(&deviceExtension->ReaderStarted);
  1423. SmartcardDebug(DEBUG_DRIVER,
  1424. ("%s!Event ReaderStarted was cleared\n",DRIVER_NAME));
  1425. action = SkipRequest;
  1426. }
  1427. else
  1428. {
  1429. // can't go to sleep mode since the reader is busy.
  1430. status = STATUS_DEVICE_BUSY;
  1431. action = CompleteRequest;
  1432. }
  1433. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  1434. break;
  1435. }
  1436. break;
  1437. case IRP_MN_SET_POWER:
  1438. SmartcardDebug(
  1439. DEBUG_DRIVER,
  1440. ("%s!Power: PowerSystem S%d\n",
  1441. DRIVER_NAME,
  1442. irpStack->Parameters.Power.State.SystemState - 1)
  1443. );
  1444. switch (irpStack->Parameters.Power.State.SystemState)
  1445. {
  1446. case PowerSystemMaximum:
  1447. case PowerSystemWorking:
  1448. case PowerSystemSleeping1:
  1449. case PowerSystemSleeping2:
  1450. if (smartcardExtension->ReaderExtension->ReaderPowerState ==
  1451. PowerReaderWorking)
  1452. {
  1453. // We're already in the right state
  1454. action = SkipRequest;
  1455. break;
  1456. }
  1457. // wake up the underlying stack...
  1458. powerState.DeviceState = PowerDeviceD0;
  1459. action = MarkPending;
  1460. break;
  1461. case PowerSystemSleeping3:
  1462. case PowerSystemHibernate:
  1463. case PowerSystemShutdown:
  1464. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  1465. if (deviceExtension->IoCount == 0)
  1466. {
  1467. // Block any further ioctls
  1468. deviceExtension->IoCount = -1;
  1469. KeClearEvent(&deviceExtension->ReaderStarted);
  1470. SmartcardDebug(DEBUG_DRIVER,
  1471. ("%s!Event ReaderStarted was cleared\n",DRIVER_NAME));
  1472. action = SkipRequest;
  1473. }
  1474. else
  1475. {
  1476. // can't go to sleep mode since the reader is busy.
  1477. status = STATUS_DEVICE_BUSY;
  1478. action = CompleteRequest;
  1479. }
  1480. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  1481. if (smartcardExtension->ReaderExtension->ReaderPowerState ==
  1482. PowerReaderOff)
  1483. {
  1484. // We're already in the right state
  1485. action = SkipRequest;
  1486. break;
  1487. }
  1488. powerState.DeviceState = PowerDeviceD3;
  1489. // first, inform the power manager of our new state.
  1490. PoSetPowerState (
  1491. DeviceObject,
  1492. SystemPowerState,
  1493. powerState
  1494. );
  1495. action = MarkPending;
  1496. break;
  1497. default:
  1498. action = SkipRequest;
  1499. break;
  1500. }
  1501. }
  1502. }
  1503. switch (action)
  1504. {
  1505. case CompleteRequest:
  1506. Irp->IoStatus.Status = status;
  1507. Irp->IoStatus.Information = 0;
  1508. SmartcardReleaseRemoveLock(smartcardExtension);
  1509. PoStartNextPowerIrp(Irp);
  1510. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1511. break;
  1512. case MarkPending:
  1513. // initialize the event we need in the completion function
  1514. KeInitializeEvent(&event,
  1515. NotificationEvent,
  1516. FALSE);
  1517. // request the device power irp
  1518. status = PoRequestPowerIrp (DeviceObject,
  1519. IRP_MN_SET_POWER,
  1520. powerState,
  1521. SCCMN50M_SystemPowerCompletion,
  1522. &event,
  1523. NULL);
  1524. ASSERT(status == STATUS_PENDING);
  1525. if (status == STATUS_PENDING)
  1526. {
  1527. // wait until the device power irp completed
  1528. status = KeWaitForSingleObject(&event,
  1529. Executive,
  1530. KernelMode,
  1531. FALSE,
  1532. NULL);
  1533. SmartcardReleaseRemoveLock(smartcardExtension);
  1534. if (powerState.SystemState == PowerSystemWorking)
  1535. {
  1536. PoSetPowerState (DeviceObject,
  1537. SystemPowerState,
  1538. powerState);
  1539. }
  1540. PoStartNextPowerIrp(Irp);
  1541. IoSkipCurrentIrpStackLocation(Irp);
  1542. status = PoCallDriver(AttachedDeviceObject, Irp);
  1543. }
  1544. else
  1545. {
  1546. SmartcardReleaseRemoveLock(smartcardExtension);
  1547. Irp->IoStatus.Status = status;
  1548. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1549. }
  1550. break;
  1551. case SkipRequest:
  1552. SmartcardReleaseRemoveLock(smartcardExtension);
  1553. PoStartNextPowerIrp(Irp);
  1554. IoSkipCurrentIrpStackLocation(Irp);
  1555. status = PoCallDriver(AttachedDeviceObject, Irp);
  1556. break;
  1557. case WaitForCompletion:
  1558. status = PoCallDriver(AttachedDeviceObject, Irp);
  1559. break;
  1560. default:
  1561. ASSERT(FALSE);
  1562. SmartcardReleaseRemoveLock(smartcardExtension);
  1563. break;
  1564. }
  1565. SmartcardDebug(
  1566. DEBUG_TRACE,
  1567. ("%s!Power: Exit %lx\n",
  1568. DRIVER_NAME,
  1569. status)
  1570. );
  1571. return status;
  1572. }
  1573. /*****************************************************************************
  1574. Routine Description:
  1575. This routine is called by the I/O system when the device is opened or closed.
  1576. Arguments:
  1577. DeviceObject - Pointer to device object for this miniport
  1578. Irp - IRP involved.
  1579. Return Value:
  1580. STATUS_SUCCESS.
  1581. *****************************************************************************/
  1582. NTSTATUS
  1583. SCCMN50M_CreateClose(
  1584. IN PDEVICE_OBJECT DeviceObject,
  1585. IN PIRP Irp
  1586. )
  1587. {
  1588. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1589. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1590. NTSTATUS status = STATUS_SUCCESS;
  1591. if (irpStack->MajorFunction == IRP_MJ_CREATE)
  1592. {
  1593. if (status != STATUS_SUCCESS)
  1594. {
  1595. status = STATUS_DEVICE_REMOVED;
  1596. }
  1597. else
  1598. {
  1599. LARGE_INTEGER timeout;
  1600. timeout.QuadPart = 0;
  1601. // test if the device has been opened already
  1602. status = KeWaitForSingleObject(
  1603. &deviceExtension->ReaderClosed,
  1604. Executive,
  1605. KernelMode,
  1606. FALSE,
  1607. &timeout
  1608. );
  1609. if (status == STATUS_SUCCESS)
  1610. {
  1611. status = SmartcardAcquireRemoveLock(
  1612. &deviceExtension->SmartcardExtension
  1613. );
  1614. KeClearEvent(&deviceExtension->ReaderClosed);
  1615. SmartcardDebug(
  1616. DEBUG_DRIVER,
  1617. ("%s!CreateClose: Open\n",
  1618. DRIVER_NAME)
  1619. );
  1620. }
  1621. else
  1622. {
  1623. // the device is already in use
  1624. status = STATUS_UNSUCCESSFUL;
  1625. }
  1626. }
  1627. }
  1628. else
  1629. {
  1630. SmartcardDebug(
  1631. DEBUG_DRIVER,
  1632. ("%s!CreateClose: Close\n",
  1633. DRIVER_NAME)
  1634. );
  1635. SmartcardReleaseRemoveLock(&deviceExtension->SmartcardExtension);
  1636. KeSetEvent(&deviceExtension->ReaderClosed, 0, FALSE);
  1637. }
  1638. Irp->IoStatus.Status = status;
  1639. Irp->IoStatus.Information = 0;
  1640. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1641. return status;
  1642. }
  1643. /*****************************************************************************
  1644. Routine Description:
  1645. This routine is called by the I/O system
  1646. when the irp should be cancelled
  1647. Arguments:
  1648. DeviceObject - Pointer to device object for this miniport
  1649. Irp - IRP involved.
  1650. Return Value:
  1651. STATUS_CANCELLED
  1652. *****************************************************************************/
  1653. NTSTATUS
  1654. SCCMN50M_Cancel(
  1655. IN PDEVICE_OBJECT DeviceObject,
  1656. IN PIRP Irp
  1657. )
  1658. {
  1659. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1660. PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
  1661. SmartcardDebug(
  1662. DEBUG_TRACE,
  1663. ("%s!Cancel: Enter\n",
  1664. DRIVER_NAME)
  1665. );
  1666. ASSERT(Irp == smartcardExtension->OsData->NotificationIrp);
  1667. IoReleaseCancelSpinLock(
  1668. Irp->CancelIrql
  1669. );
  1670. SCCMN50M_CompleteCardTracking(smartcardExtension);
  1671. SmartcardDebug(
  1672. DEBUG_TRACE,
  1673. ("%s!Cancel: Exit\n",
  1674. DRIVER_NAME)
  1675. );
  1676. return STATUS_CANCELLED;
  1677. }
  1678. /*****************************************************************************
  1679. Routine Description:
  1680. This routine is called when the calling application terminates.
  1681. We can actually only have the notification irp that we have to cancel.
  1682. Arguments:
  1683. Return Value:
  1684. *****************************************************************************/
  1685. NTSTATUS
  1686. SCCMN50M_Cleanup(
  1687. IN PDEVICE_OBJECT DeviceObject,
  1688. IN PIRP Irp
  1689. )
  1690. {
  1691. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1692. PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
  1693. NTSTATUS status = STATUS_SUCCESS;
  1694. BOOLEAN fCancelIrp = FALSE;
  1695. SmartcardDebug(
  1696. DEBUG_TRACE,
  1697. ("%s!Cleanup: Enter\n",
  1698. DRIVER_NAME)
  1699. );
  1700. if (Irp != smartcardExtension->OsData->NotificationIrp)
  1701. fCancelIrp = TRUE;
  1702. // We need to complete the notification irp
  1703. SCCMN50M_CompleteCardTracking(smartcardExtension);
  1704. if (fCancelIrp == TRUE)
  1705. {
  1706. SmartcardDebug(
  1707. DEBUG_DRIVER,
  1708. ("%s!Cleanup: Completing IRP %lx\n",
  1709. DRIVER_NAME,
  1710. Irp)
  1711. );
  1712. Irp->IoStatus.Information = 0;
  1713. Irp->IoStatus.Status = STATUS_SUCCESS;
  1714. IoCompleteRequest(
  1715. Irp,
  1716. IO_NO_INCREMENT
  1717. );
  1718. }
  1719. SmartcardDebug(
  1720. DEBUG_TRACE,
  1721. ("%s!Cleanup: Exit\n",
  1722. DRIVER_NAME)
  1723. );
  1724. return STATUS_SUCCESS;
  1725. }
  1726. /*****************************************************************************
  1727. Routine Description:
  1728. Remove the device from the system.
  1729. Arguments:
  1730. Return Value:
  1731. *****************************************************************************/
  1732. VOID
  1733. SCCMN50M_RemoveDevice(
  1734. PDEVICE_OBJECT DeviceObject
  1735. )
  1736. {
  1737. PDEVICE_EXTENSION deviceExtension;
  1738. PSMARTCARD_EXTENSION smartcardExtension;
  1739. NTSTATUS status;
  1740. PAGED_CODE();
  1741. if (DeviceObject == NULL)
  1742. {
  1743. return;
  1744. }
  1745. deviceExtension = DeviceObject->DeviceExtension;
  1746. smartcardExtension = &deviceExtension->SmartcardExtension;
  1747. SmartcardDebug(
  1748. DEBUG_TRACE,
  1749. ( "%s!RemoveDevice: Enter\n",
  1750. DRIVER_NAME)
  1751. );
  1752. if (smartcardExtension->OsData)
  1753. {
  1754. // complete pending card tracking requests (if any)
  1755. SCCMN50M_CompleteCardTracking(smartcardExtension);
  1756. ASSERT(smartcardExtension->OsData->NotificationIrp == NULL);
  1757. }
  1758. // Wait until we can safely unload the device
  1759. SmartcardReleaseRemoveLockAndWait(smartcardExtension);
  1760. ASSERT(deviceExtension->DeviceInstance < MAXIMUM_SMARTCARD_READERS);
  1761. ASSERT(DeviceSlot[deviceExtension->DeviceInstance] == TRUE);
  1762. // Mark this slot as available
  1763. DeviceSlot[deviceExtension->DeviceInstance] = FALSE;
  1764. SCCMN50M_StopDevice(deviceExtension);
  1765. if (ATTACHED_DEVICE_OBJECT)
  1766. {
  1767. IoDetachDevice(ATTACHED_DEVICE_OBJECT);
  1768. }
  1769. if (deviceExtension->PnPDeviceName.Buffer != NULL)
  1770. {
  1771. RtlFreeUnicodeString(&deviceExtension->PnPDeviceName);
  1772. }
  1773. if (smartcardExtension->OsData != NULL)
  1774. {
  1775. SmartcardExit(smartcardExtension);
  1776. }
  1777. if (smartcardExtension->ReaderExtension != NULL)
  1778. {
  1779. ExFreePool(smartcardExtension->ReaderExtension);
  1780. }
  1781. IoDeleteDevice(DeviceObject);
  1782. SmartcardDebug(
  1783. DEBUG_TRACE,
  1784. ( "%s!RemoveDevice: Exit\n",
  1785. DRIVER_NAME)
  1786. );
  1787. }
  1788. /*****************************************************************************
  1789. Routine Description:
  1790. The driver unload routine. This is called by the I/O system
  1791. when the device is unloaded from memory.
  1792. Arguments:
  1793. DriverObject - Pointer to driver object created by system.
  1794. Return Value:
  1795. STATUS_SUCCESS.
  1796. *****************************************************************************/
  1797. VOID
  1798. SCCMN50M_DriverUnload(
  1799. IN PDRIVER_OBJECT DriverObject
  1800. )
  1801. {
  1802. PAGED_CODE();
  1803. SmartcardDebug(
  1804. DEBUG_TRACE,
  1805. ("%s!DriverUnload\n",
  1806. DRIVER_NAME)
  1807. );
  1808. }
  1809. /*****************************************************************************
  1810. Routine Description:
  1811. Arguments:
  1812. Return Value:
  1813. *****************************************************************************/
  1814. VOID
  1815. SCCMN50M_CompleteCardTracking(
  1816. IN PSMARTCARD_EXTENSION SmartcardExtension
  1817. )
  1818. {
  1819. KIRQL ioIrql, keIrql;
  1820. PIRP notificationIrp;
  1821. IoAcquireCancelSpinLock(&ioIrql);
  1822. KeAcquireSpinLock(
  1823. &SmartcardExtension->OsData->SpinLock,
  1824. &keIrql
  1825. );
  1826. notificationIrp = SmartcardExtension->OsData->NotificationIrp;
  1827. SmartcardExtension->OsData->NotificationIrp = NULL;
  1828. KeReleaseSpinLock(
  1829. &SmartcardExtension->OsData->SpinLock,
  1830. keIrql
  1831. );
  1832. if (notificationIrp)
  1833. {
  1834. IoSetCancelRoutine(
  1835. notificationIrp,
  1836. NULL
  1837. );
  1838. }
  1839. IoReleaseCancelSpinLock(ioIrql);
  1840. if (notificationIrp)
  1841. {
  1842. // finish the request
  1843. if (notificationIrp->Cancel)
  1844. {
  1845. notificationIrp->IoStatus.Status = STATUS_CANCELLED;
  1846. }
  1847. else
  1848. {
  1849. notificationIrp->IoStatus.Status = STATUS_SUCCESS;
  1850. }
  1851. SmartcardDebug(
  1852. DEBUG_DRIVER,
  1853. ("%s!CompleteCardTracking: Completing NotificationIrp %lxh IoStatus=%lxh\n",
  1854. DRIVER_NAME,
  1855. notificationIrp,
  1856. notificationIrp->IoStatus.Status
  1857. )
  1858. );
  1859. notificationIrp->IoStatus.Information = 0;
  1860. IoCompleteRequest(
  1861. notificationIrp,
  1862. IO_NO_INCREMENT
  1863. );
  1864. }
  1865. }
  1866. /*****************************************************************************
  1867. * History:
  1868. * $Log: sccmnt5.c $
  1869. * Revision 1.7 2001/01/22 08:39:42 WFrischauf
  1870. * No comment given
  1871. *
  1872. * Revision 1.6 2000/09/25 10:46:24 WFrischauf
  1873. * No comment given
  1874. *
  1875. * Revision 1.5 2000/08/24 09:05:45 TBruendl
  1876. * No comment given
  1877. *
  1878. * Revision 1.4 2000/08/14 12:41:06 TBruendl
  1879. * bug fix in CreateDevice
  1880. *
  1881. * Revision 1.3 2000/07/28 09:24:15 TBruendl
  1882. * Changes for OMNIKEY on Whistler CD
  1883. *
  1884. * Revision 1.6 2000/03/03 09:50:51 TBruendl
  1885. * No comment given
  1886. *
  1887. * Revision 1.5 2000/03/01 09:32:07 TBruendl
  1888. * R02.20.0
  1889. *
  1890. * Revision 1.4 1999/12/13 07:57:18 TBruendl
  1891. * bug fixes for hiberantion tests of MS test suite
  1892. *
  1893. * Revision 1.3 1999/11/04 07:53:24 WFrischauf
  1894. * bug fixes due to error reports 2 - 7
  1895. *
  1896. * Revision 1.2 1999/06/10 09:03:59 TBruendl
  1897. * No comment given
  1898. *
  1899. * Revision 1.1 1999/02/02 13:34:41 TBruendl
  1900. * This is the first release (R01.00) of the IFD handler for CardMan running under NT5.0.
  1901. *
  1902. *
  1903. *****************************************************************************/