Process Hacker
etwsys.c
Go to the documentation of this file.
1 /*
2  * Process Hacker Extended Tools -
3  * ETW system information section
4  *
5  * Copyright (C) 2010-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 #include "resource.h"
25 #include <windowsx.h>
26 #include "etwsys.h"
27 
28 static PPH_SYSINFO_SECTION DiskSection;
29 static HWND DiskDialog;
30 static PH_LAYOUT_MANAGER DiskLayoutManager;
31 static HWND DiskGraphHandle;
32 static PH_GRAPH_STATE DiskGraphState;
33 static HWND DiskPanel;
34 
35 static PPH_SYSINFO_SECTION NetworkSection;
36 static HWND NetworkDialog;
37 static PH_LAYOUT_MANAGER NetworkLayoutManager;
38 static HWND NetworkGraphHandle;
39 static PH_GRAPH_STATE NetworkGraphState;
40 static HWND NetworkPanel;
41 
43  _In_ PPH_PLUGIN_SYSINFO_POINTERS Pointers
44  )
45 {
46  PH_SYSINFO_SECTION section;
47 
48  memset(&section, 0, sizeof(PH_SYSINFO_SECTION));
49  PhInitializeStringRef(&section.Name, L"Disk");
50  section.Flags = 0;
52 
53  DiskSection = Pointers->CreateSection(&section);
54 
55  memset(&section, 0, sizeof(PH_SYSINFO_SECTION));
56  PhInitializeStringRef(&section.Name, L"Network");
57  section.Flags = 0;
59 
60  NetworkSection = Pointers->CreateSection(&section);
61 }
62 
64  _In_ PPH_SYSINFO_SECTION Section,
65  _In_ PH_SYSINFO_SECTION_MESSAGE Message,
66  _In_opt_ PVOID Parameter1,
67  _In_opt_ PVOID Parameter2
68  )
69 {
70  switch (Message)
71  {
72  case SysInfoDestroy:
73  {
74  if (DiskDialog)
75  {
76  PhDeleteGraphState(&DiskGraphState);
77  DiskDialog = NULL;
78  }
79  }
80  return TRUE;
81  case SysInfoTick:
82  {
83  if (DiskDialog)
84  {
87  }
88  }
89  return TRUE;
91  {
92  PPH_SYSINFO_CREATE_DIALOG createDialog = Parameter1;
93 
94  createDialog->Instance = PluginInstance->DllBase;
95  createDialog->Template = MAKEINTRESOURCE(IDD_SYSINFO_DISK);
96  createDialog->DialogProc = EtpDiskDialogProc;
97  }
98  return TRUE;
100  {
101  PPH_GRAPH_DRAW_INFO drawInfo = Parameter1;
102 
104  Section->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorIoReadOther"), PhGetIntegerSetting(L"ColorIoWrite"));
105  PhGetDrawInfoGraphBuffers(&Section->GraphState.Buffers, drawInfo, EtDiskReadHistory.Count);
106 
107  if (!Section->GraphState.Valid)
108  {
109  ULONG i;
110  FLOAT max = 0;
111 
112  for (i = 0; i < drawInfo->LineDataCount; i++)
113  {
114  FLOAT data1;
115  FLOAT data2;
116 
117  Section->GraphState.Data1[i] = data1 =
118  (FLOAT)PhGetItemCircularBuffer_ULONG(&EtDiskReadHistory, i);
119  Section->GraphState.Data2[i] = data2 =
120  (FLOAT)PhGetItemCircularBuffer_ULONG(&EtDiskWriteHistory, i);
121 
122  if (max < data1 + data2)
123  max = data1 + data2;
124  }
125 
126  // Minimum scaling of 1 MB.
127  if (max < 1024 * 1024)
128  max = 1024 * 1024;
129 
130  // Scale the data.
131 
133  Section->GraphState.Data1,
134  max,
135  drawInfo->LineDataCount
136  );
138  Section->GraphState.Data2,
139  max,
140  drawInfo->LineDataCount
141  );
142 
143  Section->GraphState.Valid = TRUE;
144  }
145  }
146  return TRUE;
148  {
149  PPH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT getTooltipText = Parameter1;
150  ULONG64 diskRead;
151  ULONG64 diskWrite;
152 
153  diskRead = PhGetItemCircularBuffer_ULONG(&EtDiskReadHistory, getTooltipText->Index);
154  diskWrite = PhGetItemCircularBuffer_ULONG(&EtDiskWriteHistory, getTooltipText->Index);
155 
156  PhMoveReference(&Section->GraphState.TooltipText, PhFormatString(
157  L"R: %s\nW: %s%s\n%s",
158  PhaFormatSize(diskRead, -1)->Buffer,
159  PhaFormatSize(diskWrite, -1)->Buffer,
160  PhGetStringOrEmpty(EtpGetMaxDiskString(getTooltipText->Index)),
161  ((PPH_STRING)PhAutoDereferenceObject(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
162  ));
163  getTooltipText->Text = Section->GraphState.TooltipText->sr;
164  }
165  return TRUE;
167  {
168  PPH_SYSINFO_DRAW_PANEL drawPanel = Parameter1;
169 
170  drawPanel->Title = PhCreateString(L"Disk");
171  drawPanel->SubTitle = PhFormatString(
172  L"R: %s\nW: %s",
173  PhaFormatSize(EtDiskReadDelta.Delta, -1)->Buffer,
175  );
176  }
177  return TRUE;
178  }
179 
180  return FALSE;
181 }
182 
183 INT_PTR CALLBACK EtpDiskDialogProc(
184  _In_ HWND hwndDlg,
185  _In_ UINT uMsg,
186  _In_ WPARAM wParam,
187  _In_ LPARAM lParam
188  )
189 {
190  switch (uMsg)
191  {
192  case WM_INITDIALOG:
193  {
194  PPH_LAYOUT_ITEM graphItem;
195  PPH_LAYOUT_ITEM panelItem;
196 
197  PhInitializeGraphState(&DiskGraphState);
198 
199  DiskDialog = hwndDlg;
200  PhInitializeLayoutManager(&DiskLayoutManager, hwndDlg);
201  graphItem = PhAddLayoutItem(&DiskLayoutManager, GetDlgItem(hwndDlg, IDC_GRAPH_LAYOUT), NULL, PH_ANCHOR_ALL);
202  panelItem = PhAddLayoutItem(&DiskLayoutManager, GetDlgItem(hwndDlg, IDC_PANEL_LAYOUT), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM);
203 
204  SendMessage(GetDlgItem(hwndDlg, IDC_TITLE), WM_SETFONT, (WPARAM)DiskSection->Parameters->LargeFont, FALSE);
205 
206  DiskPanel = CreateDialog(PluginInstance->DllBase, MAKEINTRESOURCE(IDD_SYSINFO_DISKPANEL), hwndDlg, EtpDiskPanelDialogProc);
207  ShowWindow(DiskPanel, SW_SHOW);
208  PhAddLayoutItemEx(&DiskLayoutManager, DiskPanel, NULL, PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM, panelItem->Margin);
209 
210  DiskGraphHandle = CreateWindow(
212  NULL,
213  WS_VISIBLE | WS_CHILD | WS_BORDER,
214  0,
215  0,
216  3,
217  3,
218  hwndDlg,
219  NULL,
220  NULL,
221  NULL
222  );
223  Graph_SetTooltip(DiskGraphHandle, TRUE);
224 
225  PhAddLayoutItemEx(&DiskLayoutManager, DiskGraphHandle, NULL, PH_ANCHOR_ALL, graphItem->Margin);
226 
229  }
230  break;
231  case WM_DESTROY:
232  {
233  PhDeleteLayoutManager(&DiskLayoutManager);
234  }
235  break;
236  case WM_SIZE:
237  {
238  PhLayoutManagerLayout(&DiskLayoutManager);
239  }
240  break;
241  case WM_NOTIFY:
242  {
243  NMHDR *header = (NMHDR *)lParam;
244 
245  if (header->hwndFrom == DiskGraphHandle)
246  {
247  EtpNotifyDiskGraph(header);
248  }
249  }
250  break;
251  }
252 
253  return FALSE;
254 }
255 
256 INT_PTR CALLBACK EtpDiskPanelDialogProc(
257  _In_ HWND hwndDlg,
258  _In_ UINT uMsg,
259  _In_ WPARAM wParam,
260  _In_ LPARAM lParam
261  )
262 {
263  return FALSE;
264 }
265 
267  _In_ NMHDR *Header
268  )
269 {
270  switch (Header->code)
271  {
272  case GCN_GETDRAWINFO:
273  {
274  PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)Header;
275  PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo;
276 
278  DiskSection->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorIoReadOther"), PhGetIntegerSetting(L"ColorIoWrite"));
279 
281  &DiskGraphState,
282  getDrawInfo,
283  EtDiskReadHistory.Count
284  );
285 
286  if (!DiskGraphState.Valid)
287  {
288  ULONG i;
289  FLOAT max = 0;
290 
291  for (i = 0; i < drawInfo->LineDataCount; i++)
292  {
293  FLOAT data1;
294  FLOAT data2;
295 
296  DiskGraphState.Data1[i] = data1 =
297  (FLOAT)PhGetItemCircularBuffer_ULONG(&EtDiskReadHistory, i);
298  DiskGraphState.Data2[i] = data2 =
299  (FLOAT)PhGetItemCircularBuffer_ULONG(&EtDiskWriteHistory, i);
300 
301  if (max < data1 + data2)
302  max = data1 + data2;
303  }
304 
305  // Minimum scaling of 1 MB.
306  if (max < 1024 * 1024)
307  max = 1024 * 1024;
308 
309  // Scale the data.
310 
312  DiskGraphState.Data1,
313  max,
314  drawInfo->LineDataCount
315  );
317  DiskGraphState.Data2,
318  max,
319  drawInfo->LineDataCount
320  );
321 
322  DiskGraphState.Valid = TRUE;
323  }
324  }
325  break;
326  case GCN_GETTOOLTIPTEXT:
327  {
328  PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)Header;
329 
330  if (getTooltipText->Index < getTooltipText->TotalCount)
331  {
332  if (DiskGraphState.TooltipIndex != getTooltipText->Index)
333  {
334  ULONG64 diskRead;
335  ULONG64 diskWrite;
336 
337  diskRead = PhGetItemCircularBuffer_ULONG(&EtDiskReadHistory, getTooltipText->Index);
338  diskWrite = PhGetItemCircularBuffer_ULONG(&EtDiskWriteHistory, getTooltipText->Index);
339 
340  PhMoveReference(&DiskGraphState.TooltipText, PhFormatString(
341  L"R: %s\nW: %s%s\n%s",
342  PhaFormatSize(diskRead, -1)->Buffer,
343  PhaFormatSize(diskWrite, -1)->Buffer,
344  PhGetStringOrEmpty(EtpGetMaxDiskString(getTooltipText->Index)),
345  ((PPH_STRING)PhAutoDereferenceObject(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
346  ));
347  }
348 
349  getTooltipText->Text = DiskGraphState.TooltipText->sr;
350  }
351  }
352  break;
353  case GCN_MOUSEEVENT:
354  {
355  PPH_GRAPH_MOUSEEVENT mouseEvent = (PPH_GRAPH_MOUSEEVENT)Header;
356  PPH_PROCESS_RECORD record;
357 
358  record = NULL;
359 
360  if (mouseEvent->Message == WM_LBUTTONDBLCLK && mouseEvent->Index < mouseEvent->TotalCount)
361  {
362  record = EtpReferenceMaxDiskRecord(mouseEvent->Index);
363  }
364 
365  if (record)
366  {
367  PhShowProcessRecordDialog(DiskDialog, record);
369  }
370  }
371  break;
372  }
373 }
374 
376  VOID
377  )
378 {
379  DiskGraphState.Valid = FALSE;
380  DiskGraphState.TooltipIndex = -1;
381  Graph_MoveGrid(DiskGraphHandle, 1);
382  Graph_Draw(DiskGraphHandle);
383  Graph_UpdateTooltip(DiskGraphHandle);
384  InvalidateRect(DiskGraphHandle, NULL, FALSE);
385 }
386 
388  VOID
389  )
390 {
391  SetDlgItemText(DiskPanel, IDC_ZREADSDELTA_V, PhaFormatUInt64(EtDiskReadCountDelta.Delta, TRUE)->Buffer);
392  SetDlgItemText(DiskPanel, IDC_ZREADBYTESDELTA_V, PhaFormatSize(EtDiskReadDelta.Delta, -1)->Buffer);
393  SetDlgItemText(DiskPanel, IDC_ZWRITESDELTA_V, PhaFormatUInt64(EtDiskWriteCountDelta.Delta, TRUE)->Buffer);
394  SetDlgItemText(DiskPanel, IDC_ZWRITEBYTESDELTA_V, PhaFormatSize(EtDiskWriteDelta.Delta, -1)->Buffer);
395 }
396 
398  _In_ LONG Index
399  )
400 {
401  LARGE_INTEGER time;
402  ULONG maxProcessId;
403 
404  maxProcessId = PhGetItemCircularBuffer_ULONG(&EtMaxDiskHistory, Index);
405 
406  if (!maxProcessId)
407  return NULL;
408 
409  PhGetStatisticsTime(NULL, Index, &time);
410  time.QuadPart += PH_TICKS_PER_SEC - 1;
411 
412  return PhFindProcessRecord(UlongToHandle(maxProcessId), &time);
413 }
414 
416  _In_ LONG Index
417  )
418 {
419  PPH_PROCESS_RECORD maxProcessRecord;
420  PPH_STRING maxUsageString = NULL;
421 
422  if (maxProcessRecord = EtpReferenceMaxDiskRecord(Index))
423  {
424  maxUsageString = PhaFormatString(
425  L"\n%s (%lu)",
426  maxProcessRecord->ProcessName->Buffer,
427  HandleToUlong(maxProcessRecord->ProcessId)
428  );
429  PhDereferenceProcessRecord(maxProcessRecord);
430  }
431 
432  return maxUsageString;
433 }
434 
436  _In_ PPH_SYSINFO_SECTION Section,
437  _In_ PH_SYSINFO_SECTION_MESSAGE Message,
438  _In_opt_ PVOID Parameter1,
439  _In_opt_ PVOID Parameter2
440  )
441 {
442  switch (Message)
443  {
444  case SysInfoDestroy:
445  {
446  if (NetworkDialog)
447  {
448  PhDeleteGraphState(&NetworkGraphState);
449  NetworkDialog = NULL;
450  }
451  }
452  return TRUE;
453  case SysInfoTick:
454  {
455  if (NetworkDialog)
456  {
459  }
460  }
461  return TRUE;
462  case SysInfoCreateDialog:
463  {
464  PPH_SYSINFO_CREATE_DIALOG createDialog = Parameter1;
465 
466  createDialog->Instance = PluginInstance->DllBase;
467  createDialog->Template = MAKEINTRESOURCE(IDD_SYSINFO_NET);
468  createDialog->DialogProc = EtpNetworkDialogProc;
469  }
470  return TRUE;
472  {
473  PPH_GRAPH_DRAW_INFO drawInfo = Parameter1;
474 
476  Section->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorIoReadOther"), PhGetIntegerSetting(L"ColorIoWrite"));
477  PhGetDrawInfoGraphBuffers(&Section->GraphState.Buffers, drawInfo, EtNetworkReceiveHistory.Count);
478 
479  if (!Section->GraphState.Valid)
480  {
481  ULONG i;
482  FLOAT max = 0;
483 
484  for (i = 0; i < drawInfo->LineDataCount; i++)
485  {
486  FLOAT data1;
487  FLOAT data2;
488 
489  Section->GraphState.Data1[i] = data1 =
490  (FLOAT)PhGetItemCircularBuffer_ULONG(&EtNetworkReceiveHistory, i);
491  Section->GraphState.Data2[i] = data2 =
492  (FLOAT)PhGetItemCircularBuffer_ULONG(&EtNetworkSendHistory, i);
493 
494  if (max < data1 + data2)
495  max = data1 + data2;
496  }
497 
498  // Minimum scaling of 1 MB.
499  if (max < 1024 * 1024)
500  max = 1024 * 1024;
501 
502  // Scale the data.
503 
505  Section->GraphState.Data1,
506  max,
507  drawInfo->LineDataCount
508  );
510  Section->GraphState.Data2,
511  max,
512  drawInfo->LineDataCount
513  );
514 
515  Section->GraphState.Valid = TRUE;
516  }
517  }
518  return TRUE;
520  {
521  PPH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT getTooltipText = Parameter1;
522  ULONG64 networkReceive;
523  ULONG64 networkSend;
524 
525  networkReceive = PhGetItemCircularBuffer_ULONG(&EtNetworkReceiveHistory, getTooltipText->Index);
526  networkSend = PhGetItemCircularBuffer_ULONG(&EtNetworkSendHistory, getTooltipText->Index);
527 
528  PhMoveReference(&Section->GraphState.TooltipText, PhFormatString(
529  L"R: %s\nS: %s%s\n%s",
530  PhaFormatSize(networkReceive, -1)->Buffer,
531  PhaFormatSize(networkSend, -1)->Buffer,
533  ((PPH_STRING)PhAutoDereferenceObject(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
534  ));
535  getTooltipText->Text = Section->GraphState.TooltipText->sr;
536  }
537  return TRUE;
539  {
540  PPH_SYSINFO_DRAW_PANEL drawPanel = Parameter1;
541 
542  drawPanel->Title = PhCreateString(L"Network");
543  drawPanel->SubTitle = PhFormatString(
544  L"R: %s\nS: %s",
547  );
548  }
549  return TRUE;
550  }
551 
552  return FALSE;
553 }
554 
555 INT_PTR CALLBACK EtpNetworkDialogProc(
556  _In_ HWND hwndDlg,
557  _In_ UINT uMsg,
558  _In_ WPARAM wParam,
559  _In_ LPARAM lParam
560  )
561 {
562  switch (uMsg)
563  {
564  case WM_INITDIALOG:
565  {
566  PPH_LAYOUT_ITEM graphItem;
567  PPH_LAYOUT_ITEM panelItem;
568 
569  PhInitializeGraphState(&NetworkGraphState);
570 
571  NetworkDialog = hwndDlg;
572  PhInitializeLayoutManager(&NetworkLayoutManager, hwndDlg);
573  graphItem = PhAddLayoutItem(&NetworkLayoutManager, GetDlgItem(hwndDlg, IDC_GRAPH_LAYOUT), NULL, PH_ANCHOR_ALL);
574  panelItem = PhAddLayoutItem(&NetworkLayoutManager, GetDlgItem(hwndDlg, IDC_PANEL_LAYOUT), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM);
575 
576  SendMessage(GetDlgItem(hwndDlg, IDC_TITLE), WM_SETFONT, (WPARAM)NetworkSection->Parameters->LargeFont, FALSE);
577 
578  NetworkPanel = CreateDialog(PluginInstance->DllBase, MAKEINTRESOURCE(IDD_SYSINFO_NETPANEL), hwndDlg, EtpNetworkPanelDialogProc);
579  ShowWindow(NetworkPanel, SW_SHOW);
580  PhAddLayoutItemEx(&NetworkLayoutManager, NetworkPanel, NULL, PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM, panelItem->Margin);
581 
582  NetworkGraphHandle = CreateWindow(
584  NULL,
585  WS_VISIBLE | WS_CHILD | WS_BORDER,
586  0,
587  0,
588  3,
589  3,
590  hwndDlg,
591  NULL,
592  NULL,
593  NULL
594  );
595  Graph_SetTooltip(NetworkGraphHandle, TRUE);
596 
597  PhAddLayoutItemEx(&NetworkLayoutManager, NetworkGraphHandle, NULL, PH_ANCHOR_ALL, graphItem->Margin);
598 
601  }
602  break;
603  case WM_DESTROY:
604  {
605  PhDeleteLayoutManager(&NetworkLayoutManager);
606  }
607  break;
608  case WM_SIZE:
609  {
610  PhLayoutManagerLayout(&NetworkLayoutManager);
611  }
612  break;
613  case WM_NOTIFY:
614  {
615  NMHDR *header = (NMHDR *)lParam;
616 
617  if (header->hwndFrom == NetworkGraphHandle)
618  {
619  EtpNotifyNetworkGraph(header);
620  }
621  }
622  break;
623  }
624 
625  return FALSE;
626 }
627 
628 INT_PTR CALLBACK EtpNetworkPanelDialogProc(
629  _In_ HWND hwndDlg,
630  _In_ UINT uMsg,
631  _In_ WPARAM wParam,
632  _In_ LPARAM lParam
633  )
634 {
635  return FALSE;
636 }
637 
639  _In_ NMHDR *Header
640  )
641 {
642  switch (Header->code)
643  {
644  case GCN_GETDRAWINFO:
645  {
646  PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)Header;
647  PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo;
648 
650  NetworkSection->Parameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorIoReadOther"), PhGetIntegerSetting(L"ColorIoWrite"));
651 
653  &NetworkGraphState,
654  getDrawInfo,
656  );
657 
658  if (!NetworkGraphState.Valid)
659  {
660  ULONG i;
661  FLOAT max = 0;
662 
663  for (i = 0; i < drawInfo->LineDataCount; i++)
664  {
665  FLOAT data1;
666  FLOAT data2;
667 
668  NetworkGraphState.Data1[i] = data1 =
669  (FLOAT)PhGetItemCircularBuffer_ULONG(&EtNetworkReceiveHistory, i);
670  NetworkGraphState.Data2[i] = data2 =
671  (FLOAT)PhGetItemCircularBuffer_ULONG(&EtNetworkSendHistory, i);
672 
673  if (max < data1 + data2)
674  max = data1 + data2;
675  }
676 
677  // Minimum scaling of 1 MB.
678  if (max < 1024 * 1024)
679  max = 1024 * 1024;
680 
681  // Scale the data.
682 
684  NetworkGraphState.Data1,
685  max,
686  drawInfo->LineDataCount
687  );
689  NetworkGraphState.Data2,
690  max,
691  drawInfo->LineDataCount
692  );
693 
694  NetworkGraphState.Valid = TRUE;
695  }
696  }
697  break;
698  case GCN_GETTOOLTIPTEXT:
699  {
700  PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)Header;
701 
702  if (getTooltipText->Index < getTooltipText->TotalCount)
703  {
704  if (NetworkGraphState.TooltipIndex != getTooltipText->Index)
705  {
706  ULONG64 networkReceive;
707  ULONG64 networkSend;
708 
709  networkReceive = PhGetItemCircularBuffer_ULONG(&EtNetworkReceiveHistory, getTooltipText->Index);
710  networkSend = PhGetItemCircularBuffer_ULONG(&EtNetworkSendHistory, getTooltipText->Index);
711 
712  PhMoveReference(&NetworkGraphState.TooltipText, PhFormatString(
713  L"R: %s\nS: %s%s\n%s",
714  PhaFormatSize(networkReceive, -1)->Buffer,
715  PhaFormatSize(networkSend, -1)->Buffer,
717  ((PPH_STRING)PhAutoDereferenceObject(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
718  ));
719  }
720 
721  getTooltipText->Text = NetworkGraphState.TooltipText->sr;
722  }
723  }
724  break;
725  case GCN_MOUSEEVENT:
726  {
727  PPH_GRAPH_MOUSEEVENT mouseEvent = (PPH_GRAPH_MOUSEEVENT)Header;
728  PPH_PROCESS_RECORD record;
729 
730  record = NULL;
731 
732  if (mouseEvent->Message == WM_LBUTTONDBLCLK && mouseEvent->Index < mouseEvent->TotalCount)
733  {
734  record = EtpReferenceMaxNetworkRecord(mouseEvent->Index);
735  }
736 
737  if (record)
738  {
739  PhShowProcessRecordDialog(NetworkDialog, record);
741  }
742  }
743  break;
744  }
745 }
746 
748  VOID
749  )
750 {
751  NetworkGraphState.Valid = FALSE;
752  NetworkGraphState.TooltipIndex = -1;
753  Graph_MoveGrid(NetworkGraphHandle, 1);
754  Graph_Draw(NetworkGraphHandle);
755  Graph_UpdateTooltip(NetworkGraphHandle);
756  InvalidateRect(NetworkGraphHandle, NULL, FALSE);
757 }
758 
760  VOID
761  )
762 {
763  SetDlgItemText(NetworkPanel, IDC_ZRECEIVESDELTA_V, PhaFormatUInt64(EtNetworkReceiveCountDelta.Delta, TRUE)->Buffer);
764  SetDlgItemText(NetworkPanel, IDC_ZRECEIVEBYTESDELTA_V, PhaFormatSize(EtNetworkReceiveDelta.Delta, -1)->Buffer);
765  SetDlgItemText(NetworkPanel, IDC_ZSENDSDELTA_V, PhaFormatUInt64(EtNetworkSendCountDelta.Delta, TRUE)->Buffer);
766  SetDlgItemText(NetworkPanel, IDC_ZSENDBYTESDELTA_V, PhaFormatSize(EtNetworkSendDelta.Delta, -1)->Buffer);
767 }
768 
770  _In_ LONG Index
771  )
772 {
773  LARGE_INTEGER time;
774  ULONG maxProcessId;
775 
776  maxProcessId = PhGetItemCircularBuffer_ULONG(&EtMaxNetworkHistory, Index);
777 
778  if (!maxProcessId)
779  return NULL;
780 
781  PhGetStatisticsTime(NULL, Index, &time);
782  time.QuadPart += PH_TICKS_PER_SEC - 1;
783 
784  return PhFindProcessRecord(UlongToHandle(maxProcessId), &time);
785 }
786 
788  _In_ LONG Index
789  )
790 {
791  PPH_PROCESS_RECORD maxProcessRecord;
792  PPH_STRING maxUsageString = NULL;
793 
794  if (maxProcessRecord = EtpReferenceMaxNetworkRecord(Index))
795  {
796  maxUsageString = PhaFormatString(
797  L"\n%s (%lu)",
798  maxProcessRecord->ProcessName->Buffer,
799  HandleToUlong(maxProcessRecord->ProcessId)
800  );
801  PhDereferenceProcessRecord(maxProcessRecord);
802  }
803 
804  return maxUsageString;
805 }