1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
base / win / elevation_util_unittest.cc [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/win/elevation_util.h"
#include <shlobj.h>
#include "base/command_line.h"
#include "base/functional/callback.h"
#include "base/process/process.h"
#include "base/process/process_handle.h"
#include "base/process/process_iterator.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "base/win/scoped_com_initializer.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/cleanup/cleanup.h"
namespace base::win {
namespace {
constexpr wchar_t kMoreExecutable[] = L"more.com";
bool IsExplorerRunningAtMediumOrLower() {
ProcessId explorer_pid = GetExplorerPid();
return explorer_pid ? IsProcessRunningAtMediumOrLower(explorer_pid) : false;
}
} // namespace
TEST(ElevationUtil, RunDeElevated) {
if (!::IsUserAnAdmin() || !IsExplorerRunningAtMediumOrLower()) {
GTEST_SKIP();
}
Process process = RunDeElevated(CommandLine::FromString(L"more.com"));
ASSERT_TRUE(process.IsValid());
absl::Cleanup terminate_process = [&] {
EXPECT_TRUE(process.Terminate(0, false));
};
ASSERT_TRUE(IsProcessRunningAtMediumOrLower(process.Pid()));
}
class ElevationUtilRunDeElevatedNoWaitTest
: public ::testing::TestWithParam<RepeatingCallback<HRESULT()>> {};
INSTANTIATE_TEST_SUITE_P(ElevationUtilRunDeElevatedNoWaitTestCases,
ElevationUtilRunDeElevatedNoWaitTest,
::testing::Values(BindRepeating([] {
return RunDeElevatedNoWait(
CommandLine::FromString(
kMoreExecutable));
}),
BindRepeating([] {
return RunDeElevatedNoWait(
kMoreExecutable, {});
})));
TEST_P(ElevationUtilRunDeElevatedNoWaitTest, TestCases) {
if (!::IsUserAnAdmin() || !IsExplorerRunningAtMediumOrLower()) {
GTEST_SKIP();
}
ASSERT_EQ(GetProcessCount(kMoreExecutable, /*filter=*/nullptr), 0)
<< "This test requires that no instances of the `more` command are "
"running.";
ScopedCOMInitializer com_initializer(ScopedCOMInitializer::kMTA);
ASSERT_TRUE(com_initializer.Succeeded());
ASSERT_HRESULT_SUCCEEDED(GetParam().Run());
// Wait for the process to start running.
int i = 0;
for (; i < 5; ++i) {
PlatformThread::Sleep(TestTimeouts::tiny_timeout());
if (GetProcessCount(kMoreExecutable, /*filter=*/nullptr) == 1) {
break;
}
}
ASSERT_LT(i, 5);
NamedProcessIterator iter(kMoreExecutable, /*filter=*/nullptr);
const ProcessEntry* process_entry = iter.NextProcessEntry();
ASSERT_TRUE(process_entry);
ASSERT_TRUE(IsProcessRunningAtMediumOrLower(process_entry->pid()));
EXPECT_TRUE(Process::Open(process_entry->pid()).Terminate(0, false));
ASSERT_FALSE(iter.NextProcessEntry());
}
} // namespace base::win