JNA - How to convert LPARAM pointer to a Class object? - jna

I am novice jn JNA and am getting a bit confused with mixture of java and C++. In the WNDPROC callback method, the LPARAM is sent to the callback has to be used to retrive the DEV_BROADCAST_DEVICEINTERFACE class object. This is my code:
public static User32.WNDPROC WndProc = new User32.WNDPROC() {
#Override
public LRESULT callback(HWND hWnd, int uMSG, WPARAM uParam, LPARAM lParam)
{
User32.DEV_BROADCAST_DEVICEINTERFACE b = (User32.DEV_BROADCAST_DEVICEINTERFACE) lParam;
if(b != null){
System.out.println("Device Name: " + b.dbcc_name.toString ()); System.out.println("New Volume GUID:" + b.dbcc_classguid.toString());
}
}
The compiler begins to complain when I try to convert the lParam to class object, for obvious reasons. How do I achieve this?

You don't have to use LPARAM; if you're being passed a structure (or other specific type) by the native code, you can define the appropriate method signature and JNA will do the right thing, converting the native value into something useful in Java.
public LRESULT callback(HWND hWnd, int uMSG, WPARAM uParam, User32.DEV_BROADCAST_DEVICEINTERFACE lParam);

Related

From COM Pointer to Record / How to do a Delphi version of (dotNet's) Marshal.PtrToStructure

Looking for help on how to cast / convert a pointer to a record - similar to what dotNet's Marshal.PtrToStructure does - but using Delphi.
Details: using an ActiveX / COM (original code in C++). Implementing an interface allowing to catch events raised by the ActveX control.
One of the implemented interface's methods signature looks like:
procedure TIUIX_ObjImplEvent.OnEvent(const pSender: IUIX_Obj; const pEvent: IUIX_Event);
IUIX_Event is an interface (derives from IDispatch). Has a property Param1 of type Param_T.
Param1 holds a pointer to a record type.
Now, I have C# code I would like to convert to Delphi:
public void OnEvent(IUIX_Obj pSender, IUIX_Event pEvent)
{
//some more code before, and then this part:
IntPtr outPtr = new IntPtr(pEvent.Param1);
UIX_NotifyInfo ni = (UIX_NotifyInfo)System.Runtime.InteropServices.Marshal.PtrToStructure(outPtr, typeof(UIX_NotifyInfo));
}
UIX_NotifyInfo is a record (/struct).
Qustion: how to go from pEvent.Param1 to ni? Using Delphi:
procedure TIUIX_ObjImplEvent.OnEvent(const pSender: IUIX_Obj; const pEvent: IUIX_Event);
var
ni : UIX_NotifyInfo;
begin
pEvent.Handled := false;
if (pEvent.Code = e_Notify) then
begin
//how to go from pEvent.Param1 to ni like in C#'s PtrToStructure?
if (ni.nCode = UIX_Notify_BeforeShowPopup) then
begin
pEvent.Handled := true;
end;
end;
end;
My guess is using the Move procedure, but whatever I try it either does not compile or crashes :)
Move(??, ni, SizeOf(UIX_NotifyInfo));
I'm adding this after David answered...
Here's an extension to the above question (looking for how to go about Marshal.GetObjectForIUnknown).
I have this C# code:
public void OnEventMonitor(IUIX_Obj pTarget, IUIX_Event pEvent)
{
IntPtr outPtr;
pTarget.QueryImpl(typeof(IUIX_Dialog).GUID, null, out outPtr);
IUIX_Dialog dlg = (IUIX_Dialog)System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(outPtr);
}
Having:
IUIX_Event = interface(IDispatch)
IUIX_Obj = interface(IDispatch)
IUIX_Dialog = interface(IUIX_ObjImpl) (IDispatch)
My Delphi code (dlg : IUIX_Dialog, pImpl : Pointer):
pTarget.QueryImpl(GetTypeData(TypeInfo(IUIX_Dialog)).Guid, nil, #pImpl);
Move(pImpl, dlg, SizeOf(IUIX_Dialog));
The above does work.
Any better approach or that's correct way?
It's simple in unmanaged code, it's just an assignment.
var
Rec: TMyRec;
Ptr: Pointer;
....
Rec := TMyRec(Ptr^);

Cast LPARAM to a Java-Pojo

I have a c application and a java application. I communicate with jna to get results from the c program.
I Have a jna-Callback function:
public LRESULT callback(HWND hWnd, int uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WinUserConstants.WM_GRAB_BASE:
System.out.println("WM_GRAB_BASE");
return new LRESULT(1);
case WinUserConstants.WM_GRAB_TRANSFER_FINISHED:
System.out.println("WM_GRAB_TRANSFER_FINISHED");
return new LRESULT(1);
case WinUserConstants.WM_GRAB_IMAGE_SAVED:
System.out.println("WM_GRAB_IMAGE_SAVED");
return new LRESULT(1);
default:
return User32.INSTANCE.DefWindowProc(hWnd, uMsg, wParam, lParam);
}
I need the WPARAM variable. I cant change the WPARAM to String. If i do that my window shows no controls.
WPARAM is defined as "HGLOBAL on memory containing (wchar_t *)filename". I need that filename and cant access the c code.
You can use WPARAM.toPointer().getWideString(0) to extract the string.
toPointer() effectively "casts" the WPARAM to a pointer value, from which you can then extract the (wide) native C string.

How to call function "Move" in C++ Builder 6

Delphi syntax:
procedure Move(const Source; var Dest; Count: Integer);
C++ syntax:
extern PACKAGE void __fastcall Move(const void *Source, void *Dest, int Count);
I have used Function Move in Delphi long time ago,
recently I want to call it in C++ Builder 6,
I wrote it as the same as I did in Delphi,
the error appearance --> "Expression Syntax".
Dose anyone know how to call it?
or there is other function works similar to it?
BYTE src[] = "Source Data";
BYTE dst[11];
Move(src, dst, sizeof(dst));
It is better to use memmove in C++:
memmove(dst, src, sizeof(dst));

JNA call PostMessage ~ passing String "Environment"

http://www.codeguru.com/cpp/w-p/win32/tutorials/article.php/c10849/Setting-a-System-Environment-Variable.htm
SendMessage( HWND_BROADCAST , WM_SETTINGCHANGE , 0 , (LPARAM) "Environment" );
JNA and windows xp: call to notify that Environment has been changed
see link: twall.github.com/jna/3.5.1/javadoc/
see link: twall.github.com/jna/3.5.1/javadoc/com/sun/jna/platform/win32/User32.html
PostMessage(WinDef.HWND hWnd, int msg, WinDef.WPARAM wParam, WinDef.LPARAM lParam)
This function places a message in the message queue associated with the thread that created the specified window and then returns without waiting for the thread to process the message.
import com.sun.jna.*;
import com.sun.jna.win32.*;
import com.sun.jna.platform.win32.*;
import com.sun.jna.ptr.*;
public class MainJNA {
public static void main (String [] args){
String myString = "Environment";
Pointer myPointer = new Memory(myString.length()+1);
myPointer.setString(0,myString);
Pointer HWND_BROADCAST = new Pointer(0xFFFF);
int msg = 0x001A; // WM_SETTINGCHANGE = WM_WININICHANGE = 0x001A
WinDef.HWND hWnd = new WinDef.HWND( HWND_BROADCAST );
WinDef.WPARAM wParam = new WinDef.WPARAM(0);
WinDef.LPARAM lParam = new WinDef.LPARAM( myPointer.getLong(0) );
// Exception in thread "main" java.lang.IllegalArgumentException:
// Argument value 0x6d6e6f7269766e45 exceeds native capacity (4 bytes)
// mask=0xffffffff00000000
User32 user32 = (User32) Native.loadLibrary(
"user32" , User32.class , W32APIOptions.DEFAULT_OPTIONS );
user32.PostMessage( hWnd , msg , wParam , lParam );
}
} // end of class MainJNA
How to pass String parameter "Environment" to user32.PostMessage ???
And not to get Exception in thread "main" java.lang.IllegalArgumentException: Argument value 0x6d6e6f7269766e45 exceeds native capacity (4 bytes) mask=0xffffffff00000000
Thx
You're getting that error because you're trying to write a 64-bit value (myPointer.getLong(0)) into a 32-bit container (LPARAM).
You already have the pointer value you need for the LPARAM in myPointer; the recommended way to "cast" the pointer to LPARAM is to simply declare a version of PostMessage which takes an appropriately-typed fourth argument, e.g.
void PostMessage(WinDef.HWND hWnd, int msg, WinDef.WPARAM wParam, Pointer lParam);
void PostMessage(WinDef.HWND hWnd, int msg, WinDef.WPARAM wParam, String lParam);
This is preferable and more type-safe than manually converting between disparate types (i.e. from String or Pointer to an integer type).

Pinvoke stack imbalance detected

I have the following function:
[DllImport("user32.dll", CharSet=CharSet.Auto)]
static extern int SendMessage(IntPtr hWnd, int wMsg, int wParam, SPoint lParam);
It keeps complaining about Pinvoke stack imbalance when the following code executes:
SendMessage(EventRichTextBox.Handle, EM_GETSCROLLPOS, 0, OldScrollPoint);
What can cause that issue?
this is my SPoint
private struct SPoint
{
public Int32 x;
public Int32 y;
}
and
SPoint OldScrollPoint = default(SPoint);
Can't say for sure, but one obvious possibility is that you are on a 64 bit machine and int is the wrong type for wParam. It needs to be a 64 bit value in a 64 bit process.
We also have no idea how you have declared SPoint. You are meant to pass a pointer to a POINT struct. It doesn't look as though you have done that.
The correct signature is:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(
IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
Your edit clarifies that SPoint is a struct. This then is clearly wrong. You could simply pass the SPoint as an out parameter. That would be the simplest solution.
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(
IntPtr hWnd, int Msg, IntPtr wParam, out SPoint lParam);
If you wanted a more general SendMessage signature then you should use IntPtr as I stated above and use Marshal.StructureToPtr.
The wParam argument should be IntPtr. But that's not what triggers the MDA, lying about the argument type is fine but you do have to do it correctly. Structures are passed by reference in the Windows api, declare the lParam argument as ref SPoint. Or out if the structure is returned, the case for EM_GETSCROLLPOS.

Resources