Removed SCardCancelTransaction completely; Added neesting counter; refs #8
This commit is contained in:
		| @@ -7,9 +7,13 @@ | ||||
|  | ||||
| include_HEADERS = pcsc.hxx cryptoki.hxx openssl.hxx cryptaux.hxx | ||||
|  | ||||
| if !MINGW32 | ||||
| if MAC | ||||
| AM_CPPFLAGS += -I/opt/local/include -I/Library/OpenSC/include | ||||
| AM_LDFLAGS = -F/System/Library/Frameworks/PCSC.framework -L/opt/local/lib | ||||
| else | ||||
| AM_CPPFLAGS += -I/usr/include/PCSC | ||||
| endif | ||||
| endif | ||||
|  | ||||
| pkcs11dir = ${includedir}/pkcs11 | ||||
| @@ -24,7 +28,7 @@ EXTRA_DIST = $(pkgconfig_DATA).in $(shell ls -1 *.doc) | ||||
|  | ||||
| lib_LTLIBRARIES = libcryptoki++.la | ||||
|  | ||||
| libcryptoki___la_SOURCES = cryptoki.cxx cryptoki.hxx version.cxx | ||||
| libcryptoki___la_SOURCES = cryptoki.cxx cryptoki.hxx pcsc.cxx version.cxx | ||||
| libcryptoki___la_LIBADD = -lssl | ||||
| if !MINGW32 | ||||
| if !MAC | ||||
|   | ||||
							
								
								
									
										10
									
								
								src/pcsc.cxx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/pcsc.cxx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| /*! @file | ||||
|  | ||||
|     @id $Id$ | ||||
| */ | ||||
| //       1         2         3         4         5         6         7         8 | ||||
| // 45678901234567890123456789012345678901234567890123456789012345678901234567890 | ||||
|  | ||||
| #include <pcsc.hxx> | ||||
|  | ||||
| int pcsc::Connection::Reader::_neesting(0); | ||||
							
								
								
									
										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