| 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;
|
| -}
|
|
|