0

The following java program calls a native method in C that should print a message you pressed a key ! if the user presses a key. But i can't see the message as the i press the key.I also check if the function SetWindowsHookEx returns null but no,it doesn't return null.

Java Code :

package keylogger;

public class TestKeys {

private native void setWinHook();

public static void main(String args[]) {
    TestKeys o = new TestKeys();
    try {
        o.setWinHook();
        Thread.sleep(10000);
    } catch(Exception exc) {
        exc.printStackTrace();
    }
}

static {
    System.loadLibrary("MyHook");
}

} C Code :

#include <stdio.h>
#include <windows.h>
#include <w32api.h>
#include "keylogger_TestKeys.h"
static HHOOK handleKeyboardHook = NULL;
HINSTANCE hInst = NULL;

static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
  printf("You pressed a key !\n");
  return CallNextHookEx(handleKeyboardHook, nCode, wParam, lParam);
}

void Java_keylogger_TestKeys_setWinHook
 (JNIEnv *env, jobject obj) {
hInst = GetModuleHandle(NULL); // include or exclude,i don't see the result
handleKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,NULL, 0);
if(handleKeyboardHook==NULL) {
    printf("Is Null");
} else {
    printf("Is not Null");
}
printf("Inside fucntion setWinHook !");
}

/*int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
 printf("Hello World !");
 handleKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInstance, 0);
 if(handleKeyboardHook==NULL) {
  printf("Is Null");
 } else {
    printf("Is not Null");
   }
 MSG msg;
 while(GetMessage(&msg, NULL, 0, 0))
 {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
 }
 return msg.wParam;
}*/

The only output that I see is Is not NullInside fucntion setWinHook !

Where is the problem ?

What should i do so that this program returns me the message when i press the key. The only output that I see is : Inside function setWinHook !

Note :

If the above program runs on someone's machine,please mention that.

Output Pic :

enter image description here

I don't see any message on key tapping.Program just exits after 10 seconds without displaying a message.

Community
  • 1
  • 1
Suhail Gupta
  • 22,386
  • 64
  • 200
  • 328
  • Try `fflush(stdout);` after the `printf().` – user207421 May 24 '12 at 07:46
  • also check this link [http://stackoverflow.com/questions/10750037/displaying-a-message-when-the-user-taps-a-key](http://stackoverflow.com/questions/10750037/displaying-a-message-when-the-user-taps-a-key) the only difference being the absence of `WinMain` – Suhail Gupta May 29 '12 at 07:22
  • 1
    See http://stackoverflow.com/questions/3078646/jna-keyboard-hook-in-windows. It will solve your keyboard hook problem, although it won't solve your "why don't I get native console output when running a Java program" problem. – technomage May 29 '12 at 13:46
  • BTW, you *do* need your own GetMessage/PeekMessage loop in order for the keyboard hook to get run (see the example I gave above). – technomage May 29 '12 at 13:47
  • @technomage absolutely.. jna is the way to go in this case! i think you should post it as an answer ... – kritzikratzi May 30 '12 at 17:08

5 Answers5

2

You cannot simply declare a local HINSTANCE variable out of the blue and pass that to the function. A HINSTANCE is a handle to your application instance, in other words a pointer that must point at a valid location. You need to use the HINSTANCE that is your own application.

My Windows API is a bit rusty, but I believe you can do this through GetModuleHandle(). So:

void Java_keylogger_TestKeys_setWinHook
     (JNIEnv *env, jobject obj) {
   HINSTANCE hInst;
   hInst = GetModuleHandle(null);
   handleKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInst, 0);
   printf("Inside function setWinHook !");
 }

It is also quite possible that your Java goo has a HINSTANCE hidden in an object somewhere.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • and can you explain _"It is also quite possible that your Java goo has a HINSTANCE hidden in an object somewhere."_ – Suhail Gupta May 24 '12 at 08:17
  • 2
    @SuhailGupta Do you know what a HINSTANCE does? It is a very fundamental handle used in all Windows API programs. If you don't know what it does, you should not attempt advanced mechanisms like keyboard hooks. I would strongly recommend the book "Programming Windows" by Charles Petzold, very good book, informally known as the Windows API bible. – Lundin May 24 '12 at 08:29
  • though i don't know about window handles,i know that window calls the method pointed to by `SetWindowsHookEx`. In this case `LowLevelKeyboardProc`. I am surely going to learn about windows API,but i wanted to run this program ! – Suhail Gupta May 24 '12 at 08:39
  • 1
    @SuhailGupta Well it does not work, since you haven't given the hook procedure a valid handle (HINSTANCE) to your application. You need to get this from somewhere. Perhaps someone else reading this, who is less rusty on the Windows API, can point out the easiest way to obtain HINSTACE, if GetModuleHandle() doesn't work? (A way that works for certain is to call SetWindowsHookEx from WM_CREATE, then you get HINSTANCE passed to you in a struct through LPARAM.) – Lundin May 24 '12 at 08:47
  • Btw you also need to call UnhookWindowsHookEx() from somewhere to clean up when the program is done. – Lundin May 24 '12 at 08:49
  • I had taken a hint from [this line/project](http://code.google.com/p/jnativehook/source/browse/trunk/src/native/windows/NativeThread.c#370) In this code variable `hInst` is declared `NULL` but of type `extern`. This variable is being used only in [this](http://code.google.com/p/jnativehook/source/browse/trunk/src/native/windows/NativeHelpers.c) `C` file [@ this line](http://code.google.com/p/jnativehook/source/browse/trunk/src/native/windows/NativeHelpers.c#106) from [these](http://code.google.com/p/jnativehook/source/browse/#svn%2Ftrunk%2Fsrc%2Fnative%2Fwindows) files – Suhail Gupta May 24 '12 at 08:53
  • @SuhailGupta "I am surely going to learn about windows API,but i wanted to run this program!" The first is required for the second to happen. You have this back to front. – user207421 May 25 '12 at 01:22
0

Check out Java Global(low level) Keyboard/Mouse Hook

I tried to write one myself, but there seems to be too many unknown details for me (JNI, HOOKS, threading problems, etc.)

xiaofeng.li
  • 8,237
  • 2
  • 23
  • 30
0

There is for sure a better way to implement this. Here DllMain is called multiple times once a thread has been created,that doesn't seem right to me.I am not sure if this is legal ! The C Code starts a new thread to implement the keycatcher.

C Code :

#include <stdio.h>
#include <windows.h>
#include <w32api.h>
#include "keylogger_TestKeys.h"

static HHOOK handleKeyboardHook = NULL;
HINSTANCE hInst = NULL;
static DWORD hookThreadId = 0;
static HANDLE hookThreadHandle = NULL;
BOOL WINAPI installHook(HINSTANCE hinstDLL, DWORD fwdReason, LPVOID lpvReserved);
static int i = 0;

static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {

  printf("You pressed the key !");
  return CallNextHookEx(handleKeyboardHook, nCode, wParam, lParam);
}


BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
 if(hookThreadHandle==NULL) {
    printf("hookThreadHandle is NULL\n");
    LPTHREAD_START_ROUTINE lpStartAddress = &installHook;
    hookThreadHandle = CreateThread(NULL, 0, lpStartAddress, NULL, 0, &hookThreadId);
 }
}

BOOL WINAPI installHook(HINSTANCE hinstDLL, DWORD fwdReason, LPVOID lpvReserved) {
// printf("From installHook : %u",fwdReason);
printf("count : %d\n",i++);
handleKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hinstDLL, 0);
MSG msg;

while(GetMessage(&msg, NULL, 0, 0))
{
  TranslateMessage(&msg);
  DispatchMessage(&msg);
}
return msg.wParam;
}

void Java_keylogger_TestKeys_unregisterWinHook
 (JNIEnv *env, jobject obj) {
 // should have stopped the thread before unhooking
 if(handleKeyboardHook != NULL) {
    UnhookWindowsHookEx(handleKeyboardHook);
 }
}

void Java_keylogger_TestKeys_stopNativeThread // stop the native thread
  (JNIEnv *env, jobject obj) {
    PostThreadMessage(hookThreadId, WM_QUIT, (WPARAM) NULL, (LPARAM) NULL);
    WaitForSingleObject(hookThreadHandle, 5000);
}

Java Code :

package keylogger;

public class TestKeys {
private static int i = 0;
private native void setWinHook();
private native void unregisterWinHook();
private native void createWinThread();
private native void stopNativeThread();

public static void main(String args[]) {
    TestKeys o = new TestKeys();
    try {
        Thread.sleep(5000);
    }catch(Exception exc) {
        exc.printStackTrace();
    }
   o.stopNativeThread();
   o.unregisterWinHook();
   System.out.println("Native thread stopped and Hook unregistered !");

   try {
        Thread.sleep(3000); // Now you won't see the message : you pressed the key 
    }catch(Exception exc) {
        exc.printStackTrace();
    }
}

static {
    System.loadLibrary("MyHook");
}
}

I start the java program and DLLMain is called.

Suhail Gupta
  • 22,386
  • 64
  • 200
  • 328
  • Well, you should not use DllMain this way, but if your answers works, I guess that what your missing in your code is the message loop `while(GetMessage(&msg, NULL, 0, 0)) ...`, so perhaps you should use one in the code you wrote in the question. – paercebal May 30 '12 at 08:42
  • @paercebal Is there a better way to achieve this ? If there is please mention that in a separate answer. – Suhail Gupta May 30 '12 at 09:01
0

The HHOOK variable needs to be declared inside a shared data segment. Check how it is done here - http://www.codeproject.com/Articles/5002/Mousey-Roll-Over-and-Park

Superman
  • 3,027
  • 1
  • 15
  • 10
0

You need a GetMessage/PeekMessage loop in order for your keyboard hook to receive any events. For a Java implementation of a keyboard hook on windows, see JNA Keyboard Hook in Windows, or the contributed package that performs the same function in the JNA project (https://github.com/twall/jna/tree/master/contrib/w32keyhook).

Community
  • 1
  • 1
technomage
  • 9,861
  • 2
  • 26
  • 40