Process Hacker
main.c
Go to the documentation of this file.
1 /*
2  * Process Hacker Window Explorer -
3  * main program
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 "wndexp.h"
24 #include "resource.h"
25 
26 VOID NTAPI LoadCallback(
27  _In_opt_ PVOID Parameter,
28  _In_opt_ PVOID Context
29  );
30 
31 VOID NTAPI UnloadCallback(
32  _In_opt_ PVOID Parameter,
33  _In_opt_ PVOID Context
34  );
35 
37  _In_opt_ PVOID Parameter,
38  _In_opt_ PVOID Context
39  );
40 
42  _In_opt_ PVOID Parameter,
43  _In_opt_ PVOID Context
44  );
45 
47  _In_opt_ PVOID Parameter,
48  _In_opt_ PVOID Context
49  );
50 
52  _In_opt_ PVOID Parameter,
53  _In_opt_ PVOID Context
54  );
55 
57  _In_opt_ PVOID Parameter,
58  _In_opt_ PVOID Context
59  );
60 
62  _In_opt_ PVOID Parameter,
63  _In_opt_ PVOID Context
64  );
65 
66 BOOLEAN IsHookClient;
76 
78  _In_ HINSTANCE Instance,
79  _In_ ULONG Reason,
80  _Reserved_ PVOID Reserved
81  )
82 {
83  switch (Reason)
84  {
85  case DLL_PROCESS_ATTACH:
86  {
88  BOOLEAN isClient;
89 
90  isClient = FALSE;
91 
92  if (!GetModuleHandle(L"ProcessHacker.exe") || !WeGetProcedureAddress("PhLibImageBase"))
93  {
94  isClient = TRUE;
95  }
96  else
97  {
98  // WindowExplorer appears to be loading within Process Hacker. However, if there is
99  // already a server instance, the the hook will be active, and our DllMain routine
100  // will most likely be called before the plugin system is even initialized. Attempting
101  // to register a plugin would result in an access violation, so load as a client for now.
102  if (WeIsServerActive())
103  isClient = TRUE;
104  }
105 
106  if (isClient)
107  {
108  // This DLL is being loaded not as a Process Hacker plugin, but as a hook.
109  IsHookClient = TRUE;
111 
112  break;
113  }
114 
115  PluginInstance = PhRegisterPlugin(PLUGIN_NAME, Instance, &info);
116 
117  if (!PluginInstance)
118  return FALSE;
119 
120  info->DisplayName = L"Window Explorer";
121  info->Author = L"wj32";
122  info->Description = L"View and manipulate windows.";
123  info->Url = L"http://processhacker.sf.net/forums/viewtopic.php?t=1116";
124  info->HasOptions = FALSE;
125 
127  PhGetPluginCallback(PluginInstance, PluginCallbackLoad),
128  LoadCallback,
129  NULL,
130  &PluginLoadCallbackRegistration
131  );
133  PhGetPluginCallback(PluginInstance, PluginCallbackUnload),
135  NULL,
136  &PluginUnloadCallbackRegistration
137  );
138  //PhRegisterCallback(
139  // PhGetPluginCallback(PluginInstance, PluginCallbackShowOptions),
140  // ShowOptionsCallback,
141  // NULL,
142  // &PluginShowOptionsCallbackRegistration
143  // );
147  NULL,
148  &PluginMenuItemCallbackRegistration
149  );
150 
154  NULL,
155  &MainMenuInitializingCallbackRegistration
156  );
157  //PhRegisterCallback(
158  // PhGetGeneralCallback(GeneralCallbackProcessPropertiesInitializing),
159  // ProcessPropertiesInitializingCallback,
160  // NULL,
161  // &ProcessPropertiesInitializingCallbackRegistration
162  // );
166  NULL,
167  &ProcessMenuInitializingCallbackRegistration
168  );
172  NULL,
173  &ThreadMenuInitializingCallbackRegistration
174  );
175 
176  {
177  static PH_SETTING_CREATE settings[] =
178  {
183  };
184 
185  PhAddSettings(settings, sizeof(settings) / sizeof(PH_SETTING_CREATE));
186  }
187  }
188  break;
189  case DLL_PROCESS_DETACH:
190  {
191  if (IsHookClient)
192  {
194  }
195  }
196  break;
197  }
198 
199  return TRUE;
200 }
201 
202 VOID NTAPI LoadCallback(
203  _In_opt_ PVOID Parameter,
204  _In_opt_ PVOID Context
205  )
206 {
207  NOTHING;
208 }
209 
210 VOID NTAPI UnloadCallback(
211  _In_opt_ PVOID Parameter,
212  _In_opt_ PVOID Context
213  )
214 {
216 }
217 
219  _In_opt_ PVOID Parameter,
220  _In_opt_ PVOID Context
221  )
222 {
223  NOTHING;
224 }
225 
227  _In_ LPTSTR lpszDesktop,
228  _In_ LPARAM lParam
229  )
230 {
231  PhAddItemList((PPH_LIST)lParam, PhaCreateString(lpszDesktop)->Buffer);
232 
233  return TRUE;
234 }
235 
236 VOID NTAPI MenuItemCallback(
237  _In_opt_ PVOID Parameter,
238  _In_opt_ PVOID Context
239  )
240 {
241  PPH_PLUGIN_MENU_ITEM menuItem = Parameter;
242 
243  switch (menuItem->Id)
244  {
245  case ID_VIEW_WINDOWS:
246  {
247  WE_WINDOW_SELECTOR selector;
248 
249  selector.Type = WeWindowSelectorAll;
251  }
252  break;
254  {
255  PPH_LIST desktopNames;
256  PPH_STRING selectedChoice = NULL;
257 
258  desktopNames = PhCreateList(4);
259  EnumDesktops(GetProcessWindowStation(), WepEnumDesktopProc, (LPARAM)desktopNames);
260 
261  if (PhaChoiceDialog(
263  L"Desktop Windows",
264  L"Display windows for the following desktop:",
265  (PWSTR *)desktopNames->Items,
266  desktopNames->Count,
267  NULL,
269  &selectedChoice,
270  NULL,
271  NULL
272  ))
273  {
274  WE_WINDOW_SELECTOR selector;
275 
276  selector.Type = WeWindowSelectorDesktop;
277  PhSetReference(&selector.Desktop.DesktopName, selectedChoice);
279  }
280 
281  PhDereferenceObject(desktopNames);
282  }
283  break;
284  case ID_PROCESS_WINDOWS:
285  {
286  WE_WINDOW_SELECTOR selector;
287 
288  selector.Type = WeWindowSelectorProcess;
289  selector.Process.ProcessId = ((PPH_PROCESS_ITEM)menuItem->Context)->ProcessId;
291  }
292  break;
293  case ID_THREAD_WINDOWS:
294  {
295  WE_WINDOW_SELECTOR selector;
296 
297  selector.Type = WeWindowSelectorThread;
298  selector.Thread.ThreadId = ((PPH_THREAD_ITEM)menuItem->Context)->ThreadId;
300  }
301  break;
302  }
303 }
304 
306  _In_opt_ PVOID Parameter,
307  _In_opt_ PVOID Context
308  )
309 {
310  ULONG insertIndex;
311  PPH_EMENU_ITEM menuItem;
312  PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter;
313 
314  if (menuInfo->u.MainMenu.SubMenuIndex != PH_MENU_ITEM_LOCATION_VIEW)
315  return;
316 
317  if (menuItem = PhFindEMenuItem(menuInfo->Menu, PH_EMENU_FIND_STARTSWITH, L"System Information", 0))
318  insertIndex = PhIndexOfEMenuItem(menuInfo->Menu, menuItem) + 1;
319  else
320  insertIndex = 0;
321 
322  PhInsertEMenuItem(menuInfo->Menu, menuItem = PhPluginCreateEMenuItem(PluginInstance, 0, ID_VIEW_WINDOWS, L"Windows", NULL), insertIndex);
323 
325  {
326  insertIndex = PhIndexOfEMenuItem(menuInfo->Menu, menuItem) + 1;
327 
328  PhInsertEMenuItem(menuInfo->Menu, PhPluginCreateEMenuItem(PluginInstance, 0, ID_VIEW_DESKTOPWINDOWS, L"Desktop Windows...", NULL), insertIndex);
329  }
330 }
331 
333  _In_opt_ PVOID Parameter,
334  _In_opt_ PVOID Context
335  )
336 {
337  NOTHING;
338 }
339 
341  _In_opt_ PVOID Parameter,
342  _In_opt_ PVOID Context
343  )
344 {
345  PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter;
346  PPH_PROCESS_ITEM processItem;
347  ULONG flags;
348  PPH_EMENU_ITEM miscMenu;
349 
350  if (menuInfo->u.Process.NumberOfProcesses == 1)
351  processItem = menuInfo->u.Process.Processes[0];
352  else
353  processItem = NULL;
354 
355  flags = 0;
356 
357  if (!processItem)
358  flags = PH_EMENU_DISABLED;
359 
360  miscMenu = PhFindEMenuItem(menuInfo->Menu, 0, L"Miscellaneous", 0);
361 
362  if (miscMenu)
363  {
364  PhInsertEMenuItem(miscMenu, PhPluginCreateEMenuItem(PluginInstance, flags, ID_PROCESS_WINDOWS, L"Windows", processItem), -1);
365  }
366 }
367 
369  _In_opt_ PVOID Parameter,
370  _In_opt_ PVOID Context
371  )
372 {
373  PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter;
374  PPH_THREAD_ITEM threadItem;
375  ULONG insertIndex;
376  PPH_EMENU_ITEM menuItem;
377 
378  if (menuInfo->u.Thread.NumberOfThreads == 1)
379  threadItem = menuInfo->u.Thread.Threads[0];
380  else
381  threadItem = NULL;
382 
383  if (menuItem = PhFindEMenuItem(menuInfo->Menu, 0, L"Token", 0))
384  insertIndex = PhIndexOfEMenuItem(menuInfo->Menu, menuItem) + 1;
385  else
386  insertIndex = 0;
387 
388  PhInsertEMenuItem(menuInfo->Menu, menuItem = PhPluginCreateEMenuItem(PluginInstance, 0, ID_THREAD_WINDOWS,
389  L"Windows", threadItem), insertIndex);
390 
391  if (!threadItem) menuItem->Flags |= PH_EMENU_DISABLED;
392 }