* 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:
wj32
2010-09-16 09:46:40 +00:00
parent 65754f89f8
commit 992cf747d0
13 changed files with 1116 additions and 361 deletions
+14 -5
View File
@@ -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);
}
}
+6
View File
@@ -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
View File
@@ -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"
>
+349
View File
@@ -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
+43 -330
View File
@@ -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;
}
+23 -2
View File
@@ -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
+22
View File
@@ -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"
+22
View File
@@ -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"