[Windows] Add an AccessToken class to base/win.

This CL adds an AccessToken class to base/win to query properties of a
Windows access token. This is to remove the repeated use of the
GetTokenInformation API as well as removing requirements for including
the Windows headers.

Bug: 1270309
Change-Id: Ic49fee5faa7e3f3d61994de1d38ec2921de3ea4c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3301649
Reviewed-by: Will Harris <wfh@chromium.org>
Commit-Queue: James Forshaw <forshaw@chromium.org>
Cr-Commit-Position: refs/heads/main@{#946260}
NOKEYCHECK=True
GitOrigin-RevId: 158c5fad3ef830e95f1eedb702878697e4dd0154
diff --git a/policy/win/sandbox_win.cc b/policy/win/sandbox_win.cc
index 2db3ac6..ba68235 100644
--- a/policy/win/sandbox_win.cc
+++ b/policy/win/sandbox_win.cc
@@ -286,23 +286,16 @@
     BlocklistAddOneDll(kTroublesomeDlls[ix], true, policy);
 }
 
+DWORD GetSessionId() {
+  DWORD session_id;
+  CHECK(::ProcessIdToSessionId(::GetCurrentProcessId(), &session_id));
+  return session_id;
+}
+
 // Returns the object path prepended with the current logon session.
 std::wstring PrependWindowsSessionPath(const wchar_t* object) {
   // Cache this because it can't change after process creation.
-  static DWORD s_session_id = 0;
-  if (s_session_id == 0) {
-    HANDLE token;
-    DWORD session_id_length;
-    DWORD session_id = 0;
-
-    CHECK(::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &token));
-    CHECK(::GetTokenInformation(token, TokenSessionId, &session_id,
-                                sizeof(session_id), &session_id_length));
-    CloseHandle(token);
-    if (session_id)
-      s_session_id = session_id;
-  }
-
+  static DWORD s_session_id = GetSessionId();
   return base::StringPrintf(L"\\Sessions\\%lu%ls", s_session_id, object);
 }
 
diff --git a/win/src/acl.cc b/win/src/acl.cc
index 4c70d03..f43d757 100644
--- a/win/src/acl.cc
+++ b/win/src/acl.cc
@@ -15,35 +15,13 @@
 #include "base/check.h"
 #include "base/memory/free_deleter.h"
 #include "base/notreached.h"
+#include "base/win/access_token.h"
 #include "base/win/scoped_localalloc.h"
 
 namespace sandbox {
 
 namespace {
 
-bool GetDefaultDacl(
-    HANDLE token,
-    std::unique_ptr<TOKEN_DEFAULT_DACL, base::FreeDeleter>* default_dacl) {
-  if (!token)
-    return false;
-
-  DCHECK(default_dacl);
-
-  unsigned long length = 0;
-  ::GetTokenInformation(token, TokenDefaultDacl, nullptr, 0, &length);
-  if (length == 0) {
-    NOTREACHED();
-    return false;
-  }
-
-  TOKEN_DEFAULT_DACL* acl =
-      reinterpret_cast<TOKEN_DEFAULT_DACL*>(malloc(length));
-  default_dacl->reset(acl);
-
-  return !!::GetTokenInformation(token, TokenDefaultDacl, default_dacl->get(),
-                                 length, &length);
-}
-
 ACCESS_MODE ConvertAccessMode(SecurityAccessMode access_mode) {
   switch (access_mode) {
     case SecurityAccessMode::kGrant:
@@ -61,25 +39,21 @@
   return NOT_USED_ACCESS;
 }
 
-bool AddSidToDacl(const base::win::Sid& sid,
-                  ACL* old_dacl,
-                  SecurityAccessMode access_mode,
-                  ACCESS_MASK access,
-                  ACL** new_dacl) {
-  EXPLICIT_ACCESS new_access = {0};
+absl::optional<base::win::ScopedLocalAllocTyped<ACL>> AddSidToDacl(
+    const base::win::Sid& sid,
+    ACL* old_dacl,
+    SecurityAccessMode access_mode,
+    ACCESS_MASK access) {
+  EXPLICIT_ACCESS new_access = {};
   new_access.grfAccessMode = ConvertAccessMode(access_mode);
   new_access.grfAccessPermissions = access;
   new_access.grfInheritance = NO_INHERITANCE;
-
-  new_access.Trustee.pMultipleTrustee = nullptr;
-  new_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
-  new_access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
-  new_access.Trustee.ptstrName = reinterpret_cast<LPWSTR>(sid.GetPSID());
-
-  if (ERROR_SUCCESS != ::SetEntriesInAcl(1, &new_access, old_dacl, new_dacl))
-    return false;
-
-  return true;
+  ::BuildTrusteeWithSid(&new_access.Trustee, sid.GetPSID());
+  ACL* new_dacl = nullptr;
+  if (ERROR_SUCCESS != ::SetEntriesInAcl(1, &new_access, old_dacl, &new_dacl))
+    return absl::nullopt;
+  DCHECK(::IsValidAcl(new_dacl));
+  return base::win::TakeLocalAlloc(new_dacl);
 }
 
 SE_OBJECT_TYPE ConvertObjectType(SecurityObjectType object_type) {
@@ -123,33 +97,41 @@
   return absl::nullopt;
 }
 
-}  // namespace
-
 bool AddSidToDefaultDacl(HANDLE token,
+                         const base::win::AccessToken& query_token,
                          const base::win::Sid& sid,
                          SecurityAccessMode access_mode,
                          ACCESS_MASK access) {
   if (!token)
     return false;
 
-  std::unique_ptr<TOKEN_DEFAULT_DACL, base::FreeDeleter> default_dacl;
-  if (!GetDefaultDacl(token, &default_dacl))
+  absl::optional<base::win::AccessToken::Dacl> dacl = query_token.DefaultDacl();
+  if (!dacl)
+    return false;
+  auto new_dacl = AddSidToDacl(sid, dacl->GetAcl(), access_mode, access);
+  if (!new_dacl)
     return false;
 
-  ACL* new_dacl_ptr = nullptr;
-  if (!AddSidToDacl(sid, default_dacl->DefaultDacl, access_mode, access,
-                    &new_dacl_ptr)) {
-    return false;
-  }
-
-  auto new_dacl = base::win::TakeLocalAlloc(new_dacl_ptr);
   TOKEN_DEFAULT_DACL new_token_dacl = {0};
-  new_token_dacl.DefaultDacl = new_dacl.get();
-
+  new_token_dacl.DefaultDacl = new_dacl->get();
   return !!::SetTokenInformation(token, TokenDefaultDacl, &new_token_dacl,
                                  sizeof(new_token_dacl));
 }
 
+}  // namespace
+
+bool AddSidToDefaultDacl(HANDLE token,
+                         const base::win::Sid& sid,
+                         SecurityAccessMode access_mode,
+                         ACCESS_MASK access) {
+  absl::optional<base::win::AccessToken> query_token =
+      base::win::AccessToken::FromToken(token);
+  if (!query_token)
+    return false;
+
+  return AddSidToDefaultDacl(token, *query_token, sid, access_mode, access);
+}
+
 bool AddSidToDefaultDacl(HANDLE token,
                          base::win::WellKnownSid known_sid,
                          SecurityAccessMode access_mode,
@@ -161,38 +143,25 @@
 }
 
 bool RevokeLogonSidFromDefaultDacl(HANDLE token) {
-  char logon_sid_buffer[sizeof(TOKEN_GROUPS) + SECURITY_MAX_SID_SIZE];
-  DWORD size = sizeof(logon_sid_buffer);
+  absl::optional<base::win::AccessToken> query_token =
+      base::win::AccessToken::FromToken(token);
+  if (!query_token)
+    return false;
+  absl::optional<base::win::Sid> logon_sid = query_token->LogonId();
+  if (!logon_sid)
+    return ::GetLastError() == ERROR_NOT_FOUND;
 
-  if (!::GetTokenInformation(token, TokenLogonSid, logon_sid_buffer, size,
-                             &size)) {
-    // If no logon sid, there's nothing to revoke.
-    if (::GetLastError() == ERROR_NOT_FOUND)
-      return true;
-    return false;
-  }
-  TOKEN_GROUPS* logon_sid_ptr =
-      reinterpret_cast<TOKEN_GROUPS*>(logon_sid_buffer);
-  if (logon_sid_ptr->GroupCount < 1) {
-    ::SetLastError(ERROR_INVALID_TOKEN);
-    return false;
-  }
-  absl::optional<base::win::Sid> logon_sid =
-      base::win::Sid::FromPSID(logon_sid_ptr->Groups[0].Sid);
-  if (!logon_sid) {
-    ::SetLastError(ERROR_INVALID_SID);
-    return false;
-  }
-  return AddSidToDefaultDacl(token, *logon_sid, SecurityAccessMode::kRevoke, 0);
+  return AddSidToDefaultDacl(token, *query_token, *logon_sid,
+                             SecurityAccessMode::kRevoke, 0);
 }
 
 bool AddUserSidToDefaultDacl(HANDLE token, ACCESS_MASK access) {
-  absl::optional<base::win::Sid> user_sid = base::win::Sid::FromToken(token);
-  if (!user_sid)
+  absl::optional<base::win::AccessToken> query_token =
+      base::win::AccessToken::FromToken(token);
+  if (!query_token)
     return false;
-
-  return AddSidToDefaultDacl(token, *user_sid, SecurityAccessMode::kGrant,
-                             access);
+  return AddSidToDefaultDacl(token, *query_token, query_token->User(),
+                             SecurityAccessMode::kGrant, access);
 }
 
 bool AddKnownSidToObject(HANDLE object,
@@ -214,14 +183,13 @@
   }
 
   auto descriptor = base::win::TakeLocalAlloc(descriptor_ptr);
-  PACL new_dacl_ptr = nullptr;
-  if (!AddSidToDacl(sid, old_dacl, access_mode, access, &new_dacl_ptr))
+  auto new_dacl = AddSidToDacl(sid, old_dacl, access_mode, access);
+  if (!new_dacl)
     return false;
 
-  auto new_dacl = base::win::TakeLocalAlloc(new_dacl_ptr);
   return ::SetSecurityInfo(object, native_object_type,
                            DACL_SECURITY_INFORMATION, nullptr, nullptr,
-                           new_dacl.get(), nullptr) == ERROR_SUCCESS;
+                           new_dacl->get(), nullptr) == ERROR_SUCCESS;
 }
 
 bool AddKnownSidToObject(HANDLE object,
diff --git a/win/src/app_container_test.cc b/win/src/app_container_test.cc
index 5a166fe..d942eab 100644
--- a/win/src/app_container_test.cc
+++ b/win/src/app_container_test.cc
@@ -28,6 +28,7 @@
 #include "base/task/thread_pool.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_timeouts.h"
+#include "base/win/access_token.h"
 #include "base/win/scoped_handle.h"
 #include "base/win/scoped_localalloc.h"
 #include "base/win/scoped_process_information.h"
@@ -35,7 +36,6 @@
 #include "base/win/windows_version.h"
 #include "sandbox/win/src/app_container_base.h"
 #include "sandbox/win/src/sandbox_factory.h"
-#include "sandbox/win/src/win_utils.h"
 #include "sandbox/win/tests/common/controller.h"
 #include "sandbox/win/tests/common/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -68,78 +68,55 @@
                             base::RandUint64());
 }
 
-const char* TokenTypeToName(TOKEN_TYPE token_type) {
-  return token_type == ::TokenPrimary ? "Primary Token" : "Impersonation Token";
+const char* TokenTypeToName(bool impersonation) {
+  return impersonation ? "Impersonation Token" : "Primary Token";
 }
 
-void CheckToken(HANDLE token,
-                TOKEN_TYPE token_type,
+void CheckToken(const absl::optional<base::win::AccessToken>& token,
+                bool impersonation,
                 PSECURITY_CAPABILITIES security_capabilities,
-                BOOL restricted) {
-  ASSERT_EQ(restricted, ::IsTokenRestricted(token))
-      << TokenTypeToName(token_type);
-
-  DWORD appcontainer;
-  DWORD return_length;
-  ASSERT_TRUE(::GetTokenInformation(token, ::TokenIsAppContainer, &appcontainer,
-                                    sizeof(appcontainer), &return_length))
-      << TokenTypeToName(token_type);
-  ASSERT_TRUE(appcontainer) << TokenTypeToName(token_type);
-  TOKEN_TYPE token_type_real;
-  ASSERT_TRUE(::GetTokenInformation(token, ::TokenType, &token_type_real,
-                                    sizeof(token_type_real), &return_length))
-      << TokenTypeToName(token_type);
-  ASSERT_EQ(token_type_real, token_type) << TokenTypeToName(token_type);
-  if (token_type == ::TokenImpersonation) {
-    SECURITY_IMPERSONATION_LEVEL imp_level;
-    ASSERT_TRUE(::GetTokenInformation(token, ::TokenImpersonationLevel,
-                                      &imp_level, sizeof(imp_level),
-                                      &return_length))
-        << TokenTypeToName(token_type);
-    ASSERT_EQ(imp_level, ::SecurityImpersonation)
-        << TokenTypeToName(token_type);
+                bool restricted) {
+  ASSERT_TRUE(token);
+  EXPECT_EQ(restricted, token->IsRestricted())
+      << TokenTypeToName(impersonation);
+  EXPECT_TRUE(token->IsAppContainer()) << TokenTypeToName(impersonation);
+  EXPECT_EQ(token->IsImpersonation(), impersonation)
+      << TokenTypeToName(impersonation);
+  if (impersonation) {
+    EXPECT_FALSE(token->IsIdentification()) << TokenTypeToName(impersonation);
   }
 
-  absl::optional<base::win::Sid> package_sid = GetTokenAppContainerSid(token);
-  ASSERT_TRUE(package_sid) << TokenTypeToName(token_type);
-  EXPECT_TRUE(::EqualSid(security_capabilities->AppContainerSid,
-                         package_sid->GetPSID()))
-      << TokenTypeToName(token_type);
+  absl::optional<base::win::Sid> package_sid = token->AppContainerSid();
+  ASSERT_TRUE(package_sid) << TokenTypeToName(impersonation);
+  EXPECT_TRUE(package_sid->Equal(security_capabilities->AppContainerSid))
+      << TokenTypeToName(impersonation);
 
-  absl::optional<std::vector<SidAndAttributes>> capability_groups =
-      GetTokenGroups(token, ::TokenCapabilities);
-  ASSERT_TRUE(capability_groups) << TokenTypeToName(token_type);
-  const std::vector<SidAndAttributes>& capabilities = *capability_groups;
-
+  std::vector<base::win::AccessToken::Group> capabilities =
+      token->Capabilities();
   ASSERT_EQ(capabilities.size(), security_capabilities->CapabilityCount)
-      << TokenTypeToName(token_type);
+      << TokenTypeToName(impersonation);
   for (size_t index = 0; index < capabilities.size(); ++index) {
     EXPECT_EQ(capabilities[index].GetAttributes(),
               security_capabilities->Capabilities[index].Attributes)
-        << TokenTypeToName(token_type);
-    EXPECT_TRUE(::EqualSid(capabilities[index].GetPSID(),
-                           security_capabilities->Capabilities[index].Sid))
-        << TokenTypeToName(token_type);
+        << TokenTypeToName(impersonation);
+    EXPECT_TRUE(capabilities[index].GetSid().Equal(
+        security_capabilities->Capabilities[index].Sid))
+        << TokenTypeToName(impersonation);
   }
 }
 
 void CheckProcessToken(HANDLE process,
                        PSECURITY_CAPABILITIES security_capabilities,
                        bool restricted) {
-  HANDLE token_handle;
-  ASSERT_TRUE(::OpenProcessToken(process, TOKEN_ALL_ACCESS, &token_handle));
-  base::win::ScopedHandle token(token_handle);
-  CheckToken(token_handle, ::TokenPrimary, security_capabilities, restricted);
+  CheckToken(base::win::AccessToken::FromProcess(process), false,
+             security_capabilities, restricted);
 }
 
 void CheckThreadToken(HANDLE thread,
                       PSECURITY_CAPABILITIES security_capabilities,
                       bool restricted) {
-  HANDLE token_handle;
-  ASSERT_TRUE(::OpenThreadToken(thread, TOKEN_ALL_ACCESS, TRUE, &token_handle));
-  base::win::ScopedHandle token(token_handle);
-  CheckToken(token_handle, ::TokenImpersonation, security_capabilities,
-             restricted);
+  CheckToken(base::win::AccessToken::FromThread(thread), true,
+             security_capabilities, restricted);
 }
 
 // Check for LPAC using an access check. We could query for a security attribute
diff --git a/win/src/integrity_level_test.cc b/win/src/integrity_level_test.cc
index a4788af..0fa2627 100644
--- a/win/src/integrity_level_test.cc
+++ b/win/src/integrity_level_test.cc
@@ -7,12 +7,14 @@
 #include <atlsecurity.h>
 
 #include "base/process/process_info.h"
+#include "base/win/access_token.h"
 #include "base/win/windows_version.h"
 #include "sandbox/win/src/sandbox.h"
 #include "sandbox/win/src/sandbox_factory.h"
 #include "sandbox/win/src/sandbox_policy.h"
 #include "sandbox/win/tests/common/controller.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -29,29 +31,12 @@
 }
 
 SBOX_TESTS_COMMAND int CheckIntegrityLevel(int argc, wchar_t** argv) {
-  ATL::CAccessToken token;
-  if (!token.GetEffectiveToken(TOKEN_READ))
+  absl::optional<base::win::AccessToken> token =
+      base::win::AccessToken::FromEffective();
+  if (!token)
     return SBOX_TEST_FAILED;
 
-  char* buffer[100];
-  DWORD buf_size = 100;
-  if (!::GetTokenInformation(token.GetHandle(), TokenIntegrityLevel,
-                             reinterpret_cast<void*>(buffer), buf_size,
-                             &buf_size))
-    return SBOX_TEST_FAILED;
-
-  TOKEN_MANDATORY_LABEL* label =
-      reinterpret_cast<TOKEN_MANDATORY_LABEL*>(buffer);
-
-  PSID sid_low = nullptr;
-  if (!::ConvertStringSidToSid(L"S-1-16-4096", &sid_low))
-    return SBOX_TEST_FAILED;
-
-  bool is_low_sid = ::EqualSid(label->Label.Sid, sid_low);
-
-  ::LocalFree(sid_low);
-
-  if (is_low_sid)
+  if (token->IntegrityLevel() == SECURITY_MANDATORY_LOW_RID)
     return SBOX_TEST_SUCCEEDED;
 
   return SBOX_TEST_DENIED;
diff --git a/win/src/restricted_token.cc b/win/src/restricted_token.cc
index 16c96d4..7977565 100644
--- a/win/src/restricted_token.cc
+++ b/win/src/restricted_token.cc
@@ -9,25 +9,15 @@
 #include <stddef.h>
 
 #include <memory>
+#include <unordered_set>
 #include <vector>
 
 #include "base/logging.h"
+#include "base/win/access_token.h"
 #include "sandbox/win/src/acl.h"
-#include "sandbox/win/src/win_utils.h"
 
 namespace {
 
-// Wrapper for utility version to unwrap ScopedHandle.
-std::unique_ptr<BYTE[]> GetTokenInfo(const base::win::ScopedHandle& token,
-                                     TOKEN_INFORMATION_CLASS info_class,
-                                     DWORD* error) {
-  std::unique_ptr<BYTE[]> buffer;
-  *error = sandbox::GetTokenInformation(token.Get(), info_class, &buffer);
-  if (*error != ERROR_SUCCESS)
-    return nullptr;
-  return buffer;
-}
-
 LUID ConvertToLuid(const CHROME_LUID& luid) {
   LUID ret;
   memcpy(&ret, &luid, sizeof(luid));
@@ -82,6 +72,11 @@
     }
   }
   effective_token_.Set(temp_token);
+  absl::optional<base::win::AccessToken> query_token =
+      base::win::AccessToken::FromToken(effective_token_.Get());
+  if (!query_token)
+    return ERROR_NO_TOKEN;
+  query_token_.swap(query_token);
 
   init_ = true;
   return ERROR_SUCCESS;
@@ -178,21 +173,12 @@
     return err_code;
 
   HANDLE impersonation_token_handle;
-  if (!::DuplicateToken(restricted_token.Get(), SecurityImpersonation,
-                        &impersonation_token_handle)) {
+  if (!::DuplicateTokenEx(restricted_token.Get(), TOKEN_ALL_ACCESS, nullptr,
+                          SecurityImpersonation, TokenImpersonation,
+                          &impersonation_token_handle)) {
     return ::GetLastError();
   }
-  base::win::ScopedHandle impersonation_token(impersonation_token_handle);
-
-  HANDLE token_handle;
-  if (!::DuplicateHandle(::GetCurrentProcess(), impersonation_token.Get(),
-                         ::GetCurrentProcess(), &token_handle, TOKEN_ALL_ACCESS,
-                         false,  // Don't inherit.
-                         0)) {
-    return ::GetLastError();
-  }
-
-  token->Set(token_handle);
+  token->Set(impersonation_token_handle);
   return ERROR_SUCCESS;
 }
 
@@ -202,30 +188,19 @@
   if (!init_)
     return ERROR_NO_TOKEN;
 
-  DWORD error;
-  std::unique_ptr<BYTE[]> buffer =
-      GetTokenInfo(effective_token_, TokenGroups, &error);
-
-  if (!buffer)
-    return error;
-
-  TOKEN_GROUPS* token_groups = reinterpret_cast<TOKEN_GROUPS*>(buffer.get());
-
   // Build the list of the deny only group SIDs
-  for (unsigned int i = 0; i < token_groups->GroupCount; ++i) {
-    if ((token_groups->Groups[i].Attributes & SE_GROUP_INTEGRITY) == 0 &&
-        (token_groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) == 0) {
-      bool should_ignore = false;
-      for (const base::win::Sid& sid : exceptions) {
-        if (sid.Equal(token_groups->Groups[i].Sid)) {
-          should_ignore = true;
-          break;
-        }
+  for (const base::win::AccessToken::Group& group : query_token_->Groups()) {
+    if (group.IsIntegrity() || group.IsLogonId())
+      continue;
+    bool should_ignore = false;
+    for (const base::win::Sid& sid : exceptions) {
+      if (sid == group.GetSid()) {
+        should_ignore = true;
+        break;
       }
-      if (!should_ignore) {
-        sids_for_deny_only_.push_back(
-            *base::win::Sid::FromPSID(token_groups->Groups[i].Sid));
-      }
+    }
+    if (!should_ignore) {
+      sids_for_deny_only_.push_back(group.GetSid().Clone());
     }
   }
 
@@ -253,12 +228,7 @@
   if (!init_)
     return ERROR_NO_TOKEN;
 
-  absl::optional<base::win::Sid> user = base::win::Sid::CurrentUser();
-  if (!user)
-    return ERROR_INVALID_SID;
-
-  sids_for_deny_only_.push_back(std::move(*user));
-
+  sids_for_deny_only_.push_back(query_token_->User());
   return ERROR_SUCCESS;
 }
 
@@ -267,32 +237,13 @@
   DCHECK(init_);
   if (!init_)
     return ERROR_NO_TOKEN;
-
-  DWORD error;
-  std::unique_ptr<BYTE[]> buffer =
-      GetTokenInfo(effective_token_, TokenPrivileges, &error);
-
-  if (!buffer)
-    return error;
-
-  TOKEN_PRIVILEGES* token_privileges =
-      reinterpret_cast<TOKEN_PRIVILEGES*>(buffer.get());
-
+  std::unordered_set<std::wstring> privilege_set(exceptions.begin(),
+                                                 exceptions.end());
   // Build the list of privileges to disable
-  for (unsigned int i = 0; i < token_privileges->PrivilegeCount; ++i) {
-    bool should_ignore = false;
-    for (const std::wstring& name : exceptions) {
-      LUID luid = {};
-      ::LookupPrivilegeValue(nullptr, name.c_str(), &luid);
-      if (token_privileges->Privileges[i].Luid.HighPart == luid.HighPart &&
-          token_privileges->Privileges[i].Luid.LowPart == luid.LowPart) {
-        should_ignore = true;
-        break;
-      }
-    }
-    if (!should_ignore) {
-      privileges_to_disable_.push_back(
-          ConvertToChromeLuid(token_privileges->Privileges[i].Luid));
+  for (const base::win::AccessToken::Privilege& privilege :
+       query_token_->Privileges()) {
+    if (privilege_set.count(privilege.GetName()) == 0) {
+      privileges_to_disable_.push_back(privilege.GetLuid());
     }
   }
 
@@ -334,30 +285,9 @@
   if (!init_)
     return ERROR_NO_TOKEN;
 
-  DWORD error;
-  std::unique_ptr<BYTE[]> buffer =
-      GetTokenInfo(effective_token_, TokenGroups, &error);
-
-  if (!buffer)
-    return error;
-
-  TOKEN_GROUPS* token_groups = reinterpret_cast<TOKEN_GROUPS*>(buffer.get());
-
-  PSID logon_sid_ptr = nullptr;
-  for (unsigned int i = 0; i < token_groups->GroupCount; ++i) {
-    if ((token_groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) != 0) {
-      logon_sid_ptr = token_groups->Groups[i].Sid;
-      break;
-    }
-  }
-
-  if (logon_sid_ptr) {
-    absl::optional<base::win::Sid> logon_sid =
-        base::win::Sid::FromPSID(logon_sid_ptr);
-    if (!logon_sid)
-      return ERROR_INVALID_SID;
+  absl::optional<base::win::Sid> logon_sid = query_token_->LogonId();
+  if (logon_sid)
     sids_to_restrict_.push_back(std::move(*logon_sid));
-  }
   return ERROR_SUCCESS;
 }
 
@@ -365,12 +295,7 @@
   DCHECK(init_);
   if (!init_)
     return ERROR_NO_TOKEN;
-
-  absl::optional<base::win::Sid> user = base::win::Sid::CurrentUser();
-  if (!user)
-    return ERROR_INVALID_SID;
-  sids_to_restrict_.push_back(std::move(*user));
-
+  sids_to_restrict_.push_back(query_token_->User());
   return ERROR_SUCCESS;
 }
 
@@ -384,23 +309,10 @@
   if (ERROR_SUCCESS != error)
     return error;
 
-  std::unique_ptr<BYTE[]> buffer =
-      GetTokenInfo(effective_token_, TokenGroups, &error);
-
-  if (!buffer)
-    return error;
-
-  TOKEN_GROUPS* token_groups = reinterpret_cast<TOKEN_GROUPS*>(buffer.get());
-
-  // Build the list of restricting sids from all groups.
-  for (unsigned int i = 0; i < token_groups->GroupCount; ++i) {
-    if ((token_groups->Groups[i].Attributes & SE_GROUP_INTEGRITY) == 0) {
-      absl::optional<base::win::Sid> sid =
-          base::win::Sid::FromPSID(token_groups->Groups[i].Sid);
-      if (!sid)
-        return ERROR_INVALID_SID;
-      AddRestrictingSid(*sid);
-    }
+  for (const base::win::AccessToken::Group& group : query_token_->Groups()) {
+    if (group.IsIntegrity())
+      continue;
+    AddRestrictingSid(group.GetSid());
   }
 
   return ERROR_SUCCESS;
diff --git a/win/src/restricted_token.h b/win/src/restricted_token.h
index 5345161..71ac545 100644
--- a/win/src/restricted_token.h
+++ b/win/src/restricted_token.h
@@ -10,12 +10,14 @@
 #include <string>
 #include <tuple>
 
+#include "base/win/access_token.h"
 #include "base/win/scoped_handle.h"
 #include "base/win/sid.h"
 #include "base/win/windows_types.h"
 #include "sandbox/win/src/acl.h"
 #include "sandbox/win/src/restricted_token_utils.h"
 #include "sandbox/win/src/security_level.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -181,8 +183,8 @@
   // the error.
   DWORD AddRestrictingSidAllSids();
 
-  // Sets the token integrity level. This is only valid on Vista. The integrity
-  // level cannot be higher than your current integrity level.
+  // Sets the token integrity level. The integrity level cannot be higher than
+  // your current integrity level.
   DWORD SetIntegrityLevel(IntegrityLevel integrity_level);
 
   // Set a flag which indicates the created token should have a locked down
@@ -213,7 +215,9 @@
       sids_for_default_dacl_;
   // The token to restrict. Can only be set in a constructor.
   base::win::ScopedHandle effective_token_;
-  // The token integrity level. Only valid on Vista.
+  // The token in a form for querying.
+  absl::optional<base::win::AccessToken> query_token_;
+  // The token integrity level.
   IntegrityLevel integrity_level_;
   // Tells if the object is initialized or not (if Init() has been called)
   bool init_;
diff --git a/win/src/restricted_token_test.cc b/win/src/restricted_token_test.cc
index e788858..5e99ae8 100644
--- a/win/src/restricted_token_test.cc
+++ b/win/src/restricted_token_test.cc
@@ -8,13 +8,14 @@
 #include <string>
 
 #include "base/strings/stringprintf.h"
+#include "base/win/access_token.h"
 #include "base/win/scoped_handle.h"
 #include "sandbox/win/src/sandbox.h"
 #include "sandbox/win/src/sandbox_factory.h"
 #include "sandbox/win/src/target_services.h"
-#include "sandbox/win/src/win_utils.h"
 #include "sandbox/win/tests/common/controller.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -128,19 +129,12 @@
 // Opens a the process token and checks if it's restricted.
 SBOX_TESTS_COMMAND int RestrictedTokenTest_IsRestricted(int argc,
                                                         wchar_t** argv) {
-  HANDLE token_handle;
-  if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &token_handle))
+  absl::optional<base::win::AccessToken> token =
+      base::win::AccessToken::FromCurrentProcess();
+  if (!token)
     return SBOX_TEST_FIRST_ERROR;
-  base::win::ScopedHandle token(token_handle);
-
-  std::unique_ptr<BYTE[]> groups;
-  if (GetTokenInformation(token_handle, TokenRestrictedSids, &groups) !=
-      ERROR_SUCCESS) {
-    return SBOX_TEST_SECOND_ERROR;
-  }
-
-  auto* token_groups = reinterpret_cast<PTOKEN_GROUPS>(groups.get());
-  return token_groups->GroupCount > 0 ? SBOX_TEST_SUCCEEDED : SBOX_TEST_FAILED;
+  return token->RestrictedSids().size() > 0 ? SBOX_TEST_SUCCEEDED
+                                            : SBOX_TEST_FAILED;
 }
 
 TEST(RestrictedTokenTest, OpenLowPrivilegedProcess) {
diff --git a/win/src/restricted_token_unittest.cc b/win/src/restricted_token_unittest.cc
index 534d5e0..e0dd7da 100644
--- a/win/src/restricted_token_unittest.cc
+++ b/win/src/restricted_token_unittest.cc
@@ -8,6 +8,7 @@
 
 #include <vector>
 
+#include "base/win/access_token.h"
 #include "base/win/atl.h"
 #include "base/win/scoped_handle.h"
 #include "base/win/sid.h"
@@ -15,6 +16,7 @@
 #include "sandbox/win/src/acl.h"
 #include "sandbox/win/src/security_capabilities.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace sandbox {
 
@@ -83,29 +85,6 @@
     ASSERT_FALSE(logon_sid_found);
 }
 
-bool GetVariableTokenInformation(HANDLE token,
-                                 TOKEN_INFORMATION_CLASS information_class,
-                                 std::vector<char>* information) {
-  DWORD return_length;
-  if (!::GetTokenInformation(token, information_class, nullptr, 0,
-                             &return_length)) {
-    if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-      return false;
-    }
-  }
-
-  information->resize(return_length);
-  return !!::GetTokenInformation(token, information_class, information->data(),
-                                 return_length, &return_length);
-}
-
-bool GetVariableTokenInformation(const base::win::ScopedHandle& token,
-                                 TOKEN_INFORMATION_CLASS information_class,
-                                 std::vector<char>* information) {
-  return GetVariableTokenInformation(token.Get(), information_class,
-                                     information);
-}
-
 void CheckDaclForPackageSid(const base::win::ScopedHandle& token,
                             PSECURITY_CAPABILITIES security_capabilities,
                             bool package_sid_required) {
@@ -147,71 +126,43 @@
   }
 }
 
-void CheckLowBoxToken(const base::win::ScopedHandle& token,
-                      TOKEN_TYPE token_type,
+void CheckLowBoxToken(const base::win::ScopedHandle& lowbox_token,
+                      bool impersonation,
                       PSECURITY_CAPABILITIES security_capabilities) {
-  DWORD appcontainer;
-  DWORD return_length;
-  ASSERT_TRUE(::GetTokenInformation(token.Get(), ::TokenIsAppContainer,
-                                    &appcontainer, sizeof(appcontainer),
-                                    &return_length));
-  ASSERT_TRUE(appcontainer);
-  TOKEN_TYPE token_type_real;
-  ASSERT_TRUE(::GetTokenInformation(token.Get(), ::TokenType, &token_type_real,
-                                    sizeof(token_type_real), &return_length));
-  ASSERT_EQ(token_type_real, token_type);
-  if (token_type == ::TokenImpersonation) {
-    SECURITY_IMPERSONATION_LEVEL imp_level;
-    ASSERT_TRUE(::GetTokenInformation(token.Get(), ::TokenImpersonationLevel,
-                                      &imp_level, sizeof(imp_level),
-                                      &return_length));
-    ASSERT_EQ(imp_level, ::SecurityImpersonation);
-  }
+  auto token = base::win::AccessToken::FromToken(lowbox_token.Get());
+  ASSERT_TRUE(token);
+  EXPECT_TRUE(token->IsAppContainer());
+  EXPECT_EQ(impersonation, token->IsImpersonation());
+  EXPECT_FALSE(token->IsIdentification());
+  auto package_sid = token->AppContainerSid();
+  ASSERT_TRUE(package_sid);
+  EXPECT_TRUE(package_sid->Equal(security_capabilities->AppContainerSid));
 
-  std::vector<char> package_sid_buf;
-  ASSERT_TRUE(GetVariableTokenInformation(token, ::TokenAppContainerSid,
-                                          &package_sid_buf));
-  PTOKEN_APPCONTAINER_INFORMATION package_sid =
-      reinterpret_cast<PTOKEN_APPCONTAINER_INFORMATION>(package_sid_buf.data());
-  EXPECT_TRUE(::EqualSid(security_capabilities->AppContainerSid,
-                         package_sid->TokenAppContainer));
-
-  std::vector<char> capabilities_buf;
-  ASSERT_TRUE(GetVariableTokenInformation(token, ::TokenCapabilities,
-                                          &capabilities_buf));
-  PTOKEN_GROUPS capabilities =
-      reinterpret_cast<PTOKEN_GROUPS>(capabilities_buf.data());
-  ASSERT_EQ(capabilities->GroupCount, security_capabilities->CapabilityCount);
-  for (DWORD index = 0; index < capabilities->GroupCount; ++index) {
-    EXPECT_EQ(capabilities->Groups[index].Attributes,
+  auto capabilities = token->Capabilities();
+  ASSERT_EQ(capabilities.size(), security_capabilities->CapabilityCount);
+  for (size_t index = 0; index < capabilities.size(); ++index) {
+    EXPECT_EQ(capabilities[index].GetAttributes(),
               security_capabilities->Capabilities[index].Attributes);
-    EXPECT_TRUE(::EqualSid(capabilities->Groups[index].Sid,
-                           security_capabilities->Capabilities[index].Sid));
+    EXPECT_TRUE(capabilities[index].GetSid().Equal(
+        security_capabilities->Capabilities[index].Sid));
   }
 
-  CheckDaclForPackageSid(token, security_capabilities, true);
+  CheckDaclForPackageSid(lowbox_token, security_capabilities, true);
 }
 
 // Checks if a sid is in the restricting list of the restricted token.
 // Asserts if it's not the case. If count is a positive number, the number of
 // elements in the restricting sids list has to be equal.
-void CheckRestrictingSid(HANDLE restricted_token, ATL::CSid sid, int count) {
-  std::vector<char> memory;
-  ASSERT_TRUE(GetVariableTokenInformation(restricted_token,
-                                          ::TokenRestrictedSids, &memory));
-  PTOKEN_GROUPS groups = reinterpret_cast<PTOKEN_GROUPS>(memory.data());
-  ATL::CTokenGroups atl_groups(*groups);
-
+void CheckRestrictingSid(const base::win::AccessToken& token,
+                         const base::win::Sid& sid,
+                         int count) {
+  auto restricted_sids = token.RestrictedSids();
   if (count >= 0)
-    ASSERT_EQ(static_cast<unsigned>(count), atl_groups.GetCount());
-
-  ATL::CSid::CSidArray sids;
-  ATL::CAtlArray<DWORD> attributes;
-  atl_groups.GetSidsAndAttributes(&sids, &attributes);
+    ASSERT_EQ(static_cast<unsigned>(count), restricted_sids.size());
 
   bool present = false;
-  for (unsigned int i = 0; i < sids.GetCount(); ++i) {
-    if (sids[i] == sid) {
+  for (const base::win::AccessToken::Group& group : restricted_sids) {
+    if (group.GetSid() == sid) {
       present = true;
       break;
     }
@@ -220,10 +171,18 @@
   ASSERT_TRUE(present);
 }
 
-void CheckRestrictingSid(const ATL::CAccessToken& restricted_token,
-                         ATL::CSid sid,
+void CheckRestrictingSid(const base::win::AccessToken& token,
+                         base::win::WellKnownSid known_sid,
                          int count) {
-  CheckRestrictingSid(restricted_token.GetHandle(), sid, count);
+  CheckRestrictingSid(token, *base::win::Sid::FromKnownSid(known_sid), count);
+}
+
+void CheckRestrictingSid(HANDLE restricted_token,
+                         base::win::WellKnownSid known_sid,
+                         int count) {
+  auto token = base::win::AccessToken::FromToken(restricted_token);
+  ASSERT_TRUE(token);
+  CheckRestrictingSid(*token, known_sid, count);
 }
 
 }  // namespace
@@ -238,54 +197,31 @@
 // Tests the initialization with nullptr as parameter.
 TEST(RestrictedTokenTest, DefaultInit) {
   // Get the current process token.
-  HANDLE token_handle = INVALID_HANDLE_VALUE;
-  ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS,
-                                 &token_handle));
-
-  ASSERT_NE(INVALID_HANDLE_VALUE, token_handle);
-
-  ATL::CAccessToken access_token;
-  access_token.Attach(token_handle);
+  absl::optional<base::win::AccessToken> access_token =
+      base::win::AccessToken::FromCurrentProcess();
+  ASSERT_TRUE(access_token);
 
   // Create the token using the current token.
   RestrictedToken token_default;
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token_default.Init(nullptr));
 
   // Get the handle to the restricted token.
-
   base::win::ScopedHandle restricted_token_handle;
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token_default.GetRestrictedToken(&restricted_token_handle));
 
-  ATL::CAccessToken restricted_token;
-  restricted_token.Attach(restricted_token_handle.Take());
-
-  ATL::CSid sid_user_restricted;
-  ATL::CSid sid_user_default;
-  ATL::CSid sid_owner_restricted;
-  ATL::CSid sid_owner_default;
-  ASSERT_TRUE(restricted_token.GetUser(&sid_user_restricted));
-  ASSERT_TRUE(access_token.GetUser(&sid_user_default));
-  ASSERT_TRUE(restricted_token.GetOwner(&sid_owner_restricted));
-  ASSERT_TRUE(access_token.GetOwner(&sid_owner_default));
-
+  auto restricted_token =
+      base::win::AccessToken::FromToken(restricted_token_handle.Get());
+  ASSERT_TRUE(restricted_token);
   // Check if both token have the same owner and user.
-  ASSERT_EQ(sid_user_restricted, sid_user_default);
-  ASSERT_EQ(sid_owner_restricted, sid_owner_default);
+  EXPECT_EQ(restricted_token->User(), access_token->User());
+  EXPECT_EQ(restricted_token->Owner(), access_token->Owner());
 }
 
 // Tests the initialization with a custom token as parameter.
 TEST(RestrictedTokenTest, CustomInit) {
-  // Get the current process token.
-  HANDLE token_handle = INVALID_HANDLE_VALUE;
-  ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS,
-                                 &token_handle));
-
-  ASSERT_NE(INVALID_HANDLE_VALUE, token_handle);
-
-  ATL::CAccessToken access_token;
-  access_token.Attach(token_handle);
-
+  CAccessToken access_token;
+  ASSERT_TRUE(access_token.GetProcessToken(TOKEN_ALL_ACCESS));
   // Change the primary group.
   access_token.SetPrimaryGroup(ATL::Sids::World());
 
@@ -293,23 +229,18 @@
   RestrictedToken token;
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.Init(access_token.GetHandle()));
-
-  // Get the handle to the restricted token.
-
   base::win::ScopedHandle restricted_token_handle;
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.GetRestrictedToken(&restricted_token_handle));
+  auto restricted_token =
+      base::win::AccessToken::FromToken(restricted_token_handle.Get());
+  ASSERT_TRUE(restricted_token);
 
-  ATL::CAccessToken restricted_token;
-  restricted_token.Attach(restricted_token_handle.Take());
-
-  ATL::CSid sid_restricted;
   ATL::CSid sid_default;
-  ASSERT_TRUE(restricted_token.GetPrimaryGroup(&sid_restricted));
   ASSERT_TRUE(access_token.GetPrimaryGroup(&sid_default));
-
-  // Check if both token have the same owner.
-  ASSERT_EQ(sid_restricted, sid_default);
+  // Check if both token have the same primary grou.
+  ASSERT_TRUE(restricted_token->PrimaryGroup().Equal(
+      const_cast<SID*>(sid_default.GetPSID())));
 }
 
 // Verifies that the token created by the object are valid.
@@ -324,25 +255,20 @@
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.GetRestrictedToken(&restricted_token));
 
-  ASSERT_TRUE(::IsTokenRestricted(restricted_token.Get()));
-
-  DWORD length = 0;
-  TOKEN_TYPE type;
-  ASSERT_TRUE(::GetTokenInformation(restricted_token.Get(), ::TokenType, &type,
-                                    sizeof(type), &length));
-
-  ASSERT_EQ(type, TokenPrimary);
+  auto primary = base::win::AccessToken::FromToken(restricted_token.Get());
+  ASSERT_TRUE(primary);
+  EXPECT_TRUE(primary->IsRestricted());
+  EXPECT_FALSE(primary->IsImpersonation());
 
   base::win::ScopedHandle impersonation_token;
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.GetRestrictedTokenForImpersonation(&impersonation_token));
-
-  ASSERT_TRUE(::IsTokenRestricted(impersonation_token.Get()));
-
-  ASSERT_TRUE(::GetTokenInformation(impersonation_token.Get(), ::TokenType,
-                                    &type, sizeof(type), &length));
-
-  ASSERT_EQ(type, TokenImpersonation);
+  auto impersonation =
+      base::win::AccessToken::FromToken(impersonation_token.Get());
+  ASSERT_TRUE(impersonation);
+  ASSERT_TRUE(impersonation->IsRestricted());
+  ASSERT_TRUE(impersonation->IsImpersonation());
+  ASSERT_FALSE(impersonation->IsIdentification());
 }
 
 // Verifies that the token created has "Restricted" in its default dacl.
@@ -377,23 +303,17 @@
             token.AddSidForDenyOnly(base::win::WellKnownSid::kWorld));
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.GetRestrictedToken(&token_handle));
-
-  ATL::CAccessToken restricted_token;
-  restricted_token.Attach(token_handle.Take());
-
-  ATL::CTokenGroups groups;
-  ASSERT_TRUE(restricted_token.GetGroups(&groups));
-
-  ATL::CSid::CSidArray sids;
-  ATL::CAtlArray<DWORD> attributes;
-  groups.GetSidsAndAttributes(&sids, &attributes);
-
-  for (unsigned int i = 0; i < sids.GetCount(); i++) {
-    if (ATL::Sids::World() == sids[i]) {
-      ASSERT_EQ(static_cast<DWORD>(SE_GROUP_USE_FOR_DENY_ONLY),
-                attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
+  auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+  ASSERT_TRUE(restricted_token);
+  auto sid = base::win::Sid::FromKnownSid(base::win::WellKnownSid::kWorld);
+  bool found_sid = false;
+  for (const auto& group : restricted_token->Groups()) {
+    if (sid == group.GetSid()) {
+      ASSERT_TRUE(group.IsDenyOnly());
+      found_sid = true;
     }
   }
+  ASSERT_TRUE(found_sid);
 }
 
 // Tests the method "AddAllSidsForDenyOnly".
@@ -405,25 +325,18 @@
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.AddAllSidsForDenyOnly({}));
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.GetRestrictedToken(&token_handle));
-
-  ATL::CAccessToken restricted_token;
-  restricted_token.Attach(token_handle.Take());
-
-  ATL::CTokenGroups groups;
-  ASSERT_TRUE(restricted_token.GetGroups(&groups));
-
-  ATL::CSid::CSidArray sids;
-  ATL::CAtlArray<DWORD> attributes;
-  groups.GetSidsAndAttributes(&sids, &attributes);
-
+  auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+  ASSERT_TRUE(restricted_token);
+  bool found_sid = false;
   // Verify that all sids are really gone.
-  for (unsigned int i = 0; i < sids.GetCount(); i++) {
-    if ((attributes[i] & SE_GROUP_LOGON_ID) == 0 &&
-        (attributes[i] & SE_GROUP_INTEGRITY) == 0) {
-      ASSERT_EQ(static_cast<DWORD>(SE_GROUP_USE_FOR_DENY_ONLY),
-                attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
-    }
+  for (const auto& group : restricted_token->Groups()) {
+    if (group.IsLogonId() || group.IsIntegrity())
+      continue;
+    ASSERT_TRUE(group.IsDenyOnly());
+    found_sid = true;
   }
+  // Check we at least found one SID.
+  ASSERT_TRUE(found_sid);
 }
 
 // Tests the method "AddAllSidsForDenyOnly" using an exception list.
@@ -432,8 +345,9 @@
   base::win::ScopedHandle token_handle;
 
   std::vector<base::win::Sid> sids_exception;
-  sids_exception.push_back(
-      *base::win::Sid::FromKnownSid(base::win::WellKnownSid::kWorld));
+  auto sid = base::win::Sid::FromKnownSid(base::win::WellKnownSid::kWorld);
+  ASSERT_TRUE(sid);
+  sids_exception.push_back(sid->Clone());
 
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr));
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
@@ -441,28 +355,23 @@
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.GetRestrictedToken(&token_handle));
 
-  ATL::CAccessToken restricted_token;
-  restricted_token.Attach(token_handle.Take());
+  auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+  ASSERT_TRUE(restricted_token);
 
-  ATL::CTokenGroups groups;
-  ASSERT_TRUE(restricted_token.GetGroups(&groups));
-
-  ATL::CSid::CSidArray sids;
-  ATL::CAtlArray<DWORD> attributes;
-  groups.GetSidsAndAttributes(&sids, &attributes);
-
+  bool found_sid = false;
   // Verify that all sids are really gone.
-  for (unsigned int i = 0; i < sids.GetCount(); i++) {
-    if ((attributes[i] & SE_GROUP_LOGON_ID) == 0 &&
-        (attributes[i] & SE_GROUP_INTEGRITY) == 0) {
-      if (ATL::Sids::World() == sids[i]) {
-        ASSERT_EQ(0u, attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
-      } else {
-        ASSERT_EQ(static_cast<DWORD>(SE_GROUP_USE_FOR_DENY_ONLY),
-                  attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
-      }
+  for (const auto& group : restricted_token->Groups()) {
+    if (group.IsLogonId() || group.IsIntegrity())
+      continue;
+    if (sid == group.GetSid()) {
+      ASSERT_FALSE(group.IsDenyOnly());
+      // Check we at least found one SID.
+      found_sid = true;
+    } else {
+      ASSERT_TRUE(group.IsDenyOnly());
     }
   }
+  ASSERT_TRUE(found_sid);
 }
 
 // Tests test method AddOwnerSidForDenyOnly.
@@ -474,40 +383,15 @@
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.AddUserSidForDenyOnly());
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.GetRestrictedToken(&token_handle));
-
-  ATL::CAccessToken restricted_token;
-  restricted_token.Attach(token_handle.Take());
-
-  ATL::CTokenGroups groups;
-  ASSERT_TRUE(restricted_token.GetGroups(&groups));
-
-  ATL::CSid::CSidArray sids;
-  ATL::CAtlArray<DWORD> attributes;
-  groups.GetSidsAndAttributes(&sids, &attributes);
-
-  ATL::CSid user_sid;
-  ASSERT_TRUE(restricted_token.GetUser(&user_sid));
-
-  for (unsigned int i = 0; i < sids.GetCount(); ++i) {
-    if (user_sid == sids[i]) {
-      ASSERT_EQ(static_cast<DWORD>(SE_GROUP_USE_FOR_DENY_ONLY),
-                attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
-    }
-  }
+  auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+  ASSERT_TRUE(restricted_token);
+  EXPECT_TRUE(restricted_token->UserGroup().IsDenyOnly());
 }
 
 // Tests test method AddOwnerSidForDenyOnly with a custom effective token.
 TEST(RestrictedTokenTest, DenyOwnerSidCustom) {
-  // Get the current process token.
-  HANDLE access_handle = INVALID_HANDLE_VALUE;
-  ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS,
-                                 &access_handle));
-
-  ASSERT_NE(INVALID_HANDLE_VALUE, access_handle);
-
-  ATL::CAccessToken access_token;
-  access_token.Attach(access_handle);
-
+  CAccessToken access_token;
+  ASSERT_TRUE(access_token.GetProcessToken(TOKEN_ALL_ACCESS));
   RestrictedToken token;
   base::win::ScopedHandle token_handle;
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
@@ -515,26 +399,9 @@
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.AddUserSidForDenyOnly());
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.GetRestrictedToken(&token_handle));
-
-  ATL::CAccessToken restricted_token;
-  restricted_token.Attach(token_handle.Take());
-
-  ATL::CTokenGroups groups;
-  ASSERT_TRUE(restricted_token.GetGroups(&groups));
-
-  ATL::CSid::CSidArray sids;
-  ATL::CAtlArray<DWORD> attributes;
-  groups.GetSidsAndAttributes(&sids, &attributes);
-
-  ATL::CSid user_sid;
-  ASSERT_TRUE(restricted_token.GetUser(&user_sid));
-
-  for (unsigned int i = 0; i < sids.GetCount(); ++i) {
-    if (user_sid == sids[i]) {
-      ASSERT_EQ(static_cast<DWORD>(SE_GROUP_USE_FOR_DENY_ONLY),
-                attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
-    }
-  }
+  auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+  ASSERT_TRUE(restricted_token);
+  EXPECT_TRUE(restricted_token->UserGroup().IsDenyOnly());
 }
 
 // Tests the method DeleteAllPrivileges.
@@ -546,14 +413,9 @@
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.DeleteAllPrivileges({}));
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.GetRestrictedToken(&token_handle));
-
-  ATL::CAccessToken restricted_token;
-  restricted_token.Attach(token_handle.Take());
-
-  ATL::CTokenPrivileges privileges;
-  ASSERT_TRUE(restricted_token.GetPrivileges(&privileges));
-
-  ASSERT_EQ(0u, privileges.GetCount());
+  auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+  ASSERT_TRUE(restricted_token);
+  EXPECT_TRUE(restricted_token->Privileges().empty());
 }
 
 // Tests the method DeleteAllPrivileges with an exception list.
@@ -570,22 +432,11 @@
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.GetRestrictedToken(&token_handle));
 
-  ATL::CAccessToken restricted_token;
-  restricted_token.Attach(token_handle.Take());
-
-  ATL::CTokenPrivileges privileges;
-  ASSERT_TRUE(restricted_token.GetPrivileges(&privileges));
-
-  ATL::CTokenPrivileges::CNames privilege_names;
-  ATL::CTokenPrivileges::CAttributes privilege_name_attributes;
-  privileges.GetNamesAndAttributes(&privilege_names,
-                                   &privilege_name_attributes);
-
-  ASSERT_EQ(1u, privileges.GetCount());
-
-  for (unsigned int i = 0; i < privileges.GetCount(); ++i) {
-    ASSERT_EQ(privilege_names[i], SE_CHANGE_NOTIFY_NAME);
-  }
+  auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+  ASSERT_TRUE(restricted_token);
+  auto privileges = restricted_token->Privileges();
+  ASSERT_EQ(1U, privileges.size());
+  EXPECT_EQ(privileges[0].GetName(), SE_CHANGE_NOTIFY_NAME);
 }
 
 // Tests the method DeletePrivilege.
@@ -598,20 +449,10 @@
             token.DeletePrivilege(SE_CHANGE_NOTIFY_NAME));
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.GetRestrictedToken(&token_handle));
-
-  ATL::CAccessToken restricted_token;
-  restricted_token.Attach(token_handle.Take());
-
-  ATL::CTokenPrivileges privileges;
-  ASSERT_TRUE(restricted_token.GetPrivileges(&privileges));
-
-  ATL::CTokenPrivileges::CNames privilege_names;
-  ATL::CTokenPrivileges::CAttributes privilege_name_attributes;
-  privileges.GetNamesAndAttributes(&privilege_names,
-                                   &privilege_name_attributes);
-
-  for (unsigned int i = 0; i < privileges.GetCount(); ++i) {
-    ASSERT_NE(privilege_names[i], SE_CHANGE_NOTIFY_NAME);
+  auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+  ASSERT_TRUE(restricted_token);
+  for (const auto& priv : restricted_token->Privileges()) {
+    ASSERT_NE(priv.GetName(), SE_CHANGE_NOTIFY_NAME);
   }
 }
 
@@ -626,10 +467,9 @@
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.GetRestrictedToken(&token_handle));
 
-  ATL::CAccessToken restricted_token;
-  restricted_token.Attach(token_handle.Take());
-
-  CheckRestrictingSid(restricted_token, ATL::Sids::World(), 1);
+  auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+  ASSERT_TRUE(restricted_token);
+  CheckRestrictingSid(*restricted_token, base::win::WellKnownSid::kWorld, 1);
 }
 
 // Tests the method AddRestrictingSidCurrentUser.
@@ -643,26 +483,15 @@
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.GetRestrictedToken(&token_handle));
 
-  ATL::CAccessToken restricted_token;
-  restricted_token.Attach(token_handle.Take());
-  ATL::CSid user;
-  restricted_token.GetUser(&user);
-
-  CheckRestrictingSid(restricted_token, user, 1);
+  auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+  ASSERT_TRUE(restricted_token);
+  CheckRestrictingSid(*restricted_token, restricted_token->User(), 1);
 }
 
 // Tests the method AddRestrictingSidCurrentUser with a custom effective token.
 TEST(RestrictedTokenTest, AddRestrictingSidCurrentUserCustom) {
-  // Get the current process token.
-  HANDLE access_handle = INVALID_HANDLE_VALUE;
-  ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS,
-                                 &access_handle));
-
-  ASSERT_NE(INVALID_HANDLE_VALUE, access_handle);
-
-  ATL::CAccessToken access_token;
-  access_token.Attach(access_handle);
-
+  CAccessToken access_token;
+  ASSERT_TRUE(access_token.GetProcessToken(TOKEN_ALL_ACCESS));
   RestrictedToken token;
   base::win::ScopedHandle token_handle;
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
@@ -672,12 +501,9 @@
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.GetRestrictedToken(&token_handle));
 
-  ATL::CAccessToken restricted_token;
-  restricted_token.Attach(token_handle.Take());
-  ATL::CSid user;
-  restricted_token.GetUser(&user);
-
-  CheckRestrictingSid(restricted_token, user, 1);
+  auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+  ASSERT_TRUE(restricted_token);
+  CheckRestrictingSid(*restricted_token, restricted_token->User(), 1);
 }
 
 // Tests the method AddRestrictingSidLogonSession.
@@ -691,12 +517,15 @@
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.GetRestrictedToken(&token_handle));
 
-  ATL::CAccessToken restricted_token;
-  restricted_token.Attach(token_handle.Take());
-  ATL::CSid session;
-  restricted_token.GetLogonSid(&session);
+  auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+  ASSERT_TRUE(restricted_token);
+  auto session = restricted_token->LogonId();
+  if (!session) {
+    ASSERT_EQ(static_cast<DWORD>(ERROR_NOT_FOUND), ::GetLastError());
+    return;
+  }
 
-  CheckRestrictingSid(restricted_token, session, 1);
+  CheckRestrictingSid(*restricted_token, *session, 1);
 }
 
 // Tests adding a lot of restricting sids.
@@ -714,17 +543,9 @@
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.GetRestrictedToken(&token_handle));
 
-  ATL::CAccessToken restricted_token;
-  restricted_token.Attach(token_handle.Take());
-  ATL::CSid session;
-  restricted_token.GetLogonSid(&session);
-
-  std::vector<char> memory;
-  ASSERT_TRUE(GetVariableTokenInformation(restricted_token.GetHandle(),
-                                          ::TokenRestrictedSids, &memory));
-  PTOKEN_GROUPS groups = reinterpret_cast<PTOKEN_GROUPS>(memory.data());
-  ATL::CTokenGroups atl_groups(*groups);
-  ASSERT_EQ(3u, atl_groups.GetCount());
+  auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+  ASSERT_TRUE(restricted_token);
+  ASSERT_EQ(3u, restricted_token->RestrictedSids().size());
 }
 
 // Tests the method "AddRestrictingSidAllSids".
@@ -738,27 +559,17 @@
   ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
             token.GetRestrictedToken(&token_handle));
 
-  ATL::CAccessToken restricted_token;
-  restricted_token.Attach(token_handle.Take());
-
-  ATL::CTokenGroups groups;
-  ASSERT_TRUE(restricted_token.GetGroups(&groups));
-
-  ATL::CSid::CSidArray sids;
-  ATL::CAtlArray<DWORD> attributes;
-  groups.GetSidsAndAttributes(&sids, &attributes);
+  auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+  ASSERT_TRUE(restricted_token);
+  auto groups = restricted_token->Groups();
 
   // Verify that all group sids are in the restricting sid list.
-  for (unsigned int i = 0; i < sids.GetCount(); i++) {
-    if ((attributes[i] & SE_GROUP_INTEGRITY) == 0) {
-      CheckRestrictingSid(restricted_token, sids[i], -1);
-    }
+  for (const auto& group : groups) {
+    if (!group.IsIntegrity())
+      CheckRestrictingSid(*restricted_token, group.GetSid(), -1);
   }
 
-  // Verify that the user is in the restricting sid list.
-  ATL::CSid user;
-  restricted_token.GetUser(&user);
-  CheckRestrictingSid(restricted_token, user, -1);
+  CheckRestrictingSid(*restricted_token, restricted_token->User(), -1);
 }
 
 // Checks the error code when the object is initialized twice.
@@ -802,7 +613,7 @@
             CreateLowBoxToken(nullptr, PRIMARY, &caps_no_capabilities, nullptr,
                               0, &token));
   ASSERT_TRUE(token.IsValid());
-  CheckLowBoxToken(token, ::TokenPrimary, &caps_no_capabilities);
+  CheckLowBoxToken(token, false, &caps_no_capabilities);
 
   ASSERT_TRUE(ReplacePackageSidInDacl(token.Get(), SecurityObjectType::kKernel,
                                       *package_sid, TOKEN_ALL_ACCESS));
@@ -812,7 +623,7 @@
             CreateLowBoxToken(nullptr, IMPERSONATION, &caps_no_capabilities,
                               nullptr, 0, &token));
   ASSERT_TRUE(token.IsValid());
-  CheckLowBoxToken(token, ::TokenImpersonation, &caps_no_capabilities);
+  CheckLowBoxToken(token, true, &caps_no_capabilities);
 
   auto capabilities = base::win::Sid::FromKnownCapabilityVector(
       {base::win::WellKnownCapability::kInternetClient,
@@ -823,7 +634,7 @@
             CreateLowBoxToken(nullptr, PRIMARY, &caps_with_capabilities,
                               nullptr, 0, &token));
   ASSERT_TRUE(token.IsValid());
-  CheckLowBoxToken(token, ::TokenPrimary, &caps_with_capabilities);
+  CheckLowBoxToken(token, false, &caps_with_capabilities);
 
   RestrictedToken restricted_token;
   base::win::ScopedHandle token_handle;
@@ -837,8 +648,8 @@
             CreateLowBoxToken(token_handle.Get(), PRIMARY,
                               &caps_with_capabilities, nullptr, 0, &token));
   ASSERT_TRUE(token.IsValid());
-  CheckLowBoxToken(token, ::TokenPrimary, &caps_with_capabilities);
-  CheckRestrictingSid(token.Get(), ATL::Sids::World(), 1);
+  CheckLowBoxToken(token, false, &caps_with_capabilities);
+  CheckRestrictingSid(token.Get(), base::win::WellKnownSid::kWorld, 1);
 
   auto caps_for_handles_sid =
       base::win::Sid::FromSddlString(L"S-1-15-2-1-2-3-4-5-6-8");
diff --git a/win/src/target_process.cc b/win/src/target_process.cc
index 5490cfb..d8fb758 100644
--- a/win/src/target_process.cc
+++ b/win/src/target_process.cc
@@ -15,6 +15,7 @@
 
 #include "base/memory/free_deleter.h"
 #include "base/numerics/safe_conversions.h"
+#include "base/win/access_token.h"
 #include "base/win/security_util.h"
 #include "base/win/startup_information.h"
 #include "base/win/windows_version.h"
@@ -50,41 +51,16 @@
   }
 }
 
-absl::optional<base::win::Sid> GetTokenAppContainerSid(HANDLE token_handle) {
-  std::vector<char> app_container_info(sizeof(TOKEN_APPCONTAINER_INFORMATION) +
-                                       SECURITY_MAX_SID_SIZE);
-  DWORD return_length;
-
-  if (!::GetTokenInformation(
-          token_handle, TokenAppContainerSid, app_container_info.data(),
-          base::checked_cast<DWORD>(app_container_info.size()),
-          &return_length)) {
-    return absl::nullopt;
-  }
-
-  PTOKEN_APPCONTAINER_INFORMATION info =
-      reinterpret_cast<PTOKEN_APPCONTAINER_INFORMATION>(
-          app_container_info.data());
-  if (!info->TokenAppContainer)
-    return absl::nullopt;
-  return base::win::Sid::FromPSID(info->TokenAppContainer);
-}
-
-absl::optional<base::win::Sid> GetProcessAppContainerSid(HANDLE process) {
-  HANDLE token_handle;
-  if (!::OpenProcessToken(process, TOKEN_QUERY, &token_handle))
-    return absl::nullopt;
-  base::win::ScopedHandle process_token(token_handle);
-
-  return GetTokenAppContainerSid(process_token.Get());
-}
-
 bool GetAppContainerImpersonationToken(
     HANDLE process,
     HANDLE initial_token,
     const std::vector<base::win::Sid>& capabilities,
     base::win::ScopedHandle* impersonation_token) {
-  auto app_container_sid = GetProcessAppContainerSid(process);
+  absl::optional<base::win::AccessToken> token =
+      base::win::AccessToken::FromProcess(process);
+  if (!token)
+    return false;
+  auto app_container_sid = token->AppContainerSid();
   if (!app_container_sid)
     return false;
   SecurityCapabilities security_caps(*app_container_sid, capabilities);
diff --git a/win/src/win_utils.cc b/win/src/win_utils.cc
index 1db7750..c8d0702 100644
--- a/win/src/win_utils.cc
+++ b/win/src/win_utils.cc
@@ -4,6 +4,8 @@
 
 #include "sandbox/win/src/win_utils.h"
 
+#include <windows.h>
+
 #include <psapi.h>
 #include <stddef.h>
 #include <stdint.h>
@@ -543,26 +545,6 @@
   return base_address;
 }
 
-DWORD GetTokenInformation(HANDLE token,
-                          TOKEN_INFORMATION_CLASS info_class,
-                          std::unique_ptr<BYTE[]>* buffer) {
-  // Get the required buffer size.
-  DWORD size = 0;
-  ::GetTokenInformation(token, info_class, nullptr, 0, &size);
-  if (!size) {
-    return ::GetLastError();
-  }
-
-  auto temp_buffer = std::make_unique<BYTE[]>(size);
-  if (!::GetTokenInformation(token, info_class, temp_buffer.get(), size,
-                             &size)) {
-    return ::GetLastError();
-  }
-
-  *buffer = std::move(temp_buffer);
-  return ERROR_SUCCESS;
-}
-
 }  // namespace sandbox
 
 void ResolveNTFunctionPtr(const char* name, void* ptr) {
diff --git a/win/src/win_utils.h b/win/src/win_utils.h
index 8998853..6f54d20 100644
--- a/win/src/win_utils.h
+++ b/win/src/win_utils.h
@@ -5,8 +5,6 @@
 #ifndef SANDBOX_WIN_SRC_WIN_UTILS_H_
 #define SANDBOX_WIN_SRC_WIN_UTILS_H_
 
-#include <windows.h>
-
 #include <stdlib.h>
 
 #include <memory>
@@ -115,12 +113,6 @@
 // the base address. This should only be called on new, suspended processes.
 void* GetProcessBaseAddress(HANDLE process);
 
-// Calls GetTokenInformation with the desired |info_class| and returns a
-// |buffer| and the Win32 error code.
-DWORD GetTokenInformation(HANDLE token,
-                          TOKEN_INFORMATION_CLASS info_class,
-                          std::unique_ptr<BYTE[]>* buffer);
-
 }  // namespace sandbox
 
 // Resolves a function name in NTDLL to a function pointer. The second parameter
diff --git a/win/tests/common/test_utils.cc b/win/tests/common/test_utils.cc
index 5aeffd7..a59ec9c 100644
--- a/win/tests/common/test_utils.cc
+++ b/win/tests/common/test_utils.cc
@@ -4,6 +4,8 @@
 
 #include "sandbox/win/tests/common/test_utils.h"
 
+#include <windows.h>
+
 #include <stddef.h>
 #include <winioctl.h>
 
@@ -47,7 +49,7 @@
 
   REPARSE_DATA_BUFFER* data = reinterpret_cast<REPARSE_DATA_BUFFER*>(buffer);
 
-  data->ReparseTag = 0xa0000003;
+  data->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
   memcpy(data->MountPointReparseBuffer.PathBuffer, target, size_target + 2);
   data->MountPointReparseBuffer.SubstituteNameLength = size_target;
   data->MountPointReparseBuffer.PrintNameOffset = size_target + 2;
@@ -67,7 +69,7 @@
 bool DeleteReparsePoint(HANDLE source) {
   DWORD returned;
   REPARSE_DATA_BUFFER data = {0};
-  data.ReparseTag = 0xa0000003;
+  data.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
   if (!DeviceIoControl(source, FSCTL_DELETE_REPARSE_POINT, &data, 8, NULL, 0,
                        &returned, NULL)) {
     return false;
@@ -76,78 +78,4 @@
   return true;
 }
 
-SidAndAttributes::SidAndAttributes(const SID_AND_ATTRIBUTES& sid_and_attributes)
-    : attributes_(sid_and_attributes.Attributes),
-      sid_(*base::win::Sid::FromPSID(sid_and_attributes.Sid)) {}
-
-PSID SidAndAttributes::GetPSID() const {
-  return sid_.GetPSID();
-}
-
-DWORD SidAndAttributes::GetAttributes() const {
-  return attributes_;
-}
-
-absl::optional<base::win::Sid> GetTokenAppContainerSid(HANDLE token) {
-  std::vector<char> app_container_info(sizeof(TOKEN_APPCONTAINER_INFORMATION) +
-                                       SECURITY_MAX_SID_SIZE);
-  DWORD return_length;
-
-  if (!::GetTokenInformation(
-          token, TokenAppContainerSid, app_container_info.data(),
-          base::checked_cast<DWORD>(app_container_info.size()),
-          &return_length)) {
-    return absl::nullopt;
-  }
-
-  PTOKEN_APPCONTAINER_INFORMATION info =
-      reinterpret_cast<PTOKEN_APPCONTAINER_INFORMATION>(
-          app_container_info.data());
-  if (!info->TokenAppContainer)
-    return absl::nullopt;
-  return base::win::Sid::FromPSID(info->TokenAppContainer);
-}
-
-absl::optional<std::vector<SidAndAttributes>> GetTokenGroups(
-    HANDLE token,
-    TOKEN_INFORMATION_CLASS information_class) {
-  if (information_class != ::TokenCapabilities &&
-      information_class != ::TokenGroups &&
-      information_class != ::TokenRestrictedSids) {
-    return absl::nullopt;
-  }
-
-  absl::optional<std::vector<char>> groups_buf =
-      GetVariableTokenInformation(token, information_class);
-  if (!groups_buf)
-    return absl::nullopt;
-
-  PTOKEN_GROUPS groups = reinterpret_cast<PTOKEN_GROUPS>(groups_buf->data());
-  std::vector<SidAndAttributes> token_groups;
-  token_groups.reserve(groups->GroupCount);
-  for (DWORD index = 0; index < groups->GroupCount; ++index) {
-    token_groups.push_back(groups->Groups[index]);
-  }
-
-  return token_groups;
-}
-
-absl::optional<std::vector<char>> GetVariableTokenInformation(
-    HANDLE token,
-    TOKEN_INFORMATION_CLASS information_class) {
-  DWORD return_length;
-  if (!::GetTokenInformation(token, information_class, nullptr, 0,
-                             &return_length)) {
-    if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
-      return absl::nullopt;
-  }
-
-  std::vector<char> information(return_length);
-  if (!::GetTokenInformation(token, information_class, information.data(),
-                             return_length, &return_length)) {
-    return absl::nullopt;
-  }
-  return information;
-}
-
 }  // namespace sandbox
diff --git a/win/tests/common/test_utils.h b/win/tests/common/test_utils.h
index a9e62ac..f0322b6 100644
--- a/win/tests/common/test_utils.h
+++ b/win/tests/common/test_utils.h
@@ -5,13 +5,7 @@
 #ifndef SANDBOX_WIN_TESTS_COMMON_TEST_UTILS_H_
 #define SANDBOX_WIN_TESTS_COMMON_TEST_UTILS_H_
 
-#include <windows.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/win/sid.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "base/win/windows_types.h"
 
 namespace sandbox {
 
@@ -23,33 +17,6 @@
 // succeeds, false otherwise.
 bool DeleteReparsePoint(HANDLE source);
 
-// Class to hold a single Sid with attributes for a group list.
-class SidAndAttributes {
- public:
-  SidAndAttributes(const SID_AND_ATTRIBUTES& sid_and_attributes);
-
-  PSID GetPSID() const;
-  DWORD GetAttributes() const;
-
- private:
-  DWORD attributes_;
-  base::win::Sid sid_;
-};
-
-// Get the App Container sid for a token.
-absl::optional<base::win::Sid> GetTokenAppContainerSid(HANDLE token);
-
-// Get the a list of groups from a token. |information_class| can be one of
-// TokenGroups, TokenRestrictedSids or TokenCapabilities.
-absl::optional<std::vector<SidAndAttributes>> GetTokenGroups(
-    HANDLE token,
-    TOKEN_INFORMATION_CLASS information_class);
-
-// Get a variable length property from a token.
-absl::optional<std::vector<char>> GetVariableTokenInformation(
-    HANDLE token,
-    TOKEN_INFORMATION_CLASS information_class);
-
 }  // namespace sandbox
 
 #endif  // SANDBOX_WIN_TESTS_COMMON_TEST_UTILS_H_