diff options
author | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-27 19:20:42 +0000 |
---|---|---|
committer | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-27 19:20:42 +0000 |
commit | 4f1f3d0f03c79ddaace56f067cf28a27f9466b7d (patch) | |
tree | bc0bcae7b48b6e4e218d4fca358af50467893940 /sandbox | |
parent | 2377f7f26715ae20f671c5fd7e7edee778c1f64f (diff) | |
download | chromium_src-4f1f3d0f03c79ddaace56f067cf28a27f9466b7d.zip chromium_src-4f1f3d0f03c79ddaace56f067cf28a27f9466b7d.tar.gz chromium_src-4f1f3d0f03c79ddaace56f067cf28a27f9466b7d.tar.bz2 |
Improve handling and testing of reparse points.
BUG=28804
TEST=unit tests.
Review URL: http://codereview.chromium.org/553080
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37286 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox')
-rw-r--r-- | sandbox/sandbox.gyp | 5 | ||||
-rw-r--r-- | sandbox/src/file_policy_test.cc | 89 | ||||
-rw-r--r-- | sandbox/src/filesystem_policy.cc | 12 | ||||
-rw-r--r-- | sandbox/src/win_utils.cc | 80 | ||||
-rw-r--r-- | sandbox/src/win_utils.h | 7 | ||||
-rw-r--r-- | sandbox/src/win_utils_unittest.cc | 51 | ||||
-rw-r--r-- | sandbox/tests/common/controller.cc | 51 | ||||
-rw-r--r-- | sandbox/tests/common/controller.h | 10 | ||||
-rw-r--r-- | sandbox/tests/common/test_utils.cc | 72 | ||||
-rw-r--r-- | sandbox/tests/common/test_utils.h | 19 |
10 files changed, 295 insertions, 101 deletions
diff --git a/sandbox/sandbox.gyp b/sandbox/sandbox.gyp index 1574e5d..58f0059 100644 --- a/sandbox/sandbox.gyp +++ b/sandbox/sandbox.gyp @@ -286,6 +286,8 @@ 'sources': [ 'tests/common/controller.cc', 'tests/common/controller.h', + 'tests/common/test_utils.cc', + 'tests/common/test_utils.h', 'tests/integration_tests/integration_tests.cc', 'src/dep_test.cc', 'src/file_policy_test.cc', @@ -324,6 +326,8 @@ '../testing/gtest.gyp:gtest', ], 'sources': [ + 'tests/common/test_utils.cc', + 'tests/common/test_utils.h', 'tests/unit_tests/unit_tests.cc', 'src/interception_unittest.cc', 'src/service_resolver_unittest.cc', @@ -335,6 +339,7 @@ 'src/policy_opcodes_unittest.cc', 'src/ipc_unittest.cc', 'src/threadpool_unittest.cc', + 'src/win_utils_unittest.cc', ], }, { diff --git a/sandbox/src/file_policy_test.cc b/sandbox/src/file_policy_test.cc index e62f08a..f4a2e19 100644 --- a/sandbox/src/file_policy_test.cc +++ b/sandbox/src/file_policy_test.cc @@ -1,92 +1,23 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "sandbox/src/sandbox_policy.h" - #include <windows.h> #include <winioctl.h> #include "base/scoped_handle_win.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "sandbox/src/nt_internals.h" #include "sandbox/src/sandbox.h" #include "sandbox/src/sandbox_factory.h" -#include "sandbox/src/nt_internals.h" +#include "sandbox/src/sandbox_policy.h" #include "sandbox/tests/common/controller.h" +#include "sandbox/tests/common/test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" #define BINDNTDLL(name) \ name ## Function name = reinterpret_cast<name ## Function>( \ ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), #name)) -namespace { - -typedef struct _REPARSE_DATA_BUFFER { - ULONG ReparseTag; - USHORT ReparseDataLength; - USHORT Reserved; - union { - struct { - USHORT SubstituteNameOffset; - USHORT SubstituteNameLength; - USHORT PrintNameOffset; - USHORT PrintNameLength; - ULONG Flags; - WCHAR PathBuffer[1]; - } SymbolicLinkReparseBuffer; - struct { - USHORT SubstituteNameOffset; - USHORT SubstituteNameLength; - USHORT PrintNameOffset; - USHORT PrintNameLength; - WCHAR PathBuffer[1]; - } MountPointReparseBuffer; - struct { - UCHAR DataBuffer[1]; - } GenericReparseBuffer; - }; -} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; - -// Sets a reparse point. |source| will now point to |target|. Returns true if -// the call succeeds, false otherwise. -bool SetReparsePoint(HANDLE source, const wchar_t* target) { - USHORT size_target = static_cast<USHORT>(wcslen(target)) * sizeof(target[0]); - - char buffer[2000] = {0}; - DWORD returned; - - REPARSE_DATA_BUFFER* data = reinterpret_cast<REPARSE_DATA_BUFFER*>(buffer); - - data->ReparseTag = 0xa0000003; - memcpy(data->MountPointReparseBuffer.PathBuffer, target, size_target + 2); - data->MountPointReparseBuffer.SubstituteNameLength = size_target; - data->MountPointReparseBuffer.PrintNameOffset = size_target + 2; - data->ReparseDataLength = size_target + 4 + 8; - - int data_size = data->ReparseDataLength + 8; - - if (!DeviceIoControl(source, FSCTL_SET_REPARSE_POINT, &buffer, data_size, - NULL, 0, &returned, NULL)) { - return false; - } - return true; -} - -// Delete the reparse point referenced by |source|. Returns true if the call -// succeeds, false otherwise. -bool DeleteReparsePoint(HANDLE source) { - DWORD returned; - REPARSE_DATA_BUFFER data = {0}; - data.ReparseTag = 0xa0000003; - if (!DeviceIoControl(source, FSCTL_DELETE_REPARSE_POINT, &data, 8, NULL, 0, - &returned, NULL)) { - return false; - } - - return true; -} - -} // unamed namespace - namespace sandbox { const ULONG kSharing = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE; @@ -126,7 +57,7 @@ SBOX_TESTS_COMMAND int File_Win32Create(int argc, wchar_t **argv) { SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; } - std::wstring full_path = MakePathToSys32(argv[0], false); + std::wstring full_path = MakePathToSys(argv[0], false); if (full_path.empty()) { return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; } @@ -158,7 +89,7 @@ SBOX_TESTS_COMMAND int File_CreateSys32(int argc, wchar_t **argv) { if (argc != 1) return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - std::wstring file = MakePathToSys32(argv[0], true); + std::wstring file = MakePathToSys(argv[0], true); UNICODE_STRING object_name; RtlInitUnicodeString(&object_name, file.c_str()); @@ -193,7 +124,7 @@ SBOX_TESTS_COMMAND int File_OpenSys32(int argc, wchar_t **argv) { if (argc != 1) return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - std::wstring file = MakePathToSys32(argv[0], true); + std::wstring file = MakePathToSys(argv[0], true); UNICODE_STRING object_name; RtlInitUnicodeString(&object_name, file.c_str()); @@ -217,7 +148,7 @@ SBOX_TESTS_COMMAND int File_OpenSys32(int argc, wchar_t **argv) { } SBOX_TESTS_COMMAND int File_GetDiskSpace(int argc, wchar_t **argv) { - std::wstring sys_path = MakePathToSys32(L"", false); + std::wstring sys_path = MakePathToSys(L"", false); if (sys_path.empty()) { return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; } @@ -273,7 +204,7 @@ SBOX_TESTS_COMMAND int File_QueryAttributes(int argc, wchar_t **argv) { bool expect_directory = (L'd' == argv[1][0]); UNICODE_STRING object_name; - std::wstring file = MakePathToSys32(argv[0], true); + std::wstring file = MakePathToSys(argv[0], true); RtlInitUnicodeString(&object_name, file.c_str()); OBJECT_ATTRIBUTES obj_attributes = {0}; diff --git a/sandbox/src/filesystem_policy.cc b/sandbox/src/filesystem_policy.cc index c11c031..a703188 100644 --- a/sandbox/src/filesystem_policy.cc +++ b/sandbox/src/filesystem_policy.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -40,6 +40,12 @@ NTSTATUS NtCreateFileInTarget(HANDLE* target_file_handle, return status; } + if (!sandbox::SameObject(local_handle, obj_attributes->ObjectName->Buffer)) { + // The handle points somewhere else. Fail the operation. + ::CloseHandle(local_handle); + return STATUS_ACCESS_DENIED; + } + if (!::DuplicateHandle(::GetCurrentProcess(), local_handle, target_process, target_file_handle, 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { @@ -49,7 +55,7 @@ NTSTATUS NtCreateFileInTarget(HANDLE* target_file_handle, return STATUS_SUCCESS; } -} +} // namespace. namespace sandbox { @@ -61,7 +67,7 @@ bool FileSystemPolicy::GenerateRules(const wchar_t* name, return false; } - // TODO(cpu): This prefix add is a hack because we don't have the + // TODO(cpu) bug 32224: This prefix add is a hack because we don't have the // infrastructure to normalize names. In any case we need to escape the // question marks. if (!PreProcessName(mod_name, &mod_name)) { diff --git a/sandbox/src/win_utils.cc b/sandbox/src/win_utils.cc index f5d39f2..bf4936b 100644 --- a/sandbox/src/win_utils.cc +++ b/sandbox/src/win_utils.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -32,6 +32,16 @@ const KnownReservedKey kKnownKey[] = { { L"HKEY_DYN_DATA", HKEY_DYN_DATA} }; +// Returns true if the provided path points to a pipe. +bool IsPipe(const std::wstring& path) { + size_t start = 0; + if (0 == path.compare(0, sandbox::kNTPrefixLen, sandbox::kNTPrefix)) + start = sandbox::kNTPrefixLen; + + const wchar_t kPipe[] = L"pipe\\"; + return (0 == path.compare(start, arraysize(kPipe) - 1, kPipe)); +} + } // namespace namespace sandbox { @@ -77,8 +87,7 @@ DWORD IsReparsePoint(const std::wstring& full_path, bool* result) { path = path.substr(kNTPrefixLen); // Check if it's a pipe. We can't query the attributes of a pipe. - const wchar_t kPipe[] = L"pipe\\"; - if (0 == path.compare(0, arraysize(kPipe) - 1, kPipe)) { + if (IsPipe(path)) { *result = FALSE; return ERROR_SUCCESS; } @@ -111,6 +120,66 @@ DWORD IsReparsePoint(const std::wstring& full_path, bool* result) { return ERROR_SUCCESS; } +// We get a |full_path| of the form \??\c:\some\foo\bar, and the name that +// we'll get from |handle| will be \device\harddiskvolume1\some\foo\bar. +bool SameObject(HANDLE handle, const wchar_t* full_path) { + std::wstring path(full_path); + DCHECK(!path.empty()); + + // Check if it's a pipe. + if (IsPipe(path)) + return true; + + std::wstring actual_path; + if (!GetPathFromHandle(handle, &actual_path)) + return false; + + // This may end with a backslash. + const wchar_t kBackslash = '\\'; + if (path[path.length() - 1] == kBackslash) + path = path.substr(0, path.length() - 1); + + if (0 == actual_path.compare(full_path)) + return true; + + // Look for the drive letter. + size_t colon_pos = path.find(L':'); + if (colon_pos == 0 || colon_pos == std::wstring::npos) + return false; + + // Only one character for the drive. + if (colon_pos > 1 && path[colon_pos - 2] != kBackslash) + return false; + + // We only need 3 chars, but let's alloc a buffer for four. + wchar_t drive[4] = {0}; + wchar_t vol_name[MAX_PATH]; + memcpy(drive, &path[colon_pos - 1], 2 * sizeof(*drive)); + + // We'll get a double null terminated string. + DWORD vol_length = ::QueryDosDeviceW(drive, vol_name, MAX_PATH); + if (vol_length < 2 || vol_length == MAX_PATH) + return false; + + // Ignore the nulls at the end. + vol_length -= 2; + + // The two paths should be the same length. + if (vol_length + path.size() - (colon_pos + 1) != actual_path.size()) + return false; + + // Check up to the drive letter. + if (0 != actual_path.compare(0, vol_length, vol_name)) + return false; + + // Check the path after the drive letter. + if (0 != actual_path.compare(vol_length, std::wstring::npos, + &path[colon_pos + 1])) + return false; + + return true; +} + bool ConvertToLongPath(const std::wstring& short_path, std::wstring* long_path) { // Check if the path is a NT path. @@ -171,8 +240,9 @@ bool GetPathFromHandle(HANDLE handle, std::wstring* path) { NtQueryObjectFunction NtQueryObject = NULL; ResolveNTFunctionPtr("NtQueryObject", &NtQueryObject); - OBJECT_NAME_INFORMATION* name = NULL; - ULONG size = 0; + OBJECT_NAME_INFORMATION initial_buffer; + OBJECT_NAME_INFORMATION* name = &initial_buffer; + ULONG size = sizeof(initial_buffer); // Query the name information a first time to get the size of the name. NTSTATUS status = NtQueryObject(handle, ObjectNameInformation, name, size, &size); diff --git a/sandbox/src/win_utils.h b/sandbox/src/win_utils.h index b3aad3f..c52f3e3 100644 --- a/sandbox/src/win_utils.h +++ b/sandbox/src/win_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -30,8 +30,8 @@ class AutoLock { }; private: - DISALLOW_IMPLICIT_CONSTRUCTORS(AutoLock); CRITICAL_SECTION *lock_; + DISALLOW_IMPLICIT_CONSTRUCTORS(AutoLock); }; // Basic implementation of a singleton which calls the destructor @@ -71,6 +71,9 @@ bool ConvertToLongPath(const std::wstring& short_path, std::wstring* long_path); // returns true if any of them is a reparse point. DWORD IsReparsePoint(const std::wstring& full_path, bool* result); +// Returns true if the handle corresponds to the object pointed by this path. +bool SameObject(HANDLE handle, const wchar_t* full_path); + // Resolves a handle to a path. Returns true if the handle can be resolved. bool GetPathFromHandle(HANDLE handle, std::wstring* path); diff --git a/sandbox/src/win_utils_unittest.cc b/sandbox/src/win_utils_unittest.cc new file mode 100644 index 0000000..a7dc998 --- /dev/null +++ b/sandbox/src/win_utils_unittest.cc @@ -0,0 +1,51 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <windows.h> + +#include "sandbox/src/win_utils.h" +#include "sandbox/tests/common/test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(WinUtils, IsReparsePoint) { + using sandbox::IsReparsePoint; + + // Create a temp file because we need write access to it. + wchar_t temp_directory[MAX_PATH]; + wchar_t my_folder[MAX_PATH]; + ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0); + ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, my_folder), 0); + + // Delete the file and create a directory instead. + ASSERT_TRUE(::DeleteFile(my_folder)); + ASSERT_TRUE(::CreateDirectory(my_folder, NULL)); + + bool result = true; + EXPECT_EQ(ERROR_SUCCESS, IsReparsePoint(my_folder, &result)); + EXPECT_FALSE(result); + + // We have to fix Bug 32224 to pass this test. + std::wstring not_found = std::wstring(my_folder) + L"\\foo\\bar"; + // EXPECT_EQ(ERROR_PATH_NOT_FOUND, IsReparsePoint(not_found, &result)); + + std::wstring new_file = std::wstring(my_folder) + L"\\foo"; + EXPECT_EQ(ERROR_SUCCESS, IsReparsePoint(new_file, &result)); + EXPECT_FALSE(result); + + // Replace the directory with a reparse point to %temp%. + HANDLE dir = ::CreateFile(my_folder, FILE_ALL_ACCESS, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + EXPECT_TRUE(INVALID_HANDLE_VALUE != dir); + + std::wstring temp_dir_nt = std::wstring(L"\\??\\") + temp_directory; + EXPECT_TRUE(SetReparsePoint(dir, temp_dir_nt.c_str())); + + EXPECT_EQ(ERROR_SUCCESS, IsReparsePoint(new_file, &result)); + EXPECT_TRUE(result); + + EXPECT_TRUE(DeleteReparsePoint(dir)); + EXPECT_TRUE(::CloseHandle(dir)); + EXPECT_TRUE(::RemoveDirectory(my_folder)); +} diff --git a/sandbox/tests/common/controller.cc b/sandbox/tests/common/controller.cc index 802b1b6..6e0f080 100644 --- a/sandbox/tests/common/controller.cc +++ b/sandbox/tests/common/controller.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -8,17 +8,13 @@ #include "sandbox/src/sandbox_factory.h" #include "sandbox/src/sandbox_utils.h" +#include "sandbox/src/wow64.h" namespace { static const int kDefaultTimeout = 3000; -} // namespace - -namespace sandbox { - -// Utility function that constructs a full path to a file inside the system32 -// folder. +// Constructs a full path to a file inside the system32 folder. std::wstring MakePathToSys32(const wchar_t* name, bool is_obj_man_path) { wchar_t windows_path[MAX_PATH] = {0}; if (0 == ::GetSystemWindowsDirectoryW(windows_path, MAX_PATH)) @@ -36,6 +32,36 @@ std::wstring MakePathToSys32(const wchar_t* name, bool is_obj_man_path) { return full_path; } +// Constructs a full path to a file inside the syswow64 folder. +std::wstring MakePathToSysWow64(const wchar_t* name, bool is_obj_man_path) { + wchar_t windows_path[MAX_PATH] = {0}; + if (0 == ::GetSystemWindowsDirectoryW(windows_path, MAX_PATH)) + return std::wstring(); + + std::wstring full_path(windows_path); + if (full_path.empty()) + return full_path; + + if (is_obj_man_path) + full_path.insert(0, L"\\??\\"); + + full_path += L"\\SysWOW64\\"; + full_path += name; + return full_path; +} + +} // namespace + +namespace sandbox { + +std::wstring MakePathToSys(const wchar_t* name, bool is_obj_man_path) { + Wow64 current_proc(NULL, NULL); + if (current_proc.IsWow64()) + return MakePathToSysWow64(name, is_obj_man_path); + else + return MakePathToSys32(name, is_obj_man_path); +} + BrokerServices* GetBroker() { static BrokerServices* broker = SandboxFactory::GetBrokerServices(); static bool is_initialized = false; @@ -111,6 +137,17 @@ bool TestRunner::AddRuleSys32(TargetPolicy::Semantics semantics, if (win32_path.empty()) return false; + if (!AddRule(TargetPolicy::SUBSYS_FILES, semantics, win32_path.c_str())) + return false; + + Wow64 current_proc(NULL, NULL); + if (!current_proc.IsWow64()) + return true; + + win32_path = MakePathToSysWow64(pattern, false); + if (win32_path.empty()) + return false; + return AddRule(TargetPolicy::SUBSYS_FILES, semantics, win32_path.c_str()); } diff --git a/sandbox/tests/common/controller.h b/sandbox/tests/common/controller.h index 8300846..3f1d0c2 100644 --- a/sandbox/tests/common/controller.h +++ b/sandbox/tests/common/controller.h @@ -1,8 +1,8 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SANDBOX_TESTS_COMMON_CONTROLLER_H__ +#ifndef SANDBOX_TESTS_COMMON_CONTROLLER_H_ #define SANDBOX_TESTS_COMMON_CONTROLLER_H__ #include <windows.h> @@ -117,12 +117,12 @@ class TestRunner { // Returns the broker services. BrokerServices* GetBroker(); -// Constructs a full path to a file inside the system32 folder. -std::wstring MakePathToSys32(const wchar_t* name, bool is_obj_man_path); +// Constructs a full path to a file inside the system32 (or syswow64) folder. +std::wstring MakePathToSys(const wchar_t* name, bool is_obj_man_path); // Runs the given test on the target process. int DispatchCall(int argc, wchar_t **argv); } // namespace sandbox -#endif // SANDBOX_TESTS_COMMON_CONTROLLER_H__ +#endif // SANDBOX_TESTS_COMMON_CONTROLLER_H_ diff --git a/sandbox/tests/common/test_utils.cc b/sandbox/tests/common/test_utils.cc new file mode 100644 index 0000000..929c322 --- /dev/null +++ b/sandbox/tests/common/test_utils.cc @@ -0,0 +1,72 @@ +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sandbox/tests/common/test_utils.h" + +#include <winioctl.h> + +typedef struct _REPARSE_DATA_BUFFER { + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + union { + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; + struct { + UCHAR DataBuffer[1]; + } GenericReparseBuffer; + }; +} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; + +// Sets a reparse point. |source| will now point to |target|. Returns true if +// the call succeeds, false otherwise. +bool SetReparsePoint(HANDLE source, const wchar_t* target) { + USHORT size_target = static_cast<USHORT>(wcslen(target)) * sizeof(target[0]); + + char buffer[2000] = {0}; + DWORD returned; + + REPARSE_DATA_BUFFER* data = reinterpret_cast<REPARSE_DATA_BUFFER*>(buffer); + + data->ReparseTag = 0xa0000003; + memcpy(data->MountPointReparseBuffer.PathBuffer, target, size_target + 2); + data->MountPointReparseBuffer.SubstituteNameLength = size_target; + data->MountPointReparseBuffer.PrintNameOffset = size_target + 2; + data->ReparseDataLength = size_target + 4 + 8; + + int data_size = data->ReparseDataLength + 8; + + if (!DeviceIoControl(source, FSCTL_SET_REPARSE_POINT, &buffer, data_size, + NULL, 0, &returned, NULL)) { + return false; + } + return true; +} + +// Delete the reparse point referenced by |source|. Returns true if the call +// succeeds, false otherwise. +bool DeleteReparsePoint(HANDLE source) { + DWORD returned; + REPARSE_DATA_BUFFER data = {0}; + data.ReparseTag = 0xa0000003; + if (!DeviceIoControl(source, FSCTL_DELETE_REPARSE_POINT, &data, 8, NULL, 0, + &returned, NULL)) { + return false; + } + + return true; +} diff --git a/sandbox/tests/common/test_utils.h b/sandbox/tests/common/test_utils.h new file mode 100644 index 0000000..9e17660 --- /dev/null +++ b/sandbox/tests/common/test_utils.h @@ -0,0 +1,19 @@ +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SANDBOX_TESTS_COMMON_TEST_UTILS_H_ +#define SANDBOX_TESTS_COMMON_TEST_UTILS_H_ + +#include <windows.h> + +// Sets a reparse point. |source| will now point to |target|. Returns true if +// the call succeeds, false otherwise. +bool SetReparsePoint(HANDLE source, const wchar_t* target); + +// Delete the reparse point referenced by |source|. Returns true if the call +// succeeds, false otherwise. +bool DeleteReparsePoint(HANDLE source); + +#endif // SANDBOX_TESTS_COMMON_TEST_UTILS_H_ + |