2 * PROJECT: ReactOS Services
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/mscutils/servman/propsheet_recovery.c
5 * PURPOSE: Recovery property page
14 typedef struct _RECOVERYDATA
16 ENUM_SERVICE_STATUS_PROCESS
*pService
;
17 LPSERVICE_FAILURE_ACTIONS pServiceFailure
;
19 } RECOVERYDATA
, *PRECOVERYDATA
;
29 for (id
= IDS_NO_ACTION
; id
<= IDS_RESTART_COMPUTER
; id
++)
31 if (AllocAndLoadString(&lpAction
,
35 SendDlgItemMessageW(hwndDlg
,
41 SendDlgItemMessageW(hwndDlg
,
47 SendDlgItemMessageW(hwndDlg
,
48 IDC_SUBSEQUENT_FAILURES
,
57 SendDlgItemMessageW(hwndDlg
,
63 SendDlgItemMessageW(hwndDlg
,
69 SendDlgItemMessageW(hwndDlg
,
70 IDC_SUBSEQUENT_FAILURES
,
75 SendDlgItemMessageW(hwndDlg
,
81 SendDlgItemMessageW(hwndDlg
,
87 for (id
= IDC_RESTART_TEXT1
; id
<= IDC_RESTART_OPTIONS
; id
++)
88 EnableWindow(GetDlgItem(hwndDlg
, id
), FALSE
);
95 PRECOVERYDATA pRecoveryData
)
97 LPSERVICE_FAILURE_ACTIONS pServiceFailure
= NULL
;
98 SC_HANDLE hManager
= NULL
;
99 SC_HANDLE hService
= NULL
;
101 DWORD cbBytesNeeded
= 0;
103 hManager
= OpenSCManager(NULL
,
106 if (hManager
== NULL
)
112 hService
= OpenService(hManager
, pRecoveryData
->pService
->lpServiceName
, SERVICE_QUERY_CONFIG
);
113 if (hService
== NULL
)
119 if (!QueryServiceConfig2(hService
,
120 SERVICE_CONFIG_FAILURE_ACTIONS
,
125 if (cbBytesNeeded
== 0)
132 pServiceFailure
= HeapAlloc(GetProcessHeap(), 0, cbBytesNeeded
);
133 if (pServiceFailure
== NULL
)
135 SetLastError(ERROR_OUTOFMEMORY
);
140 if (!QueryServiceConfig2(hService
,
141 SERVICE_CONFIG_FAILURE_ACTIONS
,
142 (LPBYTE
)pServiceFailure
,
150 pRecoveryData
->pServiceFailure
= pServiceFailure
;
153 if (bResult
== FALSE
&& pServiceFailure
!= NULL
)
154 HeapFree(GetProcessHeap(), 0, pServiceFailure
);
157 CloseServiceHandle(hService
);
160 CloseServiceHandle(hManager
);
169 PRECOVERYDATA pRecoveryData
)
172 PWSTR startPtr
, endPtr
;
173 INT index
, id
, length
;
176 for (i
= 0; i
< min(pRecoveryData
->pServiceFailure
->cActions
, 3); i
++)
180 switch (pRecoveryData
->pServiceFailure
->lpsaActions
[i
].Type
)
186 case SC_ACTION_RESTART
:
189 wsprintf(szBuffer
, L
"%lu", pRecoveryData
->pServiceFailure
->lpsaActions
[i
].Delay
/ 60000);
190 SendDlgItemMessageW(hwndDlg
,
196 for (id
= IDC_RESTART_TEXT1
; id
<= IDC_RESTART_TEXT2
; id
++)
197 EnableWindow(GetDlgItem(hwndDlg
, id
), TRUE
);
200 case SC_ACTION_REBOOT
:
203 EnableWindow(GetDlgItem(hwndDlg
, IDC_RESTART_OPTIONS
), TRUE
);
206 case SC_ACTION_RUN_COMMAND
:
209 for (id
= IDC_RUN_GROUPBOX
; id
<= IDC_ADD_FAILCOUNT
; id
++)
210 EnableWindow(GetDlgItem(hwndDlg
, id
), TRUE
);
216 SendDlgItemMessageW(hwndDlg
,
217 IDC_FIRST_FAILURE
+ i
,
224 wsprintf(szBuffer
, L
"%lu", pRecoveryData
->pServiceFailure
->dwResetPeriod
/ 86400);
225 SendDlgItemMessageW(hwndDlg
,
231 if (pRecoveryData
->pServiceFailure
->lpCommand
!= NULL
)
233 ZeroMemory(szBuffer
, sizeof(szBuffer
));
235 startPtr
= pRecoveryData
->pServiceFailure
->lpCommand
;
236 if (*startPtr
== L
'\"')
239 endPtr
= wcschr(startPtr
, L
'\"');
242 length
= (INT
)((LONG_PTR
)endPtr
- (LONG_PTR
)startPtr
);
243 CopyMemory(szBuffer
, startPtr
, length
);
247 wcscpy(szBuffer
, startPtr
);
250 SendDlgItemMessageW(hwndDlg
,
256 ZeroMemory(szBuffer
, sizeof(szBuffer
));
260 startPtr
= endPtr
+ 1;
261 while (iswspace(*startPtr
))
264 endPtr
= wcsstr(pRecoveryData
->pServiceFailure
->lpCommand
, L
"/fail=%1%");
267 while (iswspace(*(endPtr
- 1)))
270 length
= (INT
)((LONG_PTR
)endPtr
- (LONG_PTR
)startPtr
);
271 CopyMemory(szBuffer
, startPtr
, length
);
275 wcscpy(szBuffer
, startPtr
);
278 SendDlgItemMessageW(hwndDlg
,
284 endPtr
= wcsstr(pRecoveryData
->pServiceFailure
->lpCommand
, L
"/fail=%1%");
287 SendDlgItemMessageW(hwndDlg
,
300 UpdateFailureActions(
302 PRECOVERYDATA pRecoveryData
)
305 BOOL bRestartService
= FALSE
;
306 BOOL bRunProgram
= FALSE
;
307 BOOL bRebootComputer
= FALSE
;
309 for (id
= IDC_FIRST_FAILURE
; id
<= IDC_SUBSEQUENT_FAILURES
; id
++)
311 index
= SendDlgItemMessageW(hwndDlg
,
318 case 1: /* Restart Service */
319 bRestartService
= TRUE
;
322 case 2: /* Run Program */
326 case 3: /* Reboot Computer */
327 bRebootComputer
= TRUE
;
332 for (id
= IDC_RESTART_TEXT1
; id
<= IDC_RESTART_TEXT2
; id
++)
333 EnableWindow(GetDlgItem(hwndDlg
, id
), bRestartService
);
335 for (id
= IDC_RUN_GROUPBOX
; id
<= IDC_ADD_FAILCOUNT
; id
++)
336 EnableWindow(GetDlgItem(hwndDlg
, id
), bRunProgram
);
338 EnableWindow(GetDlgItem(hwndDlg
, IDC_RESTART_OPTIONS
), bRebootComputer
);
347 WCHAR szFile
[MAX_PATH
] = {'\0'};
348 PWCHAR pszFilter
= L
"Executable Files (*.exe;*.com;*.cmd;*.bat)\0*.exe;*.com;*.cmd;*.bat\0";
351 ZeroMemory(&ofn
, sizeof(ofn
));
353 ofn
.lStructSize
= sizeof(ofn
);
354 ofn
.Flags
= OFN_EXPLORER
| OFN_HIDEREADONLY
| OFN_FILEMUSTEXIST
| OFN_PATHMUSTEXIST
| OFN_ENABLESIZING
;
355 ofn
.hwndOwner
= hwndDlg
;
356 ofn
.lpstrFilter
= pszFilter
;
357 ofn
.lpstrFile
= szFile
;
358 ofn
.nMaxFile
= MAX_PATH
;
360 if (GetOpenFileName(&ofn
))
362 SendDlgItemMessageW(hwndDlg
,
376 SERVICE_FAILURE_ACTIONS FailureActions
;
377 BOOL bRestartService
= FALSE
;
378 BOOL bRunProgram
= FALSE
;
379 BOOL bRebootComputer
= FALSE
;
382 ZeroMemory(&FailureActions
, sizeof(FailureActions
));
384 /* Count the number of valid failure actions */
385 for (id
= IDC_FIRST_FAILURE
; id
<= IDC_SUBSEQUENT_FAILURES
; id
++)
387 index
= SendDlgItemMessageW(hwndDlg
,
394 case 1: /* Restart Service */
395 bRestartService
= TRUE
;
396 FailureActions
.cActions
++;
399 case 2: /* Run Program */
401 FailureActions
.cActions
++;
404 case 3: /* Reboot Computer */
405 bRebootComputer
= TRUE
;
406 FailureActions
.cActions
++;
428 typedef struct _SERVICE_FAILURE_ACTIONS
{
433 SC_ACTION
*lpsaActions
;
434 } SERVICE_FAILURE_ACTIONS
, *LPSERVICE_FAILURE_ACTIONS
;
447 PRECOVERYDATA pRecoveryData
;
449 /* Get the window context */
450 pRecoveryData
= (PRECOVERYDATA
)GetWindowLongPtr(hwndDlg
,
452 if (pRecoveryData
== NULL
&& uMsg
!= WM_INITDIALOG
)
458 pRecoveryData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RECOVERYDATA
));
459 if (pRecoveryData
!= NULL
)
461 SetWindowLongPtr(hwndDlg
,
463 (LONG_PTR
)pRecoveryData
);
465 pRecoveryData
->pService
= ((PSERVICEPROPSHEET
)(((LPPROPSHEETPAGE
)lParam
)->lParam
))->pService
;
467 InitRecoveryPage(hwndDlg
);
469 if (GetServiceFailure(pRecoveryData
))
471 ShowFailureActions(hwndDlg
, pRecoveryData
);
477 if (pRecoveryData
!= NULL
)
479 if (pRecoveryData
->pServiceFailure
!= NULL
)
480 HeapFree(GetProcessHeap(), 0, pRecoveryData
->pServiceFailure
);
482 HeapFree(GetProcessHeap(), 0, pRecoveryData
);
487 switch(LOWORD(wParam
))
489 case IDC_FIRST_FAILURE
:
490 case IDC_SECOND_FAILURE
:
491 case IDC_SUBSEQUENT_FAILURES
:
492 if (HIWORD(wParam
) == CBN_SELCHANGE
)
494 UpdateFailureActions(hwndDlg
, pRecoveryData
);
495 pRecoveryData
->bChanged
= TRUE
;
496 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
501 case IDC_RESTART_TIME
:
504 if (HIWORD(wParam
) == EN_CHANGE
)
506 pRecoveryData
->bChanged
= TRUE
;
507 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
511 case IDC_ADD_FAILCOUNT
:
512 if (HIWORD(wParam
) == BN_CLICKED
)
514 pRecoveryData
->bChanged
= TRUE
;
515 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
519 case IDC_BROWSE_PROGRAM
:
523 case IDC_RESTART_OPTIONS
:
529 switch (((LPNMHDR
)lParam
)->code
)
532 if (pRecoveryData
->bChanged
)
534 SetFailureActions(hwndDlg
);
535 pRecoveryData
->bChanged
= FALSE
;