OLD | NEW |
| (Empty) |
1 // Copyright 2003-2010 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 #ifndef OMAHA_BASE_UTILS_H_ | |
17 #define OMAHA_BASE_UTILS_H_ | |
18 | |
19 #include <windows.h> | |
20 #include <accctrl.h> | |
21 #include <aclapi.h> | |
22 #include <sddl.h> | |
23 #include <shellapi.h> | |
24 #include <shlobj.h> | |
25 #include <atlstr.h> | |
26 #include <atlsecurity.h> | |
27 #include <atlwin.h> | |
28 #include <memory.h> | |
29 #include <map> | |
30 #include <vector> | |
31 #include "base/basictypes.h" | |
32 #include "omaha/base/constants.h" | |
33 #include "omaha/base/debug.h" | |
34 #include "omaha/base/logging.h" | |
35 #include "omaha/base/reg_key.h" | |
36 #include "omaha/base/scoped_any.h" | |
37 #include "omaha/base/static_assert.h" | |
38 #include "omaha/base/user_info.h" | |
39 | |
40 namespace omaha { | |
41 | |
42 // These definitions are not in any current Microsoft SDK header file. Taken | |
43 // from platformsdk/v6_1/files/Include/ObjIdl.h. | |
44 MIDL_INTERFACE("0000015B-0000-0000-C000-000000000046") | |
45 IGlobalOptions : public IUnknown { | |
46 public: | |
47 virtual HRESULT STDMETHODCALLTYPE Set( | |
48 /* [in] */ DWORD dwProperty, | |
49 /* [in] */ ULONG_PTR dwValue) = 0; | |
50 | |
51 virtual HRESULT STDMETHODCALLTYPE Query( | |
52 /* [in] */ DWORD dwProperty, | |
53 /* [out] */ ULONG_PTR *pdwValue) = 0; | |
54 }; | |
55 | |
56 enum __MIDL___MIDL_itf_objidl_0000_0047_0001 { | |
57 COMGLB_EXCEPTION_HANDLING = 1, | |
58 COMGLB_APPID = 2 | |
59 }; | |
60 | |
61 enum __MIDL___MIDL_itf_objidl_0000_0047_0002 { | |
62 COMGLB_EXCEPTION_HANDLE = 0, | |
63 COMGLB_EXCEPTION_DONOT_HANDLE = 1 | |
64 }; | |
65 | |
66 // Determines whether to run ClickOnce components. This constant is not defined | |
67 // in the SDK headers. | |
68 #ifndef URLACTION_MANAGED_UNSIGNED | |
69 #define URLACTION_MANAGED_UNSIGNED (0x00002004) | |
70 #endif | |
71 | |
72 ULONGLONG VersionFromString(const CString& s); | |
73 | |
74 CString StringFromVersion(ULONGLONG version); | |
75 | |
76 // Gets current directory | |
77 CString GetCurrentDir(); | |
78 | |
79 // Creates a unique file name using a new guid. Does not check for | |
80 // presence of this file in the directory. | |
81 HRESULT GetNewFileNameInDirectory(const CString& dir, CString* file_name); | |
82 | |
83 // Gets security descriptor with a DACL that grants the admin_access_mask to | |
84 // Admins and System, and the non_admin_access_mask to Interactive. | |
85 void GetEveryoneDaclSecurityDescriptor(CSecurityDesc* sd, | |
86 ACCESS_MASK admin_access_mask, | |
87 ACCESS_MASK non_admin_access_mask); | |
88 | |
89 // Get security descriptor containing a DACL that grants the ACCESS_MASK access | |
90 // to admins and system. | |
91 void GetAdminDaclSecurityDescriptor(CSecurityDesc* sd, ACCESS_MASK accessmask); | |
92 | |
93 // Get security attributes containing a DACL that grant the ACCESS_MASK access | |
94 // to admins and system. | |
95 void GetAdminDaclSecurityAttributes(CSecurityAttributes* sec_attr, | |
96 ACCESS_MASK accessmask); | |
97 | |
98 // This method is intended to be called by same or lower integrity COM clients. | |
99 // Calls ::CoInitializeSecurity with the default DACL. Servers are allowed to | |
100 // impersonate the client. | |
101 HRESULT InitializeClientSecurity(); | |
102 | |
103 // This method calls ::CoInitializeSecurity with security settings and ACLs of | |
104 // callers that are allowed access to the COM server. Clients can only identify | |
105 // the server, and custom marshaling as well as activate-as-activator are | |
106 // disallowed. | |
107 // * If the bool is set, a DACL that provides COM_RIGHTS_EXECUTE access | |
108 // for medium-integrity callers is set. | |
109 // * If the bool is not set, but the caller is Local System, the function will | |
110 // set a security descriptor that also allows the Administrators group access to | |
111 // the COM server. | |
112 HRESULT InitializeServerSecurity(bool allow_calls_from_medium); | |
113 | |
114 // Ensures that the COM marshaling machinery does not eat crashes. | |
115 HRESULT DisableCOMExceptionHandling(); | |
116 | |
117 // Merges an Allowed ACE into a named object. If the ACE already exists in the | |
118 // DACL with the same permissions (or a superset) and the same ACE flags, the | |
119 // merge is skipped. | |
120 HRESULT AddAllowedAce(const TCHAR* object_name, | |
121 SE_OBJECT_TYPE object_type, | |
122 const CSid& sid, | |
123 ACCESS_MASK required_permissions, | |
124 uint8 required_ace_flags); | |
125 | |
126 struct NamedObjectAttributes { | |
127 CString name; | |
128 CSecurityAttributes sa; | |
129 }; | |
130 | |
131 // For machine and local system, the prefix would be "Global\G{obj_name}". | |
132 // For user, the prefix would be "Global\G{user_sid}{obj_name}". | |
133 // For machine objects, returns a security attributes that gives permissions to | |
134 // both Admins and SYSTEM. This allows for cases where SYSTEM creates the named | |
135 // object first. The default DACL for SYSTEM will not allow Admins access. | |
136 void GetNamedObjectAttributes(const TCHAR* base_name, | |
137 bool is_machine, | |
138 NamedObjectAttributes* attr); | |
139 | |
140 // Returns true if the current process is running as SYSTEM. | |
141 HRESULT IsSystemProcess(bool* is_system_process); | |
142 | |
143 // Returns true if the user of the current process is Local System or it has an | |
144 // interactive session: console, terminal services, or fast user switching. | |
145 HRESULT IsUserLoggedOn(bool* is_logged_on); | |
146 | |
147 // Returns true if URLACTION_MANAGED_UNSIGNED is disabled for the Internet zone | |
148 // for the current user. | |
149 bool IsClickOnceDisabled(); | |
150 | |
151 // Wrapper around ::GetProcAddress(). | |
152 template <typename T> | |
153 bool GPA(HMODULE module, const char* function_name, T* function_pointer) { | |
154 ASSERT1(module); | |
155 ASSERT1(function_name); | |
156 ASSERT1(function_pointer); | |
157 | |
158 *function_pointer = reinterpret_cast<T>(::GetProcAddress(module, | |
159 function_name)); | |
160 if (NULL == *function_pointer) { | |
161 UTIL_LOG(LW, (_T("GetProcAddress failed [%s]"), CA2T(function_name))); | |
162 } | |
163 return NULL != *function_pointer; | |
164 } | |
165 | |
166 #define GPA_WRAP(module, \ | |
167 function, \ | |
168 proto, \ | |
169 call, \ | |
170 calling_convention, \ | |
171 result_type, \ | |
172 result_error) \ | |
173 typedef result_type (calling_convention *function##_pointer) proto; \ | |
174 inline result_type function##Wrap proto { \ | |
175 HINSTANCE module_instance = ::GetModuleHandle(_T(#module)); \ | |
176 ASSERT1(module_instance); \ | |
177 if (!module_instance) { \ | |
178 return result_error; \ | |
179 } \ | |
180 function##_pointer fn = NULL; \ | |
181 return GPA(module_instance, #function, &fn) ? (*fn) call : result_error; \ | |
182 } | |
183 | |
184 GPA_WRAP(kernel32.dll, | |
185 AttachConsole, | |
186 (DWORD process_id), | |
187 (process_id), | |
188 WINAPI, | |
189 BOOL, | |
190 0); | |
191 | |
192 // Private Object Namespaces for Vista and above. More information here: | |
193 // http://msdn2.microsoft.com/en-us/library/ms684295(VS.85).aspx | |
194 GPA_WRAP(kernel32.dll, | |
195 CreateBoundaryDescriptorW, | |
196 (LPCWSTR boundary_name, ULONG flags), | |
197 (boundary_name, flags), | |
198 WINAPI, | |
199 HANDLE, | |
200 NULL); | |
201 GPA_WRAP(kernel32.dll, | |
202 AddSIDToBoundaryDescriptor, | |
203 (HANDLE* boundary_descriptor, PSID required_sid), | |
204 (boundary_descriptor, required_sid), | |
205 WINAPI, | |
206 BOOL, | |
207 FALSE); | |
208 GPA_WRAP(kernel32.dll, | |
209 CreatePrivateNamespaceW, | |
210 (LPSECURITY_ATTRIBUTES private_namespace_attributes, LPVOID boundary_de
scriptor, LPCWSTR alias_prefix), // NOLINT | |
211 (private_namespace_attributes, boundary_descriptor, alias_prefix), | |
212 WINAPI, | |
213 HANDLE, | |
214 NULL); | |
215 GPA_WRAP(kernel32.dll, | |
216 OpenPrivateNamespaceW, | |
217 (LPVOID boundary_descriptor, LPCWSTR alias_prefix), | |
218 (boundary_descriptor, alias_prefix), | |
219 WINAPI, | |
220 HANDLE, | |
221 NULL); | |
222 | |
223 bool IsPrivateNamespaceAvailable(); | |
224 | |
225 | |
226 HRESULT PinModuleIntoProcess(const CString& module_name); | |
227 | |
228 // Creates a directory with default security. | |
229 // S_OK: Created directory | |
230 // S_FALSE: Directory already existed | |
231 // E_FAIL: Couldn't create | |
232 HRESULT CreateDir(const TCHAR* dirname, LPSECURITY_ATTRIBUTES security_attr); | |
233 | |
234 // Gets the path for the specified special folder. | |
235 HRESULT GetFolderPath(int csidl, CString* path); | |
236 | |
237 // Returns true if this directory name is 'safe' for deletion: | |
238 // - it doesn't contain ".." | |
239 // - it doesn't specify a drive root | |
240 bool SafeDirectoryNameForDeletion(const TCHAR* dir_name); | |
241 | |
242 // Deletes a directory and its files. | |
243 HRESULT DeleteDirectory(const TCHAR* ir_name); | |
244 | |
245 // Deletes all files in a directory. | |
246 HRESULT DeleteDirectoryFiles(const TCHAR* dir_name); | |
247 | |
248 // Deletes all files in a directory matching a wildcard. | |
249 HRESULT DeleteWildcardFiles(const TCHAR* dir_name, const TCHAR* wildcard_name); | |
250 | |
251 // Deletes either a file or directory before or after reboot. | |
252 HRESULT DeleteBeforeOrAfterReboot(const TCHAR* targetname); | |
253 | |
254 // Gets the size of all files in a directory. | |
255 // Aborts counting if one of the maximum criteria is reached. | |
256 HRESULT SafeGetDirectorySize(const TCHAR* dir_name, | |
257 uint64* size, | |
258 HANDLE shutdown_event, | |
259 uint64 max_size, | |
260 int max_depth, | |
261 int max_file_count, | |
262 int max_running_time_ms); | |
263 | |
264 // Gets size of all files in a directory. | |
265 HRESULT GetDirectorySize(const TCHAR* dir_name, uint64* size); | |
266 | |
267 enum TimeCategory { | |
268 PAST = 0, // older than 40 years from now | |
269 FUTURE, // in the future by > 1 day | |
270 PRESENT, // neither ANCIENT nor FUTURE | |
271 }; | |
272 | |
273 TimeCategory GetTimeCategory(time64 t); | |
274 | |
275 // Returns true if a given time is likely to be valid. | |
276 bool IsValidTime(time64 t); | |
277 | |
278 // Gets a time64 value. | |
279 // If the value is greater than the | |
280 // max value, then SetValue will be called using the max_value. | |
281 // | |
282 // Args: | |
283 // full_key_name: the reg keyto read to get the time value. | |
284 // value_name: the name for the reg key value to be read. | |
285 // (may be NULL to get the default value) | |
286 // max_time: the maximum value for the reg key. | |
287 // value: the time value read. May not be set on failure. | |
288 // limited_value: true iff will be set if the value was | |
289 // changed (and resaved). (NULL is allowable.) | |
290 HRESULT GetLimitedTimeValue(const TCHAR* full_key_name, | |
291 const TCHAR* value_name, | |
292 time64 max_time, | |
293 time64* value, | |
294 bool* limited_value); | |
295 | |
296 // Gets a time64 value trying reg keys successively if there is a | |
297 // failure in getting a value. | |
298 // | |
299 // Typically used when there is a user value and a default value if the | |
300 // user has none. | |
301 // | |
302 // Args: | |
303 // full_key_names: a list of reg keys to try successively (starting | |
304 // with index 0) to read to get the time value. The | |
305 // attempts stops as soon as there is a successful read or | |
306 // when all keys have been tried. | |
307 // key_names_length: number of keys in full_key_names. | |
308 // value_name: the name for the reg key value to be read. | |
309 // (may be NULL to get the default value) | |
310 // max_time: the maximum value for the reg key. | |
311 // value: the time value read. May not be set on failure. | |
312 // limited_value: true iff will be set if the value was | |
313 // changed (and resaved). (NULL is allowable.) | |
314 HRESULT GetLimitedTimeValues(const TCHAR* full_key_names[], | |
315 int key_names_length, | |
316 const TCHAR* value_name, | |
317 time64 max_time, | |
318 time64* value, | |
319 bool* limited_value); | |
320 | |
321 // Convert milliseconds to a relative time in units of 100ns, suitable for use | |
322 // with waitable timers | |
323 LARGE_INTEGER MSto100NSRelative(DWORD ms); | |
324 | |
325 // TODO(omaha): remove from public interface. | |
326 inline void WINAPI NullAPCFunc(ULONG_PTR) {} | |
327 | |
328 // Forces rasman.dll load to avoid a crash in wininet. | |
329 void EnsureRasmanLoaded(); | |
330 | |
331 // Returns if the HRESULT argument is a COM error | |
332 // TODO(omaha): use an ANONYMOUS_VARIABLE to avoid the situation in which the | |
333 // macro gets called like RET_IF_FAILED(hr); | |
334 // For now, use a quick fix hr -> __hr. Leading underscore names are not to be | |
335 // used in application code. | |
336 #define RET_IF_FAILED(x) \ | |
337 do { \ | |
338 HRESULT __hr(x); \ | |
339 if (FAILED(__hr)) { \ | |
340 return __hr; \ | |
341 } \ | |
342 } while (false) | |
343 | |
344 // return error if the first argument evaluates to false | |
345 #define RET_IF_FALSE(x, err) \ | |
346 do { \ | |
347 if (!(x)) { \ | |
348 return err; \ | |
349 } \ | |
350 } while (false) | |
351 | |
352 // return false if the HRESULT argument is a COM error | |
353 #define RET_FALSE_IF_FAILED(x) \ | |
354 do { \ | |
355 if (FAILED(x)) { \ | |
356 return false; \ | |
357 } \ | |
358 } while (false) | |
359 | |
360 // return true if the HRESULT argument is a COM error | |
361 #define RET_TRUE_IF_FAILED(x) \ | |
362 do { \ | |
363 if (FAILED(x)) { \ | |
364 return true; \ | |
365 } \ | |
366 } while (false) | |
367 | |
368 // return if the HRESULT argument evaluates to FAILED - but also assert | |
369 // if failed | |
370 #define RET_IF_FAILED_ASSERT(x, msg) \ | |
371 do { \ | |
372 HRESULT hr(x); \ | |
373 if (FAILED(hr)) { \ | |
374 ASSERT(false, msg); \ | |
375 return hr; \ | |
376 } \ | |
377 } while (false) | |
378 | |
379 | |
380 // return if the HRESULT argument evaluates to FAILED - but also log an error | |
381 // message if failed | |
382 #define RET_IF_FAILED_LOG(x, cat, msg) \ | |
383 do { \ | |
384 HRESULT hr(x); \ | |
385 if (FAILED(hr)) { \ | |
386 LC_LOG(cat, LEVEL_ERROR, msg); \ | |
387 return hr; \ | |
388 } \ | |
389 } while (false) | |
390 | |
391 // return if the HRESULT argument evaluates to FAILED - but also REPORT an error | |
392 // message if failed | |
393 #define RET_IF_FAILED_REPORT(x, msg, n) \ | |
394 do { \ | |
395 HRESULT hr(x); \ | |
396 if (FAILED(hr)) { \ | |
397 REPORT(false, R_ERROR, msg, n); \ | |
398 return hr; \ | |
399 } \ | |
400 } while (false) | |
401 | |
402 // Initializes a POD to zero. | |
403 // Using this function requires discipline. Don't use for types that have a | |
404 // v-table or virtual bases. | |
405 template <typename T> | |
406 inline void SetZero(T& p) { // NOLINT | |
407 // Guard against the easy mistake of | |
408 // foo(int *p) { SetZero(p); } instead of | |
409 // SetZero(*p); | |
410 // which it should be. | |
411 STATIC_ASSERT(sizeof(p) != sizeof(void*)); // NOLINT | |
412 | |
413 // A POD (plain old data) object has one of these data types: | |
414 // a fundamental type, union, struct, array, | |
415 // or class--with no constructor. PODs don't have virtual functions or | |
416 // virtual bases. | |
417 | |
418 // Test to see if the type has constructors. | |
419 union CtorTest { | |
420 T t; | |
421 int i; | |
422 }; | |
423 | |
424 // TODO(omaha): There might be a way to test if the type has virtuals | |
425 // For now, if we zero a type with virtuals by mistake, it is going to crash | |
426 // predictable at run-time when the virtuals are called. | |
427 | |
428 memset(&p, 0, sizeof(T)); | |
429 } | |
430 | |
431 inline void SecureSetZero(CString* p) { | |
432 ASSERT1(p); | |
433 if (!p->IsEmpty()) { | |
434 ::SecureZeroMemory(p->GetBufferSetLength(p->GetLength()), | |
435 p->GetLength() * sizeof(TCHAR)); | |
436 p->ReleaseBuffer(); | |
437 } | |
438 } | |
439 | |
440 inline void SecureSetZero(CComVariant* p) { | |
441 ASSERT1(p); | |
442 ASSERT1(V_VT(p) == VT_BSTR); | |
443 uint32 byte_len = ::SysStringByteLen(V_BSTR(p)); | |
444 if (byte_len > 0) { | |
445 ::SecureZeroMemory(V_BSTR(p), byte_len); | |
446 } | |
447 } | |
448 | |
449 // CreateForegroundParentWindowForUAC creates a WS_POPUP | WS_VISIBLE with zero | |
450 // size, of the STATIC WNDCLASS. It uses the default running EXE module | |
451 // handle for creation. | |
452 // | |
453 // A visible centered foreground window is needed as the parent in Windows 7 and | |
454 // above, to allow the UAC prompt to come up in the foreground, centered. | |
455 // Otherwise, the elevation prompt will be minimized on the taskbar. A zero size | |
456 // window works. A plain vanilla WS_POPUP allows the window to be free of | |
457 // adornments. WS_EX_TOOLWINDOW prevents the task bar from showing the | |
458 // zero-sized window. | |
459 // | |
460 // Returns NULL on failure. Call ::GetLastError() to get extended error | |
461 // information on failure. | |
462 inline HWND CreateForegroundParentWindowForUAC() { | |
463 CWindow foreground_parent; | |
464 if (foreground_parent.Create(_T("STATIC"), NULL, NULL, NULL, | |
465 WS_POPUP | WS_VISIBLE, WS_EX_TOOLWINDOW)) { | |
466 foreground_parent.CenterWindow(NULL); | |
467 ::SetForegroundWindow(foreground_parent); | |
468 } | |
469 return foreground_parent.Detach(); | |
470 } | |
471 | |
472 // TODO(omaha): move the definition and ShellExecuteExEnsureParent function | |
473 // below into shell.h | |
474 | |
475 #if (NTDDI_VERSION < NTDDI_WINXPSP1) | |
476 // This value is not defined in the header, but has no effect on older OSes. | |
477 #define SEE_MASK_NOZONECHECKS 0x00800000 | |
478 #endif | |
479 | |
480 // ShellExecuteExEnsureParent is a wrapper around ::ShellExecuteEx. | |
481 // It ensures that we always have a parent window. In elevation scenarios, we | |
482 // need to use the HWND property to be acknowledged as a foreground application | |
483 // on Windows Vista. Otherwise, the elevation prompt will appear minimized on | |
484 // the taskbar The UAC elevation mechanism uses the HWND as part of determining | |
485 // whether the elevation is a foreground elevation. | |
486 // | |
487 // A better place for this might be in the Process class. However, to | |
488 // reduce dependencies for the stub, placing this in utils. | |
489 // | |
490 // Return values: | |
491 // ShellExecuteExEnsureParent returns TRUE on success, and FALSE on failure. | |
492 // Call ::GetLastError() to get the extended error information on failure. | |
493 // | |
494 // Args: | |
495 // shell_exec_info structure pointer, filled in, with an optional HWND. | |
496 // The structure is not validated. If the HWND is NULL, it creates one. | |
497 bool ShellExecuteExEnsureParent(LPSHELLEXECUTEINFO shell_exec_info); | |
498 | |
499 // | |
500 // Wait with a message loop. | |
501 // Returns true if the wait completed successfully and false in case of an | |
502 // error. | |
503 // | |
504 | |
505 // Waits with a message loop until any of the synchronization objects is | |
506 // signaled. Return the index of the object that satisfied the wait. | |
507 bool WaitWithMessageLoopAny(const std::vector<HANDLE>& handles, uint32* pos); | |
508 | |
509 // Waits with message loop until all the synchronization objects are signaled. | |
510 bool WaitWithMessageLoopAll(const std::vector<HANDLE>& handles); | |
511 | |
512 // Waits with message loop until the synchronization object is signaled. | |
513 bool WaitWithMessageLoop(HANDLE h); | |
514 | |
515 // Waits with message loop for a certain period of time | |
516 bool WaitWithMessageLoopTimed(DWORD ms); | |
517 | |
518 // | |
519 // TODO(omaha): message handler classes should go in other module. | |
520 // | |
521 // Handles windows messages | |
522 class MessageHandlerInterface { | |
523 public: | |
524 virtual ~MessageHandlerInterface() {} | |
525 // Does the translate/dispatch for one window message | |
526 // msg is never NULL. | |
527 virtual void Process(MSG* msg) = 0; | |
528 }; | |
529 | |
530 // The simplest working implementation of a message handler. | |
531 // It does TranslateMessage/DispatchMessage. | |
532 class BasicMessageHandler : public MessageHandlerInterface { | |
533 public: | |
534 BasicMessageHandler() {} | |
535 virtual void Process(MSG* msg); | |
536 private: | |
537 DISALLOW_EVIL_CONSTRUCTORS(BasicMessageHandler); | |
538 }; | |
539 | |
540 // An internal detail (used to handle messages | |
541 // and adjust the handles/cnt as needed). | |
542 class MessageHandlerInternalInterface { | |
543 public: | |
544 virtual ~MessageHandlerInternalInterface() {} | |
545 // Does the translate/dispatch for one window message | |
546 // msg is never NULL and may change the handles and cnt (which are | |
547 // never NULL). | |
548 virtual void Process(MSG* msg, const HANDLE** handles, uint32* cnt) = 0; | |
549 }; | |
550 | |
551 // The callback for MessageLoopInterface::RegisterWaitForSingleObject | |
552 class WaitCallbackInterface { | |
553 public: | |
554 virtual ~WaitCallbackInterface() {} | |
555 // Return false from this method to terminate the message loop. | |
556 virtual bool HandleSignaled(HANDLE handle) = 0; | |
557 }; | |
558 | |
559 // This is similar to a threadpool interface | |
560 // but this is done on the main message loop instead. | |
561 // | |
562 // Important: These method calls are *not* threadsafe and | |
563 // should only be done on the message loop thread. | |
564 class MessageLoopInterface { | |
565 public: | |
566 virtual ~MessageLoopInterface() {} | |
567 // sets-up a callback for when the handle becomes signaled | |
568 // * the callback happens on the main thread. | |
569 // * the handle/callback is removed when | |
570 // the callback is made. | |
571 // * If the handle becomes invalid while it is being waited on, | |
572 // the message loop will exit. | |
573 // * If the handle has already been registered, | |
574 // then adding it again will essentially replace the | |
575 // previous callback with the new one. | |
576 virtual bool RegisterWaitForSingleObject(HANDLE handle, | |
577 WaitCallbackInterface* callback) = 0; | |
578 | |
579 // stops watching for the handle to be signaled | |
580 virtual bool UnregisterWait(HANDLE handle) = 0; | |
581 }; | |
582 | |
583 // An implementation of the MessageLoopInterface | |
584 class MessageLoopWithWait : public MessageLoopInterface, | |
585 private MessageHandlerInternalInterface { | |
586 public: | |
587 MessageLoopWithWait(); | |
588 | |
589 // This method needs to be called before the "Process()" | |
590 // method or else "Process()" will crash. | |
591 // | |
592 // Args: | |
593 // message_handler: handles any messages that occur | |
594 // *Note* It is the callers responsibility to keep | |
595 // message_handler around while this class exists | |
596 // and the *caller* should free message_handler | |
597 // after that. | |
598 void set_message_handler(MessageHandlerInterface* message_handler); | |
599 | |
600 // sets-up a callback for when the handle becomes signaled | |
601 virtual bool RegisterWaitForSingleObject(HANDLE handle, | |
602 WaitCallbackInterface* callback); | |
603 | |
604 // stops watching for the handle to be signaled | |
605 virtual bool UnregisterWait(HANDLE handle); | |
606 | |
607 // The message loop and handle callback routine | |
608 HRESULT Process(); | |
609 | |
610 private: | |
611 // Handles one messgae and adjus tthe handles and cnt as appropriate after | |
612 // handling the message | |
613 virtual void Process(MSG* msg, const HANDLE** handles, uint32* cnt); | |
614 | |
615 void RemoveHandleAt(uint32 pos); | |
616 | |
617 MessageHandlerInterface* message_handler_; | |
618 | |
619 // Handles that are checked for being signaled. | |
620 std::vector<HANDLE> callback_handles_; | |
621 | |
622 // What to call when a handle is signaled. | |
623 std::vector<WaitCallbackInterface*> callbacks_; | |
624 DISALLOW_EVIL_CONSTRUCTORS(MessageLoopWithWait); | |
625 }; | |
626 | |
627 // Calls an entry point that may be exposed from a DLL | |
628 // It is an error if the DLL is missing or can't be loaded | |
629 // If the entry point is missing the error returned is | |
630 // ERROR_INVALID_FUNCTION (as an HRESULT). | |
631 // Otherwise, if the function is called successfully then | |
632 // CallEntryPoint0 return S_OK and the result parameter is set to the | |
633 // return value from the function call. | |
634 HRESULT CallEntryPoint0(const TCHAR* dll_path, | |
635 const char* function_name, | |
636 HRESULT* result); | |
637 | |
638 // (Un)Registers a COM DLL with the system. Returns S_FALSE if entry | |
639 // point missing (so that it you can call (Un)RegisterDll on any DLL | |
640 // without worrying whether the DLL is actually a COM server or not). | |
641 HRESULT RegisterDll(const TCHAR* dll_path); | |
642 HRESULT UnregisterDll(const TCHAR* dll_path); | |
643 | |
644 // (Un)Registers a COM Local Server with the system. | |
645 HRESULT RegisterServer(const TCHAR* exe_path); | |
646 HRESULT UnregisterServer(const TCHAR* exe_path); | |
647 HRESULT RegisterOrUnregisterExe(const TCHAR* exe_path, const TCHAR* cmd_line); | |
648 | |
649 // (Un)Registers a COM Service with the system. | |
650 HRESULT RegisterService(const TCHAR* exe_path); | |
651 HRESULT UnregisterService(const TCHAR* exe_path); | |
652 | |
653 // Starts a service. | |
654 HRESULT RunService(const TCHAR* service_name); | |
655 | |
656 // Read an entire file into a memory buffer. Use this function when you need | |
657 // exclusive access to the file. | |
658 // Returns MEM_E_INVALID_SIZE if the file size is larger than max_len (unless | |
659 // max_len == 0, in which case it is ignored) | |
660 HRESULT ReadEntireFile(const TCHAR* filepath, | |
661 uint32 max_len, | |
662 std::vector<byte>* buffer_out); | |
663 | |
664 // Allows specifying a sharing mode such as FILE_SHARE_READ. Otherwise, | |
665 // this is identical to ReadEntireFile. | |
666 HRESULT ReadEntireFileShareMode(const TCHAR* filepath, | |
667 uint32 max_len, | |
668 DWORD share_mode, | |
669 std::vector<byte>* buffer_out); | |
670 | |
671 // Writes an entire file from a memory buffer | |
672 HRESULT WriteEntireFile(const TCHAR * filepath, | |
673 const std::vector<byte>& buffer_in); | |
674 | |
675 // Conversions between a byte stream and a std::string | |
676 HRESULT BufferToString(const std::vector<byte>& buffer_in, CStringA* str_out); | |
677 HRESULT BufferToString(const std::vector<byte>& buffer_in, CString* str_out); | |
678 HRESULT StringToBuffer(const CStringA& str_in, std::vector<byte>* buffer_out); | |
679 HRESULT StringToBuffer(const CString& str_in, std::vector<byte>* buffer_out); | |
680 | |
681 // Splits a "full regkey name" into a key name part and a value name part. | |
682 // Handles "(default)" as a value name. Treats a trailing "/" as "(default)". | |
683 HRESULT RegSplitKeyvalueName(const CString& keyvalue_name, | |
684 CString* key_name, | |
685 CString* value_name); | |
686 | |
687 // Expands string with embedded special variables which are enclosed | |
688 // in '%' pair. For example, "%PROGRAMFILES%\Google" expands to | |
689 // "C:\Program Files\Google". | |
690 // If any of the embedded variable can not be expanded, we will leave it intact | |
691 // and return HRESULT_FROM_WIN32(ERROR_NOT_FOUND) | |
692 HRESULT ExpandEnvLikeStrings(const TCHAR* src, | |
693 const std::map<CString, CString>& keywords, | |
694 CString* dest); | |
695 | |
696 // Returns true if the path represents a registry path. | |
697 bool IsRegistryPath(const TCHAR* path); | |
698 | |
699 // Returns true if the path is a URL. | |
700 bool IsUrl(const TCHAR* path); | |
701 | |
702 // Converts GUID to string. | |
703 CString GuidToString(const GUID& guid); | |
704 | |
705 // Converts string to GUID. | |
706 HRESULT StringToGuidSafe(const CString& str, GUID* guid); | |
707 | |
708 // Converts a variant containing a list of strings. | |
709 void VariantToStringList(VARIANT var, std::vector<CString>* list); | |
710 | |
711 // Appends two registry key paths, takes care of extra separators in the | |
712 // beginning or end of the key. | |
713 CString AppendRegKeyPath(const CString& one, const CString& two); | |
714 CString AppendRegKeyPath(const CString& one, | |
715 const CString& two, | |
716 const CString& three); | |
717 | |
718 // Returns the list of user keys that are present within the HKEY_USERS key | |
719 // the method only returns the keys of the users and takes care of, | |
720 // removing the well known sids. The returned values are the complete values | |
721 // from the root of the registry | |
722 HRESULT GetUserKeysFromHkeyUsers(std::vector<CString>* key_names); | |
723 | |
724 // Use when a function should be able to | |
725 // be replaced with another implementation. Usually, | |
726 // this is done for testing code only. | |
727 // | |
728 // Typical usage: | |
729 // | |
730 // typedef bool BoolPreferenceFunctionType(); | |
731 // CallInterceptor<BoolPreferenceFunctionType> should_send_stats_interceptor; | |
732 // BoolPreferenceFunctionType* ReplaceShouldSendStatsFunction( | |
733 // BoolPreferenceFunctionType* replacement) { | |
734 // return should_send_stats_interceptor.ReplaceFunction(replacement); | |
735 // } | |
736 template <typename R> | |
737 class CallInterceptor { | |
738 public: | |
739 CallInterceptor() { | |
740 interceptor_ = NULL; | |
741 } | |
742 | |
743 R* ReplaceFunction(R* replacement) { | |
744 R* old = interceptor_; | |
745 interceptor_ = replacement; | |
746 return old; | |
747 } | |
748 | |
749 R* interceptor() { | |
750 return interceptor_; | |
751 } | |
752 | |
753 private: | |
754 R* interceptor_; | |
755 DISALLOW_EVIL_CONSTRUCTORS(CallInterceptor); | |
756 }; | |
757 | |
758 // Gets a handle of the current process. The handle is a real handle | |
759 // and the caller must close it | |
760 HRESULT GetCurrentProcessHandle(HANDLE* handle); | |
761 | |
762 // Duplicates the given token from the source_process into the current process. | |
763 HRESULT DuplicateTokenIntoCurrentProcess(HANDLE source_process, | |
764 HANDLE token_to_duplicate, | |
765 CAccessToken* duplicated_token); | |
766 | |
767 // Helper class for an ATL module that registers a custom AccessPermission | |
768 // to allow local calls from interactive users and the system account. | |
769 // Derive from this class as well as CAtlModuleT (or a derivative). | |
770 // Override RegisterAppId() and UnregisterAppId(), and delegate to the | |
771 // corresponding functions in this class. | |
772 template <class T> | |
773 class LocalCallAccessPermissionHelper { | |
774 public: | |
775 HRESULT RegisterAppId() throw() { | |
776 // Local call permissions allowed for Interactive Users and Local System | |
777 static LPCTSTR ALLOW_LOCAL_CALL_SDDL = | |
778 _T("O:BAG:BAD:(A;;0x3;;;IU)(A;;0x3;;;SY)"); | |
779 | |
780 UTIL_LOG(L1, (_T("[LocalCallAccessPermissionHelper::RegisterAppId]"))); | |
781 | |
782 // First call the base ATL module implementation, so the AppId is registered | |
783 RET_IF_FAILED(T::UpdateRegistryAppId(TRUE)); | |
784 | |
785 // Next, write the AccessPermission value | |
786 RegKey key_app_id; | |
787 RET_IF_FAILED(key_app_id.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE)); | |
788 | |
789 RegKey key; | |
790 RET_IF_FAILED(key.Create(key_app_id.Key(), T::GetAppIdT())); | |
791 CSecurityDesc sd; | |
792 RET_IF_FALSE(sd.FromString(ALLOW_LOCAL_CALL_SDDL), HRESULTFromLastError()); | |
793 RET_IF_FAILED(key.SetValue( | |
794 _T("AccessPermission"), | |
795 reinterpret_cast<const byte*>(sd.GetPSECURITY_DESCRIPTOR()), | |
796 sd.GetLength())); | |
797 | |
798 UTIL_LOG(L1, (_T("[LocalCallAccessPermissionHelper::RegisterAppId]") | |
799 _T("[succeeded]"))); | |
800 return S_OK; | |
801 } | |
802 | |
803 HRESULT UnregisterAppId() throw() { | |
804 // First remove the AccesPermission entry. | |
805 RegKey key_app_id; | |
806 RET_IF_FAILED(key_app_id.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE)); | |
807 | |
808 RegKey key; | |
809 RET_IF_FAILED(key.Open(key_app_id.Key(), T::GetAppIdT(), KEY_WRITE)); | |
810 VERIFY1(SUCCEEDED(key.DeleteValue(_T("AccessPermission")))); | |
811 | |
812 // Now, call the base ATL module implementation to unregister the AppId | |
813 RET_IF_FAILED(T::UpdateRegistryAppId(FALSE)); | |
814 | |
815 UTIL_LOG(L1, (_T("[LocalCallAccessPermissionHelper::UnregisterAppId'") | |
816 _T("[succeeded]"))); | |
817 return S_OK; | |
818 } | |
819 }; | |
820 | |
821 // Returns true if the argument is a guid. | |
822 inline bool IsGuid(const TCHAR* s) { | |
823 if (!s) return false; | |
824 GUID guid = {0}; | |
825 return SUCCEEDED(StringToGuidSafe(s, &guid)); | |
826 } | |
827 | |
828 inline bool IsLocalSystemSid(const TCHAR* sid) { | |
829 ASSERT1(sid); | |
830 return _tcsicmp(sid, kLocalSystemSid) == 0; | |
831 } | |
832 | |
833 // Fills a buffer with cryptographically random bytes. | |
834 bool GenRandom(void* buffer, size_t buffer_length); | |
835 | |
836 // Deletes an object. The functor is useful in for_each algorithms. | |
837 struct DeleteFun { | |
838 template <class T> void operator()(T ptr) { delete ptr; } | |
839 }; | |
840 | |
841 // Sets or clears the specified value in the Run key to the specified command. | |
842 HRESULT ConfigureRunAtStartup(const CString& root_key_name, | |
843 const CString& run_value_name, | |
844 const CString& command, | |
845 bool install); | |
846 | |
847 // Cracks a command line and returns the program name, which is the first | |
848 // whitespace separated token. | |
849 HRESULT GetExePathFromCommandLine(const TCHAR* command_line, | |
850 CString* exe_path); | |
851 | |
852 // Waits for MSI to complete, if MSI is busy installing or uninstalling apps. | |
853 HRESULT WaitForMSIExecute(int timeout_ms); | |
854 | |
855 // Returns the value of the specified environment variable. | |
856 CString GetEnvironmentVariableAsString(const TCHAR* name); | |
857 | |
858 // Returns true if the OS is installing (e.g., Audit Mode at an OEM factory). | |
859 // NOTE: This is unreliable on Windows Vista and later. Some computers remain in | |
860 // one of the incomplete states even after OOBE. See http://b/1690617. | |
861 bool IsWindowsInstalling(); | |
862 | |
863 // TODO(omaha): unit test. | |
864 inline uint64 GetGuidMostSignificantUint64(const GUID& guid) { | |
865 return (static_cast<uint64>(guid.Data1) << 32) + | |
866 (static_cast<uint64>(guid.Data2) << 16) + | |
867 static_cast<uint64>(guid.Data3); | |
868 } | |
869 | |
870 // Calls either ATL::InterlockedExchangePointer if ATL headers are included, | |
871 // or ::InterlockedExchangePointer. ATL slightly redefines the SDK function | |
872 // with the same name. | |
873 template <typename T> | |
874 inline T* interlocked_exchange_pointer(T* volatile * target, | |
875 const T* value) { | |
876 return static_cast<T*>(InterlockedExchangePointer( | |
877 reinterpret_cast<void**>(const_cast<T**>(target)), | |
878 const_cast<T*>(value))); | |
879 } | |
880 | |
881 // Gets a guid from the system (for user id, etc.) | |
882 // The guid will be of the form: {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} | |
883 HRESULT GetGuid(CString* guid); | |
884 | |
885 // Returns the message for an error code in the user's language or an | |
886 // empty string if an error occurs. The function does not support | |
887 // "insert sequences". The sequence will be returned in the string. | |
888 CString GetMessageForSystemErrorCode(DWORD error_code); | |
889 | |
890 // Ceil function for integer types. Returns the quotient of the two | |
891 // numbers (m/n) rounded upwards to the nearest integer. | |
892 // T should be unsigned integer type, such as unsigned short, unsigned long, | |
893 // unsigned int etc. | |
894 template <typename T> | |
895 inline T CeilingDivide(T m, T n) { | |
896 ASSERT1(n != 0); | |
897 | |
898 return (m + n - 1) / n; | |
899 } | |
900 | |
901 } // namespace omaha | |
902 | |
903 #endif // OMAHA_BASE_UTILS_H_ | |
OLD | NEW |