diff --git a/Makefile b/Makefile
index baab3fa..99e6501 100644
--- a/Makefile
+++ b/Makefile
@@ -16,6 +16,7 @@ FILES = src/debug.c \
         src/settings.c \
         src/lodepng.c \
         src/dinput.c \
+        src/hook.c \
         src/opengl.c
 
 all:
diff --git a/cnc-ddraw.vcxproj b/cnc-ddraw.vcxproj
index e4f75cd..39864d4 100644
--- a/cnc-ddraw.vcxproj
+++ b/cnc-ddraw.vcxproj
@@ -14,6 +14,7 @@
     <ClCompile Include="src\clipper.c" />
     <ClCompile Include="src\debug.c" />
     <ClCompile Include="src\dinput.c" />
+    <ClCompile Include="src\hook.c" />
     <ClCompile Include="src\lodepng.c" />
     <ClCompile Include="src\main.c" />
     <ClCompile Include="src\mouse.c" />
@@ -29,8 +30,10 @@
   <ItemGroup>
     <ClInclude Include="inc\clipper.h" />
     <ClInclude Include="inc\glcorearb.h" />
+    <ClInclude Include="inc\hook.h" />
     <ClInclude Include="inc\KHR\khrplatform.h" />
     <ClInclude Include="inc\lodepng.h" />
+    <ClInclude Include="inc\mouse.h" />
     <ClInclude Include="inc\render_d3d9.h" />
     <ClInclude Include="inc\ddraw.h" />
     <ClInclude Include="inc\debug.h" />
diff --git a/cnc-ddraw.vcxproj.filters b/cnc-ddraw.vcxproj.filters
index 810b4c8..2423530 100644
--- a/cnc-ddraw.vcxproj.filters
+++ b/cnc-ddraw.vcxproj.filters
@@ -57,6 +57,9 @@
     <ClCompile Include="src\dinput.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="src\hook.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="inc\clipper.h">
@@ -101,6 +104,12 @@
     <ClInclude Include="inc\scale_pattern.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="inc\mouse.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="inc\hook.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="ddraw.rc">
diff --git a/inc/hook.h b/inc/hook.h
new file mode 100644
index 0000000..e4251e1
--- /dev/null
+++ b/inc/hook.h
@@ -0,0 +1,51 @@
+#ifndef HOOK_H
+#define HOOK_H
+
+#include <windows.h>
+
+typedef HFONT(__stdcall* CREATEFONTINDIRECTA)(CONST LOGFONT*);
+
+typedef BOOL (WINAPI* GETCURSORPOSPROC)(LPPOINT);
+typedef BOOL(WINAPI* CLIPCURSORPROC)(const RECT*);
+typedef int (WINAPI* SHOWCURSORPROC)(BOOL);
+typedef HCURSOR (WINAPI* SETCURSORPROC)(HCURSOR);
+typedef BOOL (WINAPI* GETWINDOWRECTPROC)(HWND, LPRECT);
+typedef BOOL (WINAPI* GETCLIENTRECTPROC)(HWND, LPRECT);
+typedef BOOL (WINAPI* CLIENTTOSCREENPROC)(HWND, LPPOINT);
+typedef BOOL (WINAPI* SCREENTOCLIENTPROC)(HWND, LPPOINT);
+typedef BOOL (WINAPI* SETCURSORPOSPROC)(int, int);
+typedef HWND (WINAPI* WINDOWFROMPOINTPROC)(POINT);
+typedef BOOL (WINAPI* GETCLIPCURSORPROC)(LPRECT);
+typedef BOOL (WINAPI* GETCURSORINFOPROC)(PCURSORINFO);
+typedef int (WINAPI* GETSYSTEMMETRICSPROC)(int);
+typedef BOOL (WINAPI* SETWINDOWPOSPROC)(HWND, HWND, int, int, int, int, UINT);
+typedef BOOL (WINAPI* MOVEWINDOWPROC)(HWND, int, int, int, int, BOOL);
+typedef LRESULT (WINAPI* SENDMESSAGEAPROC)(HWND, UINT, WPARAM, LPARAM);
+typedef LONG (WINAPI* SETWINDOWLONGAPROC)(HWND, int, LONG);
+
+extern GETCURSORPOSPROC real_GetCursorPos;
+extern CLIPCURSORPROC real_ClipCursor;
+extern SHOWCURSORPROC real_ShowCursor;
+extern SETCURSORPROC real_SetCursor;
+extern GETWINDOWRECTPROC real_GetWindowRect;
+extern GETCLIENTRECTPROC real_GetClientRect;
+extern CLIENTTOSCREENPROC real_ClientToScreen;
+extern SCREENTOCLIENTPROC real_ScreenToClient;
+extern SETCURSORPOSPROC real_SetCursorPos;
+extern WINDOWFROMPOINTPROC real_WindowFromPoint;
+extern GETCLIPCURSORPROC real_GetClipCursor;
+extern GETCURSORINFOPROC real_GetCursorInfo;
+extern GETSYSTEMMETRICSPROC real_GetSystemMetrics;
+extern SETWINDOWPOSPROC real_SetWindowPos;
+extern MOVEWINDOWPROC real_MoveWindow;
+extern SENDMESSAGEAPROC real_SendMessageA;
+extern SETWINDOWLONGAPROC real_SetWindowLongA;
+
+extern BOOL Hook_Active;
+
+void Hook_Init();
+void Hook_PatchIAT(HMODULE hMod, char *moduleName, char *functionName, PROC newFunction);
+PROC Hook_HotPatch(PROC function, PROC newFunction);
+void Hook_TryHotPatch(HMODULE hMod, char *moduleName, char *functionName, PROC newFunction, PROC *function);
+
+#endif
diff --git a/inc/main.h b/inc/main.h
index c6248a9..e3551ee 100644
--- a/inc/main.h
+++ b/inc/main.h
@@ -127,6 +127,7 @@ typedef struct IDirectDrawImpl
     BOOL accurateTimers;
     int bnetHack;
     BOOL bnetActive;
+    BOOL hotPatch;
     SpeedLimiter ticksLimiter;
     SpeedLimiter flipLimiter;
     SpeedLimiter fpsLimiter;
diff --git a/inc/mouse.h b/inc/mouse.h
new file mode 100644
index 0000000..dd18506
--- /dev/null
+++ b/inc/mouse.h
@@ -0,0 +1,27 @@
+#ifndef MOUSE_H
+#define MOUSE_H
+
+#include <windows.h>
+
+void mouse_lock();
+void mouse_unlock();
+
+BOOL WINAPI fake_GetCursorPos(LPPOINT lpPoint);
+BOOL WINAPI fake_ClipCursor(const RECT *lpRect);
+int WINAPI fake_ShowCursor(BOOL bShow);
+HCURSOR WINAPI fake_SetCursor(HCURSOR hCursor);
+BOOL WINAPI fake_GetWindowRect(HWND hWnd, LPRECT lpRect);
+BOOL WINAPI fake_GetClientRect(HWND hWnd, LPRECT lpRect);
+BOOL WINAPI fake_ClientToScreen(HWND hWnd, LPPOINT lpPoint);
+BOOL WINAPI fake_ScreenToClient(HWND hWnd, LPPOINT lpPoint);
+BOOL WINAPI fake_SetCursorPos(int X, int Y);
+HWND WINAPI fake_WindowFromPoint(POINT Point);
+BOOL WINAPI fake_GetClipCursor(LPRECT lpRect);
+BOOL WINAPI fake_GetCursorInfo(PCURSORINFO pci);
+int WINAPI fake_GetSystemMetrics(int nIndex);
+BOOL WINAPI fake_SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags);
+BOOL WINAPI fake_MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint);
+LRESULT WINAPI fake_SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+LONG WINAPI fake_SetWindowLongA(HWND hWnd, int nIndex, LONG dwNewLong);
+
+#endif
diff --git a/src/dinput.c b/src/dinput.c
index 5185c53..75579e6 100644
--- a/src/dinput.c
+++ b/src/dinput.c
@@ -1,7 +1,6 @@
 #include <windows.h>
 #include <dinput.h>
-
-void HookIAT(HMODULE hMod, char *moduleName, char *functionName, PROC newFunction);
+#include "hook.h"
 
 typedef HRESULT (WINAPI *DInputCreateA)(HINSTANCE, DWORD, LPDIRECTINPUTA*, LPUNKNOWN);
 typedef HRESULT (WINAPI *DICreateDevice)(IDirectInputA*, REFGUID, LPDIRECTINPUTDEVICEA *, LPUNKNOWN);
@@ -64,5 +63,5 @@ static HRESULT WINAPI fake_DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion,
 
 void dinput_init()
 {
-    HookIAT(GetModuleHandle(NULL), "dinput.dll", "DirectInputCreateA", (PROC)fake_DirectInputCreateA);
+    Hook_PatchIAT(GetModuleHandle(NULL), "dinput.dll", "DirectInputCreateA", (PROC)fake_DirectInputCreateA);
 }
diff --git a/src/hook.c b/src/hook.c
new file mode 100644
index 0000000..d85febe
--- /dev/null
+++ b/src/hook.c
@@ -0,0 +1,190 @@
+#include <windows.h>
+#include <stdio.h>
+#include "main.h"
+#include "mouse.h"
+#include "hook.h"
+
+BOOL Hook_Active;
+GETCURSORPOSPROC real_GetCursorPos = GetCursorPos;
+CLIPCURSORPROC real_ClipCursor = ClipCursor;
+SHOWCURSORPROC real_ShowCursor = ShowCursor;
+SETCURSORPROC real_SetCursor = SetCursor;
+GETWINDOWRECTPROC real_GetWindowRect = GetWindowRect;
+GETCLIENTRECTPROC real_GetClientRect = GetClientRect;
+CLIENTTOSCREENPROC real_ClientToScreen = ClientToScreen;
+SCREENTOCLIENTPROC real_ScreenToClient = ScreenToClient;
+SETCURSORPOSPROC real_SetCursorPos = SetCursorPos;
+WINDOWFROMPOINTPROC real_WindowFromPoint = WindowFromPoint;
+GETCLIPCURSORPROC real_GetClipCursor = GetClipCursor;
+GETCURSORINFOPROC real_GetCursorInfo = GetCursorInfo;
+GETSYSTEMMETRICSPROC real_GetSystemMetrics = GetSystemMetrics;
+SETWINDOWPOSPROC real_SetWindowPos = SetWindowPos;
+MOVEWINDOWPROC real_MoveWindow = MoveWindow;
+SENDMESSAGEAPROC real_SendMessageA = SendMessageA;
+SETWINDOWLONGAPROC real_SetWindowLongA = SetWindowLongA;
+
+void Hook_PatchIAT(HMODULE hMod, char *moduleName, char *functionName, PROC newFunction)
+{
+    if (!hMod || hMod == INVALID_HANDLE_VALUE || !newFunction)
+        return;
+
+    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hMod;
+    if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
+        return;
+
+    PIMAGE_NT_HEADERS pNTHeaders = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + (DWORD)pDosHeader->e_lfanew);
+    if (pNTHeaders->Signature != IMAGE_NT_SIGNATURE)
+        return;
+
+    PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDosHeader +
+        (DWORD)(pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
+
+    if (pImportDescriptor == (PIMAGE_IMPORT_DESCRIPTOR)pNTHeaders)
+        return;
+
+    while (pImportDescriptor->FirstThunk)
+    {
+        char *impModuleName = (char *)((DWORD)pDosHeader + (DWORD)(pImportDescriptor->Name));
+
+        if (_stricmp(impModuleName, moduleName) == 0)
+        {
+            PIMAGE_THUNK_DATA pFirstThunk = 
+                (PIMAGE_THUNK_DATA)((DWORD)pDosHeader + (DWORD)pImportDescriptor->FirstThunk);
+
+            PIMAGE_THUNK_DATA pOrigFirstThunk = 
+                (PIMAGE_THUNK_DATA)((DWORD)pDosHeader + (DWORD)pImportDescriptor->OriginalFirstThunk);
+
+            while (pFirstThunk->u1.Function && pOrigFirstThunk->u1.AddressOfData)
+            {
+                PIMAGE_IMPORT_BY_NAME pImport = 
+                    (PIMAGE_IMPORT_BY_NAME)((DWORD)pDosHeader + pOrigFirstThunk->u1.AddressOfData);
+
+                if ((pOrigFirstThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) == 0 &&
+                    _stricmp((const char *)pImport->Name, functionName) == 0)
+                {
+                    DWORD oldProtect;
+
+                    if (VirtualProtect(&pFirstThunk->u1.Function, sizeof(DWORD), PAGE_READWRITE, &oldProtect))
+                    {
+                        pFirstThunk->u1.Function = (DWORD)newFunction;
+                        VirtualProtect(&pFirstThunk->u1.Function, sizeof(DWORD), oldProtect, &oldProtect);
+                    }
+
+                    break;
+                }
+
+                pFirstThunk++;
+                pOrigFirstThunk++;
+            }
+        }
+
+        pImportDescriptor++;
+    }
+}
+
+PROC Hook_HotPatch(PROC function, PROC newFunction)
+{
+    PROC result = function;
+
+    unsigned short *bytes = (unsigned short *)function;
+    if (function && *bytes == 0xFF8B) // mov edi, edi
+    {
+        char *address = ((char *)function) - 5;
+        DWORD oldProtect;
+
+        if (VirtualProtect(address, 7, PAGE_EXECUTE_READWRITE, &oldProtect))
+        {
+            if (memcmp(address, (const char[]) { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }, 5) == 0 ||
+                memcmp(address, (const char[]) { 0x90, 0x90, 0x90, 0x90, 0x90 }, 5) == 0)
+            {
+                address[0] = 0xE9; // long jump
+                *((DWORD *)(&address[1])) = ((char *)newFunction) - address - 5;
+                *((WORD *)(&address[5])) = 0xF9EB; // short jump to our long jump
+
+                result = (PROC)(((char *)function) + 2);
+            }
+
+            VirtualProtect(address, 7, oldProtect, &oldProtect);
+        }
+    }
+
+    return result;
+}
+
+void Hook_TryHotPatch(HMODULE hMod, char *moduleName, char *functionName, PROC newFunction, PROC *function)
+{
+    PROC org = GetProcAddress(GetModuleHandle(moduleName), functionName);
+    if (org)
+    {
+        *function = Hook_HotPatch(org, newFunction);
+
+        if (*function == org) // hotpatch failed...
+            Hook_PatchIAT(hMod, moduleName, functionName, newFunction);
+    }
+}
+
+void Hook_Init()
+{
+    if (!Hook_Active)
+    {
+        Hook_Active = TRUE;
+
+        if (ddraw->hotPatch)
+        {
+            Hook_TryHotPatch(
+                GetModuleHandle(NULL), "user32.dll", "GetCursorPos", (PROC)fake_GetCursorPos, (PROC *)&real_GetCursorPos);
+            Hook_TryHotPatch(
+                GetModuleHandle(NULL), "user32.dll", "ClipCursor", (PROC)fake_ClipCursor, (PROC *)&real_ClipCursor);
+            Hook_TryHotPatch(
+                GetModuleHandle(NULL), "user32.dll", "ShowCursor", (PROC)fake_ShowCursor, (PROC *)&real_ShowCursor);
+            Hook_TryHotPatch(
+                GetModuleHandle(NULL), "user32.dll", "SetCursor", (PROC)fake_SetCursor, (PROC *)&real_SetCursor);
+            Hook_TryHotPatch(
+                GetModuleHandle(NULL), "user32.dll", "GetWindowRect", (PROC)fake_GetWindowRect, (PROC *)&real_GetWindowRect);
+            Hook_TryHotPatch(
+                GetModuleHandle(NULL), "user32.dll", "GetClientRect", (PROC)fake_GetClientRect, (PROC *)&real_GetClientRect);
+            Hook_TryHotPatch(
+                GetModuleHandle(NULL), "user32.dll", "ClientToScreen", (PROC)fake_ClientToScreen, (PROC *)&real_ClientToScreen);
+            Hook_TryHotPatch(
+                GetModuleHandle(NULL), "user32.dll", "ScreenToClient", (PROC)fake_ScreenToClient, (PROC *)&real_ScreenToClient);
+            Hook_TryHotPatch(
+                GetModuleHandle(NULL), "user32.dll", "SetCursorPos", (PROC)fake_SetCursorPos, (PROC *)&real_SetCursorPos);
+            Hook_TryHotPatch(
+                GetModuleHandle(NULL), "user32.dll", "GetClipCursor", (PROC)fake_GetClipCursor, (PROC *)&real_GetClipCursor);
+            Hook_TryHotPatch(
+                GetModuleHandle(NULL), "user32.dll", "WindowFromPoint", (PROC)fake_WindowFromPoint, (PROC *)&real_WindowFromPoint);
+            Hook_TryHotPatch(
+                GetModuleHandle(NULL), "user32.dll", "GetCursorInfo", (PROC)fake_GetCursorInfo, (PROC *)&real_GetCursorInfo);
+            Hook_TryHotPatch(
+                GetModuleHandle(NULL), "user32.dll", "GetSystemMetrics", (PROC)fake_GetSystemMetrics, (PROC *)&real_GetSystemMetrics);
+            Hook_TryHotPatch(
+                GetModuleHandle(NULL), "user32.dll", "SetWindowPos", (PROC)fake_SetWindowPos, (PROC *)&real_SetWindowPos);
+            Hook_TryHotPatch(
+                GetModuleHandle(NULL), "user32.dll", "MoveWindow", (PROC)fake_MoveWindow, (PROC *)&real_MoveWindow);
+            Hook_TryHotPatch(
+                GetModuleHandle(NULL), "user32.dll", "SendMessageA", (PROC)fake_SendMessageA, (PROC *)&real_SendMessageA);
+            Hook_TryHotPatch(
+                GetModuleHandle(NULL), "user32.dll", "SetWindowLongA", (PROC)fake_SetWindowLongA, (PROC *)&real_SetWindowLongA);
+        }
+        else
+        {
+            Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "GetCursorPos", (PROC)fake_GetCursorPos);
+            Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "ClipCursor", (PROC)fake_ClipCursor);
+            Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "ShowCursor", (PROC)fake_ShowCursor);
+            Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "SetCursor", (PROC)fake_SetCursor);
+            Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "GetWindowRect", (PROC)fake_GetWindowRect);
+            Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "GetClientRect", (PROC)fake_GetClientRect);
+            Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "ClientToScreen", (PROC)fake_ClientToScreen);
+            Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "ScreenToClient", (PROC)fake_ScreenToClient);
+            Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "SetCursorPos", (PROC)fake_SetCursorPos);
+            Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "GetClipCursor", (PROC)fake_GetClipCursor);
+            Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "WindowFromPoint", (PROC)fake_WindowFromPoint);
+            Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "GetCursorInfo", (PROC)fake_GetCursorInfo);
+            Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "GetSystemMetrics", (PROC)fake_GetSystemMetrics);
+            Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "SetWindowPos", (PROC)fake_SetWindowPos);
+            Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "MoveWindow", (PROC)fake_MoveWindow);
+            Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "SendMessageA", (PROC)fake_SendMessageA);
+            Hook_PatchIAT(GetModuleHandle(NULL), "user32.dll", "SetWindowLongA", (PROC)fake_SetWindowLongA);
+        }
+    }
+}
diff --git a/src/main.c b/src/main.c
index 976a8df..611e120 100644
--- a/src/main.c
+++ b/src/main.c
@@ -27,15 +27,12 @@
 #include "palette.h"
 #include "surface.h"
 #include "clipper.h"
+#include "hook.h"
+#include "mouse.h"
 #include "render_d3d9.h"
 
 #define IDR_MYMENU 93
 
-BOOL WINAPI fake_GetCursorPos(LPPOINT lpPoint);
-void mouse_init();
-void mouse_lock();
-void mouse_unlock();
-
 BOOL screenshot(struct IDirectDrawSurfaceImpl *);
 void Settings_Load();
 void Settings_Save(RECT *lpRect, int windowState);
@@ -115,7 +112,7 @@ BOOL CALLBACK EnumChildProc(HWND hWnd, LPARAM lParam)
     RECT size;
     RECT pos;
 
-    if (GetClientRect(hWnd, &size) && GetWindowRect(hWnd, &pos) && size.right > 1 && size.bottom > 1)
+    if (real_GetClientRect(hWnd, &size) && real_GetWindowRect(hWnd, &pos) && size.right > 1 && size.bottom > 1)
     {
         ChildWindowExists = TRUE;
 
@@ -552,13 +549,13 @@ HRESULT __stdcall ddraw_SetDisplayMode(IDirectDrawImpl *This, DWORD width, DWORD
             return DDERR_UNSUPPORTED;
         }
 
-        const HANDLE hbicon = LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDR_MYMENU), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0);
+        const HANDLE hbicon = LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDR_MYMENU), IMAGE_ICON, real_GetSystemMetrics(SM_CXICON), real_GetSystemMetrics(SM_CYICON), 0);
         if (hbicon)
-            SendMessage(This->hWnd, WM_SETICON, ICON_BIG, (LPARAM)hbicon);
+            real_SendMessageA(This->hWnd, WM_SETICON, ICON_BIG, (LPARAM)hbicon);
 
-        const HANDLE hsicon = LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDR_MYMENU), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);
+        const HANDLE hsicon = LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDR_MYMENU), IMAGE_ICON, real_GetSystemMetrics(SM_CXSMICON), real_GetSystemMetrics(SM_CYSMICON), 0);
         if (hsicon)
-            SendMessage(This->hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hsicon);
+            real_SendMessageA(This->hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hsicon);
     }
 
     if (ddraw->altenter)
@@ -764,23 +761,23 @@ HRESULT __stdcall ddraw_SetDisplayMode(IDirectDrawImpl *This, DWORD width, DWORD
     {
         if (!This->border)
         {
-            SetWindowLong(This->hWnd, GWL_STYLE, GetWindowLong(This->hWnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU));
+            real_SetWindowLongA(This->hWnd, GWL_STYLE, GetWindowLong(This->hWnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU));
         }
         else
         {
-            SetWindowLong(This->hWnd, GWL_STYLE, (GetWindowLong(This->hWnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW) & ~WS_MAXIMIZEBOX);
+            real_SetWindowLongA(This->hWnd, GWL_STYLE, (GetWindowLong(This->hWnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW) & ~WS_MAXIMIZEBOX);
         }
 
         if (ddraw->wine)
-            SetWindowLong(This->hWnd, GWL_STYLE, (GetWindowLong(This->hWnd, GWL_STYLE) | WS_MINIMIZEBOX) & ~(WS_MAXIMIZEBOX | WS_THICKFRAME));
+            real_SetWindowLongA(This->hWnd, GWL_STYLE, (GetWindowLong(This->hWnd, GWL_STYLE) | WS_MINIMIZEBOX) & ~(WS_MAXIMIZEBOX | WS_THICKFRAME));
 
         /* center the window with correct dimensions */
         int x = (WindowRect.left != -32000) ? WindowRect.left : (This->mode.dmPelsWidth / 2) - (This->render.width / 2);
         int y = (WindowRect.top != -32000) ? WindowRect.top : (This->mode.dmPelsHeight / 2) - (This->render.height / 2);
         RECT dst = { x, y, This->render.width + x, This->render.height + y };
         AdjustWindowRect(&dst, GetWindowLong(This->hWnd, GWL_STYLE), FALSE);
-        SetWindowPos(ddraw->hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
-        MoveWindow(This->hWnd, dst.left, dst.top, (dst.right - dst.left), (dst.bottom - dst.top), TRUE);
+        real_SetWindowPos(ddraw->hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+        real_MoveWindow(This->hWnd, dst.left, dst.top, (dst.right - dst.left), (dst.bottom - dst.top), TRUE);
 
         if (This->renderer == render_d3d9_main)
             InitDirect3D9();
@@ -800,9 +797,9 @@ HRESULT __stdcall ddraw_SetDisplayMode(IDirectDrawImpl *This, DWORD width, DWORD
         }
 
         if (ddraw->wine)
-            SetWindowLong(This->hWnd, GWL_STYLE, GetWindowLong(This->hWnd, GWL_STYLE) | WS_MINIMIZEBOX);
+            real_SetWindowLongA(This->hWnd, GWL_STYLE, GetWindowLong(This->hWnd, GWL_STYLE) | WS_MINIMIZEBOX);
 
-        SetWindowPos(This->hWnd, HWND_TOPMOST, 0, 0, This->render.width, This->render.height, SWP_SHOWWINDOW);
+        real_SetWindowPos(This->hWnd, HWND_TOPMOST, 0, 0, This->render.width, This->render.height, SWP_SHOWWINDOW);
         LastSetWindowPosTick = timeGetTime();
 
         mouse_lock();
@@ -840,7 +837,7 @@ void ToggleFullscreen()
     {
         mouse_unlock();
         WindowState = ddraw->windowed = FALSE;
-        SetWindowLong(ddraw->hWnd, GWL_STYLE, GetWindowLong(ddraw->hWnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU));
+        real_SetWindowLongA(ddraw->hWnd, GWL_STYLE, GetWindowLong(ddraw->hWnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU));
         ddraw->altenter = TRUE;
         ddraw_SetDisplayMode(ddraw, ddraw->width, ddraw->height, ddraw->bpp);
         mouse_lock();
@@ -951,8 +948,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
             if (!ddraw->windowed)
             {
                 LastSetWindowPosTick = timeGetTime();
-                SetWindowPos(ddraw->hWnd, HWND_TOPMOST, 1, 1, ddraw->render.width, ddraw->render.height, SWP_SHOWWINDOW);
-                SetWindowPos(ddraw->hWnd, HWND_TOPMOST, 0, 0, ddraw->render.width, ddraw->render.height, SWP_SHOWWINDOW);
+                real_SetWindowPos(ddraw->hWnd, HWND_TOPMOST, 1, 1, ddraw->render.width, ddraw->render.height, SWP_SHOWWINDOW);
+                real_SetWindowPos(ddraw->hWnd, HWND_TOPMOST, 0, 0, ddraw->render.width, ddraw->render.height, SWP_SHOWWINDOW);
             }
             return 0;
         }
@@ -1203,13 +1200,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
                     do
                     {
                         RECT rc;
-                        if (GetWindowRect(hWnd, &rc) && rc.bottom - rc.top == 479)
+                        if (real_GetWindowRect(hWnd, &rc) && rc.bottom - rc.top == 479)
                             hideCursor = FALSE;
 
                     } while ((hWnd = FindWindowEx(HWND_DESKTOP, hWnd, "SDlgDialog", NULL)));
 
                     if (hideCursor)
-                        while (ShowCursor(FALSE) > 0);
+                        while (real_ShowCursor(FALSE) > 0);
                 }
 
                 ddraw->bnetActive = !wParam;
@@ -1282,8 +1279,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
         case WM_AUTORENDERER:
         {
             mouse_unlock();
-            SetWindowPos(ddraw->hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
-            SetWindowPos(ddraw->hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+            real_SetWindowPos(ddraw->hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+            real_SetWindowPos(ddraw->hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
             if (!ddraw->wine)
             {
                 ShowWindow(ddraw->hWnd, SW_MINIMIZE);
@@ -1448,11 +1445,11 @@ HRESULT __stdcall ddraw_SetCooperativeLevel(IDirectDrawImpl *This, HWND hWnd, DW
 
     if (!This->WndProc)
     {
-        mouse_init();
+        Hook_Init();
 
         This->WndProc = (LRESULT(CALLBACK *)(HWND, UINT, WPARAM, LPARAM))GetWindowLong(hWnd, GWL_WNDPROC);
 
-        SetWindowLong(This->hWnd, GWL_WNDPROC, (LONG)WndProc);
+        real_SetWindowLongA(This->hWnd, GWL_WNDPROC, (LONG)WndProc);
 
         if (!This->render.hDC)
         {
@@ -1470,11 +1467,11 @@ HRESULT __stdcall ddraw_SetCooperativeLevel(IDirectDrawImpl *This, HWND hWnd, DW
 
         if (ddraw->handlemouse && ddraw->windowed)
         {
-            while (ShowCursor(FALSE) > 0); //workaround for direct input games
-            while (ShowCursor(TRUE) < 0);
+            while (real_ShowCursor(FALSE) > 0); //workaround for direct input games
+            while (real_ShowCursor(TRUE) < 0);
         }
 
-        SetCursor(LoadCursor(NULL, IDC_ARROW));
+        real_SetCursor(LoadCursor(NULL, IDC_ARROW));
 
         GetWindowText(This->hWnd, (LPTSTR)&This->title, sizeof(This->title));
 
@@ -1593,7 +1590,7 @@ ULONG __stdcall ddraw_Release(IDirectDrawImpl *This)
         DeleteCriticalSection(&This->cs);
 
         /* restore old wndproc, subsequent ddraw creation will otherwise fail */
-        SetWindowLong(This->hWnd, GWL_WNDPROC, (LONG)This->WndProc);
+        real_SetWindowLongA(This->hWnd, GWL_WNDPROC, (LONG)This->WndProc);
         HeapFree(GetProcessHeap(), 0, This);
         ddraw = NULL;
         return 0;
diff --git a/src/mouse.c b/src/mouse.c
index f4573fd..d9d19bb 100644
--- a/src/mouse.c
+++ b/src/mouse.c
@@ -14,27 +14,25 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* This is a special mouse coordinate fix for games that use GetCursorPos and expect to be in fullscreen */
-
 #include <windows.h>
 #include <stdio.h>
 #include "main.h"
 #include "surface.h"
+#include "hook.h"
 
-BOOL mouse_active = FALSE;
 int yAdjust = 0;
 
 BOOL WINAPI fake_GetCursorPos(LPPOINT lpPoint)
 {
     POINT pt, realpt;
     
-    if (!GetCursorPos(&pt) || !ddraw)
+    if (!real_GetCursorPos(&pt) || !ddraw)
         return FALSE;
     
     realpt.x = pt.x;
     realpt.y = pt.y;
     
-    if(ddraw->locked && (!ddraw->windowed || ScreenToClient(ddraw->hWnd, &pt)))
+    if(ddraw->locked && (!ddraw->windowed || real_ScreenToClient(ddraw->hWnd, &pt)))
     {
         //fallback solution for possible ClipCursor failure
         int diffx = 0, diffy = 0;
@@ -66,7 +64,7 @@ BOOL WINAPI fake_GetCursorPos(LPPOINT lpPoint)
         }
 
         if (diffx || diffy)
-            SetCursorPos(realpt.x - diffx, realpt.y - diffy);
+            real_SetCursorPos(realpt.x - diffx, realpt.y - diffy);
 
 
         if(ddraw->adjmouse)
@@ -98,7 +96,7 @@ BOOL WINAPI fake_GetCursorPos(LPPOINT lpPoint)
             }
 
             if (diffx || diffy)
-                SetCursorPos(realpt.x - diffx, realpt.y - diffy);
+                real_SetCursorPos(realpt.x - diffx, realpt.y - diffy);
         }
     }
 
@@ -127,7 +125,7 @@ int WINAPI fake_ShowCursor(BOOL bShow)
     static int count;
 
     if (ddraw && !ddraw->handlemouse)
-        return ShowCursor(bShow);
+        return real_ShowCursor(bShow);
 
     return bShow ? ++count : --count;
 }
@@ -135,70 +133,11 @@ int WINAPI fake_ShowCursor(BOOL bShow)
 HCURSOR WINAPI fake_SetCursor(HCURSOR hCursor)
 {
     if (ddraw && !ddraw->handlemouse)
-        return SetCursor(hCursor); 
+        return real_SetCursor(hCursor); 
     
     return NULL;
 }
 
-void HookIAT(HMODULE hMod, char *moduleName, char *functionName, PROC newFunction)
-{
-    if (!hMod || hMod == INVALID_HANDLE_VALUE || !newFunction)
-        return;
-
-    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hMod;
-    if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
-        return;
-
-    PIMAGE_NT_HEADERS pNTHeaders = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + (DWORD)pDosHeader->e_lfanew);
-    if (pNTHeaders->Signature != IMAGE_NT_SIGNATURE)
-        return;
-
-    PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDosHeader +
-        (DWORD)(pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
-
-    if (pImportDescriptor == (PIMAGE_IMPORT_DESCRIPTOR)pNTHeaders)
-        return;
-
-    while (pImportDescriptor->FirstThunk)
-    {
-        char *impModuleName = (char *)((DWORD)pDosHeader + (DWORD)(pImportDescriptor->Name));
-
-        if (_stricmp(impModuleName, moduleName) == 0)
-        {
-            PIMAGE_THUNK_DATA pFirstThunk = 
-                (PIMAGE_THUNK_DATA)((DWORD)pDosHeader + (DWORD)pImportDescriptor->FirstThunk);
-
-            PIMAGE_THUNK_DATA pOrigFirstThunk = 
-                (PIMAGE_THUNK_DATA)((DWORD)pDosHeader + (DWORD)pImportDescriptor->OriginalFirstThunk);
-
-            while (pFirstThunk->u1.Function && pOrigFirstThunk->u1.AddressOfData)
-            {
-                PIMAGE_IMPORT_BY_NAME pImport = 
-                    (PIMAGE_IMPORT_BY_NAME)((DWORD)pDosHeader + pOrigFirstThunk->u1.AddressOfData);
-
-                if ((pOrigFirstThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) == 0 &&
-                    _stricmp((const char *)pImport->Name, functionName) == 0)
-                {
-                    DWORD oldProtect;
-
-                    if (VirtualProtect(&pFirstThunk->u1.Function, sizeof(DWORD), PAGE_READWRITE, &oldProtect))
-                    {
-                        pFirstThunk->u1.Function = (DWORD)newFunction;
-                        VirtualProtect(&pFirstThunk->u1.Function, sizeof(DWORD), oldProtect, &oldProtect);
-                    }
-
-                    break;
-                }
-
-                pFirstThunk++;
-                pOrigFirstThunk++;
-            }
-        }
-
-        pImportDescriptor++;
-    }
-}
-
 void mouse_lock()
 {
     RECT rc;
@@ -206,15 +145,15 @@ void mouse_lock()
     if (ddraw->devmode)
     {
         if (ddraw->handlemouse)
-            while(ShowCursor(FALSE) > 0);
+            while(real_ShowCursor(FALSE) > 0);
 
         return;
     }
 
-    if (mouse_active && !ddraw->locked)
+    if (Hook_Active && !ddraw->locked)
     {
         // Get the window client area.
-        GetClientRect(ddraw->hWnd, &rc);
+        real_GetClientRect(ddraw->hWnd, &rc);
         
         if(ddraw->adjmouse)
         {
@@ -230,8 +169,8 @@ void mouse_lock()
         // Convert the client area to screen coordinates.
         POINT pt = { rc.left, rc.top };
         POINT pt2 = { rc.right, rc.bottom };
-        ClientToScreen(ddraw->hWnd, &pt);
-        ClientToScreen(ddraw->hWnd, &pt2);
+        real_ClientToScreen(ddraw->hWnd, &pt);
+        real_ClientToScreen(ddraw->hWnd, &pt2);
         
         SetRect(&rc, pt.x, pt.y, pt2.x, pt2.y);
         
@@ -239,29 +178,29 @@ void mouse_lock()
 
         if(ddraw->adjmouse)
         {
-            SetCursorPos(
+            real_SetCursorPos(
                 rc.left + (ddraw->cursor.x * ddraw->render.scaleW), 
                 rc.top + ((ddraw->cursor.y - yAdjust) * ddraw->render.scaleH));
         }
         else
         {
-            SetCursorPos(rc.left + ddraw->cursor.x, rc.top + ddraw->cursor.y - yAdjust);
+            real_SetCursorPos(rc.left + ddraw->cursor.x, rc.top + ddraw->cursor.y - yAdjust);
         }
 
         if (ddraw->handlemouse)
         {
             //SetCapture(ddraw->hWnd);
-            ClipCursor(&rc);
-            while (ShowCursor(FALSE) > 0);
+            real_ClipCursor(&rc);
+            while (real_ShowCursor(FALSE) > 0);
         }
         else
         {
             if (ddraw->hidecursor)
             {
                 ddraw->hidecursor = FALSE;
-                ShowCursor(FALSE);
+                real_ShowCursor(FALSE);
             }
-            ClipCursor(&rc);
+            real_ClipCursor(&rc);
         }
 
         ddraw->locked = TRUE;
@@ -275,12 +214,12 @@ void mouse_unlock()
     if (ddraw->devmode)
     {
         if (ddraw->handlemouse)
-            while(ShowCursor(TRUE) < 0);
+            while(real_ShowCursor(TRUE) < 0);
 
         return;
     }
 
-    if(!mouse_active)
+    if(!Hook_Active)
     {
         return;
     }
@@ -290,34 +229,34 @@ void mouse_unlock()
         ddraw->locked = FALSE;
 
         // Get the window client area.
-        GetClientRect(ddraw->hWnd, &rc);
+        real_GetClientRect(ddraw->hWnd, &rc);
         
         // Convert the client area to screen coordinates.
         POINT pt = { rc.left, rc.top };
         POINT pt2 = { rc.right, rc.bottom };
-        ClientToScreen(ddraw->hWnd, &pt);
-        ClientToScreen(ddraw->hWnd, &pt2);
+        real_ClientToScreen(ddraw->hWnd, &pt);
+        real_ClientToScreen(ddraw->hWnd, &pt2);
         SetRect(&rc, pt.x, pt.y, pt2.x, pt2.y);
        
         if (ddraw->handlemouse)
         {
-            while (ShowCursor(TRUE) < 0);
-            SetCursor(LoadCursor(NULL, IDC_ARROW));
+            while (real_ShowCursor(TRUE) < 0);
+            real_SetCursor(LoadCursor(NULL, IDC_ARROW));
         }
         else
         {
             CURSORINFO ci = { .cbSize = sizeof(CURSORINFO) };
-            if (GetCursorInfo(&ci) && ci.flags == 0)
+            if (real_GetCursorInfo(&ci) && ci.flags == 0)
             {
                 ddraw->hidecursor = TRUE;
-                while (ShowCursor(TRUE) < 0);
+                while (real_ShowCursor(TRUE) < 0);
             }
         }
 
-        ClipCursor(NULL);
+        real_ClipCursor(NULL);
         //ReleaseCapture();
         
-        SetCursorPos(
+        real_SetCursorPos(
             rc.left + ddraw->render.viewport.x + (ddraw->cursor.x * ddraw->render.scaleW), 
             rc.top + ddraw->render.viewport.y + ((ddraw->cursor.y + yAdjust) * ddraw->render.scaleH));
     }
@@ -338,11 +277,11 @@ BOOL WINAPI fake_GetWindowRect(HWND hWnd, LPRECT lpRect)
         }
         else
         {
-            return GetWindowRect(hWnd, lpRect) && MapWindowPoints(HWND_DESKTOP, ddraw->hWnd, (LPPOINT)lpRect, 2);
+            return real_GetWindowRect(hWnd, lpRect) && MapWindowPoints(HWND_DESKTOP, ddraw->hWnd, (LPPOINT)lpRect, 2);
         }
     }
 
-    return GetWindowRect(hWnd, lpRect);
+    return real_GetWindowRect(hWnd, lpRect);
 }
 
 BOOL WINAPI fake_GetClientRect(HWND hWnd, LPRECT lpRect)
@@ -357,13 +296,13 @@ BOOL WINAPI fake_GetClientRect(HWND hWnd, LPRECT lpRect)
         return TRUE;
     }
 
-    return GetClientRect(hWnd, lpRect);
+    return real_GetClientRect(hWnd, lpRect);
 }
 
 BOOL WINAPI fake_ClientToScreen(HWND hWnd, LPPOINT lpPoint)
 {
     if (ddraw && ddraw->hWnd != hWnd)
-        return ClientToScreen(hWnd, lpPoint) && ScreenToClient(ddraw->hWnd, lpPoint);
+        return real_ClientToScreen(hWnd, lpPoint) && real_ScreenToClient(ddraw->hWnd, lpPoint);
 
     return TRUE;
 }
@@ -371,7 +310,7 @@ BOOL WINAPI fake_ClientToScreen(HWND hWnd, LPPOINT lpPoint)
 BOOL WINAPI fake_ScreenToClient(HWND hWnd, LPPOINT lpPoint)
 {
     if (ddraw && ddraw->hWnd != hWnd)
-        return ClientToScreen(ddraw->hWnd, lpPoint) && ScreenToClient(hWnd, lpPoint);
+        return real_ClientToScreen(ddraw->hWnd, lpPoint) && real_ScreenToClient(hWnd, lpPoint);
 
     return TRUE;
 }
@@ -379,13 +318,13 @@ BOOL WINAPI fake_ScreenToClient(HWND hWnd, LPPOINT lpPoint)
 BOOL WINAPI fake_SetCursorPos(int X, int Y)
 {
     POINT pt = { X, Y };
-    return ddraw && ClientToScreen(ddraw->hWnd, &pt) && SetCursorPos(pt.x, pt.y);
+    return ddraw && real_ClientToScreen(ddraw->hWnd, &pt) && real_SetCursorPos(pt.x, pt.y);
 }
 
 HWND WINAPI fake_WindowFromPoint(POINT Point)
 {
     POINT pt = { Point.x, Point.y };
-    return ddraw && ClientToScreen(ddraw->hWnd, &pt) ? WindowFromPoint(pt) : NULL;
+    return ddraw && real_ClientToScreen(ddraw->hWnd, &pt) ? real_WindowFromPoint(pt) : NULL;
 }
 
 BOOL WINAPI fake_GetClipCursor(LPRECT lpRect)
@@ -405,7 +344,7 @@ BOOL WINAPI fake_GetClipCursor(LPRECT lpRect)
 
 BOOL WINAPI fake_GetCursorInfo(PCURSORINFO pci)
 {
-    return pci && ddraw && GetCursorInfo(pci) && ScreenToClient(ddraw->hWnd, &pci->ptScreenPos);
+    return pci && ddraw && real_GetCursorInfo(pci) && real_ScreenToClient(ddraw->hWnd, &pci->ptScreenPos);
 }
 
 int WINAPI fake_GetSystemMetrics(int nIndex)
@@ -419,7 +358,7 @@ int WINAPI fake_GetSystemMetrics(int nIndex)
             return ddraw->height;
     }
 
-    return GetSystemMetrics(nIndex);
+    return real_GetSystemMetrics(nIndex);
 }
 
 BOOL WINAPI fake_SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags)
@@ -427,7 +366,7 @@ BOOL WINAPI fake_SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int
     if (ddraw && ddraw->hWnd == hWnd)
         return TRUE;
 
-    return SetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
+    return real_SetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
 }
 
 BOOL WINAPI fake_MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint)
@@ -435,12 +374,12 @@ BOOL WINAPI fake_MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BO
     if (ddraw && ddraw->hWnd == hWnd)
         return TRUE;
 
-    return MoveWindow(hWnd, X, Y, nWidth, nHeight, bRepaint);
+    return real_MoveWindow(hWnd, X, Y, nWidth, nHeight, bRepaint);
 }
 
 LRESULT WINAPI fake_SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
 {
-    LRESULT result = SendMessageA(hWnd, Msg, wParam, lParam);
+    LRESULT result = real_SendMessageA(hWnd, Msg, wParam, lParam);
 
     if (result && ddraw && Msg == CB_GETDROPPEDCONTROLRECT)
     {
@@ -457,27 +396,5 @@ LONG WINAPI fake_SetWindowLongA(HWND hWnd, int nIndex, LONG dwNewLong)
     if (ddraw && ddraw->hWnd == hWnd && nIndex == GWL_STYLE)
         return 0;
 
-    return SetWindowLongA(hWnd, nIndex, dwNewLong);
-}
-
-void mouse_init()
-{
-    HookIAT(GetModuleHandle(NULL), "user32.dll", "GetCursorPos", (PROC)fake_GetCursorPos);
-    HookIAT(GetModuleHandle(NULL), "user32.dll", "ClipCursor", (PROC)fake_ClipCursor);
-    HookIAT(GetModuleHandle(NULL), "user32.dll", "ShowCursor", (PROC)fake_ShowCursor);
-    HookIAT(GetModuleHandle(NULL), "user32.dll", "SetCursor", (PROC)fake_SetCursor);
-    HookIAT(GetModuleHandle(NULL), "user32.dll", "GetWindowRect", (PROC)fake_GetWindowRect);
-    HookIAT(GetModuleHandle(NULL), "user32.dll", "GetClientRect", (PROC)fake_GetClientRect);
-    HookIAT(GetModuleHandle(NULL), "user32.dll", "ClientToScreen", (PROC)fake_ClientToScreen);
-    HookIAT(GetModuleHandle(NULL), "user32.dll", "ScreenToClient", (PROC)fake_ScreenToClient);
-    HookIAT(GetModuleHandle(NULL), "user32.dll", "SetCursorPos", (PROC)fake_SetCursorPos);
-    HookIAT(GetModuleHandle(NULL), "user32.dll", "GetClipCursor", (PROC)fake_GetClipCursor);
-    HookIAT(GetModuleHandle(NULL), "user32.dll", "WindowFromPoint", (PROC)fake_WindowFromPoint);
-    HookIAT(GetModuleHandle(NULL), "user32.dll", "GetCursorInfo", (PROC)fake_GetCursorInfo);
-    HookIAT(GetModuleHandle(NULL), "user32.dll", "GetSystemMetrics", (PROC)fake_GetSystemMetrics);
-    HookIAT(GetModuleHandle(NULL), "user32.dll", "SetWindowPos", (PROC)fake_SetWindowPos);
-    HookIAT(GetModuleHandle(NULL), "user32.dll", "MoveWindow", (PROC)fake_MoveWindow);
-    HookIAT(GetModuleHandle(NULL), "user32.dll", "SendMessageA", (PROC)fake_SendMessageA);
-    HookIAT(GetModuleHandle(NULL), "user32.dll", "SetWindowLongA", (PROC)fake_SetWindowLongA);
-    mouse_active = TRUE;
+    return real_SetWindowLongA(hWnd, nIndex, dwNewLong);
 }
diff --git a/src/settings.c b/src/settings.c
index f76beec..986033a 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -41,6 +41,8 @@ void Settings_Load()
     ddraw->noactivateapp = GetBool("noactivateapp", FALSE);
     ddraw->vhack = GetBool("vhack", FALSE);
     ddraw->accurateTimers = GetBool("accuratetimers", FALSE);
+    ddraw->hotPatch = GetBool("hotPatch", FALSE);
+    ddraw->bnetHack = GetBool("bnetHack", TRUE);
 
     WindowRect.right = GetInt("width", 0);
     WindowRect.bottom = GetInt("height", 0);
@@ -49,8 +51,6 @@ void Settings_Load()
 
     ddraw->render.maxfps = GetInt("maxfps", 125);
 
-    ddraw->bnetHack = GetBool("bnetHack", TRUE);
-
     if (ddraw->accurateTimers || ddraw->vsync)
         ddraw->fpsLimiter.hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
     //can't fully set it up here due to missing ddraw->mode.dmDisplayFrequency
@@ -279,6 +279,10 @@ static void CreateSettingsIni()
             "; Force CPU0 affinity, avoids crashes/freezing, *might* have a performance impact\n"
             "singlecpu=true\n"
             "\n"
+            "; Use hotpatching rather than IAT hooking\n"
+            "; Note: Can be used to fix issues related to new features added by cnc-ddraw such as windowed mode or stretching\n"
+            "hotPatch=false\n"
+            "\n"
             "; Workaround for battle.net on Diablo and Warcraft 2 BNE\n"
             "; Note: This hack as a negative side-effect, you can only play fullscreen with 'renderer=gdi' or via 'fullscreen=true'\n"
             "bnetHack=false\n"
diff --git a/src/surface.c b/src/surface.c
index 7e434ba..5c84db9 100644
--- a/src/surface.c
+++ b/src/surface.c
@@ -18,6 +18,7 @@
 #include <stdio.h>
 
 #include "main.h"
+#include "hook.h"
 #include "surface.h"
 #include "scale_pattern.h"
 
@@ -1008,7 +1009,7 @@ HRESULT __stdcall ddraw_surface_Unlock(IDirectDrawSurfaceImpl *This, LPVOID lpRe
         do
         {
             RECT rc;
-            if (GetWindowRect(hWnd, &rc))
+            if (real_GetWindowRect(hWnd, &rc))
             {
                 if (rc.bottom - rc.top == 479)
                     erase = TRUE;