From 4b8b72c66e4988fae09767a426e9c72bfbf98296 Mon Sep 17 00:00:00 2001 From: Andre Date: Mon, 24 Sep 2018 02:55:56 +0100 Subject: [PATCH] Implemented canvas re-grabbing, which allows you to send events when the canvas gets rebuild. --- KInput/KInput.cpp | 42 ++++++++++++++++++++++++++++++------ KInput/KInput.hpp | 11 ++++++++++ KInput/main.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++++ KInput/makefile | 8 +++---- 4 files changed, 105 insertions(+), 10 deletions(-) diff --git a/KInput/KInput.cpp b/KInput/KInput.cpp index 1b68d1c..a0e3faf 100644 --- a/KInput/KInput.cpp +++ b/KInput/KInput.cpp @@ -16,7 +16,6 @@ */ #include "KInput.hpp" -#include #include #include #include @@ -78,7 +77,6 @@ void KInput::GrabCanvas() { HMODULE JVMDLL = GetModuleHandle("jvm.dll"); if (!JVMDLL) return; - typedef int (*ptr_GCJavaVMs)(JavaVM **vmBuf, jsize bufLen, jsize * nVMs); ptr_GCJavaVMs GetJVMs = (ptr_GCJavaVMs)GetProcAddress(JVMDLL, "JNI_GetCreatedJavaVMs"); jobject TempCanvas = nullptr; do { @@ -90,16 +88,15 @@ void KInput::GrabCanvas() { if (!AWTDLL) break; - typedef jobject (JNICALL *ptr_GetComponent)(JNIEnv* env, void* platformInfo); - ptr_GetComponent GetComponent = (ptr_GetComponent)GetProcAddress(AWTDLL, "_DSGetComponent@8"); - if (!(this->AttachThread() && GetComponent)) + this->GetComponent = (ptr_GetComponent)GetProcAddress(AWTDLL, "_DSGetComponent@8"); + if (!(this->AttachThread() && this->GetComponent)) break; HWND CanvasHWND = GetCanvasHWND(); if (!CanvasHWND) break; - TempCanvas = GetComponent(this->Thread, (void*)CanvasHWND); + TempCanvas = this->GetComponent(this->Thread, (void*)CanvasHWND); if (!TempCanvas) break; @@ -127,6 +124,36 @@ void KInput::GrabCanvas() { } } +void KInput::NotifyCanvasUpdate(HWND CanvasHWND) { + this->CanvasUpdate = CanvasHWND; +} + +void KInput::UpdateCanvas() +{ + if (!CanvasUpdate) + return; + jobject TempCanvas = nullptr; + do + { + if (!(this->AttachThread() && this->GetComponent)) + break; + TempCanvas = this->GetComponent(this->Thread, (void*) CanvasUpdate); + if (!TempCanvas) + break; + if (this->Canvas) + { + this->Thread->DeleteGlobalRef(this->Canvas); + this->Canvas = nullptr; + } + this->Canvas = this->Thread->NewGlobalRef(TempCanvas); + } while (false); + if (TempCanvas) { + this->Thread->DeleteLocalRef(TempCanvas); + TempCanvas = nullptr; + } + CanvasUpdate = nullptr; +} + KInput::KInput() { std::cout << "Starting a new KInput instance! o/" << std::endl; @@ -135,6 +162,7 @@ KInput::KInput() this->Thread = nullptr; this->Client = nullptr; this->Canvas = nullptr; + this->GetComponent = nullptr; this->Canvas_Class = nullptr; this->Canvas_DispatchEvent = nullptr; this->FocusEvent_Class = nullptr; @@ -145,6 +173,7 @@ KInput::KInput() this->MouseEvent_Init = nullptr; this->MouseWheelEvent_Class = nullptr; this->MouseWheelEvent_Init = nullptr; + this->CanvasUpdate = nullptr; this->GrabCanvas(); } @@ -176,6 +205,7 @@ bool KInput::DispatchEvent(jobject Event) this->Canvas_DispatchEvent = this->Thread->GetMethodID(this->Canvas_Class, "dispatchEvent", "(Ljava/awt/AWTEvent;)V"); if (this->Canvas_DispatchEvent) { + UpdateCanvas(); this->Thread->CallVoidMethod(this->Canvas, this->Canvas_DispatchEvent, Event); return true; } diff --git a/KInput/KInput.hpp b/KInput/KInput.hpp index c2192af..bd7773f 100644 --- a/KInput/KInput.hpp +++ b/KInput/KInput.hpp @@ -1,8 +1,13 @@ #ifndef KINPUT_HPP_INCLUDED #define KINPUT_HPP_INCLUDED +#include #include #include +#include + +typedef int (*ptr_GCJavaVMs)(JavaVM **vmBuf, jsize bufLen, jsize * nVMs); +typedef jobject (JNICALL *ptr_GetComponent)(JNIEnv* env, void* platformInfo); class KInput { @@ -13,6 +18,8 @@ class KInput jobject Client; jobject Canvas; + ptr_GetComponent GetComponent; + jclass Canvas_Class; jmethodID Canvas_DispatchEvent; @@ -28,8 +35,11 @@ class KInput jclass MouseWheelEvent_Class; jmethodID MouseWheelEvent_Init; + HWND CanvasUpdate; + bool AttachThread(); void GrabCanvas(); + void UpdateCanvas(); public: KInput(); @@ -42,6 +52,7 @@ class KInput bool MouseWheelEvent(std::int32_t ID, std::int64_t When, std::int32_t Modifiers, std::int32_t X, std::int32_t Y, std::int32_t ClickCount, bool PopupTrigger, std::int32_t ScrollType, std::int32_t ScrollAmount, std::int32_t WheelRotation); + void NotifyCanvasUpdate(HWND CanvasHWND); ~KInput(); }; diff --git a/KInput/main.cpp b/KInput/main.cpp index 5e373a2..74af55e 100644 --- a/KInput/main.cpp +++ b/KInput/main.cpp @@ -17,10 +17,62 @@ #include #include +#include #include "KInput.hpp" KInput* Input = nullptr; +typedef HWND(__stdcall *ptr_CreateWindowExW)(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam); + +ptr_CreateWindowExW CreateWindowExW_Original = nullptr; +LPVOID *CreateWindowExW_Address = nullptr; + +HWND __stdcall CreateWindowExW_Hook(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) +{ + HWND Temp = CreateWindowExW_Original(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + std::wstring WStr(lpClassName); + std::string ClassNameString(WStr.begin(), WStr.end()); + if (ClassNameString == "SunAwtCanvas" && Input) { + Input->NotifyCanvasUpdate(Temp); + } + return Temp; +} + +bool HookCreateWindow() { + HMODULE kernel = GetModuleHandle("user32.dll"); + CreateWindowExW_Address = (LPVOID *) GetProcAddress(kernel, "CreateWindowExW"); + if (!CreateWindowExW_Address) { + return false; + } + + // Initialize MinHook. + if (MH_Initialize() != MH_OK) + { + return false; + } + + // Create a hook for MessageBoxW, in disabled state. + if (MH_CreateHook(CreateWindowExW_Address, ((LPVOID *) &CreateWindowExW_Hook), + ((LPVOID *) &CreateWindowExW_Original)) != MH_OK) + { + return false; + } + + // Enable the hook for CreateWindowExW. + return MH_EnableHook(CreateWindowExW_Address) == MH_OK; +} + +bool UnHookCreateWindow() { + // Disable the hook. + if (MH_DisableHook(CreateWindowExW_Address) != MH_OK) + { + return false; + } + + // Uninitialize MinHook. + return MH_Uninitialize() == MH_OK; +} + extern "C" __declspec(dllexport) bool KInput_FocusEvent(void* Data) @@ -109,6 +161,7 @@ bool __stdcall DllMain(HMODULE DLL, DWORD fdwReason, LPVOID lpvReserved) case DLL_PROCESS_ATTACH: { DisableThreadLibraryCalls(DLL); + HookCreateWindow(); Input = new KInput(); } break; @@ -116,6 +169,7 @@ bool __stdcall DllMain(HMODULE DLL, DWORD fdwReason, LPVOID lpvReserved) { if (Input) { + UnHookCreateWindow(); delete Input; Input = nullptr; } diff --git a/KInput/makefile b/KInput/makefile index 92fdd33..b4c389b 100644 --- a/KInput/makefile +++ b/KInput/makefile @@ -11,12 +11,12 @@ AR = ar.exe LD = g++.exe WINDRES = windres.exe -INC = +INC = -I"minhook\include" CFLAGS = RESINC = -LIBDIR = -LIB = -LDFLAGS = +LIBDIR = -L"minhook\lib" +LIB = -l"MinHook" +LDFLAGS = INC_RELEASE = $(INC) -I"C:\Program Files (x86)\Java\jdk1.8.0_171\include" -I"C:\Program Files (x86)\Java\jdk1.8.0_171\include\win32" CFLAGS_RELEASE = $(CFLAGS) -Os -Wall -std=c++1z -m32 -DBUILD_DLL