channels/smartcard: more unpacking
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Mon, 7 Apr 2014 05:19:58 +0000 (01:19 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Mon, 7 Apr 2014 05:19:58 +0000 (01:19 -0400)
channels/smartcard/client/smartcard_operations.c
channels/smartcard/client/smartcard_pack.c
channels/smartcard/client/smartcard_pack.h
winpr/libwinpr/smartcard/smartcard_pcsc.c

index 02c1a33..c32c1b8 100644 (file)
@@ -159,14 +159,6 @@ static void smartcard_output_alignment(IRP* irp, UINT32 seed)
                Stream_Zero(irp->output, add);
 }
 
-static void smartcard_output_repos(IRP* irp, UINT32 written)
-{
-       UINT32 add = (4 - (written % 4)) % 4;
-
-       if (add > 0)
-               Stream_Zero(irp->output, add);
-}
-
 size_t smartcard_multi_string_length_a(const char* msz)
 {
        char* p = (char*) msz;
@@ -685,49 +677,29 @@ static UINT32 smartcard_State(SMARTCARD_DEVICE* smartcard, IRP* irp)
        SCARDCONTEXT hContext;
        State_Call call;
        State_Return ret;
-       DWORD readerLen;
-       char* readerName = NULL;
-       BYTE atr[SCARD_ATR_LENGTH];
 
        status = smartcard_unpack_state_call(smartcard, irp->input, &call);
 
        if (status)
-               goto finish;
+               return status;
 
        hCard = (ULONG_PTR) call.hCard.pbHandle;
        hContext = (ULONG_PTR) call.hCard.Context.pbContext;
 
-       readerLen = SCARD_AUTOALLOCATE;
-
-       ret.rgAtr = atr;
        ret.cbAtrLen = SCARD_ATR_LENGTH;
 
-       status = SCardStatusA(hCard, (LPSTR) &readerName, &readerLen,
-                       &ret.dwState, &ret.dwProtocol, ret.rgAtr, &ret.cbAtrLen);
+       status = SCardState(hCard, &ret.dwState, &ret.dwProtocol, (BYTE*) &ret.rgAtr, &ret.cbAtrLen);
 
        if (status != SCARD_S_SUCCESS)
        {
                Stream_Zero(irp->output, 256);
-               goto finish;
+               return status;
        }
 
-       Stream_Write_UINT32(irp->output, ret.dwState); /* dwState (4 bytes) */
-       Stream_Write_UINT32(irp->output, ret.dwProtocol); /* dwProtocol (4 bytes) */
-       Stream_Write_UINT32(irp->output, ret.cbAtrLen); /* cbAtrLen (4 bytes) */
-       Stream_Write_UINT32(irp->output, 0x00000001); /* rgAtrPointer (4 bytes) */
-       Stream_Write_UINT32(irp->output, ret.cbAtrLen); /* rgAtrLength (4 bytes) */
-       Stream_Write(irp->output, ret.rgAtr, ret.cbAtrLen); /* rgAtr */
-
-       smartcard_output_repos(irp, ret.cbAtrLen);
+       smartcard_pack_state_return(smartcard, irp->output, &ret);
 
        smartcard_output_alignment(irp, 8);
 
-finish:
-       if (readerName)
-       {
-               SCardFreeMemory(hContext, readerName);
-       }
-
        return status;
 }
 
@@ -910,15 +882,7 @@ static UINT32 smartcard_Control(SMARTCARD_DEVICE* smartcard, IRP* irp)
                        call.pvInBuffer, (DWORD) call.cbInBufferSize,
                        ret.pvOutBuffer, (DWORD) call.cbOutBufferSize, &ret.cbOutBufferSize);
 
-       Stream_Write_UINT32(irp->output, (UINT32) ret.cbOutBufferSize); /* cbOutBufferSize (4 bytes) */
-       Stream_Write_UINT32(irp->output, 0x00000004); /* pvOutBufferPointer (4 bytes) */
-       Stream_Write_UINT32(irp->output, ret.cbOutBufferSize); /* pvOutBufferLength (4 bytes) */
-
-       if (ret.cbOutBufferSize > 0)
-       {
-               Stream_Write(irp->output, ret.pvOutBuffer, ret.cbOutBufferSize); /* pvOutBuffer */
-               smartcard_output_repos(irp, ret.cbOutBufferSize);
-       }
+       smartcard_pack_control_return(smartcard, irp->output, &ret);
 
        smartcard_output_alignment(irp, 8);
 
@@ -984,30 +948,17 @@ static UINT32 smartcard_GetAttrib(SMARTCARD_DEVICE* smartcard, IRP* irp)
        {
                status = SCARD_E_INSUFFICIENT_BUFFER;
        }
+
        call.cbAttrLen = cbAttrLen;
+       ret.cbAttrLen = call.cbAttrLen;
 
        if (status != SCARD_S_SUCCESS)
        {
                Stream_Zero(irp->output, 256);
                goto finish;
        }
-       else
-       {
-               ret.cbAttrLen = call.cbAttrLen;
 
-               Stream_Write_UINT32(irp->output, ret.cbAttrLen); /* cbAttrLen (4 bytes) */
-               Stream_Write_UINT32(irp->output, 0x00020000); /* pbAttrPointer (4 bytes) */
-               Stream_Write_UINT32(irp->output, ret.cbAttrLen); /* pbAttrLength (4 bytes) */
-
-               if (!ret.pbAttr)
-                       Stream_Zero(irp->output, ret.cbAttrLen); /* pbAttr */
-               else
-                       Stream_Write(irp->output, ret.pbAttr, ret.cbAttrLen); /* pbAttr */
-
-               smartcard_output_repos(irp, ret.cbAttrLen);
-               /* align to multiple of 4 */
-               Stream_Write_UINT32(irp->output, 0);
-       }
+       smartcard_pack_get_attrib_return(smartcard, irp->output, &ret);
 
        smartcard_output_alignment(irp, 8);
 
index 262c55f..adcf897 100644 (file)
@@ -885,6 +885,19 @@ UINT32 smartcard_unpack_state_call(SMARTCARD_DEVICE* smartcard, wStream* s, Stat
        return SCARD_S_SUCCESS;
 }
 
+UINT32 smartcard_pack_state_return(SMARTCARD_DEVICE* smartcard, wStream* s, State_Return* ret)
+{
+       Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */
+       Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */
+       Stream_Write_UINT32(s, ret->cbAtrLen); /* cbAtrLen (4 bytes) */
+       Stream_Write_UINT32(s, 0x00020020); /* rgAtrNdrPtr (4 bytes) */
+       Stream_Write_UINT32(s, ret->cbAtrLen); /* rgAtrLength (4 bytes) */
+       Stream_Write(s, ret->rgAtr, ret->cbAtrLen); /* rgAtr */
+       smartcard_pack_write_offset_align(smartcard, s, 4);
+
+       return SCARD_S_SUCCESS;
+}
+
 UINT32 smartcard_unpack_status_call(SMARTCARD_DEVICE* smartcard, wStream* s, Status_Call* call)
 {
        UINT32 status;
@@ -957,6 +970,22 @@ UINT32 smartcard_unpack_get_attrib_call(SMARTCARD_DEVICE* smartcard, wStream* s,
        return SCARD_S_SUCCESS;
 }
 
+UINT32 smartcard_pack_get_attrib_return(SMARTCARD_DEVICE* smartcard, wStream* s, GetAttrib_Return* ret)
+{
+       Stream_Write_UINT32(s, ret->cbAttrLen); /* cbAttrLen (4 bytes) */
+       Stream_Write_UINT32(s, 0x00020080); /* pbAttrPointer (4 bytes) */
+       Stream_Write_UINT32(s, ret->cbAttrLen); /* pbAttrLength (4 bytes) */
+
+       if (!ret->pbAttr)
+               Stream_Zero(s, ret->cbAttrLen); /* pbAttr */
+       else
+               Stream_Write(s, ret->pbAttr, ret->cbAttrLen); /* pbAttr */
+
+       smartcard_pack_write_offset_align(smartcard, s, 4);
+
+       return SCARD_S_SUCCESS;
+}
+
 UINT32 smartcard_unpack_control_call(SMARTCARD_DEVICE* smartcard, wStream* s, Control_Call* call)
 {
        UINT32 status;
@@ -1014,6 +1043,21 @@ UINT32 smartcard_unpack_control_call(SMARTCARD_DEVICE* smartcard, wStream* s, Co
        return SCARD_S_SUCCESS;
 }
 
+UINT32 smartcard_pack_control_return(SMARTCARD_DEVICE* smartcard, wStream* s, Control_Return* ret)
+{
+       Stream_Write_UINT32(s, ret->cbOutBufferSize); /* cbOutBufferSize (4 bytes) */
+       Stream_Write_UINT32(s, 0x00020040); /* pvOutBufferPointer (4 bytes) */
+       Stream_Write_UINT32(s, ret->cbOutBufferSize); /* pvOutBufferLength (4 bytes) */
+
+       if (ret->cbOutBufferSize > 0)
+       {
+               Stream_Write(s, ret->pvOutBuffer, ret->cbOutBufferSize); /* pvOutBuffer */
+               smartcard_pack_write_offset_align(smartcard, s, 4);
+       }
+
+       return SCARD_S_SUCCESS;
+}
+
 UINT32 smartcard_unpack_transmit_call(SMARTCARD_DEVICE* smartcard, wStream* s, Transmit_Call* call)
 {
        UINT32 status;
index 36321bb..75b1d00 100644 (file)
@@ -269,7 +269,7 @@ typedef struct _State_Return
        DWORD dwState;
        DWORD dwProtocol;
        /* [range] */ DWORD cbAtrLen;
-       /* [size_is][unique] */ BYTE *rgAtr;
+       /* [size_is][unique] */ BYTE rgAtr[36];
 } State_Return;
 
 typedef struct _Status_Call
@@ -463,13 +463,16 @@ UINT32 smartcard_unpack_get_status_change_a_call(SMARTCARD_DEVICE* smartcard, wS
 UINT32 smartcard_unpack_get_status_change_w_call(SMARTCARD_DEVICE* smartcard, wStream* s, GetStatusChangeW_Call* call);
 
 UINT32 smartcard_unpack_state_call(SMARTCARD_DEVICE* smartcard, wStream* s, State_Call* call);
+UINT32 smartcard_pack_state_return(SMARTCARD_DEVICE* smartcard, wStream* s, State_Return* ret);
 
 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_pack_get_attrib_return(SMARTCARD_DEVICE* smartcard, wStream* s, GetAttrib_Return* ret);
 
 UINT32 smartcard_unpack_control_call(SMARTCARD_DEVICE* smartcard, wStream* s, Control_Call* call);
+UINT32 smartcard_pack_control_return(SMARTCARD_DEVICE* smartcard, wStream* s, Control_Return* ret);
 
 UINT32 smartcard_unpack_transmit_call(SMARTCARD_DEVICE* smartcard, wStream* s, Transmit_Call* call);
 UINT32 smartcard_pack_transmit_return(SMARTCARD_DEVICE* smartcard, wStream* s, Transmit_Return* ret);
index 26a5ee7..0812252 100644 (file)
@@ -649,7 +649,30 @@ WINSCARDAPI LONG WINAPI PCSC_SCardCancelTransaction(SCARDHANDLE hCard)
 WINSCARDAPI LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard,
                LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
 {
-       return 0;
+       LONG status = SCARD_S_SUCCESS;
+
+       if (g_PCSC.pfnSCardStatus)
+       {
+               SCARDCONTEXT hContext = 0;
+               LPSTR mszReaderNames = NULL;
+               DWORD cchReaderLen = SCARD_AUTOALLOCATE;
+
+               status = g_PCSC.pfnSCardStatus(hCard, (LPSTR) &mszReaderNames, &cchReaderLen,
+                               pdwState, pdwProtocol, pbAtr, pcbAtrLen);
+               status = PCSC_MapErrorCodeToWinSCard(status);
+
+               if (mszReaderNames)
+               {
+                       if (g_PCSC.pfnSCardFreeMemory)
+                       {
+                               hContext = PCSC_GetSmartCardContextFromHandle(hCard);
+
+                               g_PCSC.pfnSCardFreeMemory(hContext, mszReaderNames);
+                       }
+               }
+       }
+
+       return status;
 }
 
 WINSCARDAPI LONG WINAPI PCSC_SCardStatusA(SCARDHANDLE hCard,