mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
* 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
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
+48
-24
@@ -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(
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <phdk.h>
|
||||
#include <windowsx.h>
|
||||
#include "extnoti.h"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -340,6 +340,10 @@
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\depend.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\main.c"
|
||||
>
|
||||
@@ -350,6 +354,14 @@
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\extsrv.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\recovery.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\resource.h"
|
||||
>
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <phdk.h>
|
||||
#include <windowsx.h>
|
||||
#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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -1,12 +1,29 @@
|
||||
#include <phdk.h>
|
||||
#include <windowsx.h>
|
||||
#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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
typedef struct _SERVICE_LIST_CONTEXT
|
||||
{
|
||||
HWND ServiceListHandle;
|
||||
PH_LAYOUT_MANAGER LayoutManager;
|
||||
} SERVICE_LIST_CONTEXT, *PSERVICE_LIST_CONTEXT;
|
||||
#include <phdk.h>
|
||||
#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);
|
||||
}
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <phdk.h>
|
||||
#include <windowsx.h>
|
||||
#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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <phdk.h>
|
||||
#include "resource.h"
|
||||
#include "sbiedll.h"
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <phdk.h>
|
||||
#include "resource.h"
|
||||
#include "toolstatus.h"
|
||||
|
||||
Reference in New Issue
Block a user