Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / install_verification / win / imported_module_verification.cc
blob3d5abb68375e1751e65cd8dd2b4ced4107f9534c
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/install_verification/win/imported_module_verification.h"
7 #include <Windows.h>
9 #include <algorithm>
10 #include <iterator>
11 #include <string>
12 #include <vector>
13 #include "base/logging.h"
14 #include "base/strings/string16.h"
15 #include "chrome/browser/install_verification/win/module_info.h"
17 namespace {
19 #if !defined(_WIN64)
20 // We must make sure not to include modules here that are likely to get unloaded
21 // because the scanning of the module is not done within a loader lock, so is
22 // not resilient to changes made to the modules list.
23 const wchar_t* const kModulesToScan[] = {
24 L"chrome.dll",
25 L"kernel32.dll",
26 L"user32.dll"
28 #endif // !defined(_WIN64)
30 bool AddressBeyondRange(const ModuleInfo& module, uintptr_t address) {
31 return module.base_address + module.size < address;
34 void ScanImportAddressTable(
35 HMODULE module_handle,
36 const std::set<ModuleInfo>& loaded_modules,
37 std::set<base::string16>* imported_modules) {
38 DCHECK(module_handle);
39 DCHECK(imported_modules);
41 // To find the Import Address Table address, we start from the DOS header.
42 // The module handle is actually the base address where the header is.
43 IMAGE_DOS_HEADER* dos_header =
44 reinterpret_cast<IMAGE_DOS_HEADER*>(module_handle);
45 // The e_lfanew is an offset from the DOS header to the NT header. It should
46 // never be 0.
47 DCHECK(dos_header->e_lfanew);
48 IMAGE_NT_HEADERS* nt_headers = reinterpret_cast<IMAGE_NT_HEADERS*>(
49 module_handle + dos_header->e_lfanew / sizeof(uintptr_t));
50 // For modules that have an import address table, its offset from the
51 // DOS header is stored in the second data directory's VirtualAddress.
52 if (!nt_headers->OptionalHeader.DataDirectory[1].VirtualAddress)
53 return;
54 IMAGE_IMPORT_DESCRIPTOR* image_descriptor =
55 reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR*>(module_handle +
56 nt_headers->OptionalHeader.DataDirectory[1].VirtualAddress /
57 sizeof(uintptr_t));
58 // The list of Import Address Tables ends with an empty {0} descriptor.
59 while (image_descriptor->Characteristics) {
60 uintptr_t* address = reinterpret_cast<uintptr_t*>(
61 module_handle + image_descriptor->FirstThunk / sizeof(uintptr_t));
62 // Each section of the Import Address Table ends with a NULL funcpointer.
63 while (*address) {
64 std::set<ModuleInfo>::const_iterator lower_bound = std::lower_bound(
65 loaded_modules.begin(), loaded_modules.end(), *address,
66 AddressBeyondRange);
67 if (lower_bound != loaded_modules.end() &&
68 lower_bound->ContainsAddress(*address)) {
69 imported_modules->insert(lower_bound->name);
71 ++address;
73 image_descriptor += sizeof(image_descriptor) / sizeof(uintptr_t);
77 } // namespace
79 void VerifyImportedModules(const std::set<ModuleInfo>& loaded_modules,
80 const ModuleIDs& module_ids,
81 ModuleVerificationDelegate* delegate){
82 // Note that module verification is temporarily disabled for 64-bit builds.
83 // See crbug.com/316274.
84 #if !defined(_WIN64)
85 std::set<base::string16> imported_module_names;
86 for (size_t i = 0; i < arraysize(kModulesToScan); ++i) {
87 HMODULE module_handle = ::GetModuleHandle(kModulesToScan[i]);
88 if (module_handle) {
89 ScanImportAddressTable(module_handle,
90 loaded_modules,
91 &imported_module_names);
95 std::vector<std::string> module_name_digests;
96 std::transform(imported_module_names.begin(),
97 imported_module_names.end(),
98 std::back_inserter(module_name_digests),
99 &CalculateModuleNameDigest);
100 ReportModuleMatches(module_name_digests, module_ids, delegate);
101 #endif