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";
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
char* p = (char*) msz;
|
||||
@ -742,7 +707,7 @@ static UINT32 smartcard_State(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
||||
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
{
|
||||
status = smartcard_output_return(irp, status);
|
||||
Stream_Zero(irp->output, 256);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
@ -766,18 +731,15 @@ finish:
|
||||
return status;
|
||||
}
|
||||
|
||||
static DWORD smartcard_Status(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL wide)
|
||||
static DWORD smartcard_StatusA(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
||||
{
|
||||
LONG status;
|
||||
SCARDHANDLE hCard;
|
||||
SCARDCONTEXT hContext;
|
||||
Status_Call call;
|
||||
DWORD state, protocol;
|
||||
DWORD readerLen = 0;
|
||||
char* readerName = NULL;
|
||||
BYTE *pbAtr = NULL;
|
||||
UINT32 dataLength = 0;
|
||||
int pos, poslen1, poslen2;
|
||||
Status_Return ret;
|
||||
DWORD cchReaderLen = 0;
|
||||
LPSTR mszReaderNames = NULL;
|
||||
|
||||
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;
|
||||
hContext = (ULONG_PTR) call.hCard.Context.pbContext;
|
||||
|
||||
pbAtr = (BYTE*) malloc(call.cbAtrLen);
|
||||
readerLen = SCARD_AUTOALLOCATE;
|
||||
if (call.cbAtrLen > 32)
|
||||
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)
|
||||
{
|
||||
status = smartcard_output_return(irp, status);
|
||||
Stream_Zero(irp->output, 256);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
poslen1 = Stream_GetPosition(irp->output);
|
||||
Stream_Write_UINT32(irp->output, readerLen);
|
||||
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);
|
||||
ret.mszReaderNames = (BYTE*) mszReaderNames;
|
||||
ret.cBytes = smartcard_multi_string_length_a((char*) ret.mszReaderNames) + 2;
|
||||
|
||||
if (call.cbAtrLen < 32)
|
||||
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_pack_status_return(smartcard, irp->output, &ret);
|
||||
|
||||
smartcard_output_alignment(irp, 8);
|
||||
|
||||
finish:
|
||||
if (readerName)
|
||||
if (mszReaderNames)
|
||||
{
|
||||
SCardFreeMemory(hContext, readerName);
|
||||
SCardFreeMemory(hContext, mszReaderNames);
|
||||
}
|
||||
|
||||
if (pbAtr)
|
||||
free(pbAtr);
|
||||
return status;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -993,7 +988,7 @@ static UINT32 smartcard_GetAttrib(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
||||
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
{
|
||||
status = smartcard_output_return(irp, status);
|
||||
Stream_Zero(irp->output, 256);
|
||||
goto finish;
|
||||
}
|
||||
else
|
||||
@ -1257,11 +1252,11 @@ void smartcard_irp_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
||||
break;
|
||||
|
||||
case SCARD_IOCTL_STATUSA:
|
||||
result = smartcard_Status(smartcard, irp, 0);
|
||||
result = smartcard_StatusA(smartcard, irp);
|
||||
break;
|
||||
|
||||
case SCARD_IOCTL_STATUSW:
|
||||
result = smartcard_Status(smartcard, irp, 1);
|
||||
result = smartcard_StatusW(smartcard, irp);
|
||||
break;
|
||||
|
||||
case SCARD_IOCTL_TRANSMIT:
|
||||
|
@ -913,6 +913,22 @@ UINT32 smartcard_unpack_status_call(SMARTCARD_DEVICE* smartcard, wStream* s, Sta
|
||||
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 status;
|
||||
|
@ -287,7 +287,7 @@ typedef struct _Status_Return
|
||||
/* [size_is][unique] */ BYTE *mszReaderNames;
|
||||
DWORD dwState;
|
||||
DWORD dwProtocol;
|
||||
BYTE pbAtr[ 32 ];
|
||||
BYTE pbAtr[32];
|
||||
/* [range] */ DWORD cbAtrLen;
|
||||
} 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_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);
|
||||
|
||||
|
@ -74,6 +74,36 @@ size_t PCSC_MultiStringLengthW(const WCHAR* 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;
|
||||
|
||||
void PCSC_AddMemoryBlock(SCARDCONTEXT hContext, void* pvMem)
|
||||
@ -517,6 +547,9 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnectA(SCARDCONTEXT hContext,
|
||||
status = g_PCSC.pfnSCardConnect(hContext, szReader,
|
||||
dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol);
|
||||
status = PCSC_MapErrorCodeToWinSCard(status);
|
||||
|
||||
if (status == SCARD_S_SUCCESS)
|
||||
PCSC_AddSmartCardHandle(hContext, *phCard);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -540,6 +573,9 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnectW(SCARDCONTEXT hContext,
|
||||
dwShareMode, dwPreferredProtocols, phCard, pdwActiveProtocol);
|
||||
status = PCSC_MapErrorCodeToWinSCard(status);
|
||||
|
||||
if (status == SCARD_S_SUCCESS)
|
||||
PCSC_AddSmartCardHandle(hContext, *phCard);
|
||||
|
||||
free(szReaderA);
|
||||
|
||||
return status;
|
||||
@ -571,6 +607,9 @@ WINSCARDAPI LONG WINAPI PCSC_SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposit
|
||||
{
|
||||
status = g_PCSC.pfnSCardDisconnect(hCard, dwDisposition);
|
||||
status = PCSC_MapErrorCodeToWinSCard(status);
|
||||
|
||||
if (status == SCARD_S_SUCCESS)
|
||||
PCSC_RemoveSmartCardHandle(hCard);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -637,14 +676,31 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatusW(SCARDHANDLE hCard,
|
||||
|
||||
if (g_PCSC.pfnSCardStatus)
|
||||
{
|
||||
mszReaderNames = NULL;
|
||||
pcchReaderLen = 0;
|
||||
UINT32 length;
|
||||
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);
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user