diff --git a/Help/How To.txt b/Help/How To.txt
index 5ffee11..148dcb3 100644
Binary files a/Help/How To.txt and b/Help/How To.txt differ
diff --git a/Help/Readme.txt b/Help/Readme.txt
index be9ca6e..d246568 100644
--- a/Help/Readme.txt
+++ b/Help/Readme.txt
@@ -32,18 +32,112 @@ R: SRLx32.dll is corrupted, maybe...
-I Have Injected the SRLx32.dll in my game, but the Char reloads shows wrong char...
R: Maybe you need modify the CreateFont function, break the CreateFont Calls and see the right place to change the font encoding
-N: puting a "mov byte ptr [eax+0x17], 0x00" before the CreateFontCall where EAX = the push pointer to the CreateFontIndirect,
-N: and 0x00 the Charset, read more here: https://msdn.microsoft.com/en-us/library/cc194829.aspx
+N: Try enalbed the CreateFont Hook and set the Charset to 0x00 in the SRL.ini
-About the SRL.ini
I will explain only what looks needed, run the game with "-help" to se the others value...
At StringsReloader
-"InEncoding" The Input Encoding; you can use 932/Unicode/utf8/ISO-8859-1 or any shit, google your encoding name...
-"OutEncoding" The same; but used to return a matched string...
+-"Encoding" Set the InEncoding and OutEncoding the same encoding.
-"Wide" True or False; Is the setting to modify the read/write method to Encoding with 16-bits
-"AntiCrash" True or False; Is the setting to games who crash on close, this can fix some cases terminating the process on you request to close it.
+-"FreeOnExit" A alternative to the AntiCrash
-"MatchIgnore" Txt1,Txt2,Txt3; Is a setting to append at the default Match ignore list, every string in the list is ignored by the string match.
-"TrimChars" (,),*; Is a setting to append strings to trim from end and begin of every line, this don't affect the return string.
+-"Delay" Log the Delay to reload very string
+-"Dump" Dump the Strings.srl including the translation
+-"DumpRetail" Dump the Strings.srl but don't export the translation
+-"Debug" Enable the Debug Output Window
+-"LogAll" Verbose mode, log all string reloads
+-"LogInput" Log all strings that the game requested the SRL translation
+-"LogOutput" Log all strings that the SRL return to the game
+-"LogFile" Save the Log window output to the a file (SRL.log)
+-"Unsafe" When false the SRL don't initialize while the game don't try load a string that is recognized game as dialogue.
+-"Rebuild" Rebuild the Strings.srl every time that the game starts
+-"TrimRangeMismatch" Trim from the begin and end all chars from input strings that isn't in the "AcceptableRange" list
+-"AcceptableRanges" Acceptable range of chars, use the char: - to specify a range, like 0-9, A-z, you can put a single char too, just don't put the -
+-"NoTrim" Disable all trim algorithms of the SRL
+-"BreakLine" Set if the game have their own breakline flag, (the default is the 0x0A byte)
+-"ReloadedPrefix" Put a prefix in all reloaded lines
+-"ReloadedSufix" Put a sufix in all realoaded lines
+-"Multithread" Make the SRL optimized for Multithreaded games, when false the SRL create a new process to store their database, keep true
+-"WindowHook" Try hook all windows user interface strings and allow translate it
+-"Invalidate" If the WindowHook only translate when you put the cursor over the text, enable this
+-"CachePointer" Cache the reload and speed up if the game request it again
+-"NoDiagCheck" Allways think in a string as a Dialogue, Don't enable with Unsafe=false
+-"LiteralMask" Reload strings Mask literally
+-"LiveSettings" Reload the SRL.ini without restart the game (Some features require restart)
+-"DecodeInputRemap" Restore any char reload in the input string before process
+-"MultiDatabase" Create multiple databases to every .lst file, Increase memory usage but speed up the SRL
+-"NoReload" Disable the SRL
+-"WorkingDir" Set a custom directory as workspace of the SRL, keep empty to use the SRL dll directory
+-"ReloadMaskArgs" If a mask contains a string that needs be translated, keep true
+-"CustomCredits" Set a custom message during the SRL loading screen
+-"LiteMode" Disable many features of the SRL to speed up
+-"RemoveViolations" If you put a char in the .lst that is being used by the Char Reloader feature, when true, the SRL will cutoff all 'ilegal' chars
+-"AsianInput" Hint the Dialogue Detection algorithm saying if the game is a japanese game or not.
+-"CaseSensitive" The SRL database match can match with case senstive or not, just change this
+-"NotCachedOnly" Use the pointer cache to don't allow the SRL process again the same string
+-"SetOutEncoding" If the Debug Low Window (aka console) display invalid chars, set true
+-"AllowEmptyReloads" Keep in the database Reloads that don't change nothing
+
+At WordWrap
+-"Enable" Disable or Enable the SRL Auto Wordwrap engine
+-"Monospaced" When false the FontName, FontSize, Bold are required
+-"FakeBreakLine" If the engine don't have any breakline char, the fakebreakline full the line with space to automatically break the line where needed
+-"FontName" The font face name to be used in the string measure
+-"FontSize" The font size to be used in hte string measure (decimal)
+-"Bold" If true, the string will measure using bold font
+-"MaxWidth" When Monospaced is true, put the max count of characters per line, when false, the max line width in pixels
At MTL
--Self-Explanatory entries... But to enable the TLib.dll is required in the game directory, you can get it at my github.
\ No newline at end of file
+-Self-Explanatory entries... But to enable the TLib.dll is required in the game directory, contact-me
+
+At Overlay (Required the Overlay.dll in the directory)
+-"Enabled" Enable or Disable the Overlay
+-"Padding" Set a default overlay padding
+
+At Filter (Dialogue Detection algorithm)
+-"DenyList" List of all characters that never will appear in a dialogue (split with ,)
+-"QuoteList" List of all quotes that appears in the game (split with ,)
+-"IgnoreList" List of things to ignore when try detect if is a dialogue
+-"TrimList" List of characters that can appears in the begin or end of a string that needs be removed before process the dialogue
+-"Sensitivity" The dialogue sensitivity level, (can use negative values), bigger values are more 'permessive' than smaller values (5 is recommended)
+-"UseDB" If the string is present in the database is automatically accepted as dialogue
+-"ForceTrim" If you enable the "NoTrim" feature, can enable this to reenable the trim only to verify if is a dialogue
+
+At Intro
+-"MinSize" Minimal Window Width and Height to show the introduction
+-"Seconds" The seconds to show the introduction screen
+-"CheckProportion" A alternative to the MinSize, Only show the introduction when the Width is bigger than the Height
+-"CreateWindowEx" Hook the CreateWindowEx to show the Intro
+-"ShowWindow" Hook the ShowWindow to show the intro (Recommended)
+-"SetWindowPos" Hook the SetWindowPost to show the Intro
+-"MoveWindow" Hook the MoveWindow to show the Intro
+
+At Hook
+-"CreateFile" Hook the game file reading and allow he read files from the SRL worspace or a directory called "Patch"
+-"UndoChars" Undo the char reload in the MultiByteToWideChar, TextOut and ExtTextOut hooks
+-"MultibyteToWideChar" Hook the MultibyteToWideChar and reload the string
+-"SetWindowText" Hook the SetWindowText and reload the string
+-"GetGlyphOutline" Hook the "GetGlyphOutline" and reload the character
+-"TextOut" Hook the TextOut and reload the string
+-"ExtTextOut" Hook the ExtTextOut and reload the string
+-"CreateFont" Hook the CreateFontA and CreateFontW and allow modify the game font
+-"CreateFontIndirect" Hook the CreateFontIndirectA and the CreateFontIndirectW and allow modify the game font
+-"FontCharset" Modify the Font Charset
+-"FaceName" Modify all fonts facename
+
+At [Hook.Font.?] (You can create any amount of font remap, just put Hook.Font.0, Hook.Font.1, Hook.Font.2, Hook.Font.3... and etc)
+-"FromFont" The original font facename to replace (keep * to all fonts)
+-"ToFont" The modified font facename to force the game load
+-"Size" Try modify the font size (accept relative values, +10, -10... and absolute values 32, 20, 24)
+
+-How to use the Intro
+R: To the intro hook catch the game initilization it's obvious, the SRL needs initialize before the game,
+N: If the SRL have a delayed initialization try rename the SRLx32.dll to d3d9.dll, and modify the game exe to load the d3d9.dll and not the old SRLx32.dll
+
+-I have 2 identic lines that but I don't want the same translation to both
+R: Split the .LST in 2 files, the .lst format don't support duplicated lines, then put one of those lines in a new .lst file
+N: If you put ::SETDB-Sample:: in the first of the line translation, the SRL will change to the "Strings-Sample.lst" after match the current string, with this you can translate a duplicate that appears one after other
\ No newline at end of file
diff --git a/SRL/FileWorker.cs b/SRL/FileWorker.cs
index 6077cf8..ec87d27 100644
--- a/SRL/FileWorker.cs
+++ b/SRL/FileWorker.cs
@@ -131,6 +131,7 @@ private static void LoadConfig() {
ForceTrim = false;
NotCachedOnly = false;
AllowEmpty = false;
+ ImportHook = false;
HookCreateWindowEx = false;
HookShowWindow = false;
HookSetWindowPos = false;
@@ -628,6 +629,12 @@ private static void LoadConfig() {
Log("Intro Injector Proportion Validator Enabled", true);
}
+ if (HookSettings.ImportHook)
+ {
+ ImportHook = true;
+ Log("Import Table Hook Method Enabled", true);
+ }
+
if (IntroSettings.Seconds > 0)
Seconds = IntroSettings.Seconds;
diff --git a/SRL/Hook/FileHook.cs b/SRL/Hook/FileHook.cs
index b544ee5..9ab8248 100644
--- a/SRL/Hook/FileHook.cs
+++ b/SRL/Hook/FileHook.cs
@@ -1,5 +1,4 @@
using System;
-using System.IO;
using System.Runtime.InteropServices;
namespace SRL
@@ -15,12 +14,13 @@ static void InstallCreateFileHooks()
dCreateFileA = new CreateFileADelegate(CreateFile);
dCreateFileW = new CreateFileWDelegate(CreateFile);
- hCreateFileA = new FxHook("kernel32.dll", "CreateFileA", dCreateFileA);
- hCreateFileW = new FxHook("kernel32.dll", "CreateFileW", dCreateFileW);
- hGetFileAttrA = new FxHook("kernel32.dll", "GetFileAttributesA", dGetFileAttrA);
- hGetFileAttrW = new FxHook("kernel32.dll", "GetFileAttributesW", dGetFileAttrW);
- hGetFileAttrExA = new FxHook("kernel32.dll", "GetFileAttributesExA", dGetFileAttrExA);
- hGetFileAttrExW = new FxHook("kernel32.dll", "GetFileAttributesExW", dGetFileAttrExW);
+ hCreateFileA = AutoHookCreator("kernel32.dll", "CreateFileA", dCreateFileA);
+ hCreateFileW = AutoHookCreator("kernel32.dll", "CreateFileW", dCreateFileW);
+ hGetFileAttrA = AutoHookCreator("kernel32.dll", "GetFileAttributesA", dGetFileAttrA);
+ hGetFileAttrW = AutoHookCreator("kernel32.dll", "GetFileAttributesW", dGetFileAttrW);
+ hGetFileAttrExA = AutoHookCreator("kernel32.dll", "GetFileAttributesExA", dGetFileAttrExA);
+ hGetFileAttrExW = AutoHookCreator("kernel32.dll", "GetFileAttributesExW", dGetFileAttrExW);
+
hCreateFileA.Install();
hCreateFileW.Install();
@@ -87,12 +87,12 @@ static string ParsePath(string Path)
static CreateFileADelegate dCreateFileA;
static CreateFileWDelegate dCreateFileW;
- static FxHook hGetFileAttrA;
- static FxHook hGetFileAttrW;
- static FxHook hGetFileAttrExA;
- static FxHook hGetFileAttrExW;
- static FxHook hCreateFileA;
- static FxHook hCreateFileW;
+ static UnmanagedHook hGetFileAttrA;
+ static UnmanagedHook hGetFileAttrW;
+ static UnmanagedHook hGetFileAttrExA;
+ static UnmanagedHook hGetFileAttrExW;
+ static UnmanagedHook hCreateFileA;
+ static UnmanagedHook hCreateFileW;
[UnmanagedFunctionPointer(CallingConvention.Winapi, CharSet = CharSet.Ansi, SetLastError = true)]
delegate uint GetFileAttributesADelegate([MarshalAs(UnmanagedType.LPStr)] string Filepath);
diff --git a/SRL/Hook/HookFX.cs b/SRL/Hook/HookFX.cs
deleted file mode 100644
index 842ef6a..0000000
--- a/SRL/Hook/HookFX.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-using System;
-using System.Text;
-using System.Runtime.InteropServices;
-
-public class FxHook : IDisposable {
-
- static int nBytes = IntPtr.Size == 8 ? 12 : 5;
-
- IntPtr addr;
- Protection old;
- byte[] src = new byte[nBytes];
- byte[] dst = new byte[nBytes];
-
- public FxHook(IntPtr source, IntPtr destination) {
- VirtualProtect(source, nBytes, Protection.PAGE_EXECUTE_READWRITE, out old);
- Marshal.Copy(source, src, 0, nBytes);
- if (IntPtr.Size == 8) {
- //x64
- new byte[] { 0x48, 0xb8 }.CopyTo(dst, 0);
- BitConverter.GetBytes(unchecked((ulong)destination.ToInt64())).CopyTo(dst, 2);
- new byte[] { 0xFF, 0xE0 }.CopyTo(dst, 10);
- } else {
- //x86
- dst[0] = 0xE9;
- var Result = (int)(destination.ToInt64() - source.ToInt64() - nBytes);
- var dx = BitConverter.GetBytes(Result);
- Array.Copy(dx, 0, dst, 1, nBytes - 1);
- }
- addr = source;
- }
- public FxHook(IntPtr source, Delegate destination) : this(source, Marshal.GetFunctionPointerForDelegate(destination)) {
- }
-
- public FxHook(string library, string function, Delegate destination) : this(GetProcAddress(LoadLibrary(library), function), destination) {
- }
-
- public void Install() {
- Marshal.Copy(dst, 0, addr, nBytes);
- }
-
- public void Uninstall() {
- Marshal.Copy(src, 0, addr, nBytes);
- }
-
- public void Dispose() {
- Uninstall();
- Protection x;
- VirtualProtect(addr, nBytes, old, out x);
- }
-
- [DllImport("kernel32.dll", SetLastError = true)]
- static extern bool VirtualProtect(IntPtr lpAddress, int dwSize, Protection flNewProtect, out Protection lpflOldProtect);
-
- [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
- static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
-
- [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
- static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);
-
- public enum Protection {
- PAGE_NOACCESS = 0x01,
- PAGE_READONLY = 0x02,
- PAGE_READWRITE = 0x04,
- PAGE_WRITECOPY = 0x08,
- PAGE_EXECUTE = 0x10,
- PAGE_EXECUTE_READ = 0x20,
- PAGE_EXECUTE_READWRITE = 0x40,
- PAGE_EXECUTE_WRITECOPY = 0x80,
- PAGE_GUARD = 0x100,
- PAGE_NOCACHE = 0x200,
- PAGE_WRITECOMBINE = 0x400
- }
-
-}
\ No newline at end of file
diff --git a/SRL/Hook/IntroInjector.cs b/SRL/Hook/IntroInjector.cs
index c4113a9..c1b6648 100644
--- a/SRL/Hook/IntroInjector.cs
+++ b/SRL/Hook/IntroInjector.cs
@@ -14,45 +14,40 @@ static partial class StringReloader {
#if !DEBUG
static CreateWindowExADelegate CreateWindowExADel;
static CreateWindowExWDelegate CreateWindowExWDel;
- static FxHook CreateWindowExAHook;
- static FxHook CreateWindowExWHook;
+ static UnmanagedHook CreateWindowExAHook;
+ static UnmanagedHook CreateWindowExWHook;
#endif
static ShowWindowDelegate ShowWindowDel;
static SetWindowPosDelegate SetWindowPosDel;
static MoveWindowDelegate MoveWindowDel;
- static FxHook ShowWindowHook;
- static FxHook SetWindowPosHook;
- static FxHook MoveWindowHook;
+ static UnmanagedHook ShowWindowHook;
+ static UnmanagedHook SetWindowPosHook;
+ static UnmanagedHook MoveWindowHook;
- static bool SysCall = true;
static void InstallIntroInjector() {
if (ShowWindowHook != null)
return;
#if !DEBUG
CreateWindowExADel = new CreateWindowExADelegate(hCreateWindowEx);
CreateWindowExWDel = new CreateWindowExWDelegate(hCreateWindowEx);
- CreateWindowExAHook = new FxHook("user32.dll", "CreateWindowExA", CreateWindowExADel);
- CreateWindowExWHook = new FxHook("user32.dll", "CreateWindowExW", CreateWindowExWDel);
+ CreateWindowExAHook = AutoHookCreator("user32.dll", "CreateWindowExA", CreateWindowExADel);
+ CreateWindowExWHook = AutoHookCreator("user32.dll", "CreateWindowExW", CreateWindowExWDel);
if (HookCreateWindowEx)
CreateWindowExADel = new CreateWindowExADelegate(hCreateWindowEx);
#endif
- SysCall = !ValidLibrary("win32u.dll");
-
- Log($"Intro Injector SysCall Support {(SysCall ? "Enabled" : "Disabled")}", true);
-
ShowWindowDel = new ShowWindowDelegate(hShowWindow);
- ShowWindowHook = new FxHook("user32.dll", "ShowWindow", ShowWindowDel);
+ ShowWindowHook = AutoHookCreator("user32.dll", "ShowWindow", ShowWindowDel);
if (HookShowWindow)
ShowWindowHook.Install();
SetWindowPosDel = new SetWindowPosDelegate(hSetWindowPos);
- SetWindowPosHook = new FxHook("user32.dll", "SetWindowPos", SetWindowPosDel);
+ SetWindowPosHook = AutoHookCreator("user32.dll", "SetWindowPos", SetWindowPosDel);
if (HookSetWindowPos)
SetWindowPosHook.Install();
MoveWindowDel = new MoveWindowDelegate(hMoveWindow);
- MoveWindowHook = new FxHook("user32.dll", "MoveWindow", MoveWindowDel);
+ MoveWindowHook = AutoHookCreator("user32.dll", "MoveWindow", MoveWindowDel);
if (HookMoveWindow)
MoveWindowHook.Install();
@@ -60,60 +55,59 @@ static void InstallIntroInjector() {
}
static bool IntroInitialized = false;
- static bool hShowWindow(IntPtr hWnd, int nCmdShow) {
- if (SysCall)
- {
+ static bool hShowWindow(IntPtr hWnd, int nCmdShow)
+ {
+ if (!ShowWindowHook.ImportHook)
ShowWindowHook.Uninstall();
- bool Rst = ShowWindow(hWnd, nCmdShow);
- ShowWindowHook.Install();
- if (nCmdShow != SW_HIDE)
- ShowIntro(hWnd);
+ bool Rst = ShowWindow(hWnd, nCmdShow);
- return Rst;
- }
-
- bool Result = NtUserShowWindow(hWnd, nCmdShow);
+ if (!ShowWindowHook.ImportHook)
+ ShowWindowHook.Install();
if (nCmdShow != SW_HIDE)
ShowIntro(hWnd);
- return Result;
+ return Rst;
}
- static bool hSetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags) {
- if (SysCall)
- {
+ static bool hSetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags)
+ {
+ if (!SetWindowPosHook.ImportHook)
SetWindowPosHook.Uninstall();
- bool Rst = SetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
- SetWindowPosHook.Install();
- ShowIntro(hWnd);
- return Rst;
- }
- bool Result = NtUserSetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
+ bool Rst = SetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
+
+ if (!SetWindowPosHook.ImportHook)
+ SetWindowPosHook.Install();
ShowIntro(hWnd);
- return Result;
+
+ return Rst;
}
- static bool hMoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint) {
- if (SysCall)
- {
+ static bool hMoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint)
+ {
+ if (!MoveWindowHook.ImportHook)
MoveWindowHook.Uninstall();
- bool Rst = MoveWindow(hWnd, X, Y, nWidth, nHeight, bRepaint);
+
+ bool Rst = MoveWindow(hWnd, X, Y, nWidth, nHeight, bRepaint);
+
+ if (!MoveWindowHook.ImportHook)
MoveWindowHook.Install();
- ShowIntro(hWnd);
- return Rst;
- }
- bool Result = NtUserMoveWindow(hWnd, X, Y, nWidth, nHeight, bRepaint);
ShowIntro(hWnd);
- return Result;
+
+ return Rst;
}
- static IntPtr hCreateWindowEx(WindowStylesEx dwExStyle, string lpClassName, string lpWindowName, WindowStyles dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam) {
- CreateWindowExWHook.Uninstall();
+ static IntPtr hCreateWindowEx(WindowStylesEx dwExStyle, string lpClassName, string lpWindowName, WindowStyles dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam)
+ {
+ if (!CreateWindowExWHook.ImportHook)
+ CreateWindowExWHook.Uninstall();
+
IntPtr Result = CreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
- CreateWindowExWHook.Install();
+
+ if (!CreateWindowExWHook.ImportHook)
+ CreateWindowExWHook.Install();
ShowIntro(Result);
return Result;
}
@@ -330,7 +324,13 @@ static Bitmap SetBitmapOpacity(Bitmap image, float opacity) {
}
}
- static bool ValidLibrary(string fileName) => LoadLibrary(fileName) != IntPtr.Zero;
+ static bool ValidExport(string Module, string Function)
+ {
+ var hModule = LoadLibrary(Module);
+ if (hModule == IntPtr.Zero)
+ return false;
+ return GetProcAddress(hModule, Function) != IntPtr.Zero;
+ }
struct IntroHelper {
public Bitmap[] Fade;
diff --git a/SRL/Hook/TextHook.cs b/SRL/Hook/TextHook.cs
index b1ba3bb..86c8d50 100644
--- a/SRL/Hook/TextHook.cs
+++ b/SRL/Hook/TextHook.cs
@@ -26,36 +26,36 @@ static partial class StringReloader {
static SetWindowTextADelegate dSetWindowTextA;
static SetWindowTextWDelegate dSetWindowTextW;
- static FxHook OutlineA;
- static FxHook OutlineW;
- static FxHook hTextOutA;
- static FxHook hTextOutW;
- static FxHook hExtTextOutA;
- static FxHook hExtTextOutW;
- static FxHook hCreatFontA;
- static FxHook hCreatFontW;
- static FxHook hCreatFontIndirectA;
- static FxHook hCreatFontIndirectW;
+ static UnmanagedHook OutlineA;
+ static UnmanagedHook OutlineW;
+ static UnmanagedHook hTextOutA;
+ static UnmanagedHook hTextOutW;
+ static UnmanagedHook hExtTextOutA;
+ static UnmanagedHook hExtTextOutW;
+ static UnmanagedHook hCreatFontA;
+ static UnmanagedHook hCreatFontW;
+ static UnmanagedHook hCreatFontIndirectA;
+ static UnmanagedHook hCreatFontIndirectW;
#if DEBUG
- static FxHook hSendMessageA;
- static FxHook hSendMessageW;
- static FxHook hCreateWindowExA;
- static FxHook hCreateWindowExW;
- static FxHook hCreateWindowA;
- static FxHook hCreateWindowW;
+ static UnmanagedHook hSendMessageA;
+ static UnmanagedHook hSendMessageW;
+ static UnmanagedHook hCreateWindowExA;
+ static UnmanagedHook hCreateWindowExW;
+ static UnmanagedHook hCreateWindowA;
+ static UnmanagedHook hCreateWindowW;
#endif
- static FxHook hSetWindowTextA;
- static FxHook hSetWindowTextW;
+ static UnmanagedHook hSetWindowTextA;
+ static UnmanagedHook hSetWindowTextW;
- static FxHook hMultiByteToWideChar;
+ static UnmanagedHook hMultiByteToWideChar;
static void InstallGlyphHooks() {
dOutlineA = new GetGlyphOutlineDelegate(hGetGlyphOutlineA);
dOutlineW = new GetGlyphOutlineDelegate(hGetGlyphOutlineW);
- OutlineA = new FxHook("gdi32.dll", "GetGlyphOutlineA", dOutlineA);
- OutlineW = new FxHook("gdi32.dll", "GetGlyphOutlineW", dOutlineW);
+ OutlineA = AutoHookCreator("gdi32.dll", "GetGlyphOutlineA", dOutlineA);
+ OutlineW = AutoHookCreator("gdi32.dll", "GetGlyphOutlineW", dOutlineW);
OutlineA.Install();
OutlineW.Install();
@@ -65,18 +65,19 @@ static void InstallTextOutHooks() {
dTextOutA = new TextOutADelegate(hTextOut);
dTextOutW = new TextOutWDelegate(hTextOut);
- hTextOutA = new FxHook("gdi32.dll", "TextOutA", dTextOutA);
- hTextOutW = new FxHook("gdi32.dll", "TextOutW", dTextOutW);
+ hTextOutA = AutoHookCreator("gdi32.dll", "TextOutA", dTextOutA);
+ hTextOutW = AutoHookCreator("gdi32.dll", "TextOutW", dTextOutW);
hTextOutA.Install();
hTextOutW.Install();
}
+
static void InstallExtTextOutHooks() {
dExtTextOutA = new ExtTextOutADelegate(hExtTextOut);
dExtTextOutW = new ExtTextOutWDelegate(hExtTextOut);
- hExtTextOutA = new FxHook("gdi32.dll", "ExtTextOutA", dExtTextOutA);
- hExtTextOutW = new FxHook("gdi32.dll", "ExtTextOutW", dExtTextOutW);
+ hExtTextOutA = AutoHookCreator("gdi32.dll", "ExtTextOutA", dExtTextOutA);
+ hExtTextOutW = AutoHookCreator("gdi32.dll", "ExtTextOutW", dExtTextOutW);
hExtTextOutA.Install();
hExtTextOutW.Install();
@@ -86,8 +87,8 @@ static void InstallCreateFontHooks() {
dCreateFontA = new CreateFontADelegate(hCreateFont);
dCreateFontW = new CreateFontWDelegate(hCreateFont);
- hCreatFontA = new FxHook("gdi32.dll", "CreateFontA", dCreateFontA);
- hCreatFontW = new FxHook("gdi32.dll", "CreateFontW", dCreateFontW);
+ hCreatFontA = AutoHookCreator("gdi32.dll", "CreateFontA", dCreateFontA);
+ hCreatFontW = AutoHookCreator("gdi32.dll", "CreateFontW", dCreateFontW);
hCreatFontA.Install();
hCreatFontW.Install();
@@ -98,8 +99,8 @@ static void InstallCreateFontIndirectHooks() {
dCreateFontIndirectW = new CreateFontIndirectWDelegate(hCreateFontIndirectW);
- hCreatFontIndirectA = new FxHook("gdi32.dll", "CreateFontIndirectA", dCreateFontIndirectA);
- hCreatFontIndirectW = new FxHook("gdi32.dll", "CreateFontIndirectW", dCreateFontIndirectW);
+ hCreatFontIndirectA = AutoHookCreator("gdi32.dll", "CreateFontIndirectA", dCreateFontIndirectA);
+ hCreatFontIndirectW = AutoHookCreator("gdi32.dll", "CreateFontIndirectW", dCreateFontIndirectW);
hCreatFontIndirectA.Install();
hCreatFontIndirectW.Install();
@@ -110,8 +111,8 @@ static void InstallSendMessageHooks() {
dSendMessageA = new SendMessageADelegate(SendMessageAHook);
dSendMessageW = new SendMessageWDelegate(SendMessageWHook);
- hSendMessageA = new FxHook("user32.dll", "SendMessageA", dSendMessageA);
- hSendMessageW = new FxHook("user32.dll", "SendMessageW", dSendMessageW);
+ hSendMessageA = AutoHookCreator("user32.dll", "SendMessageA", dSendMessageA);
+ hSendMessageW = AutoHookCreator("user32.dll", "SendMessageW", dSendMessageW);
hSendMessageA.Install();
hSendMessageW.Install();
@@ -121,8 +122,8 @@ static void InstallCreateWindowHooks() {
dCreateWindowA = new CreateWindowADelegate(CreateWindow);
dCreateWindowW = new CreateWindowWDelegate(CreateWindow);
- hCreateWindowA = new FxHook("user32.dll", "CreateWindowA", dCreateWindowA);
- hCreateWindowW = new FxHook("user32.dll", "CreateWindowW", dCreateWindowW);
+ hCreateWindowA = AutoHookCreator("user32.dll", "CreateWindowA", dCreateWindowA);
+ hCreateWindowW = AutoHookCreator("user32.dll", "CreateWindowW", dCreateWindowW);
hCreateWindowA.Install();
hCreateWindowW.Install();
@@ -132,8 +133,8 @@ static void InstallCreateWindowExHooks() {
dCreateWindowExA = new CreateWindowExADelegate(CreateWindowEx);
dCreateWindowExW = new CreateWindowExWDelegate(CreateWindowEx);
- hCreateWindowExA = new FxHook("user32.dll", "CreateWindowExA", dCreateWindowExA);
- hCreateWindowExW = new FxHook("user32.dll", "CreateWindowExW", dCreateWindowExW);
+ hCreateWindowExA = AutoHookCreator("user32.dll", "CreateWindowExA", dCreateWindowExA);
+ hCreateWindowExW = AutoHookCreator("user32.dll", "CreateWindowExW", dCreateWindowExW);
hCreateWindowExA.Install();
hCreateWindowExW.Install();
@@ -144,8 +145,8 @@ static void InstallSetWindowTextHooks() {
dSetWindowTextA = new SetWindowTextADelegate(SetWindowTextHook);
dSetWindowTextW = new SetWindowTextWDelegate(SetWindowTextHook);
- hSetWindowTextA = new FxHook("user32.dll", "SetWindowTextA", dSetWindowTextA);
- hSetWindowTextW = new FxHook("user32.dll", "SetWindowTextW", dSetWindowTextW);
+ hSetWindowTextA = AutoHookCreator("user32.dll", "SetWindowTextA", dSetWindowTextA);
+ hSetWindowTextW = AutoHookCreator("user32.dll", "SetWindowTextW", dSetWindowTextW);
hSetWindowTextA.Install();
hSetWindowTextW.Install();
@@ -154,7 +155,7 @@ static void InstallSetWindowTextHooks() {
static void InstallMultiByteToWideChar() {
dMultiByteToWideChar = new MultiByteToWideCharDelegate(MultiByteToWideCharHook);
- hMultiByteToWideChar = new FxHook("kernel32.dll", "MultiByteToWideChar", dMultiByteToWideChar);
+ hMultiByteToWideChar = AutoHookCreator("kernel32.dll", "MultiByteToWideChar", dMultiByteToWideChar);
hMultiByteToWideChar.Install();
}
@@ -167,6 +168,8 @@ public static uint hGetGlyphOutlineA(IntPtr hdc, uint uChar, uint uFormat, out G
if (Debugging)
Log("OutlineA Hooked, {0:X4}", true, uChar);
#endif
+ if (OutlineA.ImportHook)
+ return GetGlyphOutlineA(hdc, uChar, uFormat, out lpgm, cbBuffer, lpvBuffer, ref lpmat2);
OutlineA.Uninstall();
uint Ret = GetGlyphOutlineA(hdc, uChar, uFormat, out lpgm, cbBuffer, lpvBuffer, ref lpmat2);
@@ -181,6 +184,9 @@ public static uint hGetGlyphOutlineW(IntPtr hdc, uint uChar, uint uFormat, out G
Log("OutlineW Hooked, {0:X4}", true, uChar);
#endif
+ if (OutlineW.ImportHook)
+ return GetGlyphOutlineW(hdc, uChar, uFormat, out lpgm, cbBuffer, lpvBuffer, ref lpmat2);
+
OutlineW.Uninstall();
uint Ret = GetGlyphOutlineW(hdc, uChar, uFormat, out lpgm, cbBuffer, lpvBuffer, ref lpmat2);
OutlineW.Install();
@@ -188,7 +194,7 @@ public static uint hGetGlyphOutlineW(IntPtr hdc, uint uChar, uint uFormat, out G
}
public static bool hTextOut(IntPtr hdc, int nXStart, int nYStart, string lpString, int cbString) {
- lpString = ProcessManaged(lpString, false);
+ lpString = Process(lpString);
if (UndoChars) {
for (int i = 0; i < lpString.Length; i++) {
char C = lpString[i];
@@ -205,10 +211,11 @@ public static bool hTextOut(IntPtr hdc, int nXStart, int nYStart, string lpStrin
}
}
-#if DEBUG
- if (Debugging)
+ if (LogInput)
Log("TextOut Hooked, {0}", true, lpString);
-#endif
+
+ if (hTextOutW.ImportHook)
+ return TextOutW(hdc, nXStart, nYStart, lpString, cbString);
hTextOutW.Uninstall();
bool Rst = TextOutW(hdc, nXStart, nYStart, lpString, cbString);
@@ -217,7 +224,7 @@ public static bool hTextOut(IntPtr hdc, int nXStart, int nYStart, string lpStrin
}
public static bool hExtTextOut(IntPtr hdc, int X, int Y, uint fuOptions, ref RECT lprc, string lpString, uint cbCount, IntPtr lpDx) {
- lpString = ProcessManaged(lpString, false);
+ lpString = Process(lpString);
if (UndoChars) {
for (int i = 0; i < lpString.Length; i++) {
char C = lpString[i];
@@ -234,10 +241,13 @@ public static bool hExtTextOut(IntPtr hdc, int X, int Y, uint fuOptions, ref REC
}
}
-#if DEBUG
- if (Debugging)
+
+ if (LogInput)
Log("ExtTextOut Hooked, {0}", true, lpString);
-#endif
+
+
+ if (hExtTextOutW.ImportHook)
+ return ExtTextOutW(hdc, X, Y, fuOptions, ref lprc, lpString, cbCount, lpDx);
hExtTextOutW.Uninstall();
bool Rst = ExtTextOutW(hdc, X, Y, fuOptions, ref lprc, lpString, cbCount, lpDx);
@@ -265,10 +275,11 @@ static IntPtr hCreateFont(int nHeight, int nWidth, int nEscapement, int nOrienta
fdwCharSet = FontCharset;
-#if DEBUG
- if (Debugging)
+ if (LogInput)
Log("CreateFont Hooked, {0} 0x{1:X2}", true, lpszFace, fdwCharSet);
-#endif
+
+ if (hCreateFileW.ImportHook)
+ return CreateFontW(nHeight, nWidth, nEscapement, nOrientation, fnWeight, fdwItalic, fdwUnderline, fdwStrikeOut, fdwCharSet, fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily, lpszFace);
hCreatFontW.Uninstall();
var Result = CreateFontW(nHeight, nWidth, nEscapement, nOrientation, fnWeight, fdwItalic, fdwUnderline, fdwStrikeOut, fdwCharSet, fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily, lpszFace);
@@ -296,11 +307,11 @@ static IntPtr hCreateFontIndirectA(ref LOGFONTA FontInfo) {
if (FontCharset != 0)
FontInfo.lfCharSet = FontCharset;
-
-#if DEBUG
- if (Debugging)
+ if (LogInput)
Log("CreateIndirectA Hooked, {0} 0x{1:X2}", true, FontInfo.lfFaceName, FontInfo.lfCharSet);
-#endif
+
+ if (hCreatFontIndirectA.ImportHook)
+ return CreateFontIndirectA(ref FontInfo);
hCreatFontIndirectA.Uninstall();
var Result = CreateFontIndirectA(ref FontInfo);
@@ -326,11 +337,11 @@ static IntPtr hCreateFontIndirectW(ref LOGFONTW FontInfo) {
if (FontCharset != 0)
FontInfo.lfCharSet = FontCharset;
-
-#if DEBUG
- if (Debugging)
+ if (LogInput)
Log("CreateIndirectW Hooked, {0} 0x{1:X2}", true, FontInfo.lfFaceName, FontInfo.lfCharSet);
-#endif
+
+ if (hCreatFontIndirectW.ImportHook)
+ return CreateFontIndirectW(ref FontInfo);
hCreatFontIndirectW.Uninstall();
var Result = CreateFontIndirectW(ref FontInfo);
@@ -352,6 +363,10 @@ static Int32 SendMessageWHook(int hWnd, int Msg, int wParam, IntPtr lParam) {
lParam = GenString(Reload, true);
}
}
+
+ if (hSendMessageW.ImportHook)
+ return SendMessageW(hWnd, Msg, wParam, lParam);
+
hSendMessageW.Uninstall();
var Rst = SendMessageW(hWnd, Msg, wParam, lParam);
hSendMessageW.Install();
@@ -369,6 +384,10 @@ static Int32 SendMessageAHook(int hWnd, int Msg, int wParam, IntPtr lParam) {
lParam = GenString(Reload);
}
}
+
+ if (hSendMessageA.ImportHook)
+ return SendMessageA(hWnd, Msg, wParam, lParam);
+
hSendMessageA.Uninstall();
var Rst = SendMessageA(hWnd, Msg, wParam, lParam);
hSendMessageA.Install();
@@ -381,8 +400,11 @@ static IntPtr CreateWindowEx(WindowStylesEx dwExStyle, string lpClassName, strin
string Reload = StrMap(lpWindowName, IntPtr.Zero, true);
+ if (hCreateWindowExW.ImportHook)
+ return CreateWindowExW(dwExStyle, lpClassName, Reload, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
+
hCreateWindowExW.Uninstall();
- var Rst = CreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
+ var Rst = CreateWindowExW(dwExStyle, lpClassName, Reload, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
hCreateWindowExW.Install();
return Rst;
}
@@ -392,8 +414,11 @@ static IntPtr CreateWindow(string lpClassName, string lpWindowName, uint dwStyle
string Reload = StrMap(lpWindowName, IntPtr.Zero, true);
+ if (hCreateWindowExW.ImportHook)
+ return CreateWindowW(lpClassName, Reload, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
+
hCreateWindowExW.Uninstall();
- var Rst = CreateWindowW(lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
+ var Rst = CreateWindowW(lpClassName, Reload, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
hCreateWindowExW.Install();
return Rst;
}
@@ -401,6 +426,9 @@ static IntPtr CreateWindow(string lpClassName, string lpWindowName, uint dwStyle
static bool SetWindowTextHook(IntPtr hwnd, string lpString) {
lpString = StrMap(lpString, IntPtr.Zero, true);
+ if (hSetWindowTextW.ImportHook)
+ return SetWindowTextW(hwnd, lpString);
+
hSetWindowTextW.Uninstall();
var Ret = SetWindowTextW(hwnd, lpString);
hSetWindowTextW.Install();
@@ -408,10 +436,14 @@ static bool SetWindowTextHook(IntPtr hwnd, string lpString) {
}
static int MultiByteToWideCharHook(int Codepage, uint dwFlags, IntPtr Input, int cbMultiByte, IntPtr Output, int cchWideChar) {
- hMultiByteToWideChar.Uninstall();
+
+ if (!hMultiByteToWideChar.ImportHook)
+ hMultiByteToWideChar.Uninstall();
+
if (!Initialized || cbMultiByte == 0) {
int Rst = MultiByteToWideChar(Codepage, dwFlags, Input, cbMultiByte, Output, cchWideChar);
- hMultiByteToWideChar.Install();
+ if (!hMultiByteToWideChar.ImportHook)
+ hMultiByteToWideChar.Install();
return Rst;
}
string Str = GetString(Input, Len: cbMultiByte == -1 ? null : (int?)cbMultiByte, CP: Codepage);
@@ -420,15 +452,19 @@ static int MultiByteToWideCharHook(int Codepage, uint dwFlags, IntPtr Input, int
if (RStr == Str) {
int Rst = MultiByteToWideChar(Codepage, dwFlags, Input, cbMultiByte, Output, cchWideChar);
- hMultiByteToWideChar.Install();
+ if (!hMultiByteToWideChar.ImportHook)
+ hMultiByteToWideChar.Install();
return Rst;
}
- Log("MBTWC Hook: {0}", true, RStr);
+ if (LogInput)
+ Log("MBTWC Hook: {0}", true, RStr);
Output = GenString(RStr, true, Output == IntPtr.Zero ? null : (IntPtr?)Output);
- hMultiByteToWideChar.Install();
+ if (!hMultiByteToWideChar.ImportHook)
+ hMultiByteToWideChar.Install();
+
return cchWideChar;
}
diff --git a/SRL/Hook/UmanagedHook.cs b/SRL/Hook/UmanagedHook.cs
new file mode 100644
index 0000000..29743b5
--- /dev/null
+++ b/SRL/Hook/UmanagedHook.cs
@@ -0,0 +1,883 @@
+//Original Repo of this class: https://github.com/marcussacana/RemoteControl
+using System;
+using System.Runtime.InteropServices;
+using System.Reflection.Emit;
+using System.Linq;
+using System.Reflection;
+using static SRL.UnmanagedImports;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace SRL
+{
+ public struct ImportEntry
+ {
+
+ ///
+ /// The Imported Module Name
+ ///
+ public string Module;
+
+ ///
+ /// The Imported Function Name
+ ///
+ public string Function;
+
+ ///
+ /// The Import Ordinal Hint
+ ///
+ public ushort Ordinal;
+
+ ///
+ /// The Address of this Import in the IAT (Import Address Table)
+ ///
+ public IntPtr ImportAddress;
+
+ ///
+ /// The Address of the Imported Function
+ ///
+ public IntPtr FunctionAddress;
+ }
+
+ public class UnmanagedHook : UnmanagedHook {
+
+ ///
+ /// Create a new hook to the function in given pointer
+ ///
+ /// The pointer of the unmanaged function to hook
+ /// The delegate with the hook function
+ public UnmanagedHook(IntPtr Original, Delegate Hook) : base(Original, Hook, false) { }
+
+ /// Create a new Hook
+ ///
+ /// The Library name, Ex: Kernel32.dll
+ /// The Function name, Ex: CreateFile
+ /// The delegate wit the hook function
+ public UnmanagedHook(string Library, string Function, Delegate Hook) : base(Library, Function, Hook, false) { }
+
+ /// Create a new Hook
+ ///
+ /// The Import Entry to install the hook
+ /// The delegate wit the hook function
+
+ public UnmanagedHook(ImportEntry Import, Delegate Hook) : base(Import, Hook) { }
+
+ ///
+ /// Enumarete all imports of a specified process main module
+ ///
+ /// The process that have loaded the module
+ /// All Import Entries
+ public static ImportEntry[] GetImports() => GetModuleImports(Process.GetCurrentProcess().MainModule.BaseAddress);
+
+ ///
+ /// Create a hook by Import if possible
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static UnmanagedHook TryHookImport(string Library, string Function, Delegate Hook)
+ {
+ var Import = GetImport(Library, Function);
+ if (Import.HasValue)
+ return new UnmanagedHook(Import.Value, Hook);
+ else
+ return new UnmanagedHook(Library, Function, Hook);
+ }
+
+ public static ImportEntry? GetImport(string Module, string Function)
+ {
+ try
+ {
+ return (from x in GetImports() where (x.Module.ToLower() == Module.ToLower() && Function == x.Function) select x).Single();
+ }
+ catch {
+ return null;
+ }
+ }
+
+ public static ImportEntry? GetImport(string Module, ushort Ordinal)
+ {
+ try
+ {
+ return (from x in GetImports() where (x.Module.ToLower() == Module.ToLower() && Ordinal == x.Ordinal) select x).Single();
+ }
+ catch {
+ return null;
+ }
+ }
+
+ public bool ImportHook => base.ImportHook;
+ }
+
+ public class UnmanagedHook : IDisposable, Hook where T : Delegate {
+
+ static int nBytes = IntPtr.Size == 8 ? 12 : 5;
+
+ IntPtr destination;
+ IntPtr addr;
+ Protection old;
+ byte[] src = new byte[nBytes];
+ byte[] dst = new byte[nBytes];
+ bool AutoHook = false;
+ public bool ImportHook { get; private set; } = false;
+
+ List Followers = new List();
+
+ T RealDestination;
+ T HookDestination;
+
+
+ ///
+ /// Create a new hook to the function in given pointer
+ ///
+ /// The pointer of the unmanaged function to hook
+ /// The delegate with the hook function
+ /// When true the hook will be automatically uninstalled during he execution
+ public UnmanagedHook(IntPtr Original, T Hook, bool AutoHook) {
+ this.AutoHook = AutoHook;
+ RealDestination = Hook;
+
+ if (AutoHook)
+ GenerateMethod();
+
+ destination = Marshal.GetFunctionPointerForDelegate(AutoHook ? HookDestination : RealDestination);
+
+ VirtualProtect(Original, nBytes, Protection.PAGE_EXECUTE_READWRITE, out old);
+ Marshal.Copy(Original, src, 0, nBytes);
+ if (IntPtr.Size == 8) {
+ //x64
+ new byte[] { 0x48, 0xb8 }.CopyTo(dst, 0);
+ BitConverter.GetBytes(unchecked((ulong)destination.ToInt64())).CopyTo(dst, 2);
+ new byte[] { 0xFF, 0xE0 }.CopyTo(dst, 10);
+ } else {
+ //x86
+ dst[0] = 0xE9;
+ var Result = (int)(destination.ToInt64() - Original.ToInt64() - nBytes);
+ var dx = BitConverter.GetBytes(Result);
+ Array.Copy(dx, 0, dst, 1, nBytes - 1);
+ }
+ addr = Original;
+ }
+
+ ///
+ /// Install a hook exclusive to a certain module (Using the IAT Method)
+ ///
+ /// The Module Import To Hook
+ /// The Delegate with the hook function
+ public UnmanagedHook(ImportEntry Import, T Hook)
+ {
+ ImportHook = true;
+
+ addr = Import.ImportAddress;
+
+ src = new byte[IntPtr.Size];
+ VirtualProtect(Import.ImportAddress, IntPtr.Size, Protection.PAGE_READWRITE, out old);
+ Marshal.Copy(Import.ImportAddress, src, 0, IntPtr.Size);
+
+ destination = Marshal.GetFunctionPointerForDelegate(Hook);
+ dst = BitConverter.GetBytes(IntPtr.Size == 8 ? destination.ToUInt64() : destination.ToUInt32());
+ }
+
+
+ ///
+ /// Create a new hook to the function in given pointer
+ ///
+ /// The pointer of the unmanaged function to hook
+ /// The delegate with the hook function
+ public UnmanagedHook(IntPtr Original, T Hook) : this(Original, Hook, true) { }
+
+ /// Create a new Hook
+ ///
+ /// The Library name, Ex: Kernel32.dll
+ /// The Function name, Ex: CreateFile
+ /// The delegate wit the hook function
+ public UnmanagedHook(string Library, string Function, T Hook) : this(GetProcAddress(LoadLibrary(Library), Function), Hook) {
+ }
+
+
+ /// Create a new Hook
+ ///
+ /// The Library name, Ex: Kernel32.dll
+ /// The Function name, Ex: CreateFile
+ /// The delegate wit the hook function
+ /// When true the hook will be automatically uninstalled during he execution
+ public UnmanagedHook(string Library, string Function, T Hook, bool AutoHook) : this(GetProcAddress(LoadLibrary(Library), Function), Hook, AutoHook) {
+
+ }
+
+ void GenerateMethod() {
+ string ID = CurrentID++.ToString();
+ SetInstance(ID, this);
+
+ var ParametersInfo = RealDestination.Method.GetParameters();
+ var Parameters = (from x in ParametersInfo select x.ParameterType).ToArray();
+
+ List IL = new List();
+ //Uninstall(IID);
+ IL.Add(new Instruction(OpCodes.Ldstr, ID));
+ IL.Add(new Instruction(OpCodes.Call, UninstallMI));
+
+ //Invoke(Parameters);
+ switch (Parameters.Length + 1) {
+ case 1:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_1));
+ break;
+ case 2:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_2));
+ break;
+ case 3:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_3));
+ break;
+ case 4:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_4));
+ break;
+ case 5:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_5));
+ break;
+ case 6:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_6));
+ break;
+ case 7:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_7));
+ break;
+ case 8:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_8));
+ break;
+ default:
+ int Count = Parameters.Length + 1;
+ if (Count <= byte.MaxValue)
+ IL.Add(new Instruction(OpCodes.Ldc_I4_S, (byte)Count));
+ else
+ IL.Add(new Instruction(OpCodes.Ldc_I4, Count));
+ break;
+ }
+ IL.Add(new Instruction(OpCodes.Newarr, typeof(object)));
+
+ for (int i = 0, ind = -1; i < Parameters.Length + 1; i++, ind++) {
+ bool IsOut = ind >= 0 && ParametersInfo[ind].IsOut;
+ bool IsRef = ind >= 0 && ParametersInfo[ind].ParameterType.IsByRef & !IsOut;
+ if (IsOut)
+ continue;
+
+ IL.Add(new Instruction(OpCodes.Dup));
+ switch (i) {
+ case 0:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_0));
+ break;
+ case 1:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_1));
+ break;
+ case 2:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_2));
+ break;
+ case 3:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_3));
+ break;
+ case 4:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_4));
+ break;
+ case 5:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_5));
+ break;
+ case 6:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_6));
+ break;
+ case 7:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_7));
+ break;
+ case 8:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_8));
+ break;
+ default:
+ if (i <= byte.MaxValue)
+ IL.Add(new Instruction(OpCodes.Ldc_I4_S, (byte)i));
+ else
+ IL.Add(new Instruction(OpCodes.Ldc_I4, i));
+ break;
+ }
+
+
+ if (ind >= 0 && (ParametersInfo[ind].IsIn || ParametersInfo[ind].IsOut)) {
+ if (ind <= byte.MaxValue)
+ IL.Add(new Instruction(OpCodes.Ldarga_S, (byte)ind));
+ else
+ IL.Add(new Instruction(OpCodes.Ldarga, (short)ind));
+ } else {
+ switch (i) {
+ case 0:
+ IL.Add(new Instruction(OpCodes.Ldstr, ID));
+ break;
+ case 1:
+ IL.Add(new Instruction(OpCodes.Ldarg_0));
+ break;
+ case 2:
+ IL.Add(new Instruction(OpCodes.Ldarg_1));
+ break;
+ case 3:
+ IL.Add(new Instruction(OpCodes.Ldarg_2));
+ break;
+ case 4:
+ IL.Add(new Instruction(OpCodes.Ldarg_3));
+ break;
+ default:
+ if (ind <= byte.MaxValue)
+ IL.Add(new Instruction(OpCodes.Ldarg_S, (byte)ind));
+ else
+ IL.Add(new Instruction(OpCodes.Ldarg, (short)ind));
+ break;
+ }
+ }
+
+ var Type = ind >= 0 ? Parameters[ind] : null;
+ if (Type != null && IsRef)
+ Type = Parameters[ind].GetElementType();
+
+ bool Cast = true;
+ if (IsRef) {
+ var PType = Type;
+ if (PType.IsEnum && PType.IsValueType)
+ PType = Enum.GetUnderlyingType(PType);
+
+ switch (PType.FullName) {
+ case "System.SByte":
+ IL.Add(new Instruction(OpCodes.Ldind_I1));
+ break;
+ case "System.Byte":
+ IL.Add(new Instruction(OpCodes.Ldind_U1));
+ break;
+ case "System.Int16":
+ IL.Add(new Instruction(OpCodes.Ldind_I2));
+ break;
+ case "System.Char":
+ case "System.UInt16":
+ IL.Add(new Instruction(OpCodes.Ldind_U2));
+ break;
+ case "System.Int32":
+ IL.Add(new Instruction(OpCodes.Ldind_I4));
+ break;
+ case "System.UInt32":
+ IL.Add(new Instruction(OpCodes.Ldind_U4));
+ break;
+ case "System.Int64":
+ case "System.UInt64":
+ IL.Add(new Instruction(OpCodes.Ldind_I8));
+ break;
+ case "System.Single":
+ IL.Add(new Instruction(OpCodes.Ldind_R4));
+ break;
+ case "System.Double":
+ IL.Add(new Instruction(OpCodes.Ldind_R8));
+ break;
+ case "System.IntPtr":
+ case "System.UIntPtr":
+ IL.Add(new Instruction(OpCodes.Ldind_I));
+ break;
+ default:
+ if ((PType.IsValueType && !PType.IsEnum) || PType.IsClass) {
+ IL.Add(new Instruction(OpCodes.Ldobj, PType));
+ } else {
+ IL.Add(new Instruction(OpCodes.Ldind_Ref));
+ Cast = false;
+ }
+ break;
+ }
+ }
+
+ if (ind >= 0 && Cast )
+ IL.Add(new Instruction(OpCodes.Box, Type));
+
+ IL.Add(new Instruction(OpCodes.Stelem_Ref));
+ }
+
+ IL.Add(new Instruction(OpCodes.Stloc_0));
+ IL.Add(new Instruction(OpCodes.Ldloc_0));
+ IL.Add(new Instruction(OpCodes.Call, InvokeMI));
+
+ //Cast Return Type
+ var RetType = RealDestination.Method.ReturnType;
+ if (RetType.IsInterface)
+ IL.Add(new Instruction(OpCodes.Castclass, RetType));
+ else {
+ IL.Add(new Instruction(OpCodes.Unbox_Any, RetType));
+ }
+
+ for (int i = 0, ind = -1; i < Parameters.Length + 1; i++, ind++) {
+ bool IsOut = ind >= 0 && ParametersInfo[ind].IsOut;
+ bool IsRef = ind >= 0 && ParametersInfo[ind].ParameterType.IsByRef & !IsOut;
+
+ if (!IsRef && !IsOut || ind < 0)
+ continue;
+
+
+ switch (ind) {
+ case 0:
+ IL.Add(new Instruction(OpCodes.Ldarg_0));
+ break;
+ case 1:
+ IL.Add(new Instruction(OpCodes.Ldarg_1));
+ break;
+ case 2:
+ IL.Add(new Instruction(OpCodes.Ldarg_2));
+ break;
+ case 3:
+ IL.Add(new Instruction(OpCodes.Ldarg_3));
+ break;
+ default:
+
+ if (ind <= byte.MaxValue)
+ IL.Add(new Instruction(OpCodes.Ldarg_S, (byte)ind));
+ else
+ IL.Add(new Instruction(OpCodes.Ldarg, (short)ind));
+ break;
+ }
+
+ IL.Add(new Instruction(OpCodes.Ldloc_0));
+ switch (i) {
+ case 0:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_0));
+ break;
+ case 1:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_1));
+ break;
+ case 2:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_2));
+ break;
+ case 3:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_3));
+ break;
+ case 4:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_4));
+ break;
+ case 5:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_5));
+ break;
+ case 6:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_6));
+ break;
+ case 7:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_7));
+ break;
+ case 8:
+ IL.Add(new Instruction(OpCodes.Ldc_I4_8));
+ break;
+ default:
+ if (ind <= byte.MaxValue)
+ IL.Add(new Instruction(OpCodes.Ldc_I4_S, (byte)ind));
+ else
+ IL.Add(new Instruction(OpCodes.Ldc_I4, ind));
+ break;
+ }
+
+ IL.Add(new Instruction(OpCodes.Ldelem_Ref));
+
+ var Type = Parameters[ind];
+ if (IsRef || IsOut)
+ Type = Type.GetElementType();
+
+ if (Type.IsInterface) {
+ IL.Add(new Instruction(OpCodes.Castclass, Type));
+ IL.Add(new Instruction(OpCodes.Stind_Ref));
+ } else {
+ IL.Add(new Instruction(OpCodes.Unbox_Any, Type));
+
+ if (Type.IsEnum && Type.IsValueType)
+ Type = Enum.GetUnderlyingType(Type);
+
+ switch (Type.FullName) {
+ case "System.Byte":
+ case "System.SByte":
+ IL.Add(new Instruction(OpCodes.Stind_I1));
+ break;
+ case "System.Char":
+ case "System.UInt16":
+ case "System.Int16":
+ IL.Add(new Instruction(OpCodes.Stind_I2));
+ break;
+ case "System.UInt32":
+ case "System.Int32":
+ IL.Add(new Instruction(OpCodes.Stind_I4));
+ break;
+ case "System.Int64":
+ case "System.UInt64":
+ IL.Add(new Instruction(OpCodes.Stind_I8));
+ break;
+ case "System.Single":
+ IL.Add(new Instruction(OpCodes.Stind_R4));
+ break;
+ case "System.Double":
+ IL.Add(new Instruction(OpCodes.Stind_R8));
+ break;
+ case "System.IntPtr":
+ case "System.UIntPtr":
+ IL.Add(new Instruction(OpCodes.Stind_I));
+ break;
+ default:
+ if (Type.IsValueType && !Type.IsEnum) {
+ IL.Add(new Instruction(OpCodes.Stobj, Type));
+ } else {
+ IL.Add(new Instruction(OpCodes.Stind_Ref));
+ }
+ break;
+ }
+ }
+
+ }
+
+
+ //Install(IID);
+ IL.Add(new Instruction(OpCodes.Ldstr, ID));
+ IL.Add(new Instruction(OpCodes.Call, InstallMI));
+
+ //return;
+ IL.Add(new Instruction(OpCodes.Ret));
+
+#if ILDEBUG
+ var NewMethod = GenerateAssembly(ID, IL, ParametersInfo);
+ HookDestination = (T)Delegate.CreateDelegate(typeof(T), NewMethod);
+#else
+ DynamicMethod Method = new DynamicMethod("UnmanagedHook", RealDestination.Method.ReturnType, Parameters, typeof(UnmanagedImports), true);
+
+
+
+ var ILGen = Method.GetILGenerator();
+ ILGen.DeclareLocal(typeof(object[]));
+
+ foreach (var Pair in IL) {
+ if (Pair.Value == null)
+ ILGen.Emit(Pair.Key);
+ else
+ ILGen.Emit(Pair.Key, Pair.Value);
+ }
+
+ HookDestination = (T)Method.CreateDelegate(typeof(T));
+#endif
+
+ }
+
+ MethodInfo InstallMI => (from x in typeof(UnmanagedImports).GetMethods(BindingFlags.Static | BindingFlags.Public) where x.Name == "Install" select x).First();
+ MethodInfo UninstallMI => (from x in typeof(UnmanagedImports).GetMethods(BindingFlags.Static | BindingFlags.Public) where x.Name == "Uninstall" select x).First();
+ MethodInfo InvokeMI => (from x in typeof(UnmanagedImports).GetMethods(BindingFlags.Static | BindingFlags.Public) where x.Name == "Invoke" select x).First();
+
+ ///
+ /// Install the hook
+ ///
+ public void Install() {
+ Marshal.Copy(dst, 0, addr, ImportHook ? IntPtr.Size : nBytes);
+ }
+
+
+ ///
+ /// Uninstall the hook
+ ///
+ public void Uninstall() {
+ Marshal.Copy(src, 0, addr, ImportHook ? IntPtr.Size : nBytes);
+ }
+
+ Delegate Hook.GetDelegate() {
+ return RealDestination;
+ }
+
+ ///
+ /// Adds a hook to be disabled during the execution of the this hook
+ ///
+ /// The hook to be disabled
+ public void AddFollower(params object[] Followers) {
+ if (!AutoHook)
+ throw new Exception("The Auto Hook must be enabled");
+
+ foreach (object Follower in Followers) {
+ if (!(Follower is Hook))
+ throw new Exception(Follower.GetType().Name + " Isn't an UnmanagedHook Class");
+
+ this.Followers.Add(Follower);
+ }
+ }
+
+ ///
+ /// Remove a hook from the Follower list
+ ///
+ /// The hook to be removed
+ public void RemoveFollower(params object[] Followers) {
+ if (!AutoHook)
+ throw new Exception("The Auto Hook must be enabled");
+
+ foreach (object Follower in Followers) {
+ if (!(Follower is Hook))
+ throw new Exception(Follower.GetType().Name + " Isn't an UnmanagedHook Class");
+
+ this.Followers.Remove(Follower);
+ }
+ }
+
+ object[] Hook.GetFollowers() {
+ return Followers.ToArray();
+ }
+
+ public void Dispose() {
+ Uninstall();
+ Protection x;
+ VirtualProtect(addr, nBytes, old, out x);
+ }
+
+ }
+
+ static class UnmanagedImports {
+
+ [DebuggerDisplay("{Key} {Value}")]
+ internal struct Instruction {
+ public dynamic Key;
+ public dynamic Value;
+
+ public Instruction(dynamic Key, dynamic Value) {
+ this.Key = Key;
+ this.Value = Value;
+ }
+ public Instruction(dynamic Key) {
+ this.Key = Key;
+ Value = null;
+ }
+ }
+
+ internal interface Hook {
+ void Install();
+ void Uninstall();
+
+ dynamic[] GetFollowers();
+
+ Delegate GetDelegate();
+ }
+
+
+ static Dictionary InstanceMap = new Dictionary();
+
+ internal static long CurrentID = 0;
+
+ ///
+ /// INTERNAL UNMANAGED HOOK USAGE, DON'T TOUCH ME
+ ///
+ public static void Install(string ID) {
+ Hook Hook = (Hook)InstanceMap[ID];
+ Hook.Install();
+
+ foreach (object dFollower in Hook.GetFollowers()) {
+ Hook Follower = (Hook)dFollower;
+ Follower.Install();
+ }
+ }
+
+ ///
+ /// INTERNAL UNMANAGED HOOK USAGE, DON'T TOUCH ME
+ ///
+ public static void Uninstall(string ID) {
+ Hook Hook = (Hook)InstanceMap[ID];
+ Hook.Uninstall();
+
+ foreach (object dFollower in Hook.GetFollowers()) {
+ Hook Follower = (Hook)dFollower;
+ Follower.Uninstall();
+ }
+ }
+
+ ///
+ /// INTERNAL UNMANAGED HOOK USAGE, DON'T TOUCH ME
+ ///
+ public static object Invoke(object[] Parameters) {
+ if (Parameters.Length == 0)
+ throw new Exception("No Arguments Found");
+
+ string ID = (string)Parameters.First();
+ object[] Args = Parameters.Skip(1).ToArray();
+
+ Hook Hook = (Hook)InstanceMap[ID];
+
+ object Result = Hook.GetDelegate().DynamicInvoke(Args);
+ Args.CopyTo(Parameters, 1);
+ return Result;
+ }
+
+
+ internal static void SetInstance(string ID, object Instance) {
+ InstanceMap[ID] = Instance;
+ }
+ internal static ImportEntry[] GetModuleImports(IntPtr Module)
+ {
+ if (Module == IntPtr.Zero)
+ throw new Exception("Failed to catch the Main Module...");
+
+ uint PtrSize = Environment.Is64BitProcess ? 8u : 4u;
+
+ ulong OrdinalFlag = (1ul << (int)((8 * PtrSize) - 1));
+
+ ulong PEStart = Read(Module.Sum(0x3C), 4).ToUInt32();
+ ulong OptionalHeader = PEStart + 0x18;
+
+ ulong ImageDataDirectoryPtr = OptionalHeader + (PtrSize == 8 ? 0x70u : 0x60u);
+
+ ulong ImportTableEntry = ImageDataDirectoryPtr + 0x8;
+
+ IntPtr RVA = ImportTableEntry.ToIntPtr();
+
+ IntPtr ImportDesc = Module.Sum(Read(Module.Sum(RVA), 4).ToUInt32());
+
+ if (ImportDesc == Module)
+ return new ImportEntry[0];
+
+ List Entries = new List();
+
+ while (true)
+ {
+ uint OriginalFirstThunk = Read(ImportDesc.Sum(4 * 0), 4).ToUInt32();
+ //uint TimeDateStamp = Read(ImportDesc.Sum(4 * 1), 4).ToUInt32();
+ //uint ForwarderChain = Read(ImportDesc.Sum(4 * 2), 4).ToUInt32();
+ uint Name = Read(ImportDesc.Sum(4 * 3), 4).ToUInt32();
+ uint FirstThunk = Read(ImportDesc.Sum(4 * 4), 4).ToUInt32();
+
+ if (OriginalFirstThunk == 0x00)
+ break;
+
+ string ModuleName = ReadString(Module.Sum(Name), false);
+
+ IntPtr DataAddr = Module.Sum(OriginalFirstThunk);
+ IntPtr IATAddr = Module.Sum(FirstThunk);
+ while (true)
+ {
+ IntPtr EntryPtr = Read(DataAddr, PtrSize).ToIntPtr();
+
+ if (EntryPtr == IntPtr.Zero)
+ break;
+
+ bool ImportByOrdinal = false;
+ if ((EntryPtr.ToUInt64() & OrdinalFlag) == OrdinalFlag)
+ {
+ EntryPtr = (EntryPtr.ToUInt64() ^ OrdinalFlag).ToIntPtr();
+ ImportByOrdinal = true;
+ }
+ else
+ EntryPtr = Module.Sum(EntryPtr);
+
+ ushort Hint = ImportByOrdinal ? (ushort)EntryPtr.ToUInt32() : Read(EntryPtr, 2).ToUInt16();
+ string ExportName = ImportByOrdinal ? null : ReadString(EntryPtr.Sum(2), false);
+
+ Entries.Add(new ImportEntry()
+ {
+ Function = ExportName,
+ Ordinal = Hint,
+ Module = ModuleName,
+ ImportAddress = IATAddr,
+ FunctionAddress = Read(IATAddr, PtrSize).ToIntPtr()
+ });
+
+ DataAddr = DataAddr.Sum(PtrSize);
+ IATAddr = IATAddr.Sum(PtrSize);
+ }
+
+
+ ImportDesc = ImportDesc.Sum(0x14);//sizeof(_IMAGE_IMPORT_DESCRIPTOR)
+ }
+
+ return Entries.ToArray();
+ }
+
+ internal static byte[] Read(IntPtr Address, uint Length)
+ {
+ byte[] Buffer = new byte[Length];
+ ChangeProtection(Address, Buffer.Length, Protection.PAGE_READWRITE, out Protection Original);
+ Marshal.Copy(Address, Buffer, 0, Buffer.Length);
+ ChangeProtection(Address, Buffer.Length, Original);
+ return Buffer;
+ }
+
+ internal static string ReadString(IntPtr Address, bool Unicode)
+ {
+ List Buffer = new List();
+ IntPtr CPos = Address;
+ do
+ {
+ byte[] Char = Read(CPos, Unicode ? 2u : 1u);
+ if (Unicode && Char[0] == 0x00 && Char[1] == 0x00)
+ break;
+ if (!Unicode && Char[0] == 0x00)
+ break;
+
+
+ Buffer.AddRange(Char);
+
+ CPos = CPos.Sum(Unicode ? 2u : 1u);
+ } while (true);
+
+ return Unicode ? System.Text.Encoding.Unicode.GetString(Buffer.ToArray()) : System.Text.Encoding.Default.GetString(Buffer.ToArray());
+ }
+
+
+ internal static ulong ToUInt64(this IntPtr Ptr) => unchecked((ulong)Ptr.ToInt64());
+ internal static uint ToUInt32(this IntPtr Ptr) => unchecked((uint)(Ptr.ToInt64() & 0xFFFFFFFF));
+
+ internal static IntPtr ToIntPtr(this ulong Int) => new IntPtr(unchecked((long)Int));
+
+ internal static IntPtr Sum(this IntPtr Pointer, IntPtr Value) => (Pointer.ToUInt64() + Value.ToUInt64()).ToIntPtr();
+ internal static IntPtr Sum(this IntPtr Pointer, long Value) => (Pointer.ToUInt64() + (ulong)Value).ToIntPtr();
+
+ internal static uint ToUInt32(this byte[] Data, int Address = 0) => BitConverter.ToUInt32(Data, Address);
+ internal static ushort ToUInt16(this byte[] Data, int Address = 0) => BitConverter.ToUInt16(Data, Address);
+ internal static int ToInt32(this byte[] Data, int Address = 0) => BitConverter.ToInt32(Data, Address);
+ internal static long ToInt64(this byte[] Data, int Address = 0) => BitConverter.ToInt64(Data, Address);
+
+ internal static IntPtr ToIntPtr(this byte[] Data, bool? x64 = null)
+ {
+ if (x64.HasValue)
+ return new IntPtr(x64.Value ? Data.ToInt64() : Data.ToInt32());
+ if (Data.Length >= 8)
+ return new IntPtr(IntPtr.Size == 8 ? Data.ToInt64() : Data.ToInt32());
+ return new IntPtr(Data.ToInt32());
+ }
+
+
+ internal static bool ChangeProtection(IntPtr Address, int Range, Protection Protection, out Protection OriginalProtection)
+ {
+ return VirtualProtect(Address, Range, Protection, out OriginalProtection);
+ }
+
+ internal static bool ChangeProtection(IntPtr Address, int Range, Protection Protection)
+ {
+ return VirtualProtect(Address, Range, Protection, out Protection OriginalProtection);
+ }
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ internal static extern bool VirtualProtect(IntPtr lpAddress, int dwSize, Protection flNewProtect, out Protection lpflOldProtect);
+
+ [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
+ internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
+
+ [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
+ internal static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);
+ internal enum Protection {
+ PAGE_NOACCESS = 0x01,
+ PAGE_READONLY = 0x02,
+ PAGE_READWRITE = 0x04,
+ PAGE_WRITECOPY = 0x08,
+ PAGE_EXECUTE = 0x10,
+ PAGE_EXECUTE_READ = 0x20,
+ PAGE_EXECUTE_READWRITE = 0x40,
+ PAGE_EXECUTE_WRITECOPY = 0x80,
+ PAGE_GUARD = 0x100,
+ PAGE_NOCACHE = 0x200,
+ PAGE_WRITECOMBINE = 0x400
+ }
+ }
+
+ static partial class StringReloader
+ {
+ public static UnmanagedHook AutoHookCreator(string Module, string Function, Delegate Hook)
+ {
+ if (!ImportHook)
+ return new UnmanagedHook(Module, Function, Hook);
+
+ var RHook = UnmanagedHook.TryHookImport(Module, Function, Hook);
+ if (Debugging && !RHook.ImportHook)
+ Log("Import Hook Failed: {0} => {1}", true, Module, Function);
+
+ return RHook;
+ }
+ }
+}
\ No newline at end of file
diff --git a/SRL/Main.cs b/SRL/Main.cs
index 2bac0f9..4c95a3a 100644
--- a/SRL/Main.cs
+++ b/SRL/Main.cs
@@ -146,7 +146,8 @@ public static IntPtr GetDirectProcess() {
} catch { return IntPtr.Zero; }
}
- public static string ProcessManaged(string Text) {
+ public static string ProcessManaged(string Text)
+ {
Managed = true;
IntPtr Ptr = Marshal.StringToHGlobalAuto(Text);
IntPtr New = ProcessReal(Ptr);
@@ -157,15 +158,18 @@ public static string ProcessManaged(string Text) {
Marshal.FreeHGlobal(New);
return Text;
}
- static string ProcessManaged(string Text, bool Managed) {
- bool IsManaged = Managed;
- string Result = ProcessManaged(Text);
- if (!Managed)
- Managed = IsManaged;
-
- return Result;
+ public static string Process(string Text)
+ {
+ Managed = true;
+ IntPtr Ptr = Marshal.StringToHGlobalAuto(Text);
+ IntPtr New = ProcessReal(Ptr);
+ if (New == Ptr)
+ return Text;
+ Text = Marshal.PtrToStringAuto(New);
+ Marshal.FreeHGlobal(Ptr);
+ Marshal.FreeHGlobal(New);
+ return Text;
}
-
public static char ProcessManaged(char Char) {
Managed = true;
IntPtr Result = ProcessReal(new IntPtr(Char));
diff --git a/SRL/Output.cs b/SRL/Output.cs
index 6b89155..1ef3e07 100644
--- a/SRL/Output.cs
+++ b/SRL/Output.cs
@@ -261,36 +261,26 @@ internal static bool PECSVal(byte[] Data) {
return true;
}
- internal static void Error(string Message, params object[] Format) {
- if (LiteMode)
- return;
-
- bool BakLogFile = LogFile;
- LogFile = true;
- ConsoleColor Color = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Red;
- Log(Message, false, Format);
- Console.ForegroundColor = Color;
- LogFile = BakLogFile;
- }
- internal static void Warning(string Message, params object[] Format) {
- if (LiteMode)
- return;
-
- bool BakLogFile = LogFile;
- LogFile = true & Debugging;
- ConsoleColor Color = Console.ForegroundColor;
- Console.ForegroundColor = ConsoleColor.Yellow;
- Log(Message, true, Format);
- Console.ForegroundColor = Color;
- LogFile = BakLogFile;
- }
+ internal static void Error(string Message, params object[] Format) =>
+ Log(ConsoleColor.Red, Message, false, Format);
+ internal static void Warning(string Message, params object[] Format) =>
+ Log(ConsoleColor.Yellow, Message, true, Format);
internal static void Log(ConsoleColor Color, string Message, bool Optional = false, params object[] Format)
{
if (LiteMode)
return;
+ if (!ConsoleShowed)
+ {
+ Log("", true);
+
+ if (ConsoleShowed)
+ Console.Clear();
+ else
+ return;
+ }
+
bool BakLogFile = LogFile;
LogFile = true & Debugging;
ConsoleColor ColorBack = Console.ForegroundColor;
diff --git a/SRL/Reloader.cs b/SRL/Reloader.cs
index d905992..bb47429 100644
--- a/SRL/Reloader.cs
+++ b/SRL/Reloader.cs
@@ -271,14 +271,13 @@ internal static void Init() {
}
CheckArguments();
- LoadConfig();
-
if (Debugging)
{
Log(ConsoleColor.Green, "Strings Reloads - v" + SRLVersion, true);
Log(ConsoleColor.Green, "Soft-Translation Engine - By Marcussacana", true);
Log(ConsoleColor.Green, "Debug Mode Enabled...", true);
}
+ LoadConfig();
if (!DirectRequested)
Warning("You are using SRL through the old function, it is recommended to use GetDirectProcess");
diff --git a/SRL/SRL.csproj b/SRL/SRL.csproj
index e695b0d..15f2495 100644
--- a/SRL/SRL.csproj
+++ b/SRL/SRL.csproj
@@ -67,8 +67,8 @@
-
+
diff --git a/SRL/SRL.ini b/SRL/SRL.ini
index 2164d0f..ee9d7c6 100644
--- a/SRL/SRL.ini
+++ b/SRL/SRL.ini
@@ -80,6 +80,7 @@ MoveWindow=false
[Hook]
CreateFile=false
+ImportHook=true
UndoChars=true
MultiByteToWideChar=false
SetWindowText=false
diff --git a/SRL/Types.cs b/SRL/Types.cs
index 3863aee..97b9be8 100644
--- a/SRL/Types.cs
+++ b/SRL/Types.cs
@@ -343,6 +343,8 @@ internal struct HookSettings {
[FieldParmaters(Name = "SendMessage", DefaultValue = false)]
public bool SendMessage;
#endif
+ [FieldParmaters(Name = "ImportHook", DefaultValue = false)]
+ public bool ImportHook;
[FieldParmaters(Name = "CreateFile", DefaultValue = false)]
public bool CreateFile;
[FieldParmaters(Name = "MultiByteToWideChar", DefaultValue = false)]
diff --git a/SRL/Variables.cs b/SRL/Variables.cs
index f746171..fa60078 100644
--- a/SRL/Variables.cs
+++ b/SRL/Variables.cs
@@ -133,6 +133,7 @@ struct Range {
static bool HookCreateWindowEx;
static bool HookSendMessage;
#endif
+ static bool ImportHook;
static bool HookCreateFile;
static bool HookMultiByteToWideChar;
static bool HookSetWindowText;