Rename BixV Reader to VivoKey Smart Reader

This commit is contained in:
Christoph Honal
2023-10-12 00:12:52 +02:00
parent d2e607f4c6
commit 1d71760f34
36 changed files with 172 additions and 171 deletions

View File

@@ -0,0 +1,138 @@
#include "internal.h"
class CVirtualSmartCardDriverModule : public CAtlDllModuleT<CVirtualSmartCardDriverModule> {} _AtlModule;
/////////////////////////////////////////////////////////////////////////
//
// DllMain
//
// This is the main DLL Entry Point.
//
// Parameters:
// hInstance - Handle to the DLL module
// dwReason - Indicates why the DLL entry point is being called
// lpReserved - Additional information based on dwReason
//
// Return Values:
// TRUE = initialization succeeds
// FALSE = initialization fails
//
/////////////////////////////////////////////////////////////////////////
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance,
DWORD dwReason,
LPVOID lpReserved)
{
inFunc
(lpReserved);
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hInstance);
break;
case DLL_PROCESS_DETACH:
_AtlModule.Term();
break;
default:
break;
}
// Call the ATL module class so it can initialize
return _AtlModule.DllMain(dwReason, lpReserved);
}
/////////////////////////////////////////////////////////////////////////
//
// DllCanUnloadNow
//
// Used to determine whether the DLL can be unloaded by OLE
//
// Parameters:
// void - (unused argument)
//
// Return Values:
// S_OK: DLL can be unloaded
// S_FALSE: DLL cannot be unloaded now
//
/////////////////////////////////////////////////////////////////////////
STDAPI DllCanUnloadNow(void)
{
inFunc
return _AtlModule.DllCanUnloadNow();
}
/////////////////////////////////////////////////////////////////////////
//
// DllGetClassObject
//
// Returns a class factory to create an object of the requested type
//
// Parameters:
// rclsid - CLSID that will associate the correct data and code
// riid - Reference to the IID the caller will use
// ppv - pointer to an interface pointer requested in riid
//
// Return Values:
// S_OK: The object was retrieved successfully.
// CLASS_E_CLASSNOTAVAILABLE: The DLL does not support the class
//
/////////////////////////////////////////////////////////////////////////
STDAPI DllGetClassObject(__in REFCLSID rclsid, __in REFIID riid, __deref_out LPVOID* ppv)
{
inFunc
return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
}
/////////////////////////////////////////////////////////////////////////
//
// DllRegisterServer
//
// Adds entries to the system registry
//
// Parameters:
// void - (unused argument)
//
// Return Values:
// S_OK: The registry entries were created successfully
// SELFREG_E_TYPELIB: The server was unable to complete the
// registration of all the type libraries used by its classes
// SELFREG_E_CLASS: The server was unable to complete the
// registration of all the object classes
//
/////////////////////////////////////////////////////////////////////////
STDAPI DllRegisterServer(void)
{
inFunc
return S_OK;
}
/////////////////////////////////////////////////////////////////////////
//
// DllUnregisterServer
//
// Removes entries from the system registry
//
// Parameters:
// void - (unused argument)
//
// Return Values:
// S_OK: The registry entries were removed successfully
// S_FALSE: Unregistration of known entries was successful, but
// other entries still exist for this server's classes
// SELFREG_E_TYPELIB: The server was unable to remove the entries
// of all the type libraries used by its classes
// SELFREG_E_CLASS: The server was unable to to remove the entries
// of all the object classes
//
/////////////////////////////////////////////////////////////////////////
STDAPI DllUnregisterServer(void)
{
inFunc
return S_OK;
}

View File

@@ -0,0 +1,286 @@
#include "internal.h"
#include "VirtualSCReader.h"
#include "reader.h"
#include "device.h"
#include <winscard.h>
#include "memory.h"
#include <Sddl.h>
#include "sectionLocker.h"
BOOL CreateMyDACL(SECURITY_ATTRIBUTES * pSA)
{
TCHAR * szSD = TEXT("D:") // Discretionary ACL
TEXT("(D;OICI;GA;;;BG)") // Deny access to
// built-in guests
TEXT("(D;OICI;GA;;;AN)") // Deny access to
// anonymous logon
TEXT("(A;OICI;GRGWGX;;;AU)") // Allow
// read/write/execute
// to authenticated
// users
TEXT("(A;OICI;GA;;;BA)"); // Allow full control
// to administrators
if (NULL == pSA)
return FALSE;
return ConvertStringSecurityDescriptorToSecurityDescriptor(
szSD,
SDDL_REVISION_1,
&(pSA->lpSecurityDescriptor),
NULL);
}
PipeReader::PipeReader() {
rpcType=0;
state=SCARD_ABSENT;
InitializeCriticalSection(&eventSection);
InitializeCriticalSection(&dataSection);
}
void PipeReader::init(wchar_t *section) {
wchar_t temp[300];
swprintf(temp,L"SCardSimulatorDriver%i",instance);
GetPrivateProfileStringW(section,L"PIPE_NAME",temp,pipeName,300,L"VivoKeySmartReader.ini");
swprintf(temp,L"SCardSimulatorDriverEvents%i",instance);
GetPrivateProfileStringW(section,L"PIPE_EVENT_NAME",temp,pipeEventName,300,L"VivoKeySmartReader.ini");
}
bool PipeReader::CheckATR() {
if (pipe==NULL)
return false;
DWORD read=0;
DWORD command=1;
if (!WriteFile(pipe,&command,sizeof(DWORD),&read,NULL)) {
return false;
}
FlushFileBuffers(pipe);
DWORD size=0;
if (!ReadFile(pipe,&size,sizeof(DWORD),&read,NULL)) {
return false;
}
if (size==0)
return false;
BYTE ATR[100];
if (!ReadFile(pipe,ATR,size,&read,NULL)) {
return false;
}
return true;
}
bool PipeReader::QueryTransmit(BYTE *APDU,int APDUlen,BYTE **Resp,int *Resplen) {
if (pipe==NULL)
return false;
DWORD command=2;
DWORD read=0;
if (!WriteFile(pipe,&command,sizeof(DWORD),&read,NULL)) {
pipe=NULL;
return false;
}
DWORD dwAPDUlen=(DWORD)APDUlen;
if (!WriteFile(pipe,&dwAPDUlen,sizeof(DWORD),&read,NULL)) {
pipe=NULL;
return false;
}
if (!WriteFile(pipe,APDU,APDUlen,&read,NULL)) {
pipe=NULL;
return false;
}
FlushFileBuffers(pipe);
DWORD dwRespLen=0;
if (!ReadFile(pipe,&dwRespLen,sizeof(DWORD),&read,NULL)) {
pipe=NULL;
return false;
}
if (0 != dwRespLen) {
BYTE *p=(BYTE *)realloc(*Resp, dwRespLen);
if (p==NULL) {
pipe=NULL;
return false;
}
*Resp=p;
}
if (!ReadFile(pipe,*Resp,dwRespLen,&read,NULL)) {
pipe=NULL;
return false;
}
(*Resplen)=(int)dwRespLen;
return true;
}
bool PipeReader::QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset) {
if (pipe==NULL)
return false;
DWORD command=reset ? 0 : 1;
DWORD read=0;
if (!WriteFile(pipe,&command,sizeof(DWORD),&read,NULL)) {
pipe=NULL;
return false;
}
FlushFileBuffers(pipe);
DWORD size=0;
if (!ReadFile(pipe,&size,sizeof(DWORD),&read,NULL)) {
pipe=NULL;
return false;
}
if (size==0)
return false;
if (!ReadFile(pipe,ATR,size,&read,NULL)) {
pipe=NULL;
return false;
}
(*ATRsize)=size;
return true;
}
DWORD PipeReader::startServer() {
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = FALSE;
CreateMyDACL(&sa);
wchar_t temp[300];
swprintf(temp,L"\\\\.\\pipe\\%s",pipeName);
HANDLE _pipe=CreateNamedPipe(temp,PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,PIPE_TYPE_BYTE,PIPE_UNLIMITED_INSTANCES,0,0,0,&sa);
swprintf(temp,L"\\\\.\\pipe\\%s",pipeEventName);
HANDLE _eventpipe=CreateNamedPipe(temp,PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,PIPE_TYPE_BYTE,PIPE_UNLIMITED_INSTANCES,0,0,0,&sa);
wchar_t log[300];
swprintf(log,L"[VivoKeySmartReader]Pipe created:%s:%p",pipeName,_pipe);
OutputDebugString(log);
while (true) {
//__try {
BOOL ris=ConnectNamedPipe(_pipe,NULL);
if (ris==0) {
swprintf(log,L"[VivoKeySmartReader]Pipe NOT connected:%x",GetLastError());
OutputDebugString(log);
}
else {
swprintf(log,L"[VivoKeySmartReader]Pipe connected");
OutputDebugString(log);
}
ris=ConnectNamedPipe(_eventpipe,NULL);
if (ris==0) {
swprintf(log,L"[VivoKeySmartReader]Event Pipe NOT connected:%x",GetLastError());
OutputDebugString(log);
}
else {
swprintf(log,L"[VivoKeySmartReader]Event Pipe connected");
OutputDebugString(log);
}
pipe=_pipe;
eventpipe=_eventpipe;
if (!waitInsertIpr.empty()) {
// if I'm waiting for card insertion, verify if there's a card present
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;
}
}
while (true) {
// wait for a command
DWORD command=0;
DWORD read=0;
if (!ReadFile(eventpipe,&command,sizeof(DWORD),&read,NULL)) {
state=SCARD_ABSENT;
OutputDebugString(L"[VivoKeySmartReader]Pipe error");
powered=0;
pipe=NULL;
eventpipe=NULL;
if (!waitRemoveIpr.empty()) {
// card inserted
SectionLocker lock(device->m_RequestLock);
while (!waitRemoveIpr.empty()) {
CComPtr<IWDFIoRequest> ipr = waitRemoveIpr.back();
OutputDebugString(L"[VivoKeySmartReader]complete Wait Remove");
if (ipr->UnmarkCancelable()==S_OK) {
OutputDebugString(L"[VivoKeySmartReader]Wait Remove Unmarked");
ipr->CompleteWithInformation(STATUS_SUCCESS, 0);
OutputDebugString(L"[VivoKeySmartReader]Wait Remove Completed");
}
waitRemoveIpr.pop_back();
}
}
if (!waitInsertIpr.empty()) {
// card removed
SectionLocker lock(device->m_RequestLock);
while (!waitInsertIpr.empty()) {
CComPtr<IWDFIoRequest> ipr = waitInsertIpr.back();
OutputDebugString(L"[VivoKeySmartReader]cancel Wait Remove");
if (ipr->UnmarkCancelable()==S_OK) {
OutputDebugString(L"[VivoKeySmartReader]Wait Insert Unmarked");
ipr->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_CANCELLED), 0);
OutputDebugString(L"[VivoKeySmartReader]Wait Insert Cancelled");
}
waitInsertIpr.pop_back();
}
}
DisconnectNamedPipe(_pipe);
DisconnectNamedPipe(_eventpipe);
break;
}
OutputDebugString(L"[VivoKeySmartReader]Pipe data");
if (command==0)
powered=0;
if (command==0 && !waitRemoveIpr.empty()) {
// card removed
SectionLocker lock(device->m_RequestLock);
state=SCARD_ABSENT;
while (!waitRemoveIpr.empty()) {
CComPtr<IWDFIoRequest> ipr = waitRemoveIpr.back();
if (ipr->UnmarkCancelable()==S_OK)
ipr->CompleteWithInformation(STATUS_SUCCESS, 0);
waitRemoveIpr.pop_back();
}
}
else if (command==1 && !waitInsertIpr.empty()) {
// card inserted
SectionLocker lock(device->m_RequestLock);
state=SCARD_SWALLOWED;
initProtocols();
while (!waitInsertIpr.empty()) {
CComPtr<IWDFIoRequest> ipr = waitInsertIpr.back();
if (ipr->UnmarkCancelable()==S_OK)
ipr->CompleteWithInformation(STATUS_SUCCESS, 0);
waitInsertIpr.pop_back();
}
}
}
//}
//__except(EXCEPTION_EXECUTE_HANDLER) {
// wchar_t log[300];
// DWORD err=GetExceptionCode();
// swprintf(log,L"Exception:%08X",err);
// OutputDebugString(log);
//}
}
OutputDebugString(L"[VivoKeySmartReader]Pipe quit!!!");
return 0;
}
void PipeReader::shutdown() {
state=SCARD_ABSENT;
while (!waitRemoveIpr.empty()) {
SectionLocker lock(device->m_RequestLock);
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 = waitRemoveIpr.back();
if (ipr->UnmarkCancelable()==S_OK)
ipr->Complete(HRESULT_FROM_WIN32(ERROR_CANCELLED));
waitInsertIpr.pop_back();
}
}

View File

@@ -0,0 +1,124 @@
#include "internal.h"
#include "Device.h"
#include "Queue.h"
#include "SectionLocker.h"
/////////////////////////////////////////////////////////////////////////
//
// CMyQueue::CMyQueue
//
// Object constructor function
//
// Initialize member variables
//
/////////////////////////////////////////////////////////////////////////
CMyQueue::CMyQueue() :
m_pParentDevice(NULL)
{
}
/////////////////////////////////////////////////////////////////////////
//
// CMyQueue::~CMyQueue
//
// Object destructor function
//
//
/////////////////////////////////////////////////////////////////////////
CMyQueue::~CMyQueue()
{
// Release the reference that was incremented in CreateInstance()
SAFE_RELEASE(m_pParentDevice);
}
/////////////////////////////////////////////////////////////////////////
//
// CMyQueue::CreateInstance
//
// This function supports the COM factory creation system
//
// Parameters:
// parentDevice - A pointer to the CWSSDevice object
// ppUkwn - pointer to a pointer to the queue to be returned
//
// Return Values:
// S_OK: The queue was created successfully
//
/////////////////////////////////////////////////////////////////////////
HRESULT CMyQueue::CreateInstance(__in IWDFDevice* pWdfDevice, CMyDevice* pMyDevice)
{
inFunc
SectionLogger a(__FUNCTION__);
CComObject<CMyQueue>* pMyQueue = NULL;
if(NULL == pMyDevice)
{
return E_INVALIDARG;
}
HRESULT hr = CComObject<CMyQueue>::CreateInstance(&pMyQueue);
if(SUCCEEDED(hr))
{
// AddRef the object
pMyQueue->AddRef();
// Store the parent device object
pMyQueue->m_pParentDevice = pMyDevice;
// Increment the reference for the lifetime of the CMyQueue object.
pMyQueue->m_pParentDevice->AddRef();
CComPtr<IUnknown> spIUnknown;
hr = pMyQueue->QueryInterface(IID_IUnknown, (void**)&spIUnknown);
if(SUCCEEDED(hr))
{
// Create the framework queue
CComPtr<IWDFIoQueue> spDefaultQueue;
hr = pWdfDevice->CreateIoQueue( spIUnknown,
TRUE, // DefaultQueue
WdfIoQueueDispatchParallel, // Parallel queue handling
FALSE, // PowerManaged
TRUE, // AllowZeroLengthRequests
&spDefaultQueue
);
if (FAILED(hr))
{
OutputDebugString (L"[VivoKeySmartReader]IoQueue NOT Created\n");
}
else
OutputDebugString (L"[VivoKeySmartReader]IoQueue Created\n");
}
// Release the pMyQueue pointer when done. Note: UMDF holds a reference to it above
SAFE_RELEASE(pMyQueue);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////
//
// CMyQueue::OnDeviceIoControl
//
// This method is called when an IOCTL is sent to the device
//
// Parameters:
// pQueue - pointer to an IO queue
// pRequest - pointer to an IO request
// ControlCode - The IOCTL to process
// InputBufferSizeInBytes - the size of the input buffer
// OutputBufferSizeInBytes - the size of the output buffer
//
/////////////////////////////////////////////////////////////////////////
STDMETHODIMP_ (void) CMyQueue::OnDeviceIoControl(
__in IWDFIoQueue* pQueue,
__in IWDFIoRequest* pRequest,
__in ULONG ControlCode,
SIZE_T InputBufferSizeInBytes,
SIZE_T OutputBufferSizeInBytes
)
{
m_pParentDevice->ProcessIoControl(pQueue,pRequest,ControlCode,InputBufferSizeInBytes,OutputBufferSizeInBytes);
}

View File

@@ -0,0 +1,36 @@
#pragma once
class ATL_NO_VTABLE CMyQueue :
public CComObjectRootEx<CComMultiThreadModel>,
public IQueueCallbackDeviceIoControl
{
public:
virtual ~CMyQueue();
DECLARE_NOT_AGGREGATABLE(CMyQueue)
BEGIN_COM_MAP(CMyQueue)
COM_INTERFACE_ENTRY(IQueueCallbackDeviceIoControl)
END_COM_MAP()
static HRESULT CreateInstance(__in IWDFDevice* pWdfDevice, CMyDevice* pMyDevice);
protected:
CMyQueue();
// COM Interface methods
public:
// IQueueCallbackDeviceIoControl
STDMETHOD_ (void, OnDeviceIoControl)(
__in IWDFIoQueue* pQueue,
__in IWDFIoRequest* pRequest,
__in ULONG ControlCode,
SIZE_T InputBufferSizeInBytes,
SIZE_T OutputBufferSizeInBytes
);
private:
CMyDevice* m_pParentDevice; // Parent device object
};

View File

@@ -0,0 +1,440 @@
#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"[VivoKeySmartReader][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"[VivoKeySmartReader][GSTA]IOCTL_SMARTCARD_GET_STATE");
wchar_t log[300];
swprintf(log,L"[VivoKeySmartReader]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"[VivoKeySmartReader][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"[VivoKeySmartReader][POWR]IOCTL_SMARTCARD_POWER");
DWORD code=getInt(pRequest);
if (code==SCARD_COLD_RESET) {
OutputDebugString(L"[VivoKeySmartReader][POWR]SCARD_COLD_RESET");
protocol=0;
powered=1;
state=SCARD_NEGOTIABLE;
}
else if (code==SCARD_WARM_RESET) {
OutputDebugString(L"[VivoKeySmartReader][POWR]SCARD_WARM_RESET");
protocol=0;
powered=1;
state=SCARD_NEGOTIABLE;
}
else if (code==SCARD_POWER_DOWN) {
OutputDebugString(L"[VivoKeySmartReader][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"[VivoKeySmartReader][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"[VivoKeySmartReader]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"[VivoKeySmartReader]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"[VivoKeySmartReader]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"[VivoKeySmartReader]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"[VivoKeySmartReader][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"[VivoKeySmartReader][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"[VivoKeySmartReader][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"[VivoKeySmartReader][TRSM]IOCTL_SMARTCARD_TRANSMIT");
SCARD_IO_REQUEST *scardRequest=NULL;
int scardRequestSize=0;
BYTE *RAPDU=NULL;
int RAPDUSize=0;
if (!getBuffer(pRequest,(void **)&scardRequest,&scardRequestSize)
|| scardRequestSize<sizeof *scardRequest
|| scardRequest->dwProtocol!=protocol) {
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(STATUS_INVALID_DEVICE_STATE, 0);
goto end;
}
if (!QueryTransmit((BYTE *)(scardRequest+1),
scardRequestSize-sizeof(SCARD_IO_REQUEST),
&RAPDU,&RAPDUSize))
{
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(STATUS_NO_MEDIA, 0);
goto end;
}
SCARD_IO_REQUEST *p=(SCARD_IO_REQUEST *)realloc(scardRequest,RAPDUSize+sizeof(SCARD_IO_REQUEST));
if (p==NULL) {
SectionLocker lock(device->m_RequestLock);
pRequest->CompleteWithInformation(STATUS_INVALID_DEVICE_STATE, 0);
goto end;
}
scardRequest = p;
scardRequest->cbPciLength=sizeof(SCARD_IO_REQUEST);
scardRequest->dwProtocol=protocol;
memcpy(scardRequest+1,RAPDU,RAPDUSize);
setBuffer(device,pRequest,scardRequest,RAPDUSize+sizeof(SCARD_IO_REQUEST));
end:
free(scardRequest);
free(RAPDU);
}
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"[VivoKeySmartReader][GATT] - code %0X",code);
OutputDebugString(log);
switch(code) {
case SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA009):
// custom attribute; RPC_TYPE
OutputDebugString(L"[VivoKeySmartReader][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"[VivoKeySmartReader][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"[VivoKeySmartReader][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"[VivoKeySmartReader][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"[VivoKeySmartReader][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"[VivoKeySmartReader][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"[VivoKeySmartReader][GATT]SCARD_ATTR_CHARACTERISTICS");
setInt(device,pRequest,0);
return;
case SCARD_ATTR_VENDOR_NAME:
OutputDebugString(L"[VivoKeySmartReader][GATT]SCARD_ATTR_VENDOR_NAME");
setString(device,pRequest,vendorName,(int)outBufSize);
return;
case SCARD_ATTR_VENDOR_IFD_TYPE:
OutputDebugString(L"[VivoKeySmartReader][GATT]SCARD_ATTR_VENDOR_IFD_TYPE");
setString(device,pRequest,vendorIfdType,(int)outBufSize);
return;
case SCARD_ATTR_DEVICE_UNIT:
OutputDebugString(L"[VivoKeySmartReader][GATT]SCARD_ATTR_DEVICE_UNIT");
setInt(device,pRequest,deviceUnit);
return;
case SCARD_ATTR_ATR_STRING:
OutputDebugString(L"[VivoKeySmartReader][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"[VivoKeySmartReader][GATT]SCARD_ATTR_CURRENT_PROTOCOL_TYPE");
setInt(device,pRequest,protocol); // T=0 or T=1
return;
default: {
swprintf(log,L"[VivoKeySmartReader][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)
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() {
}

View File

@@ -0,0 +1,108 @@
#pragma once
#include <Winsock2.h>
#include <vector>
class CMyDevice;
class Reader {
public:
CMyDevice *device;
std::vector< CComPtr<IWDFIoRequest> > waitRemoveIpr;
std::vector< CComPtr<IWDFIoRequest> > waitInsertIpr;
inbuf;
outbuf;
HANDLE serverThread;
char vendorName[300];
char vendorIfdType[300];
int deviceUnit;
int powered;
int instance;
int rpcType;
int state;
DWORD protocol; // T0 or T1 - protocol in use
DWORD availableProtocol; // T0, T1 or Both - protocols available
void IoSmartCardGetAttribute(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize);
void IoSmartCardIsPresent(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize);
void IoSmartCardGetState(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize);
void IoSmartCardIsAbsent(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize);
void IoSmartCardPower(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize);
void IoSmartCardSetAttribute(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize);
void IoSmartCardSetProtocol(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize);
void IoSmartCardTransmit(IWDFIoRequest* pRequest,SIZE_T inBufSize,SIZE_T outBufSize);
bool initProtocols();
virtual bool QueryTransmit(BYTE *APDU,int APDUlen,BYTE **Resp,int *Resplen);
virtual bool QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset=false);
virtual bool CheckATR();
virtual DWORD startServer();
virtual void shutdown();
virtual void init(wchar_t *section);
};
class PipeReader : public Reader {
public:
wchar_t pipeName[300];
wchar_t pipeEventName[300];
HANDLE pipe;
HANDLE eventpipe;
PipeReader();
bool QueryTransmit(BYTE *APDU,int APDUlen,BYTE **Resp,int *Resplen);
bool QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset=false);
bool CheckATR();
DWORD startServer();
void shutdown();
void init(wchar_t *section);
CRITICAL_SECTION eventSection;
CRITICAL_SECTION dataSection;
};
class TcpIpReader : public Reader {
public:
static int portBase;
int port;
int eventPort;
SOCKET socket;
SOCKET AcceptSocket;
SOCKET eventsocket;
bool breakSocket;
TcpIpReader();
bool QueryTransmit(BYTE *APDU,int APDUlen,BYTE **Resp,int *Resplen);
bool QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset=false);
bool CheckATR();
DWORD startServer();
void shutdown();
void init(wchar_t *section);
CRITICAL_SECTION eventSection;
CRITICAL_SECTION dataSection;
};
class VpcdReader : public Reader {
public:
static int portBase;
short port;
void *ctx;
bool breakSocket;
bool cardPresent;
VpcdReader();
~VpcdReader();
bool QueryTransmit(BYTE *APDU,int APDUlen,BYTE **Resp,int *Resplen);
bool QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset=false);
bool CheckATR();
DWORD startServer();
void shutdown();
void init(wchar_t *section);
void signalRemoval(void);
void signalInsertion(void);
CRITICAL_SECTION ioSection;
};

View File

@@ -0,0 +1,332 @@
#include "internal.h"
#include "VirtualSCReader.h"
#include "reader.h"
#include "device.h"
#include <winscard.h>
#include "memory.h"
#include <Sddl.h>
#include "sectionLocker.h"
int TcpIpReader::portBase;
TcpIpReader::TcpIpReader() {
rpcType=1;
state=SCARD_ABSENT;
}
void TcpIpReader::init(wchar_t *section) {
portBase=GetPrivateProfileInt(L"Driver",L"RPC_PORT_BASE",29500,L"VivoKeySmartReader.ini");
port=GetPrivateProfileInt(section,L"TCP_PORT",portBase+(instance<<1),L"VivoKeySmartReader.ini");
eventPort=GetPrivateProfileInt(section,L"TCP_EVENT_PORT",portBase+1+(instance<<1),L"VivoKeySmartReader.ini");
InitializeCriticalSection(&eventSection);
InitializeCriticalSection(&dataSection);
}
bool TcpIpReader::CheckATR() {
if (AcceptSocket==NULL)
return false;
int read=0;
DWORD command=1;
if ((read=send(AcceptSocket,(char*)&command,sizeof(DWORD),NULL))<=0) {
return false;
}
DWORD size=0;
if ((read=recv(AcceptSocket,(char*)&size,sizeof(DWORD),MSG_WAITALL))<=0) {
return false;
}
if (size==0)
return false;
BYTE ATR[100];
if ((read=recv(AcceptSocket,(char*)ATR,size,MSG_WAITALL))<=0) {
return false;
}
return true;
}
bool TcpIpReader::QueryTransmit(BYTE *APDU,int APDUlen,BYTE **Resp,int *Resplen) {
if (AcceptSocket==NULL)
return false;
DWORD command=2;
DWORD read=0;
if ((read=send(AcceptSocket,(char*)&command,sizeof(DWORD),NULL))<=0) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
DWORD dwAPDUlen=(DWORD)APDUlen;
if ((read=send(AcceptSocket,(char*)&dwAPDUlen,sizeof(DWORD),NULL))<=0) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
if ((read=send(AcceptSocket,(char*)APDU,APDUlen,NULL))<=0) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
DWORD dwRespLen=0;
if ((read=recv(AcceptSocket,(char*)&dwRespLen,sizeof(DWORD),MSG_WAITALL))<=0) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
if (0 != dwRespLen) {
BYTE *p=(BYTE *)realloc(*Resp, dwRespLen);
if (p==NULL) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
*Resp=p;
}
if ((read=recv(AcceptSocket,(char*)*Resp,dwRespLen,MSG_WAITALL))<=0) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
(*Resplen)=(int)dwRespLen;
return true;
}
bool TcpIpReader::QueryATR(BYTE *ATR,DWORD *ATRsize,bool reset) {
if (AcceptSocket==NULL)
return false;
int read=0;
DWORD command=reset ? 0 : 1;
if ((read=send(AcceptSocket,(char*)&command,sizeof(DWORD),NULL))<=0) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
DWORD size=0;
if ((read=recv(AcceptSocket,(char*)&size,sizeof(DWORD),MSG_WAITALL))<=0) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
if (size==0)
return false;
if ((read=recv(AcceptSocket,(char*)ATR,size,MSG_WAITALL))<=0) {
::shutdown(AcceptSocket,SD_BOTH);
AcceptSocket=NULL;
return false;
}
(*ATRsize)=size;
return true;
}
DWORD TcpIpReader::startServer() {
breakSocket=false;
wchar_t log[300];
while (true) {
//__try {
fd_set readfds;
FD_ZERO(&readfds);
// Set server socket to set
FD_SET(socket, &readfds);
// Timeout parameter
timeval tv = { 0 };
tv.tv_sec = 5;
while(true) {
if (breakSocket)
return 0;
FD_SET(socket, &readfds);
int ret = select(0, &readfds, NULL, NULL, &tv);
if (ret > 0)
break;
if (ret<0) {
DWORD err=WSAGetLastError();
swprintf(log,L"[VivoKeySmartReader]wsa err:%x",err);
OutputDebugString(log);
if (err==0x2736) {
socket=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,0,0);
sockaddr_in Service;
Service.sin_family = AF_INET;
Service.sin_addr.s_addr = inet_addr("127.0.0.1");
Service.sin_port = htons((u_short)(port));
bind(socket, (SOCKADDR *) &Service, sizeof (Service));
listen(socket, 1);
FD_ZERO(&readfds);
// Set server socket to set
FD_SET(socket, &readfds);
}
}
}
SOCKET AcceptEventSocket;
AcceptSocket = accept(socket, NULL, NULL);
closesocket(socket);
socket=NULL;
if (AcceptSocket == INVALID_SOCKET)
return 0;
swprintf(log,L"[VivoKeySmartReader]Socket connected:%i",AcceptSocket);
OutputDebugString(log);
FD_ZERO(&readfds);
// Set server socket to set
FD_SET(eventsocket, &readfds);
while(true) {
if (breakSocket)
return 0;
FD_SET(eventsocket, &readfds);
int ret = select(0, &readfds, NULL, NULL, &tv);
if (ret > 0)
break;
if (ret<0) {
DWORD err=WSAGetLastError();
swprintf(log,L"[VivoKeySmartReader]wsa err:%x",err);
OutputDebugString(log);
if (err==0x2736) {
eventsocket=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,0,0);
sockaddr_in eventService;
eventService.sin_family = AF_INET;
eventService.sin_addr.s_addr = inet_addr("127.0.0.1");
eventService.sin_port = htons((u_short)(eventPort));
bind(eventsocket, (SOCKADDR *) &eventService, sizeof (eventService));
listen(eventsocket, 1);
FD_ZERO(&readfds);
// Set server socket to set
FD_SET(eventsocket, &readfds);
}
}
}
AcceptEventSocket = accept(eventsocket, NULL, NULL);
closesocket(eventsocket);
eventsocket=NULL;
if (AcceptEventSocket == INVALID_SOCKET)
return 0;
swprintf(log,L"[VivoKeySmartReader]Event Socket connected:%i",AcceptEventSocket);
OutputDebugString(log);
if (!waitInsertIpr.empty()) {
// if I'm waiting for card insertion, verify if there's a card present
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;
}
}
while (true) {
// wait for a command
DWORD command=0;
int read=0;
if ((read=recv(AcceptEventSocket,(char*)&command,sizeof(DWORD),MSG_WAITALL))<=0) {
state=SCARD_ABSENT;
OutputDebugString(L"[VivoKeySmartReader]Socket error");
powered=0;
::shutdown(AcceptSocket,SD_BOTH);
::shutdown(AcceptEventSocket,SD_BOTH);
if (!waitRemoveIpr.empty()) {
// card inserted
SectionLocker lock(device->m_RequestLock);
while (!waitRemoveIpr.empty()) {
CComPtr<IWDFIoRequest> ipr = waitRemoveIpr.back();
OutputDebugString(L"[VivoKeySmartReader]complete Wait Remove");
if (ipr->UnmarkCancelable()==S_OK) {
OutputDebugString(L"[VivoKeySmartReader]Wait Remove Unmarked");
ipr->CompleteWithInformation(STATUS_SUCCESS, 0);
OutputDebugString(L"[VivoKeySmartReader]Wait Remove Completed");
}
waitRemoveIpr.pop_back();
}
}
if (!waitInsertIpr.empty()) {
// card removed
SectionLocker lock(device->m_RequestLock);
while (!waitInsertIpr.empty()) {
CComPtr<IWDFIoRequest> ipr = waitInsertIpr.back();
OutputDebugString(L"[VivoKeySmartReader]cancel Wait Remove");
if (ipr->UnmarkCancelable()==S_OK) {
OutputDebugString(L"[VivoKeySmartReader]Wait Insert Unmarked");
ipr->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_CANCELLED), 0);
OutputDebugString(L"[VivoKeySmartReader]Wait Insert Cancelled");
}
waitInsertIpr.pop_back();
}
}
break;
}
OutputDebugString(L"[VivoKeySmartReader]Socket data");
if (command==0)
powered=0;
if (command==0 && !waitRemoveIpr.empty()) {
// card removed
SectionLocker lock(device->m_RequestLock);
state=SCARD_ABSENT;
while (!waitRemoveIpr.empty()) {
CComPtr<IWDFIoRequest> ipr = waitRemoveIpr.back();
if (ipr->UnmarkCancelable()==S_OK)
ipr->CompleteWithInformation(STATUS_SUCCESS, 0);
waitRemoveIpr.pop_back();
}
}
else if (command==1 && !waitInsertIpr.empty()) {
// card inserted
SectionLocker lock(device->m_RequestLock);
state=SCARD_SWALLOWED;
initProtocols();
while (!waitInsertIpr.empty()) {
CComPtr<IWDFIoRequest> ipr = waitInsertIpr.back();
if (ipr->UnmarkCancelable()==S_OK)
ipr->CompleteWithInformation(STATUS_SUCCESS, 0);
waitInsertIpr.pop_back();
}
}
}
//}
//__except(EXCEPTION_EXECUTE_HANDLER) {
// wchar_t log[300];
// DWORD err=GetExceptionCode();
// swprintf(log,L"Exception:%08X",err);
// OutputDebugString(log);
//}
}
OutputDebugString(L"[VivoKeySmartReader]Socket quit!!!");
return 0;
}
void TcpIpReader::shutdown() {
state=SCARD_ABSENT;
breakSocket=true;
{
closesocket(eventsocket);
closesocket(socket);
}
WaitForSingleObject(serverThread,10000);
serverThread=NULL;
eventsocket=NULL;
socket=NULL;
while (!waitRemoveIpr.empty()) {
SectionLocker lock(device->m_RequestLock);
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();
}
}

View File

@@ -0,0 +1,19 @@
import "wudfddi.idl";
[
uuid(8B9C88E9-7E63-46c7-832B-D48D0290E4BF),
version(1.0),
helpstring("VirtualSCReader Driver Type Library")
]
library VirtualSCReaderDriverLib
{
importlib("stdole2.tlb");
[
uuid(A44A2DF4-DCA4-4767-8EC4-86FE611C2EA7),
helpstring("VirtualSCReader Class")
]
coclass VirtualSCReaderDriver
{
[default] interface IDriverEntry;
};
};

View File

@@ -0,0 +1,21 @@
[Driver]
NumReaders=3
[Reader0]
RPC_TYPE=0
VENDOR_NAME=Fabio Ottavi
VENDOR_IFD_TYPE=Pipe Reader
DECIVE_UNIT=0
[Reader1]
RPC_TYPE=1
VENDOR_NAME=Fabio Ottavi
VENDOR_IFD_TYPE=TCP/IP Reader
DECIVE_UNIT=1
[Reader2]
RPC_TYPE=2
VENDOR_NAME=Virtual Smart Card Architecture
VENDOR_IFD_TYPE=Virtual PCD
TCP_PORT=35963
DECIVE_UNIT=2

View File

@@ -0,0 +1,98 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
/////////////////////////////////////////////////////////////////////////////
// Neutral (Default) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUD)
LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT
#pragma code_page(1252)
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 6,0,6000,16384
PRODUCTVERSION 6,0,6000,16384
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x9L
#else
FILEFLAGS 0x8L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040004b0"
BEGIN
VALUE "CompanyName", "VivoKey"
VALUE "FileDescription", "VivoKey Smart Reader Driver"
VALUE "FileVersion", "6.0.6000.16384"
VALUE "InternalName", "VivoKeySmartReader"
VALUE "LegalCopyright", "Frank Morgner, GPLv3 and VivoKey"
VALUE "OriginalFilename", "VivoKeySmartReader.dll"
VALUE "ProductName", "VivoKey Smart Reader"
VALUE "ProductVersion", "6.0.6000.16384"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x400, 1200
END
END
#endif // Neutral (Default) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Italian (Italy) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // Italian (Italy) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -0,0 +1,190 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<None Include="Exports.def" />
<None Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\vpcd\lock.c" />
<ClCompile Include="..\..\src\vpcd\vpcd.c" />
<ClCompile Include="Device.cpp" />
<ClCompile Include="DllMain.cpp" />
<ClCompile Include="Driver.cpp" />
<ClCompile Include="memory.cpp" />
<ClCompile Include="PipeReader.cpp" />
<ClCompile Include="Queue.cpp" />
<ClCompile Include="Reader.cpp" />
<ClCompile Include="sectionLocker.cpp" />
<ClCompile Include="TcpIpReader.cpp" />
<ClCompile Include="VpcdReader.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\vpcd\lock.h" />
<ClInclude Include="..\..\src\vpcd\vpcd.h" />
<ClInclude Include="Device.h" />
<ClInclude Include="Driver.h" />
<ClInclude Include="Internal.h" />
<ClInclude Include="memory.h" />
<ClInclude Include="Queue.h" />
<ClInclude Include="Reader.h" />
<ClInclude Include="Resource.h" />
<ClInclude Include="sectionLocker.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="VivoKeySmartReader.rc" />
</ItemGroup>
<ItemGroup>
<Inf Include="VivoKeySmartReader.inf" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{1D286E48-DE79-41FF-844B-56ED3764D4DA}</ProjectGuid>
<TemplateGuid>{2177f19c-eb4c-4687-9e7f-f9eec1f12cf1}</TemplateGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration>Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<RootNamespace>VivoKeySmartReader</RootNamespace>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfAtl>Static</UseOfAtl>
<UMDF_VERSION_MAJOR>1</UMDF_VERSION_MAJOR>
<DriverTargetPlatform>Desktop</DriverTargetPlatform>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfAtl>Static</UseOfAtl>
<UMDF_VERSION_MAJOR>1</UMDF_VERSION_MAJOR>
<DriverTargetPlatform>Desktop</DriverTargetPlatform>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfAtl>Static</UseOfAtl>
<UMDF_VERSION_MAJOR>1</UMDF_VERSION_MAJOR>
<DriverTargetPlatform>Desktop</DriverTargetPlatform>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfAtl>Static</UseOfAtl>
<UMDF_VERSION_MAJOR>1</UMDF_VERSION_MAJOR>
<DriverTargetPlatform>Desktop</DriverTargetPlatform>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WppEnabled>true</WppEnabled>
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">internal.h</WppScanConfigurationData>
<ExceptionHandling>Sync</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<TreatWarningAsError>false</TreatWarningAsError>
<CallingConvention>
</CallingConvention>
<ShowIncludes>true</ShowIncludes>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<ModuleDefinitionFile>.\Exports.def</ModuleDefinitionFile>
<AdditionalDependencies>Ws2_32.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WppEnabled>true</WppEnabled>
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">internal.h</WppScanConfigurationData>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<ModuleDefinitionFile>.\Exports.def</ModuleDefinitionFile>
<AdditionalDependencies>Ws2_32.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WppEnabled>true</WppEnabled>
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">internal.h</WppScanConfigurationData>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<ModuleDefinitionFile>.\Exports.def</ModuleDefinitionFile>
<AdditionalDependencies>Ws2_32.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WppEnabled>true</WppEnabled>
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">internal.h</WppScanConfigurationData>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<ModuleDefinitionFile>.\Exports.def</ModuleDefinitionFile>
<AdditionalDependencies>Ws2_32.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
</ItemGroup>
<ItemGroup>
<Midl Include="VirtualSCReader.idl" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Driver Files">
<UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
<Extensions>inf;inv;inx;mof;mc;</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<Inf Include="VivoKeySmartReader.inf">
<Filter>Driver Files</Filter>
</Inf>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Device.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Driver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Internal.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="memory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Queue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Reader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="sectionLocker.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\vpcd\lock.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\vpcd\vpcd.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="Exports.def">
<Filter>Source Files</Filter>
</None>
<ClCompile Include="Device.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Driver.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="VivoKeySmartReader.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<ClCompile Include="DllMain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="memory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PipeReader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Queue.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Reader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="sectionLocker.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TcpIpReader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="VpcdReader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\vpcd\lock.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\vpcd\vpcd.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Midl Include="VirtualSCReader.idl">
<Filter>Source Files</Filter>
</Midl>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,167 @@
#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"VivoKeySmartReader.ini");
port=(short) GetPrivateProfileInt(section,L"TCP_PORT",portBase+instance,L"VivoKeySmartReader.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) {
bool r = false;
if (APDU && APDUlen && Resplen) {
ssize_t rapdu_len = vicc_transmit((struct vicc_ctx *) ctx, APDUlen, APDU, Resp);
if (rapdu_len > 0) {
*Resplen = rapdu_len;
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();
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;
}
}
}
}

View File

@@ -0,0 +1,337 @@
#include "internal.h"
#include "VirtualSCReader.h"
#include "queue.h"
#include "device.h"
#include "driver.h"
#include <stdio.h>
#include <winscard.h>
#include "memory.h"
#include "SectionLocker.h"
HRESULT
CMyDevice::CreateInstance(
__in IWDFDriver *FxDriver,
__in IWDFDeviceInitialize * FxDeviceInit
)
/*++
Routine Description:
This method creates and initializs an instance of the virtual smart card reader driver's
device callback object.
Arguments:
FxDeviceInit - the settings for the device.
Device - a location to store the referenced pointer to the device object.
Return Value:
Status
--*/
{
inFunc
SectionLogger a(__FUNCTION__);
CComObject<CMyDevice>* device = NULL;
HRESULT hr;
OutputDebugString(L"[VivoKeySmartReader]CreateInstance"); //
// Allocate a new instance of the device class.
//
hr = CComObject<CMyDevice>::CreateInstance(&device);
if (device==NULL)
{
return E_OUTOFMEMORY;
}
//
// Initialize the instance.
//
device->AddRef();
OutputDebugString(L"[VivoKeySmartReader]SetLockingConstraint"); //
FxDeviceInit->SetLockingConstraint(WdfDeviceLevel);
CComPtr<IUnknown> spCallback;
OutputDebugString(L"[VivoKeySmartReader]QueryInterface"); //
hr = device->QueryInterface(IID_IUnknown, (void**)&spCallback);
CComPtr<IWDFDevice> spIWDFDevice;
if (SUCCEEDED(hr))
{
OutputDebugString(L"[VivoKeySmartReader]CreateDevice"); //
hr = FxDriver->CreateDevice(FxDeviceInit, spCallback, &spIWDFDevice);
}
device->numInstances=GetPrivateProfileInt(L"Driver",L"NumReaders",1,L"VivoKeySmartReader.ini");
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
OutputDebugString(L"[VivoKeySmartReader]Error at WSAStartup()\n");
}
for (int i=0;i<device->numInstances;i++) {
OutputDebugString(L"[VivoKeySmartReader]CreateDeviceInterface"); //
wchar_t name[10];
swprintf(name,L"DEV%i",i);
if (spIWDFDevice->CreateDeviceInterface(&SmartCardReaderGuid,name)!=0)
OutputDebugString(L"[VivoKeySmartReader]CreateDeviceInterface Failed");
}
SAFE_RELEASE(device);
return hr;
}
void CMyDevice::ProcessIoControl(__in IWDFIoQueue* pQueue,
__in IWDFIoRequest* pRequest,
__in ULONG ControlCode,
SIZE_T inBufSize,
SIZE_T outBufSize)
{
inFunc
SectionLogger a(__FUNCTION__);
UNREFERENCED_PARAMETER(pQueue);
wchar_t log[300];
swprintf(log,L"[VivoKeySmartReader][IOCT]IOCTL %08X - In %i Out %i",ControlCode,inBufSize,outBufSize);
OutputDebugString(log);
//SectionLocker lock(m_RequestLock);
int instance=0;
{
CComPtr<IWDFFile> pFileObject;
pRequest->GetFileObject(&pFileObject);
if (pFileObject != NULL)
{
DWORD logLen=300;
pFileObject->RetrieveFileName(log,&logLen);
instance=_wtoi(log+(logLen-2));
}
}
Reader &reader=*readers[instance];
if (ControlCode==IOCTL_SMARTCARD_GET_ATTRIBUTE) {
reader.IoSmartCardGetAttribute(pRequest,inBufSize,outBufSize);
return;
}
else if (ControlCode==IOCTL_SMARTCARD_IS_PRESENT) {
reader.IoSmartCardIsPresent(pRequest,inBufSize,outBufSize);
return;
}
else if (ControlCode==IOCTL_SMARTCARD_GET_STATE) {
reader.IoSmartCardGetState(pRequest,inBufSize,outBufSize);
return;
}
else if (ControlCode==IOCTL_SMARTCARD_IS_ABSENT) {
reader.IoSmartCardIsAbsent(pRequest,inBufSize,outBufSize);
return;
}
else if (ControlCode==IOCTL_SMARTCARD_POWER) {
reader.IoSmartCardPower(pRequest,inBufSize,outBufSize);
return;
}
else if (ControlCode==IOCTL_SMARTCARD_SET_ATTRIBUTE) {
reader.IoSmartCardSetAttribute(pRequest,inBufSize,outBufSize);
return;
}
else if (ControlCode==IOCTL_SMARTCARD_SET_PROTOCOL) {
reader.IoSmartCardSetProtocol(pRequest,inBufSize,outBufSize);
return;
}
else if (ControlCode==IOCTL_SMARTCARD_TRANSMIT) {
reader.IoSmartCardTransmit(pRequest,inBufSize,outBufSize);
return;
}
swprintf(log,L"[VivoKeySmartReader][IOCT]ERROR_NOT_SUPPORTED:%08X",ControlCode);
OutputDebugString(log);
pRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), 0);
return;
}
DWORD WINAPI ServerFunc(Reader *reader) {
return reader->startServer();
}
/////////////////////////////////////////////////////////////////////////
//
// CMyDevice::OnPrepareHardware
//
// Called by UMDF to prepare the hardware for use.
//
// Parameters:
// pWdfDevice - pointer to an IWDFDevice object representing the
// device
//
// Return Values:
// S_OK: success
//
/////////////////////////////////////////////////////////////////////////
HRESULT CMyDevice::OnPrepareHardware(
__in IWDFDevice* pWdfDevice
)
{
inFunc
SectionLogger a(__FUNCTION__);
// Store the IWDFDevice pointer
m_pWdfDevice = pWdfDevice;
// Configure the default IO Queue
HRESULT hr = CMyQueue::CreateInstance(m_pWdfDevice, this);
return hr;
}
/////////////////////////////////////////////////////////////////////////
//
// CMyDevice::OnReleaseHardware
//
// Called by WUDF to uninitialize the hardware.
//
// Parameters:
// pWdfDevice - pointer to an IWDFDevice object for the device
//
// Return Values:
// S_OK:
//
/////////////////////////////////////////////////////////////////////////
HRESULT CMyDevice::OnReleaseHardware(
__in IWDFDevice* pWdfDevice
)
{
inFunc
SectionLogger a(__FUNCTION__);
UNREFERENCED_PARAMETER(pWdfDevice);
// Release the IWDFDevice handle, if it matches
if (pWdfDevice == m_pWdfDevice.p)
{
m_pWdfDevice.Release();
}
return S_OK;
}
HRESULT CMyDevice::OnD0Entry(IN IWDFDevice* pWdfDevice,IN WDF_POWER_DEVICE_STATE previousState) {
SectionLogger a(__FUNCTION__);
UNREFERENCED_PARAMETER(pWdfDevice);
UNREFERENCED_PARAMETER(previousState);
numInstances=GetPrivateProfileInt(L"Driver",L"NumReaders",1,L"VivoKeySmartReader.ini");
readers.resize(numInstances);
for (int i=0;i<numInstances;i++) {
wchar_t section[300];
char sectionA[300];
swprintf(section,L"Reader%i",i);
sprintf(sectionA,"Reader%i",i);
int rpcType=GetPrivateProfileInt(section,L"RPC_TYPE",0,L"VivoKeySmartReader.ini");
if (rpcType==0)
readers[i]=new PipeReader();
else if (rpcType==1)
readers[i]=new TcpIpReader();
else if (rpcType==2)
readers[i]=new VpcdReader();
readers[i]->instance=i;
readers[i]->device=this;
GetPrivateProfileStringA(sectionA,"VENDOR_NAME","VivoKey",readers[i]->vendorName,sizeof readers[i]->vendorName,"VivoKeySmartReader.ini");
GetPrivateProfileStringA(sectionA,"VENDOR_IFD_TYPE","VIRTUAL_CARD_READER",readers[i]->vendorIfdType,sizeof readers[i]->vendorIfdType,"VivoKeySmartReader.ini");
readers[i]->deviceUnit=GetPrivateProfileInt(section,L"DEVICE_UNIT",i,L"VivoKeySmartReader.ini");
readers[i]->protocol=0;
readers[i]->init(section);
DWORD pipeThreadID;
readers[i]->serverThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ServerFunc,readers[i],0,&pipeThreadID);
}
return S_OK;
}
HRESULT CMyDevice::OnD0Exit(IN IWDFDevice* pWdfDevice,IN WDF_POWER_DEVICE_STATE newState) {
SectionLogger a(__FUNCTION__);
UNREFERENCED_PARAMETER(pWdfDevice);
UNREFERENCED_PARAMETER(newState);
// dovrei fermare tutti i thread in ascolto dei lettori
shutDown();
return S_OK;
}
void CMyDevice::shutDown() {
SectionLogger a(__FUNCTION__);
for (int i=0;i<numInstances;i++) {
readers[i]->shutdown();
delete readers[i];
}
numInstances=0;
}
HRESULT CMyDevice::OnQueryRemove(IN IWDFDevice* pWdfDevice) {
SectionLogger a(__FUNCTION__);
UNREFERENCED_PARAMETER(pWdfDevice);
OutputDebugString(L"[VivoKeySmartReader]OnQueryRemove");
shutDown();
return S_OK;
}
HRESULT CMyDevice::OnQueryStop(IN IWDFDevice* pWdfDevice) {
SectionLogger a(__FUNCTION__);
UNREFERENCED_PARAMETER(pWdfDevice);
OutputDebugString(L"[VivoKeySmartReader]OnQueryStop");
shutDown();
return S_OK;
}
void CMyDevice::OnSurpriseRemoval(IN IWDFDevice* pWdfDevice) {
SectionLogger a(__FUNCTION__);
UNREFERENCED_PARAMETER(pWdfDevice);
OutputDebugString(L"[VivoKeySmartReader]OnSurpriseRemoval");
shutDown();
}
STDMETHODIMP_ (void) CMyDevice::OnCancel(IN IWDFIoRequest* pWdfRequest) {
SectionLogger a(__FUNCTION__);
wchar_t log[300];
SectionLocker lock(m_RequestLock);
int instance=0;
{
CComPtr<IWDFFile> pFileObject;
pWdfRequest->GetFileObject(&pFileObject);
if (pFileObject != NULL)
{
DWORD logLen=300;
pFileObject->RetrieveFileName(log,&logLen);
instance=_wtoi(log+(logLen-2));
}
}
Reader &reader=*readers[instance];
for (std::vector< CComPtr<IWDFIoRequest> >::iterator it = reader.waitRemoveIpr.begin();
it != reader.waitRemoveIpr.end(); it++) {
if (pWdfRequest == *it) {
OutputDebugString(L"[VivoKeySmartReader]Cancel Remove");
reader.waitRemoveIpr.erase(it);
}
}
for (std::vector< CComPtr<IWDFIoRequest> >::iterator it = reader.waitInsertIpr.begin();
it != reader.waitInsertIpr.end(); it++) {
if (pWdfRequest == *it) {
OutputDebugString(L"[VivoKeySmartReader]Cancel Insert");
reader.waitInsertIpr.erase(it);
}
}
pWdfRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_CANCELLED), 0);
}

View File

@@ -0,0 +1,98 @@
#pragma once
#include <vector>
#include "reader.h"
//
// Class for the iotrace driver.
//
class CMyDevice;
class ATL_NO_VTABLE CMyDevice :
public CComObjectRootEx<CComMultiThreadModel>,
public IPnpCallbackHardware,
public IPnpCallback,
public IRequestCallbackCancel
{
public:
~CMyDevice() {
DeleteCriticalSection(&m_RequestLock);
}
DECLARE_NOT_AGGREGATABLE(CMyDevice)
BEGIN_COM_MAP(CMyDevice)
COM_INTERFACE_ENTRY(IPnpCallbackHardware)
COM_INTERFACE_ENTRY(IPnpCallback)
COM_INTERFACE_ENTRY(IRequestCallbackCancel)
END_COM_MAP()
CMyDevice(VOID)
{
InitializeCriticalSection(&m_RequestLock);
m_pWdfDevice = NULL;
}
//
// Private data members.
//
private:
CComPtr<IWDFDevice> m_pWdfDevice;
std::vector<Reader*> readers;
int numInstances;
//
// Private methods.
//
private:
HRESULT ConfigureQueue();
//
// Public methods
//
public:
CRITICAL_SECTION m_RequestLock;
//
// The factory method used to create an instance of this driver.
//
static
HRESULT CreateInstance(
__in IWDFDriver *FxDriver,
__in IWDFDeviceInitialize *FxDeviceInit
);
//
// COM methods
//
public:
//
// IUnknown methods.
//
void ProcessIoControl(__in IWDFIoQueue* pQueue,
__in IWDFIoRequest* pRequest,
__in ULONG ControlCode,
SIZE_T InputBufferSizeInBytes,
SIZE_T OutputBufferSizeInBytes);
STDMETHOD_ (HRESULT, OnPrepareHardware)(__in IWDFDevice* pWdfDevice);
STDMETHOD_ (HRESULT, OnReleaseHardware)(__in IWDFDevice* pWdfDevice);
STDMETHOD_ (HRESULT, OnD0Entry)(IN IWDFDevice* pWdfDevice,IN WDF_POWER_DEVICE_STATE previousState);
STDMETHOD_ (HRESULT, OnD0Exit )(IN IWDFDevice* pWdfDevice,IN WDF_POWER_DEVICE_STATE newState);
STDMETHOD_ (HRESULT, OnQueryRemove )(IN IWDFDevice* pWdfDevice);
STDMETHOD_ (HRESULT, OnQueryStop)(IN IWDFDevice* pWdfDevice);
STDMETHOD_ (void, OnSurpriseRemoval)(IN IWDFDevice* pWdfDevice);
STDMETHOD_ (void, OnCancel)(IN IWDFIoRequest* pWdfRequest);
void shutDown();
};

View File

@@ -0,0 +1,75 @@
#include "internal.h"
#include "VirtualSCReader.h"
#include "driver.h"
#include "device.h"
#include <stdio.h>
#include "SectionLocker.h"
CMyDriver::CMyDriver()
{
inFunc
}
/////////////////////////////////////////////////////////////////////////
//
// CMyDriver::OnDeviceAdd
//
// The framework call this function when device is detected. This driver
// creates a device callback object
//
// Parameters:
// pDriver - pointer to an IWDFDriver object
// pDeviceInit - pointer to a device initialization object
//
// Return Values:
// S_OK: device initialized successfully
//
/////////////////////////////////////////////////////////////////////////
HRESULT CMyDriver::OnDeviceAdd(
__in IWDFDriver* pDriver,
__in IWDFDeviceInitialize* pDeviceInit
)
{
inFunc
SectionLogger a(__FUNCTION__);
HRESULT hr = CMyDevice::CreateInstance(pDriver, pDeviceInit);
return hr;
}
/////////////////////////////////////////////////////////////////////////
//
// CMyDriver::OnInitialize
//
// The framework calls this function just after loading the driver. The driver
// can perform any global, device independent intialization in this routine.
//
/////////////////////////////////////////////////////////////////////////
HRESULT CMyDriver::OnInitialize(
__in IWDFDriver* pDriver
)
{
inFunc
SectionLogger a(__FUNCTION__);
UNREFERENCED_PARAMETER(pDriver);
return S_OK;
}
/////////////////////////////////////////////////////////////////////////
//
// CMyDriver::OnDeinitialize
//
// The framework calls this function just before de-initializing itself. All
// WDF framework resources should be released by driver before returning
// from this call.
//
/////////////////////////////////////////////////////////////////////////
void CMyDriver::OnDeinitialize(
__in IWDFDriver* pDriver
)
{
inFunc
SectionLogger a(__FUNCTION__);
UNREFERENCED_PARAMETER(pDriver);
return;
}

View File

@@ -0,0 +1,37 @@
#pragma once
//
// This class handles driver events for the skeleton sample. In particular
// it supports the OnDeviceAdd event, which occurs when the driver is called
// to setup per-device handlers for a new device stack.
//
class ATL_NO_VTABLE CMyDriver :
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<CMyDriver, &CLSID_VirtualSCReaderDriver>,
public IDriverEntry
{
public:
CMyDriver();
DECLARE_NO_REGISTRY()
DECLARE_CLASSFACTORY()
DECLARE_NOT_AGGREGATABLE(CMyDriver)
BEGIN_COM_MAP(CMyDriver)
COM_INTERFACE_ENTRY(IDriverEntry)
END_COM_MAP()
public:
//
// IDriverEntry
//
STDMETHOD (OnInitialize)(__in IWDFDriver* pDriver);
STDMETHOD (OnDeviceAdd)(__in IWDFDriver* pDriver, __in IWDFDeviceInitialize* pDeviceInit);
STDMETHOD_ (void, OnDeinitialize)(__in IWDFDriver* pDriver);
};
OBJECT_ENTRY_AUTO(__uuidof(VirtualSCReaderDriver), CMyDriver)

View File

@@ -0,0 +1,15 @@
; Skeleton.def : Declares the module parameters.
;
; TODO: Change the library name here to match your binary name.
;
LIBRARY "UMDFSkeleton.DLL"
EXPORTS
DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE

View File

@@ -0,0 +1,75 @@
#pragma once
#include <windows.h>
#include <atlbase.h>
#include <atlcom.h>
#include <atlstr.h>
//__user_driver; // Macro letting the compiler know this is not a kernel driver (this will help surpress needless warnings)
// Common WPD and WUDF headers
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#endif
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p) {if ((p)) { (p)->Release(); (p) = NULL; }}
#endif
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) // ntsubauth
#define STATUS_NO_MEDIA ((NTSTATUS)0xC0000178L)
#define STATUS_INVALID_DEVICE_STATE ((NTSTATUS)0xC0000184L)
//
// Include the WUDF DDI
//
#include <devioctl.h>
#include <initguid.h>
#include <propkeydef.h>
#include <propvarutil.h>
#include "PortableDeviceTypes.h"
#include "PortableDeviceClassExtension.h"
#include "PortableDevice.h"
#include "wudfddi.h"
//
// Use specstrings for in/out annotation of function parameters.
//
#include "specstrings.h"
//
// Forward definitions of classes in the other header files.
//
typedef class CMyDriver *PCMyDriver;
typedef class CMyDevice *PCMyDevice;
//
DEFINE_GUID(SmartCardReaderGuid, 0x50DD5230, 0xBA8A, 0x11D1, 0xBF,0x5D,0x00,0x00,0xF8,0x05,0xF5,0x30);
//
// Include the type specific headers.
//
//class funcTrace {
//public:
// TCHAR funcN[500];
// funcTrace (char *func) {
// TCHAR funcName[500];
// wsprintf(funcN, _T("%S"), func);
// wsprintf(funcName, _T("[VivoKeySmartReader]IN -> %s"), funcN);
// OutputDebugString(funcName);
// }
// ~funcTrace () {
// TCHAR funcName[500];
// wsprintf(funcName, _T("[VivoKeySmartReader]OUT -> %s"), funcN);
// OutputDebugString(funcName);
// }
//};
//#define inFunc funcTrace _ftrace(__FUNCTION__);
#define inFunc

View File

@@ -0,0 +1,91 @@
#include "memory.h"
#include "SectionLocker.h"
bool getBuffer(IWDFIoRequest* pRequest,void **buffer,int *bufferLen) {
IWDFMemory *inmem=NULL;
pRequest->GetInputMemory(&inmem);
if (inmem==NULL) {
OutputDebugString(L"GetInputMemory failed");
return false;
}
else {
SIZE_T size;
void *data=inmem->GetDataBuffer(&size);
if (0 != size) {
void *out = realloc(*buffer, size);
if (out==NULL) {
OutputDebugString(L"realloc failed");
return false;
}
memcpy(out,data,size);
(*buffer)=out;
}
(*bufferLen)=(int)size;
inmem->Release();
return true;
}
}
void setBuffer(CMyDevice *device,IWDFIoRequest* pRequest,void *result,int inSize) {
IWDFMemory *outmem=NULL;
pRequest->GetOutputMemory (&outmem);
if (outmem==NULL) {
SectionLocker lock(device->m_RequestLock);
OutputDebugString(L"GetOutputMemory failed");
pRequest->Complete(HRESULT_FROM_WIN32(ERROR_GEN_FAILURE));
}
else {
SectionLocker lock(device->m_RequestLock);
outmem->CopyFromBuffer(0,result,inSize);
outmem->Release();
pRequest->CompleteWithInformation(0,(SIZE_T)inSize);
}
}
void setString(CMyDevice *device,IWDFIoRequest* pRequest,char *result,int outSize) {
IWDFMemory *outmem=NULL;
pRequest->GetOutputMemory (&outmem);
if (outmem==NULL) {
SectionLocker lock(device->m_RequestLock);
OutputDebugString(L"GetOutputMemory failed");
pRequest->Complete(HRESULT_FROM_WIN32(ERROR_GEN_FAILURE));
}
else {
SectionLocker lock(device->m_RequestLock);
int size=min(outSize,(int)strlen(result)+1);
outmem->CopyFromBuffer(0,result,size);
outmem->Release();
pRequest->CompleteWithInformation(0,(SIZE_T)size);
}
}
void setInt(CMyDevice *device,IWDFIoRequest* pRequest,DWORD result) {
IWDFMemory *outmem=NULL;
pRequest->GetOutputMemory (&outmem);
if (outmem==NULL) {
SectionLocker lock(device->m_RequestLock);
OutputDebugString(L"GetOutputMemory failed");
pRequest->Complete(HRESULT_FROM_WIN32(ERROR_GEN_FAILURE));
}
else {
SectionLocker lock(device->m_RequestLock);
outmem->CopyFromBuffer(0,&result,sizeof(result));
outmem->Release();
pRequest->CompleteWithInformation(0,sizeof(result));
}
}
DWORD getInt(IWDFIoRequest* pRequest) {
IWDFMemory *inmem=NULL;
pRequest->GetInputMemory(&inmem);
if (inmem==NULL) {
OutputDebugString(L"GetInputMemory failed");
return 0xffffffff;
}
else {
SIZE_T size;
void *data=inmem->GetDataBuffer(&size);
DWORD d=*(DWORD *)data;
inmem->Release();
return d;
}
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "internal.h"
#include "device.h"
bool getBuffer(IWDFIoRequest* pRequest,void **buffer,int *bufferLen);
void setString(CMyDevice *device,IWDFIoRequest* pRequest,char *result,int outSize);
void setBuffer(CMyDevice *device,IWDFIoRequest* pRequest,void *result,int inSize);
void setInt(CMyDevice *device,IWDFIoRequest* pRequest,DWORD result);
DWORD getInt(IWDFIoRequest* pRequest);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
#include "sectionLocker.h"
void *ShowMe=NULL;
SectionLocker::SectionLocker(CRITICAL_SECTION &critsection,char *function,int line,void* object) {
critsection;
this->section=&critsection;
Function=function;
Line=line;
Object=object;
DWORD start=GetTickCount();
if (TryEnterCriticalSection(section)==0) {
char logBuffer[500];
sprintf(logBuffer,"[VivoKeySmartReader]Locking:Function:%s,Line:%i,Object:%p,Lock:%p",Function,Line,Object,section);
OutputDebugStringA(logBuffer);
ShowMe=section;
EnterCriticalSection(section);
DWORD end=GetTickCount();
sprintf(logBuffer,"[VivoKeySmartReader]Elapsed:%i ms",end-start);
OutputDebugStringA(logBuffer);
}
}
SectionLocker::~SectionLocker() {
if (section==ShowMe) {
char logBuffer[500];
sprintf(logBuffer,"[VivoKeySmartReader]Unlocking:Function:%s,Line:%i,Object:%p,Lock:%p",Function,Line,Object,section);
OutputDebugStringA(logBuffer);
ShowMe=NULL;
}
LeaveCriticalSection(section);
}
SectionLogger::SectionLogger(char *section) {
section;
start=GetTickCount();
char logBuffer[500];
SectionName=section;
sprintf(logBuffer,"[VivoKeySmartReader]Start section:%s",SectionName);
OutputDebugStringA(logBuffer);
}
SectionLogger::~SectionLogger() {
DWORD end=GetTickCount();
char logBuffer[500];
sprintf(logBuffer,"[VivoKeySmartReader]End section:%s elapsed:%i",SectionName,end-start);
OutputDebugStringA(logBuffer);
}

View File

@@ -0,0 +1,24 @@
#pragma once
#include "internal.h"
class SectionLocker {
char *Function;
int Line;
void *Object;
public:
CRITICAL_SECTION *section;
SectionLocker(CRITICAL_SECTION &critsection,char *function,int line,void* object);
//SectionLocker(CRITICAL_SECTION &section);
~SectionLocker();
};
class SectionLogger {
DWORD start;
char *SectionName;
public:
SectionLogger(char *section);
~SectionLogger();
};
#define lock(x) lockObj(x,__FUNCTION__,__LINE__,NULL)