📄 jnative.java
字号:
package org.xvolks.jnative;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.Vector;
import java.util.WeakHashMap;
import org.xvolks.jnative.exceptions.NativeException;
import org.xvolks.jnative.logging.ConsoleLogger;
import org.xvolks.jnative.logging.JNativeLogger;
import org.xvolks.jnative.logging.JNativeLogger.SEVERITY;
import org.xvolks.jnative.misc.SecurityAttributes;
import org.xvolks.jnative.misc.basicStructures.DWORD;
import org.xvolks.jnative.misc.basicStructures.HANDLE;
import org.xvolks.jnative.misc.basicStructures.HWND;
import org.xvolks.jnative.misc.basicStructures.LONG;
import org.xvolks.jnative.pointers.NullPointer;
import org.xvolks.jnative.pointers.Pointer;
import org.xvolks.jnative.pointers.memory.NativeMemoryBlock;
import org.xvolks.jnative.util.Callback;
import org.xvolks.jnative.util.DbgHelp;
import org.xvolks.jnative.util.Kernel32;
import org.xvolks.jnative.util.StructConverter;
import org.xvolks.jnative.util.WindowProc;
//import com.sun.org.apache.xerces.internal.impl.xpath.regex.ParseException;
/**
* JNative this is the main class for calling native functions.<br>
*
* $Id: JNative.java,v 1.36 2007/05/07 17:31:11 mdenty Exp $; <br>
* To do so you have to :
* <ul>
* <li>create a new JNative object (JNative messageBox = new
* JNative("User32.dll", "MessageBoxA");</li>
* <li>set its return type (messageBox.setRetVal(Type.INT);</li>
* <li>pass some parameters (messageBox.setParameter(0, Type.INT, "0");</li>
* <li>pass some parameters (messageBox.setParameter(1, Type.STRING,
* "message");</li>
* <li>pass some parameters (messageBox.setParameter(2, Type.STRING,
* "caption");</li>
* <li>pass some parameters (messageBox.setParameter(3, Type.INT, "" + 0);</li>
* <li>then invoke the function (messageBox.invoke();</li>
* <li>you can get its return value (messageBox.getRetVal();</li>
* <li>dispose native resources when they no more needed (messageBox.dispose();</li>
* </ul>
* So simple :) <br>
* if you have to deal with pointers you can create some, here is a sample, it
* uses one pointer but could have be done with 3 (one per PULARGE_INTEGER)
* <hr>
* The C function to call
*
* <pre>
* BOOL GetDiskFreeSpaceEx(LPCTSTR lpDirectoryName,
* PULARGE_INTEGER lpFreeBytesAvailable,
* PULARGE_INTEGER lpTotalNumberOfBytes,
* PULARGE_INTEGER lpTotalNumberOfFreeBytes);
*
* </pre>
*
* <HR>
* The implementation in Java with JNative
*
* <pre>
* public static final FreeDiskSpace getDiskFreeSpaceEx(String drive)
* throws NativeException, IllegalAccessException {
* if (drive == null)
* throw new NullPointerException("The drive name cannot be null !");
* Pointer lpFreeBytesAvailable = new Pointer(24);
* int i = 0;
* JNative fs = new JNative("Kernel32.dll", "GetDiskFreeSpaceExA");
* fs.setRetVal(Type.INT);
* fs.setParameter(i++, Type.STRING, drive);
* fs.setParameter(i++, lpFreeBytesAvailable.getPointer(), 8);
* fs.setParameter(i++, lpFreeBytesAvailable.getPointer() + 8, 8);
* fs.setParameter(i++, lpFreeBytesAvailable.getPointer() + 16, 8);
* fs.invoke();
* FreeDiskSpace dsp = new FreeDiskSpace(drive, lpFreeBytesAvailable);
* lpFreeBytesAvailable.dispose();
* return dsp;
* }
* </pre>
*
* <HR>
* $Id: JNative.java,v 1.36 2007/05/07 17:31:11 mdenty Exp $
*
* This software is released under the LGPL.
*
* @author Created by Marc DENTY - (c) 2006 JNative project
*/
public class JNative {
public static class LibDesc {
int handle;
String libName;
int numHolders;
@Override
public String toString() {
return String.format("Lib info (name = %s, handle = %x, inUseFor = %d)", libName, handle, numHolders);
}
}
private final static Map<String, LibDesc> mLibs;
public static LibDesc getLibDesc(String name) {
synchronized (mLibs) {
LibDesc libDesc = mLibs.get(name);
if(libDesc == null) {
libDesc = new LibDesc();
libDesc.libName = name;
mLibs.put(name, libDesc);
}
return libDesc;
}
}
/**
* Pointer on the function address
*/
private final int mJNativePointer;
@SuppressWarnings("unused")
// Used by native side (handle of the library)
private int mJNativeHModule;
// Used by native side
private int convention;
private boolean isClosed = false;
private final String mDllName;
private final String mFunctionName;
private static Map<Integer, Callback> callbacks = new TreeMap<Integer, Callback>();
/*
* The five following fields are used by native side directly !
*/
/**
* Pre-allocated parameter array, need to grow if needed
*/
private Vector<byte[]> parameters = new Vector<byte[]>();
private Vector<Integer> parameterTypes = new Vector<Integer>();
private String mRetValue;
@SuppressWarnings("unused")
private int mRetType;
@SuppressWarnings("unused")
private Vector<byte[]> getParameters() {
return parameters;
}
@SuppressWarnings("unused")
private Vector<Integer> getParameterTypes() {
return parameterTypes;
}
public static int callback(int address, long[] values) {
//if(DEBUG)
getLogger().log(SEVERITY.DEBUG, String.format("in Java callback #%x with %d arguments\n", address, values.length));
return callbacks.get(address).callback(values);
}
@Override
public String toString() {
return mDllName + "-" + mFunctionName;
}
private native int nLoadLibrary(String dllName, String funcPointer,
boolean debug) throws NativeException;
private native int nFindFunction(int libHandle, String funcPointer,
boolean debug) throws NativeException;
// private native void nSetParameter(int jNativePointer, int pos, String
// type,
// byte[] value) throws NativeException;
// private native void nSetPointer(int jNativePointer, int pos, int pointer,
// int size) throws NativeException;
//
private native String nGetParameter(int jNativePointer, int pos)
throws NativeException;
private native void nInvoke(int jNativePointer) throws NativeException;
private native void nDispose(int jNativePointer) throws NativeException;
private static native int nMalloc(int size) throws NativeException;
private static native void nFree(int pointer) throws NativeException;
private static native void nSetMemory(int pointer, byte[] buff, int offset,
int len) throws NativeException;
private static native byte[] nGetMemory(int pointer, int len)
throws NativeException;
private static native int nRegisterWindowProc(int hwnd, Object winProc,
boolean custom) throws NativeException;
private static native int nGetCurrentModule() throws NativeException;
private static native int nCreateCallBack(int numParams)
throws NativeException;
private static native boolean nReleaseCallBack(int pos)
throws NativeException;
private static native int nGetNativePattern(int jNativePointer,
byte[] pattern, int maxLen) throws NativeException;
private static native String nGetNativeSideVersion() throws NativeException;
public static void setDefaultCallingConvention(Convention defaultConvention) {
Convention.setDefaultStyle(defaultConvention);
}
/**
* Creates a function without debug output that can call an anonymous function by it's address
* * @exception NativeException
* if the dll was not found, function name is incorrect...
*/
public JNative(int address, Convention convention) throws NativeException {
if (!initDone) {
throw new IllegalStateException(
"JNative library not loaded, sorry !");
}
this.convention = convention.getValue();
mDllName = "Anonymous";
mFunctionName = mDllName;
mJNativePointer = address;
try {
setRetVal(Type.VOID);
} catch (IllegalAccessException e) {
getLogger().log(SEVERITY.ERROR, e);
}
}
/**
* Constructor exact call of new JNative(dllName, functionName, false, Convention.DEFAULT); <br>
* Creates a function without debug output
*
* @param dllName
* the name of library file
* @param functionName
* the decorated name of the function (MessageBoxA instead of
* MessageBox)
*
* @exception NativeException
* if the dll was not found, function name is incorrect...
* @see org.xvolks.jnative.JNative#getDLLFileExports(String)
*/
public JNative(String dllName, String functionName) throws NativeException {
this(dllName, functionName, false, Convention.DEFAULT);
}
/**
* Constructor exact call of new JNative(dllName, functionName, false, convention); <br>
* Creates a function without debug output
*
* @param dllName
* the name of library file
* @param functionName
* the decorated name of the function (MessageBoxA instead of
* MessageBox)
* @param convention
* convention of function call
*
*
* @exception NativeException
* if the dll was not found, function name is incorrect...
* @see org.xvolks.jnative.JNative#getDLLFileExports(String)
*/
public JNative(String dllName, String functionName, Convention convention) throws NativeException {
this(dllName, functionName, false, convention);
}
/**
* Constructor exact call of new JNative(dllName, functionName, debug, Convention.DEFAULT); <br>
* Creates a function without debug output
*
* @param dllName
* the name of library file
* @param functionName
* the decorated name of the function (MessageBoxA instead of
* MessageBox)
* @param nativeDebug
* a boolean if true the dll logs output on stdout (beware this
* is shared between all instances of JNative)
*
* @exception NativeException
* if the dll was not found, function name is incorrect...
* @see org.xvolks.jnative.JNative#getDLLFileExports(String)
*/
public JNative(String dllName, String functionName, boolean debug) throws NativeException {
this(dllName, functionName, debug, Convention.DEFAULT);
}
/**
* Constructor
*
* @param dllName
* a String the name of the library; that DLL must be in the
* library.path
* @param functionName
* a String the name of the function this is the decorated name
* (@see org.xvolks.jnative.JNative#getDLLFileExports(String))
* @param nativeDebug
* a boolean if true the dll logs output on stdout (beware this
* is shared between all instances of JNative)
* @param convention
* convention of function call
*
*
* @exception NativeException
* if the dll was not found, function name is incorrect...
* @see org.xvolks.jnative.JNative#getDLLFileExports(String)
*/
public JNative(String dllName, String functionName, boolean nativeDebug, Convention convention)
throws NativeException {
if (!initDone) {
throw new IllegalStateException(
"JNative library not loaded, sorry !");
}
this.convention = convention.getValue();
mDllName = dllName;
synchronized (mLibs) {
LibDesc libDesc = getLibDesc(mDllName);
mFunctionName = functionName;
libDesc.numHolders ++;
if(libDesc.handle == 0) {
mJNativePointer = nLoadLibrary(dllName, functionName, nativeDebug);
libDesc.handle = mJNativeHModule;
// if (DEBUG)
getLogger().log(SEVERITY.DEBUG, "Creating "+ libDesc);
} else {
// if (DEBUG)
getLogger().log(SEVERITY.DEBUG, "Resusing "+ libDesc);
mJNativeHModule = libDesc.handle;
mJNativePointer = nFindFunction(mJNativeHModule, functionName, nativeDebug);
}
}
try {
setRetVal(Type.VOID);
} catch (IllegalAccessException e) {
getLogger().log(SEVERITY.ERROR, e);
}
}
/**
* Gets the native pointer of a function, can be used to pass function pointer to an other function.
* @return the native function pointer
* @throws IllegalAccessException if this JNative object have been dispised
*/
public int getFunctionPointer() throws IllegalAccessException {
throwClosed();
return mJNativePointer;
}
public void setParameter(int pos, int value) throws /* NativeException, */
IllegalAccessException {
setParameter(pos, Type.INT, value + "");
}
/**
* Method setParameter <br>
* Sets the parameter at index <code>pos</code>
*
* @param pos
* the offset of the parameter
* @param type
* one of the enum entry (INT, STRING...)
* @param value
* the parameter in its String representation
*
* @throws IllegalAccessException
* if this object has been disposed
*
*/
public void setParameter(int pos, Type type, String value)
throws IllegalAccessException {
if(value == null)
setParameter(pos,0);
else
setParameter(pos, type, (value + '\0').getBytes());
}
/**
* Method setParameter <br>
* Sets the parameter at index <code>pos</code>
*
* @param pos
* the offset of the parameter
* @param value
* the String parameter (this parameter must be a in one) !
* @throws IllegalAccessException
* if this object has been disposed
*
*/
public void setParameter(int pos, String lValue)
throws IllegalAccessException {
setParameter(pos, Type.STRING, lValue);
}
/**
* Method setParameter <br>
* Sets the parameter at index <code>pos</code>
*
* @param pos
* the offset of the parameter
* @param type
* one of the enum entry (INT, STRING...)
* @param value
* the parameter in its byte[] representation
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -