From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/ntdll/tests/rtl.c | 88 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+)
diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c index 325a4a13b11..ac53c8dcdcc 100644 --- a/dlls/ntdll/tests/rtl.c +++ b/dlls/ntdll/tests/rtl.c @@ -101,6 +101,7 @@ static VOID (WINAPI *pRtlZeroMemory)(LPVOID,SIZE_T); static USHORT (FASTCALL *pRtlUshortByteSwap)(USHORT source); static ULONG (FASTCALL *pRtlUlongByteSwap)(ULONG source); static ULONGLONG (FASTCALL *pRtlUlonglongByteSwap)(ULONGLONG source); +static void * (WINAPI *pRtlGetElementGenericTable)(PRTL_GENERIC_TABLE, ULONG); static DWORD (WINAPI *pRtlGetThreadErrorMode)(void); static NTSTATUS (WINAPI *pRtlSetThreadErrorMode)(DWORD, LPDWORD); static PVOID (WINAPI *pRtlInsertElementGenericTable)(PRTL_GENERIC_TABLE, PVOID, CLONG, PBOOLEAN); @@ -172,6 +173,7 @@ static void InitFunctionPtrs(void) pRtlUshortByteSwap = (void *)GetProcAddress(hntdll, "RtlUshortByteSwap"); pRtlUlongByteSwap = (void *)GetProcAddress(hntdll, "RtlUlongByteSwap"); pRtlUlonglongByteSwap = (void *)GetProcAddress(hntdll, "RtlUlonglongByteSwap"); + pRtlGetElementGenericTable = (void *)GetProcAddress(hntdll, "RtlGetElementGenericTable"); pRtlGetThreadErrorMode = (void *)GetProcAddress(hntdll, "RtlGetThreadErrorMode"); pRtlSetThreadErrorMode = (void *)GetProcAddress(hntdll, "RtlSetThreadErrorMode"); pRtlInsertElementGenericTable = (void *)GetProcAddress(hntdll, "RtlInsertElementGenericTable"); @@ -5299,6 +5301,91 @@ static void test_RtlEnumerateGenericTable(void) } }
+static void test_RtlGetElementGenericTable(void) +{ + static const int elements[] = {9, 1, 5, 4, 15, 11, 2, 3, 8, 6, 0, 10, 13, 14, 7, 12}; + RTL_SPLAY_LINKS *old_table_root; + BOOLEAN success, new_element; + RTL_GENERIC_TABLE table; + int i, value, *ret; + + if (!pRtlGetElementGenericTable) + { + win_skip("RtlGetElementGenericTable is unavailable.\n"); + return; + } + + pRtlInitializeGenericTable(&table, generic_compare_proc, generic_allocate_proc, generic_free_proc, NULL); + + ret = pRtlGetElementGenericTable(&table, 0); + 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"); + } + + /* Test that RtlGetElementGenericTable() changes WhichOrderedElement and OrderedPointer, but not TableRoot */ + old_table_root = table.TableRoot; + for (i = 0; i < ARRAY_SIZE(elements); i++) + { + ret = pRtlGetElementGenericTable(&table, i); + ok(ret && *ret == elements[i], "Got unexpected pointer.\n"); + ok(table.WhichOrderedElement == i + 1, "Got unexpected WhichOrderedElement %lu.\n", + table.WhichOrderedElement); + ok(table.OrderedPointer == get_list_entry_from_data(ret), "Got unexpected OrderedPointer.\n"); + ok(table.TableRoot == old_table_root, "Got unexpected TableRoot.\n"); + } + + /* RtlInsertElementGenericTable() shouldn't touch WhichOrderedElement */ + value = 20; + ret = pRtlInsertElementGenericTable(&table, &value, sizeof(value), &new_element); + ok(ret && *ret == 20, "Got unexpected pointer.\n"); + ok(new_element, "Expected new element.\n"); + ok(table.WhichOrderedElement == ARRAY_SIZE(elements), "Got unexpected WhichOrderedElement %lu.\n", + table.WhichOrderedElement); + + /* RtlGetElementGenericTable() updates WhichOrderedElement. WhichOrderedElement points to the + * result element but its index starts from 1 instead of 0 */ + ret = pRtlGetElementGenericTable(&table, 1); + ok(ret && *ret == elements[1], "Got unexpected pointer.\n"); + ok(table.WhichOrderedElement == 2, "Got unexpected WhichOrderedElement %lu.\n", + table.WhichOrderedElement); + ok(table.OrderedPointer == get_list_entry_from_data(ret), "Got unexpected OrderedPointer.\n"); + + /* RtlDeleteElementGenericTable() should reset WhichOrderedElement and OrderedPointer */ + value = 20; + success = pRtlDeleteElementGenericTable(&table, &value); + ok(success, "RtlDeleteElementGenericTable failed.\n"); + ok(table.WhichOrderedElement == 0, "Got unexpected WhichOrderedElement %lu.\n", table.WhichOrderedElement); + ok(table.OrderedPointer == &table.InsertOrderList, "Got unexpected OrderedPointer.\n"); + + /* Out of order RtlGetElementGenericTable() calls */ + for (i = 0; i < ARRAY_SIZE(elements); i++) + { + ret = pRtlGetElementGenericTable(&table, elements[i]); + ok(ret && *ret == elements[elements[i]], "Expected %d got %d at %d.\n", + elements[elements[i]], *ret, elements[i]); + ok(table.WhichOrderedElement == elements[i] + 1, "Got unexpected WhichOrderedElement %lu.\n", + table.WhichOrderedElement); + ok(table.OrderedPointer == get_list_entry_from_data(ret), "Got unexpected OrderedPointer.\n"); + } + + /* Out of range RtlGetElementGenericTable() call */ + ret = pRtlGetElementGenericTable(&table, ARRAY_SIZE(elements)); + ok(!ret, "Got unexpected pointer.\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(); @@ -5366,4 +5453,5 @@ START_TEST(rtl) test_RtlLookupElementGenericTable(); test_RtlEnumerateGenericTableWithoutSplaying(); test_RtlEnumerateGenericTable(); + test_RtlGetElementGenericTable(); }