5 messages in net.java.dev.jna.usersRe: [jna-users] Intercepting Win32 Me...
FromSent OnAttachments
sam westDec 2, 2008 9:42 pm 
Daniel KaufmannDec 3, 2008 3:39 am 
Timothy WallDec 3, 2008 3:43 am 
sam westDec 4, 2008 3:00 pm 
Timothy WallDec 4, 2008 4:33 pm 
Actions with this message:
Paste this link in email or IM:
Paste this link in email or IM:
Atom feed for this thread
Paste this URL into your reader:
Subject:Re: [jna-users] Intercepting Win32 MessagesActions...
From:Timothy Wall (twal@dev.java.net)
Date:Dec 3, 2008 3:43:37 am
List:net.java.dev.jna.users

On Dec 3, 2008, at 12:43 AM, sam west wrote:

G'Day,

I'm trying to intercept WM_POWERBROADCAST and WTS_SESSION_CHANGE mesages from a Java app. I'd prefer to do this using a hook, but I'd settle for subclassing WndProc() and processing messages if necessary.

I've had some success with the latter, using the code snippet below (my WTSAPI dll JNA interface omitted for brevity). And this approach seems to work fine until you lock/unlock or sleep/ restart a few times, after which the window hangs. Spy++ shows a whole bunch of WM_PAINT messages getting sent to my JFrame that apparently don't get processed. Any idea what I'm doing wrong?

You should probably dig around the JDK sources to see how windows messages are handled for the underlying AWT windows. I've seen numerous references to odd handling issues in various bug reports, but never actually seen the internal JVM message handling loop(s).

I *have* gotten this code to receive messages when I change it to a system-wide global hook, but it tends to either crash the app, or, amusingly, causes a blue screen of death (presumably because hooking EVERY message in the system is a Really Bad Idea.

You're probably right.

Any thoughts why my local hook isn't working here?

final User32 lib = User32.INSTANCE; HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null); msgHook = new User32.CallWndRetProc() { public LRESULT callback(int nCode, WPARAM wParam, CWPRETSTRUCT info) {

if (nCode >= 0) { System.out.println("Got Message callback!"); } return lib.CallNextHookEx(hhk, nCode, wParam, info.getPointer()); } };

JFrame f = new JFrame(); f.pack(); f.setSize(100,100); f.setVisible(true);

swingThreadID = getSwingThreadID(); HINSTANCE threadLocalhMod = null; mhk = lib.SetWindowsHookEx(User32.WH_CALLWNDPROCRET, msgHook, threadLocalhMod, swingThreadID);

A few questions on hooking:

1. I suspect I'm using the wrong ThreadID (i've tried obtaining an ID from the Main thread and from the Swing worker thread, but neither work). Which Java thread receives the actual win32 Messages and how do I get its Thread ID?

2. The KeyHook example code starts a dummy messaging loop at the end to ensure it receives low level keyboard messages. If I start a JFrame in the same process, is this still necessary?

I never investigated why the additional message loop was required, probably something to do with messaging functionality being associated with a given thread. The loop never gets any messages, nor does it terminate, but if you take it out, the hook never gets called.

3. On SetWindowsHookEX and thread-local hooks, MSDN says "hMod [in]: Handle to the DLL containing the hook procedure pointed to by the lpfn parameter. The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process. ". Is setting the third parameter in my call to a java null sufficient to achieve this?

Double check the docs. The low level hooks work because they don't require a DLL handle. Someone posted some comments regarding the whole DLL handle thing a while back, which, while not providing a full answer, at least provided some more insight into the requirement. If you could find out what windows does with the DLL handle, you could discover whether or not being associated with the JVM's dlls would be sufficient or if you're SOL.

Thanks in advance, Sam.

Oh yeah, and JNA rocks.

Thanks. Although it does lead to some rocky coding :)