#include "internal.h"
#include "VirtualSCReader.h"
#include "reader.h"
#include "device.h"
#include <winscard.h>
#include "memory.h"
#include <Sddl.h>
#include "SectionLocker.h"
void Reader::init(wchar_t *section) {
section;
state=SCARD_ABSENT;
}
void Reader::IoSmartCardIsPresent(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize) {
UNREFERENCED_PARAMETER(inBufSize);
UNREFERENCED_PARAMETER(outBufSize);
OutputDebugString(L"[BixVReader][IPRE]IOCTL_SMARTCARD_IS_PRESENT");
if (CheckATR()) {
// there's a smart card present, so complete the request
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(STATUS_SUCCESS, 0);
}
else {
// there's no smart card present, so leave the request pending; it will be completed later
SectionLocker lock(device->m_RequestLock);
waitInsertIpr=pRequest;
IRequestCallbackCancel *callback;
device->QueryInterface(__uuidof(IRequestCallbackCancel),(void**)&callback);
pRequest->MarkCancelable(callback);
callback->Release();
}
}
void Reader::IoSmartCardGetState(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize) {
UNREFERENCED_PARAMETER(inBufSize);
UNREFERENCED_PARAMETER(outBufSize);
OutputDebugString(L"[BixVReader][GSTA]IOCTL_SMARTCARD_GET_STATE");
wchar_t log[300];
swprintf(log,L"[BixVReader]STATE:%08X",state);
OutputDebugString(log);
setInt(device,pRequest,state);
}
void Reader::IoSmartCardIsAbsent(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize) {
UNREFERENCED_PARAMETER(inBufSize);
UNREFERENCED_PARAMETER(outBufSize);
OutputDebugString(L"[BixVReader][IABS]IOCTL_SMARTCARD_IS_ABSENT");
if (!CheckATR()) {
// there's no smart card present, so complete the request
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(STATUS_SUCCESS, 0);
}
else {
SectionLocker lock(device->m_RequestLock);
// there's a smart card present, so leave the request pending; it will be completed later
waitRemoveIpr=pRequest;
IRequestCallbackCancel *callback;
device->QueryInterface(__uuidof(IRequestCallbackCancel),(void**)&callback);
pRequest->MarkCancelable(callback);
callback->Release();
}
}
void Reader::IoSmartCardPower(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize) {
UNREFERENCED_PARAMETER(inBufSize);
UNREFERENCED_PARAMETER(outBufSize);
OutputDebugString(L"[BixVReader][POWR]IOCTL_SMARTCARD_POWER");
DWORD code=getInt(pRequest);
if (code==SCARD_COLD_RESET) {
OutputDebugString(L"[BixVReader][POWR]SCARD_COLD_RESET");
protocol=0;
powered=1;
state=SCARD_NEGOTIABLE;
}
else if (code==SCARD_WARM_RESET) {
OutputDebugString(L"[BixVReader][POWR]SCARD_WARM_RESET");
protocol=0;
powered=1;
state=SCARD_NEGOTIABLE;
}
else if (code==SCARD_POWER_DOWN) {
OutputDebugString(L"[BixVReader][POWR]SCARD_POWER_DOWN");
protocol=0;
powered=0;
state=SCARD_SWALLOWED;
}
if (code==SCARD_COLD_RESET || code==SCARD_WARM_RESET) {
BYTE ATR[100];
DWORD ATRsize;
if (!QueryATR(ATR,&ATRsize,true))
{
pRequest->CompleteWithInformation(STATUS_NO_MEDIA, 0);
return;
}
setBuffer(device,pRequest,ATR,ATRsize);
}
else {
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(STATUS_SUCCESS, 0);
}
}
void Reader::IoSmartCardSetProtocol(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize) {
UNREFERENCED_PARAMETER(inBufSize);
UNREFERENCED_PARAMETER(outBufSize);
UNREFERENCED_PARAMETER(instance);
DWORD requestedProtocol=getInt(pRequest);
wchar_t log[300];
swprintf(log,L"[BixVReader][SPRT]IOCTL_SMARTCARD_SET_PROTOCOL:%08X",requestedProtocol);
OutputDebugString(log);
BYTE ATR[100];
DWORD ATRsize;
state=SCARD_SPECIFIC;
if (!QueryATR(ATR,&ATRsize,true))
{
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(STATUS_NO_MEDIA, 0);
return;
}
if (((requestedProtocol & SCARD_PROTOCOL_T1) != 0) &&
((availableProtocol & SCARD_PROTOCOL_T1) != 0)) {
protocol = SCARD_PROTOCOL_T1;
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(STATUS_SUCCESS, 0);
OutputDebugString(L"[BixVReader]PROTOCOL SET: T1");
return;
}
if (((requestedProtocol & SCARD_PROTOCOL_T0) != 0) &&
((availableProtocol & SCARD_PROTOCOL_T0) != 0)) {
protocol = SCARD_PROTOCOL_T0;
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(STATUS_SUCCESS, 0);
OutputDebugString(L"[BixVReader]PROTOCOL SET: T0");
return;
}
if (((requestedProtocol & (SCARD_PROTOCOL_DEFAULT)) != 0) &&
((availableProtocol & SCARD_PROTOCOL_T1) != 0)) {
protocol = SCARD_PROTOCOL_T1;
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(STATUS_SUCCESS, 0);
OutputDebugString(L"[BixVReader]PROTOCOL SET: T1");
return;
}
if (((requestedProtocol & (SCARD_PROTOCOL_DEFAULT)) != 0) &&
((availableProtocol & SCARD_PROTOCOL_T0) != 0)) {
protocol = SCARD_PROTOCOL_T0;
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(STATUS_SUCCESS, 0);
OutputDebugString(L"[BixVReader]PROTOCOL SET: T0");
return;
}
{
state=SCARD_NEGOTIABLE;
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0);
}
}
void Reader::IoSmartCardSetAttribute(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize) {
UNREFERENCED_PARAMETER(inBufSize);
UNREFERENCED_PARAMETER(outBufSize);
UNREFERENCED_PARAMETER(instance);
OutputDebugString(L"[BixVReader][SATT]IOCTL_SMARTCARD_SET_ATTRIBUTE");
IWDFMemory *inmem=NULL;
pRequest->GetInputMemory(&inmem);
SIZE_T size;
BYTE *data=(BYTE *)inmem->GetDataBuffer(&size);
DWORD minCode=*(DWORD*)(data);
bool handled=false;
if (minCode==SCARD_ATTR_DEVICE_IN_USE) {
SectionLocker lock(device->m_RequestLock);
OutputDebugString(L"[BixVReader][SATT]SCARD_ATTR_DEVICE_IN_USE");
pRequest->CompleteWithInformation(STATUS_SUCCESS, 0);
handled=true;
}
inmem->Release();
if (!handled) {
SectionLocker lock(device->m_RequestLock);
wchar_t log[300];
swprintf(log,L"[BixVReader][SATT]ERROR_NOT_SUPPORTED:%08X",minCode);
OutputDebugString(log);
pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0);
}
}
void Reader::IoSmartCardTransmit(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize) {
UNREFERENCED_PARAMETER(inBufSize);
UNREFERENCED_PARAMETER(outBufSize);
OutputDebugString(L"[BixVReader][TRSM]IOCTL_SMARTCARD_TRANSMIT");
BYTE APDU[1000];
int APDUSize;
getBuffer(pRequest,APDU,&APDUSize);
if (((SCARD_IO_REQUEST*)APDU)->dwProtocol!=protocol) {
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(STATUS_INVALID_DEVICE_STATE, 0);
return;
}
BYTE Resp[1000];
int RespSize;
if (!QueryTransmit(APDU+sizeof(SCARD_IO_REQUEST),APDUSize-sizeof(SCARD_IO_REQUEST),Resp+sizeof(SCARD_IO_REQUEST),&RespSize))
{
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(STATUS_NO_MEDIA, 0);
return;
}
((SCARD_IO_REQUEST*)Resp)->cbPciLength=sizeof(SCARD_IO_REQUEST);
((SCARD_IO_REQUEST*)Resp)->dwProtocol=protocol;
setBuffer(device,pRequest,Resp,RespSize+sizeof(SCARD_IO_REQUEST));
}
void Reader::IoSmartCardGetAttribute(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize) {
UNREFERENCED_PARAMETER(inBufSize);
wchar_t log[300]=L"";
char temp[300];
DWORD code=getInt(pRequest);
swprintf(log,L"[BixVReader][GATT] - code %0X",code);
OutputDebugString(log);
switch(code) {
case SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA009):
// custom attribute; RPC_TYPE
OutputDebugString(L"[BixVReader][GATT]RPC_TYPE");
setInt(device,pRequest,rpcType);
return;
case SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA00a):
// custom attribute; PipeName
if (rpcType==0) {
PipeReader *pipe=(PipeReader *)this;
OutputDebugString(L"[BixVReader][GATT]PIPE_NAME");
sprintf(temp,"%S",pipe->pipeName);
setString(device,pRequest,(char*)temp,(int)outBufSize);
}
else {
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0);
}
return;
case SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA00b):
// custom attribute; EventPipeName
if (rpcType==0) {
PipeReader *pipe=(PipeReader *)this;
OutputDebugString(L"[BixVReader][GATT]EVENT_PIPE_NAME");
sprintf(temp,"%S",pipe->pipeEventName);
setString(device,pRequest,(char*)temp,(int)outBufSize);
}
else {
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0);
}
return;
case SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA00c):
// custom attribute; TCP port
if (rpcType==1) {
TcpIpReader *tcpIp=(TcpIpReader *)this;
OutputDebugString(L"[BixVReader][GATT]PORT");
setInt(device,pRequest,tcpIp->port);
}
else {
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0);
}
return;
case SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA00d):
// custom attribute; TCP event port
if (rpcType==1) {
TcpIpReader *tcpIp=(TcpIpReader *)this;
OutputDebugString(L"[BixVReader][GATT]EVENT_PORT");
setInt(device,pRequest,tcpIp->eventPort);
}
else {
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0);
}
return;
case SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA00e):
// custom attribute; TCP base port
if (rpcType==1) {
TcpIpReader *tcpIp=(TcpIpReader *)this;
OutputDebugString(L"[BixVReader][GATT]BASE_PORT");
setInt(device,pRequest,tcpIp->portBase);
tcpIp;
}
else {
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0);
}
return;
case SCARD_ATTR_CHARACTERISTICS:
// 0x00000000 No special characteristics
OutputDebugString(L"[BixVReader][GATT]SCARD_ATTR_CHARACTERISTICS");
setInt(device,pRequest,0);
return;
case SCARD_ATTR_VENDOR_NAME:
OutputDebugString(L"[BixVReader][GATT]SCARD_ATTR_VENDOR_NAME");
setString(device,pRequest,vendorName,(int)outBufSize);
return;
case SCARD_ATTR_VENDOR_IFD_TYPE:
OutputDebugString(L"[BixVReader][GATT]SCARD_ATTR_VENDOR_IFD_TYPE");
setString(device,pRequest,vendorIfdType,(int)outBufSize);
return;
case SCARD_ATTR_DEVICE_UNIT:
OutputDebugString(L"[BixVReader][GATT]SCARD_ATTR_DEVICE_UNIT");
setInt(device,pRequest,deviceUnit);
return;
case SCARD_ATTR_ATR_STRING:
OutputDebugString(L"[BixVReader][GATT]SCARD_ATTR_ATR_STRING");
BYTE ATR[100];
DWORD ATRsize;
if (!QueryATR(ATR,&ATRsize))
{
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(STATUS_NO_MEDIA, 0);
return;
}
setBuffer(device,pRequest,ATR,ATRsize);
return;
case SCARD_ATTR_CURRENT_PROTOCOL_TYPE:
OutputDebugString(L"[BixVReader][GATT]SCARD_ATTR_CURRENT_PROTOCOL_TYPE");
setInt(device,pRequest,protocol); // T=0 or T=1
return;
default: {
swprintf(log,L"[BixVReader][GATT]ERROR_NOT_SUPPORTED:%08X",code);
OutputDebugString(log);
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0);
}
}
}
bool Reader::CheckATR() {
return false;
}
bool Reader::QueryTransmit(BYTE *APDU,int APDUlen,BYTE *Resp,int *Resplen) {
APDU;
APDUlen;
Resp;
Resplen;
return false;
}
bool Reader::QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset) {
ATR;
ATRsize;
reset;
return false;
}
bool Reader::initProtocols() {
// ask ATR to determine available protocols
BYTE ATR[100];
DWORD ATRsize=100;
availableProtocol=0;
if (QueryATR(ATR,&ATRsize,true))
{
availableProtocol=0;
int iNumHistBytes=0;
int iTotHistBytes=0;
int y=0;
int block=1;
bool isHist=false;
char let='A';
for (unsigned int i=0;i<ATRsize && ! isHist;i++) {
if (i==0) {
// we are in TS
}
else if (i==1) {
// we are in T0; read number of historical bytes
let='A';
y=ATR[i] >> 4;
iTotHistBytes=ATR[i] & 0xF;
}
else {
while ((y & 1)==0) {
let++;
y>>=1;
if (y==0) {
isHist=true;
iNumHistBytes=1;
i--;
goto end;
}
}
// we are in T(let)(block)
y=y & 0xE;
if (let=='D') {
// check available protocol(s)
int protocol=(ATR[i] & 0x0f);
availableProtocol|=1 << protocol;
// prepare for next block
let='A';
y=ATR[i] >> 4;
block++;
}
}
end:
;
}
//support at least T=0
if (availableProtocol==0)
availableProtocol=1;
return true;
}
return false;
}
DWORD Reader::startServer() {
return 0;
}
void Reader::shutdown() {
}