Process Hacker Discussion Forum

 
User avatar
wj32
Founder
Posts: 948
Joined: 17 Jan 2011 05:19
OS: Windows
Contact:

Plugin API Reference

21 Jan 2011 15:05

Process Hacker Plugins API reference.

Warning

Information contained here about these APIs may be altered or unavailable without notice!

The plugins system in Process Hacker enables developers to extend the functionality of Process Hacker. The primary goals of the plugins system are to:
  • Discourage forks of Process Hacker.
  • Offer user choice - unneeded features do not have to be loaded, decreasing memory usage and improving startup time.
When Process Hacker is started with plugin support enabled, it scans the plugins directory (by default, the "plugins" directory in the same location as ProcessHacker.exe) for DLLs. Plugin DLLs do not export any functions; rather, they register with Process Hacker in their DllMain routines. To avoid making the code too complex, instead of using a shared DLL or function pointers, ProcessHacker.exe itself exports over 800 functions available for plugins to use.

To develop plugins, you need the SDK (processhacker-*-sdk.zip).

PhRegisterPlugin Function

Registers a plugin with the Process Hacker plugin system, It specifies the name of your plugin, the base address of the DLL (HINSTANCE from your DllMain routine) allowing Process Hacker to use this address in calls to functions that require a module handle.
PHAPPAPI
PPH_PLUGIN
NTAPI
PhRegisterPlugin(
    __in PWSTR Name,
    __in PVOID DllBase,
    __out_opt PPH_PLUGIN_INFORMATION *Information
    );
Parameters:

Name [in]
Type: PWSTR
  • A string specifying the unique Internal identifier of your plugin. The name should be in the format "Organization.Plugin", e.g. "AcmeCompany.FooBarExplorer".
DllBase [in]
Type: PVOID
  • The HINSTANCE value from your DllMain routine. This is the base address of the module in memory.
Information [out, optional]
Type: PPH_PLUGIN_INFORMATION *
  • A variable which receives a pointer to the plugin's information structure. You can modify this structure to specify the Display Name, Author, Description and Options of your plugin.
Return Value:

Type: PPH_PLUGIN
  • If the function succeeds, the return value is a pointer to the PH_PLUGIN instance created by Process Hacker.

    If the function fails, the return value is NULL.

    This function typically fails because another plugin has already been registered with the same name.
 
User avatar
wj32
Founder
Posts: 948
Joined: 17 Jan 2011 05:19
OS: Windows
Contact:

Re: Plugin API Reference

21 Jan 2011 15:58

PhFindPlugin Function

Finds the PH_PLUGIN structure of a plugin. You may want to use the DllBase of the plugin in order to get function addresses.
PHAPPAPI
PPH_PLUGIN
NTAPI
PhFindPlugin(
    __in PWSTR Name
    );
Parameters:

Name [in]
Type: PWSTR
  • A string specifying the unique Internal identifier of your plugin you want to find. The name should be in the same format used in your call to PhRegisterPlugin, "Organization.Plugin", e.g. "AcmeCompany.FooBarExplorer".
Return Value:

Type: PPH_PLUGIN
  • If the function succeeds, the return value is a pointer to the PH_PLUGIN instance created by Process Hacker.

    If the function fails, the return value is NULL.

    This function typically fails because no plugin has been registered with the specified name.
 
User avatar
wj32
Founder
Posts: 948
Joined: 17 Jan 2011 05:19
OS: Windows
Contact:

Re: Plugin API Reference

21 Jan 2011 15:58

PhGetPluginCallback Function

Retrieves a plugin-related callback object.
PHAPPAPI
PPH_CALLBACK
NTAPI
PhGetPluginCallback(
    __in PPH_PLUGIN Plugin,
    __in PH_PLUGIN_CALLBACK Callback
    );
Parameters:

Plugin [in]
Type: PPH_PLUGIN
  • The plugin instance you want to retrieve the callback object for.
Callback [in]
Type: PH_PLUGIN_CALLBACK
  • The type of callback:
    PluginCallbackLoad - Invoked after all plugin DLLs have been loaded, but before the main window has been created.
    PluginCallbackUnload - Invoked when Process Hacker is shutting down.
    PluginCallbackShowOptions - Invoked when the user clicks the Options button in the plugin configuration window.
    PluginCallbackMenuItem - Invoked when the user chooses a menu item owned by the plugin.
Return Value:

Type: PPH_CALLBACK
  • If the function succeeds, the return value is a pointer to the PH_CALLBACK object for the specified callback type. You can call PhRegisterCallback to register a function to be executed when the callback is invoked.
 
User avatar
wj32
Founder
Posts: 948
Joined: 17 Jan 2011 05:19
OS: Windows
Contact:

Re: Plugin API Reference

21 Jan 2011 15:59

PhGetGeneralCallback Function

Retrieves a program-wide callback object.
PHAPPAPI
PPH_CALLBACK
NTAPI
PhGetGeneralCallback(
    __in PH_GENERAL_CALLBACK Callback
    );
Parameters:

Callback [in]
Type: PH_GENERAL_CALLBACK
  • The type of callback:
    GeneralCallbackMainWindowShowing - Invoked after all other initialization has completed but before the main window is shown. The PhMainWndHandle global variable contains a handle to the main window.
    GeneralCallbackProcessesUpdated - Invoked after process information has been updated.
    GeneralCallbackGetProcessHighlightingColor - Invoked when the highlighting color of a process needs to be retrieved. You can change the highlighting color.
    GeneralCallbackGetProcessTooltipText - Invoked when the tooltip text of a process needs to be created. You can add text to the tooltip.
    GeneralCallback---PropertiesInitializing - Invoked when the properties window for an object is being shown. You can add property pages.
    GeneralCallback---MenuInitializing - Invoked when the menu for an object is being shown. You can add menu items.
Return Value:

Type: PPH_CALLBACK
  • If the function succeeds, the return value is a pointer to the PH_CALLBACK object for the specified callback type. You can call PhRegisterCallback to register a function to be executed when the callback is invoked.
 
User avatar
wj32
Founder
Posts: 948
Joined: 17 Jan 2011 05:19
OS: Windows
Contact:

Re: Plugin API Reference

21 Jan 2011 15:59

PhPluginReserveIds Function

Reserves the specified number of control IDs guaranteed to be unique within Process Hacker. This function is not needed for most plugins.
PHAPPAPI
ULONG
NTAPI
PhPluginReserveIds(
    __in ULONG Count
    );
 
User avatar
wj32
Founder
Posts: 948
Joined: 17 Jan 2011 05:19
OS: Windows
Contact:

Re: Plugin API Reference

21 Jan 2011 16:00

PhPluginAddMenuItem Function

Adds a menu item to Process Hacker's main menu.
PHAPPAPI
ULONG_PTR
NTAPI
PhPluginAddMenuItem(
    __in PPH_PLUGIN Plugin,
    __in ULONG_PTR Location,
    __in_opt PWSTR InsertAfter,
    __in ULONG Id,
    __in PWSTR Text,
    __in_opt PVOID Context
    );
Parameters:

Plugin [in]
Type: PPH_PLUGIN
  • The plugin instance associated with the menu item.
Location [in]
Type: ULONG_PTR
  • A handle to the parent menu (cast it to ULONG_PTR), or one of the following
    PH_MENU_ITEM_LOCATION_VIEW - The View menu.
    PH_MENU_ITEM_LOCATION_TOOLS - The Tools menu.
InsertAfter [in, optional]
Type: PWSTR
  • The text of the menu item to insert the new menu item after. The search is a case-insensitive prefix search that ignores prefix characters (ampersands).
Id [in]
Type: ULONG
  • A unique identifier for the menu item. You can access this value in the PH_PLUGIN_MENU_ITEM structure that is passed to your PluginCallbackMenuItem handler. You may also specify the following flags:
    PH_MENU_ITEM_SUB_MENU - The menu item has a submenu.
Text [in]
Type: PWSTR
  • The text of the menu item.
Context [in, optional]
Type: PVOID
  • A user-defined value. You can access this value in the PH_PLUGIN_MENU_ITEM structure that is passed to your PluginCallbackMenuItem handler.
Return Value:

Type: ULONG_PTR
  • If the function succeeds, the return value is either a handle to the submenu of the new menu item (if PH_MENU_ITEM_SUB_MENU was specified), or 1.

    If the function fails, the return value is 0.
 
User avatar
wj32
Founder
Posts: 948
Joined: 17 Jan 2011 05:19
OS: Windows
Contact:

Re: Plugin API Reference

21 Jan 2011 16:00

PhPluginCreateEMenuItem Function

Creates a menu item for use within a GeneralCallback---MenuInitializing handler.
PHAPPAPI
PPH_EMENU_ITEM
NTAPI
PhPluginCreateEMenuItem(
    __in PPH_PLUGIN Plugin,
    __in ULONG Flags,
    __in ULONG Id,
    __in PWSTR Text,
    __in_opt PVOID Context
    );
Parameters:

Plugin [in]
Type: PPH_PLUGIN
  • The plugin instance associated with the menu item.
Flags [in]
Type: ULONG
  • A combination of the following:
    PH_EMENU_DISABLED - The menu item is greyed and cannot be selected.
    PH_EMENU_CHECKED - A check mark is displayed.
    PH_EMENU_HIGHLIGHT - The menu item is highlighted.
    PH_EMENU_MENUBARBREAK - Places the menu item in a new column, separated by a vertical line.
    PH_EMENU_MENUBREAK - Places the menu item in a new column, with no vertical line.
    PH_EMENU_DEFAULT - The menu item is displayed as the default item. This causes the text to be bolded.
    PH_EMENU_RADIOCHECK - Uses a radio-button mark instead of a check mark.
Id [in]
Type: ULONG
  • A unique identifier for the menu item. You can access this value in the PH_PLUGIN_MENU_ITEM structure that is passed to your PluginCallbackMenuItem handler.
Text [in]
Type: PWSTR
  • The text of the menu item.
Context [in, optional]
Type: PVOID
  • A user-defined value. You can access this value in the PH_PLUGIN_MENU_ITEM structure that is passed to your PluginCallbackMenuItem handler.
 
User avatar
wj32
Founder
Posts: 948
Joined: 17 Jan 2011 05:19
OS: Windows
Contact:

Re: Plugin API Reference

24 Jan 2011 08:26

Storing settings

To store settings, you must first call the PhAddSettings function in your DllMain routine:
static PH_SETTING_CREATE settings[] =
{
    // { type, name, default value }
    { IntegerSettingType, L"AcmeCompany.FooBarExplorer.FooCount", L"1" },
    { StringSettingType, L"AcmeCompany.FooBarExplorer.BarPath", L"C:\\Windows\\explorer.exe" }
};

// PhAddSettings(settings array, number of settings)
PhAddSettings(settings, sizeof(settings) / sizeof(PH_SETTING_CREATE));
This registers the settings in Process Hacker's settings system. You cannot register your settings in any function except your DllMain routine. You cannot modify or remove setting definitions.

To access settings, use the get/set functions:
ULONG fooCount;
PPH_STRING barPath;

fooCount = PhGetIntegerSetting(L"AcmeCompany.FooBarExplorer.FooCount");
// Use fooCount
PhSetIntegerSetting(L"AcmeCompany.FooBarExplorer.FooCount", 1234);

barPath = PhGetStringSetting(L"AcmeCompany.FooBarExplorer.BarPath");
// Use barPath
PhDereferenceObject(barPath); // Don't forget this or you will have a reference/memory leak!
PhSetStringSetting(L"AcmeCompany.FooBarExplorer.BarPath", L"C:\\Some\\New\\Path");
These functions are completely thread-safe. Note that if you attempt to access a non-existent setting or you use the wrong function (e.g. using PhGetIntegerSetting on a string setting), an exception will be raised.
 
User avatar
wj32
Founder
Posts: 948
Joined: 17 Jan 2011 05:19
OS: Windows
Contact:

Re: Plugin API Reference

24 Jan 2011 08:38

Using menu items

To add menu items to the main menu, use the PhPluginAddMenuItem function. This function must be called in your GeneralCallbackMainWindowShowing handler:
VOID NTAPI MainWindowShowingCallback(
    __in_opt PVOID Parameter,
    __in_opt PVOID Context
    )
{
    PhPluginAddMenuItem(
        PluginInstance, // your plugin instance
        PH_MENU_ITEM_LOCATION_VIEW, // location of the menu item
        L"System Information", // your menu item will be inserted after this menu item
        1234, // menu item identifier - any integer you want to use
        L"Foobar Information", // text of the menu item
        NULL // arbitrary PVOID value you can specify
        );
}
For object-specific menus, Process Hacker uses a more flexible system called EMENU:
VOID NTAPI ProcessMenuInitializingCallback(
    __in_opt PVOID Parameter,
    __in_opt PVOID Context
    )
{
    PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter;
    PPH_PROCESS_ITEM processItem;
    PPH_EMENU_ITEM myMenuItem;

    // In this particular event (GeneralCallbackProcessMenuInitializing), you are given the 
    // processes which the user selected when they invoked the context menu.
    if (menuInfo->u.Process.NumberOfProcesses == 1)
    {
        processItem = menuInfo->u.Process.Processes[0];
        myMenuItem = PhPluginCreateEMenuItem(
            PluginInstance, // your plugin instance
            0, // flags
            1234, // menu item identifier - any integer you want to use
            L"Unloaded Modules", // text of the menu item
            processItem // arbitrary PVOID value you can specify - in this case, we specify the process the user selected so we can use it later
            );
        PhInsertEMenuItem(
            menuInfo->Menu, // the parent menu (provided by the callback)
            myMenuItem, // the new menu item
            -1 // index - 0 means the first position, and -1 means the last position
            );
    }
}
When the user clicks one of your menu items, your plugin's PluginCallbackMenuItem handler is invoked:
VOID NTAPI MenuItemCallback(
    __in_opt PVOID Parameter,
    __in_opt PVOID Context
    )
{
    PPH_PLUGIN_MENU_ITEM menuItem = Parameter;

    switch (menuItem->Id)
    {
    case 1234:
        {
            // Do stuff. The arbitrary PVOID is in menuItem->Context.
        }
        break;
    // More cases?
    }
}
 
User avatar
wj32
Founder
Posts: 948
Joined: 17 Jan 2011 05:19
OS: Windows
Contact:

Re: Plugin API Reference

24 Jan 2011 08:51

The basics

Here is the DllMain routine for a basic plugin. Read the comments to learn more about the plugins system.
PPH_PLUGIN PluginInstance;
PH_CALLBACK_REGISTRATION PluginLoadCallbackRegistration;
PH_CALLBACK_REGISTRATION MainWindowShowingCallbackRegistration;
// More callback registration objects?

LOGICAL DllMain(
    __in HINSTANCE Instance, // This is really the base address of your plugin DLL. Process Hacker needs to know this value, which is why you pass it to PhRegisterPlugin.
    __in ULONG Reason,
    __reserved PVOID Reserved
    )
{
    switch (Reason)
    {
    case DLL_PROCESS_ATTACH:
        {
            PPH_PLUGIN_INFORMATION info;

            // Registers your plugin with Process Hacker.
            PluginInstance = PhRegisterPlugin(L"AcmeCompany.FooBarExplorer", Instance, &info);

            if (!PluginInstance)
                return FALSE;

            // Set up some information for your plugin.
            info->DisplayName = L"Foobar Explorer";
            info->Author = L"Acme Company";
            info->Description = L"Allows you to explore foobar objects.";
            info->HasOptions = FALSE;

            // Process Hacker notifies your plugin of events. You must use PhRegisterCallback to set up handlers for these events.
            PhRegisterCallback(
                // PhGetPluginCallback gets a pointer to a PPH_CALLBACK object that describes the event you're interested in.
                PhGetPluginCallback(PluginInstance, PluginCallbackLoad),
                // The address of your handler function.
                LoadCallback,
                // An arbitrary PVOID value. This is passed to your handler function (in this case, LoadCallback) in the Context parameter. Most of the time you won't need this.
                NULL,
                // A pointer to a PH_CALLBACK_REGISTRATION structure. This structure must be available as long as your handler function is registered (i.e. until you call PhUnregisterCallback). For best results, declare this as a global variable (see the top of this code sample)
                &PluginLoadCallbackRegistration
                );
            PhRegisterCallback(
                PhGetGeneralCallback(GeneralCallbackMainWindowShowing),
                MainWindowShowingCallback,
                NULL,
                &MainWindowShowingCallbackRegistration
                );
            // ...
            // More PhRegisterCallback calls.
        }
        break;
    }

    return TRUE;
}

// This is the handler function for the PluginCallbackLoad event.
VOID NTAPI LoadCallback(
    __in_opt PVOID Parameter, // Most callbacks give you additional information. This event doesn't give you any.
    __in_opt PVOID Context // This is the arbitrary PVOID value you specified in PhRegisterCallback.
    )
{
    // Do stuff.
}

VOID NTAPI MainWindowShowingCallback(
    __in_opt PVOID Parameter,
    __in_opt PVOID Context
    )
{
    // Do stuff.
}