JNA - How to turn `char ***devices` PointerByReferences to `char **devices` PointerByReference - java

Here is the c header file:
idevice_error_t idevice_get_device_list(char ***devices, int *count);
idevice_error_t idevice_device_list_free(char **devices);
Here is the JNA that JNAerator generated for me:
int idevice_get_device_list(PointerByReference devices, IntBuffer count);
int idevice_device_list_free(PointerByReference devices);
Here is how I'm using it. It's in Kotlin, but it's equivalent to what you'd do in Java too:
fun getDeviceList(): List<String> {
val deviceUuidsPbr = PointerByReference()
val deviceSizeBuffer = IntBuffer.wrap(IntArray(1))
val resultInt = LibIMobileDeviceLibrary.INSTANCE.idevice_get_device_list(deviceUuidsPbr, deviceSizeBuffer)
val size = deviceSizeBuffer.get()
logger.v {"getDeviceList $resultInt, Size: $size" }
val stringArrayP = deviceUuidsPbr.value
val devices = stringArrayP
.getStringArray(0, size)
.toList()
logger.v { "Devices: $devices" }
LibIMobileDeviceLibrary.INSTANCE.idevice_device_list_free(deviceUuidsPbr)
return devices
}
Everything blows up when I free memory:
LibIMobileDeviceLibrary.INSTANCE.idevice_device_list_free(deviceUuidsPbr)
The free wants a char **devices, but I'm submitting a char ***devices. How should I get the PointerByReference into the correct format?

A PointerByReference is just a pointer (to a pointer). And the two C functions being mapped simply have an extra level of indirection.
Consider this function definition:
device_get_device_list(char ***devices, int *count);
idevice_device_list_free(char **devices);
now consider foo defined to be *devices and the original functions simplify to:
device_get_device_list(char **foo, int *count);
idevice_device_list_free(char *foo);
And if you define bar as *foo you get:
device_get_device_list(char *bar, int *count);
idevice_device_list_free(char bar);
So you cannot pass the PointerByReference you are receiving from device_get_device_list (*bar) directly to idevice_device_list_free (which needs bar); you pass its pointed-to value (which happens to be a pointer to another pointer, but that doesn't matter.)
In Java you would simply change the argument in your idevice_device_list_free() call from deviceUuidsPbr to deviceUuidsPbr.getValue().
I am not a Kotlin user but it would seem based on your other code that you need deviceUuidsPbr.value there.

Related

Getting base address of dll of specific process using JNA

Updated: See updates at the bot of the question
I would like to get base address of game.dll which is inside war3.exe process.
I'm trying to do it via JNA library version 5.9.0, but no success.
The issue I faced with: I can't get game.dll module from war3.exe process.
I tried to get it using:
int pid = getProcessId("Warcraft III");
openProcess(PROCESS_ALL_ACCESS, pid);
WinDef.HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle("game.dll")
But the result of hMod is null.
Also I have tried to get all modules that war3.exe process has. As you may see it contains only 5 modules and it doesn't contain game.dll. But when I open war3.exe via Process Explorer I see definitely more than 5.
Executed with Intellij Idea:
Taken from Process Explorer:
Please, share your opinion and ideas why I get only 5 modules from IDE.
Any advice on how to get the game.dll module and its base address via JNA would be appreciated.
Updates:
As per Remy's answer I have made one more try with EnumProcessModules().
Here is my code snippet:
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Psapi;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HMODULE;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.ptr.IntByReference;
import java.util.Arrays;
import java.util.List;
import static com.sun.jna.platform.win32.WinNT.PROCESS_ALL_ACCESS;
import static handler.memory.MemoryHandler.openProcess;
public class MemoryHandler {
static final User32 user32 = User32.INSTANCE;
static final Psapi psapi = Psapi.INSTANCE;
public static void main(String[] args) {
int pid = getProcessId("Warcraft III");
HANDLE process = openProcess(PROCESS_ALL_ACCESS, pid);
HMODULE[] hMods = new HMODULE[1024];
psapi.EnumProcessModules(process, hMods, hMods.length, new IntByReference(1024));
List<HMODULE> hModList = Arrays.asList(hMods);
hModList.forEach(hMod ->
System.out.println(Pointer.nativeValue(hMod.getPointer())));
}
public static int getProcessId(String window) {
IntByReference pid = new IntByReference(0);
user32.GetWindowThreadProcessId(user32.FindWindow(null, window), pid);
return pid.getValue();
}
}
And here is the result:
As far as I understand I have got some pointers. But how should I understand which one from them is related to game.dll? I was assuming that I should get somehow the list on modules where I could see their names and base addresses.
Also if I change System.out.println(Pointer.nativeValue(hMod.getPointer()))); to hModList.forEach(System.out::println); I see the following pointers and a lot of nulls (about 1000).
Do these addresses contain the address of game.dll?
GetModuleHandle() looks in the calling process only. Since game.dll is not loaded in your own process, GetModuleHandle() can't find it.
To look for a module loaded in another process, you need to use either:
EnumProcessModules()/EnumProcessModulesEx(), using GetModuleFileNameEx() to get their file names. See Enumerating All Modules for a Process.
CreateToolhelp32Snapshot(TH32CS_SNAPMODULE|TH32CS_SNAPMODULE32), using Module32First()/Module32Next() to enumerate the snapshot. See Traversing the Module List.
Kernel32Utils.getModules() uses CreateToolhelp32Snapshot(TH32CS_SNAPMODULE), so if your Java app is running as a 64bit app then it will enumerate only 64bit modules. But war3.exe is running as a 32bit process in your screenshot, so if you use CreateToolhelp32Snapshot() in a 64bit process then you would need to use TH32CS_SNAPMODULE32 instead.
UPDATE:
As I mentioned above, if you go the EnumProcessModules() approach, you can use GetModuleFileNameEx() to determine the filename of each module. That way, you can find the module for game.dll.
More importantly:
you are lacking needed error handling of each system call. Always test return values for failures.
not an error per-se, but you really should not be requesting PROCESS_ALL_ACCESS rights with openProcess(). Request only the rights you actually need, no more. In this case, use PROCESS_QUERY_INFORMATION | PROCESS_VM_READ instead.
you are not looking at the output of the 4th parameter of EnumProcessModules() to know how many modules were actually stored in the array.
your input values of the 3rd and 4th parameters of EnumProcessModules() are wrong, they need to be expressed in bytes, not in elements.
Per the EnumProcessModules() documentation:
cb
The size of the lphModule array, in bytes.
lpcbNeeded
The number of bytes required to store all module handles in the lphModule array.
...
It is a good idea to specify a large array of HMODULE values, because it is hard to predict how many modules there will be in the process at the time you call EnumProcessModules. To determine if the lphModule array is too small to hold all module handles for the process, compare the value returned in lpcbNeeded with the value specified in cb. If lpcbNeeded is greater than cb, increase the size of the array and call EnumProcessModules again.
To determine how many modules were enumerated by the call to EnumProcessModules, divide the resulting value in the lpcbNeeded parameter by sizeof(HMODULE).
Finally I found solution, but not in Java or JNA.
I wrote this code using C++ and I will use it like dll in Java.
Here is my C++ code:
#include <conio.h>
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
#include <psapi.h>
using namespace std;
DWORD_PTR GetProcessBaseAddress(DWORD processID)
{
DWORD_PTR baseAddress = 0;
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
HMODULE* moduleArray;
LPBYTE moduleArrayBytes;
DWORD bytesRequired;
if (processHandle)
{
if (EnumProcessModules(processHandle, NULL, 0, &bytesRequired))
{
if (bytesRequired)
{
moduleArrayBytes = (LPBYTE)LocalAlloc(LPTR, bytesRequired);
if (moduleArrayBytes)
{
unsigned int moduleCount;
moduleCount = bytesRequired / sizeof(HMODULE);
moduleArray = (HMODULE*)moduleArrayBytes;
if (EnumProcessModules(processHandle, moduleArray, bytesRequired, &bytesRequired))
{
baseAddress = (DWORD_PTR)moduleArray[0];
}
LocalFree(moduleArrayBytes);
}
}
}
CloseHandle(processHandle);
}
return baseAddress;
}
DWORD GetProcessId(LPCTSTR ProcessName) // non-conflicting function name
{
PROCESSENTRY32 pt;
HANDLE hsnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
pt.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hsnap, &pt)) { // must call this first
do {
if (!lstrcmpi(pt.szExeFile, ProcessName)) {
CloseHandle(hsnap);
return pt.th32ProcessID;
}
} while (Process32Next(hsnap, &pt));
}
CloseHandle(hsnap); // close handle on failure
return 0;
}
uintptr_t GetModuleBaseAddress(DWORD procId, const wchar_t* modName)
{
uintptr_t modBaseAddr = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procId);
if (hSnap != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 modEntry;
modEntry.dwSize = sizeof(modEntry);
if (Module32First(hSnap, &modEntry))
{
do
{
if (!_wcsicmp(modEntry.szModule, modName))
{
modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &modEntry));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
int main()
{
DWORD pid = GetProcessId(TEXT("war3.exe"));
cout << "Process ID of war3.exe: "<< pid << endl;
DWORD_PTR war3_exe_base_addr = GetProcessBaseAddress(pid);
cout <<"Base address of war3.exe: "<< war3_exe_base_addr << endl;
uintptr_t gameDllBaseAddress = GetModuleBaseAddress(pid, TEXT("game.dll"));
cout <<"Base address of game.dll: " << gameDllBaseAddress << endl;
}
The result is:

How to retrieve a struct from Renderscript kernel [duplicate]

This question already has answers here:
Returning a Renderscript struct from a Renderscript kernel
(2 answers)
Closed 6 years ago.
I have a problem. I would like to retrieve a struct from a renderscript kernel. What I wanted was that I would get an input a struct element... I would modify it and then return it modified. But there is no such a way in the reflected layer. I tryied to manually deserialize the data from the buffer but I am not even able to copy the buffer to a ByteBuffer because the Allocation has validation in the copyTo on a type so I have no idea what am I supposed to do...
RenderScript supports custom elements. To create one, declare a custom typedef struct like the following one, inside a RS script:
typedef struct MyElement {
int x;
int y;
bool simpleBool;
} MyElement_t;
After the build process, a ScriptField_MyElement Java class will appear, mirroring the RS struct. You will be able to use this class to create a custom Allocation that uses your own Element:
// Declares a new Allocation, based upon the custom struct Element
Element myElement = ScriptField_MyElement.createElement(mRS);
Allocation myElementsAllocation = Allocation.createSized(mRS, myElement, 5);
// Or
Allocation myElementsAllocation = ScriptField_MyElement.create1D(mRS, sizeX).getAllocation();
You can find an example of this process inside the CustomElementExample sample project.
Also, inside the SurfaceRenderExample sample project you can see how a custom element can be used to model a mathematical structure (in this case a particle, falling with some acceleration).
Inside RenderScript scripts:
To get a custom element from an allocation:
MyElement_t el = * (MyElement_t *) rsGetElementAt(aIn, index);
To change a custom element member:
el.x = 10;
To set a custom element in an allocation:
rsSetElementAt(myAlloc, (void *)&el);
Reference: RenderScript: parallel computing on Android, the easy way
Edit:
For now, there is no direct way to copy a custom struct element to the Java side.
The CustomStructElementCopyToJava sample project provides an example of the process.
Short explanation of the example
Note: the following process is EXPERIMENTAL and not performant at all! If you plan to heavily use this process, please use the Android NDK to access the allocation.
Also, in future versions of the Android SDK, this code may break because it relies on Java reflection; some normally hidden methods can change without any notice in the Android SDK.
Let's assume using the following custom struct element:
typedef struct Point {
int x;
int y;
} Point_t;
When looking at the generated code of the struct (which can be seen, in Android Studio, by pressing CTRL+B while focusing on a ScriptField_Point element on the Java side), the following elements can be seen:
public static Element createElement(RenderScript rs) {
Element.Builder eb = new Element.Builder(rs);
eb.add(Element.I32(rs), "x");
eb.add(Element.I32(rs), "y");
return eb.create();
}
You can map the contents of the custom struct in a hacky way:
1) Define the destination byte array:
byte destinationArray[] = new byte[allocationGrayPointOrdered.getBytesSize()];
2) Use Java reflection to access the hidden Allocation.copyTo method:
private static Method getCopyToWithoutValidationMethod(){
// private void copyTo(Object array, Element.DataType dt, int arrayLen)
Method allocationHiddenCopyToMethod = null;
try {
allocationHiddenCopyToMethod = Allocation.class.getDeclaredMethod("copyTo", Object.class, Element.DataType.class, int.class);
allocationHiddenCopyToMethod.setAccessible(true);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Could not find allocationHiddenCopyToMethod");
}
return allocationHiddenCopyToMethod;
}
3) Perform the copy:
// Gets reflected method
Method copyToWithoutValidationMethod = getCopyToWithoutValidationMethod();
// Tries to copy contents
try {
copyToWithoutValidationMethod.invoke(allocationGrayPointOrdered, destinationArray,
Element.DataType.UNSIGNED_8, destinationArray.length);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
4) Once the array is filled with source data, it is then possible to map its content to a human-readable struct.
// Defines the destination array
ScriptField_Point.Item mappedItems[][] = new ScriptField_Point.Item[sizeX][sizeY];
// Wraps array contents
ByteBuffer byteBuffer = ByteBuffer.wrap(destinationArray);
// Sets byte order to be Android-like
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
// Iterates on every column and row
for (int x = 0; x < sizeX; x++) {
for (int y = 0; y < sizeY; y++) {
// Allocates a new item
ScriptField_Point.Item currentItem = new ScriptField_Point.Item();
// Calculate the offset in the source array
int currentOffset = (x + y * sizeX) * ScriptField_Point.Item.sizeof;
// Gets data from the byte array
currentItem.x = byteBuffer.getInt(currentOffset);
currentItem.y = byteBuffer.getInt(currentOffset + 4);
mappedItems[x][y] = currentItem;
}
}
For the complete explanation, please refer to the book.

JNA: Set struct pointer to NULL

I am starting to use JNA to communicate with a device on the RS485 interface of a computer. Suprisingly to me I came to good results very quickly. But now I am stuck by a simple problem. The library I use accepts a pointer to a pointer of struct. The actual signature is
func(Struct1 **, Struct2 **, Struct3 *, Struct4 *, long)
Now to indicate the size of the first parameter the library expects the last pointer to be a NULL pointer. This is what fails. Following code is what I tried so far:
Struct1.ByReference[] s = (Struct1.ByReference[]) new Struct1.ByReference().toArray(size);
int pos = 0;
// ...
// for loop to set the s[pos] struture values
for(pos = 0; pos < size - 1; pos++)
// ...
// Now set the last array element to a null pointer to indicate end-of-list
s[pos].getPointer().setPointer(0, null);// Following does not work: results in zero memoried structure
s[pos] = null; // Following does not work wither: NullPointerException at com.sun.jna.Structure.autoWrite
EDIT 1
s[pos] = new Struct1.ByReference(Pointer.NULL); // results in zero memoried structure as well
EDIT 2
According to technomage's question. If I were to write C code it would probably look something like that:
Struct1 **s = malloc(n * sizeof(Struct1*));
for(int i=0; i<n; i++)
{
if(i == n -1)
{
s[i] = NULL;
}
else
{
s[i] = malloc(sizeof(Struct1));
s[i].bla = value;
....
}
}
But be warned: I am not very skilled in C/C++. I consider Java to be my domain.
Has anyone had a similar problem? Maybe I am just not seeing the wood for the trees...
Thanks in advance.
Structures in JNA are pointers, so what you really need here is a pointer to a (pointer to a) Structure, which is a PointerByReference -- in your case, an array of them.
Given the code example above, you'll create your array of Structures, one less than n:
Struct1[] struct1Array = new Struct1[n-1];
This only allocates the Java memory for the array.
Next you'll instantiate and write the changes you make to native memory:
for (int i = 0; i < n-1; i++) {
struct1Array[i] = new Struct1();
struct1Array[i].bla = value;
struct1Array[i].write();
}
The new Struct1() allocates native side memory for these structures. It's possible to use the Structure.toArray() method to do this as well; I'm intentionally doing this a bit more manual and low-level to try to make clear what's happening.
Then you'll create a corresponding PointerByReference array to hold the pointers to these structures. You'll add an extra element for the null:
PointerByReference[] pbrArray = new PointerByReference[n];
Again, this is only java-side allocation. And then you fill it with pointers to the pointers to the structure, obtained from the Structure.getPointer() method:
for (int i = 0; i < n-1; i++) {
pbrArray[i] = new PointerByReference(struct1Array[i].getPointer());
}
pbrArray[n - 1] = new PointerByReference(Pointer.NULL);
The new PointerByReference() here allocates the native side memory for the pointer itself, which points to the native-side structure you allocated earlier.
From how I understand your initial question, you will pass this PointerByReference array to your function, which presumably updates your structures.
Since you created the two arrays in this fashion, you can keep track of their correspondence by array index. You may have to iterate through the structure array and read() the native memory into the Java-side structure to do further processing with it. Typically when you work directly with Structures being passed to methods they autowrite and autoread, but when using a PointerByReference to indirectly reference the Structure, JNA isn't as friendly.
As an alternative to tracking the two arrays by corresponding indices, you could "forget" the initial Structure assignment and recover it later using the PointerByReference.getValue() method on your array to recover a pointer to the memory for the structure, and then instantiate a new structure using that Pointer in its constructor (e.g. new Struct1(pbr.getValue()) which calls super() with that pointer).

JNA getting back a byte array

I have a library developed in C that successfully decompresses an LZMA encoded file. The signature for the file is a pointer to the data, the compressed, decompressed, and an 'out' field for the error code. The return value is a pointer to the array (or null if it fails).
The function in C looks similar to this:
char* decompressLZMA(const char *lzmaData, int compressedSize, int uncompressedSize, t_status_codes *statusCode);
I've tried using pointers and memory from other examples but they are not working.
How do I properly pass a byte array and pointer in to get data back?
This is my interface:
public interface LZMALibrary extends Library {
Memory lzma_uncompress(Memory lzma_data, int compressed_size, int uncompressed_size, Pointer status_code);
}
It appears that I wanted to make a pointer of the 'Memory' class instead. The solution that is working for me right now is to create Pointer objects, and then the library will fill up the pointers, and I get them back and handle it appropriately.
My interface turned to:
public interface LZMALibrary extends Library {
Pointer lzma_uncompress(Pointer lzma_data, int compressed_size, int uncompressed_size, Pointer status_code);
}
From there I am able to write in the data:
Pointer ptr = new Memory(lzmaData.length);
ptr.write(0, lzmaData, 0, lzmaData.length);
I also need the pointer that will be written to:
Pointer errorStatus = new Memory(4);
Then I can call the function to get a pointer back, and read that pointer if it's not null:
Pointer p = lzmaLib.lzma_uncompress(ptr, lzmaData.length, DECOMPRESSED_LENGTH, errorStatus); // DECOMPRESSED_LENGTH is a constant.
if (p != null) {
byte[] decompressedData = p.getByteArray(0, DECOMPRESSED_LENGTH);
System.out.println(new String(decompressedData, "ASCII")); // My data is ASCII text.
}
if (errorStatus != null) {
int errorStatusCode = errorStatus.getInt(0);
System.out.println("Error code: " + errorStatusCode);
}
This appears to have solved my problem. I am very new to JNA so hopefully I am not missing anything.
If there's any possible errors I might run into, please feel free to post on how to correct it.

JNA: EXCEPTION_ACCESS_VIOLATION

I'm using a C++ DLL via JNA.
I want to call the following method in Java, which writes into szVisor information that I want to read.
long FAR PASCAL DLL_GetLocalPortTS(char* szEquip,char* szVisor){
...
}
The Java interface implementation is the following:
public interface IE2E extends Library {
// Instancia de la dll, carga la librería
IE2E INSTANCE = (IE2E) Native.loadLibrary("e2e", IE2E.class);
...
int GetLocalPortTS(String equip, String[] equipInfo);
}
And the method call:
String equip = "equipID";
String equipInfo = "";
String[] rEquipInfo = {equipInfo};
IE2E sdll = IE2E.INSTANCE;
int ret = sdll.GetLocalPortTS(equip, rEquipInfo);
This execution nets me a fatal error in the JRE, but if I put both arguments as either String or String[] it doesn't. However, if I use both Strings it doesnt overwrite equipInfo and I don't get the info which I want; if I use both as arrays, the method doesn't get the equip value and doesn't operate.
Any insight on this will be welcome.
The problem is that the C code wants to write into szVisor, right? I guess it does something like this:
long GetLocalPortTS(char* szEquip,char* szVisor){
strcpy(szVisor, "I am C code result :)");
return 0;
}
If you pass in a String from the Java side, then the memory is owned by the JVM, so writing to it causes a crash. What you need is a Memory object, which is a wrapped malloc'd bit of memory that the C code can safely write to.
Your new JNA interface would be as follows. I've commented out the old version so you can compare:
public interface IE2E extends Library {
IE2E INSTANCE = (IE2E) Native.loadLibrary("e2e", IE2E.class);
//int GetLocalPortTS(String equip, String[] equipInfo);
int GetLocalPortTS(String equip, Memory equipInfo);
}
And the code to call it would be as follows, the 256 is a placeholder. Make sure you allocate enough to write the string to:
String equip = "equipID";
String equipInfo = "";
//String[] rEquipInfo = {equipInfo};
Memory rEquipInfo = new Memory(256);
IE2E sdll = IE2E.INSTANCE;
int ret = sdll.GetLocalPortTS(equip, rEquipInfo);
To use the result as a String, you'd do this:
rEquipInfo.getString(0);
As the documentation says, the Memory's finalize() method automatically calls free on the malloc'd memory so there's no need to worry about memory leaks.

Categories

Resources