📄 dcdtable.cpp
字号:
//-----------------------------------------------------------------------------------//
// Windows Graphics Programming: Win32 GDI and DirectDraw //
// ISBN 0-13-086985-6 //
// //
// Written by Yuan, Feng www.fengyuan.com //
// Copyright (c) 2000 by Hewlett-Packard Company www.hp.com //
// Published by Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com //
// //
// FileName : dcdtable.cpp //
// Description: Decode GDI handle table, Chapter 3 //
// Version : 1.00.000, May 31, 2000 //
//-----------------------------------------------------------------------------------//
#define STRICT
#include <windows.h>
#include <assert.h>
#include <stdio.h>
#include <tchar.h>
#include <winioctl.h>
#include "dialog.h"
#include "gditable.h"
#include "fxstring.h"
#include "resource.h"
#include "handles.h"
#include "creator.h"
#include "dcdtable.h"
#include "device.h"
#include "MemDump.h"
#include "..\\Periscope\Periscope.h"
#define _WIN32_WINNT 0x0500
#include "dcattr.h"
KDecodeTablePage::KDecodeTablePage()
{
m_hInst = NULL;
}
class KTemp
{
public:
KString<512> mess;
HGDIOBJ Select(HDC hDC, HGDIOBJ hHandle);
};
HGDIOBJ KTemp::Select(HDC hDC, HGDIOBJ hHandle)
{
HGDIOBJ hRslt;
if ( GetObjectType(hHandle) == OBJ_PAL )
{
hRslt = SelectPalette(hDC, (HPALETTE) hHandle, FALSE);
mess.Append("SelectPalette() returns 0x%x", (unsigned) hRslt);
}
else
{
hRslt = SelectObject(hDC, hHandle);
mess.Append("SelectObject() returns 0x%x", (unsigned) hRslt);
}
// assert(hRslt);
return hRslt;
}
void KDecodeTablePage::TestnCount(int obj, HDC hDC1, HDC hDC2, bool testdelete)
{
KTemp temp;
BOOL rslt;
// create an object
HGDIOBJ hHandle = CreateObject(obj, hDC1);
assert(hHandle);
temp.mess.Append("Create...() returns 0x%x", (unsigned) hHandle);
temp.mess.Append(", nCount=%d\r\n", m_GDITable.GetCount(hHandle));
// select into a DC1
HGDIOBJ hOld1 = temp.Select(hDC1, hHandle);
temp.mess.Append(" nCount=%d\r\n", m_GDITable.GetCount(hHandle));
// select into a DC2
HGDIOBJ hOld2 = temp.Select(hDC2, hHandle);
temp.mess.Append(" nCount=%d\r\n", m_GDITable.GetCount(hHandle));
if ( testdelete )
{
rslt = DeleteObject(hHandle);
temp.mess.Append("DeleteObject() returns %d\n", rslt);
}
// deselect from a DC2
temp.mess.Append("(De)");
temp.Select(hDC2, hOld2);
temp.mess.Append(", nCount=%d\r\n", m_GDITable.GetCount(hHandle));
// deselect from a DC1
temp.mess.Append("(De)");
temp.Select(hDC1, hOld1);
temp.mess.Append(", nCount=%d\r\n", m_GDITable.GetCount(hHandle));
rslt = DeleteObject(hHandle);
temp.mess.Append("DeleteObject() returns %d", rslt);
MessageBox(NULL, temp.mess, Commands[obj], MB_OK);
}
void KDecodeTablePage::TestnCount(bool testdelete)
{
HDC hDC = GetDC(m_hWnd);
HDC hMemDC1 = CreateCompatibleDC(hDC);
HDC hMemDC2 = CreateCompatibleDC(hDC);
TestnCount(obj_CreateSolidBrush, hMemDC1, hMemDC2, testdelete);
TestnCount(obj_CreatePen, hMemDC1, hMemDC2, testdelete);
TestnCount(obj_CreateBitmap, hMemDC1, hMemDC2, testdelete);
TestnCount(obj_CreateFont, hMemDC1, hMemDC2, testdelete);
TestnCount(obj_CreatePalette, hMemDC1, hMemDC2, testdelete);
DeleteDC(hMemDC1);
DeleteDC(hMemDC2);
ReleaseDC(m_hWnd, hDC);
}
// check reuse of rectangle region
void KDecodeTablePage::TestpUserRectRegion(void)
{
KString<1024> mess;
for (int i=0; i<8; i++)
{
HRGN hRgn = CreateRectRgn(i, i, i+10, i+10);
mess.Append("%d ", i+1);
mess.Append("%08lx\t", (unsigned) hRgn);
mess.Append("pKernel=%x\t", (unsigned) m_GDITable[hRgn].pKernel);
mess.Append("pUser=%x ", (unsigned) m_GDITable[hRgn].pUser);
RECT * pRect = (RECT *) ((unsigned char *)m_GDITable[hRgn].pUser+8);
mess.Append("[%d, ", pRect->left);
mess.Append("%d, ", pRect->top);
mess.Append("%d, ", pRect->right);
mess.Append("%d]\r\n", pRect->bottom);
KString<128> t;
t.Append("%x, ", (unsigned) m_GDITable[hRgn].pKernel);
t.Append("%x, ", m_GDITable[hRgn].nUpper);
t.Append("%x ", (unsigned) m_GDITable[hRgn].pUser);
DeleteObject(hRgn);
t.Append(" -> delete -> ");
t.Append("%x, ", (unsigned) m_GDITable[hRgn].pKernel);
t.Append("%x, ", m_GDITable[hRgn].nUpper);
t.Append("%x ", (unsigned) m_GDITable[hRgn].pUser);
OutputDebugString(t);
OutputDebugString("\n");
}
MessageBox(NULL, mess, "CreateRectRgn", MB_OK);
}
void KDecodeTablePage::TestpUserSolidBrush(void)
{
KString<1024> mess;
for (int i=0; i<8; i++)
{
HGDIOBJ hBrush = CreateSolidBrush(RGB(i*32, i*32, i*32));
mess.Append("%d ", i+1);
mess.Append("%08lx\t", (unsigned) hBrush);
mess.Append("pKernel=%x\t", (unsigned) m_GDITable[hBrush].pKernel);
mess.Append("pUser=%x ", (unsigned) m_GDITable[hBrush].pUser);
LOGBRUSH * pLogBrush = (LOGBRUSH *) m_GDITable[hBrush].pUser;
mess.Append("color=%x\r\n", pLogBrush->lbColor);
OutputDebugString(mess);
KString<128> t;
t.Append("%x, ", (unsigned) m_GDITable[hBrush].pKernel);
t.Append("%x, ", m_GDITable[hBrush].nUpper);
t.Append("%x ", (unsigned) m_GDITable[hBrush].pUser);
DeleteObject(hBrush);
t.Append(" -> delete -> ");
t.Append("%x, ", (unsigned) m_GDITable[hBrush].pKernel);
t.Append("%x, ", m_GDITable[hBrush].nUpper);
t.Append("%x ", (unsigned) m_GDITable[hBrush].pUser);
// OutputDebugString(t);
// OutputDebugString("\n");
}
MessageBox(NULL, mess, "CreateSolidBrush", MB_OK);
}
BOOL KDecodeTablePage::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HWND hExp = GetDlgItem(hWnd, IDC_EXPERIMENT);
switch (uMsg)
{
case WM_INITDIALOG:
m_hWnd = hWnd;
m_Objects.FromDlgItem(hWnd, IDC_GDITABLE);
m_Objects.AddColumn(0, 50, "Index");
m_Objects.AddColumn(1, 90, "pKernel");
m_Objects.AddColumn(2, 60, "nCount");
m_Objects.AddColumn(3, 60, "nProc");
m_Objects.AddColumn(4, 60, "nUpper");
m_Objects.AddColumn(5, 60, "nType");
m_Objects.AddColumn(6, 90, "pUser");
SendMessage(hExp, CB_ADDSTRING, 0, (LPARAM) _T("Query GDI Table"));
SendMessage(hExp, CB_ADDSTRING, 0, (LPARAM) _T("nCount: SelectObject"));
SendMessage(hExp, CB_ADDSTRING, 0, (LPARAM) _T("nCount: DeleteObject"));
SendMessage(hExp, CB_ADDSTRING, 0, (LPARAM) _T("pUser: CreateSolidBrush"));
SendMessage(hExp, CB_ADDSTRING, 0, (LPARAM) _T("pUser: CreateRectRgn"));
SendMessage(hExp, CB_ADDSTRING, 0, (LPARAM) _T("Dump GDI Table"));
SendMessage(hExp, CB_SETCURSEL, 0, 0);
return TRUE;
case WM_COMMAND:
if ( LOWORD(wParam) == IDC_GO )
switch ( SendMessage(hExp, CB_GETCURSEL, 0, 0) )
{
case 0: Query(); return TRUE;
case 1: TestnCount(false); return TRUE;
case 2: TestnCount(true); return TRUE;
case 3: TestpUserSolidBrush(); return TRUE;
case 4: TestpUserRectRegion(); return TRUE;
case 5: DumpGDITable(); return TRUE;
}
break;
case WM_NOTIFY:
if (wParam == IDC_GDITABLE)
{
NM_LISTVIEW * pInfo = (NM_LISTVIEW *) lParam;
if ( (pInfo->hdr.code == NM_CLICK) && (pInfo->iItem != -1) )
{
TCHAR sIndex[16];
unsigned nIndex;
m_Objects.GetItemText(pInfo->iItem, 0, sIndex, sizeof(sIndex));
sscanf(sIndex, "%x", & nIndex);
ShowDetails(nIndex);
return TRUE;
}
else if ( (pInfo->hdr.code == NM_DBLCLK) && (pInfo->iItem != -1) )
{
TCHAR sIndex[16];
unsigned nIndex;
m_Objects.GetItemText(pInfo->iItem, 0, sIndex, sizeof(sIndex));
sscanf(sIndex, "%x", & nIndex);
// HDC hDC = GetDC(NULL);
// Modify((unsigned) hDC & 0x3FFF);
// ReleaseDC(NULL, hDC);
Modify(nIndex);
return TRUE;
}
}
break;
case WM_DESTROY:
m_Objects.DeleteAll();
break;
}
return FALSE;
}
void KDecodeTablePage::Query(void)
{
m_Objects.DeleteAll();
DWORD nProcId;
// determine if user is interested in single process or all processes
if ( SendDlgItemMessage(m_hWnd, IDC_PROCESSONLY, BM_GETCHECK, 0, 0) == BST_CHECKED )
nProcId = GetCurrentProcessId();
else
nProcId = 0;
for (int i=0; i<=0x3FFF; i++)
{
GDITableCell cell = m_GDITable[i];
if ( (nProcId == 0) || (nProcId==m_GDITable.GetProcess(i)) ) // process matches
if ( (unsigned) cell.pKernel >= 0x80000000 ) // valid pointer to kernel address space
{
KString<64> s;
m_Objects.AddItem(0, s.Format("%4x", i));
m_Objects.AddItem(1, s.Format("%8x", (unsigned) cell.pKernel));
m_Objects.AddItem(2, s.Format("%x", m_GDITable.GetCount(i)));
m_Objects.AddItem(3, s.Format("%x", m_GDITable.GetProcess(i)));
m_Objects.AddItem(4, s.Format("%04x", cell.nUpper));
m_Objects.AddItem(5, s.Format("%04x", cell.nType));
m_Objects.AddItem(6, s.Format("%x", (unsigned) cell.pUser));
}
}
}
const char * GDIObjectTypeName(HGDIOBJ obj)
{
static char rslt[32];
switch ( HIWORD(obj) & 0x7F )
{
case 0x01: return "dc";
case 0x04: return "region";
case 0x05: return "bitmap";
case 0x08: return "palette";
case 0x0a: return "font";
case 0x10: return "brush";
case 0x21: return "enhmetafile";
case 0x30: return "pen";
case 0x50: return "extpen";
default:
wsprintfA(rslt, "unknown(%xh)", HIWORD(obj) & 0x7F);
return rslt;
}
}
class KPeriscopeClient : public KDevice
{
public:
KPeriscopeClient(const TCHAR * DeviceName) : KDevice(DeviceName)
{
}
bool Read(void * dst, const void * src, unsigned len);
};
bool KPeriscopeClient::Read(void * dst, const void * src, unsigned len)
{
unsigned cmd[2] = { (unsigned) src, len };
unsigned long dwRead;
return IoControl(IOCTL_PERISCOPE, cmd, sizeof(cmd), dst, len, &dwRead) && (dwRead==len);
}
void KDecodeTablePage::DumpGDITable(void)
{
bool pagetouched[16*256]; // 16 Mb in pages
char temp[MAX_PATH];
KMemDump memdump;
memset(pagetouched, 0, sizeof(pagetouched));
memdump.OpenDump();
for (int i=0; i<=0x3FFF; i++)
{
GDITableCell cell = m_GDITable[i];
if ( (unsigned) cell.pKernel >= 0x80000000 )
{
wsprintf(temp, "%4x %8x %8x %s", i, cell.pKernel, cell.pUser,
GDIObjectTypeName((HGDIOBJ) MAKELONG(i, cell.nUpper)));
memdump.Writeln(temp);
unsigned addr = (unsigned) cell.pKernel;
if ( (addr>>24)==0xE1 )
pagetouched[(addr & 0xFFFFFF)>>12] = true;
}
}
memdump.Newline();
KPeriscopeClient scope("PeriScope");
if ( scope.Load("c:\\periscope.sys")==ERROR_SUCCESS )
{
unsigned char buf[4096];
for (i=0; i<4096; i++)
if ( pagetouched[i] )
{
unsigned addr = 0xE1000000 + i * 4096;
scope.Read(buf, (void *) addr, sizeof(buf));
memdump.Dump(buf, addr - (unsigned)buf, 4096, sizeof(unsigned long));
memdump.Newline();
}
memdump.CloseDump();
scope.Close();
}
else
MessageBox(NULL, "Unable to load periscope", NULL, MB_OK);
}
const LPCTSTR DCProperty[] =
{
TEXT("GetBkColor/SetBkColor"),
TEXT("GetBkMode/SetBkMode"),
TEXT("GetPolyFillMode/SetPolyFillMode"),
TEXT("GetRop2/SetRop2"),
TEXT("GetStretchBltMode/SetStretchBltMode"),
TEXT("GetTextColor/SetTextColor"),
TEXT("GetMapMode/SetMapMode"),
TEXT("GetViewportOrg/SetViewportOrg"),
TEXT("GetViewportExt/SetViewportExt"),
TEXT("GetWindowOrg/SetWindowOrg"),
TEXT("GetWindowExt/SetWindowExt"),
TEXT("GetClipBox/SetClipBox"),
TEXT("GetTextAlign/SetTxtAlign"),
TEXT("GetTextJustification/SetTextJustification"),
TEXT("GetTextCharacterExtra/SetTextCharacterExtra"),
TEXT("GetAspectRatioFilterEx/SetMapperFlags")
};
#define Cap(name) DeviceCap(#name, name)
class KDecodeDC
{
unsigned * m_addr;
unsigned buffer[sizeof(DCAttr)/sizeof(unsigned)];
HDC m_hDC;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -