* switched service and network menus to use EMENU

* added plugin support for EMENU
* ExtendedServices now adds a Restart menu item

git-svn-id: svn://svn.code.sf.net/p/processhacker/code@3661 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
wj32
2010-09-23 06:34:56 +00:00
parent b4eec975f7
commit 7078bf2faf
16 changed files with 591 additions and 74 deletions
+1
View File
@@ -2,6 +2,7 @@ Process Hacker
2.6
* NEW/IMPROVED:
* Updated ExtendedServices plugin
* Performance improvements
* FIXED:
* Fixed service handle leak
+47
View File
@@ -18,6 +18,9 @@ typedef enum _PH_GENERAL_CALLBACK
GeneralCallbackNotifyEvent = 6, // PPH_PLUGIN_NOTIFY_EVENT Data [main thread]
GeneralCallbackServicePropertiesInitializing = 7, // PPH_PLUGIN_OBJECT_PROPERTIES Data [properties thread]
GeneralCallbackHandlePropertiesInitializing = 8, // PPH_PLUGIN_OBJECT_PROPERTIES Data [properties thread]
GeneralCallbackProcessMenuInitializing = 9, // PPH_PLUGIN_MENU_INFORMATION Data [main thread]
GeneralCallbackServiceMenuInitializing = 10, // PPH_PLUGIN_MENU_INFORMATION Data [main thread]
GeneralCallbackNetworkMenuInitializing = 11, // PPH_PLUGIN_MENU_INFORMATION Data [main thread]
GeneralCallbackMaximum
} PH_GENERAL_CALLBACK, *PPH_GENERAL_CALLBACK;
@@ -83,6 +86,32 @@ typedef struct _PH_PLUGIN_HANDLE_PROPERTIES_CONTEXT
PPH_HANDLE_ITEM HandleItem;
} PH_PLUGIN_HANDLE_PROPERTIES_CONTEXT, *PPH_PLUGIN_HANDLE_PROPERTIES_CONTEXT;
typedef struct _PH_EMENU_ITEM *PPH_EMENU_ITEM, *PPH_EMENU;
typedef struct _PH_PLUGIN_MENU_INFORMATION
{
PPH_EMENU Menu;
union
{
struct
{
PPH_PROCESS_ITEM *Processes;
ULONG NumberOfProcesses;
} Process;
struct
{
PPH_SERVICE_ITEM *Services;
ULONG NumberOfServices;
} Service;
struct
{
PPH_NETWORK_ITEM *NetworkItems;
ULONG NumberOfNetworkItems;
} Network;
} u;
} PH_PLUGIN_MENU_INFORMATION, *PPH_PLUGIN_MENU_INFORMATION;
typedef enum _PH_PLUGIN_CALLBACK
{
PluginCallbackLoad = 0, // [main thread]
@@ -207,6 +236,24 @@ PhPluginGetSystemStatistics(
__out PPH_PLUGIN_SYSTEM_STATISTICS Statistics
);
PHAPPAPI
PPH_EMENU_ITEM
NTAPI
PhPluginCreateEMenuItem(
__in PPH_PLUGIN Plugin,
__in ULONG Flags,
__in ULONG Id,
__in PWSTR Text,
__in_opt PVOID Context
);
PHAPPAPI
BOOLEAN
NTAPI
PhPluginTriggerEMenuItem(
__in PPH_EMENU_ITEM Item
);
#ifdef __cplusplus
}
#endif
+144 -65
View File
@@ -3320,8 +3320,8 @@ VOID PhpInitializeProcessMenu(
if (PH_IS_FAKE_PROCESS_ID(Processes[0]->ProcessId))
{
PhSetFlagsAllEMenuItems(Menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
PhSetFlagsEMenuItem(Menu, ID_PROCESS_PROPERTIES, PH_EMENU_DISABLED, 0);
PhSetFlagsEMenuItem(Menu, ID_PROCESS_SEARCHONLINE, PH_EMENU_DISABLED, 0);
PhEnableEMenuItem(Menu, ID_PROCESS_PROPERTIES, TRUE);
PhEnableEMenuItem(Menu, ID_PROCESS_SEARCHONLINE, TRUE);
}
}
else
@@ -3351,9 +3351,7 @@ VOID PhpInitializeProcessMenu(
if (WindowsVersion < WINDOWS_VISTA)
{
// Remove I/O priority.
item = PhFindEMenuItem(Menu, PH_EMENU_FIND_DESCEND, L"I/O Priority", 0);
if (item)
if (item = PhFindEMenuItem(Menu, PH_EMENU_FIND_DESCEND, L"I/O Priority", 0))
PhRemoveEMenuItem(NULL, item, 0);
}
@@ -3418,11 +3416,11 @@ VOID PhpInitializeProcessMenu(
GetWindowPlacement(SelectedProcessWindowHandle, &placement);
if (placement.showCmd == SW_MINIMIZE)
PhSetFlagsEMenuItem(item, ID_WINDOW_MINIMIZE, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
PhEnableEMenuItem(item, ID_WINDOW_MINIMIZE, FALSE);
else if (placement.showCmd == SW_MAXIMIZE)
PhSetFlagsEMenuItem(item, ID_WINDOW_MAXIMIZE, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
PhEnableEMenuItem(item, ID_WINDOW_MAXIMIZE, FALSE);
else if (placement.showCmd == SW_NORMAL)
PhSetFlagsEMenuItem(item, ID_WINDOW_RESTORE, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
PhEnableEMenuItem(item, ID_WINDOW_RESTORE, FALSE);
}
else
{
@@ -3434,9 +3432,7 @@ VOID PhpInitializeProcessMenu(
if (!WINDOWS_HAS_UAC)
{
item = PhFindEMenuItem(Menu, 0, NULL, ID_PROCESS_VIRTUALIZATION);
if (item)
if (item = PhFindEMenuItem(Menu, 0, NULL, ID_PROCESS_VIRTUALIZATION))
PhRemoveEMenuItem(NULL, item, 0);
}
}
@@ -3461,7 +3457,18 @@ VOID PhShowProcessContextMenu(
PhpInitializeProcessMenu(menu, processes, numberOfProcesses);
MapWindowPoints(ProcessTreeListHandle, NULL, &Location, 1);
if (PhPluginsEnabled)
{
PH_PLUGIN_MENU_INFORMATION menuInfo;
menuInfo.Menu = menu;
menuInfo.u.Process.Processes = processes;
menuInfo.u.Process.NumberOfProcesses = numberOfProcesses;
PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackProcessMenuInitializing), &menuInfo);
}
ClientToScreen(ProcessTreeListHandle, &Location);
item = PhShowEMenu(
menu,
@@ -3474,7 +3481,13 @@ VOID PhShowProcessContextMenu(
if (item)
{
SendMessage(PhMainWndHandle, WM_COMMAND, item->Id, 0);
BOOLEAN handled = FALSE;
if (PhPluginsEnabled)
handled = PhPluginTriggerEMenuItem(item);
if (!handled)
SendMessage(PhMainWndHandle, WM_COMMAND, item->Id, 0);
}
PhDestroyEMenu(menu);
@@ -3484,24 +3497,24 @@ VOID PhShowProcessContextMenu(
}
VOID PhpInitializeServiceMenu(
__in HMENU Menu,
__in PPH_EMENU Menu,
__in PPH_SERVICE_ITEM *Services,
__in ULONG NumberOfServices
)
{
if (NumberOfServices == 0)
{
PhEnableAllMenuItems(Menu, FALSE);
PhSetFlagsAllEMenuItems(Menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
}
else if (NumberOfServices == 1)
{
if (!Services[0]->ProcessId)
PhEnableMenuItem(Menu, ID_SERVICE_GOTOPROCESS, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_GOTOPROCESS, FALSE);
}
else
{
PhEnableAllMenuItems(Menu, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_COPY, TRUE);
PhSetFlagsAllEMenuItems(Menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
PhEnableEMenuItem(Menu, ID_SERVICE_COPY, TRUE);
}
if (NumberOfServices == 1)
@@ -3510,29 +3523,29 @@ VOID PhpInitializeServiceMenu(
{
case SERVICE_RUNNING:
{
PhEnableMenuItem(Menu, ID_SERVICE_START, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_CONTINUE, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_PAUSE,
PhEnableEMenuItem(Menu, ID_SERVICE_START, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_CONTINUE, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_PAUSE,
Services[0]->ControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE);
PhEnableMenuItem(Menu, ID_SERVICE_STOP,
PhEnableEMenuItem(Menu, ID_SERVICE_STOP,
Services[0]->ControlsAccepted & SERVICE_ACCEPT_STOP);
}
break;
case SERVICE_PAUSED:
{
PhEnableMenuItem(Menu, ID_SERVICE_START, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_CONTINUE,
PhEnableEMenuItem(Menu, ID_SERVICE_START, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_CONTINUE,
Services[0]->ControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE);
PhEnableMenuItem(Menu, ID_SERVICE_PAUSE, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_STOP,
PhEnableEMenuItem(Menu, ID_SERVICE_PAUSE, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_STOP,
Services[0]->ControlsAccepted & SERVICE_ACCEPT_STOP);
}
break;
case SERVICE_STOPPED:
{
PhEnableMenuItem(Menu, ID_SERVICE_CONTINUE, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_PAUSE, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_STOP, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_CONTINUE, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_PAUSE, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_STOP, FALSE);
}
break;
case SERVICE_START_PENDING:
@@ -3540,18 +3553,22 @@ VOID PhpInitializeServiceMenu(
case SERVICE_PAUSE_PENDING:
case SERVICE_STOP_PENDING:
{
PhEnableMenuItem(Menu, ID_SERVICE_START, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_CONTINUE, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_PAUSE, FALSE);
PhEnableMenuItem(Menu, ID_SERVICE_STOP, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_START, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_CONTINUE, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_PAUSE, FALSE);
PhEnableEMenuItem(Menu, ID_SERVICE_STOP, FALSE);
}
break;
}
if (!(Services[0]->ControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE))
{
DeleteMenu(Menu, ID_SERVICE_CONTINUE, 0);
DeleteMenu(Menu, ID_SERVICE_PAUSE, 0);
PPH_EMENU_ITEM item;
if (item = PhFindEMenuItem(Menu, 0, NULL, ID_SERVICE_CONTINUE))
PhRemoveEMenuItem(NULL, item, 0);
if (item = PhFindEMenuItem(Menu, 0, NULL, ID_SERVICE_PAUSE))
PhRemoveEMenuItem(NULL, item, 0);
}
}
}
@@ -3577,22 +3594,51 @@ VOID PhMainWndServiceListViewOnNotify(
if (numberOfServices != 0)
{
HMENU menu;
HMENU subMenu;
PPH_EMENU menu;
PPH_EMENU_ITEM item;
POINT location;
menu = LoadMenu(PhInstanceHandle, MAKEINTRESOURCE(IDR_SERVICE));
subMenu = GetSubMenu(menu, 0);
menu = PhCreateEMenu();
PhLoadResourceEMenuItem(menu, PhInstanceHandle, MAKEINTRESOURCE(IDR_SERVICE), 0);
PhSetFlagsEMenuItem(menu, ID_SERVICE_PROPERTIES, PH_EMENU_DEFAULT, PH_EMENU_DEFAULT);
SetMenuDefaultItem(subMenu, ID_SERVICE_PROPERTIES, FALSE);
PhpInitializeServiceMenu(subMenu, services, numberOfServices);
PhpInitializeServiceMenu(menu, services, numberOfServices);
PhShowContextMenu(
if (PhPluginsEnabled)
{
PH_PLUGIN_MENU_INFORMATION menuInfo;
menuInfo.Menu = menu;
menuInfo.u.Service.Services = services;
menuInfo.u.Service.NumberOfServices = numberOfServices;
PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackServiceMenuInitializing), &menuInfo);
}
location = itemActivate->ptAction;
ClientToScreen(ServiceListViewHandle, &location);
item = PhShowEMenu(
menu,
PhMainWndHandle,
ServiceListViewHandle,
subMenu,
itemActivate->ptAction
PH_EMENU_SHOW_LEFTRIGHT,
PH_ALIGN_LEFT | PH_ALIGN_TOP,
location.x,
location.y
);
DestroyMenu(menu);
if (item)
{
BOOLEAN handled = FALSE;
if (PhPluginsEnabled)
handled = PhPluginTriggerEMenuItem(item);
if (!handled)
SendMessage(PhMainWndHandle, WM_COMMAND, item->Id, 0);
}
PhDestroyEMenu(menu);
}
PhFree(services);
@@ -3640,31 +3686,35 @@ VOID PhMainWndServiceListViewOnNotify(
}
VOID PhpInitializeNetworkMenu(
__in HMENU Menu,
__in PPH_EMENU Menu,
__in PPH_NETWORK_ITEM *NetworkItems,
__in ULONG NumberOfNetworkItems
)
{
ULONG i;
PPH_EMENU_ITEM item;
if (NumberOfNetworkItems == 0)
{
PhEnableAllMenuItems(Menu, FALSE);
PhSetFlagsAllEMenuItems(Menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
}
else if (NumberOfNetworkItems == 1)
{
if (!NetworkItems[0]->ProcessId)
PhEnableMenuItem(Menu, ID_NETWORK_GOTOPROCESS, FALSE);
PhEnableEMenuItem(Menu, ID_NETWORK_GOTOPROCESS, FALSE);
}
else
{
PhEnableAllMenuItems(Menu, FALSE);
PhEnableMenuItem(Menu, ID_NETWORK_CLOSE, TRUE);
PhEnableMenuItem(Menu, ID_NETWORK_COPY, TRUE);
PhSetFlagsAllEMenuItems(Menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
PhEnableEMenuItem(Menu, ID_NETWORK_CLOSE, TRUE);
PhEnableEMenuItem(Menu, ID_NETWORK_COPY, TRUE);
}
if (WindowsVersion >= WINDOWS_VISTA)
DeleteMenu(Menu, ID_NETWORK_VIEWSTACK, 0);
{
if (item = PhFindEMenuItem(Menu, 0, NULL, ID_NETWORK_VIEWSTACK))
PhRemoveEMenuItem(NULL, item, 0);
}
// Close
if (NumberOfNetworkItems != 0)
@@ -3684,7 +3734,7 @@ VOID PhpInitializeNetworkMenu(
}
if (!closeOk)
PhEnableMenuItem(Menu, ID_NETWORK_CLOSE, FALSE);
PhEnableEMenuItem(Menu, ID_NETWORK_CLOSE, FALSE);
}
}
@@ -3709,22 +3759,51 @@ VOID PhMainWndNetworkListViewOnNotify(
if (numberOfNetworkItems != 0)
{
HMENU menu;
HMENU subMenu;
PPH_EMENU menu;
PPH_EMENU_ITEM item;
POINT location;
menu = LoadMenu(PhInstanceHandle, MAKEINTRESOURCE(IDR_NETWORK));
subMenu = GetSubMenu(menu, 0);
menu = PhCreateEMenu();
PhLoadResourceEMenuItem(menu, PhInstanceHandle, MAKEINTRESOURCE(IDR_NETWORK), 0);
PhSetFlagsEMenuItem(menu, ID_NETWORK_GOTOPROCESS, PH_EMENU_DEFAULT, PH_EMENU_DEFAULT);
SetMenuDefaultItem(subMenu, ID_NETWORK_GOTOPROCESS, FALSE);
PhpInitializeNetworkMenu(subMenu, networkItems, numberOfNetworkItems);
PhpInitializeNetworkMenu(menu, networkItems, numberOfNetworkItems);
PhShowContextMenu(
if (PhPluginsEnabled)
{
PH_PLUGIN_MENU_INFORMATION menuInfo;
menuInfo.Menu = menu;
menuInfo.u.Network.NetworkItems = networkItems;
menuInfo.u.Network.NumberOfNetworkItems = numberOfNetworkItems;
PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackNetworkMenuInitializing), &menuInfo);
}
location = itemActivate->ptAction;
ClientToScreen(NetworkListViewHandle, &location);
item = PhShowEMenu(
menu,
PhMainWndHandle,
NetworkListViewHandle,
subMenu,
itemActivate->ptAction
PH_EMENU_SHOW_LEFTRIGHT,
PH_ALIGN_LEFT | PH_ALIGN_TOP,
location.x,
location.y
);
DestroyMenu(menu);
if (item)
{
BOOLEAN handled = FALSE;
if (PhPluginsEnabled)
handled = PhPluginTriggerEMenuItem(item);
if (!handled)
SendMessage(PhMainWndHandle, WM_COMMAND, item->Id, 0);
}
PhDestroyEMenu(menu);
}
PhFree(networkItems);
+49
View File
@@ -22,6 +22,7 @@
#include <phapp.h>
#include <settings.h>
#include <emenu.h>
#include <phplug.h>
#define CINTERFACE
#define COBJMACROS
@@ -435,3 +436,51 @@ VOID PhPluginGetSystemStatistics(
Statistics->MaxCpuProcessId = UlongToHandle(PhGetItemCircularBuffer_ULONG(&PhMaxCpuHistory, 0));
Statistics->MaxIoProcessId = UlongToHandle(PhGetItemCircularBuffer_ULONG(&PhMaxIoHistory, 0));
}
static VOID NTAPI PhpPluginEMenuItemDeleteFunction(
__in PPH_EMENU_ITEM Item
)
{
PhFree(Item->Context);
}
PPH_EMENU_ITEM PhPluginCreateEMenuItem(
__in PPH_PLUGIN Plugin,
__in ULONG Flags,
__in ULONG Id,
__in PWSTR Text,
__in_opt PVOID Context
)
{
PPH_EMENU_ITEM item;
PPH_PLUGIN_MENU_ITEM pluginMenuItem;
item = PhCreateEMenuItem(Flags, ID_PLUGIN_MENU_ITEM, Text, NULL, NULL);
pluginMenuItem = PhAllocate(sizeof(PH_PLUGIN_MENU_ITEM));
pluginMenuItem->Plugin = Plugin;
pluginMenuItem->Id = Id;
pluginMenuItem->RealId = 0;
pluginMenuItem->Context = Context;
item->Context = pluginMenuItem;
item->DeleteFunction = PhpPluginEMenuItemDeleteFunction;
return item;
}
BOOLEAN PhPluginTriggerEMenuItem(
__in PPH_EMENU_ITEM Item
)
{
PPH_PLUGIN_MENU_ITEM pluginMenuItem;
if (Item->Id != ID_PLUGIN_MENU_ITEM)
return FALSE;
pluginMenuItem = Item->Context;
PhInvokeCallback(PhGetPluginCallback(pluginMenuItem->Plugin, PluginCallbackMenuItem), pluginMenuItem);
return TRUE;
}
+2 -1
View File
@@ -40,6 +40,7 @@
#define IDD_INFORMATION 129
#define IDD_FINDOBJECTS 130
#define IDD_OBJTOKEN 131
#define ID_PLUGIN_MENU_ITEM 131
#define IDD_HEAPS 132
#define IDR_PRIVILEGE 133
#define IDR_FINDOBJ 134
@@ -620,6 +621,6 @@
#define _APS_NEXT_RESOURCE_VALUE 191
#define _APS_NEXT_COMMAND_VALUE 40234
#define _APS_NEXT_CONTROL_VALUE 1271
#define _APS_NEXT_SYMED_VALUE 131
#define _APS_NEXT_SYMED_VALUE 132
#endif
#endif
+1 -1
View File
@@ -12,8 +12,8 @@
#include "providers.h"
#include "treelist.h"
#include "emenu.h"
#include "phapppub.h"
#include "phplug.h"
#endif
+1
View File
@@ -19,6 +19,7 @@ for %%a in (
circbuf_h.h
dltmgr.h
dspick.h
emenu.h
fastlock.h
graph.h
hexedit.h
+18 -1
View File
@@ -53,7 +53,7 @@ PPH_EMENU_ITEM PhCreateEMenuItem(
__in ULONG Id,
__in PWSTR Text,
__in_opt PWSTR Bitmap,
__in PVOID Context
__in_opt PVOID Context
)
{
PPH_EMENU_ITEM item;
@@ -78,6 +78,9 @@ VOID PhDestroyEMenuItem(
__in PPH_EMENU_ITEM Item
)
{
if (Item->DeleteFunction)
Item->DeleteFunction(Item);
if (Item->Flags & PH_EMENU_TEXT_OWNED)
PhFree(Item->Text);
@@ -153,6 +156,17 @@ PPH_EMENU_ITEM PhFindEMenuItem(
return NULL;
}
ULONG PhIndexOfEMenuItem(
__in PPH_EMENU_ITEM Parent,
__in PPH_EMENU_ITEM Item
)
{
if (!Parent->Items)
return -1;
return PhFindItemList(Parent->Items, Item);
}
VOID PhInsertEMenuItem(
__inout PPH_EMENU_ITEM Parent,
__inout PPH_EMENU_ITEM Item,
@@ -166,6 +180,9 @@ VOID PhInsertEMenuItem(
if (!Parent->Items)
Parent->Items = PhCreateList(16);
if (Index > Parent->Items->Count)
Index = Parent->Items->Count;
if (Index == -1)
PhAddItemList(Parent->Items, Item);
else
+29 -1
View File
@@ -16,6 +16,12 @@
#define PH_EMENU_TEXT_OWNED 0x80000000
#define PH_EMENU_BITMAP_OWNED 0x40000000
struct _PH_EMENU_ITEM;
typedef VOID (NTAPI *PPH_EMENU_ITEM_DELETE_FUNCTION)(
__in struct _PH_EMENU_ITEM *Item
);
typedef struct _PH_EMENU_ITEM
{
ULONG Flags;
@@ -25,6 +31,8 @@ typedef struct _PH_EMENU_ITEM
PVOID Parameter;
PVOID Context;
PPH_EMENU_ITEM_DELETE_FUNCTION DeleteFunction;
PVOID Reserved;
struct _PH_EMENU_ITEM *Parent;
PPH_LIST Items;
@@ -37,9 +45,10 @@ PPH_EMENU_ITEM PhCreateEMenuItem(
__in ULONG Id,
__in PWSTR Text,
__in_opt PWSTR Bitmap,
__in PVOID Context
__in_opt PVOID Context
);
PHLIBAPI
VOID PhDestroyEMenuItem(
__in PPH_EMENU_ITEM Item
);
@@ -47,6 +56,7 @@ VOID PhDestroyEMenuItem(
#define PH_EMENU_FIND_DESCEND 0x1
#define PH_EMENU_FIND_STARTSWITH 0x2
PHLIBAPI
PPH_EMENU_ITEM PhFindEMenuItem(
__in PPH_EMENU_ITEM Item,
__in ULONG Flags,
@@ -54,18 +64,27 @@ PPH_EMENU_ITEM PhFindEMenuItem(
__in_opt ULONG Id
);
PHLIBAPI
ULONG PhIndexOfEMenuItem(
__in PPH_EMENU_ITEM Parent,
__in PPH_EMENU_ITEM Item
);
PHLIBAPI
VOID PhInsertEMenuItem(
__inout PPH_EMENU_ITEM Parent,
__inout PPH_EMENU_ITEM Item,
__in ULONG Index
);
PHLIBAPI
BOOLEAN PhRemoveEMenuItem(
__inout_opt PPH_EMENU_ITEM Parent,
__in_opt PPH_EMENU_ITEM Item,
__in_opt ULONG Index
);
PHLIBAPI
VOID PhRemoveAllEMenuItems(
__inout PPH_EMENU_ITEM Parent
);
@@ -130,6 +149,15 @@ BOOLEAN PhSetFlagsEMenuItem(
__in ULONG Value
);
FORCEINLINE BOOLEAN PhEnableEMenuItem(
__in PPH_EMENU_ITEM Item,
__in ULONG Id,
__in BOOLEAN Enable
)
{
return PhSetFlagsEMenuItem(Item, Id, PH_EMENU_DISABLED, Enable ? 0 : PH_EMENU_DISABLED);
}
VOID PhSetFlagsAllEMenuItems(
__in PPH_EMENU_ITEM Item,
__in ULONG Mask,
@@ -1,4 +1,5 @@
1.1
* Added Restart menu item for services
* Fixed service handle leak
1.0
@@ -151,6 +151,16 @@ BEGIN
CTEXT "If this service fails, the computer will restart.\nRecovery actions are not supported for this service.",IDC_STATIC,51,80,179,21
END
IDD_SRVPROGRESS DIALOGEX 0, 0, 204, 61
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Progress"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Cancel",IDCANCEL,147,40,50,14
LTEXT "Progress",IDC_MESSAGE,7,7,190,8,SS_ENDELLIPSIS
CONTROL "",IDC_PROGRESS,"msctls_progress32",WS_BORDER,7,21,190,14
END
/////////////////////////////////////////////////////////////////////////////
//
@@ -191,6 +201,14 @@ BEGIN
TOPMARGIN, 7
BOTTOMMARGIN, 176
END
IDD_SRVPROGRESS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 197
TOPMARGIN, 7
BOTTOMMARGIN, 54
END
END
#endif // APSTUDIO_INVOKED
@@ -348,6 +348,10 @@
RelativePath=".\main.c"
>
</File>
<File
RelativePath=".\srvprgrs.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
@@ -45,4 +45,12 @@ INT_PTR CALLBACK EspServiceRecovery2DlgProc(
__in LPARAM lParam
);
// srvprgrs
VOID EsRestartServiceWithProgress(
__in HWND hWnd,
__in PWSTR ServiceName,
__in SC_HANDLE ServiceHandle
);
#endif
+90 -1
View File
@@ -30,14 +30,26 @@ VOID NTAPI LoadCallback(
__in_opt PVOID Context
);
VOID NTAPI MenuItemCallback(
__in_opt PVOID Parameter,
__in_opt PVOID Context
);
VOID NTAPI ServicePropertiesInitializingCallback(
__in_opt PVOID Parameter,
__in_opt PVOID Context
);
VOID NTAPI ServiceMenuInitializingCallback(
__in_opt PVOID Parameter,
__in_opt PVOID Context
);
PPH_PLUGIN PluginInstance;
PH_CALLBACK_REGISTRATION PluginLoadCallbackRegistration;
PH_CALLBACK_REGISTRATION PluginMenuItemCallbackRegistration;
PH_CALLBACK_REGISTRATION ServicePropertiesInitializingCallbackRegistration;
PH_CALLBACK_REGISTRATION ServiceMenuInitializingCallbackRegistration;
LOGICAL DllMain(
__in HINSTANCE Instance,
@@ -53,7 +65,7 @@ LOGICAL DllMain(
info.DisplayName = L"Extended Services";
info.Author = L"wj32";
info.Description = L"Adds more tabs to service properties.";
info.Description = L"Extends service management capabilities.";
info.HasOptions = FALSE;
PluginInstance = PhRegisterPlugin(L"ProcessHacker.ExtendedServices", Instance, &info);
@@ -67,6 +79,12 @@ LOGICAL DllMain(
NULL,
&PluginLoadCallbackRegistration
);
PhRegisterCallback(
PhGetPluginCallback(PluginInstance, PluginCallbackMenuItem),
MenuItemCallback,
NULL,
&PluginMenuItemCallbackRegistration
);
PhRegisterCallback(
PhGetGeneralCallback(GeneralCallbackServicePropertiesInitializing),
@@ -74,6 +92,12 @@ LOGICAL DllMain(
NULL,
&ServicePropertiesInitializingCallbackRegistration
);
PhRegisterCallback(
PhGetGeneralCallback(GeneralCallbackServiceMenuInitializing),
ServiceMenuInitializingCallback,
NULL,
&ServiceMenuInitializingCallbackRegistration
);
}
break;
}
@@ -89,6 +113,45 @@ VOID NTAPI LoadCallback(
// Nothing
}
VOID NTAPI MenuItemCallback(
__in_opt PVOID Parameter,
__in_opt PVOID Context
)
{
PPH_PLUGIN_MENU_ITEM menuItem = Parameter;
switch (menuItem->Id)
{
case ID_SERVICE_RESTART:
{
PPH_SERVICE_ITEM serviceItem = menuItem->Context;
SC_HANDLE serviceHandle;
ULONG win32Result = 0;
if (serviceHandle = PhOpenService(serviceItem->Name->Buffer, SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP))
{
EsRestartServiceWithProgress(PhMainWndHandle, serviceItem->Name->Buffer, serviceHandle);
CloseServiceHandle(serviceHandle);
}
else
{
win32Result = GetLastError();
}
if (win32Result != 0)
{
PhShowStatus(
PhMainWndHandle,
PhaFormatString(L"Unable to restart %s", serviceItem->Name->Buffer)->Buffer,
0,
win32Result
);
}
}
break;
}
}
VOID NTAPI ServicePropertiesInitializingCallback(
__in_opt PVOID Parameter,
__in_opt PVOID Context
@@ -152,3 +215,29 @@ VOID NTAPI ServicePropertiesInitializingCallback(
objectProperties->Pages[objectProperties->NumberOfPages++] = CreatePropertySheetPage(&propSheetPage);
}
}
VOID NTAPI ServiceMenuInitializingCallback(
__in_opt PVOID Parameter,
__in_opt PVOID Context
)
{
PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter;
PPH_EMENU_ITEM menuItem;
ULONG indexOfMenuItem;
if (menuInfo->u.Service.NumberOfServices == 1 && menuInfo->u.Service.Services[0]->State == SERVICE_RUNNING)
{
// Insert our Restart menu item after the Stop menu item.
menuItem = PhFindEMenuItem(menuInfo->Menu, PH_EMENU_FIND_STARTSWITH, L"Stop", 0);
if (menuItem)
indexOfMenuItem = PhIndexOfEMenuItem(menuInfo->Menu, menuItem);
PhInsertEMenuItem(
menuInfo->Menu,
PhPluginCreateEMenuItem(PluginInstance, 0, ID_SERVICE_RESTART, L"Restart", menuInfo->u.Service.Services[0]),
indexOfMenuItem + 1
);
}
}
@@ -4,10 +4,11 @@
//
#define IDD_SVCLIST 101
#define IDD_SRVLIST 101
#define ID_SERVICE_RESTART 101
#define IDD_SRVRECOVERY 102
#define IDD_RESTARTCOMP 103
#define IDD_SRVRECOVERY1 104
#define IDD_SRVRECOVERY2 104
#define IDD_SRVPROGRESS 105
#define IDC_SERVICES_LAYOUT 1001
#define IDC_MESSAGE 1002
#define IDC_FIRSTFAILURE 1003
@@ -28,14 +29,16 @@
#define IDC_RUNPROGRAM_LABEL 1020
#define IDC_RUNPROGRAM_INFO 1021
#define IDC_USEDEFAULTMESSAGE 1022
#define IDC_PROGRESS1 1023
#define IDC_PROGRESS 1023
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_RESOURCE_VALUE 106
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1023
#define _APS_NEXT_SYMED_VALUE 101
#define _APS_NEXT_CONTROL_VALUE 1024
#define _APS_NEXT_SYMED_VALUE 102
#endif
#endif
@@ -0,0 +1,171 @@
/*
* Process Hacker Extended Services -
* progress dialog
*
* 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 _RESTART_SERVICE_CONTEXT
{
PWSTR ServiceName;
SC_HANDLE ServiceHandle;
BOOLEAN Starting;
} RESTART_SERVICE_CONTEXT, *PRESTART_SERVICE_CONTEXT;
INT_PTR CALLBACK EspRestartServiceDlgProc(
__in HWND hwndDlg,
__in UINT uMsg,
__in WPARAM wParam,
__in LPARAM lParam
);
VOID EsRestartServiceWithProgress(
__in HWND hWnd,
__in PWSTR ServiceName,
__in SC_HANDLE ServiceHandle
)
{
RESTART_SERVICE_CONTEXT context;
context.ServiceName = ServiceName;
context.ServiceHandle = ServiceHandle;
context.Starting = FALSE;
DialogBoxParam(
PluginInstance->DllBase,
MAKEINTRESOURCE(IDD_SRVPROGRESS),
hWnd,
EspRestartServiceDlgProc,
(LPARAM)&context
);
}
INT_PTR CALLBACK EspRestartServiceDlgProc(
__in HWND hwndDlg,
__in UINT uMsg,
__in WPARAM wParam,
__in LPARAM lParam
)
{
PRESTART_SERVICE_CONTEXT context;
if (uMsg == WM_INITDIALOG)
{
context = (PRESTART_SERVICE_CONTEXT)lParam;
SetProp(hwndDlg, L"Context", (HANDLE)context);
}
else
{
context = (PRESTART_SERVICE_CONTEXT)GetProp(hwndDlg, L"Context");
if (uMsg == WM_DESTROY)
RemoveProp(hwndDlg, L"Context");
}
if (!context)
return FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
{
SERVICE_STATUS serviceStatus;
PhCenterWindow(hwndDlg, GetParent(hwndDlg));
// TODO: Use the progress information.
PhSetWindowStyle(GetDlgItem(hwndDlg, IDC_PROGRESS), PBS_MARQUEE, PBS_MARQUEE);
SendMessage(GetDlgItem(hwndDlg, IDC_PROGRESS), PBM_SETMARQUEE, TRUE, 75);
SetDlgItemText(hwndDlg, IDC_MESSAGE, PhaFormatString(L"Attempting to stop %s...", context->ServiceName)->Buffer);
if (ControlService(context->ServiceHandle, SERVICE_CONTROL_STOP, &serviceStatus))
{
SetTimer(hwndDlg, 1, 250, NULL);
}
else
{
PhShowStatus(
hwndDlg,
PhaFormatString(L"Unable to stop %s", context->ServiceName)->Buffer,
0,
GetLastError()
);
EndDialog(hwndDlg, IDCANCEL);
}
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDCANCEL:
{
EndDialog(hwndDlg, IDCANCEL);
}
break;
}
}
break;
case WM_TIMER:
{
if (wParam == 1)
{
SERVICE_STATUS serviceStatus;
if (QueryServiceStatus(context->ServiceHandle, &serviceStatus))
{
if (!context->Starting && serviceStatus.dwCurrentState == SERVICE_STOPPED)
{
// The service is stopped, so start the service now.
SetDlgItemText(hwndDlg, IDC_MESSAGE,
PhaFormatString(L"Attempting to start %s...", context->ServiceName)->Buffer);
if (StartService(context->ServiceHandle, 0, NULL))
{
context->Starting = TRUE;
}
else
{
PhShowStatus(
hwndDlg,
PhaFormatString(L"Unable to start %s", context->ServiceName)->Buffer,
0,
GetLastError()
);
EndDialog(hwndDlg, IDCANCEL);
}
}
else if (context->Starting && serviceStatus.dwCurrentState == SERVICE_RUNNING)
{
EndDialog(hwndDlg, IDOK);
}
}
}
}
break;
}
return FALSE;
}