all: pass context to check; win: even more error messages

master
Marc Wäckerlin 16 years ago
parent fe32a2391b
commit f6a72ef0fa
  1. 203
      src/pcsc.hxx

@ -190,7 +190,8 @@ namespace pcsc {
//! Disconnects connection. //! Disconnects connection.
~Reader() { ~Reader() {
_state = SCardDisconnect(_id, SCARD_LEAVE_CARD); _state = SCardDisconnect(_id, SCARD_LEAVE_CARD);
if (!std::uncaught_exception()) _connection.check(); if (!std::uncaught_exception())
_connection.check("disconnect smartcard");
} }
//! Get reader status. //! Get reader status.
@ -199,7 +200,8 @@ namespace pcsc {
DWORD s; DWORD s;
DWORD len(MAX_ATR_SIZE); DWORD len(MAX_ATR_SIZE);
unsigned char a[len]; 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)); return Status(s, std::string((char*)a, len));
} }
@ -210,7 +212,8 @@ namespace pcsc {
SCARD_IO_REQUEST rPci; SCARD_IO_REQUEST rPci;
check(SCardTransmit(_id, pci(), check(SCardTransmit(_id, pci(),
(unsigned char*)in.c_str(), in.size(), (unsigned char*)in.c_str(), in.size(),
&rPci, buff, &len)); &rPci, buff, &len),
"smartcard transmit message "+hex(in));
return std::string((char*)buff, len); return std::string((char*)buff, len);
} }
@ -229,17 +232,18 @@ namespace pcsc {
//! Use scoped transactions with @ref Transaction //! Use scoped transactions with @ref Transaction
void beginTransaction() { void beginTransaction() {
check(SCardBeginTransaction(_id)); check(SCardBeginTransaction(_id), "smartcard begin transaction");
} }
//! Use scoped transactions with @ref Transaction //! Use scoped transactions with @ref Transaction
void commitTransaction() { void commitTransaction() {
check(SCardEndTransaction(_id, SCARD_LEAVE_CARD)); check(SCardEndTransaction(_id, SCARD_LEAVE_CARD),
"smartcard end transaction");
} }
//! Use scoped transactions with @ref Transaction //! Use scoped transactions with @ref Transaction
void cancelTransaction() { void cancelTransaction() {
check(SCardCancelTransaction(_id)); check(SCardCancelTransaction(_id), "smartcard cancel transaction");
} }
/*! @throw not_implemented if _protocol is unknown. */ /*! @throw not_implemented if _protocol is unknown. */
@ -255,9 +259,9 @@ namespace pcsc {
//! Sets state and throws an exception if neccessary. //! Sets state and throws an exception if neccessary.
/*! @throw access_error if it is instanciated for exceptions and /*! @throw access_error if it is instanciated for exceptions and
an error occured in the last command. */ an error occured in the last command. */
bool check(long state) { bool check(long state, const std::string context="") {
_state = state; _state = state;
return _connection.check(state); return _connection.check(state, context);
} }
//! Only Connection is allowed to instanciate. //! Only Connection is allowed to instanciate.
@ -269,7 +273,8 @@ namespace pcsc {
check(SCardConnect(_connection._id, strconv(name).c_str(), check(SCardConnect(_connection._id, strconv(name).c_str(),
SCARD_SHARE_SHARED, SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1,
&_id, &_protocol)); &_id, &_protocol),
"connect smartcard \""+name+"\"");
} }
//! forbidden //! forbidden
@ -283,7 +288,7 @@ namespace pcsc {
Connection& _connection; Connection& _connection;
SCARDHANDLE _id; SCARDHANDLE _id;
long _state; DWORD _state;
DWORD _protocol; DWORD _protocol;
}; };
@ -331,13 +336,13 @@ namespace pcsc {
Connection(Scope s=SYSTEM, bool exceptions=true): Connection(Scope s=SYSTEM, bool exceptions=true):
_exc(exceptions), _id(0), _exc(exceptions), _id(0),
_state(SCardEstablishContext(s, 0, 0, &_id)) { _state(SCardEstablishContext(s, 0, 0, &_id)) {
check(); check("establish smartcard context");
} }
//! Closes the connection (releases the smartcard context) //! Closes the connection (releases the smartcard context)
~Connection() { ~Connection() {
_state = SCardReleaseContext(_id); _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. //! Scans for available readers from a specified list of groups.
@ -347,11 +352,13 @@ namespace pcsc {
std::string grp(join(groups)); std::string grp(join(groups));
DWORD num(0); DWORD num(0);
if (!check(SCardListReaders(_id, grp.size()?strconv(grp).data():0, 0, if (!check(SCardListReaders(_id, grp.size()?strconv(grp).data():0, 0,
&num))) &num),
"(1) smartcard list readers of groups "+grp))
return res; return res;
std::auto_ptr<char_t> nm(new char_t[num]); std::auto_ptr<char_t> nm(new char_t[num]);
if (!check(SCardListReaders(_id, grp.size()?strconv(grp).data():0, 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;
return res = split(strconv(string(nm.get(), num-1))); return res = split(strconv(string(nm.get(), num-1)));
} }
@ -382,34 +389,168 @@ namespace pcsc {
#ifdef WIN32 #ifdef WIN32
std::stringstream ss; std::stringstream ss;
switch (_state) { switch (_state) {
case SCARD_S_SUCCESS: case SCARD_E_SHARING_VIOLATION:
ss<<"Success"; 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; break;
case SCARD_W_UNRESPONSIVE_CARD: case SCARD_W_UNRESPONSIVE_CARD:
ss<<"The smart card is not responding to a reset."; ss<<"The smart card is not responding to a reset.";
break; break;
case SCARD_W_UNPOWERED_CARD: case SCARD_W_UNPOWERED_CARD:
ss<<"Power has been removed from the smart card, so that further" ss<<"Power has been removed from the smart card, so that"
" communication is not possible."; <<" further communication is not possible.";
break; break;
case SCARD_W_RESET_CARD: case SCARD_W_RESET_CARD:
ss<<"The smart card has been reset, so any shared state" ss<<"The smart card has been reset, so any shared state"
" information is invalid."; <<" information is invalid.";
break; break;
case SCARD_W_REMOVED_CARD: case SCARD_W_REMOVED_CARD:
ss<<"The smart card has been removed, so that further" ss<<"The smart card has been removed, so that further"
" communication is not possible."; <<" communication is not possible.";
break; break;
case SCARD_W_SECURITY_VIOLATION: case SCARD_W_SECURITY_VIOLATION:
ss<<"Access was denied because of a security violation."; ss<<"Access was denied because of a security violation.";
break; break;
case SCARD_W_WRONG_CHV: case SCARD_W_WRONG_CHV:
ss<<"The card cannot be accessed because the wrong PIN was" ss<<"The card cannot be accessed because the wrong PIN"
" presented."; <<" was presented.";
break; break;
case SCARD_W_CHV_BLOCKED: case SCARD_W_CHV_BLOCKED:
ss<<"The card cannot be accessed because the maximum number" ss<<"The card cannot be accessed because the maximum"
" of PIN entry attempts has been reached."; <<" number of PIN entry attempts has been reached.";
break; break;
case SCARD_W_EOF: case SCARD_W_EOF:
ss<<"The end of the smart card file has been reached."; 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."; ss<<"No PIN was presented to the smart card.";
break; break;
default: default:
ss<<"Unknown PCSC state: "<<_state; ss<<"Unknown PCSC state: "<<std::hex<<_state;
} }
return ss.str(); return ss.str();
#else #else
@ -435,16 +576,20 @@ namespace pcsc {
//! Sets state and throws an exception if neccessary. //! Sets state and throws an exception if neccessary.
/*! @throw access_error if it is instanciated for exceptions and /*! @throw access_error if it is instanciated for exceptions and
an error occured in the last command. */ an error occured in the last command. */
bool check(long state) { bool check(long state, const std::string& context="") {
_state = state; _state = state;
return check(); return check(context);
} }
//! Throws an exception if neccessary. //! Throws an exception if neccessary.
/*! @throw access_error if it is instanciated for exceptions and /*! @throw access_error if it is instanciated for exceptions and
an error occured in the last command. */ an error occured in the last command. */
bool check() { bool check(const std::string& context="") {
if (_exc&&_state!=SCARD_S_SUCCESS) throw access_error(error()); if (_exc&&_state!=SCARD_S_SUCCESS)
if (context.size())
throw access_error(context+": "+error());
else
throw access_error(error());
return _state==SCARD_S_SUCCESS; return _state==SCARD_S_SUCCESS;
} }

Loading…
Cancel
Save