internal static extern int SCardTransmit(IntPtr hCard, [In] ref SCard_IO_Request pioSendPci, byte[] pbSendBuffer, UInt32 cbSendLength, ref SCard_IO_Request pioRecvPci, [Out] byte[] pbRecvBuffer, ref UInt32 pcbRecvLength );
/// <summary> /// Wraps the PCSC function /// LONG SCardTransmit( /// SCARDHANDLE hCard, /// LPCSCARD_I0_REQUEST pioSendPci, /// LPCBYTE pbSendBuffer, /// DWORD cbSendLength, /// LPSCARD_IO_REQUEST pioRecvPci, /// LPBYTE pbRecvBuffer, /// LPDWORD pcbRecvLength /// ); /// </summary> /// <param name="ApduCmd">APDUCommand object with the APDU to send to the card</param> /// <returns>An APDUResponse object with the response from the card</returns> public override APDUResponse Transmit(APDUCommand ApduCmd) { uint RecvLength = (uint) (ApduCmd.Le + APDUResponse.SW_LENGTH); byte[] ApduBuffer = null; byte[] ApduResponse = new byte[RecvLength]; SCard_IO_Request ioRequest = new SCard_IO_Request(); ioRequest.m_dwProtocol = m_nProtocol; ioRequest.m_cbPciLength = 8; SCard_IO_Request ioResponse = new SCard_IO_Request(); ioResponse.m_dwProtocol = m_nProtocol; ioResponse.m_cbPciLength = 8; // Build the command APDU if (ApduCmd.Data == null) { ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + ((ApduCmd.Le != 0) ? 1 : 0)]; if (ApduCmd.Le != 0) ApduBuffer[4] = (byte) ApduCmd.Le; } else { ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + 1 + ApduCmd.Data.Length + ((ApduCmd.Le != 0) ? 1 : 0)]; for (int nI = 0; nI < ApduCmd.Data.Length; nI++) ApduBuffer[APDUCommand.APDU_MIN_LENGTH + 1 + nI] = ApduCmd.Data[nI]; ApduBuffer[APDUCommand.APDU_MIN_LENGTH] = (byte) ApduCmd.Data.Length; if (ApduCmd.Le != 0) ApduBuffer[ApduBuffer.Length - 1] = (byte)ApduCmd.Le; } ApduBuffer[0] = ApduCmd.Class; ApduBuffer[1] = ApduCmd.Ins; ApduBuffer[2] = ApduCmd.P1; ApduBuffer[3] = ApduCmd.P2; m_nLastError = SCardTransmit(m_hCard, ref ioRequest, ApduBuffer, (uint) ApduBuffer.Length, ref ioResponse, ApduResponse, ref RecvLength); if (m_nLastError != 0) { string msg = "SCardTransmit error: " + m_nLastError; throw new Exception(msg); } int sw1 = ApduResponse[ApduResponse.Length - 2] & 0xff; int sw2 = ApduResponse[ApduResponse.Length - 1] & 0xff; if (sw1 == 0x6c) //wrong length, read again with correct len { ApduBuffer = new byte[] { ApduCmd.Class, ApduCmd.Ins, ApduCmd.P1, ApduCmd.P2, (byte)sw2 }; ApduResponse = new byte[sw2 + APDUResponse.SW_LENGTH]; RecvLength = (uint)ApduResponse.Length; m_nLastError = SCardTransmit(m_hCard, ref ioRequest, ApduBuffer, (uint)ApduBuffer.Length, ref ioResponse, ApduResponse, ref RecvLength); if (m_nLastError != 0) { string msg = "SCardTransmit error: " + m_nLastError; throw new Exception(msg); } sw1 = ApduResponse[ApduResponse.Length - 2] & 0xff; sw2 = ApduResponse[ApduResponse.Length - 1] & 0xff; } MemoryStream ms = new MemoryStream(); ms.Write(ApduResponse, 0, ApduResponse.Length - APDUResponse.SW_LENGTH); //while has remaining bytes to be read while (sw1 == 0x61) { ApduBuffer = new byte[] { 0, 0xc0, 0, 0, (byte)sw2 }; //read sw2 number of bytes ApduResponse = new byte[sw2 + APDUResponse.SW_LENGTH]; RecvLength = (uint)ApduResponse.Length; m_nLastError = SCardTransmit(m_hCard, ref ioRequest, ApduBuffer, (uint)ApduBuffer.Length, ref ioResponse, ApduResponse, ref RecvLength); if (m_nLastError != 0) { string msg = "SCardTransmit error: " + m_nLastError; throw new Exception(msg); } sw1 = ApduResponse[ApduResponse.Length - 2] & 0xff; sw2 = ApduResponse[ApduResponse.Length - 1] & 0xff; if (ApduResponse.Length > APDUResponse.SW_LENGTH) { ms.Write(ApduResponse, 0, ApduResponse.Length - APDUResponse.SW_LENGTH); } } ms.WriteByte((byte)sw1); ms.WriteByte((byte)sw2); return new APDUResponse(ms.ToArray()); }
/// <summary> /// Wraps the PCSC function /// LONG SCardTransmit( /// SCARDHANDLE hCard, /// LPCSCARD_I0_REQUEST pioSendPci, /// LPCBYTE pbSendBuffer, /// DWORD cbSendLength, /// LPSCARD_IO_REQUEST pioRecvPci, /// LPBYTE pbRecvBuffer, /// LPDWORD pcbRecvLength /// ); /// </summary> /// <param name="ApduCmd">APDUCommand object with the APDU to send to the card</param> /// <returns>An APDUResponse object with the response from the card</returns> public override APDUResponse Transmit(APDUCommand ApduCmd) { uint RecvLength = (uint)(ApduCmd.Le + APDUResponse.SW_LENGTH); byte[] ApduBuffer = null; byte[] ApduResponse = new byte[RecvLength]; SCard_IO_Request ioRequest = new SCard_IO_Request(); ioRequest.m_dwProtocol = m_nProtocol; ioRequest.m_cbPciLength = 8; SCard_IO_Request ioResponse = new SCard_IO_Request(); ioResponse.m_dwProtocol = m_nProtocol; ioResponse.m_cbPciLength = 8; // Build the command APDU if (ApduCmd.Data == null) { ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + ((ApduCmd.Le != 0) ? 1 : 0)]; if (ApduCmd.Le != 0) { ApduBuffer[4] = (byte)ApduCmd.Le; } } else { ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + 1 + ApduCmd.Data.Length + ((ApduCmd.Le != 0) ? 1 : 0)]; for (int nI = 0; nI < ApduCmd.Data.Length; nI++) { ApduBuffer[APDUCommand.APDU_MIN_LENGTH + 1 + nI] = ApduCmd.Data[nI]; } ApduBuffer[APDUCommand.APDU_MIN_LENGTH] = (byte)ApduCmd.Data.Length; if (ApduCmd.Le != 0) { ApduBuffer[ApduBuffer.Length - 1] = (byte)ApduCmd.Le; } } ApduBuffer[0] = ApduCmd.Class; ApduBuffer[1] = ApduCmd.Ins; ApduBuffer[2] = ApduCmd.P1; ApduBuffer[3] = ApduCmd.P2; m_nLastError = SCardTransmit(m_hCard, ref ioRequest, ApduBuffer, (uint)ApduBuffer.Length, ref ioResponse, ApduResponse, ref RecvLength); if (m_nLastError != 0) { string msg = "SCardTransmit error: " + m_nLastError; throw new Exception(msg); } int sw1 = ApduResponse[ApduResponse.Length - 2] & 0xff; int sw2 = ApduResponse[ApduResponse.Length - 1] & 0xff; if (sw1 == 0x6c) //wrong length, read again with correct len { ApduBuffer = new byte[] { ApduCmd.Class, ApduCmd.Ins, ApduCmd.P1, ApduCmd.P2, (byte)sw2 }; ApduResponse = new byte[sw2 + APDUResponse.SW_LENGTH]; RecvLength = (uint)ApduResponse.Length; m_nLastError = SCardTransmit(m_hCard, ref ioRequest, ApduBuffer, (uint)ApduBuffer.Length, ref ioResponse, ApduResponse, ref RecvLength); if (m_nLastError != 0) { string msg = "SCardTransmit error: " + m_nLastError; throw new Exception(msg); } sw1 = ApduResponse[ApduResponse.Length - 2] & 0xff; sw2 = ApduResponse[ApduResponse.Length - 1] & 0xff; } MemoryStream ms = new MemoryStream(); ms.Write(ApduResponse, 0, ApduResponse.Length - APDUResponse.SW_LENGTH); //while has remaining bytes to be read while (sw1 == 0x61) { ApduBuffer = new byte[] { 0, 0xc0, 0, 0, (byte)sw2 }; //read sw2 number of bytes ApduResponse = new byte[sw2 + APDUResponse.SW_LENGTH]; RecvLength = (uint)ApduResponse.Length; m_nLastError = SCardTransmit(m_hCard, ref ioRequest, ApduBuffer, (uint)ApduBuffer.Length, ref ioResponse, ApduResponse, ref RecvLength); if (m_nLastError != 0) { string msg = "SCardTransmit error: " + m_nLastError; throw new Exception(msg); } sw1 = ApduResponse[ApduResponse.Length - 2] & 0xff; sw2 = ApduResponse[ApduResponse.Length - 1] & 0xff; if (ApduResponse.Length > APDUResponse.SW_LENGTH) { ms.Write(ApduResponse, 0, ApduResponse.Length - APDUResponse.SW_LENGTH); } } ms.WriteByte((byte)sw1); ms.WriteByte((byte)sw2); return(new APDUResponse(ms.ToArray())); }