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

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