From 0456a4dc50ad7d2046776dc259a699c4abdf1635 Mon Sep 17 00:00:00 2001
From: Black <yitianbuji@gmail.com>
Date: Sat, 21 Dec 2013 09:45:17 +0800
Subject: new program ntldd for dll dependences

---
 configure                  |  1 +
 configure.ac               |  1 +
 programs/ntldd/Makefile.in |  8 ++++
 programs/ntldd/ntldd.cpp   | 96 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 106 insertions(+)
 create mode 100644 programs/ntldd/Makefile.in
 create mode 100644 programs/ntldd/ntldd.cpp

diff --git a/configure b/configure
index b18d271..a036dc1 100755
--- a/configure
+++ b/configure
@@ -17370,6 +17370,7 @@ wine_fn_config_program cabarc enable_cabarc install
 wine_fn_config_program cacls enable_cacls install
 wine_fn_config_program clock enable_clock install,po
 wine_fn_config_program cmd enable_cmd install,po
+wine_fn_config_program ntldd enable_ntldd install,installbin
 wine_fn_config_test programs/cmd/tests cmd.exe_test
 wine_fn_config_program conhost enable_conhost install
 wine_fn_config_program control enable_control install
diff --git a/configure.ac b/configure.ac
index d80a2bc..c8b5b4f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3350,6 +3350,7 @@ WINE_CONFIG_PROGRAM(netsh,,[install])
 WINE_CONFIG_PROGRAM(netstat,,[install,po])
 WINE_CONFIG_PROGRAM(ngen,,[install])
 WINE_CONFIG_PROGRAM(notepad,,[install,installbin,manpage,po])
+WINE_CONFIG_PROGRAM(ntldd,,[install,installbin])
 WINE_CONFIG_PROGRAM(oleview,,[install,po])
 WINE_CONFIG_PROGRAM(ping,,[install])
 WINE_CONFIG_PROGRAM(plugplay,,[install])
diff --git a/programs/ntldd/Makefile.in b/programs/ntldd/Makefile.in
new file mode 100644
index 0000000..5e986c3
--- /dev/null
+++ b/programs/ntldd/Makefile.in
@@ -0,0 +1,8 @@
+MODULE    = ntldd.exe
+APPMODE   = -mconsole
+IMPORTS   = stdc++ user32 
+
+C_SRCS = \
+	ntldd.cpp
+
+@MAKE_PROG_RULES@
diff --git a/programs/ntldd/ntldd.cpp b/programs/ntldd/ntldd.cpp
new file mode 100644
index 0000000..a17990b
--- /dev/null
+++ b/programs/ntldd/ntldd.cpp
@@ -0,0 +1,96 @@
+#include <stdio.h>
+#include <windows.h>
+#include <iostream>
+
+#include <vector>
+#include <map>
+#include <string>
+#define _MAX_PATH 256
+
+typedef std::map<std::string, std::string> DepMapType;
+
+//------------------------------------------------------------------------------
+
+const DepMapType getDependencies(const HMODULE hMod)
+{
+    DepMapType depsMap;
+
+    IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)hMod;
+    IMAGE_OPTIONAL_HEADER * pOptHeader = (IMAGE_OPTIONAL_HEADER*)((BYTE*)hMod + pDosHeader->e_lfanew +24);
+    IMAGE_IMPORT_DESCRIPTOR* pImportDesc = (IMAGE_IMPORT_DESCRIPTOR*) ((BYTE*)hMod + pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
+
+    while ( pImportDesc->FirstThunk )
+    {
+        char* dllName = (char*) ((BYTE*)hMod + pImportDesc->Name);
+
+        std::string dllPath = "";
+        HMODULE hModDep = ::LoadLibraryEx(dllName, NULL, DONT_RESOLVE_DLL_REFERENCES);
+        if(hModDep != 0)
+        {
+            LPTSTR  strDLLPath = new TCHAR[_MAX_PATH];
+            ::GetModuleFileName(hModDep, strDLLPath, _MAX_PATH);
+            dllPath = std::string(strDLLPath);
+            delete strDLLPath;
+        }
+        FreeLibrary(hModDep);
+        depsMap[std::string(dllName)] = dllPath;
+
+        pImportDesc++;
+    }
+
+    return depsMap;
+}
+
+//------------------------------------------------------------------------------
+
+int printDependencies(const std::string libPath)
+{
+    HMODULE hMod = ::LoadLibraryEx(libPath.c_str(), NULL, DONT_RESOLVE_DLL_REFERENCES);
+    if(hMod == 0)
+    {
+        // Retrieves the last error message.
+        DWORD   lastError = GetLastError();
+        char    buffer[1024];
+        FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, lastError, 0, buffer, 1024, 0 );
+        std::cerr << "\t" << buffer << std::endl;
+        return -1;
+    }
+    const DepMapType& depMap = getDependencies(hMod);
+    FreeLibrary(hMod);
+    DepMapType::const_iterator iter;
+    for(iter = depMap.begin(); iter != depMap.end(); ++iter)
+    {
+        std::cout << "\t" << iter->first << " => " << iter->second << std::endl;
+    }
+
+    return 0;
+}
+
+//------------------------------------------------------------------------------
+
+int printUsage()
+{
+    std::cout << "ldd for Windows, Version 1.0" << std::endl;
+    std::cout << "usage:\n ldd FILE..." << std::endl;
+    return -1;
+}
+
+//------------------------------------------------------------------------------
+
+int main(int argc, char** argv)
+{
+    if(argc <= 1)
+    {
+        return printUsage();
+    }
+    int res = 0;
+    for(int i = 1; i < argc; ++i)
+    {
+        std::cout << argv[i] << std::endl;
+        res = printDependencies(argv[i]);
+    }
+    return res;
+}
+
+//------------------------------------------------------------------------------
+
-- 
1.8.3.2

