diff --git a/2.x/trunk/ProcessHacker/srvprp.c b/2.x/trunk/ProcessHacker/srvprp.c
index 4d8b4dfe9..33c2e6295 100644
--- a/2.x/trunk/ProcessHacker/srvprp.c
+++ b/2.x/trunk/ProcessHacker/srvprp.c
@@ -66,7 +66,7 @@ VOID PhShowServiceProperties(
{
PROPSHEETHEADER propSheetHeader = { sizeof(propSheetHeader) };
PROPSHEETPAGE propSheetPage;
- HPROPSHEETPAGE pages[10];
+ HPROPSHEETPAGE pages[32];
SERVICE_PROPERTIES_CONTEXT context;
PH_STD_OBJECT_SECURITY stdObjectSecurity;
PPH_ACCESS_ENTRY accessEntries;
@@ -439,16 +439,25 @@ INT_PTR CALLBACK PhpServiceGeneralDlgProc(
}
else
{
- PhShowStatus(hwndDlg, L"Unable to change service configuration",
- 0, GetLastError());
- SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID);
+ goto ErrorCase;
}
CloseServiceHandle(serviceHandle);
}
else
{
- PhShowStatus(hwndDlg, L"Unable to change service configuration", 0, GetLastError());
+ goto ErrorCase;
+ }
+
+ return TRUE;
+ErrorCase:
+ if (PhShowMessage(
+ hwndDlg,
+ MB_ICONERROR | MB_RETRYCANCEL,
+ L"Unable to change service configuration: %s",
+ ((PPH_STRING)PHA_DEREFERENCE(PhGetWin32Message(GetLastError())))->Buffer
+ ) == IDRETRY)
+ {
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID);
}
}
diff --git a/2.x/trunk/phlib/include/ph.h b/2.x/trunk/phlib/include/ph.h
index 669aef2d5..a4cf25c1e 100644
--- a/2.x/trunk/phlib/include/ph.h
+++ b/2.x/trunk/phlib/include/ph.h
@@ -1921,6 +1921,12 @@ PVOID PhGetServiceConfig(
__in SC_HANDLE ServiceHandle
);
+PHLIBAPI
+PVOID PhQueryServiceVariableSize(
+ __in SC_HANDLE ServiceHandle,
+ __in ULONG InfoLevel
+ );
+
PHLIBAPI
PPH_STRING PhGetServiceDescription(
__in SC_HANDLE ServiceHandle
diff --git a/2.x/trunk/phlib/svcsup.c b/2.x/trunk/phlib/svcsup.c
index b3a4a0a6c..0ee6c7d84 100644
--- a/2.x/trunk/phlib/svcsup.c
+++ b/2.x/trunk/phlib/svcsup.c
@@ -180,41 +180,65 @@ PVOID PhGetServiceConfig(
return buffer;
}
+PVOID PhQueryServiceVariableSize(
+ __in SC_HANDLE ServiceHandle,
+ __in ULONG InfoLevel
+ )
+{
+ PVOID buffer;
+ ULONG bufferSize = 0x100;
+
+ buffer = PhAllocate(bufferSize);
+
+ if (!QueryServiceConfig2(
+ ServiceHandle,
+ InfoLevel,
+ (BYTE *)buffer,
+ bufferSize,
+ &bufferSize
+ ))
+ {
+ PhFree(buffer);
+ buffer = PhAllocate(bufferSize);
+
+ if (!QueryServiceConfig2(
+ ServiceHandle,
+ InfoLevel,
+ (BYTE *)buffer,
+ bufferSize,
+ &bufferSize
+ ))
+ {
+ PhFree(buffer);
+ return NULL;
+ }
+ }
+
+ return buffer;
+}
+
PPH_STRING PhGetServiceDescription(
__in SC_HANDLE ServiceHandle
)
{
- PVOID buffer;
- ULONG returnLength = 0x100;
- LPSERVICE_DESCRIPTION serviceDescription;
PPH_STRING description = NULL;
+ LPSERVICE_DESCRIPTION serviceDescription;
- QueryServiceConfig2(
- ServiceHandle,
- SERVICE_CONFIG_DESCRIPTION,
- NULL,
- 0,
- &returnLength
- );
- buffer = PhAllocate(returnLength);
+ serviceDescription = PhQueryServiceVariableSize(ServiceHandle, SERVICE_CONFIG_DESCRIPTION);
- if (QueryServiceConfig2(
- ServiceHandle,
- SERVICE_CONFIG_DESCRIPTION,
- (BYTE *)buffer,
- returnLength,
- &returnLength
- ))
+ if (serviceDescription)
{
- serviceDescription = (LPSERVICE_DESCRIPTION)buffer;
-
if (serviceDescription->lpDescription)
description = PhCreateString(serviceDescription->lpDescription);
+
+ PhFree(serviceDescription);
+
+ return description;
+ }
+ else
+ {
+ return NULL;
}
-
- PhFree(buffer);
-
- return description;
}
BOOLEAN PhGetServiceDelayedAutoStart(
diff --git a/2.x/trunk/plugins/ExtendedNotifications/main.c b/2.x/trunk/plugins/ExtendedNotifications/main.c
index b3c1cd264..f045ad05f 100644
--- a/2.x/trunk/plugins/ExtendedNotifications/main.c
+++ b/2.x/trunk/plugins/ExtendedNotifications/main.c
@@ -1,3 +1,25 @@
+/*
+ * Process Hacker Extended Notifications -
+ * main program
+ *
+ * Copyright (C) 2010 wj32
+ *
+ * This file is part of Process Hacker.
+ *
+ * Process Hacker is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Process Hacker is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Process Hacker. If not, see .
+ */
+
#include
#include
#include "extnoti.h"
diff --git a/2.x/trunk/plugins/ExtendedServices/ExtendedServices.rc b/2.x/trunk/plugins/ExtendedServices/ExtendedServices.rc
index 868cc586f..42e0491c2 100644
--- a/2.x/trunk/plugins/ExtendedServices/ExtendedServices.rc
+++ b/2.x/trunk/plugins/ExtendedServices/ExtendedServices.rc
@@ -100,6 +100,49 @@ BEGIN
LTEXT "Static",IDC_MESSAGE,7,7,268,8
END
+IDD_SRVRECOVERY DIALOGEX 0, 0, 282, 183
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Recovery"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "First failure:",IDC_STATIC,7,8,40,8
+ COMBOBOX IDC_FIRSTFAILURE,85,7,103,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_SECONDFAILURE,85,23,103,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_SUBSEQUENTFAILURES,85,39,103,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Second failure:",IDC_STATIC,7,24,49,8
+ LTEXT "Subsequent failures:",IDC_STATIC,7,40,67,8
+ LTEXT "Reset fail count after:",IDC_STATIC,7,56,72,8
+ EDITTEXT IDC_RESETFAILCOUNT,85,55,40,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "days",IDC_STATIC,130,56,16,8
+ LTEXT "Restart service after:",IDC_RESTARTSERVICEAFTER_LABEL,7,72,70,8
+ EDITTEXT IDC_RESTARTSERVICEAFTER,85,71,40,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "minutes",IDC_RESTARTSERVICEAFTER_MINUTES,130,72,26,8
+ CONTROL "Enable actions for stops with errors",IDC_ENABLEFORERRORSTOPS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,87,129,10
+ PUSHBUTTON "Restart Computer Options...",IDC_RESTARTCOMPUTEROPTIONS,7,100,114,14
+ GROUPBOX "Run program",IDC_RUNPROGRAM_GROUP,7,118,268,45
+ LTEXT "Program:",IDC_RUNPROGRAM_LABEL,15,132,30,8
+ EDITTEXT IDC_RUNPROGRAM,50,131,165,12,ES_AUTOHSCROLL
+ PUSHBUTTON "Browse...",IDC_BROWSE,220,130,50,14
+ LTEXT "Append /fail=%1% to pass the fail count to the program.",IDC_RUNPROGRAM_INFO,15,148,186,8
+END
+
+IDD_RESTARTCOMP DIALOGEX 0, 0, 245, 137
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Dialog"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,134,116,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,188,116,50,14
+ LTEXT "Restart the computer after:",IDC_STATIC,7,8,90,8
+ EDITTEXT IDC_RESTARTCOMPAFTER,102,7,40,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "minutes",IDC_STATIC,147,8,26,8
+ CONTROL "Before restarting, send this message to computers on the network:",IDC_ENABLERESTARTMESSAGE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,23,231,10
+ EDITTEXT IDC_RESTARTMESSAGE,7,36,231,76,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
+ PUSHBUTTON "Use Default Message",IDC_USEDEFAULTMESSAGE,7,116,79,14
+END
+
/////////////////////////////////////////////////////////////////////////////
//
@@ -116,6 +159,22 @@ BEGIN
TOPMARGIN, 7
BOTTOMMARGIN, 176
END
+
+ IDD_SRVRECOVERY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 275
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 176
+ END
+
+ IDD_RESTARTCOMP, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 238
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 130
+ END
END
#endif // APSTUDIO_INVOKED
diff --git a/2.x/trunk/plugins/ExtendedServices/ExtendedServices.vcproj b/2.x/trunk/plugins/ExtendedServices/ExtendedServices.vcproj
index 0d6e74355..48f9731ef 100644
--- a/2.x/trunk/plugins/ExtendedServices/ExtendedServices.vcproj
+++ b/2.x/trunk/plugins/ExtendedServices/ExtendedServices.vcproj
@@ -340,6 +340,10 @@
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
+
+
@@ -350,6 +354,14 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
+
+
+
+
diff --git a/2.x/trunk/plugins/ExtendedServices/depend.c b/2.x/trunk/plugins/ExtendedServices/depend.c
new file mode 100644
index 000000000..98d071e88
--- /dev/null
+++ b/2.x/trunk/plugins/ExtendedServices/depend.c
@@ -0,0 +1,349 @@
+/*
+ * Process Hacker Extended Services -
+ * dependencies and dependents
+ *
+ * Copyright (C) 2010 wj32
+ *
+ * This file is part of Process Hacker.
+ *
+ * Process Hacker is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Process Hacker is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Process Hacker. If not, see .
+ */
+
+#include
+#include
+#include "extsrv.h"
+#include "resource.h"
+
+typedef struct _SERVICE_LIST_CONTEXT
+{
+ HWND ServiceListHandle;
+ PH_LAYOUT_MANAGER LayoutManager;
+} SERVICE_LIST_CONTEXT, *PSERVICE_LIST_CONTEXT;
+
+LPENUM_SERVICE_STATUS EsEnumDependentServices(
+ __in SC_HANDLE ServiceHandle,
+ __in_opt ULONG State,
+ __out PULONG Count
+ )
+{
+ LOGICAL result;
+ PVOID buffer;
+ ULONG bufferSize;
+ ULONG returnLength;
+ ULONG servicesReturned;
+
+ if (!State)
+ State = SERVICE_STATE_ALL;
+
+ bufferSize = 0x800;
+ buffer = PhAllocate(bufferSize);
+
+ if (!(result = EnumDependentServices(
+ ServiceHandle,
+ State,
+ buffer,
+ bufferSize,
+ &returnLength,
+ &servicesReturned
+ )))
+ {
+ if (GetLastError() == ERROR_MORE_DATA)
+ {
+ PhFree(buffer);
+ bufferSize = returnLength;
+ buffer = PhAllocate(bufferSize);
+
+ result = EnumDependentServices(
+ ServiceHandle,
+ State,
+ buffer,
+ bufferSize,
+ &returnLength,
+ &servicesReturned
+ );
+ }
+
+ if (!result)
+ {
+ PhFree(buffer);
+ return NULL;
+ }
+ }
+
+ *Count = servicesReturned;
+
+ return buffer;
+}
+
+static VOID EspLayoutServiceListControl(
+ __in HWND hwndDlg,
+ __in HWND ServiceListHandle
+ )
+{
+ RECT rect;
+
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), &rect);
+ MapWindowPoints(NULL, hwndDlg, (POINT *)&rect, 2);
+
+ MoveWindow(
+ ServiceListHandle,
+ rect.left,
+ rect.top,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ TRUE
+ );
+}
+
+INT_PTR CALLBACK EspServiceDependenciesDlgProc(
+ __in HWND hwndDlg,
+ __in UINT uMsg,
+ __in WPARAM wParam,
+ __in LPARAM lParam
+ )
+{
+ PSERVICE_LIST_CONTEXT context;
+
+ if (uMsg == WM_INITDIALOG)
+ {
+ context = PhAllocate(sizeof(SERVICE_LIST_CONTEXT));
+ memset(context, 0, sizeof(SERVICE_LIST_CONTEXT));
+
+ SetProp(hwndDlg, L"Context", (HANDLE)context);
+ }
+ else
+ {
+ context = (PSERVICE_LIST_CONTEXT)GetProp(hwndDlg, L"Context");
+
+ if (uMsg == WM_DESTROY)
+ RemoveProp(hwndDlg, L"Context");
+ }
+
+ if (!context)
+ return FALSE;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam;
+ PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)propSheetPage->lParam;
+ HWND serviceListHandle;
+ PPH_LIST serviceList;
+ SC_HANDLE serviceHandle;
+ ULONG win32Result = 0;
+ BOOLEAN success = FALSE;
+ PPH_SERVICE_ITEM *services;
+
+ SetDlgItemText(hwndDlg, IDC_MESSAGE, L"This service depends on the following services:");
+
+ PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
+ PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), NULL, PH_ANCHOR_ALL);
+
+ if (serviceHandle = PhOpenService(serviceItem->Name->Buffer, SERVICE_QUERY_CONFIG))
+ {
+ LPQUERY_SERVICE_CONFIG serviceConfig;
+
+ if (serviceConfig = PhGetServiceConfig(serviceHandle))
+ {
+ PWSTR dependency;
+ PPH_SERVICE_ITEM dependencyService;
+
+ dependency = serviceConfig->lpDependencies;
+ serviceList = PhCreateList(8);
+ success = TRUE;
+
+ if (dependency)
+ {
+ ULONG dependencyLength;
+
+ while (TRUE)
+ {
+ dependencyLength = wcslen(dependency);
+
+ if (dependencyLength == 0)
+ break;
+
+ if (dependency[0] == SC_GROUP_IDENTIFIER)
+ goto ContinueLoop;
+
+ if (dependencyService = PhReferenceServiceItem(dependency))
+ PhAddItemList(serviceList, dependencyService);
+
+ContinueLoop:
+ dependency += dependencyLength + 1;
+ }
+ }
+
+ services = PhAllocateCopy(serviceList->Items, sizeof(PPH_SERVICE_ITEM) * serviceList->Count);
+
+ serviceListHandle = PhCreateServiceListControl(hwndDlg, services, serviceList->Count);
+ context->ServiceListHandle = serviceListHandle;
+ EspLayoutServiceListControl(hwndDlg, serviceListHandle);
+ ShowWindow(serviceListHandle, SW_SHOW);
+
+ PhDereferenceObject(serviceList);
+ PhFree(serviceConfig);
+ }
+ else
+ {
+ win32Result = GetLastError();
+ }
+
+ CloseServiceHandle(serviceHandle);
+ }
+ else
+ {
+ win32Result = GetLastError();
+ }
+
+ if (!success)
+ {
+ SetDlgItemText(hwndDlg, IDC_SERVICES_LAYOUT, PhaConcatStrings2(L"Unable to enumerate dependencies: ",
+ ((PPH_STRING)PHA_DEREFERENCE(PhGetWin32Message(win32Result)))->Buffer)->Buffer);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), SW_SHOW);
+ }
+ }
+ break;
+ case WM_DESTROY:
+ {
+ PhDeleteLayoutManager(&context->LayoutManager);
+ PhFree(context);
+ }
+ break;
+ case WM_SIZE:
+ {
+ PhLayoutManagerLayout(&context->LayoutManager);
+
+ if (context->ServiceListHandle)
+ EspLayoutServiceListControl(hwndDlg, context->ServiceListHandle);
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+INT_PTR CALLBACK EspServiceDependentsDlgProc(
+ __in HWND hwndDlg,
+ __in UINT uMsg,
+ __in WPARAM wParam,
+ __in LPARAM lParam
+ )
+{
+ PSERVICE_LIST_CONTEXT context;
+
+ if (uMsg == WM_INITDIALOG)
+ {
+ context = PhAllocate(sizeof(SERVICE_LIST_CONTEXT));
+ memset(context, 0, sizeof(SERVICE_LIST_CONTEXT));
+
+ SetProp(hwndDlg, L"Context", (HANDLE)context);
+ }
+ else
+ {
+ context = (PSERVICE_LIST_CONTEXT)GetProp(hwndDlg, L"Context");
+
+ if (uMsg == WM_DESTROY)
+ RemoveProp(hwndDlg, L"Context");
+ }
+
+ if (!context)
+ return FALSE;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam;
+ PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)propSheetPage->lParam;
+ HWND serviceListHandle;
+ PPH_LIST serviceList;
+ SC_HANDLE serviceHandle;
+ ULONG win32Result = 0;
+ BOOLEAN success = FALSE;
+ PPH_SERVICE_ITEM *services;
+
+ SetDlgItemText(hwndDlg, IDC_MESSAGE, L"The following services depend on this service:");
+
+ PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
+ PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), NULL, PH_ANCHOR_ALL);
+
+ if (serviceHandle = PhOpenService(serviceItem->Name->Buffer, SERVICE_ENUMERATE_DEPENDENTS))
+ {
+ LPENUM_SERVICE_STATUS dependentServices;
+ ULONG numberOfDependentServices;
+
+ if (dependentServices = EsEnumDependentServices(serviceHandle, 0, &numberOfDependentServices))
+ {
+ ULONG i;
+ PPH_SERVICE_ITEM dependentService;
+
+ serviceList = PhCreateList(8);
+ success = TRUE;
+
+ for (i = 0; i < numberOfDependentServices; i++)
+ {
+ if (dependentService = PhReferenceServiceItem(dependentServices[i].lpServiceName))
+ PhAddItemList(serviceList, dependentService);
+ }
+
+ services = PhAllocateCopy(serviceList->Items, sizeof(PPH_SERVICE_ITEM) * serviceList->Count);
+
+ serviceListHandle = PhCreateServiceListControl(hwndDlg, services, serviceList->Count);
+ context->ServiceListHandle = serviceListHandle;
+ EspLayoutServiceListControl(hwndDlg, serviceListHandle);
+ ShowWindow(serviceListHandle, SW_SHOW);
+
+ PhDereferenceObject(serviceList);
+ PhFree(dependentServices);
+ }
+ else
+ {
+ win32Result = GetLastError();
+ }
+
+ CloseServiceHandle(serviceHandle);
+ }
+ else
+ {
+ win32Result = GetLastError();
+ }
+
+ if (!success)
+ {
+ SetDlgItemText(hwndDlg, IDC_SERVICES_LAYOUT, PhaConcatStrings2(L"Unable to enumerate dependents: ",
+ ((PPH_STRING)PHA_DEREFERENCE(PhGetWin32Message(win32Result)))->Buffer)->Buffer);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), SW_SHOW);
+ }
+ }
+ break;
+ case WM_DESTROY:
+ {
+ PhDeleteLayoutManager(&context->LayoutManager);
+ PhFree(context);
+ }
+ break;
+ case WM_SIZE:
+ {
+ PhLayoutManagerLayout(&context->LayoutManager);
+
+ if (context->ServiceListHandle)
+ EspLayoutServiceListControl(hwndDlg, context->ServiceListHandle);
+ }
+ break;
+ }
+
+ return FALSE;
+}
diff --git a/2.x/trunk/plugins/ExtendedServices/extsrv.h b/2.x/trunk/plugins/ExtendedServices/extsrv.h
new file mode 100644
index 000000000..181fac01f
--- /dev/null
+++ b/2.x/trunk/plugins/ExtendedServices/extsrv.h
@@ -0,0 +1,41 @@
+#ifndef ES_EXTSRV_H
+#define ES_EXTSRV_H
+
+// main
+
+#ifndef MAIN_PRIVATE
+extern PPH_PLUGIN PluginInstance;
+#endif
+
+// depend
+
+LPENUM_SERVICE_STATUS EsEnumDependentServices(
+ __in SC_HANDLE ServiceHandle,
+ __in_opt ULONG State,
+ __out PULONG Count
+ );
+
+INT_PTR CALLBACK EspServiceDependenciesDlgProc(
+ __in HWND hwndDlg,
+ __in UINT uMsg,
+ __in WPARAM wParam,
+ __in LPARAM lParam
+ );
+
+INT_PTR CALLBACK EspServiceDependentsDlgProc(
+ __in HWND hwndDlg,
+ __in UINT uMsg,
+ __in WPARAM wParam,
+ __in LPARAM lParam
+ );
+
+// recovery
+
+INT_PTR CALLBACK EspServiceRecoveryDlgProc(
+ __in HWND hwndDlg,
+ __in UINT uMsg,
+ __in WPARAM wParam,
+ __in LPARAM lParam
+ );
+
+#endif
diff --git a/2.x/trunk/plugins/ExtendedServices/main.c b/2.x/trunk/plugins/ExtendedServices/main.c
index 9b95bd785..ffa324409 100644
--- a/2.x/trunk/plugins/ExtendedServices/main.c
+++ b/2.x/trunk/plugins/ExtendedServices/main.c
@@ -1,12 +1,29 @@
-#include
-#include
-#include "resource.h"
+/*
+ * Process Hacker Extended Services -
+ * main program
+ *
+ * Copyright (C) 2010 wj32
+ *
+ * This file is part of Process Hacker.
+ *
+ * Process Hacker is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Process Hacker is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Process Hacker. If not, see .
+ */
-typedef struct _SERVICE_LIST_CONTEXT
-{
- HWND ServiceListHandle;
- PH_LAYOUT_MANAGER LayoutManager;
-} SERVICE_LIST_CONTEXT, *PSERVICE_LIST_CONTEXT;
+#include
+#define MAIN_PRIVATE
+#include "extsrv.h"
+#include "resource.h"
VOID NTAPI LoadCallback(
__in_opt PVOID Parameter,
@@ -72,323 +89,6 @@ VOID NTAPI LoadCallback(
// Nothing
}
-static VOID PhpLayoutServiceListControl(
- __in HWND hwndDlg,
- __in HWND ServiceListHandle
- )
-{
- RECT rect;
-
- GetWindowRect(GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), &rect);
- MapWindowPoints(NULL, hwndDlg, (POINT *)&rect, 2);
-
- MoveWindow(
- ServiceListHandle,
- rect.left,
- rect.top,
- rect.right - rect.left,
- rect.bottom - rect.top,
- TRUE
- );
-}
-
-INT_PTR CALLBACK PhpServiceDependenciesDlgProc(
- __in HWND hwndDlg,
- __in UINT uMsg,
- __in WPARAM wParam,
- __in LPARAM lParam
- )
-{
- PSERVICE_LIST_CONTEXT context;
-
- if (uMsg == WM_INITDIALOG)
- {
- context = PhAllocate(sizeof(SERVICE_LIST_CONTEXT));
- memset(context, 0, sizeof(SERVICE_LIST_CONTEXT));
-
- SetProp(hwndDlg, L"Context", (HANDLE)context);
- }
- else
- {
- context = (PSERVICE_LIST_CONTEXT)GetProp(hwndDlg, L"Context");
-
- if (uMsg == WM_DESTROY)
- RemoveProp(hwndDlg, L"Context");
- }
-
- if (!context)
- return FALSE;
-
- switch (uMsg)
- {
- case WM_INITDIALOG:
- {
- LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam;
- PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)propSheetPage->lParam;
- HWND serviceListHandle;
- PPH_LIST serviceList;
- SC_HANDLE serviceHandle;
- ULONG win32Result = 0;
- BOOLEAN success = FALSE;
- PPH_SERVICE_ITEM *services;
-
- SetDlgItemText(hwndDlg, IDC_MESSAGE, L"This service depends on the following services:");
-
- PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
- PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), NULL, PH_ANCHOR_ALL);
-
- if (serviceHandle = PhOpenService(serviceItem->Name->Buffer, SERVICE_QUERY_CONFIG))
- {
- LPQUERY_SERVICE_CONFIG serviceConfig;
-
- if (serviceConfig = PhGetServiceConfig(serviceHandle))
- {
- PWSTR dependency;
- PPH_SERVICE_ITEM dependencyService;
-
- dependency = serviceConfig->lpDependencies;
- serviceList = PhCreateList(8);
- success = TRUE;
-
- if (dependency)
- {
- ULONG dependencyLength;
-
- while (TRUE)
- {
- dependencyLength = wcslen(dependency);
-
- if (dependencyLength == 0)
- break;
-
- if (dependency[0] == SC_GROUP_IDENTIFIER)
- goto ContinueLoop;
-
- if (dependencyService = PhReferenceServiceItem(dependency))
- PhAddItemList(serviceList, dependencyService);
-
-ContinueLoop:
- dependency += dependencyLength + 1;
- }
- }
-
- services = PhAllocateCopy(serviceList->Items, sizeof(PPH_SERVICE_ITEM) * serviceList->Count);
-
- serviceListHandle = PhCreateServiceListControl(hwndDlg, services, serviceList->Count);
- context->ServiceListHandle = serviceListHandle;
- PhpLayoutServiceListControl(hwndDlg, serviceListHandle);
- ShowWindow(serviceListHandle, SW_SHOW);
-
- PhDereferenceObject(serviceList);
- PhFree(serviceConfig);
- }
- else
- {
- win32Result = GetLastError();
- }
-
- CloseServiceHandle(serviceHandle);
- }
- else
- {
- win32Result = GetLastError();
- }
-
- if (!success)
- {
- SetDlgItemText(hwndDlg, IDC_SERVICES_LAYOUT, PhaConcatStrings2(L"Unable to enumerate dependencies: ",
- ((PPH_STRING)PHA_DEREFERENCE(PhGetWin32Message(win32Result)))->Buffer)->Buffer);
- ShowWindow(GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), SW_SHOW);
- }
- }
- break;
- case WM_DESTROY:
- {
- PhDeleteLayoutManager(&context->LayoutManager);
- PhFree(context);
- }
- break;
- case WM_SIZE:
- {
- PhLayoutManagerLayout(&context->LayoutManager);
-
- if (context->ServiceListHandle)
- PhpLayoutServiceListControl(hwndDlg, context->ServiceListHandle);
- }
- break;
- }
-
- return FALSE;
-}
-
-LPENUM_SERVICE_STATUS PhEnumDependentServices(
- __in SC_HANDLE ServiceHandle,
- __in_opt ULONG State,
- __out PULONG Count
- )
-{
- LOGICAL result;
- PVOID buffer;
- ULONG bufferSize;
- ULONG returnLength;
- ULONG servicesReturned;
-
- if (!State)
- State = SERVICE_STATE_ALL;
-
- bufferSize = 0x800;
- buffer = PhAllocate(bufferSize);
-
- if (!(result = EnumDependentServices(
- ServiceHandle,
- State,
- buffer,
- bufferSize,
- &returnLength,
- &servicesReturned
- )))
- {
- if (GetLastError() == ERROR_MORE_DATA)
- {
- PhFree(buffer);
- bufferSize = returnLength;
- buffer = PhAllocate(bufferSize);
-
- result = EnumDependentServices(
- ServiceHandle,
- State,
- buffer,
- bufferSize,
- &returnLength,
- &servicesReturned
- );
- }
-
- if (!result)
- {
- PhFree(buffer);
- return NULL;
- }
- }
-
- *Count = servicesReturned;
-
- return buffer;
-}
-
-INT_PTR CALLBACK PhpServiceDependentsDlgProc(
- __in HWND hwndDlg,
- __in UINT uMsg,
- __in WPARAM wParam,
- __in LPARAM lParam
- )
-{
- PSERVICE_LIST_CONTEXT context;
-
- if (uMsg == WM_INITDIALOG)
- {
- context = PhAllocate(sizeof(SERVICE_LIST_CONTEXT));
- memset(context, 0, sizeof(SERVICE_LIST_CONTEXT));
-
- SetProp(hwndDlg, L"Context", (HANDLE)context);
- }
- else
- {
- context = (PSERVICE_LIST_CONTEXT)GetProp(hwndDlg, L"Context");
-
- if (uMsg == WM_DESTROY)
- RemoveProp(hwndDlg, L"Context");
- }
-
- if (!context)
- return FALSE;
-
- switch (uMsg)
- {
- case WM_INITDIALOG:
- {
- LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam;
- PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)propSheetPage->lParam;
- HWND serviceListHandle;
- PPH_LIST serviceList;
- SC_HANDLE serviceHandle;
- ULONG win32Result = 0;
- BOOLEAN success = FALSE;
- PPH_SERVICE_ITEM *services;
-
- SetDlgItemText(hwndDlg, IDC_MESSAGE, L"The following services depend on this service:");
-
- PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
- PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), NULL, PH_ANCHOR_ALL);
-
- if (serviceHandle = PhOpenService(serviceItem->Name->Buffer, SERVICE_ENUMERATE_DEPENDENTS))
- {
- LPENUM_SERVICE_STATUS dependentServices;
- ULONG numberOfDependentServices;
-
- if (dependentServices = PhEnumDependentServices(serviceHandle, 0, &numberOfDependentServices))
- {
- ULONG i;
- PPH_SERVICE_ITEM dependentService;
-
- serviceList = PhCreateList(8);
- success = TRUE;
-
- for (i = 0; i < numberOfDependentServices; i++)
- {
- if (dependentService = PhReferenceServiceItem(dependentServices[i].lpServiceName))
- PhAddItemList(serviceList, dependentService);
- }
-
- services = PhAllocateCopy(serviceList->Items, sizeof(PPH_SERVICE_ITEM) * serviceList->Count);
-
- serviceListHandle = PhCreateServiceListControl(hwndDlg, services, serviceList->Count);
- context->ServiceListHandle = serviceListHandle;
- PhpLayoutServiceListControl(hwndDlg, serviceListHandle);
- ShowWindow(serviceListHandle, SW_SHOW);
-
- PhDereferenceObject(serviceList);
- PhFree(dependentServices);
- }
- else
- {
- win32Result = GetLastError();
- }
-
- CloseServiceHandle(serviceHandle);
- }
- else
- {
- win32Result = GetLastError();
- }
-
- if (!success)
- {
- SetDlgItemText(hwndDlg, IDC_SERVICES_LAYOUT, PhaConcatStrings2(L"Unable to enumerate dependents: ",
- ((PPH_STRING)PHA_DEREFERENCE(PhGetWin32Message(win32Result)))->Buffer)->Buffer);
- ShowWindow(GetDlgItem(hwndDlg, IDC_SERVICES_LAYOUT), SW_SHOW);
- }
- }
- break;
- case WM_DESTROY:
- {
- PhDeleteLayoutManager(&context->LayoutManager);
- PhFree(context);
- }
- break;
- case WM_SIZE:
- {
- PhLayoutManagerLayout(&context->LayoutManager);
-
- if (context->ServiceListHandle)
- PhpLayoutServiceListControl(hwndDlg, context->ServiceListHandle);
- }
- break;
- }
-
- return FALSE;
-}
-
VOID NTAPI ServicePropertiesInitializingCallback(
__in_opt PVOID Parameter,
__in_opt PVOID Context
@@ -400,29 +100,42 @@ VOID NTAPI ServicePropertiesInitializingCallback(
serviceItem = objectProperties->Parameter;
+ // Recovery
if (objectProperties->NumberOfPages < objectProperties->MaximumNumberOfPages)
{
- // Dependencies
+ memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE));
+ propSheetPage.dwSize = sizeof(PROPSHEETPAGE);
+ propSheetPage.hInstance = PluginInstance->DllBase;
+ propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_SRVRECOVERY);
+ propSheetPage.pfnDlgProc = EspServiceRecoveryDlgProc;
+ propSheetPage.lParam = (LPARAM)serviceItem;
+ objectProperties->Pages[objectProperties->NumberOfPages++] = CreatePropertySheetPage(&propSheetPage);
+ }
+ // Dependencies
+ if (objectProperties->NumberOfPages < objectProperties->MaximumNumberOfPages)
+ {
memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE));
propSheetPage.dwSize = sizeof(PROPSHEETPAGE);
propSheetPage.dwFlags = PSP_USETITLE;
propSheetPage.hInstance = PluginInstance->DllBase;
propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_SRVLIST);
propSheetPage.pszTitle = L"Dependencies";
- propSheetPage.pfnDlgProc = PhpServiceDependenciesDlgProc;
+ propSheetPage.pfnDlgProc = EspServiceDependenciesDlgProc;
propSheetPage.lParam = (LPARAM)serviceItem;
objectProperties->Pages[objectProperties->NumberOfPages++] = CreatePropertySheetPage(&propSheetPage);
+ }
- // Dependents
-
+ // Dependents
+ if (objectProperties->NumberOfPages < objectProperties->MaximumNumberOfPages)
+ {
memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE));
propSheetPage.dwSize = sizeof(PROPSHEETPAGE);
propSheetPage.dwFlags = PSP_USETITLE;
propSheetPage.hInstance = PluginInstance->DllBase;
propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_SRVLIST);
propSheetPage.pszTitle = L"Dependents";
- propSheetPage.pfnDlgProc = PhpServiceDependentsDlgProc;
+ propSheetPage.pfnDlgProc = EspServiceDependentsDlgProc;
propSheetPage.lParam = (LPARAM)serviceItem;
objectProperties->Pages[objectProperties->NumberOfPages++] = CreatePropertySheetPage(&propSheetPage);
}
diff --git a/2.x/trunk/plugins/ExtendedServices/recovery.c b/2.x/trunk/plugins/ExtendedServices/recovery.c
new file mode 100644
index 000000000..01c4f1fc3
--- /dev/null
+++ b/2.x/trunk/plugins/ExtendedServices/recovery.c
@@ -0,0 +1,455 @@
+/*
+ * Process Hacker Extended Services -
+ * recovery information
+ *
+ * Copyright (C) 2010 wj32
+ *
+ * This file is part of Process Hacker.
+ *
+ * Process Hacker is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Process Hacker is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Process Hacker. If not, see .
+ */
+
+#include
+#include
+#include "extsrv.h"
+#include "resource.h"
+
+typedef struct _SERVICE_RECOVERY_CONTEXT
+{
+ PPH_SERVICE_ITEM ServiceItem;
+
+ BOOLEAN EnableFlagCheckBox;
+ ULONG RebootAfter; // in ms
+ PPH_STRING RebootMessage;
+} SERVICE_RECOVERY_CONTEXT, *PSERVICE_RECOVERY_CONTEXT;
+
+#define SIP(String, Integer) { (String), (PVOID)(Integer) }
+
+static PH_KEY_VALUE_PAIR ServiceActionPairs[] =
+{
+ SIP(L"Take no action", SC_ACTION_NONE),
+ SIP(L"Restart the service", SC_ACTION_RESTART),
+ SIP(L"Run a program", SC_ACTION_RUN_COMMAND),
+ SIP(L"Restart the computer", SC_ACTION_REBOOT)
+};
+
+INT_PTR CALLBACK RestartComputerDlgProc(
+ __in HWND hwndDlg,
+ __in UINT uMsg,
+ __in WPARAM wParam,
+ __in LPARAM lParam
+ );
+
+VOID EspAddServiceActionStrings(
+ __in HWND ComboBoxHandle
+ )
+{
+ ULONG i;
+
+ for (i = 0; i < sizeof(ServiceActionPairs) / sizeof(PH_KEY_VALUE_PAIR); i++)
+ ComboBox_AddString(ComboBoxHandle, (PWSTR)ServiceActionPairs[i].Key);
+
+ ComboBox_SelectString(ComboBoxHandle, -1, (PWSTR)ServiceActionPairs[i].Key);
+}
+
+SC_ACTION_TYPE EspStringToServiceAction(
+ __in PWSTR String
+ )
+{
+ ULONG integer;
+
+ if (PhFindIntegerSiKeyValuePairs(ServiceActionPairs, sizeof(ServiceActionPairs), String, &integer))
+ return integer;
+ else
+ return 0;
+}
+
+PWSTR EspServiceActionToString(
+ __in SC_ACTION_TYPE ActionType
+ )
+{
+ PWSTR string;
+
+ if (PhFindStringSiKeyValuePairs(ServiceActionPairs, sizeof(ServiceActionPairs), ActionType, &string))
+ return string;
+ else
+ return NULL;
+}
+
+static SC_ACTION_TYPE ComboBoxToServiceAction(
+ __in HWND ComboBoxHandle
+ )
+{
+ SC_ACTION_TYPE actionType;
+ PPH_STRING string;
+
+ string = PhGetComboBoxString(ComboBoxHandle, ComboBox_GetCurSel(ComboBoxHandle));
+
+ if (!string)
+ return SC_ACTION_NONE;
+
+ actionType = EspStringToServiceAction(string->Buffer);
+ PhDereferenceObject(string);
+
+ return actionType;
+}
+
+static VOID ServiceActionToComboBox(
+ __in HWND ComboBoxHandle,
+ __in SC_ACTION_TYPE ActionType
+ )
+{
+ PWSTR string;
+
+ if (string = EspServiceActionToString(ActionType))
+ ComboBox_SelectString(ComboBoxHandle, -1, string);
+ else
+ ComboBox_SelectString(ComboBoxHandle, -1, (PWSTR)ServiceActionPairs[0].Key);
+}
+
+static VOID EspFixControls(
+ __in HWND hwndDlg,
+ __in PSERVICE_RECOVERY_CONTEXT Context
+ )
+{
+ SC_ACTION_TYPE action1;
+ SC_ACTION_TYPE action2;
+ SC_ACTION_TYPE actionS;
+ BOOLEAN enableRestart;
+ BOOLEAN enableCommand;
+ BOOLEAN enableReboot;
+
+ action1 = ComboBoxToServiceAction(GetDlgItem(hwndDlg, IDC_FIRSTFAILURE));
+ action2 = ComboBoxToServiceAction(GetDlgItem(hwndDlg, IDC_SECONDFAILURE));
+ actionS = ComboBoxToServiceAction(GetDlgItem(hwndDlg, IDC_SUBSEQUENTFAILURES));
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLEFORERRORSTOPS), Context->EnableFlagCheckBox);
+
+ enableRestart = action1 == SC_ACTION_RESTART || action2 == SC_ACTION_RESTART || actionS == SC_ACTION_RESTART;
+ enableCommand = action1 == SC_ACTION_RUN_COMMAND || action2 == SC_ACTION_RUN_COMMAND || actionS == SC_ACTION_RUN_COMMAND;
+ enableReboot = action1 == SC_ACTION_REBOOT || action2 == SC_ACTION_REBOOT || actionS == SC_ACTION_REBOOT;
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RESTARTSERVICEAFTER_LABEL), enableRestart);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RESTARTSERVICEAFTER), enableRestart);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RESTARTSERVICEAFTER_MINUTES), enableRestart);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RUNPROGRAM_GROUP), enableCommand);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RUNPROGRAM_LABEL), enableCommand);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RUNPROGRAM), enableCommand);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSE), enableCommand);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RUNPROGRAM_INFO), enableCommand);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RESTARTCOMPUTEROPTIONS), enableReboot);
+}
+
+NTSTATUS EspLoadRecoveryInfo(
+ __in HWND hwndDlg,
+ __in PSERVICE_RECOVERY_CONTEXT Context
+ )
+{
+ SC_HANDLE serviceHandle;
+ LPSERVICE_FAILURE_ACTIONS failureActions;
+ SERVICE_FAILURE_ACTIONS_FLAG failureActionsFlag;
+ ULONG returnLength;
+ ULONG i;
+
+ if (!(serviceHandle = PhOpenService(Context->ServiceItem->Name->Buffer, SERVICE_QUERY_CONFIG)))
+ return NTSTATUS_FROM_WIN32(GetLastError());
+
+ if (!(failureActions = PhQueryServiceVariableSize(serviceHandle, SERVICE_CONFIG_FAILURE_ACTIONS)))
+ {
+ CloseServiceHandle(serviceHandle);
+ return NTSTATUS_FROM_WIN32(GetLastError());
+ }
+
+ // Failure action types
+
+ ServiceActionToComboBox(GetDlgItem(hwndDlg, IDC_FIRSTFAILURE),
+ failureActions->cActions >= 1 ? failureActions->lpsaActions[0].Type : SC_ACTION_NONE);
+ ServiceActionToComboBox(GetDlgItem(hwndDlg, IDC_SECONDFAILURE),
+ failureActions->cActions >= 2 ? failureActions->lpsaActions[1].Type : SC_ACTION_NONE);
+ ServiceActionToComboBox(GetDlgItem(hwndDlg, IDC_SUBSEQUENTFAILURES),
+ failureActions->cActions >= 3 ? failureActions->lpsaActions[2].Type : SC_ACTION_NONE);
+
+ // Reset fail count after
+
+ SetDlgItemInt(hwndDlg, IDC_RESETFAILCOUNT, failureActions->dwResetPeriod / (60 * 60 * 24), FALSE); // s to days
+
+ // Restart service after
+
+ SetDlgItemText(hwndDlg, IDC_RESTARTSERVICEAFTER, L"1");
+
+ for (i = 0; i < failureActions->cActions; i++)
+ {
+ if (failureActions->lpsaActions[i].Type == SC_ACTION_RESTART)
+ {
+ if (failureActions->lpsaActions[i].Delay != 0)
+ {
+ SetDlgItemInt(hwndDlg, IDC_RESTARTSERVICEAFTER,
+ failureActions->lpsaActions[i].Delay / (1000 * 60), FALSE); // ms to min
+ }
+
+ break;
+ }
+ }
+
+ // Enable actions for stops with errors
+
+ if (WindowsVersion >= WINDOWS_VISTA && QueryServiceConfig2(
+ serviceHandle,
+ SERVICE_CONFIG_FAILURE_ACTIONS_FLAG,
+ (BYTE *)&failureActionsFlag,
+ sizeof(SERVICE_FAILURE_ACTIONS_FLAG),
+ &returnLength
+ ))
+ {
+ Button_SetCheck(GetDlgItem(hwndDlg, IDC_ENABLEFORERRORSTOPS),
+ failureActionsFlag.fFailureActionsOnNonCrashFailures ? BST_CHECKED : BST_UNCHECKED);
+ Context->EnableFlagCheckBox = TRUE;
+ }
+ else
+ {
+ Context->EnableFlagCheckBox = FALSE;
+ }
+
+ // Restart computer options
+
+ Context->RebootAfter = 1 * 1000 * 60;
+
+ for (i = 0; i < failureActions->cActions; i++)
+ {
+ if (failureActions->lpsaActions[i].Type == SC_ACTION_REBOOT)
+ {
+ if (failureActions->lpsaActions[i].Delay != 0)
+ Context->RebootAfter = failureActions->lpsaActions[i].Delay;
+
+ break;
+ }
+ }
+
+ if (failureActions->lpRebootMsg && failureActions->lpRebootMsg[0] != 0)
+ PhSwapReference2(&Context->RebootMessage, PhCreateString(failureActions->lpRebootMsg));
+ else
+ PhSwapReference2(&Context->RebootMessage, NULL);
+
+ // Run program
+
+ SetDlgItemText(hwndDlg, IDC_RUNPROGRAM, failureActions->lpCommand);
+
+ PhFree(failureActions);
+ CloseServiceHandle(serviceHandle);
+
+ return STATUS_SUCCESS;
+}
+
+INT_PTR CALLBACK EspServiceRecoveryDlgProc(
+ __in HWND hwndDlg,
+ __in UINT uMsg,
+ __in WPARAM wParam,
+ __in LPARAM lParam
+ )
+{
+ PSERVICE_RECOVERY_CONTEXT context;
+
+ if (uMsg == WM_INITDIALOG)
+ {
+ context = PhAllocate(sizeof(SERVICE_RECOVERY_CONTEXT));
+ memset(context, 0, sizeof(SERVICE_RECOVERY_CONTEXT));
+
+ SetProp(hwndDlg, L"Context", (HANDLE)context);
+ }
+ else
+ {
+ context = (PSERVICE_RECOVERY_CONTEXT)GetProp(hwndDlg, L"Context");
+
+ if (uMsg == WM_DESTROY)
+ RemoveProp(hwndDlg, L"Context");
+ }
+
+ if (!context)
+ return FALSE;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ NTSTATUS status;
+ LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam;
+ PPH_SERVICE_ITEM serviceItem = (PPH_SERVICE_ITEM)propSheetPage->lParam;
+
+ context->ServiceItem = serviceItem;
+
+ EspAddServiceActionStrings(GetDlgItem(hwndDlg, IDC_FIRSTFAILURE));
+ EspAddServiceActionStrings(GetDlgItem(hwndDlg, IDC_SECONDFAILURE));
+ EspAddServiceActionStrings(GetDlgItem(hwndDlg, IDC_SUBSEQUENTFAILURES));
+
+ status = EspLoadRecoveryInfo(hwndDlg, context);
+
+ if (!NT_SUCCESS(status))
+ PhShowStatus(hwndDlg, L"Unable to query recovery information", status, 0);
+
+ EspFixControls(hwndDlg, context);
+ }
+ break;
+ case WM_DESTROY:
+ {
+ PhSwapReference2(&context->RebootMessage, NULL);
+ PhFree(context);
+ }
+ break;
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_FIRSTFAILURE:
+ case IDC_SECONDFAILURE:
+ case IDC_SUBSEQUENTFAILURES:
+ {
+ if (HIWORD(wParam) == CBN_SELCHANGE)
+ {
+ EspFixControls(hwndDlg, context);
+ }
+ }
+ break;
+ case IDC_RESTARTCOMPUTEROPTIONS:
+ {
+ DialogBoxParam(
+ PluginInstance->DllBase,
+ MAKEINTRESOURCE(IDD_RESTARTCOMP),
+ hwndDlg,
+ RestartComputerDlgProc,
+ (LPARAM)context
+ );
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+static INT_PTR CALLBACK RestartComputerDlgProc(
+ __in HWND hwndDlg,
+ __in UINT uMsg,
+ __in WPARAM wParam,
+ __in LPARAM lParam
+ )
+{
+ PSERVICE_RECOVERY_CONTEXT context;
+
+ if (uMsg == WM_INITDIALOG)
+ {
+ context = (PSERVICE_RECOVERY_CONTEXT)lParam;
+ SetProp(hwndDlg, L"Context", (HANDLE)context);
+ }
+ else
+ {
+ context = (PSERVICE_RECOVERY_CONTEXT)GetProp(hwndDlg, L"Context");
+
+ if (uMsg == WM_DESTROY)
+ RemoveProp(hwndDlg, L"Context");
+ }
+
+ if (!context)
+ return FALSE;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetDlgItemInt(hwndDlg, IDC_RESTARTCOMPAFTER, context->RebootAfter / (1000 * 60), FALSE); // ms to min
+ Button_SetCheck(GetDlgItem(hwndDlg, IDC_ENABLERESTARTMESSAGE), context->RebootMessage ? BST_CHECKED : BST_UNCHECKED);
+ SetDlgItemText(hwndDlg, IDC_RESTARTMESSAGE, PhGetString(context->RebootMessage));
+ }
+ break;
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDCANCEL:
+ EndDialog(hwndDlg, IDCANCEL);
+ break;
+ case IDOK:
+ {
+ context->RebootAfter = GetDlgItemInt(hwndDlg, IDC_RESTARTCOMPAFTER, NULL, FALSE) * 1000 * 60;
+
+ if (Button_GetCheck(GetDlgItem(hwndDlg, IDC_ENABLERESTARTMESSAGE)) == BST_CHECKED)
+ PhSwapReference2(&context->RebootMessage, PhGetWindowText(GetDlgItem(hwndDlg, IDC_RESTARTMESSAGE)));
+ else
+ PhSwapReference2(&context->RebootMessage, NULL);
+
+ EndDialog(hwndDlg, IDOK);
+ }
+ break;
+ case IDC_USEDEFAULTMESSAGE:
+ {
+ PPH_STRING message;
+ PWSTR computerName;
+ ULONG bufferSize;
+ BOOLEAN allocated = TRUE;
+
+ // Get the computer name.
+
+ bufferSize = 64;
+ computerName = PhAllocate((bufferSize + 1) * sizeof(WCHAR));
+
+ if (!GetComputerName(computerName, &bufferSize))
+ {
+ PhFree(computerName);
+ computerName = PhAllocate((bufferSize + 1) * sizeof(WCHAR));
+
+ if (!GetComputerName(computerName, &bufferSize))
+ {
+ PhFree(computerName);
+ computerName = L"(unknown)";
+ allocated = FALSE;
+ }
+ }
+
+ message = PhFormatString(
+ L"Your computer is connected to the computer named %s. "
+ L"The %s service on %s has ended unexpectedly. "
+ L"%s will restart automatically, and then you can reestablish the connection.",
+ computerName,
+ context->ServiceItem->Name->Buffer,
+ computerName,
+ computerName
+ );
+ SetDlgItemText(hwndDlg, IDC_RESTARTMESSAGE, message->Buffer);
+ PhDereferenceObject(message);
+
+ if (allocated)
+ PhFree(computerName);
+
+ Button_SetCheck(GetDlgItem(hwndDlg, IDC_ENABLERESTARTMESSAGE), BST_CHECKED);
+ }
+ break;
+ case IDC_RESTARTMESSAGE:
+ {
+ if (HIWORD(wParam) == EN_CHANGE)
+ {
+ Button_SetCheck(GetDlgItem(hwndDlg, IDC_ENABLERESTARTMESSAGE),
+ GetWindowTextLength(GetDlgItem(hwndDlg, IDC_RESTARTMESSAGE)) != 0 ? BST_CHECKED : BST_UNCHECKED);
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+}
diff --git a/2.x/trunk/plugins/ExtendedServices/resource.h b/2.x/trunk/plugins/ExtendedServices/resource.h
index 16d2627c9..5f6ba2f4a 100644
--- a/2.x/trunk/plugins/ExtendedServices/resource.h
+++ b/2.x/trunk/plugins/ExtendedServices/resource.h
@@ -4,16 +4,37 @@
//
#define IDD_SVCLIST 101
#define IDD_SRVLIST 101
+#define IDD_SRVRECOVERY 102
+#define IDD_RESTARTCOMP 103
#define IDC_SERVICES_LAYOUT 1001
#define IDC_MESSAGE 1002
+#define IDC_FIRSTFAILURE 1003
+#define IDC_SECONDFAILURE 1004
+#define IDC_SUBSEQUENTFAILURES 1005
+#define IDC_RESETFAILCOUNT 1006
+#define IDC_RESTARTSERVICEAFTER 1007
+#define IDC_RESTARTSERVICEAFTER_LABEL 1008
+#define IDC_RESTARTSERVICEAFTER_MINUTES 1009
+#define IDC_ENABLEFORERRORSTOPS 1011
+#define IDC_RESTARTCOMPUTEROPTIONS 1012
+#define IDC_RUNPROGRAM 1014
+#define IDC_BROWSE 1015
+#define IDC_RESTARTCOMPAFTER 1016
+#define IDC_CHECK1 1017
+#define IDC_ENABLERESTARTMESSAGE 1017
+#define IDC_RESTARTMESSAGE 1018
+#define IDC_RUNPROGRAM_GROUP 1019
+#define IDC_RUNPROGRAM_LABEL 1020
+#define IDC_RUNPROGRAM_INFO 1021
+#define IDC_USEDEFAULTMESSAGE 1022
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1003
+#define _APS_NEXT_CONTROL_VALUE 1023
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
diff --git a/2.x/trunk/plugins/SbieSupport/main.c b/2.x/trunk/plugins/SbieSupport/main.c
index 0892295c2..121980c6f 100644
--- a/2.x/trunk/plugins/SbieSupport/main.c
+++ b/2.x/trunk/plugins/SbieSupport/main.c
@@ -1,3 +1,25 @@
+/*
+ * Process Hacker Sandboxie Support -
+ * main program
+ *
+ * Copyright (C) 2010 wj32
+ *
+ * This file is part of Process Hacker.
+ *
+ * Process Hacker is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Process Hacker is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Process Hacker. If not, see .
+ */
+
#include
#include "resource.h"
#include "sbiedll.h"
diff --git a/2.x/trunk/plugins/ToolStatus/main.c b/2.x/trunk/plugins/ToolStatus/main.c
index f354759a4..4cd98cc59 100644
--- a/2.x/trunk/plugins/ToolStatus/main.c
+++ b/2.x/trunk/plugins/ToolStatus/main.c
@@ -1,3 +1,25 @@
+/*
+ * Process Hacker ToolStatus -
+ * main program
+ *
+ * Copyright (C) 2010 wj32
+ *
+ * This file is part of Process Hacker.
+ *
+ * Process Hacker is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Process Hacker is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Process Hacker. If not, see .
+ */
+
#include
#include "resource.h"
#include "toolstatus.h"