I'd like to use native windows api function in my java class.
The function I am interested in is GetShortPathName.
http://msdn.microsoft.com/en-us/library/aa364989%28VS.85%29.aspx
I tried to use this - http://dolf.trieschnigg.nl/eightpointthree/eightpointthree.html
but in some conditions java crashes completely when I use it, so it is not the option for me.
The question is
Do I have to write code in e.g C, make DLL and then use that DLL in JNI/JNA?
Or maybe I somehow can access the system API in different way?
I will appreciate your comments.
If maybe you could post some code as the example I would be grateful.
...
I found the answer using JNA
import com.sun.jna.Native;
import com.sun.jna.platform.win32.Kernel32;
public class Utils {
public static String GetShortPathName(String path) {
byte[] shortt = new byte[256];
//Call CKernel32 interface to execute GetShortPathNameA method
int a = CKernel32.INSTANCE.GetShortPathNameA(path, shortt, 256);
String shortPath = Native.toString(shortt);
return shortPath;
}
public interface CKernel32 extends Kernel32 {
CKernel32 INSTANCE = (CKernel32) Native.loadLibrary("kernel32", CKernel32.class);
int GetShortPathNameA(String LongName, byte[] ShortName, int BufferCount);
}
}
Thanks for hint. Following is my improved function. It uses Unicode version of the GetShortPathName
import com.sun.jna.Native;
import com.sun.jna.platform.win32.Kernel32;
public static String GetShortPathName(String path) {
char[] result = new char[256];
Kernel32.INSTANCE.GetShortPathName(path, result, result.length);
return Native.toString(result);
}
Related
I'm trying to change the desktop wallpaper on windows 7 with the IActiveDesktop interface. So I start my project and I first use the SystemParametersInfo method using the User32 class. But there isn't fade effect and I can't modify the image position. After some research, I found the IActiveDesktop interface and this question. I took the answer and I adapt it. But when I running my code, it throw Exception in thread "main" com.sun.jna.platform.win32.COM.COMException: No such interface supported(HRESULT: 80004002).
Here you can find my code:
First the class which represent the IActiveDesktop interface
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.COM.COMUtils;
import com.sun.jna.platform.win32.COM.Unknown;
import com.sun.jna.platform.win32.*;
import com.sun.jna.ptr.PointerByReference;
import static com.sun.jna.platform.win32.Ole32.INSTANCE;
public class ActiveDesktop extends Unknown {
// {75048700-EF1F-11D0-9888-006097DEACF9}
// {F490EB00-1240-11D1-9888-006097DEACF9}
private static final Guid.GUID CLSID_ActiveDesktop = getGUID("{75048700-EF1F-11D0-9888-006097DEACF9}");
private static final Guid.GUID IID_IActiveDesktop = getGUID("{F490EB00-1240-11D1-9888-006097DEACF9}");
private static Guid.GUID getGUID(String guidStr) {
Guid.GUID guid = new Guid.GUID();
INSTANCE.IIDFromString(guidStr, guid);
return guid;
}
private ActiveDesktop(Pointer pvInstance) {
super(pvInstance);
}
public static ActiveDesktop create(){
PointerByReference p = new PointerByReference();
WinNT.HRESULT hr = INSTANCE.CoCreateInstance(CLSID_ActiveDesktop, null, WTypes.CLSCTX_INPROC_SERVER, IID_IActiveDesktop, p); // THE EXCEPTION IS THROW HERE
COMUtils.checkRC(hr);
return new ActiveDesktop(p.getValue());
}
}
And the Main which just load the Ole32 librairy and IActiveDesktop interface:
import com.sun.jna.platform.win32.Ole32;
public class Main {
public static void main(String[] args) {
Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED);
try {
ActiveDesktop desktop = ActiveDesktop.create();
} finally {
Ole32.INSTANCE.CoUninitialize();
}
}
}
After a lot of googling, I cannot find an answer. Can anyone help me? May be the answer is where I found this code... In this case, please explain me what's wrong. Thank you.
NB: I'm french so my english isn't perfect. I'm sorry...
I finally found a solution. Which is to replace Ole32.COINIT_MULTITHREADED by Ole32.COINIT_APARTMENTTHREADED when initialize Ole32.
I'm trying to get the base address of a module from a process to which I have a handle to. I've tried this using the CreateToolhelp32Snapshot and EnumProcessModules methods.
The problem is it both methods return only these 5 DLLs:
underrail.exe
ndll.dll
wow64.dll
wow64win.dll
wow64cpu.dll
I know there should be more modules and trying to use this in other games returns the same 5 modules.
I have found some answers to the same question but both of them don't work out for me:
https://www.unknowncheats.me/forum/counterstrike-global-offensive/169030-modules.html
JNA - EnumProcessModules() not returning all DLLs?
The first one doesn't work since I can't use TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32 as the flags in the method.
The second one doesn't work because I can't call the method EnumProcessModulesEx()
when I try to call Psapi.INSTANCE.EnumProcessModulesEx(...)
Here is a snippet of my code:
public static int getModuleBaseAddress(int process_id) {
DWORD pid = new DWORD(process_id);
HANDLE snapshot = null;
snapshot = kernel32.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPMODULE, pid);
MODULEENTRY32W module = new MODULEENTRY32W();
while(Kernel32.INSTANCE.Module32NextW(snapshot, module)) {
String s = Native.toString(module.szModule);
Pointer x = module.modBaseAddr;
System.out.println(s);
System.out.println(x);
System.out.println("---");
}
return 0;
}
Note that using Tlhelp32.TH32CS_SNAPMODULE32 doesn't return anything and Tlhelp32.TH32CS_SNAPALL returns the same as lhelp32.TH32CS_SNAPMODULE
Thanks to Daniel Widdis I have the answer.
Currently, the method EnumProcessModulesEx is not mapped into JNA so you have to make your own custom version of Psapi, which in my case looks something like this:
import com.sun.jna.Native;
import com.sun.jna.platform.win32.Psapi;
import com.sun.jna.platform.win32.WinDef.HMODULE;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.W32APIOptions;
public interface CustomPsapi extends Psapi{
Psapi INSTANCE = Native.load("psapi", Psapi.class,
W32APIOptions.DEFAULT_OPTIONS);
public void EnumProcessModulesEx(HANDLE hProcess, HMODULE[] lphModule, int cb,
IntByReference lpcbNeeded, int dwFilterFlag);
}
Then you can load your custom class and use the methods that you mapped.
public static CustomPsapi c_psapi = Native.load("psapi", CustomPsapi.class);
As for getting all the DLLs showing up correctly, you need to use the now mapped EnumProcessModulesEx method with the flag for all modules as the last argument (0x03)
so the method should look something like this:
c_psapi.EnumProcessModulesEx(process, modules, 1024, new IntByReference(1024), 0x03);
I need to use RegLoadKey function in my java code by using jna, but I'm getting the following error message:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'RegLoadKey': The specified procedure could not be found.
Blockquote
RegLoadKey syntax
LONG WINAPI RegLoadKey(
_In_ HKEY hKey,
_In_opt_ LPCTSTR lpSubKey,
_In_ LPCTSTR lpFile
);
my code:
Advapi32.java
import com.sun.jna.platform.win32.WinReg.HKEY;
import com.sun.jna.win32.StdCallLibrary;
public interface Advapi32 extends StdCallLibrary
{
long RegLoadKey(HKEY hKey, String lpSubKey,String lpFile);
}
apiTest.java
import com.sun.jna.*;
import com.sun.jna.platform.win32.WinReg.HKEY;
public class apiTest
{
public static void main (String [] args)
{
Advapi32 lib2 = (Advapi32) Native.loadLibrary("Advapi32", Advapi32.class);
HKEY key1 = new HKEY();
String filePath = "C:\\tmp\\software";
String regName = "loadedRegKey";
long test = lib2.RegLoadKey(key1, regName, filePath);
}
I think there are several problems with my code. I'm new to windows api and jna.
Did you know that an Advapi32 encapsulation is already part of JNA?
Have a look here. I just saw that your method RegLoadKey is not yet added there. So add it and submit that change to the jna guys. Afterwards you can use it like this (pseudo code):
public class RegistryRead{
private Advapi32 api = null;
public RegistryRead(){
this.api = Advapi32.INSTANCE;
}
public void read() {
long winapi = this.api.RegLoadKey(HKEY hkey, String subkey, String file);
...
}
}
If you look at the Advapi32 library mapping that comes with JNA, you'll see that the library instantiation includes some options to the load method. Among other things, these load options automatically map things like RegLoadKey to RegLoadKeyW, which is the real name of the function you're trying to link to.
It is a typical for JNA developing error. Just add before using it.
System.setProperty("jna.library.path","PATH_TO_LIBRARY_JNA");
PATH_TO_LIBRARY_JNA - absolute path to jna lib
I'm controlling some external device using my android app, and in order to control this device it provides an sdk which is a C#(.dll) files, I know how to load .dll libraries into java and how to use it, but I can't access a lot of methods inside these libraries because it takes C# native arguments like structs which is not available in Java, and I tried equivalents in Java like classes with public elements to represent a struct but it keeps give me the error: java.lang.IllegalArgumentException: Unsupported argument type
This is how I deal with the Library(using jna):
import outsource.classes.MyClass;
import com.sun.jna.Library;
import com.sun.jna.Native;
public class Test {
public interface simpleDLL extends Library {
long H264_DVR_GetLastError(int num); // accessed without any problems
boolean H264_DVR_SetDVRMessCallBack(MyClass obj, long num); // this "MyClass" is mainly a STRUCT in the C# sdk
}
static
{
System.loadLibrary("NetSdk");
}
public static void main(String args[]) {
simpleDLL INSTANCE = (simpleDLL) Native.loadLibrary(("NetSdk"),
simpleDLL.class);
System.out.println(INSTANCE.H264_DVR_GetLastError(4));
System.out.println(INSTANCE.H264_DVR_SetDVRMessCallBack(new MyClass(),
0));
}
}
And this is how I created MyClass.Class:
public class MyClass() {
public String Id = "myDevice";
public String UserName = "admin";
public int password = 1234;
}// also tried declaring the values inside a constructor but nothing changed
and this is how the struct defined inside the sdk:
typedef struct _DEVICEINFO
{
char id[64];
char user[64];
int pw;
}DEVICEINFO,*LP_DEVICEINFO;
p.s. I know there are some ways to write an android app with C# code using VisualBasic(e.g vs-android) but that won't work in my case as the app is already written and running with java and it's pretty huge with a lot of other functionalists so it can't be rewritten.
I am trying to call OpenEvent of kernel32.dll using JNA and it fails with the error
java.lang.UnsatisfiedLinkError: Error looking up function 'OpenEvent': The specified procedure could not be found.
My stub declaration looks like this
public static native Pointer OpenEvent(int access, boolean inheritHandle, String name);
Can someone help me identify the issue here?
--
After making modification based on users feedback I dont get the error now; but OpenEvent method always returns null. This is the code that demonstrates the behavior
/**
* Hello world!
*
*/
import com.sun.jna.FromNativeContext;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.PointerType;
public class App
{
static {
Native.register("kernel32");
}
public static native HANDLE OpenEventW(int access, boolean inheritHandle,
String name);
public static native HANDLE CreateEventW(Pointer securityAttributes,
boolean manualReset, boolean initialState, String name);
public static native int GetLastError();
public static void main( String[] args )
{
HANDLE i = CreateEventW(null,false,false,"Global\\testEvent");
System.out.println("After create event:"+GetLastError());
HANDLE j = OpenEventW(100000, false, "Global\\testEvent");
System.out.println("After open event:"+GetLastError());
}
public static class HANDLE extends PointerType {
public Object fromNative(Object nativeValue, FromNativeContext context) {
Object o = super.fromNative(nativeValue, context);
if (INVALID_HANDLE_VALUE.equals(o))
return INVALID_HANDLE_VALUE;
return o;
}
}
static HANDLE INVALID_HANDLE_VALUE = new HANDLE() {
{ super.setPointer(Pointer.createConstant(-1)); }
public void setPointer(Pointer p) {
throw new UnsupportedOperationException("Immutable reference");
}
};
}
No idea what JNA is or how it works, but the problem is likely that the actual exported function is NOT "OpenEvent". It is "OpenEventA" or "OpenEventW" depending on if you want toe ASCII or Unicode variant. I assume Java strings are Unicode, so you most likely want "OpenEventW".
If you're mapping directly to the OpenEventW function without using the options provided by JNA, then you need to explicitly map the Java String to the native wchar_t* type by using WString where you currently use String. Otherwise you'll be passing invalid event IDs to the native function, which would likely cause the call to fail.