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

Side by Side Diff: tools/performondemand/performondemand.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 | « tools/performondemand/performondemand.h ('k') | tools/proxy_clsid_utils.py » ('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 2008-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 // A simple tool for performing and interacting with on demand updates.
17 #include "omaha/tools/performondemand/performondemand.h"
18 #include <windows.h>
19 #include <sddl.h>
20 #include <shlobj.h>
21 #include <atltime.h>
22 #include <tchar.h>
23 #include "omaha/common/system.h"
24 #include "omaha/common/system_info.h"
25 #include "omaha/common/utils.h"
26 #include "omaha/common/vistautil.h"
27
28 namespace omaha {
29
30 bool ParseParams(int argc, TCHAR* argv[], CString* guid, bool* is_machine,
31 bool* is_update_check_only, int* timeout) {
32 ASSERT1(argv);
33 ASSERT1(guid);
34 ASSERT1(is_machine);
35 ASSERT1(is_update_check_only);
36 ASSERT1(timeout);
37 if (argc < 3 || argc > 5) {
38 return false;
39 }
40 *guid = argv[1];
41
42 // Verify that the guid is valid.
43 GUID parsed = StringToGuid(*guid);
44 if (parsed == GUID_NULL) {
45 return false;
46 }
47
48 *is_machine = !!_ttoi(argv[2]);
49
50 if (argc >= 4) {
51 *is_update_check_only = !!_ttoi(argv[3]);
52 } else {
53 *is_update_check_only = false;
54 }
55
56 if (argc >= 5) {
57 *timeout = _ttoi(argv[4]);
58 if (*timeout == 0) {
59 return false;
60 }
61 } else {
62 *timeout = 60;
63 }
64
65 return true;
66 }
67
68
69 DWORD SetTokenIntegrityLevelMedium(HANDLE token) {
70 PSID medium_sid = NULL;
71 if (!::ConvertStringSidToSid(SDDL_ML_MEDIUM, &medium_sid)) {
72 return ::GetLastError();
73 }
74
75 TOKEN_MANDATORY_LABEL label = {0};
76 label.Label.Attributes = SE_GROUP_INTEGRITY;
77 label.Label.Sid = medium_sid;
78
79 size_t size = sizeof(TOKEN_MANDATORY_LABEL) + ::GetLengthSid(medium_sid);
80 BOOL success = ::SetTokenInformation(token, TokenIntegrityLevel, &label,
81 size);
82 DWORD result = success ? ERROR_SUCCESS : ::GetLastError();
83 ::LocalFree(medium_sid);
84 return result;
85 }
86
87 // Reads the Proxy information for the given interface from HKCU, and registers
88 // it with COM.
89 HRESULT RegisterHKCUPSClsid(IID iid,
90 HMODULE* proxy_module,
91 DWORD* revoke_cookie) {
92 ASSERT1(proxy_module);
93 ASSERT1(revoke_cookie);
94 *proxy_module = NULL;
95 *revoke_cookie = 0;
96
97 const TCHAR* const hkcu_classes_key = _T("HKCU\\Software\\Classes\\");
98
99 // Get the registered proxy for the interface.
100 CString interface_proxy_clsid_key;
101 interface_proxy_clsid_key.Format(_T("%sInterface\\%s\\ProxyStubClsid32"),
102 hkcu_classes_key, GuidToString(iid));
103 CString proxy_clsid32_value;
104 HRESULT hr = RegKey::GetValue(interface_proxy_clsid_key,
105 NULL,
106 &proxy_clsid32_value);
107 if (FAILED(hr)) {
108 wprintf(_T("RegKey::GetValue failed [%s][0x%x]\n"),
109 interface_proxy_clsid_key, hr);
110 return hr;
111 }
112
113 // Get the location of the proxy/stub DLL.
114 CString proxy_server32_entry;
115 proxy_server32_entry.Format(_T("%sClsid\\%s\\InprocServer32"),
116 hkcu_classes_key, proxy_clsid32_value);
117 CString hkcu_proxy_dll_path;
118 hr = RegKey::GetValue(proxy_server32_entry,
119 NULL,
120 &hkcu_proxy_dll_path);
121 if (FAILED(hr)) {
122 wprintf(_T("RegKey::GetValue failed [%s][0x%x]\n"),
123 proxy_server32_entry, hr);
124 return hr;
125 }
126
127 // Get the proxy/stub class object.
128 typedef HRESULT (STDAPICALLTYPE *DllGetClassObjectTypedef)(REFCLSID clsid,
129 REFIID iid,
130 void** ptr);
131 *proxy_module = ::LoadLibrary(hkcu_proxy_dll_path);
132 DllGetClassObjectTypedef fn = NULL;
133 if (!GPA(*proxy_module, "DllGetClassObject", &fn)) {
134 hr = HRESULT_FROM_WIN32(::GetLastError());
135 wprintf(_T("GetProcAddress DllGetClassObject failed [0x%x]\n"), hr);
136 return hr;
137 }
138 CComPtr<IPSFactoryBuffer> fb;
139 CLSID proxy_clsid = StringToGuid(proxy_clsid32_value);
140 hr = (*fn)(proxy_clsid, IID_IPSFactoryBuffer, reinterpret_cast<void**>(&fb));
141 if (FAILED(hr)) {
142 wprintf(_T("DllGetClassObject failed [0x%x]\n"), hr);
143 return hr;
144 }
145
146 // Register the proxy/stub class object.
147 hr = ::CoRegisterClassObject(proxy_clsid, fb, CLSCTX_INPROC_SERVER,
148 REGCLS_MULTIPLEUSE, revoke_cookie);
149 if (FAILED(hr)) {
150 wprintf(_T("CoRegisterClassObject failed [0x%x]\n"), hr);
151 return hr;
152 }
153
154 // Relate the interface with the proxy/stub, so COM does not do a lookup when
155 // unmarshaling the interface.
156 hr = ::CoRegisterPSClsid(iid, proxy_clsid);
157 if (FAILED(hr)) {
158 wprintf(_T("CoRegisterPSClsid failed [0x%x]\n"), hr);
159 return hr;
160 }
161
162 return S_OK;
163 }
164
165 // A helper class for clients of the Omaha on-demand out-of-proc COM server.
166 // An instance of this class is typically created on the stack. The class does
167 // nothing for cases where the OS is not Vista RTM with UAC off.
168 // This class does the following:
169 // * Calls CoInitializeSecurity with cloaking set to dynamic. This makes COM
170 // use the thread token instead of the process token.
171 // * Impersonates and sets the thread token to medium integrity. This allows for
172 // out-of-proc HKCU COM server activation.
173 // * Reads and registers per-user proxies for the interfaces that on-demand
174 // exposes.
175 class VistaProxyRegistrar {
176 public:
177 VistaProxyRegistrar()
178 : googleupdate_cookie_(0),
179 jobobserver_cookie_(0),
180 progresswndevents_cookie_(0),
181 is_impersonated(false) {
182 HRESULT hr = VistaProxyRegistrarImpl();
183 if (FAILED(hr)) {
184 wprintf(_T("VistaProxyRegistrarImpl failed [0x%x]\n"), hr);
185 }
186 }
187
188 ~VistaProxyRegistrar() {
189 if (googleupdate_cookie_) {
190 VERIFY1(SUCCEEDED(::CoRevokeClassObject(googleupdate_cookie_)));
191 }
192
193 if (jobobserver_cookie_) {
194 VERIFY1(SUCCEEDED(::CoRevokeClassObject(jobobserver_cookie_)));
195 }
196
197 if (progresswndevents_cookie_) {
198 VERIFY1(SUCCEEDED(::CoRevokeClassObject(progresswndevents_cookie_)));
199 }
200
201 if (is_impersonated) {
202 VERIFY1(::RevertToSelf());
203 }
204 }
205
206 private:
207 HRESULT VistaProxyRegistrarImpl() {
208 if (!SystemInfo::IsRunningOnVistaRTM() || !::IsUserAnAdmin()) {
209 return S_OK;
210 }
211
212 bool is_split_token = false;
213 HRESULT hr = vista_util::IsUserRunningSplitToken(&is_split_token);
214 if (FAILED(hr)) {
215 return hr;
216 }
217 if (is_split_token) {
218 return S_OK;
219 }
220
221 // Needs to be called very early on in a process.
222 // Turn on dynamic cloaking so COM picks up the impersonated thread token.
223 hr = ::CoInitializeSecurity(
224 NULL,
225 -1,
226 NULL,
227 NULL,
228 RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
229 RPC_C_IMP_LEVEL_IDENTIFY,
230 NULL,
231 EOAC_DYNAMIC_CLOAKING,
232 NULL);
233 if (FAILED(hr)) {
234 wprintf(_T("[CoInitializeSecurity failed][0x%x]"), hr);
235 return hr;
236 }
237
238 is_impersonated = !!::ImpersonateSelf(SecurityImpersonation);
239 if (!is_impersonated) {
240 hr = HRESULT_FROM_WIN32(::GetLastError());
241 wprintf(_T("[main: ImpersonateSelf failed][0x%x]"), hr);
242 return hr;
243 }
244
245 scoped_handle thread_token;
246 if (!::OpenThreadToken(::GetCurrentThread(),
247 TOKEN_ALL_ACCESS,
248 false,
249 address(thread_token))) {
250 hr = HRESULT_FROM_WIN32(::GetLastError());
251 wprintf(_T("[main: OpenThreadToken failed][0x%x]"), hr);
252 return hr;
253 }
254
255 DWORD result = SetTokenIntegrityLevelMedium(get(thread_token));
256 if (result != ERROR_SUCCESS) {
257 wprintf(_T("[main: SetTokenIntegrityLevelMedium failed][0x%x]"), result);
258 return HRESULT_FROM_WIN32(result);
259 }
260
261 hr = RegisterHKCUPSClsid(__uuidof(IGoogleUpdate),
262 address(googleupdate_library_),
263 &googleupdate_cookie_);
264 if (FAILED(hr)) {
265 wprintf(_T("RegisterHKCUPSClsid for IGoogleUpdate failed [0x%x]\n"), hr);
266 return hr;
267 }
268
269 hr = RegisterHKCUPSClsid(__uuidof(IJobObserver),
270 address(jobobserver_library_),
271 &jobobserver_cookie_);
272 if (FAILED(hr)) {
273 wprintf(_T("RegisterHKCUPSClsid for IJobObserver failed [0x%x]\n"), hr);
274 return hr;
275 }
276
277 hr = RegisterHKCUPSClsid(__uuidof(IProgressWndEvents),
278 address(progresswndevents_library_),
279 &progresswndevents_cookie_);
280 if (FAILED(hr)) {
281 wprintf(_T("RegisterHKCUPSClsid for IProgressWndEvents failed [0x%x]\n"),
282 hr);
283 return hr;
284 }
285
286 return S_OK;
287 }
288
289 private:
290 scoped_library googleupdate_library_;
291 scoped_library jobobserver_library_;
292 scoped_library progresswndevents_library_;
293
294 DWORD googleupdate_cookie_;
295 DWORD jobobserver_cookie_;
296 DWORD progresswndevents_cookie_;
297 bool is_impersonated;
298 };
299
300 int DoMain(int argc, TCHAR* argv[]) {
301 CString guid;
302 bool is_machine = false;
303 bool is_update_check_only = false;
304 int timeout = 60;
305 if (!ParseParams(argc, argv, &guid, &is_machine,
306 &is_update_check_only, &timeout)) {
307 wprintf(_T("Usage: performondemand.exe {GUID} {is_machine: 0|1} ")
308 _T("[is_update_check_only=0] [timeout=60]\n"));
309 return -1;
310 }
311 wprintf(_T("GUID: %s\n"), guid);
312 CComModule module;
313 scoped_co_init com_apt;
314 VistaProxyRegistrar registrar;
315
316 CComObject<JobObserver>* job_observer;
317 HRESULT hr = CComObject<JobObserver>::CreateInstance(&job_observer);
318 if (!SUCCEEDED(hr)) {
319 wprintf(_T("CComObject<JobObserver>::CreateInstance failed [0x%x]\n"), hr);
320 return -1;
321 }
322 CComPtr<IJobObserver> job_holder(job_observer);
323
324 CComPtr<IGoogleUpdate> on_demand;
325 if (is_machine && !is_update_check_only) {
326 hr = System::CoCreateInstanceAsAdmin(NULL,
327 __uuidof(OnDemandMachineAppsClass),
328 __uuidof(on_demand),
329 reinterpret_cast<void**>(&on_demand));
330 } else {
331 hr = on_demand.CoCreateInstance(is_machine ?
332 __uuidof(OnDemandMachineAppsClass) :
333 __uuidof(OnDemandUserAppsClass));
334 }
335
336 if (!SUCCEEDED(hr)) {
337 wprintf(_T("Could not create COM instance [0x%x]\n"), hr);
338 return -1;
339 }
340
341 if (is_update_check_only) {
342 hr = on_demand->CheckForUpdate(guid, job_observer);
343 } else {
344 hr = on_demand->Update(guid, job_observer);
345 }
346
347 if (!SUCCEEDED(hr)) {
348 wprintf(_T("on_demand->%sUpdate failed [0x%x]\n"),
349 is_update_check_only ? _T("CheckFor") : _T(""), hr);
350 return -1;
351 }
352
353 // Main message loop:
354 MSG msg;
355 SYSTEMTIME start_system_time = {0};
356 SYSTEMTIME current_system_time = {0};
357 ::GetSystemTime(&start_system_time);
358 CTime start_time(start_system_time);
359 CTimeSpan timeout_period(0, 0, 0, timeout);
360
361 while (::GetMessage(&msg, NULL, 0, 0)) {
362 ::TranslateMessage(&msg);
363 ::DispatchMessage(&msg);
364 ::GetSystemTime(&current_system_time);
365 CTime current_time(current_system_time);
366 CTimeSpan elapsed_time = current_time - start_time;
367 if (timeout_period < elapsed_time) {
368 wprintf(_T("Timed out.\n"));
369 // TODO(omaha): Right now the timeout does correctly break, but then
370 // the COM interactions continue on to completion.
371 break;
372 }
373 }
374 int ret_val = job_observer->observed;
375
376 return ret_val;
377 }
378
379 } // namespace omaha
380
381 int _tmain(int argc, TCHAR* argv[]) {
382 return omaha::DoMain(argc, argv);
383 }
384
OLDNEW
« no previous file with comments | « tools/performondemand/performondemand.h ('k') | tools/proxy_clsid_utils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698