blob: d4c37ffd2d08db3e05e01757f75a0e46391e21c3 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/conflicts/token_util_win.h"
#include <windows.h>
#include <stdint.h>
#include "base/win/scoped_handle.h"
namespace {
// Checks if the |token| is member of |group_sid|. |token| must be an
// impersonating token. Use a null handle to check for the token of the current
// thread. Returns false on error.
bool IsMemberOfGroupSID(SID* group_sid, HANDLE token) {
BOOL is_member = FALSE;
return ::CheckTokenMembership(token, group_sid, &is_member) && !!is_member;
}
} // namespace
bool HasAdminRights() {
// Get the SID for the administrators group.
DWORD sid_size = SECURITY_MAX_SID_SIZE;
uint8_t sid_bytes[SECURITY_MAX_SID_SIZE];
SID* administrators_sid = reinterpret_cast<SID*>(sid_bytes);
if (!::CreateWellKnownSid(WinBuiltinAdministratorsSid, nullptr,
administrators_sid, &sid_size)) {
return false;
}
// Check if the current token is member of the built-in Administrators group.
if (IsMemberOfGroupSID(administrators_sid, nullptr))
return true;
// In the case that UAC is enabled, it's possible that the current token is
// filtered. So check the linked token in case it is a member of the built-in
// Administrators group.
HANDLE current_token = nullptr;
if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &current_token))
return false;
base::win::ScopedHandle scoped_current_token(current_token);
HANDLE linked_token = nullptr;
DWORD linked_token_size = sizeof(linked_token);
if (!::GetTokenInformation(scoped_current_token.Get(), TokenLinkedToken,
&linked_token, linked_token_size,
&linked_token_size)) {
return false;
}
base::win::ScopedHandle scoped_linked_token(linked_token);
return IsMemberOfGroupSID(administrators_sid, scoped_linked_token.Get());
}