Chromium Code Reviews| 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" |
| 11 #include "app/win_util.h" | 11 #include "app/win_util.h" |
| 12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
| 13 #include "base/environment.h" | 13 #include "base/environment.h" |
| 14 #include "base/file_path.h" | 14 #include "base/file_path.h" |
| 15 #include "base/file_version_info_win.h" | 15 #include "base/file_version_info_win.h" |
| 16 #include "base/scoped_handle.h" | 16 #include "base/scoped_handle.h" |
| 17 #include "base/sha2.h" | 17 #include "base/sha2.h" |
| 18 #include "base/string_number_conversions.h" | 18 #include "base/string_number_conversions.h" |
| 19 #include "base/string_util.h" | 19 #include "base/string_util.h" |
| 20 #include "base/utf_string_conversions.h" | 20 #include "base/utf_string_conversions.h" |
| 21 #include "base/values.h" | 21 #include "base/values.h" |
| 22 #include "base/version.h" | 22 #include "base/version.h" |
| 23 #include "base/win/registry.h" | |
| 23 #include "chrome/browser/net/service_providers_win.h" | 24 #include "chrome/browser/net/service_providers_win.h" |
| 24 #include "chrome/common/chrome_constants.h" | 25 #include "chrome/common/chrome_constants.h" |
| 25 #include "chrome/common/chrome_switches.h" | 26 #include "chrome/common/chrome_switches.h" |
| 26 #include "chrome/common/notification_service.h" | 27 #include "chrome/common/notification_service.h" |
| 27 #include "grit/generated_resources.h" | 28 #include "grit/generated_resources.h" |
| 28 | 29 |
| 29 // The period of time (in milliseconds) to wait until checking to see if any | 30 // The period of time (in milliseconds) to wait until checking to see if any |
| 30 // incompatible modules exist. | 31 // incompatible modules exist. |
| 31 static const int kModuleCheckDelayMs = 60 * 1000; | 32 static const int kModuleCheckDelayMs = 60 * 1000; |
| 32 | 33 |
| 34 // The path to the Shell Extension key in the Windows registry. | |
| 35 static const wchar_t kRegPath[] = | |
| 36 L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"; | |
| 37 | |
| 33 // A sort method that sorts by ModuleType ordinal (loaded module at the top), | 38 // A sort method that sorts by ModuleType ordinal (loaded module at the top), |
| 34 // then by full name (including path). | 39 // then by full name (including path). |
| 35 static bool ModuleSort(const ModuleEnumerator::Module& a, | 40 static bool ModuleSort(const ModuleEnumerator::Module& a, |
| 36 const ModuleEnumerator::Module& b) { | 41 const ModuleEnumerator::Module& b) { |
| 37 if (a.type != b.type) | 42 if (a.type != b.type) |
| 38 return a.type < b.type; | 43 return a.type < b.type; |
| 39 if (a.location == b.location) | 44 if (a.location == b.location) |
| 40 return a.name < b.name; | 45 return a.name < b.name; |
| 41 | 46 |
| 42 return a.location < b.location; | 47 return a.location < b.location; |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 219 BrowserThread::FILE, FROM_HERE, | 224 BrowserThread::FILE, FROM_HERE, |
| 220 NewRunnableMethod(this, &ModuleEnumerator::ScanOnFileThread)); | 225 NewRunnableMethod(this, &ModuleEnumerator::ScanOnFileThread)); |
| 221 } | 226 } |
| 222 | 227 |
| 223 void ModuleEnumerator::ScanOnFileThread() { | 228 void ModuleEnumerator::ScanOnFileThread() { |
| 224 enumerated_modules_->clear(); | 229 enumerated_modules_->clear(); |
| 225 | 230 |
| 226 // Make sure the path mapping vector is setup so we can collapse paths. | 231 // Make sure the path mapping vector is setup so we can collapse paths. |
| 227 PreparePathMappings(); | 232 PreparePathMappings(); |
| 228 | 233 |
| 234 EnumerateLoadedModules(); | |
| 235 EnumerateShellExtensions(); | |
| 236 EnumerateWinsockModule(); | |
| 237 | |
| 238 MatchAgainstBlacklist(); | |
| 239 | |
| 240 std::sort(enumerated_modules_->begin(), | |
| 241 enumerated_modules_->end(), ModuleSort); | |
| 242 | |
| 243 // Send a reply back on the UI thread. | |
| 244 BrowserThread::PostTask( | |
| 245 callback_thread_id_, FROM_HERE, | |
| 246 NewRunnableMethod(this, &ModuleEnumerator::ReportBack)); | |
| 247 } | |
| 248 | |
| 249 void ModuleEnumerator::EnumerateLoadedModules() { | |
| 229 // Get all modules in the current process. | 250 // Get all modules in the current process. |
| 230 ScopedHandle snap(::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, | 251 ScopedHandle snap(::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, |
| 231 ::GetCurrentProcessId())); | 252 ::GetCurrentProcessId())); |
| 232 if (!snap.Get()) | 253 if (!snap.Get()) |
| 233 return; | 254 return; |
| 234 | 255 |
| 235 // Walk the module list. | 256 // Walk the module list. |
| 236 MODULEENTRY32 module = { sizeof(module) }; | 257 MODULEENTRY32 module = { sizeof(module) }; |
| 237 if (!::Module32First(snap.Get(), &module)) | 258 if (!::Module32First(snap.Get(), &module)) |
| 238 return; | 259 return; |
| 239 | 260 |
| 240 do { | 261 do { |
| 241 // It would be weird to present chrome.exe as a loaded module. | 262 // It would be weird to present chrome.exe as a loaded module. |
| 242 if (_wcsicmp(chrome::kBrowserProcessExecutableName, module.szModule) == 0) | 263 if (_wcsicmp(chrome::kBrowserProcessExecutableName, module.szModule) == 0) |
| 243 continue; | 264 continue; |
| 244 | 265 |
| 245 Module entry; | 266 Module entry; |
| 246 entry.type = LOADED_MODULE; | 267 entry.type = LOADED_MODULE; |
| 247 entry.status = NOT_MATCHED; | |
| 248 entry.normalized = false; | |
| 249 entry.location = module.szExePath; | 268 entry.location = module.szExePath; |
| 250 entry.digital_signer = | 269 PopulateModuleInformation(&entry); |
| 251 GetSubjectNameFromDigitalSignature(FilePath(entry.location)); | |
| 252 entry.recommended_action = NONE; | |
| 253 scoped_ptr<FileVersionInfo> version_info( | |
| 254 FileVersionInfo::CreateFileVersionInfo(FilePath(entry.location))); | |
| 255 if (version_info.get()) { | |
| 256 FileVersionInfoWin* version_info_win = | |
| 257 static_cast<FileVersionInfoWin*>(version_info.get()); | |
| 258 | |
| 259 VS_FIXEDFILEINFO* fixed_file_info = version_info_win->fixed_file_info(); | |
| 260 if (fixed_file_info) { | |
| 261 entry.description = version_info_win->file_description(); | |
| 262 entry.version = version_info_win->file_version(); | |
| 263 entry.product_name = version_info_win->product_name(); | |
| 264 } | |
| 265 } | |
| 266 | 270 |
| 267 NormalizeModule(&entry); | 271 NormalizeModule(&entry); |
| 268 CollapsePath(&entry); | 272 CollapsePath(&entry); |
| 269 enumerated_modules_->push_back(entry); | 273 enumerated_modules_->push_back(entry); |
| 270 } while (::Module32Next(snap.Get(), &module)); | 274 } while (::Module32Next(snap.Get(), &module)); |
| 275 } | |
| 271 | 276 |
| 277 void ModuleEnumerator::EnumerateShellExtensions() { | |
| 278 base::win::RegistryValueIterator registration(HKEY_LOCAL_MACHINE, kRegPath); | |
|
huanr
2010/11/18 22:01:13
Do you need to enumerate keys under HKCU?
| |
| 279 while (registration.Valid()) { | |
| 280 std::wstring key(std::wstring(L"CLSID\\") + registration.Name() + | |
| 281 L"\\InProcServer32"); | |
| 282 base::win::RegKey clsid; | |
| 283 if (!clsid.Open(HKEY_CLASSES_ROOT, key.c_str(), KEY_READ)) { | |
| 284 ++registration; | |
| 285 continue; | |
| 286 } | |
| 287 string16 dll; | |
| 288 if (!clsid.ReadValue(L"", &dll)) { | |
| 289 ++registration; | |
| 290 continue; | |
| 291 } | |
| 292 clsid.Close(); | |
| 293 | |
| 294 Module entry; | |
| 295 entry.type = SHELL_EXTENSION; | |
| 296 entry.location = dll; | |
| 297 PopulateModuleInformation(&entry); | |
| 298 | |
| 299 NormalizeModule(&entry); | |
| 300 CollapsePath(&entry); | |
| 301 enumerated_modules_->push_back(entry); | |
| 302 | |
| 303 ++registration; | |
| 304 } | |
| 305 } | |
| 306 | |
| 307 void ModuleEnumerator::EnumerateWinsockModule() { | |
| 272 // Add to this list the Winsock LSP DLLs. | 308 // Add to this list the Winsock LSP DLLs. |
| 273 WinsockLayeredServiceProviderList layered_providers; | 309 WinsockLayeredServiceProviderList layered_providers; |
| 274 GetWinsockLayeredServiceProviders(&layered_providers); | 310 GetWinsockLayeredServiceProviders(&layered_providers); |
| 275 for (size_t i = 0; i < layered_providers.size(); ++i) { | 311 for (size_t i = 0; i < layered_providers.size(); ++i) { |
| 276 Module entry; | 312 Module entry; |
| 277 entry.type = WINSOCK_MODULE_REGISTRATION; | 313 entry.type = WINSOCK_MODULE_REGISTRATION; |
| 278 entry.status = NOT_MATCHED; | 314 entry.status = NOT_MATCHED; |
| 279 entry.normalized = false; | 315 entry.normalized = false; |
| 280 entry.location = layered_providers[i].path; | 316 entry.location = layered_providers[i].path; |
| 281 entry.description = layered_providers[i].name; | 317 entry.description = layered_providers[i].name; |
| 282 entry.recommended_action = NONE; | 318 entry.recommended_action = NONE; |
| 283 | 319 |
| 284 wchar_t expanded[MAX_PATH]; | 320 wchar_t expanded[MAX_PATH]; |
| 285 DWORD size = ExpandEnvironmentStrings( | 321 DWORD size = ExpandEnvironmentStrings( |
| 286 entry.location.c_str(), expanded, MAX_PATH); | 322 entry.location.c_str(), expanded, MAX_PATH); |
| 287 if (size != 0 && size <= MAX_PATH) { | 323 if (size != 0 && size <= MAX_PATH) { |
| 288 entry.digital_signer = | 324 entry.digital_signer = |
| 289 GetSubjectNameFromDigitalSignature(FilePath(expanded)); | 325 GetSubjectNameFromDigitalSignature(FilePath(expanded)); |
| 290 } | 326 } |
| 291 entry.version = base::IntToString16(layered_providers[i].version); | 327 entry.version = base::IntToString16(layered_providers[i].version); |
| 292 | 328 |
| 293 // Paths have already been collapsed. | 329 // Paths have already been collapsed. |
| 294 NormalizeModule(&entry); | 330 NormalizeModule(&entry); |
| 295 enumerated_modules_->push_back(entry); | 331 enumerated_modules_->push_back(entry); |
| 296 } | 332 } |
| 333 } | |
| 297 | 334 |
| 298 MatchAgainstBlacklist(); | 335 void ModuleEnumerator::PopulateModuleInformation(Module* module) { |
| 336 module->status = NOT_MATCHED; | |
| 337 module->normalized = false; | |
| 338 module->digital_signer = | |
| 339 GetSubjectNameFromDigitalSignature(FilePath(module->location)); | |
| 340 module->recommended_action = NONE; | |
| 341 scoped_ptr<FileVersionInfo> version_info( | |
| 342 FileVersionInfo::CreateFileVersionInfo(FilePath(module->location))); | |
| 343 if (version_info.get()) { | |
| 344 FileVersionInfoWin* version_info_win = | |
| 345 static_cast<FileVersionInfoWin*>(version_info.get()); | |
| 299 | 346 |
| 300 std::sort(enumerated_modules_->begin(), | 347 VS_FIXEDFILEINFO* fixed_file_info = version_info_win->fixed_file_info(); |
| 301 enumerated_modules_->end(), ModuleSort); | 348 if (fixed_file_info) { |
| 302 | 349 module->description = version_info_win->file_description(); |
| 303 // Send a reply back on the UI thread. | 350 module->version = version_info_win->file_version(); |
| 304 BrowserThread::PostTask( | 351 module->product_name = version_info_win->product_name(); |
| 305 callback_thread_id_, FROM_HERE, | 352 } |
| 306 NewRunnableMethod(this, &ModuleEnumerator::ReportBack)); | 353 } |
| 307 } | 354 } |
| 308 | 355 |
| 309 void ModuleEnumerator::PreparePathMappings() { | 356 void ModuleEnumerator::PreparePathMappings() { |
| 310 path_mapping_.clear(); | 357 path_mapping_.clear(); |
| 311 | 358 |
| 312 scoped_ptr<base::Environment> environment(base::Environment::Create()); | 359 scoped_ptr<base::Environment> environment(base::Environment::Create()); |
| 313 std::vector<string16> env_vars; | 360 std::vector<string16> env_vars; |
| 314 env_vars.push_back(L"LOCALAPPDATA"); | 361 env_vars.push_back(L"LOCALAPPDATA"); |
| 315 env_vars.push_back(L"ProgramFiles"); | 362 env_vars.push_back(L"ProgramFiles"); |
| 316 env_vars.push_back(L"USERPROFILE"); | 363 env_vars.push_back(L"USERPROFILE"); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 491 return NULL; | 538 return NULL; |
| 492 } | 539 } |
| 493 | 540 |
| 494 ListValue* list = new ListValue(); | 541 ListValue* list = new ListValue(); |
| 495 | 542 |
| 496 for (ModuleEnumerator::ModulesVector::const_iterator module = | 543 for (ModuleEnumerator::ModulesVector::const_iterator module = |
| 497 enumerated_modules_.begin(); | 544 enumerated_modules_.begin(); |
| 498 module != enumerated_modules_.end(); ++module) { | 545 module != enumerated_modules_.end(); ++module) { |
| 499 DictionaryValue* data = new DictionaryValue(); | 546 DictionaryValue* data = new DictionaryValue(); |
| 500 data->SetInteger("type", module->type); | 547 data->SetInteger("type", module->type); |
| 501 data->SetString("type_description", | 548 switch (module->type) { |
| 502 (module->type == ModuleEnumerator::WINSOCK_MODULE_REGISTRATION) ? | 549 case ModuleEnumerator::SHELL_EXTENSION: |
| 503 ASCIIToWide("Winsock") : ASCIIToWide("")); | 550 data->SetString("type_description", ASCIIToWide("Shell Extension")); |
| 551 break; | |
| 552 case ModuleEnumerator::WINSOCK_MODULE_REGISTRATION: | |
| 553 data->SetString("type_description", ASCIIToWide("Winsock")); | |
| 554 break; | |
| 555 default: | |
| 556 data->SetString("type_description", ASCIIToWide("")); | |
| 557 break; | |
| 558 } | |
| 504 data->SetInteger("status", module->status); | 559 data->SetInteger("status", module->status); |
| 505 data->SetString("location", module->location); | 560 data->SetString("location", module->location); |
| 506 data->SetString("name", module->name); | 561 data->SetString("name", module->name); |
| 507 data->SetString("product_name", module->product_name); | 562 data->SetString("product_name", module->product_name); |
| 508 data->SetString("description", module->description); | 563 data->SetString("description", module->description); |
| 509 data->SetString("version", module->version.empty() ? ASCIIToWide("") : | 564 data->SetString("version", module->version.empty() ? ASCIIToWide("") : |
| 510 l10n_util::GetStringF(IDS_CONFLICTS_CHECK_VERSION_STRING, | 565 l10n_util::GetStringF(IDS_CONFLICTS_CHECK_VERSION_STRING, |
| 511 module->version)); | 566 module->version)); |
| 512 data->SetString("digital_signer", module->digital_signer); | 567 data->SetString("digital_signer", module->digital_signer); |
| 513 | 568 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 610 GenerateHash(WideToUTF8(module.name), &filename); | 665 GenerateHash(WideToUTF8(module.name), &filename); |
| 611 GenerateHash(WideToUTF8(module.location), &location); | 666 GenerateHash(WideToUTF8(module.location), &location); |
| 612 GenerateHash(WideToUTF8(module.description), &description); | 667 GenerateHash(WideToUTF8(module.description), &description); |
| 613 GenerateHash(WideToUTF8(module.digital_signer), &signer); | 668 GenerateHash(WideToUTF8(module.digital_signer), &signer); |
| 614 | 669 |
| 615 string16 url = l10n_util::GetStringF(IDS_HELP_CENTER_VIEW_CONFLICTS, | 670 string16 url = l10n_util::GetStringF(IDS_HELP_CENTER_VIEW_CONFLICTS, |
| 616 ASCIIToWide(filename), ASCIIToWide(location), | 671 ASCIIToWide(filename), ASCIIToWide(location), |
| 617 ASCIIToWide(description), ASCIIToWide(signer)); | 672 ASCIIToWide(description), ASCIIToWide(signer)); |
| 618 return GURL(WideToUTF8(url)); | 673 return GURL(WideToUTF8(url)); |
| 619 } | 674 } |
| OLD | NEW |