Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Unified Diff: chrome/install_static/product_install_details.cc

Issue 2422643002: Windows install_static refactor. (Closed)
Patch Set: sync to position 431863 Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/install_static/product_install_details.cc
diff --git a/chrome/install_static/product_install_details.cc b/chrome/install_static/product_install_details.cc
new file mode 100644
index 0000000000000000000000000000000000000000..81009b3882792fad860f8d36df918a30f415439a
--- /dev/null
+++ b/chrome/install_static/product_install_details.cc
@@ -0,0 +1,148 @@
+// 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/install_static/product_install_details.h"
+
+#include <windows.h>
+#include <assert.h>
+
+#include <algorithm>
+
+#include "chrome/install_static/install_modes.h"
+#include "chrome/install_static/install_util.h"
+#include "chrome_elf/nt_registry/nt_registry.h"
+
+namespace install_static {
+
+namespace {
+
+// Returns the executable path for the current process.
+std::wstring GetCurrentProcessExePath() {
+ std::wstring exe_path(MAX_PATH, L'\0');
+ DWORD length = ::GetModuleFileName(nullptr, &exe_path[0], exe_path.size());
+ if (!length)
+ return std::wstring();
+ exe_path.resize(length);
+ return exe_path;
+}
+
+const InstallConstants* FindInstallMode(const std::wstring& suffix) {
+ // Search for a mode with the matching suffix.
+ for (int i = 0; i < NUM_INSTALL_MODES; ++i) {
+ const InstallConstants& mode = kInstallModes[i];
+ if (!_wcsicmp(suffix.c_str(), mode.install_suffix))
+ return &mode;
+ }
+ // The first mode is always the default if all else fails.
+ return &kInstallModes[0];
+}
+
+} // namespace
+
+void InitializeProductDetailsForPrimaryModule() {
+ InstallDetails::SetForProcess(MakeProductDetails(GetCurrentProcessExePath()));
+}
+
+bool IsPathParentOf(const wchar_t* parent,
+ size_t parent_len,
+ const std::wstring& path) {
+ // Ignore all terminating path separators in |parent|.
+ while (parent_len && parent[parent_len - 1] == L'\\')
+ --parent_len;
+ // Pass if the parent was all separators.
+ if (!parent_len)
+ return false;
+ // This is a match if |parent| exactly matches |path| or is followed by a
+ // separator.
+ return !::wcsnicmp(path.c_str(), parent, parent_len) &&
+ (path.size() == parent_len || path[parent_len] == L'\\');
+}
+
+bool PathIsInProgramFiles(const std::wstring& path) {
+ static constexpr const wchar_t* kProgramFilesVariables[] = {
+ L"PROGRAMFILES", // With or without " (x86)" according to exe bitness.
+ L"PROGRAMFILES(X86)", // Always "C:\Program Files (x86)"
+ L"PROGRAMW6432", // Always "C:\Program Files" under WoW64.
+ };
+ wchar_t value[MAX_PATH];
+ *value = L'\0';
+ for (const wchar_t* variable : kProgramFilesVariables) {
+ *value = L'\0';
+ DWORD ret = ::GetEnvironmentVariableW(variable, value, _countof(value));
+ if (ret && ret < _countof(value) && IsPathParentOf(value, ret, path))
+ return true;
+ }
+
+ return false;
+}
+
+std::wstring GetInstallSuffix(const std::wstring& exe_path) {
+ // Search backwards from the end of the path for "\Application", using a
+ // manual search for the sake of case-insensitivity.
+ static constexpr wchar_t kInstallBinaryDir[] = L"\\Application";
+ constexpr size_t kInstallBinaryDirLength = _countof(kInstallBinaryDir) - 1;
+ if (exe_path.size() < kProductPathNameLength + kInstallBinaryDirLength)
+ return std::wstring();
+ std::wstring::const_reverse_iterator scan =
+ exe_path.crbegin() + (kInstallBinaryDirLength - 1);
+ while (_wcsnicmp(&*scan, kInstallBinaryDir, kInstallBinaryDirLength) &&
+ ++scan != exe_path.crend()) {
+ }
+ if (scan == exe_path.crend())
+ return std::wstring();
+
+ // Ensure that the dir is followed by a separator or is at the end of the
+ // path.
+ if (scan - exe_path.crbegin() != kInstallBinaryDirLength - 1 &&
+ *(scan - kInstallBinaryDirLength) != L'\\') {
+ return std::wstring();
+ }
+
+ // Scan backwards to the next separator or the beginning of the path.
+ std::wstring::const_reverse_iterator name =
+ std::find(scan + 1, exe_path.crend(), L'\\');
+ // Back up one character to ignore the separator/end of iteration.
+ if (name == exe_path.crend())
+ name = exe_path.crbegin() + exe_path.size() - 1;
+ else
+ --name;
+
+ // Check for a match of the product directory name.
+ if (_wcsnicmp(&*name, kProductPathName, kProductPathNameLength))
+ return std::wstring();
+
+ // Return the (possibly empty) suffix betwixt the product name and install
+ // binary dir.
+ return std::wstring(&*(name - kProductPathNameLength),
+ (name - scan) - kProductPathNameLength);
+}
+
+bool IsMultiInstall(const InstallConstants& mode, bool system_level) {
+ assert(mode.supports_multi_install);
+ std::wstring args;
+ return nt::QueryRegValueSZ(system_level ? nt::HKLM : nt::HKCU, nt::WOW6432,
+ GetClientStateKeyPath(mode.app_guid).c_str(),
+ L"UninstallArguments", &args) &&
+ args.find(L"--multi-install") != std::wstring::npos;
+}
+
+std::unique_ptr<PrimaryInstallDetails> MakeProductDetails(
+ const std::wstring& exe_path) {
+ std::unique_ptr<PrimaryInstallDetails> details(new PrimaryInstallDetails());
+
+ const InstallConstants* mode = FindInstallMode(GetInstallSuffix(exe_path));
+ const bool system_level =
+ mode->supports_system_level && PathIsInProgramFiles(exe_path);
+ const bool multi_install =
+ mode->supports_multi_install && IsMultiInstall(*mode, system_level);
+
+ details->set_mode(mode);
+ details->set_system_level(system_level);
+ details->set_multi_install(multi_install);
+ details->set_channel(DetermineChannel(*mode, system_level, multi_install));
+
+ return details;
+}
+
+} // namespace install_static

Powered by Google App Engine
This is Rietveld 408576698