⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smartcard.cpp

📁 Microsoft PCSC Example
💻 CPP
字号:
//---------------------------------------------------------------------------


#pragma hdrstop

#include "SmartCard.h"
#include <Dialogs.hpp>

//---------------------------------------------------------------------------

#pragma package(smart_init)

SCARDCONTEXT m_hContext =0; //Card Reader Contex

//Construction Method, Set the CardReaderName
TSmartCardReader::TSmartCardReader(AnsiString pCardReaderName)
{
  strcpy(CardReaderName, pCardReaderName.c_str());
}

void TSmartCardReader::ShowErrorMsg(long ErrorCode)
{
   char Msg[255];
   switch(ErrorCode)
   {
        case SCARD_E_CANCELLED: strcpy(Msg, "  The action was canceled by an SCardCancel request. "); break;
        case SCARD_E_CANT_DISPOSE: strcpy(Msg, "The system could not dispose of the media in the requested manner.  "); break;
        case SCARD_E_CARD_UNSUPPORTED: strcpy(Msg, "The smart card does not meet minimal requirements for support.  "); break;
        case SCARD_E_DUPLICATE_READER: strcpy(Msg, "The reader driver didn't produce a unique reader name. "); break;
        case SCARD_E_INSUFFICIENT_BUFFER: strcpy(Msg, "The data buffer for returned data is too small for the returned data. "); break;
        case SCARD_E_INVALID_ATR: strcpy(Msg, "An ATR string obtained from the registry is not a valid ATR string.  "); break;
        case SCARD_E_INVALID_HANDLE: strcpy(Msg, "The supplied handle was invalid.  "); break;
        case SCARD_E_INVALID_PARAMETER: strcpy(Msg, "One or more of the supplied parameters could not be properly interpreted.  "); break;
        case SCARD_E_INVALID_TARGET: strcpy(Msg, "Registry startup information is missing or invalid.  "); break;
        case SCARD_E_INVALID_VALUE: strcpy(Msg, "One or more of the supplied parameter values could not be properly interpreted.  "); break;
    case SCARD_E_NOT_READY: strcpy(Msg, "The reader or card is not ready to accept commands.  "); break;
    case SCARD_E_NOT_TRANSACTED: strcpy(Msg, "An attempt was made to end a non-existent transaction.  "); break;
    case SCARD_E_NO_MEMORY: strcpy(Msg, "Not enough memory available to complete this command.  "); break;
    case SCARD_E_NO_SERVICE: strcpy(Msg, "The smart card resource manager is not running.  "); break;
    case SCARD_E_NO_SMARTCARD: strcpy(Msg, "The operation requires a smart card, but no smart card is currently in the device.  "); break;
    case SCARD_E_PCI_TOO_SMALL: strcpy(Msg, "The PCI receive buffer was too small.  "); break;
    case SCARD_E_PROTO_MISMATCH: strcpy(Msg, "The requested protocols are incompatible with the protocol currently in use with the card.  "); break;
    case SCARD_E_READER_UNAVAILABLE: strcpy(Msg, "The specified reader is not currently available for use.  "); break;
    case SCARD_E_READER_UNSUPPORTED: strcpy(Msg, "The reader driver does not meet minimal requirements for support.  "); break;
    case SCARD_E_SERVICE_STOPPED: strcpy(Msg, "The smart card resource manager has shut down.  "); break;
    case SCARD_E_SHARING_VIOLATION: strcpy(Msg, "The smart card cannot be accessed because of other outstanding connections.  "); break;
    case SCARD_E_SYSTEM_CANCELLED: strcpy(Msg, "The action was canceled by the system, presumably to log off or shut down.  "); break;
    case SCARD_E_TIMEOUT: strcpy(Msg, "The user-specified timeout value has expired.  "); break;
    case SCARD_E_UNKNOWN_CARD: strcpy(Msg, "The specified smart card name is not recognized.  "); break;
    case SCARD_E_UNKNOWN_READER: strcpy(Msg, "The specified reader name is not recognized.  "); break;
    case SCARD_F_COMM_ERROR: strcpy(Msg, "An internal communications error has been detected.  "); break;
    case SCARD_F_INTERNAL_ERROR: strcpy(Msg, "An internal consistency check failed.  "); break;
    case SCARD_F_UNKNOWN_ERROR: strcpy(Msg, "An internal error has been detected, but the source is unknown.  "); break;
    case SCARD_F_WAITED_TOO_LONG: strcpy(Msg, "An internal consistency timer has expired.  "); break;
    case SCARD_S_SUCCESS: strcpy(Msg, "No error was encountered.  "); break;
    case SCARD_W_REMOVED_CARD: strcpy(Msg, "The smart card has been removed, so that further communication is not possible.  "); break;
    case SCARD_W_RESET_CARD: strcpy(Msg, "The smart card has been reset, so any shared state information is invalid.  "); break;
    case SCARD_W_UNPOWERED_CARD: strcpy(Msg, "Power has been removed from the smart card, so that further communication is not possible.  "); break;
    case SCARD_W_UNRESPONSIVE_CARD: strcpy(Msg, "The smart card is not responding to a reset.   "); break;
    case SCARD_W_UNSUPPORTED_CARD: strcpy(Msg, "The reader cannot communicate with the card, due to ATR string configuration conflicts.  "); break;
    default: strcpy(Msg, "unknow error");
   }
   ShowMessage(Msg);
}
//Distruction, Call CardDisconnect to Power off the card.
TSmartCardReader::~TSmartCardReader()
{
  CardDisconnect();
}

//Power On Smart card.if Success then reuturn TRUE and store ATR to
// The parameter pATR else return False and not set the pATR
bool TSmartCardReader::CardConnect(AnsiString * pATR)
{
    bool bRetval = true;
	DWORD dwAP=0;
	CardDisconnect();
    LONG res;
    bool bMuteCardChecked = false;
    SCARD_READERSTATE ReaderState;
  	ReaderState.szReader = CardReaderName;
	ReaderState.pvUserData = NULL;
	ReaderState.dwCurrentState = SCARD_STATE_UNAWARE;
	ReaderState.dwEventState = SCARD_STATE_CHANGED;
TRY_RESET_CARD_READER:
    res = SCardGetStatusChange(m_hContext,
						  100,
						  &ReaderState,
						  1);
    if (SCARD_S_SUCCESS == res)
    {
        if ((ReaderState.dwEventState & SCARD_STATE_PRESENT)== SCARD_STATE_PRESENT)
        {
            res = SCardConnect(m_hContext,
          				      CardReaderName,
							  SCARD_SHARE_DIRECT,
							  0,
							  &m_hCard,
							  &dwAP);

            if (SCARD_S_SUCCESS == res)
            {
                if (ReaderState.cbAtr <=0)
                {
                    if (bMuteCardChecked== false)
                    {
                        SCardDisconnect(m_hCard, SCARD_EJECT_CARD);
                        m_hCard = 0;
                        bMuteCardChecked = true;
                        goto TRY_RESET_CARD_READER;
                    }
                    else
                        bRetval = false;
                }
            }
            else
                bRetval = false;
        }
    }
    else
        bRetval = false;


    if (bRetval == true)
    {
        /*
        if ((0xF0 & ReaderState.rgbAtr[1]) == 0x60)
            m_ActiveProtocol = SCARD_PROTOCOL_T0;
        else if((0xF0 & ReaderState.rgbAtr[1]) == 0xE0)
            m_ActiveProtocol = SCARD_PROTOCOL_T1;
        else
            m_ActiveProtocol = SCARD_PROTOCOL_T1 | SCARD_PROTOCOL_T0;
        */
        res = SCardReconnect(m_hCard,
		                     SCARD_SHARE_EXCLUSIVE  ,
		                     SCARD_RESET_CARD | SCARD_UNPOWER_CARD,
		                     SCARD_PROTOCOL_T1 | SCARD_PROTOCOL_T0,
                            &m_ActiveProtocol);
        if (SCARD_S_SUCCESS == res)
        {
            char * cAtr = (char*)malloc(ReaderState.cbAtr * 2 + 1);
            memset(cAtr, 0, ReaderState.cbAtr * 2 + 1);
            BinToHex(ReaderState.rgbAtr, cAtr, ReaderState.cbAtr);
            *pATR = AnsiString(cAtr);
            free(cAtr);
        }
        else
            bRetval = false;
    }

	if (bRetval == false)
	{
		if (m_hCard != 0)
			SCardDisconnect(m_hCard, SCARD_UNPOWER_CARD);
        m_hCard = 0;
	}
	return bRetval;

}

//Power off Card
bool TSmartCardReader::CardDisconnect()
{
  if (m_hCard != 0)
  {
    SCardDisconnect(m_hCard, SCARD_UNPOWER_CARD);
    m_hCard = 0;
  }
  return true;
}

//Execute APDU COMMAND , szCMD' Format is Hex String
bool TSmartCardReader::RunAPDU(AnsiString szCMD, AnsiString * pResponse)
{
  if(!m_hCard)
  {
    return false;
  }
  DWORD CMDLen = szCMD.Length()/2;
  DWORD REPLen;
  SCARD_IO_REQUEST * ScardIoRequest = new SCARD_IO_REQUEST();
  ScardIoRequest->dwProtocol = this->m_ActiveProtocol;
  ScardIoRequest->cbPciLength = sizeof(SCARD_IO_REQUEST);

 // BYTE * CMD = (BYTE*)malloc(CMDLen);
 BYTE CMD[255];
  memset(CMD,0, 255);
  HexToBin(szCMD.c_str(), CMD, CMDLen);



  char cResponse[255];

  //Send Command to card
  LONG rc = SCardTransmit(m_hCard, ScardIoRequest , CMD, CMDLen, NULL, cResponse,&REPLen);
 if(rc != SCARD_S_SUCCESS)
 {
   ShowErrorMsg(rc);
   return false;
 }
 else
 {
   *pResponse = CharToHex(cResponse, REPLen, " ");
   return true;
 }
 delete ScardIoRequest;
}

//Get All Card reader names and store to Parameter pReaders
void TSmartCardReader::GetCardListReaders(TStrings * pReaders)
{
  TSmartCardReader::CardReleaseContex();
  pReaders->Clear();
  LONG res;
  //SCARD_E_CANCELLED     res: -2146435043
  res = SCardEstablishContext(SCARD_SCOPE_SYSTEM ,NULL,NULL,&m_hContext);
  if(res != SCARD_S_SUCCESS)
  {
    ShowErrorMsg(res);
    m_hContext = 0;
    return ;
  }
  
  //Look up all Card Reader and Add it to the Parameter of  pReaders
  LPTSTR pszReaders = NULL;
  LPTSTR pReader  = NULL;
  DWORD cch   = SCARD_AUTOALLOCATE;
  DWORD dwAP;

  res = SCardListReaders(m_hContext,NULL,(LPTSTR)&pszReaders,&cch);

  if(res == SCARD_S_SUCCESS)
  {
    pReader = pszReaders;
    String sReaderName = "";
    int i = 0;
    while (i < cch)
    {
      if (*pReader != '\0')
        sReaderName += * pReader;
      else
      {
        if (sReaderName != "")
          pReaders->Add(sReaderName);
        sReaderName = "";
      }
      pReader++;
      i++;
    }
  }
  SCardFreeMemory(m_hContext,pszReaders);
}

//Free Card Context
void TSmartCardReader::CardReleaseContex(void)
{
  if (m_hContext != 0)
    SCardReleaseContext(m_hContext);
}

//Convert Hex String to Char Buff

 AnsiString TSmartCardReader::CharToHex(char * pCharBuff,const DWORD dwCharLen, const AnsiString szSeparator)
{
  char * plchar = pCharBuff;
  AnsiString lResult = "";
  for (int i=0; i< dwCharLen; i++)
  {
    if (lResult != "")
      lResult += szSeparator;
    lResult = lResult + IntToHex((BYTE)*plchar,2);
    plchar++;
  }
  return lResult;
}


//Delete the Space of Parameter szSourceStr
AnsiString TSmartCardReader::NoSpace(const AnsiString szSourceStr)
{
  AnsiString lResult = "";
  for (int i =1; i<= szSourceStr.Length(); i++)
  {
    if (szSourceStr.SubString(i,1) != " ")
     lResult += szSourceStr.SubString(i,1);
  }
  return lResult;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -