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