|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: ifdtest.h
//
//--------------------------------------------------------------------------
#define min(a, b) (((a) < (b)) ? (a) : (b))
// Status codes
#define IFDSTATUS_SUCCESS 0
#define IFDSTATUS_FAILED 1
#define IFDSTATUS_CARD_UNKNOWN 2
#define IFDSTATUS_TEST_UNKNOWN 3
#define IFDSTATUS_NO_PROVIDER 4
#define IFDSTATUS_NO_FUNCTION 5
#define IFDSTATUS_END 7
// query codes
#define IFDQUERY_CARD_TESTED 0
#define IFDQUERY_CARD_NAME 1
#define IFDQUERY_TEST_RESULT 2
#define READER_TYPE_WDM "WDM PnP"
#define READER_TYPE_NT "NT 4.00"
#define READER_TYPE_VXD "Win9x VxD"
#define OS_WINNT4 "Windows NT 4.0"
#define OS_WINNT5 "Windows NT 5.0"
#define OS_WIN95 "Windows 95"
#define OS_WIN98 "Windows 98"
#define MAX_NUM_ATR 3
// Prototypes
void LogMessage(PCHAR in_pchFormat, ...); void LogOpen(PCHAR in_pchLogFile); void TestStart(PCHAR in_pchFormat, ...); void TestCheck(BOOL in_bResult, PCHAR in_pchFormat, ...); void TestEnd(void); BOOL TestFailed(void); BOOL ReaderFailed(void); CString & GetOperatingSystem(void);
void TestCheck( ULONG in_lResult, const PCHAR in_pchOperator, const ULONG in_uExpectedResult, ULONG in_uResultLength, ULONG in_uExpectedLength, UCHAR in_chSw1, UCHAR in_chSw2, UCHAR in_chExpectedSw1, UCHAR in_chExpectedSw2, PBYTE in_pchData, PBYTE in_pchExpectedData, ULONG in_uDataLength );
extern "C" {
LONG MapWinErrorToNtStatus(ULONG in_uErrorCode); }
//
// some useful macros
//
#define TEST_END() {TestEnd(); if(TestFailed()) return IFDSTATUS_FAILED;}
#define TEST_CHECK_SUCCESS(Text, Result) \
TestCheck( \ Result == ERROR_SUCCESS, \ "%s.\nReturned %8lxH (NTSTATUS %8lxH)\nExpected 0H (NTSTATUS 0H)", \ Text, \ Result, \ MapWinErrorToNtStatus(Result) \ );
#define TEST_CHECK_NOT_SUPPORTED(Text, Result) \
TestCheck( \ Result == ERROR_NOT_SUPPORTED, \ "%s.\nReturned %8lxH (NTSTATUS %8xH)\nExpected %38xH (NTSTATUS %8lxH)", \ Text, \ Result, \ MapWinErrorToNtStatus(Result), \ ERROR_NOT_SUPPORTED, \ MapWinErrorToNtStatus(ERROR_NOT_SUPPORTED) \ ); //
// Class definitions
//
class CAtr {
UCHAR m_rgbAtr[SCARD_ATR_LENGTH]; ULONG m_uAtrLength; public: CAtr() { m_uAtrLength = 0; memset(m_rgbAtr, 0, SCARD_ATR_LENGTH); }
CAtr( BYTE in_rgbAtr[], ULONG in_uAtrLength ) { *this = CAtr(); m_uAtrLength = min(SCARD_ATR_LENGTH, in_uAtrLength); memcpy(m_rgbAtr, in_rgbAtr, m_uAtrLength); }
PCHAR GetAtrString(PCHAR io_pchBuffer); PBYTE GetAtr(PBYTE *io_pchBuffer, PULONG io_puAtrLength) { *io_pchBuffer = (PBYTE) m_rgbAtr; *io_puAtrLength = m_uAtrLength; return (PBYTE) m_rgbAtr; }
ULONG GetLength() {
return m_uAtrLength; }
operator==(const CAtr& a) {
return (m_uAtrLength && a.m_uAtrLength == m_uAtrLength && memcmp(m_rgbAtr, a.m_rgbAtr, m_uAtrLength) == 0); }
operator!=(const CAtr& a) {
return !(*this == a); } };
class CReader {
// device name. E.g. SCReader0
CString m_CDeviceName;
// Name of the reader to be tested. E.g. Bull
CString m_CVendorName;
// Name of the reader to be tested. E.g. Bull
CString m_CIfdType;
// Atr of the current card
class CAtr m_CAtr;
// handle to the reader device
HANDLE m_hReader;
// Overlapped structure used by DeviceIoControl
OVERLAPPED m_Ovr;
// Overlapped structure used by WaitFor...
OVERLAPPED m_OvrWait;
// io-request struct used for transmissions
SCARD_IO_REQUEST m_ScardIoRequest;
// Storage area for smart card i/o
UCHAR m_rgbReplyBuffer[1024];
// size of the reply buffer
ULONG m_uReplyBufferSize;
// Number of bytes returned by the card
ULONG m_uReplyLength;
// function used by WaitForCardInsertion|Removal
LONG WaitForCard(const ULONG);
LONG StartWaitForCard(const ULONG);
LONG PowerCard(ULONG in_uMinorIoControlCode);
BOOL m_fDump;
public: CReader();
// Close reader
void Close(void);
// power functions
LONG CReader::ColdResetCard(void) {
return PowerCard(SCARD_COLD_RESET); }
LONG CReader::WarmResetCard(void) {
return PowerCard(SCARD_WARM_RESET); }
LONG CReader::PowerDownCard(void) {
return PowerCard(SCARD_POWER_DOWN); }
PBYTE GetAtr(PBYTE *io_pchBuffer, PULONG io_puAtrLength) { return m_CAtr.GetAtr(io_pchBuffer, io_puAtrLength); }
PCHAR GetAtrString(PCHAR io_pchBuffer) { return m_CAtr.GetAtrString(io_pchBuffer); }
HANDLE GetHandle(void) { return m_hReader; }
CString &GetDeviceName(void) { return m_CDeviceName; }
LONG VendorIoctl(CString &o_CAnswer); CString &GetVendorName(void); CString &GetIfdType(void); ULONG GetDeviceUnit(void); LONG GetState(PULONG io_puState);
// Open the reader
BOOL Open( CString &in_CReaderName );
// (Re)Open reader using the existing name
BOOL Open(void);
//
// Set size of the reply buffer
// (Only for testing purposes)
//
void SetReplyBufferSize(ULONG in_uSize) { if (in_uSize > sizeof(m_rgbReplyBuffer)) {
m_uReplyBufferSize = sizeof(m_rgbReplyBuffer);
} else { m_uReplyBufferSize = in_uSize; } }
// assigns an ATR
void SetAtr(PBYTE in_pchAtr, ULONG in_uAtrLength) {
m_CAtr = CAtr(in_pchAtr, in_uAtrLength); }
// returns the ATR of the current card
class CAtr &GetAtr() {
return m_CAtr; }
// set protocol to be used
LONG SetProtocol(const ULONG in_uProtocol);
// transmits an APDU to the reader/card
LONG Transmit( PBYTE in_pchRequest, ULONG in_uRequestLength, PBYTE *out_pchReply, PULONG out_puReplyLength );
// wait to insert card
LONG WaitForCardInsertion() { return WaitForCard(IOCTL_SMARTCARD_IS_PRESENT); };
// wait to remove card
LONG WaitForCardRemoval() { return WaitForCard(IOCTL_SMARTCARD_IS_ABSENT); };
LONG StartWaitForCardRemoval() { return StartWaitForCard(IOCTL_SMARTCARD_IS_ABSENT); };
LONG StartWaitForCardInsertion() { return StartWaitForCard(IOCTL_SMARTCARD_IS_PRESENT); };
LONG FinishWaitForCard(const BOOL in_bWait);
void SetDump(BOOL in_fOn) { m_fDump = in_fOn; } };
class CCardProvider { // Start of list pointer
static class CCardProvider *s_pFirst;
// Pointer to next provider
class CCardProvider *m_pNext;
// name of the card to be tested
CString m_CCardName;
// atr of this card
CAtr m_CAtr[3];
// test no to run
ULONG m_uTestNo;
// max number of tests
ULONG m_uTestMax;
// This flag indicates that the card test was unsuccessful
BOOL m_bTestFailed;
// This flag indicates that the card has been tested
BOOL m_bCardTested;
// set protocol function
ULONG ((*m_pSetProtocol)(class CCardProvider&, class CReader&));
// set protocol function
ULONG ((*m_pCardTest)(class CCardProvider&, class CReader&));
public:
// Constructor
CCardProvider(void);
// Constructor to be used by plug-in
CCardProvider(void (*pEntryFunction)(class CCardProvider&));
// Method that mangages all card tests
void CardTest(class CReader&, ULONG in_uTestNo);
// return if there are still untested cards
BOOL CardsUntested(void);
// List all cards that have not been tested
void ListUntestedCards(void);
// Assigns a friendly name to a card
void SetCardName(CHAR in_rgchCardName[]);
// Set ATR of the card
void SetAtr(PBYTE in_rgbAtr, ULONG in_uAtrLength);
// Assign callback functions
void SetProtocol(ULONG ((in_pFunction)(class CCardProvider&, class CReader&))) { m_pSetProtocol = in_pFunction; }
void SetCardTest(ULONG ((in_pFunction)(class CCardProvider&, class CReader&))) { m_pCardTest = in_pFunction; }
// returns the test number to perform
ULONG GetTestNo(void) { return m_uTestNo; }
BOOL IsValidAtr(CAtr in_CAtr) {
for (int i = 0; i < MAX_NUM_ATR; i++) {
if (m_CAtr[i] == in_CAtr) {
return TRUE; } } return FALSE; } };
// represents a list of all installed readers
class CReaderList {
// number of constructor calls to avoid multiple build of reader list
static ULONG m_uRefCount;
// number of currently installed readers
static ULONG m_uNumReaders;
// pointer to array of reader list
static class CReaderList **m_pList;
ULONG m_uCurrentReader;
CString m_CDeviceName; CString m_CPnPType; CString m_CVendorName; CString m_CIfdType;
public:
CReaderList(); CReaderList( CString &in_CDeviceName, CString &in_CPnPType, CString &in_CVendorName, CString &in_CIfdType ); ~CReaderList(); void AddDevice( CString in_pchDeviceName, CString in_pchPnPType );
CString &GetVendorName(ULONG in_uIndex); CString &GetDeviceName(ULONG in_uIndex); CString &GetIfdType(ULONG in_uIndex); CString &GetPnPType(ULONG in_uIndex);
ULONG GetNumReaders(void) { return m_uNumReaders; } };
// This structure represents the T=0 result file of a smart card
typedef struct _T0_RESULT_FILE_HEADER { // Offset to first test result
UCHAR Offset;
// Number of times the card has been reset
UCHAR CardResetCount;
// Version number of this card
UCHAR CardMajorVersion; UCHAR CardMinorVersion;
} T0_RESULT_FILE_HEADER, *PT0_RESULT_FILE_HEADER;
typedef struct _T0_RESULT_FILE {
//
// The following structures store the results
// of the tests. Each result comes with the
// reset count when the test was performed.
// This is used to make sure that we read not
// the result from an old test, maybe even
// performed with another reader/driver.
//
struct {
UCHAR Result; UCHAR ResetCount;
} TransferAllBytes;
struct {
UCHAR Result; UCHAR ResetCount;
} TransferNextByte;
struct {
UCHAR Result; UCHAR ResetCount;
} Read256Bytes;
struct {
UCHAR Result; UCHAR ResetCount;
} Case1Apdu;
struct {
UCHAR Result; UCHAR ResetCount;
} RestartWorkWaitingTime;
struct {
UCHAR Result; UCHAR ResetCount;
} PTS;
struct {
UCHAR Result; UCHAR ResetCount;
} PTSDataCheck;
} T0_RESULT_FILE, *PT0_RESULT_FILE;
|