1 /*
2  * PROJECT:     ReactOS Services
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        base/applications/mscutils/servman/propsheet_general.c
5  * PURPOSE:     Property dialog box message handler
6  * COPYRIGHT:   Copyright 2006-2009 Ged Murphy <gedmurphy@reactos.org>
7  *
8  */
9 
10 #include "precomp.h"
11 
12 
13 typedef struct _PAGEDATA
14 {
15     PSERVICEPROPSHEET dlgInfo;
16     BOOL bDisplayNameChanged;
17     BOOL bDescriptionChanged;
18     BOOL bBinaryPathChanged;
19     BOOL bStartTypeChanged;
20 } PAGEDATA, *PPAGEDATA;
21 
22 
23 static VOID
24 SetButtonStates(PSERVICEPROPSHEET dlgInfo,
25                 HWND hwndDlg)
26 {
27     HWND hButton;
28     LPQUERY_SERVICE_CONFIG lpServiceConfig;
29     DWORD Flags, State;
30     UINT i;
31 
32     Flags = dlgInfo->pService->ServiceStatusProcess.dwControlsAccepted;
33     State = dlgInfo->pService->ServiceStatusProcess.dwCurrentState;
34 
35     for (i = IDC_START; i <= IDC_RESUME; i++)
36     {
37         hButton = GetDlgItem(hwndDlg, i);
38         EnableWindow (hButton, FALSE);
39     }
40 
41     lpServiceConfig = GetServiceConfig(dlgInfo->pService->lpServiceName);
42     if (State == SERVICE_STOPPED &&
43         lpServiceConfig && lpServiceConfig->dwStartType != SERVICE_DISABLED)
44     {
45         hButton = GetDlgItem(hwndDlg, IDC_START);
46         EnableWindow (hButton, TRUE);
47     }
48     else if ( (Flags & SERVICE_ACCEPT_STOP) && (State == SERVICE_RUNNING) )
49     {
50         hButton = GetDlgItem(hwndDlg, IDC_STOP);
51         EnableWindow (hButton, TRUE);
52     }
53     else if ( (Flags & SERVICE_ACCEPT_PAUSE_CONTINUE) && (State == SERVICE_RUNNING) )
54     {
55         hButton = GetDlgItem(hwndDlg, IDC_PAUSE);
56         EnableWindow (hButton, TRUE);
57     }
58 
59     hButton = GetDlgItem(hwndDlg, IDC_START_PARAM);
60     EnableWindow(hButton, (State == SERVICE_STOPPED && lpServiceConfig && lpServiceConfig->dwStartType != SERVICE_DISABLED));
61 
62     if (lpServiceConfig)
63         HeapFree(GetProcessHeap(), 0, lpServiceConfig);
64 
65     /* set the main toolbar */
66     SetMenuAndButtonStates(dlgInfo->Info);
67 }
68 
69 static VOID
70 SetServiceStatusText(PSERVICEPROPSHEET dlgInfo,
71                      HWND hwndDlg)
72 {
73     LPWSTR lpStatus;
74     UINT id;
75 
76     if (dlgInfo->pService->ServiceStatusProcess.dwCurrentState == SERVICE_RUNNING)
77     {
78         id = IDS_SERVICES_STARTED;
79     }
80     else
81     {
82         id = IDS_SERVICES_STOPPED;
83     }
84 
85     if (AllocAndLoadString(&lpStatus,
86                            hInstance,
87                            id))
88     {
89         SendDlgItemMessageW(hwndDlg,
90                             IDC_SERV_STATUS,
91                             WM_SETTEXT,
92                             0,
93                             (LPARAM)lpStatus);
94         LocalFree(lpStatus);
95     }
96 }
97 
98 /*
99  * Fills the 'startup type' combo box with possible
100  * values and sets it to value of the selected item
101  */
102 static VOID
103 SetStartupType(LPWSTR lpServiceName,
104                HWND hwndDlg)
105 {
106     HWND hList;
107     LPQUERY_SERVICE_CONFIG pServiceConfig;
108     LPWSTR lpBuf;
109     DWORD StartUp = 0;
110     UINT i;
111 
112     hList = GetDlgItem(hwndDlg, IDC_START_TYPE);
113 
114     for (i = IDS_SERVICES_AUTO; i <= IDS_SERVICES_DIS; i++)
115     {
116         if (AllocAndLoadString(&lpBuf,
117                                hInstance,
118                                i))
119         {
120             SendMessageW(hList,
121                          CB_ADDSTRING,
122                          0,
123                          (LPARAM)lpBuf);
124             LocalFree(lpBuf);
125         }
126     }
127 
128     pServiceConfig = GetServiceConfig(lpServiceName);
129 
130     if (pServiceConfig)
131     {
132         switch (pServiceConfig->dwStartType)
133         {
134             case SERVICE_AUTO_START:   StartUp = 0; break;
135             case SERVICE_DEMAND_START: StartUp = 1; break;
136             case SERVICE_DISABLED:     StartUp = 2; break;
137         }
138 
139         SendMessageW(hList,
140                      CB_SETCURSEL,
141                      StartUp,
142                      0);
143 
144         HeapFree(ProcessHeap,
145                  0,
146                  pServiceConfig);
147     }
148 }
149 
150 /*
151  * Populates the General Properties dialog with
152  * the relevant service information
153  */
154 static VOID
155 InitGeneralPage(PSERVICEPROPSHEET dlgInfo,
156                 HWND hwndDlg)
157 {
158     LPQUERY_SERVICE_CONFIG pServiceConfig;
159     LPWSTR lpDescription;
160 
161     /* set the service name */
162     SendDlgItemMessageW(hwndDlg,
163                         IDC_SERV_NAME,
164                         WM_SETTEXT,
165                         0,
166                         (LPARAM)dlgInfo->pService->lpServiceName);
167 
168     /* set the display name */
169     SendDlgItemMessageW(hwndDlg,
170                         IDC_DISP_NAME,
171                         WM_SETTEXT,
172                         0,
173                         (LPARAM)dlgInfo->pService->lpDisplayName);
174 
175     /* set the description */
176     if ((lpDescription = GetServiceDescription(dlgInfo->pService->lpServiceName)))
177     {
178         SendDlgItemMessageW(hwndDlg,
179                             IDC_DESCRIPTION,
180                             WM_SETTEXT,
181                             0,
182                             (LPARAM)lpDescription);
183 
184         HeapFree(ProcessHeap,
185                  0,
186                  lpDescription);
187     }
188 
189     pServiceConfig = GetServiceConfig(dlgInfo->pService->lpServiceName);
190     if (pServiceConfig)
191     {
192         SendDlgItemMessageW(hwndDlg,
193                             IDC_EXEPATH,
194                             WM_SETTEXT,
195                             0,
196                             (LPARAM)pServiceConfig->lpBinaryPathName);
197         HeapFree(ProcessHeap,
198                  0,
199                  pServiceConfig);
200     }
201 
202 
203     /* set startup type */
204     SetStartupType(dlgInfo->pService->lpServiceName, hwndDlg);
205 
206     SetServiceStatusText(dlgInfo,
207                          hwndDlg);
208 
209     if (dlgInfo->Info->bIsUserAnAdmin)
210     {
211         EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT), TRUE);
212     }
213 }
214 
215 VOID
216 SaveDlgInfo(PPAGEDATA pPageData,
217             HWND hwndDlg)
218 {
219     LPQUERY_SERVICE_CONFIG pServiceConfig = NULL;
220     PWSTR pDisplayName = NULL;
221     PWSTR pDescription;
222     INT nLength;
223     DWORD StartUp;
224 
225     pServiceConfig = HeapAlloc(ProcessHeap,
226                                HEAP_ZERO_MEMORY,
227                                sizeof(*pServiceConfig));
228     if (pServiceConfig)
229     {
230         pServiceConfig->dwServiceType = SERVICE_NO_CHANGE;
231         pServiceConfig->dwErrorControl = SERVICE_NO_CHANGE;
232         pServiceConfig->dwStartType = SERVICE_NO_CHANGE;
233 
234         if (pPageData->bStartTypeChanged)
235         {
236             StartUp = SendDlgItemMessageW(hwndDlg, IDC_START_TYPE, CB_GETCURSEL, 0, 0);
237             switch (StartUp)
238             {
239                 case 0:
240                     pServiceConfig->dwStartType = SERVICE_AUTO_START;
241                     break;
242 
243                 case 1:
244                     pServiceConfig->dwStartType = SERVICE_DEMAND_START;
245                     break;
246                 case 2:
247                     pServiceConfig->dwStartType = SERVICE_DISABLED;
248                     break;
249             }
250         }
251 
252         if (pPageData->bBinaryPathChanged)
253         {
254             nLength = SendDlgItemMessageW(hwndDlg, IDC_EXEPATH, WM_GETTEXTLENGTH, 0, 0);
255             pServiceConfig->lpBinaryPathName = HeapAlloc(ProcessHeap,
256                                                          HEAP_ZERO_MEMORY,
257                                                          (nLength + 1) * sizeof(WCHAR));
258             if (pServiceConfig->lpBinaryPathName != NULL)
259                 SendDlgItemMessageW(hwndDlg, IDC_EXEPATH, WM_GETTEXT, nLength + 1, (LPARAM)pServiceConfig->lpBinaryPathName);
260         }
261 
262         if (pPageData->bDisplayNameChanged)
263         {
264             nLength = SendDlgItemMessageW(hwndDlg, IDC_DISP_NAME, WM_GETTEXTLENGTH, 0, 0);
265             pDisplayName = HeapAlloc(ProcessHeap,
266                                      HEAP_ZERO_MEMORY,
267                                      (nLength + 1) * sizeof(WCHAR));
268             if (pDisplayName != NULL)
269             {
270                 SendDlgItemMessageW(hwndDlg, IDC_DISP_NAME, WM_GETTEXT, nLength + 1, (LPARAM)pDisplayName);
271 
272                 if (pPageData->dlgInfo->pService->lpDisplayName)
273                     HeapFree(ProcessHeap, 0, pPageData->dlgInfo->pService->lpDisplayName);
274 
275                 pPageData->dlgInfo->pService->lpDisplayName = pDisplayName;
276                 pServiceConfig->lpDisplayName = pDisplayName;
277             }
278         }
279 
280         if (SetServiceConfig(pServiceConfig,
281                              pPageData->dlgInfo->pService->lpServiceName,
282                              NULL))
283         {
284             if (pPageData->bDisplayNameChanged)
285                 ChangeListViewText(pPageData->dlgInfo->Info,
286                                    pPageData->dlgInfo->pService,
287                                    LVNAME);
288 
289             if (pPageData->bStartTypeChanged)
290                 ChangeListViewText(pPageData->dlgInfo->Info,
291                                    pPageData->dlgInfo->pService,
292                                    LVSTARTUP);
293         }
294 
295         if (pServiceConfig->lpBinaryPathName != NULL)
296             HeapFree(ProcessHeap, 0, pServiceConfig->lpBinaryPathName);
297 
298         HeapFree(ProcessHeap, 0, pServiceConfig);
299     }
300 
301     if (pPageData->bDescriptionChanged)
302     {
303         nLength = SendDlgItemMessageW(hwndDlg, IDC_DESCRIPTION, WM_GETTEXTLENGTH, 0, 0);
304         pDescription = HeapAlloc(ProcessHeap, HEAP_ZERO_MEMORY, (nLength + 1) * sizeof(WCHAR));
305         if (pDescription != NULL)
306         {
307             SendDlgItemMessageW(hwndDlg, IDC_DESCRIPTION, WM_GETTEXT, nLength + 1, (LPARAM)pDescription);
308 
309             if (SetServiceDescription(pPageData->dlgInfo->pService->lpServiceName,
310                                       pDescription))
311             {
312                 ChangeListViewText(pPageData->dlgInfo->Info,
313                                    pPageData->dlgInfo->pService,
314                                    LVDESC);
315             }
316 
317             HeapFree(ProcessHeap, 0, pDescription);
318         }
319     }
320 }
321 
322 /*
323  * General Property dialog callback.
324  * Controls messages to the General dialog
325  */
326 INT_PTR CALLBACK
327 GeneralPageProc(HWND hwndDlg,
328                 UINT uMsg,
329                 WPARAM wParam,
330                 LPARAM lParam)
331 {
332     PPAGEDATA pPageData;
333 
334     /* Get the window context */
335     pPageData = (PPAGEDATA)GetWindowLongPtr(hwndDlg,
336                                             GWLP_USERDATA);
337     if (pPageData == NULL && uMsg != WM_INITDIALOG)
338     {
339         return FALSE;
340     }
341 
342     switch (uMsg)
343     {
344         case WM_INITDIALOG:
345             pPageData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PAGEDATA));
346             if (pPageData != NULL)
347             {
348                 SetWindowLongPtr(hwndDlg,
349                                  GWLP_USERDATA,
350                                  (LONG_PTR)pPageData);
351 
352                 pPageData->dlgInfo = (PSERVICEPROPSHEET)(((LPPROPSHEETPAGE)lParam)->lParam);
353                 if (pPageData->dlgInfo != NULL)
354                 {
355                     InitGeneralPage(pPageData->dlgInfo, hwndDlg);
356                     SetButtonStates(pPageData->dlgInfo, hwndDlg);
357                 }
358             }
359             break;
360 
361         case WM_DESTROY:
362             HeapFree(GetProcessHeap(), 0, pPageData);
363             break;
364 
365         case WM_COMMAND:
366             switch(LOWORD(wParam))
367             {
368                 case IDC_START_TYPE:
369                     if (HIWORD(wParam) == CBN_SELCHANGE)
370                     {
371                         pPageData->bStartTypeChanged = TRUE;
372                         PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
373                     }
374                     break;
375 
376                 case IDC_DISP_NAME:
377                     if (HIWORD(wParam) == EN_CHANGE)
378                     {
379                         pPageData->bDisplayNameChanged = TRUE;
380                         PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
381                     }
382                     break;
383 
384                 case IDC_DESCRIPTION:
385                     if (HIWORD(wParam) == EN_CHANGE)
386                     {
387                         pPageData->bDescriptionChanged = TRUE;
388                         PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
389                     }
390                     break;
391 
392                 case IDC_EXEPATH:
393                     if (HIWORD(wParam) == EN_CHANGE)
394                     {
395                         pPageData->bBinaryPathChanged = TRUE;
396                         PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
397                     }
398                     break;
399 
400                 case IDC_START:
401                 {
402                     WCHAR szStartParams[256];
403                     LPWSTR lpStartParams = NULL;
404 
405                     if (GetDlgItemText(hwndDlg, IDC_START_PARAM, szStartParams, 256) > 0)
406                         lpStartParams = szStartParams;
407 
408                     EnableWindow(GetDlgItem(hwndDlg, IDC_START_PARAM), FALSE);
409 
410                     RunActionWithProgress(hwndDlg,
411                                           pPageData->dlgInfo->pService->lpServiceName,
412                                           pPageData->dlgInfo->pService->lpDisplayName,
413                                           ACTION_START,
414                                           lpStartParams);
415 
416                     UpdateServiceStatus(pPageData->dlgInfo->pService);
417                     ChangeListViewText(pPageData->dlgInfo->Info, pPageData->dlgInfo->pService, LVSTATUS);
418                     SetButtonStates(pPageData->dlgInfo, hwndDlg);
419                     SetServiceStatusText(pPageData->dlgInfo, hwndDlg);
420                     break;
421                 }
422 
423                 case IDC_STOP:
424                     RunActionWithProgress(hwndDlg,
425                                           pPageData->dlgInfo->pService->lpServiceName,
426                                           pPageData->dlgInfo->pService->lpDisplayName,
427                                           ACTION_STOP,
428                                           NULL);
429 
430                     UpdateServiceStatus(pPageData->dlgInfo->pService);
431                     ChangeListViewText(pPageData->dlgInfo->Info, pPageData->dlgInfo->pService, LVSTATUS);
432                     SetButtonStates(pPageData->dlgInfo, hwndDlg);
433                     SetServiceStatusText(pPageData->dlgInfo, hwndDlg);
434                     break;
435 
436                 case IDC_PAUSE:
437                     RunActionWithProgress(hwndDlg,
438                                           pPageData->dlgInfo->pService->lpServiceName,
439                                           pPageData->dlgInfo->pService->lpDisplayName,
440                                           ACTION_PAUSE,
441                                           NULL);
442 
443                     UpdateServiceStatus(pPageData->dlgInfo->pService);
444                     ChangeListViewText(pPageData->dlgInfo->Info, pPageData->dlgInfo->pService, LVSTATUS);
445                     SetButtonStates(pPageData->dlgInfo, hwndDlg);
446                     SetServiceStatusText(pPageData->dlgInfo, hwndDlg);
447                     break;
448 
449                 case IDC_RESUME:
450                     RunActionWithProgress(hwndDlg,
451                                           pPageData->dlgInfo->pService->lpServiceName,
452                                           pPageData->dlgInfo->pService->lpDisplayName,
453                                           ACTION_RESUME,
454                                           NULL);
455 
456                     UpdateServiceStatus(pPageData->dlgInfo->pService);
457                     ChangeListViewText(pPageData->dlgInfo->Info, pPageData->dlgInfo->pService, LVSTATUS);
458                     SetButtonStates(pPageData->dlgInfo, hwndDlg);
459                     SetServiceStatusText(pPageData->dlgInfo, hwndDlg);
460                     break;
461 
462                 case IDC_EDIT:
463                     SendDlgItemMessage(hwndDlg, IDC_DISP_NAME, EM_SETREADONLY, FALSE, 0);
464                     SendDlgItemMessage(hwndDlg, IDC_DESCRIPTION, EM_SETREADONLY, FALSE, 0);
465                     SendDlgItemMessage(hwndDlg, IDC_EXEPATH, EM_SETREADONLY, FALSE, 0);
466                     EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT), FALSE);
467                     break;
468             }
469             break;
470 
471         case WM_NOTIFY:
472             switch (((LPNMHDR)lParam)->code)
473             {
474                 case PSN_APPLY:
475                     if (pPageData->bDisplayNameChanged ||
476                         pPageData->bDescriptionChanged ||
477                         pPageData->bBinaryPathChanged ||
478                         pPageData->bStartTypeChanged)
479                     {
480                         SaveDlgInfo(pPageData, hwndDlg);
481                         SetButtonStates(pPageData->dlgInfo, hwndDlg);
482                         pPageData->bDisplayNameChanged = FALSE;
483                         pPageData->bDescriptionChanged = FALSE;
484                         pPageData->bBinaryPathChanged = FALSE;
485                         pPageData->bStartTypeChanged = FALSE;
486                     }
487                     break;
488             }
489             break;
490     }
491 
492     return FALSE;
493 }
494