bool RunOpenMultiFileDialog()

in libcef/browser/native/file_dialog_runner_win.cc [301:387]


bool RunOpenMultiFileDialog(
    const CefFileDialogRunner::FileChooserParams& params,
    HWND owner,
    int* filter_index,
    std::vector<base::FilePath>* paths) {
  OPENFILENAME ofn;

  // We must do this otherwise the ofn's FlagsEx may be initialized to random
  // junk in release builds which can cause the Places Bar not to show up!
  ZeroMemory(&ofn, sizeof(ofn));
  ofn.lStructSize = sizeof(ofn);
  ofn.hwndOwner = owner;

  std::unique_ptr<wchar_t[]> filename(new wchar_t[UNICODE_STRING_MAX_CHARS]);
  filename[0] = 0;

  ofn.lpstrFile = filename.get();
  ofn.nMaxFile = UNICODE_STRING_MAX_CHARS;

  std::wstring directory;
  if (!params.default_file_name.empty()) {
    if (params.default_file_name.EndsWithSeparator()) {
      // The value is only a directory.
      directory = params.default_file_name.value();
    } else {
      // The value is a file name and possibly a directory.
      directory = params.default_file_name.DirName().value();
    }
  }
  if (!directory.empty())
    ofn.lpstrInitialDir = directory.c_str();

  std::wstring title;
  if (!params.title.empty()) {
    title = base::UTF16ToWide(params.title);
  } else {
    title = base::UTF16ToWide(
        l10n_util::GetStringUTF16(IDS_OPEN_FILES_DIALOG_TITLE));
  }
  if (!title.empty())
    ofn.lpstrTitle = title.c_str();

  // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory
  // without having to close Chrome first.
  ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER |
              OFN_ALLOWMULTISELECT | OFN_ENABLESIZING;
  if (params.hidereadonly)
    ofn.Flags |= OFN_HIDEREADONLY;

  const std::wstring& filter = GetFilterString(params.accept_types);
  if (!filter.empty()) {
    ofn.lpstrFilter = filter.c_str();
    // Indices into |lpstrFilter| start at 1.
    ofn.nFilterIndex = *filter_index + 1;
  }

  bool success = !!GetOpenFileName(&ofn);

  if (success) {
    std::vector<base::FilePath> files;
    const wchar_t* selection = ofn.lpstrFile;
    while (*selection) {  // Empty string indicates end of list.
      files.push_back(base::FilePath(selection));
      // Skip over filename and null-terminator.
      selection += files.back().value().length() + 1;
    }
    if (files.empty()) {
      success = false;
    } else if (files.size() == 1) {
      // When there is one file, it contains the path and filename.
      paths->swap(files);
    } else {
      // Otherwise, the first string is the path, and the remainder are
      // filenames.
      std::vector<base::FilePath>::iterator path = files.begin();
      for (std::vector<base::FilePath>::iterator file = path + 1;
           file != files.end(); ++file) {
        paths->push_back(path->Append(*file));
      }
    }
  }

  if (success)
    *filter_index = ofn.nFilterIndex == 0 ? 0 : ofn.nFilterIndex - 1;

  return success;
}