From 992cf747d09efa3f222239bce35a00c809fe650c Mon Sep 17 00:00:00 2001 From: wj32 Date: Thu, 16 Sep 2010 09:46:40 +0000 Subject: [PATCH] * added Recovery tab to ExtendedServices (read-only for now) * added PhQueryServiceVariableSize * added copyright headers git-svn-id: svn://svn.code.sf.net/p/processhacker/code@3629 21ef857c-d57f-4fe0-8362-d861dc6d29cd --- 2.x/trunk/ProcessHacker/srvprp.c | 19 +- 2.x/trunk/phlib/include/ph.h | 6 + 2.x/trunk/phlib/svcsup.c | 72 ++- .../plugins/ExtendedNotifications/main.c | 22 + .../ExtendedServices/ExtendedServices.rc | 59 +++ .../ExtendedServices/ExtendedServices.vcproj | 12 + 2.x/trunk/plugins/ExtendedServices/depend.c | 349 ++++++++++++++ 2.x/trunk/plugins/ExtendedServices/extsrv.h | 41 ++ 2.x/trunk/plugins/ExtendedServices/main.c | 373 ++------------ 2.x/trunk/plugins/ExtendedServices/recovery.c | 455 ++++++++++++++++++ 2.x/trunk/plugins/ExtendedServices/resource.h | 25 +- 2.x/trunk/plugins/SbieSupport/main.c | 22 + 2.x/trunk/plugins/ToolStatus/main.c | 22 + 13 files changed, 1116 insertions(+), 361 deletions(-) create mode 100644 2.x/trunk/plugins/ExtendedServices/depend.c create mode 100644 2.x/trunk/plugins/ExtendedServices/extsrv.h create mode 100644 2.x/trunk/plugins/ExtendedServices/recovery.c 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"