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 +