xpcom/io/SpecialSystemDirectory.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xpcom/io/SpecialSystemDirectory.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,826 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "SpecialSystemDirectory.h"
    1.10 +#include "nsString.h"
    1.11 +#include "nsDependentString.h"
    1.12 +#include "nsAutoPtr.h"
    1.13 +
    1.14 +#if defined(XP_WIN)
    1.15 +
    1.16 +#include <windows.h>
    1.17 +#include <shlobj.h>
    1.18 +#include <stdlib.h>
    1.19 +#include <stdio.h>
    1.20 +#include <string.h>
    1.21 +#include <direct.h>
    1.22 +#include <shlobj.h>
    1.23 +#include <knownfolders.h>
    1.24 +#include <guiddef.h>
    1.25 +#include "mozilla/WindowsVersion.h"
    1.26 +
    1.27 +using mozilla::IsWin7OrLater;
    1.28 +
    1.29 +#elif defined(XP_UNIX)
    1.30 +
    1.31 +#include <limits.h>
    1.32 +#include <unistd.h>
    1.33 +#include <stdlib.h>
    1.34 +#include <sys/param.h>
    1.35 +#include "prenv.h"
    1.36 +
    1.37 +#endif
    1.38 +
    1.39 +#if defined(VMS)
    1.40 +#include <unixlib.h>
    1.41 +#endif
    1.42 +
    1.43 +#ifndef MAXPATHLEN
    1.44 +#ifdef PATH_MAX
    1.45 +#define MAXPATHLEN PATH_MAX
    1.46 +#elif defined(MAX_PATH)
    1.47 +#define MAXPATHLEN MAX_PATH
    1.48 +#elif defined(_MAX_PATH)
    1.49 +#define MAXPATHLEN _MAX_PATH
    1.50 +#elif defined(CCHMAXPATH)
    1.51 +#define MAXPATHLEN CCHMAXPATH
    1.52 +#else
    1.53 +#define MAXPATHLEN 1024
    1.54 +#endif
    1.55 +#endif
    1.56 +
    1.57 +#ifdef XP_WIN
    1.58 +typedef HRESULT (WINAPI* nsGetKnownFolderPath)(GUID& rfid,
    1.59 +                                               DWORD dwFlags,
    1.60 +                                               HANDLE hToken,
    1.61 +                                               PWSTR *ppszPath);
    1.62 +
    1.63 +static nsGetKnownFolderPath gGetKnownFolderPath = nullptr;
    1.64 +#endif
    1.65 +
    1.66 +void StartupSpecialSystemDirectory()
    1.67 +{
    1.68 +#if defined (XP_WIN)
    1.69 +    // SHGetKnownFolderPath is only available on Windows Vista
    1.70 +    // so that we need to use GetProcAddress to get the pointer.
    1.71 +    HMODULE hShell32DLLInst = GetModuleHandleW(L"shell32.dll");
    1.72 +    if(hShell32DLLInst)
    1.73 +    {
    1.74 +        gGetKnownFolderPath = (nsGetKnownFolderPath)
    1.75 +            GetProcAddress(hShell32DLLInst, "SHGetKnownFolderPath");
    1.76 +    }
    1.77 +#endif
    1.78 +}
    1.79 +
    1.80 +#if defined (XP_WIN)
    1.81 +
    1.82 +static nsresult GetKnownFolder(GUID* guid, nsIFile** aFile)
    1.83 +{
    1.84 +    if (!guid || !gGetKnownFolderPath)
    1.85 +        return NS_ERROR_FAILURE;
    1.86 +
    1.87 +    PWSTR path = nullptr;
    1.88 +    gGetKnownFolderPath(*guid, 0, nullptr, &path);
    1.89 +
    1.90 +    if (!path)
    1.91 +        return NS_ERROR_FAILURE;
    1.92 +
    1.93 +    nsresult rv = NS_NewLocalFile(nsDependentString(path),
    1.94 +                                  true,
    1.95 +                                  aFile);
    1.96 +
    1.97 +    CoTaskMemFree(path);
    1.98 +    return rv;
    1.99 +}
   1.100 +
   1.101 +static nsresult
   1.102 +GetWindowsFolder(int folder, nsIFile** aFile)
   1.103 +{
   1.104 +    WCHAR path_orig[MAX_PATH + 3];
   1.105 +    WCHAR *path = path_orig+1;
   1.106 +    HRESULT result = SHGetSpecialFolderPathW(nullptr, path, folder, true);
   1.107 +
   1.108 +    if (!SUCCEEDED(result))
   1.109 +        return NS_ERROR_FAILURE;
   1.110 +
   1.111 +    // Append the trailing slash
   1.112 +    int len = wcslen(path);
   1.113 +    if (len > 1 && path[len - 1] != L'\\')
   1.114 +    {
   1.115 +        path[len]   = L'\\';
   1.116 +        path[++len] = L'\0';
   1.117 +    }
   1.118 +
   1.119 +    return NS_NewLocalFile(nsDependentString(path, len), true, aFile);
   1.120 +}
   1.121 +
   1.122 +__inline HRESULT
   1.123 +SHLoadLibraryFromKnownFolder(REFKNOWNFOLDERID aFolderId, DWORD aMode,
   1.124 +                             REFIID riid, void **ppv)
   1.125 +{
   1.126 +    *ppv = nullptr;
   1.127 +    IShellLibrary *plib;
   1.128 +    HRESULT hr = CoCreateInstance(CLSID_ShellLibrary, nullptr,
   1.129 +                                  CLSCTX_INPROC_SERVER,
   1.130 +                                  IID_PPV_ARGS(&plib));
   1.131 +    if (SUCCEEDED(hr)) {
   1.132 +        hr = plib->LoadLibraryFromKnownFolder(aFolderId, aMode);
   1.133 +        if (SUCCEEDED(hr)) {
   1.134 +            hr = plib->QueryInterface(riid, ppv);
   1.135 +        }
   1.136 +        plib->Release();
   1.137 +    }
   1.138 +    return hr;
   1.139 +}
   1.140 +
   1.141 +/*
   1.142 + * Check to see if we're on Win7 and up, and if so, returns the default
   1.143 + * save-to location for the Windows Library passed in through aFolderId.
   1.144 + * Otherwise falls back on pre-win7 GetWindowsFolder.
   1.145 + */
   1.146 +static nsresult
   1.147 +GetLibrarySaveToPath(int aFallbackFolderId, REFKNOWNFOLDERID aFolderId,
   1.148 +                     nsIFile** aFile)
   1.149 +{
   1.150 +    // Skip off checking for library support if the os is Vista or lower.
   1.151 +    if (!IsWin7OrLater())
   1.152 +      return GetWindowsFolder(aFallbackFolderId, aFile);
   1.153 +
   1.154 +    nsRefPtr<IShellLibrary> shellLib;
   1.155 +    nsRefPtr<IShellItem> savePath;
   1.156 +    HRESULT hr =
   1.157 +        SHLoadLibraryFromKnownFolder(aFolderId, STGM_READ,
   1.158 +                                     IID_IShellLibrary, getter_AddRefs(shellLib));
   1.159 +
   1.160 +    if (shellLib &&
   1.161 +        SUCCEEDED(shellLib->GetDefaultSaveFolder(DSFT_DETECT, IID_IShellItem,
   1.162 +                                                 getter_AddRefs(savePath)))) {
   1.163 +        wchar_t* str = nullptr;
   1.164 +        if (SUCCEEDED(savePath->GetDisplayName(SIGDN_FILESYSPATH, &str))) {
   1.165 +            nsAutoString path;
   1.166 +            path.Assign(str);
   1.167 +            path.AppendLiteral("\\");
   1.168 +            nsresult rv =
   1.169 +                NS_NewLocalFile(path, false, aFile);
   1.170 +            CoTaskMemFree(str);
   1.171 +            return rv;
   1.172 +        }
   1.173 +    }
   1.174 +
   1.175 +    return GetWindowsFolder(aFallbackFolderId, aFile);
   1.176 +}
   1.177 +
   1.178 +/**
   1.179 + * Provides a fallback for getting the path to APPDATA or LOCALAPPDATA by
   1.180 + * querying the registry when the call to SHGetSpecialFolderPathW is unable to
   1.181 + * provide these paths (Bug 513958).
   1.182 + */
   1.183 +static nsresult GetRegWindowsAppDataFolder(bool aLocal, nsIFile** aFile)
   1.184 +{
   1.185 +    HKEY key;
   1.186 +    NS_NAMED_LITERAL_STRING(keyName,
   1.187 +    "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
   1.188 +    DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName.get(), 0, KEY_READ,
   1.189 +                                &key);
   1.190 +    if (res != ERROR_SUCCESS)
   1.191 +        return NS_ERROR_FAILURE;
   1.192 +
   1.193 +    WCHAR path[MAX_PATH + 2];
   1.194 +    DWORD type, size;
   1.195 +    res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"),
   1.196 +                           nullptr, &type, (LPBYTE)&path, &size);
   1.197 +    ::RegCloseKey(key);
   1.198 +    // The call to RegQueryValueExW must succeed, the type must be REG_SZ, the
   1.199 +    // buffer size must not equal 0, and the buffer size be a multiple of 2.
   1.200 +    if (res != ERROR_SUCCESS || type != REG_SZ || size == 0 || size % 2 != 0)
   1.201 +        return NS_ERROR_FAILURE;
   1.202 +
   1.203 +    // Append the trailing slash
   1.204 +    int len = wcslen(path);
   1.205 +    if (len > 1 && path[len - 1] != L'\\')
   1.206 +    {
   1.207 +        path[len]   = L'\\';
   1.208 +        path[++len] = L'\0';
   1.209 +    }
   1.210 +
   1.211 +    return NS_NewLocalFile(nsDependentString(path, len), true, aFile);
   1.212 +}
   1.213 +
   1.214 +#endif // XP_WIN
   1.215 +
   1.216 +#if defined(XP_UNIX)
   1.217 +static nsresult
   1.218 +GetUnixHomeDir(nsIFile** aFile)
   1.219 +{
   1.220 +#ifdef VMS
   1.221 +    char *pHome;
   1.222 +    pHome = getenv("HOME");
   1.223 +    if (*pHome == '/') {
   1.224 +        return NS_NewNativeLocalFile(nsDependentCString(pHome),
   1.225 +                                     true,
   1.226 +                                     aFile);
   1.227 +    } else {
   1.228 +        return NS_NewNativeLocalFile(nsDependentCString(decc$translate_vms(pHome)),
   1.229 +                                     true,
   1.230 +                                     aFile);
   1.231 +    }
   1.232 +#elif defined(ANDROID)
   1.233 +    // XXX no home dir on android; maybe we should return the sdcard if present?
   1.234 +    return NS_ERROR_FAILURE;
   1.235 +#else
   1.236 +    return NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")),
   1.237 +                                 true, aFile);
   1.238 +#endif
   1.239 +}
   1.240 +
   1.241 +/*
   1.242 +  The following license applies to the xdg_user_dir_lookup function:
   1.243 +
   1.244 +  Copyright (c) 2007 Red Hat, Inc.
   1.245 +
   1.246 +  Permission is hereby granted, free of charge, to any person
   1.247 +  obtaining a copy of this software and associated documentation files
   1.248 +  (the "Software"), to deal in the Software without restriction,
   1.249 +  including without limitation the rights to use, copy, modify, merge,
   1.250 +  publish, distribute, sublicense, and/or sell copies of the Software,
   1.251 +  and to permit persons to whom the Software is furnished to do so,
   1.252 +  subject to the following conditions:
   1.253 +
   1.254 +  The above copyright notice and this permission notice shall be
   1.255 +  included in all copies or substantial portions of the Software.
   1.256 +
   1.257 +  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   1.258 +  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   1.259 +  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   1.260 +  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
   1.261 +  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   1.262 +  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   1.263 +  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   1.264 +  SOFTWARE.
   1.265 +*/
   1.266 +
   1.267 +static char *
   1.268 +xdg_user_dir_lookup (const char *type)
   1.269 +{
   1.270 +  FILE *file;
   1.271 +  char *home_dir, *config_home, *config_file;
   1.272 +  char buffer[512];
   1.273 +  char *user_dir;
   1.274 +  char *p, *d;
   1.275 +  int len;
   1.276 +  int relative;
   1.277 +
   1.278 +  home_dir = getenv ("HOME");
   1.279 +
   1.280 +  if (home_dir == nullptr)
   1.281 +    goto error;
   1.282 +
   1.283 +  config_home = getenv ("XDG_CONFIG_HOME");
   1.284 +  if (config_home == nullptr || config_home[0] == 0)
   1.285 +    {
   1.286 +      config_file = (char*) malloc (strlen (home_dir) + strlen ("/.config/user-dirs.dirs") + 1);
   1.287 +      if (config_file == nullptr)
   1.288 +        goto error;
   1.289 +
   1.290 +      strcpy (config_file, home_dir);
   1.291 +      strcat (config_file, "/.config/user-dirs.dirs");
   1.292 +    }
   1.293 +  else
   1.294 +    {
   1.295 +      config_file = (char*) malloc (strlen (config_home) + strlen ("/user-dirs.dirs") + 1);
   1.296 +      if (config_file == nullptr)
   1.297 +        goto error;
   1.298 +
   1.299 +      strcpy (config_file, config_home);
   1.300 +      strcat (config_file, "/user-dirs.dirs");
   1.301 +    }
   1.302 +
   1.303 +  file = fopen (config_file, "r");
   1.304 +  free (config_file);
   1.305 +  if (file == nullptr)
   1.306 +    goto error;
   1.307 +
   1.308 +  user_dir = nullptr;
   1.309 +  while (fgets (buffer, sizeof (buffer), file))
   1.310 +    {
   1.311 +      /* Remove newline at end */
   1.312 +      len = strlen (buffer);
   1.313 +      if (len > 0 && buffer[len-1] == '\n')
   1.314 +	buffer[len-1] = 0;
   1.315 +
   1.316 +      p = buffer;
   1.317 +      while (*p == ' ' || *p == '\t')
   1.318 +	p++;
   1.319 +
   1.320 +      if (strncmp (p, "XDG_", 4) != 0)
   1.321 +	continue;
   1.322 +      p += 4;
   1.323 +      if (strncmp (p, type, strlen (type)) != 0)
   1.324 +	continue;
   1.325 +      p += strlen (type);
   1.326 +      if (strncmp (p, "_DIR", 4) != 0)
   1.327 +	continue;
   1.328 +      p += 4;
   1.329 +
   1.330 +      while (*p == ' ' || *p == '\t')
   1.331 +	p++;
   1.332 +
   1.333 +      if (*p != '=')
   1.334 +	continue;
   1.335 +      p++;
   1.336 +
   1.337 +      while (*p == ' ' || *p == '\t')
   1.338 +	p++;
   1.339 +
   1.340 +      if (*p != '"')
   1.341 +	continue;
   1.342 +      p++;
   1.343 +
   1.344 +      relative = 0;
   1.345 +      if (strncmp (p, "$HOME/", 6) == 0)
   1.346 +	{
   1.347 +	  p += 6;
   1.348 +	  relative = 1;
   1.349 +	}
   1.350 +      else if (*p != '/')
   1.351 +	continue;
   1.352 +
   1.353 +      if (relative)
   1.354 +	{
   1.355 +	  user_dir = (char*) malloc (strlen (home_dir) + 1 + strlen (p) + 1);
   1.356 +          if (user_dir == nullptr)
   1.357 +            goto error2;
   1.358 +
   1.359 +	  strcpy (user_dir, home_dir);
   1.360 +	  strcat (user_dir, "/");
   1.361 +	}
   1.362 +      else
   1.363 +	{
   1.364 +	  user_dir = (char*) malloc (strlen (p) + 1);
   1.365 +          if (user_dir == nullptr)
   1.366 +            goto error2;
   1.367 +
   1.368 +	  *user_dir = 0;
   1.369 +	}
   1.370 +
   1.371 +      d = user_dir + strlen (user_dir);
   1.372 +      while (*p && *p != '"')
   1.373 +	{
   1.374 +	  if ((*p == '\\') && (*(p+1) != 0))
   1.375 +	    p++;
   1.376 +	  *d++ = *p++;
   1.377 +	}
   1.378 +      *d = 0;
   1.379 +    }
   1.380 +error2:
   1.381 +  fclose (file);
   1.382 +
   1.383 +  if (user_dir)
   1.384 +    return user_dir;
   1.385 +
   1.386 + error:
   1.387 +  return nullptr;
   1.388 +}
   1.389 +
   1.390 +static const char xdg_user_dirs[] =
   1.391 +    "DESKTOP\0"
   1.392 +    "DOCUMENTS\0"
   1.393 +    "DOWNLOAD\0"
   1.394 +    "MUSIC\0"
   1.395 +    "PICTURES\0"
   1.396 +    "PUBLICSHARE\0"
   1.397 +    "TEMPLATES\0"
   1.398 +    "VIDEOS";
   1.399 +
   1.400 +static const uint8_t xdg_user_dir_offsets[] = {
   1.401 +    0,
   1.402 +    8,
   1.403 +    18,
   1.404 +    27,
   1.405 +    33,
   1.406 +    42,
   1.407 +    54,
   1.408 +    64
   1.409 +};
   1.410 +
   1.411 +static nsresult
   1.412 +GetUnixXDGUserDirectory(SystemDirectories aSystemDirectory,
   1.413 +                        nsIFile** aFile)
   1.414 +{
   1.415 +    char *dir = xdg_user_dir_lookup
   1.416 +                    (xdg_user_dirs + xdg_user_dir_offsets[aSystemDirectory -
   1.417 +                                                         Unix_XDG_Desktop]);
   1.418 +
   1.419 +    nsresult rv;
   1.420 +    nsCOMPtr<nsIFile> file;
   1.421 +    if (dir) {
   1.422 +        rv = NS_NewNativeLocalFile(nsDependentCString(dir), true,
   1.423 +                                   getter_AddRefs(file));
   1.424 +        free(dir);
   1.425 +    } else if (Unix_XDG_Desktop == aSystemDirectory) {
   1.426 +        // for the XDG desktop dir, fall back to HOME/Desktop
   1.427 +        // (for historical compatibility)
   1.428 +        rv = GetUnixHomeDir(getter_AddRefs(file));
   1.429 +        if (NS_FAILED(rv))
   1.430 +            return rv;
   1.431 +
   1.432 +        rv = file->AppendNative(NS_LITERAL_CSTRING("Desktop"));
   1.433 +    }
   1.434 +    else {
   1.435 +      // no fallback for the other XDG dirs
   1.436 +      rv = NS_ERROR_FAILURE;
   1.437 +    }
   1.438 +
   1.439 +    if (NS_FAILED(rv))
   1.440 +        return rv;
   1.441 +
   1.442 +    bool exists;
   1.443 +    rv = file->Exists(&exists);
   1.444 +    if (NS_FAILED(rv))
   1.445 +        return rv;
   1.446 +    if (!exists) {
   1.447 +        rv = file->Create(nsIFile::DIRECTORY_TYPE, 0755);
   1.448 +        if (NS_FAILED(rv))
   1.449 +            return rv;
   1.450 +    }
   1.451 +
   1.452 +    *aFile = nullptr;
   1.453 +    file.swap(*aFile);
   1.454 +
   1.455 +    return NS_OK;
   1.456 +}
   1.457 +#endif
   1.458 +
   1.459 +nsresult
   1.460 +GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory,
   1.461 +                          nsIFile** aFile)
   1.462 +{
   1.463 +#if defined(XP_WIN)
   1.464 +    WCHAR path[MAX_PATH];
   1.465 +#else
   1.466 +    char path[MAXPATHLEN];
   1.467 +#endif
   1.468 +
   1.469 +    switch (aSystemSystemDirectory)
   1.470 +    {
   1.471 +        case OS_CurrentWorkingDirectory:
   1.472 +#if defined(XP_WIN)
   1.473 +            if (!_wgetcwd(path, MAX_PATH))
   1.474 +                return NS_ERROR_FAILURE;
   1.475 +            return NS_NewLocalFile(nsDependentString(path),
   1.476 +                                   true,
   1.477 +                                   aFile);
   1.478 +#else
   1.479 +            if(!getcwd(path, MAXPATHLEN))
   1.480 +                return NS_ERROR_FAILURE;
   1.481 +#endif
   1.482 +
   1.483 +#if !defined(XP_WIN)
   1.484 +            return NS_NewNativeLocalFile(nsDependentCString(path),
   1.485 +                                         true,
   1.486 +                                         aFile);
   1.487 +#endif
   1.488 +
   1.489 +        case OS_DriveDirectory:
   1.490 +#if defined (XP_WIN)
   1.491 +        {
   1.492 +            int32_t len = ::GetWindowsDirectoryW(path, MAX_PATH);
   1.493 +            if (len == 0)
   1.494 +                break;
   1.495 +            if (path[1] == char16_t(':') && path[2] == char16_t('\\'))
   1.496 +                path[3] = 0;
   1.497 +
   1.498 +            return NS_NewLocalFile(nsDependentString(path),
   1.499 +                                   true,
   1.500 +                                   aFile);
   1.501 +        }
   1.502 +#else
   1.503 +        return NS_NewNativeLocalFile(nsDependentCString("/"),
   1.504 +                                     true,
   1.505 +                                     aFile);
   1.506 +
   1.507 +#endif
   1.508 +
   1.509 +        case OS_TemporaryDirectory:
   1.510 +#if defined (XP_WIN)
   1.511 +            {
   1.512 +            DWORD len = ::GetTempPathW(MAX_PATH, path);
   1.513 +            if (len == 0)
   1.514 +                break;
   1.515 +            return NS_NewLocalFile(nsDependentString(path, len),
   1.516 +                                   true,
   1.517 +                                   aFile);
   1.518 +        }
   1.519 +#elif defined(MOZ_WIDGET_COCOA)
   1.520 +        {
   1.521 +            return GetOSXFolderType(kUserDomain, kTemporaryFolderType, aFile);
   1.522 +        }
   1.523 +
   1.524 +#elif defined(XP_UNIX)
   1.525 +        {
   1.526 +            static const char *tPath = nullptr;
   1.527 +            if (!tPath) {
   1.528 +                tPath = PR_GetEnv("TMPDIR");
   1.529 +                if (!tPath || !*tPath) {
   1.530 +                    tPath = PR_GetEnv("TMP");
   1.531 +                    if (!tPath || !*tPath) {
   1.532 +                        tPath = PR_GetEnv("TEMP");
   1.533 +                        if (!tPath || !*tPath) {
   1.534 +                            tPath = "/tmp/";
   1.535 +                        }
   1.536 +                    }
   1.537 +                }
   1.538 +            }
   1.539 +            return NS_NewNativeLocalFile(nsDependentCString(tPath),
   1.540 +                                         true,
   1.541 +                                         aFile);
   1.542 +        }
   1.543 +#else
   1.544 +        break;
   1.545 +#endif
   1.546 +#if defined (XP_WIN)
   1.547 +        case Win_SystemDirectory:
   1.548 +        {
   1.549 +            int32_t len = ::GetSystemDirectoryW(path, MAX_PATH);
   1.550 +
   1.551 +            // Need enough space to add the trailing backslash
   1.552 +            if (!len || len > MAX_PATH - 2)
   1.553 +                break;
   1.554 +            path[len]   = L'\\';
   1.555 +            path[++len] = L'\0';
   1.556 +
   1.557 +            return NS_NewLocalFile(nsDependentString(path, len),
   1.558 +                                   true,
   1.559 +                                   aFile);
   1.560 +        }
   1.561 +
   1.562 +        case Win_WindowsDirectory:
   1.563 +        {
   1.564 +            int32_t len = ::GetWindowsDirectoryW(path, MAX_PATH);
   1.565 +
   1.566 +            // Need enough space to add the trailing backslash
   1.567 +            if (!len || len > MAX_PATH - 2)
   1.568 +                break;
   1.569 +
   1.570 +            path[len]   = L'\\';
   1.571 +            path[++len] = L'\0';
   1.572 +
   1.573 +            return NS_NewLocalFile(nsDependentString(path, len),
   1.574 +                                   true,
   1.575 +                                   aFile);
   1.576 +        }
   1.577 +
   1.578 +        case Win_ProgramFiles:
   1.579 +        {
   1.580 +            return GetWindowsFolder(CSIDL_PROGRAM_FILES, aFile);
   1.581 +        }
   1.582 +
   1.583 +        case Win_HomeDirectory:
   1.584 +        {
   1.585 +            nsresult rv = GetWindowsFolder(CSIDL_PROFILE, aFile);
   1.586 +            if (NS_SUCCEEDED(rv))
   1.587 +                return rv;
   1.588 +
   1.589 +            int32_t len;
   1.590 +            if ((len = ::GetEnvironmentVariableW(L"HOME", path, MAX_PATH)) > 0)
   1.591 +            {
   1.592 +                // Need enough space to add the trailing backslash
   1.593 +                if (len > MAX_PATH - 2)
   1.594 +                    break;
   1.595 +
   1.596 +                path[len]   = L'\\';
   1.597 +                path[++len] = L'\0';
   1.598 +
   1.599 +                rv = NS_NewLocalFile(nsDependentString(path, len),
   1.600 +                                     true,
   1.601 +                                     aFile);
   1.602 +                if (NS_SUCCEEDED(rv))
   1.603 +                    return rv;
   1.604 +            }
   1.605 +
   1.606 +            len = ::GetEnvironmentVariableW(L"HOMEDRIVE", path, MAX_PATH);
   1.607 +            if (0 < len && len < MAX_PATH)
   1.608 +            {
   1.609 +                WCHAR temp[MAX_PATH];
   1.610 +                DWORD len2 = ::GetEnvironmentVariableW(L"HOMEPATH", temp, MAX_PATH);
   1.611 +                if (0 < len2 && len + len2 < MAX_PATH)
   1.612 +                    wcsncat(path, temp, len2);
   1.613 +
   1.614 +                len = wcslen(path);
   1.615 +
   1.616 +                // Need enough space to add the trailing backslash
   1.617 +                if (len > MAX_PATH - 2)
   1.618 +                    break;
   1.619 +
   1.620 +                path[len]   = L'\\';
   1.621 +                path[++len] = L'\0';
   1.622 +
   1.623 +                return NS_NewLocalFile(nsDependentString(path, len),
   1.624 +                                       true,
   1.625 +                                       aFile);
   1.626 +            }
   1.627 +        }
   1.628 +        case Win_Desktop:
   1.629 +        {
   1.630 +            return GetWindowsFolder(CSIDL_DESKTOP, aFile);
   1.631 +        }
   1.632 +        case Win_Programs:
   1.633 +        {
   1.634 +            return GetWindowsFolder(CSIDL_PROGRAMS, aFile);
   1.635 +        }
   1.636 +
   1.637 +        case Win_Downloads:
   1.638 +        {
   1.639 +            // Defined in KnownFolders.h.
   1.640 +            GUID folderid_downloads = {0x374de290, 0x123f, 0x4565, {0x91, 0x64,
   1.641 +                                       0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b}};
   1.642 +            nsresult rv = GetKnownFolder(&folderid_downloads, aFile);
   1.643 +            // On WinXP, there is no downloads folder, default
   1.644 +            // to 'Desktop'.
   1.645 +            if(NS_ERROR_FAILURE == rv)
   1.646 +            {
   1.647 +              rv = GetWindowsFolder(CSIDL_DESKTOP, aFile);
   1.648 +            }
   1.649 +            return rv;
   1.650 +        }
   1.651 +
   1.652 +        case Win_Controls:
   1.653 +        {
   1.654 +            return GetWindowsFolder(CSIDL_CONTROLS, aFile);
   1.655 +        }
   1.656 +        case Win_Printers:
   1.657 +        {
   1.658 +            return GetWindowsFolder(CSIDL_PRINTERS, aFile);
   1.659 +        }
   1.660 +        case Win_Personal:
   1.661 +        {
   1.662 +            return GetWindowsFolder(CSIDL_PERSONAL, aFile);
   1.663 +        }
   1.664 +        case Win_Favorites:
   1.665 +        {
   1.666 +            return GetWindowsFolder(CSIDL_FAVORITES, aFile);
   1.667 +        }
   1.668 +        case Win_Startup:
   1.669 +        {
   1.670 +            return GetWindowsFolder(CSIDL_STARTUP, aFile);
   1.671 +        }
   1.672 +        case Win_Recent:
   1.673 +        {
   1.674 +            return GetWindowsFolder(CSIDL_RECENT, aFile);
   1.675 +        }
   1.676 +        case Win_Sendto:
   1.677 +        {
   1.678 +            return GetWindowsFolder(CSIDL_SENDTO, aFile);
   1.679 +        }
   1.680 +        case Win_Bitbucket:
   1.681 +        {
   1.682 +            return GetWindowsFolder(CSIDL_BITBUCKET, aFile);
   1.683 +        }
   1.684 +        case Win_Startmenu:
   1.685 +        {
   1.686 +            return GetWindowsFolder(CSIDL_STARTMENU, aFile);
   1.687 +        }
   1.688 +        case Win_Desktopdirectory:
   1.689 +        {
   1.690 +            return GetWindowsFolder(CSIDL_DESKTOPDIRECTORY, aFile);
   1.691 +        }
   1.692 +        case Win_Drives:
   1.693 +        {
   1.694 +            return GetWindowsFolder(CSIDL_DRIVES, aFile);
   1.695 +        }
   1.696 +        case Win_Network:
   1.697 +        {
   1.698 +            return GetWindowsFolder(CSIDL_NETWORK, aFile);
   1.699 +        }
   1.700 +        case Win_Nethood:
   1.701 +        {
   1.702 +            return GetWindowsFolder(CSIDL_NETHOOD, aFile);
   1.703 +        }
   1.704 +        case Win_Fonts:
   1.705 +        {
   1.706 +            return GetWindowsFolder(CSIDL_FONTS, aFile);
   1.707 +        }
   1.708 +        case Win_Templates:
   1.709 +        {
   1.710 +            return GetWindowsFolder(CSIDL_TEMPLATES, aFile);
   1.711 +        }
   1.712 +        case Win_Common_Startmenu:
   1.713 +        {
   1.714 +            return GetWindowsFolder(CSIDL_COMMON_STARTMENU, aFile);
   1.715 +        }
   1.716 +        case Win_Common_Programs:
   1.717 +        {
   1.718 +            return GetWindowsFolder(CSIDL_COMMON_PROGRAMS, aFile);
   1.719 +        }
   1.720 +        case Win_Common_Startup:
   1.721 +        {
   1.722 +            return GetWindowsFolder(CSIDL_COMMON_STARTUP, aFile);
   1.723 +        }
   1.724 +        case Win_Common_Desktopdirectory:
   1.725 +        {
   1.726 +            return GetWindowsFolder(CSIDL_COMMON_DESKTOPDIRECTORY, aFile);
   1.727 +        }
   1.728 +        case Win_Common_AppData:
   1.729 +        {
   1.730 +            return GetWindowsFolder(CSIDL_COMMON_APPDATA, aFile);
   1.731 +        }
   1.732 +        case Win_Printhood:
   1.733 +        {
   1.734 +            return GetWindowsFolder(CSIDL_PRINTHOOD, aFile);
   1.735 +        }
   1.736 +        case Win_Cookies:
   1.737 +        {
   1.738 +            return GetWindowsFolder(CSIDL_COOKIES, aFile);
   1.739 +        }
   1.740 +        case Win_Appdata:
   1.741 +        {
   1.742 +            nsresult rv = GetWindowsFolder(CSIDL_APPDATA, aFile);
   1.743 +            if (NS_FAILED(rv))
   1.744 +                rv = GetRegWindowsAppDataFolder(false, aFile);
   1.745 +            return rv;
   1.746 +        }
   1.747 +        case Win_LocalAppdata:
   1.748 +        {
   1.749 +            nsresult rv = GetWindowsFolder(CSIDL_LOCAL_APPDATA, aFile);
   1.750 +            if (NS_FAILED(rv))
   1.751 +                rv = GetRegWindowsAppDataFolder(true, aFile);
   1.752 +            return rv;
   1.753 +        }
   1.754 +        case Win_Documents:
   1.755 +        {
   1.756 +            return GetLibrarySaveToPath(CSIDL_MYDOCUMENTS,
   1.757 +                                        FOLDERID_DocumentsLibrary,
   1.758 +                                        aFile);
   1.759 +        }
   1.760 +        case Win_Pictures:
   1.761 +        {
   1.762 +            return GetLibrarySaveToPath(CSIDL_MYPICTURES,
   1.763 +                                        FOLDERID_PicturesLibrary,
   1.764 +                                        aFile);
   1.765 +        }
   1.766 +        case Win_Music:
   1.767 +        {
   1.768 +            return GetLibrarySaveToPath(CSIDL_MYMUSIC,
   1.769 +                                        FOLDERID_MusicLibrary,
   1.770 +                                        aFile);
   1.771 +        }
   1.772 +        case Win_Videos:
   1.773 +        {
   1.774 +            return GetLibrarySaveToPath(CSIDL_MYVIDEO,
   1.775 +                                        FOLDERID_VideosLibrary,
   1.776 +                                        aFile);
   1.777 +        }
   1.778 +#endif  // XP_WIN
   1.779 +
   1.780 +#if defined(XP_UNIX)
   1.781 +        case Unix_LocalDirectory:
   1.782 +            return NS_NewNativeLocalFile(nsDependentCString("/usr/local/netscape/"),
   1.783 +                                         true,
   1.784 +                                         aFile);
   1.785 +        case Unix_LibDirectory:
   1.786 +            return NS_NewNativeLocalFile(nsDependentCString("/usr/local/lib/netscape/"),
   1.787 +                                         true,
   1.788 +                                         aFile);
   1.789 +
   1.790 +        case Unix_HomeDirectory:
   1.791 +            return GetUnixHomeDir(aFile);
   1.792 +
   1.793 +        case Unix_XDG_Desktop:
   1.794 +        case Unix_XDG_Documents:
   1.795 +        case Unix_XDG_Download:
   1.796 +        case Unix_XDG_Music:
   1.797 +        case Unix_XDG_Pictures:
   1.798 +        case Unix_XDG_PublicShare:
   1.799 +        case Unix_XDG_Templates:
   1.800 +        case Unix_XDG_Videos:
   1.801 +            return GetUnixXDGUserDirectory(aSystemSystemDirectory, aFile);
   1.802 +#endif
   1.803 +
   1.804 +        default:
   1.805 +            break;
   1.806 +    }
   1.807 +    return NS_ERROR_NOT_AVAILABLE;
   1.808 +}
   1.809 +
   1.810 +#if defined (MOZ_WIDGET_COCOA)
   1.811 +nsresult
   1.812 +GetOSXFolderType(short aDomain, OSType aFolderType, nsIFile **localFile)
   1.813 +{
   1.814 +    OSErr err;
   1.815 +    FSRef fsRef;
   1.816 +    nsresult rv = NS_ERROR_FAILURE;
   1.817 +
   1.818 +    err = ::FSFindFolder(aDomain, aFolderType, kCreateFolder, &fsRef);
   1.819 +    if (err == noErr)
   1.820 +    {
   1.821 +        NS_NewLocalFile(EmptyString(), true, localFile);
   1.822 +        nsCOMPtr<nsILocalFileMac> localMacFile(do_QueryInterface(*localFile));
   1.823 +        if (localMacFile)
   1.824 +            rv = localMacFile->InitWithFSRef(&fsRef);
   1.825 +    }
   1.826 +    return rv;
   1.827 +}
   1.828 +#endif
   1.829 +

mercurial