2015-03-19 2 views
0

В основном, что говорит мой заголовок. Я пытаюсь вставить DLL в целевое приложение, чтобы отображать вещи каждый раз, когда целевое приложение получает сообщение WM_PAINT. Существует WNDPROC моей цели:BeginPaint не работает при вызове из инъецируемой DLL, даже после того, как EndPaint вызывается в целевом приложении

#include <windows.h> 
#include <stdio.h> 

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    PAINTSTRUCT ps; 

    switch(msg) 
    { 
     case WM_PAINT: 
      BeginPaint(hwnd, &ps); 
      TextOut(ps.hdc, 0, 0, "Hello, Windows!", 15); 
      EndPaint(hwnd, &ps); 
     break; 
     case WM_CLOSE: 
      DestroyWindow(hwnd); 
     break; 
     case WM_DESTROY: 
      PostQuitMessage(0); 
     break; 
     default: 
      return DefWindowProc(hwnd, msg, wParam, lParam); 
    } 
    return 0; 
} 

А вот длл я впрыснуть:

#include <Windows.h> 
#include <stdio.h> 

WNDPROC wpOrigProc; 
HWND target_hwnd = (HWND)0x909E6; // HWND of the window I'm detouring 

LRESULT APIENTRY MyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    PAINTSTRUCT ps; 

    LRESULT result = CallWindowProc(wpOrigProc, hwnd, msg, wParam, lParam); 

    switch(msg) 
    { 
     case WM_PAINT: 
      BeginPaint(hwnd, &ps); 
      TextOut(ps.hdc, 0, 50, "That was injected!", 18); 
      EndPaint(hwnd, &ps); 
     break; 
    } 

    return result; 
} 

int APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) 
{ 
    HHOOK msgHook; 
    FILE* stream; 

    switch (reason) 
    { 
    case DLL_PROCESS_ATTACH: 
     wpOrigProc = (WNDPROC)SetWindowLongPtr(target_hwnd, GWLP_WNDPROC, (LONG)MyWndProc); 
     break; 

    case DLL_PROCESS_DETACH: 
     SetWindowLong(target_hwnd, GWL_WNDPROC, (LONG)wpOrigProc); 
     break; 
    } 

    return 1; 
} 

Теперь, я знаю, что проблема возникает из BeginPaint, потому что, если я использую GetDC и ReleaseDC вместо этого, он работает , Он также работает, если я не вызываю CallWindowProc перед BeginPaint.

Это не имеет для меня никакого смысла, поскольку оригинальный WNDPROC называет EndPaint в конце его WM_PAINT, что означает, что он не должен мешать моей вложенной WM_PAINT ... Любая идея?

+1

На стороне примечания вы должны использовать ['SetWindowSubclass()'] (https://msdn.microsoft.com/en-us/library/windows/desktop/bb762102.aspx) вместо 'SetWindowLongPtr (GWLP_WNDPROC) '. См. [Более безопасное подклассирование] (http://blogs.msdn.com/b/oldnewthing/archive/2003/11/11/55653.aspx). –

ответ

3

EndPaint() проверяет окно, поэтому следующий BeginPaint() получает DC, у которого нет какой-либо доступной (недействительной) области. Вот обсуждение о GetDC()/ReleaseDC() vs. BeginPaint()/EndPaint().

+0

Делает смысл. Причина, по которой я хотел использовать BeginPaint, заключалась в том, чтобы получить недействительную часть окна из PAINTSTRUCT. Возможно ли это, не вмешиваясь в CallWindowProc и исходный WNDPROC целевого процесса? – MyUsername112358

+1

@SoftEngi: вы можете использовать 'GetUpdateRgn', чтобы получить текущую область обновления окна и передать это' GetDCEx', чтобы имитировать DC, который вы получите от 'BeginPaint'. –

+0

Это прекрасно, спасибо! – MyUsername112358