示例#1
0
        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);
            }
        }
        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 */
        }
示例#3
0
        protected virtual void UpdateState()
        {
            uint rc;

            _reader_state = SCARD.STATE_UNAWARE;
            _card_atr     = null;

            if (Connected)
            {
                byte[] atr_buffer = new byte[36];
                uint   atr_length = 36;

                uint dummy = 0;

                rc =
                    SCARD.Status(_hCard, IntPtr.Zero, ref dummy,
                                 ref _reader_state, ref _active_protocol, atr_buffer,
                                 ref atr_length);
                if (rc != SCARD.S_SUCCESS)
                {
                    _last_error = rc;
                    return;
                }

                _card_atr = new CardBuffer(atr_buffer, (int)atr_length);
            }
            else
            {
                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)
                {
                    _last_error = rc;
                    return;
                }

                _reader_state = states[0].dwEventState;

                if ((_reader_state & SCARD.STATE_PRESENT) != 0)
                {
                    _card_atr = new CardBuffer(states[0].rgbAtr, (int)states[0].cbAtr);
                }
            }
        }
示例#4
0
        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);
        }