2016-08-16 82 views
1

我試圖掛鉤StartDocW通過mhook截獲打印。我使用AppInit_DLLs來加載我的庫。通過mook的Winapi掛鉤導致程序崩潰或掛起

DLL的代碼很簡單:

#include <windows.h> 
#include "mhook/mhook-lib/mhook.h" 
using StartDocPtr = int(*)(HDC, const DOCINFO*); 
StartDocPtr orig; 

int HookedStartDocW(HDC hdc, const DOCINFO* lpdi) { 
    return orig(hdc, lpdi); 
} 

BOOL WINAPI DllMain(__in HINSTANCE, __in DWORD Reason, __in LPVOID) { 
    orig = (StartDocPtr)GetProcAddress(GetModuleHandle("gdi32"), "StartDocW"); 
    switch (Reason) 
    { 
    case DLL_PROCESS_ATTACH: 
     Mhook_SetHook((PVOID*)&orig, &HookedStartDocW); 
     break; 
    case DLL_PROCESS_DETACH: 
     Mhook_Unhook((PVOID*)&orig); 
     break; 
    } 
} 

掛鉤工作和打印完成確定。但是,如果我將HookStartDocW更改爲以下內容:

int HookedStartDocW(HDC hdc, const DOCINFO* lpdi) { 
    char buf[40]; 
    GetModuleFileName(NULL, buf, 40); 
    return orig(hdc, lpdi); 
} 

打印程序將立即崩潰。即使我只是離開char buf[40]和評論GetModuleHandle - 程序將掛起。這是爲什麼發生?如果程序崩潰\掛在打印上(如果我添加除return orig(hdc, lpdi)之外的任何東西) - PC開始行爲非常怪異,拒絕運行程序等等。如果我重新啓動它 - Windows只是無休止地在啓動屏幕上旋轉,只有將它恢復生活的方法 - 是通過liveCD啓動並重命名\刪除我的鉤子DLL。

打印程序:Excel 2016,記事本。

編譯器 - MSVC 2015,x64發佈DLL編譯,使用MBCS而不是unicode。

+0

你忽略了從'StartDocW'簽名'WINAPI'調用約定(無論是在其更換,並指向舊功能的typedef) ,所以堆棧正在被消除。 –

回答

2

您的掛鉤聲明爲錯誤。

看的StartDocW()實際申報Wingdi.h

__gdi_entry WINGDIAPI int WINAPI StartDocW(__in HDC hdc, __in CONST DOCINFOW *lpdi); 

可以忽略__gdi_entryWINGDIAPI只需解析爲__declspec(dllimport)。這個聲明中重要的是WINAPI

幾乎所有 Win32 API函數StartDocW()使用__stdcall調用約定。 WINAPI宏解析爲__stdcall

您的代碼根本沒有指定任何調用約定,因此它使用您的編譯器的默認值,通常是__cdecl。所以你對調用堆棧管理不善。這就是爲什麼你的代碼崩潰。

如果您應該使用DOCINFOW,您也正在使用DOCINFO。在你的代碼中清楚你正在編譯MBCS而不是UNICODE,所以DOCINFO映射到DOCINFOA。您無法將DOCINFOA傳遞給StartDocW(),而是預計會有DOCINFOW

你需要修復你的聲明,如:

#include <windows.h> 
#include "mhook/mhook-lib/mhook.h" 

using StartDocPtr = int (WINAPI *)(HDC, const DOCINFOW*); 
StartDocPtr orig = nullptr; 

int WINAPI HookedStartDocW(HDC hdc, const DOCINFOW* lpdi) { 
    //... 
    return orig(hdc, lpdi); 
} 

BOOL WINAPI DllMain(__in HINSTANCE, __in DWORD Reason, __in LPVOID) { 
    orig = (StartDocPtr) GetProcAddress(GetModuleHandle(TEXT("gdi32")), "StartDocW"); 
    switch (Reason) 
    { 
    case DLL_PROCESS_ATTACH: 
     Mhook_SetHook((PVOID*)&orig, &HookedStartDocW); 
     break; 
    case DLL_PROCESS_DETACH: 
     Mhook_Unhook((PVOID*)&orig); 
     break; 
    } 
} 
+0

我最初也假定調用約定不匹配。但OP正在編譯x64代碼。我錯過了什麼? – IInspectable

+0

@IInspectable仍然存在'DOCINFO'不匹配 –