| 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);
 | 
| -}
 | 
| 
 |