libwinpr-smartcard: fix pcsc-lite SCARD_IO_REQUEST incompatibility
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Sat, 3 May 2014 18:20:17 +0000 (14:20 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Sat, 3 May 2014 18:20:17 +0000 (14:20 -0400)
winpr/libwinpr/smartcard/smartcard_pcsc.c
winpr/libwinpr/smartcard/smartcard_pcsc.h

index 54cb474..472570b 100644 (file)
@@ -69,6 +69,10 @@ char SMARTCARD_PNP_NOTIFICATION_A[] = "\\\\?PnP?\\Notification";
 WCHAR SMARTCARD_PNP_NOTIFICATION_W[] = { '\\','\\','?','P','n','P','?',
        '\\','N','o','t','i','f','i','c','a','t','i','o','n','\0' };
 
+const PCSC_SCARD_IO_REQUEST g_PCSC_rgSCardT0Pci = { SCARD_PROTOCOL_T0, sizeof(PCSC_SCARD_IO_REQUEST) };
+const PCSC_SCARD_IO_REQUEST g_PCSC_rgSCardT1Pci = { SCARD_PROTOCOL_T1, sizeof(PCSC_SCARD_IO_REQUEST) };
+const PCSC_SCARD_IO_REQUEST g_PCSC_rgSCardRawPci = { PCSC_SCARD_PROTOCOL_RAW, sizeof(PCSC_SCARD_IO_REQUEST) };
+
 WINSCARDAPI LONG WINAPI PCSC_SCardFreeMemory_Internal(SCARDCONTEXT hContext, LPCVOID pvMem);
 
 LONG PCSC_MapErrorCodeToWinSCard(LONG errorCode)
@@ -1660,12 +1664,25 @@ WINSCARDAPI LONG WINAPI PCSC_SCardTransmit(SCARDHANDLE hCard,
                LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
 {
        LONG status = SCARD_S_SUCCESS;
+       PCSC_DWORD cbExtraBytes = 0;
+       BYTE* pbExtraBytes = NULL;
+       BYTE* pcsc_pbExtraBytes = NULL;
+       PCSC_SCARD_IO_REQUEST* pcsc_pioSendPci = NULL;
+       PCSC_SCARD_IO_REQUEST* pcsc_pioRecvPci = NULL;
        PCSC_DWORD pcsc_cbSendLength = (PCSC_DWORD) cbSendLength;
-       PCSC_DWORD pcsc_cbRecvLength = (PCSC_DWORD) *pcbRecvLength;
+       PCSC_DWORD pcsc_cbRecvLength = 0;
 
        if (!g_PCSC.pfnSCardTransmit)
                return SCARD_E_NO_SERVICE;
 
+       if (!pcbRecvLength)
+               return SCARD_E_INVALID_PARAMETER;
+
+       if (*pcbRecvLength == SCARD_AUTOALLOCATE)
+               return SCARD_E_INVALID_PARAMETER;
+
+       pcsc_cbRecvLength = (PCSC_DWORD) *pcbRecvLength;
+
        if (!pioSendPci)
        {
                PCSC_DWORD dwState = 0;
@@ -1683,20 +1700,59 @@ WINSCARDAPI LONG WINAPI PCSC_SCardTransmit(SCARDHANDLE hCard,
                if (status == SCARD_S_SUCCESS)
                {
                        if (dwProtocol == SCARD_PROTOCOL_T0)
-                               pioSendPci = SCARD_PCI_T0;
+                               pcsc_pioSendPci = (PCSC_SCARD_IO_REQUEST*) PCSC_SCARD_PCI_T0;
                        else if (dwProtocol == SCARD_PROTOCOL_T1)
-                               pioSendPci = SCARD_PCI_T1;
-                       else if (dwProtocol == SCARD_PROTOCOL_RAW)
-                               pioSendPci = SCARD_PCI_RAW;
+                               pcsc_pioSendPci = (PCSC_SCARD_IO_REQUEST*) PCSC_SCARD_PCI_T1;
+                       else if (dwProtocol == PCSC_SCARD_PROTOCOL_RAW)
+                               pcsc_pioSendPci = (PCSC_SCARD_IO_REQUEST*) PCSC_SCARD_PCI_RAW;
                }
        }
+       else
+       {
+               cbExtraBytes = pioSendPci->cbPciLength - sizeof(SCARD_IO_REQUEST);
+               pcsc_pioSendPci = (PCSC_SCARD_IO_REQUEST*) malloc(sizeof(PCSC_SCARD_IO_REQUEST) + cbExtraBytes);
+
+               if (!pcsc_pioSendPci)
+                       return SCARD_E_NO_MEMORY;
+
+               pcsc_pioSendPci->dwProtocol = (PCSC_DWORD) pioSendPci->dwProtocol;
+               pcsc_pioSendPci->cbPciLength = sizeof(PCSC_SCARD_IO_REQUEST) + cbExtraBytes;
+
+               pbExtraBytes = &((BYTE*) pioSendPci)[sizeof(SCARD_IO_REQUEST)];
+               pcsc_pbExtraBytes = &((BYTE*) pcsc_pioSendPci)[sizeof(PCSC_SCARD_IO_REQUEST)];
+
+               CopyMemory(pcsc_pbExtraBytes, pbExtraBytes, cbExtraBytes);
+       }
+
+       if (pioRecvPci)
+       {
+               cbExtraBytes = pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST);
+               pcsc_pioRecvPci = (PCSC_SCARD_IO_REQUEST*) malloc(sizeof(PCSC_SCARD_IO_REQUEST) + cbExtraBytes);
+
+               if (!pcsc_pioRecvPci)
+                       return SCARD_E_NO_MEMORY;
+
+               pcsc_pioRecvPci->dwProtocol = (PCSC_DWORD) pioRecvPci->dwProtocol;
+               pcsc_pioRecvPci->cbPciLength = sizeof(PCSC_SCARD_IO_REQUEST) + cbExtraBytes;
 
-       status = (LONG) g_PCSC.pfnSCardTransmit(hCard, pioSendPci, pbSendBuffer,
-                       pcsc_cbSendLength, pioRecvPci, pbRecvBuffer, &pcsc_cbRecvLength);
+               pbExtraBytes = &((BYTE*) pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
+               pcsc_pbExtraBytes = &((BYTE*) pcsc_pioRecvPci)[sizeof(PCSC_SCARD_IO_REQUEST)];
+
+               CopyMemory(pcsc_pbExtraBytes, pbExtraBytes, cbExtraBytes);
+       }
+
+       status = (LONG) g_PCSC.pfnSCardTransmit(hCard, pcsc_pioSendPci, pbSendBuffer,
+                       pcsc_cbSendLength, pcsc_pioRecvPci, pbRecvBuffer, &pcsc_cbRecvLength);
        status = PCSC_MapErrorCodeToWinSCard(status);
 
        *pcbRecvLength = (DWORD) pcsc_cbRecvLength;
 
+       if (pioSendPci)
+               free(pcsc_pioSendPci); /* pcsc_pioSendPci is dynamically allocated only when pioSendPci is non null */
+
+       if (pioRecvPci)
+               free(pcsc_pioRecvPci); /* pcsc_pioRecvPci is dynamically allocated only when pioRecvPci is non null */
+
        return status;
 }
 
index d9f9229..acb3f37 100644 (file)
@@ -71,6 +71,10 @@ 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)
+
 typedef struct
 {
        LPCSTR szReader;
@@ -82,12 +86,11 @@ typedef struct
 }
 PCSC_SCARD_READERSTATE;
 
-typedef struct _PCSC_SCARD_IO_REQUEST
+typedef struct
 {
        PCSC_DWORD dwProtocol;
        PCSC_DWORD cbPciLength;
-} PCSC_SCARD_IO_REQUEST, *PCSC_PSCARD_IO_REQUEST, *PCSC_LPSCARD_IO_REQUEST;
-typedef const PCSC_SCARD_IO_REQUEST *PCSC_LPCSCARD_IO_REQUEST;
+} PCSC_SCARD_IO_REQUEST;
 
 struct _PCSCFunctionTable
 {
@@ -113,8 +116,8 @@ struct _PCSCFunctionTable
                        PCSC_DWORD dwControlCode, LPCVOID pbSendBuffer, PCSC_DWORD cbSendLength,
                        LPVOID pbRecvBuffer, PCSC_DWORD cbRecvLength, PCSC_LPDWORD lpBytesReturned);
        PCSC_LONG (* pfnSCardTransmit)(SCARDHANDLE hCard,
-                       const SCARD_IO_REQUEST* pioSendPci, LPCBYTE pbSendBuffer, PCSC_DWORD cbSendLength,
-                       SCARD_IO_REQUEST* pioRecvPci, LPBYTE pbRecvBuffer, PCSC_LPDWORD pcbRecvLength);
+                       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);