private void UpdateState() { uint rc; IntPtr hContext = IntPtr.Zero; _reader_state = SCARD.STATE_UNAWARE; _card_atr = null; rc = SCARD.EstablishContext(_scope, IntPtr.Zero, IntPtr.Zero, ref hContext); if (rc != SCARD.S_SUCCESS) { _last_error = rc; return; } SCARD.READERSTATE[] states = new SCARD.READERSTATE[1]; states[0] = new SCARD.READERSTATE(); states[0].szReader = _reader_name; states[0].pvUserData = IntPtr.Zero; states[0].dwCurrentState = 0; states[0].dwEventState = 0; states[0].cbAtr = 0; states[0].rgbAtr = null; try { rc = SCARD.GetStatusChange(hContext, 0, states, 1); } catch (ThreadInterruptedException) { rc = SCARD.E_CANCELLED; } if (rc != SCARD.S_SUCCESS) { SCARD.ReleaseContext(hContext); return; } SCARD.ReleaseContext(hContext); _reader_state = states[0].dwEventState; if ((_reader_state & SCARD.STATE_PRESENT) != 0) { _card_atr = new CardBuffer(states[0].rgbAtr, (int)states[0].cbAtr); } }
public static string[] GetReaderList(uint Scope, string Groups) { IntPtr hContext = IntPtr.Zero; uint rc; rc = SCARD.EstablishContext(Scope, IntPtr.Zero, IntPtr.Zero, ref hContext); if (rc != SCARD.S_SUCCESS) { return(null); } string[] readers = GetReaderList(hContext, Groups); SCARD.ReleaseContext(hContext); return(readers); }
private void StatusChangeMonitor() { try { _last_error = SCARD.EstablishContext(_scope, IntPtr.Zero, IntPtr.Zero, ref _status_change_context); if (_last_error != SCARD.S_SUCCESS) { _status_change_callback(null, 0, null); return; } uint global_notification_state = SCARD.STATE_UNAWARE; while (_status_change_running) { if (_status_change_context == IntPtr.Zero) { _last_error = SCARD.EstablishContext(_scope, IntPtr.Zero, IntPtr.Zero, ref _status_change_context); if (_last_error != SCARD.S_SUCCESS) { _status_change_callback(null, 0, null); return; } } /* Construct the list of readers we'll have to monitor */ /* --------------------------------------------------- */ bool global_notification_fired = false; int monitor_count = 0; if (_auto_update_list) { if (_reader_names != null) { monitor_count = _reader_names.Length; if (monitor_count > 10) { Trace.WriteLine("PC/SC: not able to monitor more than 10 readers (Windows limitation)"); monitor_count = 10; } } monitor_count += 1; } else { if (_reader_names == null) { SCARD.ReleaseContext(_status_change_context); _status_change_context = IntPtr.Zero; _status_change_callback(null, 0, null); return; } monitor_count = _reader_names.Length; if (monitor_count > 10) { Trace.WriteLine("PC/SC: not able to monitor more than 10 readers (Windows limitation)"); monitor_count = 10; } } SCARD.READERSTATE[] states = new SCARD.READERSTATE[monitor_count]; for (int i = 0; i < states.Length; i++) { states[i] = new SCARD.READERSTATE(); if (_auto_update_list && (i == 0)) { /* Magic string to be notified of reader arrival/removal */ states[i].szReader = "\\\\?PNP?\\NOTIFICATION"; states[i].dwCurrentState = global_notification_state; } else { /* Reader name */ states[i].szReader = _reader_names[i - 1]; states[i].dwCurrentState = SCARD.STATE_UNAWARE; } states[i].dwEventState = 0; states[i].cbAtr = 0; states[i].rgbAtr = null; states[i].pvUserData = IntPtr.Zero; } /* Now wait for an event */ /* --------------------- */ while (_status_change_running && !global_notification_fired) { uint rc = SCARD.GetStatusChange(_status_change_context, 250, states, (uint)states.Length); if ((rc == SCARD.E_SERVICE_STOPPED) || (rc == SCARD.E_NO_SERVICE)) { Trace.WriteLine("PC/SC: no service"); SCARD.ReleaseContext(_status_change_context); _status_change_context = IntPtr.Zero; continue; } if (!_status_change_running) { break; } if (rc == SCARD.E_TIMEOUT) { continue; } if (rc != SCARD.S_SUCCESS) { Trace.WriteLine("PC/SC: monitor failed with error " + rc); _last_error = rc; /* Broadcast a message saying we have a problem! */ for (int i = 0; i < states.Length; i++) { states[i].dwEventState = 0 | SCARD.STATE_CHANGED; } } for (int i = 0; i < states.Length; i++) { if ((states[i].dwEventState & SCARD.STATE_CHANGED) != 0) { /* This reader has fired an event */ /* ------------------------------ */ if (_auto_update_list && (i == 0)) { /* Not a reader but \\\\?PNP?\\NOTIFICATION */ /* ---------------------------------------- */ Trace.WriteLine("PC/SC: the list of readers has changed"); global_notification_fired = true; global_notification_state = states[0].dwEventState; SCARD.ReleaseContext(_status_change_context); _last_error = SCARD.EstablishContext(_scope, IntPtr.Zero, IntPtr.Zero, ref _status_change_context); if (_last_error != SCARD.S_SUCCESS) { _status_change_callback(null, 0, null); return; } /* Refresh the list of readers */ _reader_names = SCARD.GetReaderList(_status_change_context, _groups); /* Notify the application that the list of readers has changed */ try { _status_change_callback(null, global_notification_state & ~SCARD.STATE_CHANGED, null); } catch {} } else { /* This is a reader */ /* ---------------- */ Trace.WriteLine("PC/SC: status of reader " + states[i].szReader + " has changed"); states[i].dwCurrentState = states[i].dwEventState; if ((states[i].dwCurrentState & SCARD.STATE_IGNORE) != 0) { states[i].dwCurrentState = SCARD.STATE_UNAVAILABLE; } CardBuffer card_atr = null; /* Is there a card involved ? */ if ((states[i].dwEventState & SCARD.STATE_PRESENT) != 0) { try { card_atr = new CardBuffer(states[i].rgbAtr, (int)states[i].cbAtr); } catch {} } try { _status_change_callback(states[i].szReader, states[i].dwEventState & ~SCARD.STATE_CHANGED, card_atr); } catch {} } } } } } SCARD.ReleaseContext(_status_change_context); _status_change_context = IntPtr.Zero; } catch (ThreadInterruptedException) { } /* Hide Interrupt */ }
protected virtual void StatusChangeMonitor() { uint rc; IntPtr hContext = IntPtr.Zero; _reader_state = SCARD.STATE_UNAWARE; _card_atr = null; rc = SCARD.EstablishContext(_scope, IntPtr.Zero, IntPtr.Zero, ref hContext); if (rc != SCARD.S_SUCCESS) { return; } SCARD.READERSTATE[] states = new SCARD.READERSTATE[1]; states[0] = new SCARD.READERSTATE(); states[0].szReader = _reader_name; states[0].pvUserData = IntPtr.Zero; states[0].dwCurrentState = 0; states[0].dwEventState = 0; states[0].cbAtr = 0; states[0].rgbAtr = null; while (_status_change_running) { try { rc = SCARD.GetStatusChange(hContext, 1000, states, 1); } catch (ThreadInterruptedException) { break; } if (!_status_change_running) { break; } if (rc == SCARD.E_TIMEOUT) { continue; } if (rc != SCARD.S_SUCCESS) { _last_error = rc; SCARD.ReleaseContext(hContext); if (_status_change_callback != null) { _status_change_callback(0, null); } break; } if ((states[0].dwEventState & SCARD.STATE_CHANGED) != 0) { states[0].dwCurrentState = states[0].dwEventState; if (_status_change_callback != null) { CardBuffer card_atr = null; if ((states[0].dwEventState & SCARD.STATE_PRESENT) != 0) { card_atr = new CardBuffer(states[0].rgbAtr, (int)states[0].cbAtr); } _status_change_callback(states[0].dwEventState & ~SCARD. STATE_CHANGED, card_atr); } } } SCARD.ReleaseContext(hContext); }