Accessing GDI drawing context pixels directly - winapi

I want to read and write pixels directly from/to a drawing context, i.e. during a paint operation on a window.
I understand that there are GetPixel/SetPixel functions in Windows GDI, but for big operations it would be far better to be able to read and write pixel data directly to memory.
How can I do this using standard GDI?

You could create a compatible DC, Bitmap:
HDC hMemDC = CreateCompatibleDC(hdc);
HBITMAP hBmp = CreateCompatibleBitmap(hdc, WIDTH, HEIGHT);
SelectObject(hMemDC, hBmp);
Next, there is GetDIBits function you can use to get bits:
int GetDIBits(
_In_ HDC hdc,
_In_ HBITMAP hbmp,
_In_ UINT uStartScan,
_In_ UINT cScanLines,
_Out_ LPVOID lpvBits,
_Inout_ LPBITMAPINFO lpbi,
_In_ UINT uUsage
);
NOTE: You might need to set lpvBits to NULL to get the dimensions and format of the image via BITMAPINFO (lpbi parameter).

Use GetObject to get the BITMAP struct which contains a pointer to the bitmap's data.

Related

How to detour the main instance of a function?

I'm trying to detour ::DrawText() (and other draw text functions) for an application that has a lot of DLLs, some of which also use those functions.
I would have thought that if I detoured the main function using DetourFindFunction(), this would capture all cases from all functions in all DLLs, such that I could solve this question as there is text being displayed on the window.
Unfortunately, either CDHtmalDialog is somehow getting around the detour, or it is using some other function to draw the text on the window.
Could someone confirm that if I were to do this:
int (WINAPI *pDrawTextExW)(
_In_ HDC hdc,
_Inout_ LPWSTR lpchText,
_In_ int cchText,
_Inout_ LPRECT lprc,
_In_ UINT dwDTFormat,
_In_ LPDRAWTEXTPARAMS lpDTParams
) = 0;
int WINAPI MyDrawTextExW(
_In_ HDC hdc,
_Inout_ LPWSTR lpchText,
_In_ int cchText,
_Inout_ LPRECT lprc,
_In_ UINT dwDTFormat,
_In_ LPDRAWTEXTPARAMS lpDTParams
)
{
return (*pDrawTextExW)(hdc, lpchText, cchText, lprc, dwDTFormat, lpDTParams);
}
CCalcDrillDownDlg::CCalcDrillDownDlg(/* bunch of parameters */, CWnd *pParent)
: CDHtmlDialog(CCalcDrillDownDlg::IDD, 0, pParent)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
pDrawTextExW = decltype(pDrawTextExW)(DetourFindFunction("user32.dll", "DrawTextExW"));
DetourAttach(&(PVOID&)pDrawTextExW, MyDrawTextExW);
if (DetourTransactionCommit() == NO_ERROR)
OutputDebugString("DrawTextExW() detoured successfully\n");
for each of DrawTextA, DrawTextW, DrawTextExA, DrawTextExW that if CDHtmlDialog were to use one of these functions to draw the text with, it would get detoured? And perhaps someone would know how that class outputs text on the window's DC?
One funny thing that I did notice is that DrawTextExW() is getting detoured, trying to print the OK text on a button that is actually not displayed on the window. Not sure what that's about.
> cv32.dll!MyDrawTextExW(HDC__ * hdc=0x940111a2, wchar_t * lpchText=0x04925128, int cchText=2, tagRECT * lprc=0x012eb314, unsigned int dwDTFormat=1048613, tagDRAWTEXTPARAMS * lpDTParams=0x00000000) Line 4186 C++
uxtheme.dll!CTextDraw::DrawTextW() Unknown
uxtheme.dll!DrawThemeText() Unknown
comctl32.dll!Button_DrawThemed() Unknown
comctl32.dll!Button_DrawPush() Unknown
comctl32.dll!Button_PaintImpl() Unknown
comctl32.dll!Button_WndProc() Unknown
user32.dll!__InternalCallWinProc#20() Unknown
user32.dll!UserCallWinProcCheckWow() Unknown
user32.dll!DispatchClientMessage() Unknown
user32.dll!___fnDWORD#4() Unknown
ntdll.dll!_KiUserCallbackDispatcher#12() Unknown
user32.dll!_DispatchMessageA#4() Unknown
mfc120d.dll!AfxInternalPumpMessage() Line 181 C++
mfc120d.dll!CWinThread::PumpMessage() Line 900 C++
mfc120d.dll!AfxPumpMessage() Line 190 C++
mfc120d.dll!CWnd::RunModalLoop(unsigned long dwFlags=4) Line 4644 C++
mfc120d.dll!CWnd::CreateRunDlgIndirect(const DLGTEMPLATE * lpDialogTemplate=0x7216cc28, CWnd * pParentWnd=0x012ecd60, HINSTANCE__ * hInst=0x6f730000) Line 470 C++
mfc120d.dll!CDialog::DoModal() Line 633 C++

Meaning of negative value of MessageBoxA hWnd argument

I'm analyzing a malware in IDA, where I observed the malware launching a MessageBox with negative value of hWnd (FFFFFFF7h).
Message box arguments (Source:MSDN)
int WINAPI MessageBox(
_In_opt_ HWND hWnd,
_In_opt_ LPCTSTR lpText,
_In_opt_ LPCTSTR lpCaption,
_In_ UINT uType
);
hWnd stands for owner window, I wasn't able to find what it means when hWnd argument is negative. Any help is very much appreciated.

GetDlgCtrlID for top-level window with menu bar - return value

MSDN -> "GetDlgCtrlID function" -> Remarks:
"... Although GetDlgCtrlID may return a value if hwndCtl is a handle to a top-level window, top-level windows cannot have identifiers and such a return value is never valid."
It seems it is wrong information - "never valid".
At least for Win2k...Win8 this return value is just kernel pointer to hmenu(bar).
And my question is (primarily to MS insiders): why MSDN so inaccurate here?
(Screenshot: http://files.rsdn.ru/42164/gwl(-1)_tagwnd.png)
Upd (tagWND):
Also demo: http://files.rsdn.ru/42164/gwl(-1)_tagwnd.zip
It is not inaccurate. You create a top-level window with CreateWindowEx(). Which looks like this:
HWND WINAPI CreateWindowEx(
_In_ DWORD dwExStyle,
_In_opt_ LPCTSTR lpClassName,
_In_opt_ LPCTSTR lpWindowName,
_In_ DWORD dwStyle,
_In_ int x,
_In_ int y,
_In_ int nWidth,
_In_ int nHeight,
_In_opt_ HWND hWndParent,
_In_opt_ HMENU hMenu,
_In_opt_ HINSTANCE hInstance,
_In_opt_ LPVOID lpParam
);
Note how you don't specify the ID anywhere. But the fine print is in the description for the hMenu argument:
A handle to a menu, or specifies a child-window identifier, depending on the window style. For an overlapped or pop-up window, hMenu identifies the menu to be used with the window; it can be NULL if the class menu is to be used. For a child window, hMenu specifies the child-window identifier, an integer value used by a dialog box control to notify its parent about events. The application determines the child-window identifier; it must be unique for all child windows with the same parent window.
So you can have a menu OR a child ID. Overloaded, pretty common in the winapi, a child control can't have a menu and a toplevel window can't have a child ID. If you forge ahead and ignore this and call GetDlgCtrlID() on a toplevel window anyway then you will get back the value of the hMenu argument you specified in the create call. Well, today, always follow the api or you might get a rude surprise some day, you'd of course use GetMenu() instead.

How to identify inside screen resolution the multiple display that is enabled?

I've searched all over Google but found no answer, so If someone knows It would be very thankful!
I want to use command line or some WinApi to check the state of the multiple display.
For example : If I set : "extended screen" or "duplicate screen" I want to be able to verify it.
Just have no idea where to start.
thanks a lot
I would start with the WinAPI EnumDisplayMonitors function: http://msdn.microsoft.com/en-us/library/dd162610%28VS.85%29.aspx
BOOL EnumDisplayMonitors(
_In_ HDC hdc,
_In_ LPCRECT lprcClip,
_In_ MONITORENUMPROC lpfnEnum,
_In_ LPARAM dwData
);
You need to call this function setting the first 2 parameters to NULL like this:
EnumDisplayMonitors(NULL, NULL, MyPaintEnumProc, 0);
//Enumerates all display monitors.
//The callback function receives a NULL HDC.
Now you have your MonitorEnumProc callback function: http://msdn.microsoft.com/en-us/library/dd145061%28v=vs.85%29.aspx
BOOL CALLBACK MonitorEnumProc(
_In_ HMONITOR hMonitor,
_In_ HDC hdcMonitor,
_In_ LPRECT lprcMonitor,
_In_ LPARAM dwData
);
You wiil get filled lprcMonitor back:
A pointer to a RECT structure.
If hdcMonitor is non-NULL, this rectangle is the intersection of the clipping area of the device context identified by hdcMonitor and
the display monitor rectangle. The rectangle coordinates are
device-context coordinates.
If hdcMonitor is NULL, this rectangle is the display monitor rectangle. The rectangle coordinates are virtual-screen coordinates.
Based on this values for ALL monitors you can decide whether you have an extended mode (the rects are different) or the duplicate (they are equal).
HTH - good luck!

Using LPtoDP API problem (GDI API)

I am hooking the ExtTextOut GDI API.
There I want to retrieve the exact location of the output String.
BOOL ExtTextOut(
__in HDC hdc,
__in int X,
__in int Y,
__in UINT fuOptions,
__in const RECT *lprc,
__in LPCTSTR lpString,
__in UINT cbCount,
__in const INT *lpDx
);
In a specific case I am getting ETO_CLIPPED for the fuOptions param which mean I can get the location of the string from the RECT param or from the X,Y params.
However when I use the LPtoDP API for translating the location (RECT or X,Y) I get wrong location (before translating I get negative values).
I guess it has a wrong offset, however when I check the followings I see no indicaton for that:
Map Mode is MM_TEXT (default)
GetWindowOrgEx is 0,0
GetViewportOrgEx is 0,0
GetWindowExtEx is 1,1
GetViewportExtEx is 1,1
Does anyone have any idea, any help will be appreciated.
Thanks.
Apparently, specifying ETO_CLIPPED in the ExtTextOut fuOptions param
does not imply that the text will be output to that clip, meaning that it is not guaranteed that the device context is of type display device context, and the device context that is used can be a memory device context, as in my case, and therefore do not contains the right coordinates.
msdn: ETO_CLIPPED The text will be clipped to the rectangle.

Resources