402 lines
12 KiB
C++
402 lines
12 KiB
C++
#include "SCardLoader.h"
|
|
#include "PCSCException.h"
|
|
|
|
#ifndef TC_WINDOWS
|
|
#include <dlfcn.h>
|
|
#define LoadLibrary(x) dlopen(x, RTLD_NOW | RTLD_LOCAL)
|
|
#define FreeLibrary(x) dlclose(x)
|
|
#define GetProcAddress(x, y) dlsym(x, y)
|
|
typedef void* HMODULE;
|
|
#ifdef TC_MACOSX
|
|
#if !defined(USE_SCARD_CONTROL_112)
|
|
#define SCardControlName "SCardControl132"
|
|
#else
|
|
#define SCardControlName "SCardControl"
|
|
#endif
|
|
#else
|
|
#define SCardControlName "SCardControl"
|
|
#endif
|
|
#define SCardConnectName "SCardConnect"
|
|
#define SCardStatusName "SCardStatus"
|
|
#define SCardGetStatusChangeName "SCardGetStatusChange"
|
|
#define SCardListReaderGroupsName "SCardListReaderGroups"
|
|
#define SCardListReadersName "SCardListReaders"
|
|
#else
|
|
#define SCardControlName "SCardControl"
|
|
#define SCardConnectName "SCardConnectW"
|
|
#define SCardStatusName "SCardStatusW"
|
|
#define SCardGetStatusChangeName "SCardGetStatusChangeW"
|
|
#define SCardListReaderGroupsName "SCardListReaderGroupsW"
|
|
#define SCardListReadersName "SCardListReadersW"
|
|
#endif
|
|
|
|
using namespace std;
|
|
|
|
namespace VeraCrypt
|
|
{
|
|
HMODULE SCardLoader::hScardModule = NULL;
|
|
SCARDCONTEXT SCardLoader::hScardContext = 0;
|
|
SCardEstablishContextPtr SCardLoader::scardEstablishContext = NULL;
|
|
SCardReleaseContextPtr SCardLoader::scardReleaseContext = NULL;
|
|
SCardIsValidContextPtr SCardLoader::scardIsValidContext = NULL;
|
|
#ifndef TC_MACOSX
|
|
SCardFreeMemoryPtr SCardLoader::scardFreeMemory = NULL;
|
|
#endif
|
|
SCardConnectPtr SCardLoader::scardConnect = NULL;
|
|
SCardReconnectPtr SCardLoader::scardReconnect = NULL;
|
|
SCardDisconnectPtr SCardLoader::scardDisconnect = NULL;
|
|
SCardBeginTransactionPtr SCardLoader::scardBeginTransaction = NULL;
|
|
SCardEndTransactionPtr SCardLoader::scardEndTransaction = NULL;
|
|
SCardStatusPtr SCardLoader::scardStatus = NULL;
|
|
SCardGetStatusChangePtr SCardLoader::scardGetStatusChange = NULL;
|
|
SCardControlPtr SCardLoader::scardControl = NULL;
|
|
SCardTransmitPtr SCardLoader::scardTransmit = NULL;
|
|
SCardListReaderGroupsPtr SCardLoader::scardListReaderGroups = NULL;
|
|
SCardListReadersPtr SCardLoader::scardListReaders = NULL;
|
|
SCardCancelPtr SCardLoader::scardCancel = NULL;
|
|
SCardGetAttribPtr SCardLoader::scardGetAttrib = NULL;
|
|
SCardSetAttribPtr SCardLoader::scardSetAttrib = NULL;
|
|
SCARD_IO_REQUEST* SCardLoader::scardT0Pci = NULL;
|
|
SCARD_IO_REQUEST* SCardLoader::scardT1Pci = NULL;
|
|
SCARD_IO_REQUEST* SCardLoader::scardRawPci = NULL;
|
|
bool SCardLoader::bInitialized = false;
|
|
|
|
#ifdef TC_WINDOWS
|
|
wstring SCardLoader::GetSCardPath()
|
|
#else
|
|
string SCardLoader::GetSCardPath()
|
|
#endif
|
|
{
|
|
#ifdef TC_WINDOWS
|
|
wchar_t winscardPath[TC_MAX_PATH];
|
|
if (GetSystemDirectory(winscardPath, TC_MAX_PATH))
|
|
{
|
|
StringCbCat(winscardPath, sizeof(winscardPath), L"\\Winscard.dll");
|
|
}
|
|
else
|
|
StringCbCopy(winscardPath, sizeof(winscardPath), L"C:\\Windows\\System32\\Winscard.dll");
|
|
return winscardPath;
|
|
#elif TC_MACOSX
|
|
return "/System/Library/Frameworks/PCSC.framework/PCSC";
|
|
#else
|
|
string pcscPath = "";
|
|
FILE* pipe =
|
|
#ifdef TC_LINUX
|
|
popen("ldconfig -p", "r");
|
|
#else
|
|
popen("ldconfig -r", "r"); // FreeBSD
|
|
#endif
|
|
if (pipe)
|
|
{
|
|
char buffer[128];
|
|
while (!feof(pipe))
|
|
{
|
|
if (fgets(buffer, 128, pipe) != NULL)
|
|
{
|
|
string line(buffer);
|
|
if (line.find("libpcsclite.so") != string::npos)
|
|
{
|
|
size_t pos = line.find("=>");
|
|
if (pos != string::npos)
|
|
{
|
|
pcscPath = line.substr(pos + 3);
|
|
pos = pcscPath.find_first_of(" \t\r\n");
|
|
if (pos != string::npos)
|
|
pcscPath = pcscPath.substr(0, pos);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
pclose(pipe);
|
|
}
|
|
|
|
if (pcscPath == "")
|
|
{
|
|
pcscPath = "libpcsclite.so";
|
|
}
|
|
|
|
return pcscPath;
|
|
#endif
|
|
}
|
|
|
|
void SCardLoader::Initialize()
|
|
{
|
|
if (bInitialized)
|
|
return;
|
|
|
|
hScardModule = LoadLibrary(GetSCardPath().c_str());
|
|
if (hScardModule)
|
|
{
|
|
scardEstablishContext = (SCardEstablishContextPtr)GetProcAddress(hScardModule, "SCardEstablishContext");
|
|
scardReleaseContext = (SCardReleaseContextPtr)GetProcAddress(hScardModule, "SCardReleaseContext");
|
|
scardIsValidContext = (SCardIsValidContextPtr)GetProcAddress(hScardModule, "SCardIsValidContext");
|
|
#ifndef TC_MACOSX
|
|
scardFreeMemory = (SCardFreeMemoryPtr)GetProcAddress(hScardModule, "SCardFreeMemory");
|
|
#endif
|
|
scardConnect = (SCardConnectPtr)GetProcAddress(hScardModule, SCardConnectName);
|
|
scardReconnect = (SCardReconnectPtr)GetProcAddress(hScardModule, "SCardReconnect");
|
|
scardDisconnect = (SCardDisconnectPtr)GetProcAddress(hScardModule, "SCardDisconnect");
|
|
scardBeginTransaction = (SCardBeginTransactionPtr)GetProcAddress(hScardModule, "SCardBeginTransaction");
|
|
scardEndTransaction = (SCardEndTransactionPtr)GetProcAddress(hScardModule, "SCardEndTransaction");
|
|
scardStatus = (SCardStatusPtr)GetProcAddress(hScardModule, SCardStatusName);
|
|
scardGetStatusChange = (SCardGetStatusChangePtr)GetProcAddress(hScardModule, SCardGetStatusChangeName);
|
|
scardControl = (SCardControlPtr)GetProcAddress(hScardModule, SCardControlName);
|
|
scardTransmit = (SCardTransmitPtr)GetProcAddress(hScardModule, "SCardTransmit");
|
|
scardListReaderGroups = (SCardListReaderGroupsPtr)GetProcAddress(hScardModule, SCardListReaderGroupsName);
|
|
scardListReaders = (SCardListReadersPtr)GetProcAddress(hScardModule, SCardListReadersName);
|
|
scardCancel = (SCardCancelPtr)GetProcAddress(hScardModule, "SCardCancel");
|
|
scardGetAttrib = (SCardGetAttribPtr)GetProcAddress(hScardModule, "SCardGetAttrib");
|
|
scardSetAttrib = (SCardSetAttribPtr)GetProcAddress(hScardModule, "SCardSetAttrib");
|
|
scardT0Pci = (SCARD_IO_REQUEST*)GetProcAddress(hScardModule, "g_rgSCardT0Pci");
|
|
scardT1Pci = (SCARD_IO_REQUEST*)GetProcAddress(hScardModule, "g_rgSCardT1Pci");
|
|
scardRawPci = (SCARD_IO_REQUEST*)GetProcAddress(hScardModule, "g_rgSCardRawPci");
|
|
if (
|
|
#ifndef TC_MACOSX
|
|
scardFreeMemory &&
|
|
#endif
|
|
scardEstablishContext && scardReleaseContext && scardIsValidContext && scardConnect && scardReconnect && scardDisconnect &&
|
|
scardBeginTransaction && scardEndTransaction && scardStatus && scardGetStatusChange && scardControl && scardTransmit &&
|
|
scardListReaderGroups && scardListReaders && scardCancel && scardGetAttrib && scardSetAttrib && scardT0Pci && scardT1Pci && scardRawPci)
|
|
{
|
|
if (SCARD_S_SUCCESS == scardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hScardContext))
|
|
{
|
|
bInitialized = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!bInitialized)
|
|
{
|
|
Finalize();
|
|
}
|
|
}
|
|
|
|
void SCardLoader::Finalize()
|
|
{
|
|
if (hScardContext)
|
|
{
|
|
scardReleaseContext(hScardContext);
|
|
hScardContext = 0;
|
|
}
|
|
|
|
if (hScardModule)
|
|
{
|
|
FreeLibrary(hScardModule);
|
|
hScardModule = NULL;
|
|
}
|
|
|
|
scardEstablishContext = NULL;
|
|
scardReleaseContext = NULL;
|
|
scardIsValidContext = NULL;
|
|
#ifndef TC_MACOSX
|
|
scardFreeMemory = NULL;
|
|
#endif
|
|
scardConnect = NULL;
|
|
scardReconnect = NULL;
|
|
scardDisconnect = NULL;
|
|
scardBeginTransaction = NULL;
|
|
scardEndTransaction = NULL;
|
|
scardStatus = NULL;
|
|
scardGetStatusChange = NULL;
|
|
scardControl = NULL;
|
|
scardTransmit = NULL;
|
|
scardListReaderGroups = NULL;
|
|
scardListReaders = NULL;
|
|
scardCancel = NULL;
|
|
scardGetAttrib = NULL;
|
|
scardSetAttrib = NULL;
|
|
scardT0Pci = NULL;
|
|
scardT1Pci = NULL;
|
|
scardRawPci = NULL;
|
|
|
|
bInitialized = false;
|
|
}
|
|
|
|
SCARDCONTEXT SCardLoader::GetSCardContext()
|
|
{
|
|
return hScardContext;
|
|
}
|
|
|
|
LONG SCardLoader::SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardEstablishContext(dwScope, pvReserved1, pvReserved2, phContext);
|
|
}
|
|
|
|
LONG SCardLoader::SCardReleaseContext(SCARDCONTEXT hContext)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardReleaseContext(hContext);
|
|
}
|
|
|
|
LONG SCardLoader::SCardIsValidContext(SCARDCONTEXT hContext)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardIsValidContext(hContext);
|
|
}
|
|
|
|
#ifndef TC_MACOSX
|
|
LONG SCardLoader::SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardFreeMemory(hContext, pvMem);
|
|
}
|
|
#endif
|
|
|
|
LONG SCardLoader::SCardConnect(SCARDCONTEXT hContext, LPCTSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardConnect(hContext, szReader, dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol);
|
|
}
|
|
|
|
LONG SCardLoader::SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardReconnect(hCard, dwShareMode, dwPreferredProtocols, dwInitialization, pdwActiveProtocol);
|
|
}
|
|
|
|
LONG SCardLoader::SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardDisconnect(hCard, dwDisposition);
|
|
}
|
|
|
|
LONG SCardLoader::SCardBeginTransaction(SCARDHANDLE hCard)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardBeginTransaction(hCard);
|
|
}
|
|
|
|
LONG SCardLoader::SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardEndTransaction(hCard, dwDisposition);
|
|
}
|
|
|
|
LONG SCardLoader::SCardStatus(SCARDHANDLE hCard, LPTSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, BYTE* pbAtr, LPDWORD pcbAtrLen)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardStatus(hCard, mszReaderNames, pcchReaderLen, pdwState, pdwProtocol, pbAtr, pcbAtrLen);
|
|
}
|
|
|
|
LONG SCardLoader::SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, LPSCARD_READERSTATE rgReaderStates, DWORD cReaders)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardGetStatusChange(hContext, dwTimeout, rgReaderStates, cReaders);
|
|
}
|
|
|
|
LONG SCardLoader::SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardControl(hCard, dwControlCode, pbSendBuffer, cbSendLength, pbRecvBuffer, cbRecvLength, lpBytesReturned);
|
|
}
|
|
|
|
LONG SCardLoader::SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci, const BYTE* pbSendBuffer, DWORD cbSendLength, LPSCARD_IO_REQUEST pioRecvPci, BYTE* pbRecvBuffer, LPDWORD pcbRecvLength)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardTransmit(hCard, pioSendPci, pbSendBuffer, cbSendLength, pioRecvPci, pbRecvBuffer, pcbRecvLength);
|
|
}
|
|
|
|
LONG SCardLoader::SCardListReaderGroups(SCARDCONTEXT hContext, LPTSTR mszGroups, LPDWORD pcchGroups)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardListReaderGroups(hContext, mszGroups, pcchGroups);
|
|
}
|
|
|
|
LONG SCardLoader::SCardListReaders(SCARDCONTEXT hContext, LPCTSTR mszGroups, LPTSTR mszReaders, LPDWORD pcchReaders)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardListReaders(hContext, mszGroups, mszReaders, pcchReaders);
|
|
}
|
|
|
|
LONG SCardLoader::SCardCancel(SCARDCONTEXT hContext)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardCancel(hContext);
|
|
}
|
|
|
|
LONG SCardLoader::SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, BYTE* pbAttr, LPDWORD pcbAttrLen)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardGetAttrib(hCard, dwAttrId, pbAttr, pcbAttrLen);
|
|
}
|
|
|
|
LONG SCardLoader::SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, const BYTE* pbAttr, DWORD cbAttrLen)
|
|
{
|
|
Initialize();
|
|
|
|
if (!bInitialized)
|
|
throw ScardLibraryInitializationFailed();
|
|
|
|
return scardSetAttrib(hCard, dwAttrId, pbAttr, cbAttrLen);
|
|
}
|
|
} |