Print
Category: PowerBuilder
Hits: 1084

User Rating: 5 / 5

Star ActiveStar ActiveStar ActiveStar ActiveStar Active
 

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:

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.

 

We use cookies which are necessary for the proper functioning of our websites. We also use cookies to analyze our traffic, improve your experience and provide social media features. If you continue to use this site, you consent to our use of cookies.