xpcom/io/SpecialSystemDirectory.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "SpecialSystemDirectory.h"
michael@0 7 #include "nsString.h"
michael@0 8 #include "nsDependentString.h"
michael@0 9 #include "nsAutoPtr.h"
michael@0 10
michael@0 11 #if defined(XP_WIN)
michael@0 12
michael@0 13 #include <windows.h>
michael@0 14 #include <shlobj.h>
michael@0 15 #include <stdlib.h>
michael@0 16 #include <stdio.h>
michael@0 17 #include <string.h>
michael@0 18 #include <direct.h>
michael@0 19 #include <shlobj.h>
michael@0 20 #include <knownfolders.h>
michael@0 21 #include <guiddef.h>
michael@0 22 #include "mozilla/WindowsVersion.h"
michael@0 23
michael@0 24 using mozilla::IsWin7OrLater;
michael@0 25
michael@0 26 #elif defined(XP_UNIX)
michael@0 27
michael@0 28 #include <limits.h>
michael@0 29 #include <unistd.h>
michael@0 30 #include <stdlib.h>
michael@0 31 #include <sys/param.h>
michael@0 32 #include "prenv.h"
michael@0 33
michael@0 34 #endif
michael@0 35
michael@0 36 #if defined(VMS)
michael@0 37 #include <unixlib.h>
michael@0 38 #endif
michael@0 39
michael@0 40 #ifndef MAXPATHLEN
michael@0 41 #ifdef PATH_MAX
michael@0 42 #define MAXPATHLEN PATH_MAX
michael@0 43 #elif defined(MAX_PATH)
michael@0 44 #define MAXPATHLEN MAX_PATH
michael@0 45 #elif defined(_MAX_PATH)
michael@0 46 #define MAXPATHLEN _MAX_PATH
michael@0 47 #elif defined(CCHMAXPATH)
michael@0 48 #define MAXPATHLEN CCHMAXPATH
michael@0 49 #else
michael@0 50 #define MAXPATHLEN 1024
michael@0 51 #endif
michael@0 52 #endif
michael@0 53
michael@0 54 #ifdef XP_WIN
michael@0 55 typedef HRESULT (WINAPI* nsGetKnownFolderPath)(GUID& rfid,
michael@0 56 DWORD dwFlags,
michael@0 57 HANDLE hToken,
michael@0 58 PWSTR *ppszPath);
michael@0 59
michael@0 60 static nsGetKnownFolderPath gGetKnownFolderPath = nullptr;
michael@0 61 #endif
michael@0 62
michael@0 63 void StartupSpecialSystemDirectory()
michael@0 64 {
michael@0 65 #if defined (XP_WIN)
michael@0 66 // SHGetKnownFolderPath is only available on Windows Vista
michael@0 67 // so that we need to use GetProcAddress to get the pointer.
michael@0 68 HMODULE hShell32DLLInst = GetModuleHandleW(L"shell32.dll");
michael@0 69 if(hShell32DLLInst)
michael@0 70 {
michael@0 71 gGetKnownFolderPath = (nsGetKnownFolderPath)
michael@0 72 GetProcAddress(hShell32DLLInst, "SHGetKnownFolderPath");
michael@0 73 }
michael@0 74 #endif
michael@0 75 }
michael@0 76
michael@0 77 #if defined (XP_WIN)
michael@0 78
michael@0 79 static nsresult GetKnownFolder(GUID* guid, nsIFile** aFile)
michael@0 80 {
michael@0 81 if (!guid || !gGetKnownFolderPath)
michael@0 82 return NS_ERROR_FAILURE;
michael@0 83
michael@0 84 PWSTR path = nullptr;
michael@0 85 gGetKnownFolderPath(*guid, 0, nullptr, &path);
michael@0 86
michael@0 87 if (!path)
michael@0 88 return NS_ERROR_FAILURE;
michael@0 89
michael@0 90 nsresult rv = NS_NewLocalFile(nsDependentString(path),
michael@0 91 true,
michael@0 92 aFile);
michael@0 93
michael@0 94 CoTaskMemFree(path);
michael@0 95 return rv;
michael@0 96 }
michael@0 97
michael@0 98 static nsresult
michael@0 99 GetWindowsFolder(int folder, nsIFile** aFile)
michael@0 100 {
michael@0 101 WCHAR path_orig[MAX_PATH + 3];
michael@0 102 WCHAR *path = path_orig+1;
michael@0 103 HRESULT result = SHGetSpecialFolderPathW(nullptr, path, folder, true);
michael@0 104
michael@0 105 if (!SUCCEEDED(result))
michael@0 106 return NS_ERROR_FAILURE;
michael@0 107
michael@0 108 // Append the trailing slash
michael@0 109 int len = wcslen(path);
michael@0 110 if (len > 1 && path[len - 1] != L'\\')
michael@0 111 {
michael@0 112 path[len] = L'\\';
michael@0 113 path[++len] = L'\0';
michael@0 114 }
michael@0 115
michael@0 116 return NS_NewLocalFile(nsDependentString(path, len), true, aFile);
michael@0 117 }
michael@0 118
michael@0 119 __inline HRESULT
michael@0 120 SHLoadLibraryFromKnownFolder(REFKNOWNFOLDERID aFolderId, DWORD aMode,
michael@0 121 REFIID riid, void **ppv)
michael@0 122 {
michael@0 123 *ppv = nullptr;
michael@0 124 IShellLibrary *plib;
michael@0 125 HRESULT hr = CoCreateInstance(CLSID_ShellLibrary, nullptr,
michael@0 126 CLSCTX_INPROC_SERVER,
michael@0 127 IID_PPV_ARGS(&plib));
michael@0 128 if (SUCCEEDED(hr)) {
michael@0 129 hr = plib->LoadLibraryFromKnownFolder(aFolderId, aMode);
michael@0 130 if (SUCCEEDED(hr)) {
michael@0 131 hr = plib->QueryInterface(riid, ppv);
michael@0 132 }
michael@0 133 plib->Release();
michael@0 134 }
michael@0 135 return hr;
michael@0 136 }
michael@0 137
michael@0 138 /*
michael@0 139 * Check to see if we're on Win7 and up, and if so, returns the default
michael@0 140 * save-to location for the Windows Library passed in through aFolderId.
michael@0 141 * Otherwise falls back on pre-win7 GetWindowsFolder.
michael@0 142 */
michael@0 143 static nsresult
michael@0 144 GetLibrarySaveToPath(int aFallbackFolderId, REFKNOWNFOLDERID aFolderId,
michael@0 145 nsIFile** aFile)
michael@0 146 {
michael@0 147 // Skip off checking for library support if the os is Vista or lower.
michael@0 148 if (!IsWin7OrLater())
michael@0 149 return GetWindowsFolder(aFallbackFolderId, aFile);
michael@0 150
michael@0 151 nsRefPtr<IShellLibrary> shellLib;
michael@0 152 nsRefPtr<IShellItem> savePath;
michael@0 153 HRESULT hr =
michael@0 154 SHLoadLibraryFromKnownFolder(aFolderId, STGM_READ,
michael@0 155 IID_IShellLibrary, getter_AddRefs(shellLib));
michael@0 156
michael@0 157 if (shellLib &&
michael@0 158 SUCCEEDED(shellLib->GetDefaultSaveFolder(DSFT_DETECT, IID_IShellItem,
michael@0 159 getter_AddRefs(savePath)))) {
michael@0 160 wchar_t* str = nullptr;
michael@0 161 if (SUCCEEDED(savePath->GetDisplayName(SIGDN_FILESYSPATH, &str))) {
michael@0 162 nsAutoString path;
michael@0 163 path.Assign(str);
michael@0 164 path.AppendLiteral("\\");
michael@0 165 nsresult rv =
michael@0 166 NS_NewLocalFile(path, false, aFile);
michael@0 167 CoTaskMemFree(str);
michael@0 168 return rv;
michael@0 169 }
michael@0 170 }
michael@0 171
michael@0 172 return GetWindowsFolder(aFallbackFolderId, aFile);
michael@0 173 }
michael@0 174
michael@0 175 /**
michael@0 176 * Provides a fallback for getting the path to APPDATA or LOCALAPPDATA by
michael@0 177 * querying the registry when the call to SHGetSpecialFolderPathW is unable to
michael@0 178 * provide these paths (Bug 513958).
michael@0 179 */
michael@0 180 static nsresult GetRegWindowsAppDataFolder(bool aLocal, nsIFile** aFile)
michael@0 181 {
michael@0 182 HKEY key;
michael@0 183 NS_NAMED_LITERAL_STRING(keyName,
michael@0 184 "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
michael@0 185 DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName.get(), 0, KEY_READ,
michael@0 186 &key);
michael@0 187 if (res != ERROR_SUCCESS)
michael@0 188 return NS_ERROR_FAILURE;
michael@0 189
michael@0 190 WCHAR path[MAX_PATH + 2];
michael@0 191 DWORD type, size;
michael@0 192 res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"),
michael@0 193 nullptr, &type, (LPBYTE)&path, &size);
michael@0 194 ::RegCloseKey(key);
michael@0 195 // The call to RegQueryValueExW must succeed, the type must be REG_SZ, the
michael@0 196 // buffer size must not equal 0, and the buffer size be a multiple of 2.
michael@0 197 if (res != ERROR_SUCCESS || type != REG_SZ || size == 0 || size % 2 != 0)
michael@0 198 return NS_ERROR_FAILURE;
michael@0 199
michael@0 200 // Append the trailing slash
michael@0 201 int len = wcslen(path);
michael@0 202 if (len > 1 && path[len - 1] != L'\\')
michael@0 203 {
michael@0 204 path[len] = L'\\';
michael@0 205 path[++len] = L'\0';
michael@0 206 }
michael@0 207
michael@0 208 return NS_NewLocalFile(nsDependentString(path, len), true, aFile);
michael@0 209 }
michael@0 210
michael@0 211 #endif // XP_WIN
michael@0 212
michael@0 213 #if defined(XP_UNIX)
michael@0 214 static nsresult
michael@0 215 GetUnixHomeDir(nsIFile** aFile)
michael@0 216 {
michael@0 217 #ifdef VMS
michael@0 218 char *pHome;
michael@0 219 pHome = getenv("HOME");
michael@0 220 if (*pHome == '/') {
michael@0 221 return NS_NewNativeLocalFile(nsDependentCString(pHome),
michael@0 222 true,
michael@0 223 aFile);
michael@0 224 } else {
michael@0 225 return NS_NewNativeLocalFile(nsDependentCString(decc$translate_vms(pHome)),
michael@0 226 true,
michael@0 227 aFile);
michael@0 228 }
michael@0 229 #elif defined(ANDROID)
michael@0 230 // XXX no home dir on android; maybe we should return the sdcard if present?
michael@0 231 return NS_ERROR_FAILURE;
michael@0 232 #else
michael@0 233 return NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")),
michael@0 234 true, aFile);
michael@0 235 #endif
michael@0 236 }
michael@0 237
michael@0 238 /*
michael@0 239 The following license applies to the xdg_user_dir_lookup function:
michael@0 240
michael@0 241 Copyright (c) 2007 Red Hat, Inc.
michael@0 242
michael@0 243 Permission is hereby granted, free of charge, to any person
michael@0 244 obtaining a copy of this software and associated documentation files
michael@0 245 (the "Software"), to deal in the Software without restriction,
michael@0 246 including without limitation the rights to use, copy, modify, merge,
michael@0 247 publish, distribute, sublicense, and/or sell copies of the Software,
michael@0 248 and to permit persons to whom the Software is furnished to do so,
michael@0 249 subject to the following conditions:
michael@0 250
michael@0 251 The above copyright notice and this permission notice shall be
michael@0 252 included in all copies or substantial portions of the Software.
michael@0 253
michael@0 254 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
michael@0 255 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
michael@0 256 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
michael@0 257 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
michael@0 258 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
michael@0 259 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
michael@0 260 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
michael@0 261 SOFTWARE.
michael@0 262 */
michael@0 263
michael@0 264 static char *
michael@0 265 xdg_user_dir_lookup (const char *type)
michael@0 266 {
michael@0 267 FILE *file;
michael@0 268 char *home_dir, *config_home, *config_file;
michael@0 269 char buffer[512];
michael@0 270 char *user_dir;
michael@0 271 char *p, *d;
michael@0 272 int len;
michael@0 273 int relative;
michael@0 274
michael@0 275 home_dir = getenv ("HOME");
michael@0 276
michael@0 277 if (home_dir == nullptr)
michael@0 278 goto error;
michael@0 279
michael@0 280 config_home = getenv ("XDG_CONFIG_HOME");
michael@0 281 if (config_home == nullptr || config_home[0] == 0)
michael@0 282 {
michael@0 283 config_file = (char*) malloc (strlen (home_dir) + strlen ("/.config/user-dirs.dirs") + 1);
michael@0 284 if (config_file == nullptr)
michael@0 285 goto error;
michael@0 286
michael@0 287 strcpy (config_file, home_dir);
michael@0 288 strcat (config_file, "/.config/user-dirs.dirs");
michael@0 289 }
michael@0 290 else
michael@0 291 {
michael@0 292 config_file = (char*) malloc (strlen (config_home) + strlen ("/user-dirs.dirs") + 1);
michael@0 293 if (config_file == nullptr)
michael@0 294 goto error;
michael@0 295
michael@0 296 strcpy (config_file, config_home);
michael@0 297 strcat (config_file, "/user-dirs.dirs");
michael@0 298 }
michael@0 299
michael@0 300 file = fopen (config_file, "r");
michael@0 301 free (config_file);
michael@0 302 if (file == nullptr)
michael@0 303 goto error;
michael@0 304
michael@0 305 user_dir = nullptr;
michael@0 306 while (fgets (buffer, sizeof (buffer), file))
michael@0 307 {
michael@0 308 /* Remove newline at end */
michael@0 309 len = strlen (buffer);
michael@0 310 if (len > 0 && buffer[len-1] == '\n')
michael@0 311 buffer[len-1] = 0;
michael@0 312
michael@0 313 p = buffer;
michael@0 314 while (*p == ' ' || *p == '\t')
michael@0 315 p++;
michael@0 316
michael@0 317 if (strncmp (p, "XDG_", 4) != 0)
michael@0 318 continue;
michael@0 319 p += 4;
michael@0 320 if (strncmp (p, type, strlen (type)) != 0)
michael@0 321 continue;
michael@0 322 p += strlen (type);
michael@0 323 if (strncmp (p, "_DIR", 4) != 0)
michael@0 324 continue;
michael@0 325 p += 4;
michael@0 326
michael@0 327 while (*p == ' ' || *p == '\t')
michael@0 328 p++;
michael@0 329
michael@0 330 if (*p != '=')
michael@0 331 continue;
michael@0 332 p++;
michael@0 333
michael@0 334 while (*p == ' ' || *p == '\t')
michael@0 335 p++;
michael@0 336
michael@0 337 if (*p != '"')
michael@0 338 continue;
michael@0 339 p++;
michael@0 340
michael@0 341 relative = 0;
michael@0 342 if (strncmp (p, "$HOME/", 6) == 0)
michael@0 343 {
michael@0 344 p += 6;
michael@0 345 relative = 1;
michael@0 346 }
michael@0 347 else if (*p != '/')
michael@0 348 continue;
michael@0 349
michael@0 350 if (relative)
michael@0 351 {
michael@0 352 user_dir = (char*) malloc (strlen (home_dir) + 1 + strlen (p) + 1);
michael@0 353 if (user_dir == nullptr)
michael@0 354 goto error2;
michael@0 355
michael@0 356 strcpy (user_dir, home_dir);
michael@0 357 strcat (user_dir, "/");
michael@0 358 }
michael@0 359 else
michael@0 360 {
michael@0 361 user_dir = (char*) malloc (strlen (p) + 1);
michael@0 362 if (user_dir == nullptr)
michael@0 363 goto error2;
michael@0 364
michael@0 365 *user_dir = 0;
michael@0 366 }
michael@0 367
michael@0 368 d = user_dir + strlen (user_dir);
michael@0 369 while (*p && *p != '"')
michael@0 370 {
michael@0 371 if ((*p == '\\') && (*(p+1) != 0))
michael@0 372 p++;
michael@0 373 *d++ = *p++;
michael@0 374 }
michael@0 375 *d = 0;
michael@0 376 }
michael@0 377 error2:
michael@0 378 fclose (file);
michael@0 379
michael@0 380 if (user_dir)
michael@0 381 return user_dir;
michael@0 382
michael@0 383 error:
michael@0 384 return nullptr;
michael@0 385 }
michael@0 386
michael@0 387 static const char xdg_user_dirs[] =
michael@0 388 "DESKTOP\0"
michael@0 389 "DOCUMENTS\0"
michael@0 390 "DOWNLOAD\0"
michael@0 391 "MUSIC\0"
michael@0 392 "PICTURES\0"
michael@0 393 "PUBLICSHARE\0"
michael@0 394 "TEMPLATES\0"
michael@0 395 "VIDEOS";
michael@0 396
michael@0 397 static const uint8_t xdg_user_dir_offsets[] = {
michael@0 398 0,
michael@0 399 8,
michael@0 400 18,
michael@0 401 27,
michael@0 402 33,
michael@0 403 42,
michael@0 404 54,
michael@0 405 64
michael@0 406 };
michael@0 407
michael@0 408 static nsresult
michael@0 409 GetUnixXDGUserDirectory(SystemDirectories aSystemDirectory,
michael@0 410 nsIFile** aFile)
michael@0 411 {
michael@0 412 char *dir = xdg_user_dir_lookup
michael@0 413 (xdg_user_dirs + xdg_user_dir_offsets[aSystemDirectory -
michael@0 414 Unix_XDG_Desktop]);
michael@0 415
michael@0 416 nsresult rv;
michael@0 417 nsCOMPtr<nsIFile> file;
michael@0 418 if (dir) {
michael@0 419 rv = NS_NewNativeLocalFile(nsDependentCString(dir), true,
michael@0 420 getter_AddRefs(file));
michael@0 421 free(dir);
michael@0 422 } else if (Unix_XDG_Desktop == aSystemDirectory) {
michael@0 423 // for the XDG desktop dir, fall back to HOME/Desktop
michael@0 424 // (for historical compatibility)
michael@0 425 rv = GetUnixHomeDir(getter_AddRefs(file));
michael@0 426 if (NS_FAILED(rv))
michael@0 427 return rv;
michael@0 428
michael@0 429 rv = file->AppendNative(NS_LITERAL_CSTRING("Desktop"));
michael@0 430 }
michael@0 431 else {
michael@0 432 // no fallback for the other XDG dirs
michael@0 433 rv = NS_ERROR_FAILURE;
michael@0 434 }
michael@0 435
michael@0 436 if (NS_FAILED(rv))
michael@0 437 return rv;
michael@0 438
michael@0 439 bool exists;
michael@0 440 rv = file->Exists(&exists);
michael@0 441 if (NS_FAILED(rv))
michael@0 442 return rv;
michael@0 443 if (!exists) {
michael@0 444 rv = file->Create(nsIFile::DIRECTORY_TYPE, 0755);
michael@0 445 if (NS_FAILED(rv))
michael@0 446 return rv;
michael@0 447 }
michael@0 448
michael@0 449 *aFile = nullptr;
michael@0 450 file.swap(*aFile);
michael@0 451
michael@0 452 return NS_OK;
michael@0 453 }
michael@0 454 #endif
michael@0 455
michael@0 456 nsresult
michael@0 457 GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory,
michael@0 458 nsIFile** aFile)
michael@0 459 {
michael@0 460 #if defined(XP_WIN)
michael@0 461 WCHAR path[MAX_PATH];
michael@0 462 #else
michael@0 463 char path[MAXPATHLEN];
michael@0 464 #endif
michael@0 465
michael@0 466 switch (aSystemSystemDirectory)
michael@0 467 {
michael@0 468 case OS_CurrentWorkingDirectory:
michael@0 469 #if defined(XP_WIN)
michael@0 470 if (!_wgetcwd(path, MAX_PATH))
michael@0 471 return NS_ERROR_FAILURE;
michael@0 472 return NS_NewLocalFile(nsDependentString(path),
michael@0 473 true,
michael@0 474 aFile);
michael@0 475 #else
michael@0 476 if(!getcwd(path, MAXPATHLEN))
michael@0 477 return NS_ERROR_FAILURE;
michael@0 478 #endif
michael@0 479
michael@0 480 #if !defined(XP_WIN)
michael@0 481 return NS_NewNativeLocalFile(nsDependentCString(path),
michael@0 482 true,
michael@0 483 aFile);
michael@0 484 #endif
michael@0 485
michael@0 486 case OS_DriveDirectory:
michael@0 487 #if defined (XP_WIN)
michael@0 488 {
michael@0 489 int32_t len = ::GetWindowsDirectoryW(path, MAX_PATH);
michael@0 490 if (len == 0)
michael@0 491 break;
michael@0 492 if (path[1] == char16_t(':') && path[2] == char16_t('\\'))
michael@0 493 path[3] = 0;
michael@0 494
michael@0 495 return NS_NewLocalFile(nsDependentString(path),
michael@0 496 true,
michael@0 497 aFile);
michael@0 498 }
michael@0 499 #else
michael@0 500 return NS_NewNativeLocalFile(nsDependentCString("/"),
michael@0 501 true,
michael@0 502 aFile);
michael@0 503
michael@0 504 #endif
michael@0 505
michael@0 506 case OS_TemporaryDirectory:
michael@0 507 #if defined (XP_WIN)
michael@0 508 {
michael@0 509 DWORD len = ::GetTempPathW(MAX_PATH, path);
michael@0 510 if (len == 0)
michael@0 511 break;
michael@0 512 return NS_NewLocalFile(nsDependentString(path, len),
michael@0 513 true,
michael@0 514 aFile);
michael@0 515 }
michael@0 516 #elif defined(MOZ_WIDGET_COCOA)
michael@0 517 {
michael@0 518 return GetOSXFolderType(kUserDomain, kTemporaryFolderType, aFile);
michael@0 519 }
michael@0 520
michael@0 521 #elif defined(XP_UNIX)
michael@0 522 {
michael@0 523 static const char *tPath = nullptr;
michael@0 524 if (!tPath) {
michael@0 525 tPath = PR_GetEnv("TMPDIR");
michael@0 526 if (!tPath || !*tPath) {
michael@0 527 tPath = PR_GetEnv("TMP");
michael@0 528 if (!tPath || !*tPath) {
michael@0 529 tPath = PR_GetEnv("TEMP");
michael@0 530 if (!tPath || !*tPath) {
michael@0 531 tPath = "/tmp/";
michael@0 532 }
michael@0 533 }
michael@0 534 }
michael@0 535 }
michael@0 536 return NS_NewNativeLocalFile(nsDependentCString(tPath),
michael@0 537 true,
michael@0 538 aFile);
michael@0 539 }
michael@0 540 #else
michael@0 541 break;
michael@0 542 #endif
michael@0 543 #if defined (XP_WIN)
michael@0 544 case Win_SystemDirectory:
michael@0 545 {
michael@0 546 int32_t len = ::GetSystemDirectoryW(path, MAX_PATH);
michael@0 547
michael@0 548 // Need enough space to add the trailing backslash
michael@0 549 if (!len || len > MAX_PATH - 2)
michael@0 550 break;
michael@0 551 path[len] = L'\\';
michael@0 552 path[++len] = L'\0';
michael@0 553
michael@0 554 return NS_NewLocalFile(nsDependentString(path, len),
michael@0 555 true,
michael@0 556 aFile);
michael@0 557 }
michael@0 558
michael@0 559 case Win_WindowsDirectory:
michael@0 560 {
michael@0 561 int32_t len = ::GetWindowsDirectoryW(path, MAX_PATH);
michael@0 562
michael@0 563 // Need enough space to add the trailing backslash
michael@0 564 if (!len || len > MAX_PATH - 2)
michael@0 565 break;
michael@0 566
michael@0 567 path[len] = L'\\';
michael@0 568 path[++len] = L'\0';
michael@0 569
michael@0 570 return NS_NewLocalFile(nsDependentString(path, len),
michael@0 571 true,
michael@0 572 aFile);
michael@0 573 }
michael@0 574
michael@0 575 case Win_ProgramFiles:
michael@0 576 {
michael@0 577 return GetWindowsFolder(CSIDL_PROGRAM_FILES, aFile);
michael@0 578 }
michael@0 579
michael@0 580 case Win_HomeDirectory:
michael@0 581 {
michael@0 582 nsresult rv = GetWindowsFolder(CSIDL_PROFILE, aFile);
michael@0 583 if (NS_SUCCEEDED(rv))
michael@0 584 return rv;
michael@0 585
michael@0 586 int32_t len;
michael@0 587 if ((len = ::GetEnvironmentVariableW(L"HOME", path, MAX_PATH)) > 0)
michael@0 588 {
michael@0 589 // Need enough space to add the trailing backslash
michael@0 590 if (len > MAX_PATH - 2)
michael@0 591 break;
michael@0 592
michael@0 593 path[len] = L'\\';
michael@0 594 path[++len] = L'\0';
michael@0 595
michael@0 596 rv = NS_NewLocalFile(nsDependentString(path, len),
michael@0 597 true,
michael@0 598 aFile);
michael@0 599 if (NS_SUCCEEDED(rv))
michael@0 600 return rv;
michael@0 601 }
michael@0 602
michael@0 603 len = ::GetEnvironmentVariableW(L"HOMEDRIVE", path, MAX_PATH);
michael@0 604 if (0 < len && len < MAX_PATH)
michael@0 605 {
michael@0 606 WCHAR temp[MAX_PATH];
michael@0 607 DWORD len2 = ::GetEnvironmentVariableW(L"HOMEPATH", temp, MAX_PATH);
michael@0 608 if (0 < len2 && len + len2 < MAX_PATH)
michael@0 609 wcsncat(path, temp, len2);
michael@0 610
michael@0 611 len = wcslen(path);
michael@0 612
michael@0 613 // Need enough space to add the trailing backslash
michael@0 614 if (len > MAX_PATH - 2)
michael@0 615 break;
michael@0 616
michael@0 617 path[len] = L'\\';
michael@0 618 path[++len] = L'\0';
michael@0 619
michael@0 620 return NS_NewLocalFile(nsDependentString(path, len),
michael@0 621 true,
michael@0 622 aFile);
michael@0 623 }
michael@0 624 }
michael@0 625 case Win_Desktop:
michael@0 626 {
michael@0 627 return GetWindowsFolder(CSIDL_DESKTOP, aFile);
michael@0 628 }
michael@0 629 case Win_Programs:
michael@0 630 {
michael@0 631 return GetWindowsFolder(CSIDL_PROGRAMS, aFile);
michael@0 632 }
michael@0 633
michael@0 634 case Win_Downloads:
michael@0 635 {
michael@0 636 // Defined in KnownFolders.h.
michael@0 637 GUID folderid_downloads = {0x374de290, 0x123f, 0x4565, {0x91, 0x64,
michael@0 638 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b}};
michael@0 639 nsresult rv = GetKnownFolder(&folderid_downloads, aFile);
michael@0 640 // On WinXP, there is no downloads folder, default
michael@0 641 // to 'Desktop'.
michael@0 642 if(NS_ERROR_FAILURE == rv)
michael@0 643 {
michael@0 644 rv = GetWindowsFolder(CSIDL_DESKTOP, aFile);
michael@0 645 }
michael@0 646 return rv;
michael@0 647 }
michael@0 648
michael@0 649 case Win_Controls:
michael@0 650 {
michael@0 651 return GetWindowsFolder(CSIDL_CONTROLS, aFile);
michael@0 652 }
michael@0 653 case Win_Printers:
michael@0 654 {
michael@0 655 return GetWindowsFolder(CSIDL_PRINTERS, aFile);
michael@0 656 }
michael@0 657 case Win_Personal:
michael@0 658 {
michael@0 659 return GetWindowsFolder(CSIDL_PERSONAL, aFile);
michael@0 660 }
michael@0 661 case Win_Favorites:
michael@0 662 {
michael@0 663 return GetWindowsFolder(CSIDL_FAVORITES, aFile);
michael@0 664 }
michael@0 665 case Win_Startup:
michael@0 666 {
michael@0 667 return GetWindowsFolder(CSIDL_STARTUP, aFile);
michael@0 668 }
michael@0 669 case Win_Recent:
michael@0 670 {
michael@0 671 return GetWindowsFolder(CSIDL_RECENT, aFile);
michael@0 672 }
michael@0 673 case Win_Sendto:
michael@0 674 {
michael@0 675 return GetWindowsFolder(CSIDL_SENDTO, aFile);
michael@0 676 }
michael@0 677 case Win_Bitbucket:
michael@0 678 {
michael@0 679 return GetWindowsFolder(CSIDL_BITBUCKET, aFile);
michael@0 680 }
michael@0 681 case Win_Startmenu:
michael@0 682 {
michael@0 683 return GetWindowsFolder(CSIDL_STARTMENU, aFile);
michael@0 684 }
michael@0 685 case Win_Desktopdirectory:
michael@0 686 {
michael@0 687 return GetWindowsFolder(CSIDL_DESKTOPDIRECTORY, aFile);
michael@0 688 }
michael@0 689 case Win_Drives:
michael@0 690 {
michael@0 691 return GetWindowsFolder(CSIDL_DRIVES, aFile);
michael@0 692 }
michael@0 693 case Win_Network:
michael@0 694 {
michael@0 695 return GetWindowsFolder(CSIDL_NETWORK, aFile);
michael@0 696 }
michael@0 697 case Win_Nethood:
michael@0 698 {
michael@0 699 return GetWindowsFolder(CSIDL_NETHOOD, aFile);
michael@0 700 }
michael@0 701 case Win_Fonts:
michael@0 702 {
michael@0 703 return GetWindowsFolder(CSIDL_FONTS, aFile);
michael@0 704 }
michael@0 705 case Win_Templates:
michael@0 706 {
michael@0 707 return GetWindowsFolder(CSIDL_TEMPLATES, aFile);
michael@0 708 }
michael@0 709 case Win_Common_Startmenu:
michael@0 710 {
michael@0 711 return GetWindowsFolder(CSIDL_COMMON_STARTMENU, aFile);
michael@0 712 }
michael@0 713 case Win_Common_Programs:
michael@0 714 {
michael@0 715 return GetWindowsFolder(CSIDL_COMMON_PROGRAMS, aFile);
michael@0 716 }
michael@0 717 case Win_Common_Startup:
michael@0 718 {
michael@0 719 return GetWindowsFolder(CSIDL_COMMON_STARTUP, aFile);
michael@0 720 }
michael@0 721 case Win_Common_Desktopdirectory:
michael@0 722 {
michael@0 723 return GetWindowsFolder(CSIDL_COMMON_DESKTOPDIRECTORY, aFile);
michael@0 724 }
michael@0 725 case Win_Common_AppData:
michael@0 726 {
michael@0 727 return GetWindowsFolder(CSIDL_COMMON_APPDATA, aFile);
michael@0 728 }
michael@0 729 case Win_Printhood:
michael@0 730 {
michael@0 731 return GetWindowsFolder(CSIDL_PRINTHOOD, aFile);
michael@0 732 }
michael@0 733 case Win_Cookies:
michael@0 734 {
michael@0 735 return GetWindowsFolder(CSIDL_COOKIES, aFile);
michael@0 736 }
michael@0 737 case Win_Appdata:
michael@0 738 {
michael@0 739 nsresult rv = GetWindowsFolder(CSIDL_APPDATA, aFile);
michael@0 740 if (NS_FAILED(rv))
michael@0 741 rv = GetRegWindowsAppDataFolder(false, aFile);
michael@0 742 return rv;
michael@0 743 }
michael@0 744 case Win_LocalAppdata:
michael@0 745 {
michael@0 746 nsresult rv = GetWindowsFolder(CSIDL_LOCAL_APPDATA, aFile);
michael@0 747 if (NS_FAILED(rv))
michael@0 748 rv = GetRegWindowsAppDataFolder(true, aFile);
michael@0 749 return rv;
michael@0 750 }
michael@0 751 case Win_Documents:
michael@0 752 {
michael@0 753 return GetLibrarySaveToPath(CSIDL_MYDOCUMENTS,
michael@0 754 FOLDERID_DocumentsLibrary,
michael@0 755 aFile);
michael@0 756 }
michael@0 757 case Win_Pictures:
michael@0 758 {
michael@0 759 return GetLibrarySaveToPath(CSIDL_MYPICTURES,
michael@0 760 FOLDERID_PicturesLibrary,
michael@0 761 aFile);
michael@0 762 }
michael@0 763 case Win_Music:
michael@0 764 {
michael@0 765 return GetLibrarySaveToPath(CSIDL_MYMUSIC,
michael@0 766 FOLDERID_MusicLibrary,
michael@0 767 aFile);
michael@0 768 }
michael@0 769 case Win_Videos:
michael@0 770 {
michael@0 771 return GetLibrarySaveToPath(CSIDL_MYVIDEO,
michael@0 772 FOLDERID_VideosLibrary,
michael@0 773 aFile);
michael@0 774 }
michael@0 775 #endif // XP_WIN
michael@0 776
michael@0 777 #if defined(XP_UNIX)
michael@0 778 case Unix_LocalDirectory:
michael@0 779 return NS_NewNativeLocalFile(nsDependentCString("/usr/local/netscape/"),
michael@0 780 true,
michael@0 781 aFile);
michael@0 782 case Unix_LibDirectory:
michael@0 783 return NS_NewNativeLocalFile(nsDependentCString("/usr/local/lib/netscape/"),
michael@0 784 true,
michael@0 785 aFile);
michael@0 786
michael@0 787 case Unix_HomeDirectory:
michael@0 788 return GetUnixHomeDir(aFile);
michael@0 789
michael@0 790 case Unix_XDG_Desktop:
michael@0 791 case Unix_XDG_Documents:
michael@0 792 case Unix_XDG_Download:
michael@0 793 case Unix_XDG_Music:
michael@0 794 case Unix_XDG_Pictures:
michael@0 795 case Unix_XDG_PublicShare:
michael@0 796 case Unix_XDG_Templates:
michael@0 797 case Unix_XDG_Videos:
michael@0 798 return GetUnixXDGUserDirectory(aSystemSystemDirectory, aFile);
michael@0 799 #endif
michael@0 800
michael@0 801 default:
michael@0 802 break;
michael@0 803 }
michael@0 804 return NS_ERROR_NOT_AVAILABLE;
michael@0 805 }
michael@0 806
michael@0 807 #if defined (MOZ_WIDGET_COCOA)
michael@0 808 nsresult
michael@0 809 GetOSXFolderType(short aDomain, OSType aFolderType, nsIFile **localFile)
michael@0 810 {
michael@0 811 OSErr err;
michael@0 812 FSRef fsRef;
michael@0 813 nsresult rv = NS_ERROR_FAILURE;
michael@0 814
michael@0 815 err = ::FSFindFolder(aDomain, aFolderType, kCreateFolder, &fsRef);
michael@0 816 if (err == noErr)
michael@0 817 {
michael@0 818 NS_NewLocalFile(EmptyString(), true, localFile);
michael@0 819 nsCOMPtr<nsILocalFileMac> localMacFile(do_QueryInterface(*localFile));
michael@0 820 if (localMacFile)
michael@0 821 rv = localMacFile->InitWithFSRef(&fsRef);
michael@0 822 }
michael@0 823 return rv;
michael@0 824 }
michael@0 825 #endif
michael@0 826

mercurial