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.

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

mercurial