I am using JNA and writing some code to enumerate through all of the modules available in a process. I successfully obtain the snapshot handle via CreateToolhelp32Snapshot, however on my first Module32First call, I am getting error code 87 for "Invalid Parameter".
Below is the relevant code that I am using:
Code in question:
private void getModule() {
Pointer hSnapshot = this.kernel32.CreateToolhelp32Snapshot(WinAPI.TH32CS_SNAPMODULE, this.processId);
if(hSnapshot != null) {
WinAPI.MODULEENTRY32 moduleEntry32 = new WinAPI.MODULEENTRY32();
moduleEntry32.write(); // Write the struct in memory (for dwSize to be registered)
Pointer moduleEntry32Pointer = moduleEntry32.getPointer();
if(this.kernel32.Module32First(hSnapshot, moduleEntry32Pointer)) {
// irrelevant stuff here
}
}
System.out.println(this.kernel32.GetLastError()); // Prints out "87"
this.kernel32.CloseHandle(hSnapshot);
}
Kernel32 Mapper Class:
Pointer CreateToolhelp32Snapshot(int dwFlags, int th32ProcessID);
boolean Module32First(Pointer hSnapshot, Pointer lpme);
boolean Module32Next(Pointer hSnapshot, Pointer lpme);
ModuleEntry32 Structure:
public static class MODULEENTRY32 extends Structure {
public int dwSize = this.size();
public int th32ModuleID;
public int th32ProcessID;
public int GlblcntUsage;
public int ProccntUsage;
public Pointer modBaseAddr;
public int modBaseSize;
public Pointer hModule;
public String szModule;
public String szExePath;
public MODULEENTRY32() {
super();
}
public MODULEENTRY32(Pointer p) {
super(p);
}
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] {"dwSize", "th32ModuleID", "th32ProcessID", "GlblcntUsage", "ProccntUsage", "modBaseAddr", "modBaseSize", "hModule", "szModule", "szExePath"});
}
}
And finally, this is "WinAPI.TH32CS_SNAPMODULE":
public static final int TH32CS_SNAPMODULE = 0x00000008;
Note: The process I am enumerating on is already opened with OpenProcess and is valid. The processId is valid as well, and is obtained properly as well.
Any help would be appreciated.
Your mapping of a pointer as the second argument, while technically correct, requires you to do a lot more overhead with writing it. It is better to simply put the structure type as an argument. Structures are treated as .ByReference when used as function/method arguments, and handle all of the auto-read and write for you. So if you do this, you can omit your write() call:
boolean Module32First(Pointer hSnapshot, WinAPI.MODULEENTRY32 lpme);
boolean Module32Next(Pointer hSnapshot, WinAPI.MODULEENTRY32 lpme);
That said, the comment on your write call points to the root cause here: you need to set the dwSize value to the size of the structure. However, because of the order of initialization of Java Objects, the Structure does not have the information it needs to determine the size when initializing the dwSize variable, so this part is not giving you the correct size:
public int dwSize = this.size();
To solve this, just declare that variable and set the size later on in the constructor, e.g.,
public static class MODULEENTRY32 extends Structure {
public int dwSize;
// other declarations
public MODULEENTRY32() {
super();
dwSize = size();
}
}
In addition your mappings for szModule and szExePath are incorrect. You've only provided Pointers (a total of 16 bytes) in the structure's memory allocation, but these are fixed length character arrays. They should be defined:
public char[] szModule = new char[MAX_MODULE_NAME32 + 1];
public char[] szExePath = new char[MAX_PATH];
Note the char[] mapping is for the Unicode (_W) version of the mapping which is a reasonably safe assumption.
But rather than write yourself, you should use the mappings that already exists in the JNA user-contributed mappings in jna-platform. The MODULEENTRY32W type is already there (yes it uses DWORD so your version is simpler; but you can look at the code to see how they handled the size.) And the Module32FirstW and Module32NextW functions are also mapped. (The W suffix is for wide characters (Unicode) which all modern Windows systems use now.)
Related
I'm trying to map a structure which contains an array of structure in JNA.
The size of the embedded structure is not defined in advanced in the C++ declaration of the structure but in the java code.
My issue is that I get Exception in thread "main" java.lang.Error: Invalid memory access
The C++ header file is as follows :
typedef struct s_Param
{
char* key;
uint32_t key_value;
} Param;
typedef struct s_ParamList {
Param* init_param;
int param_list_size; // number of param items in the param List
} ParamList;
The C++ code is as follows :
int Init(
ParamList* i_initParamList,
logfunction i__callback,
const allocator* i__allocator,
void** o__content) {
...
if (i_initParamList != NULL){
printf("DLL PRINT init ---- i_initParamList = %p\n", i_initParamList);
printf("DLL PRINT init ---- i_initParamList->param_list_size = %i\n", i_initParamList->param_list_size);
if (i_initParamList->init_param == NULL){
printf("DLL PRINT init ---- i_initParamList->init_param must not be NULL\n");
returnedCode = 1;
}else{
for (int i = 0; i<i_initParamList->param_list_size;i++){
printf("DLL PRINT init ---- i_initParamList->init_param[i]->key = %s\n",i_initParamList->init_param[i].key);
printf("DLL PRINT init ---- i_initParamList->init_param[i]->key_value = %i\n",i_initParamList->init_param[i].key_value);
}
...
}
The java JNA code is as follows :
public interface MyLibrary extends Library {
#FieldOrder({ "key", "key_value" })
public static class Param extends Structure {
public static class ByReference extends Param implements Structure.ByReference {
}
public String key;
public int key_value;
public Param(){ // NOT sure that this adding constructor makes sense
super();
setAlignType(ALIGN_NONE);
}
}
#FieldOrder({ "init_param", "param_list_size" })
public static class ParamList extends Structure {
public static class ByReference extends ParamList implements Structure.ByReference {
}
public Param[] init_param;
public int param_list_size;
ParamList(){ // NOT sure that this adding constructor makes sense
super();
setAlignType(ALIGN_NONE);
}
}
public int Init(ParamList i_initParamList, logfunction i__callback, allocator i__allocator,
PointerByReference o__content);
...
}
The Sample.java code which calls the JNA library is as follows :
Note that I did not add the way the other parameters of Init function are managed as I do not have any issues with them.
int paramListSize = 4;
MyLibrary.Param[] params = new MyLibrary.Param[paramListSize];
for (int i = 0; i < paramListSize; i++) {
params[i] = new MyLibrary.Param();
}
params[0].key = "first";
params[0].key_value = 1;
params[1].key = "second";
params[1].key_value = 5;
params[2].key = "third";
params[2].key_value = 7;
params[3].key = "forth";
params[3].key_value = 9;
MyLibrary.ParamList paramList = new MyLibrary.ParamList.ByReference();
paramList.init_param = params;
paramList.param_list_size = paramListSize;
logger.debug("params = "+ params);
logger.debug("paramList = "+ paramList);
logger.debug("paramList.param_list_size = "+paramList.param_list_size);
int errInit = IFunctions.Init(paramList, logCallback, i__allocator, o__content);
The traces results coming from C++ and Java code are as follows :
10:41:28,303 DEBUG Sample:193 - params = [MyLibrary$Param;#1e67a849
10:41:28,312 DEBUG Sample:194 - paramList = MyLibrary$ParamList$ByReference(auto-allocated#0x1f3d49fe5b0 (52 bytes)) {
MyLibrary$Param init_param[4]#0x0=[MyLibrary$Param;#1e67a849
int param_list_size#0x30=0x0004
}
10:41:28,316 DEBUG Sample:195 - paramList.param_list_size = 4
Exception in thread "main" java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokeInt(Native Method)
at com.sun.jna.Function.invoke(Function.java:426)
at com.sun.jna.Function.invoke(Function.java:361)
at com.sun.jna.MyLibrary$Handler.invoke(MyLibrary.java:265)
at com.sun.proxy.$Proxy3.init(Unknown Source)
at Sample.main(Sample.java:216)
DLL PRINT init ---- i_initParamList = 000001F3D49FE5B0
DLL PRINT _init ---- init_param address = 0000021B4ADAF3D0
DLL PRINT init ---- i_initParamList->param_list_size = 1
DLL PRINT init ---- i_initParamList->init_param[i]->key =
It works if I declare my Structure in C++ header as follows :
typedef struct s_ParamList {
Param init_param[4];
int param_list_size; // number of param items in the param List
} ParamList;
But I do not want to define the init_param array size in the C++ code as it must be defined on java code side.
Regarding added following code in the javacode :
ParamList(){ // NOT sure that this adding constructor makes sense
super();
setAlignType(ALIGN_NONE);
}
I'm not sure that I have to add this in both structures i.e in ParamList and in Param structure.
But anyway if I delete both of those constructor I have exactly the same issue.
I saw another way to manage my requirement (looking at toArray(size) method from chapter Structure of https://javadoc.io/doc/net.java.dev.jna/jna/latest/index.html for 5.8.0 JNA version.
Indeed I also followed the link How to fill an array of structures in JNA? but I get Invalid Memory access. I'll create a separate question regarding this second kind of implementation if I cannot have my Structure's array in a Structure.
And I had to split the Param array and the size of the array in 2 separate parameters of Init function instead of setting them into a unique Structure.
And as I already have many parameters in my Init function I would prefer to have only one structure parameter. And I guess that It should be possible in JNA.
Does any one have a clue?
Thanx for your help.
The problem is in your mapping of this structure
typedef struct s_ParamList {
Param* init_param;
int param_list_size; // number of param items in the param List
} ParamList;
The * indicates this is a pointer to memory elsewhere that you need to define.
Structures are treated as ByValue by default inside structures, and as ByRefrence by default in function arguments. So here you need to explicitly define the ByReference version of the structure (or use a plain Pointer, which is less type safe.)
So you'll get this as the main part of your structure.
#FieldOrder({ "init_param", "param_list_size" })
public static class ParamList extends Structure {
public Param.ByReference init_param;
public int param_list_size;
}
Next, you've indicated you want to define this array and allocate its memory yourself in Java. The important thing to remember here is that C treats arrays as contiguous memory, so you really only have two choices: allocate a large block yourself with Memory and set values at the offsets manually; or use Structure.toArray() designed for exactly this case: You start with an instantiated structure and then tell the toArray() method how many copies of it you need.
So your sample code would look like this:
int paramListSize = 4;
// Note the syntax for allocating a contiguous array
MyLibrary.Param.ByReference[] params =
(MyLibrary.Param.ByReference[]) new MyLibrary.Param.ByReference().toArray(paramListSize);
// set the values as you've alread done
params[0].key = "first";
params[0].key_value = 1;
// and so on...
// Now instantiate your structure and set its members
MyLibrary.ParamList paramList = new MyLibrary.ParamList();
// The first array member is the pointer to the start of the array
paramList.init_param = params[0];
paramList.param_list_size = paramListSize;
And here, you pass it to the native function. It is ByReference by default.
You can find another general example here
Can you consider following data structure?
typedef struct s_ParamList {
int param_list_size; // number of param items in the param List
Param init_param[0];
} ParamList;
If yes, please be accurate with memory allocation and array usage, since such approach is pretty dangerous and may easily cause data overrun
My native code is
typedef struct driver_config {
unsigned int dllVersion;
unsigned int channelCount;
unsigned int reserved[10];
ChannelConfig channel[64];
} DriverConfig;
In Java my class looks like this
public class DriverConfig extends Structure {
public int dllVersion;
public int channelCount;
public int[] reserved= new int[10];
ChannelConfig[] channel = new ChannelConfig[64];
public DriverConfig() {
super();
init();
}
private void init() {
for (int i = 0; i < channel.length; i++) {
channel[i]= new ChannelConfig();
}
}
#Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "dllVersion", "channelCount", "reserved" });
}
//toString()...
}
The method declaration is
int getDriverConfig(DriverConfig driverConfig);
I tried to access the method like this
DriverConfig driverConfig = new DriverConfig();
status = dll.INSTANCE.getDriverConfig(driverConfig);
System.out.println("DriverConfig Status: " + status);
System.out.println(driverConfig.toString());
If channel.length is replaced with less then 50 the array is initialized correctly but with channel.length it did not work. It even did not show any error just nothing.
Your getFieldOrder() array does not include the last element (channel) of your structure. I see in your comments that you attempted to do this but received an error because you have not declared it public. All elements of your structure must be listed in the FieldOrder and also declared public so they can be found with reflection.
Also, with JNA 5.x (which you should be using) the #FieldOrder annotation is preferred.
You haven't identified the mapping for ChannelConfig, but your question title and this API link matching your structure indicate that it is a nested structure array. Structure arrays must be allocated using contiguous memory, either by directly allocating the native memory (new Memory()) which requires knowing the structure size, or by using Structure.toArray(). Allocating in a loop as you have done will end up with memory for each new structure allocated at possibly/probably non-contiguous locations in native memory. Given that you state that it appears to work for some values, you might be getting lucky with contiguous allocations, but your behavior is certainly undefined.
Your structure mapping should therefore be:
#FieldOrder ({"dllVersion", "channelCount", "reserved", "channel"})
public class DriverConfig extends Structure {
public int dllVersion;
public int channelCount;
public int[] reserved= new int[10];
public ChannelConfig[] channel = (ChannelConfig[]) new ChannelConfig().toArray(64);
}
I have used a static variable in a Class and I want that the value of this variable is kept unchanged after restart of the jvm.
The idea is to store this value.
Can someone help me ?
If you want a variable whose value can change during the execution of the code, to be restored to whatever it was when you stopped the JVM, the next time you start the JVM, then you need to persist the value to an external medium. This is typically done by storing the value in a file or database, and retrieving it the next time the program starts. A key question when solving this problem is how to represent the value outside the executing program. For simple types like numbers and strings, this is not much of an issue. For values that are objects of non-trivial classes, the problem becomes more interesting. This is known as object serialization.
With the disclaimer that there are many different ways to persist data, here is a minimal example using Java Serialization to make the point more concrete.
class MyClassData implements Serializable {
private String myString = "A string";
private int myNumber = 5;
// To make the point that the state of the object stored in the
// variable can change at run-time.
public void changeThings( String myString, int myNumber) {
this.myString = myString;
this.myNumber = myNumber;
}
}
public class MyClass {
private static MyClassData data = restore();
// Call before exiting the program
private static void store() {
try( ObjectOutputStream out =
new ObjectOutputStream(new FileOutputStream("data.dat"))) {
out.writeObject(data);
}
catch( IOException e ) {
// Deal with this
}
}
private static MyClassData restore() {
try( ObjectInputStream in =
new ObjectInputStream(new FileInputStream("data.dat"))) {
return (MyClassData) in.readObject();
}
catch( IOException | ClassNotFoundException e ) {
return new MyClassData();
}
}
}
You restart the jvm every thing will be clear.So you can't get the values from static variables. If you use database then only you get the values without failing.
I have the following C code which I am calling from JNA. When I call it I am getting 0 as the return value while I'm getting the real value when I test it in C.
RFIDLIB_API uint32_t get(
ipj_key key /*[i]*/,
uint32_t bank_index /*[in]*/,
uint32_t value_index /*[out]*/,
uint32_t *value /*[out]*/)
{
return ipj_get(&iri_device,key,bank_index,value_index,value);
}
Below is how I have defined this in my JNA library.
public int get(ipj_key key, int bank_index, int value_index, IntByReference value);
Below is the ip_key structure
public class ipj_key extends Structure {
public int ipj_key;
#Override
protected List getFieldOrder() {
return Arrays.asList("ipj_key");
}
}
And below is how I am calling it in my main method.
public rfidlib rlib;
public static void main(String[] args) {
MainScannerTest mainClass = new MainScannerTest();
mainClass.rlib = (rfidlib) Native.loadLibrary("rfidlib", rfidlib.class);
ipj_key key = new ipj_key();
key.ipj_key = 0xD;
IntByReference value = new IntByReference();
mainClass.rlib.get(key, 0, 0, value);
System.out.println("Antenna power is : "+ value.getValue());
}
What am I doing wrong here? Why am I getting 0 as the return value? Please advice.
My C lib has a int* as an OUT parameter. I was also trying to use it with an IntByReference, without any success.
EDIT 2017-03-16: indeed it worked with IntByReference. There might me something wrong in your C code.
An alternative would be using a Pointer instead of IntByreference
(I made it work with IntByRef and also with Pointer in my case (64bit Win7, JNA 4.3.0 and Java 64 bits jdk 1.8.0_71))
With your code snippet, this would look like the following.
First change your JNA dll interface defintion (use Pointer instead of IntByReference):
public int get(ipj_key key, int bank_index, int value_index, /*change is here*/ Pointer value);
Then change of course the variable before call:
Pointer value = new Memory(Integer.size); // Here we assume that your java platform is 32 bits (Integer.size=32)
//this should match your uint32_t. No idea if there are consequences when mixing 32/64 bits java/OS/dll ...
Then, you can do the following:
System.out.println("Antenna power is : "+ value.getInt(0));
// The offset is set to 0, since there is no reason to read the int from another offset value.
I'm trying to use JNA to query the effective permissions for a file in Windows. Eventually, I plan on using the GetEffectiveRightsFromAcl function, but to do so, I need to provide a pointer to a populated TRUSTEE structure. The JNA Platform (platform.jar) doesn't appear define this struct, so I'm trying to define it myself instead. Here's what I have so far:
public static class TRUSTEE extends Structure {
public TRUSTEE() {
super();
}
public TRUSTEE(Pointer p) {
super(p);
read();
}
public Pointer pMultipleTrustee;
public int MultipleTrusteeOperation;
public int TrusteeForm;
public int TrusteeType;
public Pointer ptstrName;
}
I'm trying to populate the structure like this:
private TRUSTEE createTrusteeForCurrentUser() {
TRUSTEE result = new TRUSTEE();
result.TrusteeForm = TRUSTEE_FORM.TRUSTEE_IS_NAME;
result.TrusteeType = TRUSTEE_TYPE.TRUSTEE_IS_USER;
String strName = "CURRENT_USER";
// How can I set result.ptstrName using strName?
}
This Google Groups thread recommends using String fields in structures when a char * is called for. However, I don't think this is appropriate in my situation, considering the ptstrName field is allowed to point to different types of things, depending on the value of TrusteeForm. So, I think I somehow need to convert from String to Pointer instead. I found the NativeString class in JNA, which would work, except it's a package-private class.
What's the recommended way to convert a Java String to a native format and obtain a Pointer to it? Am I even using the right data type for the TRUSTEE struct? I'm somewhat new to JNA, so please excuse me if I'm missing something obvious.
Update
I found a solution to my problem, but if anyone has a better solution I'd still like to hear it.
Assuming you want char * on the native side (you may need more memory allocated if the string contains non-ascii characters),
String myString = "CURRENT_USER";
Pointer m = new Memory(myString.length() + 1); // WARNING: assumes ascii-only string
m.setString(0, myString);
You can then use m wherever you need to reference the "native" string.
For wide strings (wchar_t *),
String myString = "CURRENT_USER";
Pointer m = new Memory(Native.WCHAR_SIZE * (myString.length() + 1));
m.setWideString(0, myString);
I solved the problem by copying the source code for package-private NativeString class and creating a public copy in my project. I had to make one minor alteration due to the use of a package-private method in the constructor.
Update: As #fragorl notes in the comments, the implementation of NativeString shown below is by now quite out-of-date.
Usage:
private static TRUSTEE createTrusteeForCurrentUser() {
TRUSTEE result = new TRUSTEE();
result.TrusteeForm = TRUSTEE_FORM.TRUSTEE_IS_NAME;
result.TrusteeType = TRUSTEE_TYPE.TRUSTEE_IS_USER;
result.ptstrName = new NativeString("CURRENT_USER",true).getPointer();
result.write();
return result;
}
NativeString.java:
/** Provides a temporary allocation of an immutable C string
* (<code>const char*</code> or <code>const wchar_t*</code>) for use when
* converting a Java String into a native memory function argument.
*
* #author Todd Fast, todd.fast#sun.com
* #author twall#users.sf.net
*/
public class NativeString implements CharSequence, Comparable {
private Pointer pointer;
private boolean wide;
/** Create a native string (NUL-terminated array of <code>char</code>).<p>
* If the system property <code>jna.encoding</code> is set, its value will
* be used to encode the native string. If not set or if the encoding
* is unavailable, the default platform encoding will be used.
*/
public NativeString(String string) {
this(string, false);
}
/** Create a native string as a NUL-terminated array of <code>wchar_t</code>
* (if <code>wide</code> is true) or <code>char</code>.<p>
* If the system property <code>jna.encoding</code> is set, its value will
* be used to encode the native <code>char</code>string.
* If not set or if the encoding is unavailable, the default platform
* encoding will be used.
*
* #param string value to write to native memory
* #param wide whether to store the String as <code>wchar_t</code>
*/
public NativeString(String string, boolean wide) {
if (string == null) {
throw new NullPointerException("String must not be null");
}
// Allocate the memory to hold the string. Note, we have to
// make this 1 element longer in order to accommodate the terminating
// NUL (which is generated in Pointer.setString()).
this.wide = wide;
if (wide) {
int len = (string.length() + 1 ) * Native.WCHAR_SIZE;
pointer = new Memory(len);
pointer.setString(0, string, true);
}
else {
byte[] data = Native.toByteArray(string);
pointer = new Memory(data.length + 1);
pointer.write(0, data, 0, data.length);
pointer.setByte(data.length, (byte)0);
}
}
public int hashCode() {
return toString().hashCode();
}
public boolean equals(Object other) {
if (other instanceof CharSequence) {
return compareTo(other) == 0;
}
return false;
}
public String toString() {
String s = wide ? "const wchar_t*" : "const char*";
s += "(" + pointer.getString(0, wide) + ")";
return s;
}
public Pointer getPointer() {
return pointer;
}
public char charAt(int index) {
return toString().charAt(index);
}
public int length() {
return toString().length();
}
public CharSequence subSequence(int start, int end) {
return CharBuffer.wrap(toString()).subSequence(start, end);
}
public int compareTo(Object other) {
if (other == null)
return 1;
return toString().compareTo(other.toString());
}
}
try using Pointer class in http://jna.java.net/javadoc/com/sun/jna/Pointer.html.