From dbb8a15d7c1c59f6587e0472df63fd061604a482 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Mon, 16 Oct 2006 03:19:14 +0000 Subject: [PATCH] - 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 --- reactos/include/ndk/rtlfuncs.h | 98 ++++++++++++++------ reactos/lib/rtl/generictable.c | 159 +++++++++++++++++++++++++++++++-- 2 files changed, 224 insertions(+), 33 deletions(-) diff --git a/reactos/include/ndk/rtlfuncs.h b/reactos/include/ndk/rtlfuncs.h index ef6e974da3e..dce62329efd 100644 --- a/reactos/include/ndk/rtlfuncs.h +++ b/reactos/include/ndk/rtlfuncs.h @@ -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 // diff --git a/reactos/lib/rtl/generictable.c b/reactos/lib/rtl/generictable.c index a86e4afc621..12a363e0ad7 100644 --- a/reactos/lib/rtl/generictable.c +++ b/reactos/lib/rtl/generictable.c @@ -14,7 +14,82 @@ #define NDEBUG #include -/* 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); }