void ReaderStatusChanged(uint ReaderState, CardBuffer CardAtr) { /* The ReaderStatusChanged function is called as a delegate (callback) by the SCardReader object */ /* within its backgroung thread. Therefore we must use the BeginInvoke syntax to switch back from */ /* the context of the background thread to the context of the application's main thread. Overwise */ /* we'll get a security violation when trying to access the window's visual components (that belong */ /* to the application's main thread and can't be safely manipulated by background threads). */ if (InvokeRequired) { this.BeginInvoke(new ReaderStatusChangedInvoker(ReaderStatusChanged), ReaderState, CardAtr); return; } DisplayReaderState(ReaderState, CardAtr); if (ReaderState == SCARD.STATE_UNAWARE) { if (cardChannel != null) { cardChannel.Disconnect(); cardChannel = null; } if (Reader != null) { Reader.StopMonitor(); Reader.Release(); Reader = null; } if (ReaderList != null) { ReaderList.Release(); ReaderList = null; } btnReadAgain.Enabled = false; btnWrite.Enabled = false; MessageBox.Show(this, "The reader we were working on has been removed from the system. Please click the 'Reader' link to select another reader.", Title, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); DisplayReaderState(0, null); DisplayReaderAbsent(); return; } if ((ReaderState & SCARD.STATE_EMPTY) != 0) { if (cardChannel != null) { cardChannel.Disconnect(); cardChannel = null; } btnReadAgain.Enabled = false; btnWrite.Enabled = false; } else if ((ReaderState & SCARD.STATE_UNAVAILABLE) != 0) { btnReadAgain.Enabled = false; btnWrite.Enabled = false; } else if ((ReaderState & SCARD.STATE_MUTE) != 0) { btnReadAgain.Enabled = false; btnWrite.Enabled = false; } else if ((ReaderState & SCARD.STATE_INUSE) != 0) { } else if ((ReaderState & SCARD.STATE_PRESENT) != 0) { if (cardChannel == null) { /* New card -> leave edit mode */ cardChannel = Reader.GetChannel(); DisplayWorking(false); if (cardChannel.Connect()) { cardReaderThread = new Thread(ReadCardFirst); cardReaderThread.Start(); } else { ClearDisplay(); MessageBox.Show(this, "Failed to connect to the card in the reader. Please verify that you don't have another application running in the background, that tries to access to the smartcards in the same reader.", Title, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); cardChannel = null; } } } }
void ReaderStatusChanged(uint ReaderState, CardBuffer CardAtr) { /* The ReaderStatusChanged function is called as a delegate (callback) by the SCardReader object */ /* within its backgroung thread. Therefore we must use the BeginInvoke syntax to switch back from */ /* the context of the background thread to the context of the application's main thread. Overwise */ /* we'll get a security violation when trying to access the window's visual components (that belong */ /* to the application's main thread and can't be safely manipulated by background threads). */ if (InvokeRequired) { IAsyncResult ar = this.BeginInvoke(new ReaderStatusChangedInvoker(ReaderStatusChanged), ReaderState, CardAtr); this.EndInvoke(ar); return; } DisplayReaderState(ReaderState, CardAtr); if (ReaderState == SCARD.STATE_UNAWARE) { if (Card != null) { Card.Disconnect(); Card = null; } if (Reader != null) { Reader.Release(); Reader = null; } if (ReaderList != null) { ReaderList.Release(); ReaderList = null; } MessageBox.Show(this, "The reader we were working on has been removed from the system. Please click the 'Reader' link to select another reader.", Title, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); DisplayReaderState(0, null); DisplayReaderAbsent(); return; } if ((ReaderState & SCARD.STATE_EMPTY) != 0) { if (Card != null) { AddToResult("\nCard removed\n", Color.Black, true); Card.Disconnect(); Card = null; } } else if ((ReaderState & SCARD.STATE_UNAVAILABLE) != 0) { } else if ((ReaderState & SCARD.STATE_MUTE) != 0) { } else if ((ReaderState & SCARD.STATE_INUSE) != 0) { } else if ((ReaderState & SCARD.STATE_PRESENT) != 0) { if (Card == null) { /* New card -> leave edit mode */ Card = Reader.GetChannel(); if (Card.Connect()) { AddToResult("\nCard inserted\n", Color.Black, true); if (cbAutorun.Checked) { if (!StartScript()) { AddToResult("Autorun failed\n", Color.Red); } } } else { MessageBox.Show(this, "Failed to connect to the card in the reader. Please verify that you don't have another application running in the background, that tries to access to the smartcards in the same reader.", Title, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); Card = null; } } else { AddToResult("Application state error, please remove the card\n", Color.Orange); } } }