@ -12,7 +12,6 @@
# include <cryptaux.hxx>
# include <mrw/shared.hxx>
# include <string>
# ifdef WIN32
@ -205,7 +204,8 @@ namespace pcsc {
/*! @note Please note that the Reader is required in the
destructor und must therefore live longer than the
Transaction instance . */
Transaction ( mrw : : Shared < Reader > r ) : _reader ( r ) , _running ( true ) {
Transaction ( shared_ptr < Reader > : : t r ) :
_reader ( r ) , _running ( true ) {
CRYPTOLOG ( " log " ) ;
_reader - > beginTransaction ( ) ;
}
@ -222,7 +222,7 @@ namespace pcsc {
_running = false ;
}
private :
mrw : : S hared< Reader > _reader ;
s hared_ptr < Reader > : : t _reader ;
bool _running ;
} ;
@ -424,7 +424,7 @@ namespace pcsc {
friend class Connection ;
//! Establishes a connection to the given named cardreader
Reader ( const std : : string & nm , const Connection & c ,
Reader ( const std : : string & nm , shared_ptr < Connection > : : t c ,
DWORD mode = SCARD_SHARE_SHARED ,
DWORD protocol = SCARD_PROTOCOL_T1 ) :
name ( nm ) , _connection ( c ) {
@ -441,7 +441,7 @@ namespace pcsc {
//...........................................................variables
private :
mrw : : S hared< Connection > _connection ;
s hared_ptr < Connection > : : t _connection ;
SCARDHANDLE _id ;
DWORD _state ;
DWORD _protocol ;
@ -461,160 +461,108 @@ namespace pcsc {
//................................................................methods
public :
//! Opens a connection (establishes a smartcard context)
/*! The errorhandling is defined with the @c exceptions flag:
Using exceptions :
@ code
try {
pcsc : : Connection c ; // standard with exceptions
pcsc : : Connection : : Strings r ( c . scan ( ) ) ;
} catch ( std : : exception & x ) {
std : : cout < < " Error with message: " < < x . what ( ) < < std : : endl ;
}
@ endcode
Without exceptions :
@ code
pcsc : : Connection c ( SYSTEM , false ) ;
if ( ! c ) std : : cout < < " Error with message: " < < c . error ( ) < < std : : endl ;
pcsc : : Connection : : Strings r ( c . scan ( ) ) ;
if ( ! c ) std : : cout < < " Error with message: " < < c . error ( ) < < std : : endl ;
@ endcode
Recommendation : Use exceptions !
@ param s defines the scope of the connection
@ param exceptions
- @ c true : class throws exceptions in case of an error
- @ c false : no exceptions , check your instance after each
operation */
Connection ( Scope s = USER , bool exceptions = true ) :
_connectionlifetime ( connectionlifetime ( s , exceptions ) ) {
+ + connectionlifetimecounter ( ) ;
CRYPTOLOG ( " Connection Counter is now: " < < connectionlifetimecounter ( ) ) ;
check ( " establish smartcard context " ) ;
}
Connection ( const Connection & o ) {
+ + connectionlifetimecounter ( ) ;
* this = o ;
}
//! Closes the connection (releases the smartcard context)
~ Connection ( ) {
// connection is closed, when _connectionlifetime is destructed
if ( - - connectionlifetimecounter ( ) = = 0 ) {
CRYPTOLOG ( " Delete Connection " ) ;
delete connectionlifetime ( ) ;
connectionlifetime ( ) = 0 ;
}
CRYPTOLOG ( " Connection Counter is now: " < < connectionlifetimecounter ( ) ) ;
CRYPTOLOG ( " Close Connection id= " < < _id ) ;
_state = SCardReleaseContext ( _id ) ;
if ( ! std : : uncaught_exception ( ) ) check ( " smartcard release context " ) ;
}
//! Scans for available readers from a specified list of groups.
/*! Defaults to all groups. */
Strings scan ( const Strings & groups = Strings ( ) ) {
static Strings scan ( const Strings & groups = Strings ( ) ,
Scope s = USER , bool exceptions = true ) {
Connection c ( s , exceptions ) ;
Strings res ;
std : : string grp ( join ( groups ) ) ;
std : : string grp ( c . join ( groups ) ) ;
DWORD num ( 0 ) ;
if ( ! check ( SCardListReaders ( _connectionlifetime - > id ( ) ,
groups . size ( ) ? strconv ( grp ) . data ( ) : 0 , 0 ,
& num ) ,
" smartcard get size of readers of groups " + grp ) )
if ( ! c . check ( SCardListReaders ( c . _id ,
groups . size ( ) ? strconv ( grp ) . data ( ) : 0 , 0 ,
& num ) ,
" smartcard get size of readers of groups " + grp ) )
return res ;
CRYPTOLOG ( " size of readers: " < < num ) ;
if ( ! num ) return res ;
std : : auto_ptr < char_t > nm ( new char_t [ num ] ) ;
if ( ! check ( SCardListReaders ( _connectionlifetime - > id ( ) ,
groups . size ( ) ? strconv ( grp ) . data ( ) : 0 ,
nm . get ( ) , & num ) ,
" smartcard list reader names of groups " + grp ) )
if ( ! c . check ( SCardListReaders ( c . _id ,
groups . size ( ) ? strconv ( grp ) . data ( ) : 0 ,
nm . get ( ) , & num ) ,
" smartcard list reader names of groups " + grp ) )
return res ;
CRYPTOLOG ( " got all readers, size is " < < num ) ;
if ( ! num ) return res ;
CRYPTOLOG ( " list of readers: "
< < crypto : : readable ( std : : string ( nm . get ( ) , num - 1 ) ) ) ;
return res = split ( strconv ( string ( nm . get ( ) , num - 1 ) ) ) ;
< < crypto : : readable ( std : : string ( nm . get ( ) , num - 1 ) ) ) ;
return res = c . split ( strconv ( string ( nm . get ( ) , num - 1 ) ) ) ;
}
//! 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 . */
mrw : : Shared < Reader > reader ( const std : : string & name ) {
return _connectionlifetime - > reader ( name , this ) ;
}
// //! Close connection of a named reader.
// /*! If you access the same reader through raeder() later, the
// connection will be reestablished. */
// void close(const std::string& s) {
// }
/// Reset and reestablish the connection.
/** @note You must remove all readers that have been returned by
@ ref reader ( ) , if you have assigned them to a variable
and stored them . Otherwise the connections will remain
open and next access should probably fail .
@ begincode
{
mrw : : Shared < Reader > r ( c . reader ( name ) ) ;
// use r
c . reset ( ) ; // now r is invalid
// either reassign r:
r = c . reader ( name ) ;
// or simply reset it
r . reset ( ) ;
}
// or clenaup by leaving the context of r
@ endcode */
void reset ( ) {
_connectionlifetime - > reset ( ) ;
}
//! Find all readers with a given ATR.
/*! @param atr full or partial ATR to match to the reader's ATR
@ returns list of readers that contain @ c atr in their ATR */
Strings getReadersWithAtr ( const std : : string & atr ) {
static Strings getReadersWithAtr ( const std : : string & atr ,
Scope s = USER , bool exceptions = true ) {
Connection c ( s , exceptions ) ;
Strings res ;
pcsc : : Connection : : Strings readers ( scan ( ) ) ;
pcsc : : Connection : : Strings readers ( c . 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 ( c . 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 {
return * _connectionlifetime ;
//! 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 . */
static shared_ptr < Reader > : : t reader ( const std : : string & name ,
Scope s = USER , bool exceptions = true ) {
CRYPTOLOG ( " get reader: " < < name ) ;
return shared_ptr < Reader > : : t
( new Reader ( name ,
shared_ptr < Connection > : : t
( new Connection ( s , exceptions ) ) ) ) ;
}
//................................................................methods
private :
mrw : : Shared < Reader > newreader ( const std : : string & name ) {
return new Reader ( name , * this ) ;
}
//! 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 , const std : : string & context = " " ) {
_connectionlifetime - > state ( state ) ;
return check ( context ) ;
}
//! Opens a connection (establishes a smartcard context)
/*! The errorhandling is defined with the @c exceptions flag:
//! 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 = " " ) {
return _connectionlifetime - > check ( context ) ;
Using exceptions :
@ code
try {
pcsc : : Connection c ; // standard with exceptions
pcsc : : Connection : : Strings r ( c . scan ( ) ) ;
} catch ( std : : exception & x ) {
std : : cout < < " Error with message: " < < x . what ( ) < < std : : endl ;
}
@ endcode
Without exceptions :
@ code
pcsc : : Connection c ( SYSTEM , false ) ;
if ( ! c ) std : : cout < < " Error with message: " < < c . error ( ) < < std : : endl ;
pcsc : : Connection : : Strings r ( c . scan ( ) ) ;
if ( ! c ) std : : cout < < " Error with message: " < < c . error ( ) < < std : : endl ;
@ endcode
Recommendation : Use exceptions !
@ param s defines the scope of the connection
@ param exceptions
- @ c true : class throws exceptions in case of an error
- @ c false : no exceptions , check your instance after each
operation */
Connection ( Scope s = USER , bool exceptions = true ) :
_exc ( exceptions ) , _id ( 0 ) , _s ( s ) ,
_state ( SCardEstablishContext ( s , 0 , 0 , & _id ) ) {
CRYPTOLOG ( " Open Connection id= " < < _id ) ;
check ( " establish smartcard context " ) ;
}
//! Splits a buffer with 0 separators into a vector of strings.
Strings split ( const std : : string & in ) {
static Strings split ( const std : : string & in ) {
Strings res ;
for ( std : : string : : size_type pos ( 0 ) ; pos < in . size ( ) & & in [ pos ] ! = 0 ;
pos + = res . rbegin ( ) - > size ( ) + 1 )
@ -623,7 +571,7 @@ namespace pcsc {
}
//! Joins a vector of strings into a buffer with 0 separators.
std : : string join ( const Strings & in ) {
static std : : string join ( const Strings & in ) {
std : : string res ;
if ( in . size ( ) ) {
for ( Strings : : const_iterator it ( in . begin ( ) ) ;
@ -634,498 +582,433 @@ namespace pcsc {
return res ;
}
//! Connection id
SCARDCONTEXT id ( ) {
return _connectionlifetime - > id ( ) ;
operator bool ( ) const {
# ifdef WIN32
return ( _state > > 30 & 3 ) = = 0 ;
# else
return _state = = SCARD_S_SUCCESS ;
# endif
}
//! @c true if exceptions are thrown
bool exc ( ) {
return _connectionlifetime - > exc ( ) ;
//! 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 , const std : : string & context = " " ) {
_state = state ;
check ( context ) ;
}
//..............................................................variables
private :
class ConnectionLifetime {
public :
//! opens connection that is closed on destruction
ConnectionLifetime ( Scope s , bool exc ) :
_exc ( exc ) , _id ( 0 ) , _s ( s ) ,
_state ( SCardEstablishContext ( s , 0 , 0 , & _id ) ) {
CRYPTOLOG ( " Open Connection " ) ;
check ( " establish smartcard context " ) ;
}
//! Closes the connection (releases the smartcard context)
~ ConnectionLifetime ( ) {
CRYPTOLOG ( " Close Connection " ) ;
_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
//! 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 ( ) ) {
bool check ( const std : : string & context = " " ) {
if ( _exc & & ! * this ) {
if ( context . size ( ) ) {
# ifdef SCARD_W_WRONG_CHV
if ( _state = = SCARD_W_WRONG_CHV ) {
throw wrong_pin ( context + " : " + error ( ) ) ;
} else {
if ( _state = = SCARD_W_WRONG_CHV ) {
throw wrong_pin ( context + " : " + error ( ) ) ;
} else {
# endif
throw access_error ( context + " : " + error ( ) ) ;
throw access_error ( context + " : " + error ( ) ) ;
# ifdef SCARD_W_WRONG_CHV
}
}
# endif
} else {
} else {
# ifdef SCARD_W_WRONG_CHV
if ( _state = = SCARD_W_WRONG_CHV ) {
throw wrong_pin ( error ( ) ) ;
} else {
if ( _state = = SCARD_W_WRONG_CHV ) {
throw wrong_pin ( error ( ) ) ;
} else {
# endif
throw access_error ( error ( ) ) ;
throw access_error ( error ( ) ) ;
# ifdef SCARD_W_WRONG_CHV
}
# endif
}
}
return * this ;
# endif
}
//! Get the describing text of the last error
std : : string error ( ) const {
std : : stringstream ss ;
switch ( _state ) {
}
return * this ;
}
//! Get the describing text of the last error
std : : string error ( ) const {
std : : stringstream ss ;
switch ( _state ) {
# ifdef SCARD_E_CANCELLED
case SCARD_E_CANCELLED :
ss < < " The action was canceled by an SCardCancel request. " ;
break ;
case SCARD_E_CANCELLED :
ss < < " The action was canceled by an SCardCancel request. " ;
break ;
# endif
# ifdef SCARD_E_CANT_DISPOSE
case SCARD_E_CANT_DISPOSE :
ss < < " The system could not dispose of the media in the requested "
< < " manner. " ;
break ;
case SCARD_E_CANT_DISPOSE :
ss < < " The system could not dispose of the media in the requested "
< < " manner. " ;
break ;
# endif
# ifdef SCARD_E_CARD_UNSUPPORTED
case SCARD_E_CARD_UNSUPPORTED :
ss < < " The smart card does not meet minimal requirements for "
< < " support. " ;
break ;
case SCARD_E_CARD_UNSUPPORTED :
ss < < " The smart card does not meet minimal requirements for "
< < " support. " ;
break ;
# endif
# ifdef SCARD_E_DUPLICATE_READER
case SCARD_E_DUPLICATE_READER :
ss < < " The reader driver did not produce a unique reader name. " ;
break ;
case SCARD_E_DUPLICATE_READER :
ss < < " The reader driver did not produce a unique reader name. " ;
break ;
# endif
# ifdef SCARD_E_INSUFFICIENT_BUFFER
case SCARD_E_INSUFFICIENT_BUFFER :
ss < < " The data buffer for returned data is too small for the "
< < " returned data. " ;
break ;
case SCARD_E_INSUFFICIENT_BUFFER :
ss < < " The data buffer for returned data is too small for the "
< < " returned data. " ;
break ;
# endif
# ifdef SCARD_E_INVALID_ATR
case SCARD_E_INVALID_ATR :
ss < < " An ATR string obtained from the registry is not a valid "
< < " ATR string. " ;
break ;
case SCARD_E_INVALID_ATR :
ss < < " An ATR string obtained from the registry is not a valid "
< < " ATR string. " ;
break ;
# endif
# ifdef SCARD_E_INVALID_HANDLE
case SCARD_E_INVALID_HANDLE :
ss < < " The supplied handle was not valid. " ;
break ;
case SCARD_E_INVALID_HANDLE :
ss < < " The supplied handle was not valid. " ;
break ;
# endif
# ifdef SCARD_E_INVALID_PARAMETER
case SCARD_E_INVALID_PARAMETER :
ss < < " One or more of the supplied parameters could not be properly "
< < " interpreted. " ;
break ;
case SCARD_E_INVALID_PARAMETER :
ss < < " One or more of the supplied parameters could not be properly "
< < " interpreted. " ;
break ;
# endif
# ifdef SCARD_E_INVALID_TARGET
case SCARD_E_INVALID_TARGET :
ss < < " Registry startup information is missing or not valid. " ;
break ;
case SCARD_E_INVALID_TARGET :
ss < < " Registry startup information is missing or not valid. " ;
break ;
# endif
# ifdef SCARD_E_INVALID_VALUE
case SCARD_E_INVALID_VALUE :
ss < < " One or more of the supplied parameters values could not "
< < " be properly interpreted. " ;
break ;
case SCARD_E_INVALID_VALUE :
ss < < " One or more of the supplied parameters values could not "
< < " be properly interpreted. " ;
break ;
# endif
# ifdef SCARD_E_NOT_READY
case SCARD_E_NOT_READY :
ss < < " The reader or smart card is not ready to accept commands. " ;
break ;
case SCARD_E_NOT_READY :
ss < < " The reader or smart card is not ready to accept commands. " ;
break ;
# endif
# ifdef SCARD_E_NOT_TRANSACTED
case SCARD_E_NOT_TRANSACTED :
ss < < " An attempt was made to end a nonexistent transaction. " ;
break ;
case SCARD_E_NOT_TRANSACTED :
ss < < " An attempt was made to end a nonexistent transaction. " ;
break ;
# endif
# ifdef SCARD_E_NO_MEMORY
case SCARD_E_NO_MEMORY :
ss < < " Not enough memory available to complete this command. " ;
break ;
case SCARD_E_NO_MEMORY :
ss < < " Not enough memory available to complete this command. " ;
break ;
# endif
# ifdef SCARD_E_NO_SERVICE
case SCARD_E_NO_SERVICE :
ss < < " The smart card resource manager is not running. " ;
break ;
case SCARD_E_NO_SERVICE :
ss < < " The smart card resource manager is not running. " ;
break ;
# endif
# ifdef SCARD_E_NO_SMARTCARD
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_NO_SMARTCARD :
ss < < " The operation requires a smart card, but no smart card "
< < " is currently in the device. " ;
break ;
# endif
# ifdef SCARD_E_PCI_TOO_SMALL
case SCARD_E_PCI_TOO_SMALL :
ss < < " The PCI receive buffer was too small. " ;
break ;
case SCARD_E_PCI_TOO_SMALL :
ss < < " The PCI receive buffer was too small. " ;
break ;
# endif
# ifdef SCARD_E_PROTO_MISMATCH
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_PROTO_MISMATCH :
ss < < " The requested protocols are incompatible with the protocol "
< < " currently in use with the smart card. " ;
break ;
# endif
# ifdef SCARD_E_READER_UNAVAILABLE
case SCARD_E_READER_UNAVAILABLE :
ss < < " The specified reader is not currently available for use. " ;
break ;
case SCARD_E_READER_UNAVAILABLE :
ss < < " The specified reader is not currently available for use. " ;
break ;
# endif
# ifdef SCARD_E_READER_UNSUPPORTED
case SCARD_E_READER_UNSUPPORTED :
ss < < " The reader driver does not meet minimal requirements for "
< < " support. " ;
break ;
case SCARD_E_READER_UNSUPPORTED :
ss < < " The reader driver does not meet minimal requirements for "
< < " support. " ;
break ;
# endif
# ifdef SCARD_E_SERVICE_STOPPED
case SCARD_E_SERVICE_STOPPED :
ss < < " The smart card resource manager has shut down. " ;
break ;
case SCARD_E_SERVICE_STOPPED :
ss < < " The smart card resource manager has shut down. " ;
break ;
# endif
# ifdef SCARD_E_SHARING_VIOLATION
case SCARD_E_SHARING_VIOLATION :
ss < < " The smart card cannot be accessed because of other "
< < " outstanding connections. " ;
break ;
case SCARD_E_SHARING_VIOLATION :
ss < < " The smart card cannot be accessed because of other "
< < " outstanding connections. " ;
break ;
# endif
# ifdef SCARD_E_SYSTEM_CANCELLED
case SCARD_E_SYSTEM_CANCELLED :
ss < < " The action was cancelled by the system, presumably to log "
< < " off or shut down. " ;
break ;
case SCARD_E_SYSTEM_CANCELLED :
ss < < " The action was cancelled by the system, presumably to log "
< < " off or shut down. " ;
break ;
# endif
# ifdef SCARD_E_TIMEOUT
case SCARD_E_TIMEOUT :
ss < < " The user-specified time-out value has expired. " ;
break ;
case SCARD_E_TIMEOUT :
ss < < " The user-specified time-out value has expired. " ;
break ;
# endif
# ifdef SCARD_E_UNKNOWN_CARD
case SCARD_E_UNKNOWN_CARD :
ss < < " The specified smart card name is not recognized. " ;
break ;
case SCARD_E_UNKNOWN_CARD :
ss < < " The specified smart card name is not recognized. " ;
break ;
# endif
# ifdef SCARD_E_UNKNOWN_READER
case SCARD_E_UNKNOWN_READER :
ss < < " The specified reader name is not recognized. " ;
break ;
case SCARD_E_UNKNOWN_READER :
ss < < " The specified reader name is not recognized. " ;
break ;
# endif
# ifdef SCARD_F_COMM_ERROR
case SCARD_F_COMM_ERROR :
ss < < " An internal communications error has been detected. " ;
break ;
case SCARD_F_COMM_ERROR :
ss < < " An internal communications error has been detected. " ;
break ;
# endif
# ifdef SCARD_F_INTERNAL_ERROR
case SCARD_F_INTERNAL_ERROR :
ss < < " An internal consistency check failed. " ;
break ;
case SCARD_F_INTERNAL_ERROR :
ss < < " An internal consistency check failed. " ;
break ;
# endif
# ifdef SCARD_F_UNKNOWN_ERROR
case SCARD_F_UNKNOWN_ERROR :
ss < < " An internal error has been detected, but the source is "
< < " unknown. " ;
break ;
case SCARD_F_UNKNOWN_ERROR :
ss < < " An internal error has been detected, but the source is "
< < " unknown. " ;
break ;
# endif
# ifdef SCARD_F_WAITED_TOO_LONG
case SCARD_F_WAITED_TOO_LONG :
ss < < " An internal consistency timer has expired. " ;
break ;
case SCARD_F_WAITED_TOO_LONG :
ss < < " An internal consistency timer has expired. " ;
break ;
# endif
# ifdef SCARD_S_SUCCESS
case SCARD_S_SUCCESS :
ss < < " No error was encountered. " ;
break ;
case SCARD_S_SUCCESS :
ss < < " No error was encountered. " ;
break ;
# endif
# ifdef SCARD_W_REMOVED_CARD
case SCARD_W_REMOVED_CARD :
ss < < " The smart card has been removed, so that further "
< < " communication is not possible. " ;
break ;
case SCARD_W_REMOVED_CARD :
ss < < " The smart card has been removed, so that further "
< < " communication is not possible. " ;
break ;
# endif
# ifdef SCARD_W_RESET_CARD
case SCARD_W_RESET_CARD :
ss < < " The smart card was reset. " ;
break ;
case SCARD_W_RESET_CARD :
ss < < " The smart card was reset. " ;
break ;
# endif
# ifdef SCARD_W_UNPOWERED_CARD
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_UNPOWERED_CARD :
ss < < " Power has been removed from the smart card, so that "
< < " further communication is not possible. " ;
break ;
# endif
# ifdef SCARD_W_UNRESPONSIVE_CARD
case SCARD_W_UNRESPONSIVE_CARD :
ss < < " The smart card is not responding to a reset. " ;
break ;
case SCARD_W_UNRESPONSIVE_CARD :
ss < < " The smart card is not responding to a reset. " ;
break ;
# endif
# ifdef SCARD_W_UNSUPPORTED_CARD
case SCARD_W_UNSUPPORTED_CARD :
ss < < " The reader cannot communicate with the smart card, "
< < " due to ATR configuration conflicts. " ;
break ;
case SCARD_W_UNSUPPORTED_CARD :
ss < < " The reader cannot communicate with the smart card, "
< < " due to ATR configuration conflicts. " ;
break ;
# endif
# ifdef SCARD_E_NO_READERS_AVAILABLE
case SCARD_E_NO_READERS_AVAILABLE :
ss < < " No smart card reader is available. " ;
break ;
case SCARD_E_NO_READERS_AVAILABLE :
ss < < " No smart card reader is available. " ;
break ;
# endif
# ifdef ERROR_BROKEN_PIPE
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 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 ;
# endif
# ifdef SCARD_E_BAD_SEEK
case SCARD_E_BAD_SEEK :
ss < < " There was an error trying to set the smart card file "
< < " object pointer. " ;
break ;
case SCARD_E_BAD_SEEK :
ss < < " There was an error trying to set the smart card file "
< < " object pointer. " ;
break ;
# endif
# ifdef SCARD_E_CERTIFICATE_UNAVAILABLE
case SCARD_E_CERTIFICATE_UNAVAILABLE :
ss < < " The requested certificate could not be obtained. " ;
break ;
case SCARD_E_CERTIFICATE_UNAVAILABLE :
ss < < " The requested certificate could not be obtained. " ;
break ;
# endif
# ifdef SCARD_E_COMM_DATA_LOST
case SCARD_E_COMM_DATA_LOST :
ss < < " A communications error with the smart card has been detected. " ;
break ;
case SCARD_E_COMM_DATA_LOST :
ss < < " A communications error with the smart card has been detected. " ;
break ;
# endif
# ifdef SCARD_E_DIR_NOT_FOUND
case SCARD_E_DIR_NOT_FOUND :
ss < < " The specified directory does not exist in the smart card. " ;
break ;
case SCARD_E_DIR_NOT_FOUND :
ss < < " The specified directory does not exist in the smart card. " ;
break ;
# endif
# ifdef SCARD_E_FILE_NOT_FOUND
case SCARD_E_FILE_NOT_FOUND :
ss < < " The specified file 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 ;
# endif
# ifdef SCARD_E_ICC_CREATEORDER
case SCARD_E_ICC_CREATEORDER :
ss < < " The requested order of object creation is not supported. " ;
break ;
case SCARD_E_ICC_CREATEORDER :
ss < < " The requested order of object creation is not supported. " ;
break ;
# endif
# ifdef SCARD_E_ICC_INSTALLATION
case SCARD_E_ICC_INSTALLATION :
ss < < " No primary provider can be found for the smart card. " ;
break ;
case SCARD_E_ICC_INSTALLATION :
ss < < " No primary provider can be found for the smart card. " ;
break ;
# endif
# ifdef SCARD_E_INVALID_CHV
case SCARD_E_INVALID_CHV :
ss < < " The supplied PIN is incorrect. " ;
break ;
case SCARD_E_INVALID_CHV :
ss < < " The supplied PIN is incorrect. " ;
break ;
# endif
# ifdef SCARD_E_NO_ACCESS
case SCARD_E_NO_ACCESS :
ss < < " Access is denied to this file. " ;
break ;
case SCARD_E_NO_ACCESS :
ss < < " Access is denied to this file. " ;
break ;
# endif
# ifdef SCARD_E_NO_DIR
case SCARD_E_NO_DIR :
ss < < " The supplied path does not represent a smart card directory. " ;
break ;
case SCARD_E_NO_DIR :
ss < < " The supplied path does not represent a smart card directory. " ;
break ;
# endif
# ifdef SCARD_E_NO_FILE
case SCARD_E_NO_FILE :
ss < < " The supplied path does not represent a smart card file. " ;
break ;
case SCARD_E_NO_FILE :
ss < < " The supplied path does not represent a smart card file. " ;
break ;
# endif
# ifdef SCARD_E_NO_KEY_CONTAINER
case SCARD_E_NO_KEY_CONTAINER :
ss < < " The requested key container does not exist on the smart card. " ;
break ;
case SCARD_E_NO_KEY_CONTAINER :
ss < < " The requested key container does not exist on the smart card. " ;
break ;
# endif
# ifdef SCARD_E_NO_SUCH_CERTIFICATE
case SCARD_E_NO_SUCH_CERTIFICATE :
ss < < " The requested certificate does not exist. " ;
break ;
case SCARD_E_NO_SUCH_CERTIFICATE :
ss < < " The requested certificate does not exist. " ;
break ;
# endif
# ifdef SCARD_E_SERVER_TOO_BUSY
case SCARD_E_SERVER_TOO_BUSY :
ss < < " The Smart card resource manager is too busy to complete this "
< < " operation. " ;
break ;
case SCARD_E_SERVER_TOO_BUSY :
ss < < " The Smart card resource manager is too busy to complete this "
< < " operation. " ;
break ;
# endif
# ifdef SCARD_E_UNSUPPORTED_FEATURE
case SCARD_E_UNSUPPORTED_FEATURE :
ss < < " This smart card does not support the requested feature. " ;
break ;
case SCARD_E_UNSUPPORTED_FEATURE :
ss < < " This smart card does not support the requested feature. " ;
break ;
# else
# ifdef SCARD_E_UNEXPECTED
case SCARD_E_UNEXPECTED :
ss < < " An unexpected card error has occurred. " ;
break ;
case SCARD_E_UNEXPECTED :
ss < < " An unexpected card error has occurred. " ;
break ;
# endif
# endif
# ifdef SCARD_E_UNKNOWN_RES_MNG
case SCARD_E_UNKNOWN_RES_MNG :
ss < < " An unrecognized error code was returned from a layered "
< < " component. " ;
break ;
case SCARD_E_UNKNOWN_RES_MNG :
ss < < " An unrecognized error code was returned from a layered "
< < " component. " ;
break ;
# endif
# ifdef SCARD_E_WRITE_TOO_MANY
case SCARD_E_WRITE_TOO_MANY :
ss < < " The smartcard does not have enough memory to store the "
< < " information. " ;
break ;
case SCARD_E_WRITE_TOO_MANY :
ss < < " The smartcard does not have enough memory to store the "
< < " information. " ;
break ;
# endif
# ifdef SCARD_P_SHUTDOWN
case SCARD_P_SHUTDOWN :
ss < < " The operation has been aborted to allow the server application "
< < " to exit. " ;
break ;
case SCARD_P_SHUTDOWN :
ss < < " The operation has been aborted to allow the server application "
< < " to exit. " ;
break ;
# endif
# ifdef SCARD_W_CANCELLED_BY_USER
case SCARD_W_CANCELLED_BY_USER :
ss < < " The action was cancelled by the user. " ;
break ;
case SCARD_W_CANCELLED_BY_USER :
ss < < " The action was cancelled by the user. " ;
break ;
# endif
# ifdef SCARD_W_CARD_NOT_AUTHENTICATED
case SCARD_W_CARD_NOT_AUTHENTICATED :
ss < < " No PIN was presented to the smart card. " ;
break ;
case SCARD_W_CARD_NOT_AUTHENTICATED :
ss < < " No PIN was presented to the smart card. " ;
break ;
# endif
# ifdef SCARD_W_CHV_BLOCKED
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_CHV_BLOCKED :
ss < < " The card cannot be accessed because the maximum number "
< < " of PIN entry attempts has been reached. " ;
break ;
# endif
# ifdef SCARD_W_EOF
case SCARD_W_EOF :
ss < < " The end of the smart card file has been reached. " ;
break ;
case SCARD_W_EOF :
ss < < " The end of the smart card file has been reached. " ;
break ;
# endif
# ifdef SCARD_W_SECURITY_VIOLATION
case SCARD_W_SECURITY_VIOLATION :
ss < < " Access was denied because of a security violation. " ;
break ;
case SCARD_W_SECURITY_VIOLATION :
ss < < " Access was denied because of a security violation. " ;
break ;
# endif
# ifdef SCARD_W_WRONG_CHV
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 ) ;
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 " ;
}
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 ;
}
//! 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 . */
mrw : : Shared < Reader > reader ( const std : : string & name , Connection * c ) {
CRYPTOLOG ( " get reader: " < < name < < " from " < < ( void * ) & _readers ) ;
if ( _readers . find ( name ) = = _readers . end ( ) )
_readers . insert ( std : : make_pair ( name , c - > newreader ( name ) ) ) ;
return _readers . find ( name ) - > second ;
}
/// Cleans up the readers, resets the context.
void reset ( ) {
_readers . clear ( ) ;
_state = SCardReleaseContext ( _id ) ;
check ( " smartcard release context " ) ;
_state = SCardEstablishContext ( _s , 0 , 0 , & _id ) ;
check ( " establish smartcard context " ) ;
}
private :
bool _exc ;
SCARDCONTEXT _id ;
Scope _s ;
long _state ;
//! 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 . */
static ConnectionLifetime * &
connectionlifetime ( Scope s = USER , bool exc = true ) {
static ConnectionLifetime * instance ( 0 ) ;
if ( instance = = 0 ) {
CRYPTOLOG ( " New Connection " ) ;
instance = new ConnectionLifetime ( s , exc ) ;
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 instance ;
return ss . str ( ) ;
}
static int & connectionlifetimecounter ( ) {
static int instance ( 0 ) ;
return instance ;
//! 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 :
ConnectionLifetime * _connectionlifetime ;
bool _exc ;
SCARDCONTEXT _id ;
Scope _s ;
long _state ;
} ;