blob: 8ee4aa91298b07da67e318d1aaeb05d44985406d [file] [log] [blame]
// Copyright 2018 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/chrome_cleaner/os/scoped_disable_wow64_redirection.h"
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "base/scoped_native_library.h"
namespace chrome_cleaner {
namespace {
// A helper class encapsulating run-time-linked function calls to Wow64 APIs.
class Wow64Functions {
public:
Wow64Functions()
: kernel32_lib_(base::FilePath(L"kernel32")),
is_wow_64_process_(nullptr),
wow_64_disable_wow_64_fs_redirection_(nullptr),
wow_64_revert_wow_64_fs_redirection_(nullptr) {
if (kernel32_lib_.is_valid()) {
is_wow_64_process_ = reinterpret_cast<IsWow64Process>(
kernel32_lib_.GetFunctionPointer("IsWow64Process"));
wow_64_disable_wow_64_fs_redirection_ =
reinterpret_cast<Wow64DisableWow64FSRedirection>(
kernel32_lib_.GetFunctionPointer(
"Wow64DisableWow64FsRedirection"));
wow_64_revert_wow_64_fs_redirection_ =
reinterpret_cast<Wow64RevertWow64FSRedirection>(
kernel32_lib_.GetFunctionPointer(
"Wow64RevertWow64FsRedirection"));
} else {
PLOG(ERROR) << "Cannot open library 'kernel32'.";
}
}
bool is_valid() const {
return is_wow_64_process_ && wow_64_disable_wow_64_fs_redirection_ &&
wow_64_revert_wow_64_fs_redirection_;
}
bool IsWow64() const {
BOOL result = 0;
if (!is_wow_64_process_(GetCurrentProcess(), &result))
PLOG(WARNING) << "IsWow64Process";
return !!result;
}
bool DisableFsRedirection(PVOID* previous_state) {
return !!wow_64_disable_wow_64_fs_redirection_(previous_state);
}
bool RevertFsRedirection(PVOID previous_state) {
return !!wow_64_revert_wow_64_fs_redirection_(previous_state);
}
private:
typedef BOOL(WINAPI* IsWow64Process)(HANDLE, PBOOL);
typedef BOOL(WINAPI* Wow64DisableWow64FSRedirection)(PVOID*);
typedef BOOL(WINAPI* Wow64RevertWow64FSRedirection)(PVOID);
base::ScopedNativeLibrary kernel32_lib_;
IsWow64Process is_wow_64_process_;
Wow64DisableWow64FSRedirection wow_64_disable_wow_64_fs_redirection_;
Wow64RevertWow64FSRedirection wow_64_revert_wow_64_fs_redirection_;
DISALLOW_COPY_AND_ASSIGN(Wow64Functions);
};
// Global Wow64Function instance used by ScopedDisableWow64Redirection below.
base::LazyInstance<Wow64Functions>::Leaky g_wow_64_functions =
LAZY_INSTANCE_INITIALIZER;
} // namespace
ScopedDisableWow64Redirection::ScopedDisableWow64Redirection()
: active_(false), previous_state_(nullptr) {
Wow64Functions* wow64 = g_wow_64_functions.Pointer();
if (wow64->is_valid() && wow64->IsWow64()) {
if (wow64->DisableFsRedirection(&previous_state_))
active_ = true;
else
PLOG(WARNING) << "Wow64DisableWow64FSRedirection";
}
}
ScopedDisableWow64Redirection::~ScopedDisableWow64Redirection() {
if (active_) {
// The Wow64 redirection needs to be reverted. In case of a failure, the
// process is in an invalid state where every access to the system folder
// will occurs to the wrong folder. This is unlikely to happen.
CHECK(g_wow_64_functions.Get().RevertFsRedirection(previous_state_));
}
}
} // namespace chrome_cleaner