libicdlc
library for IC driving license card
|
00001 00051 #include <windows.h> 00052 #include <winscard.h> 00053 00054 #if defined(_MSC_VER) 00055 #pragma comment(lib, "winscard.lib") 00056 #endif 00057 00058 #if defined(_MSC_VER) && 1000 < _MSC_VER 00059 #pragma once 00060 #endif 00061 00062 #ifndef SCARD_9660DA69_9652_40AF_BDB7_8E630C4F5C77_INCLUDE_GUARD 00063 #define SCARD_9660DA69_9652_40AF_BDB7_8E630C4F5C77_INCLUDE_GUARD 00064 00069 class scard 00070 { 00071 typedef TCHAR char_type; 00072 typedef unsigned char uint8_t; 00073 typedef unsigned short uint16_t; 00074 00075 SCARDHANDLE m_handle; 00076 SCARDCONTEXT m_context; 00077 LONG m_last_error; 00078 00079 public: 00080 00082 scard(); 00083 00085 ‾scard(); 00086 00094 bool connect(const char_type * reader_name); 00095 00101 bool disconnect(); 00102 00108 bool connected() const; 00109 00121 template<typename T> 00122 bool transmit(T cb, const uint8_t* data, size_t length); 00123 00129 LONG get_last_error() const; 00130 00140 template<typename T> 00141 static bool enumeration(T cb, bool check_card = false, LONG * result = NULL); 00142 00149 static uint16_t read_status_byte(const void * data, size_t length); 00150 }; 00151 00152 inline 00153 scard::scard() 00154 : m_handle(NULL) 00155 , m_context(NULL) 00156 , m_last_error(0) 00157 { 00158 } 00159 00160 inline 00161 scard::‾scard() 00162 { 00163 disconnect(); 00164 } 00165 00166 inline 00167 bool scard::connect(const char_type * reader_name) 00168 { 00169 DWORD protocol = 0; 00170 00171 disconnect(); 00172 00173 if( !reader_name || !*reader_name ) { 00174 m_last_error = SCARD_E_INVALID_PARAMETER; 00175 return false; 00176 } 00177 00178 00179 m_last_error = ::SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &m_context); 00180 if( SCARD_S_SUCCESS != m_last_error ) { 00181 return false; 00182 } 00183 00184 00185 m_last_error = ::SCardConnect(m_context, reader_name, SCARD_SHARE_SHARED, 00186 SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, &m_handle, &protocol); 00187 if( SCARD_S_SUCCESS != m_last_error ) { 00188 ::SCardReleaseContext(m_context); 00189 m_handle = NULL; 00190 m_context = NULL; 00191 return false; 00192 } 00193 00194 return true; 00195 } 00196 00197 inline 00198 bool scard::disconnect() 00199 { 00200 if( m_handle ) { 00201 m_last_error = ::SCardDisconnect(m_handle, SCARD_LEAVE_CARD); 00202 m_handle = NULL; 00203 } 00204 00205 if( m_context ) { 00206 m_last_error = SCardReleaseContext(m_context); 00207 m_context = NULL; 00208 } 00209 00210 return m_last_error != SCARD_S_SUCCESS; 00211 } 00212 00213 inline 00214 bool scard::connected() const 00215 { 00216 return NULL != m_handle; 00217 } 00218 00219 template<typename T> 00220 inline bool scard::transmit(T cb, const uint8_t* data, size_t length) 00221 { 00222 uint8_t res[2048]; 00223 DWORD cch = sizeof(res); 00224 00225 if( !connected() ) { 00226 m_last_error = SCARD_E_INVALID_HANDLE; 00227 return false; 00228 } 00229 00230 m_last_error = ::SCardTransmit(m_handle, SCARD_PCI_T1, data, 00231 length, NULL, res, &cch); 00232 if( SCARD_S_SUCCESS == m_last_error ) 00233 { 00234 cb(res, cch); 00235 } 00236 00237 return SCARD_S_SUCCESS == m_last_error; 00238 } 00239 00240 inline 00241 LONG scard::get_last_error() const 00242 { 00243 return m_last_error; 00244 } 00245 00246 template<typename T> 00247 inline static bool scard::enumeration(T cb, bool check_card, LONG * result) 00248 { 00249 LONG lr; 00250 SCARDCONTEXT context; 00251 LPTSTR readers, reader; 00252 DWORD cch = SCARD_AUTOALLOCATE; 00253 DWORD protocol = 0; 00254 SCARDHANDLE handle = NULL; 00255 00256 if( !result ) { 00257 result = &lr; 00258 } 00259 00260 00261 *result = ::SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &context); 00262 if( SCARD_S_SUCCESS == *result ) 00263 { 00264 00265 *result = ::SCardListReaders(context, NULL, (LPTSTR)&readers, &cch); 00266 if( SCARD_S_SUCCESS == *result ) 00267 { 00268 for(reader = readers; *reader; reader += _tcslen(reader) + 1 ) 00269 { 00270 if( !check_card ) 00271 { 00272 00273 cb(reader); 00274 } 00275 else 00276 { 00277 00278 *result = ::SCardConnect(context, readers, SCARD_SHARE_SHARED, 00279 SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, &handle, &protocol); 00280 if( SCARD_S_SUCCESS == *result ) { 00281 ::SCardDisconnect(handle, SCARD_LEAVE_CARD); 00282 00283 cb(reader); 00284 } 00285 } 00286 } 00287 00288 ::SCardFreeMemory(context, readers); 00289 } 00290 00291 ::SCardReleaseContext(context); 00292 } 00293 00294 return SCARD_S_SUCCESS == *result; 00295 } 00296 00297 inline 00298 uint16_t scard::read_status_byte(const void * data, size_t length) 00299 { 00300 const uint8_t * data_ = (const uint8_t*)data; 00301 00302 if( length < 2 ) { 00303 return 0xFFFF; 00304 } 00305 00306 return (data_[length - 2] << 8) | data_[length - 1]; 00307 } 00308 00309 00310 #endif