| Index: runtime/bin/file_win.cc
 | 
| diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
 | 
| index 54cd64d37d5e77f466dd9c8b9bf7acf1e96df90f..7c1268f1694ff468e91492a3c96ea3fd47a42aa2 100644
 | 
| --- a/runtime/bin/file_win.cc
 | 
| +++ b/runtime/bin/file_win.cc
 | 
| @@ -46,7 +46,8 @@ File::~File() {
 | 
|  
 | 
|  void File::Close() {
 | 
|    ASSERT(handle_->fd() >= 0);
 | 
| -  if (handle_->fd() == _fileno(stdout) || handle_->fd() == _fileno(stderr)) {
 | 
| +  if ((handle_->fd() == _fileno(stdout)) ||
 | 
| +      (handle_->fd() == _fileno(stderr))) {
 | 
|      int fd = _open("NUL", _O_WRONLY);
 | 
|      ASSERT(fd >= 0);
 | 
|      _dup2(fd, handle_->fd());
 | 
| @@ -118,7 +119,9 @@ bool File::Lock(File::LockType lock, int64_t start, int64_t end) {
 | 
|    overlapped.OffsetHigh = Utils::High32Bits(start);
 | 
|  
 | 
|    int64_t length = end == -1 ? 0 : end - start;
 | 
| -  if (length == 0) length = kMaxInt64;
 | 
| +  if (length == 0) {
 | 
| +    length = kMaxInt64;
 | 
| +  }
 | 
|    int32_t length_low = Utils::Low32Bits(length);
 | 
|    int32_t length_high = Utils::High32Bits(length);
 | 
|  
 | 
| @@ -155,7 +158,7 @@ int64_t File::Length() {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -File* File::Open(const char* name, FileOpenMode mode) {
 | 
| +File* File::FileOpenW(const wchar_t* system_name, FileOpenMode mode) {
 | 
|    int flags = O_RDONLY | O_BINARY | O_NOINHERIT;
 | 
|    if ((mode & kWrite) != 0) {
 | 
|      ASSERT((mode & kWriteOnly) == 0);
 | 
| @@ -168,9 +171,7 @@ File* File::Open(const char* name, FileOpenMode mode) {
 | 
|    if ((mode & kTruncate) != 0) {
 | 
|      flags = flags | O_TRUNC;
 | 
|    }
 | 
| -  const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
 | 
|    int fd = _wopen(system_name, flags, 0666);
 | 
| -  free(const_cast<wchar_t*>(system_name));
 | 
|    if (fd < 0) {
 | 
|      return NULL;
 | 
|    }
 | 
| @@ -185,6 +186,25 @@ File* File::Open(const char* name, FileOpenMode mode) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +File* File::ScopedOpen(const char* name, FileOpenMode mode) {
 | 
| +  const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
 | 
| +  return FileOpenW(system_name, mode);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +File* File::Open(const char* path, FileOpenMode mode) {
 | 
| +  int path_len = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
 | 
| +  wchar_t* system_name = new wchar_t[path_len];
 | 
| +  if (system_name == NULL) {
 | 
| +    return NULL;
 | 
| +  }
 | 
| +  MultiByteToWideChar(CP_UTF8, 0, path, -1, system_name, path_len);
 | 
| +  File* file = FileOpenW(system_name, mode);
 | 
| +  delete[] system_name;
 | 
| +  return file;
 | 
| +}
 | 
| +
 | 
| +
 | 
|  File* File::OpenStdio(int fd) {
 | 
|    switch (fd) {
 | 
|      case 1:
 | 
| @@ -205,7 +225,6 @@ bool File::Exists(const char* name) {
 | 
|    struct __stat64 st;
 | 
|    const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
 | 
|    bool stat_status = _wstat64(system_name, &st);
 | 
| -  free(const_cast<wchar_t*>(system_name));
 | 
|    if (stat_status == 0) {
 | 
|      return ((st.st_mode & S_IFMT) == S_IFREG);
 | 
|    } else {
 | 
| @@ -217,7 +236,6 @@ bool File::Exists(const char* name) {
 | 
|  bool File::Create(const char* name) {
 | 
|    const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
 | 
|    int fd = _wopen(system_name, O_RDONLY | O_CREAT, 0666);
 | 
| -  free(const_cast<wchar_t*>(system_name));
 | 
|    if (fd < 0) {
 | 
|      return false;
 | 
|    }
 | 
| @@ -264,10 +282,9 @@ bool File::CreateLink(const char* utf8_name, const char* utf8_target) {
 | 
|    const wchar_t* name = StringUtilsWin::Utf8ToWide(utf8_name);
 | 
|    int create_status = CreateDirectoryW(name, NULL);
 | 
|    // If the directory already existed, treat it as a success.
 | 
| -  if (create_status == 0 &&
 | 
| -      (GetLastError() != ERROR_ALREADY_EXISTS ||
 | 
| -       (GetFileAttributesW(name) & FILE_ATTRIBUTE_DIRECTORY) != 0)) {
 | 
| -    free(const_cast<wchar_t*>(name));
 | 
| +  if ((create_status == 0) &&
 | 
| +      ((GetLastError() != ERROR_ALREADY_EXISTS) ||
 | 
| +       ((GetFileAttributesW(name) & FILE_ATTRIBUTE_DIRECTORY) != 0))) {
 | 
|      return false;
 | 
|    }
 | 
|  
 | 
| @@ -279,7 +296,6 @@ bool File::CreateLink(const char* utf8_name, const char* utf8_target) {
 | 
|        OPEN_EXISTING,
 | 
|        FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
 | 
|        NULL);
 | 
| -  free(const_cast<wchar_t*>(name));
 | 
|    if (dir_handle == INVALID_HANDLE_VALUE) {
 | 
|      return false;
 | 
|    }
 | 
| @@ -287,7 +303,6 @@ bool File::CreateLink(const char* utf8_name, const char* utf8_target) {
 | 
|    const wchar_t* target = StringUtilsWin::Utf8ToWide(utf8_target);
 | 
|    int target_len = wcslen(target);
 | 
|    if (target_len > MAX_PATH - 1) {
 | 
| -    free(const_cast<wchar_t*>(target));
 | 
|      CloseHandle(dir_handle);
 | 
|      return false;
 | 
|    }
 | 
| @@ -295,7 +310,8 @@ bool File::CreateLink(const char* utf8_name, const char* utf8_target) {
 | 
|    int reparse_data_buffer_size =
 | 
|        sizeof REPARSE_DATA_BUFFER + 2 * MAX_PATH * sizeof WCHAR;
 | 
|    REPARSE_DATA_BUFFER* reparse_data_buffer =
 | 
| -      static_cast<REPARSE_DATA_BUFFER*>(calloc(reparse_data_buffer_size, 1));
 | 
| +      reinterpret_cast<REPARSE_DATA_BUFFER*>(Dart_ScopeAllocate(
 | 
| +          reparse_data_buffer_size));
 | 
|    reparse_data_buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
 | 
|    wcscpy(reparse_data_buffer->MountPointReparseBuffer.PathBuffer, target);
 | 
|    wcscpy(
 | 
| @@ -320,9 +336,9 @@ bool File::CreateLink(const char* utf8_name, const char* utf8_target) {
 | 
|        0,
 | 
|        &dummy_received_bytes,
 | 
|        NULL);
 | 
| -  if (CloseHandle(dir_handle) == 0) return false;
 | 
| -  free(const_cast<wchar_t*>(target));
 | 
| -  free(reparse_data_buffer);
 | 
| +  if (CloseHandle(dir_handle) == 0) {
 | 
| +    return false;
 | 
| +  }
 | 
|    return (result != 0);
 | 
|  }
 | 
|  
 | 
| @@ -330,7 +346,6 @@ bool File::CreateLink(const char* utf8_name, const char* utf8_target) {
 | 
|  bool File::Delete(const char* name) {
 | 
|    const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
 | 
|    int status = _wremove(system_name);
 | 
| -  free(const_cast<wchar_t*>(system_name));
 | 
|    return status != -1;
 | 
|  }
 | 
|  
 | 
| @@ -346,7 +361,6 @@ bool File::DeleteLink(const char* name) {
 | 
|    } else {
 | 
|      SetLastError(ERROR_NOT_A_REPARSE_POINT);
 | 
|    }
 | 
| -  free(const_cast<wchar_t*>(system_name));
 | 
|    return result;
 | 
|  }
 | 
|  
 | 
| @@ -359,8 +373,6 @@ bool File::Rename(const char* old_path, const char* new_path) {
 | 
|      DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING;
 | 
|      int move_status =
 | 
|          MoveFileExW(system_old_path, system_new_path, flags);
 | 
| -    free(const_cast<wchar_t*>(system_old_path));
 | 
| -    free(const_cast<wchar_t*>(system_new_path));
 | 
|      return (move_status != 0);
 | 
|    } else {
 | 
|      SetLastError(ERROR_FILE_NOT_FOUND);
 | 
| @@ -377,8 +389,6 @@ bool File::RenameLink(const char* old_path, const char* new_path) {
 | 
|      DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING;
 | 
|      int move_status =
 | 
|          MoveFileExW(system_old_path, system_new_path, flags);
 | 
| -    free(const_cast<wchar_t*>(system_old_path));
 | 
| -    free(const_cast<wchar_t*>(system_new_path));
 | 
|      return (move_status != 0);
 | 
|    } else {
 | 
|      SetLastError(ERROR_FILE_NOT_FOUND);
 | 
| @@ -398,8 +408,6 @@ bool File::Copy(const char* old_path, const char* new_path) {
 | 
|                                 NULL,
 | 
|                                 NULL,
 | 
|                                 0) != 0;
 | 
| -    free(const_cast<wchar_t*>(system_old_path));
 | 
| -    free(const_cast<wchar_t*>(system_new_path));
 | 
|      return success;
 | 
|    } else {
 | 
|      SetLastError(ERROR_FILE_NOT_FOUND);
 | 
| @@ -412,7 +420,6 @@ int64_t File::LengthFromPath(const char* name) {
 | 
|    struct __stat64 st;
 | 
|    const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
 | 
|    int stat_status = _wstat64(system_name, &st);
 | 
| -  free(const_cast<wchar_t*>(system_name));
 | 
|    if (stat_status == 0) {
 | 
|      return st.st_size;
 | 
|    }
 | 
| @@ -420,7 +427,7 @@ int64_t File::LengthFromPath(const char* name) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -char* File::LinkTarget(const char* pathname) {
 | 
| +const char* File::LinkTarget(const char* pathname) {
 | 
|    const wchar_t* name = StringUtilsWin::Utf8ToWide(pathname);
 | 
|    HANDLE dir_handle = CreateFileW(
 | 
|        name,
 | 
| @@ -430,15 +437,14 @@ char* File::LinkTarget(const char* pathname) {
 | 
|        OPEN_EXISTING,
 | 
|        FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
 | 
|        NULL);
 | 
| -  free(const_cast<wchar_t*>(name));
 | 
|    if (dir_handle == INVALID_HANDLE_VALUE) {
 | 
|      return NULL;
 | 
|    }
 | 
|  
 | 
|    int buffer_size =
 | 
|        sizeof REPARSE_DATA_BUFFER + 2 * (MAX_PATH + 1) * sizeof WCHAR;
 | 
| -  REPARSE_DATA_BUFFER* buffer =
 | 
| -      static_cast<REPARSE_DATA_BUFFER*>(calloc(buffer_size, 1));
 | 
| +  REPARSE_DATA_BUFFER* buffer = reinterpret_cast<REPARSE_DATA_BUFFER*>(
 | 
| +      Dart_ScopeAllocate(buffer_size));
 | 
|    DWORD received_bytes;  // Value is not used.
 | 
|    int result = DeviceIoControl(
 | 
|        dir_handle,
 | 
| @@ -453,11 +459,9 @@ char* File::LinkTarget(const char* pathname) {
 | 
|      DWORD error = GetLastError();
 | 
|      CloseHandle(dir_handle);
 | 
|      SetLastError(error);
 | 
| -    free(buffer);
 | 
|      return NULL;
 | 
|    }
 | 
|    if (CloseHandle(dir_handle) == 0) {
 | 
| -    free(buffer);
 | 
|      return NULL;
 | 
|    }
 | 
|  
 | 
| @@ -473,7 +477,6 @@ char* File::LinkTarget(const char* pathname) {
 | 
|      target_offset = buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset;
 | 
|      target_length = buffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
 | 
|    } else {  // Not a junction or a symbolic link.
 | 
| -    free(buffer);
 | 
|      SetLastError(ERROR_NOT_A_REPARSE_POINT);
 | 
|      return NULL;
 | 
|    }
 | 
| @@ -482,7 +485,7 @@ char* File::LinkTarget(const char* pathname) {
 | 
|    target_length /= sizeof(wchar_t);
 | 
|    target += target_offset;
 | 
|    // Remove "\??\" from beginning of target.
 | 
| -  if (target_length > 4 && wcsncmp(L"\\??\\", target, 4) == 0) {
 | 
| +  if ((target_length > 4) && (wcsncmp(L"\\??\\", target, 4) == 0)) {
 | 
|      target += 4;
 | 
|      target_length -= 4;
 | 
|    }
 | 
| @@ -494,7 +497,7 @@ char* File::LinkTarget(const char* pathname) {
 | 
|                                          0,
 | 
|                                          NULL,
 | 
|                                          NULL);
 | 
| -  char* utf8_target = reinterpret_cast<char*>(malloc(utf8_length + 1));
 | 
| +  char* utf8_target = DartUtils::ScopedCString(utf8_length + 1);
 | 
|    if (0 == WideCharToMultiByte(CP_UTF8,
 | 
|                                 0,
 | 
|                                 target,
 | 
| @@ -503,12 +506,9 @@ char* File::LinkTarget(const char* pathname) {
 | 
|                                 utf8_length,
 | 
|                                 NULL,
 | 
|                                 NULL)) {
 | 
| -    free(buffer);
 | 
| -    free(utf8_target);
 | 
|      return NULL;
 | 
|    }
 | 
|    utf8_target[utf8_length] = '\0';
 | 
| -  free(buffer);
 | 
|    return utf8_target;
 | 
|  }
 | 
|  
 | 
| @@ -520,7 +520,6 @@ void File::Stat(const char* name, int64_t* data) {
 | 
|      struct _stat64 st;
 | 
|      const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
 | 
|      int stat_status = _wstat64(system_name, &st);
 | 
| -    free(const_cast<wchar_t*>(system_name));
 | 
|      if (stat_status == 0) {
 | 
|        data[kCreatedTime] = st.st_ctime * 1000;
 | 
|        data[kModifiedTime] = st.st_mtime * 1000;
 | 
| @@ -538,7 +537,6 @@ time_t File::LastModified(const char* name) {
 | 
|    struct __stat64 st;
 | 
|    const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
 | 
|    int stat_status = _wstat64(system_name, &st);
 | 
| -  free(const_cast<wchar_t*>(system_name));
 | 
|    if (stat_status == 0) {
 | 
|      return st.st_mtime;
 | 
|    }
 | 
| @@ -548,14 +546,16 @@ time_t File::LastModified(const char* name) {
 | 
|  
 | 
|  bool File::IsAbsolutePath(const char* pathname) {
 | 
|    // Should we consider network paths?
 | 
| -  if (pathname == NULL) return false;
 | 
| +  if (pathname == NULL) {
 | 
| +    return false;
 | 
| +  }
 | 
|    return (strlen(pathname) > 2) &&
 | 
|        (pathname[1] == ':') &&
 | 
|        (pathname[2] == '\\' || pathname[2] == '/');
 | 
|  }
 | 
|  
 | 
|  
 | 
| -char* File::GetCanonicalPath(const char* pathname) {
 | 
| +const char* File::GetCanonicalPath(const char* pathname) {
 | 
|    const wchar_t* system_name = StringUtilsWin::Utf8ToWide(pathname);
 | 
|    HANDLE file_handle = CreateFileW(
 | 
|          system_name,
 | 
| @@ -566,7 +566,6 @@ char* File::GetCanonicalPath(const char* pathname) {
 | 
|          FILE_FLAG_BACKUP_SEMANTICS,
 | 
|          NULL);
 | 
|    if (file_handle == INVALID_HANDLE_VALUE) {
 | 
| -    free(const_cast<wchar_t*>(system_name));
 | 
|      return NULL;
 | 
|    }
 | 
|    wchar_t dummy_buffer[1];
 | 
| @@ -575,14 +574,14 @@ char* File::GetCanonicalPath(const char* pathname) {
 | 
|                                                 0,
 | 
|                                                 VOLUME_NAME_DOS);
 | 
|    if (required_size == 0) {
 | 
| -    free(const_cast<wchar_t*>(system_name));
 | 
|      DWORD error = GetLastError();
 | 
|      CloseHandle(file_handle);
 | 
|      SetLastError(error);
 | 
|      return NULL;
 | 
|    }
 | 
| -  wchar_t* path =
 | 
| -      static_cast<wchar_t*>(malloc(required_size * sizeof(wchar_t)));
 | 
| +  wchar_t* path;
 | 
| +  path = reinterpret_cast<wchar_t*>(
 | 
| +      Dart_ScopeAllocate(required_size * sizeof(*path)));
 | 
|    int result_size = GetFinalPathNameByHandle(file_handle,
 | 
|                                               path,
 | 
|                                               required_size,
 | 
| @@ -590,16 +589,14 @@ char* File::GetCanonicalPath(const char* pathname) {
 | 
|    ASSERT(result_size <= required_size - 1);
 | 
|    // Remove leading \\?\ if possible, unless input used it.
 | 
|    char* result;
 | 
| -  if (result_size < MAX_PATH - 1 + 4 &&
 | 
| -      result_size > 4 &&
 | 
| -      wcsncmp(path, L"\\\\?\\", 4) == 0 &&
 | 
| -      wcsncmp(system_name, L"\\\\?\\", 4) != 0) {
 | 
| +  if ((result_size < MAX_PATH - 1 + 4) &&
 | 
| +      (result_size > 4) &&
 | 
| +      (wcsncmp(path, L"\\\\?\\", 4) == 0) &&
 | 
| +      (wcsncmp(system_name, L"\\\\?\\", 4) != 0)) {
 | 
|      result = StringUtilsWin::WideToUtf8(path + 4);
 | 
|    } else {
 | 
|      result = StringUtilsWin::WideToUtf8(path);
 | 
|    }
 | 
| -  free(const_cast<wchar_t*>(system_name));
 | 
| -  free(path);
 | 
|    CloseHandle(file_handle);
 | 
|    return result;
 | 
|  }
 | 
| @@ -652,7 +649,6 @@ File::Type File::GetType(const char* pathname, bool follow_links) {
 | 
|    } else if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
 | 
|      result = kIsDirectory;
 | 
|    }
 | 
| -  free(const_cast<wchar_t*>(name));
 | 
|    return result;
 | 
|  }
 | 
|  
 | 
| @@ -671,10 +667,8 @@ File::Identical File::AreIdentical(const char* file_1, const char* file_2) {
 | 
|          FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
 | 
|          NULL);
 | 
|      if (file_handle == INVALID_HANDLE_VALUE) {
 | 
| -      free(const_cast<wchar_t*>(wide_name));
 | 
|        return File::kError;
 | 
|      }
 | 
| -    free(const_cast<wchar_t*>(wide_name));
 | 
|      int result = GetFileInformationByHandle(file_handle, &file_info[i]);
 | 
|      if (result == 0) {
 | 
|        DWORD error = GetLastError();
 | 
| @@ -686,9 +680,10 @@ File::Identical File::AreIdentical(const char* file_1, const char* file_2) {
 | 
|        return File::kError;
 | 
|      }
 | 
|    }
 | 
| -  if (file_info[0].dwVolumeSerialNumber == file_info[1].dwVolumeSerialNumber &&
 | 
| -      file_info[0].nFileIndexHigh == file_info[1].nFileIndexHigh &&
 | 
| -      file_info[0].nFileIndexLow == file_info[1].nFileIndexLow) {
 | 
| +  if ((file_info[0].dwVolumeSerialNumber ==
 | 
| +          file_info[1].dwVolumeSerialNumber) &&
 | 
| +      (file_info[0].nFileIndexHigh == file_info[1].nFileIndexHigh) &&
 | 
| +      (file_info[0].nFileIndexLow == file_info[1].nFileIndexLow)) {
 | 
|      return kIdentical;
 | 
|    } else {
 | 
|      return kDifferent;
 | 
| 
 |