Logo Search packages:      
Sourcecode: pcsc-lite version File versions  Download package

LONG SCardTransmit ( SCARDHANDLE  hCard,
LPCSCARD_IO_REQUEST  pioSendPci,
LPCBYTE  pbSendBuffer,
DWORD  cbSendLength,
LPSCARD_IO_REQUEST  pioRecvPci,
LPBYTE  pbRecvBuffer,
LPDWORD  pcbRecvLength 
)

This function sends an APDU to the smart card contained in the reader connected to by SCardConnect().

The card responds from the APDU and stores this response in pbRecvBuffer and it's length in SpcbRecvLength. SSendPci and SRecvPci are structures containing the following:

 typedef struct {
    DWORD dwProtocol;    // SCARD_PROTOCOL_T0 or SCARD_PROTOCOL_T1
    DWORD cbPciLength;   // Length of this structure - not used
 } SCARD_IO_REQUEST;

Parameters:
[in] hCard Connection made from SCardConnect().
pioSendPci [inout] Structure of protocol information.
  • SCARD_PCI_T0 - Pre-defined T=0 PCI structure.
  • SCARD_PCI_T1 - Pre-defined T=1 PCI structure.
[in] pbSendBuffer APDU to send to the card.
[in] cbSendLength Length of the APDU.
pioRecvPci [inout] Structure of protocol information.
[out] pbRecvBuffer Response from the card.
pcbRecvLength [inout] Length of the response.
Returns:
Error code.
Return values:
SCARD_S_SUCCESS Successful.
SCARD_E_INVALID_HANDLE Invalid hCard handle.
SCARD_E_NOT_TRANSACTED APDU exchange not successful.
SCARD_E_PROTO_MISMATCH Connect protocol is different than desired.
SCARD_E_INVALID_VALUE Invalid Protocol, reader name, etc.
SCARD_E_READER_UNAVAILABLE The reader has been removed.
SCARD_W_RESET_CARD The card has been reset by another application.
SCARD_W_REMOVED_CARD The card has been removed from the reader.
Test:
 LONG rv;
 SCARDCONTEXT hContext;
 SCARDHANDLE hCard;
 DWORD dwActiveProtocol, dwSendLength, dwRecvLength;
 SCARD_IO_REQUEST pioRecvPci;
 BYTE pbRecvBuffer[10];
 BYTE pbSendBuffer[] = { 0xC0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00 };
 ...
 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
 rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
 dwSendLength = sizeof(pbSendBuffer);
 dwRecvLength = sizeof(pbRecvBuffer);
 rv = SCardTransmit(hCard, SCARD_PCI_T0, pbSendBuffer, dwSendLength, &pioRecvPci, pbRecvBuffer, &dwRecvLength);

Definition at line 2553 of file winscard_clnt.c.

References transmit_struct::cbSendLength, rxSharedSegment::data, _psContextMap::dwClientID, transmit_struct::hCard, MAX_BUFFER_SIZE, MAX_BUFFER_SIZE_EXTENDED, transmit_struct::pbSendBuffer, transmit_struct::pcbRecvLength, PCSCLITE_CLIENT_ATTEMPTS, PCSCLITE_MAX_MESSAGE_SIZE, transmit_struct::pioRecvPci, transmit_struct::pioSendPci, _psContextMap::psChannelMap, psContextMap, _psChannelMap::readerName, SCARD_PROTOCOL_ANY, SCardCheckDaemonAvailability(), SHMClientRead(), SHMMessageReceive(), SYS_MutexLock(), SYS_MutexUnLock(), and WrapSHMWrite().

{
      LONG rv;
      int i;
      DWORD dwContextIndex, dwChannelIndex;

      PROFILE_START

      if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
                  pcbRecvLength == NULL || pioSendPci == NULL)
            return SCARD_E_INVALID_PARAMETER;

      if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
            return SCARD_E_NO_SERVICE;

      /*
       * Make sure this handle has been opened
       */
      rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);

      if (rv == -1)
      {
            *pcbRecvLength = 0;
            return SCARD_E_INVALID_HANDLE;
      }

      SYS_MutexLock(psContextMap[dwContextIndex].mMutex);   

      for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
      {
            char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;

            /* by default r == NULL */
            if (r && strcmp(r, (readerStates[i])->readerName) == 0)
                  break;
      }

      if (i == PCSCLITE_MAX_READERS_CONTEXTS)
      {
            SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 
            return SCARD_E_READER_UNAVAILABLE;
      }

      if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
            || (*pcbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
      {
            SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 
            return SCARD_E_INSUFFICIENT_BUFFER;
      }

      if ((cbSendLength > MAX_BUFFER_SIZE) || (*pcbRecvLength > MAX_BUFFER_SIZE))
      {
            /* extended APDU */
            unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
            transmit_struct_extended *scTransmitStructExtended = (transmit_struct_extended *)buffer;
            sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;

            scTransmitStructExtended->hCard = hCard;
            scTransmitStructExtended->cbSendLength = cbSendLength;
            scTransmitStructExtended->pcbRecvLength = *pcbRecvLength;
            scTransmitStructExtended->size = sizeof(*scTransmitStructExtended) + cbSendLength;
            memcpy(&scTransmitStructExtended->pioSendPci, pioSendPci,
                  sizeof(SCARD_IO_REQUEST));
            memcpy(scTransmitStructExtended->data, pbSendBuffer, cbSendLength);

            if (pioRecvPci)
            {
                  memcpy(&scTransmitStructExtended->pioRecvPci, pioRecvPci,
                        sizeof(SCARD_IO_REQUEST));
            }
            else
                  scTransmitStructExtended->pioRecvPci.dwProtocol = SCARD_PROTOCOL_ANY;

            rv = WrapSHMWrite(SCARD_TRANSMIT_EXTENDED,
                  psContextMap[dwContextIndex].dwClientID,
                  scTransmitStructExtended->size,
                  PCSCLITE_CLIENT_ATTEMPTS, buffer);

            if (rv == -1)
            {
                  SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 
                  return SCARD_E_NO_SERVICE;
            }

            /*
             * Read a message from the server
             */
            /* read the first block */
            rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg), psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
            if (rv == -1)
            {
                  SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 
                  return SCARD_F_COMM_ERROR;
            }

            /* we receive a sharedSegmentMsg and not a transmit_struct_extended */
            scTransmitStructExtended = (transmit_struct_extended *)&(pmsgStruct -> data);

            /* a second block is present */
            if (scTransmitStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
            {
                  rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
                        scTransmitStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
                        psContextMap[dwContextIndex].dwClientID,
                        PCSCLITE_CLIENT_ATTEMPTS);
                  if (rv == -1)
                  {
                        SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 
                        return SCARD_F_COMM_ERROR;
                  }
            }

            if (scTransmitStructExtended -> rv == SCARD_S_SUCCESS)
            {
                  /*
                   * Copy and zero it so any secret information is not leaked
                   */
                  memcpy(pbRecvBuffer, scTransmitStructExtended -> data,
                        scTransmitStructExtended -> pcbRecvLength);
                  memset(scTransmitStructExtended -> data, 0x00,
                        scTransmitStructExtended -> pcbRecvLength);

                  if (pioRecvPci)
                        memcpy(pioRecvPci, &scTransmitStructExtended -> pioRecvPci,
                              sizeof(SCARD_IO_REQUEST));
            }

            *pcbRecvLength = scTransmitStructExtended -> pcbRecvLength;
            SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 

            rv = scTransmitStructExtended -> rv;
      }
      else
      {
            /* short APDU */
            transmit_struct scTransmitStruct;
            sharedSegmentMsg msgStruct;

            scTransmitStruct.hCard = hCard;
            scTransmitStruct.cbSendLength = cbSendLength;
            scTransmitStruct.pcbRecvLength = *pcbRecvLength;
            memcpy(&scTransmitStruct.pioSendPci, pioSendPci,
                  sizeof(SCARD_IO_REQUEST));
            memcpy(scTransmitStruct.pbSendBuffer, pbSendBuffer, cbSendLength);

            if (pioRecvPci)
            {
                  memcpy(&scTransmitStruct.pioRecvPci, pioRecvPci,
                        sizeof(SCARD_IO_REQUEST));
            }
            else
                  scTransmitStruct.pioRecvPci.dwProtocol = SCARD_PROTOCOL_ANY;

            rv = WrapSHMWrite(SCARD_TRANSMIT,
                  psContextMap[dwContextIndex].dwClientID, sizeof(scTransmitStruct),
                  PCSCLITE_CLIENT_ATTEMPTS, (void *) &scTransmitStruct);

            if (rv == -1)
            {
                  SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 
                  return SCARD_E_NO_SERVICE;
            }

            /*
             * Read a message from the server
             */
            rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);

            memcpy(&scTransmitStruct, &msgStruct.data, sizeof(scTransmitStruct));

            if (rv == -1)
            {
                  SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 
                  return SCARD_F_COMM_ERROR;
            }

            /*
             * Zero it and free it so any secret information cannot be leaked
             */
            memset(scTransmitStruct.pbSendBuffer, 0x00, cbSendLength);

            if (scTransmitStruct.rv == SCARD_S_SUCCESS)
            {
                  /*
                   * Copy and zero it so any secret information is not leaked
                   */
                  memcpy(pbRecvBuffer, scTransmitStruct.pbRecvBuffer,
                        scTransmitStruct.pcbRecvLength);
                  memset(scTransmitStruct.pbRecvBuffer, 0x00,
                        scTransmitStruct.pcbRecvLength);

                  if (pioRecvPci)
                        memcpy(pioRecvPci, &scTransmitStruct.pioRecvPci,
                              sizeof(SCARD_IO_REQUEST));
            }

            *pcbRecvLength = scTransmitStruct.pcbRecvLength;
            SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex); 

            rv = scTransmitStruct.rv;
      }

      PROFILE_END

      return rv;
}


Generated by  Doxygen 1.6.0   Back to index