| Index: base/utils.h
|
| diff --git a/base/utils.h b/base/utils.h
|
| deleted file mode 100644
|
| index cfed08ba2358a96f89b86510c135d060fe42c4b9..0000000000000000000000000000000000000000
|
| --- a/base/utils.h
|
| +++ /dev/null
|
| @@ -1,903 +0,0 @@
|
| -// Copyright 2003-2010 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.
|
| -// ========================================================================
|
| -
|
| -#ifndef OMAHA_BASE_UTILS_H_
|
| -#define OMAHA_BASE_UTILS_H_
|
| -
|
| -#include <windows.h>
|
| -#include <accctrl.h>
|
| -#include <aclapi.h>
|
| -#include <sddl.h>
|
| -#include <shellapi.h>
|
| -#include <shlobj.h>
|
| -#include <atlstr.h>
|
| -#include <atlsecurity.h>
|
| -#include <atlwin.h>
|
| -#include <memory.h>
|
| -#include <map>
|
| -#include <vector>
|
| -#include "base/basictypes.h"
|
| -#include "omaha/base/constants.h"
|
| -#include "omaha/base/debug.h"
|
| -#include "omaha/base/logging.h"
|
| -#include "omaha/base/reg_key.h"
|
| -#include "omaha/base/scoped_any.h"
|
| -#include "omaha/base/static_assert.h"
|
| -#include "omaha/base/user_info.h"
|
| -
|
| -namespace omaha {
|
| -
|
| -// These definitions are not in any current Microsoft SDK header file. Taken
|
| -// from platformsdk/v6_1/files/Include/ObjIdl.h.
|
| -MIDL_INTERFACE("0000015B-0000-0000-C000-000000000046")
|
| -IGlobalOptions : public IUnknown {
|
| - public:
|
| - virtual HRESULT STDMETHODCALLTYPE Set(
|
| - /* [in] */ DWORD dwProperty,
|
| - /* [in] */ ULONG_PTR dwValue) = 0;
|
| -
|
| - virtual HRESULT STDMETHODCALLTYPE Query(
|
| - /* [in] */ DWORD dwProperty,
|
| - /* [out] */ ULONG_PTR *pdwValue) = 0;
|
| -};
|
| -
|
| -enum __MIDL___MIDL_itf_objidl_0000_0047_0001 {
|
| - COMGLB_EXCEPTION_HANDLING = 1,
|
| - COMGLB_APPID = 2
|
| -};
|
| -
|
| -enum __MIDL___MIDL_itf_objidl_0000_0047_0002 {
|
| - COMGLB_EXCEPTION_HANDLE = 0,
|
| - COMGLB_EXCEPTION_DONOT_HANDLE = 1
|
| -};
|
| -
|
| -// Determines whether to run ClickOnce components. This constant is not defined
|
| -// in the SDK headers.
|
| -#ifndef URLACTION_MANAGED_UNSIGNED
|
| -#define URLACTION_MANAGED_UNSIGNED (0x00002004)
|
| -#endif
|
| -
|
| -ULONGLONG VersionFromString(const CString& s);
|
| -
|
| -CString StringFromVersion(ULONGLONG version);
|
| -
|
| -// Gets current directory
|
| -CString GetCurrentDir();
|
| -
|
| -// Creates a unique file name using a new guid. Does not check for
|
| -// presence of this file in the directory.
|
| -HRESULT GetNewFileNameInDirectory(const CString& dir, CString* file_name);
|
| -
|
| -// Gets security descriptor with a DACL that grants the admin_access_mask to
|
| -// Admins and System, and the non_admin_access_mask to Interactive.
|
| -void GetEveryoneDaclSecurityDescriptor(CSecurityDesc* sd,
|
| - ACCESS_MASK admin_access_mask,
|
| - ACCESS_MASK non_admin_access_mask);
|
| -
|
| -// Get security descriptor containing a DACL that grants the ACCESS_MASK access
|
| -// to admins and system.
|
| -void GetAdminDaclSecurityDescriptor(CSecurityDesc* sd, ACCESS_MASK accessmask);
|
| -
|
| -// Get security attributes containing a DACL that grant the ACCESS_MASK access
|
| -// to admins and system.
|
| -void GetAdminDaclSecurityAttributes(CSecurityAttributes* sec_attr,
|
| - ACCESS_MASK accessmask);
|
| -
|
| -// This method is intended to be called by same or lower integrity COM clients.
|
| -// Calls ::CoInitializeSecurity with the default DACL. Servers are allowed to
|
| -// impersonate the client.
|
| -HRESULT InitializeClientSecurity();
|
| -
|
| -// This method calls ::CoInitializeSecurity with security settings and ACLs of
|
| -// callers that are allowed access to the COM server. Clients can only identify
|
| -// the server, and custom marshaling as well as activate-as-activator are
|
| -// disallowed.
|
| -// * If the bool is set, a DACL that provides COM_RIGHTS_EXECUTE access
|
| -// for medium-integrity callers is set.
|
| -// * If the bool is not set, but the caller is Local System, the function will
|
| -// set a security descriptor that also allows the Administrators group access to
|
| -// the COM server.
|
| -HRESULT InitializeServerSecurity(bool allow_calls_from_medium);
|
| -
|
| -// Ensures that the COM marshaling machinery does not eat crashes.
|
| -HRESULT DisableCOMExceptionHandling();
|
| -
|
| -// Merges an Allowed ACE into a named object. If the ACE already exists in the
|
| -// DACL with the same permissions (or a superset) and the same ACE flags, the
|
| -// merge is skipped.
|
| -HRESULT AddAllowedAce(const TCHAR* object_name,
|
| - SE_OBJECT_TYPE object_type,
|
| - const CSid& sid,
|
| - ACCESS_MASK required_permissions,
|
| - uint8 required_ace_flags);
|
| -
|
| -struct NamedObjectAttributes {
|
| - CString name;
|
| - CSecurityAttributes sa;
|
| -};
|
| -
|
| -// For machine and local system, the prefix would be "Global\G{obj_name}".
|
| -// For user, the prefix would be "Global\G{user_sid}{obj_name}".
|
| -// For machine objects, returns a security attributes that gives permissions to
|
| -// both Admins and SYSTEM. This allows for cases where SYSTEM creates the named
|
| -// object first. The default DACL for SYSTEM will not allow Admins access.
|
| -void GetNamedObjectAttributes(const TCHAR* base_name,
|
| - bool is_machine,
|
| - NamedObjectAttributes* attr);
|
| -
|
| -// Returns true if the current process is running as SYSTEM.
|
| -HRESULT IsSystemProcess(bool* is_system_process);
|
| -
|
| -// Returns true if the user of the current process is Local System or it has an
|
| -// interactive session: console, terminal services, or fast user switching.
|
| -HRESULT IsUserLoggedOn(bool* is_logged_on);
|
| -
|
| -// Returns true if URLACTION_MANAGED_UNSIGNED is disabled for the Internet zone
|
| -// for the current user.
|
| -bool IsClickOnceDisabled();
|
| -
|
| -// Wrapper around ::GetProcAddress().
|
| -template <typename T>
|
| -bool GPA(HMODULE module, const char* function_name, T* function_pointer) {
|
| - ASSERT1(module);
|
| - ASSERT1(function_name);
|
| - ASSERT1(function_pointer);
|
| -
|
| - *function_pointer = reinterpret_cast<T>(::GetProcAddress(module,
|
| - function_name));
|
| - if (NULL == *function_pointer) {
|
| - UTIL_LOG(LW, (_T("GetProcAddress failed [%s]"), CA2T(function_name)));
|
| - }
|
| - return NULL != *function_pointer;
|
| -}
|
| -
|
| -#define GPA_WRAP(module, \
|
| - function, \
|
| - proto, \
|
| - call, \
|
| - calling_convention, \
|
| - result_type, \
|
| - result_error) \
|
| -typedef result_type (calling_convention *function##_pointer) proto; \
|
| -inline result_type function##Wrap proto { \
|
| - HINSTANCE module_instance = ::GetModuleHandle(_T(#module)); \
|
| - ASSERT1(module_instance); \
|
| - if (!module_instance) { \
|
| - return result_error; \
|
| - } \
|
| - function##_pointer fn = NULL; \
|
| - return GPA(module_instance, #function, &fn) ? (*fn) call : result_error; \
|
| -}
|
| -
|
| -GPA_WRAP(kernel32.dll,
|
| - AttachConsole,
|
| - (DWORD process_id),
|
| - (process_id),
|
| - WINAPI,
|
| - BOOL,
|
| - 0);
|
| -
|
| -// Private Object Namespaces for Vista and above. More information here:
|
| -// http://msdn2.microsoft.com/en-us/library/ms684295(VS.85).aspx
|
| -GPA_WRAP(kernel32.dll,
|
| - CreateBoundaryDescriptorW,
|
| - (LPCWSTR boundary_name, ULONG flags),
|
| - (boundary_name, flags),
|
| - WINAPI,
|
| - HANDLE,
|
| - NULL);
|
| -GPA_WRAP(kernel32.dll,
|
| - AddSIDToBoundaryDescriptor,
|
| - (HANDLE* boundary_descriptor, PSID required_sid),
|
| - (boundary_descriptor, required_sid),
|
| - WINAPI,
|
| - BOOL,
|
| - FALSE);
|
| -GPA_WRAP(kernel32.dll,
|
| - CreatePrivateNamespaceW,
|
| - (LPSECURITY_ATTRIBUTES private_namespace_attributes, LPVOID boundary_descriptor, LPCWSTR alias_prefix), // NOLINT
|
| - (private_namespace_attributes, boundary_descriptor, alias_prefix),
|
| - WINAPI,
|
| - HANDLE,
|
| - NULL);
|
| -GPA_WRAP(kernel32.dll,
|
| - OpenPrivateNamespaceW,
|
| - (LPVOID boundary_descriptor, LPCWSTR alias_prefix),
|
| - (boundary_descriptor, alias_prefix),
|
| - WINAPI,
|
| - HANDLE,
|
| - NULL);
|
| -
|
| -bool IsPrivateNamespaceAvailable();
|
| -
|
| -
|
| -HRESULT PinModuleIntoProcess(const CString& module_name);
|
| -
|
| -// Creates a directory with default security.
|
| -// S_OK: Created directory
|
| -// S_FALSE: Directory already existed
|
| -// E_FAIL: Couldn't create
|
| -HRESULT CreateDir(const TCHAR* dirname, LPSECURITY_ATTRIBUTES security_attr);
|
| -
|
| -// Gets the path for the specified special folder.
|
| -HRESULT GetFolderPath(int csidl, CString* path);
|
| -
|
| -// Returns true if this directory name is 'safe' for deletion:
|
| -// - it doesn't contain ".."
|
| -// - it doesn't specify a drive root
|
| -bool SafeDirectoryNameForDeletion(const TCHAR* dir_name);
|
| -
|
| -// Deletes a directory and its files.
|
| -HRESULT DeleteDirectory(const TCHAR* ir_name);
|
| -
|
| -// Deletes all files in a directory.
|
| -HRESULT DeleteDirectoryFiles(const TCHAR* dir_name);
|
| -
|
| -// Deletes all files in a directory matching a wildcard.
|
| -HRESULT DeleteWildcardFiles(const TCHAR* dir_name, const TCHAR* wildcard_name);
|
| -
|
| -// Deletes either a file or directory before or after reboot.
|
| -HRESULT DeleteBeforeOrAfterReboot(const TCHAR* targetname);
|
| -
|
| -// Gets the size of all files in a directory.
|
| -// Aborts counting if one of the maximum criteria is reached.
|
| -HRESULT SafeGetDirectorySize(const TCHAR* dir_name,
|
| - uint64* size,
|
| - HANDLE shutdown_event,
|
| - uint64 max_size,
|
| - int max_depth,
|
| - int max_file_count,
|
| - int max_running_time_ms);
|
| -
|
| -// Gets size of all files in a directory.
|
| -HRESULT GetDirectorySize(const TCHAR* dir_name, uint64* size);
|
| -
|
| -enum TimeCategory {
|
| - PAST = 0, // older than 40 years from now
|
| - FUTURE, // in the future by > 1 day
|
| - PRESENT, // neither ANCIENT nor FUTURE
|
| -};
|
| -
|
| -TimeCategory GetTimeCategory(time64 t);
|
| -
|
| -// Returns true if a given time is likely to be valid.
|
| -bool IsValidTime(time64 t);
|
| -
|
| -// Gets a time64 value.
|
| -// If the value is greater than the
|
| -// max value, then SetValue will be called using the max_value.
|
| -//
|
| -// Args:
|
| -// full_key_name: the reg keyto read to get the time value.
|
| -// value_name: the name for the reg key value to be read.
|
| -// (may be NULL to get the default value)
|
| -// max_time: the maximum value for the reg key.
|
| -// value: the time value read. May not be set on failure.
|
| -// limited_value: true iff will be set if the value was
|
| -// changed (and resaved). (NULL is allowable.)
|
| -HRESULT GetLimitedTimeValue(const TCHAR* full_key_name,
|
| - const TCHAR* value_name,
|
| - time64 max_time,
|
| - time64* value,
|
| - bool* limited_value);
|
| -
|
| -// Gets a time64 value trying reg keys successively if there is a
|
| -// failure in getting a value.
|
| -//
|
| -// Typically used when there is a user value and a default value if the
|
| -// user has none.
|
| -//
|
| -// Args:
|
| -// full_key_names: a list of reg keys to try successively (starting
|
| -// with index 0) to read to get the time value. The
|
| -// attempts stops as soon as there is a successful read or
|
| -// when all keys have been tried.
|
| -// key_names_length: number of keys in full_key_names.
|
| -// value_name: the name for the reg key value to be read.
|
| -// (may be NULL to get the default value)
|
| -// max_time: the maximum value for the reg key.
|
| -// value: the time value read. May not be set on failure.
|
| -// limited_value: true iff will be set if the value was
|
| -// changed (and resaved). (NULL is allowable.)
|
| -HRESULT GetLimitedTimeValues(const TCHAR* full_key_names[],
|
| - int key_names_length,
|
| - const TCHAR* value_name,
|
| - time64 max_time,
|
| - time64* value,
|
| - bool* limited_value);
|
| -
|
| -// Convert milliseconds to a relative time in units of 100ns, suitable for use
|
| -// with waitable timers
|
| -LARGE_INTEGER MSto100NSRelative(DWORD ms);
|
| -
|
| -// TODO(omaha): remove from public interface.
|
| -inline void WINAPI NullAPCFunc(ULONG_PTR) {}
|
| -
|
| -// Forces rasman.dll load to avoid a crash in wininet.
|
| -void EnsureRasmanLoaded();
|
| -
|
| -// Returns if the HRESULT argument is a COM error
|
| -// TODO(omaha): use an ANONYMOUS_VARIABLE to avoid the situation in which the
|
| -// macro gets called like RET_IF_FAILED(hr);
|
| -// For now, use a quick fix hr -> __hr. Leading underscore names are not to be
|
| -// used in application code.
|
| -#define RET_IF_FAILED(x) \
|
| - do { \
|
| - HRESULT __hr(x); \
|
| - if (FAILED(__hr)) { \
|
| - return __hr; \
|
| - } \
|
| - } while (false)
|
| -
|
| -// return error if the first argument evaluates to false
|
| -#define RET_IF_FALSE(x, err) \
|
| - do { \
|
| - if (!(x)) { \
|
| - return err; \
|
| - } \
|
| - } while (false)
|
| -
|
| -// return false if the HRESULT argument is a COM error
|
| -#define RET_FALSE_IF_FAILED(x) \
|
| - do { \
|
| - if (FAILED(x)) { \
|
| - return false; \
|
| - } \
|
| - } while (false)
|
| -
|
| -// return true if the HRESULT argument is a COM error
|
| -#define RET_TRUE_IF_FAILED(x) \
|
| - do { \
|
| - if (FAILED(x)) { \
|
| - return true; \
|
| - } \
|
| - } while (false)
|
| -
|
| -// return if the HRESULT argument evaluates to FAILED - but also assert
|
| -// if failed
|
| -#define RET_IF_FAILED_ASSERT(x, msg) \
|
| - do { \
|
| - HRESULT hr(x); \
|
| - if (FAILED(hr)) { \
|
| - ASSERT(false, msg); \
|
| - return hr; \
|
| - } \
|
| - } while (false)
|
| -
|
| -
|
| -// return if the HRESULT argument evaluates to FAILED - but also log an error
|
| -// message if failed
|
| -#define RET_IF_FAILED_LOG(x, cat, msg) \
|
| - do { \
|
| - HRESULT hr(x); \
|
| - if (FAILED(hr)) { \
|
| - LC_LOG(cat, LEVEL_ERROR, msg); \
|
| - return hr; \
|
| - } \
|
| - } while (false)
|
| -
|
| -// return if the HRESULT argument evaluates to FAILED - but also REPORT an error
|
| -// message if failed
|
| -#define RET_IF_FAILED_REPORT(x, msg, n) \
|
| - do { \
|
| - HRESULT hr(x); \
|
| - if (FAILED(hr)) { \
|
| - REPORT(false, R_ERROR, msg, n); \
|
| - return hr; \
|
| - } \
|
| - } while (false)
|
| -
|
| -// Initializes a POD to zero.
|
| -// Using this function requires discipline. Don't use for types that have a
|
| -// v-table or virtual bases.
|
| -template <typename T>
|
| -inline void SetZero(T& p) { // NOLINT
|
| - // Guard against the easy mistake of
|
| - // foo(int *p) { SetZero(p); } instead of
|
| - // SetZero(*p);
|
| - // which it should be.
|
| - STATIC_ASSERT(sizeof(p) != sizeof(void*)); // NOLINT
|
| -
|
| - // A POD (plain old data) object has one of these data types:
|
| - // a fundamental type, union, struct, array,
|
| - // or class--with no constructor. PODs don't have virtual functions or
|
| - // virtual bases.
|
| -
|
| - // Test to see if the type has constructors.
|
| - union CtorTest {
|
| - T t;
|
| - int i;
|
| - };
|
| -
|
| - // TODO(omaha): There might be a way to test if the type has virtuals
|
| - // For now, if we zero a type with virtuals by mistake, it is going to crash
|
| - // predictable at run-time when the virtuals are called.
|
| -
|
| - memset(&p, 0, sizeof(T));
|
| -}
|
| -
|
| -inline void SecureSetZero(CString* p) {
|
| - ASSERT1(p);
|
| - if (!p->IsEmpty()) {
|
| - ::SecureZeroMemory(p->GetBufferSetLength(p->GetLength()),
|
| - p->GetLength() * sizeof(TCHAR));
|
| - p->ReleaseBuffer();
|
| - }
|
| -}
|
| -
|
| -inline void SecureSetZero(CComVariant* p) {
|
| - ASSERT1(p);
|
| - ASSERT1(V_VT(p) == VT_BSTR);
|
| - uint32 byte_len = ::SysStringByteLen(V_BSTR(p));
|
| - if (byte_len > 0) {
|
| - ::SecureZeroMemory(V_BSTR(p), byte_len);
|
| - }
|
| -}
|
| -
|
| -// CreateForegroundParentWindowForUAC creates a WS_POPUP | WS_VISIBLE with zero
|
| -// size, of the STATIC WNDCLASS. It uses the default running EXE module
|
| -// handle for creation.
|
| -//
|
| -// A visible centered foreground window is needed as the parent in Windows 7 and
|
| -// above, to allow the UAC prompt to come up in the foreground, centered.
|
| -// Otherwise, the elevation prompt will be minimized on the taskbar. A zero size
|
| -// window works. A plain vanilla WS_POPUP allows the window to be free of
|
| -// adornments. WS_EX_TOOLWINDOW prevents the task bar from showing the
|
| -// zero-sized window.
|
| -//
|
| -// Returns NULL on failure. Call ::GetLastError() to get extended error
|
| -// information on failure.
|
| -inline HWND CreateForegroundParentWindowForUAC() {
|
| - CWindow foreground_parent;
|
| - if (foreground_parent.Create(_T("STATIC"), NULL, NULL, NULL,
|
| - WS_POPUP | WS_VISIBLE, WS_EX_TOOLWINDOW)) {
|
| - foreground_parent.CenterWindow(NULL);
|
| - ::SetForegroundWindow(foreground_parent);
|
| - }
|
| - return foreground_parent.Detach();
|
| -}
|
| -
|
| -// TODO(omaha): move the definition and ShellExecuteExEnsureParent function
|
| -// below into shell.h
|
| -
|
| -#if (NTDDI_VERSION < NTDDI_WINXPSP1)
|
| -// This value is not defined in the header, but has no effect on older OSes.
|
| -#define SEE_MASK_NOZONECHECKS 0x00800000
|
| -#endif
|
| -
|
| -// ShellExecuteExEnsureParent is a wrapper around ::ShellExecuteEx.
|
| -// It ensures that we always have a parent window. In elevation scenarios, we
|
| -// need to use the HWND property to be acknowledged as a foreground application
|
| -// on Windows Vista. Otherwise, the elevation prompt will appear minimized on
|
| -// the taskbar The UAC elevation mechanism uses the HWND as part of determining
|
| -// whether the elevation is a foreground elevation.
|
| -//
|
| -// A better place for this might be in the Process class. However, to
|
| -// reduce dependencies for the stub, placing this in utils.
|
| -//
|
| -// Return values:
|
| -// ShellExecuteExEnsureParent returns TRUE on success, and FALSE on failure.
|
| -// Call ::GetLastError() to get the extended error information on failure.
|
| -//
|
| -// Args:
|
| -// shell_exec_info structure pointer, filled in, with an optional HWND.
|
| -// The structure is not validated. If the HWND is NULL, it creates one.
|
| -bool ShellExecuteExEnsureParent(LPSHELLEXECUTEINFO shell_exec_info);
|
| -
|
| -//
|
| -// Wait with a message loop.
|
| -// Returns true if the wait completed successfully and false in case of an
|
| -// error.
|
| -//
|
| -
|
| -// Waits with a message loop until any of the synchronization objects is
|
| -// signaled. Return the index of the object that satisfied the wait.
|
| -bool WaitWithMessageLoopAny(const std::vector<HANDLE>& handles, uint32* pos);
|
| -
|
| -// Waits with message loop until all the synchronization objects are signaled.
|
| -bool WaitWithMessageLoopAll(const std::vector<HANDLE>& handles);
|
| -
|
| -// Waits with message loop until the synchronization object is signaled.
|
| -bool WaitWithMessageLoop(HANDLE h);
|
| -
|
| -// Waits with message loop for a certain period of time
|
| -bool WaitWithMessageLoopTimed(DWORD ms);
|
| -
|
| -//
|
| -// TODO(omaha): message handler classes should go in other module.
|
| -//
|
| -// Handles windows messages
|
| -class MessageHandlerInterface {
|
| - public:
|
| - virtual ~MessageHandlerInterface() {}
|
| - // Does the translate/dispatch for one window message
|
| - // msg is never NULL.
|
| - virtual void Process(MSG* msg) = 0;
|
| -};
|
| -
|
| -// The simplest working implementation of a message handler.
|
| -// It does TranslateMessage/DispatchMessage.
|
| -class BasicMessageHandler : public MessageHandlerInterface {
|
| - public:
|
| - BasicMessageHandler() {}
|
| - virtual void Process(MSG* msg);
|
| - private:
|
| - DISALLOW_EVIL_CONSTRUCTORS(BasicMessageHandler);
|
| -};
|
| -
|
| -// An internal detail (used to handle messages
|
| -// and adjust the handles/cnt as needed).
|
| -class MessageHandlerInternalInterface {
|
| - public:
|
| - virtual ~MessageHandlerInternalInterface() {}
|
| - // Does the translate/dispatch for one window message
|
| - // msg is never NULL and may change the handles and cnt (which are
|
| - // never NULL).
|
| - virtual void Process(MSG* msg, const HANDLE** handles, uint32* cnt) = 0;
|
| -};
|
| -
|
| -// The callback for MessageLoopInterface::RegisterWaitForSingleObject
|
| -class WaitCallbackInterface {
|
| - public:
|
| - virtual ~WaitCallbackInterface() {}
|
| - // Return false from this method to terminate the message loop.
|
| - virtual bool HandleSignaled(HANDLE handle) = 0;
|
| -};
|
| -
|
| -// This is similar to a threadpool interface
|
| -// but this is done on the main message loop instead.
|
| -//
|
| -// Important: These method calls are *not* threadsafe and
|
| -// should only be done on the message loop thread.
|
| -class MessageLoopInterface {
|
| - public:
|
| - virtual ~MessageLoopInterface() {}
|
| - // sets-up a callback for when the handle becomes signaled
|
| - // * the callback happens on the main thread.
|
| - // * the handle/callback is removed when
|
| - // the callback is made.
|
| - // * If the handle becomes invalid while it is being waited on,
|
| - // the message loop will exit.
|
| - // * If the handle has already been registered,
|
| - // then adding it again will essentially replace the
|
| - // previous callback with the new one.
|
| - virtual bool RegisterWaitForSingleObject(HANDLE handle,
|
| - WaitCallbackInterface* callback) = 0;
|
| -
|
| - // stops watching for the handle to be signaled
|
| - virtual bool UnregisterWait(HANDLE handle) = 0;
|
| -};
|
| -
|
| -// An implementation of the MessageLoopInterface
|
| -class MessageLoopWithWait : public MessageLoopInterface,
|
| - private MessageHandlerInternalInterface {
|
| - public:
|
| - MessageLoopWithWait();
|
| -
|
| - // This method needs to be called before the "Process()"
|
| - // method or else "Process()" will crash.
|
| - //
|
| - // Args:
|
| - // message_handler: handles any messages that occur
|
| - // *Note* It is the callers responsibility to keep
|
| - // message_handler around while this class exists
|
| - // and the *caller* should free message_handler
|
| - // after that.
|
| - void set_message_handler(MessageHandlerInterface* message_handler);
|
| -
|
| - // sets-up a callback for when the handle becomes signaled
|
| - virtual bool RegisterWaitForSingleObject(HANDLE handle,
|
| - WaitCallbackInterface* callback);
|
| -
|
| - // stops watching for the handle to be signaled
|
| - virtual bool UnregisterWait(HANDLE handle);
|
| -
|
| - // The message loop and handle callback routine
|
| - HRESULT Process();
|
| -
|
| - private:
|
| - // Handles one messgae and adjus tthe handles and cnt as appropriate after
|
| - // handling the message
|
| - virtual void Process(MSG* msg, const HANDLE** handles, uint32* cnt);
|
| -
|
| - void RemoveHandleAt(uint32 pos);
|
| -
|
| - MessageHandlerInterface* message_handler_;
|
| -
|
| - // Handles that are checked for being signaled.
|
| - std::vector<HANDLE> callback_handles_;
|
| -
|
| - // What to call when a handle is signaled.
|
| - std::vector<WaitCallbackInterface*> callbacks_;
|
| - DISALLOW_EVIL_CONSTRUCTORS(MessageLoopWithWait);
|
| -};
|
| -
|
| -// Calls an entry point that may be exposed from a DLL
|
| -// It is an error if the DLL is missing or can't be loaded
|
| -// If the entry point is missing the error returned is
|
| -// ERROR_INVALID_FUNCTION (as an HRESULT).
|
| -// Otherwise, if the function is called successfully then
|
| -// CallEntryPoint0 return S_OK and the result parameter is set to the
|
| -// return value from the function call.
|
| -HRESULT CallEntryPoint0(const TCHAR* dll_path,
|
| - const char* function_name,
|
| - HRESULT* result);
|
| -
|
| -// (Un)Registers a COM DLL with the system. Returns S_FALSE if entry
|
| -// point missing (so that it you can call (Un)RegisterDll on any DLL
|
| -// without worrying whether the DLL is actually a COM server or not).
|
| -HRESULT RegisterDll(const TCHAR* dll_path);
|
| -HRESULT UnregisterDll(const TCHAR* dll_path);
|
| -
|
| -// (Un)Registers a COM Local Server with the system.
|
| -HRESULT RegisterServer(const TCHAR* exe_path);
|
| -HRESULT UnregisterServer(const TCHAR* exe_path);
|
| -HRESULT RegisterOrUnregisterExe(const TCHAR* exe_path, const TCHAR* cmd_line);
|
| -
|
| -// (Un)Registers a COM Service with the system.
|
| -HRESULT RegisterService(const TCHAR* exe_path);
|
| -HRESULT UnregisterService(const TCHAR* exe_path);
|
| -
|
| -// Starts a service.
|
| -HRESULT RunService(const TCHAR* service_name);
|
| -
|
| -// Read an entire file into a memory buffer. Use this function when you need
|
| -// exclusive access to the file.
|
| -// Returns MEM_E_INVALID_SIZE if the file size is larger than max_len (unless
|
| -// max_len == 0, in which case it is ignored)
|
| -HRESULT ReadEntireFile(const TCHAR* filepath,
|
| - uint32 max_len,
|
| - std::vector<byte>* buffer_out);
|
| -
|
| -// Allows specifying a sharing mode such as FILE_SHARE_READ. Otherwise,
|
| -// this is identical to ReadEntireFile.
|
| -HRESULT ReadEntireFileShareMode(const TCHAR* filepath,
|
| - uint32 max_len,
|
| - DWORD share_mode,
|
| - std::vector<byte>* buffer_out);
|
| -
|
| -// Writes an entire file from a memory buffer
|
| -HRESULT WriteEntireFile(const TCHAR * filepath,
|
| - const std::vector<byte>& buffer_in);
|
| -
|
| -// Conversions between a byte stream and a std::string
|
| -HRESULT BufferToString(const std::vector<byte>& buffer_in, CStringA* str_out);
|
| -HRESULT BufferToString(const std::vector<byte>& buffer_in, CString* str_out);
|
| -HRESULT StringToBuffer(const CStringA& str_in, std::vector<byte>* buffer_out);
|
| -HRESULT StringToBuffer(const CString& str_in, std::vector<byte>* buffer_out);
|
| -
|
| -// Splits a "full regkey name" into a key name part and a value name part.
|
| -// Handles "(default)" as a value name. Treats a trailing "/" as "(default)".
|
| -HRESULT RegSplitKeyvalueName(const CString& keyvalue_name,
|
| - CString* key_name,
|
| - CString* value_name);
|
| -
|
| -// Expands string with embedded special variables which are enclosed
|
| -// in '%' pair. For example, "%PROGRAMFILES%\Google" expands to
|
| -// "C:\Program Files\Google".
|
| -// If any of the embedded variable can not be expanded, we will leave it intact
|
| -// and return HRESULT_FROM_WIN32(ERROR_NOT_FOUND)
|
| -HRESULT ExpandEnvLikeStrings(const TCHAR* src,
|
| - const std::map<CString, CString>& keywords,
|
| - CString* dest);
|
| -
|
| -// Returns true if the path represents a registry path.
|
| -bool IsRegistryPath(const TCHAR* path);
|
| -
|
| -// Returns true if the path is a URL.
|
| -bool IsUrl(const TCHAR* path);
|
| -
|
| -// Converts GUID to string.
|
| -CString GuidToString(const GUID& guid);
|
| -
|
| -// Converts string to GUID.
|
| -HRESULT StringToGuidSafe(const CString& str, GUID* guid);
|
| -
|
| -// Converts a variant containing a list of strings.
|
| -void VariantToStringList(VARIANT var, std::vector<CString>* list);
|
| -
|
| -// Appends two registry key paths, takes care of extra separators in the
|
| -// beginning or end of the key.
|
| -CString AppendRegKeyPath(const CString& one, const CString& two);
|
| -CString AppendRegKeyPath(const CString& one,
|
| - const CString& two,
|
| - const CString& three);
|
| -
|
| -// Returns the list of user keys that are present within the HKEY_USERS key
|
| -// the method only returns the keys of the users and takes care of,
|
| -// removing the well known sids. The returned values are the complete values
|
| -// from the root of the registry
|
| -HRESULT GetUserKeysFromHkeyUsers(std::vector<CString>* key_names);
|
| -
|
| -// Use when a function should be able to
|
| -// be replaced with another implementation. Usually,
|
| -// this is done for testing code only.
|
| -//
|
| -// Typical usage:
|
| -//
|
| -// typedef bool BoolPreferenceFunctionType();
|
| -// CallInterceptor<BoolPreferenceFunctionType> should_send_stats_interceptor;
|
| -// BoolPreferenceFunctionType* ReplaceShouldSendStatsFunction(
|
| -// BoolPreferenceFunctionType* replacement) {
|
| -// return should_send_stats_interceptor.ReplaceFunction(replacement);
|
| -// }
|
| -template <typename R>
|
| -class CallInterceptor {
|
| - public:
|
| - CallInterceptor() {
|
| - interceptor_ = NULL;
|
| - }
|
| -
|
| - R* ReplaceFunction(R* replacement) {
|
| - R* old = interceptor_;
|
| - interceptor_ = replacement;
|
| - return old;
|
| - }
|
| -
|
| - R* interceptor() {
|
| - return interceptor_;
|
| - }
|
| -
|
| - private:
|
| - R* interceptor_;
|
| - DISALLOW_EVIL_CONSTRUCTORS(CallInterceptor);
|
| -};
|
| -
|
| -// Gets a handle of the current process. The handle is a real handle
|
| -// and the caller must close it
|
| -HRESULT GetCurrentProcessHandle(HANDLE* handle);
|
| -
|
| -// Duplicates the given token from the source_process into the current process.
|
| -HRESULT DuplicateTokenIntoCurrentProcess(HANDLE source_process,
|
| - HANDLE token_to_duplicate,
|
| - CAccessToken* duplicated_token);
|
| -
|
| -// Helper class for an ATL module that registers a custom AccessPermission
|
| -// to allow local calls from interactive users and the system account.
|
| -// Derive from this class as well as CAtlModuleT (or a derivative).
|
| -// Override RegisterAppId() and UnregisterAppId(), and delegate to the
|
| -// corresponding functions in this class.
|
| -template <class T>
|
| -class LocalCallAccessPermissionHelper {
|
| - public:
|
| - HRESULT RegisterAppId() throw() {
|
| - // Local call permissions allowed for Interactive Users and Local System
|
| - static LPCTSTR ALLOW_LOCAL_CALL_SDDL =
|
| - _T("O:BAG:BAD:(A;;0x3;;;IU)(A;;0x3;;;SY)");
|
| -
|
| - UTIL_LOG(L1, (_T("[LocalCallAccessPermissionHelper::RegisterAppId]")));
|
| -
|
| - // First call the base ATL module implementation, so the AppId is registered
|
| - RET_IF_FAILED(T::UpdateRegistryAppId(TRUE));
|
| -
|
| - // Next, write the AccessPermission value
|
| - RegKey key_app_id;
|
| - RET_IF_FAILED(key_app_id.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE));
|
| -
|
| - RegKey key;
|
| - RET_IF_FAILED(key.Create(key_app_id.Key(), T::GetAppIdT()));
|
| - CSecurityDesc sd;
|
| - RET_IF_FALSE(sd.FromString(ALLOW_LOCAL_CALL_SDDL), HRESULTFromLastError());
|
| - RET_IF_FAILED(key.SetValue(
|
| - _T("AccessPermission"),
|
| - reinterpret_cast<const byte*>(sd.GetPSECURITY_DESCRIPTOR()),
|
| - sd.GetLength()));
|
| -
|
| - UTIL_LOG(L1, (_T("[LocalCallAccessPermissionHelper::RegisterAppId]")
|
| - _T("[succeeded]")));
|
| - return S_OK;
|
| - }
|
| -
|
| - HRESULT UnregisterAppId() throw() {
|
| - // First remove the AccesPermission entry.
|
| - RegKey key_app_id;
|
| - RET_IF_FAILED(key_app_id.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE));
|
| -
|
| - RegKey key;
|
| - RET_IF_FAILED(key.Open(key_app_id.Key(), T::GetAppIdT(), KEY_WRITE));
|
| - VERIFY1(SUCCEEDED(key.DeleteValue(_T("AccessPermission"))));
|
| -
|
| - // Now, call the base ATL module implementation to unregister the AppId
|
| - RET_IF_FAILED(T::UpdateRegistryAppId(FALSE));
|
| -
|
| - UTIL_LOG(L1, (_T("[LocalCallAccessPermissionHelper::UnregisterAppId'")
|
| - _T("[succeeded]")));
|
| - return S_OK;
|
| - }
|
| -};
|
| -
|
| -// Returns true if the argument is a guid.
|
| -inline bool IsGuid(const TCHAR* s) {
|
| - if (!s) return false;
|
| - GUID guid = {0};
|
| - return SUCCEEDED(StringToGuidSafe(s, &guid));
|
| -}
|
| -
|
| -inline bool IsLocalSystemSid(const TCHAR* sid) {
|
| - ASSERT1(sid);
|
| - return _tcsicmp(sid, kLocalSystemSid) == 0;
|
| -}
|
| -
|
| -// Fills a buffer with cryptographically random bytes.
|
| -bool GenRandom(void* buffer, size_t buffer_length);
|
| -
|
| -// Deletes an object. The functor is useful in for_each algorithms.
|
| -struct DeleteFun {
|
| - template <class T> void operator()(T ptr) { delete ptr; }
|
| -};
|
| -
|
| -// Sets or clears the specified value in the Run key to the specified command.
|
| -HRESULT ConfigureRunAtStartup(const CString& root_key_name,
|
| - const CString& run_value_name,
|
| - const CString& command,
|
| - bool install);
|
| -
|
| -// Cracks a command line and returns the program name, which is the first
|
| -// whitespace separated token.
|
| -HRESULT GetExePathFromCommandLine(const TCHAR* command_line,
|
| - CString* exe_path);
|
| -
|
| -// Waits for MSI to complete, if MSI is busy installing or uninstalling apps.
|
| -HRESULT WaitForMSIExecute(int timeout_ms);
|
| -
|
| -// Returns the value of the specified environment variable.
|
| -CString GetEnvironmentVariableAsString(const TCHAR* name);
|
| -
|
| -// Returns true if the OS is installing (e.g., Audit Mode at an OEM factory).
|
| -// NOTE: This is unreliable on Windows Vista and later. Some computers remain in
|
| -// one of the incomplete states even after OOBE. See http://b/1690617.
|
| -bool IsWindowsInstalling();
|
| -
|
| -// TODO(omaha): unit test.
|
| -inline uint64 GetGuidMostSignificantUint64(const GUID& guid) {
|
| - return (static_cast<uint64>(guid.Data1) << 32) +
|
| - (static_cast<uint64>(guid.Data2) << 16) +
|
| - static_cast<uint64>(guid.Data3);
|
| -}
|
| -
|
| -// Calls either ATL::InterlockedExchangePointer if ATL headers are included,
|
| -// or ::InterlockedExchangePointer. ATL slightly redefines the SDK function
|
| -// with the same name.
|
| -template <typename T>
|
| -inline T* interlocked_exchange_pointer(T* volatile * target,
|
| - const T* value) {
|
| - return static_cast<T*>(InterlockedExchangePointer(
|
| - reinterpret_cast<void**>(const_cast<T**>(target)),
|
| - const_cast<T*>(value)));
|
| -}
|
| -
|
| -// Gets a guid from the system (for user id, etc.)
|
| -// The guid will be of the form: {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
| -HRESULT GetGuid(CString* guid);
|
| -
|
| -// Returns the message for an error code in the user's language or an
|
| -// empty string if an error occurs. The function does not support
|
| -// "insert sequences". The sequence will be returned in the string.
|
| -CString GetMessageForSystemErrorCode(DWORD error_code);
|
| -
|
| -// Ceil function for integer types. Returns the quotient of the two
|
| -// numbers (m/n) rounded upwards to the nearest integer.
|
| -// T should be unsigned integer type, such as unsigned short, unsigned long,
|
| -// unsigned int etc.
|
| -template <typename T>
|
| -inline T CeilingDivide(T m, T n) {
|
| - ASSERT1(n != 0);
|
| -
|
| - return (m + n - 1) / n;
|
| -}
|
| -
|
| -} // namespace omaha
|
| -
|
| -#endif // OMAHA_BASE_UTILS_H_
|
|
|