Index: google_update/winmain.cc |
diff --git a/google_update/winmain.cc b/google_update/winmain.cc |
deleted file mode 100644 |
index a307a0a4fc770e5cf4b2151990502cba9203a78a..0000000000000000000000000000000000000000 |
--- a/google_update/winmain.cc |
+++ /dev/null |
@@ -1,316 +0,0 @@ |
-// Copyright 2007-2009 Google Inc. |
-// |
-// Licensed under the Apache License, Version 2.0 (the "License"); |
-// you may not use this file except in compliance with the License. |
-// You may obtain a copy of the License at |
-// |
-// http://www.apache.org/licenses/LICENSE-2.0 |
-// |
-// Unless required by applicable law or agreed to in writing, software |
-// distributed under the License is distributed on an "AS IS" BASIS, |
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
-// See the License for the specific language governing permissions and |
-// limitations under the License. |
-// ======================================================================== |
- |
-// This is a small shell that loads a DLL calls its well known entry point. |
-// The intention is to only depend on OS mechanisms and avoid the LIBC |
-// dependency completely. |
-// This indirection is done primarily to: |
-// Play nicely with software firewalls. Most firewalls watch the executable |
-// module making network requests and we do not want them to notify the user |
-// after we've updated the program. The DLL can change independently of the |
-// shell and we expect the shell to remain unchanged most of the time. |
-// |
-// Changes to this executable will not appear in offical builds until they are |
-// included in an offical build and the resulting file is checked in to the |
-// saved shell location. |
- |
-// Disable the RTC checks because this shell doesn't build with a CRT. |
-#pragma runtime_checks("", off) |
- |
-#ifndef WIN32_LEAN_AND_MEAN |
-#define WIN32_LEAN_AND_MEAN |
-#endif |
- |
-#include <windows.h> |
-#include <shlobj.h> |
-#include <shlwapi.h> |
-#include <tchar.h> |
- |
-#include <atlbase.h> |
-#include <atlpath.h> |
-#include <atlstr.h> |
- |
-#include "omaha/base/constants.h" |
-#include "omaha/base/error.h" |
-#include "omaha/base/signaturevalidator.h" |
-#include "omaha/common/const_goopdate.h" |
- |
-// TODO(omaha3): move to common. |
-#include "omaha/goopdate/main.h" |
- |
-namespace omaha { |
- |
-// Disable the stack checks to keep the code size down. |
-// The check_stack pragma did not really work. The stack checks had to be |
-// disabled in the mk_file. |
-#pragma check_stack() |
- |
-// Have to define this here since this is used in signaturevalidator.cc. |
-// This is defined in error.cc, but that pulls in debug.cc, which has a lot |
-// of additional dependencies we do not want. Not worth it for just this |
-// function. |
-HRESULT HRESULTFromLastError() { |
- DWORD error_code = ::GetLastError(); |
- return (error_code != NO_ERROR) ? HRESULT_FROM_WIN32(error_code) : E_FAIL; |
-} |
- |
-// Adapted from File::Exists in file.cc. |
-bool FileExists(const TCHAR* file_name) { |
- if (!file_name || !*file_name) { |
- return false; |
- } |
- |
- WIN32_FILE_ATTRIBUTE_DATA attrs = {0}; |
- return 0 != ::GetFileAttributesEx(file_name, ::GetFileExInfoStandard, &attrs); |
-} |
- |
-// Adapted from vistautil.cc. |
-bool IsVistaOrLater() { |
- static bool known = false; |
- static bool is_vista = false; |
- if (!known) { |
- OSVERSIONINFOEX osvi = {0}; |
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); |
- osvi.dwMajorVersion = 6; |
- DWORDLONG conditional = 0; |
- VER_SET_CONDITION(conditional, VER_MAJORVERSION, VER_GREATER_EQUAL); |
- is_vista = !!::VerifyVersionInfo(&osvi, VER_MAJORVERSION, conditional); |
- known = true; |
- } |
- return is_vista; |
-} |
- |
-// Checking the full path vs. just being somewhere in Program Files is important |
-// because other programs may have lowered the ACLs of some subdirectories. |
-bool IsRunningFromProgramFilesDirectory() { |
- // Get the HMODULE for the current process. |
- HMODULE module_handle = ::GetModuleHandle(NULL); |
- if (!module_handle) { |
- return false; |
- } |
- |
- // Get the full path to the module based on the HMODULE. |
- CString module_path; |
- DWORD result = ::GetModuleFileName(module_handle, |
- module_path.GetBufferSetLength(MAX_PATH), |
- MAX_PATH); |
- module_handle = NULL; |
- |
- if (result == 0) { |
- return false; |
- } |
- |
- // Get the directory of the current process without the filename. |
- CPath path_temp(module_path); |
- path_temp.RemoveFileSpec(); |
- module_path = static_cast<CString>(path_temp); |
- |
- // Get the directory to %ProgramFiles%. |
- TCHAR folder_path_buffer[MAX_PATH] = {0}; |
- HRESULT hr = ::SHGetFolderPath(NULL, |
- CSIDL_PROGRAM_FILES, |
- NULL, |
- SHGFP_TYPE_CURRENT, |
- folder_path_buffer); |
- if (FAILED(hr)) { |
- return false; |
- } |
- |
- // Append the google/update install path onto %ProgramFiles%. |
- CString folder_path = folder_path_buffer; |
- if (!::PathAppend(CStrBuf(folder_path, MAX_PATH), |
- OMAHA_REL_GOOPDATE_INSTALL_DIR)) { |
- return false; |
- } |
- |
- folder_path.MakeLower(); |
- module_path.MakeLower(); |
- |
- // Check if module_path starts with folder_path. |
- return (module_path.Find(folder_path) == 0); |
-} |
- |
-// In the following case, we need to validate the signature of goopdate.dll |
-// before loading it to maintain the chain of trust: |
-// * Not running from a secure location |
-// * Vista and later |
-// * Running elevated/with admin privileges |
-// * UAC is not disabled |
-// |
-// We explicitly do not perform the authenticode check when UAC is disabled |
-// because the other conditions are all satisfied by the per-user instance of |
-// Omaha installed for a member of the admin group. Without an explicit check, |
-// an authenticode check would be performed every time the the per-user instance |
-// runs in these configurations. |
-// Skipping the authenticode check when UAC is disabled is also okay because the |
-// user has opted to let all applications run with the same privilege, so there |
-// is no need elevation of privileges. |
-// TODO(omaha): Eliminate the supported cases where this shell runs elevated |
-// from an unsecure location and replace the authenticode check with an error. |
-HRESULT VerifySignatureIfNecessary(const TCHAR* file_path, |
- bool is_running_from_secure_location) { |
- if (is_running_from_secure_location || |
- !IsVistaOrLater() || |
- !::IsUserAnAdmin()) { |
- return S_OK; |
- } |
- |
- // Verify the Authenticode signature but use only the local cache for |
- // revocation checks. |
- HRESULT hr = VerifySignature(file_path, false); |
-#if TEST_CERTIFICATE |
- // The chain of trust will not validate on builds signed with the test |
- // certificate. |
- if (CERT_E_UNTRUSTEDROOT == hr) { |
- hr = S_OK; |
- } |
-#endif |
- if (FAILED(hr)) { |
- return hr; |
- } |
- |
- // Verify that there is a Google certificate and that it has not expired. |
- if (!VerifySigneeIsGoogle(file_path)) { |
- return GOOGLEUPDATE_E_VERIFY_SIGNEE_IS_GOOGLE_FAILED; |
- } |
- |
- return S_OK; |
-} |
- |
-HRESULT GetRegisteredVersion(bool is_machine, CString* version) { |
- HKEY key = NULL; |
- LONG res = ::RegOpenKeyEx(is_machine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, |
- GOOPDATE_REG_RELATIVE_CLIENTS GOOPDATE_APP_ID, |
- 0, |
- KEY_READ, |
- &key); |
- if (ERROR_SUCCESS != res) { |
- return HRESULT_FROM_WIN32(res); |
- } |
- |
- DWORD type = 0; |
- DWORD version_length = 50; |
- res = ::SHQueryValueEx(key, |
- omaha::kRegValueProductVersion, |
- NULL, |
- &type, |
- CStrBuf(*version, version_length), |
- &version_length); |
- if (ERROR_SUCCESS != res) { |
- return HRESULT_FROM_WIN32(res); |
- } |
- |
- if (REG_SZ != type) { |
- return E_UNEXPECTED; |
- } |
- |
- return S_OK; |
-} |
- |
-HRESULT GetDllPath(HINSTANCE instance, bool is_machine, CString* dll_path) { |
- TCHAR base_path[MAX_PATH] = {0}; |
- TCHAR path[MAX_PATH] = {0}; |
- |
- if (!::GetModuleFileName(instance, base_path, arraysize(base_path))) { |
- return HRESULTFromLastError(); |
- } |
- ::PathRemoveFileSpec(base_path); |
- |
- // Try the side-by-side DLL first. |
- _tcscpy_s(path, arraysize(path), base_path); |
- if (!::PathAppend(path, omaha::kOmahaDllName)) { |
- return HRESULTFromLastError(); |
- } |
- if (FileExists(path)) { |
- *dll_path = path; |
- return S_OK; |
- } |
- |
- // Try the version subdirectory. |
- _tcscpy_s(path, arraysize(path), base_path); |
- CString version; |
- HRESULT hr = GetRegisteredVersion(is_machine, &version); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- if (!::PathAppend(path, version)) { |
- return HRESULTFromLastError(); |
- } |
- if (!::PathAppend(path, omaha::kOmahaDllName)) { |
- return HRESULTFromLastError(); |
- } |
- if (!FileExists(path)) { |
- return GOOGLEUPDATE_E_DLL_NOT_FOUND; |
- } |
- |
- *dll_path = path; |
- return S_OK; |
-} |
- |
-} // namespace omaha |
- |
-// Algorithm: |
-// * Looks for goopdate.dll in the current directory. |
-// * If it is not found, looks for goopdate.dll in a version subdirectory based |
-// on the version found in the registry. |
-// * Verifies the signature of the goopdate.dll file. |
-// * Loads the DLL and calls the entry point. |
-int WINAPI _tWinMain(HINSTANCE instance, |
- HINSTANCE, |
- LPTSTR, |
- int cmd_show) { |
- bool is_running_from_program_files = |
- omaha::IsRunningFromProgramFilesDirectory(); |
- |
- // We assume here that running from program files means we should check |
- // the machine install version and otherwise we should check the user |
- // version. This should be true in all end user cases except for initial |
- // installs from the temp directory, in which case the DLL should be in the |
- // same directory so this value does not get used. |
- // For developer use cases, the DLL should also be in the same directory. |
- bool is_machine = is_running_from_program_files; |
- |
- CString dll_path; |
- HRESULT hr = omaha::GetDllPath(instance, is_machine, &dll_path); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- |
- hr = omaha::VerifySignatureIfNecessary(dll_path, |
- is_running_from_program_files); |
- if (FAILED(hr)) { |
- return hr; |
- } |
- |
- HMODULE module(::LoadLibraryEx(dll_path, NULL, 0)); |
- if (!module) { |
- return omaha::HRESULTFromLastError(); |
- } |
- |
- DllEntry dll_entry = reinterpret_cast<DllEntry>( |
- ::GetProcAddress(module, omaha::kGoopdateDllEntryAnsi)); |
- if (dll_entry) { |
- // We must send in GetCommandLine() and not cmd_line because the command |
- // line parsing code expects to have the program name as the first argument |
- // and cmd_line does not provide this. |
- hr = dll_entry(::GetCommandLine(), cmd_show); |
- } else { |
- hr = E_FAIL; |
- } |
- |
- ::FreeLibrary(module); |
- |
- return hr; |
-} |