all: pass context to check; win: even more error messages
This commit is contained in:
		
							
								
								
									
										203
									
								
								src/pcsc.hxx
									
									
									
									
									
								
							
							
						
						
									
										203
									
								
								src/pcsc.hxx
									
									
									
									
									
								
							@@ -190,7 +190,8 @@ namespace pcsc {
 | 
			
		||||
          //! Disconnects connection.
 | 
			
		||||
          ~Reader() {
 | 
			
		||||
            _state = SCardDisconnect(_id, SCARD_LEAVE_CARD);
 | 
			
		||||
            if (!std::uncaught_exception()) _connection.check();
 | 
			
		||||
            if (!std::uncaught_exception())
 | 
			
		||||
              _connection.check("disconnect smartcard");
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          //! Get reader status.
 | 
			
		||||
@@ -199,7 +200,8 @@ namespace pcsc {
 | 
			
		||||
            DWORD s;
 | 
			
		||||
            DWORD len(MAX_ATR_SIZE);
 | 
			
		||||
            unsigned char a[len];
 | 
			
		||||
            check(SCardStatus(_id, 0, &dummy, &s, &_protocol, a, &len));
 | 
			
		||||
            check(SCardStatus(_id, 0, &dummy, &s, &_protocol, a, &len),
 | 
			
		||||
                  "query smartcard status");
 | 
			
		||||
            return Status(s, std::string((char*)a, len));
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
@@ -210,7 +212,8 @@ namespace pcsc {
 | 
			
		||||
            SCARD_IO_REQUEST rPci;
 | 
			
		||||
            check(SCardTransmit(_id, pci(),
 | 
			
		||||
                                (unsigned char*)in.c_str(), in.size(),
 | 
			
		||||
                                &rPci, buff, &len));
 | 
			
		||||
                                &rPci, buff, &len),
 | 
			
		||||
                  "smartcard transmit message "+hex(in));
 | 
			
		||||
            return std::string((char*)buff, len);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
@@ -229,17 +232,18 @@ namespace pcsc {
 | 
			
		||||
 | 
			
		||||
          //! Use scoped transactions with @ref Transaction
 | 
			
		||||
          void beginTransaction() {
 | 
			
		||||
            check(SCardBeginTransaction(_id));
 | 
			
		||||
            check(SCardBeginTransaction(_id), "smartcard begin transaction");
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          //! Use scoped transactions with @ref Transaction
 | 
			
		||||
          void commitTransaction() {
 | 
			
		||||
            check(SCardEndTransaction(_id, SCARD_LEAVE_CARD));
 | 
			
		||||
            check(SCardEndTransaction(_id, SCARD_LEAVE_CARD),
 | 
			
		||||
                  "smartcard end transaction");
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          //! Use scoped transactions with @ref Transaction
 | 
			
		||||
          void cancelTransaction() {
 | 
			
		||||
            check(SCardCancelTransaction(_id));
 | 
			
		||||
            check(SCardCancelTransaction(_id), "smartcard cancel transaction");
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          /*! @throw not_implemented if _protocol is unknown. */
 | 
			
		||||
@@ -255,9 +259,9 @@ namespace pcsc {
 | 
			
		||||
          //! Sets state and throws an exception if neccessary.
 | 
			
		||||
          /*! @throw access_error if it is instanciated for exceptions and
 | 
			
		||||
              an error occured in the last command. */
 | 
			
		||||
          bool check(long state) {
 | 
			
		||||
          bool check(long state, const std::string context="") {
 | 
			
		||||
            _state = state;
 | 
			
		||||
            return _connection.check(state);
 | 
			
		||||
            return _connection.check(state, context);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          //! Only Connection is allowed to instanciate.
 | 
			
		||||
@@ -269,7 +273,8 @@ namespace pcsc {
 | 
			
		||||
            check(SCardConnect(_connection._id, strconv(name).c_str(),
 | 
			
		||||
                               SCARD_SHARE_SHARED,
 | 
			
		||||
                               SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1,
 | 
			
		||||
                               &_id, &_protocol));
 | 
			
		||||
                               &_id, &_protocol),
 | 
			
		||||
                  "connect smartcard \""+name+"\"");
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          //! forbidden
 | 
			
		||||
@@ -283,7 +288,7 @@ namespace pcsc {
 | 
			
		||||
 | 
			
		||||
          Connection& _connection;
 | 
			
		||||
          SCARDHANDLE _id;
 | 
			
		||||
          long _state;
 | 
			
		||||
          DWORD _state;
 | 
			
		||||
          DWORD _protocol;
 | 
			
		||||
      
 | 
			
		||||
      };
 | 
			
		||||
@@ -331,13 +336,13 @@ namespace pcsc {
 | 
			
		||||
      Connection(Scope s=SYSTEM, bool exceptions=true):
 | 
			
		||||
          _exc(exceptions), _id(0),
 | 
			
		||||
          _state(SCardEstablishContext(s, 0, 0, &_id)) {
 | 
			
		||||
        check();
 | 
			
		||||
        check("establish smartcard context");
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      //! Closes the connection (releases the smartcard context)
 | 
			
		||||
      ~Connection() {
 | 
			
		||||
        _state = SCardReleaseContext(_id);
 | 
			
		||||
        if (!std::uncaught_exception()) check();
 | 
			
		||||
        if (!std::uncaught_exception()) check("smartcard release context");
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      //! Scans for available readers from a specified list of groups.
 | 
			
		||||
@@ -347,11 +352,13 @@ namespace pcsc {
 | 
			
		||||
        std::string grp(join(groups));
 | 
			
		||||
        DWORD num(0);
 | 
			
		||||
        if (!check(SCardListReaders(_id, grp.size()?strconv(grp).data():0, 0,
 | 
			
		||||
                                    &num)))
 | 
			
		||||
                                    &num),
 | 
			
		||||
                   "(1) smartcard list readers of groups "+grp))
 | 
			
		||||
          return res;
 | 
			
		||||
        std::auto_ptr<char_t> nm(new char_t[num]);
 | 
			
		||||
        if (!check(SCardListReaders(_id, grp.size()?strconv(grp).data():0,
 | 
			
		||||
                                    nm.get(), &num)))
 | 
			
		||||
                                    nm.get(), &num),
 | 
			
		||||
                   "(2) smartcard list readers of groups "+grp))
 | 
			
		||||
          return res;
 | 
			
		||||
        return res = split(strconv(string(nm.get(), num-1)));
 | 
			
		||||
      }
 | 
			
		||||
@@ -382,34 +389,168 @@ namespace pcsc {
 | 
			
		||||
        #ifdef WIN32
 | 
			
		||||
        std::stringstream ss;
 | 
			
		||||
        switch (_state) {
 | 
			
		||||
          case SCARD_S_SUCCESS:
 | 
			
		||||
            ss<<"Success";
 | 
			
		||||
          case SCARD_E_SHARING_VIOLATION:
 | 
			
		||||
            ss<<"The smart card cannot be accessed because of other"
 | 
			
		||||
              <<" connections outstanding.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_NO_SMARTCARD:
 | 
			
		||||
            ss<<"The operation requires a Smart Card, but no Smart Card"
 | 
			
		||||
              <<" is currently in the device.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_UNKNOWN_CARD:
 | 
			
		||||
            ss<<"The specified smart card name is not recognized.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_CANT_DISPOSE:
 | 
			
		||||
            ss<<"The system could not dispose of the media in the"
 | 
			
		||||
              <<" requested manner.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_PROTO_MISMATCH:
 | 
			
		||||
            ss<<"The requested protocols are incompatible with the"
 | 
			
		||||
              <<" protocol currently in use with the smart card.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_NOT_READY:
 | 
			
		||||
            ss<<"The reader or smart card is not ready to accept commands.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_INVALID_VALUE:
 | 
			
		||||
            ss<<"One or more of the supplied parameters values could"
 | 
			
		||||
              <<" not be properly interpreted.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_SYSTEM_CANCELLED:
 | 
			
		||||
            ss<<"The action was cancelled by the system, presumably"
 | 
			
		||||
              <<" to log off or shut down.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_F_COMM_ERROR:
 | 
			
		||||
            ss<<"An internal communications error has been detected.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_F_UNKNOWN_ERROR:
 | 
			
		||||
            ss<<"An internal error has been detected, but the source"
 | 
			
		||||
              <<" is unknown.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_INVALID_ATR:
 | 
			
		||||
            ss<<"An ATR obtained from the registry is not a valid ATR string.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_NOT_TRANSACTED:
 | 
			
		||||
            ss<<"An attempt was made to end a non-existent transaction.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_READER_UNAVAILABLE:
 | 
			
		||||
            ss<<"The specified reader is not currently available for use.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_P_SHUTDOWN:
 | 
			
		||||
            ss<<"The operation has been aborted to allow the server"
 | 
			
		||||
              <<" application to exit.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_PCI_TOO_SMALL:
 | 
			
		||||
            ss<<"The PCI Receive buffer was too small.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_READER_UNSUPPORTED:
 | 
			
		||||
            ss<<"The reader driver does not meet minimal requirements"
 | 
			
		||||
              <<" for support.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_DUPLICATE_READER:
 | 
			
		||||
            ss<<"The reader driver did not produce a unique reader name.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_CARD_UNSUPPORTED:
 | 
			
		||||
            ss<<"The smart card does not meet minimal requirements"
 | 
			
		||||
              <<" for support.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_NO_SERVICE:
 | 
			
		||||
            ss<<"The Smart card resource manager is not running.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_SERVICE_STOPPED:
 | 
			
		||||
            ss<<"The Smart card resource manager has shut down.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_UNEXPECTED:
 | 
			
		||||
            ss<<"An unexpected card error has occurred.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_ICC_INSTALLATION:
 | 
			
		||||
            ss<<"No Primary Provider can be found for the smart card.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_ICC_CREATEORDER:
 | 
			
		||||
            ss<<"The requested order of object creation is not supported.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_UNSUPPORTED_FEATURE:
 | 
			
		||||
            ss<<"This smart card does not support the requested feature.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_DIR_NOT_FOUND:
 | 
			
		||||
            ss<<"The identified directory does not exist in the smart card.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_FILE_NOT_FOUND:
 | 
			
		||||
            ss<<"The identified file does not exist in the smart card.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_NO_DIR:
 | 
			
		||||
            ss<<"The supplied path does not represent a smart card directory.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_NO_FILE:
 | 
			
		||||
            ss<<"The supplied path does not represent a smart card file.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_NO_ACCESS:
 | 
			
		||||
            ss<<"Access is denied to this file.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_WRITE_TOO_MANY:
 | 
			
		||||
            ss<<"The smartcard does not have enough memory to store"
 | 
			
		||||
              <<" the information.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_BAD_SEEK:
 | 
			
		||||
            ss<<"There was an error trying to set the smart card file"
 | 
			
		||||
              <<" object pointer.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_INVALID_CHV:
 | 
			
		||||
            ss<<"The supplied PIN is incorrect.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_UNKNOWN_RES_MNG:
 | 
			
		||||
            ss<<"An unrecognized error code was returned from a layered"
 | 
			
		||||
              <<" component.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_NO_SUCH_CERTIFICATE:
 | 
			
		||||
            ss<<"The requested certificate does not exist.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_CERTIFICATE_UNAVAILABLE:
 | 
			
		||||
            ss<<"The requested certificate could not be obtained.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_NO_READERS_AVAILABLE:
 | 
			
		||||
            ss<<"Cannot find a smart card reader.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_COMM_DATA_LOST:
 | 
			
		||||
            ss<<"A communications error with the smart card has been"
 | 
			
		||||
              <<" detected.  Retry the operation.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_NO_KEY_CONTAINER:
 | 
			
		||||
            ss<<"The requested key container does not exist on the"
 | 
			
		||||
              <<" smart card.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_E_SERVER_TOO_BUSY:
 | 
			
		||||
            ss<<"The Smart card resource manager is too busy to complete"
 | 
			
		||||
              <<" this operation.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_W_UNSUPPORTED_CARD:
 | 
			
		||||
            ss<<"The reader cannot communicate with the smart card, due"
 | 
			
		||||
              <<" to ATR configuration conflicts.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_W_UNRESPONSIVE_CARD:
 | 
			
		||||
            ss<<"The smart card is not responding to a reset.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_W_UNPOWERED_CARD:
 | 
			
		||||
            ss<<"Power has been removed from the smart card, so that further"
 | 
			
		||||
              " communication is not possible.";
 | 
			
		||||
            ss<<"Power has been removed from the smart card, so that"
 | 
			
		||||
              <<" further communication is not possible.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_W_RESET_CARD:
 | 
			
		||||
            ss<<"The smart card has been reset, so any shared state"
 | 
			
		||||
              " information is invalid.";
 | 
			
		||||
              <<" information is invalid.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_W_REMOVED_CARD:
 | 
			
		||||
            ss<<"The smart card has been removed, so that further"
 | 
			
		||||
              " communication is not possible.";
 | 
			
		||||
              <<" communication is not possible.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_W_SECURITY_VIOLATION:
 | 
			
		||||
            ss<<"Access was denied because of a security violation.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_W_WRONG_CHV:
 | 
			
		||||
            ss<<"The card cannot be accessed because the wrong PIN was"
 | 
			
		||||
              " presented.";
 | 
			
		||||
            ss<<"The card cannot be accessed because the wrong PIN"
 | 
			
		||||
              <<" was presented.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_W_CHV_BLOCKED:
 | 
			
		||||
            ss<<"The card cannot be accessed because the maximum number"
 | 
			
		||||
              " of PIN entry attempts has been reached.";
 | 
			
		||||
            ss<<"The card cannot be accessed because the maximum"
 | 
			
		||||
              <<" number of PIN entry attempts has been reached.";
 | 
			
		||||
            break;
 | 
			
		||||
          case SCARD_W_EOF:
 | 
			
		||||
            ss<<"The end of the smart card file has been reached.";
 | 
			
		||||
@@ -421,7 +562,7 @@ namespace pcsc {
 | 
			
		||||
            ss<<"No PIN was presented to the smart card.";
 | 
			
		||||
            break;
 | 
			
		||||
          default:
 | 
			
		||||
            ss<<"Unknown PCSC state: "<<_state;
 | 
			
		||||
            ss<<"Unknown PCSC state: "<<std::hex<<_state;
 | 
			
		||||
        }
 | 
			
		||||
        return ss.str();
 | 
			
		||||
        #else
 | 
			
		||||
@@ -435,16 +576,20 @@ namespace pcsc {
 | 
			
		||||
      //! Sets state and throws an exception if neccessary.
 | 
			
		||||
      /*! @throw access_error if it is instanciated for exceptions and
 | 
			
		||||
          an error occured in the last command. */
 | 
			
		||||
      bool check(long state) {
 | 
			
		||||
      bool check(long state, const std::string& context="") {
 | 
			
		||||
        _state = state;
 | 
			
		||||
        return check();
 | 
			
		||||
        return check(context);
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      //! Throws an exception if neccessary.
 | 
			
		||||
      /*! @throw access_error if it is instanciated for exceptions and
 | 
			
		||||
          an error occured in the last command. */
 | 
			
		||||
      bool check() {
 | 
			
		||||
        if (_exc&&_state!=SCARD_S_SUCCESS) throw access_error(error());
 | 
			
		||||
      bool check(const std::string& context="") {
 | 
			
		||||
        if (_exc&&_state!=SCARD_S_SUCCESS)
 | 
			
		||||
          if (context.size())
 | 
			
		||||
            throw access_error(context+": "+error());
 | 
			
		||||
          else
 | 
			
		||||
            throw access_error(error());
 | 
			
		||||
        return _state==SCARD_S_SUCCESS;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user