OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/browser/enumerate_modules_model_win.h" | 5 #include "chrome/browser/enumerate_modules_model_win.h" |
6 | 6 |
7 #include <Tlhelp32.h> | 7 #include <Tlhelp32.h> |
8 #include <wintrust.h> | 8 #include <wintrust.h> |
9 | 9 |
10 #include "app/l10n_util.h" | 10 #include "app/l10n_util.h" |
(...skipping 19 matching lines...) Expand all Loading... |
30 #include "grit/generated_resources.h" | 30 #include "grit/generated_resources.h" |
31 | 31 |
32 // The period of time (in milliseconds) to wait until checking to see if any | 32 // The period of time (in milliseconds) to wait until checking to see if any |
33 // incompatible modules exist. | 33 // incompatible modules exist. |
34 static const int kModuleCheckDelayMs = 60 * 1000; | 34 static const int kModuleCheckDelayMs = 60 * 1000; |
35 | 35 |
36 // The path to the Shell Extension key in the Windows registry. | 36 // The path to the Shell Extension key in the Windows registry. |
37 static const wchar_t kRegPath[] = | 37 static const wchar_t kRegPath[] = |
38 L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"; | 38 L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"; |
39 | 39 |
40 // A sort method that sorts by ModuleType ordinal (loaded module at the top), | 40 // A sort method that sorts by bad modules first, then by full name (including |
41 // then by full name (including path). | 41 // path). |
42 static bool ModuleSort(const ModuleEnumerator::Module& a, | 42 static bool ModuleSort(const ModuleEnumerator::Module& a, |
43 const ModuleEnumerator::Module& b) { | 43 const ModuleEnumerator::Module& b) { |
44 if (a.type != b.type) | 44 if (a.status != b.status) |
45 return a.type < b.type; | 45 return a.status > b.status; |
| 46 |
46 if (a.location == b.location) | 47 if (a.location == b.location) |
47 return a.name < b.name; | 48 return a.name < b.name; |
48 | 49 |
49 return a.location < b.location; | 50 return a.location < b.location; |
50 } | 51 } |
51 | 52 |
52 namespace { | 53 namespace { |
53 | 54 |
54 // Used to protect the LoadedModuleVector which is accessed | 55 // Used to protect the LoadedModuleVector which is accessed |
55 // from both the UI thread and the FILE thread. | 56 // from both the UI thread and the FILE thread. |
56 Lock* lock = NULL; | 57 Lock* lock = NULL; |
57 | 58 |
58 // A struct to help de-duping modules before adding them to the enumerated | 59 // A struct to help de-duping modules before adding them to the enumerated |
59 // modules vector. | 60 // modules vector. |
60 struct FindModule { | 61 struct FindModule { |
61 public: | 62 public: |
62 explicit FindModule(const ModuleEnumerator::Module& x) | 63 explicit FindModule(const ModuleEnumerator::Module& x) |
63 : module(x) {} | 64 : module(x) {} |
64 // Coverity issue 13896. | |
65 bool operator()(const ModuleEnumerator::Module& module_in) const { | 65 bool operator()(const ModuleEnumerator::Module& module_in) const { |
66 return (module.type == module_in.type) && | 66 return (module.location == module_in.location) && |
67 (module.location == module_in.location) && | |
68 (module.name == module_in.name); | 67 (module.name == module_in.name); |
69 } | 68 } |
70 | 69 |
71 const ModuleEnumerator::Module& module; | 70 const ModuleEnumerator::Module& module; |
72 }; | 71 }; |
73 | 72 |
74 } | 73 } |
75 | 74 |
76 // The browser process module blacklist. This lists all modules that are known | 75 // The browser process module blacklist. This lists all modules that are known |
77 // to cause compatibility issues within the browser process. When adding to this | 76 // to cause compatibility issues within the browser process. When adding to this |
78 // list, make sure that all paths are lower-case, in long pathname form, end | 77 // list, make sure that all paths are lower-case, in long pathname form, end |
79 // with a slash and use environments variables (or just look at one of the | 78 // with a slash and use environments variables (or just look at one of the |
80 // comments below and keep it consistent with that). When adding an entry with | 79 // comments below and keep it consistent with that). When adding an entry with |
81 // an environment variable not currently used in the list below, make sure to | 80 // an environment variable not currently used in the list below, make sure to |
82 // update the list in PreparePathMappings. Filename, Description/Signer, and | 81 // update the list in PreparePathMappings. Filename, Description/Signer, and |
83 // Location must be entered as hashes (see GenerateHash). Filename is mandatory. | 82 // Location must be entered as hashes (see GenerateHash). Filename is mandatory. |
84 // Entries without any Description, Signer info, or Location will never be | 83 // Entries without any Description, Signer info, or Location will never be |
85 // marked as confirmed bad (only as suspicious). | 84 // marked as confirmed bad (only as suspicious). |
86 const ModuleEnumerator::BlacklistEntry ModuleEnumerator::kModuleBlacklist[] = { | 85 const ModuleEnumerator::BlacklistEntry ModuleEnumerator::kModuleBlacklist[] = { |
87 // NOTE: Please keep this list sorted by dll name, then location. | 86 // NOTE: Please keep this list sorted by dll name, then location. |
88 | 87 |
89 // foldersizecolumn.dll. | 88 // foldersizecolumn.dll. |
90 {"5ec91bd7", "", "", "", "", NONE}, | 89 {"5ec91bd7", "", "", "", "", NONE}, |
91 | 90 |
92 // idmmbc.dll, "%programfiles%\\internet download manager\\", "Tonec Inc.". | 91 // idmmbc.dll, "%programfiles%\\internet download manager\\", "Tonec Inc.". |
93 // See: http://crbug.com/26892/. | 92 // See: http://crbug.com/26892/. |
94 {"b8dce5c3", "94541bf5", "d33ad640", "", "", NONE}, | 93 {"b8dce5c3", "94541bf5", "d33ad640", "", "6.03", UPDATE}, |
95 | 94 |
96 // imon.dll. See: http://crbug.com/21715. | 95 // imon.dll. See: http://crbug.com/21715. |
97 {"8f42f22e", "", "", "", "", NONE}, | 96 {"8f42f22e", "", "", "", "", NONE}, |
98 | 97 |
99 // is3lsp.dll. See: http://crbug.com/26892. | 98 // is3lsp.dll. See: http://crbug.com/26892. |
100 {"7ffbdce9", "", "", "", "", NONE}, | 99 {"7ffbdce9", "", "", "", "", NONE}, |
101 | 100 |
102 // nvlsp.dll. See: http://crbug.com/22083. | 101 // nvlsp.dll. See: http://crbug.com/22083. |
103 {"37f907e2", "", "", "", "", NONE}, | 102 {"37f907e2", "", "", "", "", NONE}, |
104 | 103 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 Version::GetVersionFromString(blacklisted.version_from)); | 186 Version::GetVersionFromString(blacklisted.version_from)); |
188 scoped_ptr<Version> version_max( | 187 scoped_ptr<Version> version_max( |
189 Version::GetVersionFromString(blacklisted.version_to)); | 188 Version::GetVersionFromString(blacklisted.version_to)); |
190 bool version_ok = !version_min.get() && !version_max.get(); | 189 bool version_ok = !version_min.get() && !version_max.get(); |
191 if (!version_ok) { | 190 if (!version_ok) { |
192 bool too_low = version_min.get() && | 191 bool too_low = version_min.get() && |
193 (!module_version.get() || | 192 (!module_version.get() || |
194 module_version->CompareTo(*version_min.get()) < 0); | 193 module_version->CompareTo(*version_min.get()) < 0); |
195 bool too_high = version_max.get() && | 194 bool too_high = version_max.get() && |
196 (!module_version.get() || | 195 (!module_version.get() || |
197 module_version->CompareTo(*version_max.get()) > 0); | 196 module_version->CompareTo(*version_max.get()) >= 0); |
198 version_ok = !too_low && !too_high; | 197 version_ok = !too_low && !too_high; |
199 } | 198 } |
200 | 199 |
201 if (version_ok) { | 200 if (version_ok) { |
202 // At this point, the names match and there is no version specified | 201 // At this point, the names match and there is no version specified |
203 // or the versions also match. | 202 // or the versions also match. |
204 | 203 |
205 std::string desc_or_signer(blacklisted.desc_or_signer); | 204 std::string desc_or_signer(blacklisted.desc_or_signer); |
206 std::string signer_hash, description_hash; | 205 std::string signer_hash, description_hash; |
207 GenerateHash(WideToUTF8(module.digital_signer), &signer_hash); | 206 GenerateHash(WideToUTF8(module.digital_signer), &signer_hash); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 | 243 |
245 void ModuleEnumerator::ScanOnFileThread() { | 244 void ModuleEnumerator::ScanOnFileThread() { |
246 base::TimeTicks start_time = base::TimeTicks::Now(); | 245 base::TimeTicks start_time = base::TimeTicks::Now(); |
247 | 246 |
248 enumerated_modules_->clear(); | 247 enumerated_modules_->clear(); |
249 | 248 |
250 // Make sure the path mapping vector is setup so we can collapse paths. | 249 // Make sure the path mapping vector is setup so we can collapse paths. |
251 PreparePathMappings(); | 250 PreparePathMappings(); |
252 | 251 |
253 base::TimeTicks checkpoint = base::TimeTicks::Now(); | 252 base::TimeTicks checkpoint = base::TimeTicks::Now(); |
| 253 |
| 254 // Enumerating loaded modules must happen first since the other types of |
| 255 // modules check for duplication against the loaded modules. |
254 EnumerateLoadedModules(); | 256 EnumerateLoadedModules(); |
255 HISTOGRAM_TIMES("Conflicts.EnumerateLoadedModules", | 257 HISTOGRAM_TIMES("Conflicts.EnumerateLoadedModules", |
256 base::TimeTicks::Now() - checkpoint); | 258 base::TimeTicks::Now() - checkpoint); |
257 | 259 |
258 checkpoint = base::TimeTicks::Now(); | 260 checkpoint = base::TimeTicks::Now(); |
259 EnumerateShellExtensions(); | 261 EnumerateShellExtensions(); |
260 HISTOGRAM_TIMES("Conflicts.EnumerateShellExtensions", | 262 HISTOGRAM_TIMES("Conflicts.EnumerateShellExtensions", |
261 base::TimeTicks::Now() - checkpoint); | 263 base::TimeTicks::Now() - checkpoint); |
262 | 264 |
263 checkpoint = base::TimeTicks::Now(); | 265 checkpoint = base::TimeTicks::Now(); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 void ModuleEnumerator::AddToListWithoutDuplicating(const Module& module) { | 398 void ModuleEnumerator::AddToListWithoutDuplicating(const Module& module) { |
397 DCHECK(module.normalized); | 399 DCHECK(module.normalized); |
398 // These are registered modules, not loaded modules so the same module | 400 // These are registered modules, not loaded modules so the same module |
399 // can be registered multiple times, often dozens of times. There is no need | 401 // can be registered multiple times, often dozens of times. There is no need |
400 // to list each registration, so we just increment the count for each module | 402 // to list each registration, so we just increment the count for each module |
401 // that is counted multiple times. | 403 // that is counted multiple times. |
402 ModulesVector::iterator iter; | 404 ModulesVector::iterator iter; |
403 iter = std::find_if(enumerated_modules_->begin(), | 405 iter = std::find_if(enumerated_modules_->begin(), |
404 enumerated_modules_->end(), | 406 enumerated_modules_->end(), |
405 FindModule(module)); | 407 FindModule(module)); |
406 if (iter != enumerated_modules_->end()) | 408 if (iter != enumerated_modules_->end()) { |
407 iter->duplicate_count++; | 409 iter->duplicate_count++; |
408 else | 410 iter->type = static_cast<ModuleType>(iter->type | module.type); |
| 411 } else { |
409 enumerated_modules_->push_back(module); | 412 enumerated_modules_->push_back(module); |
| 413 } |
410 } | 414 } |
411 | 415 |
412 void ModuleEnumerator::PreparePathMappings() { | 416 void ModuleEnumerator::PreparePathMappings() { |
413 path_mapping_.clear(); | 417 path_mapping_.clear(); |
414 | 418 |
415 scoped_ptr<base::Environment> environment(base::Environment::Create()); | 419 scoped_ptr<base::Environment> environment(base::Environment::Create()); |
416 std::vector<string16> env_vars; | 420 std::vector<string16> env_vars; |
417 env_vars.push_back(L"LOCALAPPDATA"); | 421 env_vars.push_back(L"LOCALAPPDATA"); |
418 env_vars.push_back(L"ProgramFiles"); | 422 env_vars.push_back(L"ProgramFiles"); |
419 env_vars.push_back(L"USERPROFILE"); | 423 env_vars.push_back(L"USERPROFILE"); |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 return NULL; | 610 return NULL; |
607 } | 611 } |
608 | 612 |
609 ListValue* list = new ListValue(); | 613 ListValue* list = new ListValue(); |
610 | 614 |
611 for (ModuleEnumerator::ModulesVector::const_iterator module = | 615 for (ModuleEnumerator::ModulesVector::const_iterator module = |
612 enumerated_modules_.begin(); | 616 enumerated_modules_.begin(); |
613 module != enumerated_modules_.end(); ++module) { | 617 module != enumerated_modules_.end(); ++module) { |
614 DictionaryValue* data = new DictionaryValue(); | 618 DictionaryValue* data = new DictionaryValue(); |
615 data->SetInteger("type", module->type); | 619 data->SetInteger("type", module->type); |
616 switch (module->type) { | 620 string16 type_string; |
617 case ModuleEnumerator::SHELL_EXTENSION: | 621 if ((module->type & ModuleEnumerator::LOADED_MODULE) == 0) { |
618 data->SetString("type_description", ASCIIToWide("Shell Extension")); | 622 // Module is not loaded, denote type of module. |
619 break; | 623 if (module->type & ModuleEnumerator::SHELL_EXTENSION) |
620 case ModuleEnumerator::WINSOCK_MODULE_REGISTRATION: | 624 type_string = ASCIIToWide("Shell Extension"); |
621 data->SetString("type_description", ASCIIToWide("Winsock")); | 625 if (module->type & ModuleEnumerator::WINSOCK_MODULE_REGISTRATION) { |
622 break; | 626 if (!type_string.empty()) |
623 default: | 627 type_string += ASCIIToWide(", "); |
624 data->SetString("type_description", ASCIIToWide("")); | 628 type_string += ASCIIToWide("Winsock"); |
625 break; | 629 } |
| 630 // Must be one of the above type. |
| 631 DCHECK(!type_string.empty()); |
| 632 type_string += ASCIIToWide(" -- "); |
| 633 type_string += l10n_util::GetStringUTF16(IDS_CONFLICTS_NOT_LOADED_YET); |
626 } | 634 } |
| 635 data->SetString("type_description", type_string); |
627 data->SetInteger("status", module->status); | 636 data->SetInteger("status", module->status); |
628 data->SetString("location", module->location); | 637 data->SetString("location", module->location); |
629 data->SetString("name", module->name); | 638 data->SetString("name", module->name); |
630 data->SetString("product_name", module->product_name); | 639 data->SetString("product_name", module->product_name); |
631 data->SetString("description", module->description); | 640 data->SetString("description", module->description); |
632 data->SetString("version", module->version.empty() ? ASCIIToWide("") : | 641 data->SetString("version", module->version); |
633 l10n_util::GetStringF(IDS_CONFLICTS_CHECK_VERSION_STRING, | |
634 module->version)); | |
635 data->SetString("digital_signer", module->digital_signer); | 642 data->SetString("digital_signer", module->digital_signer); |
636 | 643 |
637 // Figure out the possible resolution help string. | 644 // Figure out the possible resolution help string. |
638 string16 actions; | 645 string16 actions; |
639 string16 separator = ASCIIToWide(" ") + l10n_util::GetStringUTF16( | 646 string16 separator = ASCIIToWide(" ") + l10n_util::GetStringUTF16( |
640 IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_SEPERATOR) + | 647 IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_SEPERATOR) + |
641 ASCIIToWide(" "); | 648 ASCIIToWide(" "); |
642 | 649 |
643 if (module->recommended_action & ModuleEnumerator::NONE) { | 650 if (module->recommended_action & ModuleEnumerator::NONE) { |
644 actions = l10n_util::GetStringUTF16( | 651 actions = l10n_util::GetStringUTF16( |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 GenerateHash(WideToUTF8(module.name), &filename); | 745 GenerateHash(WideToUTF8(module.name), &filename); |
739 GenerateHash(WideToUTF8(module.location), &location); | 746 GenerateHash(WideToUTF8(module.location), &location); |
740 GenerateHash(WideToUTF8(module.description), &description); | 747 GenerateHash(WideToUTF8(module.description), &description); |
741 GenerateHash(WideToUTF8(module.digital_signer), &signer); | 748 GenerateHash(WideToUTF8(module.digital_signer), &signer); |
742 | 749 |
743 string16 url = l10n_util::GetStringF(IDS_HELP_CENTER_VIEW_CONFLICTS, | 750 string16 url = l10n_util::GetStringF(IDS_HELP_CENTER_VIEW_CONFLICTS, |
744 ASCIIToWide(filename), ASCIIToWide(location), | 751 ASCIIToWide(filename), ASCIIToWide(location), |
745 ASCIIToWide(description), ASCIIToWide(signer)); | 752 ASCIIToWide(description), ASCIIToWide(signer)); |
746 return GURL(WideToUTF8(url)); | 753 return GURL(WideToUTF8(url)); |
747 } | 754 } |
OLD | NEW |