#include "internal.h" #include "VirtualSCReader.h" #include "reader.h" #include "device.h" #include #include "memory.h" #include #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.push_back(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.push_back(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> 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() { }