|
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/. */ |
|
5 |
|
6 #include "SpecialSystemDirectory.h" |
|
7 #include "nsString.h" |
|
8 #include "nsDependentString.h" |
|
9 #include "nsAutoPtr.h" |
|
10 |
|
11 #if defined(XP_WIN) |
|
12 |
|
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" |
|
23 |
|
24 using mozilla::IsWin7OrLater; |
|
25 |
|
26 #elif defined(XP_UNIX) |
|
27 |
|
28 #include <limits.h> |
|
29 #include <unistd.h> |
|
30 #include <stdlib.h> |
|
31 #include <sys/param.h> |
|
32 #include "prenv.h" |
|
33 |
|
34 #endif |
|
35 |
|
36 #if defined(VMS) |
|
37 #include <unixlib.h> |
|
38 #endif |
|
39 |
|
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 |
|
53 |
|
54 #ifdef XP_WIN |
|
55 typedef HRESULT (WINAPI* nsGetKnownFolderPath)(GUID& rfid, |
|
56 DWORD dwFlags, |
|
57 HANDLE hToken, |
|
58 PWSTR *ppszPath); |
|
59 |
|
60 static nsGetKnownFolderPath gGetKnownFolderPath = nullptr; |
|
61 #endif |
|
62 |
|
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 } |
|
76 |
|
77 #if defined (XP_WIN) |
|
78 |
|
79 static nsresult GetKnownFolder(GUID* guid, nsIFile** aFile) |
|
80 { |
|
81 if (!guid || !gGetKnownFolderPath) |
|
82 return NS_ERROR_FAILURE; |
|
83 |
|
84 PWSTR path = nullptr; |
|
85 gGetKnownFolderPath(*guid, 0, nullptr, &path); |
|
86 |
|
87 if (!path) |
|
88 return NS_ERROR_FAILURE; |
|
89 |
|
90 nsresult rv = NS_NewLocalFile(nsDependentString(path), |
|
91 true, |
|
92 aFile); |
|
93 |
|
94 CoTaskMemFree(path); |
|
95 return rv; |
|
96 } |
|
97 |
|
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); |
|
104 |
|
105 if (!SUCCEEDED(result)) |
|
106 return NS_ERROR_FAILURE; |
|
107 |
|
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 } |
|
115 |
|
116 return NS_NewLocalFile(nsDependentString(path, len), true, aFile); |
|
117 } |
|
118 |
|
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 } |
|
137 |
|
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); |
|
150 |
|
151 nsRefPtr<IShellLibrary> shellLib; |
|
152 nsRefPtr<IShellItem> savePath; |
|
153 HRESULT hr = |
|
154 SHLoadLibraryFromKnownFolder(aFolderId, STGM_READ, |
|
155 IID_IShellLibrary, getter_AddRefs(shellLib)); |
|
156 |
|
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 } |
|
171 |
|
172 return GetWindowsFolder(aFallbackFolderId, aFile); |
|
173 } |
|
174 |
|
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; |
|
189 |
|
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; |
|
199 |
|
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 } |
|
207 |
|
208 return NS_NewLocalFile(nsDependentString(path, len), true, aFile); |
|
209 } |
|
210 |
|
211 #endif // XP_WIN |
|
212 |
|
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 } |
|
237 |
|
238 /* |
|
239 The following license applies to the xdg_user_dir_lookup function: |
|
240 |
|
241 Copyright (c) 2007 Red Hat, Inc. |
|
242 |
|
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: |
|
250 |
|
251 The above copyright notice and this permission notice shall be |
|
252 included in all copies or substantial portions of the Software. |
|
253 |
|
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 */ |
|
263 |
|
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; |
|
274 |
|
275 home_dir = getenv ("HOME"); |
|
276 |
|
277 if (home_dir == nullptr) |
|
278 goto error; |
|
279 |
|
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; |
|
286 |
|
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; |
|
295 |
|
296 strcpy (config_file, config_home); |
|
297 strcat (config_file, "/user-dirs.dirs"); |
|
298 } |
|
299 |
|
300 file = fopen (config_file, "r"); |
|
301 free (config_file); |
|
302 if (file == nullptr) |
|
303 goto error; |
|
304 |
|
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; |
|
312 |
|
313 p = buffer; |
|
314 while (*p == ' ' || *p == '\t') |
|
315 p++; |
|
316 |
|
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; |
|
326 |
|
327 while (*p == ' ' || *p == '\t') |
|
328 p++; |
|
329 |
|
330 if (*p != '=') |
|
331 continue; |
|
332 p++; |
|
333 |
|
334 while (*p == ' ' || *p == '\t') |
|
335 p++; |
|
336 |
|
337 if (*p != '"') |
|
338 continue; |
|
339 p++; |
|
340 |
|
341 relative = 0; |
|
342 if (strncmp (p, "$HOME/", 6) == 0) |
|
343 { |
|
344 p += 6; |
|
345 relative = 1; |
|
346 } |
|
347 else if (*p != '/') |
|
348 continue; |
|
349 |
|
350 if (relative) |
|
351 { |
|
352 user_dir = (char*) malloc (strlen (home_dir) + 1 + strlen (p) + 1); |
|
353 if (user_dir == nullptr) |
|
354 goto error2; |
|
355 |
|
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; |
|
364 |
|
365 *user_dir = 0; |
|
366 } |
|
367 |
|
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); |
|
379 |
|
380 if (user_dir) |
|
381 return user_dir; |
|
382 |
|
383 error: |
|
384 return nullptr; |
|
385 } |
|
386 |
|
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"; |
|
396 |
|
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 }; |
|
407 |
|
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]); |
|
415 |
|
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; |
|
428 |
|
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 } |
|
435 |
|
436 if (NS_FAILED(rv)) |
|
437 return rv; |
|
438 |
|
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 } |
|
448 |
|
449 *aFile = nullptr; |
|
450 file.swap(*aFile); |
|
451 |
|
452 return NS_OK; |
|
453 } |
|
454 #endif |
|
455 |
|
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 |
|
465 |
|
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 |
|
479 |
|
480 #if !defined(XP_WIN) |
|
481 return NS_NewNativeLocalFile(nsDependentCString(path), |
|
482 true, |
|
483 aFile); |
|
484 #endif |
|
485 |
|
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; |
|
494 |
|
495 return NS_NewLocalFile(nsDependentString(path), |
|
496 true, |
|
497 aFile); |
|
498 } |
|
499 #else |
|
500 return NS_NewNativeLocalFile(nsDependentCString("/"), |
|
501 true, |
|
502 aFile); |
|
503 |
|
504 #endif |
|
505 |
|
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 } |
|
520 |
|
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); |
|
547 |
|
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'; |
|
553 |
|
554 return NS_NewLocalFile(nsDependentString(path, len), |
|
555 true, |
|
556 aFile); |
|
557 } |
|
558 |
|
559 case Win_WindowsDirectory: |
|
560 { |
|
561 int32_t len = ::GetWindowsDirectoryW(path, MAX_PATH); |
|
562 |
|
563 // Need enough space to add the trailing backslash |
|
564 if (!len || len > MAX_PATH - 2) |
|
565 break; |
|
566 |
|
567 path[len] = L'\\'; |
|
568 path[++len] = L'\0'; |
|
569 |
|
570 return NS_NewLocalFile(nsDependentString(path, len), |
|
571 true, |
|
572 aFile); |
|
573 } |
|
574 |
|
575 case Win_ProgramFiles: |
|
576 { |
|
577 return GetWindowsFolder(CSIDL_PROGRAM_FILES, aFile); |
|
578 } |
|
579 |
|
580 case Win_HomeDirectory: |
|
581 { |
|
582 nsresult rv = GetWindowsFolder(CSIDL_PROFILE, aFile); |
|
583 if (NS_SUCCEEDED(rv)) |
|
584 return rv; |
|
585 |
|
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; |
|
592 |
|
593 path[len] = L'\\'; |
|
594 path[++len] = L'\0'; |
|
595 |
|
596 rv = NS_NewLocalFile(nsDependentString(path, len), |
|
597 true, |
|
598 aFile); |
|
599 if (NS_SUCCEEDED(rv)) |
|
600 return rv; |
|
601 } |
|
602 |
|
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); |
|
610 |
|
611 len = wcslen(path); |
|
612 |
|
613 // Need enough space to add the trailing backslash |
|
614 if (len > MAX_PATH - 2) |
|
615 break; |
|
616 |
|
617 path[len] = L'\\'; |
|
618 path[++len] = L'\0'; |
|
619 |
|
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 } |
|
633 |
|
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 } |
|
648 |
|
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 |
|
776 |
|
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); |
|
786 |
|
787 case Unix_HomeDirectory: |
|
788 return GetUnixHomeDir(aFile); |
|
789 |
|
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 |
|
800 |
|
801 default: |
|
802 break; |
|
803 } |
|
804 return NS_ERROR_NOT_AVAILABLE; |
|
805 } |
|
806 |
|
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; |
|
814 |
|
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 |
|
826 |