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

LONG SCardControl ( SCARDHANDLE  hCard,
DWORD  dwControlCode,
LPCVOID  pbSendBuffer,
DWORD  cbSendLength,
LPVOID  pbRecvBuffer,
DWORD  cbRecvLength,
LPDWORD  lpBytesReturned 
)

This function sends a command directly to the IFD Handler (reader driver) to be processed by the reader.

This is useful for creating client side reader drivers for functions like PIN pads, biometrics, or other extensions to the normal smart card reader that are not normally handled by PC/SC.

Note:
the API of this function changed. In pcsc-lite 1.2.0 and before the API was not Windows(R) PC/SC compatible. This has been corrected.
Parameters:
[in] hCard Connection made from SCardConnect().
[in] dwControlCode Control code for the operation.
Click here for a list of supported commands by some drivers.
[in] pbSendBuffer Command to send to the reader.
[in] cbSendLength Length of the command.
[out] pbRecvBuffer Response from the reader.
[in] cbRecvLength Length of the response buffer.
[out] lpBytesReturned Length of the response.
Returns:
Error code.
Return values:
SCARD_S_SUCCESS Successful (SCARD_S_SUCCESS)
SCARD_E_INVALID_HANDLE Invalid hCard handle (SCARD_E_INVALID_HANDLE)
SCARD_E_INVALID_VALUE Invalid value was presented (SCARD_E_INVALID_VALUE)
SCARD_E_INSUFFICIENT_BUFFER cbSendLength or cbRecvLength are too big (SCARD_E_INSUFFICIENT_BUFFER)
SCARD_E_NO_SERVICE The server is not runing (SCARD_E_NO_SERVICE)
SCARD_E_NOT_TRANSACTED Data exchange not successful (SCARD_E_NOT_TRANSACTED)
SCARD_E_READER_UNAVAILABLE The reader has been removed(SCARD_E_READER_UNAVAILABLE)
SCARD_F_COMM_ERROR An internal communications error has been detected (SCARD_F_COMM_ERROR)
SCARD_W_REMOVED_CARD The card has been removed from the reader(SCARD_W_REMOVED_CARD)
SCARD_W_RESET_CARD The card has been reset by another application (SCARD_W_RESET_CARD)
 LONG rv;
 SCARDCONTEXT hContext;
 SCARDHANDLE hCard;
 DWORD dwActiveProtocol, dwSendLength, dwRecvLength;
 BYTE pbRecvBuffer[10];
 BYTE pbSendBuffer[] = { 0x06, 0x00, 0x0A, 0x01, 0x01, 0x10 0x00 };
 ...
 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
 rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
          SCARD_PROTOCOL_RAW, &hCard, &dwActiveProtocol);
 dwSendLength = sizeof(pbSendBuffer);
 dwRecvLength = sizeof(pbRecvBuffer);
 rv = SCardControl(hCard, 0x42000001, pbSendBuffer, dwSendLength,
          pbRecvBuffer, sizeof(pbRecvBuffer), &dwRecvLength);

Definition at line 2329 of file winscard_clnt.c.

References control_struct::cbRecvLength, control_struct::cbSendLength, rxSharedSegment::data, control_struct::dwBytesReturned, _psContextMap::dwClientID, control_struct::dwControlCode, control_struct::hCard, MAX_BUFFER_SIZE, MAX_BUFFER_SIZE_EXTENDED, control_struct::pbRecvBuffer, control_struct::pbSendBuffer, PCSCLITE_CLIENT_ATTEMPTS, PCSCLITE_MAX_MESSAGE_SIZE, PCSCLITE_MAX_READERS_CONTEXTS, _psContextMap::psChannelMap, psContextMap, _psChannelMap::readerName, control_struct::rv, SCARD_CONTROL, SCARD_CONTROL_EXTENDED, SCARD_E_INSUFFICIENT_BUFFER, SCARD_E_INVALID_HANDLE, SCARD_E_NO_SERVICE, SCARD_E_READER_UNAVAILABLE, SCARD_F_COMM_ERROR, SCARD_S_SUCCESS, SCardCheckDaemonAvailability(), SHMClientRead(), SHMMessageReceive(), and WrapSHMWrite().

{
      LONG rv;
      control_struct scControlStruct;
      sharedSegmentMsg msgStruct;
      int i;
      DWORD dwContextIndex, dwChannelIndex;

      PROFILE_START

      /* 0 bytes received by default */
      if (NULL != lpBytesReturned)
            *lpBytesReturned = 0;

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

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

      (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);

      /* check the handle is still valid */
      rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
      if (rv == -1)
            /* the handle is now invalid
             * -> another thread may have called SCardReleaseContext
             * -> so the mMutex has been unlocked */
            return SCARD_E_INVALID_HANDLE;

      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)
      {
            (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
            return SCARD_E_READER_UNAVAILABLE;
      }

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

      if ((cbSendLength > MAX_BUFFER_SIZE) || (cbRecvLength > MAX_BUFFER_SIZE))
      {
            /* extended control */
            unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
            control_struct_extended *scControlStructExtended = (control_struct_extended *)buffer;
            sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;

            scControlStructExtended->hCard = hCard;
            scControlStructExtended->dwControlCode = dwControlCode;
            scControlStructExtended->cbSendLength = cbSendLength;
            scControlStructExtended->cbRecvLength = cbRecvLength;
            scControlStructExtended->pdwBytesReturned = 0;
            scControlStructExtended->rv = SCARD_S_SUCCESS;
            /* The size of data to send is the size of
             * struct control_struct_extended WITHOUT the data[] field
             * plus the effective data[] size
             */
            scControlStructExtended->size = sizeof(*scControlStructExtended)
                  - (sizeof(control_struct_extended) - offsetof(control_struct_extended, data))
                  + cbSendLength;
            memcpy(scControlStructExtended->data, pbSendBuffer, cbSendLength);

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

            if (rv == -1)
            {
                  (void)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)
            {
                  (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
                  return SCARD_F_COMM_ERROR;
            }

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

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

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

            if (NULL != lpBytesReturned)
                  *lpBytesReturned = scControlStructExtended -> pdwBytesReturned;

            rv = scControlStructExtended -> rv;
      }
      else
      {
            scControlStruct.hCard = hCard;
            scControlStruct.dwControlCode = dwControlCode;
            scControlStruct.cbSendLength = cbSendLength;
            scControlStruct.cbRecvLength = cbRecvLength;
            memcpy(scControlStruct.pbSendBuffer, pbSendBuffer, cbSendLength);

            rv = WrapSHMWrite(SCARD_CONTROL,
                  psContextMap[dwContextIndex].dwClientID,
                  sizeof(scControlStruct), PCSCLITE_CLIENT_ATTEMPTS, &scControlStruct);

            if (rv == -1)
            {
                  (void)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);

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

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

            if (NULL != lpBytesReturned)
                  *lpBytesReturned = scControlStruct.dwBytesReturned;

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

            rv = scControlStruct.rv;
      }

      (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);

      PROFILE_END(rv)

      return rv;
}


Generated by  Doxygen 1.6.0   Back to index