public byte[] GetAttribute(uint attribId) { if (_hContext == IntPtr.Zero) { throw new SCardException("No card reader context established. Must call SCard.EstablishContext() first."); } if (_hCard == IntPtr.Zero) { throw new SCardException("Not connected to card. Must call SCard.Connect() method first."); } byte[] attr = null; UInt32 attrLen = 0; // call get attrib to locate the attribute and receive the size of // the buffer that needs to be allocated int rtn = SCardDll.SCardGetAttrib(_hCard, attribId, attr, ref attrLen); EvalReturnCode(rtn); if (attrLen != 0) { // allocate the buffer based on size returned by previous call attr = new byte[attrLen]; // call again to get the actual data this time copied into our buffer int rtn2 = SCardDll.SCardGetAttrib(_hCard, attribId, attr, ref attrLen); EvalReturnCode(rtn2); } return(attr); }
/// <summary> /// Terminates a connection previously opened between the calling application and a smart card in the target reader. /// </summary> /// <param name="disposition">Action to take on the card in the connected reader on close.</param> public void Disconnect(DispositionOptions disposition) { if (_hCard != IntPtr.Zero) { int rtn = SCardDll.SCardDisconnect(_hCard, (UInt32)disposition); EvalReturnCode(rtn); _hCard = IntPtr.Zero; } }
/// <summary> /// Closes an established resource manager context, freeing any resources allocated under that context. /// </summary> public void ReleaseContext() { if (_hContext != IntPtr.Zero) { int rtn = SCardDll.SCardReleaseContext(_hContext); EvalReturnCode(rtn); _hContext = IntPtr.Zero; } }
/// <summary> /// Establishes the resource manager context (the scope) within which database operations are performed. /// </summary> /// <param name="Scope">Scope of the resource manager context.</param> public void EstablishContext(ScopeOptions Scope) { if (_hContext != IntPtr.Zero) { throw new SCardException("Context already established. Must call SCard.ReleaseContext() first."); } IntPtr hContext = IntPtr.Zero; int rtn = SCardDll.SCardEstablishContext((UInt32)Scope, IntPtr.Zero, IntPtr.Zero, ref hContext); EvalReturnCode(rtn); _hContext = hContext; }
/// <summary> /// Completes a previously declared transaction, allowing other applications to resume interactions with the card. /// </summary> /// <param name="disposition">Action to take on the card in the connected reader on close.</param> public void EndTransaction(DispositionOptions disposition) { if (_hContext == IntPtr.Zero) { throw new SCardException("No card reader context established. Must call SCard.EstablishContext() first."); } if (_hCard == IntPtr.Zero) { throw new SCardException("Not connected to card. Must call SCard.Connect() method first."); } int rtn = SCardDll.SCardEndTransaction(_hCard, (UInt32)disposition); EvalReturnCode(rtn); }
/// <summary> /// Establishes a connection (using a specific resource manager context) between the calling application and a smart card contained by a specific reader. If no card exists in the specified reader, an error is returned. /// </summary> /// <param name="readerName">The name of the reader that contains the target card.</param> /// <param name="shareMode">A flag that indicates whether other applications may form connections to the card.</param> /// <param name="preferredProtocols">A bitmask of acceptable protocols for the connection. Possible values may be combined with the OR operation.</param> public void Connect(string readerName, ShareModeOptions shareMode, ProtocolOptions preferredProtocols) { if (_hContext == IntPtr.Zero) { throw new SCardException("No card reader context established. Must call SCard.EstablishContext() first."); } if (_hCard != IntPtr.Zero) { throw new SCardException("Already connected to card. Must call SCard.Disconnect() first."); } IntPtr hCard = IntPtr.Zero; int rtn = SCardDll.SCardConnectA(_hContext, readerName, (UInt32)shareMode, (UInt32)preferredProtocols, ref hCard, ref _protocol); EvalReturnCode(rtn); _hCard = hCard; }
/// <summary> /// Sends a service request to the smart card and expects to receive data back from the card. /// </summary> /// <param name="apdu">The SmartCard ADPU command and response object.</param> /// <returns>adpu</returns> public SCardAdpu Transmit(SCardAdpu apdu) { if (_hContext == IntPtr.Zero) { throw new SCardException("No card reader context established. Must call SCard.EstablishContext() first."); } if (_hCard == IntPtr.Zero) { throw new SCardException("Not connected to card. Must call SCard.Connect() method first."); } byte[] send = apdu.GetSendBuffer(); byte[] recv = new byte[apdu.GetReceiveBufferSize()]; int recvLen = recv.Length; // this is an in/out value SCARD_IO_REQUEST ioRequest = new SCARD_IO_REQUEST(); ioRequest.dwProtocol = (uint)_protocol; ioRequest.cbPciLength = 8; IntPtr pioRecvPci = IntPtr.Zero; Debug.WriteLine("SCardTransmit-ADPU-send: " + ArrayUtils.HexEncode(send)); int rtn = SCardDll.SCardTransmit(_hCard, ref ioRequest, ref send[0], send.Length, pioRecvPci, ref recv[0], ref recvLen); EvalReturnCode(rtn); // resize the array if the bytes received are less than the buffer size if (recvLen < recv.Length) { Array.Resize <byte>(ref recv, (int)recvLen); } Debug.WriteLine("SCardTransmit-ADPU-recv: " + ArrayUtils.HexEncode(recv)); // update the apdu object with the receive data apdu.SetReceiveData(recv); return(apdu); }
/// <summary> /// Provides the list of named smart cards previously introduced to the system by the user. /// </summary> /// <remarks>SmartCards may not be available by Windows when accessing the machine via terminal services.</remarks> /// <returns>An array of strings contains the name of each SmartCard.</returns> public string[] ListCards() { if (_hContext == IntPtr.Zero) { throw new SCardException("No card reader context established. Must call SCard.EstablishContext() first."); } // make the first call to get the size of the string we need to allocate and use in the second call UInt32 pchCards = 0; int rtn1 = SCardDll.SCardListCardsA(_hContext, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref pchCards); EvalReturnCode(rtn1); IntPtr szListCards = IntPtr.Zero; StringBuilder b = new StringBuilder(); try { // allocate an unmanaged string szListCards = Marshal.AllocHGlobal((int)pchCards); int rtn2 = SCardDll.SCardListCardsA(_hContext, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, szListCards, ref pchCards); EvalReturnCode(rtn2); for (int i = 0; i < pchCards; i++) { b.Append((char)Marshal.ReadByte(szListCards, i)); } } finally { if (szListCards != IntPtr.Zero) { Marshal.FreeHGlobal(szListCards); } } return(b.ToString().Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries)); }