From f4f39e74fae3c8b8d8fdb2f560e8a50777b6de1d Mon Sep 17 00:00:00 2001
From: Egor Tensin <Egor.Tensin@gmail.com>
Date: Sat, 20 May 2017 02:47:57 +0300
Subject: don't load the same PDB twice

---
 src/repo.cpp       | 21 +++++++++++++++++----
 src/utils/file.cpp | 26 ++++++++++++++++++++++++++
 2 files changed, 43 insertions(+), 4 deletions(-)

(limited to 'src')

diff --git a/src/repo.cpp b/src/repo.cpp
index 9a06481..02ca1db 100644
--- a/src/repo.cpp
+++ b/src/repo.cpp
@@ -6,6 +6,7 @@
 #include "pdb/all.hpp"
 
 #include <map>
+#include <sstream>
 #include <stdexcept>
 #include <string>
 #include <utility>
@@ -41,11 +42,18 @@ namespace pdb
             return it->second;
         }
 
-        std::string pdb_already_loaded(Address online_base)
+        std::string pdb_already_loaded(Address online_base, const std::string& path)
         {
             std::ostringstream oss;
-            oss << "module with online base address " << format_address
-                << " has already been loaded";
+            oss << "module with online base address " << format_address(online_base)
+                << " has already been loaded: " << path;
+            return oss.str();
+        }
+
+        std::string pdb_already_loaded(const std::string& path)
+        {
+            std::ostringstream oss;
+            oss << "module has already been loaded: " << path;
             return oss.str();
         }
     }
@@ -53,13 +61,18 @@ namespace pdb
     Address Repo::add_pdb(Address online_base, const std::string& path)
     {
         if (online_modules.find(online_base) != online_modules.cend())
-            throw std::runtime_error{pdb_already_loaded(online_base)};
+            throw std::runtime_error{pdb_already_loaded(online_base, path)};
+
+        auto file_id = file::query_id(path);
+        if (module_ids.find(file_id) != module_ids.cend())
+            throw std::runtime_error{pdb_already_loaded(path)};
 
         Module module{online_base, dbghelp.load_pdb(path)};
         const auto offline_base = module.get_offline_base();
 
         const auto it = online_modules.emplace(online_base, std::move(module));
         offline_modules.emplace(offline_base, it.first->second);
+        module_ids.emplace(std::move(file_id));
 
         return offline_base;
     }
diff --git a/src/utils/file.cpp b/src/utils/file.cpp
index f013d90..dba8a38 100644
--- a/src/utils/file.cpp
+++ b/src/utils/file.cpp
@@ -44,5 +44,31 @@ namespace pdb
 
             return result;
         }
+
+        ID query_id(const std::string& path)
+        {
+            const Handle handle{CreateFileA(
+                path.c_str(),
+                FILE_READ_ATTRIBUTES,
+                FILE_SHARE_READ | FILE_SHARE_WRITE,
+                NULL,
+                OPEN_EXISTING,
+                FILE_ATTRIBUTE_NORMAL,
+                NULL)};
+
+            if (handle.get() == INVALID_HANDLE_VALUE)
+                throw error::windows(GetLastError());
+
+            ID id;
+
+            if (!GetFileInformationByHandleEx(
+                    handle.get(),
+                    FileIdInfo,
+                    &id,
+                    sizeof(id)))
+                throw error::windows(GetLastError());
+
+            return id;
+        }
     }
 }
-- 
cgit v1.2.3