Process Hacker
srvctl.c
Go to the documentation of this file.
1 /*
2  * Process Hacker -
3  * service list control
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 <phapp.h>
24 
25 typedef struct _PH_SERVICES_CONTEXT
26 {
27  PPH_SERVICE_ITEM *Services;
28  ULONG NumberOfServices;
29  PH_CALLBACK_REGISTRATION ModifiedEventRegistration;
30 
31  PWSTR ListViewSettingName;
32 
33  PH_LAYOUT_MANAGER LayoutManager;
34  HWND WindowHandle;
36 
38  _In_opt_ PVOID Parameter,
39  _In_opt_ PVOID Context
40  );
41 
42 INT_PTR CALLBACK PhpServicesPageProc(
43  _In_ HWND hwndDlg,
44  _In_ UINT uMsg,
45  _In_ WPARAM wParam,
46  _In_ LPARAM lParam
47  );
48 
62  _In_ HWND ParentWindowHandle,
63  _In_ PPH_SERVICE_ITEM *Services,
64  _In_ ULONG NumberOfServices
65  )
66 {
67  HWND windowHandle;
68  PPH_SERVICES_CONTEXT servicesContext;
69 
70  servicesContext = PhAllocate(sizeof(PH_SERVICES_CONTEXT));
71 
72  memset(servicesContext, 0, sizeof(PH_SERVICES_CONTEXT));
73  servicesContext->Services = Services;
74  servicesContext->NumberOfServices = NumberOfServices;
75 
76  windowHandle = CreateDialogParam(
78  MAKEINTRESOURCE(IDD_SRVLIST),
79  ParentWindowHandle,
81  (LPARAM)servicesContext
82  );
83 
84  if (!windowHandle)
85  {
86  PhFree(servicesContext);
87  return windowHandle;
88  }
89 
90  return windowHandle;
91 }
92 
94  _In_opt_ PVOID Parameter,
95  _In_opt_ PVOID Context
96  )
97 {
98  PPH_SERVICE_MODIFIED_DATA serviceModifiedData = (PPH_SERVICE_MODIFIED_DATA)Parameter;
99  PPH_SERVICES_CONTEXT servicesContext = (PPH_SERVICES_CONTEXT)Context;
101 
102  copy = PhAllocateCopy(serviceModifiedData, sizeof(PH_SERVICE_MODIFIED_DATA));
103 
104  PostMessage(servicesContext->WindowHandle, WM_PH_SERVICE_MODIFIED, 0, (LPARAM)copy);
105 }
106 
108  _In_ HWND hWnd,
109  _In_opt_ PPH_SERVICE_ITEM ServiceItem
110  )
111 {
112  HWND startButton;
113  HWND pauseButton;
114  HWND descriptionLabel;
115 
116  startButton = GetDlgItem(hWnd, IDC_START);
117  pauseButton = GetDlgItem(hWnd, IDC_PAUSE);
118  descriptionLabel = GetDlgItem(hWnd, IDC_DESCRIPTION);
119 
120  if (ServiceItem)
121  {
122  SC_HANDLE serviceHandle;
123  PPH_STRING description;
124 
125  switch (ServiceItem->State)
126  {
127  case SERVICE_RUNNING:
128  {
129  SetWindowText(startButton, L"S&top");
130  SetWindowText(pauseButton, L"&Pause");
131  EnableWindow(startButton, ServiceItem->ControlsAccepted & SERVICE_ACCEPT_STOP);
132  EnableWindow(pauseButton, ServiceItem->ControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE);
133  }
134  break;
135  case SERVICE_PAUSED:
136  {
137  SetWindowText(startButton, L"S&top");
138  SetWindowText(pauseButton, L"C&ontinue");
139  EnableWindow(startButton, ServiceItem->ControlsAccepted & SERVICE_ACCEPT_STOP);
140  EnableWindow(pauseButton, ServiceItem->ControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE);
141  }
142  break;
143  case SERVICE_STOPPED:
144  {
145  SetWindowText(startButton, L"&Start");
146  SetWindowText(pauseButton, L"&Pause");
147  EnableWindow(startButton, TRUE);
148  EnableWindow(pauseButton, FALSE);
149  }
150  break;
151  case SERVICE_START_PENDING:
152  case SERVICE_CONTINUE_PENDING:
153  case SERVICE_PAUSE_PENDING:
154  case SERVICE_STOP_PENDING:
155  {
156  SetWindowText(startButton, L"&Start");
157  SetWindowText(pauseButton, L"&Pause");
158  EnableWindow(startButton, FALSE);
159  EnableWindow(pauseButton, FALSE);
160  }
161  break;
162  }
163 
164  if (serviceHandle = PhOpenService(
165  ServiceItem->Name->Buffer,
166  SERVICE_QUERY_CONFIG
167  ))
168  {
169  if (description = PhGetServiceDescription(serviceHandle))
170  {
171  SetWindowText(descriptionLabel, description->Buffer);
172  PhDereferenceObject(description);
173  }
174 
175  CloseServiceHandle(serviceHandle);
176  }
177  }
178  else
179  {
180  SetWindowText(startButton, L"&Start");
181  SetWindowText(pauseButton, L"&Pause");
182  EnableWindow(startButton, FALSE);
183  EnableWindow(pauseButton, FALSE);
184  SetWindowText(descriptionLabel, L"");
185  }
186 }
187 
188 INT_PTR CALLBACK PhpServicesPageProc(
189  _In_ HWND hwndDlg,
190  _In_ UINT uMsg,
191  _In_ WPARAM wParam,
192  _In_ LPARAM lParam
193  )
194 {
195  PPH_SERVICES_CONTEXT servicesContext;
196  HWND lvHandle;
197 
198  if (uMsg == WM_INITDIALOG)
199  {
200  servicesContext = (PPH_SERVICES_CONTEXT)lParam;
201  SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)servicesContext);
202  }
203  else
204  {
205  servicesContext = (PPH_SERVICES_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom());
206 
207  if (uMsg == WM_DESTROY)
208  {
209  RemoveProp(hwndDlg, PhMakeContextAtom());
210  }
211  }
212 
213  if (!servicesContext)
214  return FALSE;
215 
216  lvHandle = GetDlgItem(hwndDlg, IDC_LIST);
217 
218  switch (uMsg)
219  {
220  case WM_INITDIALOG:
221  {
222  ULONG i;
223 
227  servicesContext,
228  &servicesContext->ModifiedEventRegistration
229  );
230 
231  servicesContext->WindowHandle = hwndDlg;
232 
233  // Initialize the list.
234  PhSetListViewStyle(lvHandle, TRUE, TRUE);
235  PhSetControlTheme(lvHandle, L"explorer");
236  PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 120, L"Name");
237  PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 220, L"Display Name");
238 
239  PhSetExtendedListView(lvHandle);
240 
241  for (i = 0; i < servicesContext->NumberOfServices; i++)
242  {
243  PPH_SERVICE_ITEM serviceItem;
244  INT lvItemIndex;
245 
246  serviceItem = servicesContext->Services[i];
247  lvItemIndex = PhAddListViewItem(lvHandle, MAXINT, serviceItem->Name->Buffer, serviceItem);
248  PhSetListViewSubItem(lvHandle, lvItemIndex, 1, serviceItem->DisplayName->Buffer);
249  }
250 
251  ExtendedListView_SortItems(lvHandle);
252 
253  PhpFixProcessServicesControls(hwndDlg, NULL);
254 
255  PhInitializeLayoutManager(&servicesContext->LayoutManager, hwndDlg);
256  PhAddLayoutItem(&servicesContext->LayoutManager, GetDlgItem(hwndDlg, IDC_LIST),
257  NULL, PH_ANCHOR_ALL);
258  PhAddLayoutItem(&servicesContext->LayoutManager, GetDlgItem(hwndDlg, IDC_DESCRIPTION),
260  PhAddLayoutItem(&servicesContext->LayoutManager, GetDlgItem(hwndDlg, IDC_START),
262  PhAddLayoutItem(&servicesContext->LayoutManager, GetDlgItem(hwndDlg, IDC_PAUSE),
264  }
265  break;
266  case WM_DESTROY:
267  {
268  ULONG i;
269 
270  for (i = 0; i < servicesContext->NumberOfServices; i++)
271  PhDereferenceObject(servicesContext->Services[i]);
272 
273  PhFree(servicesContext->Services);
274 
277  &servicesContext->ModifiedEventRegistration
278  );
279 
280  if (servicesContext->ListViewSettingName)
281  PhSaveListViewColumnsToSetting(servicesContext->ListViewSettingName, lvHandle);
282 
283  PhDeleteLayoutManager(&servicesContext->LayoutManager);
284 
285  PhFree(servicesContext);
286  }
287  break;
288  case WM_COMMAND:
289  {
290  INT id = LOWORD(wParam);
291 
292  switch (id)
293  {
294  case IDC_START:
295  {
296  PPH_SERVICE_ITEM serviceItem = PhGetSelectedListViewItemParam(lvHandle);
297 
298  if (serviceItem)
299  {
300  switch (serviceItem->State)
301  {
302  case SERVICE_RUNNING:
303  PhUiStopService(hwndDlg, serviceItem);
304  break;
305  case SERVICE_PAUSED:
306  PhUiStopService(hwndDlg, serviceItem);
307  break;
308  case SERVICE_STOPPED:
309  PhUiStartService(hwndDlg, serviceItem);
310  break;
311  }
312  }
313  }
314  break;
315  case IDC_PAUSE:
316  {
317  PPH_SERVICE_ITEM serviceItem = PhGetSelectedListViewItemParam(lvHandle);
318 
319  if (serviceItem)
320  {
321  switch (serviceItem->State)
322  {
323  case SERVICE_RUNNING:
324  PhUiPauseService(hwndDlg, serviceItem);
325  break;
326  case SERVICE_PAUSED:
327  PhUiContinueService(hwndDlg, serviceItem);
328  break;
329  }
330  }
331  }
332  break;
333  }
334  }
335  break;
336  case WM_NOTIFY:
337  {
338  LPNMHDR header = (LPNMHDR)lParam;
339 
341 
342  switch (header->code)
343  {
344  case NM_DBLCLK:
345  {
346  if (header->hwndFrom == lvHandle)
347  {
348  PPH_SERVICE_ITEM serviceItem = PhGetSelectedListViewItemParam(lvHandle);
349 
350  if (serviceItem)
351  {
352  PhShowServiceProperties(hwndDlg, serviceItem);
353  }
354  }
355  }
356  break;
357  case LVN_ITEMCHANGED:
358  {
359  if (header->hwndFrom == lvHandle)
360  {
361  //LPNMITEMACTIVATE itemActivate = (LPNMITEMACTIVATE)header;
362  PPH_SERVICE_ITEM serviceItem = NULL;
363 
364  if (ListView_GetSelectedCount(lvHandle) == 1)
365  serviceItem = PhGetSelectedListViewItemParam(lvHandle);
366 
367  PhpFixProcessServicesControls(hwndDlg, serviceItem);
368  }
369  }
370  break;
371  }
372  }
373  break;
374  case WM_SIZE:
375  {
376  PhLayoutManagerLayout(&servicesContext->LayoutManager);
377  }
378  break;
380  {
381  PPH_SERVICE_MODIFIED_DATA serviceModifiedData = (PPH_SERVICE_MODIFIED_DATA)lParam;
382  PPH_SERVICE_ITEM serviceItem = NULL;
383 
384  if (ListView_GetSelectedCount(lvHandle) == 1)
385  serviceItem = PhGetSelectedListViewItemParam(lvHandle);
386 
387  if (serviceModifiedData->Service == serviceItem)
388  {
389  PhpFixProcessServicesControls(hwndDlg, serviceItem);
390  }
391 
392  PhFree(serviceModifiedData);
393  }
394  break;
396  {
397  PWSTR settingName = (PWSTR)lParam;
398 
399  servicesContext->ListViewSettingName = settingName;
400  PhLoadListViewColumnsFromSetting(settingName, lvHandle);
401  }
402  break;
403  }
404 
405  return FALSE;
406 }