// Copyright (c) 2012 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/enumerate_modules_model_win.h"

#include <Tlhelp32.h>
#include <wintrust.h>
#include <algorithm>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/environment.h"
#include "base/file_version_info_win.h"
#include "base/files/file_path.h"
#include "base/i18n/case_conversion.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "base/version.h"
#include "base/win/registry.h"
#include "base/win/scoped_handle.h"
#include "base/win/windows_version.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/net/service_providers_win.h"
#include "chrome/common/chrome_constants.h"
#include "content/public/browser/notification_service.h"
#include "crypto/sha2.h"
#include "grit/generated_resources.h"
#include "grit/google_chrome_strings.h"
#include "ui/base/l10n/l10n_util.h"

using content::BrowserThread;

// The period of time (in milliseconds) to wait until checking to see if any
// incompatible modules exist.
static const int kModuleCheckDelayMs = 45 * 1000;

// The path to the Shell Extension key in the Windows registry.
static const wchar_t kRegPath[] =
    L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved";

// Short-hand for things on the blacklist you should simply get rid of.
static const ModuleEnumerator::RecommendedAction kUninstallLink =
    static_cast<ModuleEnumerator::RecommendedAction>(
        ModuleEnumerator::UNINSTALL | ModuleEnumerator::SEE_LINK);

// Short-hand for things on the blacklist we are investigating and have info.
static const ModuleEnumerator::RecommendedAction kInvestigatingLink =
    static_cast<ModuleEnumerator::RecommendedAction>(
        ModuleEnumerator::INVESTIGATING | ModuleEnumerator::SEE_LINK);

// A sort method that sorts by bad modules first, then by full name (including
// path).
static bool ModuleSort(const ModuleEnumerator::Module& a,
                       const ModuleEnumerator::Module& b) {
  if (a.status != b.status)
    return a.status > b.status;

  if (a.location == b.location)
    return a.name < b.name;

  return a.location < b.location;
}

namespace {

// Used to protect the LoadedModuleVector which is accessed
// from both the UI thread and the FILE thread.
base::Lock* lock = NULL;

// A struct to help de-duping modules before adding them to the enumerated
// modules vector.
struct FindModule {
 public:
  explicit FindModule(const ModuleEnumerator::Module& x)
    : module(x) {}
  bool operator()(const ModuleEnumerator::Module& module_in) const {
    return (module.location == module_in.location) &&
           (module.name == module_in.name);
  }

  const ModuleEnumerator::Module& module;
};

// Returns the long path name given a short path name. A short path name is a
// path that follows the 8.3 convention and has ~x in it. If the path is already
// a long path name, the function returns the current path without modification.
bool ConvertToLongPath(const base::string16& short_path,
                       base::string16* long_path) {
  wchar_t long_path_buf[MAX_PATH];
  DWORD return_value = GetLongPathName(short_path.c_str(), long_path_buf,
                                       MAX_PATH);
  if (return_value != 0 && return_value < MAX_PATH) {
    *long_path = long_path_buf;
    return true;
  }

  return false;
}

}  // namespace

// The browser process module blacklist. This lists modules that are known
// to cause compatibility issues within the browser process. When adding to this
// list, make sure that all paths are lower-case, in long pathname form, end
// with a slash and use environments variables (or just look at one of the
// comments below and keep it consistent with that). When adding an entry with
// an environment variable not currently used in the list below, make sure to
// update the list in PreparePathMappings. Filename, Description/Signer, and
// Location must be entered as hashes (see GenerateHash). Filename is mandatory.
// Entries without any Description, Signer info, or Location will never be
// marked as confirmed bad (only as suspicious).
const ModuleEnumerator::BlacklistEntry ModuleEnumerator::kModuleBlacklist[] = {
  // NOTE: Please keep this list sorted by dll name, then location.

  // Version 3.2.1.6 seems to be implicated in most cases (and 3.2.2.2 in some).
  // There is a more recent version available for download.
  // accelerator.dll, "%programfiles%\\speedbit video accelerator\\".
  { "7ba9402f", "c9132d48", "", "", "", ALL, kInvestigatingLink },

  // apiqq0.dll, "%temp%\\".
  { "26134911", "59145acf", "", "", "", ALL, kUninstallLink },

  // arking0.dll, "%systemroot%\\system32\\".
  { "f5d8f549", "23d01d5b", "", "", "", ALL, kUninstallLink },

  // arking1.dll, "%systemroot%\\system32\\".
  { "c60ca062", "23d01d5b", "", "", "", ALL, kUninstallLink },

  // aswjsflt.dll, "%ProgramFiles%\\avast software\\avast\\", "AVAST Software".
  // NOTE: The digital signature of the DLL is double null terminated.
  // Avast Antivirus prior to version 8.0 would kill the Chrome child process
  // when blocked from running.
  { "2ea5422a", "6b3a1b00", "a7db0e0c", "", "8.0", XP,
    static_cast<RecommendedAction>(UPDATE | SEE_LINK | NOTIFY_USER) },

  // aswjsflt.dll, "%ProgramFiles%\\alwil software\\avast5\\", "AVAST Software".
  // NOTE: The digital signature of the DLL is double null terminated.
  // Avast Antivirus prior to version 8.0 would kill the Chrome child process
  // when blocked from running.
  { "2ea5422a", "d8686924", "a7db0e0c", "", "8.0", XP,
    static_cast<RecommendedAction>(UPDATE | SEE_LINK | NOTIFY_USER) },

  // Said to belong to Killer NIC from BigFoot Networks (not verified). Versions
  // 6.0.0.7 and 6.0.0.10 implicated.
  // bfllr.dll, "%systemroot%\\system32\\".
  { "6bb57633", "23d01d5b", "", "", "", ALL, kInvestigatingLink },

  // clickpotatolitesahook.dll, "". Different version each report.
  { "0396e037.dll", "", "", "", "", ALL, kUninstallLink },

  // cvasds0.dll, "%temp%\\".
  { "5ce0037c", "59145acf", "", "", "", ALL, kUninstallLink },

  // cwalsp.dll, "%systemroot%\\system32\\".
  { "e579a039", "23d01d5b", "", "", "", ALL, kUninstallLink },

  // datamngr.dll (1), "%programfiles%\\searchqu toolbar\\datamngr\\".
  { "7add320b", "470a3da3", "", "", "", ALL, kUninstallLink },

  // datamngr.dll (2), "%programfiles%\\windows searchqu toolbar\\".
  { "7add320b", "7a3c8be3", "", "", "", ALL, kUninstallLink },

  // dsoqq0.dll, "%temp%\\".
  { "1c4df325", "59145acf", "", "", "", ALL, kUninstallLink },

  // flt.dll, "%programfiles%\\tueagles\\".
  { "6d01f4a1", "7935e9c2", "", "", "", ALL, kUninstallLink },

  // This looks like a malware edition of a Brazilian Bank plugin, sometimes
  // referred to as Malware.Banc.A.
  // gbieh.dll, "%programfiles%\\gbplugin\\".
  { "4cb4f2e3", "88e4a3b1", "", "", "", ALL, kUninstallLink },

  // hblitesahook.dll. Each report has different version number in location.
  { "5d10b363", "", "", "", "", ALL, kUninstallLink },

  // icf.dll, "%systemroot%\\system32\\".
  { "303825ed", "23d01d5b", "", "", "", ALL, INVESTIGATING },

  // idmmbc.dll (IDM), "%systemroot%\\system32\\". See: http://crbug.com/26892/.
  { "b8dce5c3", "23d01d5b", "", "", "6.03", ALL,
      static_cast<RecommendedAction>(UPDATE | DISABLE) },

  // imon.dll (NOD32), "%systemroot%\\system32\\". See: http://crbug.com/21715.
  { "8f42f22e", "23d01d5b", "", "", "4.0", ALL,
      static_cast<RecommendedAction>(UPDATE | DISABLE) },

  // is3lsp.dll, "%commonprogramfiles%\\is3\\anti-spyware\\".
  { "7ffbdce9", "bc5673f2", "", "", "", ALL,
      static_cast<RecommendedAction>(UPDATE | DISABLE | SEE_LINK) },

  // jsi.dll, "%programfiles%\\profilecraze\\".
  { "f9555eea", "e3548061", "", "", "", ALL, kUninstallLink },

  // kernel.dll, "%programfiles%\\contentwatch\\internet protection\\modules\\".
  { "ead2768e", "4e61ce60", "", "", "", ALL, INVESTIGATING },

  // mgking0.dll, "%systemroot%\\system32\\".
  { "d0893e38", "23d01d5b", "", "", "", ALL, kUninstallLink },

  // mgking0.dll, "%temp%\\".
  { "d0893e38", "59145acf", "", "", "", ALL, kUninstallLink },

  // mgking1.dll, "%systemroot%\\system32\\".
  { "3e837222", "23d01d5b", "", "", "", ALL, kUninstallLink },

  // mgking1.dll, "%temp%\\".
  { "3e837222", "59145acf", "", "", "", ALL, kUninstallLink },

  // mstcipha.ime, "%systemroot%\\system32\\".
  { "5523579e", "23d01d5b", "", "", "", ALL, INVESTIGATING },

  // mwtsp.dll, "%systemroot%\\system32\\".
  { "9830bff6", "23d01d5b", "", "", "", ALL, kUninstallLink },

  // nodqq0.dll, "%temp%\\".
  { "b86ce04d", "59145acf", "", "", "", ALL, kUninstallLink },

  // nProtect GameGuard Anti-cheat system. Every report has a different
  // location, since it is installed into and run from a game folder. Various
  // versions implicated.
  // npggnt.des, no fixed location.
  { "f2c8790d", "", "", "", "", ALL, kInvestigatingLink },

  // nvlsp.dll,
  // "%programfiles%\\nvidia corporation\\networkaccessmanager\\bin32\\".
  { "37f907e2", "3ad0ff23", "", "", "", ALL, INVESTIGATING },

  // post0.dll, "%systemroot%\\system32\\".
  { "7405c0c8", "23d01d5b", "", "", "", ALL, kUninstallLink },

  // questbrwsearch.dll, "%programfiles%\\questbrwsearch\\".
  { "0953ed09", "f0d5eeda", "", "", "", ALL, kUninstallLink },

  // questscan.dll, "%programfiles%\\questscan\\".
  { "f4f3391e", "119d20f7", "", "", "", ALL, kUninstallLink },

  // radhslib.dll (Naomi web filter), "%programfiles%\\rnamfler\\".
  // See http://crbug.com/12517.
  { "7edcd250", "0733dc3e", "", "", "", ALL, INVESTIGATING },

  // rlls.dll, "%programfiles%\\relevantknowledge\\".
  { "a1ed94a7", "ea9d6b36", "", "", "", ALL, kUninstallLink },

  // rooksdol.dll, "%programfiles%\\trusteer\\rapport\\bin\\".
  { "802aefef", "06120e13", "", "", "3.5.1008.40", ALL, UPDATE },

  // scanquery.dll, "%programfiles%\\scanquery\\".
  { "0b52d2ae", "a4cc88b1", "", "", "", ALL, kUninstallLink },

  // sdata.dll, "%programdata%\\srtserv\\".
  { "1936d5cc", "223c44be", "", "", "", ALL, kUninstallLink },

  // searchtree.dll,
  // "%programfiles%\\contentwatch\\internet protection\\modules\\".
  { "f6915a31", "4e61ce60", "", "", "", ALL, INVESTIGATING },

  // sgprxy.dll, "%commonprogramfiles%\\is3\\anti-spyware\\".
  { "005965ea", "bc5673f2", "", "", "", ALL, INVESTIGATING },

  // snxhk.dll, "%ProgramFiles%\\avast software\\avast\\", "AVAST Software".
  // NOTE: The digital signature of the DLL is double null terminated.
  // Avast Antivirus prior to version 8.0 would kill the Chrome child process
  // when blocked from running.
  { "46c16aa8", "6b3a1b00", "a7db0e0c", "", "8.0", XP,
    static_cast<RecommendedAction>(UPDATE | SEE_LINK | NOTIFY_USER) },

  // snxhk.dll, "%ProgramFiles%\\alwil software\\avast5\\", "AVAST Software".
  // NOTE: The digital signature of the DLL is double null terminated.
  // Avast Antivirus prior to version 8.0 would kill the Chrome child process
  // when blocked from running.
  { "46c16aa8", "d8686924", "a7db0e0c", "", "8.0", XP,
    static_cast<RecommendedAction>(UPDATE | SEE_LINK | NOTIFY_USER) },

  // sprotector.dll, "". Different location each report.
  { "24555d74", "", "", "", "", ALL, kUninstallLink },

  // swi_filter_0001.dll (Sophos Web Intelligence),
  // "%programfiles%\\sophos\\sophos anti-virus\\web intelligence\\".
  // A small random sample all showed version 1.0.5.0.
  { "61112d7b", "25fb120f", "", "", "", ALL, kInvestigatingLink },

  // twking0.dll, "%systemroot%\\system32\\".
  { "0355549b", "23d01d5b", "", "", "", ALL, kUninstallLink },

  // twking1.dll, "%systemroot%\\system32\\".
  { "02e44508", "23d01d5b", "", "", "", ALL, kUninstallLink },

  // vksaver.dll, "%systemroot%\\system32\\".
  { "c4a784d5", "23d01d5b", "", "", "", ALL, kUninstallLink },

  // vlsp.dll (Venturi Firewall?), "%systemroot%\\system32\\".
  { "2e4eb93d", "23d01d5b", "", "", "", ALL, INVESTIGATING },

  // vmn3_1dn.dll, "%appdata%\\roaming\\vmndtxtb\\".
  { "bba2037d", "9ab68585", "", "", "", ALL, kUninstallLink },

  // webanalyzer.dll,
  // "%programfiles%\\contentwatch\\internet protection\\modules\\".
  { "c70b697d", "4e61ce60", "", "", "", ALL, INVESTIGATING },

  // wowst0.dll, "%systemroot%\\system32\\".
  { "38ad9963", "23d01d5b", "", "", "", ALL, kUninstallLink },

  // wxbase28u_vc_cw.dll, "%systemroot%\\system32\\".
  { "e967210d", "23d01d5b", "", "", "", ALL, kUninstallLink },
};

// Generates an 8 digit hash from the input given.
static void GenerateHash(const std::string& input, std::string* output) {
  if (input.empty()) {
    *output = "";
    return;
  }

  uint8 hash[4];
  crypto::SHA256HashString(input, hash, sizeof(hash));
  *output = StringToLowerASCII(base::HexEncode(hash, sizeof(hash)));
}

// -----------------------------------------------------------------------------

// static
void ModuleEnumerator::NormalizeModule(Module* module) {
  base::string16 path = module->location;
  if (!ConvertToLongPath(path, &module->location))
    module->location = path;

  module->location = base::i18n::ToLower(module->location);

  // Location contains the filename, so the last slash is where the path
  // ends.
  size_t last_slash = module->location.find_last_of(L"\\");
  if (last_slash != base::string16::npos) {
    module->name = module->location.substr(last_slash + 1);
    module->location = module->location.substr(0, last_slash + 1);
  } else {
    module->name = module->location;
    module->location.clear();
  }

  // Some version strings have things like (win7_rtm.090713-1255) appended
  // to them. Remove that.
  size_t first_space = module->version.find_first_of(L" ");
  if (first_space != base::string16::npos)
    module->version = module->version.substr(0, first_space);

  module->normalized = true;
}

// static
ModuleEnumerator::ModuleStatus ModuleEnumerator::Match(
    const ModuleEnumerator::Module& module,
    const ModuleEnumerator::BlacklistEntry& blacklisted) {
  // All modules must be normalized before matching against blacklist.
  DCHECK(module.normalized);
  // Filename is mandatory and version should not contain spaces.
  DCHECK(strlen(blacklisted.filename) > 0);
  DCHECK(!strstr(blacklisted.version_from, " "));
  DCHECK(!strstr(blacklisted.version_to, " "));

  base::win::Version version = base::win::GetVersion();
  switch (version) {
     case base::win::VERSION_XP:
      if (!(blacklisted.os & XP)) return NOT_MATCHED;
      break;
    default:
      break;
  }

  std::string filename_hash, location_hash;
  GenerateHash(base::WideToUTF8(module.name), &filename_hash);
  GenerateHash(base::WideToUTF8(module.location), &location_hash);

  // Filenames are mandatory. Location is mandatory if given.
  if (filename_hash == blacklisted.filename &&
          (std::string(blacklisted.location).empty() ||
          location_hash == blacklisted.location)) {
    // We have a name match against the blacklist (and possibly location match
    // also), so check version.
    Version module_version(base::UTF16ToASCII(module.version));
    Version version_min(blacklisted.version_from);
    Version version_max(blacklisted.version_to);
    bool version_ok = !version_min.IsValid() && !version_max.IsValid();
    if (!version_ok) {
      bool too_low = version_min.IsValid() &&
          (!module_version.IsValid() ||
          module_version.CompareTo(version_min) < 0);
      bool too_high = version_max.IsValid() &&
          (!module_version.IsValid() ||
          module_version.CompareTo(version_max) >= 0);
      version_ok = !too_low && !too_high;
    }

    if (version_ok) {
      // At this point, the names match and there is no version specified
      // or the versions also match.

      std::string desc_or_signer(blacklisted.desc_or_signer);
      std::string signer_hash, description_hash;
      GenerateHash(base::WideToUTF8(module.digital_signer), &signer_hash);
      GenerateHash(base::WideToUTF8(module.description), &description_hash);

      // If signatures match (or both are empty), then we have a winner.
      if (signer_hash == desc_or_signer)
        return CONFIRMED_BAD;

      // If descriptions match (or both are empty) and the locations match, then
      // we also have a confirmed match.
      if (description_hash == desc_or_signer &&
          !location_hash.empty() && location_hash == blacklisted.location)
        return CONFIRMED_BAD;

      // We are not sure, but it is likely bad.
      return SUSPECTED_BAD;
    }
  }

  return NOT_MATCHED;
}

ModuleEnumerator::ModuleEnumerator(EnumerateModulesModel* observer)
    : enumerated_modules_(NULL),
      observer_(observer),
      limited_mode_(false),
      callback_thread_id_(BrowserThread::ID_COUNT) {
}

ModuleEnumerator::~ModuleEnumerator() {
}

void ModuleEnumerator::ScanNow(ModulesVector* list, bool limited_mode) {
  enumerated_modules_ = list;

  limited_mode_ = limited_mode;

  if (!limited_mode_) {
    CHECK(BrowserThread::GetCurrentThreadIdentifier(&callback_thread_id_));
    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
                            base::Bind(&ModuleEnumerator::ScanImpl, this));
  } else {
    // Run it synchronously.
    ScanImpl();
  }
}

void ModuleEnumerator::ScanImpl() {
  base::TimeTicks start_time = base::TimeTicks::Now();

  enumerated_modules_->clear();

  // Make sure the path mapping vector is setup so we can collapse paths.
  PreparePathMappings();

  // Enumerating loaded modules must happen first since the other types of
  // modules check for duplication against the loaded modules.
  base::TimeTicks checkpoint = base::TimeTicks::Now();
  EnumerateLoadedModules();
  base::TimeTicks checkpoint2 = base::TimeTicks::Now();
  UMA_HISTOGRAM_TIMES("Conflicts.EnumerateLoadedModules",
                      checkpoint2 - checkpoint);

  checkpoint = checkpoint2;
  EnumerateShellExtensions();
  checkpoint2 = base::TimeTicks::Now();
  UMA_HISTOGRAM_TIMES("Conflicts.EnumerateShellExtensions",
                      checkpoint2 - checkpoint);

  checkpoint = checkpoint2;
  EnumerateWinsockModules();
  checkpoint2 = base::TimeTicks::Now();
  UMA_HISTOGRAM_TIMES("Conflicts.EnumerateWinsockModules",
                      checkpoint2 - checkpoint);

  MatchAgainstBlacklist();

  std::sort(enumerated_modules_->begin(),
            enumerated_modules_->end(), ModuleSort);

  if (!limited_mode_) {
    // Send a reply back on the UI thread.
    BrowserThread::PostTask(callback_thread_id_, FROM_HERE,
                            base::Bind(&ModuleEnumerator::ReportBack, this));
  } else {
    // We are on the main thread already.
    ReportBack();
  }

  UMA_HISTOGRAM_TIMES("Conflicts.EnumerationTotalTime",
                      base::TimeTicks::Now() - start_time);
}

void ModuleEnumerator::EnumerateLoadedModules() {
  // Get all modules in the current process.
  base::win::ScopedHandle snap(::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,
                               ::GetCurrentProcessId()));
  if (!snap.Get())
    return;

  // Walk the module list.
  MODULEENTRY32 module = { sizeof(module) };
  if (!::Module32First(snap.Get(), &module))
    return;

  do {
    // It would be weird to present chrome.exe as a loaded module.
    if (_wcsicmp(chrome::kBrowserProcessExecutableName, module.szModule) == 0)
      continue;

    Module entry;
    entry.type = LOADED_MODULE;
    entry.location = module.szExePath;
    PopulateModuleInformation(&entry);

    NormalizeModule(&entry);
    CollapsePath(&entry);
    enumerated_modules_->push_back(entry);
  } while (::Module32Next(snap.Get(), &module));
}

void ModuleEnumerator::EnumerateShellExtensions() {
  ReadShellExtensions(HKEY_LOCAL_MACHINE);
  ReadShellExtensions(HKEY_CURRENT_USER);
}

void ModuleEnumerator::ReadShellExtensions(HKEY parent) {
  base::win::RegistryValueIterator registration(parent, kRegPath);
  while (registration.Valid()) {
    std::wstring key(std::wstring(L"CLSID\\") + registration.Name() +
        L"\\InProcServer32");
    base::win::RegKey clsid;
    if (clsid.Open(HKEY_CLASSES_ROOT, key.c_str(), KEY_READ) != ERROR_SUCCESS) {
      ++registration;
      continue;
    }
    base::string16 dll;
    if (clsid.ReadValue(L"", &dll) != ERROR_SUCCESS) {
      ++registration;
      continue;
    }
    clsid.Close();

    Module entry;
    entry.type = SHELL_EXTENSION;
    entry.location = dll;
    PopulateModuleInformation(&entry);

    NormalizeModule(&entry);
    CollapsePath(&entry);
    AddToListWithoutDuplicating(entry);

    ++registration;
  }
}

void ModuleEnumerator::EnumerateWinsockModules() {
  // Add to this list the Winsock LSP DLLs.
  WinsockLayeredServiceProviderList layered_providers;
  GetWinsockLayeredServiceProviders(&layered_providers);
  for (size_t i = 0; i < layered_providers.size(); ++i) {
    Module entry;
    entry.type = WINSOCK_MODULE_REGISTRATION;
    entry.status = NOT_MATCHED;
    entry.normalized = false;
    entry.location = layered_providers[i].path;
    entry.description = layered_providers[i].name;
    entry.recommended_action = NONE;
    entry.duplicate_count = 0;

    wchar_t expanded[MAX_PATH];
    DWORD size = ExpandEnvironmentStrings(
        entry.location.c_str(), expanded, MAX_PATH);
    if (size != 0 && size <= MAX_PATH) {
      entry.digital_signer =
          GetSubjectNameFromDigitalSignature(base::FilePath(expanded));
    }
    entry.version = base::IntToString16(layered_providers[i].version);

    // Paths have already been collapsed.
    NormalizeModule(&entry);
    AddToListWithoutDuplicating(entry);
  }
}

void ModuleEnumerator::PopulateModuleInformation(Module* module) {
  module->status = NOT_MATCHED;
  module->duplicate_count = 0;
  module->normalized = false;
  module->digital_signer =
      GetSubjectNameFromDigitalSignature(base::FilePath(module->location));
  module->recommended_action = NONE;
  scoped_ptr<FileVersionInfo> version_info(
      FileVersionInfo::CreateFileVersionInfo(base::FilePath(module->location)));
  if (version_info.get()) {
    FileVersionInfoWin* version_info_win =
        static_cast<FileVersionInfoWin*>(version_info.get());

    VS_FIXEDFILEINFO* fixed_file_info = version_info_win->fixed_file_info();
    if (fixed_file_info) {
      module->description = version_info_win->file_description();
      module->version = version_info_win->file_version();
      module->product_name = version_info_win->product_name();
    }
  }
}

void ModuleEnumerator::AddToListWithoutDuplicating(const Module& module) {
  DCHECK(module.normalized);
  // These are registered modules, not loaded modules so the same module
  // can be registered multiple times, often dozens of times. There is no need
  // to list each registration, so we just increment the count for each module
  // that is counted multiple times.
  ModulesVector::iterator iter;
  iter = std::find_if(enumerated_modules_->begin(),
                      enumerated_modules_->end(),
                      FindModule(module));
  if (iter != enumerated_modules_->end()) {
    iter->duplicate_count++;
    iter->type = static_cast<ModuleType>(iter->type | module.type);
  } else {
    enumerated_modules_->push_back(module);
  }
}

void ModuleEnumerator::PreparePathMappings() {
  path_mapping_.clear();

  scoped_ptr<base::Environment> environment(base::Environment::Create());
  std::vector<base::string16> env_vars;
  env_vars.push_back(L"LOCALAPPDATA");
  env_vars.push_back(L"ProgramFiles");
  env_vars.push_back(L"ProgramData");
  env_vars.push_back(L"USERPROFILE");
  env_vars.push_back(L"SystemRoot");
  env_vars.push_back(L"TEMP");
  env_vars.push_back(L"TMP");
  env_vars.push_back(L"CommonProgramFiles");
  for (std::vector<base::string16>::const_iterator variable = env_vars.begin();
       variable != env_vars.end(); ++variable) {
    std::string path;
    if (environment->GetVar(base::UTF16ToASCII(*variable).c_str(), &path)) {
      path_mapping_.push_back(
          std::make_pair(base::i18n::ToLower(base::UTF8ToUTF16(path)) + L"\\",
                         L"%" + base::i18n::ToLower(*variable) + L"%"));
    }
  }
}

void ModuleEnumerator::CollapsePath(Module* entry) {
  // Take the path and see if we can use any of the substitution values
  // from the vector constructed above to replace c:\windows with, for
  // example, %systemroot%. The most collapsed path (the one with the
  // minimum length) wins.
  size_t min_length = MAXINT;
  base::string16 location = entry->location;
  for (PathMapping::const_iterator mapping = path_mapping_.begin();
       mapping != path_mapping_.end(); ++mapping) {
    base::string16 prefix = mapping->first;
    if (StartsWith(location, prefix, false)) {
      base::string16 new_location = mapping->second +
                              location.substr(prefix.length() - 1);
      size_t length = new_location.length() - mapping->second.length();
      if (length < min_length) {
        entry->location = new_location;
        min_length = length;
      }
    }
  }
}

void ModuleEnumerator::MatchAgainstBlacklist() {
  for (size_t m = 0; m < enumerated_modules_->size(); ++m) {
    // Match this module against the blacklist.
    Module* module = &(*enumerated_modules_)[m];
    module->status = GOOD;  // We change this below potentially.
    for (size_t i = 0; i < arraysize(kModuleBlacklist); ++i) {
      #if !defined(NDEBUG)
        // This saves time when constructing the blacklist.
        std::string hashes(kModuleBlacklist[i].filename);
        std::string hash1, hash2, hash3;
        GenerateHash(kModuleBlacklist[i].filename, &hash1);
        hashes += " - " + hash1;
        GenerateHash(kModuleBlacklist[i].location, &hash2);
        hashes += " - " + hash2;
        GenerateHash(kModuleBlacklist[i].desc_or_signer, &hash3);
        hashes += " - " + hash3;
      #endif

      ModuleStatus status = Match(*module, kModuleBlacklist[i]);
      if (status != NOT_MATCHED) {
        // We have a match against the blacklist. Mark it as such.
        module->status = status;
        module->recommended_action = kModuleBlacklist[i].help_tip;
        break;
      }
    }

    // Modules loaded from these locations are frequently malicious
    // and notorious for changing frequently so they are not good candidates
    // for blacklisting individually. Mark them as suspicious if we haven't
    // classified them as bad yet.
    if (module->status == NOT_MATCHED || module->status == GOOD) {
      if (StartsWith(module->location, L"%temp%", false) ||
          StartsWith(module->location, L"%tmp%", false)) {
        module->status = SUSPECTED_BAD;
      }
    }
  }
}

void ModuleEnumerator::ReportBack() {
  if (!limited_mode_)
    DCHECK(BrowserThread::CurrentlyOn(callback_thread_id_));
  observer_->DoneScanning();
}

base::string16 ModuleEnumerator::GetSubjectNameFromDigitalSignature(
    const base::FilePath& filename) {
  HCERTSTORE store = NULL;
  HCRYPTMSG message = NULL;

  // Find the crypto message for this filename.
  bool result = !!CryptQueryObject(CERT_QUERY_OBJECT_FILE,
                                   filename.value().c_str(),
                                   CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
                                   CERT_QUERY_FORMAT_FLAG_BINARY,
                                   0,
                                   NULL,
                                   NULL,
                                   NULL,
                                   &store,
                                   &message,
                                   NULL);
  if (!result)
    return base::string16();

  // Determine the size of the signer info data.
  DWORD signer_info_size = 0;
  result = !!CryptMsgGetParam(message,
                              CMSG_SIGNER_INFO_PARAM,
                              0,
                              NULL,
                              &signer_info_size);
  if (!result)
    return base::string16();

  // Allocate enough space to hold the signer info.
  scoped_ptr<BYTE[]> signer_info_buffer(new BYTE[signer_info_size]);
  CMSG_SIGNER_INFO* signer_info =
      reinterpret_cast<CMSG_SIGNER_INFO*>(signer_info_buffer.get());

  // Obtain the signer info.
  result = !!CryptMsgGetParam(message,
                              CMSG_SIGNER_INFO_PARAM,
                              0,
                              signer_info,
                              &signer_info_size);
  if (!result)
    return base::string16();

  // Search for the signer certificate.
  CERT_INFO CertInfo = {0};
  PCCERT_CONTEXT cert_context = NULL;
  CertInfo.Issuer = signer_info->Issuer;
  CertInfo.SerialNumber = signer_info->SerialNumber;

  cert_context = CertFindCertificateInStore(
      store,
      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
      0,
      CERT_FIND_SUBJECT_CERT,
      &CertInfo,
      NULL);
  if (!cert_context)
    return base::string16();

  // Determine the size of the Subject name.
  DWORD subject_name_size = 0;
  if (!(subject_name_size = CertGetNameString(cert_context,
                                              CERT_NAME_SIMPLE_DISPLAY_TYPE,
                                              0,
                                              NULL,
                                              NULL,
                                              0))) {
    return base::string16();
  }

  base::string16 subject_name;
  subject_name.resize(subject_name_size);

  // Get subject name.
  if (!(CertGetNameString(cert_context,
                          CERT_NAME_SIMPLE_DISPLAY_TYPE,
                          0,
                          NULL,
                          const_cast<LPWSTR>(subject_name.c_str()),
                          subject_name_size))) {
    return base::string16();
  }

  return subject_name;
}

//  ----------------------------------------------------------------------------

// static
EnumerateModulesModel* EnumerateModulesModel::GetInstance() {
  return Singleton<EnumerateModulesModel>::get();
}

bool EnumerateModulesModel::ShouldShowConflictWarning() const {
  // If the user has acknowledged the conflict notification, then we don't need
  // to show it again (because the scanning only happens once per the lifetime
  // of the process). If we were to run the scanning more than once, then we'd
  // need to clear the flag somewhere when we are ready to show it again.
  if (conflict_notification_acknowledged_)
    return false;

  return confirmed_bad_modules_detected_ > 0;
}

void EnumerateModulesModel::AcknowledgeConflictNotification() {
  if (!conflict_notification_acknowledged_) {
    conflict_notification_acknowledged_ = true;
    content::NotificationService::current()->Notify(
        chrome::NOTIFICATION_MODULE_INCOMPATIBILITY_BADGE_CHANGE,
        content::Source<EnumerateModulesModel>(this),
        content::NotificationService::NoDetails());
  }
}

void EnumerateModulesModel::ScanNow() {
  if (scanning_)
    return;  // A scan is already in progress.

  lock->Acquire();  // Balanced in DoneScanning();

  scanning_ = true;

  // Instruct the ModuleEnumerator class to load this on the File thread.
  // ScanNow does not block.
  if (!module_enumerator_)
    module_enumerator_ = new ModuleEnumerator(this);
  module_enumerator_->ScanNow(&enumerated_modules_, limited_mode_);
}

base::ListValue* EnumerateModulesModel::GetModuleList() const {
  if (scanning_)
    return NULL;

  lock->Acquire();

  if (enumerated_modules_.empty()) {
    lock->Release();
    return NULL;
  }

  base::ListValue* list = new base::ListValue();

  for (ModuleEnumerator::ModulesVector::const_iterator module =
           enumerated_modules_.begin();
       module != enumerated_modules_.end(); ++module) {
    base::DictionaryValue* data = new base::DictionaryValue();
    data->SetInteger("type", module->type);
    base::string16 type_string;
    if ((module->type & ModuleEnumerator::LOADED_MODULE) == 0) {
      // Module is not loaded, denote type of module.
      if (module->type & ModuleEnumerator::SHELL_EXTENSION)
        type_string = base::ASCIIToWide("Shell Extension");
      if (module->type & ModuleEnumerator::WINSOCK_MODULE_REGISTRATION) {
        if (!type_string.empty())
          type_string += base::ASCIIToWide(", ");
        type_string += base::ASCIIToWide("Winsock");
      }
      // Must be one of the above type.
      DCHECK(!type_string.empty());
      if (!limited_mode_) {
        type_string += base::ASCIIToWide(" -- ");
        type_string += l10n_util::GetStringUTF16(IDS_CONFLICTS_NOT_LOADED_YET);
      }
    }
    data->SetString("type_description", type_string);
    data->SetInteger("status", module->status);
    data->SetString("location", module->location);
    data->SetString("name", module->name);
    data->SetString("product_name", module->product_name);
    data->SetString("description", module->description);
    data->SetString("version", module->version);
    data->SetString("digital_signer", module->digital_signer);

    if (!limited_mode_) {
      // Figure out the possible resolution help string.
      base::string16 actions;
      base::string16 separator = base::ASCIIToWide(" ") +
          l10n_util::GetStringUTF16(
              IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_SEPARATOR) +
          base::ASCIIToWide(" ");

      if (module->recommended_action & ModuleEnumerator::NONE) {
        actions = l10n_util::GetStringUTF16(
            IDS_CONFLICTS_CHECK_INVESTIGATING);
      }
      if (module->recommended_action & ModuleEnumerator::UNINSTALL) {
        if (!actions.empty())
          actions += separator;
        actions = l10n_util::GetStringUTF16(
            IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_UNINSTALL);
      }
      if (module->recommended_action & ModuleEnumerator::UPDATE) {
        if (!actions.empty())
          actions += separator;
        actions += l10n_util::GetStringUTF16(
            IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_UPDATE);
      }
      if (module->recommended_action & ModuleEnumerator::DISABLE) {
        if (!actions.empty())
          actions += separator;
        actions += l10n_util::GetStringUTF16(
            IDS_CONFLICTS_CHECK_POSSIBLE_ACTION_DISABLE);
      }
      base::string16 possible_resolution =
          actions.empty() ? base::ASCIIToWide("")
                          : l10n_util::GetStringUTF16(
                                IDS_CONFLICTS_CHECK_POSSIBLE_ACTIONS) +
          base::ASCIIToWide(" ") +
          actions;
      data->SetString("possibleResolution", possible_resolution);
      data->SetString("help_url",
                      ConstructHelpCenterUrl(*module).spec().c_str());
    }

    list->Append(data);
  }

  lock->Release();
  return list;
}

GURL EnumerateModulesModel::GetFirstNotableConflict() {
  lock->Acquire();
  GURL url;

  if (enumerated_modules_.empty()) {
    lock->Release();
    return GURL();
  }

  for (ModuleEnumerator::ModulesVector::const_iterator module =
           enumerated_modules_.begin();
       module != enumerated_modules_.end(); ++module) {
    if (!(module->recommended_action & ModuleEnumerator::NOTIFY_USER))
      continue;

    url = ConstructHelpCenterUrl(*module);
    DCHECK(url.is_valid());
    break;
  }

  lock->Release();
  return url;
}


EnumerateModulesModel::EnumerateModulesModel()
    : limited_mode_(false),
      scanning_(false),
      conflict_notification_acknowledged_(false),
      confirmed_bad_modules_detected_(0),
      suspected_bad_modules_detected_(0),
      modules_to_notify_about_(0) {
  lock = new base::Lock();
}

EnumerateModulesModel::~EnumerateModulesModel() {
  delete lock;
}

void EnumerateModulesModel::MaybePostScanningTask() {
  static bool done = false;
  if (!done) {
    done = true;

    const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
    if (base::win::GetVersion() == base::win::VERSION_XP) {
      check_modules_timer_.Start(FROM_HERE,
          base::TimeDelta::FromMilliseconds(kModuleCheckDelayMs),
          this, &EnumerateModulesModel::ScanNow);
    }
  }
}

void EnumerateModulesModel::DoneScanning() {
  confirmed_bad_modules_detected_ = 0;
  suspected_bad_modules_detected_ = 0;
  modules_to_notify_about_ = 0;
  for (ModuleEnumerator::ModulesVector::const_iterator module =
       enumerated_modules_.begin();
       module != enumerated_modules_.end(); ++module) {
    if (module->status == ModuleEnumerator::CONFIRMED_BAD) {
      ++confirmed_bad_modules_detected_;
      if (module->recommended_action & ModuleEnumerator::NOTIFY_USER)
        ++modules_to_notify_about_;
    } else if (module->status == ModuleEnumerator::SUSPECTED_BAD) {
      ++suspected_bad_modules_detected_;
      if (module->recommended_action & ModuleEnumerator::NOTIFY_USER)
        ++modules_to_notify_about_;
    }
  }

  scanning_ = false;
  lock->Release();

  UMA_HISTOGRAM_COUNTS_100("Conflicts.SuspectedBadModules",
                           suspected_bad_modules_detected_);
  UMA_HISTOGRAM_COUNTS_100("Conflicts.ConfirmedBadModules",
                           confirmed_bad_modules_detected_);

  // Notifications are not available in limited mode.
  if (limited_mode_)
    return;

  content::NotificationService::current()->Notify(
      chrome::NOTIFICATION_MODULE_LIST_ENUMERATED,
      content::Source<EnumerateModulesModel>(this),
      content::NotificationService::NoDetails());
}

GURL EnumerateModulesModel::ConstructHelpCenterUrl(
    const ModuleEnumerator::Module& module) const {
  if (!(module.recommended_action & ModuleEnumerator::SEE_LINK) &&
      !(module.recommended_action & ModuleEnumerator::NOTIFY_USER))
    return GURL();

  // Construct the needed hashes.
  std::string filename, location, description, signer;
  GenerateHash(base::WideToUTF8(module.name), &filename);
  GenerateHash(base::WideToUTF8(module.location), &location);
  GenerateHash(base::WideToUTF8(module.description), &description);
  GenerateHash(base::WideToUTF8(module.digital_signer), &signer);

  base::string16 url =
      l10n_util::GetStringFUTF16(IDS_HELP_CENTER_VIEW_CONFLICTS,
          base::ASCIIToUTF16(filename), base::ASCIIToUTF16(location),
          base::ASCIIToUTF16(description), base::ASCIIToUTF16(signer));
  return GURL(base::UTF16ToUTF8(url));
}
