- Moved actual code from SHGetSpecialFolderPathA to SHGetFolderPathW,
[wine/testsucceed.git] / dlls / shell32 / shellpath.c
blob66d4829be0ffcc4e0ae6a24b10a8f563e1a56560
1 /*
2 * Path Functions
4 * Copyright 1998, 1999, 2000 Juergen Schmied
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * NOTES:
22 * Many of these functions are in SHLWAPI.DLL also
26 #include "config.h"
27 #include "wine/port.h"
29 #include <stdarg.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include "wine/debug.h"
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winnls.h"
36 #include "winreg.h"
37 #include "wingdi.h"
38 #include "winuser.h"
40 #include "shlobj.h"
41 #include "shell32_main.h"
42 #include "undocshell.h"
43 #include "wine/unicode.h"
44 #include "shlwapi.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(shell);
49 ########## Combining and Constructing paths ##########
52 /*************************************************************************
53 * PathAppend [SHELL32.36]
55 BOOL WINAPI PathAppendAW(
56 LPVOID lpszPath1,
57 LPCVOID lpszPath2)
59 if (SHELL_OsIsUnicode())
60 return PathAppendW(lpszPath1, lpszPath2);
61 return PathAppendA(lpszPath1, lpszPath2);
64 /*************************************************************************
65 * PathCombine [SHELL32.37]
67 LPVOID WINAPI PathCombineAW(
68 LPVOID szDest,
69 LPCVOID lpszDir,
70 LPCVOID lpszFile)
72 if (SHELL_OsIsUnicode())
73 return PathCombineW( szDest, lpszDir, lpszFile );
74 return PathCombineA( szDest, lpszDir, lpszFile );
77 /*************************************************************************
78 * PathAddBackslash [SHELL32.32]
80 LPVOID WINAPI PathAddBackslashAW(LPVOID lpszPath)
82 if(SHELL_OsIsUnicode())
83 return PathAddBackslashW(lpszPath);
84 return PathAddBackslashA(lpszPath);
87 /*************************************************************************
88 * PathBuildRoot [SHELL32.30]
90 LPVOID WINAPI PathBuildRootAW(LPVOID lpszPath, int drive)
92 if(SHELL_OsIsUnicode())
93 return PathBuildRootW(lpszPath, drive);
94 return PathBuildRootA(lpszPath, drive);
98 Extracting Component Parts
101 /*************************************************************************
102 * PathFindFileName [SHELL32.34]
104 LPVOID WINAPI PathFindFileNameAW(LPCVOID lpszPath)
106 if(SHELL_OsIsUnicode())
107 return PathFindFileNameW(lpszPath);
108 return PathFindFileNameA(lpszPath);
111 /*************************************************************************
112 * PathFindExtension [SHELL32.31]
114 LPVOID WINAPI PathFindExtensionAW(LPCVOID lpszPath)
116 if (SHELL_OsIsUnicode())
117 return PathFindExtensionW(lpszPath);
118 return PathFindExtensionA(lpszPath);
122 /*************************************************************************
123 * PathGetExtensionA [internal]
125 * NOTES
126 * exported by ordinal
127 * return value points to the first char after the dot
129 static LPSTR PathGetExtensionA(LPCSTR lpszPath)
131 TRACE("(%s)\n",lpszPath);
133 lpszPath = PathFindExtensionA(lpszPath);
134 return (LPSTR)(*lpszPath?(lpszPath+1):lpszPath);
137 /*************************************************************************
138 * PathGetExtensionW [internal]
140 static LPWSTR PathGetExtensionW(LPCWSTR lpszPath)
142 TRACE("(%s)\n",debugstr_w(lpszPath));
144 lpszPath = PathFindExtensionW(lpszPath);
145 return (LPWSTR)(*lpszPath?(lpszPath+1):lpszPath);
148 /*************************************************************************
149 * PathGetExtension [SHELL32.158]
151 LPVOID WINAPI PathGetExtensionAW(LPCVOID lpszPath,DWORD void1, DWORD void2)
153 if (SHELL_OsIsUnicode())
154 return PathGetExtensionW(lpszPath);
155 return PathGetExtensionA(lpszPath);
158 /*************************************************************************
159 * PathGetArgs [SHELL32.52]
161 LPVOID WINAPI PathGetArgsAW(LPVOID lpszPath)
163 if (SHELL_OsIsUnicode())
164 return PathGetArgsW(lpszPath);
165 return PathGetArgsA(lpszPath);
168 /*************************************************************************
169 * PathGetDriveNumber [SHELL32.57]
171 int WINAPI PathGetDriveNumberAW(LPVOID lpszPath)
173 if (SHELL_OsIsUnicode())
174 return PathGetDriveNumberW(lpszPath);
175 return PathGetDriveNumberA(lpszPath);
178 /*************************************************************************
179 * PathRemoveFileSpec [SHELL32.35]
181 BOOL WINAPI PathRemoveFileSpecAW(LPVOID lpszPath)
183 if (SHELL_OsIsUnicode())
184 return PathRemoveFileSpecW(lpszPath);
185 return PathRemoveFileSpecA(lpszPath);
188 /*************************************************************************
189 * PathStripPath [SHELL32.38]
191 void WINAPI PathStripPathAW(LPVOID lpszPath)
193 if (SHELL_OsIsUnicode())
194 PathStripPathW(lpszPath);
195 else
196 PathStripPathA(lpszPath);
199 /*************************************************************************
200 * PathStripToRoot [SHELL32.50]
202 BOOL WINAPI PathStripToRootAW(LPVOID lpszPath)
204 if (SHELL_OsIsUnicode())
205 return PathStripToRootW(lpszPath);
206 return PathStripToRootA(lpszPath);
209 /*************************************************************************
210 * PathRemoveArgs [SHELL32.251]
212 void WINAPI PathRemoveArgsAW(LPVOID lpszPath)
214 if (SHELL_OsIsUnicode())
215 PathRemoveArgsW(lpszPath);
216 else
217 PathRemoveArgsA(lpszPath);
220 /*************************************************************************
221 * PathRemoveExtension [SHELL32.250]
223 void WINAPI PathRemoveExtensionAW(LPVOID lpszPath)
225 if (SHELL_OsIsUnicode())
226 PathRemoveExtensionW(lpszPath);
227 else
228 PathRemoveExtensionA(lpszPath);
233 Path Manipulations
236 /*************************************************************************
237 * PathGetShortPathA [internal]
239 LPSTR WINAPI PathGetShortPathA(LPSTR lpszPath)
241 FIXME("%s stub\n", lpszPath);
242 return NULL;
245 /*************************************************************************
246 * PathGetShortPathW [internal]
248 LPWSTR WINAPI PathGetShortPathW(LPWSTR lpszPath)
250 FIXME("%s stub\n", debugstr_w(lpszPath));
251 return NULL;
254 /*************************************************************************
255 * PathGetShortPath [SHELL32.92]
257 LPVOID WINAPI PathGetShortPathAW(LPVOID lpszPath)
259 if(SHELL_OsIsUnicode())
260 return PathGetShortPathW(lpszPath);
261 return PathGetShortPathA(lpszPath);
264 /*************************************************************************
265 * PathRemoveBlanks [SHELL32.33]
267 void WINAPI PathRemoveBlanksAW(LPVOID str)
269 if(SHELL_OsIsUnicode())
270 PathRemoveBlanksW(str);
271 else
272 PathRemoveBlanksA(str);
275 /*************************************************************************
276 * PathQuoteSpaces [SHELL32.55]
278 VOID WINAPI PathQuoteSpacesAW (LPVOID lpszPath)
280 if(SHELL_OsIsUnicode())
281 PathQuoteSpacesW(lpszPath);
282 else
283 PathQuoteSpacesA(lpszPath);
286 /*************************************************************************
287 * PathUnquoteSpaces [SHELL32.56]
289 VOID WINAPI PathUnquoteSpacesAW(LPVOID str)
291 if(SHELL_OsIsUnicode())
292 PathUnquoteSpacesW(str);
293 else
294 PathUnquoteSpacesA(str);
297 /*************************************************************************
298 * PathParseIconLocation [SHELL32.249]
300 int WINAPI PathParseIconLocationAW (LPVOID lpszPath)
302 if(SHELL_OsIsUnicode())
303 return PathParseIconLocationW(lpszPath);
304 return PathParseIconLocationA(lpszPath);
308 ########## Path Testing ##########
310 /*************************************************************************
311 * PathIsUNC [SHELL32.39]
313 BOOL WINAPI PathIsUNCAW (LPCVOID lpszPath)
315 if (SHELL_OsIsUnicode())
316 return PathIsUNCW( lpszPath );
317 return PathIsUNCA( lpszPath );
320 /*************************************************************************
321 * PathIsRelative [SHELL32.40]
323 BOOL WINAPI PathIsRelativeAW (LPCVOID lpszPath)
325 if (SHELL_OsIsUnicode())
326 return PathIsRelativeW( lpszPath );
327 return PathIsRelativeA( lpszPath );
330 /*************************************************************************
331 * PathIsRoot [SHELL32.29]
333 BOOL WINAPI PathIsRootAW(LPCVOID lpszPath)
335 if (SHELL_OsIsUnicode())
336 return PathIsRootW(lpszPath);
337 return PathIsRootA(lpszPath);
340 /*************************************************************************
341 * PathIsExeA [internal]
343 static BOOL PathIsExeA (LPCSTR lpszPath)
345 LPCSTR lpszExtension = PathGetExtensionA(lpszPath);
346 int i;
347 static const char * const lpszExtensions[] =
348 {"exe", "com", "pif", "cmd", "bat", "scf", "scr", NULL };
350 TRACE("path=%s\n",lpszPath);
352 for(i=0; lpszExtensions[i]; i++)
353 if (!strcasecmp(lpszExtension,lpszExtensions[i])) return TRUE;
355 return FALSE;
358 /*************************************************************************
359 * PathIsExeW [internal]
361 static BOOL PathIsExeW (LPCWSTR lpszPath)
363 LPCWSTR lpszExtension = PathGetExtensionW(lpszPath);
364 int i;
365 static const WCHAR lpszExtensions[][4] =
366 {{'e','x','e','\0'}, {'c','o','m','\0'}, {'p','i','f','\0'},
367 {'c','m','d','\0'}, {'b','a','t','\0'}, {'s','c','f','\0'},
368 {'s','c','r','\0'}, {'\0'} };
370 TRACE("path=%s\n",debugstr_w(lpszPath));
372 for(i=0; lpszExtensions[i][0]; i++)
373 if (!strcmpiW(lpszExtension,lpszExtensions[i])) return TRUE;
375 return FALSE;
378 /*************************************************************************
379 * PathIsExe [SHELL32.43]
381 BOOL WINAPI PathIsExeAW (LPCVOID path)
383 if (SHELL_OsIsUnicode())
384 return PathIsExeW (path);
385 return PathIsExeA(path);
388 /*************************************************************************
389 * PathIsDirectory [SHELL32.159]
391 BOOL WINAPI PathIsDirectoryAW (LPCVOID lpszPath)
393 if (SHELL_OsIsUnicode())
394 return PathIsDirectoryW (lpszPath);
395 return PathIsDirectoryA (lpszPath);
398 /*************************************************************************
399 * PathFileExists [SHELL32.45]
401 BOOL WINAPI PathFileExistsAW (LPCVOID lpszPath)
403 if (SHELL_OsIsUnicode())
404 return PathFileExistsW (lpszPath);
405 return PathFileExistsA (lpszPath);
408 /*************************************************************************
409 * PathMatchSpec [SHELL32.46]
411 BOOL WINAPI PathMatchSpecAW(LPVOID name, LPVOID mask)
413 if (SHELL_OsIsUnicode())
414 return PathMatchSpecW( name, mask );
415 return PathMatchSpecA( name, mask );
418 /*************************************************************************
419 * PathIsSameRoot [SHELL32.650]
421 BOOL WINAPI PathIsSameRootAW(LPCVOID lpszPath1, LPCVOID lpszPath2)
423 if (SHELL_OsIsUnicode())
424 return PathIsSameRootW(lpszPath1, lpszPath2);
425 return PathIsSameRootA(lpszPath1, lpszPath2);
428 /*************************************************************************
429 * IsLFNDriveA [SHELL32.41]
431 BOOL WINAPI IsLFNDriveA(LPCSTR lpszPath)
433 DWORD fnlen;
435 if (!GetVolumeInformationA(lpszPath, NULL, 0, NULL, &fnlen, NULL, NULL, 0))
436 return FALSE;
437 return fnlen > 12;
440 /*************************************************************************
441 * IsLFNDriveW [SHELL32.42]
443 BOOL WINAPI IsLFNDriveW(LPCWSTR lpszPath)
445 DWORD fnlen;
447 if (!GetVolumeInformationW(lpszPath, NULL, 0, NULL, &fnlen, NULL, NULL, 0))
448 return FALSE;
449 return fnlen > 12;
452 /*************************************************************************
453 * IsLFNDrive [SHELL32.119]
455 BOOL WINAPI IsLFNDriveAW(LPCVOID lpszPath)
457 if (SHELL_OsIsUnicode())
458 return IsLFNDriveW(lpszPath);
459 return IsLFNDriveA(lpszPath);
463 ########## Creating Something Unique ##########
465 /*************************************************************************
466 * PathMakeUniqueNameA [internal]
468 BOOL WINAPI PathMakeUniqueNameA(
469 LPSTR lpszBuffer,
470 DWORD dwBuffSize,
471 LPCSTR lpszShortName,
472 LPCSTR lpszLongName,
473 LPCSTR lpszPathName)
475 FIXME("%p %lu %s %s %s stub\n",
476 lpszBuffer, dwBuffSize, debugstr_a(lpszShortName),
477 debugstr_a(lpszLongName), debugstr_a(lpszPathName));
478 return TRUE;
481 /*************************************************************************
482 * PathMakeUniqueNameW [internal]
484 BOOL WINAPI PathMakeUniqueNameW(
485 LPWSTR lpszBuffer,
486 DWORD dwBuffSize,
487 LPCWSTR lpszShortName,
488 LPCWSTR lpszLongName,
489 LPCWSTR lpszPathName)
491 FIXME("%p %lu %s %s %s stub\n",
492 lpszBuffer, dwBuffSize, debugstr_w(lpszShortName),
493 debugstr_w(lpszLongName), debugstr_w(lpszPathName));
494 return TRUE;
497 /*************************************************************************
498 * PathMakeUniqueName [SHELL32.47]
500 BOOL WINAPI PathMakeUniqueNameAW(
501 LPVOID lpszBuffer,
502 DWORD dwBuffSize,
503 LPCVOID lpszShortName,
504 LPCVOID lpszLongName,
505 LPCVOID lpszPathName)
507 if (SHELL_OsIsUnicode())
508 return PathMakeUniqueNameW(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
509 return PathMakeUniqueNameA(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
512 /*************************************************************************
513 * PathYetAnotherMakeUniqueName [SHELL32.75]
515 * NOTES
516 * exported by ordinal
518 BOOL WINAPI PathYetAnotherMakeUniqueNameA(
519 LPSTR lpszBuffer,
520 LPCSTR lpszPathName,
521 LPCSTR lpszShortName,
522 LPCSTR lpszLongName)
524 FIXME("(%p,%p, %p ,%p):stub.\n",
525 lpszBuffer, lpszPathName, lpszShortName, lpszLongName);
526 return TRUE;
531 ########## cleaning and resolving paths ##########
534 /*************************************************************************
535 * PathFindOnPath [SHELL32.145]
537 BOOL WINAPI PathFindOnPathAW(LPVOID sFile, LPCVOID sOtherDirs)
539 if (SHELL_OsIsUnicode())
540 return PathFindOnPathW(sFile, (LPCWSTR *)sOtherDirs);
541 return PathFindOnPathA(sFile, (LPCSTR *)sOtherDirs);
544 /*************************************************************************
545 * PathCleanupSpec [SHELL32.171]
547 DWORD WINAPI PathCleanupSpecAW (LPCVOID x, LPVOID y)
549 FIXME("(%p, %p) stub\n",x,y);
550 return TRUE;
553 /*************************************************************************
554 * PathQualifyA [SHELL32]
556 BOOL WINAPI PathQualifyA(LPCSTR pszPath)
558 FIXME("%s\n",pszPath);
559 return 0;
562 /*************************************************************************
563 * PathQualifyW [SHELL32]
565 BOOL WINAPI PathQualifyW(LPCWSTR pszPath)
567 FIXME("%s\n",debugstr_w(pszPath));
568 return 0;
571 /*************************************************************************
572 * PathQualify [SHELL32.49]
574 BOOL WINAPI PathQualifyAW(LPCVOID pszPath)
576 if (SHELL_OsIsUnicode())
577 return PathQualifyW(pszPath);
578 return PathQualifyA(pszPath);
581 /*************************************************************************
582 * PathResolveA [SHELL32.51]
584 BOOL WINAPI PathResolveA(
585 LPSTR lpszPath,
586 LPCSTR *alpszPaths,
587 DWORD dwFlags)
589 FIXME("(%s,%p,0x%08lx),stub!\n",
590 lpszPath, *alpszPaths, dwFlags);
591 return 0;
594 /*************************************************************************
595 * PathResolveW [SHELL32]
597 BOOL WINAPI PathResolveW(
598 LPWSTR lpszPath,
599 LPCWSTR *alpszPaths,
600 DWORD dwFlags)
602 FIXME("(%s,%p,0x%08lx),stub!\n",
603 debugstr_w(lpszPath), debugstr_w(*alpszPaths), dwFlags);
604 return 0;
607 /*************************************************************************
608 * PathResolve [SHELL32.51]
610 BOOL WINAPI PathResolveAW(
611 LPVOID lpszPath,
612 LPCVOID *alpszPaths,
613 DWORD dwFlags)
615 if (SHELL_OsIsUnicode())
616 return PathResolveW(lpszPath, (LPCWSTR*)alpszPaths, dwFlags);
617 return PathResolveA(lpszPath, (LPCSTR*)alpszPaths, dwFlags);
620 /*************************************************************************
621 * PathProcessCommandA [SHELL32.653]
623 HRESULT WINAPI PathProcessCommandA (
624 LPCSTR lpszPath,
625 LPSTR lpszBuff,
626 DWORD dwBuffSize,
627 DWORD dwFlags)
629 FIXME("%s %p 0x%04lx 0x%04lx stub\n",
630 lpszPath, lpszBuff, dwBuffSize, dwFlags);
631 strcpy(lpszBuff, lpszPath);
632 return 0;
635 /*************************************************************************
636 * PathProcessCommandW
638 HRESULT WINAPI PathProcessCommandW (
639 LPCWSTR lpszPath,
640 LPWSTR lpszBuff,
641 DWORD dwBuffSize,
642 DWORD dwFlags)
644 FIXME("(%s, %p, 0x%04lx, 0x%04lx) stub\n",
645 debugstr_w(lpszPath), lpszBuff, dwBuffSize, dwFlags);
646 strcpyW(lpszBuff, lpszPath);
647 return 0;
650 /*************************************************************************
651 * PathProcessCommand (SHELL32.653)
653 HRESULT WINAPI PathProcessCommandAW (
654 LPCVOID lpszPath,
655 LPVOID lpszBuff,
656 DWORD dwBuffSize,
657 DWORD dwFlags)
659 if (SHELL_OsIsUnicode())
660 return PathProcessCommandW(lpszPath, lpszBuff, dwBuffSize, dwFlags);
661 return PathProcessCommandA(lpszPath, lpszBuff, dwBuffSize, dwFlags);
665 ########## special ##########
668 /*************************************************************************
669 * PathSetDlgItemPath (SHELL32.48)
671 VOID WINAPI PathSetDlgItemPathAW(HWND hDlg, int id, LPCVOID pszPath)
673 if (SHELL_OsIsUnicode())
674 PathSetDlgItemPathW(hDlg, id, pszPath);
675 else
676 PathSetDlgItemPathA(hDlg, id, pszPath);
679 /*************************************************************************
680 * SHGetFolderPathW [SHELL32.@]
682 * converts csidl to path
685 static const WCHAR szSHFolders[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\\','S','h','e','l','l',' ','F','o','l','d','e','r','s','\0'};
686 static const WCHAR szSHUserFolders[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\\','U','s','e','r',' ','S','h','e','l','l',' ','F','o','l','d','e','r','s','\0'};
687 static const WCHAR szSetup[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\\','S','e','t','u','p','\0'};
688 static const WCHAR szCurrentVersion[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0'};
690 typedef struct
692 DWORD dwFlags;
693 HKEY hRootKey;
694 LPCSTR szValueName;
695 LPCSTR szDefaultPath; /* fallback string; sub dir of windows directory */
696 } CSIDL_DATA;
698 #define CSIDL_MYFLAG_SHFOLDER 1
699 #define CSIDL_MYFLAG_SETUP 2
700 #define CSIDL_MYFLAG_CURRVER 4
701 #define CSIDL_MYFLAG_RELATIVE 8
703 #define HKLM HKEY_LOCAL_MACHINE
704 #define HKCU HKEY_CURRENT_USER
705 static const CSIDL_DATA CSIDL_Data[] =
707 { /* CSIDL_DESKTOP */
708 9, HKCU,
709 "Desktop",
710 "Desktop"
712 { /* CSIDL_INTERNET */
713 0, (HKEY)1, /* FIXME */
714 NULL,
715 NULL,
717 { /* CSIDL_PROGRAMS */
718 9, HKCU,
719 "Programs",
720 "Start Menu\\Programs"
722 { /* CSIDL_CONTROLS (.CPL files) */
723 10, HKLM,
724 "SysDir",
725 "SYSTEM"
727 { /* CSIDL_PRINTERS */
728 10, HKLM,
729 "SysDir",
730 "SYSTEM"
732 { /* CSIDL_PERSONAL */
733 1, HKCU,
734 "Personal",
735 "My Documents"
737 { /* CSIDL_FAVORITES */
738 9, HKCU,
739 "Favorites",
740 "Favorites"
742 { /* CSIDL_STARTUP */
743 9, HKCU,
744 "StartUp",
745 "Start Menu\\Programs\\StartUp"
747 { /* CSIDL_RECENT */
748 9, HKCU,
749 "Recent",
750 "Recent"
752 { /* CSIDL_SENDTO */
753 9, HKCU,
754 "SendTo",
755 "SendTo"
757 { /* CSIDL_BITBUCKET (is this c:\recycled ?) */
758 0, (HKEY)1, /* FIXME */
759 NULL,
760 "recycled"
762 { /* CSIDL_STARTMENU */
763 9, HKCU,
764 "Start Menu",
765 "Start Menu"
767 { /* CSIDL_MYDOCUMENTS */
768 0, (HKEY)1, /* FIXME */
769 NULL,
770 NULL,
772 { /* CSIDL_MYMUSIC */
773 0, (HKEY)1, /* FIXME */
774 NULL,
775 NULL,
777 { /* CSIDL_MYVIDEO */
778 0, (HKEY)1, /* FIXME */
779 NULL,
780 NULL,
782 { /* unassigned */
783 0, 0,
784 NULL,
785 NULL,
787 { /* CSIDL_DESKTOPDIRECTORY */
788 9, HKCU,
789 "Desktop",
790 "Desktop"
792 { /* CSIDL_DRIVES */
793 0, (HKEY)1, /* FIXME */
794 NULL,
795 "My Computer"
797 { /* CSIDL_NETWORK */
798 0, (HKEY)1, /* FIXME */
799 NULL,
800 "Network Neighborhood"
802 { /* CSIDL_NETHOOD */
803 9, HKCU,
804 "NetHood",
805 "NetHood"
807 { /* CSIDL_FONTS */
808 9, HKCU,
809 "Fonts",
810 "Fonts"
812 { /* CSIDL_TEMPLATES */
813 9, HKCU,
814 "Templates",
815 "ShellNew"
817 { /* CSIDL_COMMON_STARTMENU */
818 9, HKLM,
819 "Common Start Menu",
820 "Start Menu"
822 { /* CSIDL_COMMON_PROGRAMS */
823 9, HKLM,
824 "Common Programs",
827 { /* CSIDL_COMMON_STARTUP */
828 9, HKLM,
829 "Common StartUp",
830 "All Users\\Start Menu\\Programs\\StartUp"
832 { /* CSIDL_COMMON_DESKTOPDIRECTORY */
833 9, HKLM,
834 "Common Desktop",
835 "Desktop"
837 { /* CSIDL_APPDATA */
838 9, HKCU,
839 "AppData",
840 "Application Data"
842 { /* CSIDL_PRINTHOOD */
843 9, HKCU,
844 "PrintHood",
845 "PrintHood"
847 { /* CSIDL_LOCAL_APPDATA (win2k only/undocumented) */
848 1, HKCU,
849 "Local AppData",
850 "Local Settings\\Application Data",
852 { /* CSIDL_ALTSTARTUP */
853 0, (HKEY)1, /* FIXME */
854 NULL,
855 NULL
857 { /* CSIDL_COMMON_ALTSTARTUP */
858 0, (HKEY)1, /* FIXME */
859 NULL,
860 NULL
862 { /* CSIDL_COMMON_FAVORITES */
863 9, HKCU,
864 "Favorites",
865 "Favorites"
867 { /* CSIDL_INTERNET_CACHE */
868 9, HKCU,
869 "Cache",
870 "Temporary Internet Files"
872 { /* CSIDL_COOKIES */
873 9, HKCU,
874 "Cookies",
875 "Cookies"
877 { /* CSIDL_HISTORY */
878 9, HKCU,
879 "History",
880 "History"
882 { /* CSIDL_COMMON_APPDATA */
883 9, HKLM,
884 "Common AppData",
885 "All Users\\Application Data"
887 { /* CSIDL_WINDOWS */
888 2, HKLM,
889 "WinDir",
890 "Windows"
892 { /* CSIDL_SYSTEM */
893 10, HKLM,
894 "SysDir",
895 "SYSTEM"
897 { /* CSIDL_PROGRAM_FILES */
898 4, HKLM,
899 "ProgramFilesDir",
900 "Program Files"
902 { /* CSIDL_MYPICTURES */
903 1, HKCU,
904 "My Pictures",
905 "My Documents\\My Pictures"
907 { /* CSIDL_PROFILE */
908 10, HKLM,
909 "WinDir", /* correct ? */
912 { /* CSIDL_SYSTEMX86 */
913 10, HKLM,
914 "SysDir",
915 "SYSTEM"
917 { /* CSIDL_PROGRAM_FILESX86 */
918 4, HKLM,
919 "ProgramFilesDir",
920 "Program Files"
922 { /* CSIDL_PROGRAM_FILES_COMMON */
923 4, HKLM,
924 "CommonFilesDir",
925 "Program Files\\Common Files" /* ? */
927 { /* CSIDL_PROGRAM_FILES_COMMONX86 */
928 4, HKLM,
929 "CommonFilesDir",
930 "Program Files\\Common Files" /* ? */
932 { /* CSIDL_COMMON_TEMPLATES */
933 0, (HKEY)1, /* FIXME */
934 NULL,
935 NULL
937 { /* CSIDL_COMMON_DOCUMENTS */
938 0, (HKEY)1, /* FIXME */
939 NULL,
940 NULL
942 { /* CSIDL_COMMON_ADMINTOOLS */
943 0, (HKEY)1, /* FIXME */
944 NULL,
945 NULL
947 { /* CSIDL_ADMINTOOLS */
948 9, HKCU,
949 "Administrative Tools",
950 "Start Menu\\Programs\\Administrative Tools"
952 { /* CSIDL_CONNECTIONS */
953 0, (HKEY)1, /* FIXME */
954 NULL,
955 NULL
957 { /* unassigned 32*/
958 0, 0,
959 NULL,
960 NULL,
962 { /* unassigned 33*/
963 0, 0,
964 NULL,
965 NULL,
967 { /* unassigned 34*/
968 0, 0,
969 NULL,
970 NULL,
972 { /* CSIDL_COMMON_MUSIC */
973 0, 0, /* FIXME */
974 NULL,
975 NULL,
977 { /* CSIDL_COMMON_PICTURES */
978 0, 0, /* FIXME */
979 NULL,
980 NULL,
982 { /* CSIDL_COMMON_VIDEO */
983 0, 0, /* FIXME */
984 NULL,
985 NULL,
987 { /* CSIDL_RESOURCES */
988 0, 0, /* FIXME */
989 NULL,
990 NULL,
992 { /* CSIDL_RESOURCES_LOCALIZED */
993 0, 0, /* FIXME */
994 NULL,
995 NULL,
997 { /* CSIDL_COMMON_OEM_LINKS */
998 0, 0, /* FIXME */
999 NULL,
1000 NULL,
1002 { /* CSIDL_CDBURN_AREA */
1003 0, 0, /* FIXME */
1004 NULL,
1005 NULL,
1007 { /* unassigned 3C */
1008 0, 0,
1009 NULL,
1010 NULL,
1012 { /* CSIDL_COMPUTERSNEARME */
1013 0, 0, /* FIXME */
1014 NULL,
1015 NULL,
1017 { /* CSIDL_PROFILES */
1018 0, 0, /* FIXME */
1019 NULL,
1020 NULL,
1023 #undef HKCU
1024 #undef HKLM
1026 HRESULT WINAPI SHGetFolderPathW(
1027 HWND hwndOwner,
1028 int csidl,
1029 HANDLE hToken, /* [in] FIXME: get paths for specific user */
1030 DWORD dwFlags, /* [in] FIXME: SHGFP_TYPE_CURRENT|SHGFP_TYPE_DEFAULT */
1031 LPWSTR pszPath)
1033 WCHAR szValueName[MAX_PATH], szDefaultPath[MAX_PATH], szBuildPath[MAX_PATH];
1034 HKEY hRootKey, hKey;
1035 DWORD dwCsidlFlags;
1036 DWORD dwType, dwDisp, dwPathLen = MAX_PATH;
1037 DWORD folder = csidl & CSIDL_FOLDER_MASK;
1038 WCHAR *p;
1040 TRACE("%p,%p,csidl=0x%04x\n", hwndOwner,pszPath,csidl);
1042 if ((folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0])) ||
1043 (CSIDL_Data[folder].hRootKey == 0))
1045 ERR("folder 0x%04lx unknown or not allowed\n", folder);
1046 return E_FAIL;
1048 if (CSIDL_Data[folder].hRootKey == (HKEY)1)
1050 FIXME("folder 0x%04lx unknown, please add.\n", folder);
1051 return E_FAIL;
1054 dwCsidlFlags = CSIDL_Data[folder].dwFlags;
1055 hRootKey = CSIDL_Data[folder].hRootKey;
1056 MultiByteToWideChar(CP_ACP, 0, CSIDL_Data[folder].szValueName, -1, szValueName, MAX_PATH);
1057 MultiByteToWideChar(CP_ACP, 0, CSIDL_Data[folder].szDefaultPath, -1, szDefaultPath, MAX_PATH);
1059 if (dwCsidlFlags & CSIDL_MYFLAG_SHFOLDER)
1061 /* user shell folders */
1062 if (RegCreateKeyExW(hRootKey,szSHUserFolders,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return E_FAIL;
1064 if (RegQueryValueExW(hKey,szValueName,NULL,&dwType,(LPBYTE)pszPath,&dwPathLen))
1066 RegCloseKey(hKey);
1068 /* shell folders */
1069 if (RegCreateKeyExW(hRootKey,szSHFolders,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return E_FAIL;
1071 if (RegQueryValueExW(hKey,szValueName,NULL,&dwType,(LPBYTE)pszPath,&dwPathLen))
1074 /* value not existing */
1075 if (dwCsidlFlags & CSIDL_MYFLAG_RELATIVE)
1077 GetWindowsDirectoryW(pszPath, MAX_PATH);
1078 PathAddBackslashW(pszPath);
1079 strcatW(pszPath, szDefaultPath);
1081 else
1083 GetSystemDirectoryW(pszPath, MAX_PATH);
1084 strcpyW(pszPath + 3, szDefaultPath);
1086 dwType=REG_SZ;
1087 RegSetValueExW(hKey,szValueName,0,REG_SZ,(LPBYTE)pszPath,strlenW(pszPath)+1);
1090 RegCloseKey(hKey);
1092 else
1094 LPCWSTR pRegPath;
1096 if (dwCsidlFlags & CSIDL_MYFLAG_SETUP)
1097 pRegPath = szSetup;
1098 else if (dwCsidlFlags & CSIDL_MYFLAG_CURRVER)
1099 pRegPath = szCurrentVersion;
1100 else
1102 ERR("folder settings broken, please correct !\n");
1103 return E_FAIL;
1106 if (RegCreateKeyExW(hRootKey,pRegPath,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return E_FAIL;
1108 if (RegQueryValueExW(hKey,szValueName,NULL,&dwType,(LPBYTE)pszPath,&dwPathLen))
1110 /* value not existing */
1111 if (dwCsidlFlags & CSIDL_MYFLAG_RELATIVE)
1113 GetWindowsDirectoryW(pszPath, MAX_PATH);
1114 PathAddBackslashW(pszPath);
1115 strcatW(pszPath, szDefaultPath);
1117 else
1119 GetSystemDirectoryW(pszPath, MAX_PATH);
1120 strcpyW(pszPath + 3, szDefaultPath);
1122 dwType=REG_SZ;
1123 RegSetValueExW(hKey,szValueName,0,REG_SZ,(LPBYTE)pszPath,strlenW(pszPath)+1);
1125 RegCloseKey(hKey);
1128 /* expand paths like %USERPROFILE% */
1129 if (dwType == REG_EXPAND_SZ)
1131 ExpandEnvironmentStringsW(pszPath, szDefaultPath, MAX_PATH);
1132 strcpyW(pszPath, szDefaultPath);
1135 /* if we don't care about existing directories we are ready */
1136 if(csidl & CSIDL_FLAG_DONT_VERIFY) return S_OK;
1138 if (PathFileExistsW(pszPath)) return S_OK;
1140 /* not existing but we are not allowed to create it */
1141 if (!(csidl & CSIDL_FLAG_CREATE)) return E_FAIL;
1143 /* create directory/directories */
1144 strcpyW(szBuildPath, pszPath);
1145 p = strchrW(szBuildPath, '\\');
1146 while (p)
1148 *p = 0;
1149 if (!PathFileExistsW(szBuildPath))
1151 if (!CreateDirectoryW(szBuildPath,NULL))
1153 ERR("Failed to create directory '%s'.\n", debugstr_w(pszPath));
1154 return E_FAIL;
1157 *p = '\\';
1158 p = strchrW(p+1, '\\');
1160 /* last component must be created too. */
1161 if (!PathFileExistsW(szBuildPath))
1163 if (!CreateDirectoryW(szBuildPath,NULL))
1165 ERR("Failed to create directory '%s'.\n", debugstr_w(pszPath));
1166 return E_FAIL;
1170 TRACE("Created missing system directory '%s'\n", debugstr_w(pszPath));
1171 return S_OK;
1174 /*************************************************************************
1175 * SHGetFolderPathA [SHELL32.@]
1177 HRESULT WINAPI SHGetFolderPathA(
1178 HWND hwndOwner,
1179 int csidl,
1180 HANDLE hToken,
1181 DWORD dwFlags,
1182 LPSTR pszPath)
1184 WCHAR szTemp[MAX_PATH];
1185 HRESULT hr;
1187 hr = SHGetFolderPathW(hwndOwner, csidl, hToken, dwFlags, szTemp);
1188 if (hr == S_OK)
1190 if (!WideCharToMultiByte( CP_ACP, 0, szTemp, -1, pszPath, MAX_PATH, NULL, NULL ))
1191 pszPath[MAX_PATH - 1] = 0;
1194 TRACE("%p,%p,csidl=0x%04x\n",hwndOwner,pszPath,csidl);
1196 return hr;
1199 /*************************************************************************
1200 * SHGetSpecialFolderPathA [SHELL32.@]
1202 BOOL WINAPI SHGetSpecialFolderPathA (
1203 HWND hwndOwner,
1204 LPSTR szPath,
1205 int csidl,
1206 BOOL bCreate)
1208 return (SHGetFolderPathA(
1209 hwndOwner,
1210 csidl + (bCreate ? CSIDL_FLAG_CREATE : 0),
1211 NULL,
1213 szPath)) == S_OK ? TRUE : FALSE;
1216 /*************************************************************************
1217 * SHGetSpecialFolderPathW
1219 BOOL WINAPI SHGetSpecialFolderPathW (
1220 HWND hwndOwner,
1221 LPWSTR szPath,
1222 int csidl,
1223 BOOL bCreate)
1225 return (SHGetFolderPathW(
1226 hwndOwner,
1227 csidl + (bCreate ? CSIDL_FLAG_CREATE : 0),
1228 NULL,
1230 szPath)) == S_OK ? TRUE : FALSE;
1233 /*************************************************************************
1234 * SHGetSpecialFolderPath (SHELL32.175)
1236 BOOL WINAPI SHGetSpecialFolderPathAW (
1237 HWND hwndOwner,
1238 LPVOID szPath,
1239 int csidl,
1240 BOOL bCreate)
1243 if (SHELL_OsIsUnicode())
1244 return SHGetSpecialFolderPathW (hwndOwner, szPath, csidl, bCreate);
1245 return SHGetSpecialFolderPathA (hwndOwner, szPath, csidl, bCreate);