windows-nt/Source/XPSP1/NT/drivers/smartcrd/ifdtest/ifdscrpt.cpp
2020-09-26 16:20:57 +08:00

856 lines
19 KiB
C++

/*++
Copyright (C) Microsoft Corporation, 1996 - 1999
Module Name:
scdrvtst
Abstract:
IOCTL test program for smart card driver.
Author:
Klaus Schutz (kschutz) Dec-1996
Revision History:
--*/
#include <afx.h>
#include <afxtempl.h>
#include <winioctl.h>
#include <conio.h>
#include <winsmcrd.h>
#include "ifdtest.h"
class CCardList;
// This represents a single function of a card
class CCardFunction {
CString m_CName;
CHAR m_chShortCut;
CByteArray m_CData;
CCardFunction *m_pCNextFunction;
public:
CCardFunction(
CString &in_CName,
CHAR in_chShortCut,
CByteArray &in_CData
);
friend CCardList;
};
// This is a single card
class CCard {
CString m_CName;
CHAR m_chShortCut;
CCardFunction *m_pCFirstFunction;
CCard *m_pCNextCard;
public:
CCard(
CString & in_CCardName,
CHAR in_chShortCut
);
friend CCardList;
};
// This implements a list of cards
class CCardList {
CString m_CScriptFileName;
CCard *m_pCFirstCard;
CCard *m_pCCurrentCard;
ULONG m_uNumCards;
public:
CCardList(CString &in_CScriptFileName);
void
AddCard(
CString &in_CardName,
CHAR in_chShortCut
);
void
AddCardFunction(
CString &in_CFunctionName,
CHAR in_chShortCut,
CByteArray &l_pCData
);
void ShowCards(
void (__cdecl *in_pCallBack)(void *in_pContext, PCHAR in_pchCardName),
void *in_pContext
);
BOOL SelectCard(CHAR in_chShortCut);
void ReleaseCard(void);
CString GetCardName(void);
ULONG GetNumCards(void) {
return m_uNumCards;
}
BOOL IsCardSelected(void);
BOOL ListFunctions(void);
CByteArray *GetApdu(CHAR in_chShortCut);
};
CCardFunction::CCardFunction(
CString &in_CName,
CHAR in_chShortCut,
CByteArray &in_CData
)
/*++
Adds a function to the current card
--*/
{
m_CName = in_CName;
m_chShortCut = in_chShortCut;
m_CData.Copy(in_CData);
m_pCNextFunction = NULL;
}
CCard::CCard(
CString &in_CCardName,
CHAR in_chShortCut
)
/*++
Routine Description:
Constructor for a new card
Arguments:
CardName - Reference to card to add
in_uPos - index of shortcut key
Return Value:
--*/
{
m_CName = in_CCardName;
m_chShortCut = in_chShortCut;
m_pCNextCard = NULL;
m_pCFirstFunction = NULL;
}
void
CCardList::AddCard(
CString &in_CCardName,
CHAR in_chShortCut
)
/*++
Routine Description:
Adds a new card to CardList
Arguments:
in_CCardName - Reference to card to add
--*/
{
CCard *l_pCNewCard = new CCard(in_CCardName, in_chShortCut);
if (m_pCFirstCard == NULL) {
m_pCFirstCard = l_pCNewCard;
} else {
CCard *l_pCCurrent = m_pCFirstCard;
while (l_pCCurrent->m_pCNextCard) {
l_pCCurrent = l_pCCurrent->m_pCNextCard;
}
l_pCCurrent->m_pCNextCard = l_pCNewCard;
}
m_pCCurrentCard = l_pCNewCard;
m_uNumCards += 1;
}
void
CCardList::AddCardFunction(
CString &in_CFunctionName,
CHAR in_chShortCut,
CByteArray &in_pCData
)
/*++
Routine Description:
Adds a new function to the current card
Arguments:
in_CCardName - Reference to card to add
in_chShortCut - Shortcut key
Return Value:
--*/
{
CCardFunction *l_pCNewFunction = new CCardFunction(
in_CFunctionName,
in_chShortCut,
in_pCData
);
if (m_pCCurrentCard->m_pCFirstFunction == NULL) {
m_pCCurrentCard->m_pCFirstFunction = l_pCNewFunction;
} else {
CCardFunction *l_pCCurrent = m_pCCurrentCard->m_pCFirstFunction;
while (l_pCCurrent->m_pCNextFunction) {
l_pCCurrent = l_pCCurrent->m_pCNextFunction;
}
l_pCCurrent->m_pCNextFunction = l_pCNewFunction;
}
}
CCardList::CCardList(
CString &in_CScriptFileName
)
/*++
Routine Description:
Adds a new function to the current card
Arguments:
CardName - Reference to card to add
in_uPos - index of shortcut key
Return Value:
--*/
{
CStdioFile l_CScriptFile;
CHAR l_rgchBuffer[255], l_chKey;
ULONG l_uLineNumber = 0;
BOOL l_bContinue = FALSE;
CByteArray l_Data;
CString l_CCommand;
m_pCFirstCard = NULL;
m_pCCurrentCard = NULL;
if (l_CScriptFile.Open(in_CScriptFileName, CFile::modeRead) == NULL) {
printf("Script file cannot be opened: %s\n", in_CScriptFileName);
return;
}
m_CScriptFileName = in_CScriptFileName;
while (l_CScriptFile.ReadString(l_rgchBuffer, sizeof(l_rgchBuffer) - 1)) {
try {
CString l_CLine(l_rgchBuffer);
CString l_CCommandApdu;
l_uLineNumber += 1;
if (l_CLine.GetLength() != 0 && l_CLine[0] == '#') {
// comment line found, skip this line
continue;
}
// Get rid of leading and trailing spaces
l_CLine.TrimLeft();
l_CLine.TrimRight();
int l_ichStart = l_CLine.Find('[');
int l_ichKey = l_CLine.Find('&');
int l_ichEnd = l_CLine.Find(']');
if(l_ichStart == 0 && l_ichKey > 0 && l_ichEnd > l_ichKey + 1) {
//
// Add new card to list
//
CString l_CardName;
// Change card name from [&Card] to [C]ard
l_CardName =
l_CLine.Mid(l_ichStart + 1, l_ichKey - l_ichStart - 1) +
'[' +
l_CLine[l_ichKey + 1] +
']' +
l_CLine.Mid(l_ichKey + 2, l_ichEnd - l_ichKey - 2);
AddCard(
l_CardName,
l_CardName[l_ichKey]
);
} else if (l_ichStart == -1 && l_ichKey >= 0 && l_ichEnd == -1) {
//
// Add new function to current card
//
// Get function name
CString l_CToken = l_CLine.SpanExcluding(",");
// Search for shurtcut key
l_ichKey = l_CToken.Find('&');
if (l_ichKey == -1) {
throw "Missing '&' in function name";
}
l_chKey = l_CToken[l_ichKey + 1];
// Change card function from &Function to [F]unction
l_CCommand =
l_CToken.Mid(l_ichStart + 1, l_ichKey - l_ichStart - 1) +
'[' +
l_CToken[l_ichKey + 1] +
']' +
l_CToken.Right(l_CToken.GetLength() - l_ichKey - 2);
LONG l_lComma = l_CLine.Find(',');
if (l_lComma == -1) {
throw "Missing command APDU";
} else {
l_CCommandApdu = l_CLine.Right(l_CLine.GetLength() - l_lComma - 1);
}
} else if (l_bContinue) {
l_CCommandApdu = l_CLine;
} else if (l_CLine.GetLength() != 0 && l_CLine[0] != '#') {
throw "Line invalid";
}
if (l_CCommandApdu != "") {
do {
CHAR l_chData;
l_CCommandApdu.TrimLeft();
ULONG l_uLength = l_CCommandApdu.GetLength();
if (l_uLength >= 3 &&
l_CCommandApdu[0] == '\'' &&
l_CCommandApdu[2] == '\'') {
// add ascsii character like 'c'
l_chData = l_CCommandApdu[1];
l_Data.Add(l_chData);
} else if(l_uLength >= 3 &&
l_CCommandApdu[0] == '\"' &&
l_CCommandApdu.Right(l_uLength - 2).Find('\"') != -1) {
// add string like "string"
for (INT l_iIndex = 1; l_CCommandApdu[l_iIndex] != '\"'; l_iIndex++) {
l_Data.Add(l_CCommandApdu[l_iIndex]);
}
} else if (l_CCommandApdu.SpanIncluding("0123456789abcdefABCDEF").GetLength() == 2) {
sscanf(l_CCommandApdu, "%2x", &l_chData);
l_Data.Add(l_chData);
} else {
l_CCommandApdu = l_CCommandApdu.SpanExcluding(",");
static CString l_CError;
l_CError = "Illegal value found: " + l_CCommandApdu;
throw (PCHAR) (LPCSTR) l_CError;
}
l_ichStart = l_CCommandApdu.Find(',');
if (l_ichStart != -1) {
l_CCommandApdu = l_CLine.Right(l_CCommandApdu.GetLength() - l_ichStart - 1);
}
} while (l_ichStart != -1);
if (l_CLine.Find('\\') != -1) {
// we have to read more data from the file
l_bContinue = TRUE;
} else {
if (m_pCCurrentCard == NULL) {
throw "Card command found, but no card defined";
}
AddCardFunction(
l_CCommand,
l_chKey,
l_Data
);
l_CCommand = "";
l_Data.RemoveAll();
l_bContinue = FALSE;
}
}
}
catch (PCHAR in_pchError){
printf(
"%s (%d): %s\n",
in_CScriptFileName,
l_uLineNumber,
in_pchError
);
l_CCommand = "";
l_Data.RemoveAll();
l_bContinue = FALSE;
}
}
m_pCCurrentCard = NULL;
}
void
CCardList::ShowCards(
void (__cdecl *in_pCallBack)(void *in_pContext, PCHAR in_pchCardName),
void *in_pContext
)
{
CCard *l_pCCurrentCard = m_pCFirstCard;
if (l_pCCurrentCard == NULL) {
return;
}
while(l_pCCurrentCard) {
(*in_pCallBack) (in_pContext, (PCHAR) (LPCSTR) l_pCCurrentCard->m_CName);
l_pCCurrentCard = l_pCCurrentCard->m_pCNextCard;
}
}
BOOL
CCardList::ListFunctions(
void
)
/*++
List all card functions
--*/
{
if (m_pCCurrentCard == NULL)
return FALSE;
CCardFunction *l_pCCurrentFunction = m_pCCurrentCard->m_pCFirstFunction;
while(l_pCCurrentFunction) {
printf(" %s\n", (LPCSTR) l_pCCurrentFunction->m_CName);
l_pCCurrentFunction = l_pCCurrentFunction->m_pCNextFunction;
}
return TRUE;
}
BOOL
CCardList::SelectCard(
CHAR in_chShortCut
)
/*++
Routine Description:
Selectd a card by shorcut
Arguments:
chShortCut - Shortcut key
Return Value:
TRUE - card found and selected
FALSE - no card with that shortcut found
--*/
{
m_pCCurrentCard = m_pCFirstCard;
while(m_pCCurrentCard) {
if (m_pCCurrentCard->m_chShortCut == in_chShortCut) {
return TRUE;
}
m_pCCurrentCard = m_pCCurrentCard->m_pCNextCard;
}
m_pCCurrentCard = NULL;
return FALSE;
}
void CCardList::ReleaseCard(
void
)
{
m_pCCurrentCard = NULL;
}
BOOL
CCardList::IsCardSelected(
void
)
{
return (m_pCCurrentCard != NULL);
}
CString
CCardList::GetCardName(
void
)
{
CString l_CCardName;
INT l_iLeft = m_pCCurrentCard->m_CName.Find('[');
INT l_iLength = m_pCCurrentCard->m_CName.GetLength();
l_CCardName =
m_pCCurrentCard->m_CName.Left(l_iLeft) +
m_pCCurrentCard->m_CName[l_iLeft + 1] +
m_pCCurrentCard->m_CName.Right(l_iLength - l_iLeft - 3);
return l_CCardName;
}
CByteArray *
CCardList::GetApdu(
CHAR in_chShortCut
)
{
CCardFunction *l_pCCurrentFunction = m_pCCurrentCard->m_pCFirstFunction;
while(l_pCCurrentFunction) {
if (l_pCCurrentFunction->m_chShortCut == in_chShortCut) {
return &l_pCCurrentFunction->m_CData;
}
l_pCCurrentFunction = l_pCCurrentFunction->m_pCNextFunction;
}
return NULL;
}
void
ManualTest(
CReader &in_CReader
)
{
CCardList l_CCardList(CString("ifdtest.dat"));
ULONG l_uRepeat = 0;
LONG l_lResult;
CHAR l_chSelection;
PUCHAR l_pbResult;
ULONG l_uState, l_uPrevState;
CString l_CAnswer;
CString l_CCardStates[] = { "Unknown", "Absent", "Present" , "Swallowed", "Powered", "Negotiable", "Specific" };
BOOL l_bWaitForInsertion, l_bWaitForRemoval;
while (TRUE) {
ULONG l_uResultLength = 0;
printf("Manual reader test\n");
printf("------------------\n");
if (l_CCardList.IsCardSelected()) {
printf("%s Commands:\n", l_CCardList.GetCardName());
l_CCardList.ListFunctions();
printf("Other Commands:\n");
printf(" [r]epeat command\n");
printf(" E[x]it\n");
} else {
printf("Reader Commands:\n");
printf(" Protocol: T=[0], T=[1]\n");
printf(" Power : [c]oldReset, Power[d]own, Warm[r]eset\n");
printf(" Card : [p]resent, [a]bsent, [s]tatus\n");
printf(" PwrMngnt: [h]ibernation\n");
printf(" Test : [v]endor IOCTL\n");
if (l_CCardList.GetNumCards() != 0) {
printf("Card Commands:\n");
l_CCardList.ShowCards((void (__cdecl *)(void *,char *)) printf, " %s\n");
}
printf("Other Commands:\n");
printf(" E[x]it\n");
}
printf(
"\n[%s|%s|%ld] - Command: ",
in_CReader.GetVendorName(),
in_CReader.GetIfdType(),
in_CReader.GetDeviceUnit()
);
l_chSelection = (CHAR) _getche();
putchar('\n');
if (l_CCardList.IsCardSelected()) {
switch (l_chSelection) {
case 'x':
l_CCardList.ReleaseCard();
continue;
case 'r':
printf("Enter repeat count: ");
scanf("%2d", &l_uRepeat);
if (l_uRepeat > 99) {
l_uRepeat = 0;
}
printf("Enter command: ");
l_chSelection = (CHAR) _getche();
// no bbreak;
default:
CByteArray *l_pCData;
if((l_pCData = l_CCardList.GetApdu(l_chSelection)) != NULL) {
l_lResult = in_CReader.Transmit(
l_pCData->GetData(),
(ULONG) l_pCData->GetSize(),
&l_pbResult,
&l_uResultLength
);
} else {
printf("Invalid Selection");
continue;
}
break;
}
} else {
switch(l_chSelection){
case '0':
printf("Changing to T=0");
l_lResult = in_CReader.SetProtocol(SCARD_PROTOCOL_T0);
break;
case '1':
printf("Changing to T=1");
l_lResult = in_CReader.SetProtocol(SCARD_PROTOCOL_T1);
break;
case 'c':
printf("Cold reset");
l_lResult = in_CReader.ColdResetCard();
in_CReader.GetAtr(&l_pbResult, &l_uResultLength);
break;
case 'r':
printf("Warm reset");
l_lResult = in_CReader.WarmResetCard();
in_CReader.GetAtr(&l_pbResult, &l_uResultLength);
break;
case 'd':
printf("Power down");
l_lResult = in_CReader.PowerDownCard();
break;
case 'h':
printf("Hibernation test...(1 min)\nHibernate machine now!");
l_uPrevState = SCARD_UNKNOWN;
l_bWaitForInsertion = FALSE;
l_bWaitForRemoval = FALSE;
for (l_uRepeat = 0; l_uRepeat < 60; l_uRepeat++) {
l_lResult = in_CReader.GetState(&l_uState);
l_lResult = in_CReader.FinishWaitForCard(FALSE);
if (l_uPrevState != SCARD_UNKNOWN &&
l_lResult == ERROR_SUCCESS) {
printf("\n Card %s", l_bWaitForInsertion ? "inserted" : "removed");
l_uPrevState = SCARD_UNKNOWN;
l_bWaitForInsertion = FALSE;
l_bWaitForRemoval = FALSE;
}
if (l_uState == SCARD_ABSENT) {
if (l_bWaitForInsertion == FALSE) {
l_lResult = in_CReader.StartWaitForCardInsertion();
l_bWaitForInsertion = TRUE;
l_bWaitForRemoval = FALSE;
}
} else {
if (l_bWaitForRemoval == FALSE) {
l_lResult = in_CReader.StartWaitForCardRemoval();
l_bWaitForRemoval = TRUE;
l_bWaitForInsertion = FALSE;
}
}
if (l_uState != l_uPrevState) {
printf("\n %s", l_CCardStates[l_uState]);
}
if (l_uState >= SCARD_PRESENT && l_uState < SCARD_NEGOTIABLE) {
l_lResult = in_CReader.ColdResetCard();
}
if (l_uState == SCARD_NEGOTIABLE) {
l_lResult = in_CReader.SetProtocol(
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1
);
}
printf(".");
l_uPrevState = l_uState;
LONG l_uGoal = clock() + CLOCKS_PER_SEC;
while(l_uGoal > clock())
;
}
printf("\nPlease %s card", l_uState >= SCARD_PRESENT ? "remove" : "insert");
in_CReader.FinishWaitForCard(TRUE);
printf("\n");
continue;
break;
case 's':
printf("Get state");
l_lResult = in_CReader.GetState(&l_uState);
printf("Get state 1");
l_pbResult = (PBYTE) &l_uState;
l_uResultLength = sizeof(ULONG);
break;
case 'a':
printf("Waiting for removal...");
l_lResult = in_CReader.WaitForCardRemoval();
break;
case 'p':
printf("Waiting for insertion...");
l_lResult = in_CReader.WaitForCardInsertion();
break;
case 'v':
printf("Test Vendor IOCTL...");
l_lResult = in_CReader.VendorIoctl(l_CAnswer);
l_pbResult = (PUCHAR) ((LPCSTR) l_CAnswer);
l_uResultLength = l_CAnswer.GetLength();
break;
case 'x':
exit(0);
default:
// Try to select a card
if (l_CCardList.SelectCard(l_chSelection) == FALSE) {
printf("Invalid selection\n");
}
l_uRepeat = 0;
continue;
}
}
printf(
"\nReturn value: %lxh (NTSTATUS %lxh)\n",
l_lResult,
MapWinErrorToNtStatus(l_lResult)
);
if (l_lResult == ERROR_SUCCESS && l_uResultLength) {
ULONG l_uIndex, l_uLine, l_uCol;
// The I/O request has data returned
printf("Data returned (%ld bytes):\n %04x: ", l_uResultLength, 0);
for (l_uLine = 0, l_uIndex = 0;
l_uLine < ((l_uResultLength - 1) / 8) + 1;
l_uLine++) {
for (l_uCol = 0, l_uIndex = l_uLine * 8;
l_uCol < 8; l_uCol++,
l_uIndex++) {
printf(
l_uIndex < l_uResultLength ? "%02x " : " ",
l_pbResult[l_uIndex]
);
}
putchar(' ');
for (l_uCol = 0, l_uIndex = l_uLine * 8;
l_uCol < 8; l_uCol++,
l_uIndex++) {
printf(
l_uIndex < l_uResultLength ? "%c" : " ",
isprint(l_pbResult[l_uIndex]) ? l_pbResult[l_uIndex] : '.'
);
}
putchar('\n');
if (l_uIndex < l_uResultLength) {
printf(" %04x: ", l_uIndex + 1);
}
}
}
putchar('\n');
}
}