Код, о котором идет речь, перехватывает файл explorer.exe, но сбой при входе в функцию обратного вызова:
Unhandled exception at 0x60055b50 (redacted.dll) in explorer.exe: 0xC0000005: Access violation writing location 0x548b0cca.
CallStack:
> redacted.dll!myCallWndProcRetCallback(int nCode=0x00000000, unsigned int wParam=0x00000000, long lParam=0x015afa58) Line 799 C++
user32.dll!_DispatchHookW@16() + 0x31 bytes
user32.dll!_fnHkINLPCWPRETSTRUCTW@20() + 0x5e bytes
user32.dll!___fnDWORD@4() + 0x24 bytes
ntdll.dll!_KiUserCallbackDispatcher@12() + 0x13 bytes
user32.dll!_NtUserMessageCall@28() + 0xc bytes
user32.dll!_SendMessageW@16() + 0x49 bytes
explorer.exe!CTaskBand::_FindIndexByHwnd() + 0x21 bytes
explorer.exe!CTaskBand::_HandleShellHook() + 0x48 bytes
explorer.exe!CTaskBand::v_WndProc() + 0x660 bytes
explorer.exe!CImpWndProc::s_WndProc() + 0x3f bytes
Visual Studio 2005 произвела следующую разборку:
--- c:\projects\redacted.cpp -------------------------
//------------------------------------------------------------------------------
LRESULT CALLBACK myCallWndProcRetCallback(int nCode, WPARAM wParam, LPARAM lParam) {
60055B50 inc dword ptr [ebx+548B0CC4h]
60055B56 and al,18h
60055B58 mov eax,dword ptr [g_callWndProcRetHook (600B9EE8h)]
60055B5D push esi
а память вокруг 0x548B0CC4 это все ?????? так что это не отображенная память, следовательно сбой.
Машинный код в начале myCallWndProcRetCallback:
0x60055B50: ff 83 c4 0c 8b 54 24 18 a1 e8 9e 0b 60 56 52 57 50 ff 15 8c a6 09 60 5f 5e 83 c4 08 c2 0c 00 cc 8b 4c 24 04 8b 01 8b 50
Но Visual Studio также иногда дает следующую разборку для этой функции:
--- c:\projects\redacted.cpp -------------------------
60055B51 add esp,0Ch
if ( nCode == HC_ACTION && lParam != NULL) {
60055B54 mov edx,dword ptr [esp+18h]
60055B58 mov eax,dword ptr [g_callWndProcRetHook (600B9EE8h)]
60055B5D push esi
Это похоже на правильную разборку, но это на 1 байт позже, чем разборка выше! Вы можете видеть, что инструкции такие же, начиная с 0x60055B58.
Итак, похоже, что компоновщик говорит, что функция имеет значение 0x60055B50, но код фактически начинается с 0x60055B51. Я подтвердил, что первым является обратный вызов, установленный в хуке Windows. Поэтому, когда Windows перезванивает в функцию, она выполняет неверный код.
У меня вопрос: как компоновщик может ошибиться? Я сделал восстановление, и проблема ушла, это кажется случайным. В то время, когда использовался параметр компоновщика / FORCE: MULTIPLE, но без него не сообщалось об ошибке связи для этого обратного вызова.
Позднее добавление: это может быть связано с перемещением или перебазированием DLL? Если перемещение было отключено на 1 байт, это может вызвать проблему?