Skip to content

Commit

Permalink
fixed bug preventing work with remote readers when no local is presen…
Browse files Browse the repository at this point in the history
…t (for unicode apps)
  • Loading branch information
petrs committed Sep 11, 2019
1 parent 3d3b1f3 commit c2b5674
Showing 1 changed file with 112 additions and 43 deletions.
155 changes: 112 additions & 43 deletions Winscard/Winscard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1104,10 +1104,24 @@ SCard LONG STDCALL SCardListReadersW(

// Try to read list of remote readers if required
if (theApp.m_remoteConfig.bRedirect) {
string_type readers = "";
list<string_type> remoteReaders;
if (theApp.Remote_ListReaders(&(theApp.m_remoteConfig), &remoteReaders) == SCARD_S_SUCCESS) {
// Put remote readers into list
theApp.m_winscardConfig.listVIRTUAL_READERS = remoteReaders;
theApp.remoteCardsATRMap.clear(); // Clear ATR of remote cards
// Obtain ATR for every remote reader
ls::iterator iter;
for (iter = remoteReaders.begin(); iter != remoteReaders.end(); iter++) {
string_type atr;
status = theApp.Remote_SCardConnect(&(theApp.m_remoteConfig), *iter, &atr);
if (status == SCARD_S_SUCCESS) {
theApp.remoteCardsATRMap[*iter] = atr;
}
}


// readers from cfg file
theApp.m_winscardConfig.listVIRTUAL_READERS.insert(theApp.m_winscardConfig.listVIRTUAL_READERS.begin(),
theApp.m_winscardConfig.listVIRTUAL_READERS_STATIC.begin(), theApp.m_winscardConfig.listVIRTUAL_READERS_STATIC.end()); // readers from cfg file
}
Expand All @@ -1117,8 +1131,15 @@ SCard LONG STDCALL SCardListReadersW(
// NO BUFFER IS SUPPLIED
// OBTAIN REQUIRED LENGTH FOR REAL READERS
DWORD realLen = 0;
if ((status = (*Original_SCardListReadersW)(hContext, mszGroups, NULL, &realLen)) == SCARD_S_SUCCESS) {
*pcchReaders = realLen;
status = (*Original_SCardListReadersW)(hContext, mszGroups, NULL, &realLen);
*pcchReaders = realLen;
// Supress error when virtual readers are set
if (status == SCARD_E_NO_READERS_AVAILABLE && theApp.m_winscardConfig.listVIRTUAL_READERS.size() > 0) {
*pcchReaders = 0;
status = SCARD_S_SUCCESS;
}

if (status == SCARD_S_SUCCESS) {
// ALLOCATE OWN BUFFER FOR REAL AND VIRTUAL READERS
size_t virtReadersLen = 0;
CCommonFnc::String_SerializeAsSeparatedArray(&theApp.m_winscardConfig.listVIRTUAL_READERS, L'\0', NULL, &virtReadersLen);
Expand All @@ -1127,43 +1148,64 @@ SCard LONG STDCALL SCardListReadersW(
WCHAR* readers = new WCHAR[newLen];
memset(readers, 0, newLen * sizeof(WCHAR));
*pcchReaders = newLen;
realLen = newLen;
if ((status = (*Original_SCardListReadersW)(hContext, mszGroups, readers, &realLen)) == SCARD_S_SUCCESS) {
*pcchReaders = realLen;
status = (*Original_SCardListReadersW)(hContext, mszGroups, readers, pcchReaders);


if (status == SCARD_E_NO_READERS_AVAILABLE) {
// No real readers are available. Check if virtual readers are supplied
if (theApp.m_winscardConfig.listVIRTUAL_READERS.size() > 0) {
// COPY NAME OF VIRTUAL READERS TO END
WCHAR* virtReadersPtr = readers;
if (realLen > 0) { // Jump right after real readers
virtReadersPtr += realLen - 1;
}
CCommonFnc::String_SerializeAsSeparatedArray(&theApp.m_winscardConfig.listVIRTUAL_READERS, L'\0', virtReadersPtr, &virtReadersLen);
// If no real readers were present, add two trailing zeroes, one otherwise
if (realLen == 0) {
*pcchReaders = (DWORD)(virtReadersLen + 1); // Add additional zero
}
else {
*pcchReaders = (DWORD)(realLen + virtReadersLen); // additional zero was already inserted before
}
mszReaders[*pcchReaders - 1] = 0;
LogDebugString(string_format(_CONV("No real cards available, but virtual readers specified => continuing only with virtual readers.\n")));
// Virtual readers are required => continue as OK (only virtual will be returned)
status = SCARD_S_SUCCESS;
*pcchReaders = 0;
}
// CAST mszReaders TO char** IS NECESSARY TO CORRECTLY PROPAGATE ALLOCATED BUFFER
WCHAR** temp = (WCHAR**)mszReaders;
*temp = readers;
CCommonFnc::String_ParseNullSeparatedArray(readers, *pcchReaders, &readersList);
// ADD ALLOCATED MEMORY TO LIST FOR FUTURE DEALLOCATION
theApp.m_wcharAllocatedMemoryList.push_back(readers);
else {
// No virtual readers specified => return SCARD_E_NO_READERS_AVAILABLE error
}
}

if (status == SCARD_S_SUCCESS) {
// COPY NAME OF VIRTUAL READERS TO THE END
WCHAR* virtReadersPtr = readers;
if (realLen > 0) { // Jump right after real readers
virtReadersPtr += realLen - 1;
}
CCommonFnc::String_SerializeAsSeparatedArray(&theApp.m_winscardConfig.listVIRTUAL_READERS, L'\0', virtReadersPtr, &virtReadersLen);
// If no real readers were present, add two trailing zeroes, one otherwise
if (realLen == 0) {
*pcchReaders = (DWORD)(virtReadersLen + 1); // Add additional zero
}
else {
*pcchReaders = (DWORD)(realLen + virtReadersLen); // additional zero was already inserted before
}
mszReaders[*pcchReaders - 1] = 0;
}
// CAST mszReaders TO char** IS NECESSARY TO CORRECTLY PROPAGATE ALLOCATED BUFFER
WCHAR** temp = (WCHAR**)mszReaders;
*temp = readers;
CCommonFnc::String_ParseNullSeparatedArray(readers, *pcchReaders, &readersList);
// ADD ALLOCATED MEMORY TO LIST FOR FUTURE DEALLOCATION
theApp.m_wcharAllocatedMemoryList.push_back(readers);
}
}
else {
// BUFFER SUPPLIED
// OBTAIN REQUIRED LENGTH FOR REAL READERS
DWORD realLen = *pcchReaders;
if ((status = (*Original_SCardListReadersW)(hContext, mszGroups, NULL, &realLen)) == SCARD_S_SUCCESS) {
status = (*Original_SCardListReadersW)(hContext, mszGroups, NULL, &realLen);

// Supress error when virtual readers are set
if (status == SCARD_E_NO_READERS_AVAILABLE && theApp.m_winscardConfig.listVIRTUAL_READERS.size() > 0) {
realLen = 0;
status = SCARD_S_SUCCESS;
}

if (status == SCARD_S_SUCCESS) {
size_t virtReadersLen = 0;
CCommonFnc::String_SerializeAsSeparatedArray(&theApp.m_winscardConfig.listVIRTUAL_READERS, L'\0', NULL, &virtReadersLen);

if ((realLen + virtReadersLen + 2 > *pcchReaders) || (mszReaders == NULL)) {
LogWinscardRules(_CONV("Likely dummy call to obtain required buffer length for readers\n"));
// SUPPLIED BUFFER IS NOT LARGE ENOUGHT
*pcchReaders = (DWORD)(realLen + virtReadersLen + 2);
if (mszReaders != NULL) status = SCARD_E_INSUFFICIENT_BUFFER;
Expand All @@ -1172,25 +1214,39 @@ SCard LONG STDCALL SCardListReadersW(
// SUPPLIED BUFFER IS OK, COPY REAL AND VIRTUAL READERS
realLen = *pcchReaders - 1;
memset(mszReaders, 0x00, *pcchReaders * sizeof(WCHAR));
if ((status = (*Original_SCardListReadersW)(hContext, mszGroups, mszReaders, &realLen)) == SCARD_S_SUCCESS) {
status = (*Original_SCardListReadersW)(hContext, mszGroups, mszReaders, &realLen);
if (status == SCARD_E_NO_READERS_AVAILABLE) {
// No real readers are available. Check if virtual readers are supplied
if (theApp.m_winscardConfig.listVIRTUAL_READERS.size() > 0) {
LogDebugString(string_format(_CONV("No real cards available, but virtual readers specified => continuing only with virtual readers.\n")));
// Virtual readers are required => continue as OK (only virtual will be returned)
status = SCARD_S_SUCCESS;
realLen = 0;
}
else {
// No virtual readers specified => return SCARD_E_NO_READERS_AVAILABLE error
}
}
if (status == SCARD_S_SUCCESS) {
*pcchReaders = realLen;
// COPY NAME OF VIRTUAL READERS TO END (IF USED)
if (theApp.m_winscardConfig.listVIRTUAL_READERS.size() > 0) {
WCHAR* virtReadersPtr = mszReaders;
if (realLen > 0) { // Jump right after real readers
virtReadersPtr += realLen - 1;
}
CCommonFnc::String_SerializeAsSeparatedArray(&theApp.m_winscardConfig.listVIRTUAL_READERS, L'\0', virtReadersPtr, &virtReadersLen);

// If no real readers were present, add two trailing zeroes, one otherwise
if (realLen == 0) {
*pcchReaders = (DWORD)(virtReadersLen + 1); // Add additional zero
}
else {
*pcchReaders = (DWORD)(realLen + virtReadersLen); // additional zero was already inserted before
}
mszReaders[*pcchReaders - 1] = 0;
}
else { *pcchReaders = realLen; }
// If no real readers were present, add two trailing zeroes, one otherwise
if (realLen == 0) {
*pcchReaders = (DWORD)(virtReadersLen + 1); // Add additional zero
}
else {
*pcchReaders = (DWORD)(realLen + virtReadersLen); // additional zero was already inserted before
}
mszReaders[*pcchReaders - 1] = 0;

CCommonFnc::String_ParseNullSeparatedArray(mszReaders, *pcchReaders, &readersList);
}
}
Expand Down Expand Up @@ -1938,15 +1994,26 @@ SCard LONG STDCALL SCardGetStatusChangeW(
IN DWORD cReaders
) {
LONG status = SCARD_S_SUCCESS;
char readerNameA[1000];
memset(readerNameA, 0, sizeof(readerNameA));
// Convert wchar to ascii
std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor;
std::string readerNameA = convertor.to_bytes(rgReaderStates->szReader);
//std::string readerNameA = convertor.to_bytes(rgReaderStates->szReader);
int len = wcslen(rgReaderStates->szReader);
if (sizeof(readerNameA) < len) {
return SCARD_F_INTERNAL_ERROR;
}
for (int i = 0; i < len; i++) {
readerNameA[i] = (char) rgReaderStates->szReader[i];
}
//std::string readerNameA = convertor.to_bytes(rgReaderStates->szReader);

LogWinscardRules(_CONV("SCardGetStatusChangeW called\n"));
string_type message = string_format(_CONV("-> rgReaderStates.szReader: %s\n"), readerNameA);
string_type message = string_format(_CONV("-> rgReaderStates.szReader: '%s'\n"), readerNameA);
//string_type message = string_format(_CONV("-> rgReaderStates.szReader: %s\n"), rgReaderStates->szReader);
LogWinscardRules(message);
if (theApp.IsRemoteReader(readerNameA)) {
status = SCARD_S_SUCCESS;
status = SCARD_S_SUCCESS;
}
else {
status = (*Original_SCardGetStatusChangeW)(hContext, dwTimeout, rgReaderStates, cReaders);
Expand All @@ -1966,6 +2033,8 @@ SCard LONG STDCALL SCardUIDlgSelectCardA(
) {
LogWinscardRules(_CONV("SCardUIDlgSelectCardA called\n"));
return (*Original_SCardUIDlgSelectCardA)(a);


}


Expand Down Expand Up @@ -3432,8 +3501,8 @@ LONG CWinscardApp::Remote_SendRequest(REMOTE_CONFIG* pRemoteConfig, string_type
string_type l = Remote_FormatRequest(targetReader, theApp.m_remoteConfig.nextCommandID, command, commandData, "", CMD_LINE_SEPARATOR);
pRemoteConfig->pSocket->SendLine(l);
replace(l.begin(), l.end(), '\n', ' ');
//message = string_format(_CONV("::-> %s\n"), l.c_str());
message = string_format(_CONV("::-> %s %s\n"), command.c_str(), "(hidden data)");
message = string_format(_CONV("::-> %s\n"), l.c_str());
//message = string_format(_CONV("::-> %s %s\n"), command.c_str(), "(hidden data)");
LogWinscardRules(message);
if (REMOTE_APDU_RESPONSE_WAIT_TIME > 0) {
_sleep(REMOTE_APDU_RESPONSE_WAIT_TIME);
Expand All @@ -3445,8 +3514,8 @@ LONG CWinscardApp::Remote_SendRequest(REMOTE_CONFIG* pRemoteConfig, string_type
status = Remote_ParseResponse(l, theApp.m_remoteConfig.nextCommandID, pResponse);

replace(pResponse->begin(), pResponse->end(), '\n', ' ');
//message = string_format(_CONV("::<- %s\n"), pResponse->c_str());
message = string_format(_CONV("::<- %s\n"), "(hidden response)");
message = string_format(_CONV("::<- %s\n"), pResponse->c_str());
//message = string_format(_CONV("::<- %s\n"), "(hidden response)");
LogWinscardRules(message);

if (pRemoteConfig->bOpenSocketForEveryCommand) {
Expand Down

0 comments on commit c2b5674

Please sign in to comment.