Package uk.co.nimp.scard

Source Code of uk.co.nimp.scard.PcScTerminalManager$Win32PCSC$SCARD_IO_REQUEST

/*
*/
/**
*
* @author
*/

package uk.co.nimp.scard;

import com.atolsystems.atolutilities.AStringUtilities;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.smartcardio.CardException;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.ptr.ByteByReference;
import com.sun.jna.ptr.ShortByReference;
import com.sun.jna.ptr.*;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.ptr.NativeLongByReference;
import com.sun.jna.StringArray;
import com.sun.jna.WString;
import java.io.File;
import java.io.IOException;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;


public class PcScTerminalManager extends GenericTerminalManager {

    static public interface Win32PCSC extends Library {

        /*LONG SCardEstablishContext(
        __in   DWORD dwScope,
        __in   LPCVOID pvReserved1,
        __in   LPCVOID pvReserved2,
        __out  LPSCARDCONTEXT phContext
        );*/
        NativeLong SCardEstablishContext(
                int dwScope,
                Pointer pvReserved1,
                Pointer pvReserved2,
                NativeLongByReference phContext);

        /*LONG SCardReleaseContext(
          __in  SCARDCONTEXT hContext
        );*/
        NativeLong SCardReleaseContext(
              NativeLong hContext);

        /*LONG SCardFreeMemory(
        __in  SCARDCONTEXT hContext,
        __in  LPCVOID pvMem
        );*/
        /*NativeLong SCardFreeMemory(
                NativeLong hContext,
                Pointer pvMem);*/

        /*LONG SCardListReaders(
        __in     SCARDCONTEXT hContext,
        __in     LPCTSTR mszGroups,
        __out    LPTSTR mszReaders,
        __inout  LPDWORD pcchReaders
        );*/
        NativeLong SCardListReadersW(
                NativeLong hContext,
                String mszGroups,
                //PointerByReference mszReaders,
                short[] mszReaders,
                ShortByReference pcchReaders);
        //NativeLong pcchReaders);
        //Short pcchReaders);

        /*typedef struct {
        LPCTSTR szReader;
        LPVOID  pvUserData;
        DWORD   dwCurrentState;
        DWORD   dwEventState;
        DWORD   cbAtr;
        BYTE    rgbAtr[36];
        }SCARD_READERSTATE, *PSCARD_READERSTATE, *LPSCARD_READERSTATE;*/
        public static class SCARD_READERSTATE extends Structure {

            public WString szReader;
            public Pointer pvUserData;
            public int dwCurrentState;
            public int dwEventState;
            public int cbAtr;
            public byte rgbAtr[];//36];
        }

        /*LONG SCardGetStatusChange(
        __in     SCARDCONTEXT hContext,
        __in     DWORD dwTimeout,
        __inout  LPSCARD_READERSTATE rgReaderStates,
        __in     DWORD cReaders
        );*/
        NativeLong SCardGetStatusChangeW(
                NativeLong hContext,
                int dwTimeout,
                SCARD_READERSTATE rgReaderStates[],
                int cReaders);

        /*LONG SCardConnect(
        __in   SCARDCONTEXT hContext,
        __in   LPCTSTR szReader,
        __in   DWORD dwShareMode,
        __in   DWORD dwPreferredProtocols,
        __out  LPSCARDHANDLE phCard,
        __out  LPDWORD pdwActiveProtocol
        );*/
        NativeLong SCardConnectW(
                NativeLong hContext,
                WString szReader,
                int dwShareMode,
                int dwPreferredProtocols,
                NativeLongByReference phCard,
                IntByReference pdwActiveProtocol);

        /*LONG WINAPI SCardReconnect(
          __in       SCARDHANDLE hCard,
          __in       DWORD dwShareMode,
          __in       DWORD dwPreferredProtocols,
          __in       DWORD dwInitialization,
          __out_opt  LPDWORD pdwActiveProtocol
        );*/
        NativeLong SCardReconnect(
                NativeLong hCard,
                int dwShareMode,
                int dwPreferredProtocols,
                int dwInitialization,
                IntByReference pdwActiveProtocol
        );

        /*LONG SCardDisconnect(
        __in  SCARDHANDLE hCard,
        __in  DWORD dwDisposition
        );*/
        NativeLong SCardDisconnect(
                NativeLong hCard,
                int dwDisposition);

        /*LONG SCardStatus(
        __in     SCARDHANDLE hCard,
        __out    LPTSTR szReaderName,
        __inout  LPDWORD pcchReaderLen,
        __out    LPDWORD pdwState,
        __out    LPDWORD pdwProtocol,
        __out    LPBYTE pbAtr,
        __inout  LPDWORD pcbAtrLen
        );*/
        NativeLong SCardStatusW(
                NativeLong hCard,
                WString szReaderName,
                IntByReference pcchReaderLen,
                IntByReference pdwState,
                IntByReference pdwProtocol,
                byte pbAtr[],
                IntByReference pcbAtrLen);

        /*typedef struct {
        DWORD dwProtocol;
        DWORD cbPciLength;
        }SCARD_IO_REQUEST;*/
        public static class SCARD_IO_REQUEST extends Structure {

            public int dwProtocol;
            public int cbPciLength;
        }

        /* LONG SCardTransmit(
        __in     SCARDHANDLE hCard,
        __in     LPCSCARD_IO_REQUEST pioSendPci,
        __in     LPCBYTE pbSendBuffer,
        __in     DWORD cbSendLength,
        __inout  LPSCARD_IO_REQUEST pioRecvPci,
        __out    LPBYTE pbRecvBuffer,
        __inout  LPDWORD pcbRecvLength
        );*/
        NativeLong SCardTransmit(
                NativeLong hCard,
                SCARD_IO_REQUEST pioSendPci,
                byte[] pbSendBuffer,
                int cbSendLength,
                SCARD_IO_REQUEST pioRecvPci,
                byte[] pbRecvBuffer,
                IntByReference pcbRecvLength);

        /* LONG WINAPI SCardGetAttrib(
          __in     SCARDHANDLE hCard,
          __in     DWORD dwAttrId,
          __out    LPBYTE pbAttr,
          __inout  LPDWORD pcbAttrLen
        );*/
        NativeLong SCardGetAttrib(
                NativeLong hCard,
                int dwAttrId,
                byte[] pbAttr,
                IntByReference pcbAttrLen);

    }
    static final Throwable initException;
    static final Win32PCSC win32PCSC;
    static final String CONF_FILE_NAME="PcScTerminalManager.conf";
    static final String LIB_NAME="winscard";

    private static long contextId=0;
    static {
        Throwable ex;
        Win32PCSC trial;
        try {
            trial = (Win32PCSC) Native.loadLibrary(LIB_NAME, Win32PCSC.class);
            ex = null;
        } catch (Throwable e) {
            ex = e;
            trial = null;
        }
        win32PCSC = trial;
        initException = ex;
        if(null==initException){
            try {
                PcScTerminalManager.initContext();
                //GenericTerminalManager.registerTerminalManager(PcScTerminalManager.class);
            } catch (ScardException ex1) {
                Logger.getLogger(PcScTerminalManager.class.getName()).log(Level.SEVERE, null, ex1);
            }
        }
    }

    public PcScTerminalManager(){
    }
    protected String getConfFileName(){
        return CONF_FILE_NAME;
    }
    @Override
    protected void loadConfigurationImpl(File argFile) throws Exception {
        if(null!=initException)
            throw new Exception(initException);
        if(null==win32PCSC)
            throw new NullPointerException(LIB_NAME+" could not be loaded");
    }

    static public /*synchronized*/ void initContext() throws ScardException {
  if (contextId == 0) {
            NativeLongByReference phContext = new NativeLongByReference();
            phContext.setValue(new NativeLong((long) 0));
            NativeLong status = win32PCSC.SCardEstablishContext(SCARD_SCOPE_USER, Pointer.NULL, Pointer.NULL, phContext);
            Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    if(0!=contextId)
                        win32PCSC.SCardReleaseContext(new NativeLong(contextId));
                }
            });
            if (0 != status.longValue()) {
                throw new PcScException(status.intValue());
            }
      contextId = phContext.getValue().longValue();
  }
    }

    /**
     *
     * @param win32Status
     * @return the equivalent GenericTerminal.State
     */
    static protected GenericTerminal.State win32Status2GenericTerminalState(byte win32Status){
        if(SCARD_ABSENT==win32Status)
            return GenericTerminal.State.CARD_ABSENT;
        return GenericTerminal.State.CARD_PRESENT;
    }

    /**
     *
     * @param win32Protocol
     * @return the equivalent GenericTerminal protocol code
     */
    static protected int win32Protocol2GenericTerminalProtocol(byte win32Protocol){
        switch(win32Protocol)
        {
            case SCARD_PROTOCOL_T0:
                return GenericTerminal.PROTOCOL_T_0;
            case SCARD_PROTOCOL_T1:
                return GenericTerminal.PROTOCOL_T_1;
            default:
                return GenericTerminal.PROTOCOL_UNDEFINED;
        }
    }

    @Override
    public List<GenericTerminal> list() throws ScardException {
        ShortByReference requiredSize = new ShortByReference();
        NativeLong status = win32PCSC.SCardListReadersW(new NativeLong(contextId), null, null, requiredSize);
        List<GenericTerminal> terminalsList;
        if (SCARD_E_NO_READERS_AVAILABLE == status.longValue()) {
            terminalsList = new ArrayList<GenericTerminal>(0);
            return Collections.unmodifiableList(terminalsList);
        }
        if (SCARD_S_SUCCESS != status.longValue()) {
            throw new PcScException(status.intValue());
        }
        short nativeOut[] = new short[requiredSize.getValue()];
        status = win32PCSC.SCardListReadersW(new NativeLong(contextId), null, nativeOut, requiredSize);
        if (SCARD_S_SUCCESS != status.longValue()) {
            throw new PcScException(status.intValue());
        }
        String[] readerNames=AStringUtilities.shortsToStrings(nativeOut);
        terminalsList = new ArrayList<GenericTerminal>(readerNames.length);


        for (int i=0;i<readerNames.length;i++) {
            String name=readerNames[i];
            GenericTerminal terminal = getTerminalImpl(name);
            terminalsList.add(terminal);
            //byte[] terminalStatus={0,0};
            //SCardStatus(contextId, terminalStatus);
            int[] terminalStatus = SCardGetStatusChange(contextId, 0,
        new int[] {SCARD_STATE_UNAWARE}, new String[] {name});

            GenericTerminal.State newState=win32Status2GenericTerminalState((byte)terminalStatus[0]);
            switch(newState){
                case CARD_ABSENT:
                    if((GenericTerminal.State.CARD_PRESENT==terminal.state)||
                       (GenericTerminal.State.CARD_INSERTION==terminal.state))
                        terminal.state=GenericTerminal.State.CARD_REMOVAL;
                    else
                        terminal.state=GenericTerminal.State.CARD_ABSENT;
                    break;
                case CARD_PRESENT:
                    if((GenericTerminal.State.CARD_ABSENT==terminal.state)||
                       (GenericTerminal.State.CARD_REMOVAL==terminal.state))
                        terminal.state=GenericTerminal.State.CARD_INSERTION;
                    else
                        terminal.state=GenericTerminal.State.CARD_PRESENT;
                    break;
            }
        }
        return Collections.unmodifiableList(terminalsList);
    }

    private static final Map<String,Reference<GenericTerminal>> terminals
  = new HashMap<String,Reference<GenericTerminal>>();

    protected static /*synchronized*/ GenericTerminal getTerminalImpl(String name) {
  synchronized(terminals){
            Reference<GenericTerminal> ref = terminals.get(name);
            GenericTerminal terminal = (ref != null) ? ref.get() : null;
            if (terminal != null) {
                return terminal;
            }
            terminal = new PcScTerminal(contextId,name);
            terminals.put(name, new WeakReference<GenericTerminal>(terminal));
            return terminal;
        }
    }

/*    static long SCardEstablishContext(int scope) throws PcScException {
        NativeLongByReference phContext = new NativeLongByReference();
        phContext.setValue(new NativeLong((long) 0));
        NativeLong status = win32PCSC.SCardEstablishContext(scope, Pointer.NULL, Pointer.NULL, phContext);
        if (0 != status.longValue()) {
            throw new PcScException(status.intValue());
        }
        return phContext.getValue().longValue();
    }*/

    static long SCardConnect(long contextId, String readerName, int shareMode, int preferredProtocols) throws PcScException {
        NativeLongByReference phCard = new NativeLongByReference();
        IntByReference pdwActiveProtocol = new IntByReference();
        NativeLong status = win32PCSC.SCardConnectW(new NativeLong(contextId), new WString(readerName), shareMode, preferredProtocols,
                phCard,
                pdwActiveProtocol);
        if (SCARD_S_SUCCESS != status.longValue()) {
            throw new PcScException(status.intValue());
        }
        return phCard.getValue().longValue();
    }

    static long SCardReconnect(long cardId, int shareMode, int preferredProtocols, int activationPolicy) throws PcScException {
        NativeLongByReference phCard = new NativeLongByReference();
        IntByReference pdwActiveProtocol = new IntByReference();
        NativeLong status = win32PCSC.SCardReconnect(new NativeLong(cardId), shareMode, preferredProtocols,
                activationPolicy,
                pdwActiveProtocol);
        if (SCARD_S_SUCCESS != status.longValue()) {
            throw new PcScException(status.intValue());
        }
        return phCard.getValue().longValue();
    }

    static byte[] SCardTransmit(long cardId, int protocol, byte[] buf, int ofs, int len) throws PcScException {
        Win32PCSC.SCARD_IO_REQUEST pioSendPci = new Win32PCSC.SCARD_IO_REQUEST();
        pioSendPci.dwProtocol = protocol;
        pioSendPci.cbPciLength = 8;
        IntByReference pcbRecvLength = new IntByReference();
        byte pbRecvBuffer[] = new byte[65536 + 16];
        pcbRecvLength.setValue(65536 + 16);
        if (0 != ofs) {
            byte temp[] = new byte[len];
            for (int i = 0; i < len; i++) {
                temp[i] = buf[ofs + i];
            }
            buf = temp;
        }
        NativeLong callStatus = win32PCSC.SCardTransmit(new NativeLong(cardId),
                pioSendPci,
                buf, len,
                (Win32PCSC.SCARD_IO_REQUEST) null,
                pbRecvBuffer, pcbRecvLength);
        if (SCARD_S_SUCCESS != callStatus.longValue()) {
            throw new PcScException("buf.length="+buf.length+", len="+len,callStatus.intValue());
        }
        byte out[] = new byte[pcbRecvLength.getValue()];
        for (int i = 0; i < pcbRecvLength.getValue(); i++) {
            out[i] = pbRecvBuffer[i];
        }
        return out;
    }

    static byte[] SCardGetAttrib(long cardId, int dwAttrId) throws PcScException {
        IntByReference pcbRecvLength = new IntByReference();
        byte pbRecvBuffer[] = new byte[200];
        pcbRecvLength.setValue(200);

        NativeLong callStatus = win32PCSC.SCardGetAttrib(new NativeLong(cardId),
                dwAttrId,
                pbRecvBuffer /*null*/, pcbRecvLength);
        if (SCARD_S_SUCCESS != callStatus.longValue()) {
            /*if (ERROR_NOT_SUPPORTED != callStatus.longValue()) {
                throw new PcScException("win32PCSC.SCardGetAttrib: attribute not supported",callStatus.intValue());
            }*/
        throw new PcScException("win32PCSC.SCardGetAttrib",callStatus.intValue());
        }
        byte out[] = new byte[pcbRecvLength.getValue()];
        for (int i = 0; i < pcbRecvLength.getValue(); i++) {
            out[i] = pbRecvBuffer[i];
        }
        return out;
    }

    // returns the ATR of the card, updates status[] with reader state and protocol
    static byte[] SCardStatus(long cardId, byte[] status) throws ScardException {
        IntByReference pcchReaderLen = new IntByReference();
        IntByReference pdwState = new IntByReference();
        IntByReference pdwProtocol = new IntByReference();
        byte pbAtr[] = new byte[36];
        IntByReference pcbAtrLen = new IntByReference();
        pcbAtrLen.setValue(36);
        NativeLong callStatus = win32PCSC.SCardStatusW(new NativeLong(cardId), null, pcchReaderLen, pdwState, pdwProtocol, pbAtr, pcbAtrLen);
        if (SCARD_S_SUCCESS != callStatus.longValue()) {
            throw new PcScException(callStatus.intValue());
        }
        byte out[] = new byte[pcbAtrLen.getValue()];
        for (int i = 0; i < pcbAtrLen.getValue(); i++) {
            out[i] = pbAtr[i];
        }
        status[0]=(byte) pdwState.getValue();
        status[1]=(byte) pdwProtocol.getValue();
        return out;
    }

    static void SCardDisconnect(long cardId, int disposition) throws PcScException {
        NativeLong status = win32PCSC.SCardDisconnect(new NativeLong(cardId), disposition);
        if (SCARD_S_SUCCESS != status.longValue()) {
            throw new PcScException(status.intValue());
        }
    }

    static int[] SCardGetStatusChange(long contextId, long timeout, int[] currentState, String[] readerNames) throws ScardException {
        Win32PCSC.SCARD_READERSTATE readerStates[] = new Win32PCSC.SCARD_READERSTATE[readerNames.length];

        for (int i = 0; i < readerNames.length; i++) {
            readerStates[i] = new Win32PCSC.SCARD_READERSTATE();
            readerStates[i].szReader = new WString(readerNames[i]);
            readerStates[i].pvUserData = Pointer.NULL;
            readerStates[i].dwCurrentState = currentState[i];
            readerStates[i].dwEventState = SCARD_STATE_UNAWARE;
            readerStates[i].cbAtr = 0;
            readerStates[i].rgbAtr = new byte[36];
        }

        NativeLong status = win32PCSC.SCardGetStatusChangeW(new NativeLong(contextId), (int) timeout, readerStates, readerNames.length);
        if (SCARD_S_SUCCESS != status.longValue()) {
            throw new PcScException(status.intValue());
        }
        int out[] = new int[readerNames.length];
        for (int i = 0; i < readerNames.length; i++) {
            out[i] = readerStates[i].dwEventState;
        }
        return out;
    }

    final static int SCARD_S_SUCCESS = 0x00000000;
    final static int SCARD_E_CANCELLED = 0x80100002;
    final static int SCARD_E_CANT_DISPOSE = 0x8010000E;
    final static int SCARD_E_INSUFFICIENT_BUFFER = 0x80100008;
    final static int SCARD_E_INVALID_ATR = 0x80100015;
    final static int SCARD_E_INVALID_HANDLE = 0x80100003;
    final static int SCARD_E_INVALID_PARAMETER = 0x80100004;
    final static int SCARD_E_INVALID_TARGET = 0x80100005;
    final static int SCARD_E_INVALID_VALUE = 0x80100011;
    final static int SCARD_E_NO_MEMORY = 0x80100006;
    final static int SCARD_F_COMM_ERROR = 0x80100013;
    final static int SCARD_F_INTERNAL_ERROR = 0x80100001;
    final static int SCARD_F_UNKNOWN_ERROR = 0x80100014;
    final static int SCARD_F_WAITED_TOO_LONG = 0x80100007;
    final static int SCARD_E_UNKNOWN_READER = 0x80100009;
    final static int SCARD_E_TIMEOUT = 0x8010000A;
    final static int SCARD_E_SHARING_VIOLATION = 0x8010000B;
    final static int SCARD_E_NO_SMARTCARD = 0x8010000C;
    final static int SCARD_E_UNKNOWN_CARD = 0x8010000D;
    final static int SCARD_E_PROTO_MISMATCH = 0x8010000F;
    final static int SCARD_E_NOT_READY = 0x80100010;
    final static int SCARD_E_SYSTEM_CANCELLED = 0x80100012;
    final static int SCARD_E_NOT_TRANSACTED = 0x80100016;
    final static int SCARD_E_READER_UNAVAILABLE = 0x80100017;
    final static int SCARD_W_UNSUPPORTED_CARD = 0x80100065;
    final static int SCARD_W_UNRESPONSIVE_CARD = 0x80100066;
    final static int SCARD_W_UNPOWERED_CARD = 0x80100067;
    final static int SCARD_W_RESET_CARD = 0x80100068;
    final static int SCARD_W_REMOVED_CARD = 0x80100069;
    final static int SCARD_W_INSERTED_CARD = 0x8010006A;
    final static int SCARD_E_UNSUPPORTED_FEATURE = 0x8010001F;
    final static int SCARD_E_PCI_TOO_SMALL = 0x80100019;
    final static int SCARD_E_READER_UNSUPPORTED = 0x8010001A;
    final static int SCARD_E_DUPLICATE_READER = 0x8010001B;
    final static int SCARD_E_CARD_UNSUPPORTED = 0x8010001C;
    final static int SCARD_E_NO_SERVICE = 0x8010001D;
    final static int SCARD_E_SERVICE_STOPPED = 0x8010001E;
    // MS undocumented
    final static int SCARD_E_NO_READERS_AVAILABLE = 0x8010002E;
    // std. Windows invalid handle return code, used instead of SCARD code
    final static int WINDOWS_ERROR_INVALID_HANDLE = 6;
    final static int WINDOWS_ERROR_INVALID_PARAMETER = 87;

    final static int SCARD_LEAVE_CARD = 0x0000;
    final static int SCARD_RESET_CARD = 0x0001;
    final static int SCARD_UNPOWER_CARD = 0x0002;
    final static int SCARD_EJECT_CARD = 0x0003;

    final static int SCARD_SCOPE_USER = 0x0000;
    final static int SCARD_SCOPE_TERMINAL = 0x0001;
    final static int SCARD_SCOPE_SYSTEM = 0x0002;
    final static int SCARD_SCOPE_GLOBAL = 0x0003;

    final static int SCARD_SHARE_EXCLUSIVE = 0x0001;
    final static int SCARD_SHARE_SHARED = 0x0002;
    final static int SCARD_SHARE_DIRECT = 0x0003;

    final static int SCARD_STATE_UNAWARE = 0x0000;
    final static int SCARD_STATE_IGNORE = 0x0001;
    final static int SCARD_STATE_CHANGED = 0x0002;
    final static int SCARD_STATE_UNKNOWN = 0x0004;
    final static int SCARD_STATE_UNAVAILABLE = 0x0008;
    final static int SCARD_STATE_EMPTY = 0x0010;
    final static int SCARD_STATE_PRESENT = 0x0020;
    final static int SCARD_STATE_ATRMATCH = 0x0040;
    final static int SCARD_STATE_EXCLUSIVE = 0x0080;
    final static int SCARD_STATE_INUSE = 0x0100;
    final static int SCARD_STATE_MUTE = 0x0200;
    final static int SCARD_STATE_UNPOWERED = 0x0400;

    final static int TIMEOUT_INFINITE = 0xffffffff;
    final static int SCARD_AUTOALLOCATE = -1;

    final static int SCARD_PROTOCOL_T0 = 0x0001;
    final static int SCARD_PROTOCOL_T1 = 0x0002;
    final static int SCARD_PROTOCOL_RAW = 0x10000;
    final static int SCARD_UNKNOWN = 0x0000;
    final static int SCARD_ABSENT = 0x0001;
    final static int SCARD_PRESENT = 0x0002;
    final static int SCARD_SWALLOWED = 0x0003;
    final static int SCARD_POWERED = 0x0004;
    final static int SCARD_NEGOTIABLE = 0x0005;
    final static int SCARD_SPECIFIC = 0x0006;

    //final static int ERROR_NOT_SUPPORTED = 0x32;
}
TOP

Related Classes of uk.co.nimp.scard.PcScTerminalManager$Win32PCSC$SCARD_IO_REQUEST

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.