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.

855 lines
19 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. scdrvtst
  5. Abstract:
  6. IOCTL test program for smart card driver.
  7. Author:
  8. Klaus Schutz (kschutz) Dec-1996
  9. Revision History:
  10. --*/
  11. #include <afx.h>
  12. #include <afxtempl.h>
  13. #include <winioctl.h>
  14. #include <conio.h>
  15. #include <winsmcrd.h>
  16. #include "ifdtest.h"
  17. class CCardList;
  18. // This represents a single function of a card
  19. class CCardFunction {
  20. CString m_CName;
  21. CHAR m_chShortCut;
  22. CByteArray m_CData;
  23. CCardFunction *m_pCNextFunction;
  24. public:
  25. CCardFunction(
  26. CString &in_CName,
  27. CHAR in_chShortCut,
  28. CByteArray &in_CData
  29. );
  30. friend CCardList;
  31. };
  32. // This is a single card
  33. class CCard {
  34. CString m_CName;
  35. CHAR m_chShortCut;
  36. CCardFunction *m_pCFirstFunction;
  37. CCard *m_pCNextCard;
  38. public:
  39. CCard(
  40. CString & in_CCardName,
  41. CHAR in_chShortCut
  42. );
  43. friend CCardList;
  44. };
  45. // This implements a list of cards
  46. class CCardList {
  47. CString m_CScriptFileName;
  48. CCard *m_pCFirstCard;
  49. CCard *m_pCCurrentCard;
  50. ULONG m_uNumCards;
  51. public:
  52. CCardList(CString &in_CScriptFileName);
  53. void
  54. AddCard(
  55. CString &in_CardName,
  56. CHAR in_chShortCut
  57. );
  58. void
  59. AddCardFunction(
  60. CString &in_CFunctionName,
  61. CHAR in_chShortCut,
  62. CByteArray &l_pCData
  63. );
  64. void ShowCards(
  65. void (__cdecl *in_pCallBack)(void *in_pContext, PCHAR in_pchCardName),
  66. void *in_pContext
  67. );
  68. BOOL SelectCard(CHAR in_chShortCut);
  69. void ReleaseCard(void);
  70. CString GetCardName(void);
  71. ULONG GetNumCards(void) {
  72. return m_uNumCards;
  73. }
  74. BOOL IsCardSelected(void);
  75. BOOL ListFunctions(void);
  76. CByteArray *GetApdu(CHAR in_chShortCut);
  77. };
  78. CCardFunction::CCardFunction(
  79. CString &in_CName,
  80. CHAR in_chShortCut,
  81. CByteArray &in_CData
  82. )
  83. /*++
  84. Adds a function to the current card
  85. --*/
  86. {
  87. m_CName = in_CName;
  88. m_chShortCut = in_chShortCut;
  89. m_CData.Copy(in_CData);
  90. m_pCNextFunction = NULL;
  91. }
  92. CCard::CCard(
  93. CString &in_CCardName,
  94. CHAR in_chShortCut
  95. )
  96. /*++
  97. Routine Description:
  98. Constructor for a new card
  99. Arguments:
  100. CardName - Reference to card to add
  101. in_uPos - index of shortcut key
  102. Return Value:
  103. --*/
  104. {
  105. m_CName = in_CCardName;
  106. m_chShortCut = in_chShortCut;
  107. m_pCNextCard = NULL;
  108. m_pCFirstFunction = NULL;
  109. }
  110. void
  111. CCardList::AddCard(
  112. CString &in_CCardName,
  113. CHAR in_chShortCut
  114. )
  115. /*++
  116. Routine Description:
  117. Adds a new card to CardList
  118. Arguments:
  119. in_CCardName - Reference to card to add
  120. --*/
  121. {
  122. CCard *l_pCNewCard = new CCard(in_CCardName, in_chShortCut);
  123. if (m_pCFirstCard == NULL) {
  124. m_pCFirstCard = l_pCNewCard;
  125. } else {
  126. CCard *l_pCCurrent = m_pCFirstCard;
  127. while (l_pCCurrent->m_pCNextCard) {
  128. l_pCCurrent = l_pCCurrent->m_pCNextCard;
  129. }
  130. l_pCCurrent->m_pCNextCard = l_pCNewCard;
  131. }
  132. m_pCCurrentCard = l_pCNewCard;
  133. m_uNumCards += 1;
  134. }
  135. void
  136. CCardList::AddCardFunction(
  137. CString &in_CFunctionName,
  138. CHAR in_chShortCut,
  139. CByteArray &in_pCData
  140. )
  141. /*++
  142. Routine Description:
  143. Adds a new function to the current card
  144. Arguments:
  145. in_CCardName - Reference to card to add
  146. in_chShortCut - Shortcut key
  147. Return Value:
  148. --*/
  149. {
  150. CCardFunction *l_pCNewFunction = new CCardFunction(
  151. in_CFunctionName,
  152. in_chShortCut,
  153. in_pCData
  154. );
  155. if (m_pCCurrentCard->m_pCFirstFunction == NULL) {
  156. m_pCCurrentCard->m_pCFirstFunction = l_pCNewFunction;
  157. } else {
  158. CCardFunction *l_pCCurrent = m_pCCurrentCard->m_pCFirstFunction;
  159. while (l_pCCurrent->m_pCNextFunction) {
  160. l_pCCurrent = l_pCCurrent->m_pCNextFunction;
  161. }
  162. l_pCCurrent->m_pCNextFunction = l_pCNewFunction;
  163. }
  164. }
  165. CCardList::CCardList(
  166. CString &in_CScriptFileName
  167. )
  168. /*++
  169. Routine Description:
  170. Adds a new function to the current card
  171. Arguments:
  172. CardName - Reference to card to add
  173. in_uPos - index of shortcut key
  174. Return Value:
  175. --*/
  176. {
  177. CStdioFile l_CScriptFile;
  178. CHAR l_rgchBuffer[255], l_chKey;
  179. ULONG l_uLineNumber = 0;
  180. BOOL l_bContinue = FALSE;
  181. CByteArray l_Data;
  182. CString l_CCommand;
  183. m_pCFirstCard = NULL;
  184. m_pCCurrentCard = NULL;
  185. if (l_CScriptFile.Open(in_CScriptFileName, CFile::modeRead) == NULL) {
  186. printf("Script file cannot be opened: %s\n", in_CScriptFileName);
  187. return;
  188. }
  189. m_CScriptFileName = in_CScriptFileName;
  190. while (l_CScriptFile.ReadString(l_rgchBuffer, sizeof(l_rgchBuffer) - 1)) {
  191. try {
  192. CString l_CLine(l_rgchBuffer);
  193. CString l_CCommandApdu;
  194. l_uLineNumber += 1;
  195. if (l_CLine.GetLength() != 0 && l_CLine[0] == '#') {
  196. // comment line found, skip this line
  197. continue;
  198. }
  199. // Get rid of leading and trailing spaces
  200. l_CLine.TrimLeft();
  201. l_CLine.TrimRight();
  202. int l_ichStart = l_CLine.Find('[');
  203. int l_ichKey = l_CLine.Find('&');
  204. int l_ichEnd = l_CLine.Find(']');
  205. if(l_ichStart == 0 && l_ichKey > 0 && l_ichEnd > l_ichKey + 1) {
  206. //
  207. // Add new card to list
  208. //
  209. CString l_CardName;
  210. // Change card name from [&Card] to [C]ard
  211. l_CardName =
  212. l_CLine.Mid(l_ichStart + 1, l_ichKey - l_ichStart - 1) +
  213. '[' +
  214. l_CLine[l_ichKey + 1] +
  215. ']' +
  216. l_CLine.Mid(l_ichKey + 2, l_ichEnd - l_ichKey - 2);
  217. AddCard(
  218. l_CardName,
  219. l_CardName[l_ichKey]
  220. );
  221. } else if (l_ichStart == -1 && l_ichKey >= 0 && l_ichEnd == -1) {
  222. //
  223. // Add new function to current card
  224. //
  225. // Get function name
  226. CString l_CToken = l_CLine.SpanExcluding(",");
  227. // Search for shurtcut key
  228. l_ichKey = l_CToken.Find('&');
  229. if (l_ichKey == -1) {
  230. throw "Missing '&' in function name";
  231. }
  232. l_chKey = l_CToken[l_ichKey + 1];
  233. // Change card function from &Function to [F]unction
  234. l_CCommand =
  235. l_CToken.Mid(l_ichStart + 1, l_ichKey - l_ichStart - 1) +
  236. '[' +
  237. l_CToken[l_ichKey + 1] +
  238. ']' +
  239. l_CToken.Right(l_CToken.GetLength() - l_ichKey - 2);
  240. LONG l_lComma = l_CLine.Find(',');
  241. if (l_lComma == -1) {
  242. throw "Missing command APDU";
  243. } else {
  244. l_CCommandApdu = l_CLine.Right(l_CLine.GetLength() - l_lComma - 1);
  245. }
  246. } else if (l_bContinue) {
  247. l_CCommandApdu = l_CLine;
  248. } else if (l_CLine.GetLength() != 0 && l_CLine[0] != '#') {
  249. throw "Line invalid";
  250. }
  251. if (l_CCommandApdu != "") {
  252. do {
  253. CHAR l_chData;
  254. l_CCommandApdu.TrimLeft();
  255. ULONG l_uLength = l_CCommandApdu.GetLength();
  256. if (l_uLength >= 3 &&
  257. l_CCommandApdu[0] == '\'' &&
  258. l_CCommandApdu[2] == '\'') {
  259. // add ascsii character like 'c'
  260. l_chData = l_CCommandApdu[1];
  261. l_Data.Add(l_chData);
  262. } else if(l_uLength >= 3 &&
  263. l_CCommandApdu[0] == '\"' &&
  264. l_CCommandApdu.Right(l_uLength - 2).Find('\"') != -1) {
  265. // add string like "string"
  266. for (INT l_iIndex = 1; l_CCommandApdu[l_iIndex] != '\"'; l_iIndex++) {
  267. l_Data.Add(l_CCommandApdu[l_iIndex]);
  268. }
  269. } else if (l_CCommandApdu.SpanIncluding("0123456789abcdefABCDEF").GetLength() == 2) {
  270. sscanf(l_CCommandApdu, "%2x", &l_chData);
  271. l_Data.Add(l_chData);
  272. } else {
  273. l_CCommandApdu = l_CCommandApdu.SpanExcluding(",");
  274. static CString l_CError;
  275. l_CError = "Illegal value found: " + l_CCommandApdu;
  276. throw (PCHAR) (LPCSTR) l_CError;
  277. }
  278. l_ichStart = l_CCommandApdu.Find(',');
  279. if (l_ichStart != -1) {
  280. l_CCommandApdu = l_CLine.Right(l_CCommandApdu.GetLength() - l_ichStart - 1);
  281. }
  282. } while (l_ichStart != -1);
  283. if (l_CLine.Find('\\') != -1) {
  284. // we have to read more data from the file
  285. l_bContinue = TRUE;
  286. } else {
  287. if (m_pCCurrentCard == NULL) {
  288. throw "Card command found, but no card defined";
  289. }
  290. AddCardFunction(
  291. l_CCommand,
  292. l_chKey,
  293. l_Data
  294. );
  295. l_CCommand = "";
  296. l_Data.RemoveAll();
  297. l_bContinue = FALSE;
  298. }
  299. }
  300. }
  301. catch (PCHAR in_pchError){
  302. printf(
  303. "%s (%d): %s\n",
  304. in_CScriptFileName,
  305. l_uLineNumber,
  306. in_pchError
  307. );
  308. l_CCommand = "";
  309. l_Data.RemoveAll();
  310. l_bContinue = FALSE;
  311. }
  312. }
  313. m_pCCurrentCard = NULL;
  314. }
  315. void
  316. CCardList::ShowCards(
  317. void (__cdecl *in_pCallBack)(void *in_pContext, PCHAR in_pchCardName),
  318. void *in_pContext
  319. )
  320. {
  321. CCard *l_pCCurrentCard = m_pCFirstCard;
  322. if (l_pCCurrentCard == NULL) {
  323. return;
  324. }
  325. while(l_pCCurrentCard) {
  326. (*in_pCallBack) (in_pContext, (PCHAR) (LPCSTR) l_pCCurrentCard->m_CName);
  327. l_pCCurrentCard = l_pCCurrentCard->m_pCNextCard;
  328. }
  329. }
  330. BOOL
  331. CCardList::ListFunctions(
  332. void
  333. )
  334. /*++
  335. List all card functions
  336. --*/
  337. {
  338. if (m_pCCurrentCard == NULL)
  339. return FALSE;
  340. CCardFunction *l_pCCurrentFunction = m_pCCurrentCard->m_pCFirstFunction;
  341. while(l_pCCurrentFunction) {
  342. printf(" %s\n", (LPCSTR) l_pCCurrentFunction->m_CName);
  343. l_pCCurrentFunction = l_pCCurrentFunction->m_pCNextFunction;
  344. }
  345. return TRUE;
  346. }
  347. BOOL
  348. CCardList::SelectCard(
  349. CHAR in_chShortCut
  350. )
  351. /*++
  352. Routine Description:
  353. Selectd a card by shorcut
  354. Arguments:
  355. chShortCut - Shortcut key
  356. Return Value:
  357. TRUE - card found and selected
  358. FALSE - no card with that shortcut found
  359. --*/
  360. {
  361. m_pCCurrentCard = m_pCFirstCard;
  362. while(m_pCCurrentCard) {
  363. if (m_pCCurrentCard->m_chShortCut == in_chShortCut) {
  364. return TRUE;
  365. }
  366. m_pCCurrentCard = m_pCCurrentCard->m_pCNextCard;
  367. }
  368. m_pCCurrentCard = NULL;
  369. return FALSE;
  370. }
  371. void CCardList::ReleaseCard(
  372. void
  373. )
  374. {
  375. m_pCCurrentCard = NULL;
  376. }
  377. BOOL
  378. CCardList::IsCardSelected(
  379. void
  380. )
  381. {
  382. return (m_pCCurrentCard != NULL);
  383. }
  384. CString
  385. CCardList::GetCardName(
  386. void
  387. )
  388. {
  389. CString l_CCardName;
  390. INT l_iLeft = m_pCCurrentCard->m_CName.Find('[');
  391. INT l_iLength = m_pCCurrentCard->m_CName.GetLength();
  392. l_CCardName =
  393. m_pCCurrentCard->m_CName.Left(l_iLeft) +
  394. m_pCCurrentCard->m_CName[l_iLeft + 1] +
  395. m_pCCurrentCard->m_CName.Right(l_iLength - l_iLeft - 3);
  396. return l_CCardName;
  397. }
  398. CByteArray *
  399. CCardList::GetApdu(
  400. CHAR in_chShortCut
  401. )
  402. {
  403. CCardFunction *l_pCCurrentFunction = m_pCCurrentCard->m_pCFirstFunction;
  404. while(l_pCCurrentFunction) {
  405. if (l_pCCurrentFunction->m_chShortCut == in_chShortCut) {
  406. return &l_pCCurrentFunction->m_CData;
  407. }
  408. l_pCCurrentFunction = l_pCCurrentFunction->m_pCNextFunction;
  409. }
  410. return NULL;
  411. }
  412. void
  413. ManualTest(
  414. CReader &in_CReader
  415. )
  416. {
  417. CCardList l_CCardList(CString("ifdtest.dat"));
  418. ULONG l_uRepeat = 0;
  419. LONG l_lResult;
  420. CHAR l_chSelection;
  421. PUCHAR l_pbResult;
  422. ULONG l_uState, l_uPrevState;
  423. CString l_CAnswer;
  424. CString l_CCardStates[] = { "Unknown", "Absent", "Present" , "Swallowed", "Powered", "Negotiable", "Specific" };
  425. BOOL l_bWaitForInsertion, l_bWaitForRemoval;
  426. while (TRUE) {
  427. ULONG l_uResultLength = 0;
  428. printf("Manual reader test\n");
  429. printf("------------------\n");
  430. if (l_CCardList.IsCardSelected()) {
  431. printf("%s Commands:\n", l_CCardList.GetCardName());
  432. l_CCardList.ListFunctions();
  433. printf("Other Commands:\n");
  434. printf(" [r]epeat command\n");
  435. printf(" E[x]it\n");
  436. } else {
  437. printf("Reader Commands:\n");
  438. printf(" Protocol: T=[0], T=[1]\n");
  439. printf(" Power : [c]oldReset, Power[d]own, Warm[r]eset\n");
  440. printf(" Card : [p]resent, [a]bsent, [s]tatus\n");
  441. printf(" PwrMngnt: [h]ibernation\n");
  442. printf(" Test : [v]endor IOCTL\n");
  443. if (l_CCardList.GetNumCards() != 0) {
  444. printf("Card Commands:\n");
  445. l_CCardList.ShowCards((void (__cdecl *)(void *,char *)) printf, " %s\n");
  446. }
  447. printf("Other Commands:\n");
  448. printf(" E[x]it\n");
  449. }
  450. printf(
  451. "\n[%s|%s|%ld] - Command: ",
  452. in_CReader.GetVendorName(),
  453. in_CReader.GetIfdType(),
  454. in_CReader.GetDeviceUnit()
  455. );
  456. l_chSelection = (CHAR) _getche();
  457. putchar('\n');
  458. if (l_CCardList.IsCardSelected()) {
  459. switch (l_chSelection) {
  460. case 'x':
  461. l_CCardList.ReleaseCard();
  462. continue;
  463. case 'r':
  464. printf("Enter repeat count: ");
  465. scanf("%2d", &l_uRepeat);
  466. if (l_uRepeat > 99) {
  467. l_uRepeat = 0;
  468. }
  469. printf("Enter command: ");
  470. l_chSelection = (CHAR) _getche();
  471. // no bbreak;
  472. default:
  473. CByteArray *l_pCData;
  474. if((l_pCData = l_CCardList.GetApdu(l_chSelection)) != NULL) {
  475. l_lResult = in_CReader.Transmit(
  476. l_pCData->GetData(),
  477. (ULONG) l_pCData->GetSize(),
  478. &l_pbResult,
  479. &l_uResultLength
  480. );
  481. } else {
  482. printf("Invalid Selection");
  483. continue;
  484. }
  485. break;
  486. }
  487. } else {
  488. switch(l_chSelection){
  489. case '0':
  490. printf("Changing to T=0");
  491. l_lResult = in_CReader.SetProtocol(SCARD_PROTOCOL_T0);
  492. break;
  493. case '1':
  494. printf("Changing to T=1");
  495. l_lResult = in_CReader.SetProtocol(SCARD_PROTOCOL_T1);
  496. break;
  497. case 'c':
  498. printf("Cold reset");
  499. l_lResult = in_CReader.ColdResetCard();
  500. in_CReader.GetAtr(&l_pbResult, &l_uResultLength);
  501. break;
  502. case 'r':
  503. printf("Warm reset");
  504. l_lResult = in_CReader.WarmResetCard();
  505. in_CReader.GetAtr(&l_pbResult, &l_uResultLength);
  506. break;
  507. case 'd':
  508. printf("Power down");
  509. l_lResult = in_CReader.PowerDownCard();
  510. break;
  511. case 'h':
  512. printf("Hibernation test...(1 min)\nHibernate machine now!");
  513. l_uPrevState = SCARD_UNKNOWN;
  514. l_bWaitForInsertion = FALSE;
  515. l_bWaitForRemoval = FALSE;
  516. for (l_uRepeat = 0; l_uRepeat < 60; l_uRepeat++) {
  517. l_lResult = in_CReader.GetState(&l_uState);
  518. l_lResult = in_CReader.FinishWaitForCard(FALSE);
  519. if (l_uPrevState != SCARD_UNKNOWN &&
  520. l_lResult == ERROR_SUCCESS) {
  521. printf("\n Card %s", l_bWaitForInsertion ? "inserted" : "removed");
  522. l_uPrevState = SCARD_UNKNOWN;
  523. l_bWaitForInsertion = FALSE;
  524. l_bWaitForRemoval = FALSE;
  525. }
  526. if (l_uState == SCARD_ABSENT) {
  527. if (l_bWaitForInsertion == FALSE) {
  528. l_lResult = in_CReader.StartWaitForCardInsertion();
  529. l_bWaitForInsertion = TRUE;
  530. l_bWaitForRemoval = FALSE;
  531. }
  532. } else {
  533. if (l_bWaitForRemoval == FALSE) {
  534. l_lResult = in_CReader.StartWaitForCardRemoval();
  535. l_bWaitForRemoval = TRUE;
  536. l_bWaitForInsertion = FALSE;
  537. }
  538. }
  539. if (l_uState != l_uPrevState) {
  540. printf("\n %s", l_CCardStates[l_uState]);
  541. }
  542. if (l_uState >= SCARD_PRESENT && l_uState < SCARD_NEGOTIABLE) {
  543. l_lResult = in_CReader.ColdResetCard();
  544. }
  545. if (l_uState == SCARD_NEGOTIABLE) {
  546. l_lResult = in_CReader.SetProtocol(
  547. SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1
  548. );
  549. }
  550. printf(".");
  551. l_uPrevState = l_uState;
  552. LONG l_uGoal = clock() + CLOCKS_PER_SEC;
  553. while(l_uGoal > clock())
  554. ;
  555. }
  556. printf("\nPlease %s card", l_uState >= SCARD_PRESENT ? "remove" : "insert");
  557. in_CReader.FinishWaitForCard(TRUE);
  558. printf("\n");
  559. continue;
  560. break;
  561. case 's':
  562. printf("Get state");
  563. l_lResult = in_CReader.GetState(&l_uState);
  564. printf("Get state 1");
  565. l_pbResult = (PBYTE) &l_uState;
  566. l_uResultLength = sizeof(ULONG);
  567. break;
  568. case 'a':
  569. printf("Waiting for removal...");
  570. l_lResult = in_CReader.WaitForCardRemoval();
  571. break;
  572. case 'p':
  573. printf("Waiting for insertion...");
  574. l_lResult = in_CReader.WaitForCardInsertion();
  575. break;
  576. case 'v':
  577. printf("Test Vendor IOCTL...");
  578. l_lResult = in_CReader.VendorIoctl(l_CAnswer);
  579. l_pbResult = (PUCHAR) ((LPCSTR) l_CAnswer);
  580. l_uResultLength = l_CAnswer.GetLength();
  581. break;
  582. case 'x':
  583. exit(0);
  584. default:
  585. // Try to select a card
  586. if (l_CCardList.SelectCard(l_chSelection) == FALSE) {
  587. printf("Invalid selection\n");
  588. }
  589. l_uRepeat = 0;
  590. continue;
  591. }
  592. }
  593. printf(
  594. "\nReturn value: %lxh (NTSTATUS %lxh)\n",
  595. l_lResult,
  596. MapWinErrorToNtStatus(l_lResult)
  597. );
  598. if (l_lResult == ERROR_SUCCESS && l_uResultLength) {
  599. ULONG l_uIndex, l_uLine, l_uCol;
  600. // The I/O request has data returned
  601. printf("Data returned (%ld bytes):\n %04x: ", l_uResultLength, 0);
  602. for (l_uLine = 0, l_uIndex = 0;
  603. l_uLine < ((l_uResultLength - 1) / 8) + 1;
  604. l_uLine++) {
  605. for (l_uCol = 0, l_uIndex = l_uLine * 8;
  606. l_uCol < 8; l_uCol++,
  607. l_uIndex++) {
  608. printf(
  609. l_uIndex < l_uResultLength ? "%02x " : " ",
  610. l_pbResult[l_uIndex]
  611. );
  612. }
  613. putchar(' ');
  614. for (l_uCol = 0, l_uIndex = l_uLine * 8;
  615. l_uCol < 8; l_uCol++,
  616. l_uIndex++) {
  617. printf(
  618. l_uIndex < l_uResultLength ? "%c" : " ",
  619. isprint(l_pbResult[l_uIndex]) ? l_pbResult[l_uIndex] : '.'
  620. );
  621. }
  622. putchar('\n');
  623. if (l_uIndex < l_uResultLength) {
  624. printf(" %04x: ", l_uIndex + 1);
  625. }
  626. }
  627. }
  628. putchar('\n');
  629. }
  630. }