我正试图通过StartDocW挂钩mhook来拦截打印。我使用AppInit_DLLs来加载我的库。
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;
}
}
Hook工作正常,打印完成。但如果我将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 :(得分:2)
您的挂钩声明错误。
查看StartDocW()
中Wingdi.h
的实际声明:
__gdi_entry WINGDIAPI int WINAPI StartDocW(__in HDC hdc, __in CONST DOCINFOW *lpdi);
您可以忽略__gdi_entry
。 WINGDIAPI
只需解析为__declspec(dllimport)
。本声明中重要的是WINAPI
。
与几乎所有 Win32 API函数一样,StartDocW()
使用__stdcall
调用约定。 WINAPI
宏解析为__stdcall
。
您的代码根本没有指定任何调用约定,因此它使用编译器的默认值,通常是__cdecl
。所以你对调用堆栈管理不善。这就是你的代码崩溃的原因。
当您应该使用DOCINFO
时,您也在使用DOCINFOW
。在您的代码中很明显,您正在为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;
}
}