我有一个在程序工作期间动态加载的DLL(特别是:mIRC的DLL插件)。加载DLL后,我将程序的窗口和编辑框子类化,以捕获一些消息:
LRESULT CALLBACK ChatWndProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK EditBoxProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
...
//wndMirc and channelEditBox acquired elsewhere
SetWindowSubclass(channelEditBox, EditBoxProc, EditBoxProcId, nullptr);
SetWindowSubclass(wndMirc, ChatWndProc, ChannelWndProcId, nullptr);
在DLL卸载时,我删除了子类:
RemoveWindowSubclass(wndMirc, ChatWndProc, ChannelWndProcId);
RemoveWindowSubclass(channelEditBox, EditBoxProc, EditBoxProcId);
之后,程序完全崩溃,除了调试器Exception thrown at 0x0FAA3559 in mIRC.exe: 0xC0000005: Access violation executing location 0x0FAA3559.
但是,如果我没有继承窗口,只有编辑框,一切都很好(除了我不能截取窗口的消息)。在这两种情况下GetLastError
都没有表明任何问题。
我已经读过你的程序并不拥有的子类化窗口并不是一个好主意,但是有了钩子我会得到更多更丑陋的代码+我无法拦截某些消息(比如编辑框中的WM_KEYDOWN)。任何帮助表示赞赏。
编辑:澄清事情,卸载分两个阶段进行:首先从mIRC内部int __stdcall UnloadDll(int isTimeout)
调用,我删除子类;然后使用BOOL APIENTRY DllMain(HMODULE hDllHandle, DWORD dwReason, LPVOID lpReserved)
调用dwReason==DLL_PROCESS_DETACH
- 在第二阶段之后,程序崩溃。
编辑2:崩溃现场的堆栈跟踪:
0f7e3559() Unknown
[Frames below may be incorrect and/or missing]
comctl32.dll!71f1f5ee() Unknown
user32.dll!752871be() Unknown
user32.dll!75286238() Unknown
user32.dll!752868ea() Unknown
user32.dll!752878b0() Unknown
user32.dll!75287d31() Unknown
user32.dll!75287dfa() Unknown
mIRC.exe!01107f9f() Unknown
mIRC.exe!0110e0e9() Unknown
mIRC.exe!011eec7c() Unknown
kernel32.dll!759d33aa() Unknown
ntdll.dll!77049f72() Unknown
ntdll.dll!77049f45() Unknown