Added memicmpW.
[wine.git] / dlls / shell32 / shellpath.c
blob498d9bca7d302bcb341a7dd7ad2100d7c3977632
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 static void PathGetShortPathA(LPSTR pszPath)
241 CHAR path[MAX_PATH];
243 TRACE("%s\n", pszPath);
245 if (GetShortPathNameA(pszPath, path, MAX_PATH))
247 lstrcpyA(pszPath, path);
251 /*************************************************************************
252 * PathGetShortPathW [internal]
254 static void PathGetShortPathW(LPWSTR pszPath)
256 WCHAR path[MAX_PATH];
258 TRACE("%s\n", debugstr_w(pszPath));
260 if (GetShortPathNameW(pszPath, path, MAX_PATH))
262 lstrcpyW(pszPath, path);
266 /*************************************************************************
267 * PathGetShortPath [SHELL32.92]
269 VOID WINAPI PathGetShortPathAW(LPVOID pszPath)
271 if(SHELL_OsIsUnicode())
272 PathGetShortPathW(pszPath);
273 PathGetShortPathA(pszPath);
276 /*************************************************************************
277 * PathRemoveBlanks [SHELL32.33]
279 void WINAPI PathRemoveBlanksAW(LPVOID str)
281 if(SHELL_OsIsUnicode())
282 PathRemoveBlanksW(str);
283 else
284 PathRemoveBlanksA(str);
287 /*************************************************************************
288 * PathQuoteSpaces [SHELL32.55]
290 VOID WINAPI PathQuoteSpacesAW (LPVOID lpszPath)
292 if(SHELL_OsIsUnicode())
293 PathQuoteSpacesW(lpszPath);
294 else
295 PathQuoteSpacesA(lpszPath);
298 /*************************************************************************
299 * PathUnquoteSpaces [SHELL32.56]
301 VOID WINAPI PathUnquoteSpacesAW(LPVOID str)
303 if(SHELL_OsIsUnicode())
304 PathUnquoteSpacesW(str);
305 else
306 PathUnquoteSpacesA(str);
309 /*************************************************************************
310 * PathParseIconLocation [SHELL32.249]
312 int WINAPI PathParseIconLocationAW (LPVOID lpszPath)
314 if(SHELL_OsIsUnicode())
315 return PathParseIconLocationW(lpszPath);
316 return PathParseIconLocationA(lpszPath);
320 ########## Path Testing ##########
322 /*************************************************************************
323 * PathIsUNC [SHELL32.39]
325 BOOL WINAPI PathIsUNCAW (LPCVOID lpszPath)
327 if (SHELL_OsIsUnicode())
328 return PathIsUNCW( lpszPath );
329 return PathIsUNCA( lpszPath );
332 /*************************************************************************
333 * PathIsRelative [SHELL32.40]
335 BOOL WINAPI PathIsRelativeAW (LPCVOID lpszPath)
337 if (SHELL_OsIsUnicode())
338 return PathIsRelativeW( lpszPath );
339 return PathIsRelativeA( lpszPath );
342 /*************************************************************************
343 * PathIsRoot [SHELL32.29]
345 BOOL WINAPI PathIsRootAW(LPCVOID lpszPath)
347 if (SHELL_OsIsUnicode())
348 return PathIsRootW(lpszPath);
349 return PathIsRootA(lpszPath);
352 /*************************************************************************
353 * PathIsExeA [internal]
355 static BOOL PathIsExeA (LPCSTR lpszPath)
357 LPCSTR lpszExtension = PathGetExtensionA(lpszPath);
358 int i;
359 static const char * const lpszExtensions[] =
360 {"exe", "com", "pif", "cmd", "bat", "scf", "scr", NULL };
362 TRACE("path=%s\n",lpszPath);
364 for(i=0; lpszExtensions[i]; i++)
365 if (!strcasecmp(lpszExtension,lpszExtensions[i])) return TRUE;
367 return FALSE;
370 /*************************************************************************
371 * PathIsExeW [internal]
373 static BOOL PathIsExeW (LPCWSTR lpszPath)
375 LPCWSTR lpszExtension = PathGetExtensionW(lpszPath);
376 int i;
377 static const WCHAR lpszExtensions[][4] =
378 {{'e','x','e','\0'}, {'c','o','m','\0'}, {'p','i','f','\0'},
379 {'c','m','d','\0'}, {'b','a','t','\0'}, {'s','c','f','\0'},
380 {'s','c','r','\0'}, {'\0'} };
382 TRACE("path=%s\n",debugstr_w(lpszPath));
384 for(i=0; lpszExtensions[i][0]; i++)
385 if (!strcmpiW(lpszExtension,lpszExtensions[i])) return TRUE;
387 return FALSE;
390 /*************************************************************************
391 * PathIsExe [SHELL32.43]
393 BOOL WINAPI PathIsExeAW (LPCVOID path)
395 if (SHELL_OsIsUnicode())
396 return PathIsExeW (path);
397 return PathIsExeA(path);
400 /*************************************************************************
401 * PathIsDirectory [SHELL32.159]
403 BOOL WINAPI PathIsDirectoryAW (LPCVOID lpszPath)
405 if (SHELL_OsIsUnicode())
406 return PathIsDirectoryW (lpszPath);
407 return PathIsDirectoryA (lpszPath);
410 /*************************************************************************
411 * PathFileExists [SHELL32.45]
413 BOOL WINAPI PathFileExistsAW (LPCVOID lpszPath)
415 if (SHELL_OsIsUnicode())
416 return PathFileExistsW (lpszPath);
417 return PathFileExistsA (lpszPath);
420 /*************************************************************************
421 * PathMatchSpec [SHELL32.46]
423 BOOL WINAPI PathMatchSpecAW(LPVOID name, LPVOID mask)
425 if (SHELL_OsIsUnicode())
426 return PathMatchSpecW( name, mask );
427 return PathMatchSpecA( name, mask );
430 /*************************************************************************
431 * PathIsSameRoot [SHELL32.650]
433 BOOL WINAPI PathIsSameRootAW(LPCVOID lpszPath1, LPCVOID lpszPath2)
435 if (SHELL_OsIsUnicode())
436 return PathIsSameRootW(lpszPath1, lpszPath2);
437 return PathIsSameRootA(lpszPath1, lpszPath2);
440 /*************************************************************************
441 * IsLFNDriveA [SHELL32.41]
443 BOOL WINAPI IsLFNDriveA(LPCSTR lpszPath)
445 DWORD fnlen;
447 if (!GetVolumeInformationA(lpszPath, NULL, 0, NULL, &fnlen, NULL, NULL, 0))
448 return FALSE;
449 return fnlen > 12;
452 /*************************************************************************
453 * IsLFNDriveW [SHELL32.42]
455 BOOL WINAPI IsLFNDriveW(LPCWSTR lpszPath)
457 DWORD fnlen;
459 if (!GetVolumeInformationW(lpszPath, NULL, 0, NULL, &fnlen, NULL, NULL, 0))
460 return FALSE;
461 return fnlen > 12;
464 /*************************************************************************
465 * IsLFNDrive [SHELL32.119]
467 BOOL WINAPI IsLFNDriveAW(LPCVOID lpszPath)
469 if (SHELL_OsIsUnicode())
470 return IsLFNDriveW(lpszPath);
471 return IsLFNDriveA(lpszPath);
475 ########## Creating Something Unique ##########
477 /*************************************************************************
478 * PathMakeUniqueNameA [internal]
480 BOOL WINAPI PathMakeUniqueNameA(
481 LPSTR lpszBuffer,
482 DWORD dwBuffSize,
483 LPCSTR lpszShortName,
484 LPCSTR lpszLongName,
485 LPCSTR lpszPathName)
487 FIXME("%p %lu %s %s %s stub\n",
488 lpszBuffer, dwBuffSize, debugstr_a(lpszShortName),
489 debugstr_a(lpszLongName), debugstr_a(lpszPathName));
490 return TRUE;
493 /*************************************************************************
494 * PathMakeUniqueNameW [internal]
496 BOOL WINAPI PathMakeUniqueNameW(
497 LPWSTR lpszBuffer,
498 DWORD dwBuffSize,
499 LPCWSTR lpszShortName,
500 LPCWSTR lpszLongName,
501 LPCWSTR lpszPathName)
503 FIXME("%p %lu %s %s %s stub\n",
504 lpszBuffer, dwBuffSize, debugstr_w(lpszShortName),
505 debugstr_w(lpszLongName), debugstr_w(lpszPathName));
506 return TRUE;
509 /*************************************************************************
510 * PathMakeUniqueName [SHELL32.47]
512 BOOL WINAPI PathMakeUniqueNameAW(
513 LPVOID lpszBuffer,
514 DWORD dwBuffSize,
515 LPCVOID lpszShortName,
516 LPCVOID lpszLongName,
517 LPCVOID lpszPathName)
519 if (SHELL_OsIsUnicode())
520 return PathMakeUniqueNameW(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
521 return PathMakeUniqueNameA(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
524 /*************************************************************************
525 * PathYetAnotherMakeUniqueName [SHELL32.75]
527 * NOTES
528 * exported by ordinal
530 BOOL WINAPI PathYetAnotherMakeUniqueName(
531 LPWSTR lpszBuffer,
532 LPCWSTR lpszPathName,
533 LPCWSTR lpszShortName,
534 LPCWSTR lpszLongName)
536 FIXME("(%p, %s, %s ,%s):stub.\n",
537 lpszBuffer, debugstr_w(lpszPathName), debugstr_w(lpszShortName), debugstr_w(lpszLongName));
538 return TRUE;
543 ########## cleaning and resolving paths ##########
546 /*************************************************************************
547 * PathFindOnPath [SHELL32.145]
549 BOOL WINAPI PathFindOnPathAW(LPVOID sFile, LPCVOID sOtherDirs)
551 if (SHELL_OsIsUnicode())
552 return PathFindOnPathW(sFile, (LPCWSTR *)sOtherDirs);
553 return PathFindOnPathA(sFile, (LPCSTR *)sOtherDirs);
556 /*************************************************************************
557 * PathCleanupSpec [SHELL32.171]
559 DWORD WINAPI PathCleanupSpecAW (LPCVOID x, LPVOID y)
561 FIXME("(%p, %p) stub\n",x,y);
562 return TRUE;
565 /*************************************************************************
566 * PathQualifyA [SHELL32]
568 BOOL WINAPI PathQualifyA(LPCSTR pszPath)
570 FIXME("%s\n",pszPath);
571 return 0;
574 /*************************************************************************
575 * PathQualifyW [SHELL32]
577 BOOL WINAPI PathQualifyW(LPCWSTR pszPath)
579 FIXME("%s\n",debugstr_w(pszPath));
580 return 0;
583 /*************************************************************************
584 * PathQualify [SHELL32.49]
586 BOOL WINAPI PathQualifyAW(LPCVOID pszPath)
588 if (SHELL_OsIsUnicode())
589 return PathQualifyW(pszPath);
590 return PathQualifyA(pszPath);
593 /*************************************************************************
594 * PathResolveA [SHELL32.51]
596 BOOL WINAPI PathResolveA(
597 LPSTR lpszPath,
598 LPCSTR *alpszPaths,
599 DWORD dwFlags)
601 FIXME("(%s,%p,0x%08lx),stub!\n",
602 lpszPath, *alpszPaths, dwFlags);
603 return 0;
606 /*************************************************************************
607 * PathResolveW [SHELL32]
609 BOOL WINAPI PathResolveW(
610 LPWSTR lpszPath,
611 LPCWSTR *alpszPaths,
612 DWORD dwFlags)
614 FIXME("(%s,%p,0x%08lx),stub!\n",
615 debugstr_w(lpszPath), debugstr_w(*alpszPaths), dwFlags);
616 return 0;
619 /*************************************************************************
620 * PathResolve [SHELL32.51]
622 BOOL WINAPI PathResolveAW(
623 LPVOID lpszPath,
624 LPCVOID *alpszPaths,
625 DWORD dwFlags)
627 if (SHELL_OsIsUnicode())
628 return PathResolveW(lpszPath, (LPCWSTR*)alpszPaths, dwFlags);
629 return PathResolveA(lpszPath, (LPCSTR*)alpszPaths, dwFlags);
632 /*************************************************************************
633 * PathProcessCommandA [SHELL32.653]
635 HRESULT WINAPI PathProcessCommandA (
636 LPCSTR lpszPath,
637 LPSTR lpszBuff,
638 DWORD dwBuffSize,
639 DWORD dwFlags)
641 FIXME("%s %p 0x%04lx 0x%04lx stub\n",
642 lpszPath, lpszBuff, dwBuffSize, dwFlags);
643 strcpy(lpszBuff, lpszPath);
644 return 0;
647 /*************************************************************************
648 * PathProcessCommandW
650 HRESULT WINAPI PathProcessCommandW (
651 LPCWSTR lpszPath,
652 LPWSTR lpszBuff,
653 DWORD dwBuffSize,
654 DWORD dwFlags)
656 FIXME("(%s, %p, 0x%04lx, 0x%04lx) stub\n",
657 debugstr_w(lpszPath), lpszBuff, dwBuffSize, dwFlags);
658 strcpyW(lpszBuff, lpszPath);
659 return 0;
662 /*************************************************************************
663 * PathProcessCommand (SHELL32.653)
665 HRESULT WINAPI PathProcessCommandAW (
666 LPCVOID lpszPath,
667 LPVOID lpszBuff,
668 DWORD dwBuffSize,
669 DWORD dwFlags)
671 if (SHELL_OsIsUnicode())
672 return PathProcessCommandW(lpszPath, lpszBuff, dwBuffSize, dwFlags);
673 return PathProcessCommandA(lpszPath, lpszBuff, dwBuffSize, dwFlags);
677 ########## special ##########
680 /*************************************************************************
681 * PathSetDlgItemPath (SHELL32.48)
683 VOID WINAPI PathSetDlgItemPathAW(HWND hDlg, int id, LPCVOID pszPath)
685 if (SHELL_OsIsUnicode())
686 PathSetDlgItemPathW(hDlg, id, pszPath);
687 else
688 PathSetDlgItemPathA(hDlg, id, pszPath);
691 /*************************************************************************
692 * SHGetFolderPathW [SHELL32.@]
694 * converts csidl to path
697 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'};
698 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'};
699 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'};
700 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'};
702 typedef struct
704 DWORD dwFlags;
705 HKEY hRootKey;
706 LPCSTR szValueName;
707 LPCSTR szDefaultPath; /* fallback string; sub dir of windows directory */
708 } CSIDL_DATA;
710 #define CSIDL_MYFLAG_SHFOLDER 1
711 #define CSIDL_MYFLAG_SETUP 2
712 #define CSIDL_MYFLAG_CURRVER 4
713 #define CSIDL_MYFLAG_RELATIVE 8
715 #define HKLM HKEY_LOCAL_MACHINE
716 #define HKCU HKEY_CURRENT_USER
717 static const CSIDL_DATA CSIDL_Data[] =
719 { /* CSIDL_DESKTOP */
720 9, HKCU,
721 "Desktop",
722 "Desktop"
724 { /* CSIDL_INTERNET */
725 0, (HKEY)1, /* FIXME */
726 NULL,
727 NULL,
729 { /* CSIDL_PROGRAMS */
730 9, HKCU,
731 "Programs",
732 "Start Menu\\Programs"
734 { /* CSIDL_CONTROLS (.CPL files) */
735 10, HKLM,
736 "SysDir",
737 "SYSTEM"
739 { /* CSIDL_PRINTERS */
740 10, HKLM,
741 "SysDir",
742 "SYSTEM"
744 { /* CSIDL_PERSONAL */
745 1, HKCU,
746 "Personal",
747 "My Documents"
749 { /* CSIDL_FAVORITES */
750 9, HKCU,
751 "Favorites",
752 "Favorites"
754 { /* CSIDL_STARTUP */
755 9, HKCU,
756 "StartUp",
757 "Start Menu\\Programs\\StartUp"
759 { /* CSIDL_RECENT */
760 9, HKCU,
761 "Recent",
762 "Recent"
764 { /* CSIDL_SENDTO */
765 9, HKCU,
766 "SendTo",
767 "SendTo"
769 { /* CSIDL_BITBUCKET - Recycle Bin */
770 0, (HKEY)1, /* FIXME */
771 NULL,
772 "recycled"
774 { /* CSIDL_STARTMENU */
775 9, HKCU,
776 "Start Menu",
777 "Start Menu"
779 { /* CSIDL_MYDOCUMENTS */
780 0, (HKEY)1, /* FIXME */
781 NULL,
782 NULL
784 { /* CSIDL_MYMUSIC */
785 1, HKCU,
786 "My Music",
787 "My Documents\\My Music"
789 { /* CSIDL_MYMUSIC */
790 1, HKCU,
791 "My Video",
792 "My Documents\\My Video"
794 { /* unassigned */
795 0, 0,
796 NULL,
797 NULL,
799 { /* CSIDL_DESKTOPDIRECTORY */
800 9, HKCU,
801 "Desktop",
802 "Desktop"
804 { /* CSIDL_DRIVES */
805 0, (HKEY)1, /* FIXME */
806 NULL,
807 "My Computer"
809 { /* CSIDL_NETWORK */
810 0, (HKEY)1, /* FIXME */
811 NULL,
812 "Network Neighborhood"
814 { /* CSIDL_NETHOOD */
815 9, HKCU,
816 "NetHood",
817 "NetHood"
819 { /* CSIDL_FONTS */
820 9, HKCU,
821 "Fonts",
822 "Fonts"
824 { /* CSIDL_TEMPLATES */
825 9, HKCU,
826 "Templates",
827 "ShellNew"
829 { /* CSIDL_COMMON_STARTMENU */
830 9, HKLM,
831 "Common Start Menu",
832 "Start Menu"
834 { /* CSIDL_COMMON_PROGRAMS */
835 9, HKLM,
836 "Common Programs",
839 { /* CSIDL_COMMON_STARTUP */
840 9, HKLM,
841 "Common StartUp",
842 "All Users\\Start Menu\\Programs\\StartUp"
844 { /* CSIDL_COMMON_DESKTOPDIRECTORY */
845 9, HKLM,
846 "Common Desktop",
847 "Desktop"
849 { /* CSIDL_APPDATA */
850 9, HKCU,
851 "AppData",
852 "Application Data"
854 { /* CSIDL_PRINTHOOD */
855 9, HKCU,
856 "PrintHood",
857 "PrintHood"
859 { /* CSIDL_LOCAL_APPDATA (win2k only/undocumented) */
860 1, HKCU,
861 "Local AppData",
862 "Local Settings\\Application Data",
864 { /* CSIDL_ALTSTARTUP */
865 0, (HKEY)1, /* FIXME */
866 NULL,
867 NULL
869 { /* CSIDL_COMMON_ALTSTARTUP */
870 0, (HKEY)1, /* FIXME */
871 NULL,
872 NULL
874 { /* CSIDL_COMMON_FAVORITES */
875 9, HKCU,
876 "Favorites",
877 "Favorites"
879 { /* CSIDL_INTERNET_CACHE (32) */
880 9, HKCU,
881 "Cache",
882 "Temporary Internet Files"
884 { /* CSIDL_COOKIES (33) */
885 9, HKCU,
886 "Cookies",
887 "Cookies"
889 { /* CSIDL_HISTORY (34) */
890 9, HKCU,
891 "History",
892 "History"
894 { /* CSIDL_COMMON_APPDATA */
895 9, HKLM,
896 "Common AppData",
897 "All Users\\Application Data"
899 { /* CSIDL_WINDOWS */
900 2, HKLM,
901 "WinDir",
902 "Windows"
904 { /* CSIDL_SYSTEM */
905 10, HKLM,
906 "SysDir",
907 "SYSTEM"
909 { /* CSIDL_PROGRAM_FILES */
910 4, HKLM,
911 "ProgramFilesDir",
912 "Program Files"
914 { /* CSIDL_MYPICTURES */
915 1, HKCU,
916 "My Pictures",
917 "My Documents\\My Pictures"
919 { /* CSIDL_PROFILE */
920 10, HKLM,
921 "WinDir", /* correct ? */
924 { /* CSIDL_SYSTEMX86 */
925 10, HKLM,
926 "SysDir",
927 "SYSTEM"
929 { /* CSIDL_PROGRAM_FILESX86 */
930 4, HKLM,
931 "ProgramFilesDir",
932 "Program Files"
934 { /* CSIDL_PROGRAM_FILES_COMMON */
935 4, HKLM,
936 "CommonFilesDir",
937 "Program Files\\Common Files" /* ? */
939 { /* CSIDL_PROGRAM_FILES_COMMONX86 */
940 4, HKLM,
941 "CommonFilesDir",
942 "Program Files\\Common Files" /* ? */
944 { /* CSIDL_COMMON_TEMPLATES */
945 9, HKLM,
946 "Common Templates",
947 /*"Documents and Settings\\"*/"All Users\\Templates"
949 { /* CSIDL_COMMON_DOCUMENTS */
950 9, HKLM,
951 "Common Documents",
952 /*"Documents and Settings\\"*/"All Users\\Documents"
954 { /* CSIDL_COMMON_ADMINTOOLS */
955 9, HKLM,
956 "Common Administrative Tools",
957 /*"Documents and Settings\\"*/"All Users\\Start Menu\\Programs\\Administrative Tools"
959 { /* CSIDL_ADMINTOOLS */
960 9, HKCU,
961 "Administrative Tools",
962 "Start Menu\\Programs\\Administrative Tools"
964 { /* CSIDL_CONNECTIONS */
965 0, 0, /* FIXME */
966 NULL,
967 NULL
969 { /* unassigned 32 */
970 0, 0,
971 NULL,
972 NULL
974 { /* unassigned 33 */
975 0, 0,
976 NULL,
977 NULL
979 { /* unassigned 34 */
980 0, 0,
981 NULL,
982 NULL
984 { /* CSIDL_COMMON_MUSIC */
985 9, HKLM,
986 "CommonMusic",
987 /*"Documents and Settings\\"*/"All Users\\Documents\\My Music"
989 { /* CSIDL_COMMON_PICTURES */
990 9, HKLM,
991 "CommonPictures",
992 /*"Documents and Settings\\"*/"All Users\\Documents\\My Pictures"
994 { /* CSIDL_COMMON_VIDEO */
995 9, HKLM,
996 "CommonVideo",
997 /*"Documents and Settings\\"*/"All Users\\Documents\\My Video"
999 { /* CSIDL_RESOURCES */
1000 0, (HKEY)2,
1001 NULL,
1002 "Resources"
1004 { /* CSIDL_RESOURCES_LOCALIZED */
1005 0, 0, /* FIXME */
1006 NULL,
1007 NULL
1009 { /* CSIDL_COMMON_OEM_LINKS */
1010 0, 0, /* FIXME */
1011 NULL,
1012 NULL
1014 { /* CSIDL_CDBURN_AREA */
1015 1, HKCU,
1016 "CD Burning",
1017 "Local Settings\\Application Data\\Microsoft\\CD Burning"
1019 { /* unassigned 3C */
1020 0, 0,
1021 NULL,
1022 NULL
1024 { /* CSIDL_COMPUTERSNEARME */
1025 0, 0, /* FIXME */
1026 NULL,
1027 NULL
1029 { /* CSIDL_PROFILES */
1030 0, 0, /* FIXME */
1031 NULL,
1032 NULL
1035 #undef HKCU
1036 #undef HKLM
1038 /**********************************************************************/
1040 HRESULT WINAPI SHGetFolderPathW(
1041 HWND hwndOwner,
1042 int csidl,
1043 HANDLE hToken, /* [in] FIXME: get paths for specific user */
1044 DWORD dwFlags, /* [in] FIXME: SHGFP_TYPE_CURRENT|SHGFP_TYPE_DEFAULT */
1045 LPWSTR pszPath)
1047 WCHAR szValueName[MAX_PATH], szDefaultPath[MAX_PATH], szBuildPath[MAX_PATH];
1048 HKEY hRootKey, hKey;
1049 DWORD dwCsidlFlags;
1050 DWORD dwType, dwDisp, dwPathLen = MAX_PATH;
1051 DWORD folder = csidl & CSIDL_FOLDER_MASK;
1052 WCHAR *p;
1054 TRACE("%p,%p,csidl=0x%04x\n", hwndOwner,pszPath,csidl);
1056 if ((folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0])) ||
1057 (CSIDL_Data[folder].hRootKey == 0))
1059 ERR("folder 0x%04lx unknown or not allowed\n", folder);
1060 return E_FAIL;
1062 if (CSIDL_Data[folder].hRootKey == (HKEY)1)
1064 FIXME("folder 0x%04lx unknown, please add.\n", folder);
1065 return E_FAIL;
1068 dwCsidlFlags = CSIDL_Data[folder].dwFlags;
1069 hRootKey = CSIDL_Data[folder].hRootKey;
1070 MultiByteToWideChar(CP_ACP, 0, CSIDL_Data[folder].szValueName, -1, szValueName, MAX_PATH);
1071 MultiByteToWideChar(CP_ACP, 0, CSIDL_Data[folder].szDefaultPath, -1, szDefaultPath, MAX_PATH);
1073 /* Special case for some values that don't exist in registry */
1074 if (CSIDL_Data[folder].hRootKey == (HKEY)2)
1076 GetWindowsDirectoryW(pszPath, MAX_PATH);
1077 PathAddBackslashW(pszPath);
1078 strcatW(pszPath, szDefaultPath);
1079 return S_OK;
1082 if (dwCsidlFlags & CSIDL_MYFLAG_SHFOLDER)
1084 /* user shell folders */
1085 if (RegCreateKeyExW(hRootKey,szSHUserFolders,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return E_FAIL;
1087 if (RegQueryValueExW(hKey,szValueName,NULL,&dwType,(LPBYTE)pszPath,&dwPathLen))
1089 RegCloseKey(hKey);
1091 /* shell folders */
1092 if (RegCreateKeyExW(hRootKey,szSHFolders,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return E_FAIL;
1094 if (RegQueryValueExW(hKey,szValueName,NULL,&dwType,(LPBYTE)pszPath,&dwPathLen))
1097 /* value not existing */
1098 if (dwCsidlFlags & CSIDL_MYFLAG_RELATIVE)
1100 GetWindowsDirectoryW(pszPath, MAX_PATH);
1101 PathAddBackslashW(pszPath);
1102 strcatW(pszPath, szDefaultPath);
1104 else
1106 GetSystemDirectoryW(pszPath, MAX_PATH);
1107 strcpyW(pszPath + 3, szDefaultPath);
1109 dwType=REG_SZ;
1110 RegSetValueExW(hKey,szValueName,0,REG_SZ,(LPBYTE)pszPath,strlenW(pszPath)+1);
1113 RegCloseKey(hKey);
1115 else
1117 LPCWSTR pRegPath;
1119 if (dwCsidlFlags & CSIDL_MYFLAG_SETUP)
1120 pRegPath = szSetup;
1121 else if (dwCsidlFlags & CSIDL_MYFLAG_CURRVER)
1122 pRegPath = szCurrentVersion;
1123 else
1125 ERR("folder settings broken, please correct !\n");
1126 return E_FAIL;
1129 if (RegCreateKeyExW(hRootKey,pRegPath,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return E_FAIL;
1131 if (RegQueryValueExW(hKey,szValueName,NULL,&dwType,(LPBYTE)pszPath,&dwPathLen))
1133 /* value not existing */
1134 if (dwCsidlFlags & CSIDL_MYFLAG_RELATIVE)
1136 GetWindowsDirectoryW(pszPath, MAX_PATH);
1137 PathAddBackslashW(pszPath);
1138 strcatW(pszPath, szDefaultPath);
1140 else
1142 GetSystemDirectoryW(pszPath, MAX_PATH);
1143 strcpyW(pszPath + 3, szDefaultPath);
1145 dwType=REG_SZ;
1146 RegSetValueExW(hKey,szValueName,0,REG_SZ,(LPBYTE)pszPath,strlenW(pszPath)+1);
1148 RegCloseKey(hKey);
1151 /* expand paths like %USERPROFILE% */
1152 if (dwType == REG_EXPAND_SZ)
1154 ExpandEnvironmentStringsW(pszPath, szDefaultPath, MAX_PATH);
1155 strcpyW(pszPath, szDefaultPath);
1158 /* if we don't care about existing directories we are ready */
1159 if(csidl & CSIDL_FLAG_DONT_VERIFY) return S_OK;
1161 if (PathFileExistsW(pszPath)) return S_OK;
1163 /* not existing but we are not allowed to create it */
1164 if (!(csidl & CSIDL_FLAG_CREATE)) return E_FAIL;
1166 /* create directory/directories */
1167 strcpyW(szBuildPath, pszPath);
1168 p = strchrW(szBuildPath, '\\');
1169 while (p)
1171 *p = 0;
1172 if (!PathFileExistsW(szBuildPath))
1174 if (!CreateDirectoryW(szBuildPath,NULL))
1176 ERR("Failed to create directory '%s'.\n", debugstr_w(pszPath));
1177 return E_FAIL;
1180 *p = '\\';
1181 p = strchrW(p+1, '\\');
1183 /* last component must be created too. */
1184 if (!PathFileExistsW(szBuildPath))
1186 if (!CreateDirectoryW(szBuildPath,NULL))
1188 ERR("Failed to create directory '%s'.\n", debugstr_w(pszPath));
1189 return E_FAIL;
1193 TRACE("Created missing system directory '%s'\n", debugstr_w(pszPath));
1194 return S_OK;
1197 /*************************************************************************
1198 * SHGetFolderPathA [SHELL32.@]
1200 HRESULT WINAPI SHGetFolderPathA(
1201 HWND hwndOwner,
1202 int csidl,
1203 HANDLE hToken,
1204 DWORD dwFlags,
1205 LPSTR pszPath)
1207 WCHAR szTemp[MAX_PATH];
1208 HRESULT hr;
1210 hr = SHGetFolderPathW(hwndOwner, csidl, hToken, dwFlags, szTemp);
1211 if (hr == S_OK)
1213 if (!WideCharToMultiByte( CP_ACP, 0, szTemp, -1, pszPath, MAX_PATH, NULL, NULL ))
1214 pszPath[MAX_PATH - 1] = 0;
1217 TRACE("%p,%p,csidl=0x%04x\n",hwndOwner,pszPath,csidl);
1219 return hr;
1222 /*************************************************************************
1223 * SHGetSpecialFolderPathA [SHELL32.@]
1225 BOOL WINAPI SHGetSpecialFolderPathA (
1226 HWND hwndOwner,
1227 LPSTR szPath,
1228 int csidl,
1229 BOOL bCreate)
1231 return (SHGetFolderPathA(
1232 hwndOwner,
1233 csidl + (bCreate ? CSIDL_FLAG_CREATE : 0),
1234 NULL,
1236 szPath)) == S_OK ? TRUE : FALSE;
1239 /*************************************************************************
1240 * SHGetSpecialFolderPathW
1242 BOOL WINAPI SHGetSpecialFolderPathW (
1243 HWND hwndOwner,
1244 LPWSTR szPath,
1245 int csidl,
1246 BOOL bCreate)
1248 return (SHGetFolderPathW(
1249 hwndOwner,
1250 csidl + (bCreate ? CSIDL_FLAG_CREATE : 0),
1251 NULL,
1253 szPath)) == S_OK ? TRUE : FALSE;
1256 /*************************************************************************
1257 * SHGetSpecialFolderPath (SHELL32.175)
1259 BOOL WINAPI SHGetSpecialFolderPathAW (
1260 HWND hwndOwner,
1261 LPVOID szPath,
1262 int csidl,
1263 BOOL bCreate)
1266 if (SHELL_OsIsUnicode())
1267 return SHGetSpecialFolderPathW (hwndOwner, szPath, csidl, bCreate);
1268 return SHGetSpecialFolderPathA (hwndOwner, szPath, csidl, bCreate);