Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / chrome_elf / thunk_getter.cc
blob649fb0ca518c963e8f4d4299acca3a75dea8e964
1 // Copyright 2014 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.
5 #include <stdint.h>
6 #include <windows.h>
8 #include "base/basictypes.h"
9 #include "sandbox/win/src/interception_internal.h"
10 #include "sandbox/win/src/internal_types.h"
11 #include "sandbox/win/src/sandbox_utils.h"
12 #include "sandbox/win/src/service_resolver.h"
14 namespace {
15 enum Version {
16 VERSION_PRE_XP_SP2 = 0, // Not supported.
17 VERSION_XP_SP2,
18 VERSION_SERVER_2003, // Also includes XP Pro x64 and Server 2003 R2.
19 VERSION_VISTA, // Also includes Windows Server 2008.
20 VERSION_WIN7, // Also includes Windows Server 2008 R2.
21 VERSION_WIN8, // Also includes Windows Server 2012.
22 VERSION_WIN8_1,
23 VERSION_WIN10,
24 VERSION_WIN_LAST, // Indicates error condition.
27 // Whether a process is running under WOW64 (the wrapper that allows 32-bit
28 // processes to run on 64-bit versions of Windows). This will return
29 // WOW64_DISABLED for both "32-bit Chrome on 32-bit Windows" and "64-bit
30 // Chrome on 64-bit Windows". WOW64_UNKNOWN means "an error occurred", e.g.
31 // the process does not have sufficient access rights to determine this.
32 enum WOW64Status { WOW64_DISABLED, WOW64_ENABLED, WOW64_UNKNOWN, };
34 WOW64Status GetWOW64StatusForCurrentProcess() {
35 typedef BOOL(WINAPI * IsWow64ProcessFunc)(HANDLE, PBOOL);
36 IsWow64ProcessFunc is_wow64_process = reinterpret_cast<IsWow64ProcessFunc>(
37 GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process"));
38 if (!is_wow64_process)
39 return WOW64_DISABLED;
40 BOOL is_wow64 = FALSE;
41 if (!is_wow64_process(GetCurrentProcess(), &is_wow64))
42 return WOW64_UNKNOWN;
43 return is_wow64 ? WOW64_ENABLED : WOW64_DISABLED;
46 class OSInfo {
47 public:
48 struct VersionNumber {
49 int major;
50 int minor;
51 int build;
54 struct ServicePack {
55 int major;
56 int minor;
59 OSInfo() {
60 OSVERSIONINFOEX version_info = {sizeof(version_info)};
61 GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info));
62 version_number_.major = version_info.dwMajorVersion;
63 version_number_.minor = version_info.dwMinorVersion;
64 version_number_.build = version_info.dwBuildNumber;
65 if ((version_number_.major == 5) && (version_number_.minor > 0)) {
66 // Treat XP Pro x64, Home Server, and Server 2003 R2 as Server 2003.
67 version_ =
68 (version_number_.minor == 1) ? VERSION_XP_SP2 : VERSION_SERVER_2003;
69 if (version_ == VERSION_XP_SP2 && version_info.wServicePackMajor < 2)
70 version_ = VERSION_PRE_XP_SP2;
71 } else if (version_number_.major == 6) {
72 switch (version_number_.minor) {
73 case 0:
74 // Treat Windows Server 2008 the same as Windows Vista.
75 version_ = VERSION_VISTA;
76 break;
77 case 1:
78 // Treat Windows Server 2008 R2 the same as Windows 7.
79 version_ = VERSION_WIN7;
80 break;
81 case 2:
82 // Treat Windows Server 2012 the same as Windows 8.
83 version_ = VERSION_WIN8;
84 break;
85 default:
86 version_ = VERSION_WIN8_1;
87 break;
89 } else if (version_number_.major == 10) {
90 version_ = VERSION_WIN10;
91 } else if (version_number_.major > 6) {
92 version_ = VERSION_WIN_LAST;
93 } else {
94 version_ = VERSION_PRE_XP_SP2;
97 service_pack_.major = version_info.wServicePackMajor;
98 service_pack_.minor = version_info.wServicePackMinor;
101 Version version() const { return version_; }
102 VersionNumber version_number() const { return version_number_; }
103 ServicePack service_pack() const { return service_pack_; }
105 private:
106 Version version_;
107 VersionNumber version_number_;
108 ServicePack service_pack_;
110 DISALLOW_COPY_AND_ASSIGN(OSInfo);
113 } // namespace
115 sandbox::ServiceResolverThunk* GetThunk(bool relaxed) {
116 // Create a thunk via the appropriate ServiceResolver instance.
117 sandbox::ServiceResolverThunk* thunk = NULL;
119 // No thunks for unsupported OS versions.
120 OSInfo os_info;
121 if (os_info.version() <= VERSION_PRE_XP_SP2)
122 return thunk;
124 // Pseudo-handle, no need to close.
125 HANDLE current_process = ::GetCurrentProcess();
127 #if defined(_WIN64)
128 // ServiceResolverThunk can handle all the formats in 64-bit (instead only
129 // handling one like it does in 32-bit versions).
130 thunk = new sandbox::ServiceResolverThunk(current_process, relaxed);
131 #else
132 if (GetWOW64StatusForCurrentProcess() == WOW64_ENABLED) {
133 if (os_info.version() >= VERSION_WIN8)
134 thunk = new sandbox::Wow64W8ResolverThunk(current_process, relaxed);
135 else
136 thunk = new sandbox::Wow64ResolverThunk(current_process, relaxed);
137 } else if (os_info.version() >= VERSION_WIN8) {
138 thunk = new sandbox::Win8ResolverThunk(current_process, relaxed);
139 } else {
140 thunk = new sandbox::ServiceResolverThunk(current_process, relaxed);
142 #endif
144 return thunk;