15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch#include <Aclapi.h>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/tests/validation_tests/commands.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/tests/common/controller.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the HKEY corresponding to name. If there is no HKEY corresponding
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to the name it returns NULL.
17d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)HKEY GetHKEYFromString(const base::string16 &name) {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (L"HKLM" == name)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return HKEY_LOCAL_MACHINE;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (L"HKCR" == name)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return HKEY_CLASSES_ROOT;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (L"HKCC" == name)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return HKEY_CURRENT_CONFIG;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (L"HKCU" == name)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return HKEY_CURRENT_USER;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (L"HKU" == name)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return HKEY_USERS;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Modifies string to remove the leading and trailing quotes.
33d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)void trim_quote(base::string16* string) {
34d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  base::string16::size_type pos1 = string->find_first_not_of(L'"');
35d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  base::string16::size_type pos2 = string->find_last_not_of(L'"');
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  if (base::string16::npos == pos1 || base::string16::npos == pos2)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*string) = L"";
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*string) = string->substr(pos1, pos2 + 1);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)int TestOpenFile(base::string16 path, bool for_write) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wchar_t path_expanded[MAX_PATH + 1] = {0};
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD size = ::ExpandEnvironmentStrings(path.c_str(), path_expanded,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          MAX_PATH);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!size)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sandbox::SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE file;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file = ::CreateFile(path_expanded,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      for_write ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      NULL,  // No security attributes.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      OPEN_EXISTING,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      FILE_FLAG_BACKUP_SEMANTICS,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      NULL);  // No template.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (INVALID_HANDLE_VALUE != file) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::CloseHandle(file);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sandbox::SBOX_TEST_SUCCEEDED;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ERROR_ACCESS_DENIED == ::GetLastError()) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return sandbox::SBOX_TEST_DENIED;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return sandbox::SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sandbox {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SBOX_TESTS_COMMAND int ValidWindow(int argc, wchar_t **argv) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (1 != argc)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HWND window = reinterpret_cast<HWND>(static_cast<ULONG_PTR>(_wtoi(argv[0])));
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TestValidWindow(window);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TestValidWindow(HWND window) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (::IsWindow(window))
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_SUCCEEDED;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SBOX_TEST_DENIED;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SBOX_TESTS_COMMAND int OpenProcessCmd(int argc, wchar_t **argv) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (2 != argc)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD process_id = _wtol(argv[0]);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD access_mask = _wtol(argv[1]);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TestOpenProcess(process_id, access_mask);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TestOpenProcess(DWORD process_id, DWORD access_mask) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE process = ::OpenProcess(access_mask,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 FALSE,  // Do not inherit handle.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 process_id);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == process) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ERROR_ACCESS_DENIED == ::GetLastError()) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SBOX_TEST_DENIED;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::CloseHandle(process);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_SUCCEEDED;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SBOX_TESTS_COMMAND int OpenThreadCmd(int argc, wchar_t **argv) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (1 != argc)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD thread_id = _wtoi(argv[0]);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TestOpenThread(thread_id);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TestOpenThread(DWORD thread_id) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE thread = ::OpenThread(THREAD_QUERY_INFORMATION,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               FALSE,  // Do not inherit handles.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               thread_id);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == thread) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ERROR_ACCESS_DENIED == ::GetLastError()) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SBOX_TEST_DENIED;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::CloseHandle(thread);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_SUCCEEDED;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SBOX_TESTS_COMMAND int OpenFile(int argc, wchar_t **argv) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (1 != argc)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
146d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  base::string16 path = argv[0];
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  trim_quote(&path);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TestOpenReadFile(path);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
152d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)int TestOpenReadFile(const base::string16& path) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TestOpenFile(path, false);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TestOpenWriteFile(int argc, wchar_t **argv) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (1 != argc)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
160d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  base::string16 path = argv[0];
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  trim_quote(&path);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TestOpenWriteFile(path);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
166d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)int TestOpenWriteFile(const base::string16& path) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TestOpenFile(path, true);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SBOX_TESTS_COMMAND int OpenKey(int argc, wchar_t **argv) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (0 == argc || argc > 2)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the hive.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HKEY base_key = GetHKEYFromString(argv[0]);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the subkey.
178d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  base::string16 subkey;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (2 == argc) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    subkey = argv[1];
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    trim_quote(&subkey);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TestOpenKey(base_key, subkey);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
187d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)int TestOpenKey(HKEY base_key, base::string16 subkey) {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HKEY key;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LONG err_code = ::RegOpenKeyEx(base_key,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 subkey.c_str(),
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 0,  // Reserved, must be 0.
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 MAXIMUM_ALLOWED,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 &key);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ERROR_SUCCESS == err_code) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::RegCloseKey(key);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_SUCCEEDED;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (ERROR_INVALID_HANDLE == err_code ||
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             ERROR_ACCESS_DENIED  == err_code) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_DENIED;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if the current's thread desktop is the interactive desktop.
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In Vista there is a more direct test but for XP and w2k we need to check
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the object name.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsInteractiveDesktop(bool* is_interactive) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HDESK current_desk = ::GetThreadDesktop(::GetCurrentThreadId());
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == current_desk) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wchar_t current_desk_name[256] = {0};
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!::GetUserObjectInformationW(current_desk, UOI_NAME, current_desk_name,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  sizeof(current_desk_name), NULL)) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *is_interactive = (0 == _wcsicmp(L"default", current_desk_name));
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SBOX_TESTS_COMMAND int OpenInteractiveDesktop(int, wchar_t **) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TestOpenInputDesktop();
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TestOpenInputDesktop() {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_interactive = false;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsInteractiveDesktop(&is_interactive) && is_interactive) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_SUCCEEDED;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HDESK desk = ::OpenInputDesktop(0, FALSE, DESKTOP_CREATEWINDOW);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (desk) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::CloseDesktop(desk);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_SUCCEEDED;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SBOX_TEST_DENIED;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SBOX_TESTS_COMMAND int SwitchToSboxDesktop(int, wchar_t **) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TestSwitchDesktop();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TestSwitchDesktop() {
244577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  HDESK desktop = ::GetThreadDesktop(::GetCurrentThreadId());
245577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  if (NULL == desktop) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_FAILED;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
248577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  if (::SwitchDesktop(desktop)) {
249577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch    return SBOX_TEST_SUCCEEDED;
250577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  }
251577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  return SBOX_TEST_DENIED;
252577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch}
253577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch
254577f0d8067567e25b63130cd6d3c45f50df1221aBen MurdochSBOX_TESTS_COMMAND int OpenAlternateDesktop(int, wchar_t **argv) {
255577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  return TestOpenAlternateDesktop(argv[0]);
256577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch}
257577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch
258577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdochint TestOpenAlternateDesktop(wchar_t *desktop_name) {
259577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  // Test for WRITE_DAC permission on the handle.
260577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  HDESK desktop = ::GetThreadDesktop(::GetCurrentThreadId());
261577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  if (desktop) {
262577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch    HANDLE test_handle;
263577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch    if (::DuplicateHandle(::GetCurrentProcess(), desktop,
264577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch                          ::GetCurrentProcess(), &test_handle,
265577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch                          WRITE_DAC, FALSE, 0)) {
266577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch      DWORD result = ::SetSecurityInfo(test_handle, SE_WINDOW_OBJECT,
267577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch                                       DACL_SECURITY_INFORMATION, NULL, NULL,
268577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch                                       NULL, NULL);
269577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch      ::CloseHandle(test_handle);
270577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch      if (result != ERROR_ACCESS_DENIED) {
271577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch        return SBOX_TEST_SUCCEEDED;
272577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch      }
273577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch    } else if (::GetLastError() != ERROR_ACCESS_DENIED) {
274577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch      return SBOX_TEST_FAILED;
275577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch    }
276577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  }
277577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch
278577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  // Open by name with WRITE_DAC.
279577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  if ((desktop = ::OpenDesktop(desktop_name, 0, FALSE, WRITE_DAC)) ||
280577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch      ::GetLastError() != ERROR_ACCESS_DENIED) {
281577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch    ::CloseDesktop(desktop);
282577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch    return SBOX_TEST_SUCCEEDED;
283577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  }
284577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch
285577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  return SBOX_TEST_DENIED;
286577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch}
287577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch
288577f0d8067567e25b63130cd6d3c45f50df1221aBen MurdochBOOL CALLBACK DesktopTestEnumProc(LPTSTR desktop_name, LPARAM result) {
289577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  return TRUE;
290577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch}
291577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch
292577f0d8067567e25b63130cd6d3c45f50df1221aBen MurdochSBOX_TESTS_COMMAND int EnumAlternateWinsta(int, wchar_t **) {
293577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  return TestEnumAlternateWinsta();
294577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch}
295577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch
296577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdochint TestEnumAlternateWinsta() {
297577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  int result = SBOX_TEST_DENIED;
298577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  // Try to enumerate the destops on the alternate windowstation.
299577f0d8067567e25b63130cd6d3c45f50df1221aBen Murdoch  if (::EnumDesktopsW(NULL, DesktopTestEnumProc, 0)) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_SUCCEEDED;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SBOX_TEST_DENIED;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SBOX_TESTS_COMMAND int SleepCmd(int argc, wchar_t **argv) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (1 != argc)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::Sleep(_wtoi(argv[0]));
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SBOX_TEST_SUCCEEDED;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace sandbox
315