| Index: tools/performondemand/performondemand.cc
|
| diff --git a/tools/performondemand/performondemand.cc b/tools/performondemand/performondemand.cc
|
| deleted file mode 100644
|
| index ea40bfe57a6b5dae1c954f78ebdc7c5d07921fb2..0000000000000000000000000000000000000000
|
| --- a/tools/performondemand/performondemand.cc
|
| +++ /dev/null
|
| @@ -1,384 +0,0 @@
|
| -// Copyright 2008-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.
|
| -// ========================================================================
|
| -//
|
| -// A simple tool for performing and interacting with on demand updates.
|
| -#include "omaha/tools/performondemand/performondemand.h"
|
| -#include <windows.h>
|
| -#include <sddl.h>
|
| -#include <shlobj.h>
|
| -#include <atltime.h>
|
| -#include <tchar.h>
|
| -#include "omaha/common/system.h"
|
| -#include "omaha/common/system_info.h"
|
| -#include "omaha/common/utils.h"
|
| -#include "omaha/common/vistautil.h"
|
| -
|
| -namespace omaha {
|
| -
|
| -bool ParseParams(int argc, TCHAR* argv[], CString* guid, bool* is_machine,
|
| - bool* is_update_check_only, int* timeout) {
|
| - ASSERT1(argv);
|
| - ASSERT1(guid);
|
| - ASSERT1(is_machine);
|
| - ASSERT1(is_update_check_only);
|
| - ASSERT1(timeout);
|
| - if (argc < 3 || argc > 5) {
|
| - return false;
|
| - }
|
| - *guid = argv[1];
|
| -
|
| - // Verify that the guid is valid.
|
| - GUID parsed = StringToGuid(*guid);
|
| - if (parsed == GUID_NULL) {
|
| - return false;
|
| - }
|
| -
|
| - *is_machine = !!_ttoi(argv[2]);
|
| -
|
| - if (argc >= 4) {
|
| - *is_update_check_only = !!_ttoi(argv[3]);
|
| - } else {
|
| - *is_update_check_only = false;
|
| - }
|
| -
|
| - if (argc >= 5) {
|
| - *timeout = _ttoi(argv[4]);
|
| - if (*timeout == 0) {
|
| - return false;
|
| - }
|
| - } else {
|
| - *timeout = 60;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -
|
| -DWORD SetTokenIntegrityLevelMedium(HANDLE token) {
|
| - PSID medium_sid = NULL;
|
| - if (!::ConvertStringSidToSid(SDDL_ML_MEDIUM, &medium_sid)) {
|
| - return ::GetLastError();
|
| - }
|
| -
|
| - TOKEN_MANDATORY_LABEL label = {0};
|
| - label.Label.Attributes = SE_GROUP_INTEGRITY;
|
| - label.Label.Sid = medium_sid;
|
| -
|
| - size_t size = sizeof(TOKEN_MANDATORY_LABEL) + ::GetLengthSid(medium_sid);
|
| - BOOL success = ::SetTokenInformation(token, TokenIntegrityLevel, &label,
|
| - size);
|
| - DWORD result = success ? ERROR_SUCCESS : ::GetLastError();
|
| - ::LocalFree(medium_sid);
|
| - return result;
|
| -}
|
| -
|
| -// Reads the Proxy information for the given interface from HKCU, and registers
|
| -// it with COM.
|
| -HRESULT RegisterHKCUPSClsid(IID iid,
|
| - HMODULE* proxy_module,
|
| - DWORD* revoke_cookie) {
|
| - ASSERT1(proxy_module);
|
| - ASSERT1(revoke_cookie);
|
| - *proxy_module = NULL;
|
| - *revoke_cookie = 0;
|
| -
|
| - const TCHAR* const hkcu_classes_key = _T("HKCU\\Software\\Classes\\");
|
| -
|
| - // Get the registered proxy for the interface.
|
| - CString interface_proxy_clsid_key;
|
| - interface_proxy_clsid_key.Format(_T("%sInterface\\%s\\ProxyStubClsid32"),
|
| - hkcu_classes_key, GuidToString(iid));
|
| - CString proxy_clsid32_value;
|
| - HRESULT hr = RegKey::GetValue(interface_proxy_clsid_key,
|
| - NULL,
|
| - &proxy_clsid32_value);
|
| - if (FAILED(hr)) {
|
| - wprintf(_T("RegKey::GetValue failed [%s][0x%x]\n"),
|
| - interface_proxy_clsid_key, hr);
|
| - return hr;
|
| - }
|
| -
|
| - // Get the location of the proxy/stub DLL.
|
| - CString proxy_server32_entry;
|
| - proxy_server32_entry.Format(_T("%sClsid\\%s\\InprocServer32"),
|
| - hkcu_classes_key, proxy_clsid32_value);
|
| - CString hkcu_proxy_dll_path;
|
| - hr = RegKey::GetValue(proxy_server32_entry,
|
| - NULL,
|
| - &hkcu_proxy_dll_path);
|
| - if (FAILED(hr)) {
|
| - wprintf(_T("RegKey::GetValue failed [%s][0x%x]\n"),
|
| - proxy_server32_entry, hr);
|
| - return hr;
|
| - }
|
| -
|
| - // Get the proxy/stub class object.
|
| - typedef HRESULT (STDAPICALLTYPE *DllGetClassObjectTypedef)(REFCLSID clsid,
|
| - REFIID iid,
|
| - void** ptr);
|
| - *proxy_module = ::LoadLibrary(hkcu_proxy_dll_path);
|
| - DllGetClassObjectTypedef fn = NULL;
|
| - if (!GPA(*proxy_module, "DllGetClassObject", &fn)) {
|
| - hr = HRESULT_FROM_WIN32(::GetLastError());
|
| - wprintf(_T("GetProcAddress DllGetClassObject failed [0x%x]\n"), hr);
|
| - return hr;
|
| - }
|
| - CComPtr<IPSFactoryBuffer> fb;
|
| - CLSID proxy_clsid = StringToGuid(proxy_clsid32_value);
|
| - hr = (*fn)(proxy_clsid, IID_IPSFactoryBuffer, reinterpret_cast<void**>(&fb));
|
| - if (FAILED(hr)) {
|
| - wprintf(_T("DllGetClassObject failed [0x%x]\n"), hr);
|
| - return hr;
|
| - }
|
| -
|
| - // Register the proxy/stub class object.
|
| - hr = ::CoRegisterClassObject(proxy_clsid, fb, CLSCTX_INPROC_SERVER,
|
| - REGCLS_MULTIPLEUSE, revoke_cookie);
|
| - if (FAILED(hr)) {
|
| - wprintf(_T("CoRegisterClassObject failed [0x%x]\n"), hr);
|
| - return hr;
|
| - }
|
| -
|
| - // Relate the interface with the proxy/stub, so COM does not do a lookup when
|
| - // unmarshaling the interface.
|
| - hr = ::CoRegisterPSClsid(iid, proxy_clsid);
|
| - if (FAILED(hr)) {
|
| - wprintf(_T("CoRegisterPSClsid failed [0x%x]\n"), hr);
|
| - return hr;
|
| - }
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -// A helper class for clients of the Omaha on-demand out-of-proc COM server.
|
| -// An instance of this class is typically created on the stack. The class does
|
| -// nothing for cases where the OS is not Vista RTM with UAC off.
|
| -// This class does the following:
|
| -// * Calls CoInitializeSecurity with cloaking set to dynamic. This makes COM
|
| -// use the thread token instead of the process token.
|
| -// * Impersonates and sets the thread token to medium integrity. This allows for
|
| -// out-of-proc HKCU COM server activation.
|
| -// * Reads and registers per-user proxies for the interfaces that on-demand
|
| -// exposes.
|
| -class VistaProxyRegistrar {
|
| - public:
|
| - VistaProxyRegistrar()
|
| - : googleupdate_cookie_(0),
|
| - jobobserver_cookie_(0),
|
| - progresswndevents_cookie_(0),
|
| - is_impersonated(false) {
|
| - HRESULT hr = VistaProxyRegistrarImpl();
|
| - if (FAILED(hr)) {
|
| - wprintf(_T("VistaProxyRegistrarImpl failed [0x%x]\n"), hr);
|
| - }
|
| - }
|
| -
|
| - ~VistaProxyRegistrar() {
|
| - if (googleupdate_cookie_) {
|
| - VERIFY1(SUCCEEDED(::CoRevokeClassObject(googleupdate_cookie_)));
|
| - }
|
| -
|
| - if (jobobserver_cookie_) {
|
| - VERIFY1(SUCCEEDED(::CoRevokeClassObject(jobobserver_cookie_)));
|
| - }
|
| -
|
| - if (progresswndevents_cookie_) {
|
| - VERIFY1(SUCCEEDED(::CoRevokeClassObject(progresswndevents_cookie_)));
|
| - }
|
| -
|
| - if (is_impersonated) {
|
| - VERIFY1(::RevertToSelf());
|
| - }
|
| - }
|
| -
|
| - private:
|
| - HRESULT VistaProxyRegistrarImpl() {
|
| - if (!SystemInfo::IsRunningOnVistaRTM() || !::IsUserAnAdmin()) {
|
| - return S_OK;
|
| - }
|
| -
|
| - bool is_split_token = false;
|
| - HRESULT hr = vista_util::IsUserRunningSplitToken(&is_split_token);
|
| - if (FAILED(hr)) {
|
| - return hr;
|
| - }
|
| - if (is_split_token) {
|
| - return S_OK;
|
| - }
|
| -
|
| - // Needs to be called very early on in a process.
|
| - // Turn on dynamic cloaking so COM picks up the impersonated thread token.
|
| - hr = ::CoInitializeSecurity(
|
| - NULL,
|
| - -1,
|
| - NULL,
|
| - NULL,
|
| - RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
|
| - RPC_C_IMP_LEVEL_IDENTIFY,
|
| - NULL,
|
| - EOAC_DYNAMIC_CLOAKING,
|
| - NULL);
|
| - if (FAILED(hr)) {
|
| - wprintf(_T("[CoInitializeSecurity failed][0x%x]"), hr);
|
| - return hr;
|
| - }
|
| -
|
| - is_impersonated = !!::ImpersonateSelf(SecurityImpersonation);
|
| - if (!is_impersonated) {
|
| - hr = HRESULT_FROM_WIN32(::GetLastError());
|
| - wprintf(_T("[main: ImpersonateSelf failed][0x%x]"), hr);
|
| - return hr;
|
| - }
|
| -
|
| - scoped_handle thread_token;
|
| - if (!::OpenThreadToken(::GetCurrentThread(),
|
| - TOKEN_ALL_ACCESS,
|
| - false,
|
| - address(thread_token))) {
|
| - hr = HRESULT_FROM_WIN32(::GetLastError());
|
| - wprintf(_T("[main: OpenThreadToken failed][0x%x]"), hr);
|
| - return hr;
|
| - }
|
| -
|
| - DWORD result = SetTokenIntegrityLevelMedium(get(thread_token));
|
| - if (result != ERROR_SUCCESS) {
|
| - wprintf(_T("[main: SetTokenIntegrityLevelMedium failed][0x%x]"), result);
|
| - return HRESULT_FROM_WIN32(result);
|
| - }
|
| -
|
| - hr = RegisterHKCUPSClsid(__uuidof(IGoogleUpdate),
|
| - address(googleupdate_library_),
|
| - &googleupdate_cookie_);
|
| - if (FAILED(hr)) {
|
| - wprintf(_T("RegisterHKCUPSClsid for IGoogleUpdate failed [0x%x]\n"), hr);
|
| - return hr;
|
| - }
|
| -
|
| - hr = RegisterHKCUPSClsid(__uuidof(IJobObserver),
|
| - address(jobobserver_library_),
|
| - &jobobserver_cookie_);
|
| - if (FAILED(hr)) {
|
| - wprintf(_T("RegisterHKCUPSClsid for IJobObserver failed [0x%x]\n"), hr);
|
| - return hr;
|
| - }
|
| -
|
| - hr = RegisterHKCUPSClsid(__uuidof(IProgressWndEvents),
|
| - address(progresswndevents_library_),
|
| - &progresswndevents_cookie_);
|
| - if (FAILED(hr)) {
|
| - wprintf(_T("RegisterHKCUPSClsid for IProgressWndEvents failed [0x%x]\n"),
|
| - hr);
|
| - return hr;
|
| - }
|
| -
|
| - return S_OK;
|
| - }
|
| -
|
| - private:
|
| - scoped_library googleupdate_library_;
|
| - scoped_library jobobserver_library_;
|
| - scoped_library progresswndevents_library_;
|
| -
|
| - DWORD googleupdate_cookie_;
|
| - DWORD jobobserver_cookie_;
|
| - DWORD progresswndevents_cookie_;
|
| - bool is_impersonated;
|
| -};
|
| -
|
| -int DoMain(int argc, TCHAR* argv[]) {
|
| - CString guid;
|
| - bool is_machine = false;
|
| - bool is_update_check_only = false;
|
| - int timeout = 60;
|
| - if (!ParseParams(argc, argv, &guid, &is_machine,
|
| - &is_update_check_only, &timeout)) {
|
| - wprintf(_T("Usage: performondemand.exe {GUID} {is_machine: 0|1} ")
|
| - _T("[is_update_check_only=0] [timeout=60]\n"));
|
| - return -1;
|
| - }
|
| - wprintf(_T("GUID: %s\n"), guid);
|
| - CComModule module;
|
| - scoped_co_init com_apt;
|
| - VistaProxyRegistrar registrar;
|
| -
|
| - CComObject<JobObserver>* job_observer;
|
| - HRESULT hr = CComObject<JobObserver>::CreateInstance(&job_observer);
|
| - if (!SUCCEEDED(hr)) {
|
| - wprintf(_T("CComObject<JobObserver>::CreateInstance failed [0x%x]\n"), hr);
|
| - return -1;
|
| - }
|
| - CComPtr<IJobObserver> job_holder(job_observer);
|
| -
|
| - CComPtr<IGoogleUpdate> on_demand;
|
| - if (is_machine && !is_update_check_only) {
|
| - hr = System::CoCreateInstanceAsAdmin(NULL,
|
| - __uuidof(OnDemandMachineAppsClass),
|
| - __uuidof(on_demand),
|
| - reinterpret_cast<void**>(&on_demand));
|
| - } else {
|
| - hr = on_demand.CoCreateInstance(is_machine ?
|
| - __uuidof(OnDemandMachineAppsClass) :
|
| - __uuidof(OnDemandUserAppsClass));
|
| - }
|
| -
|
| - if (!SUCCEEDED(hr)) {
|
| - wprintf(_T("Could not create COM instance [0x%x]\n"), hr);
|
| - return -1;
|
| - }
|
| -
|
| - if (is_update_check_only) {
|
| - hr = on_demand->CheckForUpdate(guid, job_observer);
|
| - } else {
|
| - hr = on_demand->Update(guid, job_observer);
|
| - }
|
| -
|
| - if (!SUCCEEDED(hr)) {
|
| - wprintf(_T("on_demand->%sUpdate failed [0x%x]\n"),
|
| - is_update_check_only ? _T("CheckFor") : _T(""), hr);
|
| - return -1;
|
| - }
|
| -
|
| - // Main message loop:
|
| - MSG msg;
|
| - SYSTEMTIME start_system_time = {0};
|
| - SYSTEMTIME current_system_time = {0};
|
| - ::GetSystemTime(&start_system_time);
|
| - CTime start_time(start_system_time);
|
| - CTimeSpan timeout_period(0, 0, 0, timeout);
|
| -
|
| - while (::GetMessage(&msg, NULL, 0, 0)) {
|
| - ::TranslateMessage(&msg);
|
| - ::DispatchMessage(&msg);
|
| - ::GetSystemTime(¤t_system_time);
|
| - CTime current_time(current_system_time);
|
| - CTimeSpan elapsed_time = current_time - start_time;
|
| - if (timeout_period < elapsed_time) {
|
| - wprintf(_T("Timed out.\n"));
|
| - // TODO(omaha): Right now the timeout does correctly break, but then
|
| - // the COM interactions continue on to completion.
|
| - break;
|
| - }
|
| - }
|
| - int ret_val = job_observer->observed;
|
| -
|
| - return ret_val;
|
| -}
|
| -
|
| -} // namespace omaha
|
| -
|
| -int _tmain(int argc, TCHAR* argv[]) {
|
| - return omaha::DoMain(argc, argv);
|
| -}
|
| -
|
|
|