173 lines
4.0 KiB
C++
173 lines
4.0 KiB
C++
#include "internal.h"
|
|
#include "VirtualSCReader.h"
|
|
#include "reader.h"
|
|
#include "device.h"
|
|
#include <winscard.h>
|
|
#include "memory.h"
|
|
#include <Sddl.h>
|
|
#include "sectionLocker.h"
|
|
#include "../../src/vpcd/vpcd.h"
|
|
|
|
|
|
int VpcdReader::portBase;
|
|
|
|
VpcdReader::VpcdReader() {
|
|
rpcType=2;
|
|
state = SCARD_ABSENT;
|
|
cardPresent = false;
|
|
InitializeCriticalSection(&ioSection);
|
|
}
|
|
|
|
VpcdReader::~VpcdReader() {
|
|
DeleteCriticalSection(&ioSection);
|
|
}
|
|
void VpcdReader::init(wchar_t *section) {
|
|
portBase=GetPrivateProfileInt(L"Driver",L"RPC_PORT_BASE",VPCDPORT,L"BixVReader.ini");
|
|
|
|
port=(short) GetPrivateProfileInt(section,L"TCP_PORT",portBase+instance,L"BixVReader.ini");
|
|
}
|
|
|
|
bool VpcdReader::CheckATR() {
|
|
bool r = false;
|
|
|
|
if (vicc_present((struct vicc_ctx *) ctx) == 1) {
|
|
r = true;
|
|
}
|
|
|
|
|
|
if (r) {
|
|
signalInsertion();
|
|
}
|
|
else {
|
|
signalRemoval();
|
|
}
|
|
|
|
return r;
|
|
}
|
|
bool VpcdReader::QueryTransmit(BYTE *APDU,int APDUlen,BYTE *Resp,int *Resplen) {
|
|
unsigned char *rapdu = NULL;
|
|
ssize_t rapdu_len;
|
|
bool r = false;
|
|
|
|
if (APDU && APDUlen && Resp && Resplen) {
|
|
rapdu_len = vicc_transmit((struct vicc_ctx *) ctx, APDUlen, APDU, &rapdu);
|
|
if (rapdu_len > 0) {
|
|
memcpy(Resp, rapdu, rapdu_len);
|
|
*Resplen = rapdu_len;
|
|
free(rapdu);
|
|
r = true;
|
|
} else {
|
|
signalRemoval();
|
|
}
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
bool VpcdReader::QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset) {
|
|
unsigned char *atr = NULL;
|
|
int atr_len;
|
|
bool r = false;
|
|
|
|
if (ATR && ATRsize) {
|
|
atr_len = vicc_getatr((struct vicc_ctx *) ctx, &atr);
|
|
if (atr_len > 0) {
|
|
/* TODO do length checking on length of ATR when ATRsize is
|
|
* correctly initialized by Reader.cpp */
|
|
memcpy(ATR, atr, atr_len);
|
|
*ATRsize = atr_len;
|
|
free(atr);
|
|
r = true;
|
|
if (reset) {
|
|
vicc_reset((struct vicc_ctx *) ctx);
|
|
}
|
|
} else {
|
|
signalRemoval();
|
|
}
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
DWORD VpcdReader::startServer() {
|
|
breakSocket = false;
|
|
ctx = vicc_init(NULL, port);
|
|
while (!breakSocket) {
|
|
CheckATR();
|
|
Sleep(1000);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void VpcdReader::shutdown() {
|
|
breakSocket=true;
|
|
WaitForSingleObject(serverThread,10000);
|
|
serverThread = NULL;
|
|
vicc_exit((struct vicc_ctx *) ctx);
|
|
state=SCARD_ABSENT;
|
|
ctx = NULL;
|
|
if (!waitRemoveIpr.empty()) {
|
|
SectionLocker lock(device->m_RequestLock);
|
|
while (!waitRemoveIpr.empty()) {
|
|
CComPtr<IWDFIoRequest> ipr = waitRemoveIpr.back();
|
|
if (ipr->UnmarkCancelable()==S_OK)
|
|
ipr->Complete(HRESULT_FROM_WIN32(ERROR_CANCELLED));
|
|
waitRemoveIpr.pop_back();
|
|
}
|
|
}
|
|
while (!waitInsertIpr.empty()) {
|
|
SectionLocker lock(device->m_RequestLock);
|
|
CComPtr<IWDFIoRequest> ipr = waitInsertIpr.back();
|
|
if (ipr->UnmarkCancelable()==S_OK)
|
|
ipr->Complete(HRESULT_FROM_WIN32(ERROR_CANCELLED));
|
|
waitInsertIpr.pop_back();
|
|
}
|
|
}
|
|
|
|
void VpcdReader::signalRemoval(void) {
|
|
if (cardPresent) {
|
|
cardPresent = false;
|
|
state=SCARD_ABSENT;
|
|
if (!waitRemoveIpr.empty()) {
|
|
SectionLocker lock(device->m_RequestLock);
|
|
while (!waitRemoveIpr.empty()) {
|
|
CComPtr<IWDFIoRequest> ipr = waitRemoveIpr.back();
|
|
if (ipr->UnmarkCancelable()==S_OK) {
|
|
ipr->CompleteWithInformation(STATUS_SUCCESS, 0);
|
|
}
|
|
waitRemoveIpr.pop_back();
|
|
}
|
|
}
|
|
if (!waitInsertIpr.empty()) {
|
|
SectionLocker lock(device->m_RequestLock);
|
|
while (!waitInsertIpr.empty()) {
|
|
CComPtr<IWDFIoRequest> ipr = waitInsertIpr.back();
|
|
SectionLocker lock(device->m_RequestLock);
|
|
if (ipr->UnmarkCancelable()==S_OK) {
|
|
ipr->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_CANCELLED), 0);
|
|
}
|
|
waitInsertIpr.pop_back();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void VpcdReader::signalInsertion(void) {
|
|
if (!cardPresent) {
|
|
cardPresent = true;
|
|
while (!waitInsertIpr.empty()) {
|
|
if (initProtocols()) {
|
|
SectionLocker lock(device->m_RequestLock);
|
|
while (!waitInsertIpr.empty()) {
|
|
CComPtr<IWDFIoRequest> ipr = waitInsertIpr.back();
|
|
if (ipr->UnmarkCancelable()==S_OK) {
|
|
ipr->CompleteWithInformation(STATUS_SUCCESS, 0);
|
|
}
|
|
waitInsertIpr.pop_back();
|
|
}
|
|
state=SCARD_SWALLOWED;
|
|
}
|
|
}
|
|
}
|
|
}
|