I am writing a JNI key logger and the native code for that is as below.
#include "com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper.h"
#include "com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper_KeyListener.h"
#include <cstring>
#include <windows.h>
#include <iostream>
#include <stdio.h>
HINSTANCE hinst;
HHOOK hhk;
JNIEnv * thisEnv;
jclass thisClazz;
jmethodID mid;
LRESULT __declspec(dllexport)__stdcall CALLBACK KeyboardProc(int ,WPARAM , LPARAM );
BOOL WINAPI DllMain( __in HINSTANCE hinstDLL,
__in DWORD fdwReason,
__in LPVOID lpvReserved
) {
hinst = hinstDLL;
return TRUE;
}
LRESULT __declspec(dllexport)__stdcall CALLBACK KeyboardProc(int nCode,WPARAM wParam, LPARAM lParam){
thisEnv->CallStaticVoidMethod(thisClazz, mid, nCode);
LRESULT RetVal = CallNextHookEx( hhk, nCode, wParam, lParam );
return RetVal;
}
JNIEXPORT void JNICALL Java_com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper_unhookKeyListener
(JNIEnv * env, jclass clazz){
thisEnv = NULL;
thisClazz = NULL;
mid = NULL;
UnhookWindowsHookEx(hhk);
}
JNIEXPORT void JNICALL Java_com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper_hookKeyListener
(JNIEnv * env, jclass clazz){
thisEnv = env;
thisClazz = clazz;
mid = env->GetStaticMethodID( clazz, "onKeyPress", "(I)V");
hhk = SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,hinst,0);
}
Intent of the program is to notify java program(a static method onKeyPress) from the native code where I'll log keys and notify user. I'll first call hookKeyListener(native version: Java_com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper_hookKeyListener) where i'll register windows hook and store all parameters(env, jclass and mid). In the callback(KeyboardProc) I'll notify java program using previously stored env , jClass , mid. and finally unregister hook.
Now the problem what I am facing is, java method(static) is not getting called from native code.Below are few of my observations.
1>If call java method in Java_com_webspur_rmtadmin_java_app_keylogger_KeyloggerHelper_hookKeyListener, it is successfully calling java method(This means I can call static methods)
2>I wrote some test code in KeyboardProc(CallBack) like creating file and logging keys into it, then it is working well(This means Hook is registered correctly and also getting called when key is pressed)
But I am not able to call java code from CallBack(KeyboardProc).I have a doubt on stored variables(env, jClass, mid)-can I store these parameters to global variables?If not, Then how can I call java program from native code?Any help is appreciated.
Below is the java code I want to call from native code.
package com.webspur.rmtadmin.java.app.keylogger;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.HashMap;
public class KeyloggerHelper {
static{
System.loadLibrary("KeyHookLibrary");
}
public interface KeyListener{
public void onKeyPress(int keyCode);
}
private static boolean started = false;
private static KeyListener keyListener = null;
private static BufferedWriter writer = null;
private static HashMap<Integer, String> specialKeys = new HashMap<Integer, String>();
public static void init(){
try{
File logFile = new File("./resources/leylog.txt");
if(!logFile.exists())
logFile.createNewFile();
writer = new BufferedWriter(new FileWriter(logFile, true));
}catch (Exception e) {
e.printStackTrace();
}
}
public static void start(KeyListener listener){
keyListener = listener;
if(!started)
startInternal();
}
public static void stop(){
keyListener = null;
if(started)
stopInternal();
}
private static void stopInternal() {
try{
unhookKeyListener();
started = false;
writer.close();
}catch (Exception e) {
e.printStackTrace();
}
}
private static native void unhookKeyListener();
private static void startInternal(){
hookKeyListener();
started = true;
}
private static native void hookKeyListener();
public static void onKeyPress(int keyCode){
try{
if(keyListener!=null)
keyListener.onKeyPress(keyCode);
writer.append((char)keyCode);
}catch (Exception e) {
//ignore..
}
}
}