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

Side by Side Diff: google_update/winmain.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months 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 unified diff | Download patch
« no previous file with comments | « google_update/resource.rc ('k') | goopdate/app.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2007-2009 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 // ========================================================================
15
16 // This is a small shell that loads a DLL calls its well known entry point.
17 // The intention is to only depend on OS mechanisms and avoid the LIBC
18 // dependency completely.
19 // This indirection is done primarily to:
20 // Play nicely with software firewalls. Most firewalls watch the executable
21 // module making network requests and we do not want them to notify the user
22 // after we've updated the program. The DLL can change independently of the
23 // shell and we expect the shell to remain unchanged most of the time.
24 //
25 // Changes to this executable will not appear in offical builds until they are
26 // included in an offical build and the resulting file is checked in to the
27 // saved shell location.
28
29 // Disable the RTC checks because this shell doesn't build with a CRT.
30 #pragma runtime_checks("", off)
31
32 #ifndef WIN32_LEAN_AND_MEAN
33 #define WIN32_LEAN_AND_MEAN
34 #endif
35
36 #include <windows.h>
37 #include <shlobj.h>
38 #include <shlwapi.h>
39 #include <tchar.h>
40
41 #include <atlbase.h>
42 #include <atlpath.h>
43 #include <atlstr.h>
44
45 #include "omaha/base/constants.h"
46 #include "omaha/base/error.h"
47 #include "omaha/base/signaturevalidator.h"
48 #include "omaha/common/const_goopdate.h"
49
50 // TODO(omaha3): move to common.
51 #include "omaha/goopdate/main.h"
52
53 namespace omaha {
54
55 // Disable the stack checks to keep the code size down.
56 // The check_stack pragma did not really work. The stack checks had to be
57 // disabled in the mk_file.
58 #pragma check_stack()
59
60 // Have to define this here since this is used in signaturevalidator.cc.
61 // This is defined in error.cc, but that pulls in debug.cc, which has a lot
62 // of additional dependencies we do not want. Not worth it for just this
63 // function.
64 HRESULT HRESULTFromLastError() {
65 DWORD error_code = ::GetLastError();
66 return (error_code != NO_ERROR) ? HRESULT_FROM_WIN32(error_code) : E_FAIL;
67 }
68
69 // Adapted from File::Exists in file.cc.
70 bool FileExists(const TCHAR* file_name) {
71 if (!file_name || !*file_name) {
72 return false;
73 }
74
75 WIN32_FILE_ATTRIBUTE_DATA attrs = {0};
76 return 0 != ::GetFileAttributesEx(file_name, ::GetFileExInfoStandard, &attrs);
77 }
78
79 // Adapted from vistautil.cc.
80 bool IsVistaOrLater() {
81 static bool known = false;
82 static bool is_vista = false;
83 if (!known) {
84 OSVERSIONINFOEX osvi = {0};
85 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
86 osvi.dwMajorVersion = 6;
87 DWORDLONG conditional = 0;
88 VER_SET_CONDITION(conditional, VER_MAJORVERSION, VER_GREATER_EQUAL);
89 is_vista = !!::VerifyVersionInfo(&osvi, VER_MAJORVERSION, conditional);
90 known = true;
91 }
92 return is_vista;
93 }
94
95 // Checking the full path vs. just being somewhere in Program Files is important
96 // because other programs may have lowered the ACLs of some subdirectories.
97 bool IsRunningFromProgramFilesDirectory() {
98 // Get the HMODULE for the current process.
99 HMODULE module_handle = ::GetModuleHandle(NULL);
100 if (!module_handle) {
101 return false;
102 }
103
104 // Get the full path to the module based on the HMODULE.
105 CString module_path;
106 DWORD result = ::GetModuleFileName(module_handle,
107 module_path.GetBufferSetLength(MAX_PATH),
108 MAX_PATH);
109 module_handle = NULL;
110
111 if (result == 0) {
112 return false;
113 }
114
115 // Get the directory of the current process without the filename.
116 CPath path_temp(module_path);
117 path_temp.RemoveFileSpec();
118 module_path = static_cast<CString>(path_temp);
119
120 // Get the directory to %ProgramFiles%.
121 TCHAR folder_path_buffer[MAX_PATH] = {0};
122 HRESULT hr = ::SHGetFolderPath(NULL,
123 CSIDL_PROGRAM_FILES,
124 NULL,
125 SHGFP_TYPE_CURRENT,
126 folder_path_buffer);
127 if (FAILED(hr)) {
128 return false;
129 }
130
131 // Append the google/update install path onto %ProgramFiles%.
132 CString folder_path = folder_path_buffer;
133 if (!::PathAppend(CStrBuf(folder_path, MAX_PATH),
134 OMAHA_REL_GOOPDATE_INSTALL_DIR)) {
135 return false;
136 }
137
138 folder_path.MakeLower();
139 module_path.MakeLower();
140
141 // Check if module_path starts with folder_path.
142 return (module_path.Find(folder_path) == 0);
143 }
144
145 // In the following case, we need to validate the signature of goopdate.dll
146 // before loading it to maintain the chain of trust:
147 // * Not running from a secure location
148 // * Vista and later
149 // * Running elevated/with admin privileges
150 // * UAC is not disabled
151 //
152 // We explicitly do not perform the authenticode check when UAC is disabled
153 // because the other conditions are all satisfied by the per-user instance of
154 // Omaha installed for a member of the admin group. Without an explicit check,
155 // an authenticode check would be performed every time the the per-user instance
156 // runs in these configurations.
157 // Skipping the authenticode check when UAC is disabled is also okay because the
158 // user has opted to let all applications run with the same privilege, so there
159 // is no need elevation of privileges.
160 // TODO(omaha): Eliminate the supported cases where this shell runs elevated
161 // from an unsecure location and replace the authenticode check with an error.
162 HRESULT VerifySignatureIfNecessary(const TCHAR* file_path,
163 bool is_running_from_secure_location) {
164 if (is_running_from_secure_location ||
165 !IsVistaOrLater() ||
166 !::IsUserAnAdmin()) {
167 return S_OK;
168 }
169
170 // Verify the Authenticode signature but use only the local cache for
171 // revocation checks.
172 HRESULT hr = VerifySignature(file_path, false);
173 #if TEST_CERTIFICATE
174 // The chain of trust will not validate on builds signed with the test
175 // certificate.
176 if (CERT_E_UNTRUSTEDROOT == hr) {
177 hr = S_OK;
178 }
179 #endif
180 if (FAILED(hr)) {
181 return hr;
182 }
183
184 // Verify that there is a Google certificate and that it has not expired.
185 if (!VerifySigneeIsGoogle(file_path)) {
186 return GOOGLEUPDATE_E_VERIFY_SIGNEE_IS_GOOGLE_FAILED;
187 }
188
189 return S_OK;
190 }
191
192 HRESULT GetRegisteredVersion(bool is_machine, CString* version) {
193 HKEY key = NULL;
194 LONG res = ::RegOpenKeyEx(is_machine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
195 GOOPDATE_REG_RELATIVE_CLIENTS GOOPDATE_APP_ID,
196 0,
197 KEY_READ,
198 &key);
199 if (ERROR_SUCCESS != res) {
200 return HRESULT_FROM_WIN32(res);
201 }
202
203 DWORD type = 0;
204 DWORD version_length = 50;
205 res = ::SHQueryValueEx(key,
206 omaha::kRegValueProductVersion,
207 NULL,
208 &type,
209 CStrBuf(*version, version_length),
210 &version_length);
211 if (ERROR_SUCCESS != res) {
212 return HRESULT_FROM_WIN32(res);
213 }
214
215 if (REG_SZ != type) {
216 return E_UNEXPECTED;
217 }
218
219 return S_OK;
220 }
221
222 HRESULT GetDllPath(HINSTANCE instance, bool is_machine, CString* dll_path) {
223 TCHAR base_path[MAX_PATH] = {0};
224 TCHAR path[MAX_PATH] = {0};
225
226 if (!::GetModuleFileName(instance, base_path, arraysize(base_path))) {
227 return HRESULTFromLastError();
228 }
229 ::PathRemoveFileSpec(base_path);
230
231 // Try the side-by-side DLL first.
232 _tcscpy_s(path, arraysize(path), base_path);
233 if (!::PathAppend(path, omaha::kOmahaDllName)) {
234 return HRESULTFromLastError();
235 }
236 if (FileExists(path)) {
237 *dll_path = path;
238 return S_OK;
239 }
240
241 // Try the version subdirectory.
242 _tcscpy_s(path, arraysize(path), base_path);
243 CString version;
244 HRESULT hr = GetRegisteredVersion(is_machine, &version);
245 if (FAILED(hr)) {
246 return hr;
247 }
248 if (!::PathAppend(path, version)) {
249 return HRESULTFromLastError();
250 }
251 if (!::PathAppend(path, omaha::kOmahaDllName)) {
252 return HRESULTFromLastError();
253 }
254 if (!FileExists(path)) {
255 return GOOGLEUPDATE_E_DLL_NOT_FOUND;
256 }
257
258 *dll_path = path;
259 return S_OK;
260 }
261
262 } // namespace omaha
263
264 // Algorithm:
265 // * Looks for goopdate.dll in the current directory.
266 // * If it is not found, looks for goopdate.dll in a version subdirectory based
267 // on the version found in the registry.
268 // * Verifies the signature of the goopdate.dll file.
269 // * Loads the DLL and calls the entry point.
270 int WINAPI _tWinMain(HINSTANCE instance,
271 HINSTANCE,
272 LPTSTR,
273 int cmd_show) {
274 bool is_running_from_program_files =
275 omaha::IsRunningFromProgramFilesDirectory();
276
277 // We assume here that running from program files means we should check
278 // the machine install version and otherwise we should check the user
279 // version. This should be true in all end user cases except for initial
280 // installs from the temp directory, in which case the DLL should be in the
281 // same directory so this value does not get used.
282 // For developer use cases, the DLL should also be in the same directory.
283 bool is_machine = is_running_from_program_files;
284
285 CString dll_path;
286 HRESULT hr = omaha::GetDllPath(instance, is_machine, &dll_path);
287 if (FAILED(hr)) {
288 return hr;
289 }
290
291 hr = omaha::VerifySignatureIfNecessary(dll_path,
292 is_running_from_program_files);
293 if (FAILED(hr)) {
294 return hr;
295 }
296
297 HMODULE module(::LoadLibraryEx(dll_path, NULL, 0));
298 if (!module) {
299 return omaha::HRESULTFromLastError();
300 }
301
302 DllEntry dll_entry = reinterpret_cast<DllEntry>(
303 ::GetProcAddress(module, omaha::kGoopdateDllEntryAnsi));
304 if (dll_entry) {
305 // We must send in GetCommandLine() and not cmd_line because the command
306 // line parsing code expects to have the program name as the first argument
307 // and cmd_line does not provide this.
308 hr = dll_entry(::GetCommandLine(), cmd_show);
309 } else {
310 hr = E_FAIL;
311 }
312
313 ::FreeLibrary(module);
314
315 return hr;
316 }
OLDNEW
« no previous file with comments | « google_update/resource.rc ('k') | goopdate/app.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698