[SmartcardServices-Changes] [144] trunk/SmartCardServices/src/PKCS11dotNetV2
source_changes at macosforge.org
source_changes at macosforge.org
Mon Feb 20 06:41:40 PST 2012
Revision: 144
http://trac.macosforge.org/projects/smartcardservices/changeset/144
Author: ludovic.rousseau at gmail.com
Date: 2012-02-20 06:41:36 -0800 (Mon, 20 Feb 2012)
Log Message:
-----------
Add missing files
Added Paths:
-----------
trunk/SmartCardServices/src/PKCS11dotNetV2/DeviceMonitor.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/DeviceMonitor.hpp
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/DeviceMonitor.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/DeviceMonitor.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/DeviceMonitor.cpp 2012-02-20 14:41:36 UTC (rev 144)
@@ -0,0 +1,1275 @@
+/*
+* PKCS#11 library for .Net smart cards
+* Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*
+*/
+
+
+#include <memory>
+#include <boost/foreach.hpp>
+#include <boost/mem_fn.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <vector>
+#include <string>
+#include "Log.hpp"
+#include "DeviceMonitor.hpp"
+
+#ifdef MACOSX_LEOPARD
+#define SCardIsValidContext(x) SCARD_S_SUCCESS
+#endif
+
+extern boost::mutex io_mutex;
+
+extern boost::condition_variable g_WaitForSlotEventCondition;
+
+extern boost::mutex g_WaitForSlotEventMutex;
+
+extern bool g_bWaitForSlotEvent;
+
+const BYTE g_DotNetSmartCardAtr[ ] = { 0x3b, 0x16, 0x96, 0x41, 0x73, 0x74, 0x72, 0x69, 0x64 };
+
+SCARDCONTEXT DeviceMonitor::m_hContext = 0;
+
+bool DeviceMonitor::m_bStopPolling = false;
+
+bool DeviceMonitor::m_bAlive = false;
+
+boost::condition_variable g_WaitForDeviceMonitorThreadCondition;
+
+boost::mutex g_WaitForDeviceMonitorThreadMutex;
+
+
+/*
+*/
+DeviceMonitor::DeviceMonitor( ) {
+
+ m_stEmptyDevice = "empty";
+
+ unsigned char ucDeviceID = 0;
+
+ BOOST_FOREACH( boost::shared_ptr< Device >& d, m_aDevices ) {
+
+ SCARD_READERSTATE s;
+
+ memset( &s, 0, sizeof( SCARD_READERSTATE ) );
+
+ s.szReader = m_stEmptyDevice.c_str( );
+
+ s.dwCurrentState = SCARD_STATE_EMPTY;
+
+ s.dwEventState = SCARD_STATE_EMPTY;
+
+ d.reset( new Device( s, ucDeviceID ) );
+
+ ++ucDeviceID;
+ }
+}
+
+
+/* Spy reader insertion/removal
+*/
+void DeviceMonitor::getDevicesStates( const SCARDCONTEXT& h ) {
+
+ long rv = SCardIsValidContext( h );
+
+ if( SCARD_S_SUCCESS != rv ) {
+
+ return;
+ }
+
+ // Get the name of all the connected devices
+ std::vector< std::string > vDevices;
+
+ vDevices.reserve( g_iMaxReader );
+
+ vDevices.clear( );
+
+ getDevicesList( h, vDevices );
+
+ // Build an SCARD_READERSTATE array for all seen devices
+ SCARD_READERSTATE aReaderStates[ g_iMaxReader ];
+
+ memset( aReaderStates, 0, sizeof( aReaderStates ) );
+
+ unsigned char j = 0;
+
+ size_t m = vDevices.size( );
+
+ BOOST_FOREACH( SCARD_READERSTATE &scr, aReaderStates ) {
+
+ memset( &scr, 0, sizeof( SCARD_READERSTATE ) );
+
+ if( j < m ) {
+
+ aReaderStates[ j ].szReader = vDevices.at( j ).c_str( );
+
+ ++j;
+
+ } else {
+
+ break;
+ }
+ }
+
+ // Query the status for all known devices
+ rv = SCardGetStatusChange( h, 100, &aReaderStates[ 0 ], j );
+
+ if( SCARD_S_SUCCESS != rv ) {
+
+ Log::log( "DeviceMonitor::getDevicesStates - SCardGetStatusChange <%#02x>", rv );
+ }
+
+ if( ( SCARD_W_REMOVED_CARD == rv ) || ( SCARD_W_RESET_CARD == rv ) ) {
+
+ DWORD dwActiveProtocol = SCARD_PROTOCOL_T0;
+
+ rv = SCardReconnect( h, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_LEAVE_CARD, &dwActiveProtocol );
+
+ if( SCARD_S_SUCCESS != rv ) {
+
+ Log::log( "DeviceMonitor::getDevicesStates - SCardReconnect <%#02x>", rv );
+
+ } else {
+
+ rv = SCardGetStatusChange( h, 100, &aReaderStates[ 0 ], j );
+ }
+ }
+
+ // Create inner device objects
+ j = 0;
+
+ BOOST_FOREACH( SCARD_READERSTATE &scr, aReaderStates ) {
+
+ // If he reader exists
+ if( scr.szReader ) {
+
+ scr.dwCurrentState = scr.dwEventState;
+
+ addReader( scr, j );
+ }
+
+ ++j;
+ }
+}
+
+
+/*
+*/
+void DeviceMonitor::getDevicesList( const SCARDCONTEXT& h, std::vector< std::string >& a_DeviceList ) {
+
+ long rv = SCardIsValidContext( h );
+
+ if( SCARD_S_SUCCESS != rv ) {
+
+ return;
+ }
+
+ a_DeviceList.clear( );
+
+ // Get the device list from the PCSC layer
+ //LPSTR pszReaders = NULL;
+ if ( m_bStopPolling ) {
+
+ // If the library has been unloaded the thread must stopped right now
+ return;
+ }
+ /*
+ #ifdef SCARD_AUTOALLOCATE
+ DWORD dwReaders = SCARD_AUTOALLOCATE;
+
+ LONG rv = SCardListReaders( h, NULL, (LPSTR)&pszReaders, &dwReaders );
+
+ if( SCARD_S_SUCCESS != rv )
+ {
+ Log::log( "DeviceMonitor::getDevicesList - SCardListReaders <%#02x>", rv );
+
+ SCardFreeMemory( h, pszReaders );
+
+ if( ( SCARD_W_REMOVED_CARD == rv ) || ( SCARD_W_RESET_CARD == rv ) ) {
+
+ DWORD dwActiveProtocol = 0;
+
+ rv = SCardReconnect( h, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_LEAVE_CARD, &dwActiveProtocol );
+
+ if( SCARD_S_SUCCESS != rv ) {
+
+ Log::log( "DeviceMonitor::getDevicesList - SCardReconnect <%#02x>", rv );
+ return;
+ }
+
+ rv = SCardListReaders( h, NULL, (LPSTR)&pszReaders, &dwReaders );
+
+ if( SCARD_S_SUCCESS != rv ) {
+
+ Log::log( "DeviceMonitor::getDevicesList - SCardListReaders (2) <%#02x>", rv );
+ SCardFreeMemory( h, pszReaders );
+
+ return;
+ }
+
+ } else {
+
+ return;
+ }
+ }
+ #else
+ */
+ DWORD dwReaders = 0;
+ rv = SCardListReaders( h, NULL, NULL, &dwReaders );
+
+ if( SCARD_S_SUCCESS != rv ) {
+
+ if( ( SCARD_W_REMOVED_CARD == rv ) || ( SCARD_W_RESET_CARD == rv ) ) {
+
+ DWORD dwActiveProtocol = 0;
+
+ rv = SCardReconnect( h, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_LEAVE_CARD, &dwActiveProtocol );
+
+ if( SCARD_S_SUCCESS != rv ) {
+
+ return;
+ }
+
+ rv = SCardListReaders( h, NULL, NULL, &dwReaders );
+
+ if( SCARD_S_SUCCESS != rv ) {
+
+ return;
+ }
+
+ } else {
+
+ return;
+ }
+ }
+
+ std::auto_ptr< char > pszReaders( new char[ dwReaders ] );
+ memset( pszReaders.get( ), 0, dwReaders );
+ //pszReaders = (char *)malloc(dwReaders);
+
+ rv = SCardListReaders( h, NULL, pszReaders.get( ), &dwReaders);
+ //#endif
+
+ // Construct the PCSC device list
+ LPSTR pReader = pszReaders.get( );
+
+ while( pReader && ( '\0' != *pReader ) )
+ {
+ std::string s( pReader );
+
+ std::vector< std::string >::iterator i = a_DeviceList.begin( );
+
+ a_DeviceList.insert( i, s );
+
+ // Advance to the next value
+ size_t readerNameLen = s.length( );
+
+ pReader = ( pReader + readerNameLen + 1 );
+ }
+
+ //#ifdef SCARD_AUTOALLOCATE
+ // SCardFreeMemory( h, pszReaders );
+ //#else
+ //free(pszReaders);
+ //#endif
+}
+
+
+/*
+*/
+void DeviceMonitor::getReader( SCARD_READERSTATE& scr ) {
+
+ BOOST_FOREACH( boost::shared_ptr< Device >& d, m_aDevices ) {
+
+ if( d.get( ) && ( 0 == d->getReaderName( ).compare( scr.szReader ) ) ) {
+
+ //Log::log( " ===> Update reader <%s>\n", scr.szReader );
+
+ d->put( scr );
+
+ return;
+ }
+ }
+}
+
+
+/*
+*/
+void DeviceMonitor::updateReader( const SCARD_READERSTATE& scr ) {
+
+ BOOST_FOREACH( boost::shared_ptr< Device >& d, m_aDevices ) {
+
+ if( d.get( ) && ( 0 == d->getReaderName( ).compare( scr.szReader ) ) ) {
+
+ //Log::log( " ===> Update reader <%s>\n", scr.szReader );
+
+ d->update( scr );
+
+ return;
+ }
+ }
+}
+
+
+/*
+*/
+void DeviceMonitor::removeReader( LPCSTR s ) {
+
+ unsigned char ucDeviceID = 0;
+
+ BOOST_FOREACH( boost::shared_ptr< Device >& d, m_aDevices ) {
+
+ if( d.get( ) && ( 0 == d->getReaderName( ).compare( s ) ) ) {
+
+ Log::log( "DeviceMonitor::removeReader - <%s> - id <%d>", s, ucDeviceID );
+
+ SCARD_READERSTATE s;
+
+ memset( &s, 0, sizeof( SCARD_READERSTATE ) );
+
+ s.szReader = m_stEmptyDevice.c_str( );
+
+ s.dwCurrentState = SCARD_STATE_EMPTY;
+
+ s.dwEventState = SCARD_STATE_EMPTY;
+
+ d.reset( new Device( s, ucDeviceID ) );
+
+ return;
+ }
+
+ ++ucDeviceID;
+ }
+}
+
+
+/*
+*/
+void DeviceMonitor::addReader( const SCARDCONTEXT& h, const std::string& a_stDeviceName ) {
+
+ // Query the status of the device
+ SCARD_READERSTATE scr;
+ memset( &scr, 0, sizeof( SCARD_READERSTATE ) );
+ scr.szReader = a_stDeviceName.c_str( );
+
+ if( h ) {
+
+ LONG rv = SCardGetStatusChange( h, 100, &scr, 1 );
+
+ if( SCARD_S_SUCCESS != rv ) {
+
+ Log::log( "DeviceMonitor::addReader - SCardGetStatusChange <%#02x>", rv );
+
+ }
+
+ if( ( SCARD_W_REMOVED_CARD == rv ) || ( SCARD_W_RESET_CARD == rv ) ) {
+
+ DWORD dwActiveProtocol = 0;
+
+ rv = SCardReconnect( h, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_LEAVE_CARD, &dwActiveProtocol );
+
+ if( SCARD_S_SUCCESS != rv ) {
+
+ Log::log( "DeviceMonitor::addReader - SCardReconnect <%#02x>", rv );
+ return;
+ }
+
+ SCardGetStatusChange( h, 100, &scr, 1 );
+ }
+ }
+
+ scr.dwCurrentState = scr.dwEventState;
+
+ unsigned char ucDeviceID = 0;
+
+ BOOST_FOREACH( boost::shared_ptr< Device >& d, m_aDevices ) {
+
+ if( d.get( ) && ( 0 == d->getReaderName( ).compare( m_stEmptyDevice ) ) ) {
+
+ Log::log( "DeviceMonitor::addReader - <%s> - id <%d>", a_stDeviceName.c_str( ), ucDeviceID );
+
+ d.reset( new Device( scr, ucDeviceID ) );
+
+ /*if( SCARD_STATE_PRESENT & scr.dwEventState ) {
+
+ d->addMiniDriver( );
+ }*/
+
+ break;
+ }
+
+ ++ucDeviceID;
+ }
+}
+
+
+/*
+*/
+void DeviceMonitor::addReader( const SCARD_READERSTATE& a_State, const unsigned char& a_ucDeviceID ) {
+
+ BOOST_FOREACH( boost::shared_ptr< Device >& d, m_aDevices ) {
+
+ if( d.get( ) && ( 0 == d->getReaderName( ).compare( m_stEmptyDevice ) ) ) {
+
+ Log::log( "DeviceMonitor::addReader - <%s> - id <%d>", a_State.szReader, a_ucDeviceID );
+
+ d.reset( new Device( a_State, a_ucDeviceID ) );
+
+ return;
+ }
+ }
+}
+
+
+/*
+*/
+void DeviceMonitor::removeSmartCard( const std::string& a_stReaderName ) {
+
+ unsigned char ucDeviceID = 0;
+
+ BOOST_FOREACH( boost::shared_ptr< Device >& d, m_aDevices ) {
+
+ if( d.get( ) && ( 0 == d->getReaderName( ).compare( a_stReaderName ) ) ) {
+
+ Log::log( "DeviceMonitor::removeSmartCard - <%s> - id <%d>", a_stReaderName.c_str( ), ucDeviceID );
+
+ // Remove the MiniDriver dedicated to this smart card
+ d->removeMiniDriver( );
+
+ // Initialize the state of the device to monitor
+ SCARD_READERSTATE s;
+
+ memset( &s, 0, sizeof( SCARD_READERSTATE ) );
+
+ s.szReader = d->getReaderName( ).c_str( );
+
+ s.dwCurrentState = SCARD_STATE_EMPTY;
+
+ s.dwEventState = SCARD_STATE_EMPTY;
+
+ d->update( s );
+
+ return;
+ }
+
+ ++ucDeviceID;
+ }
+}
+
+
+/*
+*/
+void DeviceMonitor::addSmartCard( const std::string& a_stReaderName ) {
+
+ unsigned char ucDeviceID = 0;
+
+ BOOST_FOREACH( boost::shared_ptr< Device >& d, m_aDevices ) {
+
+ if( d.get( ) && ( 0 == d->getReaderName( ).compare( a_stReaderName ) ) ) {
+
+ Log::log( "DeviceMonitor::addSmartCard - <%s> - id <%d>", a_stReaderName.c_str( ), ucDeviceID );
+
+ //try {
+
+ d->addMiniDriver( );
+
+ //} catch( ... ) {
+
+ // If the smart card is removed during the read operation
+ // If the smart card is not a .NET smart card
+ // then an exception is thrown
+ //}
+
+ return;
+ }
+
+ ++ucDeviceID;
+ }
+}
+
+
+/*
+*/
+bool DeviceMonitor::isReaderExists( const SCARDCONTEXT& h, const std::string& a_stReaderName ) {
+
+ std::vector< std::string > deviceList;
+
+ getDevicesList( h, deviceList );
+
+ BOOST_FOREACH( const std::string& s, deviceList ) {
+
+ if( 0 == s.compare( a_stReaderName ) ) {
+
+ Log::log( "DeviceMonitor::isReaderExists - Reader <%s> exists", a_stReaderName.c_str( ) );
+
+ return true;
+ }
+ }
+
+ return false;
+ /*
+ SCARD_READERSTATE scr;
+
+ memset( &scr, 0, sizeof( SCARD_READERSTATE ) );
+
+ scr.szReader = a_stReaderName.c_str( );
+
+ LONG rv = SCardGetStatusChange( h, 100, &scr, 1 );
+
+ Log::log( "DeviceMonitor::isReaderExists - Current state <%#02x>", scr.dwCurrentState );
+ Log::log( "DeviceMonitor::isReaderExists - Event state <%#02x>", scr.dwEventState );
+
+ if( SCARD_S_SUCCESS != rv ) { // Expect for 0x8010002E Cannot find a smart card reader
+
+ Log::log( "DeviceMonitor::isReaderExists - SCardGetStatusChange <%#02x>", rv );
+
+ return false;
+ }
+
+ return true;
+ */
+}
+
+
+/*
+*/
+void DeviceMonitor::unblockWaitingThread( void ) {
+
+ if( ! g_bWaitForSlotEvent ) {
+
+ boost::lock_guard< boost::mutex > lock( g_WaitForSlotEventMutex );
+ g_bWaitForSlotEvent = true;
+ }
+
+ g_WaitForSlotEventCondition.notify_all( );
+}
+
+
+/*
+*/
+void DeviceMonitor::notifyListenerReaderInserted( const std::string& a_stReaderName ) {
+
+ if( m_bStopPolling ) {
+
+ return;
+ }
+
+ // Update the states of the listeners
+ BOOST_FOREACH( IDeviceMonitorListener* const d, m_Listeners ) {
+
+ if( d ) {
+
+ d->notifyReaderInserted( a_stReaderName );
+ }
+ }
+
+ // Give access to the state
+ unblockWaitingThread( );
+}
+
+
+/*
+*/
+void DeviceMonitor::notifyListenerReaderRemoved( const std::string& a_stReaderName ) {
+
+ if( m_bStopPolling ) {
+
+ return;
+ }
+
+ BOOST_FOREACH( IDeviceMonitorListener* const d, m_Listeners ) {
+
+ if( d ) {
+
+ d->notifyReaderRemoved( a_stReaderName );
+ }
+ }
+
+ unblockWaitingThread( );
+}
+
+
+/*
+*/
+void DeviceMonitor::notifyListenerSmartCardInserted( const std::string& a_stReaderName ) {
+
+ if( m_bStopPolling ) {
+
+ return;
+ }
+
+ BOOST_FOREACH( IDeviceMonitorListener* const d, m_Listeners ) {
+
+ if( d ) {
+
+ d->notifySmartCardInserted( a_stReaderName );
+ }
+ }
+
+ unblockWaitingThread( );
+}
+
+
+/*
+*/
+void DeviceMonitor::notifyListenerSmartCardRemoved( const std::string& a_stReaderName ) {
+
+ if( m_bStopPolling ) {
+
+ return;
+ }
+
+ BOOST_FOREACH( IDeviceMonitorListener* const d, m_Listeners ) {
+
+ if( d ) {
+
+ d->notifySmartCardRemoved( a_stReaderName );
+ }
+ }
+
+ unblockWaitingThread( );
+}
+
+
+/*
+*/
+void DeviceMonitor::notifyListenerSmartCardChanged( const std::string& a_stReaderName ) {
+
+ if( m_bStopPolling ) {
+
+ return;
+ }
+
+ BOOST_FOREACH( IDeviceMonitorListener* const d, m_Listeners ) {
+
+ if( d ) {
+
+ d->notifySmartCardChanged( a_stReaderName );
+ }
+ }
+
+ unblockWaitingThread( );
+}
+
+
+/*
+*/
+void DeviceMonitor::addListener( IDeviceMonitorListener* const a_pListener ) {
+
+ if( a_pListener ) {
+
+ m_Listeners.insert( m_Listeners.begin( ), a_pListener );
+ }
+}
+
+
+/*
+*/
+void DeviceMonitor::printDeviceList( void ) {
+
+ //Log::log( "\n=============== DEVICES" );
+
+ int i = 0;
+ BOOST_FOREACH( boost::shared_ptr< Device > scr, m_aDevices ) {
+
+ if( scr.get( ) ) {
+
+ printReaderState( scr->getReaderState( ), i );
+
+ }
+
+ ++i;
+ }
+
+ //Log::log( "=============== DEVICES\n" );
+}
+
+
+/*
+*/
+void DeviceMonitor::printReaderStateList( boost::array< SCARD_READERSTATE, g_iMaxReader + 1 >& l ) {
+
+ int i = 0;
+
+ BOOST_FOREACH( SCARD_READERSTATE &scr, l ) {
+
+ printReaderState( scr, i );
+
+ ++i;
+ }
+}
+
+
+/*
+*/
+void DeviceMonitor::printReaderState( const SCARD_READERSTATE& scrs, const int& iIndex ) {
+
+ if( !Log::s_bEnableLog || !scrs.szReader ) {
+
+ return;
+ }
+
+ std::string stStateCurrent;
+ getState( scrs.dwCurrentState, stStateCurrent );
+
+ std::string stStateEvent;
+ getState( scrs.dwEventState, stStateEvent );
+
+ std::string stATR;
+ Log::toString( scrs.rgbAtr, scrs.cbAtr, stATR );
+
+ Log::log( "Index <%d> - szReader <%s> - dwCurrentState <%#02x> (%s) - dwEventState <%#02x> (%s) - cbAtr <%#02x> - rgbAtr <%s>", iIndex, scrs.szReader, scrs.dwCurrentState, stStateCurrent.c_str( ), scrs.dwEventState, stStateEvent.c_str( ), scrs.cbAtr, stATR.c_str( ) );
+}
+
+
+/*
+*/
+void DeviceMonitor::getState( const DWORD& dwState, std::string& stState ) {
+
+ // The application requested that this reader be ignored. No other bits will be set.
+ if( SCARD_STATE_IGNORE == ( SCARD_STATE_IGNORE & dwState ) ) {
+ stState += "SCARD_STATE_IGNORE ";
+ }
+
+ // This implies that there is a difference between the state believed by the application, and
+ // the state known by the Service Manager. When this bit is set, the application may assume a
+ // significant state change has occurred on this reader.
+ if( SCARD_STATE_CHANGED == ( SCARD_STATE_CHANGED & dwState ) ) {
+ stState += "SCARD_STATE_CHANGED ";
+ }
+
+ // This implies that the given reader name is not recognized by the Service Manager. If this bit
+ // is set, then SCARD_STATE_CHANGED and SCARD_STATE_IGNORE will also be set.
+ if( SCARD_STATE_UNKNOWN == ( SCARD_STATE_UNKNOWN & dwState ) ) {
+ stState += "SCARD_STATE_UNKNOWN ";
+ }
+
+ // This implies that the actual state of this reader is not available. If this bit is set,
+ // then all the following bits are clear.
+ if( SCARD_STATE_UNAVAILABLE == ( SCARD_STATE_UNAVAILABLE & dwState ) ) {
+ stState += "SCARD_STATE_UNAVAILABLE ";
+ }
+
+ // This implies that there is not card in the reader. If this bit is set, all the following bits will be clear.
+ if( SCARD_STATE_EMPTY == ( SCARD_STATE_EMPTY & dwState ) ) {
+ stState += "SCARD_STATE_EMPTY ";
+ }
+
+ // This implies that there is a card in the reader.
+ if( SCARD_STATE_PRESENT == ( SCARD_STATE_PRESENT & dwState ) ) {
+ stState += "SCARD_STATE_PRESENT ";
+ }
+
+ // This implies that there is a card in the reader with an ATR matching one of the target cards.
+ // If this bit is set, SCARD_STATE_PRESENT will also be set. This bit is only returned on the SCardLocateCard() service.
+ if( SCARD_STATE_ATRMATCH == ( SCARD_STATE_ATRMATCH & dwState ) ) {
+ stState += "SCARD_STATE_ATRMATCH ";
+ }
+
+ // This implies that the card in the reader is allocated for exclusive use by another application.
+ // If this bit is set, SCARD_STATE_PRESENT will also be set.
+ if( SCARD_STATE_EXCLUSIVE == ( SCARD_STATE_EXCLUSIVE & dwState ) ) {
+ stState += "SCARD_STATE_EXCLUSIVE ";
+ }
+
+ // This implies that the card in the reader is in use by one or more other applications, but may be
+ // connected to in shared mode. If this bit is set, SCARD_STATE_PRESENT will also be set.
+ if( SCARD_STATE_INUSE == ( SCARD_STATE_INUSE & dwState ) ) {
+ stState += "SCARD_STATE_INUSE ";
+ }
+
+ // This implies that the card in the reader is unresponsive or not supported by the reader or software.
+ if( SCARD_STATE_MUTE == ( SCARD_STATE_MUTE & dwState ) ) {
+ stState += "SCARD_STATE_MUTE ";
+ }
+
+ // This implies that the card in the reader has not been powered up.
+ if( SCARD_STATE_UNPOWERED == ( SCARD_STATE_UNPOWERED & dwState ) ) {
+ stState += "SCARD_STATE_UNPOWERED ";
+ }
+
+ // The application is unaware of the current state, and would like to know. The use of this value
+ // results in an immediate return from state transition monitoring services. This is represented by
+ // all bits set to zero.
+ if( stState.empty( ) && ( SCARD_STATE_UNAWARE == ( SCARD_STATE_UNAWARE & dwState ) ) ) {
+ stState += "SCARD_STATE_UNAWARE ";
+ }
+}
+
+
+/*
+*/
+void DeviceMonitor::start( void ) {
+
+ // Initialize the PCSC context
+ long hResult = SCardEstablishContext( SCARD_SCOPE_USER, NULL, NULL, &m_hContext );
+
+ if( SCARD_S_SUCCESS != hResult ) {
+
+ //throw std::exception( );
+ return;
+ }
+
+ // Establish the list of the connected devices
+ getDevicesStates( m_hContext );
+
+ m_bStopPolling = false;
+
+ DeviceMonitor::m_bAlive = false;
+
+ m_ThreadListener.reset( new boost::thread( &DeviceMonitor::monitorReaderEvent, this ) );
+
+ Log::log( "DeviceMonitor::start - Wait for thread starting..." );
+
+ Timer t;
+ t.start( );
+
+ /*
+ ==========
+ unsigned int i = 0;
+
+ do {
+
+ boost::this_thread::sleep( boost::posix_time::milliseconds( 100 ) );
+
+ i += 100;
+
+ Log::log( "DeviceMonitor::start - DeviceMonitor::m_bAlive <%d> - i <%ld>", DeviceMonitor::m_bAlive, i );
+
+ } while( ( false == DeviceMonitor::m_bAlive ) && ( i < 1000 ) );
+ ============
+ */
+ {
+ boost::mutex::scoped_lock lock( g_WaitForDeviceMonitorThreadMutex );
+
+ while( !DeviceMonitor::m_bAlive ) {
+
+ g_WaitForDeviceMonitorThreadCondition.wait( lock );
+ }
+ }
+ //g_WaitForDeviceMonitorThreadCondition.timed_wait( lock, boost::posix_time::milliseconds( 1000 ) );
+ t.stop( "DeviceMonitor::start - Thread started" );
+}
+
+
+/*
+*/
+void DeviceMonitor::stop( void ) {
+
+ Log::begin( "DeviceMonitor::stop" );
+
+ //unblockWaitingThread( );
+ g_WaitForSlotEventCondition.notify_all( );
+
+ Log::log( "DeviceMonitor::stop - Wait for event thread unblocked" );
+
+ long rv = SCardCancel( m_hContext );
+ Log::log( "DeviceMonitor::stop - SCardCancel <%#02x>", rv );
+
+ m_bStopPolling = true;
+ //Log::log( "DeviceMonitor::stop - m_bStopPolling <%#02x>", m_bStopPolling );
+
+ Log::log( "DeviceMonitor::stop - bAlive <%#02x>", DeviceMonitor::m_bAlive );
+
+ if( DeviceMonitor::m_bAlive ) {
+
+ Log::log( "DeviceMonitor::stop - Waiting the thread stops..." );
+ Timer t;
+ t.start( );
+
+ unsigned int i = 0;
+
+ do {
+
+ boost::this_thread::sleep( boost::posix_time::milliseconds( 100 ) );
+
+ Log::log( "DeviceMonitor::stop - DeviceMonitor::m_bAlive <%d> - i <%ld>", DeviceMonitor::m_bAlive, i );
+
+ i+= 100;
+
+ } while( DeviceMonitor::m_bAlive && ( i < 2000 ) );
+
+ t.stop( "DeviceMonitor::stop - Thread stopped" );
+ }
+
+ Log::end( "DeviceMonitor::stop" );
+}
+
+
+/* Spy reader insertion/removal
+*/
+void DeviceMonitor::monitorReaderEvent( void ) {
+
+ Log::log( "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ DEVICE MONITOR THREAD STARTS ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\n" );
+
+ // Unblock all mutex waiting for the device monitor thread start
+ {
+ boost::mutex::scoped_lock lock( g_WaitForDeviceMonitorThreadMutex );
+
+ DeviceMonitor::m_bAlive = true;
+ }
+ g_WaitForDeviceMonitorThreadCondition.notify_all( );
+
+
+ if( DeviceMonitor::m_bStopPolling ) {
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - Stop thread at begining " );
+
+ DeviceMonitor::m_bAlive = false;
+
+ return;
+ }
+
+ try {
+
+ std::string PNP_NOTIFICATION( "\\\\?PnP?\\Notification" );
+
+ std::vector< std::string > vDevices;
+
+ vDevices.reserve( g_iMaxReader );
+
+ vDevices.clear( );
+
+ // Build the smart card reader states buffer. Reserve the first cell to Plug&Play notification declaration
+ SCARD_READERSTATE aReaderStates[ g_iMaxReader + 1 ];
+
+ memset( &aReaderStates[ 0 ], 0, sizeof( aReaderStates ) );
+
+ aReaderStates[ 0 ].szReader = PNP_NOTIFICATION.c_str( );
+
+ DWORD dwReaderStatesCount = 1;
+
+ BOOST_FOREACH( boost::shared_ptr< Device >& d, m_aDevices ) {
+
+ // Ignore empty device cell
+ if( d.get( ) && d->getReaderName( ).compare( m_stEmptyDevice ) ) {
+
+ d->put( aReaderStates[ dwReaderStatesCount ] );
+
+ ++dwReaderStatesCount;
+ }
+ }
+
+ size_t uiReaderStatesLen = sizeof( aReaderStates ) / sizeof( SCARD_READERSTATE );
+
+ // Start to spy the readers states
+ do {
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - Start polling" );
+
+ if ( DeviceMonitor::m_bStopPolling ) {
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - Stop polling required before status request" );
+ break;
+ }
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - Query new card/reader status for:" );
+ for( size_t i = 0 ; i < uiReaderStatesLen ; ++i ) {
+
+ if( aReaderStates[ i ].szReader ) {
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - <%s>", aReaderStates[ i ].szReader );
+ }
+ }
+
+ // Query the status for all known devices plus the Plug&Play notification
+ long rv;
+ try {
+ rv = SCardGetStatusChange( DeviceMonitor::m_hContext, INFINITE, aReaderStates, dwReaderStatesCount );
+ }
+ catch( ... ) { }
+
+ boost::mutex::scoped_lock lock( io_mutex );
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - SCardGetStatusChange <%#02x>", rv );
+
+ if ( DeviceMonitor::m_bStopPolling ) {
+
+ // If the library has been unloaded the thread must stopped right now
+ Log::log( "DeviceMonitor::monitorReaderEvent - Stop polling required after status request" );
+ break;
+ }
+
+ // Check if the get status action has been canceled or failed
+ if( SCARD_E_CANCELLED == rv ) {
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - SCardGetStatusChange cancelled <%#02x>", rv );
+ break;
+
+ } else if( ( SCARD_W_REMOVED_CARD == rv ) || ( SCARD_W_RESET_CARD == rv ) ) {
+
+ DWORD dwActiveProtocol = 0;
+ rv = SCardReconnect( DeviceMonitor::m_hContext, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_LEAVE_CARD, &dwActiveProtocol );
+
+ if( SCARD_S_SUCCESS != rv ) {
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - SCardReconnect failed <%#02x>", rv );
+ break;
+ }
+
+ continue;
+
+ } else if( SCARD_S_SUCCESS != rv ) {
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - SCardGetStatusChange failed <%#02x>", rv );
+ break;
+ }
+
+ if ( m_bStopPolling ) {
+
+ // If the library has been unloaded the thread must stopped right now
+ break;
+ }
+
+ // A Plug&Play event occured. A reader has been removed or inserted
+ if( aReaderStates[ 0 ].dwEventState & SCARD_STATE_CHANGED ) {
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - Pnp status changed" );
+
+ // Get the new device list
+ getDevicesList( m_hContext, vDevices );
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - New device list created" );
+
+ if ( m_bStopPolling ) {
+
+ // If the library has been unloaded the thread must stopped right now
+ Log::log( "DeviceMonitor::monitorReaderEvent - Stop polling required after device list creation" );
+ break;
+ }
+
+ // First compare the current readers with the new device list to know if the reader has been previously detected
+ bool bFound = false;
+
+ BOOST_FOREACH( SCARD_READERSTATE& rs, aReaderStates ) {
+
+ if( rs.szReader && PNP_NOTIFICATION.compare( rs.szReader ) ) {
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - Check removal of reader <%s>", rs.szReader );
+
+ bFound = false;
+
+ BOOST_FOREACH( std::string& s, vDevices ) {
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - Locate removal of reader <%s> compared to <%s>", rs.szReader, s.c_str( ) );
+
+ if( 0 == s.compare( (LPSTR)( rs.szReader ) ) ) {
+
+ // The reader is still in use
+ bFound = true;
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - Reader <%s> still in use", s.c_str( ) );
+
+ break;
+ }
+ }
+
+ if( !bFound ) {
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - Reader <%s> removed", rs.szReader );
+
+ // The reader has been removed
+ notifyListenerReaderRemoved( rs.szReader );
+
+ // Remove the device from the current device list
+ removeReader( rs.szReader );
+ }
+ }
+ }
+
+ // Second compare the new device list to the old one to know if new devices have been inserted
+ BOOST_FOREACH( std::string& s, vDevices ) {
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - Locate new reader for reader <%s>", s.c_str( ) );
+
+ bool bFound = false;
+
+ BOOST_FOREACH( SCARD_READERSTATE& rs, aReaderStates ) {
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - Locate new reader for reader <%s> compared to <%s>", s.c_str( ), rs.szReader );
+
+ if( rs.szReader && ( 0 == s.compare( (LPSTR)( rs.szReader ) ) ) ) {
+
+ // The reader is already known
+ bFound = true;
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - Reader <%s> is known", rs.szReader );
+
+ break;
+ }
+ }
+
+ if( !bFound ) {
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - Found new reader <%s>", s.c_str( ) );
+
+ // The reader is unknown. Add the new reader into the current device list
+ addReader( m_hContext, s );
+
+ // Notify the insertion
+ notifyListenerReaderInserted( s );
+ }
+ }
+ }
+
+ // A real change state notification came.
+ // Locate state changes in the current reader list avoiding the first cell which is dedicated to Plug&Play notification declaration
+ BOOST_FOREACH( SCARD_READERSTATE& srs, aReaderStates ) {
+
+ // Update the state
+ srs.dwCurrentState = srs.dwEventState;
+
+ if( !srs.szReader ) {
+
+ continue;
+ }
+
+ if( !PNP_NOTIFICATION.compare( srs.szReader ) ) {
+
+ continue;
+ }
+
+ if( SCARD_STATE_CHANGED & srs.dwEventState ) {
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - Reader <%s> - State changed <%#02x>", srs.szReader, srs.dwEventState );
+
+ // Get the current registered reader state to compare with the new incoming state
+ SCARD_READERSTATE scr;
+
+ memset( &scr, 0, sizeof( SCARD_READERSTATE ) );
+
+ scr.szReader = srs.szReader;
+
+ getReader( scr );
+
+ // If a smart card is present and this is not already the state of the reader
+ if( ( SCARD_STATE_PRESENT & srs.dwEventState ) && ( 0 == ( SCARD_STATE_PRESENT & scr.dwCurrentState ) ) ) {
+// LCA: remove comment on ATR test!
+ // !!!!! ONLY NOTIFY IF A .NET SMART CARD IS PRESENT !!!!!
+ if( ( SCARD_STATE_MUTE != ( SCARD_STATE_MUTE & srs.dwEventState ) ) && ( 0 == memcmp( g_DotNetSmartCardAtr, srs.rgbAtr, srs.cbAtr ) ) ) {
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - Reader <%s> - .NET Card inserted", srs.szReader );
+
+ try {
+
+ addSmartCard( srs.szReader );
+
+ notifyListenerSmartCardInserted( srs.szReader );
+
+ } catch( ... ) {
+
+ // This is not a .NET smart card. Nothing to do.
+ }
+ }
+
+ // If a smart card been removed and this is not already the state of the reader
+ } else if( ( SCARD_STATE_EMPTY & srs.dwEventState ) && ( 0 == ( SCARD_STATE_EMPTY & scr.dwCurrentState ) ) ) {
+// LCA: Only notify for .NET card?
+ bool isDotNetToken = true;
+
+ BOOST_FOREACH( boost::shared_ptr< Device >& d, m_aDevices ) {
+
+ // Ignore empty device cell
+ if( d.get( ) && ( 0 == d->getReaderName( ).compare( srs.szReader ) ) ) {
+
+ try {
+
+ d->getCardModule( );
+
+ } catch (...) {
+
+ isDotNetToken = false;
+ }
+
+ break;
+ }
+ }
+
+ if (isDotNetToken)
+ {
+ Log::log( "DeviceMonitor::monitorReaderEvent - Reader <%s> - Card removed", srs.szReader );
+
+ // Query the status of the device
+ if( isReaderExists( m_hContext, srs.szReader ) ) {
+
+ // The reader exists, only the smart card has been removed
+ removeSmartCard( srs.szReader );
+
+ notifyListenerSmartCardRemoved( srs.szReader );
+
+ } else {
+
+ // The reader has been removed and also the smart card
+ notifyListenerReaderRemoved( srs.szReader );
+
+ // Remove the device from the current device list
+ removeReader( srs.szReader );
+ }
+ }
+ }
+ }
+
+ // Store the reader state
+ updateReader( srs );
+ }
+ Log::log( "DeviceMonitor::monitorReaderEvent - Rebuild the list of readers to poll" );
+
+ // Build the new smart card reader state buffer with the plug& play notification query as first cell
+ dwReaderStatesCount = 1;
+
+ //memset( &aReaderStates[ 1 ], 0, sizeof( SCARD_READERSTATE ) * (v g_iMaxReader );
+
+ //aReaderStates[ 0 ].szReader = /*readerNames[ 0 ];*/ PNP_NOTIFICATION.c_str( );
+
+ BOOST_FOREACH( boost::shared_ptr< Device >& d, m_aDevices ) {
+
+ memset( &aReaderStates[ dwReaderStatesCount ], 0, sizeof( SCARD_READERSTATE ) );
+
+ // Ignore empty device cell
+ if( d.get( ) && d->getReaderName( ).compare( m_stEmptyDevice ) ) {
+
+ d->put( aReaderStates[ dwReaderStatesCount ] );
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - Prepare to poll reader <%s>", aReaderStates[ dwReaderStatesCount ].szReader );
+
+ //memset( readerNames[ dwReaderStatesCount ], 0,sizeof( readerNames[ dwReaderStatesCount ] ) );
+
+ //memcpy( readerNames[ dwReaderStatesCount ], d->getReaderName( ).c_str( ), d->getReaderName( ).size( ) );
+
+ //aReaderStates[ dwReaderStatesCount ].szReader = d->getReaderName( ).c_str( ); //readerNames[ dwReaderStatesCount ];
+
+ ++dwReaderStatesCount;
+ }
+ }
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - Ready to poll" );
+
+ } while( !DeviceMonitor::m_bStopPolling );
+
+ } catch( ... ) {
+
+ Log::log( "DeviceMonitor::monitorReaderEvent - CRASH !");
+ }
+
+ LONG l = SCardReleaseContext( DeviceMonitor::m_hContext );
+ Log::log( "DeviceMonitor::monitorReaderEvent - SCardReleaseContext <%#02x>", l );
+
+ Log::log( "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ DEVICE MONITOR THREAD STOPS ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\n" );
+
+ DeviceMonitor::m_bAlive = false;
+}
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/DeviceMonitor.hpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/DeviceMonitor.hpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/DeviceMonitor.hpp 2012-02-20 14:41:36 UTC (rev 144)
@@ -0,0 +1,133 @@
+/*
+* PKCS#11 library for .Net smart cards
+* Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*
+*/
+
+
+#ifndef __GEMALTO_DEVICE_MONITOR__
+#define __GEMALTO_DEVICE_MONITOR__
+
+
+#include <vector>
+#include <string>
+#include <list>
+#include <boost/shared_ptr.hpp>
+#include <boost/array.hpp>
+#include <boost/thread.hpp>
+
+
+#ifdef __APPLE__
+#include <PCSC/winscard.h>
+#else
+#include <winscard.h>
+#endif
+
+
+//#ifdef __sun
+//typedef LPSTR LPTSTR;
+//#endif
+
+#include "IDeviceMonitorListener.hpp"
+#include "Device.hpp"
+
+
+const int g_iMaxReader = 5; //MAXIMUM_SMARTCARD_READERS
+
+
+/*
+*/
+class DeviceMonitor {
+
+public:
+
+ DeviceMonitor( );
+
+ virtual ~DeviceMonitor( ) { }
+
+ typedef boost::array< boost::shared_ptr< Device >, g_iMaxReader > DEVICES;
+
+ inline DEVICES& getDeviceList( void ) { return m_aDevices; };
+
+ void addListener( IDeviceMonitorListener* const );
+
+ inline void removeListener( IDeviceMonitorListener* const a_pListener ) { m_Listeners.remove( a_pListener ); }
+
+ void start( void );
+
+ void stop( void );
+
+ size_t size( ) { return m_aDevices.size( ); }
+
+ static SCARDCONTEXT m_hContext;
+
+ static bool m_bStopPolling;
+
+ static bool m_bAlive;
+
+private:
+
+ void getDevicesList( const SCARDCONTEXT&, std::vector< std::string >& );
+
+ void getDevicesStates( const SCARDCONTEXT& );
+
+ void monitorReaderEvent( void );
+
+ void notifyListenerReaderInserted( const std::string& );
+
+ void notifyListenerReaderRemoved( const std::string& );
+
+ void notifyListenerSmartCardInserted( const std::string& );
+
+ void notifyListenerSmartCardRemoved( const std::string& );
+
+ void notifyListenerSmartCardChanged( const std::string& );
+
+ void updateReader( const SCARD_READERSTATE& );
+
+ void removeReader( LPCSTR );
+
+ void addReader( const SCARDCONTEXT&, const std::string& );
+
+ void addReader( const SCARD_READERSTATE&, const unsigned char& );
+
+ void removeSmartCard( const std::string& );
+
+ void addSmartCard( const std::string& );
+
+ void getReader( SCARD_READERSTATE& );
+
+ void unblockWaitingThread( void );
+
+ bool isReaderExists( const SCARDCONTEXT& h, const std::string& );
+
+ DEVICES m_aDevices;
+
+ std::list< IDeviceMonitorListener* > m_Listeners;
+
+ std::string m_stEmptyDevice;
+
+ boost::shared_ptr< boost::thread > m_ThreadListener;
+
+ void printReaderState( const SCARD_READERSTATE& scrs, const int& iIndex );
+ void printDeviceList( void );
+ void printReaderStateList( boost::array< SCARD_READERSTATE, g_iMaxReader + 1 >& );
+ void getState( const DWORD& dwState, std::string& stState );
+
+};
+
+#endif
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/smartcardservices-changes/attachments/20120220/f7759c13/attachment-0001.html>
More information about the SmartcardServices-Changes
mailing list