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
22 * Many of these functions are in SHLWAPI.DLL also
27 #include "wine/port.h"
32 #include "wine/debug.h"
41 #include "shell32_main.h"
42 #include "undocshell.h"
44 #include "wine/unicode.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
50 ########## Combining and Constructing paths ##########
53 /*************************************************************************
54 * PathAppend [SHELL32.36]
56 BOOL WINAPI
PathAppendAW(
60 if (SHELL_OsIsUnicode())
61 return PathAppendW(lpszPath1
, lpszPath2
);
62 return PathAppendA(lpszPath1
, lpszPath2
);
65 /*************************************************************************
66 * PathCombine [SHELL32.37]
68 LPVOID WINAPI
PathCombineAW(
73 if (SHELL_OsIsUnicode())
74 return PathCombineW( szDest
, lpszDir
, lpszFile
);
75 return PathCombineA( szDest
, lpszDir
, lpszFile
);
78 /*************************************************************************
79 * PathAddBackslash [SHELL32.32]
81 LPVOID WINAPI
PathAddBackslashAW(LPVOID lpszPath
)
83 if(SHELL_OsIsUnicode())
84 return PathAddBackslashW(lpszPath
);
85 return PathAddBackslashA(lpszPath
);
88 /*************************************************************************
89 * PathBuildRoot [SHELL32.30]
91 LPVOID WINAPI
PathBuildRootAW(LPVOID lpszPath
, int drive
)
93 if(SHELL_OsIsUnicode())
94 return PathBuildRootW(lpszPath
, drive
);
95 return PathBuildRootA(lpszPath
, drive
);
99 Extracting Component Parts
102 /*************************************************************************
103 * PathFindFileName [SHELL32.34]
105 LPVOID WINAPI
PathFindFileNameAW(LPCVOID lpszPath
)
107 if(SHELL_OsIsUnicode())
108 return PathFindFileNameW(lpszPath
);
109 return PathFindFileNameA(lpszPath
);
112 /*************************************************************************
113 * PathFindExtension [SHELL32.31]
115 LPVOID WINAPI
PathFindExtensionAW(LPCVOID lpszPath
)
117 if (SHELL_OsIsUnicode())
118 return PathFindExtensionW(lpszPath
);
119 return PathFindExtensionA(lpszPath
);
123 /*************************************************************************
124 * PathGetExtensionA [internal]
127 * exported by ordinal
128 * return value points to the first char after the dot
130 static LPSTR
PathGetExtensionA(LPCSTR lpszPath
)
132 TRACE("(%s)\n",lpszPath
);
134 lpszPath
= PathFindExtensionA(lpszPath
);
135 return (LPSTR
)(*lpszPath
?(lpszPath
+1):lpszPath
);
138 /*************************************************************************
139 * PathGetExtensionW [internal]
141 static LPWSTR
PathGetExtensionW(LPCWSTR lpszPath
)
143 TRACE("(%s)\n",debugstr_w(lpszPath
));
145 lpszPath
= PathFindExtensionW(lpszPath
);
146 return (LPWSTR
)(*lpszPath
?(lpszPath
+1):lpszPath
);
149 /*************************************************************************
150 * PathGetExtension [SHELL32.158]
152 LPVOID WINAPI
PathGetExtensionAW(LPCVOID lpszPath
,DWORD void1
, DWORD void2
)
154 if (SHELL_OsIsUnicode())
155 return PathGetExtensionW(lpszPath
);
156 return PathGetExtensionA(lpszPath
);
159 /*************************************************************************
160 * PathGetArgs [SHELL32.52]
162 LPVOID WINAPI
PathGetArgsAW(LPVOID lpszPath
)
164 if (SHELL_OsIsUnicode())
165 return PathGetArgsW(lpszPath
);
166 return PathGetArgsA(lpszPath
);
169 /*************************************************************************
170 * PathGetDriveNumber [SHELL32.57]
172 int WINAPI
PathGetDriveNumberAW(LPVOID lpszPath
)
174 if (SHELL_OsIsUnicode())
175 return PathGetDriveNumberW(lpszPath
);
176 return PathGetDriveNumberA(lpszPath
);
179 /*************************************************************************
180 * PathRemoveFileSpec [SHELL32.35]
182 BOOL WINAPI
PathRemoveFileSpecAW(LPVOID lpszPath
)
184 if (SHELL_OsIsUnicode())
185 return PathRemoveFileSpecW(lpszPath
);
186 return PathRemoveFileSpecA(lpszPath
);
189 /*************************************************************************
190 * PathStripPath [SHELL32.38]
192 void WINAPI
PathStripPathAW(LPVOID lpszPath
)
194 if (SHELL_OsIsUnicode())
195 PathStripPathW(lpszPath
);
197 PathStripPathA(lpszPath
);
200 /*************************************************************************
201 * PathStripToRoot [SHELL32.50]
203 BOOL WINAPI
PathStripToRootAW(LPVOID lpszPath
)
205 if (SHELL_OsIsUnicode())
206 return PathStripToRootW(lpszPath
);
207 return PathStripToRootA(lpszPath
);
210 /*************************************************************************
211 * PathRemoveArgs [SHELL32.251]
213 void WINAPI
PathRemoveArgsAW(LPVOID lpszPath
)
215 if (SHELL_OsIsUnicode())
216 PathRemoveArgsW(lpszPath
);
218 PathRemoveArgsA(lpszPath
);
221 /*************************************************************************
222 * PathRemoveExtension [SHELL32.250]
224 void WINAPI
PathRemoveExtensionAW(LPVOID lpszPath
)
226 if (SHELL_OsIsUnicode())
227 PathRemoveExtensionW(lpszPath
);
229 PathRemoveExtensionA(lpszPath
);
237 /*************************************************************************
238 * PathGetShortPathA [internal]
240 static void PathGetShortPathA(LPSTR pszPath
)
244 TRACE("%s\n", pszPath
);
246 if (GetShortPathNameA(pszPath
, path
, MAX_PATH
))
248 lstrcpyA(pszPath
, path
);
252 /*************************************************************************
253 * PathGetShortPathW [internal]
255 static void PathGetShortPathW(LPWSTR pszPath
)
257 WCHAR path
[MAX_PATH
];
259 TRACE("%s\n", debugstr_w(pszPath
));
261 if (GetShortPathNameW(pszPath
, path
, MAX_PATH
))
263 lstrcpyW(pszPath
, path
);
267 /*************************************************************************
268 * PathGetShortPath [SHELL32.92]
270 VOID WINAPI
PathGetShortPathAW(LPVOID pszPath
)
272 if(SHELL_OsIsUnicode())
273 PathGetShortPathW(pszPath
);
274 PathGetShortPathA(pszPath
);
277 /*************************************************************************
278 * PathRemoveBlanks [SHELL32.33]
280 void WINAPI
PathRemoveBlanksAW(LPVOID str
)
282 if(SHELL_OsIsUnicode())
283 PathRemoveBlanksW(str
);
285 PathRemoveBlanksA(str
);
288 /*************************************************************************
289 * PathQuoteSpaces [SHELL32.55]
291 VOID WINAPI
PathQuoteSpacesAW (LPVOID lpszPath
)
293 if(SHELL_OsIsUnicode())
294 PathQuoteSpacesW(lpszPath
);
296 PathQuoteSpacesA(lpszPath
);
299 /*************************************************************************
300 * PathUnquoteSpaces [SHELL32.56]
302 VOID WINAPI
PathUnquoteSpacesAW(LPVOID str
)
304 if(SHELL_OsIsUnicode())
305 PathUnquoteSpacesW(str
);
307 PathUnquoteSpacesA(str
);
310 /*************************************************************************
311 * PathParseIconLocation [SHELL32.249]
313 int WINAPI
PathParseIconLocationAW (LPVOID lpszPath
)
315 if(SHELL_OsIsUnicode())
316 return PathParseIconLocationW(lpszPath
);
317 return PathParseIconLocationA(lpszPath
);
321 ########## Path Testing ##########
323 /*************************************************************************
324 * PathIsUNC [SHELL32.39]
326 BOOL WINAPI
PathIsUNCAW (LPCVOID lpszPath
)
328 if (SHELL_OsIsUnicode())
329 return PathIsUNCW( lpszPath
);
330 return PathIsUNCA( lpszPath
);
333 /*************************************************************************
334 * PathIsRelative [SHELL32.40]
336 BOOL WINAPI
PathIsRelativeAW (LPCVOID lpszPath
)
338 if (SHELL_OsIsUnicode())
339 return PathIsRelativeW( lpszPath
);
340 return PathIsRelativeA( lpszPath
);
343 /*************************************************************************
344 * PathIsRoot [SHELL32.29]
346 BOOL WINAPI
PathIsRootAW(LPCVOID lpszPath
)
348 if (SHELL_OsIsUnicode())
349 return PathIsRootW(lpszPath
);
350 return PathIsRootA(lpszPath
);
353 /*************************************************************************
354 * PathIsExeA [internal]
356 static BOOL
PathIsExeA (LPCSTR lpszPath
)
358 LPCSTR lpszExtension
= PathGetExtensionA(lpszPath
);
360 static const char * const lpszExtensions
[] =
361 {"exe", "com", "pif", "cmd", "bat", "scf", "scr", NULL
};
363 TRACE("path=%s\n",lpszPath
);
365 for(i
=0; lpszExtensions
[i
]; i
++)
366 if (!strcasecmp(lpszExtension
,lpszExtensions
[i
])) return TRUE
;
371 /*************************************************************************
372 * PathIsExeW [internal]
374 static BOOL
PathIsExeW (LPCWSTR lpszPath
)
376 LPCWSTR lpszExtension
= PathGetExtensionW(lpszPath
);
378 static const WCHAR lpszExtensions
[][4] =
379 {{'e','x','e','\0'}, {'c','o','m','\0'}, {'p','i','f','\0'},
380 {'c','m','d','\0'}, {'b','a','t','\0'}, {'s','c','f','\0'},
381 {'s','c','r','\0'}, {'\0'} };
383 TRACE("path=%s\n",debugstr_w(lpszPath
));
385 for(i
=0; lpszExtensions
[i
][0]; i
++)
386 if (!strcmpiW(lpszExtension
,lpszExtensions
[i
])) return TRUE
;
391 /*************************************************************************
392 * PathIsExe [SHELL32.43]
394 BOOL WINAPI
PathIsExeAW (LPCVOID path
)
396 if (SHELL_OsIsUnicode())
397 return PathIsExeW (path
);
398 return PathIsExeA(path
);
401 /*************************************************************************
402 * PathIsDirectory [SHELL32.159]
404 BOOL WINAPI
PathIsDirectoryAW (LPCVOID lpszPath
)
406 if (SHELL_OsIsUnicode())
407 return PathIsDirectoryW (lpszPath
);
408 return PathIsDirectoryA (lpszPath
);
411 /*************************************************************************
412 * PathFileExists [SHELL32.45]
414 BOOL WINAPI
PathFileExistsAW (LPCVOID lpszPath
)
416 if (SHELL_OsIsUnicode())
417 return PathFileExistsW (lpszPath
);
418 return PathFileExistsA (lpszPath
);
421 /*************************************************************************
422 * PathMatchSpec [SHELL32.46]
424 BOOL WINAPI
PathMatchSpecAW(LPVOID name
, LPVOID mask
)
426 if (SHELL_OsIsUnicode())
427 return PathMatchSpecW( name
, mask
);
428 return PathMatchSpecA( name
, mask
);
431 /*************************************************************************
432 * PathIsSameRoot [SHELL32.650]
434 BOOL WINAPI
PathIsSameRootAW(LPCVOID lpszPath1
, LPCVOID lpszPath2
)
436 if (SHELL_OsIsUnicode())
437 return PathIsSameRootW(lpszPath1
, lpszPath2
);
438 return PathIsSameRootA(lpszPath1
, lpszPath2
);
441 /*************************************************************************
442 * IsLFNDriveA [SHELL32.41]
444 BOOL WINAPI
IsLFNDriveA(LPCSTR lpszPath
)
448 if (!GetVolumeInformationA(lpszPath
, NULL
, 0, NULL
, &fnlen
, NULL
, NULL
, 0))
453 /*************************************************************************
454 * IsLFNDriveW [SHELL32.42]
456 BOOL WINAPI
IsLFNDriveW(LPCWSTR lpszPath
)
460 if (!GetVolumeInformationW(lpszPath
, NULL
, 0, NULL
, &fnlen
, NULL
, NULL
, 0))
465 /*************************************************************************
466 * IsLFNDrive [SHELL32.119]
468 BOOL WINAPI
IsLFNDriveAW(LPCVOID lpszPath
)
470 if (SHELL_OsIsUnicode())
471 return IsLFNDriveW(lpszPath
);
472 return IsLFNDriveA(lpszPath
);
476 ########## Creating Something Unique ##########
478 /*************************************************************************
479 * PathMakeUniqueNameA [internal]
481 BOOL WINAPI
PathMakeUniqueNameA(
484 LPCSTR lpszShortName
,
488 FIXME("%p %lu %s %s %s stub\n",
489 lpszBuffer
, dwBuffSize
, debugstr_a(lpszShortName
),
490 debugstr_a(lpszLongName
), debugstr_a(lpszPathName
));
494 /*************************************************************************
495 * PathMakeUniqueNameW [internal]
497 BOOL WINAPI
PathMakeUniqueNameW(
500 LPCWSTR lpszShortName
,
501 LPCWSTR lpszLongName
,
502 LPCWSTR lpszPathName
)
504 FIXME("%p %lu %s %s %s stub\n",
505 lpszBuffer
, dwBuffSize
, debugstr_w(lpszShortName
),
506 debugstr_w(lpszLongName
), debugstr_w(lpszPathName
));
510 /*************************************************************************
511 * PathMakeUniqueName [SHELL32.47]
513 BOOL WINAPI
PathMakeUniqueNameAW(
516 LPCVOID lpszShortName
,
517 LPCVOID lpszLongName
,
518 LPCVOID lpszPathName
)
520 if (SHELL_OsIsUnicode())
521 return PathMakeUniqueNameW(lpszBuffer
,dwBuffSize
, lpszShortName
,lpszLongName
,lpszPathName
);
522 return PathMakeUniqueNameA(lpszBuffer
,dwBuffSize
, lpszShortName
,lpszLongName
,lpszPathName
);
525 /*************************************************************************
526 * PathYetAnotherMakeUniqueName [SHELL32.75]
529 * exported by ordinal
531 BOOL WINAPI
PathYetAnotherMakeUniqueName(
533 LPCWSTR lpszPathName
,
534 LPCWSTR lpszShortName
,
535 LPCWSTR lpszLongName
)
537 FIXME("(%p, %s, %s ,%s):stub.\n",
538 lpszBuffer
, debugstr_w(lpszPathName
), debugstr_w(lpszShortName
), debugstr_w(lpszLongName
));
544 ########## cleaning and resolving paths ##########
547 /*************************************************************************
548 * PathFindOnPath [SHELL32.145]
550 BOOL WINAPI
PathFindOnPathAW(LPVOID sFile
, LPCVOID sOtherDirs
)
552 if (SHELL_OsIsUnicode())
553 return PathFindOnPathW(sFile
, (LPCWSTR
*)sOtherDirs
);
554 return PathFindOnPathA(sFile
, (LPCSTR
*)sOtherDirs
);
557 /*************************************************************************
558 * PathCleanupSpec [SHELL32.171]
560 DWORD WINAPI
PathCleanupSpecAW (LPCVOID x
, LPVOID y
)
562 FIXME("(%p, %p) stub\n",x
,y
);
566 /*************************************************************************
567 * PathQualifyA [SHELL32]
569 BOOL WINAPI
PathQualifyA(LPCSTR pszPath
)
571 FIXME("%s\n",pszPath
);
575 /*************************************************************************
576 * PathQualifyW [SHELL32]
578 BOOL WINAPI
PathQualifyW(LPCWSTR pszPath
)
580 FIXME("%s\n",debugstr_w(pszPath
));
584 /*************************************************************************
585 * PathQualify [SHELL32.49]
587 BOOL WINAPI
PathQualifyAW(LPCVOID pszPath
)
589 if (SHELL_OsIsUnicode())
590 return PathQualifyW(pszPath
);
591 return PathQualifyA(pszPath
);
594 /*************************************************************************
595 * PathResolveA [SHELL32.51]
597 BOOL WINAPI
PathResolveA(
602 FIXME("(%s,%p,0x%08lx),stub!\n",
603 lpszPath
, *alpszPaths
, dwFlags
);
607 /*************************************************************************
608 * PathResolveW [SHELL32]
610 BOOL WINAPI
PathResolveW(
615 FIXME("(%s,%p,0x%08lx),stub!\n",
616 debugstr_w(lpszPath
), debugstr_w(*alpszPaths
), dwFlags
);
620 /*************************************************************************
621 * PathResolve [SHELL32.51]
623 BOOL WINAPI
PathResolveAW(
628 if (SHELL_OsIsUnicode())
629 return PathResolveW(lpszPath
, (LPCWSTR
*)alpszPaths
, dwFlags
);
630 return PathResolveA(lpszPath
, (LPCSTR
*)alpszPaths
, dwFlags
);
633 /*************************************************************************
634 * PathProcessCommandA [SHELL32.653]
636 HRESULT WINAPI
PathProcessCommandA (
642 FIXME("%s %p 0x%04lx 0x%04lx stub\n",
643 lpszPath
, lpszBuff
, dwBuffSize
, dwFlags
);
644 strcpy(lpszBuff
, lpszPath
);
648 /*************************************************************************
649 * PathProcessCommandW
651 HRESULT WINAPI
PathProcessCommandW (
657 FIXME("(%s, %p, 0x%04lx, 0x%04lx) stub\n",
658 debugstr_w(lpszPath
), lpszBuff
, dwBuffSize
, dwFlags
);
659 strcpyW(lpszBuff
, lpszPath
);
663 /*************************************************************************
664 * PathProcessCommand (SHELL32.653)
666 HRESULT WINAPI
PathProcessCommandAW (
672 if (SHELL_OsIsUnicode())
673 return PathProcessCommandW(lpszPath
, lpszBuff
, dwBuffSize
, dwFlags
);
674 return PathProcessCommandA(lpszPath
, lpszBuff
, dwBuffSize
, dwFlags
);
678 ########## special ##########
681 /*************************************************************************
682 * PathSetDlgItemPath (SHELL32.48)
684 VOID WINAPI
PathSetDlgItemPathAW(HWND hDlg
, int id
, LPCVOID pszPath
)
686 if (SHELL_OsIsUnicode())
687 PathSetDlgItemPathW(hDlg
, id
, pszPath
);
689 PathSetDlgItemPathA(hDlg
, id
, pszPath
);
692 /*************************************************************************
693 * SHGetFolderPathW [SHELL32.@]
695 * converts csidl to path
698 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'};
699 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'};
700 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'};
701 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'};
708 LPCSTR szDefaultPath
; /* fallback string; sub dir of windows directory */
711 #define CSIDL_MYFLAG_SHFOLDER 1
712 #define CSIDL_MYFLAG_SETUP 2
713 #define CSIDL_MYFLAG_CURRVER 4
714 #define CSIDL_MYFLAG_RELATIVE 8
716 #define HKLM HKEY_LOCAL_MACHINE
717 #define HKCU HKEY_CURRENT_USER
718 #define HKEY_DISALLOWED (HKEY)0
719 #define HKEY_UNIMPLEMENTED (HKEY)1
720 #define HKEY_WINDOWSPATH (HKEY)2
721 #define HKEY_NONEXISTENT (HKEY)3
722 static const CSIDL_DATA CSIDL_Data
[] =
724 { /* CSIDL_DESKTOP */
729 { /* CSIDL_INTERNET */
734 { /* CSIDL_PROGRAMS */
739 { /* CSIDL_CONTROLS (.CPL files) */
744 { /* CSIDL_PRINTERS */
749 { /* CSIDL_PERSONAL */
754 { /* CSIDL_FAVORITES */
759 { /* CSIDL_STARTUP */
762 "Start Menu\\Programs\\StartUp"
774 { /* CSIDL_BITBUCKET - Recycle Bin */
779 { /* CSIDL_STARTMENU */
784 { /* CSIDL_MYDOCUMENTS */
785 0, HKEY_UNIMPLEMENTED
, /* FIXME */
789 { /* CSIDL_MYMUSIC */
792 "My Documents\\My Music"
794 { /* CSIDL_MYVIDEO */
797 "My Documents\\My Video"
804 { /* CSIDL_DESKTOPDIRECTORY */
814 { /* CSIDL_NETWORK */
819 { /* CSIDL_NETHOOD */
829 { /* CSIDL_TEMPLATES */
834 { /* CSIDL_COMMON_STARTMENU */
839 { /* CSIDL_COMMON_PROGRAMS */
844 { /* CSIDL_COMMON_STARTUP */
847 "All Users\\Start Menu\\Programs\\StartUp"
849 { /* CSIDL_COMMON_DESKTOPDIRECTORY */
854 { /* CSIDL_APPDATA */
859 { /* CSIDL_PRINTHOOD */
864 { /* CSIDL_LOCAL_APPDATA (win2k only/undocumented) */
867 "Local Settings\\Application Data",
869 { /* CSIDL_ALTSTARTUP */
874 { /* CSIDL_COMMON_ALTSTARTUP */
879 { /* CSIDL_COMMON_FAVORITES */
884 { /* CSIDL_INTERNET_CACHE (32) */
887 "Temporary Internet Files"
889 { /* CSIDL_COOKIES (33) */
894 { /* CSIDL_HISTORY (34) */
899 { /* CSIDL_COMMON_APPDATA */
902 "All Users\\Application Data"
904 { /* CSIDL_WINDOWS */
914 { /* CSIDL_PROGRAM_FILES */
919 { /* CSIDL_MYPICTURES */
922 "My Documents\\My Pictures"
924 { /* CSIDL_PROFILE */
926 "WinDir", /* correct ? */
929 { /* CSIDL_SYSTEMX86 */
934 { /* CSIDL_PROGRAM_FILESX86 */
939 { /* CSIDL_PROGRAM_FILES_COMMON */
942 "Program Files\\Common Files" /* ? */
944 { /* CSIDL_PROGRAM_FILES_COMMONX86 */
947 "Program Files\\Common Files" /* ? */
949 { /* CSIDL_COMMON_TEMPLATES */
952 /*"Documents and Settings\\"*/"All Users\\Templates"
954 { /* CSIDL_COMMON_DOCUMENTS */
957 /*"Documents and Settings\\"*/"All Users\\Documents"
959 { /* CSIDL_COMMON_ADMINTOOLS */
961 "Common Administrative Tools",
962 /*"Documents and Settings\\"*/"All Users\\Start Menu\\Programs\\Administrative Tools"
964 { /* CSIDL_ADMINTOOLS */
966 "Administrative Tools",
967 "Start Menu\\Programs\\Administrative Tools"
969 { /* CSIDL_CONNECTIONS */
974 { /* unassigned 32 */
979 { /* unassigned 33 */
984 { /* unassigned 34 */
989 { /* CSIDL_COMMON_MUSIC */
992 /*"Documents and Settings\\"*/"All Users\\Documents\\My Music"
994 { /* CSIDL_COMMON_PICTURES */
997 /*"Documents and Settings\\"*/"All Users\\Documents\\My Pictures"
999 { /* CSIDL_COMMON_VIDEO */
1002 /*"Documents and Settings\\"*/"All Users\\Documents\\My Video"
1004 { /* CSIDL_RESOURCES */
1005 0, HKEY_WINDOWSPATH
,
1009 { /* CSIDL_RESOURCES_LOCALIZED */
1014 { /* CSIDL_COMMON_OEM_LINKS */
1019 { /* CSIDL_CDBURN_AREA */
1022 "Local Settings\\Application Data\\Microsoft\\CD Burning"
1024 { /* unassigned 3C */
1029 { /* CSIDL_COMPUTERSNEARME */
1034 { /* CSIDL_PROFILES */
1043 /**********************************************************************/
1045 HRESULT WINAPI
SHGetFolderPathW(
1048 HANDLE hToken
, /* [in] FIXME: get paths for specific user */
1049 DWORD dwFlags
, /* [in] FIXME: SHGFP_TYPE_CURRENT|SHGFP_TYPE_DEFAULT */
1052 WCHAR szValueName
[MAX_PATH
], szDefaultPath
[MAX_PATH
], szBuildPath
[MAX_PATH
];
1053 HKEY hRootKey
, hKey
;
1055 DWORD dwType
, dwDisp
, dwPathLen
= MAX_PATH
;
1056 DWORD folder
= csidl
& CSIDL_FOLDER_MASK
;
1059 TRACE("%p,%p,csidl=0x%04x\n", hwndOwner
,pszPath
,csidl
);
1062 return E_INVALIDARG
;
1065 if ((folder
>= sizeof(CSIDL_Data
) / sizeof(CSIDL_Data
[0])) ||
1066 (CSIDL_Data
[folder
].hRootKey
== HKEY_DISALLOWED
))
1067 return E_INVALIDARG
;
1068 if (CSIDL_Data
[folder
].hRootKey
== HKEY_UNIMPLEMENTED
)
1070 FIXME("folder 0x%04lx unknown, please add.\n", folder
);
1073 if (CSIDL_Data
[folder
].hRootKey
== HKEY_NONEXISTENT
)
1076 /* Special case for some values that don't exist in registry */
1077 if (CSIDL_Data
[folder
].hRootKey
== HKEY_WINDOWSPATH
)
1079 GetWindowsDirectoryW(pszPath
, MAX_PATH
);
1080 PathAddBackslashW(pszPath
);
1081 strcatW(pszPath
, szDefaultPath
);
1085 dwCsidlFlags
= CSIDL_Data
[folder
].dwFlags
;
1086 hRootKey
= CSIDL_Data
[folder
].hRootKey
;
1087 MultiByteToWideChar(CP_ACP
, 0, CSIDL_Data
[folder
].szValueName
, -1, szValueName
, MAX_PATH
);
1088 MultiByteToWideChar(CP_ACP
, 0, CSIDL_Data
[folder
].szDefaultPath
, -1, szDefaultPath
, MAX_PATH
);
1090 if (dwCsidlFlags
& CSIDL_MYFLAG_SHFOLDER
)
1092 /* user shell folders */
1093 if (RegCreateKeyExW(hRootKey
,szSHUserFolders
,0,NULL
,0,KEY_ALL_ACCESS
,NULL
,&hKey
,&dwDisp
)) return E_FAIL
;
1095 if (RegQueryValueExW(hKey
,szValueName
,NULL
,&dwType
,(LPBYTE
)pszPath
,&dwPathLen
))
1100 if (RegCreateKeyExW(hRootKey
,szSHFolders
,0,NULL
,0,KEY_ALL_ACCESS
,NULL
,&hKey
,&dwDisp
)) return E_FAIL
;
1102 if (RegQueryValueExW(hKey
,szValueName
,NULL
,&dwType
,(LPBYTE
)pszPath
,&dwPathLen
))
1105 /* value not existing */
1106 if (dwCsidlFlags
& CSIDL_MYFLAG_RELATIVE
)
1108 GetWindowsDirectoryW(pszPath
, MAX_PATH
);
1109 PathAddBackslashW(pszPath
);
1110 strcatW(pszPath
, szDefaultPath
);
1114 GetSystemDirectoryW(pszPath
, MAX_PATH
);
1115 strcpyW(pszPath
+ 3, szDefaultPath
);
1118 RegSetValueExW(hKey
,szValueName
,0,REG_SZ
,(LPBYTE
)pszPath
,strlenW(pszPath
)+1);
1127 if (dwCsidlFlags
& CSIDL_MYFLAG_SETUP
)
1129 else if (dwCsidlFlags
& CSIDL_MYFLAG_CURRVER
)
1130 pRegPath
= szCurrentVersion
;
1133 ERR("folder settings broken, please correct !\n");
1137 if (RegCreateKeyExW(hRootKey
,pRegPath
,0,NULL
,0,KEY_ALL_ACCESS
,NULL
,&hKey
,&dwDisp
)) return E_FAIL
;
1139 if (RegQueryValueExW(hKey
,szValueName
,NULL
,&dwType
,(LPBYTE
)pszPath
,&dwPathLen
))
1141 /* value not existing */
1142 if (dwCsidlFlags
& CSIDL_MYFLAG_RELATIVE
)
1144 GetWindowsDirectoryW(pszPath
, MAX_PATH
);
1145 PathAddBackslashW(pszPath
);
1146 strcatW(pszPath
, szDefaultPath
);
1150 GetSystemDirectoryW(pszPath
, MAX_PATH
);
1151 strcpyW(pszPath
+ 3, szDefaultPath
);
1154 RegSetValueExW(hKey
,szValueName
,0,REG_SZ
,(LPBYTE
)pszPath
,strlenW(pszPath
)+1);
1159 /* expand paths like %USERPROFILE% */
1160 if (dwType
== REG_EXPAND_SZ
)
1162 ExpandEnvironmentStringsW(pszPath
, szDefaultPath
, MAX_PATH
);
1163 strcpyW(pszPath
, szDefaultPath
);
1166 /* if we don't care about existing directories we are ready */
1167 if(csidl
& CSIDL_FLAG_DONT_VERIFY
) return S_OK
;
1169 if (PathFileExistsW(pszPath
)) return S_OK
;
1171 /* not existing but we are not allowed to create it */
1172 if (!(csidl
& CSIDL_FLAG_CREATE
)) return E_FAIL
;
1174 /* create directory/directories */
1175 strcpyW(szBuildPath
, pszPath
);
1176 p
= strchrW(szBuildPath
, '\\');
1180 if (!PathFileExistsW(szBuildPath
))
1182 if (!CreateDirectoryW(szBuildPath
,NULL
))
1184 ERR("Failed to create directory '%s'.\n", debugstr_w(pszPath
));
1189 p
= strchrW(p
+1, '\\');
1191 /* last component must be created too. */
1192 if (!PathFileExistsW(szBuildPath
))
1194 if (!CreateDirectoryW(szBuildPath
,NULL
))
1196 ERR("Failed to create directory '%s'.\n", debugstr_w(pszPath
));
1201 TRACE("Created missing system directory '%s'\n", debugstr_w(pszPath
));
1205 /*************************************************************************
1206 * SHGetFolderPathA [SHELL32.@]
1208 HRESULT WINAPI
SHGetFolderPathA(
1215 WCHAR szTemp
[MAX_PATH
];
1219 return E_INVALIDARG
;
1222 hr
= SHGetFolderPathW(hwndOwner
, csidl
, hToken
, dwFlags
, szTemp
);
1224 WideCharToMultiByte(CP_ACP
, 0, szTemp
, -1, pszPath
, MAX_PATH
, NULL
,
1227 TRACE("%p,%p,csidl=0x%04x\n",hwndOwner
,pszPath
,csidl
);
1232 /*************************************************************************
1233 * SHGetSpecialFolderPathA [SHELL32.@]
1235 BOOL WINAPI
SHGetSpecialFolderPathA (
1241 return (SHGetFolderPathA(
1243 csidl
+ (bCreate
? CSIDL_FLAG_CREATE
: 0),
1246 szPath
)) == S_OK
? TRUE
: FALSE
;
1249 /*************************************************************************
1250 * SHGetSpecialFolderPathW
1252 BOOL WINAPI
SHGetSpecialFolderPathW (
1258 return (SHGetFolderPathW(
1260 csidl
+ (bCreate
? CSIDL_FLAG_CREATE
: 0),
1263 szPath
)) == S_OK
? TRUE
: FALSE
;
1266 /*************************************************************************
1267 * SHGetSpecialFolderPath (SHELL32.175)
1269 BOOL WINAPI
SHGetSpecialFolderPathAW (
1276 if (SHELL_OsIsUnicode())
1277 return SHGetSpecialFolderPathW (hwndOwner
, szPath
, csidl
, bCreate
);
1278 return SHGetSpecialFolderPathA (hwndOwner
, szPath
, csidl
, bCreate
);
1281 /*************************************************************************
1282 * SHGetSpecialFolderLocation [SHELL32.@]
1284 * gets the folder locations from the registry and creates a pidl
1285 * creates missing reg keys and directories
1289 * nFolder [I] CSIDL_xxxxx
1290 * ppidl [O] PIDL of a special folder
1293 * In NT5, SHGetSpecialFolderLocation needs the <winntdir>/Recent
1294 * directory. If the directory is missing it returns a x80070002.
1295 * In most cases, this forwards to SHGetSpecialFolderPath, but
1296 * CSIDLs with virtual folders (not real paths) must be handled
1299 HRESULT WINAPI
SHGetSpecialFolderLocation(
1302 LPITEMIDLIST
* ppidl
)
1304 HRESULT hr
= E_INVALIDARG
;
1306 TRACE("(%p,0x%x,%p)\n", hwndOwner
,nFolder
,ppidl
);
1309 return E_INVALIDARG
;
1315 *ppidl
= _ILCreateDesktop();
1318 case CSIDL_INTERNET
:
1319 *ppidl
= _ILCreateIExplore();
1322 case CSIDL_CONTROLS
:
1323 *ppidl
= _ILCreateControlPanel();
1326 case CSIDL_PRINTERS
:
1327 *ppidl
= _ILCreatePrinters();
1330 case CSIDL_BITBUCKET
:
1331 *ppidl
= _ILCreateBitBucket();
1335 *ppidl
= _ILCreateMyComputer();
1339 *ppidl
= _ILCreateNetwork();
1342 case CSIDL_ALTSTARTUP
:
1343 case CSIDL_COMMON_ALTSTARTUP
:
1347 case CSIDL_COMPUTERSNEARME
:
1353 WCHAR szPath
[MAX_PATH
];
1355 if (SHGetSpecialFolderPathW(hwndOwner
, szPath
, nFolder
, TRUE
))
1359 TRACE("Value=%s\n", debugstr_w(szPath
));
1360 hr
= SHILCreateFromPathW(szPath
, ppidl
, &attributes
);
1367 TRACE("-- (new pidl %p)\n",*ppidl
);
1371 /*************************************************************************
1372 * SHGetFolderLocation [SHELL32.@]
1375 * the pidl can be a simple one. since we can't get the path out of the pidl
1376 * we have to take all data from the pidl
1377 * Mostly we forward to SHGetSpecialFolderLocation, but a few special cases
1380 HRESULT WINAPI
SHGetFolderLocation(
1385 LPITEMIDLIST
*ppidl
)
1389 TRACE_(shell
)("%p 0x%08x %p 0x%08lx %p\n",
1390 hwnd
, csidl
, hToken
, dwFlags
, ppidl
);
1393 return E_INVALIDARG
;
1397 case CSIDL_ALTSTARTUP
:
1398 case CSIDL_COMMON_ALTSTARTUP
:
1403 hr
= SHGetSpecialFolderLocation(hwnd
, csidl
, ppidl
);