Process Hacker
main.c
Go to the documentation of this file.
1 /*
2  * Process Hacker Sandboxie Support -
3  * main program
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 <phdk.h>
24 #include "resource.h"
25 #include "sbiedll.h"
26 
27 typedef struct _BOX_INFO
28 {
29  WCHAR BoxName[34];
30  PH_STRINGREF IpcRoot;
31  WCHAR IpcRootBuffer[256];
33 
34 typedef struct _BOXED_PROCESS
35 {
36  HANDLE ProcessId;
37  WCHAR BoxName[34];
39 
40 VOID NTAPI LoadCallback(
41  _In_opt_ PVOID Parameter,
42  _In_opt_ PVOID Context
43  );
44 
46  _In_opt_ PVOID Parameter,
47  _In_opt_ PVOID Context
48  );
49 
51  _In_opt_ PVOID Parameter,
52  _In_opt_ PVOID Context
53  );
54 
56  _In_opt_ PVOID Parameter,
57  _In_opt_ PVOID Context
58  );
59 
61  _In_opt_ PVOID Parameter,
62  _In_opt_ PVOID Context
63  );
64 
66  _In_opt_ PVOID Parameter,
67  _In_opt_ PVOID Context
68  );
69 
71  _In_opt_ PVOID Parameter,
72  _In_opt_ PVOID Context
73  );
74 
76  _In_opt_ PVOID Parameter,
77  _In_opt_ PVOID Context
78  );
79 
81  _In_opt_ PVOID Context,
82  _In_ BOOLEAN TimerOrWaitFired
83  );
84 
85 INT_PTR CALLBACK OptionsDlgProc(
86  _In_ HWND hwndDlg,
87  _In_ UINT uMsg,
88  _In_ WPARAM wParam,
89  _In_ LPARAM lParam
90  );
91 
100 
105 
109 
112 
114  _In_ HINSTANCE Instance,
115  _In_ ULONG Reason,
116  _Reserved_ PVOID Reserved
117  )
118 {
119  switch (Reason)
120  {
121  case DLL_PROCESS_ATTACH:
122  {
124 
125  PluginInstance = PhRegisterPlugin(PLUGIN_NAME, Instance, &info);
126 
127  if (!PluginInstance)
128  return FALSE;
129 
130  info->DisplayName = L"Sandboxie Support";
131  info->Author = L"wj32";
132  info->Description = L"Provides functionality for sandboxed processes.";
133  info->Url = L"http://processhacker.sf.net/forums/viewtopic.php?t=1115";
134  info->HasOptions = TRUE;
135 
137  PhGetPluginCallback(PluginInstance, PluginCallbackLoad),
138  LoadCallback,
139  NULL,
140  &PluginLoadCallbackRegistration
141  );
145  NULL,
146  &PluginShowOptionsCallbackRegistration
147  );
151  NULL,
152  &PluginMenuItemCallbackRegistration
153  );
154 
158  NULL,
159  &MainMenuInitializingCallbackRegistration
160  );
164  NULL,
165  &ProcessesUpdatedCallbackRegistration
166  );
170  NULL,
171  &GetProcessHighlightingColorCallbackRegistration
172  );
176  NULL,
177  &GetProcessTooltipTextCallbackRegistration
178  );
179 
180  {
181  static PH_SETTING_CREATE settings[] =
182  {
183  { StringSettingType, SETTING_NAME_SBIE_DLL_PATH, L"C:\\Program Files\\Sandboxie\\SbieDll.dll" }
184  };
185 
186  PhAddSettings(settings, sizeof(settings) / sizeof(PH_SETTING_CREATE));
187  }
188  }
189  break;
190  }
191 
192  return TRUE;
193 }
194 
196  _In_ PVOID Entry1,
197  _In_ PVOID Entry2
198  )
199 {
200  return ((PBOXED_PROCESS)Entry1)->ProcessId == ((PBOXED_PROCESS)Entry2)->ProcessId;
201 }
202 
204  _In_ PVOID Entry
205  )
206 {
207  return HandleToUlong(((PBOXED_PROCESS)Entry)->ProcessId) / 4;
208 }
209 
210 VOID NTAPI LoadCallback(
211  _In_opt_ PVOID Parameter,
212  _In_opt_ PVOID Context
213  )
214 {
215  PPH_STRING sbieDllPath;
216  HMODULE module;
217  HANDLE timerQueueHandle;
218  HANDLE timerHandle;
219 
220  BoxedProcessesHashtable = PhCreateHashtable(
221  sizeof(BOXED_PROCESS),
224  32
225  );
226 
228  module = LoadLibrary(sbieDllPath->Buffer);
229  PhDereferenceObject(sbieDllPath);
230 
231  SbieApi_QueryBoxPath = (PVOID)GetProcAddress(module, SbieApi_QueryBoxPath_Name);
232  SbieApi_EnumBoxes = (PVOID)GetProcAddress(module, SbieApi_EnumBoxes_Name);
233  SbieApi_EnumProcessEx = (PVOID)GetProcAddress(module, SbieApi_EnumProcessEx_Name);
234  SbieDll_KillAll = (PVOID)GetProcAddress(module, SbieDll_KillAll_Name);
235 
236  if (NT_SUCCESS(RtlCreateTimerQueue(&timerQueueHandle)))
237  {
238  RtlCreateTimer(timerQueueHandle, &timerHandle, RefreshSandboxieInfo, NULL, 0, 4000, 0);
239  }
240 }
241 
243  _In_opt_ PVOID Parameter,
244  _In_opt_ PVOID Context
245  )
246 {
247  DialogBox(
248  PluginInstance->DllBase,
249  MAKEINTRESOURCE(IDD_OPTIONS),
250  (HWND)Parameter,
252  );
253 }
254 
255 VOID NTAPI MenuItemCallback(
256  _In_opt_ PVOID Parameter,
257  _In_opt_ PVOID Context
258  )
259 {
260  PPH_PLUGIN_MENU_ITEM menuItem = Parameter;
261 
262  switch (menuItem->Id)
263  {
264  case 1:
265  {
268  L"terminate",
269  L"all sandboxed processes",
270  NULL,
271  FALSE
272  ))
273  {
274  PBOXED_PROCESS boxedProcess;
275  ULONG enumerationKey = 0;
276 
277  // Make sure we have an update-to-date list.
279 
280  PhAcquireQueuedLockShared(&BoxedProcessesLock);
281 
282  while (PhEnumHashtable(BoxedProcessesHashtable, &boxedProcess, &enumerationKey))
283  {
284  HANDLE processHandle;
285 
286  if (NT_SUCCESS(PhOpenProcess(&processHandle, PROCESS_TERMINATE, boxedProcess->ProcessId)))
287  {
288  PhTerminateProcess(processHandle, STATUS_SUCCESS);
289  NtClose(processHandle);
290  }
291  }
292 
293  PhReleaseQueuedLockShared(&BoxedProcessesLock);
294  }
295  }
296  break;
297  }
298 }
299 
301  _In_opt_ PVOID Parameter,
302  _In_opt_ PVOID Context
303  )
304 {
305  PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter;
306 
307  if (!SbieDll_KillAll)
308  return;
309  if (menuInfo->u.MainMenu.SubMenuIndex != PH_MENU_ITEM_LOCATION_TOOLS)
310  return;
311 
312  PhInsertEMenuItem(menuInfo->Menu, PhPluginCreateEMenuItem(PluginInstance, PH_EMENU_SEPARATOR, 0, L"", NULL), -1);
313  PhInsertEMenuItem(menuInfo->Menu, PhPluginCreateEMenuItem(PluginInstance, 0, 1, L"Terminate Sandboxed Processes", NULL), -1);
314 }
315 
317  _In_opt_ PVOID Parameter,
318  _In_opt_ PVOID Context
319  )
320 {
321  PBOXED_PROCESS boxedProcess;
322  ULONG enumerationKey = 0;
323 
325  {
326  // Invalidate the nodes of boxed processes (so they use the correct highlighting color).
327 
328  PhAcquireQueuedLockShared(&BoxedProcessesLock);
329 
331  {
332  while (PhEnumHashtable(BoxedProcessesHashtable, &boxedProcess, &enumerationKey))
333  {
334  PPH_PROCESS_NODE processNode;
335 
336  if (processNode = PhFindProcessNode(boxedProcess->ProcessId))
337  PhUpdateProcessNode(processNode);
338  }
339 
341  }
342 
343  PhReleaseQueuedLockShared(&BoxedProcessesLock);
344  }
345 }
346 
348  _In_opt_ PVOID Parameter,
349  _In_opt_ PVOID Context
350  )
351 {
352  PPH_PLUGIN_GET_HIGHLIGHTING_COLOR getHighlightingColor = Parameter;
353  BOXED_PROCESS lookupBoxedProcess;
354  PBOXED_PROCESS boxedProcess;
355 
356  PhAcquireQueuedLockShared(&BoxedProcessesLock);
357 
358  lookupBoxedProcess.ProcessId = ((PPH_PROCESS_ITEM)getHighlightingColor->Parameter)->ProcessId;
359 
360  if (boxedProcess = PhFindEntryHashtable(BoxedProcessesHashtable, &lookupBoxedProcess))
361  {
362  getHighlightingColor->BackColor = RGB(0x33, 0x33, 0x00);
363  getHighlightingColor->Cache = TRUE;
364  getHighlightingColor->Handled = TRUE;
365  }
366 
367  PhReleaseQueuedLockShared(&BoxedProcessesLock);
368 }
369 
371  _In_opt_ PVOID Parameter,
372  _In_opt_ PVOID Context
373  )
374 {
375  PPH_PLUGIN_GET_TOOLTIP_TEXT getTooltipText = Parameter;
376  BOXED_PROCESS lookupBoxedProcess;
377  PBOXED_PROCESS boxedProcess;
378 
379  PhAcquireQueuedLockShared(&BoxedProcessesLock);
380 
381  lookupBoxedProcess.ProcessId = ((PPH_PROCESS_ITEM)getTooltipText->Parameter)->ProcessId;
382 
383  if (boxedProcess = PhFindEntryHashtable(BoxedProcessesHashtable, &lookupBoxedProcess))
384  {
385  PhAppendFormatStringBuilder(getTooltipText->StringBuilder, L"Sandboxie:\n Box name: %s\n", boxedProcess->BoxName);
386  }
387 
388  PhReleaseQueuedLockShared(&BoxedProcessesLock);
389 }
390 
392  _In_opt_ PVOID Context,
393  _In_ BOOLEAN TimerOrWaitFired
394  )
395 {
396  LONG index;
397  WCHAR boxName[34];
398  ULONG pids[512];
399  PBOX_INFO boxInfo;
400 
402  return;
403 
404  PhAcquireQueuedLockExclusive(&BoxedProcessesLock);
405 
406  PhClearHashtable(BoxedProcessesHashtable);
407 
408  BoxInfoCount = 0;
409 
410  index = -1;
411 
412  while ((index = SbieApi_EnumBoxes(index, boxName)) != -1)
413  {
414  if (SbieApi_EnumProcessEx(boxName, TRUE, 0, pids) == 0)
415  {
416  ULONG count;
417  PULONG pid;
418 
419  count = pids[0];
420  pid = &pids[1];
421 
422  while (count != 0)
423  {
424  BOXED_PROCESS boxedProcess;
425 
426  boxedProcess.ProcessId = ULongToHandle(*pid);
427  memcpy(boxedProcess.BoxName, boxName, sizeof(boxName));
428 
429  PhAddEntryHashtable(BoxedProcessesHashtable, &boxedProcess);
430 
431  count--;
432  pid++;
433  }
434  }
435 
436  if (BoxInfoCount < 16)
437  {
438  ULONG filePathLength = 0;
439  ULONG keyPathLength = 0;
440  ULONG ipcPathLength = 0;
441 
442  boxInfo = &BoxInfo[BoxInfoCount++];
443  memcpy(boxInfo->BoxName, boxName, sizeof(boxName));
444 
446  boxName,
447  NULL,
448  NULL,
449  NULL,
450  &filePathLength,
451  &keyPathLength,
452  &ipcPathLength
453  );
454 
455  if (ipcPathLength < sizeof(boxInfo->IpcRootBuffer))
456  {
457  boxInfo->IpcRootBuffer[0] = 0;
459  boxName,
460  NULL,
461  NULL,
462  boxInfo->IpcRootBuffer,
463  NULL,
464  NULL,
465  &ipcPathLength
466  );
467 
468  if (boxInfo->IpcRootBuffer[0] != 0)
469  {
470  PhInitializeStringRef(&boxInfo->IpcRoot, boxInfo->IpcRootBuffer);
471  }
472  else
473  {
474  BoxInfoCount--;
475  }
476  }
477  else
478  {
479  BoxInfoCount--;
480  }
481  }
482  }
483 
485 
486  PhReleaseQueuedLockExclusive(&BoxedProcessesLock);
487 }
488 
489 INT_PTR CALLBACK OptionsDlgProc(
490  _In_ HWND hwndDlg,
491  _In_ UINT uMsg,
492  _In_ WPARAM wParam,
493  _In_ LPARAM lParam
494  )
495 {
496  switch (uMsg)
497  {
498  case WM_INITDIALOG:
499  {
500  PPH_STRING sbieDllPath;
501 
503  SetDlgItemText(hwndDlg, IDC_SBIEDLLPATH, sbieDllPath->Buffer);
504  PhDereferenceObject(sbieDllPath);
505  }
506  break;
507  case WM_COMMAND:
508  {
509  switch (LOWORD(wParam))
510  {
511  case IDCANCEL:
512  EndDialog(hwndDlg, IDCANCEL);
513  break;
514  case IDOK:
515  {
517  &PhaGetDlgItemText(hwndDlg, IDC_SBIEDLLPATH)->sr);
518 
519  EndDialog(hwndDlg, IDOK);
520  }
521  break;
522  case IDC_BROWSE:
523  {
524  static PH_FILETYPE_FILTER filters[] =
525  {
526  { L"SbieDll.dll", L"SbieDll.dll" },
527  { L"All files (*.*)", L"*.*" }
528  };
529  PVOID fileDialog;
530  PPH_STRING fileName;
531 
532  fileDialog = PhCreateOpenFileDialog();
533  PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER));
534 
535  fileName = PhGetFileName(PhaGetDlgItemText(hwndDlg, IDC_SBIEDLLPATH));
536  PhSetFileDialogFileName(fileDialog, fileName->Buffer);
537  PhDereferenceObject(fileName);
538 
539  if (PhShowFileDialog(hwndDlg, fileDialog))
540  {
541  fileName = PhGetFileDialogFileName(fileDialog);
542  SetDlgItemText(hwndDlg, IDC_SBIEDLLPATH, fileName->Buffer);
543  PhDereferenceObject(fileName);
544  }
545 
546  PhFreeFileDialog(fileDialog);
547  }
548  break;
549  }
550  }
551  break;
552  }
553 
554  return FALSE;
555 }