SendMessage (hwnd, зарегистрированный mssghere, 0, 1) получил, но не правильно распознан перехваченным потоком, к которому он был отправлен! - PullRequest
1 голос
/ 20 февраля 2011

Я пытаюсь отправить зарегистрированное пользователем сообщение в оконную процедуру, процедура получает сообщение, но не видит, что отправляет свое конкретное зарегистрированное сообщение.

Итак, с самого начала ... Я удостоверяюсь, что всеЭкземпляры DLL делятся сообщениями.

#pragma data_seg (".shared")
...
...
UINT    WM_HOOKEX = 0;
...
#pragma data_seg ()
#pragma comment(linker,"/SECTION:.shared,RWS")

В dllmain я проверяю, что он зарегистрирован только один раз

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )
{
    if( ul_reason_for_call == DLL_PROCESS_ATTACH ) 
    {
        hDll = (HINSTANCE) hModule; 
        //DisableThreadLibraryCalls( hDll );

        if( WM_HOOKEX==NULL )
            WM_HOOKEX = ::RegisterWindowMessage( _T("WM_HOOKEX_RK") );          
    }

    return TRUE;
}

Позже с экспортированной функцией dll (которая разделяет dll и сообщение), которую я использую в своем приложении, я подключаюсь кпроцедуры нужного окна и отправьте ему это сообщение с

SendMessage( plist,WM_HOOKEX,0,1 );

Подключенная процедура получает сообщение (как я проверяю его с помощью отладки dll), но не может увидеть, что это за сообщение.Отладка Dll показывает, что поток имеет зарегистрированное сообщение в своей памяти, но процедура не получает правильные параметры сообщения.

Также я уверен, что оно получает это сообщение, а не какое-то другое, потому что это единственное сообщение, направленное на процедуру, которую я вызываю, поэтому я исключаю возможность того, что мой пользовательский mssg может все еще находиться в очереди,тогда почему я удивляюсь, почему в течение нескольких дней, почему он не получает сообщение, потому что даже отладка показывает, что он хранит пользовательское сообщение в своей памяти!

Это процедура, которая получает его (или фактически не получает)

#define pCW ((CWPSTRUCT*)lParam)

LRESULT HookProc (
  int code,       // hook code
  WPARAM wParam,  // virtual-key code
  LPARAM lParam   // keystroke-message information
)
{
    if( (pCW->message == WM_HOOKEX) && pCW->lParam ) 
    {
        ::UnhookWindowsHookEx( g_hHook );

        if( g_bSubclassed ) 
            goto END;       // already subclassed?

        // Let's increase the reference count of the DLL (via LoadLibrary),
        // so it's NOT unmapped once the hook is removed;
        TCHAR lib_name[MAX_PATH]; 
        ::GetModuleFileName( hDll, lib_name, MAX_PATH );

        if( !::LoadLibrary( lib_name ) )
            goto END;       

        // Subclass START button
        OldProc = (WNDPROC) 
            ::SetWindowLong( g_hWnd, GWL_WNDPROC, (long)NewProc );
        if( OldProc==NULL )         // failed?
            ::FreeLibrary( hDll );
        else {                      // success -> leave "HookInjEx.dll"
            ::MessageBeep(MB_OK);   // mapped into "explorer.exe"
            g_bSubclassed = true;
        }       
    }
    else if( pCW->message == WM_HOOKEX ) 
    {
        ::UnhookWindowsHookEx( g_hHook );

        // Failed to restore old window procedure? => Don't unmap the
        // DLL either. Why? Because then "explorer.exe" would call our
        // "unmapped" NewProc and  crash!!
        if( !SetWindowLong( g_hWnd, GWL_WNDPROC, (long)OldProc ) )
            goto END;

        ::FreeLibrary( hDll );

        ::MessageBeep(MB_OK);
        g_bSubclassed = false;  
    }

END:
    return ::CallNextHookEx(g_hHook, code, wParam, lParam);
}

Я подозреваю, что все это связано с тем, что я отправляю сообщение с экспортированной функцией, которую я вызываю из моего приложения.Если я делаю это с помощью функции из примера приложения, поставляемого с оригинальным проектом, он использует импортированную функцию, я думаю, что, возможно, причиной может быть экспортированная функция.

Также я не могу проверить импортированную функцию как ее с другого языка.

edit:

Так что я также пытался регистрировать mssg каждый раз, как кто-то здесь предложил, но это не отличалось, странная вещь в том, что все работает нормально, если я вызываю функцию, которая перехватывает иотправляет mssg внутренне, это заголовок функции, которую использует приложение GUI (в этом случае все работает нормально)

#if !defined INJECT_EX__H
#define INJECT_EX__H


#ifdef INJECT_EX_EXPORTS
#define HOOKDLL_API __declspec(dllexport)
#else
#define HOOKDLL_API __declspec(dllimport)
#endif


extern int HOOKDLL_API g_bSubclassed;
HOOKDLL_API int InjectDll();
HOOKDLL_API int UnmapDll();

#endif // !defined(INJECT_EX__H)


#define DIPSLIBAPI extern "C" __declspec(dllexport)

// External function prototypes
DIPSLIBAPI BOOL WINAPI SetDIPSHook(BOOL hook_it, BOOL just_save_list, int lobby, int type);

Так что это заголовок, который, я считаю, приложение GUI использует функцию injectdll как импортированную функциюи может быть, поэтому он работает?Если я использую функцию, экспортированную без этого заголовка, то mssg не видится правильно.

edit2:

Вот директивы препроцессора из проекта dll: _DEBUG WIN32 _WINDOWS _USRDLL INJECT_EX_EXPORTS

Ответы [ 2 ]

1 голос
/ 20 февраля 2011

Мне не совсем понятно, о чем вы описываете проблему.Я предполагаю, что это будет соответствовать поведению, которое вы получите, если WM_HOOKEX будет все еще 0 в введенной DLL.Предполагая, что это проблема, вам нужно сделать следующее:

volatile UINT WM_HOOKEX = 0;

Это гарантирует, что компилятор не будет оптимизировать ссылки на WM_HOOKEX, а будет читать его из памяти каждый раз, когда вы его используете.

0 голосов
/ 20 февраля 2011

Одна конкретная проблема заключается в том, что вы должны вызвать :: RegisterWindowMessage (_T ("WM_HOOKEX_RK"));в каждом процессе вы хотите получить его.Система вернет вам один и тот же номер сообщения в любом процессе, сообщение зарегистрировано в масштабе всей системы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...