Chromium Code Reviews| Index: chrome/browser/conflicts/module_event_sink_impl_win.cc |
| diff --git a/chrome/browser/conflicts/module_event_sink_impl_win.cc b/chrome/browser/conflicts/module_event_sink_impl_win.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..f02e0cf44e968ead0eaafcd026a2be39860d4865 |
| --- /dev/null |
| +++ b/chrome/browser/conflicts/module_event_sink_impl_win.cc |
| @@ -0,0 +1,97 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/conflicts/module_event_sink_impl_win.h" |
| + |
| +#include <windows.h> |
| +#include <psapi.h> |
| + |
| +#include "base/bind.h" |
| +#include "base/callback.h" |
| +#include "base/files/file_path.h" |
| +#include "base/macros.h" |
| +#include "base/memory/ptr_util.h" |
| +#include "base/strings/string_piece.h" |
| +#include "chrome/browser/conflicts/module_database_win.h" |
| +#include "chrome/common/conflicts/module_watcher_win.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "mojo/public/cpp/bindings/strong_binding.h" |
| + |
| +ModuleEventSinkImpl::ModuleEventSinkImpl(base::ProcessHandle process, |
| + content::ProcessType process_type, |
| + ModuleDatabase* module_database) |
| + : process_(process), module_database_(module_database), process_id_(0) { |
| + process_id_ = ::GetProcessId(process_); |
| + module_database->OnProcessStarted(process_id_, process_type); |
| +} |
| + |
| +ModuleEventSinkImpl::~ModuleEventSinkImpl() = default; |
| + |
| +// static |
| +void ModuleEventSinkImpl::Create(base::ProcessHandle process, |
| + content::ProcessType process_type, |
| + ModuleDatabase* module_database, |
| + mojom::ModuleEventSinkRequest request) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + auto module_event_sink_impl = base::MakeUnique<ModuleEventSinkImpl>( |
| + process, process_type, module_database); |
| + base::Closure error_handler = base::Bind(&ModuleDatabase::OnProcessEnded, |
| + base::Unretained(module_database), |
| + module_event_sink_impl->process_id_); |
| + auto binding = mojo::MakeStrongBinding(std::move(module_event_sink_impl), |
| + std::move(request)); |
| + binding->set_connection_error_handler(error_handler); |
| +} |
| + |
| +void ModuleEventSinkImpl::OnModuleEvent(mojom::ModuleEventType event_type, |
| + uint64_t load_address) { |
| + // Mojo takes care of validating |event_type|, so only |load_address| needs to |
| + // be checked. Load addresses must be aligned with the allocation granularity |
| + // which is at least 64KB on any supported Windows OS. |
| + if (load_address == 0 || load_address % (64 * 1024) != 0) |
| + return; |
| + |
| + switch (event_type) { |
| + case mojom::ModuleEventType::MODULE_ALREADY_LOADED: |
| + case mojom::ModuleEventType::MODULE_LOADED: |
| + return OnModuleLoad(event_type, load_address); |
| + |
| + case mojom::ModuleEventType::MODULE_UNLOADED: |
| + return OnModuleUnload(load_address); |
| + } |
| +} |
| + |
| +void ModuleEventSinkImpl::OnModuleLoad(mojom::ModuleEventType event_type, |
| + uint64_t load_address) { |
| + DCHECK(event_type == mojom::ModuleEventType::MODULE_ALREADY_LOADED || |
| + event_type == mojom::ModuleEventType::MODULE_LOADED); |
| + |
| + // Convert the |load_address| to a module handle. |
| + HMODULE module = |
| + reinterpret_cast<HMODULE>(static_cast<uintptr_t>(load_address)); |
| + |
| + // Get the module path. |
| + wchar_t temp_path[MAX_PATH]; |
| + temp_path[0] = 0; |
| + if (!::GetModuleFileNameEx(process_, module, temp_path, arraysize(temp_path))) |
|
grt (UTC plus 2)
2016/12/20 21:09:53
MSDN says this truncates the path if the buffer is
chrisha
2016/12/21 20:15:00
Done.
|
| + return; |
| + |
| + // Get the module information. |
| + MODULEINFO info = {}; |
| + size_t length = GetModuleInformation(process_, module, &info, sizeof(info)); |
|
grt (UTC plus 2)
2016/12/20 21:09:53
DWORD |length| should be captured from GetModuleFi
chrisha
2016/12/21 20:15:00
Err... oops.
Done.
|
| + if (length == 0) |
| + return; |
| + |
| + // Convert this all to a ModuleEvent and forward this on to the module |
| + // database. |
| + ModuleWatcher::ModuleEvent event( |
| + event_type, base::FilePath(base::StringPiece16(temp_path, length)), |
| + module, info.SizeOfImage); |
| + module_database_->OnModuleEvent(process_id_, event); |
| +} |
| + |
| +void ModuleEventSinkImpl::OnModuleUnload(uint64_t load_address) { |
| + module_database_->OnModuleUnload(process_id_, |
| + static_cast<uintptr_t>(load_address)); |
| +} |