374 lines
7.2 KiB
C
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
|
||
|
|
||
|
|
||
|
|