Author: ion Date: Mon Oct 16 07:19:14 2006 New Revision: 24541
URL: http://svn.reactos.org/svn/reactos?rev=24541&view=rev Log: - 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.
Modified: trunk/reactos/include/ndk/rtlfuncs.h trunk/reactos/lib/rtl/generictable.c
Modified: trunk/reactos/include/ndk/rtlfuncs.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/rtlfuncs.h?rev=... ============================================================================== --- trunk/reactos/include/ndk/rtlfuncs.h (original) +++ trunk/reactos/include/ndk/rtlfuncs.h Mon Oct 16 07:19:14 2006 @@ -212,51 +212,74 @@ #endif #endif
-// -// This macro does nothing in kernel mode +#ifdef NTOS_KERNEL_RUNTIME + +// +// 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); +RtlSplay( + IN PRTL_SPLAY_LINKS Links +);
NTSYSAPI PRTL_SPLAY_LINKS NTAPI -RtlDelete(PRTL_SPLAY_LINKS Links); +RtlDelete(IN PRTL_SPLAY_LINKS Links +);
NTSYSAPI VOID NTAPI RtlDeleteNoSplay( - PRTL_SPLAY_LINKS Links, - PRTL_SPLAY_LINKS *Root + IN PRTL_SPLAY_LINKS Links, + OUT PRTL_SPLAY_LINKS *Root );
NTSYSAPI PRTL_SPLAY_LINKS NTAPI -RtlSubtreeSuccessor(PRTL_SPLAY_LINKS Links); +RtlSubtreeSuccessor( + IN PRTL_SPLAY_LINKS Links +);
NTSYSAPI PRTL_SPLAY_LINKS NTAPI -RtlSubtreePredecessor(PRTL_SPLAY_LINKS Links); +RtlSubtreePredecessor( + IN PRTL_SPLAY_LINKS Links +);
NTSYSAPI PRTL_SPLAY_LINKS NTAPI -RtlRealSuccessor(PRTL_SPLAY_LINKS Links); +RtlRealSuccessor( + IN PRTL_SPLAY_LINKS Links +);
NTSYSAPI PRTL_SPLAY_LINKS NTAPI -RtlRealPredecessor(PRTL_SPLAY_LINKS Links); +RtlRealPredecessor( + IN PRTL_SPLAY_LINKS Links +);
#define RtlIsLeftChild(Links) \ (RtlLeftChild(RtlParent(Links)) == (PRTL_SPLAY_LINKS)(Links)) @@ -304,16 +327,6 @@ _SplayParent->RightChild = _SplayChild; \ _SplayChild->Parent = _SplayParent; \ } -#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
// @@ -2492,6 +2505,35 @@ 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 // NTSYSAPI
Modified: trunk/reactos/lib/rtl/generictable.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/generictable.c?rev=... ============================================================================== --- trunk/reactos/lib/rtl/generictable.c (original) +++ trunk/reactos/lib/rtl/generictable.c Mon Oct 16 07:19:14 2006 @@ -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 @@ 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 @@ 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 @@ RtlEnumerateGenericTableWithoutSplayingAvl(IN PRTL_AVL_TABLE Table, IN OUT PVOID *RestartKey) { + /* FIXME! */ return RtlEnumerateGenericTableWithoutSplayingAvl(Table, RestartKey); }