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.

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