Invoke WinInet Functions Used Java + JNA

大憨熊 提交于 2019-12-24 15:48:45

问题


sorry for my English.

I try invoke WinInet InternetSetOptionW method for setting up IE proxy. InternetSetOptionW returns me "true", but IE proxy doesn't change.

What i do wrong?

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.LongByReference;
import com.sun.jna.win32.StdCallLibrary;


public interface WinInet extends StdCallLibrary {
    public WinInet INSTANCE = (WinInet) Native.loadLibrary("Wininet", WinInet.class);

    public boolean InternetSetOptionW(int unused, int dwOption,
            Pointer lpBuffer, int dwBufferLength);
}

import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.Union;
import com.sun.jna.WString;


public class WindowsProxy {
public static final int INTERNET_OPTION_SETTINGS_CHANGED = 39;
public static final int INTERNET_OPTION_REFRESH = 37;

public static final int INTERNET_PER_CONN_FLAGS = 1;
public static final int INTERNET_PER_CONN_PROXY_SERVER = 2;
public static final int INTERNET_PER_CONN_PROXY_BYPASS  = 3;
public static final int INTERNET_PER_CONN_AUTOCONFIG_URL = 4;
public static final int INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5;

public static final int PROXY_TYPE_AUTO_PROXY_URL = 4;

public static final int INTERNET_OPTION_PER_CONNECTION_OPTION = 75;

public static class INTERNET_PER_CONN_OPTION extends Structure {
    public int dwOption;
    public Value value;

    public static class FILETIME extends Structure {
        public int dwLowDateTime;
        public int dwHighDateTime;
    }

    public static class Value extends Union {
        public int dwValue;
        public WString pszValue;
        public FILETIME ftValue;
    }
}

public static class INTERNET_PER_CONN_OPTION_LIST extends Structure {
    public int dwSize;
    public WString pszConnection;
    public int dwOptionCount;
    public int dwOptionError;
    public Pointer pOptions;
}

public static void setProxySettings() {
    INTERNET_PER_CONN_OPTION_LIST list = new INTERNET_PER_CONN_OPTION_LIST();

    INTERNET_PER_CONN_OPTION option = new INTERNET_PER_CONN_OPTION();

    option.dwOption = INTERNET_PER_CONN_PROXY_SERVER;
    option.value.pszValue = new WString("http://localhost:8080");

    list.pszConnection = null;
    list.dwOptionCount = 1;
    list.dwOptionError = 0;
    list.pOptions = option.getPointer();
    list.dwSize = list.size();

    int size = list.size();

    boolean result = WinInet.INSTANCE.InternetSetOptionW(0,
            INTERNET_OPTION_PER_CONNECTION_OPTION, list.getPointer(), size);

    System.out.println(result);

    result = WinInet.INSTANCE.InternetSetOptionW(0,
            INTERNET_OPTION_SETTINGS_CHANGED, null, 0);

    System.out.println(result);

    result = WinInet.INSTANCE.InternetSetOptionW(0,
            INTERNET_OPTION_REFRESH, null, 0);

    System.out.println(result);
}

public static void main(String[] args) {
    setProxySettings();
}
}

Thanks for help!

Eng


回答1:


I've tried to translate wininet.h header to Java by hand, but it is quite complicated with too many structures.

Maybe you can try JNAerator http://code.google.com/p/jnaerator/

Edited:

I have managed to run a few WinInet methods with following WinInet structures but I am stucked with WinInet.INTERNET_PER_CONN_OPTION_LISTW using InternetQueryOption for WinInet.INTERNET_OPTION_PER_CONNECTION_OPTION query which it returns GetLastError value 12010.

I am not sure how Java translates C/C++ List.dwSize=sizeof(INTERNET_PER_CONN_OPTION_LISTW) into Java equivalent, optionlist.dwSize = new DWORD(optionlist.size());

Kernel32.java:

import com.sun.jna.Native;
import com.sun.jna.win32.StdCallLibrary;

public interface Kernel32 extends StdCallLibrary {
    public Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("Kernel32", Kernel32.class);

    public int GetLastError();
}

WinInet.java:

    import java.util.HashMap;
    import java.util.Map;
    import com.sun.jna.Library;
    import com.sun.jna.Native;
    import com.sun.jna.Pointer;
    import com.sun.jna.Structure;
    import com.sun.jna.Union;
    import com.sun.jna.WString;
    import com.sun.jna.platform.win32.BaseTSD.DWORD_PTR;
    import com.sun.jna.platform.win32.WinBase.FILETIME;
    import com.sun.jna.platform.win32.WinDef.DWORD;
    import com.sun.jna.ptr.IntByReference;
    import com.sun.jna.win32.StdCallLibrary;
    import com.sun.jna.win32.W32APIFunctionMapper;
    import com.sun.jna.win32.W32APITypeMapper;


    /*
     * http://source.winehq.org/source/include/wininet.h
     */
    public interface WinInet extends StdCallLibrary {
        final static Map<String, Object> WIN32API_OPTIONS = new HashMap<String, Object>() {
            private static final long serialVersionUID = 1L;
            {
                put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
                put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
            }
        };

        public WinInet INSTANCE = (WinInet) Native.loadLibrary("Wininet", WinInet.class, WIN32API_OPTIONS);

        public static final DWORD INTERNET_PER_CONN_FLAGS                        = new DWORD(1);
        public static final DWORD INTERNET_PER_CONN_PROXY_SERVER                 = new DWORD(2);
        public static final DWORD INTERNET_PER_CONN_PROXY_BYPASS                 = new DWORD(3);
        public static final DWORD INTERNET_PER_CONN_AUTOCONFIG_URL               = new DWORD(4);
        public static final DWORD INTERNET_PER_CONN_AUTODISCOVERY_FLAGS          = new DWORD(5);
        public static final DWORD INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL     = new DWORD(6);
        public static final DWORD INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS = new DWORD(7);
        public static final DWORD INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME  = new DWORD(8);
        public static final DWORD INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL   = new DWORD(9); 

        /* Values for INTERNET_PER_CONN_FLAGS */
        public static final DWORD PROXY_TYPE_DIRECT                              = new DWORD(0x00000001);
        public static final DWORD PROXY_TYPE_PROXY                               = new DWORD(0x00000002);
        public static final DWORD PROXY_TYPE_AUTO_PROXY_URL                      = new DWORD(0x00000004);
        public static final DWORD PROXY_TYPE_AUTO_DETECT                         = new DWORD(0x00000008);

        public static final DWORD INTERNET_OPTION_REFRESH                 = new DWORD(37);
        public static final DWORD INTERNET_OPTION_SETTINGS_CHANGED        = new DWORD(39);
        public static final DWORD INTERNET_OPTION_VERSION                 = new DWORD(40);
        public static final DWORD INTERNET_OPTION_USER_AGENT              = new DWORD(41);
        public static final DWORD INTERNET_OPTION_PER_CONNECTION_OPTION   = new DWORD(75);
        public static final DWORD INTERNET_OPTION_PROXY_SETTINGS_CHANGED  = new DWORD(95);

        /*
            typedef struct {
                DWORD dwMajorVersion;
                DWORD dwMinorVersion;
            } INTERNET_VERSION_INFO,* LPINTERNET_VERSION_INFO;
         */     
        public class INTERNET_VERSION_INFO extends Structure {
            public DWORD dwMajorVersion;
            public DWORD dwMinorVersion;
            public INTERNET_VERSION_INFO() {
                super();
                initFieldOrder();
            }
            protected void initFieldOrder() {
                setFieldOrder(new java.lang.String[]{"dwMajorVersion", "dwMinorVersion"});
            }
            public INTERNET_VERSION_INFO(DWORD dwMajorVersion, DWORD dwMinorVersion) {
                super();
                this.dwMajorVersion = dwMajorVersion;
                this.dwMinorVersion = dwMinorVersion;
                initFieldOrder();
            }
            public static class ByReference extends INTERNET_VERSION_INFO implements Structure.ByReference {

            };
            public static class ByValue extends INTERNET_VERSION_INFO implements Structure.ByValue {

            };
        }   

        /*
            typedef struct _INTERNET_PER_CONN_OPTIONW {
                DWORD dwOption;
                union {
                    DWORD    dwValue;
                    LPWSTR    pszValue;
                    FILETIME ftValue;
                } Value;
            } INTERNET_PER_CONN_OPTIONW, *LPINTERNET_PER_CONN_OPTIONW; 
         */
        public class INTERNET_PER_CONN_OPTIONW extends Structure {
            public DWORD dwOption;
            public Value_union Value;
            public static class Value_union extends Union {
                public DWORD dwValue;
                public WString pszValue;
                public FILETIME ftValue;
                public Value_union() {
                    super();
                }
                public static class ByReference extends Value_union implements Structure.ByReference {

                };
                public static class ByValue extends Value_union implements Structure.ByValue {

                };
            };
            public INTERNET_PER_CONN_OPTIONW() {
                super();
                initFieldOrder();
            }
            protected void initFieldOrder() {
                setFieldOrder(new java.lang.String[]{"dwOption", "Value"});
            }
            public INTERNET_PER_CONN_OPTIONW(DWORD dwOption, Value_union Value) {
                super();
                this.dwOption = dwOption;
                this.Value = Value;
                initFieldOrder();
            }
            public static class ByReference extends INTERNET_PER_CONN_OPTIONW implements Structure.ByReference {

            };
            public static class ByValue extends INTERNET_PER_CONN_OPTIONW implements Structure.ByValue {

            };
        }

        /*
        typedef struct _INTERNET_PER_CONN_OPTION_LISTW {
            DWORD                       dwSize;
            LPWSTR                      pszConnection;
            DWORD                       dwOptionCount;
            DWORD                       dwOptionError;
            LPINTERNET_PER_CONN_OPTIONW pOptions;
        } INTERNET_PER_CONN_OPTION_LISTW, *LPINTERNET_PER_CONN_OPTION_LISTW;    
         */
        public class INTERNET_PER_CONN_OPTION_LISTW extends Structure {
            public DWORD dwSize;
            public WString pszConnection;
            public DWORD dwOptionCount;
            public DWORD dwOptionError;
            public INTERNET_PER_CONN_OPTIONW.ByReference pOptions;
            public INTERNET_PER_CONN_OPTION_LISTW() {
                super();
                initFieldOrder();
            }
            protected void initFieldOrder() {
                setFieldOrder(new java.lang.String[]{"dwSize", "pszConnection", "dwOptionCount", "dwOptionError", "pOptions"});
            }
            public INTERNET_PER_CONN_OPTION_LISTW(DWORD dwSize, WString pszConnection, DWORD dwOptionCount, DWORD dwOptionError, INTERNET_PER_CONN_OPTIONW.ByReference pOptions) {
                super();
                this.dwSize = dwSize;
                this.pszConnection = pszConnection;
                this.dwOptionCount = dwOptionCount;
                this.dwOptionError = dwOptionError;
                this.pOptions = pOptions;
                initFieldOrder();
            }
            public static class ByReference extends INTERNET_PER_CONN_OPTION_LISTW implements Structure.ByReference {

            };
            public static class ByValue extends INTERNET_PER_CONN_OPTION_LISTW implements Structure.ByValue {

            };
        }
        /*
        BOOL InternetSetOption(
                  __in  HINTERNET hInternet,
                  __in  DWORD dwOption,
                  __in  LPVOID lpBuffer,
                  __in  DWORD dwBufferLength
                );
         */    
        public boolean InternetSetOption(
                Pointer hInternet, 
                DWORD dwOption,
                Pointer lpBuffer, 
                IntByReference dwBufferLength);

        public boolean InternetSetOption(
                Pointer hInternet, 
                DWORD dwOption,
                WinInet.INTERNET_PER_CONN_OPTION_LISTW lpBuffer, 
                IntByReference dwBufferLength);

        //BOOLAPI InternetQueryOptionW(HINTERNET ,DWORD ,LPVOID ,LPDWORD);  
        public boolean InternetQueryOption(
                Pointer hInternet,
                DWORD dwOption,
                Pointer lpBuffer,
                IntByReference len
                );
        public boolean InternetQueryOption(
                Pointer hInternet,
                DWORD dwOption,
                WinInet.INTERNET_VERSION_INFO lpBuffer,
                IntByReference len
                );
        public boolean InternetQueryOption(
                Pointer hInternet,
                DWORD dwOption,
                WinInet.INTERNET_PER_CONN_OPTION_LISTW lpBuffer,
                IntByReference len
                );


    }

WindowsProxy.java:

import com.sun.jna.Pointer;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.ptr.IntByReference;

public class WindowsProxy {

    public static void setProxySettings() {

        Pointer hInternet = null;
        IntByReference len = new IntByReference();

        System.out.println("Get version...");

        WinInet.INTERNET_VERSION_INFO versionInfo = null;

        if (!WinInet.INSTANCE.InternetQueryOption(hInternet,WinInet.INTERNET_OPTION_VERSION, versionInfo, len)){
        /*
            ERROR_INSUFFICIENT_BUFFER
            122 (0x7A)
            The data area passed to a system call is too small.     
        */
            System.out.println("InternetQueryOption failed!:" + Kernel32.INSTANCE.GetLastError());
        }

        versionInfo = new WinInet.INTERNET_VERSION_INFO();

        if (!WinInet.INSTANCE.InternetQueryOption(hInternet,WinInet.INTERNET_OPTION_VERSION, versionInfo, len)){
            System.out.println("InternetQueryOption failed!:" + Kernel32.INSTANCE.GetLastError());
        }
        System.out.println("Version:" + versionInfo.dwMajorVersion + "." + versionInfo.dwMinorVersion); //IE5+ = 1.2

        System.out.println("Set proxy...");

        WinInet.INTERNET_PER_CONN_OPTION_LISTW optionlist2 = new WinInet.INTERNET_PER_CONN_OPTION_LISTW();

        WinInet.INTERNET_PER_CONN_OPTIONW.ByReference ref2 = new WinInet.INTERNET_PER_CONN_OPTIONW.ByReference();
        WinInet.INTERNET_PER_CONN_OPTIONW[] option2 = (WinInet.INTERNET_PER_CONN_OPTIONW[])ref2.toArray(3);

        option2[0].dwOption = WinInet.INTERNET_PER_CONN_PROXY_SERVER;
        option2[0].Value.pszValue = new WString("http=http://localhost:8080");

        option2[1].dwOption = WinInet.INTERNET_PER_CONN_FLAGS; 
        option2[1].Value.dwValue = new DWORD(WinInet.PROXY_TYPE_PROXY.byteValue() | WinInet.PROXY_TYPE_DIRECT.byteValue());

        option2[2].dwOption = WinInet.INTERNET_PER_CONN_PROXY_BYPASS; 
        option2[2].Value.pszValue = new WString("<local>"); 

        optionlist2.pszConnection = null;
        optionlist2.dwOptionCount = new DWORD(3);
        optionlist2.dwOptionError = new DWORD(0);
        optionlist2.pOptions = ref2;

        if (!WinInet.INSTANCE.InternetSetOption(hInternet,WinInet.INTERNET_OPTION_PER_CONNECTION_OPTION, optionlist2, len)){
            System.out.println("InternetSetOption failed!:" + Kernel32.INSTANCE.GetLastError());
        }

//      System.out.println("Set changed...");
//      
//      if (!WinInet.INSTANCE.InternetSetOption(hInternet,WinInet.INTERNET_OPTION_SETTINGS_CHANGED, (Pointer)null, len)){
//          System.out.println("InternetSetOption failed!:" + Kernel32.INSTANCE.GetLastError());
//      }

        System.out.println("Set refreshed...");

        if (!WinInet.INSTANCE.InternetSetOption(hInternet,WinInet.INTERNET_OPTION_REFRESH, (Pointer)null, len)){
            System.out.println("InternetSetOption failed!:" + Kernel32.INSTANCE.GetLastError());
        }


        System.out.println("Get options...");

        WinInet.INTERNET_PER_CONN_OPTION_LISTW optionlist = new WinInet.INTERNET_PER_CONN_OPTION_LISTW();

        WinInet.INTERNET_PER_CONN_OPTIONW.ByReference ref = new WinInet.INTERNET_PER_CONN_OPTIONW.ByReference();
        WinInet.INTERNET_PER_CONN_OPTIONW[] option = (WinInet.INTERNET_PER_CONN_OPTIONW[])ref.toArray(5);

        option[0].dwOption = WinInet.INTERNET_PER_CONN_AUTOCONFIG_URL;
        option[1].dwOption = WinInet.INTERNET_PER_CONN_AUTODISCOVERY_FLAGS;
        option[2].dwOption = WinInet.INTERNET_PER_CONN_FLAGS;
        option[3].dwOption = WinInet.INTERNET_PER_CONN_PROXY_BYPASS;
        option[4].dwOption = WinInet.INTERNET_PER_CONN_PROXY_SERVER;

        optionlist.pszConnection = null;
        optionlist.dwOptionCount = new DWORD(5);
        optionlist.dwOptionError = new DWORD(0);
        optionlist.pOptions = ref;
        optionlist.dwSize = new DWORD(optionlist.size());

        if (!WinInet.INSTANCE.InternetQueryOption(hInternet,WinInet.INTERNET_OPTION_PER_CONNECTION_OPTION, optionlist, len)){
        /*
            ERROR_INTERNET_BAD_OPTION_LENGTH
            12010
            The length of an option supplied to InternetQueryOption or InternetSetOption is incorrect for the type of option specified. 
        */

            System.out.println("InternetQueryOption failed!:" + Kernel32.INSTANCE.GetLastError());
        }

        if(option[0].Value.pszValue != null)
            System.out.println(option[0].Value.pszValue);

        if((option[2].Value.dwValue.byteValue() & WinInet.PROXY_TYPE_AUTO_PROXY_URL.byteValue()) == WinInet.PROXY_TYPE_AUTO_PROXY_URL.byteValue())
            System.out.println("PROXY_TYPE_AUTO_PROXY_URL");

        if((option[2].Value.dwValue.byteValue() & WinInet.PROXY_TYPE_AUTO_DETECT.byteValue()) == WinInet.PROXY_TYPE_AUTO_DETECT.byteValue())
            System.out.println("PROXY_TYPE_AUTO_DETECT");    

    }

    public static void main(String[] args) {
        setProxySettings();
    }
}

Output:

Get version...
InternetQueryOption failed!:122
Version:1.2
Set proxy...
Set refreshed...
Get options...
InternetQueryOption failed!:12010

The test codes in WindowsProxy.java are taken from http://support.microsoft.com/kb/226473

Edited

The InternetQueryOption failed!:12010 error in the output disappears when the following modification is made (by assigning the size value to len object) :

len.setValue(optionlist.size());

if (!WinInet.INSTANCE.InternetQueryOption(hInternet,WinInet.INTERNET_OPTION_PER_CONNECTION_OPTION, optionlist, len)){
/*
    ERROR_INTERNET_BAD_OPTION_LENGTH
    12010
    The length of an option supplied to InternetQueryOption or InternetSetOption is incorrect for the type of option specified. 
*/

    System.out.println("InternetQueryOption failed!:" + Kernel32.INSTANCE.GetLastError());
}


来源:https://stackoverflow.com/questions/5501787/invoke-wininet-functions-used-java-jna

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!