Invoke WinInet Functions Used Java + JNA
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 lpB开发者_如何学JAVAuffer, 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
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());
}
精彩评论