channels/smartcard: implement clean SCardStatusW
This commit is contained in:
parent
bbfd4fb361
commit
c2fb729167
@ -145,35 +145,6 @@ const char* smartcard_get_ioctl_string(UINT32 ioControlCode, BOOL funcName)
|
|||||||
return funcName ? "SCardUnknown" : "SCARD_IOCTL_UNKNOWN";
|
return funcName ? "SCardUnknown" : "SCARD_IOCTL_UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT32 smartcard_output_string(IRP* irp, char* src, BOOL wide)
|
|
||||||
{
|
|
||||||
BYTE* p;
|
|
||||||
UINT32 len;
|
|
||||||
|
|
||||||
p = Stream_Pointer(irp->output);
|
|
||||||
len = strlen(src) + 1;
|
|
||||||
|
|
||||||
if (wide)
|
|
||||||
{
|
|
||||||
UINT32 i;
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++ )
|
|
||||||
{
|
|
||||||
p[2 * i] = src[i] < 0 ? '?' : src[i];
|
|
||||||
p[2 * i + 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
len *= 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memcpy(p, src, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream_Seek(irp->output, len);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void smartcard_output_alignment(IRP* irp, UINT32 seed)
|
static void smartcard_output_alignment(IRP* irp, UINT32 seed)
|
||||||
{
|
{
|
||||||
const UINT32 field_lengths = 20;/* Remove the lengths of the fields
|
const UINT32 field_lengths = 20;/* Remove the lengths of the fields
|
||||||
@ -196,12 +167,6 @@ static void smartcard_output_repos(IRP* irp, UINT32 written)
|
|||||||
Stream_Zero(irp->output, add);
|
Stream_Zero(irp->output, add);
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT32 smartcard_output_return(IRP* irp, UINT32 status)
|
|
||||||
{
|
|
||||||
Stream_Zero(irp->output, 256);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t smartcard_multi_string_length_a(const char* msz)
|
size_t smartcard_multi_string_length_a(const char* msz)
|
||||||
{
|
{
|
||||||
char* p = (char*) msz;
|
char* p = (char*) msz;
|
||||||
@ -742,7 +707,7 @@ static UINT32 smartcard_State(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
|||||||
|
|
||||||
if (status != SCARD_S_SUCCESS)
|
if (status != SCARD_S_SUCCESS)
|
||||||
{
|
{
|
||||||
status = smartcard_output_return(irp, status);
|
Stream_Zero(irp->output, 256);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -766,18 +731,15 @@ finish:
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD smartcard_Status(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL wide)
|
static DWORD smartcard_StatusA(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
||||||
{
|
{
|
||||||
LONG status;
|
LONG status;
|
||||||
SCARDHANDLE hCard;
|
SCARDHANDLE hCard;
|
||||||
SCARDCONTEXT hContext;
|
SCARDCONTEXT hContext;
|
||||||
Status_Call call;
|
Status_Call call;
|
||||||
DWORD state, protocol;
|
Status_Return ret;
|
||||||
DWORD readerLen = 0;
|
DWORD cchReaderLen = 0;
|
||||||
char* readerName = NULL;
|
LPSTR mszReaderNames = NULL;
|
||||||
BYTE *pbAtr = NULL;
|
|
||||||
UINT32 dataLength = 0;
|
|
||||||
int pos, poslen1, poslen2;
|
|
||||||
|
|
||||||
status = smartcard_unpack_status_call(smartcard, irp->input, &call);
|
status = smartcard_unpack_status_call(smartcard, irp->input, &call);
|
||||||
|
|
||||||
@ -787,53 +749,86 @@ static DWORD smartcard_Status(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL wide)
|
|||||||
hCard = (ULONG_PTR) call.hCard.pbHandle;
|
hCard = (ULONG_PTR) call.hCard.pbHandle;
|
||||||
hContext = (ULONG_PTR) call.hCard.Context.pbContext;
|
hContext = (ULONG_PTR) call.hCard.Context.pbContext;
|
||||||
|
|
||||||
pbAtr = (BYTE*) malloc(call.cbAtrLen);
|
if (call.cbAtrLen > 32)
|
||||||
readerLen = SCARD_AUTOALLOCATE;
|
call.cbAtrLen = 32;
|
||||||
|
|
||||||
status = SCardStatusA(hCard, (LPSTR) &readerName, &readerLen, &state, &protocol, pbAtr, &call.cbAtrLen);
|
ret.cbAtrLen = call.cbAtrLen;
|
||||||
|
ZeroMemory(ret.pbAtr, 32);
|
||||||
|
|
||||||
|
cchReaderLen = SCARD_AUTOALLOCATE;
|
||||||
|
|
||||||
|
status = SCardStatusA(hCard, (LPSTR) &mszReaderNames, &cchReaderLen,
|
||||||
|
&ret.dwState, &ret.dwProtocol, (BYTE*) &ret.pbAtr, &ret.cbAtrLen);
|
||||||
|
|
||||||
if (status != SCARD_S_SUCCESS)
|
if (status != SCARD_S_SUCCESS)
|
||||||
{
|
{
|
||||||
status = smartcard_output_return(irp, status);
|
Stream_Zero(irp->output, 256);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
poslen1 = Stream_GetPosition(irp->output);
|
ret.mszReaderNames = (BYTE*) mszReaderNames;
|
||||||
Stream_Write_UINT32(irp->output, readerLen);
|
ret.cBytes = smartcard_multi_string_length_a((char*) ret.mszReaderNames) + 2;
|
||||||
Stream_Write_UINT32(irp->output, 0x00020001);
|
|
||||||
Stream_Write_UINT32(irp->output, state);
|
|
||||||
Stream_Write_UINT32(irp->output, protocol);
|
|
||||||
Stream_Write(irp->output, pbAtr, call.cbAtrLen);
|
|
||||||
|
|
||||||
if (call.cbAtrLen < 32)
|
smartcard_pack_status_return(smartcard, irp->output, &ret);
|
||||||
Stream_Zero(irp->output, 32 - call.cbAtrLen);
|
|
||||||
Stream_Write_UINT32(irp->output, call.cbAtrLen);
|
|
||||||
|
|
||||||
poslen2 = Stream_GetPosition(irp->output);
|
|
||||||
Stream_Write_UINT32(irp->output, readerLen);
|
|
||||||
|
|
||||||
if (readerName)
|
|
||||||
dataLength += smartcard_output_string(irp, readerName, wide);
|
|
||||||
dataLength += smartcard_output_string(irp, "\0", wide);
|
|
||||||
smartcard_output_repos(irp, dataLength);
|
|
||||||
|
|
||||||
pos = Stream_GetPosition(irp->output);
|
|
||||||
Stream_SetPosition(irp->output, poslen1);
|
|
||||||
Stream_Write_UINT32(irp->output,dataLength);
|
|
||||||
Stream_SetPosition(irp->output, poslen2);
|
|
||||||
Stream_Write_UINT32(irp->output,dataLength);
|
|
||||||
Stream_SetPosition(irp->output, pos);
|
|
||||||
|
|
||||||
smartcard_output_alignment(irp, 8);
|
smartcard_output_alignment(irp, 8);
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
if (readerName)
|
if (mszReaderNames)
|
||||||
{
|
{
|
||||||
SCardFreeMemory(hContext, readerName);
|
SCardFreeMemory(hContext, mszReaderNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pbAtr)
|
return status;
|
||||||
free(pbAtr);
|
}
|
||||||
|
|
||||||
|
static DWORD smartcard_StatusW(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
||||||
|
{
|
||||||
|
LONG status;
|
||||||
|
SCARDHANDLE hCard;
|
||||||
|
SCARDCONTEXT hContext;
|
||||||
|
Status_Call call;
|
||||||
|
Status_Return ret;
|
||||||
|
DWORD cchReaderLen = 0;
|
||||||
|
LPWSTR mszReaderNames = NULL;
|
||||||
|
|
||||||
|
status = smartcard_unpack_status_call(smartcard, irp->input, &call);
|
||||||
|
|
||||||
|
if (status)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
hCard = (ULONG_PTR) call.hCard.pbHandle;
|
||||||
|
hContext = (ULONG_PTR) call.hCard.Context.pbContext;
|
||||||
|
|
||||||
|
if (call.cbAtrLen > 32)
|
||||||
|
call.cbAtrLen = 32;
|
||||||
|
|
||||||
|
ret.cbAtrLen = call.cbAtrLen;
|
||||||
|
ZeroMemory(ret.pbAtr, 32);
|
||||||
|
|
||||||
|
cchReaderLen = SCARD_AUTOALLOCATE;
|
||||||
|
|
||||||
|
status = SCardStatusW(hCard, (LPWSTR) &mszReaderNames, &cchReaderLen,
|
||||||
|
&ret.dwState, &ret.dwProtocol, (BYTE*) &ret.pbAtr, &ret.cbAtrLen);
|
||||||
|
|
||||||
|
if (status != SCARD_S_SUCCESS)
|
||||||
|
{
|
||||||
|
Stream_Zero(irp->output, 256);
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.mszReaderNames = (BYTE*) mszReaderNames;
|
||||||
|
ret.cBytes = (smartcard_multi_string_length_w((WCHAR*) ret.mszReaderNames) + 2) * 2;
|
||||||
|
|
||||||
|
smartcard_pack_status_return(smartcard, irp->output, &ret);
|
||||||
|
|
||||||
|
smartcard_output_alignment(irp, 8);
|
||||||
|
|
||||||
|
finish:
|
||||||
|
if (mszReaderNames)
|
||||||
|
{
|
||||||
|
SCardFreeMemory(hContext, mszReaderNames);
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -993,7 +988,7 @@ static UINT32 smartcard_GetAttrib(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
|||||||
|
|
||||||
if (status != SCARD_S_SUCCESS)
|
if (status != SCARD_S_SUCCESS)
|
||||||
{
|
{
|
||||||
status = smartcard_output_return(irp, status);
|
Stream_Zero(irp->output, 256);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1257,11 +1252,11 @@ void smartcard_irp_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SCARD_IOCTL_STATUSA:
|
case SCARD_IOCTL_STATUSA:
|
||||||
result = smartcard_Status(smartcard, irp, 0);
|
result = smartcard_StatusA(smartcard, irp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCARD_IOCTL_STATUSW:
|
case SCARD_IOCTL_STATUSW:
|
||||||
result = smartcard_Status(smartcard, irp, 1);
|
result = smartcard_StatusW(smartcard, irp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCARD_IOCTL_TRANSMIT:
|
case SCARD_IOCTL_TRANSMIT:
|
||||||
|
@ -913,6 +913,22 @@ UINT32 smartcard_unpack_status_call(SMARTCARD_DEVICE* smartcard, wStream* s, Sta
|
|||||||
return SCARD_S_SUCCESS;
|
return SCARD_S_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINT32 smartcard_pack_status_return(SMARTCARD_DEVICE* smartcard, wStream* s, Status_Return* ret)
|
||||||
|
{
|
||||||
|
Stream_Write_UINT32(s, ret->cBytes); /* cBytes (4 bytes) */
|
||||||
|
Stream_Write_UINT32(s, 0x00020010); /* mszReaderNamesNdrPtr (4 bytes) */
|
||||||
|
Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */
|
||||||
|
Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */
|
||||||
|
Stream_Write(s, ret->pbAtr, 32); /* pbAtr (32 bytes) */
|
||||||
|
Stream_Write_UINT32(s, ret->cbAtrLen); /* cbAtrLen (4 bytes) */
|
||||||
|
|
||||||
|
Stream_Write_UINT32(s, ret->cBytes); /* mszReaderNamesNdrLen (4 bytes) */
|
||||||
|
Stream_Write(s, ret->mszReaderNames, ret->cBytes);
|
||||||
|
smartcard_pack_write_offset_align(smartcard, s, 4);
|
||||||
|
|
||||||
|
return SCARD_S_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
UINT32 smartcard_unpack_get_attrib_call(SMARTCARD_DEVICE* smartcard, wStream* s, GetAttrib_Call* call)
|
UINT32 smartcard_unpack_get_attrib_call(SMARTCARD_DEVICE* smartcard, wStream* s, GetAttrib_Call* call)
|
||||||
{
|
{
|
||||||
UINT32 status;
|
UINT32 status;
|
||||||
|
@ -287,7 +287,7 @@ typedef struct _Status_Return
|
|||||||
/* [size_is][unique] */ BYTE *mszReaderNames;
|
/* [size_is][unique] */ BYTE *mszReaderNames;
|
||||||
DWORD dwState;
|
DWORD dwState;
|
||||||
DWORD dwProtocol;
|
DWORD dwProtocol;
|
||||||
BYTE pbAtr[ 32 ];
|
BYTE pbAtr[32];
|
||||||
/* [range] */ DWORD cbAtrLen;
|
/* [range] */ DWORD cbAtrLen;
|
||||||
} Status_Return;
|
} Status_Return;
|
||||||
|
|
||||||
@ -465,6 +465,7 @@ UINT32 smartcard_unpack_get_status_change_w_call(SMARTCARD_DEVICE* smartcard, wS
|
|||||||
UINT32 smartcard_unpack_state_call(SMARTCARD_DEVICE* smartcard, wStream* s, State_Call* call);
|
UINT32 smartcard_unpack_state_call(SMARTCARD_DEVICE* smartcard, wStream* s, State_Call* call);
|
||||||
|
|
||||||
UINT32 smartcard_unpack_status_call(SMARTCARD_DEVICE* smartcard, wStream* s, Status_Call* call);
|
UINT32 smartcard_unpack_status_call(SMARTCARD_DEVICE* smartcard, wStream* s, Status_Call* call);
|
||||||
|
UINT32 smartcard_pack_status_return(SMARTCARD_DEVICE* smartcard, wStream* s, Status_Return* ret);
|
||||||
|
|
||||||
UINT32 smartcard_unpack_get_attrib_call(SMARTCARD_DEVICE* smartcard, wStream* s, GetAttrib_Call* call);
|
UINT32 smartcard_unpack_get_attrib_call(SMARTCARD_DEVICE* smartcard, wStream* s, GetAttrib_Call* call);
|
||||||
|
|
||||||
|
@ -74,6 +74,36 @@ size_t PCSC_MultiStringLengthW(const WCHAR* msz)
|
|||||||
return (p - msz);
|
return (p - msz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static wListDictionary* g_SmartCards = NULL;
|
||||||
|
|
||||||
|
void PCSC_AddSmartCardHandle(SCARDCONTEXT hContext, SCARDHANDLE hCard)
|
||||||
|
{
|
||||||
|
if (!g_SmartCards)
|
||||||
|
g_SmartCards = ListDictionary_New(TRUE);
|
||||||
|
|
||||||
|
ListDictionary_Add(g_SmartCards, (void*) hCard, (void*) hContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* PCSC_RemoveSmartCardHandle(SCARDHANDLE hCard)
|
||||||
|
{
|
||||||
|
if (!g_SmartCards)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return ListDictionary_Remove(g_SmartCards, (void*) hCard);
|
||||||
|
}
|
||||||
|
|
||||||
|
SCARDCONTEXT PCSC_GetSmartCardContextFromHandle(SCARDHANDLE hCard)
|
||||||
|
{
|
||||||
|
SCARDCONTEXT hContext;
|
||||||
|
|
||||||
|
if (!g_SmartCards)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
hContext = (SCARDCONTEXT) ListDictionary_GetItemValue(g_SmartCards, (void*) hCard);
|
||||||
|
|
||||||
|
return hContext;
|
||||||
|
}
|
||||||
|
|
||||||
static wListDictionary* g_MemoryBlocks = NULL;
|
static wListDictionary* g_MemoryBlocks = NULL;
|
||||||
|
|
||||||
void PCSC_AddMemoryBlock(SCARDCONTEXT hContext, void* pvMem)
|
void PCSC_AddMemoryBlock(SCARDCONTEXT hContext, void* pvMem)
|
||||||
@ -517,6 +547,9 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnectA(SCARDCONTEXT hContext,
|
|||||||
status = g_PCSC.pfnSCardConnect(hContext, szReader,
|
status = g_PCSC.pfnSCardConnect(hContext, szReader,
|
||||||
dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol);
|
dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol);
|
||||||
status = PCSC_MapErrorCodeToWinSCard(status);
|
status = PCSC_MapErrorCodeToWinSCard(status);
|
||||||
|
|
||||||
|
if (status == SCARD_S_SUCCESS)
|
||||||
|
PCSC_AddSmartCardHandle(hContext, *phCard);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@ -540,6 +573,9 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnectW(SCARDCONTEXT hContext,
|
|||||||
dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol);
|
dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol);
|
||||||
status = PCSC_MapErrorCodeToWinSCard(status);
|
status = PCSC_MapErrorCodeToWinSCard(status);
|
||||||
|
|
||||||
|
if (status == SCARD_S_SUCCESS)
|
||||||
|
PCSC_AddSmartCardHandle(hContext, *phCard);
|
||||||
|
|
||||||
free(szReaderA);
|
free(szReaderA);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@ -571,6 +607,9 @@ WINSCARDAPI LONG WINAPI PCSC_SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposit
|
|||||||
{
|
{
|
||||||
status = g_PCSC.pfnSCardDisconnect(hCard, dwDisposition);
|
status = g_PCSC.pfnSCardDisconnect(hCard, dwDisposition);
|
||||||
status = PCSC_MapErrorCodeToWinSCard(status);
|
status = PCSC_MapErrorCodeToWinSCard(status);
|
||||||
|
|
||||||
|
if (status == SCARD_S_SUCCESS)
|
||||||
|
PCSC_RemoveSmartCardHandle(hCard);
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@ -637,14 +676,31 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatusW(SCARDHANDLE hCard,
|
|||||||
|
|
||||||
if (g_PCSC.pfnSCardStatus)
|
if (g_PCSC.pfnSCardStatus)
|
||||||
{
|
{
|
||||||
mszReaderNames = NULL;
|
UINT32 length;
|
||||||
pcchReaderLen = 0;
|
SCARDCONTEXT hContext = 0;
|
||||||
|
LPSTR mszReaderNamesA = NULL;
|
||||||
|
|
||||||
/* FIXME: unicode conversion */
|
if (!mszReaderNames)
|
||||||
|
pcchReaderLen = 0;
|
||||||
|
|
||||||
status = g_PCSC.pfnSCardStatus(hCard, (LPSTR) mszReaderNames, pcchReaderLen,
|
status = g_PCSC.pfnSCardStatus(hCard, (LPSTR) &mszReaderNamesA, pcchReaderLen,
|
||||||
pdwState, pdwProtocol, pbAtr, pcbAtrLen);
|
pdwState, pdwProtocol, pbAtr, pcbAtrLen);
|
||||||
status = PCSC_MapErrorCodeToWinSCard(status);
|
status = PCSC_MapErrorCodeToWinSCard(status);
|
||||||
|
|
||||||
|
if (mszReaderNamesA)
|
||||||
|
{
|
||||||
|
length = (UINT32) PCSC_MultiStringLengthA(mszReaderNamesA);
|
||||||
|
ConvertToUnicode(CP_UTF8, 0, mszReaderNamesA, length + 2, (WCHAR**) mszReaderNames, 0);
|
||||||
|
|
||||||
|
hContext = PCSC_GetSmartCardContextFromHandle(hCard);
|
||||||
|
|
||||||
|
PCSC_AddMemoryBlock(hContext, mszReaderNames);
|
||||||
|
|
||||||
|
if (g_PCSC.pfnSCardFreeMemory)
|
||||||
|
{
|
||||||
|
g_PCSC.pfnSCardFreeMemory(hContext, mszReaderNamesA);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
Loading…
Reference in New Issue
Block a user