diff --git a/src/pcsc.hxx b/src/pcsc.hxx index 3cc0e68..a25bf8a 100644 --- a/src/pcsc.hxx +++ b/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 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: "<