/// <summary>
        /// The SCardTransmit function sends a service request to the smart card and expects to receive data back from the card.
        /// </summary>
        /// <param name="sendBuffer">
        /// The actual data to be written to the card.
        /// </param>
        /// <param name="sendLength">
        /// The length, in bytes, of the sendBuffer parameter.
        /// </param>
        /// <param name="responseBuffer">
        /// Returned data from the card.
        /// </param>
        /// <param name="responseLength">
        /// Supplies the length, in bytes, of the responseBuffer parameter and receives the actual
        /// number of bytes received from the smart card.
        /// </param>
        public void Transmit(byte[] sendBuffer, int sendLength, byte[] responseBuffer, ref int responseLength)
        {
            SCARD_IO_REQUEST SCARD_PCI;

            SCARD_PCI.dwProtocol  = (uint)activeSCardProtocol;
            SCARD_PCI.cbPciLength = 8;

            Trace.WriteLineIf(this.scardTrace, HexFormatting.Dump("--> C-APDU: 0x", sendBuffer, sendLength, 16, ValueFormat.HexASCII));

            int ret = WinSCardAPIWrapper.SCardTransmit(phCARD, ref SCARD_PCI, sendBuffer,
                                                       sendLength,
                                                       IntPtr.Zero,
                                                       responseBuffer,
                                                       ref responseLength);

            if (ret == 0)
            {
                RespApdu respApdu = new RespApdu(responseBuffer, responseLength);
                Trace.WriteLineIf(scardTrace, respApdu.ToString());
            }
            else
            {
                throw new WinSCardException(scardTrace, "SCard.Transmit", ret);
            }
        }
        /// <summary>
        /// The SCardGetAttrib function gets the current reader attributes.
        /// It does not affect the state of the reader, driver, or card.
        /// </summary>
        /// <param name="attrId">
        /// Identifier for the attribute to get.
        /// </param>
        /// <param name="responseBuffer">
        /// The response buffer.
        /// </param>
        /// <param name="responseLength">
        /// Supplies the length of the responseBuffer in bytes, and receives the actual length
        /// of the received attribute.
        /// </param>
        public void GetAttrib(uint attrId, byte[] responseBuffer, ref int responseLength)
        {
            Trace.WriteLineIf(this.scardTrace, string.Format("    SCard.SCardGetAttrib(AttrId: {0})", (SCARD_ATTR)attrId));

            int ret = WinSCardAPIWrapper.SCardGetAttrib(phCARD, (uint)attrId, responseBuffer, ref responseLength);

            if (ret == 0)
            {
                Trace.WriteLineIf(this.scardTrace, HexFormatting.Dump("        Attr. Value: 0x", responseBuffer, responseLength, 16, ValueFormat.HexASCII));
            }
            else
            {
                throw new WinSCardException(scardTrace, "SCard.Control", ret);
            }
        }
        /// <summary>
        /// The SCardReconnect function reestablishes an existing connection between the calling application and
        /// a smart card. This function moves a card handle from direct access to general access, or acknowledges
        /// and clears an error condition that is preventing further access to the card.
        /// </summary>
        /// <param name="dwShareMode">
        /// A flag that indicates whether other applications may form connections to the card.
        /// </param>
        /// <param name="dwPrefProtocol">
        /// A bitmask of acceptable protocols for the connection. Possible values may be combined with the OR operation.
        /// </param>
        /// <param name="disconnectAction">
        /// Action to take on the card in the connected reader on close.
        /// </param>
        /// <returns>
        /// If the function succeeds, the function returns SCARD_S_SUCCESS.
        /// If the function fails, it returns an error code.
        /// </returns>
        public void Reconnect(SCARD_SHARE_MODE dwShareMode, SCARD_PROTOCOL dwPrefProtocol, SCARD_DISCONNECT disconnectAction)
        {
            int ret = WinSCardAPIWrapper.SCardReconnect(phCARD, (uint)dwShareMode, (uint)dwPrefProtocol,
                                                        (uint)disconnectAction, out activeSCardProtocol);

            if (ret == 0)
            {
                Trace.WriteLineIf(scardTrace, String.Format("    SCard.Reconnect(SHARE_MODE.{0}, SCARD_PROTOCOL.{1}, SCARD_DISCONNECT.{2} )",
                                                            dwShareMode, (SCARD_PROTOCOL)dwPrefProtocol, (SCARD_DISCONNECT)disconnectAction));
                Trace.WriteLineIf(scardTrace, String.Format("        Active Protocol: SCARD_PROTOCOL.{0} ", (SCARD_PROTOCOL)activeSCardProtocol));
                Trace.WriteLineIf(this.TraceSCard, HexFormatting.Dump("        ATR: 0x", this.Atr, this.Atr.Length, 24));
            }
            else
            {
                throw new WinSCardException(scardTrace, "SCard.Reconnect", ret);
            }
        }
        /// <summary>
        /// The SCardConnect function 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="szReader">
        /// The name of the reader that contains the target card.
        /// </param>
        /// <param name="dwShareMode">
        /// A flag that indicates whether other applications may form connections to the card.
        /// </param>
        /// <param name="dwPrefProtocol">
        /// A bitmask of acceptable protocols for the connection. Possible values may be combined with the OR operation.
        /// </param>
        public void Connect(string szReader, SCARD_SHARE_MODE dwShareMode, SCARD_PROTOCOL dwPrefProtocol)
        {
            int ret = WinSCardAPIWrapper.SCardConnect(phContext, szReader, (uint)dwShareMode, (uint)dwPrefProtocol, out phCARD, out activeSCardProtocol);

            if (ret == 0)
            {
                connectedReaderName = szReader;
                Trace.WriteLineIf(scardTrace, String.Format("    SCard.Connect({0}, SHARE_MODE.{1}, SCARD_PROTOCOL.{2})",
                                                            szReader, dwShareMode, (SCARD_PROTOCOL)dwPrefProtocol));
                Trace.WriteLineIf(scardTrace, String.Format("        Active Protocol: SCARD_PROTOCOL.{0} ", (SCARD_PROTOCOL)activeSCardProtocol));
                Trace.WriteLineIf(this.TraceSCard, HexFormatting.Dump("        ATR: 0x", this.Atr, this.Atr.Length, 24));
            }
            else
            {
                connectedReaderName = null;
                throw new WinSCardException(scardTrace, "SCard.Connect", ret);
                //Trace.WriteLineIf(pcscTrace, String.Format("    Error: SCardConnect failed with 0x{0:X8}.", ret));
            }
        }
        /// <summary>
        /// The SCardControl function gives you direct control of the reader.
        /// You can call it any time after a successful call to SCardConnect and before
        /// a successful call to SCardDisconnect. The effect on the state of the reader
        /// depends on the control code.
        /// </summary>
        /// <param name="dwControlCode">
        /// Control code for the operation. This value identifies the specific operation to be performed.
        /// </param>
        /// <param name="inBuffer">
        /// A buffer that contains the data required to perform the operation.
        /// This parameter can be null if the dwControlCode parameter specifies an operation that does
        /// not require input data.
        /// </param>
        /// <param name="inBufferLength">
        /// Length of the input buffer.
        /// </param>
        /// <param name="outBuffer">
        /// The output buffer.
        /// </param>
        /// <param name="outBufferSize">
        /// Size, in bytes, of the output buffer.
        /// </param>
        /// <param name="bytesReturned">
        /// Supplies the length, in bytes, of the outBuffer parameter.
        /// </param>
        public void Control(uint dwControlCode, byte[] inBuffer, int inBufferLength, byte[] outBuffer, int outBufferSize, ref int bytesReturned)
        {
            Trace.WriteLineIf(this.scardTrace, string.Format("    SCard.Control (Cntrl Code: 0x{0:X}", dwControlCode));
            //Trace.WriteLineIf( this.scardTrace, HexFormatting.Dump(string.Format( "--> SCard.Control (Cntrl Code: 0x{0:X} ): 0x",
            //                                                    dwControlCode ), inBuffer, inBufferLength, 16, ValueFormat.HexASCII ) );

            int ret = WinSCardAPIWrapper.SCardControl(phCARD,
                                                      dwControlCode,
                                                      inBuffer,
                                                      inBufferLength,
                                                      outBuffer,
                                                      outBufferSize,
                                                      ref bytesReturned);

            if (ret == 0)
            {
                Trace.WriteLineIf(this.scardTrace, HexFormatting.Dump("        Value: 0x", outBuffer, bytesReturned, 16, ValueFormat.HexASCII));
            }
            else
            {
                throw new WinSCardException(scardTrace, "SCard.Control", ret);
            }
        }