For React Native.
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/ntdll/ntdll.spec | 2 +- dlls/ntdll/rtl.c | 75 +++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- include/ddk/ntddk.h | 1 + 4 files changed, 78 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 8614ecf9d47..63fc62c5d38 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -819,7 +819,7 @@ @ stdcall RtlInitializeSRWLock(ptr) @ stdcall RtlInitializeSid(ptr ptr long) # @ stub RtlInitializeStackTraceDataBase -@ stub RtlInsertElementGenericTable +@ stdcall RtlInsertElementGenericTable(ptr ptr long ptr) @ stdcall RtlInsertElementGenericTableAvl(ptr ptr long ptr) @ cdecl -arch=!i386 RtlInstallFunctionTableCallback(long long long ptr ptr wstr) @ stdcall RtlInt64ToUnicodeString(int64 long ptr) diff --git a/dlls/ntdll/rtl.c b/dlls/ntdll/rtl.c index ee330482162..8138c060795 100644 --- a/dlls/ntdll/rtl.c +++ b/dlls/ntdll/rtl.c @@ -236,6 +236,24 @@ NTSTATUS WINAPI RtlResetNtUserPfn(void) return STATUS_SUCCESS; }
+/* data is a place holder to align stored data on a 8 byte boundary */ +struct rtl_generic_table_entry +{ + RTL_SPLAY_LINKS splay_links; + LIST_ENTRY list_entry; + LONGLONG data; +}; + +static void *get_data_from_splay_links(RTL_SPLAY_LINKS *links) +{ + return (unsigned char *)links + FIELD_OFFSET(struct rtl_generic_table_entry, data); +} + +static LIST_ENTRY *get_list_entry_from_splay_links(RTL_SPLAY_LINKS *links) +{ + return (LIST_ENTRY *)((unsigned char *)links + FIELD_OFFSET(struct rtl_generic_table_entry, list_entry)); +} + static void rtl_splay_replace(RTL_SPLAY_LINKS *x, RTL_SPLAY_LINKS *y, RTL_SPLAY_LINKS **root) { if (RtlIsRoot(x)) @@ -556,6 +574,63 @@ BOOLEAN WINAPI RtlIsGenericTableEmpty(RTL_GENERIC_TABLE *table) return !table->TableRoot; }
+/*********************************************************************** + * RtlInsertElementGenericTable (NTDLL.@) + */ +void * WINAPI RtlInsertElementGenericTable(RTL_GENERIC_TABLE *table, void *value, CLONG size, BOOLEAN *new_element) +{ + RTL_SPLAY_LINKS *child, *parent = NULL; + RTL_GENERIC_COMPARE_RESULTS result; + void *buffer; + + TRACE("(%p, %p, %lu, %p)\n", table, value, size, new_element); + + child = table->TableRoot; + while (child) + { + buffer = get_data_from_splay_links(child); + result = table->CompareRoutine(table, buffer, value); + parent = child; + if (result == GenericLessThan) + { + child = child->RightChild; + } + else if (result == GenericGreaterThan) + { + child = child->LeftChild; + } + else + { + if (new_element) + *new_element = FALSE; + return buffer; + } + } + + /* data should be stored on a 8 byte boundary */ + child = (RTL_SPLAY_LINKS *)table->AllocateRoutine(table, size + FIELD_OFFSET(struct rtl_generic_table_entry, data)); + RtlInitializeSplayLinks(child); + InsertTailList(&table->InsertOrderList, get_list_entry_from_splay_links(child)); + buffer = get_data_from_splay_links(child); + memcpy(buffer, value, size); + + if (parent) + { + buffer = get_data_from_splay_links(parent); + result = table->CompareRoutine(table, buffer, value); + if (result == GenericLessThan) + RtlInsertAsRightChild(parent, child); + else + RtlInsertAsLeftChild(parent, child); + } + + if (new_element) + *new_element = TRUE; + table->TableRoot = RtlSplay(child); + table->NumberGenericTableElements++; + return get_data_from_splay_links(child); +} + /****************************************************************************** * RtlEnumerateGenericTableWithoutSplaying [NTDLL.@] */ diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 57a947ea821..050409f993d 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -1150,7 +1150,7 @@ @ stub RtlInitializeRangeList @ stdcall RtlInitializeSid(ptr ptr long) @ stub RtlInitializeUnicodePrefix -@ stub RtlInsertElementGenericTable +@ stdcall RtlInsertElementGenericTable(ptr ptr long ptr) @ stdcall RtlInsertElementGenericTableAvl(ptr ptr long ptr) @ stub RtlInsertElementGenericTableFull @ stub RtlInsertElementGenericTableFullAvl diff --git a/include/ddk/ntddk.h b/include/ddk/ntddk.h index 67198da2f3d..f16b3fd628a 100644 --- a/include/ddk/ntddk.h +++ b/include/ddk/ntddk.h @@ -308,6 +308,7 @@ BOOLEAN WINAPI RtlEqualString(const STRING*,const STRING*,BOOLEAN); void * WINAPI RtlGetElementGenericTable(PRTL_GENERIC_TABLE,ULONG); void WINAPI RtlInitializeGenericTable(PRTL_GENERIC_TABLE,PRTL_GENERIC_COMPARE_ROUTINE,PRTL_GENERIC_ALLOCATE_ROUTINE,PRTL_GENERIC_FREE_ROUTINE,void *); void WINAPI RtlInitializeGenericTableAvl(PRTL_AVL_TABLE,PRTL_AVL_COMPARE_ROUTINE,PRTL_AVL_ALLOCATE_ROUTINE, PRTL_AVL_FREE_ROUTINE,void *); +PVOID WINAPI RtlInsertElementGenericTable(PRTL_GENERIC_TABLE,PVOID,CLONG,PBOOLEAN); void WINAPI RtlInsertElementGenericTableAvl(PRTL_AVL_TABLE,void *,ULONG,BOOL*); BOOLEAN WINAPI RtlIsGenericTableEmpty(PRTL_GENERIC_TABLE); void * WINAPI RtlLookupElementGenericTable(PRTL_GENERIC_TABLE,void *);
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/ntdll/ntdll.spec | 2 +- dlls/ntdll/rtl.c | 38 +++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- include/ddk/ntddk.h | 1 + 4 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 63fc62c5d38..cb6682d7e5c 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -615,7 +615,7 @@ @ stdcall RtlDeleteAtomFromAtomTable(ptr long) @ stdcall RtlDeleteCriticalSection(ptr) @ stdcall -arch=!i386 RtlDeleteGrowableFunctionTable(ptr) -@ stub RtlDeleteElementGenericTable +@ stdcall RtlDeleteElementGenericTable(ptr ptr) @ stub RtlDeleteElementGenericTableAvl @ cdecl -arch=!i386 RtlDeleteFunctionTable(ptr) @ stdcall RtlDeleteNoSplay(ptr ptr) diff --git a/dlls/ntdll/rtl.c b/dlls/ntdll/rtl.c index 8138c060795..7f5282e8b97 100644 --- a/dlls/ntdll/rtl.c +++ b/dlls/ntdll/rtl.c @@ -254,6 +254,25 @@ static LIST_ENTRY *get_list_entry_from_splay_links(RTL_SPLAY_LINKS *links) return (LIST_ENTRY *)((unsigned char *)links + FIELD_OFFSET(struct rtl_generic_table_entry, list_entry)); }
+static RTL_SPLAY_LINKS *rtl_splay_find(RTL_GENERIC_TABLE *table, void *value) +{ + RTL_GENERIC_COMPARE_RESULTS result; + RTL_SPLAY_LINKS *child; + + child = table->TableRoot; + while (child) + { + result = table->CompareRoutine(table, get_data_from_splay_links(child), value); + if (result == GenericLessThan) + child = child->RightChild; + else if (result == GenericGreaterThan) + child = child->LeftChild; + else + return child; + } + return NULL; +} + static void rtl_splay_replace(RTL_SPLAY_LINKS *x, RTL_SPLAY_LINKS *y, RTL_SPLAY_LINKS **root) { if (RtlIsRoot(x)) @@ -631,6 +650,25 @@ void * WINAPI RtlInsertElementGenericTable(RTL_GENERIC_TABLE *table, void *value return get_data_from_splay_links(child); }
+BOOLEAN WINAPI RtlDeleteElementGenericTable(RTL_GENERIC_TABLE *table, void *value) +{ + RTL_SPLAY_LINKS *child; + + TRACE("(%p, %p)\n", table, value); + + child = rtl_splay_find(table, value); + if (!child) + return FALSE; + + table->TableRoot = RtlDelete(child); + RemoveEntryList(get_list_entry_from_splay_links(child)); + table->NumberGenericTableElements--; + table->OrderedPointer = &table->InsertOrderList; + table->WhichOrderedElement = 0; + table->FreeRoutine(table, child); + return TRUE; +} + /****************************************************************************** * RtlEnumerateGenericTableWithoutSplaying [NTDLL.@] */ diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 050409f993d..49a29d06644 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -1054,7 +1054,7 @@ @ stdcall RtlDelete(ptr) @ stdcall RtlDeleteAce(ptr long) @ stdcall RtlDeleteAtomFromAtomTable(ptr long) -@ stub RtlDeleteElementGenericTable +@ stdcall RtlDeleteElementGenericTable(ptr ptr) @ stub RtlDeleteElementGenericTableAvl @ stdcall RtlDeleteNoSplay(ptr ptr) @ stub RtlDeleteOwnersRanges diff --git a/include/ddk/ntddk.h b/include/ddk/ntddk.h index f16b3fd628a..36c52097c16 100644 --- a/include/ddk/ntddk.h +++ b/include/ddk/ntddk.h @@ -301,6 +301,7 @@ NTSTATUS WINAPI PsSetLoadImageNotifyRoutineEx(PLOAD_IMAGE_NOTIFY_ROUTINE,ULONG_ LONG WINAPI RtlCompareString(const STRING*,const STRING*,BOOLEAN); void WINAPI RtlCopyString(STRING*,const STRING*); PRTL_SPLAY_LINKS WINAPI RtlDelete(PRTL_SPLAY_LINKS); +BOOLEAN WINAPI RtlDeleteElementGenericTable(PRTL_GENERIC_TABLE,PVOID); void WINAPI RtlDeleteNoSplay(PRTL_SPLAY_LINKS,PRTL_SPLAY_LINKS *); void * WINAPI RtlEnumerateGenericTableWithoutSplaying(PRTL_GENERIC_TABLE,PVOID*); void * WINAPI RtlEnumerateGenericTableWithoutSplayingAvl(PRTL_AVL_TABLE,PVOID*);
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/ntdll/tests/rtl.c | 119 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+)
diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c index 05a27ec6b2c..9d1c5ec7497 100644 --- a/dlls/ntdll/tests/rtl.c +++ b/dlls/ntdll/tests/rtl.c @@ -91,6 +91,7 @@ __ASM_STDCALL_FUNC( wrap_fastcall_func1, 8, static HMODULE hntdll = 0; static PRTL_SPLAY_LINKS (WINAPI *pRtlDelete)(PRTL_SPLAY_LINKS); static void (WINAPI *pRtlDeleteNoSplay)(PRTL_SPLAY_LINKS, PRTL_SPLAY_LINKS *); +static BOOLEAN (WINAPI *pRtlDeleteElementGenericTable)(PRTL_GENERIC_TABLE,PVOID); static VOID (WINAPI *pRtlMoveMemory)(LPVOID,LPCVOID,SIZE_T); static VOID (WINAPI *pRtlFillMemory)(LPVOID,SIZE_T,BYTE); static VOID (WINAPI *pRtlFillMemoryUlong)(LPVOID,SIZE_T,ULONG); @@ -100,6 +101,7 @@ static ULONG (FASTCALL *pRtlUlongByteSwap)(ULONG source); static ULONGLONG (FASTCALL *pRtlUlonglongByteSwap)(ULONGLONG source); static DWORD (WINAPI *pRtlGetThreadErrorMode)(void); static NTSTATUS (WINAPI *pRtlSetThreadErrorMode)(DWORD, LPDWORD); +static PVOID (WINAPI *pRtlInsertElementGenericTable)(PRTL_GENERIC_TABLE, PVOID, CLONG, PBOOLEAN); static NTSTATUS (WINAPI *pRtlIpv4AddressToStringExA)(const IN_ADDR *, USHORT, LPSTR, PULONG); static NTSTATUS (WINAPI *pRtlIpv4StringToAddressExA)(PCSTR, BOOLEAN, IN_ADDR *, PUSHORT); static NTSTATUS (WINAPI *pRtlIpv6AddressToStringExA)(struct in6_addr *, ULONG, USHORT, PCHAR, PULONG); @@ -156,6 +158,7 @@ static void InitFunctionPtrs(void) ok(hntdll != 0, "LoadLibrary failed\n"); if (hntdll) { pRtlDelete = (void *)GetProcAddress(hntdll, "RtlDelete"); + pRtlDeleteElementGenericTable = (void *)GetProcAddress(hntdll, "RtlDeleteElementGenericTable"); pRtlDeleteNoSplay = (void *)GetProcAddress(hntdll, "RtlDeleteNoSplay"); pRtlMoveMemory = (void *)GetProcAddress(hntdll, "RtlMoveMemory"); pRtlFillMemory = (void *)GetProcAddress(hntdll, "RtlFillMemory"); @@ -166,6 +169,7 @@ static void InitFunctionPtrs(void) pRtlUlonglongByteSwap = (void *)GetProcAddress(hntdll, "RtlUlonglongByteSwap"); pRtlGetThreadErrorMode = (void *)GetProcAddress(hntdll, "RtlGetThreadErrorMode"); pRtlSetThreadErrorMode = (void *)GetProcAddress(hntdll, "RtlSetThreadErrorMode"); + pRtlInsertElementGenericTable = (void *)GetProcAddress(hntdll, "RtlInsertElementGenericTable"); pRtlIpv4AddressToStringExA = (void *)GetProcAddress(hntdll, "RtlIpv4AddressToStringExA"); pRtlIpv4StringToAddressExA = (void *)GetProcAddress(hntdll, "RtlIpv4StringToAddressExA"); pRtlIpv6AddressToStringExA = (void *)GetProcAddress(hntdll, "RtlIpv6AddressToStringExA"); @@ -4854,6 +4858,31 @@ static void test_RtlDelete(void) ok(root == NULL, "Got unexpected root.\n"); }
+/* data is a place holder to align stored data on a 8 byte boundary */ +struct rtl_generic_table_entry +{ + RTL_SPLAY_LINKS splay_links; + LIST_ENTRY list_entry; + LONGLONG data; +}; + +static void *get_data_from_list_entry(LIST_ENTRY *list_entry) +{ + return (unsigned char *)list_entry + FIELD_OFFSET(struct rtl_generic_table_entry, data) + - FIELD_OFFSET(struct rtl_generic_table_entry, list_entry); +} + +static RTL_SPLAY_LINKS *get_splay_links_from_data(void *data) +{ + return (RTL_SPLAY_LINKS *)((unsigned char *)data - FIELD_OFFSET(struct rtl_generic_table_entry, data)); +} + +static LIST_ENTRY *get_list_entry_from_data(void *data) +{ + return (LIST_ENTRY *)((unsigned char *)data - FIELD_OFFSET(struct rtl_generic_table_entry, data) + + FIELD_OFFSET(struct rtl_generic_table_entry, list_entry)); +} + static RTL_GENERIC_COMPARE_RESULTS WINAPI generic_compare_proc(RTL_GENERIC_TABLE *table, void *p1, void *p2) { int *value1 = p1, *value2 = p2; @@ -4868,6 +4897,10 @@ static RTL_GENERIC_COMPARE_RESULTS WINAPI generic_compare_proc(RTL_GENERIC_TABLE
static void * WINAPI generic_allocate_proc(RTL_GENERIC_TABLE *table, CLONG size) { + CLONG *last_allocated = table->TableContext; + + if (last_allocated) + *last_allocated = size; return malloc(size); }
@@ -4940,6 +4973,91 @@ static void test_RtlIsGenericTableEmpty(void) ok(!empty, "Expected not empty.\n"); }
+static void test_RtlInsertElementGenericTable(void) +{ + static const int elements[] = {1, 9, 5, 4, 7, 2, 3, 8, 6}; + int i, value, *ret, *first_ret = NULL, *last_ret = NULL; + ULONG count, size, last_allocated; + BOOLEAN new_element, success; + RTL_GENERIC_TABLE table; + LIST_ENTRY *entry; + + if (!pRtlInsertElementGenericTable) + { + win_skip("RtlInsertElementGenericTable is unavailable.\n"); + return; + } + + pRtlInitializeGenericTable(&table, generic_compare_proc, generic_allocate_proc, + generic_free_proc, (void *)&last_allocated); + + for (i = 0; i < ARRAY_SIZE(elements); i++) + { + value = elements[i]; + ret = pRtlInsertElementGenericTable(&table, &value, sizeof(value), &new_element); + ok(ret && *ret == value, "Got unexpected pointer.\n"); + ok(new_element, "Expected new element.\n"); + ok(table.TableRoot == get_splay_links_from_data(ret), "Got unexpected TableRoot.\n"); + + if (i == 0) + first_ret = ret; + if (i == ARRAY_SIZE(elements) - 1) + last_ret = ret; + } + + count = pRtlNumberGenericTableElements(&table); + ok(count == ARRAY_SIZE(elements), "Got unexpected count %ld.\n", count); + + /* Test that the allocated memory includes a RTL_SPLAY_LINKS and a LIST_ENTRY header. The data + * is aligned on a 8 byte boundary */ + size = FIELD_OFFSET(struct rtl_generic_table_entry, data) + sizeof(value); + ok(last_allocated == size, "Expected %lu, got %lu.\n", size, last_allocated); + + /* Check that InsertOrderList points to a doubly linked list of elements in insertion order */ + ok(table.InsertOrderList.Flink == get_list_entry_from_data(first_ret), "Got unexpected Flink.\n"); + ok(table.InsertOrderList.Blink == get_list_entry_from_data(last_ret), "Got unexpected Blink.\n"); + for (i = 0, entry = table.InsertOrderList.Flink; entry->Flink != table.InsertOrderList.Flink; + i++, entry = entry->Flink) + { + ret = (int *)get_data_from_list_entry(entry); + ok(*ret == elements[i], "Got unexpected pointer, value %d.\n", *ret); + } + ok(i == ARRAY_SIZE(elements), "Got unexpected index %d.\n", i); + for (i = ARRAY_SIZE(elements) - 1, entry = table.InsertOrderList.Blink; + entry->Blink != table.InsertOrderList.Blink; i--, entry = entry->Blink) + { + ret = (int *)get_data_from_list_entry(entry); + ok(*ret == elements[i], "Got unexpected pointer, value %d.\n", *ret); + } + ok(i == -1, "Got unexpected index %d.\n", i); + + /* Insert the same element again */ + ret = pRtlInsertElementGenericTable(&table, &value, sizeof(value), &new_element); + ok(ret && *ret == value, "Got unexpected pointer.\n"); + ok(!new_element, "Expected old element.\n"); + + count = pRtlNumberGenericTableElements(&table); + ok(count == ARRAY_SIZE(elements), "Got unexpected count %ld.\n", count); + + /* Insert a new element with new_element pointer being NULL */ + value = 0; + ret = pRtlInsertElementGenericTable(&table, &value, sizeof(value), NULL); + ok(ret && ret != &value && *ret == 0, "Got unexpected pointer.\n"); + + count = pRtlNumberGenericTableElements(&table); + ok(count == ARRAY_SIZE(elements) + 1, "Got unexpected count %ld.\n", count); + + success = pRtlDeleteElementGenericTable(&table, &value); + ok(success, "RtlDeleteElementGenericTable failed.\n"); + + for (i = 0; i < ARRAY_SIZE(elements); i++) + { + value = elements[i]; + success = pRtlDeleteElementGenericTable(&table, &value); + ok(success, "RtlDeleteElementGenericTable failed.\n"); + } +} + START_TEST(rtl) { InitFunctionPtrs(); @@ -5002,4 +5120,5 @@ START_TEST(rtl) test_RtlInitializeGenericTable(); test_RtlNumberGenericTableElements(); test_RtlIsGenericTableEmpty(); + test_RtlInsertElementGenericTable(); }
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/ntdll/tests/rtl.c | 45 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c index 9d1c5ec7497..69af20619e6 100644 --- a/dlls/ntdll/tests/rtl.c +++ b/dlls/ntdll/tests/rtl.c @@ -5058,6 +5058,50 @@ static void test_RtlInsertElementGenericTable(void) } }
+static void test_RtlDeleteElementGenericTable(void) +{ + static const int elements[] = {1, 9, 5, 4, 7, 2, 3, 8, 6}; + BOOLEAN success, new_element, empty; + RTL_GENERIC_TABLE table; + int i, value, *ret; + + if (!pRtlDeleteElementGenericTable) + { + win_skip("RtlDeleteElementGenericTable is unavailable.\n"); + return; + } + + pRtlInitializeGenericTable(&table, generic_compare_proc, generic_allocate_proc, generic_free_proc, NULL); + + success = pRtlDeleteElementGenericTable(&table, NULL); + ok(!success, "Got unexpected pointer.\n"); + + for (i = 0; i < ARRAY_SIZE(elements); i++) + { + value = elements[i]; + ret = pRtlInsertElementGenericTable(&table, &value, sizeof(value), &new_element); + ok(ret && *ret == value, "Got unexpected pointer.\n"); + ok(new_element, "Expected new element.\n"); + } + + for (i = 0; i < ARRAY_SIZE(elements); i++) + { + value = elements[i]; + success = pRtlDeleteElementGenericTable(&table, &value); + ok(success, "RtlDeleteElementGenericTable failed.\n"); + ok(table.NumberGenericTableElements == ARRAY_SIZE(elements) - i - 1, + "Got unexpected NumberGenericTableElements %lu.\n", table.NumberGenericTableElements); + } + + empty = pRtlIsGenericTableEmpty(&table); + ok(empty, "Expected empty.\n"); + + /* Delete non-existent element */ + value = elements[0]; + success = pRtlDeleteElementGenericTable(&table, &value); + ok(!success, "RtlDeleteElementGenericTable succeeded.\n"); +} + START_TEST(rtl) { InitFunctionPtrs(); @@ -5121,4 +5165,5 @@ START_TEST(rtl) test_RtlNumberGenericTableElements(); test_RtlIsGenericTableEmpty(); test_RtlInsertElementGenericTable(); + test_RtlDeleteElementGenericTable(); }
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/ntdll/rtl.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/rtl.c b/dlls/ntdll/rtl.c index 7f5282e8b97..1828b860531 100644 --- a/dlls/ntdll/rtl.c +++ b/dlls/ntdll/rtl.c @@ -702,10 +702,18 @@ void * WINAPI RtlGetElementGenericTable(RTL_GENERIC_TABLE *table, ULONG index) /****************************************************************************** * RtlLookupElementGenericTable [NTDLL.@] */ -void * WINAPI RtlLookupElementGenericTable(RTL_GENERIC_TABLE *table, void *buffer) +void * WINAPI RtlLookupElementGenericTable(RTL_GENERIC_TABLE *table, void *value) { - FIXME("(%p, %p) stub!\n", table, buffer); - return NULL; + RTL_SPLAY_LINKS *child; + + TRACE("(%p, %p)\n", table, value); + + child = rtl_splay_find(table, value); + if (!child) + return FALSE; + + table->TableRoot = RtlSplay(child); + return get_data_from_splay_links(child); }
/******************************************************************************
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/ntdll/tests/rtl.c | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+)
diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c index 69af20619e6..eaee2768c6a 100644 --- a/dlls/ntdll/tests/rtl.c +++ b/dlls/ntdll/tests/rtl.c @@ -115,6 +115,7 @@ static void (WINAPI *pRtlInitializeGenericTable)(RTL_GENERIC_TABLE *, PRTL_ PRTL_GENERIC_ALLOCATE_ROUTINE, PRTL_GENERIC_FREE_ROUTINE, void *); static void * (WINAPI *pRtlFindExportedRoutineByName)(HMODULE,const char *); +static void * (WINAPI *pRtlLookupElementGenericTable)(PRTL_GENERIC_TABLE, void *); static ULONG (WINAPI *pRtlNumberGenericTableElements)(PRTL_GENERIC_TABLE); static NTSTATUS (WINAPI *pLdrEnumerateLoadedModules)(void *, void *, void *); static NTSTATUS (WINAPI *pLdrRegisterDllNotification)(ULONG, PLDR_DLL_NOTIFICATION_FUNCTION, void *, void **); @@ -181,6 +182,7 @@ static void InitFunctionPtrs(void) pRtlInitializeCriticalSectionEx = (void *)GetProcAddress(hntdll, "RtlInitializeCriticalSectionEx"); pRtlInitializeGenericTable = (void *)GetProcAddress(hntdll, "RtlInitializeGenericTable"); pRtlFindExportedRoutineByName = (void *)GetProcAddress(hntdll, "RtlFindExportedRoutineByName"); + pRtlLookupElementGenericTable = (void *)GetProcAddress(hntdll, "RtlLookupElementGenericTable"); pRtlNumberGenericTableElements = (void *)GetProcAddress(hntdll, "RtlNumberGenericTableElements"); pLdrEnumerateLoadedModules = (void *)GetProcAddress(hntdll, "LdrEnumerateLoadedModules"); pLdrRegisterDllNotification = (void *)GetProcAddress(hntdll, "LdrRegisterDllNotification"); @@ -5102,6 +5104,52 @@ static void test_RtlDeleteElementGenericTable(void) ok(!success, "RtlDeleteElementGenericTable succeeded.\n"); }
+static void test_RtlLookupElementGenericTable(void) +{ + static const int elements[] = {1, 9, 5, 4, 7, 2, 3, 8, 6}; + BOOLEAN new_element, success; + RTL_GENERIC_TABLE table; + int i, value, *ret; + + if (!pRtlLookupElementGenericTable) + { + win_skip("RtlLookupElementGenericTable is unavailable.\n"); + return; + } + + pRtlInitializeGenericTable(&table, generic_compare_proc, generic_allocate_proc, generic_free_proc, NULL); + + ret = pRtlLookupElementGenericTable(&table, NULL); + ok(!ret, "Got unexpected pointer.\n"); + + value = 1; + ret = pRtlLookupElementGenericTable(&table, &value); + ok(!ret, "Got unexpected pointer.\n"); + + for (i = 0; i < ARRAY_SIZE(elements); i++) + { + value = elements[i]; + ret = pRtlInsertElementGenericTable(&table, &value, sizeof(value), &new_element); + ok(ret && *ret == value, "Got unexpected pointer.\n"); + ok(new_element, "Expected new element.\n"); + } + + for (i = 0; i < ARRAY_SIZE(elements); i++) + { + value = elements[i]; + ret = pRtlLookupElementGenericTable(&table, &value); + ok(ret && *ret == value, "Got unexpected pointer.\n"); + ok(table.TableRoot == get_splay_links_from_data(ret), "Got unexpected TableRoot.\n"); + } + + for (i = 0; i < ARRAY_SIZE(elements); i++) + { + value = elements[i]; + success = pRtlDeleteElementGenericTable(&table, &value); + ok(success, "RtlDeleteElementGenericTable failed.\n"); + } +} + START_TEST(rtl) { InitFunctionPtrs(); @@ -5166,4 +5214,5 @@ START_TEST(rtl) test_RtlIsGenericTableEmpty(); test_RtlInsertElementGenericTable(); test_RtlDeleteElementGenericTable(); + test_RtlLookupElementGenericTable(); }