Fix crash on app list start page keyboard navigation with <4 apps.
[chromium-blink-merge.git] / sandbox / win / tests / validation_tests / commands.cc
blob10a4a13761210f4b9f634118db65812910aa12c0
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <Aclapi.h>
6 #include <windows.h>
7 #include <string>
9 #include "sandbox/win/tests/validation_tests/commands.h"
11 #include "sandbox/win/tests/common/controller.h"
13 namespace {
15 // Returns the HKEY corresponding to name. If there is no HKEY corresponding
16 // to the name it returns NULL.
17 HKEY GetHKEYFromString(const base::string16 &name) {
18 if (name == L"HKLM")
19 return HKEY_LOCAL_MACHINE;
20 if (name == L"HKCR")
21 return HKEY_CLASSES_ROOT;
22 if (name == L"HKCC")
23 return HKEY_CURRENT_CONFIG;
24 if (name == L"HKCU")
25 return HKEY_CURRENT_USER;
26 if (name == L"HKU")
27 return HKEY_USERS;
29 return NULL;
32 // Modifies string to remove the leading and trailing quotes.
33 void trim_quote(base::string16* string) {
34 base::string16::size_type pos1 = string->find_first_not_of(L'"');
35 base::string16::size_type pos2 = string->find_last_not_of(L'"');
37 if (pos1 == base::string16::npos || pos2 == base::string16::npos)
38 string->clear();
39 else
40 (*string) = string->substr(pos1, pos2 + 1);
43 int TestOpenFile(base::string16 path, bool for_write) {
44 wchar_t path_expanded[MAX_PATH + 1] = {0};
45 DWORD size = ::ExpandEnvironmentStrings(path.c_str(), path_expanded,
46 MAX_PATH);
47 if (!size)
48 return sandbox::SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
50 HANDLE file;
51 file = ::CreateFile(path_expanded,
52 for_write ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ,
53 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
54 NULL, // No security attributes.
55 OPEN_EXISTING,
56 FILE_FLAG_BACKUP_SEMANTICS,
57 NULL); // No template.
59 if (file != INVALID_HANDLE_VALUE) {
60 ::CloseHandle(file);
61 return sandbox::SBOX_TEST_SUCCEEDED;
63 return (::GetLastError() == ERROR_ACCESS_DENIED) ?
64 sandbox::SBOX_TEST_DENIED : sandbox::SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
67 } // namespace
69 namespace sandbox {
71 SBOX_TESTS_COMMAND int ValidWindow(int argc, wchar_t **argv) {
72 return (argc == 1) ?
73 TestValidWindow(
74 reinterpret_cast<HWND>(static_cast<ULONG_PTR>(_wtoi(argv[0])))) :
75 SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
78 int TestValidWindow(HWND window) {
79 return ::IsWindow(window) ? SBOX_TEST_SUCCEEDED : SBOX_TEST_DENIED;
82 SBOX_TESTS_COMMAND int OpenProcessCmd(int argc, wchar_t **argv) {
83 return (argc == 2) ?
84 TestOpenProcess(_wtol(argv[0]), _wtol(argv[1])) :
85 SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
88 int TestOpenProcess(DWORD process_id, DWORD access_mask) {
89 HANDLE process = ::OpenProcess(access_mask,
90 FALSE, // Do not inherit handle.
91 process_id);
92 if (process != NULL) {
93 ::CloseHandle(process);
94 return SBOX_TEST_SUCCEEDED;
96 return (::GetLastError() == ERROR_ACCESS_DENIED) ?
97 sandbox::SBOX_TEST_DENIED : sandbox::SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
100 SBOX_TESTS_COMMAND int OpenThreadCmd(int argc, wchar_t **argv) {
101 return (argc == 1) ?
102 TestOpenThread(_wtoi(argv[0])) : SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
105 int TestOpenThread(DWORD thread_id) {
106 HANDLE thread = ::OpenThread(THREAD_QUERY_INFORMATION,
107 FALSE, // Do not inherit handles.
108 thread_id);
109 if (thread != NULL) {
110 ::CloseHandle(thread);
111 return SBOX_TEST_SUCCEEDED;
113 return (::GetLastError() == ERROR_ACCESS_DENIED) ?
114 sandbox::SBOX_TEST_DENIED : sandbox::SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
117 SBOX_TESTS_COMMAND int OpenFileCmd(int argc, wchar_t **argv) {
118 if (1 != argc)
119 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
121 base::string16 path = argv[0];
122 trim_quote(&path);
124 return TestOpenReadFile(path);
127 int TestOpenReadFile(const base::string16& path) {
128 return TestOpenFile(path, false);
131 int TestOpenWriteFile(int argc, wchar_t **argv) {
132 if (argc != 1)
133 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
135 base::string16 path = argv[0];
136 trim_quote(&path);
137 return TestOpenWriteFile(path);
140 int TestOpenWriteFile(const base::string16& path) {
141 return TestOpenFile(path, true);
144 SBOX_TESTS_COMMAND int OpenKey(int argc, wchar_t **argv) {
145 if (argc != 1 && argc != 2)
146 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
148 // Get the hive.
149 HKEY base_key = GetHKEYFromString(argv[0]);
151 // Get the subkey.
152 base::string16 subkey;
153 if (argc == 2) {
154 subkey = argv[1];
155 trim_quote(&subkey);
158 return TestOpenKey(base_key, subkey);
161 int TestOpenKey(HKEY base_key, base::string16 subkey) {
162 HKEY key;
163 LONG err_code = ::RegOpenKeyEx(base_key,
164 subkey.c_str(),
165 0, // Reserved, must be 0.
166 MAXIMUM_ALLOWED,
167 &key);
168 if (err_code == ERROR_SUCCESS) {
169 ::RegCloseKey(key);
170 return SBOX_TEST_SUCCEEDED;
172 return (err_code == ERROR_INVALID_HANDLE || err_code == ERROR_ACCESS_DENIED) ?
173 SBOX_TEST_DENIED : SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
176 // Returns true if the current's thread desktop is the interactive desktop.
177 // In Vista there is a more direct test but for XP and w2k we need to check
178 // the object name.
179 bool IsInteractiveDesktop(bool* is_interactive) {
180 HDESK current_desk = ::GetThreadDesktop(::GetCurrentThreadId());
181 if (current_desk == NULL)
182 return false;
183 wchar_t current_desk_name[256] = {0};
184 if (!::GetUserObjectInformationW(current_desk, UOI_NAME, current_desk_name,
185 sizeof(current_desk_name), NULL))
186 return false;
187 *is_interactive = (0 == _wcsicmp(L"default", current_desk_name));
188 return true;
191 SBOX_TESTS_COMMAND int OpenInteractiveDesktop(int, wchar_t **) {
192 return TestOpenInputDesktop();
195 int TestOpenInputDesktop() {
196 bool is_interactive = false;
197 if (IsInteractiveDesktop(&is_interactive) && is_interactive)
198 return SBOX_TEST_SUCCEEDED;
199 HDESK desk = ::OpenInputDesktop(0, FALSE, DESKTOP_CREATEWINDOW);
200 if (desk) {
201 ::CloseDesktop(desk);
202 return SBOX_TEST_SUCCEEDED;
204 return SBOX_TEST_DENIED;
207 SBOX_TESTS_COMMAND int SwitchToSboxDesktop(int, wchar_t **) {
208 return TestSwitchDesktop();
211 int TestSwitchDesktop() {
212 HDESK desktop = ::GetThreadDesktop(::GetCurrentThreadId());
213 if (desktop == NULL)
214 return SBOX_TEST_FAILED;
215 return ::SwitchDesktop(desktop) ? SBOX_TEST_SUCCEEDED : SBOX_TEST_DENIED;
218 SBOX_TESTS_COMMAND int OpenAlternateDesktop(int, wchar_t **argv) {
219 return TestOpenAlternateDesktop(argv[0]);
222 int TestOpenAlternateDesktop(wchar_t *desktop_name) {
223 // Test for WRITE_DAC permission on the handle.
224 HDESK desktop = ::GetThreadDesktop(::GetCurrentThreadId());
225 if (desktop) {
226 HANDLE test_handle;
227 if (::DuplicateHandle(::GetCurrentProcess(), desktop,
228 ::GetCurrentProcess(), &test_handle,
229 WRITE_DAC, FALSE, 0)) {
230 DWORD result = ::SetSecurityInfo(test_handle, SE_WINDOW_OBJECT,
231 DACL_SECURITY_INFORMATION, NULL, NULL,
232 NULL, NULL);
233 ::CloseHandle(test_handle);
234 if (result == ERROR_SUCCESS)
235 return SBOX_TEST_SUCCEEDED;
236 } else if (::GetLastError() != ERROR_ACCESS_DENIED) {
237 return SBOX_TEST_FAILED;
241 // Open by name with WRITE_DAC.
242 desktop = ::OpenDesktop(desktop_name, 0, FALSE, WRITE_DAC);
243 if (!desktop && ::GetLastError() == ERROR_ACCESS_DENIED)
244 return SBOX_TEST_DENIED;
245 ::CloseDesktop(desktop);
246 return SBOX_TEST_SUCCEEDED;
249 BOOL CALLBACK DesktopTestEnumProc(LPTSTR desktop_name, LPARAM result) {
250 return TRUE;
253 SBOX_TESTS_COMMAND int EnumAlternateWinsta(int, wchar_t **) {
254 return TestEnumAlternateWinsta();
257 int TestEnumAlternateWinsta() {
258 // Try to enumerate the destops on the alternate windowstation.
259 return ::EnumDesktopsW(NULL, DesktopTestEnumProc, 0) ?
260 SBOX_TEST_SUCCEEDED : SBOX_TEST_DENIED;
263 SBOX_TESTS_COMMAND int SleepCmd(int argc, wchar_t **argv) {
264 if (argc != 1)
265 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
267 ::Sleep(_wtoi(argv[0]));
268 return SBOX_TEST_SUCCEEDED;
271 SBOX_TESTS_COMMAND int AllocateCmd(int argc, wchar_t **argv) {
272 if (argc != 1)
273 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
275 size_t mem_size = static_cast<size_t>(_wtoll(argv[0]));
276 void* memory = ::VirtualAlloc(NULL, mem_size, MEM_COMMIT | MEM_RESERVE,
277 PAGE_READWRITE);
278 if (!memory) {
279 // We need to give the broker a chance to kill our process on failure.
280 ::Sleep(5000);
281 return SBOX_TEST_DENIED;
284 return ::VirtualFree(memory, 0, MEM_RELEASE) ?
285 SBOX_TEST_SUCCEEDED : SBOX_TEST_FAILED;
289 } // namespace sandbox