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.

858 lines
31 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. smcioctl.c
  5. Abstract:
  6. This module handles all IOCTL requests to the smart card reader.
  7. Environment:
  8. Kernel mode only.
  9. Notes:
  10. This module is shared by Windows NT and Windows 9x
  11. Revision History:
  12. - Created June 1997 by Klaus Schutz
  13. --*/
  14. #define _ISO_TABLES_
  15. #ifndef SMCLIB_VXD
  16. #ifndef SMCLIB_CE
  17. #include <stdarg.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <ntddk.h>
  21. #endif
  22. #endif
  23. #include "smclib.h"
  24. #define IOCTL_SMARTCARD_DEBUG SCARD_CTL_CODE(98)
  25. #define CheckUserBuffer(_len_) \
  26. if (SmartcardExtension->IoRequest.ReplyBuffer == NULL || \
  27. SmartcardExtension->IoRequest.ReplyBufferLength < (_len_)) { \
  28. status = STATUS_BUFFER_TOO_SMALL; \
  29. break; \
  30. }
  31. #define CheckMinCardStatus(_status_) \
  32. if (SmartcardExtension->ReaderCapabilities.CurrentState < (_status_)) { \
  33. status = STATUS_INVALID_DEVICE_STATE; \
  34. break; \
  35. }
  36. #define ReturnULong(_value_) \
  37. { \
  38. CheckUserBuffer(sizeof(ULONG)) \
  39. *(PULONG) SmartcardExtension->IoRequest.ReplyBuffer = (_value_); \
  40. *SmartcardExtension->IoRequest.Information = sizeof(ULONG); \
  41. }
  42. #define ReturnUChar(_value_) \
  43. { \
  44. CheckUserBuffer(sizeof(UCHAR)) \
  45. *(PUCHAR) SmartcardExtension->IoRequest.ReplyBuffer = (_value_); \
  46. *SmartcardExtension->IoRequest.Information = sizeof(UCHAR); \
  47. }
  48. #define DIM(_array_) (sizeof(_array_) / sizeof(_array_[0]))
  49. PTCHAR
  50. MapIoControlCodeToString(
  51. ULONG IoControlCode
  52. )
  53. {
  54. ULONG i;
  55. static struct {
  56. ULONG IoControlCode;
  57. PTCHAR String;
  58. } IoControlList[] = {
  59. IOCTL_SMARTCARD_POWER, TEXT("POWER"),
  60. IOCTL_SMARTCARD_GET_ATTRIBUTE, TEXT("GET_ATTRIBUTE"),
  61. IOCTL_SMARTCARD_SET_ATTRIBUTE, TEXT("SET_ATTRIBUTE"),
  62. IOCTL_SMARTCARD_CONFISCATE, TEXT("CONFISCATE"),
  63. IOCTL_SMARTCARD_TRANSMIT, TEXT("TRANSMIT"),
  64. IOCTL_SMARTCARD_EJECT, TEXT("EJECT"),
  65. IOCTL_SMARTCARD_SWALLOW, TEXT("SWALLOW"),
  66. IOCTL_SMARTCARD_IS_PRESENT, TEXT("IS_PRESENT"),
  67. IOCTL_SMARTCARD_IS_ABSENT, TEXT("IS_ABSENT"),
  68. IOCTL_SMARTCARD_SET_PROTOCOL, TEXT("SET_PROTOCOL"),
  69. IOCTL_SMARTCARD_GET_STATE, TEXT("GET_STATE"),
  70. IOCTL_SMARTCARD_GET_LAST_ERROR, TEXT("GET_LAST_ERROR")
  71. };
  72. for (i = 0; i < DIM(IoControlList); i++) {
  73. if (IoControlCode == IoControlList[i].IoControlCode) {
  74. return IoControlList[i].String;
  75. }
  76. }
  77. return TEXT("*** UNKNOWN ***");
  78. }
  79. NTSTATUS
  80. SmartcardDeviceIoControl(
  81. PSMARTCARD_EXTENSION SmartcardExtension
  82. )
  83. /*++
  84. Routine Description:
  85. This routine handles the smart card lib specific io control requests.
  86. The driver has to call the function from the driver's io control request.
  87. It checks the parameters of the call and depending on the type of
  88. the call returns the requested value or calls the driver in order
  89. to perform an operation like POWER or TRANSMIT.
  90. NOTE: This function is used by Windows NT and VxD driver
  91. Arguments:
  92. SmartcardExtension - The pointer to the smart card data struct
  93. Return Value:
  94. NTSTATUS value
  95. --*/
  96. {
  97. NTSTATUS status = STATUS_SUCCESS;
  98. #ifdef SMCLIB_NT
  99. KIRQL Irql;
  100. #endif
  101. switch (SmartcardExtension->MajorIoControlCode) {
  102. #if DEBUG
  103. ULONG CurrentDebugLevel, bytesTransferred;
  104. #endif
  105. PSCARD_IO_REQUEST scardIoRequest;
  106. case IOCTL_SMARTCARD_GET_ATTRIBUTE:
  107. //
  108. // Please refer to the Interoperrability standard for ICC
  109. //
  110. switch (SmartcardExtension->MinorIoControlCode) {
  111. case SCARD_ATTR_VENDOR_NAME:
  112. CheckUserBuffer(SmartcardExtension->VendorAttr.VendorName.Length);
  113. RtlCopyMemory(
  114. SmartcardExtension->IoRequest.ReplyBuffer,
  115. SmartcardExtension->VendorAttr.VendorName.Buffer,
  116. SmartcardExtension->VendorAttr.VendorName.Length
  117. );
  118. *SmartcardExtension->IoRequest.Information =
  119. SmartcardExtension->VendorAttr.VendorName.Length;
  120. break;
  121. case SCARD_ATTR_VENDOR_IFD_TYPE:
  122. CheckUserBuffer(SmartcardExtension->VendorAttr.IfdType.Length);
  123. RtlCopyMemory(
  124. SmartcardExtension->IoRequest.ReplyBuffer,
  125. SmartcardExtension->VendorAttr.IfdType.Buffer,
  126. SmartcardExtension->VendorAttr.IfdType.Length
  127. );
  128. *SmartcardExtension->IoRequest.Information =
  129. SmartcardExtension->VendorAttr.IfdType.Length;
  130. break;
  131. case SCARD_ATTR_VENDOR_IFD_VERSION:
  132. ReturnULong(
  133. SmartcardExtension->VendorAttr.IfdVersion.BuildNumber |
  134. SmartcardExtension->VendorAttr.IfdVersion.VersionMinor << 16 |
  135. SmartcardExtension->VendorAttr.IfdVersion.VersionMajor << 24
  136. );
  137. break;
  138. case SCARD_ATTR_VENDOR_IFD_SERIAL_NO:
  139. if (SmartcardExtension->VendorAttr.IfdSerialNo.Length == 0) {
  140. status = STATUS_NOT_SUPPORTED;
  141. } else {
  142. CheckUserBuffer(SmartcardExtension->VendorAttr.IfdSerialNo.Length);
  143. RtlCopyMemory(
  144. SmartcardExtension->IoRequest.ReplyBuffer,
  145. SmartcardExtension->VendorAttr.IfdSerialNo.Buffer,
  146. SmartcardExtension->VendorAttr.IfdSerialNo.Length
  147. );
  148. *SmartcardExtension->IoRequest.Information =
  149. SmartcardExtension->VendorAttr.IfdSerialNo.Length;
  150. }
  151. break;
  152. case SCARD_ATTR_DEVICE_UNIT:
  153. // Return the unit number of this device
  154. ReturnULong(SmartcardExtension->VendorAttr.UnitNo);
  155. break;
  156. case SCARD_ATTR_CHANNEL_ID:
  157. //
  158. // Return reader type / channel id in form
  159. // 0xDDDDCCCC where D is reader type and C is channel number
  160. //
  161. ReturnULong(
  162. SmartcardExtension->ReaderCapabilities.ReaderType << 16l |
  163. SmartcardExtension->ReaderCapabilities.Channel
  164. );
  165. break;
  166. case SCARD_ATTR_CHARACTERISTICS:
  167. // Return mechanical characteristics of the reader
  168. ReturnULong(
  169. SmartcardExtension->ReaderCapabilities.MechProperties
  170. )
  171. break;
  172. case SCARD_ATTR_CURRENT_PROTOCOL_TYPE:
  173. // Return the currently selected protocol
  174. CheckMinCardStatus(SCARD_NEGOTIABLE);
  175. ReturnULong(
  176. SmartcardExtension->CardCapabilities.Protocol.Selected
  177. );
  178. break;
  179. case SCARD_ATTR_CURRENT_CLK:
  180. //
  181. // Return the current ICC clock freq. encoded as little
  182. // endian integer value (3.58 MHZ is 3580)
  183. //
  184. CheckMinCardStatus(SCARD_NEGOTIABLE);
  185. if(SmartcardExtension->CardCapabilities.PtsData.CLKFrequency) {
  186. ReturnULong(SmartcardExtension->CardCapabilities.PtsData.CLKFrequency);
  187. } else {
  188. ReturnULong(SmartcardExtension->ReaderCapabilities.CLKFrequency.Default);
  189. }
  190. break;
  191. case SCARD_ATTR_CURRENT_F:
  192. // Return the current F value encoded as little endian integer
  193. CheckMinCardStatus(SCARD_NEGOTIABLE);
  194. if (SmartcardExtension->CardCapabilities.Fl >=
  195. DIM(ClockRateConversion)) {
  196. status = STATUS_UNRECOGNIZED_MEDIA;
  197. break;
  198. }
  199. ASSERT(SmartcardExtension->CardCapabilities.Fl <
  200. DIM(ClockRateConversion));
  201. ReturnULong(
  202. SmartcardExtension->CardCapabilities.ClockRateConversion[
  203. SmartcardExtension->CardCapabilities.Fl
  204. ].F
  205. );
  206. break;
  207. case SCARD_ATTR_CURRENT_D:
  208. //
  209. // Return the current D value encoded as little endian integer
  210. // in units of 1/64. So return 1 if D is 1/64.
  211. //
  212. CheckMinCardStatus(SCARD_NEGOTIABLE);
  213. ASSERT(
  214. SmartcardExtension->CardCapabilities.Dl <
  215. DIM(BitRateAdjustment)
  216. );
  217. ASSERT(
  218. SmartcardExtension->CardCapabilities.BitRateAdjustment[
  219. SmartcardExtension->CardCapabilities.Dl
  220. ].DDivisor != 0
  221. );
  222. //
  223. // Check the current value of Dl.
  224. // It should definitely not be greater than the array bounds
  225. // and the value in the array is not allowed to be zero
  226. //
  227. if (SmartcardExtension->CardCapabilities.Dl >=
  228. DIM(BitRateAdjustment) ||
  229. SmartcardExtension->CardCapabilities.BitRateAdjustment[
  230. SmartcardExtension->CardCapabilities.Dl
  231. ].DDivisor == 0) {
  232. status = STATUS_UNRECOGNIZED_MEDIA;
  233. break;
  234. }
  235. ReturnULong(
  236. SmartcardExtension->CardCapabilities.BitRateAdjustment[
  237. SmartcardExtension->CardCapabilities.Dl
  238. ].DNumerator /
  239. SmartcardExtension->CardCapabilities.BitRateAdjustment[
  240. SmartcardExtension->CardCapabilities.Dl
  241. ].DDivisor
  242. );
  243. break;
  244. case SCARD_ATTR_CURRENT_W:
  245. // Return the work waiting time (integer) for T=0
  246. CheckMinCardStatus(SCARD_NEGOTIABLE);
  247. ReturnULong(SmartcardExtension->CardCapabilities.T0.WI);
  248. break;
  249. case SCARD_ATTR_CURRENT_N:
  250. // Return extra guard time
  251. CheckMinCardStatus(SCARD_NEGOTIABLE);
  252. ReturnULong(SmartcardExtension->CardCapabilities.N);
  253. break;
  254. case SCARD_ATTR_CURRENT_IFSC:
  255. // Return the current information field size card
  256. CheckMinCardStatus(SCARD_NEGOTIABLE);
  257. if (SmartcardExtension->T1.IFSC) {
  258. ReturnULong(SmartcardExtension->T1.IFSC);
  259. } else {
  260. ReturnULong(SmartcardExtension->CardCapabilities.T1.IFSC);
  261. }
  262. break;
  263. case SCARD_ATTR_CURRENT_IFSD:
  264. // Return the current information field size card
  265. CheckMinCardStatus(SCARD_NEGOTIABLE);
  266. if (SmartcardExtension->T1.IFSD) {
  267. ReturnULong(SmartcardExtension->T1.IFSD);
  268. } else {
  269. ReturnULong(SmartcardExtension->ReaderCapabilities.MaxIFSD);
  270. }
  271. break;
  272. case SCARD_ATTR_CURRENT_BWT:
  273. // Return the current block waiting time for T=1
  274. CheckMinCardStatus(SCARD_NEGOTIABLE);
  275. ReturnULong(SmartcardExtension->CardCapabilities.T1.BWI);
  276. break;
  277. case SCARD_ATTR_CURRENT_CWT:
  278. // Return the current character waiting time for T=1
  279. CheckMinCardStatus(SCARD_NEGOTIABLE);
  280. ReturnULong(SmartcardExtension->CardCapabilities.T1.CWI);
  281. break;
  282. case SCARD_ATTR_CURRENT_EBC_ENCODING:
  283. // Return the current error checking method
  284. CheckMinCardStatus(SCARD_NEGOTIABLE);
  285. ReturnULong(SmartcardExtension->CardCapabilities.T1.EDC);
  286. break;
  287. case SCARD_ATTR_DEFAULT_CLK:
  288. ReturnULong(
  289. SmartcardExtension->ReaderCapabilities.CLKFrequency.Default
  290. );
  291. break;
  292. case SCARD_ATTR_MAX_CLK:
  293. ReturnULong(
  294. SmartcardExtension->ReaderCapabilities.CLKFrequency.Max
  295. );
  296. break;
  297. case SCARD_ATTR_DEFAULT_DATA_RATE:
  298. ReturnULong(
  299. SmartcardExtension->ReaderCapabilities.DataRate.Default
  300. );
  301. break;
  302. case SCARD_ATTR_MAX_DATA_RATE:
  303. ReturnULong(
  304. SmartcardExtension->ReaderCapabilities.DataRate.Max
  305. );
  306. break;
  307. case SCARD_ATTR_ATR_STRING:
  308. // Return ATR of currently inserted card
  309. CheckUserBuffer(MAXIMUM_ATR_LENGTH);
  310. CheckMinCardStatus(SCARD_NEGOTIABLE);
  311. RtlCopyMemory(
  312. SmartcardExtension->IoRequest.ReplyBuffer,
  313. SmartcardExtension->CardCapabilities.ATR.Buffer,
  314. SmartcardExtension->CardCapabilities.ATR.Length
  315. );
  316. *SmartcardExtension->IoRequest.Information =
  317. SmartcardExtension->CardCapabilities.ATR.Length;
  318. break;
  319. case SCARD_ATTR_ICC_TYPE_PER_ATR:
  320. //
  321. // Return ICC type, based on ATR.
  322. // We currently support only T=0 and T=1, so return
  323. // 1 for those protocols otherwise 0 (unknown ICC type)
  324. //
  325. CheckMinCardStatus(SCARD_NEGOTIABLE);
  326. ReturnUChar(
  327. ((SmartcardExtension->CardCapabilities.Protocol.Selected &
  328. (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)) ? 1 : 0)
  329. );
  330. break;
  331. case SCARD_ATTR_ICC_PRESENCE:
  332. // Return the status of the card
  333. AccessUnsafeData(&Irql);
  334. switch (SmartcardExtension->ReaderCapabilities.CurrentState) {
  335. case SCARD_UNKNOWN:
  336. status = STATUS_INVALID_DEVICE_STATE;
  337. break;
  338. case SCARD_ABSENT:
  339. ReturnUChar(0);
  340. break;
  341. case SCARD_PRESENT:
  342. ReturnUChar(1);
  343. break;
  344. default:
  345. ReturnUChar(2);
  346. break;
  347. }
  348. EndAccessUnsafeData(Irql);
  349. break;
  350. case SCARD_ATTR_ICC_INTERFACE_STATUS:
  351. // Return if card contacts are active
  352. ReturnUChar(
  353. (SmartcardExtension->ReaderCapabilities.CurrentState >=
  354. SCARD_SWALLOWED ? (UCHAR) -1 : 0)
  355. );
  356. break;
  357. case SCARD_ATTR_PROTOCOL_TYPES:
  358. ReturnULong(
  359. SmartcardExtension->ReaderCapabilities.SupportedProtocols
  360. );
  361. break;
  362. case SCARD_ATTR_MAX_IFSD:
  363. ReturnULong(
  364. SmartcardExtension->ReaderCapabilities.MaxIFSD
  365. );
  366. break;
  367. case SCARD_ATTR_POWER_MGMT_SUPPORT:
  368. ReturnULong(
  369. SmartcardExtension->ReaderCapabilities.PowerMgmtSupport
  370. );
  371. break;
  372. default:
  373. status = STATUS_NOT_SUPPORTED;
  374. break;
  375. }
  376. break;
  377. case IOCTL_SMARTCARD_SET_ATTRIBUTE:
  378. switch (SmartcardExtension->MinorIoControlCode) {
  379. case SCARD_ATTR_SUPRESS_T1_IFS_REQUEST:
  380. //
  381. // The card does not support ifs request, so
  382. // we turn off ifs negotiation
  383. //
  384. SmartcardExtension->T1.State = T1_START;
  385. break;
  386. default:
  387. status = STATUS_NOT_SUPPORTED;
  388. break;
  389. }
  390. break;
  391. #if defined(DEBUG) && defined(SMCLIB_NT)
  392. case IOCTL_SMARTCARD_GET_PERF_CNTR:
  393. switch (SmartcardExtension->MinorIoControlCode) {
  394. case SCARD_PERF_NUM_TRANSMISSIONS:
  395. ReturnULong(SmartcardExtension->PerfInfo->NumTransmissions);
  396. break;
  397. case SCARD_PERF_BYTES_TRANSMITTED:
  398. ReturnULong(
  399. SmartcardExtension->PerfInfo->BytesSent +
  400. SmartcardExtension->PerfInfo->BytesReceived
  401. );
  402. break;
  403. case SCARD_PERF_TRANSMISSION_TIME:
  404. ReturnULong(
  405. (ULONG) (SmartcardExtension->PerfInfo->IoTickCount.QuadPart *
  406. KeQueryTimeIncrement() /
  407. 10)
  408. );
  409. break;
  410. }
  411. break;
  412. #endif
  413. case IOCTL_SMARTCARD_CONFISCATE:
  414. if (SmartcardExtension->ReaderFunction[RDF_CARD_CONFISCATE] == NULL) {
  415. status = STATUS_NOT_SUPPORTED;
  416. break;
  417. }
  418. status = SmartcardExtension->ReaderFunction[RDF_CARD_CONFISCATE](
  419. SmartcardExtension
  420. );
  421. break;
  422. case IOCTL_SMARTCARD_EJECT:
  423. if (SmartcardExtension->ReaderFunction[RDF_CARD_EJECT] == NULL) {
  424. status = STATUS_NOT_SUPPORTED;
  425. break;
  426. }
  427. status = SmartcardExtension->ReaderFunction[RDF_CARD_EJECT](
  428. SmartcardExtension
  429. );
  430. break;
  431. #ifdef SMCLIB_VXD
  432. case IOCTL_SMARTCARD_GET_LAST_ERROR:
  433. //
  434. // Return error of the last overlapped operation
  435. // Used for Windows VxD's that can't return the
  436. // error code within IoComplete like NT can
  437. //
  438. ReturnULong(SmartcardExtension->LastError);
  439. break;
  440. #endif
  441. case IOCTL_SMARTCARD_GET_STATE:
  442. // Return current state of the smartcard
  443. CheckUserBuffer(sizeof(ULONG));
  444. AccessUnsafeData(&Irql);
  445. *(PULONG) SmartcardExtension->IoRequest.ReplyBuffer =
  446. SmartcardExtension->ReaderCapabilities.CurrentState;
  447. *SmartcardExtension->IoRequest.Information =
  448. sizeof(ULONG);
  449. EndAccessUnsafeData(Irql);
  450. break;
  451. case IOCTL_SMARTCARD_POWER:
  452. if (SmartcardExtension->ReaderFunction[RDF_CARD_POWER] == NULL) {
  453. status = STATUS_NOT_SUPPORTED;
  454. break;
  455. }
  456. // Check if a card is present
  457. if (SmartcardExtension->ReaderCapabilities.CurrentState <=
  458. SCARD_ABSENT) {
  459. status = STATUS_INVALID_DEVICE_STATE;
  460. break;
  461. }
  462. // Initialize the card capabilities struct
  463. SmartcardInitializeCardCapabilities(
  464. SmartcardExtension
  465. );
  466. switch (SmartcardExtension->MinorIoControlCode) {
  467. case SCARD_COLD_RESET:
  468. case SCARD_WARM_RESET:
  469. CheckUserBuffer(MAXIMUM_ATR_LENGTH);
  470. case SCARD_POWER_DOWN:
  471. status = SmartcardExtension->ReaderFunction[RDF_CARD_POWER](
  472. SmartcardExtension
  473. );
  474. break;
  475. default:
  476. status = STATUS_INVALID_DEVICE_REQUEST;
  477. break;
  478. }
  479. break;
  480. case IOCTL_SMARTCARD_SET_PROTOCOL:
  481. //
  482. // Since we return the selected protocol, the return buffer
  483. // must be large enough to hold the result
  484. //
  485. CheckUserBuffer(sizeof(ULONG));
  486. // Set the protocol to be used with the current card
  487. if (SmartcardExtension->ReaderFunction[RDF_SET_PROTOCOL] == NULL) {
  488. status = STATUS_NOT_SUPPORTED;
  489. break;
  490. }
  491. // Check if we're already in specific state
  492. if (SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_SPECIFIC &&
  493. (SmartcardExtension->CardCapabilities.Protocol.Selected &
  494. SmartcardExtension->MinorIoControlCode)) {
  495. status = STATUS_SUCCESS;
  496. break;
  497. }
  498. // Check if a card is present and not already in specific mode
  499. if (SmartcardExtension->ReaderCapabilities.CurrentState <=
  500. SCARD_ABSENT) {
  501. status = STATUS_INVALID_DEVICE_STATE;
  502. break;
  503. }
  504. // We only check the ATR when the user selects T=0 or T=1
  505. if (SmartcardExtension->MinorIoControlCode & (SCARD_PROTOCOL_Tx)) {
  506. if (SmartcardExtension->MinorIoControlCode & SCARD_PROTOCOL_DEFAULT) {
  507. // Select default PTS values
  508. SmartcardExtension->CardCapabilities.PtsData.Type = PTS_TYPE_DEFAULT;
  509. } else {
  510. // Select best possible PTS data
  511. SmartcardExtension->CardCapabilities.PtsData.Type = PTS_TYPE_OPTIMAL;
  512. }
  513. // Evaluate ATR
  514. status = SmartcardUpdateCardCapabilities(SmartcardExtension);
  515. } else {
  516. // caller doesn't want neither T=0 nor T=1 -> force callback
  517. status = STATUS_UNRECOGNIZED_MEDIA;
  518. }
  519. if (status == STATUS_UNRECOGNIZED_MEDIA &&
  520. SmartcardExtension->ReaderFunction[RDF_ATR_PARSE] != NULL) {
  521. // let the driver evaluate the ATR, since we don't know it
  522. status = SmartcardExtension->ReaderFunction[RDF_ATR_PARSE](
  523. SmartcardExtension
  524. );
  525. }
  526. if (status != STATUS_SUCCESS) {
  527. // Evaluation of the ATR failed It doesn't make sense to continue
  528. break;
  529. }
  530. // Check if card is now in the right status
  531. if (SmartcardExtension->ReaderCapabilities.CurrentState <
  532. SCARD_NEGOTIABLE) {
  533. status = STATUS_INVALID_DEVICE_STATE;
  534. break;
  535. }
  536. //
  537. // Check if the user tries to select a protocol that
  538. // the card doesn't support
  539. //
  540. if ((SmartcardExtension->CardCapabilities.Protocol.Supported &
  541. SmartcardExtension->MinorIoControlCode) == 0) {
  542. //
  543. // Since the card does not support the request protocol
  544. // we need to set back any automatic seletions done by
  545. // SmartcardUpdateCardCapabilities()
  546. //
  547. SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_NEGOTIABLE;
  548. SmartcardExtension->CardCapabilities.Protocol.Selected = 0;
  549. status = STATUS_NOT_SUPPORTED;
  550. break;
  551. }
  552. status = SmartcardExtension->ReaderFunction[RDF_SET_PROTOCOL](
  553. SmartcardExtension
  554. );
  555. break;
  556. case IOCTL_SMARTCARD_TRANSMIT:
  557. if (SmartcardExtension->ReaderFunction[RDF_TRANSMIT] == NULL) {
  558. status = STATUS_NOT_SUPPORTED;
  559. break;
  560. }
  561. //
  562. // Check if card is in the right status
  563. //
  564. if (SmartcardExtension->ReaderCapabilities.CurrentState !=
  565. SCARD_SPECIFIC) {
  566. status = STATUS_INVALID_DEVICE_STATE;
  567. break;
  568. }
  569. if (SmartcardExtension->IoRequest.RequestBufferLength <
  570. sizeof(SCARD_IO_REQUEST)) {
  571. status = STATUS_INVALID_PARAMETER;
  572. break;
  573. }
  574. //
  575. // Check if the requested io-protocol matches
  576. // the prev. seleced protocol
  577. //
  578. scardIoRequest = (PSCARD_IO_REQUEST)
  579. SmartcardExtension->IoRequest.RequestBuffer;
  580. if (scardIoRequest->dwProtocol !=
  581. SmartcardExtension->CardCapabilities.Protocol.Selected) {
  582. status = STATUS_INVALID_DEVICE_STATE;
  583. break;
  584. }
  585. SmartcardExtension->SmartcardRequest.BufferLength = 0;
  586. #if defined(DEBUG) && defined(SMCLIB_NT)
  587. SmartcardExtension->PerfInfo->NumTransmissions += 1;
  588. if (SmartcardExtension->IoRequest.RequestBufferLength >=
  589. sizeof(SCARD_IO_REQUEST)) {
  590. bytesTransferred =
  591. SmartcardExtension->IoRequest.RequestBufferLength -
  592. sizeof(SCARD_IO_REQUEST);
  593. SmartcardExtension->PerfInfo->BytesSent +=
  594. bytesTransferred;
  595. }
  596. KeQueryTickCount(&SmartcardExtension->PerfInfo->TickStart);
  597. #endif
  598. status = SmartcardExtension->ReaderFunction[RDF_TRANSMIT](
  599. SmartcardExtension
  600. );
  601. #if defined(DEBUG) && defined(SMCLIB_NT)
  602. KeQueryTickCount(&SmartcardExtension->PerfInfo->TickEnd);
  603. if (*SmartcardExtension->IoRequest.Information >=
  604. sizeof(SCARD_IO_REQUEST)) {
  605. SmartcardExtension->PerfInfo->BytesReceived +=
  606. *SmartcardExtension->IoRequest.Information -
  607. sizeof(SCARD_IO_REQUEST);
  608. bytesTransferred +=
  609. *SmartcardExtension->IoRequest.Information -
  610. sizeof(SCARD_IO_REQUEST);
  611. }
  612. SmartcardExtension->PerfInfo->IoTickCount.QuadPart +=
  613. SmartcardExtension->PerfInfo->TickEnd.QuadPart -
  614. SmartcardExtension->PerfInfo->TickStart.QuadPart;
  615. if (FALSE) {
  616. ULONG timeInMilliSec = (ULONG)
  617. ((SmartcardExtension->PerfInfo->TickEnd.QuadPart -
  618. SmartcardExtension->PerfInfo->TickStart.QuadPart) *
  619. KeQueryTimeIncrement() /
  620. 10000);
  621. // check for a transferrate of < 400 bps
  622. if (status == STATUS_SUCCESS &&
  623. timeInMilliSec > 0 &&
  624. bytesTransferred * 5 < timeInMilliSec * 2) {
  625. SmartcardDebug(
  626. DEBUG_PERF,
  627. ("%s!SmartcardDeviceControl: Datarate for reader %*s was %3ld Baud (%3ld)\n",
  628. DRIVER_NAME,
  629. SmartcardExtension->VendorAttr.VendorName.Length,
  630. SmartcardExtension->VendorAttr.VendorName.Buffer,
  631. bytesTransferred * 1000 / timeInMilliSec,
  632. bytesTransferred)
  633. );
  634. }
  635. }
  636. #endif
  637. break;
  638. case IOCTL_SMARTCARD_SWALLOW:
  639. if (SmartcardExtension->ReaderFunction[RDF_READER_SWALLOW] == NULL) {
  640. status = STATUS_NOT_SUPPORTED;
  641. break;
  642. }
  643. status = SmartcardExtension->ReaderFunction[RDF_READER_SWALLOW](
  644. SmartcardExtension
  645. );
  646. break;
  647. #if DEBUG
  648. case IOCTL_SMARTCARD_DEBUG:
  649. //
  650. // Toggle debug bit
  651. //
  652. CurrentDebugLevel =
  653. SmartcardGetDebugLevel();
  654. SmartcardSetDebugLevel(
  655. SmartcardExtension->MinorIoControlCode ^ CurrentDebugLevel
  656. );
  657. break;
  658. #endif
  659. default:
  660. //
  661. // check if the bit for a vendor ioctl is set and if the driver
  662. // has registered a callback function
  663. //
  664. if ((SmartcardExtension->MajorIoControlCode & CTL_CODE(0, 2048, 0, 0)) == 0 ||
  665. SmartcardExtension->ReaderFunction[RDF_IOCTL_VENDOR] == NULL) {
  666. status = STATUS_INVALID_DEVICE_REQUEST;
  667. } else {
  668. //
  669. // Call the driver if it has registered a callback for vendor calls
  670. //
  671. status = SmartcardExtension->ReaderFunction[RDF_IOCTL_VENDOR](
  672. SmartcardExtension
  673. );
  674. }
  675. break;
  676. } // end switch
  677. return status;
  678. }