Process Hacker
gdihndl.c
Go to the documentation of this file.
1 /*
2  * Process Hacker -
3  * GDI handles dialog
4  *
5  * Copyright (C) 2010 wj32
6  *
7  * This file is part of Process Hacker.
8  *
9  * Process Hacker is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Process Hacker is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include <phapp.h>
24 #include <ntgdi.h>
25 
26 typedef struct _GDI_HANDLES_CONTEXT
27 {
28  PPH_PROCESS_ITEM ProcessItem;
29  PPH_LIST List;
31 
32 typedef struct _PH_GDI_HANDLE_ITEM
33 {
34  PGDI_HANDLE_ENTRY Entry;
35  ULONG Handle;
36  PVOID Object;
37  PWSTR TypeName;
38  PPH_STRING Information;
40 
41 INT_PTR CALLBACK PhpGdiHandlesDlgProc(
42  _In_ HWND hwndDlg,
43  _In_ UINT uMsg,
44  _In_ WPARAM wParam,
45  _In_ LPARAM lParam
46  );
47 
49  _In_ HWND ParentWindowHandle,
50  _In_ PPH_PROCESS_ITEM ProcessItem
51  )
52 {
53  GDI_HANDLES_CONTEXT context;
54  ULONG i;
55 
56  context.ProcessItem = ProcessItem;
57  context.List = PhCreateList(20);
58 
59  DialogBoxParam(
61  MAKEINTRESOURCE(IDD_GDIHANDLES),
62  ParentWindowHandle,
64  (LPARAM)&context
65  );
66 
67  for (i = 0; i < context.List->Count; i++)
68  {
69  PPH_GDI_HANDLE_ITEM gdiHandleItem = context.List->Items[i];
70 
71  if (gdiHandleItem->Information)
72  PhDereferenceObject(gdiHandleItem->Information);
73 
74  PhFree(context.List->Items[i]);
75  }
76 
77  PhDereferenceObject(context.List);
78 }
79 
81  _In_ ULONG Unique
82  )
83 {
84  switch (GDI_CLIENT_TYPE_FROM_UNIQUE(Unique))
85  {
87  return L"Alt. DC";
89  return L"Bitmap";
91  return L"Brush";
93  return L"Client Object";
95  return L"DIB Section";
96  case GDI_CLIENT_DC_TYPE:
97  return L"DC";
99  return L"ExtPen";
101  return L"Font";
103  return L"Metafile DC";
105  return L"Enhanced Metafile";
107  return L"Metafile";
109  return L"Palette";
110  case GDI_CLIENT_PEN_TYPE:
111  return L"Pen";
113  return L"Region";
114  default:
115  return NULL;
116  }
117 }
118 
120  _In_ ULONG Handle
121  )
122 {
123  HGDIOBJ handle;
124 
125  handle = (HGDIOBJ)Handle;
126 
127  switch (GDI_CLIENT_TYPE_FROM_HANDLE(Handle))
128  {
131  {
132  BITMAP bitmap;
133 
134  if (GetObject(handle, sizeof(BITMAP), &bitmap))
135  {
136  return PhFormatString(
137  L"Width: %u, Height: %u, Depth: %u",
138  bitmap.bmWidth,
139  bitmap.bmHeight,
140  bitmap.bmBitsPixel
141  );
142  }
143  }
144  break;
146  {
147  LOGBRUSH brush;
148 
149  if (GetObject(handle, sizeof(LOGBRUSH), &brush))
150  {
151  return PhFormatString(
152  L"Style: %u, Color: 0x%08x, Hatch: 0x%Ix",
153  brush.lbStyle,
154  _byteswap_ulong(brush.lbColor),
155  brush.lbHatch
156  );
157  }
158  }
159  break;
161  {
162  EXTLOGPEN pen;
163 
164  if (GetObject(handle, sizeof(EXTLOGPEN), &pen))
165  {
166  return PhFormatString(
167  L"Style: 0x%x, Width: %u, Color: 0x%08x",
168  pen.elpPenStyle,
169  pen.elpWidth,
170  _byteswap_ulong(pen.elpColor)
171  );
172  }
173  }
174  break;
176  {
177  LOGFONT font;
178 
179  if (GetObject(handle, sizeof(LOGFONT), &font))
180  {
181  return PhFormatString(
182  L"Face: %s, Height: %d",
183  font.lfFaceName,
184  font.lfHeight
185  );
186  }
187  }
188  break;
190  {
191  USHORT count;
192 
193  if (GetObject(handle, sizeof(USHORT), &count))
194  {
195  return PhFormatString(
196  L"Entries: %u",
197  (ULONG)count
198  );
199  }
200  }
201  break;
202  case GDI_CLIENT_PEN_TYPE:
203  {
204  LOGPEN pen;
205 
206  if (GetObject(handle, sizeof(LOGPEN), &pen))
207  {
208  return PhFormatString(
209  L"Style: %u, Width: %u, Color: 0x%08x",
210  pen.lopnStyle,
211  pen.lopnWidth.x,
212  _byteswap_ulong(pen.lopnColor)
213  );
214  }
215  }
216  break;
217  }
218 
219  return NULL;
220 }
221 
223  _In_ HWND hwndDlg,
224  _In_ PGDI_HANDLES_CONTEXT Context
225  )
226 {
227  HWND lvHandle;
228  ULONG i;
229  PGDI_SHARED_MEMORY gdiShared;
230  USHORT processId;
231  PGDI_HANDLE_ENTRY handle;
232  PPH_GDI_HANDLE_ITEM gdiHandleItem;
233 
234  lvHandle = GetDlgItem(hwndDlg, IDC_LIST);
235 
236  ListView_DeleteAllItems(lvHandle);
238 
239  for (i = 0; i < Context->List->Count; i++)
240  {
241  gdiHandleItem = Context->List->Items[i];
242 
243  if (gdiHandleItem->Information)
244  PhDereferenceObject(gdiHandleItem->Information);
245 
246  PhFree(Context->List->Items[i]);
247  }
248 
249  PhClearList(Context->List);
250 
251  gdiShared = (PGDI_SHARED_MEMORY)NtCurrentPeb()->GdiSharedHandleTable;
252  processId = (USHORT)Context->ProcessItem->ProcessId;
253 
254  for (i = 0; i < GDI_MAX_HANDLE_COUNT; i++)
255  {
256  PWSTR typeName;
257  INT lvItemIndex;
258  WCHAR pointer[PH_PTR_STR_LEN_1];
259 
260  handle = &gdiShared->Handles[i];
261 
262  if (handle->Owner.ProcessId != processId)
263  continue;
264 
265  typeName = PhpGetGdiHandleTypeName(handle->Unique);
266 
267  if (!typeName)
268  continue;
269 
270  gdiHandleItem = PhAllocate(sizeof(PH_GDI_HANDLE_ITEM));
271  gdiHandleItem->Entry = handle;
272  gdiHandleItem->Handle = GDI_MAKE_HANDLE(i, handle->Unique);
273  gdiHandleItem->Object = handle->Object;
274  gdiHandleItem->TypeName = typeName;
275  gdiHandleItem->Information = PhpGetGdiHandleInformation(gdiHandleItem->Handle);
276  PhAddItemList(Context->List, gdiHandleItem);
277 
278  lvItemIndex = PhAddListViewItem(lvHandle, MAXINT, gdiHandleItem->TypeName, gdiHandleItem);
279  PhPrintPointer(pointer, (PVOID)gdiHandleItem->Handle);
280  PhSetListViewSubItem(lvHandle, lvItemIndex, 1, pointer);
281  PhPrintPointer(pointer, gdiHandleItem->Object);
282  PhSetListViewSubItem(lvHandle, lvItemIndex, 2, pointer);
283  PhSetListViewSubItem(lvHandle, lvItemIndex, 3, PhGetString(gdiHandleItem->Information));
284  }
285 
286  ExtendedListView_SortItems(lvHandle);
287  ExtendedListView_SetRedraw(lvHandle, TRUE);
288 }
289 
291  _In_ PVOID Item1,
292  _In_ PVOID Item2,
293  _In_opt_ PVOID Context
294  )
295 {
296  PPH_GDI_HANDLE_ITEM item1 = Item1;
297  PPH_GDI_HANDLE_ITEM item2 = Item2;
298 
299  return uintcmp(item1->Handle, item2->Handle);
300 }
301 
303  _In_ PVOID Item1,
304  _In_ PVOID Item2,
305  _In_opt_ PVOID Context
306  )
307 {
308  PPH_GDI_HANDLE_ITEM item1 = Item1;
309  PPH_GDI_HANDLE_ITEM item2 = Item2;
310 
311  return uintptrcmp((ULONG_PTR)item1->Object, (ULONG_PTR)item2->Object);
312 }
313 
314 INT_PTR CALLBACK PhpGdiHandlesDlgProc(
315  _In_ HWND hwndDlg,
316  _In_ UINT uMsg,
317  _In_ WPARAM wParam,
318  _In_ LPARAM lParam
319  )
320 {
321  switch (uMsg)
322  {
323  case WM_INITDIALOG:
324  {
325  PGDI_HANDLES_CONTEXT context = (PGDI_HANDLES_CONTEXT)lParam;
326  HWND lvHandle;
327 
328  SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context);
329 
330  lvHandle = GetDlgItem(hwndDlg, IDC_LIST);
331 
332  PhSetListViewStyle(lvHandle, FALSE, TRUE);
333  PhSetControlTheme(lvHandle, L"explorer");
334  PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 100, L"Type");
335  PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 80, L"Handle");
336  PhAddListViewColumn(lvHandle, 2, 2, 2, LVCFMT_LEFT, 80, L"Object");
337  PhAddListViewColumn(lvHandle, 3, 3, 3, LVCFMT_LEFT, 200, L"Information");
338 
339  PhSetExtendedListView(lvHandle);
344 
345  PhpRefreshGdiHandles(hwndDlg, context);
346  }
347  break;
348  case WM_DESTROY:
349  {
350  RemoveProp(hwndDlg, PhMakeContextAtom());
351  }
352  break;
353  case WM_COMMAND:
354  {
355  switch (LOWORD(wParam))
356  {
357  case IDCANCEL:
358  case IDOK:
359  EndDialog(hwndDlg, IDOK);
360  break;
361  case IDC_REFRESH:
362  {
363  PhpRefreshGdiHandles(hwndDlg, (PGDI_HANDLES_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()));
364  }
365  break;
366  }
367  }
368  break;
369  case WM_NOTIFY:
370  {
371  PhHandleListViewNotifyForCopy(lParam, GetDlgItem(hwndDlg, IDC_LIST));
372  }
373  break;
374  }
375 
376  return FALSE;
377 }