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

519 lines
11 KiB
C++

//+-------------------------------------------------------------------------
//
// 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;