Index: trunk/src/chrome_elf/create_file/chrome_create_file.cc |
=================================================================== |
--- trunk/src/chrome_elf/create_file/chrome_create_file.cc (revision 245500) |
+++ trunk/src/chrome_elf/create_file/chrome_create_file.cc (working copy) |
@@ -1,237 +0,0 @@ |
-// Copyright 2014 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 "chrome_elf/create_file/chrome_create_file.h" |
- |
-#include <string> |
- |
-#include "base/strings/string16.h" |
-#include "chrome_elf/chrome_elf_constants.h" |
-#include "chrome_elf/ntdll_cache.h" |
-#include "sandbox/win/src/nt_internals.h" |
- |
-namespace { |
- |
-// From ShlObj.h in the Windows SDK. |
-#define CSIDL_LOCAL_APPDATA 0x001c |
- |
-typedef BOOL (WINAPI *PathIsUNCFunction)( |
- IN LPCWSTR path); |
- |
-typedef BOOL (WINAPI *PathAppendFunction)( |
- IN LPWSTR path, |
- IN LPCWSTR more); |
- |
-typedef BOOL (WINAPI *PathIsPrefixFunction)( |
- IN LPCWSTR prefix, |
- IN LPCWSTR path); |
- |
-typedef HRESULT (WINAPI *SHGetFolderPathFunction)( |
- IN HWND hwnd_owner, |
- IN int folder, |
- IN HANDLE token, |
- IN DWORD flags, |
- OUT LPWSTR path); |
- |
-PathIsUNCFunction g_path_is_unc_func; |
-PathAppendFunction g_path_append_func; |
-PathIsPrefixFunction g_path_is_prefix_func; |
-SHGetFolderPathFunction g_get_folder_func; |
- |
-// Populates the g_*_func pointers to functions which will be used in |
-// ShouldBypass(). Chrome_elf cannot have a load-time dependency on shell32 or |
-// shlwapi as this would induce a load-time dependency on user32.dll. Instead, |
-// the addresses of the functions we need are retrieved the first time this |
-// method is called, and cached to avoid subsequent calls to GetProcAddress(). |
-// It is assumed that the host process will never unload these functions. |
-// Returns true if all the functions needed are present. |
-bool PopulateShellFunctions() { |
- // Early exit if functions have already been populated. |
- if (g_path_is_unc_func && g_path_append_func && |
- g_path_is_prefix_func && g_get_folder_func) { |
- return true; |
- } |
- |
- // Get the addresses of the functions we need and store them for future use. |
- // These handles are intentionally leaked to ensure that these modules do not |
- // get unloaded. |
- HMODULE shell32 = ::LoadLibrary(L"shell32.dll"); |
- HMODULE shlwapi = ::LoadLibrary(L"shlwapi.dll"); |
- |
- if (!shlwapi || !shell32) |
- return false; |
- |
- g_path_is_unc_func = reinterpret_cast<PathIsUNCFunction>( |
- ::GetProcAddress(shlwapi, "PathIsUNCW")); |
- g_path_append_func = reinterpret_cast<PathAppendFunction>( |
- ::GetProcAddress(shlwapi, "PathAppendW")); |
- g_path_is_prefix_func = reinterpret_cast<PathIsPrefixFunction>( |
- ::GetProcAddress(shlwapi, "PathIsPrefixW")); |
- g_get_folder_func = reinterpret_cast<SHGetFolderPathFunction>( |
- ::GetProcAddress(shell32, "SHGetFolderPathW")); |
- |
- return g_path_is_unc_func && g_path_append_func && |
- g_path_is_prefix_func && g_get_folder_func; |
-} |
- |
-} // namespace |
- |
-HANDLE WINAPI CreateFileWRedirect( |
- LPCWSTR file_name, |
- DWORD desired_access, |
- DWORD share_mode, |
- LPSECURITY_ATTRIBUTES security_attributes, |
- DWORD creation_disposition, |
- DWORD flags_and_attributes, |
- HANDLE template_file) { |
- if (ShouldBypass(file_name)) { |
- return CreateFileNTDLL(file_name, |
- desired_access, |
- share_mode, |
- security_attributes, |
- creation_disposition, |
- flags_and_attributes, |
- template_file); |
- } |
- return CreateFile(file_name, |
- desired_access, |
- share_mode, |
- security_attributes, |
- creation_disposition, |
- flags_and_attributes, |
- template_file); |
- |
-} |
- |
-HANDLE CreateFileNTDLL( |
- LPCWSTR file_name, |
- DWORD desired_access, |
- DWORD share_mode, |
- LPSECURITY_ATTRIBUTES security_attributes, |
- DWORD creation_disposition, |
- DWORD flags_and_attributes, |
- HANDLE template_file) { |
- HANDLE file_handle = INVALID_HANDLE_VALUE; |
- NTSTATUS result = STATUS_UNSUCCESSFUL; |
- IO_STATUS_BLOCK io_status_block = {}; |
- |
- // Convert from Win32 domain to to NT creation disposition values. |
- switch (creation_disposition) { |
- case CREATE_NEW: |
- creation_disposition = FILE_CREATE; |
- break; |
- case CREATE_ALWAYS: |
- creation_disposition = FILE_OVERWRITE_IF; |
- break; |
- case OPEN_EXISTING: |
- creation_disposition = FILE_OPEN; |
- break; |
- case OPEN_ALWAYS: |
- creation_disposition = FILE_OPEN_IF; |
- break; |
- case TRUNCATE_EXISTING: |
- creation_disposition = FILE_OVERWRITE; |
- break; |
- default: |
- SetLastError(ERROR_INVALID_PARAMETER); |
- return INVALID_HANDLE_VALUE; |
- } |
- |
- if (!g_ntdll_lookup["NtCreateFile"] || |
- !g_ntdll_lookup["RtlInitUnicodeString"]) { |
- return INVALID_HANDLE_VALUE; |
- } |
- |
- NtCreateFileFunction create_file = |
- reinterpret_cast<NtCreateFileFunction>(g_ntdll_lookup["NtCreateFile"]); |
- |
- RtlInitUnicodeStringFunction init_unicode_string = |
- reinterpret_cast<RtlInitUnicodeStringFunction>( |
- g_ntdll_lookup["RtlInitUnicodeString"]); |
- |
- UNICODE_STRING path_unicode_string; |
- |
- // Format the path into an NT path. Arguably this should be done with |
- // RtlDosPathNameToNtPathName_U, but afaict this is equivalent for |
- // local paths. Using this with a UNC path name will almost certainly |
- // break in interesting ways. |
- base::string16 filename_string(L"\\??\\"); |
- filename_string += file_name; |
- |
- init_unicode_string(&path_unicode_string, filename_string.c_str()); |
- |
- OBJECT_ATTRIBUTES path_attributes = {}; |
- InitializeObjectAttributes(&path_attributes, |
- &path_unicode_string, |
- OBJ_CASE_INSENSITIVE, |
- NULL, // No Root Directory |
- NULL); // No Security Descriptor |
- |
- // Set create_options, desired_access, and flags_and_attributes to match those |
- // set by kernel32!CreateFile. |
- ULONG create_options = FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_ARCHIVE; |
- desired_access |= 0x100080; |
- flags_and_attributes &= 0x2FFA7; |
- |
- result = create_file(&file_handle, |
- desired_access, |
- &path_attributes, |
- &io_status_block, |
- 0, // Allocation size |
- flags_and_attributes, |
- share_mode, |
- creation_disposition, |
- create_options, |
- NULL, |
- 0); |
- |
- if (result != STATUS_SUCCESS) { |
- if (result == STATUS_OBJECT_NAME_COLLISION && |
- creation_disposition == FILE_CREATE) { |
- SetLastError(ERROR_FILE_EXISTS); |
- } |
- return INVALID_HANDLE_VALUE; |
- } |
- |
- if (creation_disposition == FILE_OPEN_IF) { |
- SetLastError(io_status_block.Information == FILE_OPENED ? |
- ERROR_ALREADY_EXISTS : ERROR_SUCCESS); |
- } else if (creation_disposition == FILE_OVERWRITE_IF) { |
- SetLastError(io_status_block.Information == FILE_OVERWRITTEN ? |
- ERROR_ALREADY_EXISTS : ERROR_SUCCESS); |
- } else { |
- SetLastError(ERROR_SUCCESS); |
- } |
- |
- return file_handle; |
-} |
- |
-bool ShouldBypass(LPCWSTR file_name) { |
- // If the shell functions are not present, forward the call to kernel32. |
- if (!PopulateShellFunctions()) |
- return false; |
- |
- // Forward all UNC filepaths to kernel32. |
- if (g_path_is_unc_func(file_name)) |
- return false; |
- |
- wchar_t local_appdata_path[MAX_PATH]; |
- |
- // Get the %LOCALAPPDATA% Path and append the location of our UserData |
- // directory to it. |
- HRESULT appdata_result = g_get_folder_func( |
- NULL, CSIDL_LOCAL_APPDATA, NULL, 0, local_appdata_path); |
- |
- // If getting the %LOCALAPPDATA% path or appending to it failed, then forward |
- // the call to kernel32. |
- if (!SUCCEEDED(appdata_result) || |
- !g_path_append_func(local_appdata_path, kAppDataDirName) || |
- !g_path_append_func(local_appdata_path, kUserDataDirName)) { |
- return false; |
- } |
- |
- // Check if we are trying to access something in the UserData dir. If so, |
- // then redirect the call to bypass kernel32. |
- return !!g_path_is_prefix_func(local_appdata_path, file_name); |
-} |