📄 pcscom.~cpp
字号:
/*
* Card Application Class using PC/SC Standard
*
* Writen by Alfred Meng
*
* Oct. 15, 2000
*
*@ident "PCSCOM V1.0"
*/
#include <stdio.h>
#include <assert.h>
#include "pcscom.h"
#include "gdcmd.h"
#include "cardutil.h"
LPVOID SCMalloc (IN DWORD dwSize)
{
return(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize));
}
LONG SCFree (IN LPVOID lpMemory)
{
LONG lResult;
assert(lpMemory != NULL);
if (HeapFree(GetProcessHeap(), 0, lpMemory))
{
lResult = SCARD_S_SUCCESS;
}
else
{
lResult = GetLastError();
}
return lResult;
}
LONG SCListReaders (IN SCARDCONTEXT hContext,
IN LPCTSTR lpmszReaderGroups,
OUT LPTSTR * lplpmszReaderNames)
{
LONG lResult;
DWORD dwReaders;
assert(lplpmszReaderNames != NULL);
* lplpmszReaderNames = NULL;
lResult = SCardListReaders(hContext,
lpmszReaderGroups,
NULL, // NULL to indicate we want to
&dwReaders); // know the length of the buffer
if (lResult != SCARD_S_SUCCESS)
{
return lResult;
}
LPTSTR lpmszReaderNames = (LPTSTR) SCMalloc(dwReaders * sizeof(char));
if (lpmszReaderNames == NULL)
{
return ERROR_OUTOFMEMORY;
}
lResult = SCardListReaders(hContext,
lpmszReaderGroups,
lpmszReaderNames,
&dwReaders);
if (lResult == SCARD_S_SUCCESS)
{
*lplpmszReaderNames = lpmszReaderNames;
}
else
{
SCFree((LPVOID) lpmszReaderNames);
}
return lResult;
}
TPCSC::TPCSC()
{
bStarted = FALSE;
hContext = NULL;
iso_case4( CASE4_Disable );
assign(GDCommand,TOTAL_CMD); // Using G&D Command Set
}
int TPCSC::openterm(short rid )
{
if (bStarted==FALSE) Startup();
if ( !Opened(rid-1) )
return OpenReader(rid-1);
return 1;
}
int TPCSC::closeterm()
{
// loop for all reader
CloseReader(0);
Shutdown();
bStarted = FALSE;
return 1;
}
int TPCSC::opened()
{
return Opened(0);
}
int TPCSC::opensam(int plug)
{
if ( plug <0 || plug>=dwNumReaders) return -1;
if ( Opened(plug) ) return 1;
return OpenReader(plug);
}
int TPCSC::selectICC(int icc,bool reqATR)
{
if (SelectReader(icc) != -1 ) {
if (reqATR) RequestATR();
return 1;
}
return -1;
}
int TPCSC::hascard()
{
DWORD dwReaderLen = 0;
DWORD dwState;
DWORD dwProtocol;
BYTE atr[MAXIMUM_ATTR_STRING_LENGTH];
DWORD dwAtrLen;
rc = SCardStatus(hCards[curReader],NULL,&dwReaderLen,&dwState,&dwProtocol,atr,&dwAtrLen);
if ( rc == SCARD_S_SUCCESS && dwState == SCARD_SPECIFIC ) return 1;
return 0;
}
int TPCSC::ejectcard(bool beep)
{
rc = SCardEndTransaction(hCards[curReader], SCARD_LEAVE_CARD );
return 1;
}
char TPCSC::TermType() const
{
return 0x0F;
}
char *TPCSC::GetError() const
{
/*
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
0, // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Process any inserts in lpMsgBuf.
// ...
// Display the string.
MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
// Free the buffer.
LocalFree( lpMsgBuf );
*/
return "ERROR";
}
void TPCSC::Shutdown()
{
if (lpmszReaderNames != NULL) SCFree((LPVOID) lpmszReaderNames);
for ( int i=0; i<dwNumReaders;i++ ) if ( hCards[i] != NULL ) CloseReader(i);
}
LONG TPCSC::Startup()
{
LPTSTR lpszReaderName=NULL;
curReader = -1;
dwNumReaders = 0;
lpmszReaderNames = NULL;
for ( int i=0; i<MAXIMUM_SMARTCARD_READERS; i++ ) hCards[i] = NULL;
rc=SCardEstablishContext(SCARD_SCOPE_USER,NULL,NULL,&hContext);
if ( rc != SCARD_S_SUCCESS ) return rc;
SCListReaders(hContext,NULL,(LPTSTR *) &lpmszReaderNames);
if (rc != SCARD_S_SUCCESS) return rc;
if ( lpmszReaderNames != NULL ) {
lpszReaderName = lpmszReaderNames;
ZeroMemory((LPVOID)rsReaders, sizeof(rsReaders));
while ((*lpszReaderName != 0x0 ) &&
(dwNumReaders < MAXIMUM_SMARTCARD_READERS))
{
rsReaders[dwNumReaders].szReader = (LPCTSTR)lpszReaderName;
rsReaders[dwNumReaders].dwCurrentState = SCARD_STATE_UNAWARE;
dwNumReaders++;
lpszReaderName += lstrlen(lpszReaderName) + 1;
}
}
if (dwNumReaders == 0)
{
SetLastError(SCARD_E_READER_UNAVAILABLE);
rc = SCARD_E_READER_UNAVAILABLE;
}
else {
//rc = SCardGetStatusChange(hContext,INFINITE,rsReaders,dwNumReaders);
curReader = 0; // set default reader
}
bStarted = TRUE;
return rc;
}
LONG TPCSC::OpenReader(DWORD rid,DWORD prepro,DWORD smode)
{
LPBYTE lpbResponse = NULL;
if ( rid <0 || rid>=dwNumReaders) return -1;
dwMode[rid] = smode;
dwPrePro[rid] = prepro;
rc = SCardGetStatusChange(hContext,INFINITE,rsReaders,dwNumReaders);
if (!(rsReaders[rid].dwEventState & SCARD_STATE_PRESENT))
{
return SCARD_E_NO_SMARTCARD;
}
rc = SCardConnect(hContext,rsReaders[rid].szReader,
smode, prepro, &hCards[rid],&dwActivePro[rid]);
if ( rc == SCARD_S_SUCCESS ) curReader = rid;
return rc;
}
int TPCSC::RequestATR()
{
DWORD dwReaderLen = 0;
DWORD dwState;
DWORD dwProtocol;
BYTE atr[MAXIMUM_ATTR_STRING_LENGTH];
DWORD dwAtrLen;
DWORD cByte = MAXIMUM_ATTR_STRING_LENGTH;
if ( curReader <0 || curReader>=dwNumReaders) return -1;
// reconnect for smartcard changed
rc = SCardReconnect(hCards[curReader],
dwMode[curReader],
dwPrePro[curReader],
SCARD_LEAVE_CARD ,
&dwActivePro[curReader]);
if ( rc != SCARD_S_SUCCESS ) return -1;
// rc = SCardStatus(hCards[curReader],NULL,&dwReaderLen,&dwState,&dwProtocol,atr,&dwAtrLen);
if ( rc == SCARD_S_SUCCESS /*&& dwState == SCARD_SPECIFIC */) {
SCardBeginTransaction( hCards[curReader] );
rc = SCardGetAttrib(hCards[curReader],SCARD_ATTR_ATR_STRING,
(LPBYTE)&atr, &cByte);
if ( rc==SCARD_S_SUCCESS) {
memcpy(Resp,atr,cByte);
RespLen = cByte;
SW1 = SW2 = 0x0;
}
}
return rc;
}
LONG TPCSC::CloseReader(DWORD rid)
{
if ( rid<0 || rid >=dwNumReaders) return -1; // inVaild
if ( rid == curReader ) curReader = -1; // NO Reader selected
if (hCards[rid] != NULL) {
rc = SCardEndTransaction(hCards[rid], SCARD_LEAVE_CARD );
rc = SCardDisconnect(hCards[rid], SCARD_LEAVE_CARD);
hCards[rid] = NULL;
}
return rc;
}
BOOL TPCSC::Opened(DWORD rid)
{
if ( rid <0 || rid >=dwNumReaders) return FALSE;
return (hCards[rid]!=NULL)?TRUE:FALSE;
}
BOOL TPCSC::SelectReader(DWORD rid)
{
if ( rid <0 || rid>=dwNumReaders) return -1; // inVaild
if ( hCards[rid]!=NULL ) return curReader = rid;
return -1;
}
int TPCSC::sendapdu(TAPDU *pApdu)
{
unsigned long ulRespLen;
TAPDU tAPDU;
if ( curReader <0 || curReader>=dwNumReaders) return -1;
if ( hCards[curReader] == NULL) return -2; // NOT OPENED
memcpy(&__apdu,pApdu,sizeof(TAPDU));
memcpy(&tAPDU,pApdu,sizeof(TAPDU));
if ( tAPDU.len != 5 ) // ! CASE 2
if ( tAPDU.len > 4 )
if ( tAPDU.len != (tAPDU.apdu[4] + 5) ) {
tAPDU.len--; // Because PCSC didn't support CASE 4, so...
}
__redo:
ulRespLen = 0xff;
pApdu->gap = GetTickCount();
switch (dwActivePro[curReader]) {
case SCARD_PROTOCOL_T0:
rc = SCardTransmit(hCards[curReader],SCARD_PCI_T0,tAPDU.apdu,tAPDU.len,NULL,Resp,&ulRespLen);
break;
case SCARD_PROTOCOL_T1:
rc = SCardTransmit(hCards[curReader],SCARD_PCI_T1,tAPDU.apdu,tAPDU.len,NULL,Resp,&ulRespLen);
break;
default:
rc = SCardTransmit(hCards[curReader],SCARD_PCI_RAW,tAPDU.apdu,tAPDU.len,NULL,Resp,&ulRespLen);
}
pApdu->gap = (GetTickCount() - pApdu->gap);
tAPDU.gap = pApdu->gap;
RespLen = ulRespLen;
if ( RespLen == 0xff ){ // error with CT
Resp[0] = 0xF0;
Resp[1] = 0x80;
RespLen = 2;
}
if (__fHook!=NULL)
(*__fHook)(&tAPDU, Resp, RespLen);
SW1 = Resp[RespLen-2]; SW2 = Resp[RespLen-1];
RespLen -= 2;
if ( rc != SCARD_S_SUCCESS ) return rc;
if ( SW1== 0x61 ) {
memcpy(tAPDU.apdu,"\x00\xC0\x00\x00\x00",5);
tAPDU.apdu[0] = __iso_cla;
tAPDU.len = 5;
tAPDU.apdu[4] = SW2;
RespLen = SW2 + 2;
tAPDU.tag = 0x0;
goto __redo;
}/* else if ( SW1== 0x6C ) {
tAPDU.apdu[tAPDU.len-1] = SW2;
tAPDU.tag = 0x0;
goto __redo;
} */
return rc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -