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.

1668 lines
54 KiB

  1. /*****************************************************************************
  2. @doc INT EXT
  3. ******************************************************************************
  4. * $ProjectName: $
  5. * $ProjectRevision: $
  6. *-----------------------------------------------------------------------------
  7. * $Source: z:/pr/cmbp0/sw/cmbp0.ms/rcs/cmbp0wdm.c $
  8. * $Revision: 1.11 $
  9. *-----------------------------------------------------------------------------
  10. * $Author: WFrischauf $
  11. *-----------------------------------------------------------------------------
  12. * History: see EOF
  13. *-----------------------------------------------------------------------------
  14. *
  15. * Copyright 2000 OMNIKEY AG
  16. ******************************************************************************/
  17. #include <cmbp0wdm.h>
  18. #ifdef NT4
  19. #include <cmbp0nt4.h>
  20. #else
  21. #include <cmbp0pnp.h>
  22. #endif
  23. #include <cmbp0scr.h>
  24. #include <cmbp0log.h>
  25. BOOLEAN DeviceSlot[CMMOB_MAX_DEVICE];
  26. // this is a list of our supported data rates
  27. ULONG SupportedDataRates[] = { 9600, 19200, 38400, 76800, 115200,
  28. 153600, 192000, 307200};
  29. // this is a list of our supported clock frequencies
  30. ULONG SupportedCLKFrequencies[] = { 4000, 8000};
  31. /*****************************************************************************
  32. DriverEntry:
  33. entry function of the driver. setup the callbacks for the OS and try to
  34. initialize a device object for every device in the system
  35. Arguments:
  36. DriverObject context of the driver
  37. RegistryPath path to the registry entry for the driver
  38. Return Value:
  39. STATUS_SUCCESS
  40. STATUS_UNSUCCESSFUL
  41. ******************************************************************************/
  42. NTSTATUS DriverEntry(
  43. PDRIVER_OBJECT DriverObject,
  44. PUNICODE_STRING RegistryPath
  45. )
  46. {
  47. NTSTATUS NTStatus = STATUS_SUCCESS;
  48. ULONG ulDevice;
  49. //#if DBG
  50. // SmartcardSetDebugLevel(DEBUG_ALL);
  51. //#endif
  52. SmartcardDebug(DEBUG_TRACE,
  53. ("%s!DriverEntry: Enter - %s %s\n",DRIVER_NAME,__DATE__,__TIME__));
  54. //
  55. // tell the system our entry points
  56. //
  57. DriverObject->MajorFunction[IRP_MJ_CREATE] = CMMOB_CreateClose;
  58. DriverObject->MajorFunction[IRP_MJ_CLOSE] = CMMOB_CreateClose;
  59. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CMMOB_DeviceIoControl;
  60. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = CMMOB_SystemControl;
  61. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = CMMOB_Cleanup;
  62. DriverObject->DriverUnload = CMMOB_UnloadDriver;
  63. #ifndef NT4
  64. DriverObject->MajorFunction[IRP_MJ_PNP] = CMMOB_PnPDeviceControl;
  65. DriverObject->MajorFunction[IRP_MJ_POWER] = CMMOB_PowerDeviceControl;
  66. DriverObject->DriverExtension->AddDevice = CMMOB_AddDevice;
  67. SmartcardDebug(DEBUG_TRACE,
  68. ("%s!DriverEntry: PnP Version\n",DRIVER_NAME));
  69. #else
  70. //
  71. // try to initialize all devices
  72. //
  73. for (ulDevice = 0; ulDevice < CMMOB_MAX_DEVICE; ulDevice++)
  74. {
  75. //
  76. // create and start all connected devices
  77. //
  78. if (CMMOB_CreateAndStartDevice(DriverObject) != STATUS_SUCCESS)
  79. {
  80. break;
  81. }
  82. }
  83. //
  84. // report a failure if no device was found
  85. //
  86. if (DriverObject->DeviceObject == NULL)
  87. {
  88. NTStatus = STATUS_UNSUCCESSFUL;
  89. SmartcardLogError(DriverObject,
  90. CMMOB_NO_DEVICE_FOUND,
  91. NULL,
  92. 0);
  93. }
  94. #endif
  95. SmartcardDebug(DEBUG_TRACE,
  96. ("%s!DriverEntry: Exit %x\n",DRIVER_NAME,NTStatus));
  97. return NTStatus;
  98. }
  99. /*****************************************************************************
  100. Routine Description:
  101. Trys to read the reader name from the registry
  102. Arguments:
  103. DriverObject context of call
  104. SmartcardExtension ptr to smartcard extension
  105. Return Value:
  106. none
  107. ******************************************************************************/
  108. VOID CMMOB_SetVendorAndIfdName(
  109. IN PDEVICE_OBJECT PhysicalDeviceObject,
  110. IN PSMARTCARD_EXTENSION SmartcardExtension
  111. )
  112. {
  113. RTL_QUERY_REGISTRY_TABLE parameters[3];
  114. UNICODE_STRING vendorNameU;
  115. ANSI_STRING vendorNameA;
  116. UNICODE_STRING ifdTypeU;
  117. ANSI_STRING ifdTypeA;
  118. HANDLE regKey = NULL;
  119. RtlZeroMemory (parameters, sizeof(parameters));
  120. RtlZeroMemory (&vendorNameU, sizeof(vendorNameU));
  121. RtlZeroMemory (&vendorNameA, sizeof(vendorNameA));
  122. RtlZeroMemory (&ifdTypeU, sizeof(ifdTypeU));
  123. RtlZeroMemory (&ifdTypeA, sizeof(ifdTypeA));
  124. try
  125. {
  126. //
  127. // try to read the reader name from the registry
  128. // if that does not work, we will use the default
  129. // (hardcoded) name
  130. //
  131. if (IoOpenDeviceRegistryKey(PhysicalDeviceObject,
  132. PLUGPLAY_REGKEY_DEVICE,
  133. KEY_READ,
  134. &regKey) != STATUS_SUCCESS)
  135. {
  136. SmartcardDebug(DEBUG_ERROR,
  137. ("%s!SetVendorAndIfdName: IoOpenDeviceRegistryKey failed\n",DRIVER_NAME));
  138. leave;
  139. }
  140. parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  141. parameters[0].Name = L"VendorName";
  142. parameters[0].EntryContext = &vendorNameU;
  143. parameters[0].DefaultType = REG_SZ;
  144. parameters[0].DefaultData = &vendorNameU;
  145. parameters[0].DefaultLength = 0;
  146. parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
  147. parameters[1].Name = L"IfdType";
  148. parameters[1].EntryContext = &ifdTypeU;
  149. parameters[1].DefaultType = REG_SZ;
  150. parameters[1].DefaultData = &ifdTypeU;
  151. parameters[1].DefaultLength = 0;
  152. if (RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  153. (PWSTR) regKey,
  154. parameters,
  155. NULL,
  156. NULL) != STATUS_SUCCESS)
  157. {
  158. SmartcardDebug(DEBUG_ERROR,
  159. ("%s!SetVendorAndIfdName: RtlQueryRegistryValues failed\n",DRIVER_NAME));
  160. leave;
  161. }
  162. if (RtlUnicodeStringToAnsiString(&vendorNameA,&vendorNameU,TRUE) != STATUS_SUCCESS)
  163. {
  164. SmartcardDebug(DEBUG_ERROR,
  165. ("%s!SetVendorAndIfdName: RtlUnicodeStringToAnsiString failed\n",DRIVER_NAME));
  166. leave;
  167. }
  168. if (RtlUnicodeStringToAnsiString(&ifdTypeA,&ifdTypeU,TRUE) != STATUS_SUCCESS)
  169. {
  170. SmartcardDebug(DEBUG_ERROR,
  171. ("%s!SetVendorAndIfdName: RtlUnicodeStringToAnsiString failed\n",DRIVER_NAME));
  172. leave;
  173. }
  174. if (vendorNameA.Length == 0 ||
  175. vendorNameA.Length > MAXIMUM_ATTR_STRING_LENGTH ||
  176. ifdTypeA.Length == 0 ||
  177. ifdTypeA.Length > MAXIMUM_ATTR_STRING_LENGTH)
  178. {
  179. SmartcardDebug(DEBUG_ERROR,
  180. ("%s!SetVendorAndIfdName: vendor name or ifdtype not found or to long\n",DRIVER_NAME));
  181. leave;
  182. }
  183. RtlCopyMemory(SmartcardExtension->VendorAttr.VendorName.Buffer,
  184. vendorNameA.Buffer,
  185. vendorNameA.Length);
  186. SmartcardExtension->VendorAttr.VendorName.Length = vendorNameA.Length;
  187. RtlCopyMemory(SmartcardExtension->VendorAttr.IfdType.Buffer,
  188. ifdTypeA.Buffer,
  189. ifdTypeA.Length);
  190. SmartcardExtension->VendorAttr.IfdType.Length = ifdTypeA.Length;
  191. SmartcardDebug(DEBUG_DRIVER,
  192. ("%s!SetVendorAndIfdName: overwritting vendor name and ifdtype\n",DRIVER_NAME));
  193. }
  194. finally
  195. {
  196. if (vendorNameU.Buffer != NULL)
  197. {
  198. RtlFreeUnicodeString(&vendorNameU);
  199. }
  200. if (vendorNameA.Buffer != NULL)
  201. {
  202. RtlFreeAnsiString(&vendorNameA);
  203. }
  204. if (ifdTypeU.Buffer != NULL)
  205. {
  206. RtlFreeUnicodeString(&ifdTypeU);
  207. }
  208. if (ifdTypeA.Buffer != NULL)
  209. {
  210. RtlFreeAnsiString(&ifdTypeA);
  211. }
  212. if (regKey != NULL)
  213. {
  214. ZwClose (regKey);
  215. }
  216. }
  217. }
  218. /*****************************************************************************
  219. Routine Description:
  220. creates a new device object for the driver, allocates & initializes all
  221. neccessary structures (i.e. SmartcardExtension & ReaderExtension).
  222. Arguments:
  223. DriverObject context of call
  224. DeviceObject ptr to the created device object
  225. Return Value:
  226. STATUS_SUCCESS
  227. STATUS_INSUFFICIENT_RESOURCES
  228. NTStatus returned by smclib.sys
  229. ******************************************************************************/
  230. NTSTATUS CMMOB_CreateDevice(
  231. IN PDRIVER_OBJECT DriverObject,
  232. IN PDEVICE_OBJECT PhysicalDeviceObject,
  233. OUT PDEVICE_OBJECT *DeviceObject
  234. )
  235. {
  236. NTSTATUS NTStatus = STATUS_SUCCESS;
  237. NTSTATUS RegStatus;
  238. RTL_QUERY_REGISTRY_TABLE ParamTable[2];
  239. UNICODE_STRING RegistryPath;
  240. UNICODE_STRING RegistryValue;
  241. WCHAR szRegValue[256];
  242. UNICODE_STRING DeviceName;
  243. UNICODE_STRING Tmp;
  244. WCHAR Buffer[64];
  245. SmartcardDebug(DEBUG_TRACE,
  246. ( "%s!CreateDevice: Enter\n",DRIVER_NAME ));
  247. try
  248. {
  249. ULONG ulDeviceInstance;
  250. PDEVICE_EXTENSION DeviceExtension;
  251. PREADER_EXTENSION ReaderExtension;
  252. PSMARTCARD_EXTENSION SmartcardExtension;
  253. *DeviceObject = NULL;
  254. for (ulDeviceInstance = 0; ulDeviceInstance < CMMOB_MAX_DEVICE; ulDeviceInstance++)
  255. {
  256. if (DeviceSlot[ulDeviceInstance] == FALSE)
  257. {
  258. DeviceSlot[ulDeviceInstance] = TRUE;
  259. break;
  260. }
  261. }
  262. if (ulDeviceInstance == CMMOB_MAX_DEVICE)
  263. {
  264. NTStatus = STATUS_INSUFFICIENT_RESOURCES;
  265. leave;
  266. }
  267. //
  268. // construct the device name
  269. //
  270. DeviceName.Buffer = Buffer;
  271. DeviceName.MaximumLength = sizeof(Buffer);
  272. DeviceName.Length = 0;
  273. RtlInitUnicodeString(&Tmp,CARDMAN_MOBILE_DEVICE_NAME);
  274. RtlCopyUnicodeString(&DeviceName,&Tmp);
  275. DeviceName.Buffer[(DeviceName.Length)/sizeof(WCHAR)-1] = L'0' + (WCHAR)ulDeviceInstance;
  276. //
  277. // Create the device object
  278. //
  279. NTStatus = IoCreateDevice(DriverObject,
  280. sizeof(DEVICE_EXTENSION),
  281. &DeviceName,
  282. FILE_DEVICE_SMARTCARD,
  283. 0,
  284. TRUE,
  285. DeviceObject);
  286. if (NTStatus != STATUS_SUCCESS)
  287. {
  288. SmartcardLogError(DriverObject,
  289. CMMOB_INSUFFICIENT_RESOURCES,
  290. NULL,
  291. 0);
  292. leave;
  293. }
  294. //
  295. // tell the OS that we supposed to do buffered io
  296. //
  297. (*DeviceObject)->Flags |= DO_BUFFERED_IO;
  298. #ifndef NT4
  299. // this is necessary, that power routine is called at IRQL_PASSIVE
  300. (*DeviceObject)->Flags |= DO_POWER_PAGABLE;
  301. // tells the IO Manager initialization is done
  302. (*DeviceObject)->Flags &= ~DO_DEVICE_INITIALIZING;
  303. #endif
  304. //
  305. // set up the device extension.
  306. //
  307. DeviceExtension = (*DeviceObject)->DeviceExtension;
  308. RtlZeroMemory( DeviceExtension, sizeof( DEVICE_EXTENSION ));
  309. SmartcardExtension = &DeviceExtension->SmartcardExtension;
  310. // used for synchronise access to lIoCount
  311. KeInitializeSpinLock(&DeviceExtension->SpinLockIoCount);
  312. // Used for stop / start notification
  313. KeInitializeEvent(&DeviceExtension->ReaderStarted,
  314. NotificationEvent,
  315. FALSE);
  316. // Used for update thread notification after hibernation
  317. KeInitializeEvent(&DeviceExtension->CanRunUpdateThread,
  318. NotificationEvent,
  319. TRUE);
  320. //
  321. // allocate the reader extension
  322. //
  323. ReaderExtension = ExAllocatePool(NonPagedPool,sizeof( READER_EXTENSION ));
  324. if (ReaderExtension == NULL)
  325. {
  326. SmartcardLogError(DriverObject,
  327. CMMOB_INSUFFICIENT_RESOURCES,
  328. NULL,
  329. 0);
  330. NTStatus = STATUS_INSUFFICIENT_RESOURCES;
  331. leave;
  332. }
  333. RtlZeroMemory( ReaderExtension, sizeof( READER_EXTENSION ));
  334. SmartcardExtension->ReaderExtension = ReaderExtension;
  335. // ----------------------------------------------
  336. // initialize mutex
  337. // ----------------------------------------------
  338. KeInitializeMutex(&SmartcardExtension->ReaderExtension->CardManIOMutex,0L);
  339. //
  340. // enter correct version of the lib
  341. //
  342. SmartcardExtension->Version = SMCLIB_VERSION;
  343. //
  344. // setup smartcard extension - callback's
  345. //
  346. SmartcardExtension->ReaderFunction[RDF_CARD_POWER] = CMMOB_CardPower;
  347. SmartcardExtension->ReaderFunction[RDF_TRANSMIT] = CMMOB_Transmit;
  348. SmartcardExtension->ReaderFunction[RDF_SET_PROTOCOL] = CMMOB_SetProtocol;
  349. SmartcardExtension->ReaderFunction[RDF_CARD_TRACKING] = CMMOB_CardTracking;
  350. SmartcardExtension->ReaderFunction[RDF_IOCTL_VENDOR] = CMMOB_IoCtlVendor;
  351. //
  352. // setup smartcard extension - vendor attribute
  353. //
  354. // default values
  355. RtlCopyMemory(SmartcardExtension->VendorAttr.VendorName.Buffer,
  356. CMMOB_VENDOR_NAME,sizeof(CMMOB_VENDOR_NAME));
  357. SmartcardExtension->VendorAttr.VendorName.Length = sizeof(CMMOB_VENDOR_NAME);
  358. RtlCopyMemory(SmartcardExtension->VendorAttr.IfdType.Buffer,
  359. CMMOB_PRODUCT_NAME,sizeof(CMMOB_PRODUCT_NAME));
  360. SmartcardExtension->VendorAttr.IfdType.Length = sizeof(CMMOB_PRODUCT_NAME);
  361. // try to overwrite with registry values
  362. CMMOB_SetVendorAndIfdName(PhysicalDeviceObject, SmartcardExtension);
  363. SmartcardExtension->VendorAttr.UnitNo = ulDeviceInstance;
  364. SmartcardExtension->VendorAttr.IfdVersion.VersionMajor = CMMOB_MAJOR_VERSION;
  365. SmartcardExtension->VendorAttr.IfdVersion.VersionMinor = CMMOB_MINOR_VERSION;
  366. SmartcardExtension->VendorAttr.IfdVersion.BuildNumber = CMMOB_BUILD_NUMBER;
  367. SmartcardExtension->VendorAttr.IfdSerialNo.Length = 0;
  368. //
  369. // setup smartcard extension - reader capabilities
  370. //
  371. SmartcardExtension->ReaderCapabilities.SupportedProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
  372. SmartcardExtension->ReaderCapabilities.ReaderType = SCARD_READER_TYPE_PCMCIA;
  373. SmartcardExtension->ReaderCapabilities.MechProperties = 0;
  374. SmartcardExtension->ReaderCapabilities.Channel = 0;
  375. // set supported frequencies
  376. SmartcardExtension->ReaderCapabilities.CLKFrequency.Default = 4000; //not used if CLKFrequenciesSupported is supplied
  377. SmartcardExtension->ReaderCapabilities.CLKFrequency.Max = 8000; //not used if CLKFrequenciesSupported is supplied
  378. SmartcardExtension->ReaderCapabilities.CLKFrequenciesSupported.Entries =
  379. sizeof(SupportedCLKFrequencies) / sizeof(SupportedCLKFrequencies[0]);
  380. SmartcardExtension->ReaderCapabilities.CLKFrequenciesSupported.List =
  381. SupportedCLKFrequencies;
  382. // set supported baud rates
  383. SmartcardExtension->ReaderCapabilities.DataRate.Default = 9600; //not used if DataRatesSupported is supplied
  384. SmartcardExtension->ReaderCapabilities.DataRate.Max = 307200; //not used if DataRatesSupported is supplied
  385. SmartcardExtension->ReaderCapabilities.DataRatesSupported.Entries =
  386. sizeof(SupportedDataRates) / sizeof(SupportedDataRates[0]);
  387. SmartcardExtension->ReaderCapabilities.DataRatesSupported.List =
  388. SupportedDataRates;
  389. // maximum buffer size
  390. SmartcardExtension->ReaderCapabilities.MaxIFSD = 254;
  391. //
  392. // Current state of the reader
  393. //
  394. SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_UNKNOWN;
  395. SmartcardExtension->ReaderExtension->ulOldCardState = UNKNOWN;
  396. SmartcardExtension->ReaderExtension->ulNewCardState = UNKNOWN;
  397. SmartcardExtension->ReaderExtension->ulFWVersion = 100;
  398. //
  399. // Initialization of buffers
  400. //
  401. SmartcardExtension->SmartcardRequest.BufferSize = MIN_BUFFER_SIZE;
  402. SmartcardExtension->SmartcardReply.BufferSize = MIN_BUFFER_SIZE;
  403. NTStatus = SmartcardInitialize(SmartcardExtension);
  404. SmartcardExtension->ReaderExtension->ReaderPowerState = PowerReaderWorking;
  405. SmartcardExtension->ReaderExtension->CardParameters.bStopBits=2;
  406. SmartcardExtension->ReaderExtension->CardParameters.fSynchronousCard=FALSE;
  407. SmartcardExtension->ReaderExtension->CardParameters.fInversRevers=FALSE;
  408. SmartcardExtension->ReaderExtension->CardParameters.bClockFrequency=4;
  409. SmartcardExtension->ReaderExtension->CardParameters.fT0Mode=FALSE;
  410. SmartcardExtension->ReaderExtension->CardParameters.fT0Write=FALSE;
  411. SmartcardExtension->ReaderExtension->fReadCIS = FALSE;
  412. SmartcardExtension->ReaderExtension->bPreviousFlags1 = 0;
  413. if (NTStatus != STATUS_SUCCESS)
  414. {
  415. SmartcardLogError(DriverObject,
  416. CMMOB_INSUFFICIENT_RESOURCES,
  417. NULL,
  418. 0);
  419. leave;
  420. }
  421. //
  422. // tell the lib our device object & create symbolic link
  423. //
  424. SmartcardExtension->OsData->DeviceObject = *DeviceObject;
  425. #ifndef NT4
  426. // W2000 is till now the only OS which supports WDM version 1.10
  427. // So check this to determine if we have an Plug&Play able resource manager
  428. // Otherwise it is Windows 98 / ME
  429. if (IoIsWdmVersionAvailable (1,10))
  430. {
  431. DeviceExtension->OSVersion = OS_Windows2000;
  432. }
  433. else
  434. {
  435. // Read HKLM\Software\Microsoft\Windows\CurrentVersion\VersionNumber
  436. // to determine the version of Windows (95, 98, 98SE and ME)
  437. RegistryValue.Length=0;
  438. RegistryValue.MaximumLength=sizeof(szRegValue);
  439. RegistryValue.Buffer=szRegValue;
  440. RtlZeroMemory(ParamTable,sizeof(ParamTable));
  441. ParamTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  442. ParamTable[0].Name = L"VersionNumber";
  443. ParamTable[0].EntryContext = &RegistryValue;
  444. ParamTable[0].DefaultType = REG_SZ;
  445. ParamTable[0].DefaultData = &RegistryValue;
  446. ParamTable[0].DefaultLength = RegistryValue.MaximumLength;
  447. RtlInitUnicodeString(&RegistryPath,
  448. L"\\Registry\\Machine\\Software\\Microsoft\\Windows\\CurrentVersion");
  449. RegStatus = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
  450. RegistryPath.Buffer,
  451. ParamTable,
  452. NULL,
  453. NULL);
  454. if (RegStatus == STATUS_SUCCESS)
  455. {
  456. ULONG ulMajorVersion;
  457. ULONG ulMinorVersion;
  458. ULONG ulBuild;
  459. ULONG ulStrLength;
  460. ULONG ulStrPos;
  461. ULONG ulStrPosPrevious;
  462. ulStrLength=RegistryValue.Length;
  463. ulStrPos=0;
  464. ulStrPosPrevious=ulStrPos;
  465. while (szRegValue[ulStrPos] != L'.' &&
  466. szRegValue[ulStrPos] != L'\0' &&
  467. ulStrPos != ulStrLength/sizeof(WCHAR))
  468. {
  469. ulStrPos ++;
  470. }
  471. szRegValue[ulStrPos] = L'\0';
  472. RegistryValue.Length= (USHORT) ((ulStrPos-ulStrPosPrevious)*sizeof(WCHAR));
  473. RtlUnicodeStringToInteger(&RegistryValue,10,&ulMajorVersion);
  474. ulStrPos++;
  475. if (ulStrPos < ulStrLength/sizeof(WCHAR))
  476. {
  477. ulStrPosPrevious=ulStrPos;
  478. while (szRegValue[ulStrPos] != L'.' &&
  479. szRegValue[ulStrPos] != L'\0' &&
  480. ulStrPos != ulStrLength)
  481. {
  482. ulStrPos ++;
  483. }
  484. szRegValue[ulStrPos] = L'\0';
  485. RegistryValue.Length= (USHORT) ((ulStrPos-ulStrPosPrevious)*sizeof(WCHAR));
  486. RegistryValue.Buffer=&szRegValue[ulStrPosPrevious];
  487. RtlUnicodeStringToInteger(&RegistryValue,10,&ulMinorVersion);
  488. ulStrPos++;
  489. if (ulStrPos < ulStrLength/sizeof(WCHAR))
  490. {
  491. ulStrPosPrevious=ulStrPos;
  492. while (szRegValue[ulStrPos] != L'.' &&
  493. szRegValue[ulStrPos] != L'\0' &&
  494. ulStrPos != ulStrLength)
  495. {
  496. ulStrPos ++;
  497. }
  498. szRegValue[ulStrPos] = L'\0';
  499. RegistryValue.Length= (USHORT) ((ulStrPos-ulStrPosPrevious)*sizeof(WCHAR));
  500. RegistryValue.Buffer=&szRegValue[ulStrPosPrevious];
  501. RtlUnicodeStringToInteger(&RegistryValue,10,&ulBuild);
  502. }
  503. }
  504. SmartcardDebug(DEBUG_DRIVER,
  505. ("%s!CreateDevice: MS Windows Version %li.%li.%li\n",DRIVER_NAME,
  506. ulMajorVersion,ulMinorVersion,ulBuild));
  507. if (ulMajorVersion > 4 ||
  508. (ulMajorVersion == 4 &&
  509. ulMinorVersion > 10 ))
  510. {
  511. DeviceExtension->OSVersion = OS_WindowsME;
  512. }
  513. else if (ulMajorVersion == 4 &&
  514. ulMinorVersion == 10 )
  515. {
  516. if (ulBuild < 2222)
  517. {
  518. DeviceExtension->OSVersion = OS_Windows98;
  519. }
  520. else
  521. {
  522. DeviceExtension->OSVersion = OS_Windows98SE;
  523. }
  524. }
  525. else
  526. {
  527. DeviceExtension->OSVersion = OS_Windows95;
  528. }
  529. }
  530. else
  531. {
  532. // assume it's Windows 98 -> no standby mode
  533. DeviceExtension->OSVersion = OS_Windows98;
  534. }
  535. }
  536. SmartcardDebug(DEBUG_DRIVER,
  537. ("%s!CreateDevice: Operating system is %s\n",DRIVER_NAME,
  538. szOSVersion[DeviceExtension->OSVersion]));
  539. if (DeviceExtension->OSVersion == OS_Windows2000)
  540. {
  541. if (DeviceExtension->PnPDeviceName.Buffer == NULL)
  542. {
  543. // ----------------------------------------------
  544. // register our new device
  545. // ----------------------------------------------
  546. NTStatus = IoRegisterDeviceInterface(PhysicalDeviceObject,
  547. &SmartCardReaderGuid,
  548. NULL,
  549. &DeviceExtension->PnPDeviceName);
  550. SmartcardDebug(DEBUG_DRIVER,
  551. ("%s!CreateDevice: PnPDeviceName.Buffer = %lx\n",DRIVER_NAME,
  552. DeviceExtension->PnPDeviceName.Buffer));
  553. SmartcardDebug(DEBUG_DRIVER,
  554. ("%s!CreateDevice: PnPDeviceName.BufferLength = %lx\n",DRIVER_NAME,
  555. DeviceExtension->PnPDeviceName.Length));
  556. SmartcardDebug(DEBUG_DRIVER,
  557. ("%s!CreateDevice: IoRegisterDeviceInterface returned=%lx\n",DRIVER_NAME,NTStatus));
  558. }
  559. else
  560. {
  561. SmartcardDebug(DEBUG_DRIVER,
  562. ("%s!CreateDevice: Interface already exists\n",DRIVER_NAME));
  563. }
  564. }
  565. else
  566. #endif
  567. {
  568. // ----------------------------------------------
  569. // create symbolic link
  570. // ----------------------------------------------
  571. NTStatus = SmartcardCreateLink(&DeviceExtension->LinkDeviceName,&DeviceName);
  572. SmartcardDebug(DEBUG_DRIVER,
  573. ("%s!CreateDevice: SmartcardCreateLink returned=%lx\n",DRIVER_NAME,NTStatus));
  574. }
  575. if (NTStatus != STATUS_SUCCESS)
  576. {
  577. SmartcardLogError(DriverObject,
  578. CMMOB_INSUFFICIENT_RESOURCES,
  579. NULL,
  580. 0);
  581. leave;
  582. }
  583. }
  584. finally
  585. {
  586. if (NTStatus != STATUS_SUCCESS)
  587. {
  588. CMMOB_UnloadDevice(*DeviceObject);
  589. *DeviceObject = NULL;
  590. }
  591. }
  592. SmartcardDebug(DEBUG_TRACE,
  593. ( "%s!CreateDevice: Exit %x\n",DRIVER_NAME,NTStatus ));
  594. return NTStatus;
  595. }
  596. /*****************************************************************************
  597. Routine Description:
  598. get the actual configuration from the passed FullResourceDescriptor
  599. and initializes the reader hardware
  600. Note:
  601. for an NT 4.00 build the resources must be translated by the HAL
  602. Arguments:
  603. DeviceObject context of call
  604. FullResourceDescriptor actual configuration of the reader
  605. Return Value:
  606. STATUS_SUCCESS
  607. NTStatus returned from the HAL (NT 4.00 only )
  608. NTStatus returned by LowLevel routines
  609. ******************************************************************************/
  610. NTSTATUS CMMOB_StartDevice(
  611. PDEVICE_OBJECT DeviceObject,
  612. PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
  613. )
  614. {
  615. NTSTATUS NTStatus = STATUS_SUCCESS;
  616. PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
  617. PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
  618. PSMARTCARD_EXTENSION SmartcardExtension = &DeviceExtension->SmartcardExtension;
  619. PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
  620. ULONG ulCount;
  621. ULONG ulCISIndex;
  622. UCHAR bTupleCode[2];
  623. UCHAR bFirmware[2];
  624. SmartcardDebug(DEBUG_TRACE,
  625. ("%s!StartDevice: Enter\n",DRIVER_NAME));
  626. //
  627. // Get the number of resources we need
  628. //
  629. ulCount = FullResourceDescriptor->PartialResourceList.Count;
  630. PartialDescriptor = FullResourceDescriptor->PartialResourceList.PartialDescriptors;
  631. //
  632. // parse all partial descriptors
  633. //
  634. while (ulCount--)
  635. {
  636. switch (PartialDescriptor->Type)
  637. {
  638. #ifdef MEMORYCARD
  639. case CmResourceTypeMemory:
  640. {
  641. //
  642. // 0 - memory, 1 - IO
  643. //
  644. #ifdef NT4
  645. ULONG AddressSpace = 0;
  646. BOOLEAN fTranslated;
  647. PHYSICAL_ADDRESS PhysicalAddress;
  648. #endif
  649. //
  650. // Get Mem-length
  651. //
  652. ReaderExtension->ulMemWindow = PartialDescriptor->u.Memory.Length;
  653. ASSERT(PartialDescriptor->u.Memory.Length >= 4096);
  654. //
  655. // Get Mem-base
  656. //
  657. #ifndef NT4
  658. ReaderExtension->pMemBase = MmMapIoSpace (PartialDescriptor->u.Memory.Start,
  659. PartialDescriptor->u.Memory.Length,
  660. FALSE);
  661. DeviceExtension->fUnMapMem = TRUE;
  662. #else
  663. //
  664. // let the hal translate the address
  665. //
  666. fTranslated = HalTranslateBusAddress(FullResourceDescriptor->InterfaceType,
  667. FullResourceDescriptor->BusNumber,
  668. PartialDescriptor->u.Memory.Start,
  669. &AddressSpace,
  670. &PhysicalAddress);
  671. if (fTranslated == TRUE && AddressSpace == 0)
  672. {
  673. ReaderExtension->pMemBase = MmMapIoSpace(PhysicalAddress,
  674. PartialDescriptor->u.Memory.Length,
  675. FALSE);
  676. DeviceExtension->fUnMapMem = TRUE;
  677. }
  678. else
  679. {
  680. ReaderExtension->pMemBase = (PVOID) PhysicalAddress.LowPart;
  681. }
  682. #endif
  683. SmartcardDebug(DEBUG_TRACE,
  684. ("%s!StartDevice: MemBase = %lxh\n",DRIVER_NAME,ReaderExtension->pMemBase));
  685. }
  686. break;
  687. #endif
  688. #ifdef IOCARD
  689. case CmResourceTypePort:
  690. {
  691. #ifdef NT4
  692. //
  693. // 0 - memory, 1 - IO
  694. //
  695. ULONG AddressSpace = 1;
  696. BOOLEAN fTranslated;
  697. PHYSICAL_ADDRESS PhysicalAddress;
  698. #endif
  699. //
  700. // Get IO-length
  701. //
  702. ReaderExtension->ulIoWindow = PartialDescriptor->u.Port.Length;
  703. ASSERT(PartialDescriptor->u.Port.Length >= 8);
  704. //
  705. // Get IO-base
  706. //
  707. #ifndef NT4
  708. #ifndef _WIN64
  709. ReaderExtension->pIoBase = (PVOID) PartialDescriptor->u.Port.Start.LowPart;
  710. #else
  711. ReaderExtension->pIoBase = (PVOID) PartialDescriptor->u.Port.Start.QuadPart;
  712. #endif
  713. #else
  714. //
  715. // let the hal translate the address
  716. //
  717. fTranslated = HalTranslateBusAddress(FullResourceDescriptor->InterfaceType,
  718. FullResourceDescriptor->BusNumber,
  719. PartialDescriptor->u.Port.Start,
  720. &AddressSpace,
  721. &PhysicalAddress);
  722. if (fTranslated == TRUE && AddressSpace == 0)
  723. {
  724. ReaderExtension->pIoBase = MmMapIoSpace(PhysicalAddress,
  725. PartialDescriptor->u.Port.Length,
  726. FALSE);
  727. DeviceExtension->fUnMapMem = TRUE;
  728. }
  729. else
  730. {
  731. ReaderExtension->pIoBase = (PVOID) PhysicalAddress.LowPart;
  732. }
  733. #endif
  734. SmartcardDebug(DEBUG_TRACE,
  735. ("%s!StartDevice: IoBase = %lxh\n",DRIVER_NAME,ReaderExtension->pIoBase));
  736. }
  737. break;
  738. #endif
  739. default:
  740. break;
  741. }
  742. PartialDescriptor++;
  743. }
  744. try
  745. {
  746. //
  747. // Base initialized ?
  748. //
  749. #ifdef MEMORYCARD
  750. if (ReaderExtension->pMemBase == NULL)
  751. #endif
  752. #ifdef IOCARD
  753. if (ReaderExtension->pIoBase == NULL)
  754. #endif
  755. {
  756. #ifndef NT4
  757. //
  758. // under NT 4.0 the failure of this fct for the second reader
  759. // means there is only one device
  760. //
  761. SmartcardLogError(DeviceObject,
  762. CMMOB_ERROR_MEM_PORT,
  763. NULL,
  764. 0);
  765. #endif
  766. NTStatus = STATUS_INSUFFICIENT_RESOURCES;
  767. leave;
  768. }
  769. // initialize base addresses
  770. #ifdef MEMORYCARD
  771. ReaderExtension->pbCISBase= (PUCHAR) ReaderExtension->pMemBase;
  772. ReaderExtension->pbRegsBase= ReaderExtension->pbCISBase + 0x400;
  773. ReaderExtension->pbDataBase= ReaderExtension->pbCISBase + 0x800;
  774. #endif
  775. #ifdef IOCARD
  776. ReaderExtension->pbRegsBase= (PUCHAR) ReaderExtension->pIoBase;
  777. #endif
  778. NTStatus=CMMOB_ResetReader (ReaderExtension);
  779. SmartcardDebug(DEBUG_DRIVER,
  780. ("%s!DEBUG_DRIVER: ResetReader retval = %x\n",DRIVER_NAME, NTStatus));
  781. if (NTStatus != STATUS_SUCCESS)
  782. {
  783. SmartcardLogError(DeviceObject,
  784. CMMOB_CANT_INITIALIZE_READER,
  785. NULL,
  786. 0);
  787. leave;
  788. }
  789. #ifdef IOCARD
  790. //
  791. // read firmware version from CIS
  792. //
  793. ReaderExtension->fReadCIS=TRUE;
  794. ReaderExtension->fTActive=TRUE;
  795. NTStatus=CMMOB_SetFlags1 (ReaderExtension);
  796. if (NTStatus != STATUS_SUCCESS)
  797. {
  798. SmartcardLogError(DeviceObject,
  799. CMMOB_CANT_INITIALIZE_READER,
  800. NULL,
  801. 0);
  802. leave;
  803. }
  804. ulCISIndex = 0;
  805. do
  806. {
  807. NTStatus=CMMOB_ReadBuffer(ReaderExtension, ulCISIndex, 2, bTupleCode);
  808. if (NTStatus != STATUS_SUCCESS)
  809. {
  810. leave;
  811. }
  812. if (bTupleCode[0] == 0x15)
  813. {
  814. // this is the version tuple
  815. // read firmware version
  816. NTStatus=CMMOB_ReadBuffer(ReaderExtension, ulCISIndex+2, 2, bFirmware);
  817. if (NTStatus != STATUS_SUCCESS)
  818. {
  819. leave;
  820. }
  821. SmartcardExtension->ReaderExtension->ulFWVersion = 100*(ULONG)bFirmware[0]+bFirmware[1];
  822. SmartcardDebug(DEBUG_TRACE,
  823. ("%s!StartDevice: Firmware version = %li\n",
  824. DRIVER_NAME, SmartcardExtension->ReaderExtension->ulFWVersion));
  825. }
  826. ulCISIndex += bTupleCode[1] + 2;
  827. }
  828. while (bTupleCode[1] != 0 &&
  829. bTupleCode[0] != 0x15 &&
  830. bTupleCode[0] != 0xFF &&
  831. ulCISIndex < CMMOB_MAX_CIS_SIZE);
  832. ReaderExtension->fReadCIS=FALSE;
  833. ReaderExtension->fTActive=FALSE;
  834. NTStatus=CMMOB_SetFlags1 (ReaderExtension);
  835. if (NTStatus != STATUS_SUCCESS)
  836. {
  837. SmartcardLogError(DeviceObject,
  838. CMMOB_CANT_INITIALIZE_READER,
  839. NULL,
  840. 0);
  841. leave;
  842. }
  843. #endif
  844. //
  845. // start update thread
  846. //
  847. NTStatus = CMMOB_StartCardTracking(DeviceObject);
  848. // signal that the reader has been started (again)
  849. KeSetEvent(&DeviceExtension->ReaderStarted, 0, FALSE);
  850. #ifndef NT4
  851. if (DeviceExtension->OSVersion == OS_Windows2000)
  852. {
  853. NTStatus = IoSetDeviceInterfaceState(&DeviceExtension->PnPDeviceName,TRUE);
  854. }
  855. #endif
  856. }
  857. finally
  858. {
  859. if (NTStatus != STATUS_SUCCESS)
  860. {
  861. CMMOB_StopDevice(DeviceObject);
  862. }
  863. }
  864. SmartcardDebug(DEBUG_TRACE,
  865. ("%s!StartDevice: Exit %x\n",DRIVER_NAME,NTStatus));
  866. return NTStatus;
  867. }
  868. /*****************************************************************************
  869. Routine Description:
  870. Unmap the IO port
  871. Arguments:
  872. DeviceObject context of call
  873. Return Value:
  874. void
  875. ******************************************************************************/
  876. VOID
  877. CMMOB_StopDevice(
  878. PDEVICE_OBJECT DeviceObject
  879. )
  880. {
  881. PDEVICE_EXTENSION DeviceExtension;
  882. if (DeviceObject == NULL)
  883. {
  884. return;
  885. }
  886. SmartcardDebug(DEBUG_TRACE,
  887. ( "%s!StopDevice: Enter\n",DRIVER_NAME ));
  888. DeviceExtension = DeviceObject->DeviceExtension;
  889. KeClearEvent(&DeviceExtension->ReaderStarted);
  890. //
  891. // stop update thread
  892. //
  893. CMMOB_StopCardTracking(DeviceObject);
  894. // power down the card for saftey reasons
  895. if (DeviceExtension->SmartcardExtension.ReaderExtension->ulOldCardState == POWERED)
  896. {
  897. // we have to wait for the mutex before
  898. KeWaitForSingleObject(&DeviceExtension->SmartcardExtension.ReaderExtension->CardManIOMutex,
  899. Executive,
  900. KernelMode,
  901. FALSE,
  902. NULL);
  903. CMMOB_PowerOffCard(&DeviceExtension->SmartcardExtension);
  904. KeReleaseMutex(&DeviceExtension->SmartcardExtension.ReaderExtension->CardManIOMutex,
  905. FALSE);
  906. }
  907. //
  908. // unmap ports
  909. //
  910. if (DeviceExtension->fUnMapMem)
  911. {
  912. #ifdef MEMORYCARD
  913. MmUnmapIoSpace(DeviceExtension->SmartcardExtension.ReaderExtension->pMemBase,
  914. DeviceExtension->SmartcardExtension.ReaderExtension->ulMemWindow);
  915. #endif
  916. #ifdef IOCARD
  917. MmUnmapIoSpace(DeviceExtension->SmartcardExtension.ReaderExtension->pIoBase,
  918. DeviceExtension->SmartcardExtension.ReaderExtension->ulIoWindow);
  919. #endif
  920. DeviceExtension->fUnMapMem = FALSE;
  921. }
  922. SmartcardDebug(DEBUG_TRACE,
  923. ( "%s!StopDevice: Exit\n",DRIVER_NAME ));
  924. }
  925. /*****************************************************************************
  926. Routine Description:
  927. close connections to smclib.sys and the pcmcia driver, delete symbolic
  928. link and mark the slot as unused.
  929. Arguments:
  930. DeviceObject device to unload
  931. Return Value:
  932. void
  933. ******************************************************************************/
  934. VOID CMMOB_UnloadDevice(
  935. PDEVICE_OBJECT DeviceObject
  936. )
  937. {
  938. PDEVICE_EXTENSION DeviceExtension;
  939. if (DeviceObject == NULL)
  940. {
  941. return;
  942. }
  943. SmartcardDebug(DEBUG_TRACE,
  944. ( "%s!UnloadDevice: Enter\n",DRIVER_NAME ));
  945. DeviceExtension = DeviceObject->DeviceExtension;
  946. //
  947. // It is possible that someone yanks out the pcmcia card when the
  948. // resource manager still has a connection to the device.
  949. // We need this flag to know that the device has been removed.
  950. //
  951. DeviceExtension->fDeviceRemoved = TRUE;
  952. ASSERT(DeviceExtension->SmartcardExtension.VendorAttr.UnitNo < CMMOB_MAX_DEVICE);
  953. //
  954. // Mark this slot as available
  955. //
  956. DeviceSlot[DeviceExtension->SmartcardExtension.VendorAttr.UnitNo] = FALSE;
  957. //
  958. // report to the lib that the device will be unloaded
  959. //
  960. if (DeviceExtension->SmartcardExtension.OsData != NULL)
  961. {
  962. //
  963. // finish pending tracking requests
  964. //
  965. CMMOB_CompleteCardTracking (&DeviceExtension->SmartcardExtension);
  966. }
  967. #ifdef NT4
  968. // for WDM driver the remove lock is acquired in the PnP routine
  969. // so in case of NT4 we have to acquire it her
  970. SmartcardAcquireRemoveLock(&DeviceExtension->SmartcardExtension);
  971. #endif
  972. // Wait until we can safely unload the device
  973. SmartcardReleaseRemoveLockAndWait(&DeviceExtension->SmartcardExtension);
  974. SmartcardExit(&DeviceExtension->SmartcardExtension);
  975. #ifndef NT4
  976. if (DeviceExtension->OSVersion == OS_Windows2000)
  977. {
  978. //
  979. // disable interface
  980. //
  981. if (DeviceExtension->PnPDeviceName.Buffer != NULL)
  982. {
  983. // disable our device so no one can open it
  984. IoSetDeviceInterfaceState(&DeviceExtension->PnPDeviceName,FALSE);
  985. RtlFreeUnicodeString(&DeviceExtension->PnPDeviceName);
  986. DeviceExtension->PnPDeviceName.Buffer = NULL;
  987. }
  988. }
  989. else
  990. #endif
  991. {
  992. //
  993. // Delete the symbolic link of the smart card reader
  994. //
  995. if (DeviceExtension->LinkDeviceName.Buffer != NULL)
  996. {
  997. NTSTATUS NTStatus;
  998. NTStatus = IoDeleteSymbolicLink(&DeviceExtension->LinkDeviceName);
  999. //
  1000. // we continue even if an error occurs
  1001. //
  1002. ASSERT(NTStatus == STATUS_SUCCESS);
  1003. RtlFreeUnicodeString(&DeviceExtension->LinkDeviceName);
  1004. DeviceExtension->LinkDeviceName.Buffer = NULL;
  1005. }
  1006. }
  1007. if (DeviceExtension->SmartcardExtension.ReaderExtension != NULL)
  1008. {
  1009. ExFreePool(DeviceExtension->SmartcardExtension.ReaderExtension);
  1010. DeviceExtension->SmartcardExtension.ReaderExtension = NULL;
  1011. }
  1012. //
  1013. // Detach from the pcmcia driver
  1014. // Under NT 4.0 we did not attach to the pcmcia driver
  1015. //
  1016. if (DeviceExtension->AttachedDeviceObject)
  1017. {
  1018. IoDetachDevice(DeviceExtension->AttachedDeviceObject);
  1019. DeviceExtension->AttachedDeviceObject = NULL;
  1020. }
  1021. //
  1022. // delete the device object
  1023. //
  1024. IoDeleteDevice(DeviceObject);
  1025. SmartcardDebug(DEBUG_TRACE,
  1026. ( "%s!UnloadDevice: Exit\n",DRIVER_NAME ));
  1027. return;
  1028. }
  1029. /*****************************************************************************
  1030. CMMOB_UnloadDriver:
  1031. unloads all devices for a given driver object
  1032. Arguments:
  1033. DriverObject context of driver
  1034. Return Value:
  1035. void
  1036. ******************************************************************************/
  1037. VOID CMMOB_UnloadDriver(
  1038. PDRIVER_OBJECT DriverObject
  1039. )
  1040. {
  1041. PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
  1042. ULONG ulSizeOfResources;
  1043. SmartcardDebug(DEBUG_TRACE,
  1044. ( "%s!UnloadDriver: Enter\n",DRIVER_NAME ));
  1045. #ifdef NT4
  1046. if (DriverObject->DeviceObject != NULL)
  1047. {
  1048. ulSizeOfResources = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
  1049. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  1050. //
  1051. // allocate memory for the resource descriptor
  1052. //
  1053. FullResourceDescriptor = ExAllocatePool(PagedPool,ulSizeOfResources);
  1054. if (FullResourceDescriptor == NULL)
  1055. {
  1056. return;
  1057. }
  1058. RtlZeroMemory(FullResourceDescriptor, ulSizeOfResources);
  1059. //
  1060. // unload all device objects of that driver object
  1061. //
  1062. while (DriverObject->DeviceObject)
  1063. {
  1064. CMMOB_StopDevice(DriverObject->DeviceObject);
  1065. CMMOB_ReportResources(DriverObject, FullResourceDescriptor);
  1066. CMMOB_UnloadDevice(DriverObject->DeviceObject);
  1067. }
  1068. //
  1069. // free local resources
  1070. //
  1071. ExFreePool(FullResourceDescriptor);
  1072. }
  1073. #endif
  1074. SmartcardDebug(DEBUG_TRACE,
  1075. ( "%s!UnloadDriver: Exit\n",DRIVER_NAME ));
  1076. }
  1077. /*****************************************************************************
  1078. CMMOB_CreateClose:
  1079. allowes only one open process a time
  1080. Arguments:
  1081. DeviceObject context of device
  1082. Irp context of call
  1083. Return Value:
  1084. STATUS_SUCCESS
  1085. STATUS_DEVICE_BUSY
  1086. ******************************************************************************/
  1087. NTSTATUS CMMOB_CreateClose(
  1088. PDEVICE_OBJECT DeviceObject,
  1089. PIRP Irp
  1090. )
  1091. {
  1092. NTSTATUS NTStatus = STATUS_SUCCESS;
  1093. PDEVICE_EXTENSION DeviceExtension;
  1094. PSMARTCARD_EXTENSION SmartcardExtension;
  1095. PIO_STACK_LOCATION IrpStack;
  1096. SmartcardDebug(DEBUG_TRACE,
  1097. ("%s!CreateClose: Enter ",DRIVER_NAME));
  1098. DeviceExtension = DeviceObject->DeviceExtension;
  1099. SmartcardExtension = &DeviceExtension->SmartcardExtension;
  1100. IrpStack = IoGetCurrentIrpStackLocation( Irp );
  1101. //
  1102. // dispatch major function
  1103. //
  1104. switch (IrpStack->MajorFunction)
  1105. {
  1106. case IRP_MJ_CREATE:
  1107. SmartcardDebug(DEBUG_IOCTL,("%s!CreateClose: IRP_MJ_CREATE\n",DRIVER_NAME));
  1108. if (DeviceExtension->fRemovePending)
  1109. {
  1110. NTStatus = STATUS_DEVICE_BUSY;
  1111. }
  1112. else
  1113. {
  1114. if (InterlockedIncrement(&DeviceExtension->lOpenCount) > 1)
  1115. {
  1116. InterlockedDecrement(&DeviceExtension->lOpenCount);
  1117. NTStatus = STATUS_ACCESS_DENIED;
  1118. }
  1119. }
  1120. break;
  1121. case IRP_MJ_CLOSE:
  1122. SmartcardDebug(DEBUG_IOCTL,("%s!CreateClose: IRP_MJ_CLOSE\n",DRIVER_NAME));
  1123. if (InterlockedDecrement(&DeviceExtension->lOpenCount) < 0)
  1124. {
  1125. InterlockedIncrement(&DeviceExtension->lOpenCount);
  1126. }
  1127. break;
  1128. default:
  1129. //
  1130. // unrecognized command
  1131. //
  1132. SmartcardDebug(DEBUG_IOCTL,("unexpected IRP\n"));
  1133. NTStatus = STATUS_INVALID_DEVICE_REQUEST;
  1134. break;
  1135. }
  1136. Irp->IoStatus.Information = 0;
  1137. Irp->IoStatus.Status = NTStatus;
  1138. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1139. SmartcardDebug(DEBUG_TRACE,
  1140. ("%s!CreateClose: Exit %x\n",DRIVER_NAME,NTStatus));
  1141. return NTStatus;
  1142. }
  1143. NTSTATUS CMMOB_SystemControl(
  1144. PDEVICE_OBJECT DeviceObject,
  1145. PIRP Irp
  1146. )
  1147. {
  1148. PDEVICE_EXTENSION DeviceExtension;
  1149. NTSTATUS status = STATUS_SUCCESS;
  1150. DeviceExtension = DeviceObject->DeviceExtension;
  1151. IoSkipCurrentIrpStackLocation(Irp);
  1152. status = IoCallDriver(DeviceExtension->AttachedDeviceObject, Irp);
  1153. return status;
  1154. }
  1155. /*****************************************************************************
  1156. CMMOB_DeviceIoControl:
  1157. all IRP's requiring IO are queued to the StartIo routine, other requests
  1158. are served immediately
  1159. Arguments:
  1160. DeviceObject context of device
  1161. Irp context of call
  1162. Return Value:
  1163. STATUS_SUCCESS
  1164. STATUS_PENDING
  1165. ******************************************************************************/
  1166. NTSTATUS CMMOB_DeviceIoControl(
  1167. PDEVICE_OBJECT DeviceObject,
  1168. PIRP Irp
  1169. )
  1170. {
  1171. NTSTATUS NTStatus;
  1172. PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
  1173. KIRQL irql;
  1174. PIO_STACK_LOCATION irpSL;
  1175. SmartcardDebug(DEBUG_TRACE,
  1176. ("%s!DeviceIoControl: Enter\n",DRIVER_NAME));
  1177. irpSL = IoGetCurrentIrpStackLocation(Irp);
  1178. #if DBG
  1179. switch (irpSL->Parameters.DeviceIoControl.IoControlCode)
  1180. {
  1181. case IOCTL_SMARTCARD_EJECT:
  1182. SmartcardDebug(DEBUG_IOCTL,
  1183. ("%s!DeviceIoControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_EJECT"));
  1184. break;
  1185. case IOCTL_SMARTCARD_GET_ATTRIBUTE:
  1186. SmartcardDebug(DEBUG_IOCTL,
  1187. ("%s!DeviceIoControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_GET_ATTRIBUTE"));
  1188. break;
  1189. case IOCTL_SMARTCARD_GET_LAST_ERROR:
  1190. SmartcardDebug(DEBUG_IOCTL,
  1191. ("%s!DeviceIoControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_GET_LAST_ERROR"));
  1192. break;
  1193. case IOCTL_SMARTCARD_GET_STATE:
  1194. SmartcardDebug(DEBUG_IOCTL,
  1195. ("%s!DeviceIoControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_GET_STATE"));
  1196. break;
  1197. case IOCTL_SMARTCARD_IS_ABSENT:
  1198. SmartcardDebug(DEBUG_IOCTL,
  1199. ("%s!DeviceIoControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_IS_ABSENT"));
  1200. break;
  1201. case IOCTL_SMARTCARD_IS_PRESENT:
  1202. SmartcardDebug(DEBUG_IOCTL,
  1203. ("%s!DeviceIoControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_IS_PRESENT"));
  1204. break;
  1205. case IOCTL_SMARTCARD_POWER:
  1206. SmartcardDebug(DEBUG_IOCTL,
  1207. ("%s!DeviceIoControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_POWER"));
  1208. break;
  1209. case IOCTL_SMARTCARD_SET_ATTRIBUTE:
  1210. SmartcardDebug(DEBUG_IOCTL,
  1211. ("%s!DeviceIoControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_SET_ATTRIBUTE"));
  1212. break;
  1213. case IOCTL_SMARTCARD_SET_PROTOCOL:
  1214. SmartcardDebug(DEBUG_IOCTL,
  1215. ("%s!DeviceIoControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_SET_PROTOCOL"));
  1216. break;
  1217. case IOCTL_SMARTCARD_SWALLOW:
  1218. SmartcardDebug(DEBUG_IOCTL,
  1219. ("%s!DeviceIoControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_SWALLOW"));
  1220. break;
  1221. case IOCTL_SMARTCARD_TRANSMIT:
  1222. SmartcardDebug(DEBUG_IOCTL,
  1223. ("%s!DeviceIoControl: %s\n", DRIVER_NAME, "IOCTL_SMARTCARD_TRANSMIT"));
  1224. break;
  1225. default:
  1226. SmartcardDebug(DEBUG_IOCTL,
  1227. ("%s!DeviceIoControl: %s\n", DRIVER_NAME, "Vendor specific or unexpected IOCTL"));
  1228. break;
  1229. }
  1230. #endif
  1231. KeAcquireSpinLock(&DeviceExtension->SpinLockIoCount, &irql);
  1232. if (DeviceExtension->lIoCount == 0)
  1233. {
  1234. KeReleaseSpinLock(&DeviceExtension->SpinLockIoCount, irql);
  1235. NTStatus = KeWaitForSingleObject(&DeviceExtension->ReaderStarted,
  1236. Executive,
  1237. KernelMode,
  1238. FALSE,
  1239. NULL);
  1240. ASSERT(NTStatus == STATUS_SUCCESS);
  1241. KeAcquireSpinLock(&DeviceExtension->SpinLockIoCount, &irql);
  1242. }
  1243. ASSERT(DeviceExtension->lIoCount >= 0);
  1244. DeviceExtension->lIoCount++;
  1245. KeReleaseSpinLock(&DeviceExtension->SpinLockIoCount, irql);
  1246. // Can't accept a new io request if:
  1247. if (DeviceExtension->fDeviceRemoved == TRUE ||
  1248. //flag set when processing IRP_MN_REMOVE_DEVICE
  1249. DeviceExtension->fRemovePending == TRUE)
  1250. // flag set when driver has answered success to IRP_MN_QUERY_REMOVE_DEVICE
  1251. {
  1252. NTStatus = STATUS_DELETE_PENDING;
  1253. Irp->IoStatus.Status = NTStatus;
  1254. Irp->IoStatus.Information = 0;
  1255. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1256. KeAcquireSpinLock(&DeviceExtension->SpinLockIoCount, &irql);
  1257. DeviceExtension->lIoCount--;
  1258. ASSERT(DeviceExtension->lIoCount >= 0);
  1259. KeReleaseSpinLock(&DeviceExtension->SpinLockIoCount, irql);
  1260. return NTStatus;
  1261. }
  1262. NTStatus = SmartcardAcquireRemoveLock(&DeviceExtension->SmartcardExtension);
  1263. if (NTStatus != STATUS_SUCCESS)
  1264. {
  1265. // the device has been removed. Fail the call
  1266. NTStatus = STATUS_DELETE_PENDING;
  1267. Irp->IoStatus.Status = NTStatus;
  1268. Irp->IoStatus.Information = 0;
  1269. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1270. KeAcquireSpinLock(&DeviceExtension->SpinLockIoCount, &irql);
  1271. DeviceExtension->lIoCount--;
  1272. ASSERT(DeviceExtension->lIoCount >= 0);
  1273. KeReleaseSpinLock(&DeviceExtension->SpinLockIoCount, irql);
  1274. SmartcardDebug(DEBUG_TRACE,
  1275. ("%s!DeviceIoControl: Exit %x\n",DRIVER_NAME,NTStatus));
  1276. return NTStatus;
  1277. }
  1278. KeWaitForSingleObject(&DeviceExtension->SmartcardExtension.ReaderExtension->CardManIOMutex,
  1279. Executive,
  1280. KernelMode,
  1281. FALSE,
  1282. NULL);
  1283. // get current card state
  1284. NTStatus = CMMOB_UpdateCurrentState(&DeviceExtension->SmartcardExtension);
  1285. NTStatus = SmartcardDeviceControl(&DeviceExtension->SmartcardExtension,Irp);
  1286. KeReleaseMutex(&DeviceExtension->SmartcardExtension.ReaderExtension->CardManIOMutex,
  1287. FALSE);
  1288. SmartcardReleaseRemoveLock(&DeviceExtension->SmartcardExtension);
  1289. KeAcquireSpinLock(&DeviceExtension->SpinLockIoCount, &irql);
  1290. DeviceExtension->lIoCount--;
  1291. ASSERT(DeviceExtension->lIoCount >= 0);
  1292. KeReleaseSpinLock(&DeviceExtension->SpinLockIoCount, irql);
  1293. SmartcardDebug(DEBUG_TRACE,
  1294. ("%s!DeviceIoControl: Exit %x\n",DRIVER_NAME,NTStatus));
  1295. return NTStatus;
  1296. }
  1297. /*****************************************************************************
  1298. Routine Description:
  1299. This routine is called by the I/O system when the calling thread terminates
  1300. Arguments:
  1301. DeviceObject - Pointer to device object for this miniport
  1302. Irp - IRP involved.
  1303. Return Value:
  1304. STATUS_CANCELLED
  1305. ******************************************************************************/
  1306. NTSTATUS CMMOB_Cleanup(
  1307. IN PDEVICE_OBJECT DeviceObject,
  1308. IN PIRP Irp
  1309. )
  1310. {
  1311. PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
  1312. PSMARTCARD_EXTENSION SmartcardExtension = &DeviceExtension->SmartcardExtension;
  1313. SmartcardDebug(DEBUG_TRACE,
  1314. ("%s!Cleanup: Enter\n",DRIVER_NAME));
  1315. if (SmartcardExtension->OsData->NotificationIrp != NULL &&
  1316. // test if there is a pending IRP at all
  1317. SmartcardExtension->ReaderExtension != NULL &&
  1318. // if the device has been removed ReaderExtension == NULL
  1319. DeviceExtension->lOpenCount == 1 )
  1320. // complete card tracking only if this is the the last close call
  1321. // otherwise the card tracking of the resource manager is canceled
  1322. {
  1323. //
  1324. // We need to complete the notification irp
  1325. //
  1326. CMMOB_CompleteCardTracking(SmartcardExtension);
  1327. }
  1328. SmartcardDebug(DEBUG_DRIVER,
  1329. ("%s!Cleanup: Completing IRP %lx\n",DRIVER_NAME,Irp));
  1330. Irp->IoStatus.Information = 0;
  1331. Irp->IoStatus.Status = STATUS_SUCCESS;
  1332. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  1333. SmartcardDebug(DEBUG_TRACE,
  1334. ("%s!Cleanup: Exit\n",DRIVER_NAME));
  1335. return STATUS_SUCCESS;
  1336. }
  1337. /*****************************************************************************
  1338. SysDelay:
  1339. performs a required delay. The usage of KeStallExecutionProcessor is
  1340. very nasty, but it happends only if SysDelay is called in the context of
  1341. our DPC routine (which is only called if a card change was detected).
  1342. For 'normal' IO we have Irql < DISPATCH_LEVEL, so if the reader is polled
  1343. while waiting for response we will not block the entire system
  1344. Arguments:
  1345. Timeout delay in milli seconds
  1346. Return Value:
  1347. void
  1348. ******************************************************************************/
  1349. VOID SysDelay(
  1350. ULONG Timeout
  1351. )
  1352. {
  1353. LARGE_INTEGER SysTimeout;
  1354. if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
  1355. {
  1356. ULONG Cnt = 20 * Timeout;
  1357. SmartcardDebug(DEBUG_DRIVER,
  1358. ("%s! Waiting at IRQL >= DISPATCH_LEVEL %l\n",DRIVER_NAME,Timeout));
  1359. while (Cnt--)
  1360. {
  1361. //
  1362. // KeStallExecutionProcessor: counted in us
  1363. //
  1364. KeStallExecutionProcessor( 50 );
  1365. }
  1366. }
  1367. else
  1368. {
  1369. SysTimeout = RtlConvertLongToLargeInteger(Timeout * -10000L);
  1370. //
  1371. // KeDelayExecutionThread: counted in 100 ns
  1372. //
  1373. KeDelayExecutionThread( KernelMode, FALSE, &SysTimeout );
  1374. }
  1375. return;
  1376. }
  1377. /*****************************************************************************
  1378. * History:
  1379. * $Log: cmbp0wdm.c $
  1380. * Revision 1.11 2001/01/22 08:12:22 WFrischauf
  1381. * No comment given
  1382. *
  1383. * Revision 1.9 2000/09/25 14:24:33 WFrischauf
  1384. * No comment given
  1385. *
  1386. * Revision 1.8 2000/08/24 09:05:14 TBruendl
  1387. * No comment given
  1388. *
  1389. * Revision 1.7 2000/08/16 16:52:17 WFrischauf
  1390. * No comment given
  1391. *
  1392. * Revision 1.6 2000/08/09 12:46:01 WFrischauf
  1393. * No comment given
  1394. *
  1395. * Revision 1.5 2000/07/27 13:53:06 WFrischauf
  1396. * No comment given
  1397. *
  1398. *
  1399. ******************************************************************************/