123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// found in the LICENSE file. 423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include <stdint.h> 623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include <windows.h> 723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/basictypes.h" 923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "sandbox/win/src/interception_internal.h" 1023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "sandbox/win/src/internal_types.h" 1123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "sandbox/win/src/sandbox_utils.h" 1223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "sandbox/win/src/service_resolver.h" 1323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 1423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)namespace { 1523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)enum Version { 1623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) VERSION_PRE_XP_SP2 = 0, // Not supported. 1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) VERSION_XP_SP2, 1823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) VERSION_SERVER_2003, // Also includes XP Pro x64 and Server 2003 R2. 1923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) VERSION_VISTA, // Also includes Windows Server 2008. 2023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) VERSION_WIN7, // Also includes Windows Server 2008 R2. 2123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) VERSION_WIN8, // Also includes Windows Server 2012. 2223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) VERSION_WIN8_1, 2323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) VERSION_WIN_LAST, // Indicates error condition. 2423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}; 2523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 2623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Whether a process is running under WOW64 (the wrapper that allows 32-bit 2723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// processes to run on 64-bit versions of Windows). This will return 2823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// WOW64_DISABLED for both "32-bit Chrome on 32-bit Windows" and "64-bit 2923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Chrome on 64-bit Windows". WOW64_UNKNOWN means "an error occurred", e.g. 3023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// the process does not have sufficient access rights to determine this. 3123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)enum WOW64Status { WOW64_DISABLED, WOW64_ENABLED, WOW64_UNKNOWN, }; 3223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 3323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)WOW64Status GetWOW64StatusForCurrentProcess() { 3423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) typedef BOOL(WINAPI * IsWow64ProcessFunc)(HANDLE, PBOOL); 3523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) IsWow64ProcessFunc is_wow64_process = reinterpret_cast<IsWow64ProcessFunc>( 3623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process")); 3723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!is_wow64_process) 3823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return WOW64_DISABLED; 3923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) BOOL is_wow64 = FALSE; 4023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!is_wow64_process(GetCurrentProcess(), &is_wow64)) 4123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return WOW64_UNKNOWN; 4223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return is_wow64 ? WOW64_ENABLED : WOW64_DISABLED; 4323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 4423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 4523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)class OSInfo { 4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public: 4723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) struct VersionNumber { 4823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int major; 4923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int minor; 5023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int build; 5123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) }; 5223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 5323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) struct ServicePack { 5423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int major; 5523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int minor; 5623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) }; 5723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 5823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) OSInfo() { 5923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) OSVERSIONINFOEX version_info = {sizeof(version_info)}; 6023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info)); 6123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) version_number_.major = version_info.dwMajorVersion; 6223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) version_number_.minor = version_info.dwMinorVersion; 6323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) version_number_.build = version_info.dwBuildNumber; 6423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if ((version_number_.major == 5) && (version_number_.minor > 0)) { 6523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Treat XP Pro x64, Home Server, and Server 2003 R2 as Server 2003. 6623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) version_ = 6723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) (version_number_.minor == 1) ? VERSION_XP_SP2 : VERSION_SERVER_2003; 6823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (version_ == VERSION_XP_SP2 && version_info.wServicePackMajor < 2) 6923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) version_ = VERSION_PRE_XP_SP2; 7023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } else if (version_number_.major == 6) { 7123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) switch (version_number_.minor) { 7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) case 0: 7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Treat Windows Server 2008 the same as Windows Vista. 7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) version_ = VERSION_VISTA; 7523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) break; 7623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) case 1: 7723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Treat Windows Server 2008 R2 the same as Windows 7. 7823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) version_ = VERSION_WIN7; 7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) break; 8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) case 2: 8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Treat Windows Server 2012 the same as Windows 8. 8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) version_ = VERSION_WIN8; 8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) break; 8423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) default: 8523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) version_ = VERSION_WIN8_1; 8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) break; 8723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 8823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } else if (version_number_.major > 6) { 8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) version_ = VERSION_WIN_LAST; 9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } else { 9123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) version_ = VERSION_PRE_XP_SP2; 9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 9323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) service_pack_.major = version_info.wServicePackMajor; 9523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) service_pack_.minor = version_info.wServicePackMinor; 9623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 9723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 9823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) Version version() const { return version_; } 9923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) VersionNumber version_number() const { return version_number_; } 10023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ServicePack service_pack() const { return service_pack_; } 10123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 10223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) private: 10323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) Version version_; 10423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) VersionNumber version_number_; 10523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ServicePack service_pack_; 10623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 10723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(OSInfo); 10823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}; 10923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 11023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} // namespace 11123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 11223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)sandbox::ServiceResolverThunk* GetThunk(bool relaxed) { 11323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Create a thunk via the appropriate ServiceResolver instance. 11423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) sandbox::ServiceResolverThunk* thunk = NULL; 11523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 11623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // No thunks for unsupported OS versions. 11723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) OSInfo os_info; 11823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (os_info.version() <= VERSION_PRE_XP_SP2) 11923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return thunk; 12023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 12123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Pseudo-handle, no need to close. 12223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) HANDLE current_process = ::GetCurrentProcess(); 12323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 12423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#if defined(_WIN64) 12523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // ServiceResolverThunk can handle all the formats in 64-bit (instead only 12623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // handling one like it does in 32-bit versions). 12723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) thunk = new sandbox::ServiceResolverThunk(current_process, relaxed); 12823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#else 12923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (GetWOW64StatusForCurrentProcess() == WOW64_ENABLED) { 13023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (os_info.version() >= VERSION_WIN8) 13123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) thunk = new sandbox::Wow64W8ResolverThunk(current_process, relaxed); 13223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) else 13323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) thunk = new sandbox::Wow64ResolverThunk(current_process, relaxed); 13423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } else if (os_info.version() >= VERSION_WIN8) { 13523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) thunk = new sandbox::Win8ResolverThunk(current_process, relaxed); 13623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } else { 13723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) thunk = new sandbox::ServiceResolverThunk(current_process, relaxed); 13823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 13923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#endif 14023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 14123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return thunk; 14223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 143