Smart Cards in .NET, Part 3 - Smart card resource manager
(Page 4 of 6 )
The WinSCard is a sealed class, so you won’t be able to derive from it, but you may refer to it occasionally if you wish to invoke a function directly from your own P/Invoke code. And below, you’ll find code for the SCResMgr.cs that encapsulates the Smart Card resource manager.
using System;
using System.Collections;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace SCLib
{
public sealed class SCResMgr : IDisposable
{
// Methods
public SCResMgr()
{
this.m_fDisposed = false;
this.m_hContext = IntPtr.Zero;
}
private void _Dispose(bool fDisposing)
{
if (!this.m_fDisposed)
{
if (this.m_hContext != IntPtr.Zero)
{
WinSCard.SCardCancel(this.m_hContext);
WinSCard.SCardReleaseContext(this.m_hContext);
this.m_hContext = IntPtr.Zero;
}
this.m_fDisposed = true;
}
}
private int _SplitMultiString(string msz, IList aList)
{
int nTemp;
int nCount = 0;
// For each string
for (int nIter = 0; msz[nIter] != '\0'; nIter = nTemp + 1)
{
nTemp = nIter;
// While not end of String
while (msz[nTemp] != '\0')
{
nTemp++;
}
aList.Add(msz.Substring(nIter, nTemp - nIter));
nCount++;
}
// Return Count
return nCount;
}
~SCResMgr()
{
this._Dispose(false);
}
public void Dispose()
{
this._Dispose(true);
GC.SuppressFinalize(this);
}
// Context Functions
public bool EstablishContext(SCardContextScope nScope)
{
if (this.m_fDisposed)
{
throw new ObjectDisposedException(base.GetType().FullName);
}
if (this.m_hContext != IntPtr.Zero)
{
throw new InvalidOperationException();
}
uint nErrCode = WinSCard.SCardEstablishContext((uint) nScope, IntPtr.Zero, IntPtr.Zero, out this.m_hContext);
// If Service not running
if (nErrCode == 0x8010001d)
{
MessageBox.Show("The ensure that SCardSvr Service is running. PC/SC routines won't be available.");
return false;
}
// else there is some other problem
if (nErrCode != 0)
{
MessageBox.Show(string.Format("SCardEstablishContext failed: 0x{0:X8}", nErrCode));
SCardException.RaiseWin32ResponseCode(nErrCode);
}
return true;
}
public void ReleaseContext()
{
// Sanity Check
if (this.m_fDisposed)
{
throw new ObjectDisposedException(base.GetType().FullName);
}
// Check Context
if (this.m_hContext == IntPtr.Zero)
{
throw new InvalidOperationException();
}
uint nErrCode = WinSCard.SCardReleaseContext(this.m_hContext);
// Set Zero
this.m_hContext = IntPtr.Zero;
// Was there an error
if (nErrCode != 0)
{
SCardException.RaiseWin32ResponseCode(nErrCode);
}
}
public bool IsValidContext()
{
// Sanity Check
if (this.m_fDisposed)
{
throw new ObjectDisposedException(base.GetType().FullName);
}
// Verify Context exists
if (this.m_hContext == IntPtr.Zero)
{
throw new InvalidOperationException();
}
// Call native fxn and return appropriately
uint nErrCode = WinSCard.SCardIsValidContext(this.m_hContext);
if (nErrCode == 0)
{
return true;
}
return false;
}
// Tracking Functions
public void Cancel()
{
if (this.m_hContext == IntPtr.Zero)
{
throw new InvalidOperationException();
}
uint nErrCode = WinSCard.SCardCancel(this.m_hContext);
if (nErrCode != 0)
{
SCardException.RaiseWin32ResponseCode(nErrCode);
}
}
public bool GetStatusChange(int nTimeout, SCStateInfo[] vaSCStates)
{
int nLen = vaSCStates.Length;
WinSCard.SCARD_READERSTATE[] statearray = new WinSCard.SCARD_READERSTATE[nLen];
for (int nIter = 0; nIter < nLen; nIter++)
{
statearray[nIter].szReader = vaSCStates[nIter].sReaderName;
statearray[nIter].pvUserData = IntPtr.Zero;
statearray[nIter].dwCurrentState = (uint) vaSCStates[nIter].nCurrentState;
statearray[nIter].dwEventState = 0;
statearray[nIter].cbAtr = 0;
statearray[nIter].rgbAtr = null;
}
uint nErrCode = WinSCard.SCardGetStatusChange(this.m_hContext, (uint) nTimeout, statearray, (uint) statearray.Length);
if (nErrCode == 0)
{
for (int nLoopCnt = 0; nLoopCnt < nLen; nLoopCnt++)
{
vaSCStates[nLoopCnt].nEventState = (SCStates) statearray[nLoopCnt].dwEventState;
if ((statearray[nLoopCnt].cbAtr > 0) && (statearray[nLoopCnt].rgbAtr != null))
{
vaSCStates[nLoopCnt].vbATR = new byte[statearray[nLoopCnt].cbAtr];
Buffer.BlockCopy(statearray[nLoopCnt].rgbAtr, 0, vaSCStates[nLoopCnt].vbATR, 0, (int) statearray[nLoopCnt].cbAtr);
}
else
{
vaSCStates[nLoopCnt].vbATR = null;
}
}
return true;
}
// If Timeout or SCardCancel happened just bail out
if ((nErrCode == 0x8010000a) || (nErrCode == 0x80100002))
{
return false;
}
// If we reach here there is a problem
SCardException.RaiseWin32ResponseCode(nErrCode);
throw new InvalidProgramException();
}
public bool GetStatusChange(int nTimeout, ref SCStateInfo aSCInfo)
{
SCStateInfo[] infoArray = new SCStateInfo[1] { aSCInfo } ;
bool bStatus = this.GetStatusChange(nTimeout, infoArray);
aSCInfo = infoArray[0];
return bStatus;
}
public bool GetStatusChange(int nTimeout, string sReaderName, SCStates nCurrentState, out SCStates nEventState)
{
SCStateInfo info;
info.sReaderName = sReaderName;
info.nCurrentState = nCurrentState;
info.nEventState = SCStates.Unaware;
info.vbATR = null;
bool bStatus = this.GetStatusChange(nTimeout, ref info);
nEventState = info.nEventState;
return bStatus;
}
// Database Functions
public int ListReaderGroups(IList aReaderGroupsList)
{
// Sanity Check
if (this.m_fDisposed)
{
throw new ObjectDisposedException(base.GetType().FullName);
}
// Sanity Check
if (this.m_hContext == IntPtr.Zero)
{
throw new InvalidOperationException();
}
int nRet = 0;
IntPtr ptrRMgrMem = IntPtr.Zero;
uint nMax = uint.MaxValue;
uint nErrCode = WinSCard.SCardListReaderGroups(this.m_hContext, ref ptrRMgrMem, ref nMax);
// Success
if (nErrCode == 0)
{
string text = Marshal.PtrToStringAuto(ptrRMgrMem, (int) nMax);
nRet = this._SplitMultiString(text, aReaderGroupsList);
nErrCode = WinSCard.SCardFreeMemory(this.m_hContext, ptrRMgrMem);
return nRet;
}
// Error
if (nErrCode == 2148532270)
{
return 0;
}
// Exception
SCardException.RaiseWin32ResponseCode(nErrCode);
return nRet;
}
public int ListReaders(IList aReadersList)
{
return this.ListReaders((string[]) null, aReadersList);
}
public int ListReaders(string sGroup, IList aReadersList)
{
// Sanity Check
if ((sGroup == null) || (sGroup.Length == 0))
{
throw new ArgumentNullException();
}
string[] textArray = new string[1] { sGroup } ;
return this.ListReaders(textArray, aReadersList);
}
public int ListReaders(string[] vsGroups, IList aReadersList)
{
// Sanity Check
if (this.m_fDisposed)
{
throw new ObjectDisposedException(base.GetType().FullName);
}
if (this.m_hContext == IntPtr.Zero)
{
throw new InvalidOperationException();
}
int nReaders = 0;
string text = null;
if ((vsGroups != null) && (vsGroups.Length > 0))
{
string[] textArray = vsGroups;
for (int nIter = 0; nIter < textArray.Length; nIter++)
{
string strTemp = textArray[nIter];
text = text + strTemp;
text = text + '\0';
}
text = text + '\0';
}
IntPtr ptrMem = IntPtr.Zero;
// Autoallocate
uint nMax = uint.MaxValue;
uint nErrCode = WinSCard.SCardListReaders(this.m_hContext, text, ref ptrMem, ref nMax);
// Success
if (nErrCode == 0)
{
string sReaders = Marshal.PtrToStringAuto(ptrMem, (int) nMax);
nReaders = this._SplitMultiString(sReaders, aReadersList);
// Free Autoallocate
nErrCode = WinSCard.SCardFreeMemory(this.m_hContext, ptrMem);
return nReaders;
}
// Couln't find a Reader???
if (nErrCode == 2148532270)
{
return 0;
}
// Report Error
SCardException.RaiseWin32ResponseCode(nErrCode);
return nReaders;
}
// Properties
public IntPtr Context
{
get
{
return this.m_hContext;
}
}
// Fields
private bool m_fDisposed;
private IntPtr m_hContext;
}
}
Next: CardCommand and SelectSmart >>
More .NET Articles
More By Digvijay Chauhan
|
| · | | | · | | | · | | | · | | | · | | | · | | | · | | | · | | | · | | | · | | | · | | | · | | | · | | | · | | | · | | | · | | | · | | | | |
|