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 i
, index
, id
, length
;
175 for (i
= 0; i
< min(pRecoveryData
->pServiceFailure
->cActions
, 3); i
++)
179 switch (pRecoveryData
->pServiceFailure
->lpsaActions
[i
].Type
)
185 case SC_ACTION_RESTART
:
188 wsprintf(szBuffer
, L
"%lu", pRecoveryData
->pServiceFailure
->lpsaActions
[i
].Delay
/ 60000);
189 SendDlgItemMessageW(hwndDlg
,
195 for (id
= IDC_RESTART_TEXT1
; id
<= IDC_RESTART_TEXT2
; id
++)
196 EnableWindow(GetDlgItem(hwndDlg
, id
), TRUE
);
199 case SC_ACTION_REBOOT
:
202 EnableWindow(GetDlgItem(hwndDlg
, IDC_RESTART_OPTIONS
), TRUE
);
205 case SC_ACTION_RUN_COMMAND
:
208 for (id
= IDC_RUN_GROUPBOX
; id
<= IDC_ADD_FAILCOUNT
; id
++)
209 EnableWindow(GetDlgItem(hwndDlg
, id
), TRUE
);
215 SendDlgItemMessageW(hwndDlg
,
216 IDC_FIRST_FAILURE
+ i
,
223 wsprintf(szBuffer
, L
"%lu", pRecoveryData
->pServiceFailure
->dwResetPeriod
/ 86400);
224 SendDlgItemMessageW(hwndDlg
,
230 if (pRecoveryData
->pServiceFailure
->lpCommand
!= NULL
)
232 ZeroMemory(szBuffer
, sizeof(szBuffer
));
234 startPtr
= pRecoveryData
->pServiceFailure
->lpCommand
;
235 if (*startPtr
== L
'\"')
238 endPtr
= wcschr(startPtr
, L
'\"');
241 length
= (INT
)((LONG_PTR
)endPtr
- (LONG_PTR
)startPtr
);
242 CopyMemory(szBuffer
, startPtr
, length
);
246 wcscpy(szBuffer
, startPtr
);
249 SendDlgItemMessageW(hwndDlg
,
255 ZeroMemory(szBuffer
, sizeof(szBuffer
));
259 startPtr
= endPtr
+ 1;
260 while (iswspace(*startPtr
))
263 endPtr
= wcsstr(pRecoveryData
->pServiceFailure
->lpCommand
, L
"/fail=%1%");
266 while (iswspace(*(endPtr
- 1)))
269 length
= (INT
)((LONG_PTR
)endPtr
- (LONG_PTR
)startPtr
);
270 CopyMemory(szBuffer
, startPtr
, length
);
274 wcscpy(szBuffer
, startPtr
);
277 SendDlgItemMessageW(hwndDlg
,
283 endPtr
= wcsstr(pRecoveryData
->pServiceFailure
->lpCommand
, L
"/fail=%1%");
286 SendDlgItemMessageW(hwndDlg
,
299 UpdateFailureActions(
301 PRECOVERYDATA pRecoveryData
)
304 BOOL bRestartService
= FALSE
;
305 BOOL bRunProgram
= FALSE
;
306 BOOL bRebootComputer
= FALSE
;
308 for (id
= IDC_FIRST_FAILURE
; id
<= IDC_SUBSEQUENT_FAILURES
; id
++)
310 index
= SendDlgItemMessageW(hwndDlg
,
317 case 1: /* Restart Service */
318 bRestartService
= TRUE
;
321 case 2: /* Run Program */
325 case 3: /* Reboot Computer */
326 bRebootComputer
= TRUE
;
331 for (id
= IDC_RESTART_TEXT1
; id
<= IDC_RESTART_TEXT2
; id
++)
332 EnableWindow(GetDlgItem(hwndDlg
, id
), bRestartService
);
334 for (id
= IDC_RUN_GROUPBOX
; id
<= IDC_ADD_FAILCOUNT
; id
++)
335 EnableWindow(GetDlgItem(hwndDlg
, id
), bRunProgram
);
337 EnableWindow(GetDlgItem(hwndDlg
, IDC_RESTART_OPTIONS
), bRebootComputer
);
346 WCHAR szFile
[MAX_PATH
] = {'\0'};
347 PWCHAR pszFilter
= L
"Executable Files (*.exe;*.com;*.cmd;*.bat)\0*.exe;*.com;*.cmd;*.bat\0";
350 ZeroMemory(&ofn
, sizeof(ofn
));
352 ofn
.lStructSize
= sizeof(ofn
);
353 ofn
.Flags
= OFN_HIDEREADONLY
| OFN_FILEMUSTEXIST
| OFN_PATHMUSTEXIST
| OFN_ENABLESIZING
;
354 ofn
.hwndOwner
= hwndDlg
;
355 ofn
.lpstrFilter
= pszFilter
;
356 ofn
.lpstrFile
= szFile
;
357 ofn
.nMaxFile
= MAX_PATH
;
359 if (GetOpenFileName(&ofn
))
361 SendDlgItemMessageW(hwndDlg
,
375 SERVICE_FAILURE_ACTIONS FailureActions
;
376 BOOL bRestartService
= FALSE
;
377 BOOL bRunProgram
= FALSE
;
378 BOOL bRebootComputer
= FALSE
;
381 ZeroMemory(&FailureActions
, sizeof(FailureActions
));
383 /* Count the number of valid failure actions */
384 for (id
= IDC_FIRST_FAILURE
; id
<= IDC_SUBSEQUENT_FAILURES
; id
++)
386 index
= SendDlgItemMessageW(hwndDlg
,
393 case 1: /* Restart Service */
394 bRestartService
= TRUE
;
395 FailureActions
.cActions
++;
398 case 2: /* Run Program */
400 FailureActions
.cActions
++;
403 case 3: /* Reboot Computer */
404 bRebootComputer
= TRUE
;
405 FailureActions
.cActions
++;
427 typedef struct _SERVICE_FAILURE_ACTIONS
{
432 SC_ACTION
*lpsaActions
;
433 } SERVICE_FAILURE_ACTIONS
, *LPSERVICE_FAILURE_ACTIONS
;
446 PRECOVERYDATA pRecoveryData
;
448 /* Get the window context */
449 pRecoveryData
= (PRECOVERYDATA
)GetWindowLongPtr(hwndDlg
,
451 if (pRecoveryData
== NULL
&& uMsg
!= WM_INITDIALOG
)
457 pRecoveryData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RECOVERYDATA
));
458 if (pRecoveryData
!= NULL
)
460 SetWindowLongPtr(hwndDlg
,
462 (LONG_PTR
)pRecoveryData
);
464 pRecoveryData
->pService
= ((PSERVICEPROPSHEET
)(((LPPROPSHEETPAGE
)lParam
)->lParam
))->pService
;
466 InitRecoveryPage(hwndDlg
);
468 if (GetServiceFailure(pRecoveryData
))
470 ShowFailureActions(hwndDlg
, pRecoveryData
);
476 if (pRecoveryData
!= NULL
)
478 if (pRecoveryData
->pServiceFailure
!= NULL
)
479 HeapFree(GetProcessHeap(), 0, pRecoveryData
->pServiceFailure
);
481 HeapFree(GetProcessHeap(), 0, pRecoveryData
);
486 switch(LOWORD(wParam
))
488 case IDC_FIRST_FAILURE
:
489 case IDC_SECOND_FAILURE
:
490 case IDC_SUBSEQUENT_FAILURES
:
491 if (HIWORD(wParam
) == CBN_SELCHANGE
)
493 UpdateFailureActions(hwndDlg
, pRecoveryData
);
494 pRecoveryData
->bChanged
= TRUE
;
495 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
500 case IDC_RESTART_TIME
:
503 if (HIWORD(wParam
) == EN_CHANGE
)
505 pRecoveryData
->bChanged
= TRUE
;
506 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
510 case IDC_ADD_FAILCOUNT
:
511 if (HIWORD(wParam
) == BN_CLICKED
)
513 pRecoveryData
->bChanged
= TRUE
;
514 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
518 case IDC_BROWSE_PROGRAM
:
522 case IDC_RESTART_OPTIONS
:
528 switch (((LPNMHDR
)lParam
)->code
)
531 if (pRecoveryData
->bChanged
)
533 SetFailureActions(hwndDlg
);
534 pRecoveryData
->bChanged
= FALSE
;