📄 pcscctrl.cpp
字号:
// PcScCtrl.cpp: implementation of the CPcScCtrl class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "PcScCtrl.h"
#include "Helper.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
ISO7816_CMD SimCmd =
{
0xa0, //GSM SIM CLASS
0xa4, //Select
0xf2, //Status
0xb0, //Read Binary
0xd6, //UpdateBinary;
0xb2, //ReadRecord;
0xdc, //UpdateRecord;
0xa2, //Seek;
0x32, //Increase;
0x20, //VerifyChv;
0x24, //ChangeChv;
0x26, //DisableChv;
0x28, //EnableChv;
0x2c, //UnblockChv;
0x04, //Invalidate;
0x44, //Rehabilitate;
0x88, //RunGsmAlgorithm;
0xfa, //Sleep;
0xc0, //GetResponse;
};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CPcScCtrl::CPcScCtrl()
{
m_bGetRes = TRUE;
m_nCurReader = 0;
hCard = NULL;
hContext = NULL;
LONG lResult = EstablishContext();
if(lResult != SCARD_S_SUCCESS)
Helper::ShowLastError(lResult);
}
CPcScCtrl::~CPcScCtrl()
{
LONG lReturn;
if(hCard)
{
lReturn = SCardDisconnect(hCard, SCARD_LEAVE_CARD);
ASSERT(lReturn == SCARD_S_SUCCESS);
}
if (hContext != NULL)
{
lReturn = SCardReleaseContext(hContext);
ASSERT(lReturn == SCARD_S_SUCCESS);
}
}
LONG CPcScCtrl::ListReaders()
{
LONG lResult;
LPTSTR lpmszReaderNames;
LONG nReaders = 0;
m_asReaderNames.RemoveAll();
EstablishContext();
if(hContext == NULL)
return nReaders;
//__try
{
//
// Get the list of registered readers associated with the specified
// group(s).
// Note: The buffer is automatically allocated and must be freed
// by SCFree().
//
lResult = SCListReaders(hContext,
NULL,
(LPTSTR *) &lpmszReaderNames);
//Helper::ShowLastError(lResult);
if (lResult != SCARD_S_SUCCESS)
{
//__leave;
}else{
DWORD dwNumReaders = 0;
LPTSTR lpszReaderName = lpmszReaderNames;
TRACE(_T("\n"));
TRACE(_T("Registered Reader(s)\n"));
TRACE(_T("====================\n"));
//
// Walk through the list of readers and print out some information.
// Note: The list of readers are in a multi-string structure.
//
while (*lpszReaderName != _T('\0'))
{
++dwNumReaders;
TRACE(_T("%02d: %s\n"), dwNumReaders, lpszReaderName);
CString ts(lpszReaderName);
m_asReaderNames.Add(ts);
lpszReaderName += lstrlen(lpszReaderName) + 1;
nReaders++;
}
//
// Inform the user if no reader was found.
//
if (dwNumReaders == 0)
{
TRACE(_T("No registered reader was found"));
AfxMessageBox(_T("No registered reader was found"));
}
}
}
// Don't forget to release memory, if allocated.
//
if (lpmszReaderNames != NULL)
SCFree((LPVOID) lpmszReaderNames);
return nReaders;
}
LONG CPcScCtrl::DoAPDU(LPBYTE cmdAPDU, DWORD len, LPBYTE resAPDU,DWORD &reslen)
{
LONG lResult;
if(hCard == NULL)
{
lResult = SCARD_E_NO_SMARTCARD;
Helper::ShowLastError(lResult);
}
//
// Send APDU to card
//
lResult = SCardTransmit(hCard,
SCARD_PCI_T0,
cmdAPDU,
len,
NULL,
resAPDU,
&reslen);
//
// If API successful but card operation failed, then
// return SW1 and SW2 as error code
//
if (lResult == SCARD_S_SUCCESS)
{
//
// Sanity check
//
if(len == 5)//Must be Read
{
ASSERT(reslen >= 2);
}else{
ASSERT(reslen == 2);
}
if(reslen == 2)
{
if ( m_bGetRes &&
(resAPDU[0] == 0x61 || resAPDU[0] == 0x9f)
)
{
BYTE len = resAPDU[1];
DWORD dwStatusLen = len + 2;
//BYTE apdu[5] = {0xa0, 0xc0, 0x00, 0x00, len};
CMDAPDU cmdApdu;
cmdApdu.klass = SimCmd.Klass;
cmdApdu.inc = SimCmd.GetResponse;
cmdApdu.p1 = 0;
cmdApdu.p2 = 0;
cmdApdu.p3 = len;
//
// Send APDU to card.
//
lResult = SCardTransmit(hCard,
SCARD_PCI_T0,
(LPBYTE)&cmdApdu,
5,
NULL,
resAPDU,
&dwStatusLen);
if (lResult == SCARD_S_SUCCESS)
{
reslen = dwStatusLen;
TRACE(_T("%d response bytes available\n"),reslen);
}
}
}
#ifdef _DEBUG
if (reslen>=2)
{
BYTE errseq[2];
errseq[0] = resAPDU[reslen-2];
errseq[1] = resAPDU[reslen-1];
TRACE("%s\n",FormatErrMsg(errseq));
}
#endif
if(reslen >= 2)
{
UCHAR SW1 = resAPDU[reslen-2];
LONG lRet = MAKELONG(MAKEWORD(resAPDU[reslen-1],SW1), 0x0000);
return lRet;
}
}
if(lResult != SCARD_S_SUCCESS)
Helper::ShowLastError(lResult);
return lResult;
}
LPVOID CPcScCtrl::SCMalloc(DWORD dwSize)
{
return(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize));
}
LONG CPcScCtrl::SCFree(LPVOID lpMemory)
{
LONG lResult;
//
// Parameters sanity check.
//
ASSERT(lpMemory != NULL);
if (HeapFree(GetProcessHeap(), 0, lpMemory))
{
lResult = SCARD_S_SUCCESS;
}
else
{
lResult = GetLastError();
}
return lResult;
}
LONG CPcScCtrl::SCListReaders(SCARDCONTEXT hContext, LPCTSTR lpmszReaderGroups, LPTSTR *lplpmszReaderNames)
{
LONG lResult;
DWORD dwReaders;
//
// Parameters sanity check.
//
ASSERT(lplpmszReaderNames != NULL);
//
// Initialize returned info.
//
* lplpmszReaderNames = NULL;
//
// First find the required buffer length.
//
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;
}
//
// Allocate memory.
//
LPTSTR lpmszReaderNames = (LPTSTR) SCMalloc(dwReaders * sizeof(_TCHAR));
if (lpmszReaderNames == NULL)
{
return ERROR_OUTOFMEMORY;
}
//
// Now actually get the list of reader names.
//
lResult = SCardListReaders(hContext,
lpmszReaderGroups,
lpmszReaderNames,
&dwReaders);
if (lResult == SCARD_S_SUCCESS)
{
//
// Successful, so return pointer to reader names.
//
*lplpmszReaderNames = lpmszReaderNames;
}
else
{
//
// Error occurred, so free memory.
//
SCFree((LPVOID) lpmszReaderNames);
}
return lResult;
}
DWORD CPcScCtrl::TrackingCard(DWORD dwCurrentState)
{
LONG lResult;
EstablishContext();
if(m_asReaderNames.GetSize() == 0 || hContext == NULL)
return SCARD_STATE_UNKNOWN;
SCARD_READERSTATE rsReaders;
ZeroMemory((LPVOID)&rsReaders, sizeof(rsReaders));
rsReaders.szReader = (LPCTSTR)m_asReaderNames[m_nCurReader];
rsReaders.dwCurrentState = dwCurrentState;
//
// Now check state of the current reader
//
lResult = SCardGetStatusChange(hContext,
INFINITE,
&rsReaders,
1);
if (lResult != SCARD_S_SUCCESS)
return SCARD_STATE_UNKNOWN;
return rsReaders.dwEventState;
}
LONG CPcScCtrl::SetCurReader(INT n)
{
if (m_asReaderNames.GetSize() == 0 || m_asReaderNames.GetSize() < n)
return -1;
m_nCurReader = n;
if(hCard)
{
LONG lResult = SCardEndTransaction(
hCard,
SCARD_LEAVE_CARD
);
// if(lResult != SCARD_S_SUCCESS)
// {
// Helper::ShowLastError(lResult);
// return lResult;
// }
lResult = SCardDisconnect(hCard, SCARD_LEAVE_CARD);
if(lResult != SCARD_S_SUCCESS)
{
Helper::ShowLastError(lResult);
return lResult;
}
hCard = NULL;
}
DWORD dwActiveProtocol;
//
// Connect to the card
//
LONG lResult = SCardConnect(hContext,
m_asReaderNames[m_nCurReader],
SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
&hCard,
&dwActiveProtocol);
if(lResult != SCARD_S_SUCCESS)
Helper::ShowLastError(lResult);
if(lResult == SCARD_S_SUCCESS)
lResult = SCardBeginTransaction(hCard);
return lResult;
}
INT CPcScCtrl::GetCurReader()
{
return m_nCurReader;
}
LONG CPcScCtrl::Select(UCHAR id[],RESAPDU &resApdu )
{
CMDAPDU cmdApdu;
cmdApdu.klass = SimCmd.Klass;
cmdApdu.inc = SimCmd.Select;
cmdApdu.p1 = 0;
cmdApdu.p2 = 0;
cmdApdu.p3 = 2;
cmdApdu.data[0] = id[0];
cmdApdu.data[1] = id[1];
return DoAPDU((LPBYTE)&cmdApdu,5+2,resApdu.data,resApdu.len);
}
LONG CPcScCtrl::Select(ULONG id, RESAPDU &resApdu)
{
UCHAR aid[2];
aid[0] = (UCHAR)((id >> 8) & 0xff);
aid[1] = (UCHAR)(id & 0xff);
return Select(aid,resApdu);
}
LONG CPcScCtrl::Status(RESAPDU &resApdu)
{
CMDAPDU cmdApdu;
cmdApdu.klass = SimCmd.Klass;
cmdApdu.inc = SimCmd.Status;
cmdApdu.p1 = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -