Merge pull request #5884 from akallabeth/smartcard_ndr_strict
Smartcard tighter input validation
This commit is contained in:
commit
99786970a3
@ -73,8 +73,7 @@ static UINT irp_complete(IRP* irp)
|
||||
error = rdpdr_send(rdpdr, irp->output);
|
||||
irp->output = NULL;
|
||||
|
||||
irp_free(irp);
|
||||
return error;
|
||||
return irp_free(irp);
|
||||
}
|
||||
|
||||
IRP* irp_new(DEVMAN* devman, wStream* s, UINT* error)
|
||||
|
@ -1471,7 +1471,7 @@ static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, void*
|
||||
|
||||
data_in = rdpdr->data_in;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(data_in, (int)dataLength))
|
||||
if (!Stream_EnsureRemainingCapacity(data_in, dataLength))
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
|
||||
return ERROR_INVALID_DATA;
|
||||
@ -1602,6 +1602,12 @@ static DWORD WINAPI rdpdr_virtual_channel_client_thread(LPVOID arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void queue_free(void* obj)
|
||||
{
|
||||
wStream* s = obj;
|
||||
Stream_Free(s, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
@ -1630,6 +1636,8 @@ static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, LPVOID pDa
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
rdpdr->queue->object.fnObjectFree = queue_free;
|
||||
|
||||
if (!(rdpdr->thread =
|
||||
CreateThread(NULL, 0, rdpdr_virtual_channel_client_thread, (void*)rdpdr, 0, NULL)))
|
||||
{
|
||||
|
@ -211,7 +211,8 @@ static LONG smartcard_EstablishContext_Decode(SMARTCARD_DEVICE* smartcard,
|
||||
if (!call)
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_establish_context_call(smartcard, irp->input, call)))
|
||||
status = smartcard_unpack_establish_context_call(smartcard, irp->input, call);
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
{
|
||||
return log_status_error(TAG, "smartcard_unpack_establish_context_call", status);
|
||||
}
|
||||
@ -223,7 +224,7 @@ static LONG smartcard_EstablishContext_Call(SMARTCARD_DEVICE* smartcard,
|
||||
SMARTCARD_OPERATION* operation)
|
||||
{
|
||||
LONG status;
|
||||
SCARDCONTEXT hContext = -1;
|
||||
SCARDCONTEXT hContext = { 0 };
|
||||
EstablishContext_Return ret;
|
||||
IRP* irp = operation->irp;
|
||||
EstablishContext_Call* call = operation->call;
|
||||
@ -255,7 +256,8 @@ static LONG smartcard_EstablishContext_Call(SMARTCARD_DEVICE* smartcard,
|
||||
|
||||
smartcard_scard_context_native_to_redir(smartcard, &(ret.hContext), hContext);
|
||||
|
||||
if ((status = smartcard_pack_establish_context_return(smartcard, irp->output, &ret)))
|
||||
status = smartcard_pack_establish_context_return(smartcard, irp->output, &ret);
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
{
|
||||
return log_status_error(TAG, "smartcard_pack_establish_context_return", status);
|
||||
}
|
||||
@ -274,7 +276,8 @@ static LONG smartcard_ReleaseContext_Decode(SMARTCARD_DEVICE* smartcard,
|
||||
if (!call)
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_context_call(smartcard, irp->input, call, "ReleaseContext")))
|
||||
status = smartcard_unpack_context_call(smartcard, irp->input, call, "ReleaseContext");
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
log_status_error(TAG, "smartcard_unpack_context_call", status);
|
||||
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
|
||||
@ -364,7 +367,7 @@ static LONG smartcard_ListReaderGroupsA_Call(SMARTCARD_DEVICE* smartcard,
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
return status;
|
||||
|
||||
status = smartcard_pack_list_reader_groups_return(smartcard, irp->output, &ret);
|
||||
status = smartcard_pack_list_reader_groups_return(smartcard, irp->output, &ret, FALSE);
|
||||
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
return status;
|
||||
@ -409,7 +412,7 @@ static LONG smartcard_ListReaderGroupsW_Call(SMARTCARD_DEVICE* smartcard,
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
return status;
|
||||
|
||||
status = smartcard_pack_list_reader_groups_return(smartcard, irp->output, &ret);
|
||||
status = smartcard_pack_list_reader_groups_return(smartcard, irp->output, &ret, TRUE);
|
||||
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
return status;
|
||||
@ -538,7 +541,7 @@ static LONG smartcard_ListReadersA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_O
|
||||
call->mszGroups = NULL;
|
||||
}
|
||||
|
||||
if (status)
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
{
|
||||
return log_status_error(TAG, "SCardListReadersA", status);
|
||||
}
|
||||
@ -547,7 +550,8 @@ static LONG smartcard_ListReadersA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_O
|
||||
ret.msz = (BYTE*)mszReaders;
|
||||
ret.cBytes = cchReaders;
|
||||
|
||||
if ((status = smartcard_pack_list_readers_return(smartcard, irp->output, &ret, FALSE)))
|
||||
status = smartcard_pack_list_readers_return(smartcard, irp->output, &ret, FALSE);
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
{
|
||||
return log_status_error(TAG, "smartcard_pack_list_readers_return", status);
|
||||
}
|
||||
@ -684,7 +688,6 @@ static LONG smartcard_ListReadersW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_O
|
||||
{
|
||||
LONG status;
|
||||
ListReaders_Return ret;
|
||||
LPWSTR mszReaders = NULL;
|
||||
DWORD cchReaders = 0;
|
||||
IRP* irp = operation->irp;
|
||||
ListReaders_Call* call = operation->call;
|
||||
@ -693,11 +696,17 @@ static LONG smartcard_ListReadersW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_O
|
||||
const char* sz;
|
||||
const WCHAR* wz;
|
||||
} string;
|
||||
union {
|
||||
WCHAR** ppw;
|
||||
WCHAR* pw;
|
||||
CHAR* pc;
|
||||
BYTE* pb;
|
||||
} mszReaders;
|
||||
|
||||
string.bp = call->mszGroups;
|
||||
cchReaders = SCARD_AUTOALLOCATE;
|
||||
status = ret.ReturnCode =
|
||||
SCardListReadersW(operation->hContext, string.wz, (LPWSTR)&mszReaders, &cchReaders);
|
||||
SCardListReadersW(operation->hContext, string.wz, (LPWSTR)&mszReaders.pw, &cchReaders);
|
||||
|
||||
if (call->mszGroups)
|
||||
{
|
||||
@ -708,14 +717,13 @@ static LONG smartcard_ListReadersW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_O
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
return log_status_error(TAG, "SCardListReadersW", status);
|
||||
|
||||
cchReaders = filter_device_by_name_w(smartcard->names, &mszReaders, cchReaders);
|
||||
ret.msz = (BYTE*)mszReaders;
|
||||
ret.cBytes = cchReaders * 2;
|
||||
|
||||
cchReaders = filter_device_by_name_w(smartcard->names, &mszReaders.pw, cchReaders);
|
||||
ret.msz = mszReaders.pb;
|
||||
ret.cBytes = cchReaders;
|
||||
status = smartcard_pack_list_readers_return(smartcard, irp->output, &ret, TRUE);
|
||||
|
||||
if (mszReaders)
|
||||
SCardFreeMemory(operation->hContext, mszReaders);
|
||||
if (mszReaders.pb)
|
||||
SCardFreeMemory(operation->hContext, mszReaders.pb);
|
||||
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
return status;
|
||||
@ -945,24 +953,36 @@ static LONG smartcard_ReadCacheA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPE
|
||||
ReadCache_Return ret = { 0 };
|
||||
ReadCacheA_Call* call = operation->call;
|
||||
IRP* irp = operation->irp;
|
||||
BOOL autoalloc = (call->Common.cbDataLen == SCARD_AUTOALLOCATE);
|
||||
|
||||
if (!call->Common.fPbDataIsNULL)
|
||||
{
|
||||
ret.cbDataLen = call->Common.cbDataLen;
|
||||
ret.pbData = malloc(ret.cbDataLen);
|
||||
if (!ret.pbData)
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
if (autoalloc)
|
||||
{
|
||||
ret.pbData = malloc(ret.cbDataLen);
|
||||
if (!ret.pbData)
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ret.ReturnCode = SCardReadCacheA(operation->hContext, call->Common.CardIdentifier,
|
||||
call->Common.FreshnessCounter, call->szLookupName, ret.pbData,
|
||||
&ret.cbDataLen);
|
||||
if (autoalloc)
|
||||
ret.ReturnCode = SCardReadCacheA(operation->hContext, call->Common.CardIdentifier,
|
||||
call->Common.FreshnessCounter, call->szLookupName,
|
||||
(BYTE*)&ret.pbData, &ret.cbDataLen);
|
||||
else
|
||||
ret.ReturnCode = SCardReadCacheA(operation->hContext, call->Common.CardIdentifier,
|
||||
call->Common.FreshnessCounter, call->szLookupName,
|
||||
ret.pbData, &ret.cbDataLen);
|
||||
log_status_error(TAG, "SCardReadCacheA", ret.ReturnCode);
|
||||
free(call->szLookupName);
|
||||
free(call->Common.CardIdentifier);
|
||||
|
||||
status = smartcard_pack_read_cache_return(smartcard, irp->output, &ret);
|
||||
free(ret.pbData);
|
||||
if (autoalloc)
|
||||
SCardFreeMemory(operation->hContext, ret.pbData);
|
||||
else
|
||||
free(ret.pbData);
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
return status;
|
||||
|
||||
@ -975,24 +995,35 @@ static LONG smartcard_ReadCacheW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPE
|
||||
ReadCache_Return ret = { 0 };
|
||||
ReadCacheW_Call* call = operation->call;
|
||||
IRP* irp = operation->irp;
|
||||
|
||||
BOOL autoalloc = (call->Common.cbDataLen == SCARD_AUTOALLOCATE);
|
||||
if (!call->Common.fPbDataIsNULL)
|
||||
{
|
||||
ret.cbDataLen = call->Common.cbDataLen;
|
||||
ret.pbData = malloc(ret.cbDataLen);
|
||||
if (!ret.pbData)
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
if (autoalloc)
|
||||
{
|
||||
ret.pbData = malloc(ret.cbDataLen);
|
||||
if (!ret.pbData)
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ret.ReturnCode = SCardReadCacheW(operation->hContext, call->Common.CardIdentifier,
|
||||
call->Common.FreshnessCounter, call->szLookupName, ret.pbData,
|
||||
&ret.cbDataLen);
|
||||
if (autoalloc)
|
||||
ret.ReturnCode = SCardReadCacheW(operation->hContext, call->Common.CardIdentifier,
|
||||
call->Common.FreshnessCounter, call->szLookupName,
|
||||
(BYTE*)&ret.pbData, &ret.cbDataLen);
|
||||
else
|
||||
ret.ReturnCode = SCardReadCacheW(operation->hContext, call->Common.CardIdentifier,
|
||||
call->Common.FreshnessCounter, call->szLookupName,
|
||||
ret.pbData, &ret.cbDataLen);
|
||||
log_status_error(TAG, "SCardReadCacheW", ret.ReturnCode);
|
||||
free(call->szLookupName);
|
||||
free(call->Common.CardIdentifier);
|
||||
|
||||
status = smartcard_pack_read_cache_return(smartcard, irp->output, &ret);
|
||||
free(ret.pbData);
|
||||
if (autoalloc)
|
||||
SCardFreeMemory(operation->hContext, ret.pbData);
|
||||
else
|
||||
free(ret.pbData);
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
return status;
|
||||
|
||||
@ -1042,7 +1073,8 @@ static LONG smartcard_GetTransmitCount_Call(SMARTCARD_DEVICE* smartcard,
|
||||
|
||||
ret.ReturnCode = SCardGetTransmitCount(operation->hContext, &ret.cTransmitCount);
|
||||
log_status_error(TAG, "SCardGetTransmitCount", ret.ReturnCode);
|
||||
if ((status = smartcard_pack_get_transmit_count_return(smartcard, irp->output, &ret)))
|
||||
status = smartcard_pack_get_transmit_count_return(smartcard, irp->output, &ret);
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
return status;
|
||||
|
||||
return ret.ReturnCode;
|
||||
@ -1074,7 +1106,7 @@ static LONG smartcard_GetReaderIcon_Call(SMARTCARD_DEVICE* smartcard,
|
||||
free(call->szReaderName);
|
||||
status = smartcard_pack_get_reader_icon_return(smartcard, irp->output, &ret);
|
||||
SCardFreeMemory(operation->hContext, ret.pbData);
|
||||
if (status)
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
return status;
|
||||
|
||||
return ret.ReturnCode;
|
||||
@ -1094,7 +1126,7 @@ static LONG smartcard_GetDeviceTypeId_Call(SMARTCARD_DEVICE* smartcard,
|
||||
free(call->szReaderName);
|
||||
|
||||
status = smartcard_pack_device_type_id_return(smartcard, irp->output, &ret);
|
||||
if (status)
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
return status;
|
||||
|
||||
return ret.ReturnCode;
|
||||
@ -1144,7 +1176,8 @@ static LONG smartcard_GetStatusChangeA_Call(SMARTCARD_DEVICE* smartcard,
|
||||
ret.rgReaderStates[index].dwCurrentState = call->rgReaderStates[index].dwCurrentState;
|
||||
ret.rgReaderStates[index].dwEventState = call->rgReaderStates[index].dwEventState;
|
||||
ret.rgReaderStates[index].cbAtr = call->rgReaderStates[index].cbAtr;
|
||||
CopyMemory(&(ret.rgReaderStates[index].rgbAtr), &(call->rgReaderStates[index].rgbAtr), 32);
|
||||
CopyMemory(&(ret.rgReaderStates[index].rgbAtr), &(call->rgReaderStates[index].rgbAtr),
|
||||
sizeof(ret.rgReaderStates[index].rgbAtr));
|
||||
}
|
||||
|
||||
smartcard_pack_get_status_change_return(smartcard, irp->output, &ret, FALSE);
|
||||
@ -1208,7 +1241,8 @@ static LONG smartcard_GetStatusChangeW_Call(SMARTCARD_DEVICE* smartcard,
|
||||
ret.rgReaderStates[index].dwCurrentState = call->rgReaderStates[index].dwCurrentState;
|
||||
ret.rgReaderStates[index].dwEventState = call->rgReaderStates[index].dwEventState;
|
||||
ret.rgReaderStates[index].cbAtr = call->rgReaderStates[index].cbAtr;
|
||||
CopyMemory(&(ret.rgReaderStates[index].rgbAtr), &(call->rgReaderStates[index].rgbAtr), 32);
|
||||
CopyMemory(&(ret.rgReaderStates[index].rgbAtr), &(call->rgReaderStates[index].rgbAtr),
|
||||
sizeof(ret.rgReaderStates[index].rgbAtr));
|
||||
}
|
||||
|
||||
smartcard_pack_get_status_change_return(smartcard, irp->output, &ret, TRUE);
|
||||
@ -1290,13 +1324,6 @@ static LONG smartcard_ConnectA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERA
|
||||
call->Common.dwPreferredProtocols, &hCard, &ret.dwActiveProtocol);
|
||||
smartcard_scard_context_native_to_redir(smartcard, &(ret.hContext), operation->hContext);
|
||||
smartcard_scard_handle_native_to_redir(smartcard, &(ret.hCard), hCard);
|
||||
smartcard_trace_connect_return(smartcard, &ret);
|
||||
|
||||
if (status)
|
||||
{
|
||||
log_status_error(TAG, "SCardConnectA", status);
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
status = smartcard_pack_connect_return(smartcard, irp->output, &ret);
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
@ -1344,13 +1371,6 @@ static LONG smartcard_ConnectW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERA
|
||||
call->Common.dwPreferredProtocols, &hCard, &ret.dwActiveProtocol);
|
||||
smartcard_scard_context_native_to_redir(smartcard, &(ret.hContext), operation->hContext);
|
||||
smartcard_scard_handle_native_to_redir(smartcard, &(ret.hCard), hCard);
|
||||
smartcard_trace_connect_return(smartcard, &ret);
|
||||
|
||||
if (status)
|
||||
{
|
||||
log_status_error(TAG, "SCardConnectW", status);
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
status = smartcard_pack_connect_return(smartcard, irp->output, &ret);
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
@ -1545,7 +1565,7 @@ static LONG smartcard_StatusA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERAT
|
||||
LPSTR mszReaderNames = NULL;
|
||||
IRP* irp = operation->irp;
|
||||
Status_Call* call = operation->call;
|
||||
ZeroMemory(ret.pbAtr, 32);
|
||||
|
||||
call->cbAtrLen = 32;
|
||||
cbAtrLen = call->cbAtrLen;
|
||||
|
||||
@ -1601,8 +1621,7 @@ static LONG smartcard_StatusW_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPER
|
||||
static LONG smartcard_StatusW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation)
|
||||
{
|
||||
LONG status;
|
||||
Status_Return ret;
|
||||
DWORD cchReaderLen = 0;
|
||||
Status_Return ret = { 0 };
|
||||
LPWSTR mszReaderNames = NULL;
|
||||
IRP* irp = operation->irp;
|
||||
Status_Call* call = operation->call;
|
||||
@ -1615,28 +1634,19 @@ static LONG smartcard_StatusW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERAT
|
||||
cbAtrLen = call->cbAtrLen = 32;
|
||||
|
||||
if (call->fmszReaderNamesIsNULL)
|
||||
cchReaderLen = 0;
|
||||
ret.cBytes = 0;
|
||||
else
|
||||
cchReaderLen = SCARD_AUTOALLOCATE;
|
||||
ret.cBytes = SCARD_AUTOALLOCATE;
|
||||
|
||||
ZeroMemory(ret.pbAtr, 32);
|
||||
status = ret.ReturnCode =
|
||||
SCardStatusW(operation->hCard, call->fmszReaderNamesIsNULL ? NULL : (LPWSTR)&mszReaderNames,
|
||||
&cchReaderLen, &ret.dwState, &ret.dwProtocol, (BYTE*)&ret.pbAtr, &cbAtrLen);
|
||||
&ret.cBytes, &ret.dwState, &ret.dwProtocol, (BYTE*)&ret.pbAtr, &cbAtrLen);
|
||||
log_status_error(TAG, "SCardStatusW", status);
|
||||
if (status == SCARD_S_SUCCESS)
|
||||
{
|
||||
if (!call->fmszReaderNamesIsNULL)
|
||||
ret.mszReaderNames = (BYTE*)mszReaderNames;
|
||||
|
||||
// WinScard returns the number of CHARACTERS whereas pcsc-lite returns the
|
||||
// number of BYTES.
|
||||
#ifdef _WIN32
|
||||
ret.cBytes = cchReaderLen * 2;
|
||||
#else
|
||||
ret.cBytes = cchReaderLen;
|
||||
#endif
|
||||
|
||||
ret.cbAtrLen = cbAtrLen;
|
||||
}
|
||||
|
||||
@ -1701,7 +1711,7 @@ static LONG smartcard_Transmit_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERA
|
||||
free(call->pioSendPci);
|
||||
free(call->pioRecvPci);
|
||||
|
||||
if (status)
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
return status;
|
||||
return ret.ReturnCode;
|
||||
}
|
||||
@ -1811,23 +1821,14 @@ static LONG smartcard_GetAttrib_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPER
|
||||
autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr, &cbAttrLen);
|
||||
log_status_error(TAG, "SCardGetAttrib", ret.ReturnCode);
|
||||
ret.cbAttrLen = cbAttrLen;
|
||||
free(ret.pbAttr);
|
||||
|
||||
if (ret.ReturnCode)
|
||||
{
|
||||
WLog_WARN(TAG, "SCardGetAttrib: %s (0x%08" PRIX32 ") cbAttrLen: %" PRIu32 "",
|
||||
SCardGetAttributeString(call->dwAttrId), call->dwAttrId, call->cbAttrLen);
|
||||
Stream_Zero(irp->output, 256);
|
||||
|
||||
return ret.ReturnCode;
|
||||
}
|
||||
|
||||
status = smartcard_pack_get_attrib_return(smartcard, irp->output, &ret, call->dwAttrId);
|
||||
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
return status;
|
||||
|
||||
return ret.ReturnCode;
|
||||
if (autoAllocate)
|
||||
SCardFreeMemory(operation->hContext, ret.pbAttr);
|
||||
else
|
||||
free(ret.pbAttr);
|
||||
return status;
|
||||
}
|
||||
|
||||
static LONG smartcard_SetAttrib_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation)
|
||||
@ -2115,7 +2116,8 @@ static LONG smartcard_LocateCardsByATRA_Call(SMARTCARD_DEVICE* smartcard,
|
||||
ret.rgReaderStates[i].dwCurrentState = state->dwCurrentState;
|
||||
ret.rgReaderStates[i].dwEventState = state->dwEventState;
|
||||
ret.rgReaderStates[i].cbAtr = state->cbAtr;
|
||||
CopyMemory(&(ret.rgReaderStates[i].rgbAtr), &(state->rgbAtr), 32);
|
||||
CopyMemory(&(ret.rgReaderStates[i].rgbAtr), &(state->rgbAtr),
|
||||
sizeof(ret.rgReaderStates[i].rgbAtr));
|
||||
}
|
||||
|
||||
free(states);
|
||||
@ -2184,10 +2186,12 @@ LONG smartcard_irp_device_control_decode(SMARTCARD_DEVICE* smartcard,
|
||||
if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
|
||||
(ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
|
||||
{
|
||||
if ((status = smartcard_unpack_common_type_header(smartcard, irp->input)))
|
||||
status = smartcard_unpack_common_type_header(smartcard, irp->input);
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
return status;
|
||||
|
||||
if ((status = smartcard_unpack_private_type_header(smartcard, irp->input)))
|
||||
status = smartcard_unpack_private_type_header(smartcard, irp->input);
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -2451,7 +2455,9 @@ LONG smartcard_irp_device_control_call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OP
|
||||
* Since it's a SHOULD and not a MUST, we don't care
|
||||
* about it, but we still reserve at least 2048 bytes.
|
||||
*/
|
||||
Stream_EnsureRemainingCapacity(irp->output, 2048);
|
||||
if (!Stream_EnsureRemainingCapacity(irp->output, 2048))
|
||||
return SCARD_E_NO_MEMORY;
|
||||
|
||||
/* Device Control Response */
|
||||
Stream_Seek_UINT32(irp->output); /* OutputBufferLength (4 bytes) */
|
||||
Stream_Seek(irp->output, SMARTCARD_COMMON_TYPE_HEADER_LENGTH); /* CommonTypeHeader (8 bytes) */
|
||||
@ -2687,7 +2693,7 @@ LONG smartcard_irp_device_control_call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OP
|
||||
|
||||
irp->IoStatus = STATUS_SUCCESS;
|
||||
|
||||
if ((result & 0xC0000000) == 0xC0000000)
|
||||
if ((result & 0xC0000000L) == 0xC0000000L)
|
||||
{
|
||||
/* NTSTATUS error */
|
||||
irp->IoStatus = (UINT32)result;
|
||||
@ -2704,7 +2710,7 @@ LONG smartcard_irp_device_control_call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OP
|
||||
smartcard_pack_common_type_header(smartcard, irp->output); /* CommonTypeHeader (8 bytes) */
|
||||
smartcard_pack_private_type_header(smartcard, irp->output,
|
||||
objectBufferLength); /* PrivateTypeHeader (8 bytes) */
|
||||
Stream_Write_UINT32(irp->output, result); /* Result (4 bytes) */
|
||||
Stream_Write_INT32(irp->output, result); /* Result (4 bytes) */
|
||||
Stream_SetPosition(irp->output, Stream_Length(irp->output));
|
||||
return SCARD_S_SUCCESS;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,8 @@
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2015 Thincast Technologies GmbH
|
||||
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
|
||||
* Copyright 2020 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2020 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -26,6 +28,8 @@
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/smartcard.h>
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/* interface type_scard_pack */
|
||||
/* [unique][version][uuid] */
|
||||
|
||||
@ -138,7 +142,7 @@ typedef struct _LocateCardsA_Call
|
||||
{
|
||||
REDIR_SCARDCONTEXT hContext;
|
||||
/* [range] */ DWORD cBytes;
|
||||
/* [size_is] */ char* mszCards;
|
||||
/* [size_is] */ CHAR* mszCards;
|
||||
/* [range] */ DWORD cReaders;
|
||||
/* [size_is] */ LPSCARD_READERSTATEA rgReaderStates;
|
||||
} LocateCardsA_Call;
|
||||
@ -228,7 +232,7 @@ typedef struct _Connect_Common
|
||||
|
||||
typedef struct _ConnectA_Call
|
||||
{
|
||||
/* [string] */ unsigned char* szReader;
|
||||
/* [string] */ CHAR* szReader;
|
||||
Connect_Common Common;
|
||||
} ConnectA_Call;
|
||||
|
||||
@ -436,14 +440,16 @@ typedef struct _WriteCacheW_Call
|
||||
WriteCache_Common Common;
|
||||
} WriteCacheW_Call;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#define SMARTCARD_COMMON_TYPE_HEADER_LENGTH 8
|
||||
#define SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH 8
|
||||
|
||||
#include "smartcard_main.h"
|
||||
|
||||
LONG smartcard_pack_write_size_align(SMARTCARD_DEVICE* smartcard, wStream* s, UINT32 size,
|
||||
LONG smartcard_pack_write_size_align(SMARTCARD_DEVICE* smartcard, wStream* s, size_t size,
|
||||
UINT32 alignment);
|
||||
LONG smartcard_unpack_read_size_align(SMARTCARD_DEVICE* smartcard, wStream* s, UINT32 size,
|
||||
LONG smartcard_unpack_read_size_align(SMARTCARD_DEVICE* smartcard, wStream* s, size_t size,
|
||||
UINT32 alignment);
|
||||
|
||||
SCARDCONTEXT smartcard_scard_context_native_from_redir(SMARTCARD_DEVICE* smartcard,
|
||||
@ -479,7 +485,7 @@ LONG smartcard_unpack_list_reader_groups_call(SMARTCARD_DEVICE* smartcard, wStre
|
||||
ListReaderGroups_Call* call, BOOL unicode);
|
||||
|
||||
LONG smartcard_pack_list_reader_groups_return(SMARTCARD_DEVICE* smartcard, wStream* s,
|
||||
const ListReaderGroups_Return* ret);
|
||||
const ListReaderGroups_Return* ret, BOOL unicode);
|
||||
|
||||
LONG smartcard_unpack_list_readers_call(SMARTCARD_DEVICE* smartcard, wStream* s,
|
||||
ListReaders_Call* call, BOOL unicode);
|
||||
@ -515,8 +521,8 @@ LONG smartcard_unpack_connect_a_call(SMARTCARD_DEVICE* smartcard, wStream* s, Co
|
||||
|
||||
LONG smartcard_unpack_connect_w_call(SMARTCARD_DEVICE* smartcard, wStream* s, ConnectW_Call* call);
|
||||
|
||||
LONG smartcard_pack_connect_return(SMARTCARD_DEVICE* smartcard, wStream* s, Connect_Return* ret);
|
||||
void smartcard_trace_connect_return(SMARTCARD_DEVICE* smartcard, const Connect_Return* ret);
|
||||
LONG smartcard_pack_connect_return(SMARTCARD_DEVICE* smartcard, wStream* s,
|
||||
const Connect_Return* ret);
|
||||
|
||||
LONG smartcard_unpack_reconnect_call(SMARTCARD_DEVICE* smartcard, wStream* s, Reconnect_Call* call);
|
||||
|
||||
@ -553,9 +559,6 @@ LONG smartcard_pack_get_attrib_return(SMARTCARD_DEVICE* smartcard, wStream* s,
|
||||
LONG smartcard_unpack_set_attrib_call(SMARTCARD_DEVICE* smartcard, wStream* s,
|
||||
SetAttrib_Call* call);
|
||||
|
||||
LONG smartcard_pack_set_attrib_return(SMARTCARD_DEVICE* smartcard, wStream* s,
|
||||
const GetAttrib_Return* ret);
|
||||
|
||||
LONG smartcard_unpack_control_call(SMARTCARD_DEVICE* smartcard, wStream* s, Control_Call* call);
|
||||
|
||||
LONG smartcard_pack_control_return(SMARTCARD_DEVICE* smartcard, wStream* s,
|
||||
|
921
scripts/test-scard.cpp
Normal file
921
scripts/test-scard.cpp
Normal file
@ -0,0 +1,921 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Smartcard API test program
|
||||
*
|
||||
* This simple program can be used to trigger calls for (almost) the
|
||||
* entire SCARD API.
|
||||
* Compile on windows, connect with FreeRDP via RDP with smartcard
|
||||
* redirection enabled and run this test program on the windows
|
||||
* machine.
|
||||
*
|
||||
* Copyright 2020 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2020 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
|
||||
#include <comdef.h>
|
||||
#include <winscard.h>
|
||||
|
||||
static const WCHAR* listW[] = { nullptr, L"SCard$AllReaders\000", L"SCard$DefaultReaders\000",
|
||||
L"SCard$LocalReaders\000", L"SCard$SystemReaders\000" };
|
||||
static const char* listA[] = { nullptr, "SCard$AllReaders\000", "SCard$DefaultReaders\000",
|
||||
"SCard$LocalReaders\000", "SCard$SystemReaders\000" };
|
||||
|
||||
static std::string scope2str(DWORD scope)
|
||||
{
|
||||
switch (scope)
|
||||
{
|
||||
case SCARD_SCOPE_USER:
|
||||
return "SCARD_SCOPE_USER";
|
||||
case SCARD_SCOPE_TERMINAL:
|
||||
return "SCARD_SCOPE_TERMINAL";
|
||||
case SCARD_SCOPE_SYSTEM:
|
||||
return "SCARD_SCOPE_SYSTEM";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static std::string err2str(LONG code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case ERROR_BROKEN_PIPE:
|
||||
return "ERROR_BROKEN_PIPE";
|
||||
case SCARD_E_BAD_SEEK:
|
||||
return "SCARD_E_BAD_SEEK";
|
||||
case SCARD_E_CANCELLED:
|
||||
return "SCARD_E_CANCELLED";
|
||||
case SCARD_E_CANT_DISPOSE:
|
||||
return "SCARD_E_CANT_DISPOSE";
|
||||
case SCARD_E_CARD_UNSUPPORTED:
|
||||
return "SCARD_E_CARD_UNSUPPORTED";
|
||||
case SCARD_E_CERTIFICATE_UNAVAILABLE:
|
||||
return "SCARD_E_CERTIFICATE_UNAVAILABLE";
|
||||
case SCARD_E_COMM_DATA_LOST:
|
||||
return "SCARD_E_COMM_DATA_LOST";
|
||||
case SCARD_E_DIR_NOT_FOUND:
|
||||
return "SCARD_E_DIR_NOT_FOUND";
|
||||
case SCARD_E_DUPLICATE_READER:
|
||||
return "SCARD_E_DUPLICATE_READER";
|
||||
case SCARD_E_FILE_NOT_FOUND:
|
||||
return "SCARD_E_FILE_NOT_FOUND";
|
||||
case SCARD_E_ICC_CREATEORDER:
|
||||
return "SCARD_E_ICC_CREATEORDER";
|
||||
case SCARD_E_ICC_INSTALLATION:
|
||||
return "SCARD_E_ICC_INSTALLATION";
|
||||
case SCARD_E_INSUFFICIENT_BUFFER:
|
||||
return "SCARD_E_INSUFFICIENT_BUFFER";
|
||||
case SCARD_E_INVALID_ATR:
|
||||
return "SCARD_E_INVALID_ATR";
|
||||
case SCARD_E_INVALID_CHV:
|
||||
return "SCARD_E_INVALID_CHV";
|
||||
case SCARD_E_INVALID_HANDLE:
|
||||
return "SCARD_E_INVALID_HANDLE";
|
||||
case SCARD_E_INVALID_PARAMETER:
|
||||
return "SCARD_E_INVALID_PARAMETER";
|
||||
case SCARD_E_INVALID_TARGET:
|
||||
return "SCARD_E_INVALID_TARGET";
|
||||
case SCARD_E_INVALID_VALUE:
|
||||
return "SCARD_E_INVALID_VALUE";
|
||||
case SCARD_E_NO_ACCESS:
|
||||
return "SCARD_E_NO_ACCESS";
|
||||
case SCARD_E_NO_DIR:
|
||||
return "SCARD_E_NO_DIR";
|
||||
case SCARD_E_NO_FILE:
|
||||
return "SCARD_E_NO_FILE";
|
||||
case SCARD_E_NO_KEY_CONTAINER:
|
||||
return "SCARD_E_NO_KEY_CONTAINER";
|
||||
case SCARD_E_NO_MEMORY:
|
||||
return "SCARD_E_NO_MEMORY";
|
||||
case SCARD_E_NO_PIN_CACHE:
|
||||
return "SCARD_E_NO_PIN_CACHE";
|
||||
case SCARD_E_NO_READERS_AVAILABLE:
|
||||
return "SCARD_E_NO_READERS_AVAILABLE";
|
||||
case SCARD_E_NO_SERVICE:
|
||||
return "SCARD_E_NO_SERVICE";
|
||||
case SCARD_E_NO_SMARTCARD:
|
||||
return "SCARD_E_NO_SMARTCARD";
|
||||
case SCARD_E_NO_SUCH_CERTIFICATE:
|
||||
return "SCARD_E_NO_SUCH_CERTIFICATE";
|
||||
case SCARD_E_NOT_READY:
|
||||
return "SCARD_E_NOT_READY";
|
||||
case SCARD_E_NOT_TRANSACTED:
|
||||
return "SCARD_E_NOT_TRANSACTED";
|
||||
case SCARD_E_PCI_TOO_SMALL:
|
||||
return "SCARD_E_PCI_TOO_SMALL";
|
||||
case SCARD_E_PIN_CACHE_EXPIRED:
|
||||
return "SCARD_E_PIN_CACHE_EXPIRED";
|
||||
case SCARD_E_PROTO_MISMATCH:
|
||||
return "SCARD_E_PROTO_MISMATCH";
|
||||
case SCARD_E_READ_ONLY_CARD:
|
||||
return "SCARD_E_READ_ONLY_CARD";
|
||||
case SCARD_E_READER_UNAVAILABLE:
|
||||
return "SCARD_E_READER_UNAVAILABLE";
|
||||
case SCARD_E_READER_UNSUPPORTED:
|
||||
return "SCARD_E_READER_UNSUPPORTED";
|
||||
case SCARD_E_SERVER_TOO_BUSY:
|
||||
return "SCARD_E_SERVER_TOO_BUSY";
|
||||
case SCARD_E_SERVICE_STOPPED:
|
||||
return "SCARD_E_SERVICE_STOPPED";
|
||||
case SCARD_E_SHARING_VIOLATION:
|
||||
return "SCARD_E_SHARING_VIOLATION";
|
||||
case SCARD_E_SYSTEM_CANCELLED:
|
||||
return "SCARD_E_SYSTEM_CANCELLED";
|
||||
case SCARD_E_TIMEOUT:
|
||||
return "SCARD_E_TIMEOUT";
|
||||
case SCARD_E_UNEXPECTED:
|
||||
return "SCARD_E_UNEXPECTED";
|
||||
case SCARD_E_UNKNOWN_CARD:
|
||||
return "SCARD_E_UNKNOWN_CARD";
|
||||
case SCARD_E_UNKNOWN_READER:
|
||||
return "SCARD_E_UNKNOWN_READER";
|
||||
case SCARD_E_UNKNOWN_RES_MNG:
|
||||
return "SCARD_E_UNKNOWN_RES_MNG";
|
||||
case SCARD_E_UNSUPPORTED_FEATURE:
|
||||
return "SCARD_E_UNSUPPORTED_FEATURE";
|
||||
case SCARD_E_WRITE_TOO_MANY:
|
||||
return "SCARD_E_WRITE_TOO_MANY";
|
||||
case SCARD_F_COMM_ERROR:
|
||||
return "SCARD_F_COMM_ERROR";
|
||||
case SCARD_F_INTERNAL_ERROR:
|
||||
return "SCARD_F_INTERNAL_ERROR";
|
||||
case SCARD_F_UNKNOWN_ERROR:
|
||||
return "SCARD_F_UNKNOWN_ERROR";
|
||||
case SCARD_F_WAITED_TOO_LONG:
|
||||
return "SCARD_F_WAITED_TOO_LONG";
|
||||
case SCARD_P_SHUTDOWN:
|
||||
return "SCARD_P_SHUTDOWN";
|
||||
case SCARD_S_SUCCESS:
|
||||
return "SCARD_S_SUCCESS";
|
||||
case SCARD_W_CANCELLED_BY_USER:
|
||||
return "SCARD_W_CANCELLED_BY_USER";
|
||||
case SCARD_W_CACHE_ITEM_NOT_FOUND:
|
||||
return "SCARD_W_CACHE_ITEM_NOT_FOUND";
|
||||
case SCARD_W_CACHE_ITEM_STALE:
|
||||
return "SCARD_W_CACHE_ITEM_STALE";
|
||||
case SCARD_W_CACHE_ITEM_TOO_BIG:
|
||||
return "SCARD_W_CACHE_ITEM_TOO_BIG";
|
||||
case SCARD_W_CARD_NOT_AUTHENTICATED:
|
||||
return "SCARD_W_CARD_NOT_AUTHENTICATED";
|
||||
case SCARD_W_CHV_BLOCKED:
|
||||
return "SCARD_W_CHV_BLOCKED";
|
||||
case SCARD_W_EOF:
|
||||
return "SCARD_W_EOF";
|
||||
case SCARD_W_REMOVED_CARD:
|
||||
return "SCARD_W_REMOVED_CARD";
|
||||
case SCARD_W_RESET_CARD:
|
||||
return "SCARD_W_RESET_CARD";
|
||||
case SCARD_W_SECURITY_VIOLATION:
|
||||
return "SCARD_W_SECURITY_VIOLATION";
|
||||
case SCARD_W_UNPOWERED_CARD:
|
||||
return "SCARD_W_UNPOWERED_CARD";
|
||||
case SCARD_W_UNRESPONSIVE_CARD:
|
||||
return "SCARD_W_UNRESPONSIVE_CARD";
|
||||
case SCARD_W_UNSUPPORTED_CARD:
|
||||
return "SCARD_W_UNSUPPORTED_CARD";
|
||||
case SCARD_W_WRONG_CHV:
|
||||
return "SCARD_W_WRONG_CHV";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static std::wstring err2wstr(LONG code)
|
||||
{
|
||||
auto str = err2str(code);
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||
return converter.from_bytes(str);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static bool test_listreadergroups(SCARDCONTEXT hContext) {
|
||||
auto rc = SCardListReaderGroupsA(hContext, &groups, &foobar);
|
||||
rc = SCardListReaderGroupsW(hContext, &groups, &foobar);
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool test_valid(SCARDCONTEXT context)
|
||||
{
|
||||
auto rc = SCardIsValidContext(context);
|
||||
if (rc)
|
||||
std::cerr << "SCardIsValidContext failed with " << err2str(rc) << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_list_readers_a(SCARDCONTEXT context)
|
||||
{
|
||||
for (auto cur : listA)
|
||||
{
|
||||
LPSTR mszReaders = nullptr;
|
||||
DWORD chReaders = SCARD_AUTOALLOCATE;
|
||||
auto rc = SCardListReadersA(context, cur, reinterpret_cast<LPSTR>(&mszReaders), &chReaders);
|
||||
if (!cur)
|
||||
{
|
||||
cur = "NULL";
|
||||
}
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardListReadersA [" << cur << "] failed with " << err2str(rc)
|
||||
<< std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto start = mszReaders;
|
||||
auto end = &mszReaders[chReaders];
|
||||
|
||||
std::cout << "SCardListReadersA [" << cur << "] " << chReaders << " [";
|
||||
while (start < end)
|
||||
{
|
||||
std::cout << start << ", ";
|
||||
start += strnlen(start, chReaders) + 2;
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
}
|
||||
SCardFreeMemory(context, mszReaders);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_list_readers_w(SCARDCONTEXT context)
|
||||
{
|
||||
for (auto cur : listW)
|
||||
{
|
||||
LPWSTR mszReaders = nullptr;
|
||||
DWORD chReaders = SCARD_AUTOALLOCATE;
|
||||
auto rc =
|
||||
SCardListReadersW(context, cur, reinterpret_cast<LPWSTR>(&mszReaders), &chReaders);
|
||||
if (!cur)
|
||||
{
|
||||
cur = L"NULL";
|
||||
}
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::wcerr << L"SCardListReadersW [" << cur << L"] failed with " << err2wstr(rc)
|
||||
<< std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto start = mszReaders;
|
||||
auto end = &mszReaders[chReaders];
|
||||
|
||||
std::wcout << L"SCardListReadersW [" << cur << L"] " << chReaders << L" [";
|
||||
while (start < end)
|
||||
{
|
||||
std::wcout << start << L", ";
|
||||
start += wcsnlen(start, chReaders) + 2;
|
||||
}
|
||||
std::wcout << L"]" << std::endl;
|
||||
}
|
||||
SCardFreeMemory(context, mszReaders);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_list_reader_groups_a(SCARDCONTEXT context)
|
||||
{
|
||||
LPSTR mszReaders = nullptr;
|
||||
DWORD chReaders = SCARD_AUTOALLOCATE;
|
||||
auto rc = SCardListReaderGroupsA(context, reinterpret_cast<LPSTR>(&mszReaders), &chReaders);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardListReaderGroupsA failed with " << err2str(rc) << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto start = mszReaders;
|
||||
auto end = &mszReaders[chReaders];
|
||||
|
||||
std::cout << "SCardListReaderGroupsA " << chReaders << " [";
|
||||
while (start < end)
|
||||
{
|
||||
std::cout << start << ", ";
|
||||
start += strnlen(start, chReaders) + 2;
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
}
|
||||
SCardFreeMemory(context, mszReaders);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_list_reader_groups_w(SCARDCONTEXT context)
|
||||
{
|
||||
LPWSTR mszReaders = nullptr;
|
||||
DWORD chReaders = SCARD_AUTOALLOCATE;
|
||||
auto rc = SCardListReaderGroupsW(context, reinterpret_cast<LPWSTR>(&mszReaders), &chReaders);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::wcerr << L"SCardListReaderGroupsW failed with " << err2wstr(rc) << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto start = mszReaders;
|
||||
auto end = &mszReaders[chReaders];
|
||||
|
||||
std::wcout << L"SCardListReaderGroupsW " << chReaders << L" [";
|
||||
while (start < end)
|
||||
{
|
||||
std::wcout << start << L", ";
|
||||
start += wcsnlen(start, chReaders) + 2;
|
||||
}
|
||||
std::wcout << L"]" << std::endl;
|
||||
}
|
||||
SCardFreeMemory(context, mszReaders);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_introduce_forget_reader_groups_a(SCARDCONTEXT context)
|
||||
{
|
||||
LPSTR group = "somefancygroup";
|
||||
|
||||
auto rc = SCardIntroduceReaderGroupA(context, group);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardIntroduceReaderGroupA failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SCardForgetReaderGroupA(context, group);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardForgetReaderGroupA failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool test_introduce_forget_reader_groups_w(SCARDCONTEXT context)
|
||||
{
|
||||
LPWSTR group = L"somefancygroup";
|
||||
|
||||
auto rc = SCardIntroduceReaderGroupW(context, group);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardIntroduceReaderGroupW failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SCardForgetReaderGroupW(context, group);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardForgetReaderGroupW failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool test_introduce_forget_reader_a(SCARDCONTEXT context)
|
||||
{
|
||||
LPSTR reader = "somefancygroup";
|
||||
LPSTR device = "otherfancy";
|
||||
|
||||
auto rc = SCardIntroduceReaderA(context, reader, device);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardIntroduceReaderA failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SCardForgetReaderA(context, reader);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardForgetReaderA failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool test_introduce_forget_reader_w(SCARDCONTEXT context)
|
||||
{
|
||||
LPWSTR reader = L"somefancygroup";
|
||||
LPWSTR device = L"otherfancy";
|
||||
|
||||
auto rc = SCardIntroduceReaderW(context, reader, device);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardIntroduceReaderW failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SCardForgetReaderW(context, reader);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardForgetReaderW failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool test_list_cards_a(SCARDCONTEXT context)
|
||||
{
|
||||
DWORD chCards = SCARD_AUTOALLOCATE;
|
||||
LPSTR mszCards = nullptr;
|
||||
auto rc =
|
||||
SCardListCardsA(context, nullptr, nullptr, 0, reinterpret_cast<LPSTR>(&mszCards), &chCards);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardListCardsA failed with " << err2str(rc) << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto start = mszCards;
|
||||
auto end = &mszCards[chCards];
|
||||
std::cout << "SCardListCardsA " << chCards << " [";
|
||||
while (start < end)
|
||||
{
|
||||
std::cout << start << ", ";
|
||||
start += strnlen(start, chCards) + 2;
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_list_cards_w(SCARDCONTEXT context)
|
||||
{
|
||||
DWORD chCards = SCARD_AUTOALLOCATE;
|
||||
LPWSTR mszCards = nullptr;
|
||||
auto rc = SCardListCardsW(context, nullptr, nullptr, 0, reinterpret_cast<LPWSTR>(&mszCards),
|
||||
&chCards);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardListCardsW failed with " << err2str(rc) << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto start = mszCards;
|
||||
auto end = &mszCards[chCards];
|
||||
std::cout << "SCardListCardsW " << chCards << " [";
|
||||
while (start < end)
|
||||
{
|
||||
std::wcout << start << L", ";
|
||||
start += wcsnlen(start, chCards) + 2;
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_cache_a(SCARDCONTEXT context)
|
||||
{
|
||||
BYTE wdata[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
const DWORD wdatalen = sizeof(wdata);
|
||||
BYTE data[32] = {};
|
||||
DWORD datalen = sizeof(data);
|
||||
LPSTR name = "testdata";
|
||||
UUID id = {};
|
||||
|
||||
auto rc = SCardWriteCacheA(context, &id, 0, name, wdata, wdatalen);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardWriteCacheA failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
rc = SCardReadCacheA(context, &id, 0, name, data, &datalen);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardReadCacheA failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wdatalen != datalen)
|
||||
{
|
||||
std::cerr << "SCardWriteCacheA wrote " << wdatalen << "bytes, SCardReadCacheA read "
|
||||
<< datalen << "bytes" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcmp(wdata, data, wdatalen) != 0)
|
||||
{
|
||||
std::cerr << "SCardWriteCacheA / SCardReadCacheA data corruption detected" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_cache_w(SCARDCONTEXT context)
|
||||
{
|
||||
BYTE wdata[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
const DWORD wdatalen = sizeof(wdata);
|
||||
BYTE data[32] = {};
|
||||
DWORD datalen = sizeof(data);
|
||||
LPWSTR name = L"testdata";
|
||||
UUID id = {};
|
||||
|
||||
auto rc = SCardWriteCacheW(context, &id, 0, name, wdata, wdatalen);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardWriteCacheW failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
rc = SCardReadCacheW(context, &id, 0, name, data, &datalen);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardReadCacheW failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wdatalen != datalen)
|
||||
{
|
||||
std::cerr << "SCardReadCacheW wrote " << wdatalen << "bytes, SCardReadCacheW read "
|
||||
<< datalen << "bytes" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcmp(wdata, data, wdatalen) != 0)
|
||||
{
|
||||
std::cerr << "SCardReadCacheW / SCardReadCacheW data corruption detected" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_reader_icon_a(SCARDCONTEXT context)
|
||||
{
|
||||
LPSTR name = "Gemalto PC Twin Reader 00 00\0\0";
|
||||
LPBYTE pbIcon = nullptr;
|
||||
DWORD cbIcon = SCARD_AUTOALLOCATE;
|
||||
|
||||
auto rc = SCardGetReaderIconA(context, name, reinterpret_cast<LPBYTE>(&pbIcon), &cbIcon);
|
||||
SCardFreeMemory(context, pbIcon);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardGetReaderIconA failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_reader_icon_w(SCARDCONTEXT context)
|
||||
{
|
||||
LPWSTR name = L"Gemalto PC Twin Reader 00 00\0\0";
|
||||
LPBYTE pbIcon = nullptr;
|
||||
DWORD cbIcon = SCARD_AUTOALLOCATE;
|
||||
|
||||
auto rc = SCardGetReaderIconW(context, name, reinterpret_cast<LPBYTE>(&pbIcon), &cbIcon);
|
||||
SCardFreeMemory(context, pbIcon);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardGetReaderIconW failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_locate_cards_a(SCARDCONTEXT context)
|
||||
{
|
||||
LPSTR name = "Gemalto PC Twin Reader 00 00\0\0";
|
||||
SCARD_READERSTATEA rgReaderStates[16] = {};
|
||||
|
||||
auto rc = SCardLocateCardsA(context, name, rgReaderStates, ARRAYSIZE(rgReaderStates));
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardLocateCardsA failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_locate_cards_w(SCARDCONTEXT context)
|
||||
{
|
||||
LPWSTR name = L"Gemalto PC Twin Reader 00 00\0\0";
|
||||
SCARD_READERSTATEW rgReaderStates[16] = {};
|
||||
|
||||
auto rc = SCardLocateCardsW(context, name, rgReaderStates, ARRAYSIZE(rgReaderStates));
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardLocateCardsW failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_locate_cards_by_atr_a(SCARDCONTEXT context)
|
||||
{
|
||||
SCARD_READERSTATEA rgReaderStates[16] = {};
|
||||
SCARD_ATRMASK rgAtrMasks[16] = {};
|
||||
|
||||
auto rc = SCardLocateCardsByATRA(context, rgAtrMasks, ARRAYSIZE(rgAtrMasks), rgReaderStates,
|
||||
ARRAYSIZE(rgReaderStates));
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardLocateCardsByATRA failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_locate_cards_by_atr_w(SCARDCONTEXT context)
|
||||
{
|
||||
SCARD_READERSTATEW rgReaderStates[16] = {};
|
||||
SCARD_ATRMASK rgAtrMasks[16] = {};
|
||||
|
||||
auto rc = SCardLocateCardsByATRW(context, rgAtrMasks, ARRAYSIZE(rgAtrMasks), rgReaderStates,
|
||||
ARRAYSIZE(rgReaderStates));
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardLocateCardsByATRW failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_devicetype_id_a(SCARDCONTEXT context)
|
||||
{
|
||||
BYTE data[32] = {};
|
||||
LPSTR name = "testdata";
|
||||
DWORD type;
|
||||
|
||||
auto rc = SCardGetDeviceTypeIdA(context, name, &type);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardGetDeviceTypeIdA failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_devicetype_id_w(SCARDCONTEXT context)
|
||||
{
|
||||
BYTE data[32] = {};
|
||||
LPWSTR name = L"testdata";
|
||||
DWORD type;
|
||||
|
||||
auto rc = SCardGetDeviceTypeIdW(context, name, &type);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardGetDeviceTypeIdW failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_transmitcount(SCARDHANDLE handle)
|
||||
{
|
||||
BYTE data[32] = {};
|
||||
LPWSTR name = L"testdata";
|
||||
DWORD count;
|
||||
|
||||
auto rc = SCardGetTransmitCount(handle, &count);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardGetTransmitCount failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
std::cout << "SCardGetTransmitCount() " << count << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_status_a(SCARDHANDLE handle)
|
||||
{
|
||||
BYTE data[32] = {};
|
||||
LPWSTR name = L"testdata";
|
||||
DWORD count;
|
||||
/*
|
||||
auto rc = SCardStatusA(handle, names, len, &state, &protocol, attr, &attrlen);
|
||||
if (rc != SCARD_S_SUCCESS) {
|
||||
std::cerr << "SCardGetDeviceTypeIdW failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_status_w(SCARDHANDLE handle)
|
||||
{
|
||||
BYTE data[32] = {};
|
||||
LPWSTR name = L"testdata";
|
||||
DWORD count;
|
||||
/*
|
||||
auto rc = SCardStatusA(handle, names, len, &state, &protocol, attr, &attrlen);
|
||||
if (rc != SCARD_S_SUCCESS) {
|
||||
std::cerr << "SCardGetDeviceTypeIdW failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_get_attrib(SCARDCONTEXT context, SCARDHANDLE handle)
|
||||
{
|
||||
DWORD attrlen = SCARD_AUTOALLOCATE;
|
||||
LPBYTE attr = nullptr;
|
||||
|
||||
auto rc =
|
||||
SCardGetAttrib(handle, SCARD_ATTR_ATR_STRING, reinterpret_cast<LPBYTE>(&attr), &attrlen);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardGetAttrib failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
std::cout << "SCardGetAttrib [" << attrlen << "]: " << (char*)attr << std::endl;
|
||||
SCardFreeMemory(context, attr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_set_attrib(SCARDCONTEXT context, SCARDHANDLE handle)
|
||||
{
|
||||
DWORD attrlen = SCARD_AUTOALLOCATE;
|
||||
BYTE attr[] = "0123456789";
|
||||
|
||||
auto rc = SCardSetAttrib(handle, SCARD_ATTR_SUPRESS_T1_IFS_REQUEST, attr, ARRAYSIZE(attr));
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardSetAttrib failed with " << err2str(rc) << std::endl;
|
||||
return false;
|
||||
}
|
||||
std::cout << "SCardSetAttrib [" << attrlen << "]: " << (char*)attr << std::endl;
|
||||
SCardFreeMemory(context, attr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << "Hello World!" << std::endl;
|
||||
try
|
||||
{
|
||||
auto scopes = { SCARD_SCOPE_USER, SCARD_SCOPE_SYSTEM };
|
||||
for (auto scope : scopes)
|
||||
{
|
||||
SCARDCONTEXT context;
|
||||
auto rc = SCardEstablishContext(scope, nullptr, nullptr, &context);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardEstablishContext [" << scope2str(scope) << "] failed with "
|
||||
<< err2str(rc) << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "SCardEstablishContext [" << scope2str(scope) << "] success"
|
||||
<< std::endl;
|
||||
|
||||
test_valid(context);
|
||||
|
||||
test_list_reader_groups_a(context);
|
||||
test_list_reader_groups_w(context);
|
||||
|
||||
test_list_readers_a(context);
|
||||
test_list_readers_w(context);
|
||||
|
||||
test_list_cards_a(context);
|
||||
test_list_cards_w(context);
|
||||
|
||||
test_introduce_forget_reader_groups_a(context);
|
||||
test_introduce_forget_reader_groups_w(context);
|
||||
|
||||
test_introduce_forget_reader_a(context);
|
||||
test_introduce_forget_reader_w(context);
|
||||
|
||||
// TODO: Introduce/Remove reader to group
|
||||
test_locate_cards_a(context);
|
||||
test_locate_cards_w(context);
|
||||
|
||||
test_locate_cards_by_atr_a(context);
|
||||
test_locate_cards_by_atr_w(context);
|
||||
|
||||
test_cache_a(context);
|
||||
test_cache_w(context);
|
||||
|
||||
test_reader_icon_a(context);
|
||||
test_reader_icon_w(context);
|
||||
|
||||
test_devicetype_id_a(context);
|
||||
test_devicetype_id_w(context);
|
||||
|
||||
// TODO: statuschange
|
||||
// TODO: begin/end transaction
|
||||
// TODO: state
|
||||
// TODO: transmit
|
||||
// TODO: control
|
||||
|
||||
{
|
||||
DWORD protocol;
|
||||
SCARDHANDLE handle = 0;
|
||||
LPSTR mszReaders;
|
||||
DWORD chReaders = SCARD_AUTOALLOCATE;
|
||||
|
||||
LONG status = SCardListReadersA(
|
||||
context, nullptr, reinterpret_cast<LPSTR>(&mszReaders), &chReaders);
|
||||
if (status == SCARD_S_SUCCESS)
|
||||
status = SCardConnectA(context, mszReaders, SCARD_SHARE_SHARED,
|
||||
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 |
|
||||
SCARD_PROTOCOL_Tx | SCARD_PROTOCOL_RAW,
|
||||
&handle, &protocol);
|
||||
SCardFreeMemory(context, mszReaders);
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardConnectA ["
|
||||
<< "] failed with " << err2str(status) << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
test_status_a(handle);
|
||||
test_status_w(handle);
|
||||
test_get_attrib(context, handle);
|
||||
test_set_attrib(context, handle);
|
||||
test_transmitcount(handle);
|
||||
|
||||
status = SCardDisconnect(handle, 0);
|
||||
if (status)
|
||||
{
|
||||
std::cerr << "SCardDisconnect ["
|
||||
<< "] failed with " << err2str(status) << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
DWORD protocol;
|
||||
SCARDHANDLE handle = 0;
|
||||
LPWSTR mszReaders;
|
||||
DWORD chReaders = SCARD_AUTOALLOCATE;
|
||||
|
||||
LONG status = SCardListReadersW(
|
||||
context, nullptr, reinterpret_cast<LPWSTR>(&mszReaders), &chReaders);
|
||||
if (status == SCARD_S_SUCCESS)
|
||||
status = SCardConnectW(context, mszReaders, SCARD_SHARE_SHARED,
|
||||
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 |
|
||||
SCARD_PROTOCOL_Tx | SCARD_PROTOCOL_RAW,
|
||||
&handle, &protocol);
|
||||
SCardFreeMemory(context, mszReaders);
|
||||
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardConnectW ["
|
||||
<< "] failed with " << err2str(status) << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
test_status_a(handle);
|
||||
test_status_w(handle);
|
||||
test_get_attrib(context, handle);
|
||||
test_set_attrib(context, handle);
|
||||
test_transmitcount(handle);
|
||||
|
||||
status = SCardDisconnect(handle, 0);
|
||||
if (status)
|
||||
{
|
||||
std::cerr << "SCardDisconnect ["
|
||||
<< "] failed with " << err2str(status) << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rc = SCardReleaseContext(context);
|
||||
if (rc != SCARD_S_SUCCESS)
|
||||
{
|
||||
std::cerr << "SCardReleaseContext [" << scope2str(scope) << "] failed with "
|
||||
<< err2str(rc) << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr << "exception!!!!" << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -3,6 +3,8 @@
|
||||
* Smart Card API
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2020 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2020 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -106,14 +108,14 @@
|
||||
|
||||
#define SCARD_ATR_LENGTH 33
|
||||
|
||||
#define SCARD_PROTOCOL_UNDEFINED 0x00000000
|
||||
#define SCARD_PROTOCOL_T0 0x00000001
|
||||
#define SCARD_PROTOCOL_T1 0x00000002
|
||||
#define SCARD_PROTOCOL_RAW 0x00010000
|
||||
#define SCARD_PROTOCOL_UNDEFINED 0x00000000u
|
||||
#define SCARD_PROTOCOL_T0 0x00000001u
|
||||
#define SCARD_PROTOCOL_T1 0x00000002u
|
||||
#define SCARD_PROTOCOL_RAW 0x00010000u
|
||||
|
||||
#define SCARD_PROTOCOL_Tx (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
|
||||
#define SCARD_PROTOCOL_DEFAULT 0x80000000
|
||||
#define SCARD_PROTOCOL_OPTIMAL 0x00000000
|
||||
#define SCARD_PROTOCOL_DEFAULT 0x80000000u
|
||||
#define SCARD_PROTOCOL_OPTIMAL 0x00000000u
|
||||
|
||||
#define SCARD_POWER_DOWN 0
|
||||
#define SCARD_COLD_RESET 1
|
||||
@ -681,7 +683,7 @@ extern "C"
|
||||
WINSCARDAPI LONG WINAPI SCardForgetCardTypeA(SCARDCONTEXT hContext, LPCSTR szCardName);
|
||||
WINSCARDAPI LONG WINAPI SCardForgetCardTypeW(SCARDCONTEXT hContext, LPCWSTR szCardName);
|
||||
|
||||
WINSCARDAPI LONG WINAPI SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem);
|
||||
WINSCARDAPI LONG WINAPI SCardFreeMemory(SCARDCONTEXT hContext, LPVOID pvMem);
|
||||
|
||||
WINSCARDAPI HANDLE WINAPI SCardAccessStartedEvent(void);
|
||||
|
||||
@ -959,7 +961,7 @@ typedef LONG(WINAPI* fnSCardSetCardTypeProviderNameW)(SCARDCONTEXT hContext, LPC
|
||||
typedef LONG(WINAPI* fnSCardForgetCardTypeA)(SCARDCONTEXT hContext, LPCSTR szCardName);
|
||||
typedef LONG(WINAPI* fnSCardForgetCardTypeW)(SCARDCONTEXT hContext, LPCWSTR szCardName);
|
||||
|
||||
typedef LONG(WINAPI* fnSCardFreeMemory)(SCARDCONTEXT hContext, LPCVOID pvMem);
|
||||
typedef LONG(WINAPI* fnSCardFreeMemory)(SCARDCONTEXT hContext, LPVOID pvMem);
|
||||
|
||||
typedef HANDLE(WINAPI* fnSCardAccessStartedEvent)(void);
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
* Smart Card API
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2020 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2020 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -34,7 +36,7 @@
|
||||
#include "smartcard_inspect.h"
|
||||
|
||||
static INIT_ONCE g_Initialized = INIT_ONCE_STATIC_INIT;
|
||||
static PSCardApiFunctionTable g_SCardApi = NULL;
|
||||
static const SCardApiFunctionTable* g_SCardApi = NULL;
|
||||
|
||||
#define TAG WINPR_TAG("smartcard")
|
||||
|
||||
@ -296,7 +298,7 @@ WINSCARDAPI LONG WINAPI SCardForgetCardTypeW(SCARDCONTEXT hContext, LPCWSTR szCa
|
||||
SCARDAPI_STUB_CALL_LONG(SCardForgetCardTypeW, hContext, szCardName);
|
||||
}
|
||||
|
||||
WINSCARDAPI LONG WINAPI SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
|
||||
WINSCARDAPI LONG WINAPI SCardFreeMemory(SCARDCONTEXT hContext, LPVOID pvMem)
|
||||
{
|
||||
SCARDAPI_STUB_CALL_LONG(SCardFreeMemory, hContext, pvMem);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,8 @@
|
||||
* Smart Card API
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2020 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2020 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -23,6 +25,6 @@
|
||||
#include <winpr/platform.h>
|
||||
#include <winpr/smartcard.h>
|
||||
|
||||
PSCardApiFunctionTable Inspect_RegisterSCardApi(PSCardApiFunctionTable pSCardApi);
|
||||
const SCardApiFunctionTable* Inspect_RegisterSCardApi(const SCardApiFunctionTable* pSCardApi);
|
||||
|
||||
#endif /* WINPR_SMARTCARD_INSPECT_PRIVATE_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,8 @@
|
||||
* Smart Card API
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2020 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2020 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -40,17 +42,68 @@
|
||||
*/
|
||||
|
||||
#ifdef __APPLE__
|
||||
typedef unsigned int PCSC_DWORD;
|
||||
typedef PCSC_DWORD *PCSC_PDWORD, *PCSC_LPDWORD;
|
||||
typedef unsigned int PCSC_ULONG;
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef BYTE
|
||||
typedef uint8_t PCSC_BYTE;
|
||||
#endif
|
||||
typedef uint8_t PCSC_UCHAR;
|
||||
typedef PCSC_UCHAR* PCSC_PUCHAR;
|
||||
typedef uint16_t PCSC_USHORT;
|
||||
|
||||
#ifndef __COREFOUNDATION_CFPLUGINCOM__
|
||||
typedef uint32_t PCSC_ULONG;
|
||||
typedef void* PCSC_LPVOID;
|
||||
typedef int16_t PCSC_BOOL;
|
||||
#endif
|
||||
|
||||
typedef PCSC_ULONG* PCSC_PULONG;
|
||||
typedef int PCSC_LONG;
|
||||
typedef const void* PCSC_LPCVOID;
|
||||
typedef uint32_t PCSC_DWORD;
|
||||
typedef PCSC_DWORD* PCSC_PDWORD;
|
||||
typedef uint16_t PCSC_WORD;
|
||||
typedef int32_t PCSC_LONG;
|
||||
typedef const char* PCSC_LPCSTR;
|
||||
typedef const PCSC_BYTE* PCSC_LPCBYTE;
|
||||
typedef PCSC_BYTE* PCSC_LPBYTE;
|
||||
typedef PCSC_DWORD* PCSC_LPDWORD;
|
||||
typedef char* PCSC_LPSTR;
|
||||
|
||||
#else
|
||||
typedef unsigned long PCSC_DWORD;
|
||||
typedef PCSC_DWORD *PCSC_PDWORD, *PCSC_LPDWORD;
|
||||
|
||||
#ifndef BYTE
|
||||
typedef unsigned char PCSC_BYTE;
|
||||
#endif
|
||||
typedef unsigned char PCSC_UCHAR;
|
||||
typedef PCSC_UCHAR* PCSC_PUCHAR;
|
||||
typedef unsigned short PCSC_USHORT;
|
||||
|
||||
#ifndef __COREFOUNDATION_CFPLUGINCOM__
|
||||
typedef unsigned long PCSC_ULONG;
|
||||
typedef PCSC_ULONG* PCSC_PULONG;
|
||||
typedef void* PCSC_LPVOID;
|
||||
#endif
|
||||
|
||||
typedef const void* PCSC_LPCVOID;
|
||||
typedef unsigned long PCSC_DWORD;
|
||||
typedef PCSC_DWORD* PCSC_PDWORD;
|
||||
typedef long PCSC_LONG;
|
||||
typedef const char* PCSC_LPCSTR;
|
||||
typedef const PCSC_BYTE* PCSC_LPCBYTE;
|
||||
typedef PCSC_BYTE* PCSC_LPBYTE;
|
||||
typedef PCSC_DWORD* PCSC_LPDWORD;
|
||||
typedef char* PCSC_LPSTR;
|
||||
|
||||
/* these types were deprecated but still used by old drivers and
|
||||
* applications. So just declare and use them. */
|
||||
typedef PCSC_LPSTR PCSC_LPTSTR;
|
||||
typedef PCSC_LPCSTR PCSC_LPCTSTR;
|
||||
|
||||
/* types unused by pcsc-lite */
|
||||
typedef short PCSC_BOOL;
|
||||
typedef unsigned short PCSC_WORD;
|
||||
typedef PCSC_ULONG* PCSC_PULONG;
|
||||
|
||||
#endif
|
||||
|
||||
#define PCSC_SCARD_UNKNOWN 0x0001
|
||||
@ -61,8 +114,8 @@ typedef long PCSC_LONG;
|
||||
#define PCSC_SCARD_NEGOTIABLE 0x0020
|
||||
#define PCSC_SCARD_SPECIFIC 0x0040
|
||||
|
||||
#define PCSC_SCARD_PROTOCOL_RAW 0x00000004
|
||||
#define PCSC_SCARD_PROTOCOL_T15 0x00000008
|
||||
#define PCSC_SCARD_PROTOCOL_RAW 0x00000004u
|
||||
#define PCSC_SCARD_PROTOCOL_T15 0x00000008u
|
||||
|
||||
#define PCSC_MAX_BUFFER_SIZE 264
|
||||
#define PCSC_MAX_BUFFER_SIZE_EXTENDED (4 + 3 + (1 << 16) + 3 + 2)
|
||||
@ -71,10 +124,6 @@ typedef long PCSC_LONG;
|
||||
|
||||
#define PCSC_SCARD_AUTOALLOCATE (PCSC_DWORD)(-1)
|
||||
|
||||
#define PCSC_SCARD_PCI_T0 (&g_PCSC_rgSCardT0Pci)
|
||||
#define PCSC_SCARD_PCI_T1 (&g_PCSC_rgSCardT1Pci)
|
||||
#define PCSC_SCARD_PCI_RAW (&g_PCSC_rgSCardRawPci)
|
||||
|
||||
#define PCSC_SCARD_CTL_CODE(code) (0x42000000 + (code))
|
||||
#define PCSC_CM_IOCTL_GET_FEATURE_REQUEST PCSC_SCARD_CTL_CODE(3400)
|
||||
|
||||
@ -118,49 +167,8 @@ typedef struct
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
struct _PCSCFunctionTable
|
||||
{
|
||||
PCSC_LONG(*pfnSCardEstablishContext)
|
||||
(PCSC_DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext);
|
||||
PCSC_LONG (*pfnSCardReleaseContext)(SCARDCONTEXT hContext);
|
||||
PCSC_LONG (*pfnSCardIsValidContext)(SCARDCONTEXT hContext);
|
||||
PCSC_LONG(*pfnSCardConnect)
|
||||
(SCARDCONTEXT hContext, LPCSTR szReader, PCSC_DWORD dwShareMode,
|
||||
PCSC_DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, PCSC_LPDWORD pdwActiveProtocol);
|
||||
PCSC_LONG(*pfnSCardReconnect)
|
||||
(SCARDHANDLE hCard, PCSC_DWORD dwShareMode, PCSC_DWORD dwPreferredProtocols,
|
||||
PCSC_DWORD dwInitialization, PCSC_LPDWORD pdwActiveProtocol);
|
||||
PCSC_LONG (*pfnSCardDisconnect)(SCARDHANDLE hCard, PCSC_DWORD dwDisposition);
|
||||
PCSC_LONG (*pfnSCardBeginTransaction)(SCARDHANDLE hCard);
|
||||
PCSC_LONG (*pfnSCardEndTransaction)(SCARDHANDLE hCard, PCSC_DWORD dwDisposition);
|
||||
PCSC_LONG(*pfnSCardStatus)
|
||||
(SCARDHANDLE hCard, LPSTR mszReaderName, PCSC_LPDWORD pcchReaderLen, PCSC_LPDWORD pdwState,
|
||||
PCSC_LPDWORD pdwProtocol, LPBYTE pbAtr, PCSC_LPDWORD pcbAtrLen);
|
||||
PCSC_LONG(*pfnSCardGetStatusChange)
|
||||
(SCARDCONTEXT hContext, PCSC_DWORD dwTimeout, PCSC_SCARD_READERSTATE* rgReaderStates,
|
||||
PCSC_DWORD cReaders);
|
||||
PCSC_LONG(*pfnSCardControl)
|
||||
(SCARDHANDLE hCard, PCSC_DWORD dwControlCode, LPCVOID pbSendBuffer, PCSC_DWORD cbSendLength,
|
||||
LPVOID pbRecvBuffer, PCSC_DWORD cbRecvLength, PCSC_LPDWORD lpBytesReturned);
|
||||
PCSC_LONG(*pfnSCardTransmit)
|
||||
(SCARDHANDLE hCard, const PCSC_SCARD_IO_REQUEST* pioSendPci, LPCBYTE pbSendBuffer,
|
||||
PCSC_DWORD cbSendLength, PCSC_SCARD_IO_REQUEST* pioRecvPci, LPBYTE pbRecvBuffer,
|
||||
PCSC_LPDWORD pcbRecvLength);
|
||||
PCSC_LONG(*pfnSCardListReaderGroups)
|
||||
(SCARDCONTEXT hContext, LPSTR mszGroups, PCSC_LPDWORD pcchGroups);
|
||||
PCSC_LONG(*pfnSCardListReaders)
|
||||
(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, PCSC_LPDWORD pcchReaders);
|
||||
PCSC_LONG (*pfnSCardFreeMemory)(SCARDCONTEXT hContext, LPCVOID pvMem);
|
||||
PCSC_LONG (*pfnSCardCancel)(SCARDCONTEXT hContext);
|
||||
PCSC_LONG(*pfnSCardGetAttrib)
|
||||
(SCARDHANDLE hCard, PCSC_DWORD dwAttrId, LPBYTE pbAttr, PCSC_LPDWORD pcbAttrLen);
|
||||
PCSC_LONG(*pfnSCardSetAttrib)
|
||||
(SCARDHANDLE hCard, PCSC_DWORD dwAttrId, LPCBYTE pbAttr, PCSC_DWORD cbAttrLen);
|
||||
};
|
||||
typedef struct _PCSCFunctionTable PCSCFunctionTable;
|
||||
|
||||
int PCSC_InitializeSCardApi(void);
|
||||
PSCardApiFunctionTable PCSC_GetSCardApiFunctionTable(void);
|
||||
const SCardApiFunctionTable* PCSC_GetSCardApiFunctionTable(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user