- Added some generic table routines to rtlfuncs.h so that they can be used in user-mode.

- Implemented RtlInsertElementGenericTable and RtlInsertElementGenericTableFull (Splay-Tree versions). Also implemented a helper function RtlpFindGenericTableNodeOrParent when we're not given one and need to locate it manually.
- Defined structure for generic table entries so that we can properly return user data and do the right allocations.

svn path=/trunk/; revision=24541
This commit is contained in:
Alex Ionescu 2006-10-16 03:19:14 +00:00
parent 693525bd5a
commit dbb8a15d7c
2 changed files with 224 additions and 33 deletions

View file

@ -212,51 +212,74 @@ RtlConvertUlongToLuid(ULONG Ulong)
#endif
#endif
#ifdef NTOS_KERNEL_RUNTIME
//
// This macro does nothing in kernel mode
// Executing RTL functions at DISPATCH_LEVEL or higher will result in a
// bugcheck.
//
#define RTL_PAGED_CODE PAGED_CODE
#else
//
// This macro does nothing in user mode
//
#define RTL_PAGED_CODE NOP_FUNCTION
#endif
//
// RTL Splay Tree Functions
//
NTSYSAPI
PRTL_SPLAY_LINKS
NTAPI
RtlSplay(PRTL_SPLAY_LINKS Links);
NTSYSAPI
PRTL_SPLAY_LINKS
NTAPI
RtlDelete(PRTL_SPLAY_LINKS Links);
NTSYSAPI
VOID
NTAPI
RtlDeleteNoSplay(
PRTL_SPLAY_LINKS Links,
PRTL_SPLAY_LINKS *Root
RtlSplay(
IN PRTL_SPLAY_LINKS Links
);
NTSYSAPI
PRTL_SPLAY_LINKS
NTAPI
RtlSubtreeSuccessor(PRTL_SPLAY_LINKS Links);
RtlDelete(IN PRTL_SPLAY_LINKS Links
);
NTSYSAPI
VOID
NTAPI
RtlDeleteNoSplay(
IN PRTL_SPLAY_LINKS Links,
OUT PRTL_SPLAY_LINKS *Root
);
NTSYSAPI
PRTL_SPLAY_LINKS
NTAPI
RtlSubtreePredecessor(PRTL_SPLAY_LINKS Links);
RtlSubtreeSuccessor(
IN PRTL_SPLAY_LINKS Links
);
NTSYSAPI
PRTL_SPLAY_LINKS
NTAPI
RtlRealSuccessor(PRTL_SPLAY_LINKS Links);
RtlSubtreePredecessor(
IN PRTL_SPLAY_LINKS Links
);
NTSYSAPI
PRTL_SPLAY_LINKS
NTAPI
RtlRealPredecessor(PRTL_SPLAY_LINKS Links);
RtlRealSuccessor(
IN PRTL_SPLAY_LINKS Links
);
NTSYSAPI
PRTL_SPLAY_LINKS
NTAPI
RtlRealPredecessor(
IN PRTL_SPLAY_LINKS Links
);
#define RtlIsLeftChild(Links) \
(RtlLeftChild(RtlParent(Links)) == (PRTL_SPLAY_LINKS)(Links))
@ -306,16 +329,6 @@ RtlRealPredecessor(PRTL_SPLAY_LINKS Links);
}
#endif
#ifdef NTOS_KERNEL_RUNTIME
//
// Executing RTL functions at DISPATCH_LEVEL or higher will result in a
// bugcheck.
//
#define RTL_PAGED_CODE PAGED_CODE
#endif
//
// Error and Exception Functions
//
@ -2491,6 +2504,35 @@ VOID
NTAPI
DbgBreakPoint(VOID);
//
// Generic Table Functions
//
PVOID
NTAPI
RtlInsertElementGenericTable(
IN PRTL_GENERIC_TABLE Table,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT PBOOLEAN NewElement OPTIONAL
);
PVOID
NTAPI
RtlInsertElementGenericTableFull(
IN PRTL_GENERIC_TABLE Table,
IN PVOID Buffer,
IN ULONG BufferSize,
OUT PBOOLEAN NewElement OPTIONAL,
IN PVOID NodeOrParent,
IN TABLE_SEARCH_RESULT SearchResult
);
BOOLEAN
NTAPI
RtlIsGenericTableEmpty(
IN PRTL_GENERIC_TABLE Table
);
//
// Handle Table Functions
//

View file

@ -14,7 +14,82 @@
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
/* Internal header for table entries */
typedef struct _TABLE_ENTRY_HEADER
{
RTL_SPLAY_LINKS SplayLinks;
LIST_ENTRY ListEntry;
LONGLONG UserData;
} TABLE_ENTRY_HEADER, *PTABLE_ENTRY_HEADER;
/* PRIVATE FUNCTIONS *********************************************************/
TABLE_SEARCH_RESULT
NTAPI
RtlpFindGenericTableNodeOrParent(IN PRTL_GENERIC_TABLE Table,
IN PVOID Buffer,
OUT PRTL_SPLAY_LINKS *NodeOrParent)
{
PRTL_SPLAY_LINKS CurrentNode, ChildNode;
RTL_GENERIC_COMPARE_RESULTS Result;
/* Quick check to see if the table is empty */
if (RtlIsGenericTableEmpty(Table)) return TableEmptyTree;
/* Set the current node */
CurrentNode = Table->TableRoot;
/* Start compare loop */
while (TRUE)
{
/* Do the compare */
Result = Table->CompareRoutine(Table,
Buffer,
&((PTABLE_ENTRY_HEADER)CurrentNode)->
UserData);
if (Result == GenericLessThan)
{
/* We're less, check if this is the left child */
if ((ChildNode = RtlLeftChild(CurrentNode)))
{
/* Continue searching from this node */
ChildNode = CurrentNode;
}
else
{
/* Otherwise, the element isn't in this tree */
*NodeOrParent = CurrentNode;
return TableInsertAsLeft;
}
}
else if (Result == GenericGreaterThan)
{
/* We're more, check if this is the right child */
if ((ChildNode = RtlRightChild(CurrentNode)))
{
/* Continue searching from this node */
ChildNode = CurrentNode;
}
else
{
/* Otherwise, the element isn't in this tree */
*NodeOrParent = CurrentNode;
return TableInsertAsRight;
}
}
else
{
/* We should've found the node */
ASSERT(Result == GenericEqual);
/* Return node found */
*NodeOrParent = CurrentNode;
return TableFoundNode;
}
}
}
/* SPLAY FUNCTIONS ***********************************************************/
/*
* @implemented
@ -49,8 +124,19 @@ RtlInsertElementGenericTable(IN PRTL_GENERIC_TABLE Table,
IN ULONG BufferSize,
OUT PBOOLEAN NewElement OPTIONAL)
{
UNIMPLEMENTED;
return 0;
PRTL_SPLAY_LINKS NodeOrParent;
TABLE_SEARCH_RESULT Result;
/* Get the splay links and table search result immediately */
Result = RtlpFindGenericTableNodeOrParent(Table, Buffer, &NodeOrParent);
/* Now call the routine to do the full insert */
return RtlInsertElementGenericTableFull(Table,
Buffer,
BufferSize,
NewElement,
NodeOrParent,
Result);
}
/*
@ -65,8 +151,70 @@ RtlInsertElementGenericTableFull(IN PRTL_GENERIC_TABLE Table,
IN PVOID NodeOrParent,
IN TABLE_SEARCH_RESULT SearchResult)
{
UNIMPLEMENTED;
return 0;
PRTL_SPLAY_LINKS NewNode;
/* Check if the entry wasn't already found */
if (SearchResult != TableFoundNode)
{
/* We're doing an allocation, sanity check */
ASSERT(Table->NumberGenericTableElements != (MAXULONG - 1));
/* Allocate a node */
NewNode = Table->AllocateRoutine(Table,
BufferSize +
FIELD_OFFSET(TABLE_ENTRY_HEADER,
UserData));
if (!NewNode)
{
/* No memory or other allocation error, fail */
if (NewElement) *NewElement = FALSE;
return NULL;
}
/* Initialize the new inserted element */
RtlInitializeSplayLinks(NewNode);
InsertTailList(&Table->InsertOrderList,
&((PTABLE_ENTRY_HEADER)NewNode)->ListEntry);
/* Increase element count */
Table->NumberGenericTableElements++;
/* Check where we should insert the entry */
if (SearchResult == TableEmptyTree)
{
/* This is the new root node */
Table->TableRoot = NewNode;
}
else if (SearchResult == TableInsertAsLeft)
{
/* Insert it left */
RtlInsertAsLeftChild(NodeOrParent, NewNode);
}
else
{
/* Right node */
RtlInsertAsRightChild(NodeOrParent, NewNode);
}
/* Copy user buffer */
RtlCopyMemory(&((PTABLE_ENTRY_HEADER)NewNode)->UserData,
Buffer,
BufferSize);
}
else
{
/* Return the node we already found */
NewNode = NodeOrParent;
}
/* Splay the tree */
Table->TableRoot = RtlSplay(NewNode);
/* Return status */
if (NewElement) *NewElement = (SearchResult == TableFoundNode);
/* Return pointer to user data */
return &((PTABLE_ENTRY_HEADER)NewNode)->UserData;
}
/*
@ -289,6 +437,7 @@ NTAPI
RtlEnumerateGenericTableWithoutSplayingAvl(IN PRTL_AVL_TABLE Table,
IN OUT PVOID *RestartKey)
{
/* FIXME! */
return RtlEnumerateGenericTableWithoutSplayingAvl(Table, RestartKey);
}