| Index: base/vistautil.cc
|
| diff --git a/base/vistautil.cc b/base/vistautil.cc
|
| deleted file mode 100644
|
| index 45aecea0e1502fb49aa72262d077b5ca8cd33b3a..0000000000000000000000000000000000000000
|
| --- a/base/vistautil.cc
|
| +++ /dev/null
|
| @@ -1,585 +0,0 @@
|
| -// Copyright 2006-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.
|
| -// ========================================================================
|
| -
|
| -#include "omaha/base/vistautil.h"
|
| -#include <accctrl.h>
|
| -#include <Aclapi.h>
|
| -#include <Sddl.h>
|
| -#include <ShellAPI.h>
|
| -#include <shlobj.h>
|
| -#include "base/scoped_ptr.h"
|
| -#include "omaha/base/debug.h"
|
| -#include "omaha/base/error.h"
|
| -#include "omaha/base/logging.h"
|
| -#include "omaha/base/process.h"
|
| -#include "omaha/base/reg_key.h"
|
| -#include "omaha/base/utils.h"
|
| -#include "omaha/base/vista_utils.h"
|
| -#include "omaha/third_party/smartany/scoped_any.h"
|
| -
|
| -namespace omaha {
|
| -
|
| -namespace vista_util {
|
| -
|
| -static SID_IDENTIFIER_AUTHORITY mandatory_label_auth =
|
| - SECURITY_MANDATORY_LABEL_AUTHORITY;
|
| -
|
| -
|
| -static HRESULT GetSidIntegrityLevel(PSID sid, MANDATORY_LEVEL* level) {
|
| - if (!IsValidSid(sid))
|
| - return E_FAIL;
|
| -
|
| - SID_IDENTIFIER_AUTHORITY* authority = GetSidIdentifierAuthority(sid);
|
| - if (!authority)
|
| - return E_FAIL;
|
| -
|
| - if (memcmp(authority, &mandatory_label_auth,
|
| - sizeof(SID_IDENTIFIER_AUTHORITY)))
|
| - return E_FAIL;
|
| -
|
| - PUCHAR count = GetSidSubAuthorityCount(sid);
|
| - if (!count || *count != 1)
|
| - return E_FAIL;
|
| -
|
| - DWORD* rid = GetSidSubAuthority(sid, 0);
|
| - if (!rid)
|
| - return E_FAIL;
|
| -
|
| - if ((*rid & 0xFFF) != 0 || *rid > SECURITY_MANDATORY_PROTECTED_PROCESS_RID)
|
| - return E_FAIL;
|
| -
|
| - *level = static_cast<MANDATORY_LEVEL>(*rid >> 12);
|
| - return S_OK;
|
| -}
|
| -
|
| -// Will return S_FALSE and MandatoryLevelMedium if the acl is NULL
|
| -static HRESULT GetAclIntegrityLevel(PACL acl, MANDATORY_LEVEL* level,
|
| - bool* and_children) {
|
| - *level = MandatoryLevelMedium;
|
| - if (and_children)
|
| - *and_children = false;
|
| - if (!acl) {
|
| - // This is the default label value if the acl was empty
|
| - return S_FALSE;
|
| - }
|
| -
|
| - SYSTEM_MANDATORY_LABEL_ACE* mandatory_label_ace;
|
| - if (!GetAce(acl, 0, reinterpret_cast<void**>(&mandatory_label_ace)))
|
| - return S_FALSE;
|
| -
|
| - if (mandatory_label_ace->Header.AceType != SYSTEM_MANDATORY_LABEL_ACE_TYPE)
|
| - return S_FALSE;
|
| -
|
| - if (!(mandatory_label_ace->Mask & SYSTEM_MANDATORY_LABEL_NO_WRITE_UP)) {
|
| - // I have found that if this flag is not set, a low integrity label doesn't
|
| - // prevent writes from being virtualized. MS provides zero documentation.
|
| - // I just did an MSDN search, a Google search, and a search of the Beta
|
| - // Vista SDKs, and no docs. TODO(omaha): Check docs again periodically.
|
| - // For now, act as if no label was set, and default to medium.
|
| - return S_FALSE;
|
| - }
|
| -
|
| - if (and_children) {
|
| - *and_children = ((mandatory_label_ace->Header.AceFlags &
|
| - (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE))
|
| - == (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE));
|
| - }
|
| -
|
| - return GetSidIntegrityLevel(reinterpret_cast<SID*>(&mandatory_label_ace->
|
| - SidStart), level);
|
| -}
|
| -
|
| -// If successful, the caller needs to free the ACL using LocalFree()
|
| -// on failure, returns NULL
|
| -static ACL* CreateMandatoryLabelAcl(MANDATORY_LEVEL level, bool and_children) {
|
| - int ace_size = sizeof(SYSTEM_MANDATORY_LABEL_ACE)
|
| - - sizeof(DWORD) + GetSidLengthRequired(1);
|
| - int acl_size = sizeof(ACL) + ace_size;
|
| -
|
| - ACL* acl = reinterpret_cast<ACL*>(LocalAlloc(LPTR, acl_size));
|
| - if (!acl)
|
| - return NULL;
|
| -
|
| - bool failed = true;
|
| - if (InitializeAcl(acl, acl_size, ACL_REVISION)) {
|
| - if (level > 0) {
|
| - SYSTEM_MANDATORY_LABEL_ACE* ace = reinterpret_cast<
|
| - SYSTEM_MANDATORY_LABEL_ACE*>(LocalAlloc(LPTR, ace_size));
|
| - if (ace) {
|
| - ace->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE;
|
| - ace->Header.AceFlags = and_children ?
|
| - (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE) : 0;
|
| - ace->Header.AceSize = static_cast<WORD>(ace_size);
|
| - ace->Mask = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP;
|
| -
|
| - SID* sid = reinterpret_cast<SID*>(&ace->SidStart);
|
| -
|
| - if (InitializeSid(sid, &mandatory_label_auth, 1)) {
|
| - *GetSidSubAuthority(sid, 0) = static_cast<DWORD>(level) << 12;
|
| - failed = !AddAce(acl, ACL_REVISION, 0, ace, ace_size);
|
| - }
|
| - LocalFree(ace);
|
| - }
|
| - }
|
| - }
|
| - if (failed) {
|
| - LocalFree(acl);
|
| - acl = NULL;
|
| - }
|
| - return acl;
|
| -}
|
| -
|
| -
|
| -TCHAR* AllocFullRegPath(HKEY root, const TCHAR* subkey) {
|
| - if (!subkey)
|
| - return NULL;
|
| -
|
| - const TCHAR* root_string;
|
| -
|
| - if (root == HKEY_CURRENT_USER)
|
| - root_string = _T("CURRENT_USER\\");
|
| - else if (root == HKEY_LOCAL_MACHINE)
|
| - root_string = _T("MACHINE\\");
|
| - else if (root == HKEY_CLASSES_ROOT)
|
| - root_string = _T("CLASSES_ROOT\\");
|
| - else if (root == HKEY_USERS)
|
| - root_string = _T("USERS\\");
|
| - else
|
| - return NULL;
|
| -
|
| - size_t root_size = _tcslen(root_string);
|
| - size_t size = root_size + _tcslen(subkey) + 1;
|
| - TCHAR* result = reinterpret_cast<TCHAR*>(LocalAlloc(LPTR,
|
| - size * sizeof(TCHAR)));
|
| - if (!result)
|
| - return NULL;
|
| -
|
| - memcpy(result, root_string, size * sizeof(TCHAR));
|
| - memcpy(result + root_size, subkey, (1 + size - root_size) * sizeof(TCHAR));
|
| - return result;
|
| -}
|
| -
|
| -
|
| -bool IsUserNonElevatedAdmin() {
|
| - // If pre-Vista return false;
|
| - if (!IsVistaOrLater()) {
|
| - return false;
|
| - }
|
| -
|
| - bool non_elevated_admin = false;
|
| - scoped_handle token;
|
| - if (::OpenProcessToken(::GetCurrentProcess(), TOKEN_READ, address(token))) {
|
| - TOKEN_ELEVATION_TYPE elevation_type = TokenElevationTypeDefault;
|
| - DWORD infoLen = 0;
|
| - if (::GetTokenInformation(get(token),
|
| - TokenElevationType,
|
| - reinterpret_cast<void*>(&elevation_type),
|
| - sizeof(elevation_type),
|
| - &infoLen)) {
|
| - if (elevation_type == TokenElevationTypeLimited) {
|
| - non_elevated_admin = true;
|
| - }
|
| - }
|
| - }
|
| -
|
| - return non_elevated_admin;
|
| -}
|
| -
|
| -bool IsUserAdmin() {
|
| - // Determine if the user is part of the adminstators group. This will return
|
| - // true in case of XP and 2K if the user belongs to admin group. In case of
|
| - // Vista, it only returns true if the admin is running elevated.
|
| - SID_IDENTIFIER_AUTHORITY nt_authority = SECURITY_NT_AUTHORITY;
|
| - PSID administrators_group = NULL;
|
| - BOOL result = ::AllocateAndInitializeSid(&nt_authority,
|
| - 2,
|
| - SECURITY_BUILTIN_DOMAIN_RID,
|
| - DOMAIN_ALIAS_RID_ADMINS,
|
| - 0, 0, 0, 0, 0, 0,
|
| - &administrators_group);
|
| - if (result) {
|
| - if (!::CheckTokenMembership(NULL, administrators_group, &result)) {
|
| - result = false;
|
| - }
|
| - ::FreeSid(administrators_group);
|
| - }
|
| - return !!result;
|
| -}
|
| -
|
| -bool IsVistaOrLater() {
|
| - static bool known = false;
|
| - static bool is_vista = false;
|
| - if (!known) {
|
| - OSVERSIONINFOEX osvi = { 0 };
|
| - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
| - osvi.dwMajorVersion = 6;
|
| - DWORDLONG conditional = 0;
|
| - VER_SET_CONDITION(conditional, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
| - is_vista = !!VerifyVersionInfo(&osvi, VER_MAJORVERSION, conditional);
|
| - // If the Win32 API failed for some other reason, callers may incorrectly
|
| - // perform non-Vista operations. Assert we don't see any other failures.
|
| - ASSERT1(is_vista || ERROR_OLD_WIN_VERSION == ::GetLastError());
|
| - known = true;
|
| - }
|
| - return is_vista;
|
| -}
|
| -
|
| -HRESULT IsUserRunningSplitToken(bool* is_split_token) {
|
| - ASSERT1(is_split_token);
|
| -
|
| - if (!IsVistaOrLater()) {
|
| - *is_split_token = false;
|
| - return S_OK;
|
| - }
|
| -
|
| - scoped_handle process_token;
|
| - if (!::OpenProcessToken(::GetCurrentProcess(),
|
| - TOKEN_QUERY,
|
| - address(process_token))) {
|
| - HRESULT hr = HRESULTFromLastError();
|
| - UTIL_LOG(L1, (_T("[OpenProcessToken failed][0x%x]"), hr));
|
| - return hr;
|
| - }
|
| -
|
| - TOKEN_ELEVATION_TYPE elevation_type = TokenElevationTypeDefault;
|
| - DWORD size_returned = 0;
|
| - if (!::GetTokenInformation(get(process_token),
|
| - TokenElevationType,
|
| - &elevation_type,
|
| - sizeof(elevation_type),
|
| - &size_returned)) {
|
| - HRESULT hr = HRESULTFromLastError();
|
| - UTIL_LOG(L1, (_T("[GetTokenInformation failed][0x%x]"), hr));
|
| - return hr;
|
| - }
|
| -
|
| - *is_split_token = elevation_type == TokenElevationTypeFull ||
|
| - elevation_type == TokenElevationTypeLimited;
|
| - ASSERT1(*is_split_token || elevation_type == TokenElevationTypeDefault);
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -bool IsUACMaybeOn() {
|
| - ASSERT1(vista_util::IsVistaOrLater());
|
| -
|
| - // The presence of a split token definitively indicates that UAC is on. But
|
| - // the absence does not necessarily indicate that UAC is off.
|
| - bool is_split_token = false;
|
| - if (SUCCEEDED(IsUserRunningSplitToken(&is_split_token)) && is_split_token) {
|
| - return true;
|
| - }
|
| -
|
| - const TCHAR* key_name = _T("HKLM\\SOFTWARE\\Microsoft\\Windows\\")
|
| - _T("CurrentVersion\\Policies\\System");
|
| -
|
| - DWORD enable_lua = 0;
|
| - return FAILED(RegKey::GetValue(key_name, _T("EnableLUA"), &enable_lua)) ||
|
| - enable_lua;
|
| -}
|
| -
|
| -bool IsElevatedWithUACMaybeOn() {
|
| - return IsUserAdmin() && IsVistaOrLater() && IsUACMaybeOn();
|
| -}
|
| -
|
| -HRESULT RunElevated(const TCHAR* file_path,
|
| - const TCHAR* parameters,
|
| - int show_window,
|
| - DWORD* exit_code) {
|
| - UTIL_LOG(L1, (_T("[Running elevated][%s][%s]"), file_path, parameters));
|
| -
|
| - ASSERT1(vista_util::IsVistaOrLater());
|
| - ASSERT1(!vista_util::IsUserAdmin());
|
| -
|
| - SHELLEXECUTEINFO shell_execute_info;
|
| - shell_execute_info.cbSize = sizeof(SHELLEXECUTEINFO);
|
| - shell_execute_info.fMask = SEE_MASK_FLAG_NO_UI |
|
| - SEE_MASK_NOZONECHECKS |
|
| - SEE_MASK_NOASYNC;
|
| - if (exit_code != NULL) {
|
| - shell_execute_info.fMask |= SEE_MASK_NOCLOSEPROCESS;
|
| - }
|
| - shell_execute_info.hProcess = NULL;
|
| - shell_execute_info.hwnd = NULL;
|
| - shell_execute_info.lpVerb = L"runas";
|
| - shell_execute_info.lpFile = file_path;
|
| - shell_execute_info.lpParameters = parameters;
|
| - shell_execute_info.lpDirectory = NULL;
|
| - shell_execute_info.nShow = show_window;
|
| - shell_execute_info.hInstApp = NULL;
|
| -
|
| - if (!ShellExecuteExEnsureParent(&shell_execute_info)) {
|
| - return AtlHresultFromLastError();
|
| - }
|
| -
|
| - scoped_process process(shell_execute_info.hProcess);
|
| -
|
| - // Wait for the end of the spawned process, if needed
|
| - if (exit_code) {
|
| - WaitForSingleObject(get(process), INFINITE);
|
| - VERIFY1(GetExitCodeProcess(get(process), exit_code));
|
| - UTIL_LOG(L1, (_T("[Elevated process exited][PID: %u][exit code: %u]"),
|
| - Process::GetProcessIdFromHandle(get(process)), *exit_code));
|
| - } else {
|
| - UTIL_LOG(L1, (_T("[Elevated process exited][PID: %u]"),
|
| - Process::GetProcessIdFromHandle(get(process))));
|
| - }
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -
|
| -HRESULT GetProcessIntegrityLevel(DWORD process_id, MANDATORY_LEVEL* level) {
|
| - if (!IsVistaOrLater())
|
| - return E_NOTIMPL;
|
| -
|
| - if (process_id == 0)
|
| - process_id = ::GetCurrentProcessId();
|
| -
|
| - HRESULT result = E_FAIL;
|
| - HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, process_id);
|
| - if (process != NULL) {
|
| - HANDLE current_token;
|
| - if (OpenProcessToken(process,
|
| - TOKEN_QUERY | TOKEN_QUERY_SOURCE,
|
| - ¤t_token)) {
|
| - DWORD label_size = 0;
|
| - TOKEN_MANDATORY_LABEL* label;
|
| - GetTokenInformation(current_token, TokenIntegrityLevel,
|
| - NULL, 0, &label_size);
|
| - if (label_size && (label = reinterpret_cast<TOKEN_MANDATORY_LABEL*>
|
| - (LocalAlloc(LPTR, label_size))) != NULL) {
|
| - if (GetTokenInformation(current_token, TokenIntegrityLevel,
|
| - label, label_size, &label_size)) {
|
| - result = GetSidIntegrityLevel(label->Label.Sid, level);
|
| - }
|
| - LocalFree(label);
|
| - }
|
| - CloseHandle(current_token);
|
| - }
|
| - CloseHandle(process);
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -
|
| -HRESULT GetFileOrFolderIntegrityLevel(const TCHAR* file,
|
| - MANDATORY_LEVEL* level, bool* and_children) {
|
| - if (!IsVistaOrLater())
|
| - return E_NOTIMPL;
|
| -
|
| - PSECURITY_DESCRIPTOR descriptor;
|
| - PACL acl = NULL;
|
| -
|
| - DWORD result = GetNamedSecurityInfo(const_cast<TCHAR*>(file), SE_FILE_OBJECT,
|
| - LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, &acl, &descriptor);
|
| - if (result != ERROR_SUCCESS)
|
| - return HRESULT_FROM_WIN32(result);
|
| -
|
| - HRESULT hr = GetAclIntegrityLevel(acl, level, and_children);
|
| - LocalFree(descriptor);
|
| - return hr;
|
| -}
|
| -
|
| -
|
| -HRESULT SetFileOrFolderIntegrityLevel(const TCHAR* file,
|
| - MANDATORY_LEVEL level, bool and_children) {
|
| - if (!IsVistaOrLater())
|
| - return E_NOTIMPL;
|
| -
|
| - ACL* acl = CreateMandatoryLabelAcl(level, and_children);
|
| - if (!acl)
|
| - return E_FAIL;
|
| -
|
| - DWORD result = SetNamedSecurityInfo(const_cast<TCHAR*>(file), SE_FILE_OBJECT,
|
| - LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, acl);
|
| - LocalFree(acl);
|
| - return HRESULT_FROM_WIN32(result);
|
| -}
|
| -
|
| -
|
| -HRESULT GetRegKeyIntegrityLevel(HKEY root, const TCHAR* subkey,
|
| - MANDATORY_LEVEL* level, bool* and_children) {
|
| - if (!IsVistaOrLater())
|
| - return E_NOTIMPL;
|
| -
|
| - TCHAR* reg_path = AllocFullRegPath(root, subkey);
|
| - if (!reg_path)
|
| - return E_FAIL;
|
| -
|
| - PSECURITY_DESCRIPTOR descriptor;
|
| - PACL acl = NULL;
|
| -
|
| - DWORD result = GetNamedSecurityInfo(reg_path, SE_REGISTRY_KEY,
|
| - LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, &acl, &descriptor);
|
| - if (result != ERROR_SUCCESS) {
|
| - LocalFree(reg_path);
|
| - return HRESULT_FROM_WIN32(result);
|
| - }
|
| -
|
| - HRESULT hr = GetAclIntegrityLevel(acl, level, and_children);
|
| - LocalFree(descriptor);
|
| - LocalFree(reg_path);
|
| - return hr;
|
| -}
|
| -
|
| -
|
| -HRESULT SetRegKeyIntegrityLevel(HKEY root, const TCHAR* subkey,
|
| - MANDATORY_LEVEL level, bool and_children) {
|
| - if (!IsVistaOrLater())
|
| - return E_NOTIMPL;
|
| -
|
| - TCHAR* reg_path = AllocFullRegPath(root, subkey);
|
| - if (!reg_path)
|
| - return E_FAIL;
|
| -
|
| - ACL* acl = CreateMandatoryLabelAcl(level, and_children);
|
| - if (!acl) {
|
| - LocalFree(reg_path);
|
| - return E_FAIL;
|
| - }
|
| -
|
| - DWORD result = SetNamedSecurityInfo(reg_path, SE_REGISTRY_KEY,
|
| - LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, acl);
|
| - LocalFree(acl);
|
| - LocalFree(reg_path);
|
| - return HRESULT_FROM_WIN32(result);
|
| -}
|
| -
|
| -
|
| -CSecurityDesc* BuildSecurityDescriptor(const TCHAR* sddl_sacl,
|
| - ACCESS_MASK mask) {
|
| - if (!IsVistaOrLater()) {
|
| - return NULL;
|
| - }
|
| -
|
| - scoped_ptr<CSecurityDesc> security_descriptor(new CSecurityDesc);
|
| - security_descriptor->FromString(sddl_sacl);
|
| -
|
| - // Fill out the rest of the security descriptor from the process token.
|
| - CAccessToken token;
|
| - if (!token.GetProcessToken(TOKEN_QUERY)) {
|
| - return NULL;
|
| - }
|
| -
|
| - // The owner.
|
| - CSid sid_owner;
|
| - if (!token.GetOwner(&sid_owner)) {
|
| - return NULL;
|
| - }
|
| - security_descriptor->SetOwner(sid_owner);
|
| -
|
| - // The group.
|
| - CSid sid_group;
|
| - if (!token.GetPrimaryGroup(&sid_group)) {
|
| - return NULL;
|
| - }
|
| - security_descriptor->SetGroup(sid_group);
|
| -
|
| - // The discretionary access control list.
|
| - CDacl dacl;
|
| - if (!token.GetDefaultDacl(&dacl)) {
|
| - return NULL;
|
| - }
|
| -
|
| - // Add an access control entry mask for the current user.
|
| - // This is what grants this user access from lower integrity levels.
|
| - CSid sid_user;
|
| - if (!token.GetUser(&sid_user)) {
|
| - return NULL;
|
| - }
|
| -
|
| - if (!dacl.AddAllowedAce(sid_user, mask)) {
|
| - return NULL;
|
| - }
|
| -
|
| - // Lastly, save the dacl to this descriptor.
|
| - security_descriptor->SetDacl(dacl);
|
| - return security_descriptor.release();
|
| -};
|
| -
|
| -CSecurityDesc* CreateLowIntegritySecurityDesc(ACCESS_MASK mask) {
|
| - return BuildSecurityDescriptor(LOW_INTEGRITY_SDDL_SACL, mask);
|
| -}
|
| -
|
| -CSecurityDesc* CreateMediumIntegritySecurityDesc(ACCESS_MASK mask) {
|
| - return BuildSecurityDescriptor(MEDIUM_INTEGRITY_SDDL_SACL, mask);
|
| -}
|
| -
|
| -HRESULT AddLowIntegritySaclToExistingDesc(CSecurityDesc* sd) {
|
| - ASSERT1(sd);
|
| - ASSERT1(sd->GetPSECURITY_DESCRIPTOR());
|
| -
|
| - if (!IsVistaOrLater()) {
|
| - return S_FALSE;
|
| - }
|
| -
|
| - CSecurityDesc sd_low;
|
| - if (!sd_low.FromString(LOW_INTEGRITY_SDDL_SACL)) {
|
| - HRESULT hr = HRESULTFromLastError();
|
| - UTIL_LOG(LE, (_T("[Failed to parse LOW_INTEGRITY_SDDL_SACL][0x%x]"), hr));
|
| - return hr;
|
| - }
|
| -
|
| - // Atl::CSacl does not support SYSTEM_MANDATORY_LABEL_ACE_TYPE.
|
| - BOOL sacl_present = FALSE;
|
| - BOOL sacl_defaulted = FALSE;
|
| - PACL sacl = NULL;
|
| - if (!::GetSecurityDescriptorSacl(
|
| - const_cast<SECURITY_DESCRIPTOR*>(sd_low.GetPSECURITY_DESCRIPTOR()),
|
| - &sacl_present,
|
| - &sacl,
|
| - &sacl_defaulted) ||
|
| - !sacl) {
|
| - HRESULT hr = HRESULTFromLastError();
|
| - UTIL_LOG(LE, (_T("[Failed to get the low integrity SACL][0x%x]"), hr));
|
| - return hr;
|
| - }
|
| -
|
| - ACL_SIZE_INFORMATION acl_size = {0};
|
| - if (!::GetAclInformation(sacl,
|
| - &acl_size,
|
| - sizeof(acl_size),
|
| - AclSizeInformation)) {
|
| - HRESULT hr = HRESULTFromLastError();
|
| - UTIL_LOG(LE, (_T("[Failed to get AclSizeInformation][0x%x]"), hr));
|
| - return hr;
|
| - }
|
| -
|
| - // The CSecurityDesc destructor expects the memory to have been malloced.
|
| - PACL new_sacl = static_cast<PACL>(malloc(acl_size.AclBytesInUse));
|
| - ::CopyMemory(new_sacl, sacl, acl_size.AclBytesInUse);
|
| -
|
| - CSacl sacl_empty;
|
| - sd->SetSacl(sacl_empty);
|
| -
|
| - if (!::SetSecurityDescriptorSacl(
|
| - const_cast<SECURITY_DESCRIPTOR*>(sd->GetPSECURITY_DESCRIPTOR()),
|
| - sacl_present,
|
| - new_sacl,
|
| - sacl_defaulted)) {
|
| - HRESULT hr = HRESULTFromLastError();
|
| - UTIL_LOG(LE, (_T("[Failed to set the low integrity SACL][0x%x]"), hr));
|
| - free(new_sacl);
|
| - return hr;
|
| - }
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -} // namespace vista_util
|
| -
|
| -} // namespace omaha
|
| -
|
|
|