Tech Articles


Detecting a smart card insertion/removal from PowerBuilder


This is a follow up article to an earlier article I wrote called Communication with a smart card from PowerBuilder. In that article I showed how to interact with a smart card once it was inserted in the reader.  In this article, we're going to look at how we can monitor the card reader to determine when the user inserts or removes a smart card from it.

This article assumes you have the code in place from that earlier article.  In particular, it assumes that you've got the code in place to establish the context for the API calls, read a list of the available smart card readers and close the context once we're done interacting with the readers.

The particular function we're going to call is SCardGetStatusChange.  However, that function takes an array of a structure called SCARD_READERSTATE, so we're going to declare a structure in PowerBuilder to match that first.  That structure looks like this: 

 global type s_readerstate from structure  
      string          reader  
      unsignedlong          userdata  
      unsignedlong          currentstate  
      unsignedlong          eventstate  
      unsignedlong          atr  
      byte          rgbatr[36]  
 end type  

 Now that we have the structure defined, we can declare our local external function: 

 Function ulong SCardGetStatusChange( &  
  ulong hContext, &  
  ulong dwTimeout, &  
  ref s_readerstate      rgReaderStates[], &  
  ulong pcchReaders &  
 ) Library "winscard.dll" Alias for "SCardGetStatusChangeW"  

 Next, let's look at the code that calls it.   We're assuming here that we've already established the API context and obtained a list of readers on the system from the code in the previous article.

 integer     i  
 long        ll_count  
 ulong       rc  
 s_readerstate          ls_readerstate[]  
 ll_count = UpperBound ( readers )  
 FOR i = 1 TO ll_count  
      ls_readerstate[i].reader = readers[i]  
      ls_readerstate[i].currentstate = 0  
      ls_readerstate[i].atr = 36  
 NEXT  
 rc = SCardGetStatusChange( context, 0, ls_readerstate, ll_count) ;  

Some things to note:

  • The ls_readerstate represents the array of readers that you want to monitor the status of.  As written, this code will monitor every reader currently installed on the system.  This same function can also monitor to determine if the user adds a new reader to the system, but I'm not going to demonstrate that as part of this article.
  • You have some options with regard to the CurrentState parameter on the structure.  If you know the state of the reader (perhaps from a previous call) you can pass that in and the return from the function call will tell you if the status changed.  What I'm doing here is passing SCARD_STATE_UNAWARE (0) to indicate I don't know the state of the reader and so the return will always indicate there is a change and give me the current status.  I'm assuming here that you will be saving off the status you are interested in and detecting the change within the PowerBuilder code.
  • The atr attribute indicates the size of the buffer being passed in the rgbatr attribute.  This should always be 36.
  • The second parameter to the API call is the duration in milliseconds that the call should wait looking for a status change.  I've set this to 0 so that we get an intermediate return.  I'm assuming here that you'll add the code to an event/function triggered by a timer call so that it runs on a regular basis.

As this code is written, the eventstate attribute of the structure will tell you the current state of the reader.  Here's an example from my system:

The eventstate value needs to be interpreted as an 8 character hexidecimal value.  The first half of the value (first 4 characters) is a count, the meaning of which depends how the call was made.  For our purposes, we don't care about that value.  The second half (last 4 characters) contains the status information we're looking for.  More details, including the values for the flags for the second half of the value can be found at: Reader State.  

Looking at these two specific values, the one for the first reader is 131106. In hexidecimal that is 0002 0022.  The first half (0002 is the count which we can ignore.  The second half (0022) is the sum of SCARD_STATE_CHANGED (2) which we will always get as this code is written and SCARD_STATE_PRESENT (20) which indicates that there is a smart card installed in that reader.  The value for the second reader is 65554.  In hexidecimal that is 0001 0012.  Once again we can ignore the first half of the value (0001).  The second half (0012) is once again composed of SCARD_STATE_CHANGED (2) and another value, this time SCARD_STATE_EMPTY (10) which shows that reader is empty.

What I'm not showing here is parsing the values, tracking the status of each reader, and using a timer event or timer object to re-evaluate the status on a regular basis.  I'm assuming the reader can take it from here.

 

Comments (0)
There are no comments posted here yet

Find Articles by Tag

Encryption RibbonBar Builder GhostScript Installation Database Table Debugging API DevOps .NET Assembly Variable OAuth 2.0 Resize Windows 10 Icons SnapObjects DragDrop Import JSON SVN Encoding Syntax IDE PBVM RibbonBar Messagging JSONGenerator Source Code 32-bit CrypterObject Excel Text Array Bug Trial SqlExecutor Open Source Jenkins Repository Source Control Export SQL Server Windows OS PowerBuilder Event Menu Web Service Proxy MessageBox Window SOAP Linux OS PDF RESTClient Platform CI/CD SqlModelMapper Import UI Database Object Design NativePDF PowerServer Web Performance Database Painter .NET DataStore Database Table Data COM .NET Std Framework JSONParser InfoMaker Data License PowerScript (PS) Model Service Web API DataWindow Git Testing Configuration Charts DataWindow JSON PowerBuilder (Appeon) TortoiseGit SnapDevelop Debugger Icon Sort RichTextEdit Control Database Profile Transaction DataType OrcaScript PDFlib Outlook Oracle PBNI C# UI Themes Database ODBC OAuth Expression WinAPI Stored Procedure SQL Error Android Debug File Event Handler Branch & Merge ActiveX Elevate Conference XML Authorization PostgreSQL CoderObject Export JSON Event Handling REST JSON Deployment TreeView PFC OLE HTTPClient External Functions Automated Testing BLOB Script TLS/SSL UI Modernization PowerBuilder Compiler Database Connection Validation Graph Database Table Schema PBDOM WebBrowser Filter 64-bit PostgreSQL ODBC driver Visual Studio iOS Class Azure Mobile TFS SDK Application Authentication DLL Migration PowerServer Mobile Interface