Process Hacker
depend.c
Go to the documentation of this file.
1 /*
2  * Process Hacker Extended Services -
3  * dependencies and dependents
4  *
5  * Copyright (C) 2010 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 <windowsx.h>
25 #include "extsrv.h"
26 #include "resource.h"
27 
28 typedef struct _SERVICE_LIST_CONTEXT
29 {
30  HWND ServiceListHandle;
31  PH_LAYOUT_MANAGER LayoutManager;
33 
34 LPENUM_SERVICE_STATUS EsEnumDependentServices(
35  _In_ SC_HANDLE ServiceHandle,
36  _In_opt_ ULONG State,
37  _Out_ PULONG Count
38  )
39 {
40  LOGICAL result;
41  PVOID buffer;
42  ULONG bufferSize;
43  ULONG returnLength;
44  ULONG servicesReturned;
45 
46  if (!State)
47  State = SERVICE_STATE_ALL;
48 
49  bufferSize = 0x800;
50  buffer = PhAllocate(bufferSize);
51 
52  if (!(result = EnumDependentServices(
53  ServiceHandle,
54  State,
55  buffer,
56  bufferSize,
57  &returnLength,
58  &servicesReturned
59  )))
60  {
61  if (GetLastError() == ERROR_MORE_DATA)
62  {
63  PhFree(buffer);
64  bufferSize = returnLength;
65  buffer = PhAllocate(bufferSize);
66 
67  result = EnumDependentServices(
68  ServiceHandle,
69  State,
70  buffer,
71  bufferSize,
72  &returnLength,
73  &servicesReturned
74  );
75  }
76 
77  if (!result)
78  {
79  PhFree(buffer);
80  return NULL;
81  }
82  }
83 
84  *Count = servicesReturned;
85 
86  return buffer;
87 }
88 
89 static VOID EspLayoutServiceListControl(
90  _In_ HWND hwndDlg,
91  _In_ HWND ServiceListHandle
92  )
93 {
94  RECT rect;
95 
96  GetWindowRect(GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), &rect);
97  MapWindowPoints(NULL, hwndDlg, (POINT *)&rect, 2);
98 
99  MoveWindow(
100  ServiceListHandle,
101  rect.left,
102  rect.top,
103  rect.right - rect.left,
104  rect.bottom - rect.top,
105  TRUE
106  );
107 }
108 
110  _In_ HWND hwndDlg,
111  _In_ UINT uMsg,
112  _In_ WPARAM wParam,
113  _In_ LPARAM lParam
114  )
115 {
116  PSERVICE_LIST_CONTEXT context;
117 
118  if (uMsg == WM_INITDIALOG)
119  {
120  context = PhAllocate(sizeof(SERVICE_LIST_CONTEXT));
121  memset(context, 0, sizeof(SERVICE_LIST_CONTEXT));
122 
123  SetProp(hwndDlg, L"Context", (HANDLE)context);
124  }
125  else
126  {
127  context = (PSERVICE_LIST_CONTEXT)GetProp(hwndDlg, L"Context");
128 
129  if (uMsg == WM_DESTROY)
130  RemoveProp(hwndDlg, L"Context");
131  }
132 
133  if (!context)
134  return FALSE;
135 
136  switch (uMsg)
137  {
138  case WM_INITDIALOG:
139  {
140  LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam;
141  PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)propSheetPage->lParam;
142  HWND serviceListHandle;
143  PPH_LIST serviceList;
144  SC_HANDLE serviceHandle;
145  ULONG win32Result = 0;
146  BOOLEAN success = FALSE;
147  PPH_SERVICE_ITEM *services;
148 
149  SetDlgItemText(hwndDlg, IDC_MESSAGE, L"This service depends on the following services:");
150 
151  PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
152  PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), NULL, PH_ANCHOR_ALL);
153 
154  if (serviceHandle = PhOpenService(serviceItem->Name->Buffer, SERVICE_QUERY_CONFIG))
155  {
156  LPQUERY_SERVICE_CONFIG serviceConfig;
157 
158  if (serviceConfig = PhGetServiceConfig(serviceHandle))
159  {
160  PWSTR dependency;
161  PPH_SERVICE_ITEM dependencyService;
162 
163  dependency = serviceConfig->lpDependencies;
164  serviceList = PhCreateList(8);
165  success = TRUE;
166 
167  if (dependency)
168  {
169  ULONG dependencyLength;
170 
171  while (TRUE)
172  {
173  dependencyLength = (ULONG)PhCountStringZ(dependency);
174 
175  if (dependencyLength == 0)
176  break;
177 
178  if (dependency[0] == SC_GROUP_IDENTIFIER)
179  goto ContinueLoop;
180 
181  if (dependencyService = PhReferenceServiceItem(dependency))
182  PhAddItemList(serviceList, dependencyService);
183 
184 ContinueLoop:
185  dependency += dependencyLength + 1;
186  }
187  }
188 
189  services = PhAllocateCopy(serviceList->Items, sizeof(PPH_SERVICE_ITEM) * serviceList->Count);
190 
191  serviceListHandle = PhCreateServiceListControl(hwndDlg, services, serviceList->Count);
192  context->ServiceListHandle = serviceListHandle;
193  EspLayoutServiceListControl(hwndDlg, serviceListHandle);
194  ShowWindow(serviceListHandle, SW_SHOW);
195 
196  PhDereferenceObject(serviceList);
197  PhFree(serviceConfig);
198  }
199  else
200  {
201  win32Result = GetLastError();
202  }
203 
204  CloseServiceHandle(serviceHandle);
205  }
206  else
207  {
208  win32Result = GetLastError();
209  }
210 
211  if (!success)
212  {
213  SetDlgItemText(hwndDlg, IDC_SERVICES_LAYOUT, PhaConcatStrings2(L"Unable to enumerate dependencies: ",
214  ((PPH_STRING)PhAutoDereferenceObject(PhGetWin32Message(win32Result)))->Buffer)->Buffer);
215  ShowWindow(GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), SW_SHOW);
216  }
217  }
218  break;
219  case WM_DESTROY:
220  {
221  PhDeleteLayoutManager(&context->LayoutManager);
222  PhFree(context);
223  }
224  break;
225  case WM_SIZE:
226  {
227  PhLayoutManagerLayout(&context->LayoutManager);
228 
229  if (context->ServiceListHandle)
230  EspLayoutServiceListControl(hwndDlg, context->ServiceListHandle);
231  }
232  break;
233  }
234 
235  return FALSE;
236 }
237 
239  _In_ HWND hwndDlg,
240  _In_ UINT uMsg,
241  _In_ WPARAM wParam,
242  _In_ LPARAM lParam
243  )
244 {
245  PSERVICE_LIST_CONTEXT context;
246 
247  if (uMsg == WM_INITDIALOG)
248  {
249  context = PhAllocate(sizeof(SERVICE_LIST_CONTEXT));
250  memset(context, 0, sizeof(SERVICE_LIST_CONTEXT));
251 
252  SetProp(hwndDlg, L"Context", (HANDLE)context);
253  }
254  else
255  {
256  context = (PSERVICE_LIST_CONTEXT)GetProp(hwndDlg, L"Context");
257 
258  if (uMsg == WM_DESTROY)
259  RemoveProp(hwndDlg, L"Context");
260  }
261 
262  if (!context)
263  return FALSE;
264 
265  switch (uMsg)
266  {
267  case WM_INITDIALOG:
268  {
269  LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam;
270  PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)propSheetPage->lParam;
271  HWND serviceListHandle;
272  PPH_LIST serviceList;
273  SC_HANDLE serviceHandle;
274  ULONG win32Result = 0;
275  BOOLEAN success = FALSE;
276  PPH_SERVICE_ITEM *services;
277 
278  SetDlgItemText(hwndDlg, IDC_MESSAGE, L"The following services depend on this service:");
279 
280  PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
281  PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), NULL, PH_ANCHOR_ALL);
282 
283  if (serviceHandle = PhOpenService(serviceItem->Name->Buffer, SERVICE_ENUMERATE_DEPENDENTS))
284  {
285  LPENUM_SERVICE_STATUS dependentServices;
286  ULONG numberOfDependentServices;
287 
288  if (dependentServices = EsEnumDependentServices(serviceHandle, 0, &numberOfDependentServices))
289  {
290  ULONG i;
291  PPH_SERVICE_ITEM dependentService;
292 
293  serviceList = PhCreateList(8);
294  success = TRUE;
295 
296  for (i = 0; i < numberOfDependentServices; i++)
297  {
298  if (dependentService = PhReferenceServiceItem(dependentServices[i].lpServiceName))
299  PhAddItemList(serviceList, dependentService);
300  }
301 
302  services = PhAllocateCopy(serviceList->Items, sizeof(PPH_SERVICE_ITEM) * serviceList->Count);
303 
304  serviceListHandle = PhCreateServiceListControl(hwndDlg, services, serviceList->Count);
305  context->ServiceListHandle = serviceListHandle;
306  EspLayoutServiceListControl(hwndDlg, serviceListHandle);
307  ShowWindow(serviceListHandle, SW_SHOW);
308 
309  PhDereferenceObject(serviceList);
310  PhFree(dependentServices);
311  }
312  else
313  {
314  win32Result = GetLastError();
315  }
316 
317  CloseServiceHandle(serviceHandle);
318  }
319  else
320  {
321  win32Result = GetLastError();
322  }
323 
324  if (!success)
325  {
326  SetDlgItemText(hwndDlg, IDC_SERVICES_LAYOUT, PhaConcatStrings2(L"Unable to enumerate dependents: ",
327  ((PPH_STRING)PhAutoDereferenceObject(PhGetWin32Message(win32Result)))->Buffer)->Buffer);
328  ShowWindow(GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), SW_SHOW);
329  }
330  }
331  break;
332  case WM_DESTROY:
333  {
334  PhDeleteLayoutManager(&context->LayoutManager);
335  PhFree(context);
336  }
337  break;
338  case WM_SIZE:
339  {
340  PhLayoutManagerLayout(&context->LayoutManager);
341 
342  if (context->ServiceListHandle)
343  EspLayoutServiceListControl(hwndDlg, context->ServiceListHandle);
344  }
345  break;
346  }
347 
348  return FALSE;
349 }