Removed SCardCancelTransaction completely; Added neesting counter; refs #8
This commit is contained in:
77
src/pcsc.hxx
77
src/pcsc.hxx
@@ -143,6 +143,13 @@ namespace pcsc {
|
||||
runtime_error(const std::string& reason, const std::string& data) throw():
|
||||
exception("runtime error,\n"+reason+":\n"+crypto::hex(data)) {}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class neesting_error: public exception {
|
||||
public:
|
||||
neesting_error() throw():
|
||||
exception("neesting error: more endTransaction than beginTransaction")
|
||||
{}
|
||||
};
|
||||
//@}
|
||||
|
||||
//! @addtogroup pcsclib
|
||||
@@ -165,25 +172,26 @@ namespace pcsc {
|
||||
friend class Transaction;
|
||||
//! Scoped transaction.
|
||||
/*! This is a scoped transaction. That means, the
|
||||
transaction is started in the constructor and cancelled
|
||||
in the destructor, unless it is committed before. That
|
||||
means: If you commit the transaction, it is executed. If
|
||||
you leave the code block unexpectedly, i.e. through an
|
||||
exception, the transaction is cancelled.
|
||||
transaction is started in the constructor and ended in
|
||||
the destructor, unless it is already ended before. In
|
||||
case of an exception or leaving the block, the
|
||||
transaction is always cleaned up.
|
||||
|
||||
There's a neesting counter to make sure, transaction is
|
||||
started only once and ended only once, even though the
|
||||
locking can be neested.
|
||||
|
||||
@code
|
||||
pcsc::Connection c;
|
||||
{
|
||||
Transaction t(c.reader("name"));
|
||||
[...] // do some stuff, possible exceptions thrown
|
||||
if (problem) return; // automatically cancelled
|
||||
if (problem) return; // automatically ended
|
||||
[...]
|
||||
t.commit(); // commit if we reach this line
|
||||
} // cancelled, unless commit reaced
|
||||
@endcode
|
||||
|
||||
@note Micro$oft QinSCard does not know cancel, therefore
|
||||
on Windoze cancel is replaced by commit. */
|
||||
t.end(); // ended if we reach this line
|
||||
[...]
|
||||
} // also ended, unless commit reaced
|
||||
@endcode */
|
||||
class Transaction {
|
||||
public:
|
||||
//! Begins a transaction.
|
||||
@@ -195,18 +203,13 @@ namespace pcsc {
|
||||
}
|
||||
//! Cancels the transaction if not yet finished.
|
||||
~Transaction() try {
|
||||
cancel();
|
||||
end();
|
||||
} catch (...) {
|
||||
if (!std::uncaught_exception()) throw;
|
||||
}
|
||||
//! Ends (commits) the running transaction.
|
||||
void commit() {
|
||||
if (_running) _reader.commitTransaction();
|
||||
_running = false;
|
||||
}
|
||||
//! Cancels the running transaction.
|
||||
void cancel() {
|
||||
if (_running) _reader.cancelTransaction();
|
||||
//! Ends the running transaction.
|
||||
void end() {
|
||||
if (_running) _reader.endTransaction();
|
||||
_running = false;
|
||||
}
|
||||
private:
|
||||
@@ -348,25 +351,26 @@ namespace pcsc {
|
||||
private:
|
||||
|
||||
//! Use scoped transactions with @ref Transaction
|
||||
/*! Calls @c SCardBeginTransaction unless it's already inside
|
||||
a transaction. */
|
||||
void beginTransaction() {
|
||||
check(SCardBeginTransaction(_id), "smartcard begin transaction");
|
||||
if (++_neesting==1)
|
||||
check(SCardBeginTransaction(_id), "smartcard begin transaction");
|
||||
}
|
||||
|
||||
//! Use scoped transactions with @ref Transaction
|
||||
void commitTransaction() {
|
||||
check(SCardEndTransaction(_id, SCARD_LEAVE_CARD),
|
||||
"smartcard end transaction");
|
||||
}
|
||||
|
||||
//! Use scoped transactions with @ref Transaction
|
||||
/*! @note Micro$oft QinSCard does not know cancel, therefore
|
||||
on Windoze cancel is replaced by commit. */
|
||||
void cancelTransaction() {
|
||||
#ifndef WIN32
|
||||
check(SCardCancelTransaction(_id), "smartcard cancel transaction");
|
||||
#endif
|
||||
check(SCardEndTransaction(_id, SCARD_LEAVE_CARD),
|
||||
"smartcard end transaction");
|
||||
/*! Calls @c SCardEndTransaction if it's inside a transaction.
|
||||
|
||||
@throws neesting_error if there are more calls to @c
|
||||
endTransaction than to @c beginTransaction. */
|
||||
void endTransaction() {
|
||||
if (--_neesting==0)
|
||||
check(SCardEndTransaction(_id, SCARD_LEAVE_CARD),
|
||||
"smartcard end transaction");
|
||||
else if (_neesting<0) {
|
||||
_neesting = 0;
|
||||
throw neesting_error();
|
||||
}
|
||||
}
|
||||
|
||||
/*! @throw not_implemented if _protocol is unknown. */
|
||||
@@ -414,6 +418,7 @@ namespace pcsc {
|
||||
SCARDHANDLE _id;
|
||||
DWORD _state;
|
||||
DWORD _protocol;
|
||||
static int _neesting;
|
||||
|
||||
};
|
||||
//------------------------------------------------------------------Reader
|
||||
|
Reference in New Issue
Block a user