diff --git a/src/directinput.c b/src/directinput.c
index 6dd5e5e..13d06b8 100644
--- a/src/directinput.c
+++ b/src/directinput.c
@@ -19,10 +19,15 @@ DIRECTINPUTCREATEEXPROC real_DirectInputCreateEx;
 DIRECTINPUT8CREATEPROC real_DirectInput8Create;
 
 static DICREATEDEVICEPROC real_di_CreateDevice;
+static PROC* di_CreateDevice_vtbl_addr;
 static DICREATEDEVICEEXPROC real_di_CreateDeviceEx;
+static PROC* di_CreateDeviceEx_vtbl_addr;
 static DIDSETCOOPERATIVELEVELPROC real_did_SetCooperativeLevel;
+static PROC* did_SetCooperativeLevel_vtbl_addr;
 static DIDGETDEVICEDATAPROC real_did_GetDeviceData;
+static PROC* did_GetDeviceData_vtbl_addr;
 static DIDGETDEVICESTATEPROC real_did_GetDeviceState;
+static PROC* did_GetDeviceState_vtbl_addr;
 static LPDIRECTINPUTDEVICEA g_mouse_device;
 
 static PROC hook_func(PROC* org_func, PROC new_func)
@@ -121,17 +126,20 @@ static HRESULT WINAPI fake_di_CreateDevice(
 
         if (!real_did_SetCooperativeLevel)
         {
+            did_SetCooperativeLevel_vtbl_addr = (PROC*)&(*lplpDIDevice)->lpVtbl->SetCooperativeLevel;
+
             real_did_SetCooperativeLevel =
-                (DIDSETCOOPERATIVELEVELPROC)hook_func(
-                    (PROC*)&(*lplpDIDevice)->lpVtbl->SetCooperativeLevel, (PROC)fake_did_SetCooperativeLevel);
+                (DIDSETCOOPERATIVELEVELPROC)hook_func(did_SetCooperativeLevel_vtbl_addr, (PROC)fake_did_SetCooperativeLevel);
+
+            did_GetDeviceData_vtbl_addr = (PROC*)&(*lplpDIDevice)->lpVtbl->GetDeviceData;
 
             real_did_GetDeviceData =
-                (DIDGETDEVICEDATAPROC)hook_func(
-                    (PROC*)&(*lplpDIDevice)->lpVtbl->GetDeviceData, (PROC)fake_did_GetDeviceData);
+                (DIDGETDEVICEDATAPROC)hook_func(did_GetDeviceData_vtbl_addr, (PROC)fake_did_GetDeviceData);
+
+            did_GetDeviceState_vtbl_addr = (PROC*)&(*lplpDIDevice)->lpVtbl->GetDeviceState;
 
             real_did_GetDeviceState =
-                (DIDGETDEVICESTATEPROC)hook_func(
-                    (PROC*)&(*lplpDIDevice)->lpVtbl->GetDeviceState, (PROC)fake_did_GetDeviceState);
+                (DIDGETDEVICESTATEPROC)hook_func(did_GetDeviceState_vtbl_addr, (PROC)fake_did_GetDeviceState);
         }
     }
 
@@ -158,17 +166,20 @@ static HRESULT WINAPI fake_di_CreateDeviceEx(
 
         if (!real_did_SetCooperativeLevel)
         {
+            did_SetCooperativeLevel_vtbl_addr = (PROC*)&(*lplpDIDevice)->lpVtbl->SetCooperativeLevel;
+
             real_did_SetCooperativeLevel =
-                (DIDSETCOOPERATIVELEVELPROC)hook_func(
-                    (PROC*)&(*lplpDIDevice)->lpVtbl->SetCooperativeLevel, (PROC)fake_did_SetCooperativeLevel);
+                (DIDSETCOOPERATIVELEVELPROC)hook_func(did_SetCooperativeLevel_vtbl_addr, (PROC)fake_did_SetCooperativeLevel);
+
+            did_GetDeviceData_vtbl_addr = (PROC*)&(*lplpDIDevice)->lpVtbl->GetDeviceData;
 
             real_did_GetDeviceData =
-                (DIDGETDEVICEDATAPROC)hook_func(
-                    (PROC*)&(*lplpDIDevice)->lpVtbl->GetDeviceData, (PROC)fake_did_GetDeviceData);
+                (DIDGETDEVICEDATAPROC)hook_func(did_GetDeviceData_vtbl_addr, (PROC)fake_did_GetDeviceData);
+
+            did_GetDeviceState_vtbl_addr = (PROC*)&(*lplpDIDevice)->lpVtbl->GetDeviceState;
 
             real_did_GetDeviceState =
-                (DIDGETDEVICESTATEPROC)hook_func(
-                    (PROC*)&(*lplpDIDevice)->lpVtbl->GetDeviceState, (PROC)fake_did_GetDeviceState);
+                (DIDGETDEVICESTATEPROC)hook_func(did_GetDeviceState_vtbl_addr, (PROC)fake_did_GetDeviceState);
         }
     }
 
@@ -186,7 +197,7 @@ HRESULT WINAPI fake_DirectInputCreateA(
     if (!real_DirectInputCreateA)
     {
         real_DirectInputCreateA =
-            (DIRECTINPUTCREATEAPROC)real_GetProcAddress(GetModuleHandle("dinput.dll"), "DirectInputCreateA");
+            (DIRECTINPUTCREATEAPROC)real_GetProcAddress(real_LoadLibraryA("dinput.dll"), "DirectInputCreateA");
 
         if (real_DirectInputCreateA == fake_DirectInputCreateA)
         {
@@ -204,8 +215,10 @@ HRESULT WINAPI fake_DirectInputCreateA(
 
     if (SUCCEEDED(result) && !real_di_CreateDevice && !g_config.no_dinput_hook)
     {
+        di_CreateDevice_vtbl_addr = (PROC*)&(*lplpDirectInput)->lpVtbl->CreateDevice;
+
         real_di_CreateDevice =
-            (DICREATEDEVICEPROC)hook_func((PROC*)&(*lplpDirectInput)->lpVtbl->CreateDevice, (PROC)fake_di_CreateDevice);
+            (DICREATEDEVICEPROC)hook_func(di_CreateDevice_vtbl_addr, (PROC)fake_di_CreateDevice);
     }
 
     return result;
@@ -222,7 +235,7 @@ HRESULT WINAPI fake_DirectInputCreateW(
     if (!real_DirectInputCreateW)
     {
         real_DirectInputCreateW =
-            (DIRECTINPUTCREATEWPROC)real_GetProcAddress(GetModuleHandle("dinput.dll"), "DirectInputCreateW");
+            (DIRECTINPUTCREATEWPROC)real_GetProcAddress(real_LoadLibraryA("dinput.dll"), "DirectInputCreateW");
 
         if (real_DirectInputCreateW == fake_DirectInputCreateW)
         {
@@ -240,8 +253,10 @@ HRESULT WINAPI fake_DirectInputCreateW(
 
     if (SUCCEEDED(result) && !real_di_CreateDevice && !g_config.no_dinput_hook)
     {
+        di_CreateDevice_vtbl_addr = (PROC*)&(*lplpDirectInput)->lpVtbl->CreateDevice;
+
         real_di_CreateDevice =
-            (DICREATEDEVICEPROC)hook_func((PROC*)&(*lplpDirectInput)->lpVtbl->CreateDevice, (PROC)fake_di_CreateDevice);
+            (DICREATEDEVICEPROC)hook_func(di_CreateDevice_vtbl_addr, (PROC)fake_di_CreateDevice);
     }
 
     return result;
@@ -259,7 +274,7 @@ HRESULT WINAPI fake_DirectInputCreateEx(
     if (!real_DirectInputCreateEx)
     {
         real_DirectInputCreateEx =
-            (DIRECTINPUTCREATEEXPROC)real_GetProcAddress(GetModuleHandle("dinput.dll"), "DirectInputCreateEx");
+            (DIRECTINPUTCREATEEXPROC)real_GetProcAddress(real_LoadLibraryA("dinput.dll"), "DirectInputCreateEx");
 
         if (real_DirectInputCreateEx == fake_DirectInputCreateEx)
         {
@@ -277,8 +292,10 @@ HRESULT WINAPI fake_DirectInputCreateEx(
 
     if (SUCCEEDED(result) && !real_di_CreateDevice && !g_config.no_dinput_hook)
     {
+        di_CreateDevice_vtbl_addr = (PROC*)&(*ppvOut)->lpVtbl->CreateDevice;
+
         real_di_CreateDevice =
-            (DICREATEDEVICEPROC)hook_func((PROC*)&(*ppvOut)->lpVtbl->CreateDevice, (PROC)fake_di_CreateDevice);
+            (DICREATEDEVICEPROC)hook_func(di_CreateDevice_vtbl_addr, (PROC)fake_di_CreateDevice);
     }
 
     if (SUCCEEDED(result) &&
@@ -287,8 +304,10 @@ HRESULT WINAPI fake_DirectInputCreateEx(
         (IsEqualGUID(&IID_IDirectInput7A, riidltf) || IsEqualGUID(&IID_IDirectInput7W, riidltf)) 
         && !g_config.no_dinput_hook)
     {
+        di_CreateDeviceEx_vtbl_addr = (PROC*)&(*ppvOut)->lpVtbl->CreateDeviceEx;
+
         real_di_CreateDeviceEx =
-            (DICREATEDEVICEEXPROC)hook_func((PROC*)&(*ppvOut)->lpVtbl->CreateDeviceEx, (PROC)fake_di_CreateDeviceEx);
+            (DICREATEDEVICEEXPROC)hook_func(di_CreateDeviceEx_vtbl_addr, (PROC)fake_di_CreateDeviceEx);
     }
 
     return result;
@@ -306,7 +325,7 @@ HRESULT WINAPI fake_DirectInput8Create(
     if (!real_DirectInput8Create)
     {
         real_DirectInput8Create =
-            (DIRECTINPUT8CREATEPROC)real_GetProcAddress(GetModuleHandle("dinput8.dll"), "DirectInput8Create");
+            (DIRECTINPUT8CREATEPROC)real_GetProcAddress(real_LoadLibraryA("dinput8.dll"), "DirectInput8Create");
 
         if (real_DirectInput8Create == fake_DirectInput8Create)
         {
@@ -324,8 +343,10 @@ HRESULT WINAPI fake_DirectInput8Create(
 
     if (SUCCEEDED(result) && !real_di_CreateDevice && !g_config.no_dinput_hook)
     {
+        di_CreateDevice_vtbl_addr = (PROC*)&(*ppvOut)->lpVtbl->CreateDevice;
+
         real_di_CreateDevice =
-            (DICREATEDEVICEPROC)hook_func((PROC*)&(*ppvOut)->lpVtbl->CreateDevice, (PROC)fake_di_CreateDevice);
+            (DICREATEDEVICEPROC)hook_func(di_CreateDevice_vtbl_addr, (PROC)fake_di_CreateDevice);
     }
 
     return result;
@@ -383,6 +404,31 @@ void dinput_hook_init()
 
 void dinput_hook_exit()
 {
+    if (di_CreateDevice_vtbl_addr && *di_CreateDevice_vtbl_addr == (PROC)fake_di_CreateDevice)
+    {
+        hook_func(di_CreateDevice_vtbl_addr, (PROC)real_di_CreateDevice);
+    }
+
+    if (di_CreateDeviceEx_vtbl_addr && *di_CreateDeviceEx_vtbl_addr == (PROC)fake_di_CreateDeviceEx)
+    {
+        hook_func(di_CreateDeviceEx_vtbl_addr, (PROC)real_di_CreateDeviceEx);
+    }
+
+    if (did_SetCooperativeLevel_vtbl_addr && *did_SetCooperativeLevel_vtbl_addr == (PROC)fake_did_SetCooperativeLevel)
+    {
+        hook_func(did_SetCooperativeLevel_vtbl_addr, (PROC)real_did_SetCooperativeLevel);
+    }
+
+    if (did_GetDeviceData_vtbl_addr && *did_GetDeviceData_vtbl_addr == (PROC)fake_did_GetDeviceData)
+    {
+        hook_func(did_GetDeviceData_vtbl_addr, (PROC)real_did_GetDeviceData);
+    }
+
+    if (did_GetDeviceState_vtbl_addr && *did_GetDeviceState_vtbl_addr == (PROC)fake_did_GetDeviceState)
+    {
+        hook_func(did_GetDeviceState_vtbl_addr, (PROC)real_did_GetDeviceState);
+    }
+
 #ifdef _MSC_VER
     if (g_dinput_hook_active)
     {