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