added draft lib for suisseid - by now: detect Post SuisseID; refs #28
This commit is contained in:
628
src/pcsc.hxx
628
src/pcsc.hxx
@@ -11,7 +11,7 @@
|
||||
#define PCSC_HXX
|
||||
|
||||
#ifndef PCSC_LOG
|
||||
//! Declare PCSC_LOG before #include in your code, if you want logging.
|
||||
//! Declare PCSC_LOG before #include in your de, if you want logging.
|
||||
/*! PCSC_LOG passes its argument to a stream, so your definition must
|
||||
behave so that the argument can be streamed.
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include <cryptaux.hxx>
|
||||
|
||||
#include <mrw/shared.hxx>
|
||||
#include <string>
|
||||
|
||||
#ifdef WIN32
|
||||
@@ -214,8 +215,8 @@ namespace pcsc {
|
||||
/*! @note Please note that the Reader is required in the
|
||||
destructor und must therefore live longer than the
|
||||
Transaction instance. */
|
||||
Transaction(Reader& r): _reader(r), _running(true) {
|
||||
_reader.beginTransaction();
|
||||
Transaction(mrw::Shared<Reader> r): _reader(r), _running(true) {
|
||||
_reader->beginTransaction();
|
||||
}
|
||||
//! Cancels the transaction if not yet finished.
|
||||
~Transaction() try {
|
||||
@@ -225,11 +226,11 @@ namespace pcsc {
|
||||
}
|
||||
//! Ends the running transaction.
|
||||
void end() {
|
||||
if (_running) _reader.endTransaction();
|
||||
if (_running) _reader->endTransaction();
|
||||
_running = false;
|
||||
}
|
||||
private:
|
||||
Reader& _reader;
|
||||
mrw::Shared<Reader> _reader;
|
||||
bool _running;
|
||||
};
|
||||
|
||||
@@ -248,7 +249,7 @@ namespace pcsc {
|
||||
~Reader() {
|
||||
_state = SCardDisconnect(_id, SCARD_RESET_CARD);
|
||||
if (!std::uncaught_exception())
|
||||
_connection.check("disconnect smartcard");
|
||||
_connection->check("disconnect smartcard");
|
||||
}
|
||||
|
||||
//! Get reader status.
|
||||
@@ -411,7 +412,7 @@ namespace pcsc {
|
||||
case SCARD_PROTOCOL_T0: return SCARD_PCI_T0;
|
||||
case SCARD_PROTOCOL_T1: return SCARD_PCI_T1;
|
||||
}
|
||||
if (_connection._exc) throw not_implemented("unknown protocol");
|
||||
if (_connection->exc()) throw not_implemented("unknown protocol");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -420,18 +421,18 @@ namespace pcsc {
|
||||
an error occured in the last command. */
|
||||
bool check(long state, const std::string context="") {
|
||||
_state = state;
|
||||
return _connection.check(state, context);
|
||||
return _connection->check(state, context);
|
||||
}
|
||||
|
||||
//! Only Connection is allowed to instanciate.
|
||||
friend class Connection;
|
||||
|
||||
//! Establishes a connection to the given named cardreader
|
||||
Reader(const std::string& nm, Connection& c,
|
||||
Reader(const std::string& nm, const Connection& c,
|
||||
DWORD mode=SCARD_SHARE_SHARED,
|
||||
DWORD protocol=SCARD_PROTOCOL_T1):
|
||||
name(nm), _connection(c) {
|
||||
check(SCardConnect(_connection._id, strconv(name).c_str(),
|
||||
check(SCardConnect(_connection->id(), strconv(name).c_str(),
|
||||
mode, protocol,
|
||||
&_id, &_protocol),
|
||||
"connect smartcard \""+name);
|
||||
@@ -440,13 +441,10 @@ namespace pcsc {
|
||||
//! forbidden
|
||||
Reader();
|
||||
|
||||
//! forbidden
|
||||
Reader(const Reader&);
|
||||
|
||||
//...........................................................variables
|
||||
private:
|
||||
|
||||
Connection& _connection;
|
||||
mrw::Shared<Connection> _connection;
|
||||
SCARDHANDLE _id;
|
||||
DWORD _state;
|
||||
DWORD _protocol;
|
||||
@@ -495,15 +493,13 @@ namespace pcsc {
|
||||
- @c false: no exceptions, check your instance after each
|
||||
operation */
|
||||
Connection(Scope s=USER, bool exceptions=true):
|
||||
_exc(exceptions), _id(0),
|
||||
_state(SCardEstablishContext(s, 0, 0, &_id)) {
|
||||
_connectionlifetime(new ConnectionLifetime(s, exceptions)) {
|
||||
check("establish smartcard context");
|
||||
}
|
||||
|
||||
//! Closes the connection (releases the smartcard context)
|
||||
~Connection() {
|
||||
_state = SCardReleaseContext(_id);
|
||||
if (!std::uncaught_exception()) check("smartcard release context");
|
||||
// connection is closed, when last _connectionlifetime is destructed
|
||||
}
|
||||
|
||||
//! Scans for available readers from a specified list of groups.
|
||||
@@ -512,14 +508,16 @@ namespace pcsc {
|
||||
Strings res;
|
||||
std::string grp(join(groups));
|
||||
DWORD num(0);
|
||||
if (!check(SCardListReaders(_id, groups.size()?strconv(grp).data():0, 0,
|
||||
if (!check(SCardListReaders(_connectionlifetime->id(),
|
||||
groups.size()?strconv(grp).data():0, 0,
|
||||
&num),
|
||||
"smartcard get size of readers of groups "+grp))
|
||||
return res;
|
||||
PCSC_LOG("size of readers: "<<num);
|
||||
if (!num) return res;
|
||||
std::auto_ptr<char_t> nm(new char_t[num]);
|
||||
if (!check(SCardListReaders(_id, groups.size()?strconv(grp).data():0,
|
||||
if (!check(SCardListReaders(_connectionlifetime->id(),
|
||||
groups.size()?strconv(grp).data():0,
|
||||
nm.get(), &num),
|
||||
"smartcard list reader names of groups "+grp))
|
||||
return res;
|
||||
@@ -533,12 +531,10 @@ namespace pcsc {
|
||||
//! Get a reader, open a connection if not already open.
|
||||
/*! First use scan() to get a list of readers, then open a
|
||||
connection to the reader, then access it. */
|
||||
Reader& reader(const std::string& name) {
|
||||
if (_reader.find(name)==_reader.end())
|
||||
_reader.insert
|
||||
(std::make_pair
|
||||
(name, shared_ptr<Reader>::t(new Reader(name, *this))));
|
||||
return *_reader.find(name)->second;
|
||||
mrw::Shared<Reader> reader(const std::string& name) {
|
||||
if (_readers.find(name)==_readers.end())
|
||||
_readers.insert(std::make_pair(name, new Reader(name, *this)));
|
||||
return _readers.find(name)->second;
|
||||
}
|
||||
|
||||
//! Close connection of a named reader.
|
||||
@@ -556,257 +552,14 @@ namespace pcsc {
|
||||
pcsc::Connection::Strings readers(scan());
|
||||
for (pcsc::Connection::Strings::const_iterator it(readers.begin());
|
||||
it!=readers.end(); ++it)
|
||||
if (crypto::hex(reader(*it).status().atr).find(atr)!=string::npos)
|
||||
if (crypto::hex(reader(*it)->status().atr).find(atr)!=string::npos)
|
||||
res.push_back(*it);
|
||||
return res;
|
||||
}
|
||||
|
||||
//! @c false if last operation was not successful
|
||||
operator bool() const {
|
||||
#ifdef WIN32
|
||||
return (_state>>30&3)==0;
|
||||
#else
|
||||
return _state==SCARD_S_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
//! Get the describing text of the last error
|
||||
std::string error() const {
|
||||
std::stringstream ss;
|
||||
switch (_state) {
|
||||
case SCARD_E_CANCELLED:
|
||||
ss<<"The action was canceled by an SCardCancel request.";
|
||||
break;
|
||||
case SCARD_E_CANT_DISPOSE:
|
||||
ss<<"The system could not dispose of the media in the requested"
|
||||
<<" manner.";
|
||||
break;
|
||||
case SCARD_E_CARD_UNSUPPORTED:
|
||||
ss<<"The smart card 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_INSUFFICIENT_BUFFER:
|
||||
ss<<"The data buffer for returned data is too small for the"
|
||||
<<" returned data.";
|
||||
break;
|
||||
case SCARD_E_INVALID_ATR:
|
||||
ss<<"An ATR string obtained from the registry is not a valid"
|
||||
<<" ATR string.";
|
||||
break;
|
||||
case SCARD_E_INVALID_HANDLE:
|
||||
ss<<"The supplied handle was not valid.";
|
||||
break;
|
||||
case SCARD_E_INVALID_PARAMETER:
|
||||
ss<<"One or more of the supplied parameters could not be properly"
|
||||
<<" interpreted.";
|
||||
break;
|
||||
case SCARD_E_INVALID_TARGET:
|
||||
ss<<"Registry startup information is missing or not valid.";
|
||||
break;
|
||||
case SCARD_E_INVALID_VALUE:
|
||||
ss<<"One or more of the supplied parameters values could not"
|
||||
<<" be properly interpreted.";
|
||||
break;
|
||||
case SCARD_E_NOT_READY:
|
||||
ss<<"The reader or smart card is not ready to accept commands.";
|
||||
break;
|
||||
case SCARD_E_NOT_TRANSACTED:
|
||||
ss<<"An attempt was made to end a nonexistent transaction.";
|
||||
break;
|
||||
case SCARD_E_NO_MEMORY:
|
||||
ss<<"Not enough memory available to complete this command.";
|
||||
break;
|
||||
case SCARD_E_NO_SERVICE:
|
||||
ss<<"The smart card resource manager is not running.";
|
||||
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_PCI_TOO_SMALL:
|
||||
ss<<"The PCI receive buffer was too small.";
|
||||
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_READER_UNAVAILABLE:
|
||||
ss<<"The specified reader is not currently available for use.";
|
||||
break;
|
||||
case SCARD_E_READER_UNSUPPORTED:
|
||||
ss<<"The reader driver does not meet minimal requirements for"
|
||||
<<" support.";
|
||||
break;
|
||||
case SCARD_E_SERVICE_STOPPED:
|
||||
ss<<"The smart card resource manager has shut down.";
|
||||
break;
|
||||
case SCARD_E_SHARING_VIOLATION:
|
||||
ss<<"The smart card cannot be accessed because of other outstanding"
|
||||
<<" connections.";
|
||||
break;
|
||||
case SCARD_E_SYSTEM_CANCELLED:
|
||||
ss<<"The action was cancelled by the system, presumably to log"
|
||||
<<" off or shut down.";
|
||||
break;
|
||||
case SCARD_E_TIMEOUT:
|
||||
ss<<"The user-specified time-out value has expired.";
|
||||
break;
|
||||
case SCARD_E_UNKNOWN_CARD:
|
||||
ss<<"The specified smart card name is not recognized.";
|
||||
break;
|
||||
case SCARD_E_UNKNOWN_READER:
|
||||
ss<<"The specified reader name is not recognized.";
|
||||
break;
|
||||
case SCARD_E_UNSUPPORTED_FEATURE:
|
||||
ss<<"This smart card does not support the requested feature.";
|
||||
break;
|
||||
case SCARD_F_COMM_ERROR:
|
||||
ss<<"An internal communications error has been detected.";
|
||||
break;
|
||||
case SCARD_F_INTERNAL_ERROR:
|
||||
ss<<"An internal consistency check failed.";
|
||||
break;
|
||||
case SCARD_F_UNKNOWN_ERROR:
|
||||
ss<<"An internal error has been detected, but the source is"
|
||||
<<" unknown.";
|
||||
break;
|
||||
case SCARD_F_WAITED_TOO_LONG:
|
||||
ss<<"An internal consistency timer has expired.";
|
||||
break;
|
||||
case SCARD_S_SUCCESS:
|
||||
ss<<"No error was encountered.";
|
||||
break;
|
||||
case SCARD_W_REMOVED_CARD:
|
||||
ss<<"The smart card has been removed, so that further communication"
|
||||
<<" is not possible.";
|
||||
break;
|
||||
case SCARD_W_RESET_CARD:
|
||||
ss<<"The smart card was reset.";
|
||||
break;
|
||||
case SCARD_W_UNPOWERED_CARD:
|
||||
ss<<"Power has been removed from the smart card, so that"
|
||||
<<" further communication is not possible.";
|
||||
break;
|
||||
case SCARD_W_UNRESPONSIVE_CARD:
|
||||
ss<<"The smart card is not responding to a reset.";
|
||||
break;
|
||||
case SCARD_W_UNSUPPORTED_CARD:
|
||||
ss<<"The reader cannot communicate with the smart card,"
|
||||
<<" due to ATR configuration conflicts.";
|
||||
break;
|
||||
#ifndef __APPLE__
|
||||
case SCARD_E_NO_READERS_AVAILABLE:
|
||||
ss<<"No smart card reader is available.";
|
||||
break;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
case ERROR_BROKEN_PIPE:
|
||||
ss<<"The client attempted a smart card operation in a"
|
||||
<<" remote session, such as a client session running"
|
||||
<<" on a terminal server, and the operating system in"
|
||||
<<" use does not support smart card redirection.";
|
||||
break;
|
||||
case SCARD_E_BAD_SEEK:
|
||||
ss<<"There was an error trying to set the smart card file"
|
||||
<<" object pointer.";
|
||||
break;
|
||||
case SCARD_E_CERTIFICATE_UNAVAILABLE:
|
||||
ss<<"The requested certificate could not be obtained.";
|
||||
break;
|
||||
case SCARD_E_COMM_DATA_LOST:
|
||||
ss<<"A communications error with the smart card has been detected.";
|
||||
break;
|
||||
case SCARD_E_DIR_NOT_FOUND:
|
||||
ss<<"The specified directory does not exist in the smart card.";
|
||||
break;
|
||||
case SCARD_E_FILE_NOT_FOUND:
|
||||
ss<<"The specified file does not exist in the smart card.";
|
||||
break;
|
||||
case SCARD_E_ICC_CREATEORDER:
|
||||
ss<<"The requested order of object creation is not supported.";
|
||||
break;
|
||||
case SCARD_E_ICC_INSTALLATION:
|
||||
ss<<"No primary provider can be found for the smart card.";
|
||||
break;
|
||||
case SCARD_E_INVALID_CHV:
|
||||
ss<<"The supplied PIN is incorrect.";
|
||||
break;
|
||||
case SCARD_E_NO_ACCESS:
|
||||
ss<<"Access is denied to this file.";
|
||||
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_KEY_CONTAINER:
|
||||
ss<<"The requested key container does not exist on the smart card.";
|
||||
break;
|
||||
case SCARD_E_NO_SUCH_CERTIFICATE:
|
||||
ss<<"The requested certificate does not exist.";
|
||||
break;
|
||||
case SCARD_E_SERVER_TOO_BUSY:
|
||||
ss<<"The Smart card resource manager is too busy to complete this"
|
||||
<<" operation.";
|
||||
break;
|
||||
case SCARD_E_UNEXPECTED:
|
||||
ss<<"An unexpected card error has occurred.";
|
||||
break;
|
||||
case SCARD_E_UNKNOWN_RES_MNG:
|
||||
ss<<"An unrecognized error code was returned from a layered"
|
||||
<<" component.";
|
||||
break;
|
||||
case SCARD_E_WRITE_TOO_MANY:
|
||||
ss<<"The smartcard does not have enough memory to store the"
|
||||
<<" information.";
|
||||
break;
|
||||
case SCARD_P_SHUTDOWN:
|
||||
ss<<"The operation has been aborted to allow the server application"
|
||||
<<" to exit.";
|
||||
break;
|
||||
case SCARD_W_CANCELLED_BY_USER:
|
||||
ss<<"The action was cancelled by the user.";
|
||||
break;
|
||||
case SCARD_W_CARD_NOT_AUTHENTICATED:
|
||||
ss<<"No PIN was presented to the smart card.";
|
||||
break;
|
||||
case SCARD_W_CHV_BLOCKED:
|
||||
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.";
|
||||
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.";
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ss<<"unknown PCSC state=0x"
|
||||
<<std::hex<<std::setfill('0')<<std::setw(8)<<_state;
|
||||
switch (_state>>30) {
|
||||
case 0: ss<<" means SUCCESS"; break;
|
||||
case 1: ss<<" means INFORMATIONAL"; break;
|
||||
case 2: ss<<" means WARNING"; break;
|
||||
case 3: ss<<" means ERROR"; break;
|
||||
default: ss<<" illegal value";
|
||||
}
|
||||
ss<<" C="<<(_state>>29&1);
|
||||
ss<<" R="<<(_state>>28&1);
|
||||
ss<<" Facility=0x"<<std::hex<<std::setfill('0')<<std::setw(3)
|
||||
<<(_state>>16&0xfff);
|
||||
ss<<" Code=0x"<<std::hex<<std::setfill('0')<<std::setw(4)
|
||||
<<(_state&0xffff);
|
||||
}
|
||||
return ss.str();
|
||||
return *_connectionlifetime;
|
||||
}
|
||||
|
||||
//................................................................methods
|
||||
@@ -816,20 +569,15 @@ namespace pcsc {
|
||||
/*! @throw access_error if it is instanciated for exceptions and
|
||||
an error occured in the last command. */
|
||||
bool check(long state, const std::string& context="") {
|
||||
_state = state;
|
||||
_connectionlifetime->state(state);
|
||||
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(const std::string& context="") {
|
||||
if (_exc&&!*this)
|
||||
if (context.size())
|
||||
throw access_error(context+": "+error());
|
||||
else
|
||||
throw access_error(error());
|
||||
return *this;
|
||||
return _connectionlifetime->check(context);
|
||||
}
|
||||
|
||||
//! Splits a buffer with 0 separators into a vector of strings.
|
||||
@@ -852,14 +600,324 @@ namespace pcsc {
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
//! Connection id
|
||||
SCARDCONTEXT id() {
|
||||
return _connectionlifetime->id();
|
||||
}
|
||||
|
||||
//! @c true if exceptions are thrown
|
||||
bool exc() {
|
||||
return _connectionlifetime->exc();
|
||||
}
|
||||
|
||||
//..............................................................variables
|
||||
private:
|
||||
private:
|
||||
|
||||
class ConnectionLifetime {
|
||||
public:
|
||||
//! opens connection that is closed on destruction
|
||||
ConnectionLifetime(Scope s, bool exc):
|
||||
_exc(exc), _id(0),
|
||||
_state(SCardEstablishContext(s, 0, 0, &_id)) {
|
||||
check("establish smartcard context");
|
||||
}
|
||||
//! Closes the connection (releases the smartcard context)
|
||||
~ConnectionLifetime() {
|
||||
_state = SCardReleaseContext(_id);
|
||||
if (!std::uncaught_exception()) check("smartcard release context");
|
||||
}
|
||||
//! @c false if last operation was not successful
|
||||
operator bool() const {
|
||||
#ifdef WIN32
|
||||
return (_state>>30&3)==0;
|
||||
#else
|
||||
return _state==SCARD_S_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
//! Throws an exception if neccessary.
|
||||
/*! @throw access_error if it is instanciated for exceptions and
|
||||
an error occured in the last command. */
|
||||
bool check(const std::string& context="") {
|
||||
if (_exc&&!*this)
|
||||
if (context.size())
|
||||
throw access_error(context+": "+error());
|
||||
else
|
||||
throw access_error(error());
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Get the describing text of the last error
|
||||
std::string error() const {
|
||||
std::stringstream ss;
|
||||
switch (_state) {
|
||||
case SCARD_E_CANCELLED:
|
||||
ss<<"The action was canceled by an SCardCancel request.";
|
||||
break;
|
||||
case SCARD_E_CANT_DISPOSE:
|
||||
ss<<"The system could not dispose of the media in the requested"
|
||||
<<" manner.";
|
||||
break;
|
||||
case SCARD_E_CARD_UNSUPPORTED:
|
||||
ss<<"The smart card 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_INSUFFICIENT_BUFFER:
|
||||
ss<<"The data buffer for returned data is too small for the"
|
||||
<<" returned data.";
|
||||
break;
|
||||
case SCARD_E_INVALID_ATR:
|
||||
ss<<"An ATR string obtained from the registry is not a valid"
|
||||
<<" ATR string.";
|
||||
break;
|
||||
case SCARD_E_INVALID_HANDLE:
|
||||
ss<<"The supplied handle was not valid.";
|
||||
break;
|
||||
case SCARD_E_INVALID_PARAMETER:
|
||||
ss<<"One or more of the supplied parameters could not be properly"
|
||||
<<" interpreted.";
|
||||
break;
|
||||
case SCARD_E_INVALID_TARGET:
|
||||
ss<<"Registry startup information is missing or not valid.";
|
||||
break;
|
||||
case SCARD_E_INVALID_VALUE:
|
||||
ss<<"One or more of the supplied parameters values could not"
|
||||
<<" be properly interpreted.";
|
||||
break;
|
||||
case SCARD_E_NOT_READY:
|
||||
ss<<"The reader or smart card is not ready to accept commands.";
|
||||
break;
|
||||
case SCARD_E_NOT_TRANSACTED:
|
||||
ss<<"An attempt was made to end a nonexistent transaction.";
|
||||
break;
|
||||
case SCARD_E_NO_MEMORY:
|
||||
ss<<"Not enough memory available to complete this command.";
|
||||
break;
|
||||
case SCARD_E_NO_SERVICE:
|
||||
ss<<"The smart card resource manager is not running.";
|
||||
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_PCI_TOO_SMALL:
|
||||
ss<<"The PCI receive buffer was too small.";
|
||||
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_READER_UNAVAILABLE:
|
||||
ss<<"The specified reader is not currently available for use.";
|
||||
break;
|
||||
case SCARD_E_READER_UNSUPPORTED:
|
||||
ss<<"The reader driver does not meet minimal requirements for"
|
||||
<<" support.";
|
||||
break;
|
||||
case SCARD_E_SERVICE_STOPPED:
|
||||
ss<<"The smart card resource manager has shut down.";
|
||||
break;
|
||||
case SCARD_E_SHARING_VIOLATION:
|
||||
ss<<"The smart card cannot be accessed because of other outstanding"
|
||||
<<" connections.";
|
||||
break;
|
||||
case SCARD_E_SYSTEM_CANCELLED:
|
||||
ss<<"The action was cancelled by the system, presumably to log"
|
||||
<<" off or shut down.";
|
||||
break;
|
||||
case SCARD_E_TIMEOUT:
|
||||
ss<<"The user-specified time-out value has expired.";
|
||||
break;
|
||||
case SCARD_E_UNKNOWN_CARD:
|
||||
ss<<"The specified smart card name is not recognized.";
|
||||
break;
|
||||
case SCARD_E_UNKNOWN_READER:
|
||||
ss<<"The specified reader name is not recognized.";
|
||||
break;
|
||||
case SCARD_E_UNSUPPORTED_FEATURE:
|
||||
ss<<"This smart card does not support the requested feature.";
|
||||
break;
|
||||
case SCARD_F_COMM_ERROR:
|
||||
ss<<"An internal communications error has been detected.";
|
||||
break;
|
||||
case SCARD_F_INTERNAL_ERROR:
|
||||
ss<<"An internal consistency check failed.";
|
||||
break;
|
||||
case SCARD_F_UNKNOWN_ERROR:
|
||||
ss<<"An internal error has been detected, but the source is"
|
||||
<<" unknown.";
|
||||
break;
|
||||
case SCARD_F_WAITED_TOO_LONG:
|
||||
ss<<"An internal consistency timer has expired.";
|
||||
break;
|
||||
case SCARD_S_SUCCESS:
|
||||
ss<<"No error was encountered.";
|
||||
break;
|
||||
case SCARD_W_REMOVED_CARD:
|
||||
ss<<"The smart card has been removed, so that further communication"
|
||||
<<" is not possible.";
|
||||
break;
|
||||
case SCARD_W_RESET_CARD:
|
||||
ss<<"The smart card was reset.";
|
||||
break;
|
||||
case SCARD_W_UNPOWERED_CARD:
|
||||
ss<<"Power has been removed from the smart card, so that"
|
||||
<<" further communication is not possible.";
|
||||
break;
|
||||
case SCARD_W_UNRESPONSIVE_CARD:
|
||||
ss<<"The smart card is not responding to a reset.";
|
||||
break;
|
||||
case SCARD_W_UNSUPPORTED_CARD:
|
||||
ss<<"The reader cannot communicate with the smart card,"
|
||||
<<" due to ATR configuration conflicts.";
|
||||
break;
|
||||
#ifndef __APPLE__
|
||||
case SCARD_E_NO_READERS_AVAILABLE:
|
||||
ss<<"No smart card reader is available.";
|
||||
break;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
case ERROR_BROKEN_PIPE:
|
||||
ss<<"The client attempted a smart card operation in a"
|
||||
<<" remote session, such as a client session running"
|
||||
<<" on a terminal server, and the operating system in"
|
||||
<<" use does not support smart card redirection.";
|
||||
break;
|
||||
case SCARD_E_BAD_SEEK:
|
||||
ss<<"There was an error trying to set the smart card file"
|
||||
<<" object pointer.";
|
||||
break;
|
||||
case SCARD_E_CERTIFICATE_UNAVAILABLE:
|
||||
ss<<"The requested certificate could not be obtained.";
|
||||
break;
|
||||
case SCARD_E_COMM_DATA_LOST:
|
||||
ss<<"A communications error with the smart card has been detected.";
|
||||
break;
|
||||
case SCARD_E_DIR_NOT_FOUND:
|
||||
ss<<"The specified directory does not exist in the smart card.";
|
||||
break;
|
||||
case SCARD_E_FILE_NOT_FOUND:
|
||||
ss<<"The specified file does not exist in the smart card.";
|
||||
break;
|
||||
case SCARD_E_ICC_CREATEORDER:
|
||||
ss<<"The requested order of object creation is not supported.";
|
||||
break;
|
||||
case SCARD_E_ICC_INSTALLATION:
|
||||
ss<<"No primary provider can be found for the smart card.";
|
||||
break;
|
||||
case SCARD_E_INVALID_CHV:
|
||||
ss<<"The supplied PIN is incorrect.";
|
||||
break;
|
||||
case SCARD_E_NO_ACCESS:
|
||||
ss<<"Access is denied to this file.";
|
||||
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_KEY_CONTAINER:
|
||||
ss<<"The requested key container does not exist on the smart card.";
|
||||
break;
|
||||
case SCARD_E_NO_SUCH_CERTIFICATE:
|
||||
ss<<"The requested certificate does not exist.";
|
||||
break;
|
||||
case SCARD_E_SERVER_TOO_BUSY:
|
||||
ss<<"The Smart card resource manager is too busy to complete this"
|
||||
<<" operation.";
|
||||
break;
|
||||
case SCARD_E_UNEXPECTED:
|
||||
ss<<"An unexpected card error has occurred.";
|
||||
break;
|
||||
case SCARD_E_UNKNOWN_RES_MNG:
|
||||
ss<<"An unrecognized error code was returned from a layered"
|
||||
<<" component.";
|
||||
break;
|
||||
case SCARD_E_WRITE_TOO_MANY:
|
||||
ss<<"The smartcard does not have enough memory to store the"
|
||||
<<" information.";
|
||||
break;
|
||||
case SCARD_P_SHUTDOWN:
|
||||
ss<<"The operation has been aborted to allow the server application"
|
||||
<<" to exit.";
|
||||
break;
|
||||
case SCARD_W_CANCELLED_BY_USER:
|
||||
ss<<"The action was cancelled by the user.";
|
||||
break;
|
||||
case SCARD_W_CARD_NOT_AUTHENTICATED:
|
||||
ss<<"No PIN was presented to the smart card.";
|
||||
break;
|
||||
case SCARD_W_CHV_BLOCKED:
|
||||
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.";
|
||||
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.";
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ss<<"unknown PCSC state=0x"
|
||||
<<std::hex<<std::setfill('0')<<std::setw(8)<<_state;
|
||||
switch (_state>>30) {
|
||||
case 0: ss<<" means SUCCESS"; break;
|
||||
case 1: ss<<" means INFORMATIONAL"; break;
|
||||
case 2: ss<<" means WARNING"; break;
|
||||
case 3: ss<<" means ERROR"; break;
|
||||
default: ss<<" illegal value";
|
||||
}
|
||||
ss<<" C="<<(_state>>29&1);
|
||||
ss<<" R="<<(_state>>28&1);
|
||||
ss<<" Facility=0x"<<std::hex<<std::setfill('0')<<std::setw(3)
|
||||
<<(_state>>16&0xfff);
|
||||
ss<<" Code=0x"<<std::hex<<std::setfill('0')<<std::setw(4)
|
||||
<<(_state&0xffff);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
//! set state
|
||||
void state(long s) {
|
||||
_state = s;
|
||||
}
|
||||
//! @returns state
|
||||
long state() {
|
||||
return _state;
|
||||
}
|
||||
//! @returns connection id
|
||||
SCARDCONTEXT id() {
|
||||
return _id;
|
||||
}
|
||||
bool exc() {
|
||||
return _exc;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool _exc;
|
||||
SCARDCONTEXT _id;
|
||||
long _state;
|
||||
};
|
||||
|
||||
bool _exc;
|
||||
SCARDCONTEXT _id;
|
||||
long _state;
|
||||
std::map<std::string, shared_ptr<Reader>::t > _reader;
|
||||
|
||||
//! Readers are closed when the last shared object is destructed
|
||||
std::map<std::string, mrw::Shared<Reader> > _readers;
|
||||
|
||||
//! Connection is closed when the last shared object is destructed
|
||||
/*! Handling the connection lifetime in a separate shared object
|
||||
allows to copy connections and still make sure, that the
|
||||
lifetime of the connection is as long as all copied opbjects
|
||||
live. */
|
||||
mrw::Shared<ConnectionLifetime> _connectionlifetime;
|
||||
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user