1 // Copyright 2018 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/chrome_cleaner/os/scoped_disable_wow64_redirection.h" 6 7 #include "base/files/file_path.h" 8 #include "base/lazy_instance.h" 9 #include "base/logging.h" 10 #include "base/scoped_native_library.h" 11 12 namespace chrome_cleaner { 13 namespace { 14 15 // A helper class encapsulating run-time-linked function calls to Wow64 APIs. 16 class Wow64Functions { 17 public: Wow64Functions()18 Wow64Functions() 19 : kernel32_lib_(base::FilePath(L"kernel32")), 20 is_wow_64_process_(nullptr), 21 wow_64_disable_wow_64_fs_redirection_(nullptr), 22 wow_64_revert_wow_64_fs_redirection_(nullptr) { 23 if (kernel32_lib_.is_valid()) { 24 is_wow_64_process_ = reinterpret_cast<IsWow64Process>( 25 kernel32_lib_.GetFunctionPointer("IsWow64Process")); 26 wow_64_disable_wow_64_fs_redirection_ = 27 reinterpret_cast<Wow64DisableWow64FSRedirection>( 28 kernel32_lib_.GetFunctionPointer( 29 "Wow64DisableWow64FsRedirection")); 30 wow_64_revert_wow_64_fs_redirection_ = 31 reinterpret_cast<Wow64RevertWow64FSRedirection>( 32 kernel32_lib_.GetFunctionPointer( 33 "Wow64RevertWow64FsRedirection")); 34 } else { 35 PLOG(ERROR) << "Cannot open library 'kernel32'."; 36 } 37 } 38 is_valid() const39 bool is_valid() const { 40 return is_wow_64_process_ && wow_64_disable_wow_64_fs_redirection_ && 41 wow_64_revert_wow_64_fs_redirection_; 42 } 43 IsWow64() const44 bool IsWow64() const { 45 BOOL result = 0; 46 if (!is_wow_64_process_(GetCurrentProcess(), &result)) 47 PLOG(WARNING) << "IsWow64Process"; 48 return !!result; 49 } 50 DisableFsRedirection(PVOID * previous_state)51 bool DisableFsRedirection(PVOID* previous_state) { 52 return !!wow_64_disable_wow_64_fs_redirection_(previous_state); 53 } 54 RevertFsRedirection(PVOID previous_state)55 bool RevertFsRedirection(PVOID previous_state) { 56 return !!wow_64_revert_wow_64_fs_redirection_(previous_state); 57 } 58 59 private: 60 typedef BOOL(WINAPI* IsWow64Process)(HANDLE, PBOOL); 61 typedef BOOL(WINAPI* Wow64DisableWow64FSRedirection)(PVOID*); 62 typedef BOOL(WINAPI* Wow64RevertWow64FSRedirection)(PVOID); 63 64 base::ScopedNativeLibrary kernel32_lib_; 65 66 IsWow64Process is_wow_64_process_; 67 Wow64DisableWow64FSRedirection wow_64_disable_wow_64_fs_redirection_; 68 Wow64RevertWow64FSRedirection wow_64_revert_wow_64_fs_redirection_; 69 70 DISALLOW_COPY_AND_ASSIGN(Wow64Functions); 71 }; 72 73 // Global Wow64Function instance used by ScopedDisableWow64Redirection below. 74 base::LazyInstance<Wow64Functions>::Leaky g_wow_64_functions = 75 LAZY_INSTANCE_INITIALIZER; 76 77 } // namespace 78 ScopedDisableWow64Redirection()79ScopedDisableWow64Redirection::ScopedDisableWow64Redirection() 80 : active_(false), previous_state_(nullptr) { 81 Wow64Functions* wow64 = g_wow_64_functions.Pointer(); 82 if (wow64->is_valid() && wow64->IsWow64()) { 83 if (wow64->DisableFsRedirection(&previous_state_)) 84 active_ = true; 85 else 86 PLOG(WARNING) << "Wow64DisableWow64FSRedirection"; 87 } 88 } 89 ~ScopedDisableWow64Redirection()90ScopedDisableWow64Redirection::~ScopedDisableWow64Redirection() { 91 if (active_) { 92 // The Wow64 redirection needs to be reverted. In case of a failure, the 93 // process is in an invalid state where every access to the system folder 94 // will occurs to the wrong folder. This is unlikely to happen. 95 CHECK(g_wow_64_functions.Get().RevertFsRedirection(previous_state_)); 96 } 97 } 98 99 } // namespace chrome_cleaner 100