SHGetSpecialFolderPathA must be able to create a full path if it
[wine.git] / dlls / shell32 / shellpath.c
blobe3e0d0bd7caaaab6b7ac5bc379eb71cfae1d5251
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);
23 ########## Combining and Constructing paths ##########
26 /*************************************************************************
27 * PathAppendAW [SHELL32.36]
29 BOOL WINAPI PathAppendAW(
30 LPVOID lpszPath1,
31 LPCVOID lpszPath2)
33 if (SHELL_OsIsUnicode())
34 return PathAppendW(lpszPath1, lpszPath2);
35 return PathAppendA(lpszPath1, lpszPath2);
38 /*************************************************************************
39 * PathCombineAW [SHELL32.37]
41 LPVOID WINAPI PathCombineAW(
42 LPVOID szDest,
43 LPCVOID lpszDir,
44 LPCVOID lpszFile)
46 if (SHELL_OsIsUnicode())
47 return PathCombineW( szDest, lpszDir, lpszFile );
48 return PathCombineA( szDest, lpszDir, lpszFile );
51 /*************************************************************************
52 * PathAddBackslashAW [SHELL32.32]
54 LPVOID WINAPI PathAddBackslashAW(LPVOID lpszPath)
56 if(SHELL_OsIsUnicode())
57 return PathAddBackslashW(lpszPath);
58 return PathAddBackslashA(lpszPath);
61 /*************************************************************************
62 * PathBuildRootAW [SHELL32.30]
64 LPVOID WINAPI PathBuildRootAW(LPVOID lpszPath, int drive)
66 if(SHELL_OsIsUnicode())
67 return PathBuildRootW(lpszPath, drive);
68 return PathBuildRootA(lpszPath, drive);
72 Extracting Component Parts
75 /*************************************************************************
76 * PathFindFileNameAW [SHELL32.34]
78 LPVOID WINAPI PathFindFileNameAW(LPCVOID lpszPath)
80 if(SHELL_OsIsUnicode())
81 return PathFindFileNameW(lpszPath);
82 return PathFindFileNameA(lpszPath);
85 /*************************************************************************
86 * PathFindExtensionAW [SHELL32.31]
88 LPVOID WINAPI PathFindExtensionAW(LPCVOID lpszPath)
90 if (SHELL_OsIsUnicode())
91 return PathFindExtensionW(lpszPath);
92 return PathFindExtensionA(lpszPath);
96 /*************************************************************************
97 * PathGetExtensionA [internal]
99 * NOTES
100 * exported by ordinal
101 * return value points to the first char after the dot
103 static LPSTR PathGetExtensionA(LPCSTR lpszPath)
105 TRACE("(%s)\n",lpszPath);
107 lpszPath = PathFindExtensionA(lpszPath);
108 return (LPSTR)(*lpszPath?(lpszPath+1):lpszPath);
111 /*************************************************************************
112 * PathGetExtensionW [internal]
114 static LPWSTR PathGetExtensionW(LPCWSTR lpszPath)
116 TRACE("(%s)\n",debugstr_w(lpszPath));
118 lpszPath = PathFindExtensionW(lpszPath);
119 return (LPWSTR)(*lpszPath?(lpszPath+1):lpszPath);
122 /*************************************************************************
123 * PathGetExtensionAW [SHELL32.158]
125 LPVOID WINAPI PathGetExtensionAW(LPCVOID lpszPath)
127 if (SHELL_OsIsUnicode())
128 return PathGetExtensionW(lpszPath);
129 return PathGetExtensionA(lpszPath);
132 /*************************************************************************
133 * PathGetArgsAW [SHELL32.52]
135 LPVOID WINAPI PathGetArgsAW(LPVOID lpszPath)
137 if (SHELL_OsIsUnicode())
138 return PathGetArgsW(lpszPath);
139 return PathGetArgsA(lpszPath);
142 /*************************************************************************
143 * PathGetDriveNumber [SHELL32.57]
145 int WINAPI PathGetDriveNumberAW(LPVOID lpszPath)
147 if (SHELL_OsIsUnicode())
148 return PathGetDriveNumberW(lpszPath);
149 return PathGetDriveNumberA(lpszPath);
152 /*************************************************************************
153 * PathRemoveFileSpec [SHELL32.35]
155 BOOL WINAPI PathRemoveFileSpecAW(LPVOID lpszPath)
157 if (SHELL_OsIsUnicode())
158 return PathRemoveFileSpecW(lpszPath);
159 return PathRemoveFileSpecA(lpszPath);
162 /*************************************************************************
163 * PathStripPathAW [SHELL32.38]
165 void WINAPI PathStripPathAW(LPVOID lpszPath)
167 if (SHELL_OsIsUnicode())
168 return PathStripPathW(lpszPath);
169 return PathStripPathA(lpszPath);
172 /*************************************************************************
173 * PathStripToRootAW [SHELL32.50]
175 BOOL WINAPI PathStripToRootAW(LPVOID lpszPath)
177 if (SHELL_OsIsUnicode())
178 return PathStripToRootW(lpszPath);
179 return PathStripToRootA(lpszPath);
182 /*************************************************************************
183 * PathRemoveArgsAW [SHELL32.251]
185 void WINAPI PathRemoveArgsAW(LPVOID lpszPath)
187 if (SHELL_OsIsUnicode())
188 PathRemoveArgsW(lpszPath);
189 PathRemoveArgsA(lpszPath);
192 /*************************************************************************
193 * PathRemoveExtensionAW [SHELL32.250]
195 void WINAPI PathRemoveExtensionAW(LPVOID lpszPath)
197 if (SHELL_OsIsUnicode())
198 return PathRemoveExtensionW(lpszPath);
199 return PathRemoveExtensionA(lpszPath);
204 Path Manipulations
207 /*************************************************************************
208 * PathGetShortPathA [internal]
210 LPSTR WINAPI PathGetShortPathA(LPSTR lpszPath)
212 FIXME("%s stub\n", lpszPath);
213 return NULL;
216 /*************************************************************************
217 * PathGetShortPathW [internal]
219 LPWSTR WINAPI PathGetShortPathW(LPWSTR lpszPath)
221 FIXME("%s stub\n", debugstr_w(lpszPath));
222 return NULL;
225 /*************************************************************************
226 * PathGetShortPathAW [SHELL32.92]
228 LPVOID WINAPI PathGetShortPathAW(LPVOID lpszPath)
230 if(SHELL_OsIsUnicode())
231 return PathGetShortPathW(lpszPath);
232 return PathGetShortPathA(lpszPath);
235 /*************************************************************************
236 * PathRemoveBlanksAW [SHELL32.33]
238 void WINAPI PathRemoveBlanksAW(LPVOID str)
240 if(SHELL_OsIsUnicode())
241 PathRemoveBlanksW(str);
242 PathRemoveBlanksA(str);
245 /*************************************************************************
246 * PathQuoteSpacesAW [SHELL32.55]
248 LPVOID WINAPI PathQuoteSpacesAW (LPVOID lpszPath)
250 if(SHELL_OsIsUnicode())
251 return PathQuoteSpacesW(lpszPath);
252 return PathQuoteSpacesA(lpszPath);
255 /*************************************************************************
256 * PathUnquoteSpacesAW [SHELL32.56]
258 VOID WINAPI PathUnquoteSpacesAW(LPVOID str)
260 if(SHELL_OsIsUnicode())
261 PathUnquoteSpacesW(str);
262 else
263 PathUnquoteSpacesA(str);
266 /*************************************************************************
267 * PathParseIconLocationAW [SHELL32.249]
269 int WINAPI PathParseIconLocationAW (LPVOID lpszPath)
271 if(SHELL_OsIsUnicode())
272 return PathParseIconLocationW(lpszPath);
273 return PathParseIconLocationA(lpszPath);
277 ########## Path Testing ##########
279 /*************************************************************************
280 * PathIsUNCAW [SHELL32.39]
282 BOOL WINAPI PathIsUNCAW (LPCVOID lpszPath)
284 if (SHELL_OsIsUnicode())
285 return PathIsUNCW( lpszPath );
286 return PathIsUNCA( lpszPath );
289 /*************************************************************************
290 * PathIsRelativeAW [SHELL32.40]
292 BOOL WINAPI PathIsRelativeAW (LPCVOID lpszPath)
294 if (SHELL_OsIsUnicode())
295 return PathIsRelativeW( lpszPath );
296 return PathIsRelativeA( lpszPath );
299 /*************************************************************************
300 * PathIsRootAW [SHELL32.29]
302 BOOL WINAPI PathIsRootAW(LPCVOID lpszPath)
304 if (SHELL_OsIsUnicode())
305 return PathIsRootW(lpszPath);
306 return PathIsRootA(lpszPath);
309 /*************************************************************************
310 * PathIsExeA [internal]
312 static BOOL PathIsExeA (LPCSTR lpszPath)
314 LPCSTR lpszExtension = PathGetExtensionA(lpszPath);
315 int i = 0;
316 static char * lpszExtensions[6] = {"exe", "com", "pid", "cmd", "bat", NULL };
318 TRACE("path=%s\n",lpszPath);
320 for(i=0; lpszExtensions[i]; i++)
321 if (!strcasecmp(lpszExtension,lpszExtensions[i])) return TRUE;
323 return FALSE;
326 /*************************************************************************
327 * PathIsExeW [internal]
329 static BOOL PathIsExeW (LPCWSTR lpszPath)
331 LPCWSTR lpszExtension = PathGetExtensionW(lpszPath);
332 int i = 0;
333 static WCHAR lpszExtensions[6][4] =
334 {{'e','x','e','\0'}, {'c','o','m','\0'}, {'p','i','d','\0'},
335 {'c','m','d','\0'}, {'b','a','t','\0'}, {'\0'} };
337 TRACE("path=%s\n",debugstr_w(lpszPath));
339 for(i=0; lpszExtensions[i]; i++)
340 if (!strcmpiW(lpszExtension,lpszExtensions[i])) return TRUE;
342 return FALSE;
345 /*************************************************************************
346 * PathIsExeAW [SHELL32.43]
348 BOOL WINAPI PathIsExeAW (LPCVOID path)
350 if (SHELL_OsIsUnicode())
351 return PathIsExeW (path);
352 return PathIsExeA(path);
355 /*************************************************************************
356 * PathIsDirectoryAW [SHELL32.159]
358 BOOL WINAPI PathIsDirectoryAW (LPCVOID lpszPath)
360 if (SHELL_OsIsUnicode())
361 return PathIsDirectoryW (lpszPath);
362 return PathIsDirectoryA (lpszPath);
365 /*************************************************************************
366 * PathFileExistsAW [SHELL32.45]
368 BOOL WINAPI PathFileExistsAW (LPCVOID lpszPath)
370 if (SHELL_OsIsUnicode())
371 return PathFileExistsW (lpszPath);
372 return PathFileExistsA (lpszPath);
375 /*************************************************************************
376 * PathMatchSpecAW [SHELL32.46]
378 BOOL WINAPI PathMatchSpecAW(LPVOID name, LPVOID mask)
380 if (SHELL_OsIsUnicode())
381 return PathMatchSpecW( name, mask );
382 return PathMatchSpecA( name, mask );
385 /*************************************************************************
386 * PathIsSameRootAW [SHELL32.650]
388 BOOL WINAPI PathIsSameRootAW(LPCVOID lpszPath1, LPCVOID lpszPath2)
390 if (SHELL_OsIsUnicode())
391 return PathIsSameRootW(lpszPath1, lpszPath2);
392 return PathIsSameRootA(lpszPath1, lpszPath2);
395 /*************************************************************************
396 * IsLFNDriveA [SHELL32.119]
398 * NOTES
399 * exported by ordinal Name
401 BOOL WINAPI IsLFNDriveA(LPCSTR lpszPath)
403 DWORD fnlen;
405 if (!GetVolumeInformationA(lpszPath,NULL,0,NULL,&fnlen,NULL,NULL,0))
406 return FALSE;
407 return fnlen>12;
411 ########## Creating Something Unique ##########
413 /*************************************************************************
414 * PathMakeUniqueNameA [internal]
416 BOOL WINAPI PathMakeUniqueNameA(
417 LPSTR lpszBuffer,
418 DWORD dwBuffSize,
419 LPCSTR lpszShortName,
420 LPCSTR lpszLongName,
421 LPCSTR lpszPathName)
423 FIXME("%p %lu %s %s %s stub\n",
424 lpszBuffer, dwBuffSize, debugstr_a(lpszShortName),
425 debugstr_a(lpszLongName), debugstr_a(lpszPathName));
426 return TRUE;
429 /*************************************************************************
430 * PathMakeUniqueNameW [internal]
432 BOOL WINAPI PathMakeUniqueNameW(
433 LPWSTR lpszBuffer,
434 DWORD dwBuffSize,
435 LPCWSTR lpszShortName,
436 LPCWSTR lpszLongName,
437 LPCWSTR lpszPathName)
439 FIXME("%p %lu %s %s %s stub\n",
440 lpszBuffer, dwBuffSize, debugstr_w(lpszShortName),
441 debugstr_w(lpszLongName), debugstr_w(lpszPathName));
442 return TRUE;
445 /*************************************************************************
446 * PathMakeUniqueNameAW [SHELL32.47]
448 BOOL WINAPI PathMakeUniqueNameAW(
449 LPVOID lpszBuffer,
450 DWORD dwBuffSize,
451 LPCVOID lpszShortName,
452 LPCVOID lpszLongName,
453 LPCVOID lpszPathName)
455 if (SHELL_OsIsUnicode())
456 return PathMakeUniqueNameW(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
457 return PathMakeUniqueNameA(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
460 /*************************************************************************
461 * PathYetAnotherMakeUniqueNameA [SHELL32.75]
463 * NOTES
464 * exported by ordinal
466 BOOL WINAPI PathYetAnotherMakeUniqueNameA(
467 LPSTR lpszBuffer,
468 LPCSTR lpszPathName,
469 LPCSTR lpszShortName,
470 LPCSTR lpszLongName)
472 FIXME("(%p,%p, %p ,%p):stub.\n",
473 lpszBuffer, lpszPathName, lpszShortName, lpszLongName);
474 return TRUE;
479 ########## cleaning and resolving paths ##########
482 /*************************************************************************
483 * PathFindOnPathAW [SHELL32]
485 BOOL WINAPI PathFindOnPathAW(LPVOID sFile, LPCVOID sOtherDirs)
487 if (SHELL_OsIsUnicode())
488 return PathFindOnPathW(sFile, sOtherDirs);
489 return PathFindOnPathA(sFile, sOtherDirs);
492 /*************************************************************************
493 * PathCleanupSpecAW [SHELL32]
495 DWORD WINAPI PathCleanupSpecAW (LPCVOID x, LPVOID y)
497 FIXME("(%p, %p) stub\n",x,y);
498 return TRUE;
501 /*************************************************************************
502 * PathQualifyA [SHELL32]
504 BOOL WINAPI PathQualifyA(LPCSTR pszPath)
506 FIXME("%s\n",pszPath);
507 return 0;
510 /*************************************************************************
511 * PathQualifyW [SHELL32]
513 BOOL WINAPI PathQualifyW(LPCWSTR pszPath)
515 FIXME("%s\n",debugstr_w(pszPath));
516 return 0;
519 /*************************************************************************
520 * PathQualifyAW [SHELL32]
522 BOOL WINAPI PathQualifyAW(LPCVOID pszPath)
524 if (SHELL_OsIsUnicode())
525 return PathQualifyW(pszPath);
526 return PathQualifyA(pszPath);
529 /*************************************************************************
530 * PathResolveA [SHELL32.51]
532 BOOL WINAPI PathResolveA(
533 LPSTR lpszPath,
534 LPCSTR *alpszPaths,
535 DWORD dwFlags)
537 FIXME("(%s,%p,0x%08lx),stub!\n",
538 lpszPath, *alpszPaths, dwFlags);
539 return 0;
542 /*************************************************************************
543 * PathResolveW [SHELL32]
545 BOOL WINAPI PathResolveW(
546 LPWSTR lpszPath,
547 LPCWSTR *alpszPaths,
548 DWORD dwFlags)
550 FIXME("(%s,%p,0x%08lx),stub!\n",
551 debugstr_w(lpszPath), debugstr_w(*alpszPaths), dwFlags);
552 return 0;
555 /*************************************************************************
556 * PathResolveAW [SHELL32]
558 BOOL WINAPI PathResolveAW(
559 LPVOID lpszPath,
560 LPCVOID *alpszPaths,
561 DWORD dwFlags)
563 if (SHELL_OsIsUnicode())
564 return PathResolveW(lpszPath, (LPCWSTR*)alpszPaths, dwFlags);
565 return PathResolveA(lpszPath, (LPCSTR*)alpszPaths, dwFlags);
568 /*************************************************************************
569 * PathProcessCommandA [SHELL32.653]
571 HRESULT WINAPI PathProcessCommandA (
572 LPCSTR lpszPath,
573 LPSTR lpszBuff,
574 DWORD dwBuffSize,
575 DWORD dwFlags)
577 FIXME("%s %p 0x%04lx 0x%04lx stub\n",
578 lpszPath, lpszBuff, dwBuffSize, dwFlags);
579 strcpy(lpszBuff, lpszPath);
580 return 0;
583 /*************************************************************************
584 * PathProcessCommandW
586 HRESULT WINAPI PathProcessCommandW (
587 LPCWSTR lpszPath,
588 LPWSTR lpszBuff,
589 DWORD dwBuffSize,
590 DWORD dwFlags)
592 FIXME("(%s, %p, 0x%04lx, 0x%04lx) stub\n",
593 debugstr_w(lpszPath), lpszBuff, dwBuffSize, dwFlags);
594 strcpyW(lpszBuff, lpszPath);
595 return 0;
598 /*************************************************************************
599 * PathProcessCommandAW
601 HRESULT WINAPI PathProcessCommandAW (
602 LPCVOID lpszPath,
603 LPVOID lpszBuff,
604 DWORD dwBuffSize,
605 DWORD dwFlags)
607 if (SHELL_OsIsUnicode())
608 return PathProcessCommandW(lpszPath, lpszBuff, dwBuffSize, dwFlags);
609 return PathProcessCommandA(lpszPath, lpszBuff, dwBuffSize, dwFlags);
613 ########## special ##########
616 /*************************************************************************
617 * PathSetDlgItemPathAW
619 BOOL WINAPI PathSetDlgItemPathAW(HWND hDlg, int id, LPCVOID pszPath)
620 { if (SHELL_OsIsUnicode())
621 return PathSetDlgItemPathW(hDlg, id, pszPath);
622 return PathSetDlgItemPathA(hDlg, id, pszPath);
626 /*************************************************************************
627 * SHGetSpecialFolderPathA [SHELL32.175]
629 * converts csidl to path
632 static const char * const szSHFolders = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
633 static const char * const szSHUserFolders = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders";
634 static const char * const szSetup = "Software\\Microsoft\\Windows\\CurrentVersion\\Setup";
635 static const char * const szCurrentVersion = "Software\\Microsoft\\Windows\\CurrentVersion";
636 #if 0
637 static const char * const szEnvUserProfile = "%USERPROFILE%";
638 static const char * const szEnvSystemRoot = "%SYSTEMROOT%";
639 #endif
641 typedef struct
643 DWORD dwFlags;
644 HKEY hRootKey;
645 LPCSTR szValueName;
646 LPCSTR szDefaultPath; /* fallback string; sub dir of windows directory */
647 } CSIDL_DATA;
649 #define CSIDL_MYFLAG_SHFOLDER 1
650 #define CSIDL_MYFLAG_SETUP 2
651 #define CSIDL_MYFLAG_CURRVER 4
652 #define CSIDL_MYFLAG_RELATIVE 8
654 #define HKLM HKEY_LOCAL_MACHINE
655 #define HKCU HKEY_CURRENT_USER
656 static const CSIDL_DATA CSIDL_Data[] =
658 { /* CSIDL_DESKTOP */
659 9, HKCU,
660 "Desktop",
661 "Desktop"
663 { /* CSIDL_INTERNET (??) */
664 0, 1, /* FIXME */
665 NULL,
666 NULL,
668 { /* CSIDL_PROGRAMS */
669 9, HKCU,
670 "Programs",
671 "Start Menu\\Programs"
673 { /* CSIDL_CONTROLS (.CPL files) */
674 10, HKLM,
675 "SysDir",
676 "SYSTEM"
678 { /* CSIDL_PRINTERS */
679 10, HKLM,
680 "SysDir",
681 "SYSTEM"
683 { /* CSIDL_PERSONAL */
684 1, HKCU,
685 "Personal",
686 "My Documents"
688 { /* CSIDL_FAVORITES */
689 9, HKCU,
690 "Favorites",
691 "Favorites"
693 { /* CSIDL_STARTUP */
694 9, HKCU,
695 "StartUp",
696 "Start Menu\\Programs\\StartUp"
698 { /* CSIDL_RECENT */
699 9, HKCU,
700 "Recent",
701 "Recent"
703 { /* CSIDL_SENDTO */
704 9, HKCU,
705 "SendTo",
706 "SendTo"
708 { /* CSIDL_BITBUCKET (is this c:\recycled ?) */
709 0, 1, /* FIXME */
710 NULL,
711 "recycled"
713 { /* CSIDL_STARTMENU */
714 9, HKCU,
715 "Start Menu",
716 "Start Menu"
718 { /* not known */
719 0, 0,
720 NULL,
721 NULL,
723 { /* not known */
724 0, 0,
725 NULL,
726 NULL,
728 { /* not known */
729 0, 0,
730 NULL,
731 NULL,
733 { /* not known */
734 0, 0,
735 NULL,
736 NULL,
738 { /* CSIDL_DESKTOPDIRECTORY */
739 9, HKCU,
740 "Desktop",
741 "Desktop"
743 { /* CSIDL_DRIVES */
744 0, 1, /* FIXME */
745 NULL,
746 "My Computer"
748 { /* CSIDL_NETWORK */
749 0, 1, /* FIXME */
750 NULL,
751 "Network Neighborhood"
753 { /* CSIDL_NETHOOD */
754 9, HKCU,
755 "NetHood",
756 "NetHood"
758 { /* CSIDL_FONTS */
759 9, HKCU,
760 "Fonts",
761 "Fonts"
763 { /* CSIDL_TEMPLATES */
764 9, HKCU,
765 "Templates",
766 "ShellNew"
768 { /* CSIDL_COMMON_STARTMENU */
769 9, HKLM,
770 "Common Start Menu",
771 "Start Menu"
773 { /* CSIDL_COMMON_PROGRAMS */
774 9, HKLM,
775 "Common Programs",
778 { /* CSIDL_COMMON_STARTUP */
779 9, HKLM,
780 "Common StartUp",
781 "All Users\\Start Menu\\Programs\\StartUp"
783 { /* CSIDL_COMMON_DESKTOPDIRECTORY */
784 9, HKLM,
785 "Common Desktop",
786 "Desktop"
788 { /* CSIDL_APPDATA */
789 9, HKCU,
790 "AppData",
791 "Application Data"
793 { /* CSIDL_PRINTHOOD */
794 9, HKCU,
795 "PrintHood",
796 "PrintHood"
798 { /* not known */
799 0, 0,
800 NULL,
801 NULL,
803 { /* CSIDL_ALTSTARTUP */
804 0, 1, /* FIXME */
805 NULL,
806 NULL
808 { /* CSIDL_COMMON_ALTSTARTUP */
809 0, 1, /* FIXME */
810 NULL,
811 NULL
813 { /* CSIDL_COMMON_FAVORITES */
814 9, HKCU,
815 "Favorites",
816 "Favorites"
818 { /* CSIDL_INTERNET_CACHE */
819 9, HKCU,
820 "Cache",
821 "Temporary Internet Files"
823 { /* CSIDL_COOKIES */
824 9, HKCU,
825 "Cookies",
826 "Cookies"
828 { /* CSIDL_HISTORY */
829 9, HKCU,
830 "History",
831 "History"
833 { /* CSIDL_COMMON_APPDATA */
834 9, HKLM,
835 "Common AppData",
836 "All Users\\Application Data"
838 { /* CSIDL_WINDOWS */
839 2, HKLM,
840 "WinDir",
841 "Windows"
843 { /* CSIDL_SYSTEM */
844 10, HKLM,
845 "SysDir",
846 "SYSTEM"
848 { /* CSIDL_PROGRAM_FILES */
849 4, HKLM,
850 "ProgramFilesDir",
851 "Program Files"
853 { /* CSIDL_MYPICTURES */
854 1, HKCU,
855 "My Pictures",
856 "My Documents\\My Pictures"
858 { /* CSIDL_PROFILE */
859 10, HKLM,
860 "WinDir", /* correct ? */
863 { /* CSIDL_SYSTEMX86 */
864 10, HKLM,
865 "SysDir",
866 "SYSTEM"
868 { /* CSIDL_PROGRAM_FILESX86 */
869 4, HKLM,
870 "ProgramFilesDir",
871 "Program Files"
873 { /* CSIDL_PROGRAM_FILES_COMMON */
874 4, HKLM,
875 "CommonFilesDir",
876 "Program Files\\Common Files" /* ? */
878 { /* CSIDL_PROGRAM_FILES_COMMONX86 */
879 4, HKLM,
880 "CommonFilesDir",
881 "Program Files\\Common Files" /* ? */
883 { /* CSIDL_COMMON_TEMPLATES */
884 0, 1, /* FIXME */
885 NULL,
886 NULL
888 { /* CSIDL_COMMON_DOCUMENTS */
889 0, 1, /* FIXME */
890 NULL,
891 NULL
893 { /* CSIDL_COMMON_ADMINTOOLS */
894 0, 1, /* FIXME */
895 NULL,
896 NULL
898 { /* CSIDL_ADMINTOOLS */
899 9, HKCU,
900 "Administrative Tools",
901 "Start Menu\\Programs\\Administrative Tools"
903 { /* CSIDL_CONNECTIONS */
904 0, 1, /* FIXME */
905 NULL,
906 NULL
909 #undef HKCU
910 #undef HKLM
912 /**********************************************************************/
914 BOOL WINAPI SHGetSpecialFolderPathA (
915 HWND hwndOwner,
916 LPSTR szPath,
917 DWORD csidl,
918 BOOL bCreate)
920 CHAR szValueName[MAX_PATH], szDefaultPath[MAX_PATH], szBuildPath[MAX_PATH];
921 HKEY hRootKey, hKey;
922 DWORD dwFlags;
923 DWORD dwType, dwDisp, dwPathLen = MAX_PATH;
924 DWORD folder = csidl & CSIDL_FOLDER_MASK;
925 CHAR *p;
927 TRACE("0x%04x,%p,csidl=%lu,0x%04x\n", hwndOwner,szPath,csidl,bCreate);
929 if ((folder > CSIDL_CONNECTIONS) || (CSIDL_Data[folder].hRootKey == 0))
931 ERR("folder unknown or not allowed\n");
932 return FALSE;
934 if (CSIDL_Data[folder].hRootKey == 1)
936 FIXME("folder unknown, please add.\n");
937 return FALSE;
940 dwFlags = CSIDL_Data[folder].dwFlags;
941 hRootKey = CSIDL_Data[folder].hRootKey;
942 strcpy(szValueName, CSIDL_Data[folder].szValueName);
943 strcpy(szDefaultPath, CSIDL_Data[folder].szDefaultPath);
945 if (dwFlags & CSIDL_MYFLAG_SHFOLDER)
947 /* user shell folders */
948 if (RegCreateKeyExA(hRootKey,szSHUserFolders,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return FALSE;
950 if (RegQueryValueExA(hKey,szValueName,NULL,&dwType,(LPBYTE)szPath,&dwPathLen))
952 RegCloseKey(hKey);
954 /* shell folders */
955 if (RegCreateKeyExA(hRootKey,szSHFolders,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return FALSE;
957 if (RegQueryValueExA(hKey,szValueName,NULL,&dwType,(LPBYTE)szPath,&dwPathLen))
960 /* value not existing */
961 if (dwFlags & CSIDL_MYFLAG_RELATIVE)
963 GetWindowsDirectoryA(szPath, MAX_PATH);
964 PathAddBackslashA(szPath);
965 strcat(szPath, szDefaultPath);
967 else
969 strcpy(szPath, "C:\\"); /* FIXME ??? */
970 strcat(szPath, szDefaultPath);
972 RegSetValueExA(hKey,szValueName,0,REG_SZ,(LPBYTE)szPath,strlen(szPath)+1);
975 RegCloseKey(hKey);
977 else
979 LPCSTR pRegPath;
981 if (dwFlags & CSIDL_MYFLAG_SETUP)
982 pRegPath = szSetup;
983 else
984 if (dwFlags & CSIDL_MYFLAG_CURRVER)
985 pRegPath = szCurrentVersion;
986 else
988 ERR("folder settings broken, please correct !\n");
989 return FALSE;
992 if (RegCreateKeyExA(hRootKey,pRegPath,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return FALSE;
994 if (RegQueryValueExA(hKey,szValueName,NULL,&dwType,(LPBYTE)szPath,&dwPathLen))
996 /* value not existing */
997 if (dwFlags & CSIDL_MYFLAG_RELATIVE)
999 GetWindowsDirectoryA(szPath, MAX_PATH);
1000 PathAddBackslashA(szPath);
1001 strcat(szPath, szDefaultPath);
1003 else
1005 strcpy(szPath, "C:\\"); /* FIXME ??? */
1006 strcat(szPath, szDefaultPath);
1008 RegSetValueExA(hKey,szValueName,0,REG_SZ,(LPBYTE)szPath,strlen(szPath)+1);
1010 RegCloseKey(hKey);
1013 /* expand paths like %USERPROFILE% */
1014 if (dwType == REG_EXPAND_SZ)
1016 ExpandEnvironmentStringsA(szPath, szDefaultPath, MAX_PATH);
1017 strcpy(szPath, szDefaultPath);
1020 /* if we don't care about existing directories we are ready */
1021 if(csidl & CSIDL_FLAG_DONT_VERIFY) return TRUE;
1023 if (PathFileExistsA(szPath)) return TRUE;
1025 /* not existing but we are not allowed to create it */
1026 if (!bCreate) return FALSE;
1028 /* create directory/directories */
1029 strcpy(szBuildPath, szPath);
1030 p = strchr(szBuildPath, '\\');
1031 while (p)
1033 *p = 0;
1034 if (!PathFileExistsA(szBuildPath))
1036 if (!CreateDirectoryA(szBuildPath,NULL))
1038 ERR("Failed to create directory '%s'.\n", szPath);
1039 return FALSE;
1042 *p = '\\';
1043 p = strchr(p+1, '\\');
1046 MESSAGE("Created not existing system directory '%s'\n", szPath);
1047 return TRUE;
1050 /*************************************************************************
1051 * SHGetSpecialFolderPathW
1053 BOOL WINAPI SHGetSpecialFolderPathW (
1054 HWND hwndOwner,
1055 LPWSTR szPath,
1056 DWORD csidl,
1057 BOOL bCreate)
1059 char szTemp[MAX_PATH];
1061 if (SHGetSpecialFolderPathA(hwndOwner, szTemp, csidl, bCreate))
1063 if (!MultiByteToWideChar( CP_ACP, 0, szTemp, -1, szPath, MAX_PATH ))
1064 szPath[MAX_PATH-1] = 0;
1067 TRACE("0x%04x,%p,csidl=%lu,0x%04x\n", hwndOwner,szPath,csidl,bCreate);
1069 return TRUE;
1072 /*************************************************************************
1073 * SHGetSpecialFolderPathAW
1075 BOOL WINAPI SHGetSpecialFolderPathAW (
1076 HWND hwndOwner,
1077 LPVOID szPath,
1078 DWORD csidl,
1079 BOOL bCreate)
1082 if (SHELL_OsIsUnicode())
1083 return SHGetSpecialFolderPathW (hwndOwner, szPath, csidl, bCreate);
1084 return SHGetSpecialFolderPathA (hwndOwner, szPath, csidl, bCreate);
1087 /*************************************************************************
1088 * SHGetFolderPathA [SHFOLDER.@]
1090 HRESULT WINAPI SHGetFolderPathA(
1091 HWND hwndOwner,
1092 int nFolder,
1093 HANDLE hToken, /* [in] FIXME: get paths for specific user */
1094 DWORD dwFlags, /* [in] FIXME: SHGFP_TYPE_CURRENT|SHGFP_TYPE_DEFAULT */
1095 LPSTR pszPath)
1097 return (SHGetSpecialFolderPathA(
1098 hwndOwner,
1099 pszPath,
1100 CSIDL_FOLDER_MASK & nFolder,
1101 CSIDL_FLAG_CREATE & nFolder )) ? S_OK : E_FAIL;
1104 /*************************************************************************
1105 * SHGetFolderPathW [SHFOLDER.@]
1107 HRESULT WINAPI SHGetFolderPathW(
1108 HWND hwndOwner,
1109 int nFolder,
1110 HANDLE hToken,
1111 DWORD dwFlags,
1112 LPWSTR pszPath)
1114 return (SHGetSpecialFolderPathW(
1115 hwndOwner,
1116 pszPath,
1117 CSIDL_FOLDER_MASK & nFolder,
1118 CSIDL_FLAG_CREATE & nFolder )) ? S_OK : E_FAIL;