示例#1
0
        /// <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);
        }
示例#2
0
        /// <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));
            }
        }
示例#3
0
        /// <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);
        }
示例#4
0
        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);
        }
示例#5
0
        private OperationResult ReleaseContext(IntPtr context)
        {
            int returnCode = WinscardWrapper.SCardReleaseContext(context);

            var operationResult = ReturnCodeManager.GetErrorMessage(returnCode);

            return(operationResult);
        }
示例#6
0
        /// <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);
        }
示例#7
0
        /// <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);
        }
示例#8
0
        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);
        }