Files
wj32 5a2a05b056 Improve string APIs
git-svn-id: svn://svn.code.sf.net/p/processhacker/code@6006 21ef857c-d57f-4fe0-8362-d861dc6d29cd
2015-05-31 09:42:33 +00:00

227 lines
6.5 KiB
C

/*
* Process Hacker -
* extension manager
*
* Copyright (C) 2011 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/>.
*/
/*
* The extension manager provides support for generic extensions. It sits directly
* underneath the plugin manager, and has no knowledge of plugin details (how they are
* loaded, plugin information, etc.).
*/
#include <phapp.h>
#include <extmgri.h>
LIST_ENTRY PhEmAppContextListHead = { &PhEmAppContextListHead, &PhEmAppContextListHead };
ULONG PhEmAppContextCount = 0;
PH_EM_OBJECT_TYPE_STATE PhEmObjectTypeState[EmMaximumObjectType] = { 0 };
/**
* Initializes the extension manager module.
*/
VOID PhEmInitialization(
VOID
)
{
ULONG i;
for (i = 0; i < EmMaximumObjectType; i++)
{
InitializeListHead(&PhEmObjectTypeState[i].ExtensionListHead);
}
}
/**
* Initializes an extension application context.
*
* \param AppContext The application context.
* \param AppName The application name.
*/
VOID PhEmInitializeAppContext(
_Out_ PPH_EM_APP_CONTEXT AppContext,
_In_ PPH_STRINGREF AppName
)
{
AppContext->AppName = *AppName;
memset(AppContext->Extensions, 0, sizeof(AppContext->Extensions));
InsertTailList(&PhEmAppContextListHead, &AppContext->ListEntry);
PhEmAppContextCount++;
}
/**
* Sets the object extension size and callbacks for an object type.
*
* \param AppContext The application context.
* \param ObjectType The type of object for which the extension is being registered.
* \param ExtensionSize The size of the extension, in bytes.
* \param CreateCallback The object creation callback.
* \param DeleteCallback The object deletion callback.
*/
VOID PhEmSetObjectExtension(
_Inout_ PPH_EM_APP_CONTEXT AppContext,
_In_ PH_EM_OBJECT_TYPE ObjectType,
_In_ SIZE_T ExtensionSize,
_In_opt_ PPH_EM_OBJECT_CALLBACK CreateCallback,
_In_opt_ PPH_EM_OBJECT_CALLBACK DeleteCallback
)
{
PPH_EM_OBJECT_TYPE_STATE objectTypeState;
PPH_EM_OBJECT_EXTENSION objectExtension;
objectTypeState = &PhEmObjectTypeState[ObjectType];
objectExtension = AppContext->Extensions[ObjectType];
if (!objectExtension)
{
objectExtension = PhAllocate(sizeof(PH_EM_OBJECT_EXTENSION));
memset(objectExtension, 0, sizeof(PH_EM_OBJECT_EXTENSION));
InsertTailList(&objectTypeState->ExtensionListHead, &objectExtension->ListEntry);
AppContext->Extensions[ObjectType] = objectExtension;
objectExtension->ExtensionSize = ExtensionSize;
objectExtension->ExtensionOffset = objectTypeState->ExtensionOffset;
objectTypeState->ExtensionOffset += ExtensionSize;
}
objectExtension->Callbacks[EmObjectCreate] = CreateCallback;
objectExtension->Callbacks[EmObjectDelete] = DeleteCallback;
}
/**
* Gets the object extension for an object.
*
* \param AppContext The application context.
* \param ObjectType The type of object for which an extension has been registered.
* \param Object The object.
*/
PVOID PhEmGetObjectExtension(
_In_ PPH_EM_APP_CONTEXT AppContext,
_In_ PH_EM_OBJECT_TYPE ObjectType,
_In_ PVOID Object
)
{
PPH_EM_OBJECT_EXTENSION objectExtension;
objectExtension = AppContext->Extensions[ObjectType];
if (!objectExtension)
return NULL;
return (PCHAR)Object + PhEmObjectTypeState[ObjectType].InitialSize + objectExtension->ExtensionOffset;
}
/**
* Determines the size of an object, including extensions.
*
* \param ObjectType The object type.
* \param InitialSize The initial size of the object.
*/
SIZE_T PhEmGetObjectSize(
_In_ PH_EM_OBJECT_TYPE ObjectType,
_In_ SIZE_T InitialSize
)
{
PhEmObjectTypeState[ObjectType].InitialSize = InitialSize;
return InitialSize + PhEmObjectTypeState[ObjectType].ExtensionOffset;
}
/**
* Invokes callbacks for an object operation.
*
* \param ObjectType The object type.
* \param Object The object.
* \param Operation The operation being performed.
*/
VOID PhEmCallObjectOperation(
_In_ PH_EM_OBJECT_TYPE ObjectType,
_In_ PVOID Object,
_In_ PH_EM_OBJECT_OPERATION Operation
)
{
PPH_EM_OBJECT_TYPE_STATE objectTypeState;
PLIST_ENTRY listEntry;
PPH_EM_OBJECT_EXTENSION objectExtension;
if (PhEmAppContextCount == 0)
return;
objectTypeState = &PhEmObjectTypeState[ObjectType];
listEntry = objectTypeState->ExtensionListHead.Flink;
while (listEntry != &objectTypeState->ExtensionListHead)
{
objectExtension = CONTAINING_RECORD(listEntry, PH_EM_OBJECT_EXTENSION, ListEntry);
if (objectExtension->Callbacks[Operation])
{
objectExtension->Callbacks[Operation](
Object,
ObjectType,
(PCHAR)Object + objectTypeState->InitialSize + objectExtension->ExtensionOffset
);
}
listEntry = listEntry->Flink;
}
}
/**
* Parses an application name and sub-ID pair.
*
* \param CompoundId The compound identifier.
* \param AppName A variable which receives the application name.
* \param SubId A variable which receives the sub-ID.
*/
BOOLEAN PhEmParseCompoundId(
_In_ PPH_STRINGREF CompoundId,
_Out_ PPH_STRINGREF AppName,
_Out_ PULONG SubId
)
{
PH_STRINGREF firstPart;
PH_STRINGREF secondPart;
ULONG64 integer;
firstPart = *CompoundId;
if (firstPart.Length == 0)
return FALSE;
if (firstPart.Buffer[0] != '+')
return FALSE;
PhSkipStringRef(&firstPart, sizeof(WCHAR));
PhSplitStringRefAtChar(&firstPart, '+', &firstPart, &secondPart);
if (firstPart.Length == 0 || secondPart.Length == 0)
return FALSE;
if (!PhStringToInteger64(&secondPart, 10, &integer))
return FALSE;
*AppName = firstPart;
*SubId = (ULONG)integer;
return TRUE;
}