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

LONG SCardStatus ( SCARDHANDLE  hCard,
LPSTR  mszReaderName,
LPDWORD  pcchReaderLen,
LPDWORD  pdwState,
LPDWORD  pdwProtocol,
LPBYTE  pbAtr,
LPDWORD  pcbAtrLen 
)

Returns the current status of the reader connected to by hCard.

It's friendly name will be stored in szReaderName. pcchReaderLen will be the size of the allocated buffer for szReaderName, while pcbAtrLen will be the size of the allocated buffer for pbAtr. If either of these is too small, the function will return with SCARD_E_INSUFFICIENT_BUFFER and the necessary size in pcchReaderLen and pcbAtrLen. The current state, and protocol will be stored in pdwState and pdwProtocol respectively.

*pdwState also contains a number of events in the upper 16 bits (*pdwState & 0xFFFF0000). This number of events is incremented for each card insertion or removal in the specified reader. This can be used to detect a card removal/insertion between two calls to SCardStatus().

If *pcchReaderLen is equal to SCARD_AUTOALLOCATE then the function will allocate itself the needed memory for mszReaderName. Use SCardFreeMemory() to release it.

If *pcbAtrLen is equal to SCARD_AUTOALLOCATE then the function will allocate itself the needed memory for pbAtr. Use SCardFreeMemory() to release it.

Parameters:
[in]hCardConnection made from SCardConnect().
[in,out]mszReaderNameFriendly name of this reader.
[in,out]pcchReaderLenSize of the szReaderName multistring.
[out]pdwStateCurrent state of this reader. pdwState is a DWORD possibly OR'd with the following values:
  • SCARD_ABSENT - There is no card in the reader.
  • SCARD_PRESENT - There is a card in the reader, but it has not been moved into position for use.
  • SCARD_SWALLOWED - There is a card in the reader in position for use. The card is not powered.
  • SCARD_POWERED - Power is being provided to the card, but the reader driver is unaware of the mode of the card.
  • SCARD_NEGOTIABLE - The card has been reset and is awaiting PTS negotiation.
  • SCARD_SPECIFIC - The card has been reset and specific communication protocols have been established.
[out]pdwProtocolCurrent protocol of this reader.
[out]pbAtrCurrent ATR of a card in this reader.
[out]pcbAtrLenLength of ATR.
Returns:
Error code.
Return values:
SCARD_S_SUCCESSSuccessful (SCARD_S_SUCCESS)
SCARD_E_INSUFFICIENT_BUFFERNot enough allocated memory for szReaderName or for pbAtr (SCARD_E_INSUFFICIENT_BUFFER)
SCARD_E_INVALID_HANDLEInvalid hCard handle (SCARD_E_INVALID_HANDLE)
SCARD_E_INVALID_PARAMETERpcchReaderLen or pcbAtrLen is NULL (SCARD_E_INVALID_PARAMETER)
SCARD_E_NO_MEMORYMemory allocation failed (SCARD_E_NO_MEMORY)
SCARD_E_NO_SERVICEThe server is not running (SCARD_E_NO_SERVICE)
SCARD_E_READER_UNAVAILABLEThe reader has been removed (SCARD_E_READER_UNAVAILABLE)
SCARD_F_COMM_ERRORAn internal communications error has been detected (SCARD_F_COMM_ERROR)
SCARD_F_INTERNAL_ERRORAn internal consistency check failed (SCARD_F_INTERNAL_ERROR)
SCARD_W_REMOVED_CARDThe smart card has been removed (SCARD_W_REMOVED_CARD)
SCARD_W_RESET_CARDThe smart card has been reset (SCARD_W_RESET_CARD)
 SCARDCONTEXT hContext;
 SCARDHANDLE hCard;
 DWORD dwActiveProtocol;
 DWORD dwState, dwProtocol, dwAtrLen, dwReaderLen;
 BYTE pbAtr[MAX_ATR_SIZE];
 ...
 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
 rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
          SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
 ...
 dwAtrLen = sizeof(pbAtr);
 rv = SCardStatus(hCard, NULL, &dwReaderLen, &dwState, &dwProtocol, pbAtr, &dwAtrLen);
 SCARDCONTEXT hContext;
 SCARDHANDLE hCard;
 DWORD dwActiveProtocol;
 DWORD dwState, dwProtocol, dwAtrLen, dwReaderLen;
 BYTE *pbAtr = NULL;
 char *pcReader = NULL;
 ...
 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
 rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
          SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
 ...
 dwReaderLen = SCARD_AUTOALLOCATE;
 dwAtrLen = SCARD_AUTOALLOCATE;
 rv = SCardStatus(hCard, (LPSTR)&pcReader, &dwReaderLen, &dwState,
          &dwProtocol, (LPBYTE)&pbAtr, &dwAtrLen);

Definition at line 1411 of file winscard_clnt.c.

References pubReaderStatesList::cardAtrLength, pubReaderStatesList::cardProtocol, pubReaderStatesList::eventCounter, MAX_ATR_SIZE, MessageReceive(), MessageSendWithHeader(), PCSCLITE_LOCK_POLL_RATE, PCSCLITE_MAX_READERS_CONTEXTS, ReaderContext::readerState, SCARD_AUTOALLOCATE, SCARD_E_INSUFFICIENT_BUFFER, SCARD_E_INVALID_HANDLE, SCARD_E_INVALID_PARAMETER, SCARD_E_NO_MEMORY, SCARD_E_READER_UNAVAILABLE, SCARD_E_SHARING_VIOLATION, SCARD_F_INTERNAL_ERROR, SCARD_S_SUCCESS, SCARD_STATUS, and SYS_USleep().

{
      DWORD dwReaderLen, dwAtrLen;
      LONG rv;
      int i;
      struct status_struct scStatusStruct;
      SCONTEXTMAP * currentContextMap;
      CHANNEL_MAP * pChannelMap;
      char *r;
      char *bufReader = NULL;
      LPBYTE bufAtr = NULL;
      DWORD dummy = 0;

      PROFILE_START

      /* default output values */
      if (pdwState)
            *pdwState = 0;

      if (pdwProtocol)
            *pdwProtocol = 0;

      /* Check for NULL parameters */
      if (pcchReaderLen == NULL)
            pcchReaderLen = &dummy;

      if (pcbAtrLen == NULL)
            pcbAtrLen = &dummy;

      /* length passed from caller */
      dwReaderLen = *pcchReaderLen;
      dwAtrLen = *pcbAtrLen;

      *pcchReaderLen = 0;
      *pcbAtrLen = 0;

      /*
       * Make sure this handle has been opened
       */
      rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
            &pChannelMap);
      if (rv == -1)
            return SCARD_E_INVALID_HANDLE;

      (void)pthread_mutex_lock(currentContextMap->mMutex);

      /* check the handle is still valid */
      rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
            &pChannelMap);
      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;

      /* synchronize reader states with daemon */
      rv = getReaderStates(currentContextMap);
      if (rv != SCARD_S_SUCCESS)
            goto end;

      r = pChannelMap->readerName;
      for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
      {
            /* by default r == NULL */
            if (r && strcmp(r, readerStates[i].readerName) == 0)
                  break;
      }

      if (i == PCSCLITE_MAX_READERS_CONTEXTS)
      {
            rv = SCARD_E_READER_UNAVAILABLE;
            goto end;
      }

      /* Retry loop for blocking behaviour */
retry:

      /* initialise the structure */
      memset(&scStatusStruct, 0, sizeof(scStatusStruct));
      scStatusStruct.hCard = hCard;

      rv = MessageSendWithHeader(SCARD_STATUS, currentContextMap->dwClientID,
            sizeof(scStatusStruct), (void *) &scStatusStruct);

      if (rv != SCARD_S_SUCCESS)
            goto end;

      /*
       * Read a message from the server
       */
      rv = MessageReceive(&scStatusStruct, sizeof(scStatusStruct),
            currentContextMap->dwClientID);

      if (rv != SCARD_S_SUCCESS)
            goto end;

      rv = scStatusStruct.rv;

      if (sharing_shall_block && (SCARD_E_SHARING_VIOLATION == rv))
      {
            (void)SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
            goto retry;
      }

      if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INSUFFICIENT_BUFFER)
      {
            /*
             * An event must have occurred
             */
            goto end;
      }

      /*
       * Now continue with the client side SCardStatus
       */

      *pcchReaderLen = strlen(pChannelMap->readerName) + 1;
      *pcbAtrLen = readerStates[i].cardAtrLength;

      if (pdwState)
            *pdwState = (readerStates[i].eventCounter << 16) + readerStates[i].readerState;

      if (pdwProtocol)
            *pdwProtocol = readerStates[i].cardProtocol;

      if (SCARD_AUTOALLOCATE == dwReaderLen)
      {
            dwReaderLen = *pcchReaderLen;
            bufReader = malloc(dwReaderLen);
            if (NULL == bufReader)
            {
                  rv = SCARD_E_NO_MEMORY;
                  goto end;
            }
            if (NULL == mszReaderName)
            {
                  rv = SCARD_E_INVALID_PARAMETER;
                  goto end;
            }
            *(char **)mszReaderName = bufReader;
      }
      else
            bufReader = mszReaderName;

      /* return SCARD_E_INSUFFICIENT_BUFFER only if buffer pointer is non NULL */
      if (bufReader)
      {
            if (*pcchReaderLen > dwReaderLen)
                  rv = SCARD_E_INSUFFICIENT_BUFFER;

            strncpy(bufReader, pChannelMap->readerName, dwReaderLen);
      }

      if (SCARD_AUTOALLOCATE == dwAtrLen)
      {
            dwAtrLen = *pcbAtrLen;
            bufAtr = malloc(dwAtrLen);
            if (NULL == bufAtr)
            {
                  rv = SCARD_E_NO_MEMORY;
                  goto end;
            }
            if (NULL == pbAtr)
            {
                  rv = SCARD_E_INVALID_PARAMETER;
                  goto end;
            }
            *(LPBYTE *)pbAtr = bufAtr;
      }
      else
            bufAtr = pbAtr;

      if (bufAtr)
      {
            if (*pcbAtrLen > dwAtrLen)
                  rv = SCARD_E_INSUFFICIENT_BUFFER;

            memcpy(bufAtr, readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
      }

end:
      (void)pthread_mutex_unlock(currentContextMap->mMutex);

      PROFILE_END(rv)

      return rv;
}

Here is the call graph for this function:


Generated by  Doxygen 1.6.0   Back to index