Paul Gofman : kernel32/tests: Add test for DDAG node dependencies structure.

Alexandre Julliard julliard at winehq.org
Thu Oct 21 16:04:17 CDT 2021


Module: wine
Branch: master
Commit: 231542b39e8b17878fe1b9e6c75d7e095f192945
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=231542b39e8b17878fe1b9e6c75d7e095f192945

Author: Paul Gofman <pgofman at codeweavers.com>
Date:   Thu Oct 21 15:47:26 2021 +0300

kernel32/tests: Add test for DDAG node dependencies structure.

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/tests/module.c | 103 +++++++++++++++++++++++++++++++++++++++++++
 include/winternl.h           |  10 ++++-
 2 files changed, 112 insertions(+), 1 deletion(-)

diff --git a/dlls/kernel32/tests/module.c b/dlls/kernel32/tests/module.c
index 60654754302..fd369ff33e9 100644
--- a/dlls/kernel32/tests/module.c
+++ b/dlls/kernel32/tests/module.c
@@ -1329,6 +1329,108 @@ static void test_LdrGetDllFullName(void)
             wine_dbgstr_w(expected_path), wine_dbgstr_w(path_buffer) );
 }
 
+static void test_ddag_node(void)
+{
+    static const struct
+    {
+        const WCHAR *dllname;
+        BOOL optional;
+    }
+    expected_exe_dependencies[] =
+    {
+        { L"advapi32.dll" },
+        { L"msvcrt.dll", TRUE },
+        { L"user32.dll", TRUE },
+    };
+    LDR_DDAG_NODE *node, *dep_node, *prev_node;
+    LDR_DATA_TABLE_ENTRY *mod, *mod2;
+    SINGLE_LIST_ENTRY *se, *se2;
+    LDR_DEPENDENCY *dep, *dep2;
+    NTSTATUS status;
+    unsigned int i;
+    HMODULE hexe;
+
+    hexe = GetModuleHandleW( NULL );
+    ok( !!hexe, "Got NULL exe handle.\n" );
+
+    status = LdrFindEntryForAddress( hexe, &mod );
+    ok( !status, "Got unexpected status %#x.\n", status );
+
+    if (!(node = mod->DdagNode))
+    {
+        skip( "DdagNode is NULL, skipping tests.\n" );
+        return;
+    }
+
+    ok( !!node->Modules.Flink, "Got NULL module link.\n" );
+    mod2 = CONTAINING_RECORD(node->Modules.Flink, LDR_DATA_TABLE_ENTRY, NodeModuleLink);
+    ok( mod2 == mod || broken( (void **)mod2 == (void **)mod - 1 ), "Got unexpected mod2 %p, expected %p.\n",
+            mod2, mod );
+    if (mod2 != mod)
+    {
+        win_skip( "Old LDR_DATA_TABLE_ENTRY structure, skipping tests.\n" );
+        return;
+    }
+    ok( node->Modules.Flink->Flink == &node->Modules, "Expected one element in list.\n" );
+
+    ok( !node->IncomingDependencies.Tail, "Expected empty incoming dependencies list.\n" );
+
+    /* node->Dependencies.Tail is NULL on Windows 10 1507-1607 32 bit test, maybe due to broken structure layout. */
+    ok( !!node->Dependencies.Tail || broken( sizeof(void *) == 4 && !node->Dependencies.Tail),
+            "Expected nonempty dependencies list.\n" );
+    if (!node->Dependencies.Tail)
+    {
+        win_skip( "Empty dependencies list.\n" );
+        return;
+    }
+    ok( node->LoadCount == -1, "Got unexpected LoadCount %d.\n", node->LoadCount );
+
+    prev_node = NULL;
+    se = node->Dependencies.Tail;
+    for (i = 0; i < ARRAY_SIZE(expected_exe_dependencies); ++i)
+    {
+        winetest_push_context( "Dep %u (%s)", i, debugstr_w(expected_exe_dependencies[i].dllname) );
+
+        se = se->Next;
+
+        ok( !!se, "Got NULL list element.\n" );
+        dep = CONTAINING_RECORD(se, LDR_DEPENDENCY, dependency_to_entry);
+        ok( dep->dependency_from == node, "Got unexpected dependency_from %p.\n", dep->dependency_from );
+        ok( !!dep->dependency_to, "Got null dependency_to.\n" );
+        dep_node = dep->dependency_to;
+        ok( !!dep_node, "Got NULL dep_node.\n" );
+
+        if (dep_node == prev_node && expected_exe_dependencies[i].optional)
+        {
+            win_skip( "Module is not directly referenced.\n" );
+            winetest_pop_context();
+            prev_node = dep_node;
+            continue;
+        }
+
+        mod2 = CONTAINING_RECORD(dep_node->Modules.Flink, LDR_DATA_TABLE_ENTRY, NodeModuleLink);
+        ok( !lstrcmpW( mod2->BaseDllName.Buffer, expected_exe_dependencies[i].dllname ),
+                "Got unexpected module %s.\n", debugstr_w(mod2->BaseDllName.Buffer));
+
+        se2 = dep_node->IncomingDependencies.Tail;
+        ok( !!se2, "Got empty incoming dependencies list.\n" );
+        do
+        {
+            se2 = se2->Next;
+            dep2 = CONTAINING_RECORD(se2, LDR_DEPENDENCY, dependency_from_entry);
+        }
+        while (dep2 != dep && se2 != dep_node->IncomingDependencies.Tail);
+        ok( dep2 == dep, "Dependency not found in incoming deps list.\n" );
+
+        ok( dep_node->LoadCount > 0 || broken(!dep_node->LoadCount) /* Win8 */,
+                "Got unexpected LoadCount %d.\n", dep_node->LoadCount );
+
+        winetest_pop_context();
+        prev_node = dep_node;
+    }
+    ok( se == node->Dependencies.Tail, "Expected end of the list.\n" );
+}
+
 START_TEST(module)
 {
     WCHAR filenameW[MAX_PATH];
@@ -1363,4 +1465,5 @@ START_TEST(module)
     test_SetDefaultDllDirectories();
     test_LdrGetDllHandleEx();
     test_LdrGetDllFullName();
+    test_ddag_node();
 }
diff --git a/include/winternl.h b/include/winternl.h
index 097dea4601a..e53914b600f 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -3260,6 +3260,14 @@ typedef struct _LDRP_CSLIST
     SINGLE_LIST_ENTRY *Tail;
 } LDRP_CSLIST, *PLDRP_CSLIST;
 
+typedef struct _LDR_DEPENDENCY
+{
+    LDRP_CSLIST dependency_to_entry;
+    struct _LDR_DDAG_NODE *dependency_to;
+    LDRP_CSLIST dependency_from_entry;
+    struct _LDR_DDAG_NODE *dependency_from;
+} LDR_DEPENDENCY, *PLDR_DEPENDENCY;
+
 typedef enum _LDR_DDAG_STATE
 {
     LdrModulesMerged = -5,
@@ -3283,7 +3291,7 @@ typedef struct _LDR_DDAG_NODE
 {
     LIST_ENTRY Modules;
     LDR_SERVICE_TAG_RECORD *ServiceTagList;
-    ULONG LoadCount;
+    LONG LoadCount;
     ULONG LoadWhileUnloadingCount;
     ULONG LowestLink;
     LDRP_CSLIST Dependencies;




More information about the wine-cvs mailing list