Process Hacker
iconext.c
Go to the documentation of this file.
1 /*
2  * Process Hacker Extended Tools -
3  * notification icon extensions
4  *
5  * Copyright (C) 2011 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 "exttools.h"
24 
25 #define GPU_ICON_ID 1
26 #define DISK_ICON_ID 2
27 #define NETWORK_ICON_ID 3
28 
30  _In_ struct _PH_NF_ICON *Icon,
31  _Out_ PVOID *NewIconOrBitmap,
32  _Out_ PULONG Flags,
33  _Out_ PPH_STRING *NewText,
34  _In_opt_ PVOID Context
35  );
36 
38  _In_ struct _PH_NF_ICON *Icon,
39  _In_ ULONG_PTR WParam,
40  _In_ ULONG_PTR LParam,
41  _In_opt_ PVOID Context
42  );
43 
45  _In_ struct _PH_NF_ICON *Icon,
46  _Out_ PVOID *NewIconOrBitmap,
47  _Out_ PULONG Flags,
48  _Out_ PPH_STRING *NewText,
49  _In_opt_ PVOID Context
50  );
51 
53  _In_ struct _PH_NF_ICON *Icon,
54  _In_ ULONG_PTR WParam,
55  _In_ ULONG_PTR LParam,
56  _In_opt_ PVOID Context
57  );
58 
60  _In_ struct _PH_NF_ICON *Icon,
61  _Out_ PVOID *NewIconOrBitmap,
62  _Out_ PULONG Flags,
63  _Out_ PPH_STRING *NewText,
64  _In_opt_ PVOID Context
65  );
66 
68  _In_ struct _PH_NF_ICON *Icon,
69  _In_ ULONG_PTR WParam,
70  _In_ ULONG_PTR LParam,
71  _In_opt_ PVOID Context
72  );
73 
75  VOID
76  )
77 {
79 
80  data.MessageCallback = NULL;
81 
87  NULL,
88  L"GPU History",
90  &data
91  );
92 
98  NULL,
99  L"Disk History",
100  PH_NF_ICON_SHOW_MINIINFO | (EtEtwEnabled ? 0 : PH_NF_ICON_UNAVAILABLE),
101  &data
102  );
103 
109  NULL,
110  L"Network History",
111  PH_NF_ICON_SHOW_MINIINFO | (EtEtwEnabled ? 0 : PH_NF_ICON_UNAVAILABLE),
112  &data
113  );
114 }
115 
117  _In_ struct _PH_NF_ICON *Icon,
118  _Out_ PVOID *NewIconOrBitmap,
119  _Out_ PULONG Flags,
120  _Out_ PPH_STRING *NewText,
121  _In_opt_ PVOID Context
122  )
123 {
124  static PH_GRAPH_DRAW_INFO drawInfo =
125  {
126  16,
127  16,
128  0,
129  2,
130  RGB(0x00, 0x00, 0x00),
131 
132  16,
133  NULL,
134  NULL,
135  0,
136  0,
137  0,
138  0
139  };
140  ULONG maxDataCount;
141  ULONG lineDataCount;
142  PFLOAT lineData1;
143  HBITMAP bitmap;
144  PVOID bits;
145  HDC hdc;
146  HBITMAP oldBitmap;
147  HANDLE maxGpuProcessId;
148  PPH_PROCESS_ITEM maxGpuProcessItem;
149  PH_FORMAT format[8];
150 
151  // Icon
152 
153  Icon->Pointers->BeginBitmap(&drawInfo.Width, &drawInfo.Height, &bitmap, &bits, &hdc, &oldBitmap);
154  maxDataCount = drawInfo.Width / 2 + 1;
155  lineData1 = _alloca(maxDataCount * sizeof(FLOAT));
156 
157  lineDataCount = min(maxDataCount, EtGpuNodeHistory.Count);
158  PhCopyCircularBuffer_FLOAT(&EtGpuNodeHistory, lineData1, lineDataCount);
159 
160  drawInfo.LineDataCount = lineDataCount;
161  drawInfo.LineData1 = lineData1;
162  drawInfo.LineColor1 = PhGetIntegerSetting(L"ColorCpuKernel");
163  drawInfo.LineBackColor1 = PhHalveColorBrightness(drawInfo.LineColor1);
164 
165  if (bits)
166  PhDrawGraphDirect(hdc, bits, &drawInfo);
167 
168  SelectObject(hdc, oldBitmap);
169  *NewIconOrBitmap = bitmap;
170  *Flags = PH_NF_UPDATE_IS_BITMAP;
171 
172  // Text
173 
174  if (EtMaxGpuNodeHistory.Count != 0)
175  maxGpuProcessId = UlongToHandle(PhGetItemCircularBuffer_ULONG(&EtMaxGpuNodeHistory, 0));
176  else
177  maxGpuProcessId = NULL;
178 
179  if (maxGpuProcessId)
180  maxGpuProcessItem = PhReferenceProcessItem(maxGpuProcessId);
181  else
182  maxGpuProcessItem = NULL;
183 
184  PhInitFormatS(&format[0], L"GPU Usage: ");
185  PhInitFormatF(&format[1], EtGpuNodeUsage * 100, 2);
186  PhInitFormatC(&format[2], '%');
187 
188  if (maxGpuProcessItem)
189  {
190  PhInitFormatC(&format[3], '\n');
191  PhInitFormatSR(&format[4], maxGpuProcessItem->ProcessName->sr);
192  PhInitFormatS(&format[5], L": ");
193  PhInitFormatF(&format[6], EtGetProcessBlock(maxGpuProcessItem)->GpuNodeUsage * 100, 2);
194  PhInitFormatC(&format[7], '%');
195  }
196 
197  *NewText = PhFormat(format, maxGpuProcessItem ? 8 : 3, 128);
198  if (maxGpuProcessItem) PhDereferenceObject(maxGpuProcessItem);
199 }
200 
202  _In_ struct _PH_NF_ICON *Icon,
203  _In_ ULONG_PTR WParam,
204  _In_ ULONG_PTR LParam,
205  _In_opt_ PVOID Context
206  )
207 {
208  switch (LOWORD(LParam))
209  {
211  {
212  PPH_NF_MSG_SHOWMINIINFOSECTION_DATA data = (PVOID)WParam;
213 
214  data->SectionName = L"GPU";
215  }
216  return TRUE;
217  }
218 
219  return FALSE;
220 }
221 
223  _In_ struct _PH_NF_ICON *Icon,
224  _Out_ PVOID *NewIconOrBitmap,
225  _Out_ PULONG Flags,
226  _Out_ PPH_STRING *NewText,
227  _In_opt_ PVOID Context
228  )
229 {
230  static PH_GRAPH_DRAW_INFO drawInfo =
231  {
232  16,
233  16,
235  2,
236  RGB(0x00, 0x00, 0x00),
237 
238  16,
239  NULL,
240  NULL,
241  0,
242  0,
243  0,
244  0
245  };
246  ULONG maxDataCount;
247  ULONG lineDataCount;
248  PFLOAT lineData1;
249  PFLOAT lineData2;
250  FLOAT max;
251  ULONG i;
252  HBITMAP bitmap;
253  PVOID bits;
254  HDC hdc;
255  HBITMAP oldBitmap;
256  HANDLE maxDiskProcessId;
257  PPH_PROCESS_ITEM maxDiskProcessItem;
258  PH_FORMAT format[6];
259 
260  // Icon
261 
262  Icon->Pointers->BeginBitmap(&drawInfo.Width, &drawInfo.Height, &bitmap, &bits, &hdc, &oldBitmap);
263  maxDataCount = drawInfo.Width / 2 + 1;
264  lineData1 = _alloca(maxDataCount * sizeof(FLOAT));
265  lineData2 = _alloca(maxDataCount * sizeof(FLOAT));
266 
267  lineDataCount = min(maxDataCount, EtDiskReadHistory.Count);
268  max = 1024 * 1024; // minimum scaling of 1 MB.
269 
270  for (i = 0; i < lineDataCount; i++)
271  {
272  lineData1[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(&EtDiskReadHistory, i);
273  lineData2[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(&EtDiskWriteHistory, i);
274 
275  if (max < lineData1[i] + lineData2[i])
276  max = lineData1[i] + lineData2[i];
277  }
278 
279  PhDivideSinglesBySingle(lineData1, max, lineDataCount);
280  PhDivideSinglesBySingle(lineData2, max, lineDataCount);
281 
282  drawInfo.LineDataCount = lineDataCount;
283  drawInfo.LineData1 = lineData1;
284  drawInfo.LineData2 = lineData2;
285  drawInfo.LineColor1 = PhGetIntegerSetting(L"ColorIoReadOther");
286  drawInfo.LineColor2 = PhGetIntegerSetting(L"ColorIoWrite");
287  drawInfo.LineBackColor1 = PhHalveColorBrightness(drawInfo.LineColor1);
288  drawInfo.LineBackColor2 = PhHalveColorBrightness(drawInfo.LineColor2);
289 
290  if (bits)
291  PhDrawGraphDirect(hdc, bits, &drawInfo);
292 
293  SelectObject(hdc, oldBitmap);
294  *NewIconOrBitmap = bitmap;
295  *Flags = PH_NF_UPDATE_IS_BITMAP;
296 
297  // Text
298 
299  if (EtMaxDiskHistory.Count != 0)
300  maxDiskProcessId = UlongToHandle(PhGetItemCircularBuffer_ULONG(&EtMaxDiskHistory, 0));
301  else
302  maxDiskProcessId = NULL;
303 
304  if (maxDiskProcessId)
305  maxDiskProcessItem = PhReferenceProcessItem(maxDiskProcessId);
306  else
307  maxDiskProcessItem = NULL;
308 
309  PhInitFormatS(&format[0], L"Disk\nR: ");
311  PhInitFormatS(&format[2], L"\nW: ");
313 
314  if (maxDiskProcessItem)
315  {
316  PhInitFormatC(&format[4], '\n');
317  PhInitFormatSR(&format[5], maxDiskProcessItem->ProcessName->sr);
318  }
319 
320  *NewText = PhFormat(format, maxDiskProcessItem ? 6 : 4, 128);
321  if (maxDiskProcessItem) PhDereferenceObject(maxDiskProcessItem);
322 }
323 
325  _In_ struct _PH_NF_ICON *Icon,
326  _In_ ULONG_PTR WParam,
327  _In_ ULONG_PTR LParam,
328  _In_opt_ PVOID Context
329  )
330 {
331  switch (LOWORD(LParam))
332  {
334  {
335  PPH_NF_MSG_SHOWMINIINFOSECTION_DATA data = (PVOID)WParam;
336 
337  data->SectionName = L"Disk";
338  }
339  return TRUE;
340  }
341 
342  return FALSE;
343 }
344 
346  _In_ struct _PH_NF_ICON *Icon,
347  _Out_ PVOID *NewIconOrBitmap,
348  _Out_ PULONG Flags,
349  _Out_ PPH_STRING *NewText,
350  _In_opt_ PVOID Context
351  )
352 {
353  static PH_GRAPH_DRAW_INFO drawInfo =
354  {
355  16,
356  16,
358  2,
359  RGB(0x00, 0x00, 0x00),
360 
361  16,
362  NULL,
363  NULL,
364  0,
365  0,
366  0,
367  0
368  };
369  ULONG maxDataCount;
370  ULONG lineDataCount;
371  PFLOAT lineData1;
372  PFLOAT lineData2;
373  FLOAT max;
374  ULONG i;
375  HBITMAP bitmap;
376  PVOID bits;
377  HDC hdc;
378  HBITMAP oldBitmap;
379  HANDLE maxNetworkProcessId;
380  PPH_PROCESS_ITEM maxNetworkProcessItem;
381  PH_FORMAT format[6];
382 
383  // Icon
384 
385  Icon->Pointers->BeginBitmap(&drawInfo.Width, &drawInfo.Height, &bitmap, &bits, &hdc, &oldBitmap);
386  maxDataCount = drawInfo.Width / 2 + 1;
387  lineData1 = _alloca(maxDataCount * sizeof(FLOAT));
388  lineData2 = _alloca(maxDataCount * sizeof(FLOAT));
389 
390  lineDataCount = min(maxDataCount, EtNetworkReceiveHistory.Count);
391  max = 1024 * 1024; // minimum scaling of 1 MB.
392 
393  for (i = 0; i < lineDataCount; i++)
394  {
395  lineData1[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(&EtNetworkReceiveHistory, i);
396  lineData2[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(&EtNetworkSendHistory, i);
397 
398  if (max < lineData1[i] + lineData2[i])
399  max = lineData1[i] + lineData2[i];
400  }
401 
402  PhDivideSinglesBySingle(lineData1, max, lineDataCount);
403  PhDivideSinglesBySingle(lineData2, max, lineDataCount);
404 
405  drawInfo.LineDataCount = lineDataCount;
406  drawInfo.LineData1 = lineData1;
407  drawInfo.LineData2 = lineData2;
408  drawInfo.LineColor1 = PhGetIntegerSetting(L"ColorIoReadOther");
409  drawInfo.LineColor2 = PhGetIntegerSetting(L"ColorIoWrite");
410  drawInfo.LineBackColor1 = PhHalveColorBrightness(drawInfo.LineColor1);
411  drawInfo.LineBackColor2 = PhHalveColorBrightness(drawInfo.LineColor2);
412 
413  if (bits)
414  PhDrawGraphDirect(hdc, bits, &drawInfo);
415 
416  SelectObject(hdc, oldBitmap);
417  *NewIconOrBitmap = bitmap;
418  *Flags = PH_NF_UPDATE_IS_BITMAP;
419 
420  // Text
421 
422  if (EtMaxNetworkHistory.Count != 0)
423  maxNetworkProcessId = UlongToHandle(PhGetItemCircularBuffer_ULONG(&EtMaxNetworkHistory, 0));
424  else
425  maxNetworkProcessId = NULL;
426 
427  if (maxNetworkProcessId)
428  maxNetworkProcessItem = PhReferenceProcessItem(maxNetworkProcessId);
429  else
430  maxNetworkProcessItem = NULL;
431 
432  PhInitFormatS(&format[0], L"Network\nR: ");
434  PhInitFormatS(&format[2], L"\nS: ");
436 
437  if (maxNetworkProcessItem)
438  {
439  PhInitFormatC(&format[4], '\n');
440  PhInitFormatSR(&format[5], maxNetworkProcessItem->ProcessName->sr);
441  }
442 
443  *NewText = PhFormat(format, maxNetworkProcessItem ? 6 : 4, 128);
444  if (maxNetworkProcessItem) PhDereferenceObject(maxNetworkProcessItem);
445 }
446 
448  _In_ struct _PH_NF_ICON *Icon,
449  _In_ ULONG_PTR WParam,
450  _In_ ULONG_PTR LParam,
451  _In_opt_ PVOID Context
452  )
453 {
454  switch (LOWORD(LParam))
455  {
457  {
458  PPH_NF_MSG_SHOWMINIINFOSECTION_DATA data = (PVOID)WParam;
459 
460  data->SectionName = L"Network";
461  }
462  return TRUE;
463  }
464 
465  return FALSE;
466 }