/// <summary> /// Terminates all connections for given card. /// </summary> /// <remarks> /// The card very likely is not attached to the cardreader at the moment of execution, /// so SCARD_LEAVE_CARD is used here to avoid error log messages from underlying winscard api. /// </remarks> private OperationResult DisconnectCardMultiHandlesAware(Card cardForDisconnect) { var currentHandle = cardForDisconnect.ConnectionHandle; // disconnect first (current) handle var mainReturnCode = WinscardWrapper.SCardDisconnect(cardForDisconnect.ConnectionHandle, WinscardWrapper.SCARD_LEAVE_CARD); var mainDisconnectResult = ReturnCodeManager.GetErrorMessage(mainReturnCode); Logger.TraceEvent(TraceEventType.Verbose, 0, "First handler disconnect result: {0}", mainDisconnectResult.StatusDescription); // disconnect the rest handles if (mainDisconnectResult.IsSuccessful) { var restHandlers = _cardConnectionManager.GetConnections(cardForDisconnect.InternalUid); Logger.TraceEvent(TraceEventType.Verbose, 0, "Card has {0} handlers", restHandlers.Length); foreach (var handleToDisconnect in restHandlers.Where(x => x != currentHandle)) { var returnCode = WinscardWrapper.SCardDisconnect(handleToDisconnect, WinscardWrapper.SCARD_LEAVE_CARD); var result = ReturnCodeManager.GetErrorMessage(returnCode); Logger.TraceEvent(TraceEventType.Verbose, 0, "Card handler disconnect result: {0}", result.StatusDescription); } _cardConnectionManager.CardDisconnected(cardForDisconnect.InternalUid); } cardForDisconnect.ConnectionHandle = IntPtr.Zero; return(mainDisconnectResult); }
/// <summary> /// Establish Context of Resource Manager. /// </summary> public OperationResult EstablishContext() { lock (_locker) { if (_contextManager.IsContextExist(Thread.CurrentThread.ManagedThreadId)) { Logger.TraceEvent(TraceEventType.Verbose, 0, "Context is already established."); Logger.Flush(); return(new OperationResult(true, WinscardWrapper.SCARD_S_SUCCESS, null, null)); } IntPtr resourceManagerContext; IntPtr notUsed1 = IntPtr.Zero; IntPtr notUsed2 = IntPtr.Zero; int returnCode = WinscardWrapper.SCardEstablishContext(WinscardWrapper.SCARD_SCOPE_USER, notUsed1, notUsed2, out resourceManagerContext); if (returnCode == WinscardWrapper.SCARD_S_SUCCESS) { Logger.TraceEvent(TraceEventType.Verbose, 0, "Context established"); Logger.Flush(); _contextManager.AddContext(Thread.CurrentThread.ManagedThreadId, resourceManagerContext); } return(ReturnCodeManager.GetErrorMessage(returnCode)); } }
/// <summary> /// The function provides the current status of a smart card in a reader. /// </summary> public OperationResult GetCardState(Card cardToRead) { if (cardToRead == null) { throw new ArgumentNullException("cardToRead"); } var sizeOfReadersListStructure = 0; var cardStateStatus = 0; var dwActProtocol = 0; var tmpAtrBytes = new byte[257]; var tmpAtrLen = 32; var returnCode = WinscardWrapper.SCardStatus(cardToRead.ConnectionHandle, cardToRead.CardreaderName, ref sizeOfReadersListStructure, ref cardStateStatus, ref dwActProtocol, ref tmpAtrBytes[0], ref tmpAtrLen); OperationResult result = ReturnCodeManager.GetErrorMessage(returnCode); if (result.IsSuccessful) { cardToRead.State = new CardState(cardStateStatus); cardToRead.Atr = tmpAtrBytes.Take(tmpAtrLen).ToArray(); cardToRead.Protocol = dwActProtocol; } return(result); }
public OperationResult WaitForChanges(ref CardreaderStatus[] statuses) { var resourceManagerContext = EstablishContextIfNotEstablished(); var scardStatuses = new WinscardWrapper.SCARD_READERSTATE[statuses.Length]; for (var i = 0; i < statuses.Length; i++) { scardStatuses[i] = statuses[i].ToScardStatus(); } Logger.TraceEvent(TraceEventType.Verbose, 0, "SCardGetStatusChange started"); Logger.Flush(); var returnCode = WinscardWrapper.SCardGetStatusChange( resourceManagerContext, WinscardWrapper.INFINITE, scardStatuses, scardStatuses.Length); Logger.TraceEvent(TraceEventType.Verbose, 0, "SCardGetStatusChange ended"); Logger.Flush(); var operationResult = ReturnCodeManager.GetErrorMessage(returnCode); if (operationResult.IsSuccessful) { for (var i = 0; i < statuses.Length; i++) { statuses[i].NewStatusFlags = scardStatuses[i].dwEventState; } } return(operationResult); }
private OperationResult ReleaseContext(IntPtr context) { int returnCode = WinscardWrapper.SCardReleaseContext(context); var operationResult = ReturnCodeManager.GetErrorMessage(returnCode); return(operationResult); }
/// <summary> /// Return card readers list. /// </summary> public OperationResult GetCardReadersList(out string[] readersList) { var resourceManagerContext = EstablishContextIfNotEstablished(); readersList = new string[0]; OperationResult result; int sizeOfReadersListStructure = 0; int returnCode = WinscardWrapper.SCardListReaders(resourceManagerContext, null, null, ref sizeOfReadersListStructure); if (returnCode != WinscardWrapper.SCARD_S_SUCCESS) { result = ReturnCodeManager.GetErrorMessage(returnCode); } else { // Fill reader list var cardReadersList = new byte[sizeOfReadersListStructure]; returnCode = WinscardWrapper.SCardListReaders(resourceManagerContext, null, cardReadersList, ref sizeOfReadersListStructure); if (returnCode != WinscardWrapper.SCARD_S_SUCCESS) { result = ReturnCodeManager.GetErrorMessage(returnCode); } else { // Convert to strings readersList = ConvertReadersBuffer(cardReadersList); result = ReturnCodeManager.GetErrorMessage(returnCode); } } return(result); }
/// <summary> /// Establishing a connection to smart card contained by a specific reader. /// <param name="cardreaderName">Card reader name to connection.</param> /// </summary> public ConnectResult Connect(string cardreaderName, Guid?idOverride = null) { var resourceManagerContext = EstablishContextIfNotEstablished(); IntPtr cardConnectionHandle; int connectionProtocolType; int returnCode = WinscardWrapper.SCardConnect( resourceManagerContext, cardreaderName, WinscardWrapper.SCARD_SHARE_SHARED, WinscardWrapper.SCARD_PROTOCOL_T0 | WinscardWrapper.SCARD_PROTOCOL_T1, out cardConnectionHandle, out connectionProtocolType); var operationResult = ReturnCodeManager.GetErrorMessage(returnCode); var connectResult = new ConnectResult(operationResult); if (operationResult.IsSuccessful) { var newCard = new Card( Thread.CurrentThread.ManagedThreadId, cardConnectionHandle, cardreaderName, connectionProtocolType); _cardConnectionManager.AddConnection( idOverride ?? newCard.InternalUid, Thread.CurrentThread.ManagedThreadId, cardConnectionHandle); connectResult.ConnectedCard = newCard; } return(connectResult); }
private ApduResponse SendAPDU(Card card, byte[] bytesToSend, int expectedRequestLength) { Logger.TraceEvent(TraceEventType.Verbose, 0, "SendAPDU started"); Logger.TraceEvent(TraceEventType.Verbose, 0, "bytesToSend: {0}", BitConverter.ToString(bytesToSend)); Logger.TraceEvent(TraceEventType.Verbose, 0, "card connection handle: {0}", card.ConnectionHandle); Logger.Flush(); IntPtr cardConnectionHandle = card.ConnectionHandle; // establish a new temporary connection in case of context mismatch if (card.ThreadId != Thread.CurrentThread.ManagedThreadId) { Logger.TraceEvent(TraceEventType.Verbose, 0, string.Format("Card context mismatch. Original thread: {0}. Current thread: {1}", card.ThreadId, Thread.CurrentThread.ManagedThreadId)); Logger.Flush(); if (!_cardConnectionManager.IsConnectionExist(card.InternalUid, Thread.CurrentThread.ManagedThreadId)) { // establish a new connection var connectionResult = Connect(card.CardreaderName, card.InternalUid); if (!connectionResult.IsSuccessful) { return(new ApduResponse { ReturnCode = connectionResult.StatusCode, RecvBuff = new byte[0], ResponseLength = 0 }); } // use a handle of a new connection cardConnectionHandle = connectionResult.ConnectedCard.ConnectionHandle; Logger.TraceEvent(TraceEventType.Verbose, 0, "SendAPDU: new connection established. Handle: " + cardConnectionHandle); } else { cardConnectionHandle = _cardConnectionManager .GetConnection(card.InternalUid, Thread.CurrentThread.ManagedThreadId); Logger.TraceEvent(TraceEventType.Verbose, 0, "SendAPDU: existed card context found. Handle: " + cardConnectionHandle); } } var recvBuff = new byte[500]; WinscardWrapper.SCARD_IO_REQUEST pioSendRequest; pioSendRequest.dwProtocol = card.Protocol; pioSendRequest.cbPciLength = PciLength; int returnCode = WinscardWrapper.SCardTransmit( cardConnectionHandle, ref pioSendRequest, ref bytesToSend[0], bytesToSend.Length, ref pioSendRequest, ref recvBuff[0], ref expectedRequestLength); Logger.TraceEvent(TraceEventType.Verbose, 0, "SendAPDU ended. Return code: " + returnCode); Logger.Flush(); //http://msdn.microsoft.com/en-us/library/windows/desktop/aa379804(v=vs.85).aspx //The pcbRecvLength should be at least n+2 and will be set to n+2 upon return. var result = new ApduResponse { RecvBuff = recvBuff, ResponseLength = expectedRequestLength, ReturnCode = returnCode }; return(result); }