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.

1315 lines
35 KiB

  1. #include "gemcore.h"
  2. #include "iopack.h"
  3. #pragma PAGEDCODE
  4. NTSTATUS CGemCore::read(CIoPacket* Irp)
  5. {
  6. NTSTATUS status;
  7. ULONG ReplyLength;
  8. ReplyLength = Irp->getReadLength();
  9. TRACE("GemCore read requested...\n");
  10. status = readAndWait((PUCHAR)Irp->getBuffer(),Irp->getReadLength(),(PUCHAR)Irp->getBuffer(),&ReplyLength);
  11. if(!NT_SUCCESS(status)) ReplyLength = 0;
  12. Irp->setInformation(ReplyLength);
  13. TRACE("GemCore read response:\n");
  14. //TRACE_BUFFER(Irp->getBuffer(),ReplyLength);
  15. return status;
  16. }
  17. #pragma PAGEDCODE
  18. NTSTATUS CGemCore::write(CIoPacket* Irp)
  19. {
  20. NTSTATUS status;
  21. ULONG ReplyLength;
  22. ReplyLength = Irp->getWriteLength();
  23. TRACE("GemCore write requested...\n");
  24. //TRACE_BUFFER(Irp->getBuffer(),Irp->getWriteLength());
  25. status = writeAndWait((PUCHAR)Irp->getBuffer(),Irp->getReadLength(),(PUCHAR)Irp->getBuffer(),&ReplyLength);
  26. if(!NT_SUCCESS(status)) ReplyLength = 0;
  27. Irp->setInformation(ReplyLength);
  28. TRACE("GemCore write response:\n");
  29. //TRACE_BUFFER(Irp->getBuffer(),ReplyLength);
  30. return status;
  31. }
  32. #pragma PAGEDCODE
  33. // Reader interface functions...
  34. NTSTATUS CGemCore::readAndWait(BYTE * pRequest,ULONG RequestLength,BYTE * pReply,ULONG* pReplyLength)
  35. {
  36. ULONG length;
  37. ULONG BufferLength;
  38. BOOL extendedCommand;
  39. ULONG replyLength;
  40. ULONG expectedReplyLength;
  41. ULONG replyBufferPosition = 0;
  42. if(!RequestLength || !pRequest || !pReply || !pReplyLength || RequestLength<5)
  43. return STATUS_INVALID_PARAMETER;
  44. length = pRequest[4];
  45. if (!length || (length > READER_DATA_BUFFER_SIZE - 3))
  46. {
  47. // If the length is lower or equal to 252 (255 - (<IFD Status> + <SW1> + <SW2>))
  48. // (standard OROS cmds)
  49. extendedCommand = TRUE;
  50. TRACE("******** EXTENDED COMMAND REQUESTED! ");
  51. TRACE_BUFFER(pRequest,RequestLength);
  52. if(!length) length = 256;
  53. expectedReplyLength = length;
  54. }
  55. else extendedCommand = FALSE;
  56. pOutputBuffer[0] = GEMCORE_CARD_READ;
  57. memory->copy(pOutputBuffer+1,pRequest,5);
  58. length = 6;
  59. BufferLength = InputBufferLength;
  60. NTSTATUS status = protocol->writeAndWait(pOutputBuffer,length,pInputBuffer,&BufferLength);
  61. if(!NT_SUCCESS(status) || !BufferLength)
  62. {
  63. *pReplyLength = 0;
  64. return status;
  65. }
  66. status = translateStatus(pInputBuffer[0],0);
  67. if(!NT_SUCCESS(status))
  68. {
  69. *pReplyLength = 0;
  70. return status;
  71. }
  72. // Extended command valid only if card reports 0 status!
  73. if(pInputBuffer[0]!=0)
  74. {
  75. extendedCommand = FALSE;
  76. }
  77. // ISV: If card finish Xfer, do not send send second part of the command!
  78. // This will fix CyberFlex card problem...
  79. if(extendedCommand && BufferLength==3)
  80. {
  81. TRACE("******** EXTENDED COMMAND CANCELLED BY CARD REPLY!\n");
  82. extendedCommand = FALSE;
  83. }
  84. // Skip status byte
  85. replyLength = BufferLength - 1;
  86. if(extendedCommand)
  87. {
  88. // Copy first part of the reply to the output buffer...
  89. // Skip status byte.
  90. if(*pReplyLength<(replyBufferPosition + replyLength))
  91. {
  92. *pReplyLength = 0;
  93. return STATUS_INVALID_BUFFER_SIZE;
  94. }
  95. memory->copy(pReply,pInputBuffer+1, replyLength);
  96. replyBufferPosition = replyLength;
  97. // Read second block of data...
  98. pOutputBuffer[0] = GEMCORE_CARD_READ;
  99. memory->copy(pOutputBuffer+1,"\xFF\xFF\xFF\xFF", 4);
  100. pOutputBuffer[5] = (BYTE ) (expectedReplyLength - replyLength);
  101. length = 6;
  102. BufferLength = InputBufferLength;
  103. status = protocol->writeAndWait(pOutputBuffer,length,pInputBuffer,&BufferLength);
  104. if(!NT_SUCCESS(status) || !BufferLength)
  105. {
  106. *pReplyLength = 0;
  107. return status;
  108. }
  109. status = translateStatus(pInputBuffer[0],0);
  110. if(!NT_SUCCESS(status))
  111. {
  112. *pReplyLength = 0;
  113. return status;
  114. }
  115. // Skip status byte.
  116. replyLength = BufferLength - 1;
  117. }
  118. if(*pReplyLength<(replyBufferPosition + replyLength))
  119. {
  120. TRACE("Gemcore: INVALID BUFFER LENGTH - buffer length %d, reply length %d\n",*pReplyLength,(replyBufferPosition + replyLength));
  121. *pReplyLength = 0;
  122. return STATUS_INVALID_BUFFER_SIZE;
  123. }
  124. // Skip status byte.
  125. if(replyLength) memory->copy(pReply+replyBufferPosition,pInputBuffer+1, replyLength);
  126. *pReplyLength = replyBufferPosition + replyLength;
  127. TRACE("GemCore readAndWait() response with Length %d \n",*pReplyLength);
  128. //TRACE_BUFFER(pReply,*pReplyLength);
  129. return status;
  130. }
  131. #pragma PAGEDCODE
  132. NTSTATUS CGemCore::writeAndWait(BYTE * pRequest,ULONG RequestLength,BYTE * pReply,ULONG* pReplyLength)
  133. {
  134. ULONG length;
  135. ULONG BufferLength;
  136. NTSTATUS status;
  137. TRACE("\nGEMCORE WRITE:\n");
  138. //TRACE_BUFFER(pRequest,RequestLength);
  139. if(!RequestLength || !pRequest || RequestLength<5)
  140. {
  141. TRACE("\nGEMCORE WRITE: INVALID IN PARAMETERS...\n");
  142. return STATUS_INVALID_PARAMETER;
  143. }
  144. length = pRequest[4];
  145. if(RequestLength<length+5)
  146. {
  147. TRACE("\nGEMCORE WRITE: INVALID REQUESTED LENGTH...\n");
  148. return STATUS_INVALID_PARAMETER;
  149. }
  150. if (length > READER_DATA_BUFFER_SIZE - 7)
  151. {
  152. // If the length is lower or equal than the extended available space (255)
  153. // Prepare and send the first part of the extended ISO In command:
  154. // The five command bytes are added in cmd buffer: 0xFF,0xFF,0xFF,0xFF,LN-248
  155. // Read second block of data...
  156. pOutputBuffer[0] = GEMCORE_CARD_WRITE;
  157. memory->copy(pOutputBuffer+1,"\xFF\xFF\xFF\xFF", 4);
  158. length = length - (READER_DATA_BUFFER_SIZE - 7);
  159. pOutputBuffer[5] = (BYTE )length;
  160. memory->copy(pOutputBuffer+6,pRequest + 5 + 248, length);
  161. // Add size of header...
  162. length += 6;
  163. BufferLength = InputBufferLength;
  164. status = protocol->writeAndWait(pOutputBuffer,length,pInputBuffer,&BufferLength);
  165. if(!NT_SUCCESS(status) || !BufferLength)
  166. {
  167. return status;
  168. }
  169. if(!NT_SUCCESS(status))
  170. {
  171. return status;
  172. }
  173. // NOW prepare and send the Second part of the extended ISO In command:
  174. // The five command bytes are added in cmd buffer.
  175. // The data field is added (248 bytes).
  176. // The command is sent to IFD.
  177. // Now set length to first block of data...
  178. length = 248;
  179. }
  180. pOutputBuffer[0] = GEMCORE_CARD_WRITE;
  181. memory->copy(pOutputBuffer+1,pRequest,4);
  182. pOutputBuffer[5] = pRequest[4]; // Warning you must specified full APDU length
  183. memory->copy(pOutputBuffer+6,pRequest+5, length);
  184. // Add size of header...
  185. length += 6;
  186. BufferLength = InputBufferLength;
  187. status = protocol->writeAndWait(pOutputBuffer,length,pInputBuffer,&BufferLength);
  188. if(!NT_SUCCESS(status) || !BufferLength)
  189. {
  190. *pReplyLength = 0;
  191. return status;
  192. }
  193. status = translateStatus(pInputBuffer[0],0);
  194. if(!NT_SUCCESS(status))
  195. {
  196. *pReplyLength = 0;
  197. return status;
  198. }
  199. // Skip status byte.
  200. length = BufferLength - 1;
  201. if(*pReplyLength<length)
  202. {
  203. *pReplyLength = 0;
  204. return STATUS_INVALID_BUFFER_SIZE;
  205. }
  206. // Skip status byte.
  207. if(length) memory->copy(pReply,pInputBuffer+1, length);
  208. *pReplyLength = length;
  209. TRACE("GemCore writeAndWait() response\n");
  210. //TRACE_BUFFER(pReply,*pReplyLength);
  211. return status;
  212. }
  213. #pragma PAGEDCODE
  214. ReaderConfig CGemCore::getConfiguration()
  215. {
  216. return configuration;
  217. }
  218. #pragma PAGEDCODE
  219. NTSTATUS CGemCore::setConfiguration(ReaderConfig configuration)
  220. {
  221. this->configuration = configuration;
  222. return STATUS_SUCCESS;
  223. }
  224. #pragma PAGEDCODE
  225. NTSTATUS CGemCore::ioctl(ULONG ControlCode,BYTE* pRequest,ULONG RequestLength,BYTE* pReply,ULONG* pReplyLength)
  226. {
  227. ULONG length;
  228. ULONG BufferLength;
  229. NTSTATUS status;
  230. TRACE("\nGEMCORE VendorIOCTL:\n");
  231. //TRACE_BUFFER(pRequest,RequestLength);
  232. if(!RequestLength || !pRequest)
  233. {
  234. TRACE("\nGEMCORE IOCTL: INVALID IN PARAMETERS...\n");
  235. *pReplyLength = 0;
  236. return STATUS_INVALID_PARAMETER;
  237. }
  238. memory->copy(pOutputBuffer,pRequest, RequestLength);
  239. // Send direct gemcore command
  240. BufferLength = InputBufferLength;
  241. status = protocol->writeAndWait(pOutputBuffer,RequestLength,pInputBuffer,&BufferLength);
  242. if(!NT_SUCCESS(status) || !BufferLength)
  243. {
  244. *pReplyLength = 0;
  245. return status;
  246. }
  247. // NOTE: DO NOT TRANSLATE REPLY, USER REQUIRED TO GET THIS INFORMATION
  248. // SO, keep status byte.
  249. length = BufferLength;
  250. if(*pReplyLength<length)
  251. {
  252. *pReplyLength = 0;
  253. return STATUS_BUFFER_TOO_SMALL;
  254. }
  255. // Skip status byte.
  256. if(length) memory->copy(pReply, pInputBuffer, length);
  257. *pReplyLength = length;
  258. TRACE("GemCore VendorIOCTL() response\n");
  259. //TRACE_BUFFER(pReply,*pReplyLength);
  260. return status;
  261. }
  262. #pragma PAGEDCODE
  263. NTSTATUS CGemCore::SwitchSpeed(ULONG ControlCode,BYTE* pRequest,ULONG RequestLength,BYTE* pReply,ULONG* pReplyLength)
  264. {
  265. ULONG length;
  266. ULONG BufferLength;
  267. NTSTATUS status;
  268. BYTE NewTA1;
  269. TRACE("\nGEMCORE SwitchSpeed:\n");
  270. //TRACE_BUFFER(pRequest,RequestLength);
  271. if(!RequestLength || !pRequest)
  272. {
  273. TRACE("\nGEMCORE SwitchSpeed: INVALID IN PARAMETERS...\n");
  274. *pReplyLength = 0;
  275. return STATUS_INVALID_PARAMETER;
  276. }
  277. NewTA1 = pRequest[0];
  278. // Modify speed value in reader's memory.
  279. length = 6;
  280. pOutputBuffer[0] = 0x23; // Write memory command
  281. pOutputBuffer[1] = 0x01; // The type of memory is iData.
  282. pOutputBuffer[2] = 0x00; // Address high byte.
  283. pOutputBuffer[3] = 0x89; // Address low byte.
  284. pOutputBuffer[4] = 0x01; // Number of byte to write
  285. // New speed.
  286. pOutputBuffer[5] = NewTA1;
  287. // Send direct gemcore command
  288. BufferLength = InputBufferLength;
  289. status = protocol->writeAndWait(pOutputBuffer,length,pInputBuffer,&BufferLength);
  290. if(!NT_SUCCESS(status) || !BufferLength)
  291. {
  292. *pReplyLength = 0;
  293. return status;
  294. }
  295. length = BufferLength;
  296. if(*pReplyLength<length)
  297. {
  298. *pReplyLength = 0;
  299. return STATUS_BUFFER_TOO_SMALL;
  300. }
  301. // Copy the full reply
  302. if(length) memory->copy(pReply, pInputBuffer, length);
  303. *pReplyLength = length;
  304. TRACE("GemCore SwitchSpeed() response\n");
  305. //TRACE_BUFFER(pReply,*pReplyLength);
  306. return status;
  307. }
  308. // TODO:
  309. // ??????????????????
  310. // It is specific to device not Gemcore
  311. // I would suggest to move it into the specific reader object!
  312. #pragma PAGEDCODE
  313. NTSTATUS CGemCore::VendorAttribute(ULONG ControlCode,BYTE* pRequest,ULONG RequestLength,BYTE* pReply,ULONG* pReplyLength)
  314. {
  315. NTSTATUS status;
  316. ULONG TagValue;
  317. TRACE("\nGEMCORE VendorAttibute:\n");
  318. //TRACE_BUFFER(pRequest,RequestLength);
  319. if(!RequestLength || !pRequest)
  320. {
  321. TRACE("\nGEMCORE VendorAttibute: INVALID IN PARAMETERS...\n");
  322. *pReplyLength = 0;
  323. return STATUS_INVALID_PARAMETER;
  324. }
  325. if (RequestLength < sizeof(TagValue))
  326. {
  327. *pReplyLength = 0;
  328. return STATUS_BUFFER_TOO_SMALL;
  329. }
  330. TagValue = (ULONG) *((PULONG)pRequest);
  331. switch(ControlCode)
  332. {
  333. // Get an attribute
  334. case IOCTL_SMARTCARD_VENDOR_GET_ATTRIBUTE:
  335. switch (TagValue)
  336. {
  337. // Power Timeout (SCARD_ATTR_SPEC_POWER_TIMEOUT)
  338. case SCARD_ATTR_SPEC_POWER_TIMEOUT:
  339. if (*pReplyLength < (ULONG) sizeof(configuration.PowerTimeOut))
  340. {
  341. *pReplyLength = 0;
  342. return STATUS_BUFFER_TOO_SMALL;
  343. }
  344. // Copy the value of PowerTimeout in the reply buffer
  345. memory->copy(
  346. pReply,
  347. &configuration.PowerTimeOut,
  348. sizeof(configuration.PowerTimeOut));
  349. *pReplyLength = (ULONG)sizeof(configuration.PowerTimeOut);
  350. status = STATUS_SUCCESS;
  351. break;
  352. case SCARD_ATTR_MANUFACTURER_NAME:
  353. if (*pReplyLength < ATTR_LENGTH)
  354. {
  355. *pReplyLength = 0;
  356. return STATUS_BUFFER_TOO_SMALL;
  357. }
  358. // Copy the value of PowerTimeout in the reply buffer
  359. memory->copy(
  360. pReply,
  361. ATTR_MANUFACTURER_NAME,
  362. sizeof(ATTR_MANUFACTURER_NAME));
  363. *pReplyLength = (ULONG)sizeof(ATTR_MANUFACTURER_NAME);
  364. status = STATUS_SUCCESS;
  365. break;
  366. case SCARD_ATTR_ORIGINAL_FILENAME:
  367. if (*pReplyLength < ATTR_LENGTH)
  368. {
  369. *pReplyLength = 0;
  370. return STATUS_BUFFER_TOO_SMALL;
  371. }
  372. // Copy the value of PowerTimeout in the reply buffer
  373. memory->copy(
  374. pReply,
  375. ATTR_ORIGINAL_FILENAME,
  376. sizeof(ATTR_ORIGINAL_FILENAME));
  377. *pReplyLength = (ULONG)sizeof(ATTR_ORIGINAL_FILENAME);
  378. status = STATUS_SUCCESS;
  379. break;
  380. // Unknown tag, we return STATUS_NOT_SUPPORTED
  381. default:
  382. *pReplyLength = 0;
  383. status = STATUS_NOT_SUPPORTED;
  384. }
  385. break;
  386. // Set the value of one tag (IOCTL_SMARTCARD_VENDOR_SET_ATTRIBUTE)
  387. case IOCTL_SMARTCARD_VENDOR_SET_ATTRIBUTE:
  388. switch (TagValue)
  389. {
  390. // Power Timeout (SCARD_ATTR_SPEC_POWER_TIMEOUT)
  391. case SCARD_ATTR_SPEC_POWER_TIMEOUT:
  392. if (RequestLength <(ULONG) (sizeof(configuration.PowerTimeOut) + sizeof(TagValue)))
  393. {
  394. *pReplyLength = 0;
  395. return STATUS_BUFFER_TOO_SMALL;
  396. }
  397. memory->copy(
  398. &configuration.PowerTimeOut,
  399. pRequest + sizeof(TagValue),
  400. sizeof(configuration.PowerTimeOut));
  401. *pReplyLength = 0;
  402. status = STATUS_SUCCESS;
  403. break;
  404. // Unknown tag, we return STATUS_NOT_SUPPORTED
  405. default:
  406. *pReplyLength = 0;
  407. status = STATUS_NOT_SUPPORTED;
  408. }
  409. break;
  410. default:
  411. *pReplyLength = 0;
  412. status = STATUS_NOT_SUPPORTED;
  413. break;
  414. }
  415. TRACE("GemCore VendorAttibute() response\n");
  416. //TRACE_BUFFER(pReply,*pReplyLength);
  417. return status;
  418. }
  419. #pragma PAGEDCODE
  420. NTSTATUS CGemCore::powerUp(BYTE* pReply,ULONG* pReplyLength)
  421. {
  422. BYTE CFG = 0,PCK;
  423. ULONG length,i;
  424. ULONG BufferLength;
  425. NTSTATUS status;
  426. switch(configuration.Voltage)
  427. {
  428. case CARD_VOLTAGE_3V: CFG = 0x02;break;
  429. case CARD_VOLTAGE_5V: CFG = 0x01;break;
  430. default: CFG = 0x00;break;
  431. }
  432. switch(configuration.PTSMode)
  433. {
  434. case PTS_MODE_DISABLED: CFG |= 0x10;break;
  435. case PTS_MODE_OPTIMAL: CFG |= 0x20;break;
  436. case PTS_MODE_MANUALLY: CFG |= 0x10;break;
  437. case PTS_MODE_DEFAULT: CFG = 0x00;break; // do not add cfg field
  438. default: CFG = 0x00;break; // same
  439. }
  440. length = 0;
  441. pOutputBuffer[length++] = GEMCORE_CARD_POWER_UP;
  442. // YN: if CFG = 0 that means we just need to do a power without CFG
  443. // This append in the case with a card in specific mode (presence of TA2)
  444. if(CFG) pOutputBuffer[length++] = CFG;
  445. BufferLength = InputBufferLength;
  446. protocol->set_WTR_Delay(protocol->get_Power_WTR_Delay());
  447. status = protocol->writeAndWait(pOutputBuffer,length,pInputBuffer,&BufferLength);
  448. protocol->set_Default_WTR_Delay();
  449. if (NT_SUCCESS(status))
  450. {
  451. if(BufferLength)
  452. {
  453. BufferLength--;
  454. TRACE("GemCore status %x\n",pInputBuffer[0]);
  455. status = translateStatus(pInputBuffer[0],GEMCORE_CARD_POWER);
  456. if(!NT_SUCCESS(status))
  457. {
  458. TRACE("GemCore FAILED TO POWER UP CARD! Status %x\n", status);
  459. *pReplyLength = 0;
  460. return status;
  461. }
  462. TRACE("GemCore power() ATR");
  463. TRACE_BUFFER(pInputBuffer+1,BufferLength);
  464. // Skip status byte and copy ATR
  465. if(pInputBuffer[1]==0x3B || pInputBuffer[1]==0x3F)
  466. {
  467. memory->copy(pReply,pInputBuffer+1,BufferLength);
  468. *pReplyLength = BufferLength;
  469. }
  470. else
  471. {
  472. *pReplyLength = 0;
  473. return STATUS_UNSUCCESSFUL;
  474. }
  475. //return status; //YN: do not return now
  476. }
  477. else
  478. {
  479. *pReplyLength = 0;
  480. return STATUS_UNSUCCESSFUL;
  481. }
  482. // YN: add PTS capabilities
  483. if (pInputBuffer[0] == 0x00)
  484. {
  485. if(configuration.PTSMode == PTS_MODE_MANUALLY)
  486. {
  487. length = 0;
  488. pOutputBuffer[length++] = GEMCORE_CARD_POWER_UP;
  489. CFG |= 0xF0; //Manual PPS and 3V or 5V module
  490. pOutputBuffer[length++] = CFG;
  491. pOutputBuffer[length++] = configuration.PTS0;
  492. if ((configuration.PTS0 & PTS_NEGOTIATE_PTS1) != 0) pOutputBuffer[length++] = configuration.PTS1;
  493. if ((configuration.PTS0 & PTS_NEGOTIATE_PTS2) != 0) pOutputBuffer[length++] = configuration.PTS2;
  494. if ((configuration.PTS0 & PTS_NEGOTIATE_PTS3) != 0) pOutputBuffer[length++] = configuration.PTS3;
  495. // computes the exclusive-oring of all characters from CFG to PTS3
  496. PCK = 0xFF;
  497. for (i=2; i<length; i++) { PCK ^= pOutputBuffer[i];}
  498. pOutputBuffer[length++] = PCK;
  499. BufferLength = InputBufferLength;
  500. protocol->set_WTR_Delay(protocol->get_Power_WTR_Delay());
  501. status = protocol->writeAndWait(pOutputBuffer,length,pInputBuffer,&BufferLength);
  502. protocol->set_Default_WTR_Delay();
  503. // Copy into buffer only when it fail.
  504. if (!NT_SUCCESS(status) || (BufferLength != 1) || (pInputBuffer[0] != 0x00))
  505. {
  506. *pReplyLength = BufferLength;
  507. if (BufferLength > 1)
  508. {
  509. memory->copy(pReply,pInputBuffer,BufferLength);
  510. }
  511. }
  512. return status;
  513. }
  514. }
  515. }
  516. else
  517. {
  518. *pReplyLength = 0;
  519. }
  520. return status;
  521. }
  522. #pragma PAGEDCODE
  523. NTSTATUS CGemCore::power(ULONG ControlCode,BYTE* pReply,ULONG* pReplyLength, BOOLEAN Specific)
  524. {
  525. ULONG length;
  526. ULONG BufferLength;
  527. ULONG PreviousState;
  528. NTSTATUS status;
  529. switch(ControlCode)
  530. {
  531. case SCARD_COLD_RESET:
  532. //ISV: First treat any card as ISO card on cold reset!
  533. // Defines the type of the card (ISOCARD) and set the card presence
  534. RestoreISOsetting();
  535. length = 2;
  536. BufferLength = InputBufferLength;
  537. pOutputBuffer[0] = GEMCORE_DEFINE_CARD_TYPE;
  538. pOutputBuffer[1] = (UCHAR)configuration.Type;
  539. status = protocol->writeAndWait(pOutputBuffer,length,pInputBuffer,&BufferLength);
  540. if(NT_SUCCESS(status))
  541. {
  542. if(BufferLength) status = translateStatus(pInputBuffer[0],GEMCORE_CARD_POWER);
  543. }
  544. if (!NT_SUCCESS(status))
  545. {
  546. return status;
  547. }
  548. if(Specific == FALSE)
  549. {
  550. //
  551. // Just define card default values
  552. //
  553. RestoreISOsetting();
  554. }
  555. PreviousState = protocol->getCardState();
  556. // Power down first for a cold reset
  557. // YN : verify power state of card first
  558. length = 0;
  559. pOutputBuffer[length++] = GEMCORE_CARD_POWER_DOWN;
  560. BufferLength = InputBufferLength;
  561. status = protocol->writeAndWait(pOutputBuffer,length,pInputBuffer,&BufferLength);
  562. if(NT_SUCCESS(status))
  563. {
  564. if(BufferLength) status = translateStatus(pInputBuffer[0],GEMCORE_CARD_POWER);
  565. }
  566. TRACE("GemCore powerDown() response\n");
  567. //TRACE_BUFFER(pInputBuffer,BufferLength);
  568. *pReplyLength = 0;
  569. if(status != STATUS_SUCCESS)
  570. {
  571. return status;
  572. }
  573. // YN this is PowerTimeout must be a
  574. if ((PreviousState & SCARD_POWERED) && (configuration.PowerTimeOut))
  575. {
  576. // Waits for the Power Timeout to be elapsed.
  577. // before doing reset.
  578. TRACE("GEMCORE power, ColdReset timeout %d ms\n", configuration.PowerTimeOut);
  579. DELAY(configuration.PowerTimeOut);
  580. }
  581. case SCARD_WARM_RESET:
  582. // If card have a Specific mode let Gemcore negociate properly with this card.
  583. if(Specific)
  584. {
  585. // keep configuration of the reader.
  586. configuration.PTSMode = PTS_MODE_DEFAULT;
  587. status = powerUp(pReply, pReplyLength);
  588. }
  589. else if(configuration.Type == TRANSPARENT_MODE_CARD)
  590. {
  591. // ISV: Command 12 will fail in transparant mode...
  592. // Let's set reader in ISO mode first!
  593. TRACE(" WARM RESET for Transparent mode requested...\n");
  594. RestoreISOsetting();
  595. length = 2;
  596. BufferLength = InputBufferLength;
  597. pOutputBuffer[0] = GEMCORE_DEFINE_CARD_TYPE;
  598. pOutputBuffer[1] = (UCHAR)configuration.Type;
  599. status = protocol->writeAndWait(pOutputBuffer,length,pInputBuffer,&BufferLength);
  600. if(NT_SUCCESS(status))
  601. {
  602. if(BufferLength) status = translateStatus(pInputBuffer[0],GEMCORE_CARD_POWER);
  603. }
  604. if (!NT_SUCCESS(status))
  605. {
  606. return status;
  607. }
  608. // do not lost transparent config on warm reset
  609. // keep configuration of the reader.
  610. status = powerUp(pReply, pReplyLength);
  611. }
  612. else
  613. {
  614. // Do a regular ISO reset
  615. status = powerUp(pReply, pReplyLength);
  616. }
  617. return status;
  618. break;
  619. case SCARD_POWER_DOWN:
  620. length = 0;
  621. pOutputBuffer[length++] = GEMCORE_CARD_POWER_DOWN;
  622. BufferLength = InputBufferLength;
  623. status = protocol->writeAndWait(pOutputBuffer,length,pInputBuffer,&BufferLength);
  624. if(NT_SUCCESS(status))
  625. {
  626. if(BufferLength) status = translateStatus(pInputBuffer[0],GEMCORE_CARD_POWER);
  627. }
  628. TRACE("GemCore powerDown() response\n");
  629. //TRACE_BUFFER(pInputBuffer,BufferLength);
  630. *pReplyLength = 0;
  631. return status;
  632. break;
  633. }
  634. *pReplyLength = 0;
  635. return STATUS_INVALID_DEVICE_REQUEST;
  636. }
  637. #pragma PAGEDCODE
  638. VOID CGemCore::cancel()
  639. {
  640. }
  641. #pragma PAGEDCODE
  642. NTSTATUS CGemCore::initialize()
  643. {
  644. TRACE("Initializing Gemcore interface...\n");
  645. TRACE("Setting Gemcore reader mode...\n");
  646. Initialized = TRUE;
  647. Mode = READER_MODE_NATIVE;
  648. NTSTATUS status = setReaderMode(READER_MODE_NATIVE);
  649. if(!NT_SUCCESS(status))
  650. {
  651. TRACE("Failed to set Gemcore reader mode %x\n",READER_MODE_NATIVE);
  652. return STATUS_INVALID_DEVICE_STATE;
  653. }
  654. TRACE("Getting Gemcore reader version...\n");
  655. ULONG VersionLength = VERSION_STRING_MAX_LENGTH;
  656. status = getReaderVersion(Version,&VersionLength);
  657. if(!NT_SUCCESS(status))
  658. {
  659. TRACE("Failed to get GemCore reader interface version...\n");
  660. return STATUS_INVALID_DEVICE_STATE;
  661. }
  662. else
  663. {
  664. Version[VersionLength] = 0x00;
  665. TRACE("****** GemCore version - %s ******\n",Version);
  666. }
  667. TRACE("Gemcore interface initialized...\n");
  668. return status;
  669. }
  670. #pragma PAGEDCODE
  671. ULONG CGemCore::getReaderState()
  672. {
  673. ULONG BufferLength;
  674. pOutputBuffer[0] = GEMCORE_GET_CARD_STATUS;
  675. BufferLength = InputBufferLength;
  676. NTSTATUS status = protocol->writeAndWait(pOutputBuffer,1,pInputBuffer,&BufferLength);
  677. TRACE("GemCore getReaderState() response\n");
  678. //TRACE_BUFFER(pInputBuffer,BufferLength);
  679. if(!NT_SUCCESS(status) || !BufferLength || (BufferLength<2))
  680. {
  681. TRACE("FAILED!\n");
  682. return SCARD_ABSENT;
  683. }
  684. if (!(pInputBuffer[1] & 0x04))
  685. {
  686. TRACE("*** Card is absent!\n");
  687. return SCARD_ABSENT;
  688. }
  689. else
  690. if (pInputBuffer[1] & 0x04)
  691. {
  692. TRACE("*** Card is present!\n");
  693. return SCARD_SWALLOWED;
  694. }
  695. else
  696. {
  697. TRACE("Card state is unknown!\n");
  698. return SCARD_ABSENT;
  699. }
  700. return SCARD_ABSENT;
  701. }
  702. #pragma PAGEDCODE
  703. NTSTATUS CGemCore::getReaderVersion(PUCHAR pVersion, PULONG pLength)
  704. {
  705. ULONG BufferLength;
  706. ULONG length;
  707. if(!pVersion || !pLength) return STATUS_INVALID_PARAMETER;
  708. length = sizeof(GEMCORE_GET_FIRMWARE_VERSION);
  709. // Remove last 0x00
  710. if(length) length--;
  711. memory->copy(pOutputBuffer,GEMCORE_GET_FIRMWARE_VERSION,length);
  712. BufferLength = InputBufferLength;
  713. TRACE("getReaderVersion() \n");
  714. //TRACE_BUFFER(pOutputBuffer,length);
  715. NTSTATUS status = protocol->writeAndWait(pOutputBuffer,length,pInputBuffer,&BufferLength);
  716. if(!NT_SUCCESS(status) || !BufferLength)
  717. {
  718. *pLength = 0;
  719. return STATUS_UNSUCCESSFUL;
  720. }
  721. if (pInputBuffer[0])
  722. {
  723. *pLength = 0;
  724. return translateStatus(pInputBuffer[0],0);
  725. }
  726. if(BufferLength-1 > *pLength)
  727. {
  728. BufferLength = *pLength;
  729. }
  730. // Remove status byte...
  731. BufferLength--;
  732. if(BufferLength) memory->copy(pVersion,pInputBuffer+1,BufferLength);
  733. *pLength = BufferLength;
  734. return STATUS_SUCCESS;
  735. }
  736. #pragma PAGEDCODE
  737. NTSTATUS CGemCore::setReaderMode(ULONG mode)
  738. {
  739. BYTE CFG_BYTE;
  740. ULONG BufferLength;
  741. switch(mode)
  742. {
  743. case READER_MODE_NATIVE: CFG_BYTE = 0x00; break;
  744. case READER_MODE_ROS: CFG_BYTE = 0x08; break;
  745. case READER_MODE_TLP: CFG_BYTE = 0x09; break;
  746. default: CFG_BYTE = 0x00; break;
  747. }
  748. pOutputBuffer[0] = GEMCORE_READER_SET_MODE;
  749. pOutputBuffer[1] = 0x00;
  750. pOutputBuffer[2] = CFG_BYTE;
  751. BufferLength = InputBufferLength;
  752. NTSTATUS status = protocol->writeAndWait(pOutputBuffer,3,pInputBuffer,&BufferLength);
  753. if(!NT_SUCCESS(status))
  754. {
  755. TRACE("Failed to set reader mode...\n");
  756. return status;
  757. }
  758. return status;
  759. };
  760. #pragma PAGEDCODE
  761. NTSTATUS CGemCore::translateStatus( const BYTE ReaderStatus, const ULONG IoctlType)
  762. {
  763. switch (ReaderStatus)
  764. {
  765. case 0x00 : return STATUS_SUCCESS;
  766. case 0x01 : return STATUS_NO_SUCH_DEVICE;
  767. case 0x02 : return STATUS_NO_SUCH_DEVICE;
  768. case 0x03 : return STATUS_INVALID_PARAMETER;
  769. case 0x04 : return STATUS_IO_TIMEOUT;
  770. case 0x05 : return STATUS_INVALID_PARAMETER;
  771. case 0x09 : return STATUS_INVALID_PARAMETER;
  772. case 0x10 : return STATUS_UNRECOGNIZED_MEDIA;
  773. case 0x11 : return STATUS_UNRECOGNIZED_MEDIA;
  774. case 0x12 : return STATUS_INVALID_PARAMETER;
  775. case 0x13 : return STATUS_CONNECTION_ABORTED;
  776. case 0x14 : return STATUS_UNRECOGNIZED_MEDIA;
  777. case 0x15 : return STATUS_UNRECOGNIZED_MEDIA;
  778. case 0x16 : return STATUS_INVALID_PARAMETER;
  779. case 0x17 : return STATUS_UNRECOGNIZED_MEDIA;
  780. case 0x18 : return STATUS_UNRECOGNIZED_MEDIA;
  781. case 0x19 : return STATUS_INVALID_PARAMETER;
  782. case 0x1A : return STATUS_INVALID_PARAMETER;
  783. case 0x1B : return STATUS_INVALID_PARAMETER;
  784. case 0x1C : return STATUS_INVALID_PARAMETER;
  785. case 0x1D : return STATUS_UNRECOGNIZED_MEDIA;
  786. case 0x1E : return STATUS_INVALID_PARAMETER;
  787. case 0x1F : return STATUS_INVALID_PARAMETER;
  788. case 0x20 : return STATUS_INVALID_PARAMETER;
  789. case 0x30 : return STATUS_IO_TIMEOUT;
  790. case 0xA0 : return STATUS_SUCCESS;
  791. case 0xA1 : return STATUS_UNRECOGNIZED_MEDIA;
  792. case 0xA2 :
  793. if(IoctlType == GEMCORE_CARD_POWER) return STATUS_UNRECOGNIZED_MEDIA;
  794. else return STATUS_IO_TIMEOUT;
  795. case 0xA3 : return STATUS_PARITY_ERROR;
  796. case 0xA4 : return STATUS_REQUEST_ABORTED;
  797. case 0xA5 : return STATUS_REQUEST_ABORTED;
  798. case 0xA6 : return STATUS_REQUEST_ABORTED;
  799. case 0xA7 : return STATUS_UNRECOGNIZED_MEDIA;
  800. case 0xCF : return STATUS_INVALID_PARAMETER;
  801. case 0xE4 : return STATUS_UNRECOGNIZED_MEDIA;
  802. case 0xE5 : return STATUS_SUCCESS;
  803. case 0xE7 : return STATUS_SUCCESS;
  804. case 0xF7 : return STATUS_NO_MEDIA;
  805. case 0xF8 : return STATUS_UNRECOGNIZED_MEDIA;
  806. case 0xFB : return STATUS_NO_MEDIA;
  807. default : return STATUS_INVALID_PARAMETER;
  808. }
  809. }
  810. #pragma PAGEDCODE
  811. VOID CGemCore::RestoreISOsetting(VOID)
  812. {
  813. configuration.Type = ISO_CARD;//ISO_CARD (02)
  814. configuration.PresenceDetection = DEFAULT_PRESENCE_DETECTION; // (0D)
  815. configuration.Voltage = CARD_DEFAULT_VOLTAGE; //CARD_DEFAULT_VOLTAGE;
  816. configuration.PTSMode = PTS_MODE_DISABLED; //PTS_MODE_DISABLED;
  817. configuration.PTS0 = 0;
  818. configuration.PTS1 = 0;
  819. configuration.PTS2 = 0;
  820. configuration.PTS3 = 0;
  821. configuration.Vpp = 0; //CARD_DEFAULT_VPP;
  822. configuration.ActiveProtocol = 0;// Undefined
  823. }
  824. #pragma PAGEDCODE
  825. NTSTATUS CGemCore::setTransparentConfig(
  826. PSCARD_CARD_CAPABILITIES cardCapabilities,
  827. BYTE NewWtx
  828. )
  829. /*++
  830. Routine Description:
  831. Set the parameters of the transparent mode.
  832. Arguments:
  833. PSCARD_CARD_CAPABILITIES CardCapabilities - structure for card
  834. NewWtx - holds the value (ms) of the new Wtx
  835. --*/
  836. {
  837. LONG etu;
  838. BYTE temp,mask,index;
  839. ULONG Length, BufferLength;
  840. NTSTATUS status;
  841. TRACE("\nGEMCORE T1 setTransparentConfig Enter\n");
  842. // Inverse or direct conversion
  843. if (cardCapabilities->InversConvention)
  844. configuration.transparent.CFG |= 0x20;
  845. else
  846. configuration.transparent.CFG &= 0xDF;
  847. // Transparent T=1 like (with 1 byte for the length).
  848. configuration.transparent.CFG |= 0x08;
  849. // ETU = ((F[Fi]/D[Di]) - 1) / 3
  850. etu = cardCapabilities->ClockRateConversion[
  851. (BYTE) configuration.transparent.Fi].F;
  852. if (cardCapabilities->BitRateAdjustment[
  853. (BYTE) configuration.transparent.Fi].DNumerator) {
  854. etu /= cardCapabilities->BitRateAdjustment[
  855. (BYTE) configuration.transparent.Di].DNumerator;
  856. }
  857. etu -= 1;
  858. etu /= 3;
  859. configuration.transparent.ETU = (BYTE) ( 0x000000FF & etu);
  860. if (cardCapabilities->N == 0xFF) {
  861. configuration.transparent.EGT = (BYTE) 0x00;
  862. } else {
  863. configuration.transparent.EGT = (BYTE) cardCapabilities->N;
  864. }
  865. configuration.transparent.CWT = (BYTE) cardCapabilities->T1.CWI;
  866. if (NewWtx) {
  867. for (mask = 0x80,index = 8; index !=0x00; index--) {
  868. temp = NewWtx & mask;
  869. if (temp == mask)
  870. break;
  871. mask = mask/2;
  872. }
  873. configuration.transparent.BWI = cardCapabilities->T1.BWI + index;
  874. } else {
  875. configuration.transparent.BWI = cardCapabilities->T1.BWI;
  876. }
  877. Length = 6;
  878. BufferLength = InputBufferLength;
  879. pOutputBuffer[0] = GEMCORE_CARD_POWER_UP;
  880. pOutputBuffer[1] = configuration.transparent.CFG;
  881. pOutputBuffer[2] = configuration.transparent.ETU;
  882. pOutputBuffer[3] = configuration.transparent.EGT;
  883. pOutputBuffer[4] = configuration.transparent.CWT;
  884. pOutputBuffer[5] = configuration.transparent.BWI;
  885. status = protocol->writeAndWait(pOutputBuffer,Length,pInputBuffer,&BufferLength);
  886. if(NT_SUCCESS(status))
  887. {
  888. if(BufferLength) status = translateStatus(pInputBuffer[0],GEMCORE_CARD_POWER);
  889. }
  890. TRACE("\nGEMCORE T1 setTransparentConfig Exit\n");
  891. return status;
  892. }
  893. #pragma PAGEDCODE
  894. NTSTATUS CGemCore::setProtocol(ULONG ProtocolRequested)
  895. {
  896. NTSTATUS status;
  897. UCHAR Buffer[256];
  898. ULONG BufferLength = 256;
  899. switch(ProtocolRequested)
  900. {
  901. case SCARD_PROTOCOL_T1:
  902. configuration.PTS0 = PTS_NEGOTIATE_T1 | PTS_NEGOTIATE_PTS1;
  903. configuration.ActiveProtocol = SCARD_PROTOCOL_T1;
  904. break;
  905. case SCARD_PROTOCOL_T0:
  906. configuration.PTS0 = PTS_NEGOTIATE_T0 | PTS_NEGOTIATE_PTS1;
  907. configuration.ActiveProtocol = SCARD_PROTOCOL_T0;
  908. default:
  909. break;
  910. }
  911. // PTS1 has to be set before at power up...
  912. //configuration.PTS1 = CardCapabilities->PtsData.Fl << 4 | CardCapabilities->PtsData.Dl;
  913. if(configuration.PTSMode == PTS_MODE_MANUALLY)
  914. {
  915. status = powerUp(Buffer,&BufferLength);
  916. }
  917. else {
  918. status = power(SCARD_COLD_RESET, Buffer, &BufferLength, FALSE);
  919. }
  920. if(NT_SUCCESS(status))
  921. {
  922. if(BufferLength) status = translateStatus(pInputBuffer[0],GEMCORE_CARD_POWER);
  923. }
  924. return status;
  925. }
  926. // TODO:
  927. // What the purpose of the function?
  928. // It's name does not tell anything...
  929. // Actually it was suggested for the different purposes.
  930. // Function has to be rewritten! It has a lot of mixed stuff like getting
  931. // card status for example.
  932. // ............................
  933. //
  934. // Use to made full T1 exchange in transparent mode
  935. //
  936. #pragma PAGEDCODE
  937. NTSTATUS CGemCore::translate_request(BYTE * pRequest,ULONG RequestLength,BYTE * pReply,ULONG* pReplyLength, PSCARD_CARD_CAPABILITIES cardCapabilities, BYTE NewWtx)
  938. {
  939. NTSTATUS status;
  940. UCHAR Cmd[256];
  941. ULONG CmdLength = 0;
  942. UCHAR Buffer[256];
  943. ULONG BufferLength;
  944. ULONG length;
  945. //
  946. // If the current card type <> TRANSPARENT_MODE_CARD
  947. //
  948. if (configuration.Type != TRANSPARENT_MODE_CARD)
  949. {
  950. // We read the status of the card to known the current voltage and the TA1
  951. BufferLength = 256;
  952. CmdLength = 1;
  953. Cmd[0] = GEMCORE_GET_CARD_STATUS;
  954. status = protocol->writeAndWait(Cmd,CmdLength,Buffer,&BufferLength);
  955. // verify return code of reader
  956. if(NT_SUCCESS(status))
  957. {
  958. if(BufferLength) status = translateStatus(Buffer[0],GEMCORE_CARD_POWER);
  959. }
  960. if (!NT_SUCCESS(status))
  961. {
  962. return status;
  963. }
  964. // Update Config
  965. configuration.transparent.CFG = Buffer[1] & 0x01; //Vcc
  966. configuration.transparent.Fi = Buffer[3] >>4; //Fi
  967. configuration.transparent.Di = 0x0F & Buffer[3]; //Di
  968. //We define the type of the card.
  969. BufferLength = 256;
  970. CmdLength = 2;
  971. // assign TRANSPARENT_MODE_CARD
  972. configuration.Type = TRANSPARENT_MODE_CARD;
  973. Cmd[0] = GEMCORE_DEFINE_CARD_TYPE;
  974. Cmd[1] = (BYTE) configuration.Type;
  975. status = protocol->writeAndWait(Cmd,CmdLength,Buffer,&BufferLength);
  976. if(NT_SUCCESS(status))
  977. {
  978. if(BufferLength) status = translateStatus(Buffer[0],GEMCORE_CARD_POWER);
  979. }
  980. if (!NT_SUCCESS(status))
  981. {
  982. return status;
  983. }
  984. // YN ? Mandatory!!! Else reader will be slow in T=1
  985. // Set the transparent configuration
  986. setTransparentConfig(cardCapabilities, NewWtx);
  987. NewWtx = 0; // to not repeat again this call
  988. }
  989. ///////
  990. if(NewWtx)
  991. {
  992. setTransparentConfig(cardCapabilities, NewWtx);
  993. }
  994. TRACE("\nGEMCORE T1 translate_request:\n");
  995. //TRACE_BUFFER(pRequest,RequestLength);
  996. if(!RequestLength || !pRequest ) return STATUS_INVALID_PARAMETER;
  997. length = RequestLength; // protocol
  998. if (RequestLength >= READER_DATA_BUFFER_SIZE )
  999. {
  1000. // If the length is upper than the standard available space (254)
  1001. // Then Send the last datas
  1002. // If the length is lower or equal than the extended available space (255)
  1003. // Prepare and send the first part of the extended ISO In command:
  1004. // The five command bytes are added in cmd buffer: 0xFF,0xFF,0xFF,0xFF,LN-248
  1005. // Read second block of data...
  1006. pOutputBuffer[0] = GEMCORE_CARD_WRITE; // specific for transparent exchange write long...
  1007. length = length - 254 + 1;
  1008. memory->copy(pOutputBuffer+1,pRequest + 254, length - 1);
  1009. // Add size of header...
  1010. length += 6;
  1011. BufferLength = InputBufferLength;
  1012. status = protocol->writeAndWait(pOutputBuffer,length,pInputBuffer,&BufferLength);
  1013. if(!NT_SUCCESS(status) || !BufferLength)
  1014. {
  1015. return status;
  1016. }
  1017. // prepare next paquet
  1018. length = 254;
  1019. }
  1020. pOutputBuffer[0] = GEMCORE_CARD_EXCHANGE;
  1021. memory->copy(pOutputBuffer +1 ,pRequest, length);
  1022. // Add size of header...
  1023. length += 1;
  1024. BufferLength = InputBufferLength;
  1025. status = protocol->writeAndWait(pOutputBuffer,length,pInputBuffer,&BufferLength);
  1026. if(!NT_SUCCESS(status) || !BufferLength)
  1027. {
  1028. *pReplyLength = 0;
  1029. return status;
  1030. }
  1031. // If the IFD signals more data to read...
  1032. // YN: 2 block for response...
  1033. if (BufferLength > 0 && pInputBuffer[0] == 0x1B)
  1034. {
  1035. ULONG BufferLength2 = 256;
  1036. UCHAR pInputBuffer2[256];
  1037. // Send a command to read the last data.
  1038. pOutputBuffer[0] = GEMCORE_CARD_READ; // specific for transparent exchange read long...
  1039. length = 1;
  1040. status = protocol->writeAndWait(pOutputBuffer,length,pInputBuffer2,&BufferLength2);
  1041. if(!NT_SUCCESS(status) || !BufferLength2)
  1042. {
  1043. *pReplyLength = 0;
  1044. return status;
  1045. }
  1046. if ((BufferLength + BufferLength2 - 2) > *pReplyLength)
  1047. {
  1048. *pReplyLength = 0;
  1049. return STATUS_INVALID_PARAMETER;
  1050. }
  1051. // Copy the last reader status
  1052. pInputBuffer[0] = pInputBuffer2[0];
  1053. status = translateStatus(pInputBuffer[0],0);
  1054. if(!NT_SUCCESS(status))
  1055. {
  1056. *pReplyLength = 0;
  1057. return status;
  1058. }
  1059. // Skip 2 status byte.
  1060. *pReplyLength = BufferLength + BufferLength2 - 2;
  1061. // Skip status byte.
  1062. if(*pReplyLength)
  1063. {
  1064. memory->copy(pReply,pInputBuffer+1, BufferLength -1);
  1065. memory->copy(pReply + (BufferLength-1), pInputBuffer2 +1, BufferLength2 -1);
  1066. }
  1067. TRACE("GemCore translate_request2 () response\n");
  1068. //TRACE_BUFFER(pReply,*pReplyLength);
  1069. return status;
  1070. }
  1071. status = translateStatus(pInputBuffer[0],0);
  1072. if(!NT_SUCCESS(status))
  1073. {
  1074. *pReplyLength = 0;
  1075. return status;
  1076. }
  1077. // Skip status byte.
  1078. length = BufferLength - 1;
  1079. if(*pReplyLength < length)
  1080. {
  1081. *pReplyLength = 0;
  1082. return STATUS_INVALID_BUFFER_SIZE;
  1083. }
  1084. // Skip status byte.
  1085. if(length)
  1086. {
  1087. memory->copy(pReply,pInputBuffer+1, length);
  1088. }
  1089. *pReplyLength = length;
  1090. TRACE("GemCore translate_request() response\n");
  1091. //TRACE_BUFFER(pReply,*pReplyLength);
  1092. return status;
  1093. };
  1094. // TODO:
  1095. // ???????????
  1096. #pragma PAGEDCODE
  1097. NTSTATUS CGemCore::translate_response(BYTE * pRequest,ULONG RequestLength,BYTE * pReply,ULONG* pReplyLength)
  1098. {
  1099. switch(configuration.ActiveProtocol)
  1100. {
  1101. case SCARD_PROTOCOL_T1:
  1102. break;
  1103. case SCARD_PROTOCOL_T0:
  1104. default:
  1105. break;
  1106. }
  1107. return STATUS_SUCCESS;
  1108. };