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)); | 
| +} |