Windows2000/private/windows/screg/winreg/server/regstate.c
2020-09-30 17:12:32 +02:00

374 lines
7.2 KiB
C

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
RegState.c
Abstract:
This module contains helper functions for maintaining
user mode state for registry objects
Author:
Adam Edwards (adamed) 06-May-1998
Key Functions:
StateObjectInit
StateObjectListInit
StateObjectListIsEmpty
StateObjectListRemove
StateObjectListFind
StateObjectListAdd
StateObjectListClear
Notes:
The StateObjectList stores the most frequently accessed
objects at the head of the list for quick retrieval. All
objects in the list must inherit from StateObject, and must
be distinguishable by a unique 32-bit key. Duplicate
objects are not supported, so the client must take care
not to store duplicates (two objects with the same key) in
the list.
--*/
#ifdef LOCAL
#include <rpc.h>
#include "regrpc.h"
#include "localreg.h"
#include "regstate.h"
#include <malloc.h>
VOID StateObjectInit(
StateObject* pObject,
PVOID pvKey)
/*++
Routine Description:
This function will initialize a StateObject. All objects
which inherit from this must call this function before doing
any custom initialization.
Arguments:
pObject -- the object to initialize.
pvKey -- a unique key for the object used for searches and comparisons
between objects.
Return Value:
None -- the function does nothing which could fail.
--*/
{
RtlZeroMemory(pObject, sizeof(*pObject));
pObject->pvKey = pvKey;
}
VOID StateObjectListInit(
StateObjectList* pList,
PVOID pvKey)
/*++
Routine Description:
This function will initialize a StateObjectList. All objects
which inherit from this must call this function before doing
any custom initialization.
Arguments:
pList -- pointer to list to initialize.
pvKey -- a unique key that identifies the list. This parameter is
necessary since the list itself is a StateObject, which requires a
key. It can be set to 0 if this list will not be searched for
as part of another list, but should be set otherwise to a unique
value.
Return Value:
None -- the function does nothing which could fail.
--*/
{
StateObjectInit(
(StateObject*) pList,
pvKey);
pList->pHead = NULL;
}
BOOL StateObjectListIsEmpty(StateObjectList* pList)
/*++
Routine Description:
This function returns information on whether or not this
list is empty.
Arguments:
pList -- pointer to list in question
Return Value:
TRUE if the list is empty,
FALSE if not.
--*/
{
return NULL == pList->pHead;
}
StateObject* StateObjectListRemove(
StateObjectList* pList,
PVOID pvKey)
/*++
Routine Description:
This function will remove an object from the list --
it does *not* destroy the object.
Arguments:
pList -- the list to remove the object from
pvKey -- a unique key identifying the object to remove
Return Value:
a pointer to the removed object if successful,
NULL otherwise
--*/
{
StateObject* pObject;
// First, we need to find an object with the desired key
pObject = StateObjectListFind(
pList,
pvKey);
if (!pObject) {
return NULL;
}
// Now that we've executed the find, the object is at the front
// of the list -- we can remove it by setting the head to the
// next object in the list
pList->pHead = (StateObject*) (pObject->Links.Flink);
// Make sure the new head's previous pointer is NULL since it
// has no predecessor
if (pList->pHead) {
pList->pHead->Links.Blink = NULL;
}
return pObject;
}
StateObject* StateObjectListFind(
StateObjectList* pList,
PVOID pvKey)
/*++
Routine Description:
This function will find an object in the list
Arguments:
pList -- the list in which to search
pvKey -- a unique key identifying the object sought
Return Value:
a pointer to the object if an object with a key matching pvKey is found,
NULL otherwise
--*/
{
StateObject* pCurrent;
// Loop through all objects in the list until we get to the end
for (pCurrent = pList->pHead;
pCurrent != NULL;
pCurrent = (StateObject*) pCurrent->Links.Flink)
{
// See if this object's key matches the desired key
if (pvKey == pCurrent->pvKey) {
PLIST_ENTRY pFlink;
PLIST_ENTRY pBlink;
// If the desired object is at the front, this is a no op --
// we don't have to move anything, just return the object
if (pCurrent == pList->pHead) {
return pCurrent;
}
// We need to move the found object to the front of the list
// Remove the object from its current position
// by severing its links
pBlink = pCurrent->Links.Blink;
pFlink = pCurrent->Links.Flink;
if (pBlink) {
pBlink->Flink = pFlink;
}
if (pFlink) {
pFlink->Blink = pBlink;
}
// Re-add it to the front
StateObjectListAdd(
pList,
pCurrent);
return pCurrent;
}
}
// We never found an object with the desired key above, so its
// not in the list
return NULL;
}
VOID StateObjectListAdd(
StateObjectList* pList,
StateObject* pObject)
/*++
Routine Description:
This function will add an object to the list
Arguments:
pList -- the list in which to add the object
pObject -- pointer to an object which has been initialized
with StateObjectInit; this object will be stored in the list.
Return Value:
None -- this function does nothing which could fail.
Note:
Only one object with a particular key should exist in the list. This
requirement is not enforced by this function or the list itself, so
clients need to ensure that they follow this rule.
--*/
{
// Create the links between the object and what's currently
// at the front of the list
if (pList->pHead) {
pObject->Links.Flink = (PLIST_ENTRY) pList->pHead;
pList->pHead->Links.Blink = (PLIST_ENTRY) pObject;
}
// Put the object at the front of the list
pList->pHead = pObject;
pList->pHead->Links.Blink = NULL;
}
VOID StateObjectListClear(
StateObjectList* pList,
PFNDestroyObject pfnDestroy)
/*++
Routine Description:
This function will remove and destroy all objects
in the list.
Arguments:
pList -- the list to clear
pfnDestroy -- pointer to a function which will be called for
each object in order to destroy (free resources such as memory,
kernel objects, etc) it.
Return Value:
None -- this function does nothing which could fail.
--*/
{
StateObject* pCurrent;
// Keep removing objects until the list is empty
while (!StateObjectListIsEmpty(pList))
{
StateObject* pObject;
// Remove whatever's at the front of the list
pObject = StateObjectListRemove(
pList,
pList->pHead->pvKey);
ASSERT(pObject);
// Destroy the removed object
pfnDestroy(pObject);
}
}
#endif // LOCAL