summaryrefslogtreecommitdiffstats
path: root/xpcom/io/SpecialSystemDirectory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom/io/SpecialSystemDirectory.cpp')
-rw-r--r--xpcom/io/SpecialSystemDirectory.cpp830
1 files changed, 830 insertions, 0 deletions
diff --git a/xpcom/io/SpecialSystemDirectory.cpp b/xpcom/io/SpecialSystemDirectory.cpp
new file mode 100644
index 000000000..9ce8eb85b
--- /dev/null
+++ b/xpcom/io/SpecialSystemDirectory.cpp
@@ -0,0 +1,830 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SpecialSystemDirectory.h"
+#include "nsString.h"
+#include "nsDependentString.h"
+#include "nsAutoPtr.h"
+
+#if defined(XP_WIN)
+
+#include <windows.h>
+#include <shlobj.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <direct.h>
+#include <shlobj.h>
+#include <knownfolders.h>
+#include <guiddef.h>
+#include "mozilla/WindowsVersion.h"
+
+using mozilla::IsWin7OrLater;
+
+#elif defined(XP_UNIX)
+
+#include <limits.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include "prenv.h"
+#if defined(MOZ_WIDGET_COCOA)
+#include "CocoaFileUtils.h"
+#endif
+
+#endif
+
+#ifndef MAXPATHLEN
+#ifdef PATH_MAX
+#define MAXPATHLEN PATH_MAX
+#elif defined(MAX_PATH)
+#define MAXPATHLEN MAX_PATH
+#elif defined(_MAX_PATH)
+#define MAXPATHLEN _MAX_PATH
+#elif defined(CCHMAXPATH)
+#define MAXPATHLEN CCHMAXPATH
+#else
+#define MAXPATHLEN 1024
+#endif
+#endif
+
+#ifdef XP_WIN
+typedef HRESULT (WINAPI* nsGetKnownFolderPath)(GUID& rfid,
+ DWORD dwFlags,
+ HANDLE hToken,
+ PWSTR* ppszPath);
+
+static nsGetKnownFolderPath gGetKnownFolderPath = nullptr;
+#endif
+
+void
+StartupSpecialSystemDirectory()
+{
+#if defined (XP_WIN)
+ // SHGetKnownFolderPath is only available on Windows Vista
+ // so that we need to use GetProcAddress to get the pointer.
+ HMODULE hShell32DLLInst = GetModuleHandleW(L"shell32.dll");
+ if (hShell32DLLInst) {
+ gGetKnownFolderPath = (nsGetKnownFolderPath)
+ GetProcAddress(hShell32DLLInst, "SHGetKnownFolderPath");
+ }
+#endif
+}
+
+#if defined (XP_WIN)
+
+static nsresult
+GetKnownFolder(GUID* aGuid, nsIFile** aFile)
+{
+ if (!aGuid || !gGetKnownFolderPath) {
+ return NS_ERROR_FAILURE;
+ }
+
+ PWSTR path = nullptr;
+ gGetKnownFolderPath(*aGuid, 0, nullptr, &path);
+
+ if (!path) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsresult rv = NS_NewLocalFile(nsDependentString(path),
+ true,
+ aFile);
+
+ CoTaskMemFree(path);
+ return rv;
+}
+
+static nsresult
+GetWindowsFolder(int aFolder, nsIFile** aFile)
+{
+ WCHAR path_orig[MAX_PATH + 3];
+ WCHAR* path = path_orig + 1;
+ HRESULT result = SHGetSpecialFolderPathW(nullptr, path, aFolder, true);
+
+ if (!SUCCEEDED(result)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // Append the trailing slash
+ int len = wcslen(path);
+ if (len > 1 && path[len - 1] != L'\\') {
+ path[len] = L'\\';
+ path[++len] = L'\0';
+ }
+
+ return NS_NewLocalFile(nsDependentString(path, len), true, aFile);
+}
+
+__inline HRESULT
+SHLoadLibraryFromKnownFolder(REFKNOWNFOLDERID aFolderId, DWORD aMode,
+ REFIID riid, void** ppv)
+{
+ *ppv = nullptr;
+ IShellLibrary* plib;
+ HRESULT hr = CoCreateInstance(CLSID_ShellLibrary, nullptr,
+ CLSCTX_INPROC_SERVER,
+ IID_PPV_ARGS(&plib));
+ if (SUCCEEDED(hr)) {
+ hr = plib->LoadLibraryFromKnownFolder(aFolderId, aMode);
+ if (SUCCEEDED(hr)) {
+ hr = plib->QueryInterface(riid, ppv);
+ }
+ plib->Release();
+ }
+ return hr;
+}
+
+/*
+ * Check to see if we're on Win7 and up, and if so, returns the default
+ * save-to location for the Windows Library passed in through aFolderId.
+ * Otherwise falls back on pre-win7 GetWindowsFolder.
+ */
+static nsresult
+GetLibrarySaveToPath(int aFallbackFolderId, REFKNOWNFOLDERID aFolderId,
+ nsIFile** aFile)
+{
+ // Skip off checking for library support if the os is Vista or lower.
+ if (!IsWin7OrLater()) {
+ return GetWindowsFolder(aFallbackFolderId, aFile);
+ }
+
+ RefPtr<IShellLibrary> shellLib;
+ RefPtr<IShellItem> savePath;
+ HRESULT hr =
+ SHLoadLibraryFromKnownFolder(aFolderId, STGM_READ,
+ IID_IShellLibrary, getter_AddRefs(shellLib));
+
+ if (shellLib &&
+ SUCCEEDED(shellLib->GetDefaultSaveFolder(DSFT_DETECT, IID_IShellItem,
+ getter_AddRefs(savePath)))) {
+ wchar_t* str = nullptr;
+ if (SUCCEEDED(savePath->GetDisplayName(SIGDN_FILESYSPATH, &str))) {
+ nsAutoString path;
+ path.Assign(str);
+ path.Append('\\');
+ nsresult rv =
+ NS_NewLocalFile(path, false, aFile);
+ CoTaskMemFree(str);
+ return rv;
+ }
+ }
+
+ return GetWindowsFolder(aFallbackFolderId, aFile);
+}
+
+/**
+ * Provides a fallback for getting the path to APPDATA or LOCALAPPDATA by
+ * querying the registry when the call to SHGetSpecialFolderPathW is unable to
+ * provide these paths (Bug 513958).
+ */
+static nsresult
+GetRegWindowsAppDataFolder(bool aLocal, nsIFile** aFile)
+{
+ HKEY key;
+ NS_NAMED_LITERAL_STRING(keyName,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
+ DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName.get(), 0, KEY_READ,
+ &key);
+ if (res != ERROR_SUCCESS) {
+ return NS_ERROR_FAILURE;
+ }
+
+ WCHAR path[MAX_PATH + 2];
+ DWORD type, size;
+ res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"),
+ nullptr, &type, (LPBYTE)&path, &size);
+ ::RegCloseKey(key);
+ // The call to RegQueryValueExW must succeed, the type must be REG_SZ, the
+ // buffer size must not equal 0, and the buffer size be a multiple of 2.
+ if (res != ERROR_SUCCESS || type != REG_SZ || size == 0 || size % 2 != 0) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // Append the trailing slash
+ int len = wcslen(path);
+ if (len > 1 && path[len - 1] != L'\\') {
+ path[len] = L'\\';
+ path[++len] = L'\0';
+ }
+
+ return NS_NewLocalFile(nsDependentString(path, len), true, aFile);
+}
+
+#endif // XP_WIN
+
+#if defined(XP_UNIX)
+static nsresult
+GetUnixHomeDir(nsIFile** aFile)
+{
+#if defined(ANDROID)
+ // XXX no home dir on android; maybe we should return the sdcard if present?
+ return NS_ERROR_FAILURE;
+#else
+ return NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")),
+ true, aFile);
+#endif
+}
+
+/*
+ The following license applies to the xdg_user_dir_lookup function:
+
+ Copyright (c) 2007 Red Hat, Inc.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+static char*
+xdg_user_dir_lookup(const char* aType)
+{
+ FILE* file;
+ char* home_dir;
+ char* config_home;
+ char* config_file;
+ char buffer[512];
+ char* user_dir;
+ char* p;
+ char* d;
+ int len;
+ int relative;
+
+ home_dir = getenv("HOME");
+
+ if (!home_dir) {
+ goto error;
+ }
+
+ config_home = getenv("XDG_CONFIG_HOME");
+ if (!config_home || config_home[0] == 0) {
+ config_file = (char*)malloc(strlen(home_dir) +
+ strlen("/.config/user-dirs.dirs") + 1);
+ if (!config_file) {
+ goto error;
+ }
+
+ strcpy(config_file, home_dir);
+ strcat(config_file, "/.config/user-dirs.dirs");
+ } else {
+ config_file = (char*)malloc(strlen(config_home) +
+ strlen("/user-dirs.dirs") + 1);
+ if (!config_file) {
+ goto error;
+ }
+
+ strcpy(config_file, config_home);
+ strcat(config_file, "/user-dirs.dirs");
+ }
+
+ file = fopen(config_file, "r");
+ free(config_file);
+ if (!file) {
+ goto error;
+ }
+
+ user_dir = nullptr;
+ while (fgets(buffer, sizeof(buffer), file)) {
+ /* Remove newline at end */
+ len = strlen(buffer);
+ if (len > 0 && buffer[len - 1] == '\n') {
+ buffer[len - 1] = 0;
+ }
+
+ p = buffer;
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+
+ if (strncmp(p, "XDG_", 4) != 0) {
+ continue;
+ }
+ p += 4;
+ if (strncmp(p, aType, strlen(aType)) != 0) {
+ continue;
+ }
+ p += strlen(aType);
+ if (strncmp(p, "_DIR", 4) != 0) {
+ continue;
+ }
+ p += 4;
+
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+
+ if (*p != '=') {
+ continue;
+ }
+ p++;
+
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+
+ if (*p != '"') {
+ continue;
+ }
+ p++;
+
+ relative = 0;
+ if (strncmp(p, "$HOME/", 6) == 0) {
+ p += 6;
+ relative = 1;
+ } else if (*p != '/') {
+ continue;
+ }
+
+ if (relative) {
+ user_dir = (char*)malloc(strlen(home_dir) + 1 + strlen(p) + 1);
+ if (!user_dir) {
+ goto error2;
+ }
+
+ strcpy(user_dir, home_dir);
+ strcat(user_dir, "/");
+ } else {
+ user_dir = (char*)malloc(strlen(p) + 1);
+ if (!user_dir) {
+ goto error2;
+ }
+
+ *user_dir = 0;
+ }
+
+ d = user_dir + strlen(user_dir);
+ while (*p && *p != '"') {
+ if ((*p == '\\') && (*(p + 1) != 0)) {
+ p++;
+ }
+ *d++ = *p++;
+ }
+ *d = 0;
+ }
+error2:
+ fclose(file);
+
+ if (user_dir) {
+ return user_dir;
+ }
+
+error:
+ return nullptr;
+}
+
+static const char xdg_user_dirs[] =
+ "DESKTOP\0"
+ "DOCUMENTS\0"
+ "DOWNLOAD\0"
+ "MUSIC\0"
+ "PICTURES\0"
+ "PUBLICSHARE\0"
+ "TEMPLATES\0"
+ "VIDEOS";
+
+static const uint8_t xdg_user_dir_offsets[] = {
+ 0,
+ 8,
+ 18,
+ 27,
+ 33,
+ 42,
+ 54,
+ 64
+};
+
+static nsresult
+GetUnixXDGUserDirectory(SystemDirectories aSystemDirectory,
+ nsIFile** aFile)
+{
+ char* dir = xdg_user_dir_lookup(
+ xdg_user_dirs + xdg_user_dir_offsets[aSystemDirectory - Unix_XDG_Desktop]);
+
+ nsresult rv;
+ nsCOMPtr<nsIFile> file;
+ if (dir) {
+ rv = NS_NewNativeLocalFile(nsDependentCString(dir), true,
+ getter_AddRefs(file));
+ free(dir);
+ } else if (Unix_XDG_Desktop == aSystemDirectory) {
+ // for the XDG desktop dir, fall back to HOME/Desktop
+ // (for historical compatibility)
+ rv = GetUnixHomeDir(getter_AddRefs(file));
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = file->AppendNative(NS_LITERAL_CSTRING("Desktop"));
+ } else {
+ // no fallback for the other XDG dirs
+ rv = NS_ERROR_FAILURE;
+ }
+
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ bool exists;
+ rv = file->Exists(&exists);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ if (!exists) {
+ rv = file->Create(nsIFile::DIRECTORY_TYPE, 0755);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ }
+
+ *aFile = nullptr;
+ file.swap(*aFile);
+
+ return NS_OK;
+}
+#endif
+
+nsresult
+GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory,
+ nsIFile** aFile)
+{
+#if defined(XP_WIN)
+ WCHAR path[MAX_PATH];
+#else
+ char path[MAXPATHLEN];
+#endif
+
+ switch (aSystemSystemDirectory) {
+ case OS_CurrentWorkingDirectory:
+#if defined(XP_WIN)
+ if (!_wgetcwd(path, MAX_PATH)) {
+ return NS_ERROR_FAILURE;
+ }
+ return NS_NewLocalFile(nsDependentString(path),
+ true,
+ aFile);
+#else
+ if (!getcwd(path, MAXPATHLEN)) {
+ return NS_ERROR_FAILURE;
+ }
+#endif
+
+#if !defined(XP_WIN)
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ true,
+ aFile);
+#endif
+
+ case OS_DriveDirectory:
+#if defined (XP_WIN)
+ {
+ int32_t len = ::GetWindowsDirectoryW(path, MAX_PATH);
+ if (len == 0) {
+ break;
+ }
+ if (path[1] == char16_t(':') && path[2] == char16_t('\\')) {
+ path[3] = 0;
+ }
+
+ return NS_NewLocalFile(nsDependentString(path),
+ true,
+ aFile);
+ }
+#else
+ return NS_NewNativeLocalFile(nsDependentCString("/"),
+ true,
+ aFile);
+
+#endif
+
+ case OS_TemporaryDirectory:
+#if defined (XP_WIN)
+ {
+ DWORD len = ::GetTempPathW(MAX_PATH, path);
+ if (len == 0) {
+ break;
+ }
+ return NS_NewLocalFile(nsDependentString(path, len),
+ true,
+ aFile);
+ }
+#elif defined(MOZ_WIDGET_COCOA)
+ {
+ return GetOSXFolderType(kUserDomain, kTemporaryFolderType, aFile);
+ }
+
+#elif defined(XP_UNIX)
+ {
+ static const char* tPath = nullptr;
+ if (!tPath) {
+ tPath = PR_GetEnv("TMPDIR");
+ if (!tPath || !*tPath) {
+ tPath = PR_GetEnv("TMP");
+ if (!tPath || !*tPath) {
+ tPath = PR_GetEnv("TEMP");
+ if (!tPath || !*tPath) {
+ tPath = "/tmp/";
+ }
+ }
+ }
+ }
+ return NS_NewNativeLocalFile(nsDependentCString(tPath),
+ true,
+ aFile);
+ }
+#else
+ break;
+#endif
+#if defined (XP_WIN)
+ case Win_SystemDirectory: {
+ int32_t len = ::GetSystemDirectoryW(path, MAX_PATH);
+
+ // Need enough space to add the trailing backslash
+ if (!len || len > MAX_PATH - 2) {
+ break;
+ }
+ path[len] = L'\\';
+ path[++len] = L'\0';
+
+ return NS_NewLocalFile(nsDependentString(path, len),
+ true,
+ aFile);
+ }
+
+ case Win_WindowsDirectory: {
+ int32_t len = ::GetWindowsDirectoryW(path, MAX_PATH);
+
+ // Need enough space to add the trailing backslash
+ if (!len || len > MAX_PATH - 2) {
+ break;
+ }
+
+ path[len] = L'\\';
+ path[++len] = L'\0';
+
+ return NS_NewLocalFile(nsDependentString(path, len),
+ true,
+ aFile);
+ }
+
+ case Win_ProgramFiles: {
+ return GetWindowsFolder(CSIDL_PROGRAM_FILES, aFile);
+ }
+
+ case Win_HomeDirectory: {
+ nsresult rv = GetWindowsFolder(CSIDL_PROFILE, aFile);
+ if (NS_SUCCEEDED(rv)) {
+ return rv;
+ }
+
+ int32_t len;
+ if ((len = ::GetEnvironmentVariableW(L"HOME", path, MAX_PATH)) > 0) {
+ // Need enough space to add the trailing backslash
+ if (len > MAX_PATH - 2) {
+ break;
+ }
+
+ path[len] = L'\\';
+ path[++len] = L'\0';
+
+ rv = NS_NewLocalFile(nsDependentString(path, len),
+ true,
+ aFile);
+ if (NS_SUCCEEDED(rv)) {
+ return rv;
+ }
+ }
+
+ len = ::GetEnvironmentVariableW(L"HOMEDRIVE", path, MAX_PATH);
+ if (0 < len && len < MAX_PATH) {
+ WCHAR temp[MAX_PATH];
+ DWORD len2 = ::GetEnvironmentVariableW(L"HOMEPATH", temp, MAX_PATH);
+ if (0 < len2 && len + len2 < MAX_PATH) {
+ wcsncat(path, temp, len2);
+ }
+
+ len = wcslen(path);
+
+ // Need enough space to add the trailing backslash
+ if (len > MAX_PATH - 2) {
+ break;
+ }
+
+ path[len] = L'\\';
+ path[++len] = L'\0';
+
+ return NS_NewLocalFile(nsDependentString(path, len),
+ true,
+ aFile);
+ }
+ }
+ case Win_Desktop: {
+ return GetWindowsFolder(CSIDL_DESKTOP, aFile);
+ }
+ case Win_Programs: {
+ return GetWindowsFolder(CSIDL_PROGRAMS, aFile);
+ }
+
+ case Win_Downloads: {
+ // Defined in KnownFolders.h.
+ GUID folderid_downloads = {
+ 0x374de290, 0x123f, 0x4565,
+ { 0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b }
+ };
+ nsresult rv = GetKnownFolder(&folderid_downloads, aFile);
+ // On WinXP, there is no downloads folder, default
+ // to 'Desktop'.
+ if (NS_ERROR_FAILURE == rv) {
+ rv = GetWindowsFolder(CSIDL_DESKTOP, aFile);
+ }
+ return rv;
+ }
+
+ case Win_Controls: {
+ return GetWindowsFolder(CSIDL_CONTROLS, aFile);
+ }
+ case Win_Printers: {
+ return GetWindowsFolder(CSIDL_PRINTERS, aFile);
+ }
+ case Win_Personal: {
+ return GetWindowsFolder(CSIDL_PERSONAL, aFile);
+ }
+ case Win_Favorites: {
+ return GetWindowsFolder(CSIDL_FAVORITES, aFile);
+ }
+ case Win_Startup: {
+ return GetWindowsFolder(CSIDL_STARTUP, aFile);
+ }
+ case Win_Recent: {
+ return GetWindowsFolder(CSIDL_RECENT, aFile);
+ }
+ case Win_Sendto: {
+ return GetWindowsFolder(CSIDL_SENDTO, aFile);
+ }
+ case Win_Bitbucket: {
+ return GetWindowsFolder(CSIDL_BITBUCKET, aFile);
+ }
+ case Win_Startmenu: {
+ return GetWindowsFolder(CSIDL_STARTMENU, aFile);
+ }
+ case Win_Desktopdirectory: {
+ return GetWindowsFolder(CSIDL_DESKTOPDIRECTORY, aFile);
+ }
+ case Win_Drives: {
+ return GetWindowsFolder(CSIDL_DRIVES, aFile);
+ }
+ case Win_Network: {
+ return GetWindowsFolder(CSIDL_NETWORK, aFile);
+ }
+ case Win_Nethood: {
+ return GetWindowsFolder(CSIDL_NETHOOD, aFile);
+ }
+ case Win_Fonts: {
+ return GetWindowsFolder(CSIDL_FONTS, aFile);
+ }
+ case Win_Templates: {
+ return GetWindowsFolder(CSIDL_TEMPLATES, aFile);
+ }
+ case Win_Common_Startmenu: {
+ return GetWindowsFolder(CSIDL_COMMON_STARTMENU, aFile);
+ }
+ case Win_Common_Programs: {
+ return GetWindowsFolder(CSIDL_COMMON_PROGRAMS, aFile);
+ }
+ case Win_Common_Startup: {
+ return GetWindowsFolder(CSIDL_COMMON_STARTUP, aFile);
+ }
+ case Win_Common_Desktopdirectory: {
+ return GetWindowsFolder(CSIDL_COMMON_DESKTOPDIRECTORY, aFile);
+ }
+ case Win_Common_AppData: {
+ return GetWindowsFolder(CSIDL_COMMON_APPDATA, aFile);
+ }
+ case Win_Printhood: {
+ return GetWindowsFolder(CSIDL_PRINTHOOD, aFile);
+ }
+ case Win_Cookies: {
+ return GetWindowsFolder(CSIDL_COOKIES, aFile);
+ }
+ case Win_Appdata: {
+ nsresult rv = GetWindowsFolder(CSIDL_APPDATA, aFile);
+ if (NS_FAILED(rv)) {
+ rv = GetRegWindowsAppDataFolder(false, aFile);
+ }
+ return rv;
+ }
+ case Win_LocalAppdata: {
+ nsresult rv = GetWindowsFolder(CSIDL_LOCAL_APPDATA, aFile);
+ if (NS_FAILED(rv)) {
+ rv = GetRegWindowsAppDataFolder(true, aFile);
+ }
+ return rv;
+ }
+#if defined(MOZ_CONTENT_SANDBOX)
+ case Win_LocalAppdataLow: {
+ // This should only really fail on versions pre-Vista, in which case this
+ // shouldn't have been used in the first place.
+ GUID localAppDataLowGuid = FOLDERID_LocalAppDataLow;
+ return GetKnownFolder(&localAppDataLowGuid, aFile);
+ }
+#endif
+ case Win_Documents: {
+ return GetLibrarySaveToPath(CSIDL_MYDOCUMENTS,
+ FOLDERID_DocumentsLibrary,
+ aFile);
+ }
+ case Win_Pictures: {
+ return GetLibrarySaveToPath(CSIDL_MYPICTURES,
+ FOLDERID_PicturesLibrary,
+ aFile);
+ }
+ case Win_Music: {
+ return GetLibrarySaveToPath(CSIDL_MYMUSIC,
+ FOLDERID_MusicLibrary,
+ aFile);
+ }
+ case Win_Videos: {
+ return GetLibrarySaveToPath(CSIDL_MYVIDEO,
+ FOLDERID_VideosLibrary,
+ aFile);
+ }
+#endif // XP_WIN
+
+#if defined(XP_UNIX)
+ case Unix_LocalDirectory:
+ return NS_NewNativeLocalFile(nsDependentCString("/usr/local/netscape/"),
+ true,
+ aFile);
+ case Unix_LibDirectory:
+ return NS_NewNativeLocalFile(nsDependentCString("/usr/local/lib/netscape/"),
+ true,
+ aFile);
+
+ case Unix_HomeDirectory:
+ return GetUnixHomeDir(aFile);
+
+ case Unix_XDG_Desktop:
+ case Unix_XDG_Documents:
+ case Unix_XDG_Download:
+ case Unix_XDG_Music:
+ case Unix_XDG_Pictures:
+ case Unix_XDG_PublicShare:
+ case Unix_XDG_Templates:
+ case Unix_XDG_Videos:
+ return GetUnixXDGUserDirectory(aSystemSystemDirectory, aFile);
+#endif
+
+ default:
+ break;
+ }
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+#if defined (MOZ_WIDGET_COCOA)
+nsresult
+GetOSXFolderType(short aDomain, OSType aFolderType, nsIFile** aLocalFile)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+ if (aFolderType == kTemporaryFolderType) {
+ NS_NewLocalFile(EmptyString(), true, aLocalFile);
+ nsCOMPtr<nsILocalFileMac> localMacFile(do_QueryInterface(*aLocalFile));
+ if (localMacFile) {
+ rv = localMacFile->InitWithCFURL(
+ CocoaFileUtils::GetTemporaryFolderCFURLRef());
+ }
+ return rv;
+ }
+
+ OSErr err;
+ FSRef fsRef;
+ err = ::FSFindFolder(aDomain, aFolderType, kCreateFolder, &fsRef);
+ if (err == noErr) {
+ NS_NewLocalFile(EmptyString(), true, aLocalFile);
+ nsCOMPtr<nsILocalFileMac> localMacFile(do_QueryInterface(*aLocalFile));
+ if (localMacFile) {
+ rv = localMacFile->InitWithFSRef(&fsRef);
+ }
+ }
+ return rv;
+}
+#endif
+