Move all values of SHGetSpecialFolderPathA into an array, add some
[wine.git] / dlls / shell32 / shellpath.c
blobc587981ceaec4a841bff226ae41d644b84c19c90
1 /*
2 * Path Functions
4 * Many of this functions are in SHLWAPI.DLL also
6 */
7 #include <string.h>
8 #include <ctype.h>
9 #include "debugtools.h"
10 #include "windef.h"
11 #include "winnls.h"
12 #include "winreg.h"
14 #include "shlobj.h"
15 #include "shell32_main.h"
16 #include "wine/undocshell.h"
17 #include "wine/unicode.h"
18 #include "shlwapi.h"
20 DEFAULT_DEBUG_CHANNEL(shell);
22 #define isSlash(x) ((x)=='\\' || (x)=='/')
24 ########## Combining and Constructing paths ##########
27 /*************************************************************************
28 * PathAppendAW [SHELL32.36]
30 BOOL WINAPI PathAppendAW(
31 LPVOID lpszPath1,
32 LPCVOID lpszPath2)
34 if (SHELL_OsIsUnicode())
35 return PathAppendW(lpszPath1, lpszPath2);
36 return PathAppendA(lpszPath1, lpszPath2);
39 /*************************************************************************
40 * PathCombineAW [SHELL32.37]
42 LPVOID WINAPI PathCombineAW(
43 LPVOID szDest,
44 LPCVOID lpszDir,
45 LPCVOID lpszFile)
47 if (SHELL_OsIsUnicode())
48 return PathCombineW( szDest, lpszDir, lpszFile );
49 return PathCombineA( szDest, lpszDir, lpszFile );
52 /*************************************************************************
53 * PathAddBackslashAW [SHELL32.32]
55 LPVOID WINAPI PathAddBackslashAW(LPVOID lpszPath)
57 if(SHELL_OsIsUnicode())
58 return PathAddBackslashW(lpszPath);
59 return PathAddBackslashA(lpszPath);
62 /*************************************************************************
63 * PathBuildRootAW [SHELL32.30]
65 LPVOID WINAPI PathBuildRootAW(LPVOID lpszPath, int drive)
67 if(SHELL_OsIsUnicode())
68 return PathBuildRootW(lpszPath, drive);
69 return PathBuildRootA(lpszPath, drive);
73 Extracting Component Parts
76 /*************************************************************************
77 * PathFindFileNameAW [SHELL32.34]
79 LPVOID WINAPI PathFindFileNameAW(LPCVOID lpszPath)
81 if(SHELL_OsIsUnicode())
82 return PathFindFileNameW(lpszPath);
83 return PathFindFileNameA(lpszPath);
86 /*************************************************************************
87 * PathFindExtensionAW [SHELL32.31]
89 LPVOID WINAPI PathFindExtensionAW(LPCVOID lpszPath)
91 if (SHELL_OsIsUnicode())
92 return PathFindExtensionW(lpszPath);
93 return PathFindExtensionA(lpszPath);
97 /*************************************************************************
98 * PathGetExtensionA [internal]
100 * NOTES
101 * exported by ordinal
102 * return value points to the first char after the dot
104 static LPSTR PathGetExtensionA(LPCSTR lpszPath)
106 TRACE("(%s)\n",lpszPath);
108 lpszPath = PathFindExtensionA(lpszPath);
109 return (LPSTR)(*lpszPath?(lpszPath+1):lpszPath);
112 /*************************************************************************
113 * PathGetExtensionW [internal]
115 static LPWSTR PathGetExtensionW(LPCWSTR lpszPath)
117 TRACE("(%s)\n",debugstr_w(lpszPath));
119 lpszPath = PathFindExtensionW(lpszPath);
120 return (LPWSTR)(*lpszPath?(lpszPath+1):lpszPath);
123 /*************************************************************************
124 * PathGetExtensionAW [SHELL32.158]
126 LPVOID WINAPI PathGetExtensionAW(LPCVOID lpszPath)
128 if (SHELL_OsIsUnicode())
129 return PathGetExtensionW(lpszPath);
130 return PathGetExtensionA(lpszPath);
133 /*************************************************************************
134 * PathGetArgsAW [SHELL32.52]
136 LPVOID WINAPI PathGetArgsAW(LPVOID lpszPath)
138 if (SHELL_OsIsUnicode())
139 return PathGetArgsW(lpszPath);
140 return PathGetArgsA(lpszPath);
143 /*************************************************************************
144 * PathGetDriveNumber [SHELL32.57]
146 int WINAPI PathGetDriveNumberAW(LPVOID lpszPath)
148 if (SHELL_OsIsUnicode())
149 return PathGetDriveNumberW(lpszPath);
150 return PathGetDriveNumberA(lpszPath);
153 /*************************************************************************
154 * PathRemoveFileSpec [SHELL32.35]
156 BOOL WINAPI PathRemoveFileSpecAW(LPVOID lpszPath)
158 if (SHELL_OsIsUnicode())
159 return PathRemoveFileSpecW(lpszPath);
160 return PathRemoveFileSpecA(lpszPath);
163 /*************************************************************************
164 * PathStripPathAW [SHELL32.38]
166 void WINAPI PathStripPathAW(LPVOID lpszPath)
168 if (SHELL_OsIsUnicode())
169 return PathStripPathW(lpszPath);
170 return PathStripPathA(lpszPath);
173 /*************************************************************************
174 * PathStripToRootAW [SHELL32.50]
176 BOOL WINAPI PathStripToRootAW(LPVOID lpszPath)
178 if (SHELL_OsIsUnicode())
179 return PathStripToRootW(lpszPath);
180 return PathStripToRootA(lpszPath);
183 /*************************************************************************
184 * PathRemoveArgsAW [SHELL32.251]
186 void WINAPI PathRemoveArgsAW(LPVOID lpszPath)
188 if (SHELL_OsIsUnicode())
189 PathRemoveArgsW(lpszPath);
190 PathRemoveArgsA(lpszPath);
193 /*************************************************************************
194 * PathRemoveExtensionAW [SHELL32.250]
196 void WINAPI PathRemoveExtensionAW(LPVOID lpszPath)
198 if (SHELL_OsIsUnicode())
199 return PathRemoveExtensionW(lpszPath);
200 return PathRemoveExtensionA(lpszPath);
205 Path Manipulations
208 /*************************************************************************
209 * PathGetShortPathA [internal]
211 LPSTR WINAPI PathGetShortPathA(LPSTR lpszPath)
213 FIXME("%s stub\n", lpszPath);
214 return NULL;
217 /*************************************************************************
218 * PathGetShortPathW [internal]
220 LPWSTR WINAPI PathGetShortPathW(LPWSTR lpszPath)
222 FIXME("%s stub\n", debugstr_w(lpszPath));
223 return NULL;
226 /*************************************************************************
227 * PathGetShortPathAW [SHELL32.92]
229 LPVOID WINAPI PathGetShortPathAW(LPVOID lpszPath)
231 if(SHELL_OsIsUnicode())
232 return PathGetShortPathW(lpszPath);
233 return PathGetShortPathA(lpszPath);
236 /*************************************************************************
237 * PathRemoveBlanksAW [SHELL32.33]
239 void WINAPI PathRemoveBlanksAW(LPVOID str)
241 if(SHELL_OsIsUnicode())
242 PathRemoveBlanksW(str);
243 PathRemoveBlanksA(str);
246 /*************************************************************************
247 * PathQuoteSpacesAW [SHELL32.55]
249 LPVOID WINAPI PathQuoteSpacesAW (LPVOID lpszPath)
251 if(SHELL_OsIsUnicode())
252 return PathQuoteSpacesW(lpszPath);
253 return PathQuoteSpacesA(lpszPath);
256 /*************************************************************************
257 * PathUnquoteSpacesAW [SHELL32.56]
259 VOID WINAPI PathUnquoteSpacesAW(LPVOID str)
261 if(SHELL_OsIsUnicode())
262 PathUnquoteSpacesW(str);
263 else
264 PathUnquoteSpacesA(str);
267 /*************************************************************************
268 * PathParseIconLocationAW [SHELL32.249]
270 int WINAPI PathParseIconLocationAW (LPVOID lpszPath)
272 if(SHELL_OsIsUnicode())
273 return PathParseIconLocationW(lpszPath);
274 return PathParseIconLocationA(lpszPath);
278 ########## Path Testing ##########
280 /*************************************************************************
281 * PathIsUNCAW [SHELL32.39]
283 BOOL WINAPI PathIsUNCAW (LPCVOID lpszPath)
285 if (SHELL_OsIsUnicode())
286 return PathIsUNCW( lpszPath );
287 return PathIsUNCA( lpszPath );
290 /*************************************************************************
291 * PathIsRelativeAW [SHELL32.40]
293 BOOL WINAPI PathIsRelativeAW (LPCVOID lpszPath)
295 if (SHELL_OsIsUnicode())
296 return PathIsRelativeW( lpszPath );
297 return PathIsRelativeA( lpszPath );
300 /*************************************************************************
301 * PathIsRootAW [SHELL32.29]
303 BOOL WINAPI PathIsRootAW(LPCVOID lpszPath)
305 if (SHELL_OsIsUnicode())
306 return PathIsRootW(lpszPath);
307 return PathIsRootA(lpszPath);
310 /*************************************************************************
311 * PathIsExeA [internal]
313 static BOOL PathIsExeA (LPCSTR lpszPath)
315 LPCSTR lpszExtension = PathGetExtensionA(lpszPath);
316 int i = 0;
317 static char * lpszExtensions[6] = {"exe", "com", "pid", "cmd", "bat", NULL };
319 TRACE("path=%s\n",lpszPath);
321 for(i=0; lpszExtensions[i]; i++)
322 if (!strcasecmp(lpszExtension,lpszExtensions[i])) return TRUE;
324 return FALSE;
327 /*************************************************************************
328 * PathIsExeW [internal]
330 static BOOL PathIsExeW (LPCWSTR lpszPath)
332 LPCWSTR lpszExtension = PathGetExtensionW(lpszPath);
333 int i = 0;
334 static WCHAR lpszExtensions[6][4] =
335 {{'e','x','e','\0'}, {'c','o','m','\0'}, {'p','i','d','\0'},
336 {'c','m','d','\0'}, {'b','a','t','\0'}, {'\0'} };
338 TRACE("path=%s\n",debugstr_w(lpszPath));
340 for(i=0; lpszExtensions[i]; i++)
341 if (!strcmpiW(lpszExtension,lpszExtensions[i])) return TRUE;
343 return FALSE;
346 /*************************************************************************
347 * PathIsExeAW [SHELL32.43]
349 BOOL WINAPI PathIsExeAW (LPCVOID path)
351 if (SHELL_OsIsUnicode())
352 return PathIsExeW (path);
353 return PathIsExeA(path);
356 /*************************************************************************
357 * PathIsDirectoryAW [SHELL32.159]
359 BOOL WINAPI PathIsDirectoryAW (LPCVOID lpszPath)
361 if (SHELL_OsIsUnicode())
362 return PathIsDirectoryW (lpszPath);
363 return PathIsDirectoryA (lpszPath);
366 /*************************************************************************
367 * PathFileExistsAW [SHELL32.45]
369 BOOL WINAPI PathFileExistsAW (LPCVOID lpszPath)
371 if (SHELL_OsIsUnicode())
372 return PathFileExistsW (lpszPath);
373 return PathFileExistsA (lpszPath);
376 /*************************************************************************
377 * PathMatchSpecAW [SHELL32.46]
379 BOOL WINAPI PathMatchSpecAW(LPVOID name, LPVOID mask)
381 if (SHELL_OsIsUnicode())
382 return PathMatchSpecW( name, mask );
383 return PathMatchSpecA( name, mask );
386 /*************************************************************************
387 * PathIsSameRootAW [SHELL32.650]
389 BOOL WINAPI PathIsSameRootAW(LPCVOID lpszPath1, LPCVOID lpszPath2)
391 if (SHELL_OsIsUnicode())
392 return PathIsSameRootW(lpszPath1, lpszPath2);
393 return PathIsSameRootA(lpszPath1, lpszPath2);
396 /*************************************************************************
397 * IsLFNDriveA [SHELL32.119]
399 * NOTES
400 * exported by ordinal Name
402 BOOL WINAPI IsLFNDriveA(LPCSTR lpszPath)
404 DWORD fnlen;
406 if (!GetVolumeInformationA(lpszPath,NULL,0,NULL,&fnlen,NULL,NULL,0))
407 return FALSE;
408 return fnlen>12;
412 ########## Creating Something Unique ##########
414 /*************************************************************************
415 * PathMakeUniqueNameA [internal]
417 BOOL WINAPI PathMakeUniqueNameA(
418 LPSTR lpszBuffer,
419 DWORD dwBuffSize,
420 LPCSTR lpszShortName,
421 LPCSTR lpszLongName,
422 LPCSTR lpszPathName)
424 FIXME("%p %lu %s %s %s stub\n",
425 lpszBuffer, dwBuffSize, debugstr_a(lpszShortName),
426 debugstr_a(lpszLongName), debugstr_a(lpszPathName));
427 return TRUE;
430 /*************************************************************************
431 * PathMakeUniqueNameW [internal]
433 BOOL WINAPI PathMakeUniqueNameW(
434 LPWSTR lpszBuffer,
435 DWORD dwBuffSize,
436 LPCWSTR lpszShortName,
437 LPCWSTR lpszLongName,
438 LPCWSTR lpszPathName)
440 FIXME("%p %lu %s %s %s stub\n",
441 lpszBuffer, dwBuffSize, debugstr_w(lpszShortName),
442 debugstr_w(lpszLongName), debugstr_w(lpszPathName));
443 return TRUE;
446 /*************************************************************************
447 * PathMakeUniqueNameAW [SHELL32.47]
449 BOOL WINAPI PathMakeUniqueNameAW(
450 LPVOID lpszBuffer,
451 DWORD dwBuffSize,
452 LPCVOID lpszShortName,
453 LPCVOID lpszLongName,
454 LPCVOID lpszPathName)
456 if (SHELL_OsIsUnicode())
457 return PathMakeUniqueNameW(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
458 return PathMakeUniqueNameA(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
461 /*************************************************************************
462 * PathYetAnotherMakeUniqueNameA [SHELL32.75]
464 * NOTES
465 * exported by ordinal
467 BOOL WINAPI PathYetAnotherMakeUniqueNameA(
468 LPSTR lpszBuffer,
469 LPCSTR lpszPathName,
470 LPCSTR lpszShortName,
471 LPCSTR lpszLongName)
473 FIXME("(%p,%p, %p ,%p):stub.\n",
474 lpszBuffer, lpszPathName, lpszShortName, lpszLongName);
475 return TRUE;
480 ########## cleaning and resolving paths ##########
483 /*************************************************************************
484 * PathFindOnPathAW [SHELL32]
486 BOOL WINAPI PathFindOnPathAW(LPVOID sFile, LPCVOID sOtherDirs)
488 if (SHELL_OsIsUnicode())
489 return PathFindOnPathW(sFile, sOtherDirs);
490 return PathFindOnPathA(sFile, sOtherDirs);
493 /*************************************************************************
494 * PathCleanupSpecAW [SHELL32]
496 DWORD WINAPI PathCleanupSpecAW (LPVOID x, LPVOID y)
498 FIXME("(%p, %p) stub\n",x,y);
499 return TRUE;
502 /*************************************************************************
503 * PathQualifyA [SHELL32]
505 BOOL WINAPI PathQualifyA(LPCSTR pszPath)
507 FIXME("%s\n",pszPath);
508 return 0;
511 /*************************************************************************
512 * PathQualifyW [SHELL32]
514 BOOL WINAPI PathQualifyW(LPCWSTR pszPath)
516 FIXME("%s\n",debugstr_w(pszPath));
517 return 0;
520 /*************************************************************************
521 * PathQualifyAW [SHELL32]
523 BOOL WINAPI PathQualifyAW(LPCVOID pszPath)
525 if (SHELL_OsIsUnicode())
526 return PathQualifyW(pszPath);
527 return PathQualifyA(pszPath);
530 /*************************************************************************
531 * PathResolveA [SHELL32.51]
533 BOOL WINAPI PathResolveA(
534 LPSTR lpszPath,
535 LPCSTR *alpszPaths,
536 DWORD dwFlags)
538 FIXME("(%s,%p,0x%08lx),stub!\n",
539 lpszPath, *alpszPaths, dwFlags);
540 return 0;
543 /*************************************************************************
544 * PathResolveW [SHELL32]
546 BOOL WINAPI PathResolveW(
547 LPWSTR lpszPath,
548 LPCWSTR *alpszPaths,
549 DWORD dwFlags)
551 FIXME("(%s,%p,0x%08lx),stub!\n",
552 debugstr_w(lpszPath), debugstr_w(*alpszPaths), dwFlags);
553 return 0;
556 /*************************************************************************
557 * PathResolveAW [SHELL32]
559 BOOL WINAPI PathResolveAW(
560 LPVOID lpszPath,
561 LPCVOID *alpszPaths,
562 DWORD dwFlags)
564 if (SHELL_OsIsUnicode())
565 return PathResolveW(lpszPath, (LPCWSTR*)alpszPaths, dwFlags);
566 return PathResolveA(lpszPath, (LPCSTR*)alpszPaths, dwFlags);
569 /*************************************************************************
570 * PathProcessCommandA [SHELL32.653]
572 HRESULT WINAPI PathProcessCommandA (
573 LPCSTR lpszPath,
574 LPSTR lpszBuff,
575 DWORD dwBuffSize,
576 DWORD dwFlags)
578 FIXME("%s %p 0x%04lx 0x%04lx stub\n",
579 lpszPath, lpszBuff, dwBuffSize, dwFlags);
580 strcpy(lpszBuff, lpszPath);
581 return 0;
584 /*************************************************************************
585 * PathProcessCommandW
587 HRESULT WINAPI PathProcessCommandW (
588 LPCWSTR lpszPath,
589 LPWSTR lpszBuff,
590 DWORD dwBuffSize,
591 DWORD dwFlags)
593 FIXME("(%s, %p, 0x%04lx, 0x%04lx) stub\n",
594 debugstr_w(lpszPath), lpszBuff, dwBuffSize, dwFlags);
595 strcpyW(lpszBuff, lpszPath);
596 return 0;
599 /*************************************************************************
600 * PathProcessCommandAW
602 HRESULT WINAPI PathProcessCommandAW (
603 LPCVOID lpszPath,
604 LPVOID lpszBuff,
605 DWORD dwBuffSize,
606 DWORD dwFlags)
608 if (SHELL_OsIsUnicode())
609 return PathProcessCommandW(lpszPath, lpszBuff, dwBuffSize, dwFlags);
610 return PathProcessCommandA(lpszPath, lpszBuff, dwBuffSize, dwFlags);
614 ########## special ##########
617 /*************************************************************************
618 * PathSetDlgItemPathAW
620 BOOL WINAPI PathSetDlgItemPathAW(HWND hDlg, int id, LPCVOID pszPath)
621 { if (SHELL_OsIsUnicode())
622 return PathSetDlgItemPathW(hDlg, id, pszPath);
623 return PathSetDlgItemPathA(hDlg, id, pszPath);
627 /*************************************************************************
628 * SHGetSpecialFolderPathA [SHELL32.175]
630 * converts csidl to path
633 static const char * const szSHFolders = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
634 static const char * const szSHUserFolders = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders";
635 static const char * const szSetup = "Software\\Microsoft\\Windows\\CurrentVersion\\Setup";
636 static const char * const szCurrentVersion = "Software\\Microsoft\\Windows\\CurrentVersion";
637 #if 0
638 static const char * const szEnvUserProfile = "%USERPROFILE%";
639 static const char * const szEnvSystemRoot = "%SYSTEMROOT%";
640 #endif
642 typedef struct
644 DWORD dwFlags;
645 HKEY hRootKey;
646 LPCSTR szValueName;
647 LPCSTR szDefaultPath; /* fallback string; sub dir of windows directory */
648 } CSIDL_DATA;
650 #define CSIDL_MYFLAG_SHFOLDER 1
651 #define CSIDL_MYFLAG_SETUP 2
652 #define CSIDL_MYFLAG_CURRVER 4
653 #define CSIDL_MYFLAG_RELATIVE 8
655 #define HKLM HKEY_LOCAL_MACHINE
656 #define HKCU HKEY_CURRENT_USER
657 static const CSIDL_DATA CSIDL_Data[] =
659 { /* CSIDL_DESKTOP */
660 9, HKCU,
661 "Desktop",
662 "Desktop"
664 { /* CSIDL_INTERNET (??) */
665 0, 1, /* FIXME */
666 NULL,
667 NULL,
669 { /* CSIDL_PROGRAMS */
670 9, HKCU,
671 "Programs",
672 "Start Menu\\Programs"
674 { /* CSIDL_CONTROLS (.CPL files) */
675 10, HKLM,
676 "SysDir",
677 "SYSTEM"
679 { /* CSIDL_PRINTERS */
680 10, HKLM,
681 "SysDir",
682 "SYSTEM"
684 { /* CSIDL_PERSONAL */
685 1, HKCU,
686 "Personal",
687 "My Documents"
689 { /* CSIDL_FAVORITES */
690 9, HKCU,
691 "Favorites",
692 "Favorites"
694 { /* CSIDL_STARTUP */
695 9, HKCU,
696 "StartUp",
697 "Start Menu\\Programs\\StartUp"
699 { /* CSIDL_RECENT */
700 9, HKCU,
701 "Recent",
702 "Recent"
704 { /* CSIDL_SENDTO */
705 9, HKCU,
706 "SendTo",
707 "SendTo"
709 { /* CSIDL_BITBUCKET (??) */
710 0, 1, /* FIXME */
711 NULL,
712 NULL
714 { /* CSIDL_STARTMENU */
715 9, HKCU,
716 "Start Menu",
717 "Start Menu"
719 { /* not known */
720 0, 0,
721 NULL,
722 NULL,
724 { /* not known */
725 0, 0,
726 NULL,
727 NULL,
729 { /* not known */
730 0, 0,
731 NULL,
732 NULL,
734 { /* not known */
735 0, 0,
736 NULL,
737 NULL,
739 { /* CSIDL_DESKTOPDIRECTORY */
740 9, HKCU,
741 "Desktop",
742 "Desktop"
744 { /* CSIDL_DRIVES */
745 0, 1, /* FIXME */
746 NULL,
747 "My Computer"
749 { /* CSIDL_NETWORK */
750 0, 1, /* FIXME */
751 NULL,
752 "Network Neighborhood"
754 { /* CSIDL_NETHOOD */
755 9, HKCU,
756 "NetHood",
757 "NetHood"
759 { /* CSIDL_FONTS */
760 9, HKCU,
761 "Fonts",
762 "Fonts"
764 { /* CSIDL_TEMPLATES */
765 9, HKCU,
766 "Templates",
767 "ShellNew"
769 { /* CSIDL_COMMON_STARTMENU */
770 9, HKLM,
771 "Common Start Menu",
772 "Start Menu"
774 { /* CSIDL_COMMON_PROGRAMS */
775 9, HKLM,
776 "Common Programs",
779 { /* CSIDL_COMMON_STARTUP */
780 9, HKLM,
781 "Common StartUp",
782 "All Users\\Start Menu\\Programs\\StartUp"
784 { /* CSIDL_COMMON_DESKTOPDIRECTORY */
785 9, HKLM,
786 "Common Desktop",
787 "Desktop"
789 { /* CSIDL_APPDATA */
790 9, HKCU,
791 "AppData",
792 "Application Data"
794 { /* CSIDL_PRINTHOOD */
795 9, HKCU,
796 "PrintHood",
797 "PrintHood"
799 { /* not known */
800 0, 0,
801 NULL,
802 NULL,
804 { /* CSIDL_ALTSTARTUP */
805 0, 1, /* FIXME */
806 NULL,
807 NULL
809 { /* CSIDL_COMMON_ALTSTARTUP */
810 0, 1, /* FIXME */
811 NULL,
812 NULL
814 { /* CSIDL_COMMON_FAVORITES */
815 9, HKCU,
816 "Favorites",
817 "Favorites"
819 { /* CSIDL_INTERNET_CACHE */
820 9, HKCU,
821 "Cache",
822 "Temporary Internet Files"
824 { /* CSIDL_COOKIES */
825 9, HKCU,
826 "Cookies",
827 "Cookies"
829 { /* CSIDL_HISTORY */
830 9, HKCU,
831 "History",
832 "History"
834 { /* CSIDL_COMMON_APPDATA */
835 9, HKLM,
836 "Common AppData",
837 "All Users\\Application Data"
839 { /* CSIDL_WINDOWS */
840 2, HKLM,
841 "WinDir",
842 "Windows"
844 { /* CSIDL_SYSTEM */
845 10, HKLM,
846 "SysDir",
847 "SYSTEM"
849 { /* CSIDL_PROGRAM_FILES */
850 4, HKLM,
851 "ProgramFilesDir",
852 "Program Files"
854 { /* CSIDL_MYPICTURES */
855 1, HKCU,
856 "My Pictures",
857 "My Documents\\My Pictures"
859 { /* CSIDL_PROFILE */
860 10, HKLM,
861 "WinDir", /* correct ? */
864 { /* CSIDL_SYSTEMX86 */
865 10, HKLM,
866 "SysDir",
867 "SYSTEM"
869 { /* CSIDL_PROGRAM_FILESX86 */
870 4, HKLM,
871 "ProgramFilesDir",
872 "Program Files"
874 { /* CSIDL_PROGRAM_FILES_COMMON */
875 4, HKLM,
876 "CommonFilesDir",
877 "Program Files\\Common Files" /* ? */
879 { /* CSIDL_PROGRAM_FILES_COMMONX86 */
880 4, HKLM,
881 "CommonFilesDir",
882 "Program Files\\Common Files" /* ? */
884 { /* CSIDL_COMMON_TEMPLATES */
885 0, 1, /* FIXME */
886 NULL,
887 NULL
889 { /* CSIDL_COMMON_DOCUMENTS */
890 0, 1, /* FIXME */
891 NULL,
892 NULL
894 { /* CSIDL_COMMON_ADMINTOOLS */
895 0, 1, /* FIXME */
896 NULL,
897 NULL
899 { /* CSIDL_ADMINTOOLS */
900 9, HKCU,
901 "Administrative Tools",
902 "Start Menu\\Programs\\Administrative Tools"
904 { /* CSIDL_CONNECTIONS */
905 0, 1, /* FIXME */
906 NULL,
907 NULL
910 #undef HKCU
911 #undef HKLM
913 BOOL WINAPI SHGetSpecialFolderPathA (
914 HWND hwndOwner,
915 LPSTR szPath,
916 DWORD csidl,
917 BOOL bCreate)
919 CHAR szValueName[MAX_PATH], szDefaultPath[MAX_PATH];
920 HKEY hRootKey, hKey;
921 DWORD dwFlags;
922 DWORD dwType, dwDisp, dwPathLen = MAX_PATH;
923 DWORD folder = csidl & CSIDL_FOLDER_MASK;
925 TRACE("0x%04x,%p,csidl=%lu,0x%04x\n", hwndOwner,szPath,csidl,bCreate);
927 if ((folder > CSIDL_CONNECTIONS) || (CSIDL_Data[folder].hRootKey == 0))
929 ERR("folder unknown or not allowed\n");
930 return FALSE;
932 if (CSIDL_Data[folder].hRootKey == 1)
934 FIXME("folder unknown, please add.\n");
935 return FALSE;
938 dwFlags = CSIDL_Data[folder].dwFlags;
939 hRootKey = CSIDL_Data[folder].hRootKey;
940 strcpy(szValueName, CSIDL_Data[folder].szValueName);
941 strcpy(szDefaultPath, CSIDL_Data[folder].szDefaultPath);
943 if (dwFlags & CSIDL_MYFLAG_SHFOLDER)
945 /* user shell folders */
946 if (RegCreateKeyExA(hRootKey,szSHUserFolders,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return FALSE;
948 if (RegQueryValueExA(hKey,szValueName,NULL,&dwType,(LPBYTE)szPath,&dwPathLen))
950 RegCloseKey(hKey);
952 /* shell folders */
953 if (RegCreateKeyExA(hRootKey,szSHFolders,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return FALSE;
955 if (RegQueryValueExA(hKey,szValueName,NULL,&dwType,(LPBYTE)szPath,&dwPathLen))
958 /* value not existing */
959 if (dwFlags & CSIDL_MYFLAG_RELATIVE)
961 GetWindowsDirectoryA(szPath, MAX_PATH);
962 PathAddBackslashA(szPath);
963 strcat(szPath, szDefaultPath);
965 else
967 strcpy(szPath, "C:\\"); /* FIXME ??? */
968 strcat(szPath, szDefaultPath);
970 RegSetValueExA(hKey,szValueName,0,REG_SZ,(LPBYTE)szPath,strlen(szPath)+1);
973 RegCloseKey(hKey);
975 else
977 LPCSTR pRegPath;
979 if (dwFlags & CSIDL_MYFLAG_SETUP)
980 pRegPath = szSetup;
981 else
982 if (dwFlags & CSIDL_MYFLAG_CURRVER)
983 pRegPath = szCurrentVersion;
984 else
986 ERR("folder settings broken, please correct !\n");
987 return FALSE;
990 if (RegCreateKeyExA(hRootKey,pRegPath,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return FALSE;
992 if (RegQueryValueExA(hKey,szValueName,NULL,&dwType,(LPBYTE)szPath,&dwPathLen))
994 /* value not existing */
995 if (dwFlags & CSIDL_MYFLAG_RELATIVE)
997 GetWindowsDirectoryA(szPath, MAX_PATH);
998 PathAddBackslashA(szPath);
999 strcat(szPath, szDefaultPath);
1001 else
1003 strcpy(szPath, "C:\\"); /* FIXME ??? */
1004 strcat(szPath, szDefaultPath);
1006 RegSetValueExA(hKey,szValueName,0,REG_SZ,(LPBYTE)szPath,strlen(szPath)+1);
1008 RegCloseKey(hKey);
1011 /* expand paths like %USERPROFILE% */
1012 if (dwType == REG_EXPAND_SZ)
1014 ExpandEnvironmentStringsA(szPath, szDefaultPath, MAX_PATH);
1015 strcpy(szPath, szDefaultPath);
1018 /* if we don't care about existing directories we are ready */
1019 if(csidl & CSIDL_FLAG_DONT_VERIFY) return TRUE;
1021 if (PathFileExistsA(szPath)) return TRUE;
1023 /* not existing but we are not allowed to create it */
1024 if (!bCreate) return FALSE;
1026 if (!CreateDirectoryA(szPath,NULL))
1028 ERR("Failed to create directory '%s'.\n", szPath);
1029 return FALSE;
1032 MESSAGE("Created not existing system directory '%s'\n", szPath);
1033 return TRUE;
1036 /*************************************************************************
1037 * SHGetSpecialFolderPathW
1039 BOOL WINAPI SHGetSpecialFolderPathW (
1040 HWND hwndOwner,
1041 LPWSTR szPath,
1042 DWORD csidl,
1043 BOOL bCreate)
1045 char szTemp[MAX_PATH];
1047 if (SHGetSpecialFolderPathA(hwndOwner, szTemp, csidl, bCreate))
1049 if (!MultiByteToWideChar( CP_ACP, 0, szTemp, -1, szPath, MAX_PATH ))
1050 szPath[MAX_PATH-1] = 0;
1053 TRACE("0x%04x,%p,csidl=%lu,0x%04x\n", hwndOwner,szPath,csidl,bCreate);
1055 return TRUE;
1058 /*************************************************************************
1059 * SHGetSpecialFolderPathAW
1061 BOOL WINAPI SHGetSpecialFolderPathAW (
1062 HWND hwndOwner,
1063 LPVOID szPath,
1064 DWORD csidl,
1065 BOOL bCreate)
1068 if (SHELL_OsIsUnicode())
1069 return SHGetSpecialFolderPathW (hwndOwner, szPath, csidl, bCreate);
1070 return SHGetSpecialFolderPathA (hwndOwner, szPath, csidl, bCreate);
1073 /*************************************************************************
1074 * SHGetFolderPathA [SHFOLDER.@]
1076 HRESULT WINAPI SHGetFolderPathA(
1077 HWND hwndOwner,
1078 int nFolder,
1079 HANDLE hToken, /* [in] FIXME: get paths for specific user */
1080 DWORD dwFlags, /* [in] FIXME: SHGFP_TYPE_CURRENT|SHGFP_TYPE_DEFAULT */
1081 LPSTR pszPath)
1083 return (SHGetSpecialFolderPathA(
1084 hwndOwner,
1085 pszPath,
1086 CSIDL_FOLDER_MASK & nFolder,
1087 CSIDL_FLAG_CREATE & nFolder )) ? S_OK : E_FAIL;
1090 /*************************************************************************
1091 * SHGetFolderPathW [SHFOLDER.@]
1093 HRESULT WINAPI SHGetFolderPathW(
1094 HWND hwndOwner,
1095 int nFolder,
1096 HANDLE hToken,
1097 DWORD dwFlags,
1098 LPWSTR pszPath)
1100 return (SHGetSpecialFolderPathW(
1101 hwndOwner,
1102 pszPath,
1103 CSIDL_FOLDER_MASK & nFolder,
1104 CSIDL_FLAG_CREATE & nFolder )) ? S_OK : E_FAIL;