libicdlc
library for IC driving license card

libicdlc/scard.hpp

説明を見る。
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
 全て クラス ファイル 関数 変数 マクロ定義