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

2101 lines
53 KiB
C++

#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <afx.h>
#include <afxtempl.h>
#include <winioctl.h>
#include <winsmcrd.h>
#include "ifdtest.h"
class CCardProvider *CCardProvider::s_pFirst;
#define INSERT_CARD "Please insert smart card"
#define REMOVE_CARD "Please remove smart card"
PCHAR
CAtr::GetAtrString(
PCHAR in_pchBuffer
)
{
for (ULONG i = 0; i < m_uAtrLength; i++) {
sprintf(in_pchBuffer + i * 3, "%02X ", m_rgbAtr[i]);
}
return in_pchBuffer;
}
CCardProvider::CCardProvider(
void
)
{
m_pNext = NULL;
m_uTestNo = 0;
m_bCardTested = FALSE;
m_bTestFailed = FALSE;
m_pSetProtocol = NULL;
m_pCardTest = NULL;
}
CCardProvider::CCardProvider(
void (*in_pEntryFunction)(class CCardProvider&)
)
/*++
Routine Description:
Constructor for class CCardProvider.
This constructor is called for every card that is to be tested.
It creates a new instance and appends it to a singly linked list
Arguments:
Pointer to function that registers all test functions
--*/
{
class CCardProvider *l_pCardProvider;
*this = CCardProvider();
if (s_pFirst == NULL) {
s_pFirst = new CCardProvider;
l_pCardProvider = s_pFirst;
} else {
l_pCardProvider = s_pFirst;
while (l_pCardProvider->m_pNext) {
l_pCardProvider = l_pCardProvider->m_pNext;
}
l_pCardProvider->m_pNext = new CCardProvider;
l_pCardProvider = l_pCardProvider->m_pNext;
}
(*in_pEntryFunction)(*l_pCardProvider);
}
BOOL
CCardProvider::CardsUntested(
void
)
{
class CCardProvider *l_pCCardProvider = s_pFirst;
while (l_pCCardProvider) {
if (l_pCCardProvider->m_bCardTested == FALSE) {
return TRUE;
}
l_pCCardProvider = l_pCCardProvider->m_pNext;
}
return FALSE;
}
void
CCardProvider::CardTest(
class CReader& io_pCReader,
ULONG in_uTestNo
)
/*++
Routine Description:
Calls every registered card provider in the list until one of
the providers indicates that it recognized the card
Arguments:
io_pCReader - reference to the test structure
Return Value:
IFDSTATUS value
--*/
{
class CCardProvider *l_pCCardProvider = s_pFirst;
ULONG l_uStatus;
while (l_pCCardProvider) {
if ( l_pCCardProvider->IsValidAtr(io_pCReader.GetAtr()) ) {
if (l_pCCardProvider->m_bCardTested) {
// We tested this card already
LogMessage("Card has been tested already. Please remove the card");
return;
}
l_pCCardProvider->m_bCardTested = TRUE;
LogMessage(
"\nTesting card %s",
(LPCSTR) l_pCCardProvider->m_CCardName
);
if (l_pCCardProvider->m_pSetProtocol == NULL) {
return;
}
// Call card provider function
l_uStatus = (*l_pCCardProvider->m_pSetProtocol)(
*l_pCCardProvider,
io_pCReader
);
if (l_uStatus == IFDSTATUS_END) {
return;
}
if (l_uStatus != IFDSTATUS_SUCCESS) {
return;
}
// Check if the card test function pointer exists
if (l_pCCardProvider->m_pCardTest == NULL) {
return;
}
if (in_uTestNo) {
// user wants to run only a single test
l_pCCardProvider->m_uTestNo = in_uTestNo;
LogMessage("Test No. %2d", l_pCCardProvider->m_uTestNo);
// Call card provider function
l_uStatus = (*l_pCCardProvider->m_pCardTest)(
*l_pCCardProvider,
io_pCReader
);
return;
}
// run the whole test set
for (l_pCCardProvider->m_uTestNo = 1; ;l_pCCardProvider->m_uTestNo++) {
LogMessage("Test No. %2d", l_pCCardProvider->m_uTestNo);
// Call card provider function
l_uStatus = (*l_pCCardProvider->m_pCardTest)(
*l_pCCardProvider,
io_pCReader
);
if (l_uStatus != IFDSTATUS_SUCCESS) {
return;
}
}
}
l_pCCardProvider = l_pCCardProvider->m_pNext;
}
PCHAR l_rgbAtrBuffer = new CHAR[256];
LogMessage("Card unknown!");
LogMessage(" CURRENT CARD");
LogMessage(" %s", io_pCReader.GetAtrString(l_rgbAtrBuffer));
for (l_pCCardProvider = s_pFirst;
l_pCCardProvider;
l_pCCardProvider = l_pCCardProvider->m_pNext) {
if (l_pCCardProvider->m_bCardTested == FALSE) {
LogMessage(" * %s", (LPCSTR) l_pCCardProvider->m_CCardName);
for (int i = 0; i < MAX_NUM_ATR && l_pCCardProvider->m_CAtr[i].GetLength(); i++) {
LogMessage(" %s", l_pCCardProvider->m_CAtr[i].GetAtrString(l_rgbAtrBuffer));
}
}
}
delete l_rgbAtrBuffer;
LogMessage("Please remove card");
}
void
CCardProvider::ListUntestedCards(
void
)
/*++
Routine Description:
Prints a list of all cards that have not been tested
--*/
{
class CCardProvider *l_pCCardProvider = s_pFirst;
while (l_pCCardProvider) {
if (l_pCCardProvider->m_bCardTested == FALSE) {
LogMessage(" * %s", (LPCSTR) l_pCCardProvider->m_CCardName);
}
l_pCCardProvider = l_pCCardProvider->m_pNext;
}
}
void
CCardProvider::SetAtr(
BYTE in_rgbAtr[],
ULONG in_uAtrLength
)
/*++
Routine Description:
Sets the ATR of the card
Arguments:
in_rgchAtr - the atr string
in_uAtrLength - length of the atr
--*/
{
for (int i = 0; i < MAX_NUM_ATR; i++) {
if (m_CAtr[i].GetLength() == 0) {
m_CAtr[i] = CAtr(in_rgbAtr, in_uAtrLength);
return;
}
}
}
void
CCardProvider::SetCardName(
CHAR in_rgchCardName[]
)
/*++
Routine Description:
Sets a friendly name for the card
Arguments:
in_rgchCardName - Friendly name for the card
--*/
{
m_CCardName = in_rgchCardName;
}
void
CheckCardMonitor(
CReader &in_CReader
)
{
ULONG l_lResult, l_uReplyLength, l_lTestNo = 1;
time_t l_lStartTime;
BOOL l_bResult;
OVERLAPPED l_Ovr;
HANDLE l_hReader = in_CReader.GetHandle();
l_Ovr.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ResetEvent(l_Ovr.hEvent);
LogMessage("=============================");
LogMessage("Part A: Checking card monitor");
LogMessage("=============================");
LogMessage(" << %s", REMOVE_CARD);
in_CReader.WaitForCardRemoval();
TestStart("%2d. %s", l_lTestNo++, INSERT_CARD);
l_lResult = in_CReader.WaitForCardInsertion();
TEST_CHECK_SUCCESS("Reader failed card insertion monitor", l_lResult);
TestEnd();
TestStart("%2d. IOCTL_SMARTCARD_IS_PRESENT", l_lTestNo++);
l_bResult = DeviceIoControl (
l_hReader,
IOCTL_SMARTCARD_IS_PRESENT,
NULL,
0,
NULL,
0,
&l_uReplyLength,
&l_Ovr
);
TestCheck(
l_bResult == TRUE,
"DeviceIoControl should return TRUE with card inserted"
);
TestEnd();
TestStart("%2d. %s", l_lTestNo++, REMOVE_CARD);
l_lResult = in_CReader.WaitForCardRemoval();
TEST_CHECK_SUCCESS("Reader failed card removal monitor", l_lResult);
TestEnd();
TestStart("%2d. IOCTL_SMARTCARD_IS_ABSENT", l_lTestNo++);
l_bResult = DeviceIoControl (
l_hReader,
IOCTL_SMARTCARD_IS_ABSENT,
NULL,
0,
NULL,
0,
&l_uReplyLength,
&l_Ovr
);
TestCheck(
l_bResult == TRUE,
"DeviceIoControl should return TRUE with card removed"
);
TestEnd();
TestStart("%2d. Insert and remove a smart card repeatedly", l_lTestNo++);
for (l_lStartTime = time(NULL); time(NULL) - l_lStartTime < 15;) {
l_lResult = in_CReader.ColdResetCard();
#ifdef insert_remove_alternate
l_bResult = DeviceIoControl (
l_hReader,
IOCTL_SMARTCARD_IS_PRESENT,
NULL,
0,
NULL,
0,
&l_uReplyLength,
&l_Ovr
);
SetLastError(0);
l_bResult = GetOverlappedResult(
l_hReader,
&l_Ovr,
&l_uReplyLength,
FALSE
);
l_lResult = GetLastError();
TestCheck(
l_bResult == TRUE && l_lResult == ERROR_SUCCESS ||
l_bResult == FALSE &&
(l_lResult == ERROR_IO_INCOMPLETE ||
l_lResult == ERROR_BUSY ||
l_lResult == ERROR_IO_PENDING),
"Reader failed card insertion monitor.\nReturned %2lxH",
l_lResult
);
l_bResult = DeviceIoControl (
l_hReader,
IOCTL_SMARTCARD_IS_ABSENT,
NULL,
0,
NULL,
0,
&l_uReplyLength,
&l_Ovr
);
SetLastError(0);
l_bResult = GetOverlappedResult(
l_hReader,
&l_Ovr,
&l_uReplyLength,
FALSE
);
l_lResult = GetLastError();
TestCheck(
l_bResult == TRUE && l_lResult == ERROR_SUCCESS ||
l_bResult == FALSE &&
(l_lResult == ERROR_IO_INCOMPLETE ||
l_lResult == ERROR_BUSY ||
l_lResult == ERROR_IO_PENDING),
"Reader failed card removal monitor:\nReturned %2lxH",
l_lResult
);
#endif
}
#ifdef insert_remove_alternate
l_bResult = GetOverlappedResult(
l_hReader,
&l_Ovr,
&l_uReplyLength,
TRUE
);
#endif
TestEnd();
LogMessage("Press any key to continue");
_getch();
if (ReaderFailed()) {
exit(-1);
}
}
void
CheckReader(
CReader &in_CReader
)
/*++
Routine Description:
Checks the attributes of a reader.
Once with card inserted and then without
Arguments:
Return Value:
--*/
{
BOOL l_bResult;
ULONG l_iIndex, l_uReplyLength, l_lTestNo = 1, l_uStart, l_uEnd;
OVERLAPPED l_Ovr;
UCHAR l_rgbReplyBuffer[512];
HANDLE l_hReader = in_CReader.GetHandle();
l_Ovr.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ResetEvent(l_Ovr.hEvent);
#define ATTR(x) #x, x
struct {
PCHAR m_pchName;
ULONG m_uType;
} l_aAttr[] = {
ATTR(SCARD_ATTR_VENDOR_NAME),
ATTR(SCARD_ATTR_VENDOR_IFD_TYPE),
ATTR(SCARD_ATTR_DEVICE_UNIT),
ATTR(SCARD_ATTR_ATR_STRING),
ATTR(SCARD_ATTR_DEFAULT_CLK),
ATTR(SCARD_ATTR_MAX_CLK),
ATTR(SCARD_ATTR_DEFAULT_DATA_RATE),
ATTR(SCARD_ATTR_MAX_DATA_RATE),
ATTR(SCARD_ATTR_MAX_IFSD),
ATTR(SCARD_ATTR_CURRENT_PROTOCOL_TYPE),
ATTR(SCARD_ATTR_PROTOCOL_TYPES),
0, 0,
ATTR(SCARD_ATTR_ATR_STRING),
ATTR(SCARD_ATTR_CURRENT_PROTOCOL_TYPE)
};
LogMessage("=======================");
LogMessage("Part B: Checking reader");
LogMessage("=======================");
BOOL l_bCardInserted = FALSE;
LogMessage(" << %s", REMOVE_CARD);
in_CReader.WaitForCardRemoval();
TestStart("%2d. Device name", l_lTestNo++);
CString l_COperatingSystem = GetOperatingSystem();
if (l_COperatingSystem == OS_WINNT4) {
TestCheck(
in_CReader.GetDeviceName().Left(12) == "\\\\.\\SCReader",
"Device name is not NT 4.0 compliant"
);
} else if (l_COperatingSystem == OS_WIN95 ||
l_COperatingSystem == OS_WIN98) {
// there is no special naming convention for Win9x
} else {
TestCheck(
in_CReader.GetDeviceName().Find("{50dd5230-ba8a-11d1-bf5d-0000f805f530}") != -1,
"Device name is not WDM PnP compliant"
);
}
TestEnd();
TestStart(
"%2d. Null pointer check",
l_lTestNo++
);
for (l_iIndex = 0; l_aAttr[l_iIndex].m_pchName; l_iIndex++) {
// try to crash reader by using null pointers as arguments
l_bResult = DeviceIoControl (
l_hReader,
IOCTL_SMARTCARD_GET_ATTRIBUTE,
&l_aAttr[l_iIndex].m_uType,
sizeof(ULONG),
NULL,
1000,
&l_uReplyLength,
&l_Ovr
);
ULONG l_lResult = GetLastError();
TestCheck(
l_lResult == ERROR_INSUFFICIENT_BUFFER ||
l_lResult == ERROR_BAD_COMMAND,
"IOCTL_SMARTCARD_GET_ATTRIBUTE (%lxh) should fail\nReturned %2lxH (NTSTATUS %lxH)\nExpected %2lxH (NTSTATUS %lxH)\nor %2lxH (NTSTATUS %lxH)",
l_aAttr[l_iIndex].m_uType & 0xFFFF,
l_lResult,
MapWinErrorToNtStatus(l_lResult),
ERROR_INSUFFICIENT_BUFFER,
MapWinErrorToNtStatus(ERROR_BAD_COMMAND),
ERROR_BAD_COMMAND,
MapWinErrorToNtStatus(ERROR_BAD_COMMAND)
);
}
TestEnd();
for (l_iIndex = 0; l_iIndex < sizeof(l_aAttr) / sizeof(l_aAttr[0]); l_iIndex++) {
if (l_aAttr[l_iIndex].m_pchName == 0) {
TestStart("%2d. Close driver with I/O-request still pending", l_lTestNo++);
// Check if the reader correctly terminates pending io-requests
l_bResult = DeviceIoControl (
l_hReader,
IOCTL_SMARTCARD_IS_PRESENT,
NULL,
0,
NULL,
0,
&l_uReplyLength,
&l_Ovr
);
TestCheck(
l_bResult == FALSE,
"Wait for present succeeded with no card inserted"
);
// With the pending i/o request close and re-open the driver
in_CReader.Close();
l_bResult = in_CReader.Open();
TestCheck(
l_bResult,
"Reader failed to terminate pending i/o request"
);
TestEnd();
if (TestFailed()) {
// If the open failed we can't contiue
exit(GetLastError());
}
l_hReader = in_CReader.GetHandle();
LogMessage(" >> Please insert 'IBM PC/SC Compliance Test Card'");
in_CReader.WaitForCardInsertion();
l_bCardInserted = TRUE;
// Cold reset
TestStart("%2d. Cold reset", l_lTestNo++);
l_uStart = clock();
LONG l_lResult = in_CReader.ColdResetCard();
l_uEnd = clock();
TEST_CHECK_SUCCESS("Cold reset failed", l_lResult);
TestCheck(
(l_uEnd - l_uStart) / CLOCKS_PER_SEC <= 2,
"Cold reset took too long.\nElapsed time %ld sec\nExpected time %ld sec",
(l_uEnd - l_uStart) / CLOCKS_PER_SEC,
2
);
TestEnd();
if (TestFailed()) {
exit(l_lResult);
}
// Set protocol
TestStart("%2d. Set protocol to T0 | T1", l_lTestNo++);
l_lResult = in_CReader.SetProtocol(
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1
);
TEST_CHECK_SUCCESS("Set protocol failed", l_lResult);
TestEnd();
continue;
}
TestStart("%2d. %s", l_lTestNo++, l_aAttr[l_iIndex].m_pchName);
SetLastError(0);
*(PULONG) l_rgbReplyBuffer = 0;
l_bResult = DeviceIoControl (
l_hReader,
IOCTL_SMARTCARD_GET_ATTRIBUTE,
&l_aAttr[l_iIndex].m_uType,
sizeof(ULONG),
l_rgbReplyBuffer,
sizeof(l_rgbReplyBuffer),
&l_uReplyLength,
&l_Ovr
);
if (l_bResult == FALSE && GetLastError() == ERROR_IO_PENDING) {
//
// The I/O request returned pending, so
// wait until the request is finished
//
SetLastError(0);
l_bResult = GetOverlappedResult(
l_hReader,
&l_Ovr,
&l_uReplyLength,
TRUE
);
}
if (GetLastError() != ERROR_SUCCESS) {
l_bResult = FALSE;
} else {
l_rgbReplyBuffer[l_uReplyLength] = 0;
}
LONG l_lResult = GetLastError();
switch (l_aAttr[l_iIndex].m_uType) {
case SCARD_ATTR_VENDOR_NAME:
TEST_CHECK_SUCCESS(
"Ioctl SCARD_ATTR_VENDOR_NAME failed",
l_lResult
);
TestCheck(
strlen((PCHAR) l_rgbReplyBuffer) != 0,
"No vendor name defined"
);
TestEnd();
break;
case SCARD_ATTR_VENDOR_IFD_TYPE:
TEST_CHECK_SUCCESS(
"Ioctl SCARD_ATTR_VENDOR_IFD_TYPE failed",
l_lResult
);
TestCheck(
strlen((PCHAR) l_rgbReplyBuffer) != 0,
"No ifd type defined"
);
TestEnd();
break;
case SCARD_ATTR_DEVICE_UNIT:
TEST_CHECK_SUCCESS(
"Ioctl SCARD_ATTR_DEVICE_UNIT failed",
l_lResult
);
TestCheck(
*(PULONG) l_rgbReplyBuffer < 4,
"Invalid value: %ld (0 - 3)",
*(PULONG) l_rgbReplyBuffer
);
TestEnd();
break;
case SCARD_ATTR_ATR_STRING:
if (l_bCardInserted) {
TEST_CHECK_SUCCESS(
"Ioctl SCARD_ATTR_ATR_STRING failed",
l_lResult
);
} else {
TestCheck(
l_bResult == FALSE,
"Reader returned ATR with no card inserted"
);
}
TestEnd();
break;
case SCARD_ATTR_DEFAULT_CLK:
case SCARD_ATTR_MAX_CLK:
TEST_CHECK_SUCCESS(
"Ioctl SCARD_ATTR_DEFAULT_CLK/SCARD_ATTR_MAX_CLK failed",
l_lResult
);
TestCheck(
*(PULONG) l_rgbReplyBuffer >= 1000 && *(PULONG) l_rgbReplyBuffer <= 20000,
"Invalid value %ld (1000 - 20000)",
*(PULONG) l_rgbReplyBuffer
);
TestEnd();
break;
case SCARD_ATTR_DEFAULT_DATA_RATE:
case SCARD_ATTR_MAX_DATA_RATE:
TEST_CHECK_SUCCESS(
"Ioctl SCARD_ATTR_DEFAULT_DATA_RATE/SCARD_ATTR_MAX_DATA_RATE failed",
l_lResult
);
TestEnd();
break;
case SCARD_ATTR_MAX_IFSD:
TEST_CHECK_SUCCESS(
"Ioctl SCARD_ATTR_MAX_IFSD failed",
l_lResult
);
TestCheck(
*(PULONG) l_rgbReplyBuffer >= 1 && *(PULONG) l_rgbReplyBuffer <= 254,
"Invalid value: %ld (1 - 254)",
*(PULONG) l_rgbReplyBuffer
);
TestEnd();
break;
case SCARD_ATTR_PROTOCOL_TYPES:
TEST_CHECK_SUCCESS(
"Ioctl SCARD_ATTR_PROTOCOL_TYPES failed",
l_lResult
);
// check if the reader at least supports T=0 and T=1
TestCheck(
(*(PULONG) l_rgbReplyBuffer & SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) ==
(SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1),
"Reader must support T=0 and T=1"
);
TestEnd();
break;
case SCARD_ATTR_CURRENT_PROTOCOL_TYPE:
if (l_bCardInserted) {
TEST_CHECK_SUCCESS(
"Ioctl SCARD_ATTR_CURRENT_PROTOCOL_TYPE failed",
l_lResult
);
TestCheck(
*(PULONG) l_rgbReplyBuffer != 0,
"Reader returned no protocol"
);
} else {
// Check that without a card the current protocol is set to 0
TestCheck(
l_bResult == FALSE,
"Ioctl SCARD_ATTR_CURRENT_PROTOCOL_TYPE failed should fail with no card inserted"
);
}
TestEnd();
break;
default:
TestCheck(
l_bResult,
"Ioctl returned %lxh",
GetLastError()
);
TestEnd();
break;
}
}
LogMessage(" << %s", REMOVE_CARD);
in_CReader.WaitForCardRemoval();
LogMessage(" << Please insert smart card BACKWARDS");
in_CReader.WaitForCardInsertion();
TestStart("%2d. IOCTL_SMARTCARD_GET_STATE", l_lTestNo++);
ULONG l_uState;
l_bResult = DeviceIoControl (
l_hReader,
IOCTL_SMARTCARD_GET_STATE,
NULL,
0,
&l_uState,
sizeof(l_uState),
&l_uReplyLength,
&l_Ovr
);
LONG l_lResult = GetLastError();
TestCheck(
l_bResult,
"IOCTL_SMARTCARD_GET_STATE failed.\nReturned %8lxH (NTSTATUS %8lxH).\nExpected %8lxH (NTSTATUS %8lxH)",
l_lResult,
MapWinErrorToNtStatus(l_lResult),
ERROR_SUCCESS,
MapWinErrorToNtStatus(ERROR_SUCCESS)
);
TestCheck(
l_uState <= SCARD_SWALLOWED,
"Invalid reader state.\nReturned %d\nExpected <= %d",
l_uState,
SCARD_SWALLOWED
);
TestEnd();
TestStart("%2d. Cold reset", l_lTestNo++);
l_uStart = clock();
l_lResult = in_CReader.ColdResetCard();
l_uEnd = clock();
TestCheck(
l_lResult == ERROR_UNRECOGNIZED_MEDIA,
"Cold reset failed.\nReturned %8lxH (NTSTATUS %8lxH).\nExpected %8lxH (NTSTATUS %8lxH)",
l_lResult,
MapWinErrorToNtStatus(l_lResult),
ERROR_UNRECOGNIZED_MEDIA,
MapWinErrorToNtStatus(ERROR_UNRECOGNIZED_MEDIA)
);
TestCheck(
(l_uEnd - l_uStart) / CLOCKS_PER_SEC <= 2,
"Cold reset took too long.\nElapsed time %ld sec\nExpected time %ld sec",
(l_uEnd - l_uStart) / CLOCKS_PER_SEC,
2
);
TestEnd();
}
void
SimulateResMngr(
CReader &in_CReader
)
{
BOOL l_bWaitForPresent = FALSE, l_bWaitForAbsent = FALSE, l_bResult;
BOOL l_bMustWait = FALSE, l_bPoweredDown = FALSE;
ULONG l_uState, l_uStatus, l_uReplyLength, l_uStateExpected = SCARD_ABSENT, l_lTestNo = 1;
ULONG l_uMinorIoctl;
OVERLAPPED l_Ovr, l_OvrWait;
HANDLE l_hReader = in_CReader.GetHandle();
l_Ovr.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ResetEvent(l_Ovr.hEvent);
l_OvrWait.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ResetEvent(l_OvrWait.hEvent);
LogMessage("===================================");
LogMessage("Part C: Resource Manager Simulation");
LogMessage("===================================");
LogMessage(" << %s", REMOVE_CARD);
in_CReader.WaitForCardRemoval();
while (TRUE) {
TestStart("%2d. IOCTL_SMARTCARD_GET_STATE", l_lTestNo++);
l_bResult = DeviceIoControl (
l_hReader,
IOCTL_SMARTCARD_GET_STATE,
NULL,
0,
&l_uState,
sizeof(l_uState),
&l_uReplyLength,
&l_Ovr
);
LONG l_lResult = GetLastError();
TestCheck(
l_bResult,
"IOCTL_SMARTCARD_GET_STATE failed.\nReturned %8lxH (NTSTATUS %8lxH).\nExpected %8lxH (NTSTATUS %8lxH)",
l_lResult,
MapWinErrorToNtStatus(l_lResult),
ERROR_SUCCESS,
MapWinErrorToNtStatus(ERROR_SUCCESS)
);
TestEnd();
if (l_bWaitForPresent) {
TestStart("%2d. %s", l_lTestNo++, INSERT_CARD);
l_bResult = GetOverlappedResult(
l_hReader,
&l_OvrWait,
&l_uReplyLength,
TRUE
);
l_lResult = GetLastError();
TestCheck(
l_bResult,
"Card insertion monitor failed.\nReturned %8lxH (NTSTATUS %8lxH).\nExpected %8lxH (NTSTATUS %8lxH)",
l_lResult,
MapWinErrorToNtStatus(l_lResult),
ERROR_SUCCESS,
MapWinErrorToNtStatus(ERROR_SUCCESS)
);
l_lResult = GetLastError();
TestEnd();
l_bWaitForPresent = FALSE;
continue;
}
if (l_bWaitForAbsent) {
if (l_bMustWait) {
TestStart("%2d. %s", l_lTestNo++, REMOVE_CARD);
} else {
TestStart("%2d. GetOverlappedResult", l_lTestNo++);
}
l_bResult = GetOverlappedResult(
l_hReader,
&l_OvrWait,
&l_uReplyLength,
l_bMustWait
);
if (l_bMustWait == FALSE) {
TestCheck(
l_bResult == FALSE,
"Smart card not removed"
);
TestEnd();
if (TestFailed()) {
return;
}
} else {
l_lResult = GetLastError();
TestCheck(
l_bResult,
"Card removal monitor failed.\nReturned %8lxH (NTSTATUS %8lxH).\nExpected %8lxH (NTSTATUS %8lxH)",
l_lResult,
MapWinErrorToNtStatus(l_lResult),
ERROR_SUCCESS,
MapWinErrorToNtStatus(ERROR_SUCCESS)
);
TestEnd();
if (TestFailed()) {
return;
}
l_bWaitForAbsent = FALSE;
continue;
}
}
TestStart("%2d. Checking reader status", l_lTestNo++);
switch (l_uState) {
case SCARD_UNKNOWN:
TestCheck(FALSE, "Reader returned illegal state SCARD_UNKNOWN");
TestEnd();
return;
case SCARD_ABSENT:
TestCheck(
l_uStateExpected == SCARD_ABSENT,
"Invalid reader state.\nCurrent state = %d\nExpected state = %d",
l_uState,
l_uStateExpected
);
TestEnd();
if (TestFailed()) {
return;
}
if (l_bMustWait) {
return;
}
TestStart("%2d. IOCTL_SMARTCARD_IS_PRESENT", l_lTestNo++);
l_bResult = DeviceIoControl (
l_hReader,
IOCTL_SMARTCARD_IS_PRESENT,
NULL,
0,
NULL,
0,
&l_uReplyLength,
&l_OvrWait
);
TestCheck(
GetLastError() == ERROR_IO_PENDING,
"Monitor is supposed to return ERROR_IO_PENDING (%lxh)",
GetLastError()
);
TestEnd();
if (TestFailed()) {
return;
}
l_bWaitForPresent = TRUE;
l_uStateExpected = SCARD_PRESENT;
break;
case SCARD_PRESENT:
case SCARD_SWALLOWED:
case SCARD_POWERED:
if (l_bPoweredDown) {
TestCheck(
l_uStateExpected <= SCARD_POWERED,
"Invalid reader state.\nCurrent state = %d\nExpected state <= %d",
l_uState,
l_uStateExpected
);
TestEnd();
if (TestFailed()) {
return;
}
l_bMustWait = TRUE;
l_uStateExpected = SCARD_ABSENT;
break;
}
TestCheck(
l_uStateExpected > SCARD_ABSENT,
"Invalid reader state.\nCurrent state = %d\nExpected state <= %d",
l_uState,
l_uStateExpected
);
TestEnd();
if (TestFailed()) {
return;
}
TestStart("%2d. IOCTL_SMARTCARD_IS_ABSENT", l_lTestNo++);
l_bResult = DeviceIoControl (
l_hReader,
IOCTL_SMARTCARD_IS_ABSENT,
NULL,
0,
NULL,
0,
&l_uReplyLength,
&l_OvrWait
);
l_lResult = GetLastError();
TestCheck(
l_bResult == FALSE,
"IOCTL_SMARTCARD_IS_ABSENT should fail.\nReturned %8lxH (NTSTATUS %8lxH).\nExpected %8lxH (NTSTATUS %8lxH)",
l_lResult,
MapWinErrorToNtStatus(l_lResult),
ERROR_IO_PENDING,
MapWinErrorToNtStatus(ERROR_IO_PENDING)
);
TestEnd();
l_bWaitForAbsent = TRUE;
TestStart("%2d. Cold reset card", l_lTestNo++);
l_uStatus = in_CReader.ColdResetCard();
TEST_CHECK_SUCCESS("ColdReset", l_uStatus)
l_uStateExpected = SCARD_NEGOTIABLE;
TestEnd();
if (TestFailed()) {
return;
}
break;
case SCARD_NEGOTIABLE:
TestCheck(
l_bPoweredDown == FALSE,
"Invalid reader state.\nCurrent state = %d\nExpected state = %d",
l_uState,
SCARD_PRESENT
);
TestCheck(
l_uStateExpected > SCARD_ABSENT,
"Invalid reader state.\nCurrent state = %d\nExpected state <= %d",
l_uState,
l_uStateExpected
);
TestEnd();
if (TestFailed()) {
return;
}
TestStart("%2d. Set protocol to T0 | T1", l_lTestNo++);
l_uStatus = in_CReader.SetProtocol(
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1
);
TestCheck(
l_uStatus == ERROR_SUCCESS,
"Protocol selection failed with error %lxh",
GetLastError()
);
TestEnd();
if (TestFailed()) {
return;
}
l_uStateExpected = SCARD_SPECIFIC;
break;
case SCARD_SPECIFIC:
TestCheck(
l_bPoweredDown == FALSE,
"Invalid reader state.\nCurrent state = %d\nExpected state = %d",
l_uState,
SCARD_PRESENT
);
TestCheck(
l_uStateExpected > SCARD_ABSENT,
"Invalid reader state.\nReturned %d\nExpected < %d",
l_uState,
l_uStateExpected
);
TestEnd();
if (TestFailed()) {
return;
}
TestStart("%2d. IOCTL_SMARTCARD_POWER (SCARD_POWER_DOWN)", l_lTestNo++);
l_uMinorIoctl = SCARD_POWER_DOWN;
SetLastError(0);
l_bResult = DeviceIoControl (
l_hReader,
IOCTL_SMARTCARD_POWER,
&l_uMinorIoctl,
sizeof(l_uMinorIoctl),
NULL,
0,
&l_uReplyLength,
&l_Ovr
);
if (l_bResult == FALSE && GetLastError() == ERROR_IO_PENDING) {
SetLastError(0);
l_bResult = GetOverlappedResult(
l_hReader,
&l_Ovr,
&l_uReplyLength,
TRUE
);
}
l_lResult = GetLastError();
TEST_CHECK_SUCCESS("IOCTL_SMARTCARD_POWER failed", l_lResult);
TestEnd();
l_uStateExpected = SCARD_PRESENT;
l_bPoweredDown = TRUE;
break;
default:
TestCheck(
FALSE,
"Reader returned invalid state %d",
l_uState
);
TestEnd();
return;
}
}
}
void
PowerManagementTest(
CReader &in_CReader,
ULONG in_uWaitTime
)
{
LONG l_lResult;
ULONG l_uState, l_uPrevState, l_uRepeat;
ULONG l_uDuration = 30;
if (in_uWaitTime > 30 && in_uWaitTime < 120) {
l_uDuration = in_uWaitTime;
}
LogMessage("=============================");
LogMessage("Part E: Power Management Test");
LogMessage("=============================");
LogMessage("Note: Each test cycle takes %ld seconds!", l_uDuration);
LogMessage(" << %s", REMOVE_CARD);
in_CReader.WaitForCardRemoval();
LogMessage("Test 1: DO NOT INSERT smart card during hibernate mode");
TestStart("Card out / card out - Hibernate now");
l_lResult = in_CReader.StartWaitForCardInsertion();
l_lResult = in_CReader.GetState(&l_uPrevState);
for (l_uRepeat = 0; l_uRepeat < l_uDuration; l_uRepeat++) {
l_lResult = in_CReader.GetState(&l_uState);
LONG l_uGoal = clock() + CLOCKS_PER_SEC;
while(l_uGoal > clock())
;
printf("\x08\x08%2ld", l_uDuration - l_uRepeat);
}
printf("\x08\x08 ");
l_lResult = in_CReader.FinishWaitForCard(FALSE);
TestCheck(
l_lResult == ERROR_IO_INCOMPLETE,
"GetOverlappedResult failed\nReturned %8lx\nExpected %8lx",
l_lResult,
ERROR_IO_INCOMPLETE
);
TestEnd();
TestStart("%s", INSERT_CARD);
l_lResult = in_CReader.FinishWaitForCard(TRUE);
TEST_CHECK_SUCCESS("Reader failed card insertion", l_lResult);
TestEnd();
TestStart("Checking reader status");
l_lResult = in_CReader.GetState(&l_uState);
TEST_CHECK_SUCCESS("Reader failed IOCTL_SMARTCARD_GET_STATE", l_lResult);
TestCheck(
l_uState > SCARD_ABSENT,
"Invalid reader state.\nReturned %d\nExpected > %d",
l_uState,
SCARD_ABSENT
);
TestEnd();
//
// Test 2
//
LogMessage("Test 2: REMOVE smart card DURING hibernate mode");
TestStart("Card in / card out - Hibernate now");
l_lResult = in_CReader.StartWaitForCardRemoval();
l_lResult = in_CReader.GetState(&l_uPrevState);
for (l_uRepeat = 0; l_uRepeat < l_uDuration; l_uRepeat++) {
l_lResult = in_CReader.GetState(&l_uState);
LONG l_uGoal = clock() + CLOCKS_PER_SEC;
while(l_uGoal > clock())
;
printf("\x08\x08%2ld", l_uDuration - l_uRepeat);
}
printf("\x08\x08 ");
l_lResult = in_CReader.FinishWaitForCard(FALSE);
TEST_CHECK_SUCCESS(
"GetOverlappedResult failed",
l_lResult
);
TestEnd();
TestStart("Checking reader status");
l_lResult = in_CReader.GetState(&l_uState);
TEST_CHECK_SUCCESS("Reader failed IOCTL_SMARTCARD_GET_STATE", l_lResult);
TestCheck(
l_uState == SCARD_ABSENT,
"Invalid reader state.\nReturned %d\nExpected %d",
l_uState,
SCARD_ABSENT
);
TestEnd();
LogMessage(" >> %s", INSERT_CARD);
in_CReader.WaitForCardInsertion();
//
// Test 3
//
LogMessage("Test 3: DO NOT REMOVE smart card during hibernate mode");
TestStart("Card in / card in - Hibernate now");
l_lResult = in_CReader.StartWaitForCardRemoval();
l_lResult = in_CReader.GetState(&l_uPrevState);
for (l_uRepeat = 0; l_uRepeat < l_uDuration; l_uRepeat++) {
l_lResult = in_CReader.GetState(&l_uState);
LONG l_uGoal = clock() + CLOCKS_PER_SEC;
while(l_uGoal > clock())
;
printf("\x08\x08%2ld", l_uDuration - l_uRepeat);
}
printf("\x08\x08 ");
l_lResult = in_CReader.FinishWaitForCard(FALSE);
TEST_CHECK_SUCCESS(
"GetOverlappedResult failed",
l_lResult
);
TestEnd();
TestStart("Checking reader status");
l_lResult = in_CReader.GetState(&l_uState);
TEST_CHECK_SUCCESS("Reader failed IOCTL_SMARTCARD_GET_STATE", l_lResult);
TestCheck(
l_uState >= SCARD_PRESENT,
"Invalid reader state.\nReturned %d\nExpected > %d",
l_uState,
SCARD_ABSENT
);
TestEnd();
LogMessage(" << %s", REMOVE_CARD);
in_CReader.WaitForCardRemoval();
//
// Test 4
//
LogMessage("Test 4: INSERT smart card DURING hibernate mode");
TestStart("Card out / card in - Hibernate now");
l_lResult = in_CReader.StartWaitForCardInsertion();
l_lResult = in_CReader.GetState(&l_uPrevState);
for (l_uRepeat = 0; l_uRepeat < l_uDuration; l_uRepeat++) {
l_lResult = in_CReader.GetState(&l_uState);
LONG l_uGoal = clock() + CLOCKS_PER_SEC;
while(l_uGoal > clock())
;
printf("\x08\x08%2ld", l_uDuration - l_uRepeat);
}
printf("\x08\x08 ");
l_lResult = in_CReader.FinishWaitForCard(FALSE);
TEST_CHECK_SUCCESS(
"GetOverlappedResult failed",
l_lResult
);
TestEnd();
TestStart("Checking reader status");
l_lResult = in_CReader.GetState(&l_uState);
TEST_CHECK_SUCCESS("Reader failed IOCTL_SMARTCARD_GET_STATE", l_lResult);
TestCheck(
l_uState >= SCARD_PRESENT,
"Invalid reader state.\nReturned %d\nExpected > %d",
l_uState,
SCARD_ABSENT
);
TestEnd();
}
class CArgv {
int m_iArgc;
char **m_pArgv;
BOOL *m_pfRef;
public:
CArgv(int in_iArgc, char **in_pArgv);
int OptionExist(PCHAR);
PCHAR ParameterExist(PCHAR);
PCHAR CheckParameters(CString);
PCHAR CArgv::ParameterUnused(void);
};
CArgv::CArgv(
int in_iArgc,
char **in_pArgv
)
{
m_iArgc = in_iArgc;
m_pArgv = in_pArgv;
m_pfRef = new BOOL[in_iArgc];
memset(m_pfRef, 0, sizeof(BOOL) * in_iArgc);
}
CArgv::OptionExist(
PCHAR in_pchParameter
)
{
for (int i = 0; i < m_iArgc; i++) {
if (m_pArgv[i][0] == '-' || m_pArgv[i][0] == '/') {
int j = 1;
while (m_pArgv[i][j] && m_pArgv[i][j] != ' ') {
if (strncmp(m_pArgv[i] + j, in_pchParameter, strlen(m_pArgv[i] + j)) == 0) {
m_pfRef[i] = TRUE;
return i;
}
j++;
}
}
}
return 0;
}
PCHAR
CArgv::ParameterExist(
PCHAR in_pchParameter
)
{
if (int i = OptionExist(in_pchParameter)) {
m_pfRef[i + 1] = TRUE;
return m_pArgv[i + 1];
}
return NULL;
}
PCHAR
CArgv::CheckParameters(
CString in_CParameters
)
/*++
Routine Description:
Checks if the command line includes in invalid/unknown parameter
--*/
{
int i, l_iPos;
for (i = 1; i < m_iArgc; i++) {
if ((l_iPos = in_CParameters.Find(m_pArgv[i])) == -1) {
return m_pArgv[i];
}
if (l_iPos + 3 < in_CParameters.GetLength() &&
in_CParameters[l_iPos + 3] == '*') {
// skip the next parameter
i += 1;
}
}
return NULL;
}
PCHAR
CArgv::ParameterUnused(
void
)
{
int i;
for (i = 1; i < m_iArgc; i++) {
if (m_pfRef[i] == FALSE) {
return m_pArgv[i];
}
}
return NULL;
}
CString &
GetOperatingSystem(
void
)
{
static CString l_COperatingSystem;
OSVERSIONINFO VersionInformation;
if (l_COperatingSystem.GetLength() == 0) {
VersionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&VersionInformation) == FALSE) {
l_COperatingSystem += "Unknown";
} else {
if (VersionInformation.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
if (VersionInformation.dwMinorVersion == 0) {
l_COperatingSystem += OS_WIN95;
} else {
l_COperatingSystem += OS_WIN98;
}
} else if (VersionInformation.dwPlatformId == VER_PLATFORM_WIN32_NT) {
if (VersionInformation.dwMajorVersion <= 4) {
l_COperatingSystem += OS_WINNT4;
} else {
l_COperatingSystem += OS_WINNT5;
}
} else {
l_COperatingSystem += "Unknown";
}
}
}
return l_COperatingSystem;
}
CString &
SelectReader(
void
)
{
CReaderList l_CReaderList;
ULONG l_uIndex, l_uReader;
ULONG l_uNumReaders = l_CReaderList.GetNumReaders();
static CString l_CEmpty("");
if (l_uNumReaders == 0) {
return l_CEmpty;
}
if (l_uNumReaders == 1) {
return l_CReaderList.GetDeviceName(0);
}
CString l_CLetter;
printf("\n");
printf(" Vendor IfdType Type\n");
printf(" -----------------------------------------------------\n");
for (l_uIndex = 0; l_uIndex < l_uNumReaders; l_uIndex++) {
INT l_iLetterPos;
INT l_iLength = l_CReaderList.GetVendorName(l_uIndex).GetLength();
CString l_CVendorName = l_CReaderList.GetVendorName(l_uIndex);
for (l_iLetterPos = 0;
l_iLetterPos < l_CVendorName.GetLength();
l_iLetterPos++) {
CHAR l_chLetter = l_CVendorName[l_iLetterPos];
if (l_chLetter == ' ' || l_chLetter == 'x') {
continue;
}
if (l_CLetter.Find(l_chLetter) == -1) {
l_CLetter += l_chLetter;
break;
}
}
if (l_iLetterPos >= l_iLength) {
l_CVendorName += (CHAR) (l_uIndex + '0') ;
l_iLetterPos = l_iLength;
}
printf(
" %s[%c]%-*s %-20s %8s\n",
(LPCSTR) l_CVendorName.Left(l_iLetterPos),
l_CVendorName[l_iLetterPos],
20 - l_iLetterPos,
l_CVendorName.Right(l_iLength - l_iLetterPos - 1),
(LPCSTR) l_CReaderList.GetIfdType(l_uIndex),
(LPCSTR) l_CReaderList.GetPnPType(l_uIndex)
);
}
putchar('\n');
do {
printf("\rSelect reader: \010");
CHAR l_chInput = (CHAR) _getche();
if (l_chInput == 3) {
exit(-1);
}
l_uReader = l_CLetter.Find(l_chInput);
} while(l_uReader == -1);
printf("\n");
return l_CReaderList.GetDeviceName(l_uReader);
}
CString
SelectReader(
CString &in_CVendorName
)
{
CReaderList l_CReaderList;
ULONG l_uIndex;
ULONG l_uNumReaders = l_CReaderList.GetNumReaders();
CString l_CVendorName = in_CVendorName;
l_CVendorName.MakeLower();
for (l_uIndex = 0; l_uIndex < l_uNumReaders; l_uIndex++) {
CString l_CVendorListName = l_CReaderList.GetVendorName(l_uIndex);
l_CVendorListName.MakeLower();
if (l_CVendorListName.Find(l_CVendorName) != -1) {
return l_CReaderList.GetDeviceName(l_uIndex);
}
}
return CString("");
}
//**********************************************************************
//
// StopService()
//
// PURPOSE : This function attempts to stop a service. It will fail
// the service has any dependent services.
// It also allows a timeout
// value to be passed, to prevent a scenario in which a
// service shutdown hangs, and in turn the application
// stopping the service hangs.
//
// PARAMETERS: hSCM - open handle to the service control manager
// hService - open handle to the service to be stopped
// dwTimeout - maximum time (in milliseconds) to wait
// for the service and its dependencies to stop
//
// RETURN VALUE: TRUE if the service is successfully stopped
//
//**********************************************************************
BOOL StopService( SC_HANDLE hSCM, SC_HANDLE hService,
DWORD dwTimeout ) {
SERVICE_STATUS ss;
DWORD dwStartTime = GetTickCount();
// Make sure the service is not already stopped
if ( !QueryServiceStatus( hService, &ss ) )
return FALSE;
if ( ss.dwCurrentState == SERVICE_STOPPED )
return FALSE;
// If a stop is pending, just wait for it
while ( ss.dwCurrentState == SERVICE_STOP_PENDING ) {
Sleep( 5000 );
if ( !QueryServiceStatus( hService, &ss ) )
return FALSE;
if ( ss.dwCurrentState == SERVICE_STOPPED )
return FALSE;
if ( GetTickCount() - dwStartTime > dwTimeout )
return FALSE;
}
// Send a stop code to service
if ( !ControlService( hService, SERVICE_CONTROL_STOP, &ss ) )
return FALSE;
// Wait for the service to stop
while ( ss.dwCurrentState != SERVICE_STOPPED ) {
Sleep( 5000 );
if ( !QueryServiceStatus( hService, &ss ) )
return FALSE;
if ( ss.dwCurrentState == SERVICE_STOPPED )
break;
if ( GetTickCount() - dwStartTime > dwTimeout )
return FALSE;
}
// Return success
return TRUE;
}
__cdecl
main(
int argc,
char* argv[]
)
{
CArgv l_CArgv(argc, argv);
BOOL l_bSuccess, l_fInvalidParameter = FALSE;
BOOL l_bStoppedScardsvr = FALSE; // true==> we succesfully stoped scardsvr service
SC_HANDLE l_hSCM = NULL;
SC_HANDLE l_hService = NULL;
LogMessage("Smart Card Reader Test Suite");
LogMessage("Version 2.0.5");
LogMessage("Copyright(c) Microsoft Corporation 1997 - 1999");
if(PCHAR l_pchArgv = l_CArgv.CheckParameters("-d -e -h -m -r * -sa -sb -sc -sd -se -t * -v * -w *")) {
LogMessage("Invalid Parameter '%s'", l_pchArgv);
l_fInvalidParameter = TRUE;
}
if (l_fInvalidParameter ||
l_CArgv.OptionExist("h")) {
LogMessage("IfdTest [-d] [-m] [-r name] [-sa] [-sb] [-sc] [-sd] [-se] [-ss] [-w sec] [-t test] [-v name]\n");
LogMessage(" -d dumps all i/o");
LogMessage(" -e ends (stops) scardsvr service");
LogMessage(" -m manual test");
LogMessage(" -r name opens reader using device name");
LogMessage(" -sa skips card monitor test");
LogMessage(" -sb skips general reader test");
LogMessage(" -sc skips resource manager simulation");
LogMessage(" -sd skips card tests");
LogMessage(" -se skips power management tests");
LogMessage(" -v name opens reader using vendor name");
LogMessage(" -t test runs only specific card test in part d");
LogMessage(" -w sec runs power management test using specified waiting time");
exit(-1);
}
static CReader l_CReader;
CString l_CDeviceName;
//
// sandysp 5/9/01: stop scardsvr service because open will fail if it's running
//
if (l_CArgv.OptionExist("e")) {
l_hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT );
if (l_hSCM) {
// Open the specified service
l_hService = OpenService( l_hSCM,
"scardsvr",
SERVICE_STOP | SERVICE_START | SERVICE_QUERY_STATUS );
if (l_hService) {
// Try to stop the service, specifying a 30 second timeout
l_bStoppedScardsvr = StopService( l_hSCM, l_hService, 30000 ) ;
}
}
}
if (PCHAR l_pchReader = l_CArgv.ParameterExist("r")) {
l_CDeviceName = CString("\\\\.\\") + CString(l_pchReader);
} else if (PCHAR l_pchVendorName = l_CArgv.ParameterExist("v")) {
CReaderList l_CReaderList;
l_CDeviceName = SelectReader(CString(l_pchVendorName));
} else {
CReaderList l_CReaderList;
l_CDeviceName = SelectReader();
}
if (l_CDeviceName == "") {
LogMessage("No reader found");
exit (-1);
}
l_bSuccess = l_CReader.Open(l_CDeviceName);
LogMessage(".");
if (l_bSuccess == FALSE) {
LogMessage("Can't open smart card reader");
exit (-1);
}
if (l_CArgv.OptionExist("d")) {
l_CReader.SetDump(TRUE);
}
void ManualTest(CReader &in_CReader);
if (l_CArgv.OptionExist("m")) {
ManualTest(l_CReader);
}
CCardProvider l_CCardProvider;
LogOpen("ifdtest");
time_t l_osBinaryTime;
time( &l_osBinaryTime );
CTime l_CTime( l_osBinaryTime );
LogMessage("Vendor: %s", l_CReader.GetVendorName());
LogMessage("Reader: %s", l_CReader.GetIfdType());
LogMessage(
"Date: %d/%02d/%02d",
l_CTime.GetMonth(),
l_CTime.GetDay(),
l_CTime.GetYear()
);
LogMessage(
"Time: %d:%02d",
l_CTime.GetHour(),
l_CTime.GetMinute()
);
LogMessage("OS: %s", (LPCSTR) GetOperatingSystem());
//
// Check if the reader properly supports
// card insertion and removal
//
if (l_CArgv.OptionExist("sa")) {
LogMessage("=================================");
LogMessage("Part A: Card monitor test skipped");
LogMessage("=================================");
} else {
CheckCardMonitor(l_CReader);
}
if (l_CArgv.OptionExist("sb")) {
LogMessage("===========================");
LogMessage("Part B: Reader test skipped");
LogMessage("===========================");
} else {
CheckReader(l_CReader);
}
if (l_CArgv.OptionExist("sc")) {
LogMessage("===========================================");
LogMessage("Part C: Resource Manager Simulation skipped");
LogMessage("===========================================");
} else {
// Check res manager behavior
SimulateResMngr(l_CReader);
}
if (l_CArgv.OptionExist("sd")) {
LogMessage("========================================");
LogMessage("Part D: Smart Card Provider Test skipped");
LogMessage("========================================");
} else {
ULONG l_uTestNo = 0;
PCHAR l_pchTestNo;
if (l_pchTestNo = l_CArgv.ParameterExist("t")) {
// The user wants us to run only one test
l_uTestNo = atoi(l_pchTestNo);
}
while (l_CCardProvider.CardsUntested()) {
LogMessage("================================");
LogMessage("Part D: Smart Card Provider Test");
LogMessage("================================");
LogMessage("Insert any of the following PC/SC Compliance Test Cards:");
l_CCardProvider.ListUntestedCards();
LogMessage(" >> %s", INSERT_CARD);
if (l_CReader.WaitForCardInsertion() != ERROR_SUCCESS) {
LogMessage("Reader failed card insertion monitor");
return -1;
}
// Reset the card
if (l_CReader.ColdResetCard() != ERROR_SUCCESS) {
LogMessage("Unable to reset smart card");
} else {
// Try to run tests with this card
l_CCardProvider.CardTest(l_CReader, l_uTestNo);
if (l_uTestNo != 0) {
// Quit the program if we only run one test.
return 0;
}
}
LogMessage(" << %s", REMOVE_CARD);
if (l_CReader.WaitForCardRemoval() != ERROR_SUCCESS) {
LogMessage("Reader failed card removal monitor");
return -1;
}
}
}
if (GetOperatingSystem() == OS_WINNT5) {
if (l_CArgv.OptionExist("se")) {
LogMessage("=====================================");
LogMessage("Part E: Power Management Test skipped");
LogMessage("=====================================");
} else {
ULONG l_uWaitTime = 0;
if (PCHAR l_pchWaitTime = l_CArgv.ParameterExist("w")) {
// The user wants us to run only one test
l_uWaitTime = atoi(l_pchWaitTime);
}
PowerManagementTest(l_CReader, l_uWaitTime);
}
}
//
// Sandysp 5/9/01: restart smart card reader service if we stopped it
//
if (l_bStoppedScardsvr) {
StartService( l_hService, 0, NULL );
}
if ( l_hService )
CloseServiceHandle( l_hService );
if ( l_hSCM )
CloseServiceHandle( l_hSCM );
LogMessage("Reader %s the test", (ReaderFailed() ? "failed" : "passed"));
return 0;
}