| OLD | NEW | 
|    1 // Copyright 2016 The Chromium Authors. All rights reserved. |    1 // Copyright 2016 The Chromium Authors. All rights reserved. | 
|    2 // Use of this source code is governed by a BSD-style license that can be |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 #include "chrome/common/conflicts/module_watcher_win.h" |    5 #include "chrome/common/conflicts/module_watcher_win.h" | 
|    6  |    6  | 
|    7 #include <windows.h> |    7 #include <windows.h> | 
|    8 #include <tlhelp32.h> |    8 #include <tlhelp32.h> | 
|    9 #include <winternl.h>  // For UNICODE_STRING. |    9 #include <winternl.h>  // For UNICODE_STRING. | 
|   10  |   10  | 
|   11 #include <string> |   11 #include <string> | 
|   12 #include <utility> |  | 
|   13  |   12  | 
|   14 #include "base/lazy_instance.h" |   13 #include "base/lazy_instance.h" | 
|   15 #include "base/memory/ptr_util.h" |   14 #include "base/memory/ptr_util.h" | 
|   16 #include "base/strings/string_piece.h" |  | 
|   17 #include "base/strings/utf_string_conversions.h" |   15 #include "base/strings/utf_string_conversions.h" | 
|   18 #include "base/synchronization/lock.h" |   16 #include "base/synchronization/lock.h" | 
|   19 #include "base/win/scoped_handle.h" |   17 #include "base/win/scoped_handle.h" | 
|   20  |   18  | 
|   21 // These structures and functions are documented in MSDN, see |   19 // These structures and functions are documented in MSDN, see | 
|   22 // http://msdn.microsoft.com/en-us/library/gg547638(v=vs.85).aspx |   20 // http://msdn.microsoft.com/en-us/library/gg547638(v=vs.85).aspx | 
|   23 // there are however no headers or import libraries available in the |   21 // there are however no headers or import libraries available in the | 
|   24 // Platform SDK. They are declared outside of the anonymous namespace to |   22 // Platform SDK. They are declared outside of the anonymous namespace to | 
|   25 // allow them to be forward declared in the header file. |   23 // allow them to be forward declared in the header file. | 
|   26 enum { |   24 enum { | 
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   91 // Global pointer to the singleton ModuleWatcher, if one exists. Under |   89 // Global pointer to the singleton ModuleWatcher, if one exists. Under | 
|   92 // |module_watcher_lock|. |   90 // |module_watcher_lock|. | 
|   93 ModuleWatcher* g_module_watcher_instance = nullptr; |   91 ModuleWatcher* g_module_watcher_instance = nullptr; | 
|   94  |   92  | 
|   95 // Names of the DLL notification registration functions. These are exported by |   93 // Names of the DLL notification registration functions. These are exported by | 
|   96 // ntdll. |   94 // ntdll. | 
|   97 constexpr wchar_t kNtDll[] = L"ntdll.dll"; |   95 constexpr wchar_t kNtDll[] = L"ntdll.dll"; | 
|   98 constexpr char kLdrRegisterDllNotification[] = "LdrRegisterDllNotification"; |   96 constexpr char kLdrRegisterDllNotification[] = "LdrRegisterDllNotification"; | 
|   99 constexpr char kLdrUnregisterDllNotification[] = "LdrUnregisterDllNotification"; |   97 constexpr char kLdrUnregisterDllNotification[] = "LdrUnregisterDllNotification"; | 
|  100  |   98  | 
|  101 // Helper function for converting a UNICODE_STRING to a FilePath. |   99 // Helper function for converting a UNICODE_STRING to a UTF8 std::string. | 
|  102 base::FilePath ToFilePath(const UNICODE_STRING* str) { |  100 std::string ToString(const UNICODE_STRING* str) { | 
|  103   return base::FilePath( |  101   std::string s; | 
|  104       base::StringPiece16(str->Buffer, str->Length / sizeof(wchar_t))); |  102   base::WideToUTF8(str->Buffer, str->Length / sizeof(wchar_t), &s); | 
 |  103   return s; | 
|  105 } |  104 } | 
|  106  |  105  | 
|  107 template <typename NotificationDataType> |  106 template <typename NotificationDataType> | 
|  108 void OnModuleEvent(mojom::ModuleEventType event_type, |  107 void OnModuleEvent(mojom::ModuleEventType event_type, | 
|  109                    const NotificationDataType& notification_data, |  108                    const NotificationDataType& notification_data, | 
|  110                    const ModuleWatcher::OnModuleEventCallback& callback) { |  109                    const ModuleWatcher::OnModuleEventCallback& callback) { | 
|  111   ModuleWatcher::ModuleEvent event( |  110   mojom::ModuleEvent event; | 
|  112       event_type, ToFilePath(notification_data.FullDllName), |  111   event.event_type = event_type; | 
|  113       notification_data.DllBase, notification_data.SizeOfImage); |  112   event.module_path = ToString(notification_data.FullDllName); | 
 |  113   event.load_address = reinterpret_cast<uintptr_t>(notification_data.DllBase); | 
 |  114   event.size = notification_data.SizeOfImage; | 
|  114   callback.Run(event); |  115   callback.Run(event); | 
|  115 } |  116 } | 
|  116  |  117  | 
|  117 }  // namespace |  118 }  // namespace | 
|  118  |  119  | 
|  119 // static |  120 // static | 
|  120 std::unique_ptr<ModuleWatcher> ModuleWatcher::Create( |  121 std::unique_ptr<ModuleWatcher> ModuleWatcher::Create( | 
|  121     OnModuleEventCallback callback) { |  122     const OnModuleEventCallback& callback) { | 
|  122   // If a ModuleWatcher already exists then bail out. |  123   // If a ModuleWatcher already exists then bail out. | 
|  123   base::AutoLock lock(g_module_watcher_lock.Get()); |  124   base::AutoLock lock(g_module_watcher_lock.Get()); | 
|  124   if (g_module_watcher_instance) |  125   if (g_module_watcher_instance) | 
|  125     return nullptr; |  126     return nullptr; | 
|  126  |  127  | 
|  127   // This thread acquired the right to create a ModuleWatcher, so do so. |  128   // This thread acquired the right to create a ModuleWatcher, so do so. | 
|  128   g_module_watcher_instance = new ModuleWatcher(std::move(callback)); |  129   g_module_watcher_instance = new ModuleWatcher(callback); | 
|  129   return base::WrapUnique(g_module_watcher_instance); |  130   return base::WrapUnique(g_module_watcher_instance); | 
|  130 } |  131 } | 
|  131  |  132  | 
|  132 ModuleWatcher::~ModuleWatcher() { |  133 ModuleWatcher::~ModuleWatcher() { | 
|  133   // As soon as |g_module_watcher_instance| is null any dispatched callbacks |  134   // As soon as |g_module_watcher_instance| is null any dispatched callbacks | 
|  134   // will be silently absorbed by LoaderNotificationCallback. |  135   // will be silently absorbed by LoaderNotificationCallback. | 
|  135   base::AutoLock lock(g_module_watcher_lock.Get()); |  136   base::AutoLock lock(g_module_watcher_lock.Get()); | 
|  136   DCHECK_EQ(g_module_watcher_instance, this); |  137   DCHECK_EQ(g_module_watcher_instance, this); | 
|  137   g_module_watcher_instance = nullptr; |  138   g_module_watcher_instance = nullptr; | 
|  138   UnregisterDllNotificationCallback(); |  139   UnregisterDllNotificationCallback(); | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
|  166     if (snap.IsValid()) |  167     if (snap.IsValid()) | 
|  167       break; |  168       break; | 
|  168     if (::GetLastError() != ERROR_BAD_LENGTH) |  169     if (::GetLastError() != ERROR_BAD_LENGTH) | 
|  169       return; |  170       return; | 
|  170   } |  171   } | 
|  171   if (!snap.IsValid()) |  172   if (!snap.IsValid()) | 
|  172     return; |  173     return; | 
|  173  |  174  | 
|  174   // Walk the module list. |  175   // Walk the module list. | 
|  175   MODULEENTRY32 module = {sizeof(module)}; |  176   MODULEENTRY32 module = {sizeof(module)}; | 
 |  177   std::string path; | 
|  176   for (BOOL result = ::Module32First(snap.Get(), &module); result != FALSE; |  178   for (BOOL result = ::Module32First(snap.Get(), &module); result != FALSE; | 
|  177        result = ::Module32Next(snap.Get(), &module)) { |  179        result = ::Module32Next(snap.Get(), &module)) { | 
|  178     ModuleEvent event(mojom::ModuleEventType::MODULE_ALREADY_LOADED, |  180     base::WideToUTF8(module.szExePath, ::wcslen(module.szExePath), &path); | 
|  179                       base::FilePath(module.szExePath), module.modBaseAddr, |  181     mojom::ModuleEvent event; | 
|  180                       module.modBaseSize); |  182     event.event_type = mojom::ModuleEventType::MODULE_ALREADY_LOADED; | 
 |  183     event.module_path = path; | 
 |  184     event.load_address = reinterpret_cast<uintptr_t>(module.modBaseAddr); | 
 |  185     event.size = module.modBaseSize; | 
|  181     callback_.Run(event); |  186     callback_.Run(event); | 
|  182   } |  187   } | 
|  183  |  188  | 
|  184   return; |  189   return; | 
|  185 } |  190 } | 
|  186  |  191  | 
|  187 // static |  192 // static | 
|  188 ModuleWatcher::OnModuleEventCallback ModuleWatcher::GetCallbackForContext( |  193 ModuleWatcher::OnModuleEventCallback ModuleWatcher::GetCallbackForContext( | 
|  189     void* context) { |  194     void* context) { | 
|  190   base::AutoLock lock(g_module_watcher_lock.Get()); |  195   base::AutoLock lock(g_module_watcher_lock.Get()); | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
|  213                     notification_data->Unloaded, callback); |  218                     notification_data->Unloaded, callback); | 
|  214       break; |  219       break; | 
|  215  |  220  | 
|  216     default: |  221     default: | 
|  217       // This is unexpected, but not a reason to crash. |  222       // This is unexpected, but not a reason to crash. | 
|  218       NOTREACHED() << "Unknown LDR_DLL_NOTIFICATION_REASON: " |  223       NOTREACHED() << "Unknown LDR_DLL_NOTIFICATION_REASON: " | 
|  219                    << notification_reason; |  224                    << notification_reason; | 
|  220   } |  225   } | 
|  221 } |  226 } | 
|  222  |  227  | 
|  223 ModuleWatcher::ModuleWatcher(OnModuleEventCallback callback) |  228 ModuleWatcher::ModuleWatcher(const OnModuleEventCallback& callback) | 
|  224     : callback_(std::move(callback)) { |  229     : callback_(callback) { | 
|  225   RegisterDllNotificationCallback(); |  230   RegisterDllNotificationCallback(); | 
|  226   EnumerateAlreadyLoadedModules(); |  231   EnumerateAlreadyLoadedModules(); | 
|  227 } |  232 } | 
| OLD | NEW |