Process Hacker
output.c
Go to the documentation of this file.
1 /*
2  * Process Hacker Network Tools -
3  * output dialog
4  *
5  * Copyright (C) 2010-2015 wj32
6  * Copyright (C) 2012-2015 dmex
7  *
8  * This file is part of Process Hacker.
9  *
10  * Process Hacker is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * Process Hacker is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #include "nettools.h"
25 
26 static RECT MinimumSize = { -1, -1, -1, -1 };
27 
28 static INT_PTR CALLBACK NetworkOutputDlgProc(
29  _In_ HWND hwndDlg,
30  _In_ UINT uMsg,
31  _In_ WPARAM wParam,
32  _In_ LPARAM lParam
33  )
34 {
36 
37  if (uMsg == WM_INITDIALOG)
38  {
39  context = (PNETWORK_OUTPUT_CONTEXT)lParam;
40  SetProp(hwndDlg, L"Context", (HANDLE)context);
41  }
42  else
43  {
44  context = (PNETWORK_OUTPUT_CONTEXT)GetProp(hwndDlg, L"Context");
45 
46  if (uMsg == WM_DESTROY)
47  {
50 
51  if (context->ProcessHandle)
52  {
53  // Terminate the child process.
54  PhTerminateProcess(context->ProcessHandle, STATUS_SUCCESS);
55 
56  // Close the child process handle.
57  NtClose(context->ProcessHandle);
58  }
59 
60  // Close the pipe handle.
61  if (context->PipeReadHandle)
62  NtClose(context->PipeReadHandle);
63 
64  RemoveProp(hwndDlg, L"Context");
65  PhFree(context);
66  }
67  }
68 
69  if (!context)
70  return FALSE;
71 
72  switch (uMsg)
73  {
74  case WM_INITDIALOG:
75  {
76  PH_RECTANGLE windowRectangle;
77 
78  context->WindowHandle = hwndDlg;
79  context->OutputHandle = GetDlgItem(hwndDlg, IDC_NETOUTPUTEDIT);
80 
81  PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
82  PhAddLayoutItem(&context->LayoutManager, context->OutputHandle, NULL, PH_ANCHOR_ALL);
83  PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_MORE_INFO), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
84  PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT);
85 
88 
89  if (MinimumSize.left == -1)
90  {
91  RECT rect;
92 
93  rect.left = 0;
94  rect.top = 0;
95  rect.right = 190;
96  rect.bottom = 120;
97  MapDialogRect(hwndDlg, &rect);
98  MinimumSize = rect;
99  MinimumSize.left = 0;
100  }
101 
102  // Check for first-run default position.
103  if (windowRectangle.Position.X == 0 || windowRectangle.Position.Y == 0)
104  {
105  PhCenterWindow(hwndDlg, GetParent(hwndDlg));
106  }
107  else
108  {
110  }
111 
112  if (context->IpAddress.Type == PH_IPV4_NETWORK_TYPE)
113  {
115  }
116  else
117  {
119  }
120 
121  switch (context->Action)
122  {
124  {
125  HANDLE dialogThread = INVALID_HANDLE_VALUE;
126 
127  Static_SetText(context->WindowHandle,
128  PhaFormatString(L"Tracing route to %s...", context->IpAddressString)->Buffer
129  );
130 
131  if (dialogThread = PhCreateThread(0, NetworkTracertThreadStart, (PVOID)context))
132  NtClose(dialogThread);
133  }
134  break;
136  {
137  HANDLE dialogThread = INVALID_HANDLE_VALUE;
138 
139  Static_SetText(context->WindowHandle,
140  PhaFormatString(L"Whois %s...", context->IpAddressString)->Buffer
141  );
142 
143  ShowWindow(GetDlgItem(hwndDlg, IDC_MORE_INFO), SW_SHOW);
144 
145  if (dialogThread = PhCreateThread(0, NetworkWhoisThreadStart, (PVOID)context))
146  NtClose(dialogThread);
147  }
148  break;
149  }
150  }
151  break;
152  case WM_COMMAND:
153  {
154  switch (LOWORD(wParam))
155  {
156  case IDCANCEL:
157  case IDOK:
158  PostQuitMessage(0);
159  break;
160  }
161  }
162  break;
163  case WM_SIZE:
165  break;
166  case WM_SIZING:
167  PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom);
168  break;
169  case WM_CTLCOLORDLG:
170  case WM_CTLCOLORSTATIC:
171  {
172  HDC hDC = (HDC)wParam;
173  HWND hwndChild = (HWND)lParam;
174 
175  // Check if old graph colors are enabled.
176  if (!PhGetIntegerSetting(L"GraphColorMode"))
177  break;
178 
179  // Set a transparent background for the control backcolor.
180  SetBkMode(hDC, TRANSPARENT);
181 
182  // Check for our edit control and change the color.
183  if (hwndChild == context->OutputHandle)
184  {
185  // Set text color as the Green PH graph text color.
186  SetTextColor(hDC, RGB(124, 252, 0));
187 
188  // Set a black control backcolor.
189  return (INT_PTR)GetStockBrush(BLACK_BRUSH);
190  }
191  }
192  break;
193  case WM_NOTIFY:
194  {
195  switch (((LPNMHDR)lParam)->code)
196  {
197  case NM_CLICK:
198  case NM_RETURN:
199  {
200  PNMLINK syslink = (PNMLINK)lParam;
201 
202  if (syslink->hdr.idFrom == IDC_MORE_INFO)
203  {
206  PhaConcatStrings2(L"http://wq.apnic.net/apnic-bin/whois.pl?searchtext=", context->IpAddressString)->Buffer,
207  NULL
208  );
209  }
210  }
211  break;
212  }
213  }
214  break;
215  case NTM_RECEIVEDTRACE:
216  {
217  OEM_STRING inputString;
218  UNICODE_STRING convertedString;
219  PH_STRING_BUILDER receivedString;
220 
221  if (wParam != 0)
222  {
223  inputString.Buffer = (PCHAR)lParam;
224  inputString.Length = (USHORT)wParam;
225 
226  if (NT_SUCCESS(RtlOemStringToUnicodeString(&convertedString, &inputString, TRUE)))
227  {
228  PPH_STRING windowText = NULL;
229 
230  PhInitializeStringBuilder(&receivedString, PAGE_SIZE);
231 
232  // Get the current output text.
233  windowText = PhGetWindowText(context->OutputHandle);
234 
235  // Append the current output text to the New string.
236  if (!PhIsNullOrEmptyString(windowText))
237  PhAppendStringBuilder(&receivedString, &windowText->sr);
238 
239  PhAppendFormatStringBuilder(&receivedString, L"%s", convertedString.Buffer);
240 
241  // Remove leading newlines.
242  if (receivedString.String->Length >= 2 * 2 &&
243  receivedString.String->Buffer[0] == '\r' &&
244  receivedString.String->Buffer[1] == '\n')
245  {
246  PhRemoveStringBuilder(&receivedString, 0, 2);
247  }
248 
249  SetWindowText(context->OutputHandle, receivedString.String->Buffer);
250  SendMessage(
251  context->OutputHandle,
252  EM_SETSEL,
253  receivedString.String->Length / 2 - 1,
254  receivedString.String->Length / 2 - 1
255  );
256  SendMessage(context->OutputHandle, WM_VSCROLL, SB_BOTTOM, 0);
257 
258  PhDereferenceObject(windowText);
259  PhDeleteStringBuilder(&receivedString);
260  RtlFreeUnicodeString(&convertedString);
261  }
262  }
263  }
264  break;
265  case NTM_RECEIVEDWHOIS:
266  {
267  OEM_STRING inputString;
268  UNICODE_STRING convertedString;
269  PH_STRING_BUILDER receivedString;
270 
271  if (lParam != 0)
272  {
273  inputString.Buffer = (PCHAR)lParam;
274  inputString.Length = (USHORT)wParam;
275 
276  if (NT_SUCCESS(RtlOemStringToUnicodeString(&convertedString, &inputString, TRUE)))
277  {
278  USHORT i;
279 
280  PhInitializeStringBuilder(&receivedString, PAGE_SIZE);
281 
282  // Convert carriage returns.
283  for (i = 0; i < convertedString.Length; i++)
284  {
285  if (convertedString.Buffer[i] == '\n')
286  {
287  PhAppendStringBuilder2(&receivedString, L"\r\n");
288  }
289  else
290  {
291  PhAppendCharStringBuilder(&receivedString, convertedString.Buffer[i]);
292  }
293  }
294 
295  // Remove leading newlines.
296  if (receivedString.String->Length >= 2 * 2 &&
297  receivedString.String->Buffer[0] == '\r' &&
298  receivedString.String->Buffer[1] == '\n')
299  {
300  PhRemoveStringBuilder(&receivedString, 0, 2);
301  }
302 
303  SetWindowText(context->OutputHandle, receivedString.String->Buffer);
304  SendMessage(
305  context->OutputHandle,
306  EM_SETSEL,
307  receivedString.String->Length / 2 - 1,
308  receivedString.String->Length / 2 - 1
309  );
310  SendMessage(context->OutputHandle, WM_VSCROLL, SB_TOP, 0);
311 
312  PhDeleteStringBuilder(&receivedString);
313  RtlFreeUnicodeString(&convertedString);
314  }
315 
316  PhFree((PVOID)lParam);
317  }
318  }
319  break;
320  case NTM_RECEIVEDFINISH:
321  {
322  PPH_STRING windowText = PhGetWindowText(context->WindowHandle);
323 
324  if (windowText)
325  {
326  Static_SetText(
327  context->WindowHandle,
328  PhaFormatString(L"%s Finished.", windowText->Buffer)->Buffer
329  );
330  PhDereferenceObject(windowText);
331  }
332  }
333  break;
334  }
335 
336  return FALSE;
337 }
338 
339 static NTSTATUS PhNetworkOutputDialogThreadStart(
340  _In_ PVOID Parameter
341  )
342 {
343  BOOL result;
344  MSG message;
345  HWND windowHandle;
346  PH_AUTO_POOL autoPool;
348 
349  PhInitializeAutoPool(&autoPool);
350 
351  windowHandle = CreateDialogParam(
352  (HINSTANCE)PluginInstance->DllBase,
353  MAKEINTRESOURCE(IDD_OUTPUT),
356  (LPARAM)Parameter
357  );
358 
359  ShowWindow(windowHandle, SW_SHOW);
360  SetForegroundWindow(windowHandle);
361 
362  while (result = GetMessage(&message, NULL, 0, 0))
363  {
364  if (result == -1)
365  break;
366 
367  if (!IsDialogMessage(context->WindowHandle, &message))
368  {
369  TranslateMessage(&message);
370  DispatchMessage(&message);
371  }
372 
373  PhDrainAutoPool(&autoPool);
374  }
375 
376  PhDeleteAutoPool(&autoPool);
377  DestroyWindow(windowHandle);
378 
379  return STATUS_SUCCESS;
380 }
381 
383  _In_ PH_NETWORK_ACTION Action,
384  _In_ PPH_NETWORK_ITEM NetworkItem
385  )
386 {
387  HANDLE dialogThread = INVALID_HANDLE_VALUE;
388  PNETWORK_OUTPUT_CONTEXT context;
389 
390  context = (PNETWORK_OUTPUT_CONTEXT)PhAllocate(sizeof(NETWORK_OUTPUT_CONTEXT));
391  memset(context, 0, sizeof(NETWORK_OUTPUT_CONTEXT));
392 
393  context->Action = Action;
394  context->NetworkItem = NetworkItem;
395  context->IpAddress = NetworkItem->RemoteEndpoint.Address;
396 
397  if (context->Action == NETWORK_ACTION_PING)
398  {
399  if (dialogThread = PhCreateThread(0, PhNetworkPingDialogThreadStart, (PVOID)context))
400  NtClose(dialogThread);
401  }
402  else
403  {
404  if (dialogThread = PhCreateThread(0, PhNetworkOutputDialogThreadStart, (PVOID)context))
405  NtClose(dialogThread);
406  }
407 }