Fixed typo in ProgramsW.
[wine/multimedia.git] / dlls / shell32 / shellpath.c
blob186f551f70e4048caabc3a44e1804b7ce9bd3b49
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 "pidl.h"
44 #include "wine/unicode.h"
45 #include "shlwapi.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(shell);
50 ########## Combining and Constructing paths ##########
53 /*************************************************************************
54 * PathAppend [SHELL32.36]
56 BOOL WINAPI PathAppendAW(
57 LPVOID lpszPath1,
58 LPCVOID lpszPath2)
60 if (SHELL_OsIsUnicode())
61 return PathAppendW(lpszPath1, lpszPath2);
62 return PathAppendA(lpszPath1, lpszPath2);
65 /*************************************************************************
66 * PathCombine [SHELL32.37]
68 LPVOID WINAPI PathCombineAW(
69 LPVOID szDest,
70 LPCVOID lpszDir,
71 LPCVOID lpszFile)
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]
126 * NOTES
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);
196 else
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);
217 else
218 PathRemoveArgsA(lpszPath);
221 /*************************************************************************
222 * PathRemoveExtension [SHELL32.250]
224 void WINAPI PathRemoveExtensionAW(LPVOID lpszPath)
226 if (SHELL_OsIsUnicode())
227 PathRemoveExtensionW(lpszPath);
228 else
229 PathRemoveExtensionA(lpszPath);
234 Path Manipulations
237 /*************************************************************************
238 * PathGetShortPathA [internal]
240 static void PathGetShortPathA(LPSTR pszPath)
242 CHAR path[MAX_PATH];
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);
284 else
285 PathRemoveBlanksA(str);
288 /*************************************************************************
289 * PathQuoteSpaces [SHELL32.55]
291 VOID WINAPI PathQuoteSpacesAW (LPVOID lpszPath)
293 if(SHELL_OsIsUnicode())
294 PathQuoteSpacesW(lpszPath);
295 else
296 PathQuoteSpacesA(lpszPath);
299 /*************************************************************************
300 * PathUnquoteSpaces [SHELL32.56]
302 VOID WINAPI PathUnquoteSpacesAW(LPVOID str)
304 if(SHELL_OsIsUnicode())
305 PathUnquoteSpacesW(str);
306 else
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);
359 int i;
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;
368 return FALSE;
371 /*************************************************************************
372 * PathIsExeW [internal]
374 static BOOL PathIsExeW (LPCWSTR lpszPath)
376 LPCWSTR lpszExtension = PathGetExtensionW(lpszPath);
377 int i;
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;
388 return FALSE;
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)
446 DWORD fnlen;
448 if (!GetVolumeInformationA(lpszPath, NULL, 0, NULL, &fnlen, NULL, NULL, 0))
449 return FALSE;
450 return fnlen > 12;
453 /*************************************************************************
454 * IsLFNDriveW [SHELL32.42]
456 BOOL WINAPI IsLFNDriveW(LPCWSTR lpszPath)
458 DWORD fnlen;
460 if (!GetVolumeInformationW(lpszPath, NULL, 0, NULL, &fnlen, NULL, NULL, 0))
461 return FALSE;
462 return fnlen > 12;
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(
482 LPSTR lpszBuffer,
483 DWORD dwBuffSize,
484 LPCSTR lpszShortName,
485 LPCSTR lpszLongName,
486 LPCSTR lpszPathName)
488 FIXME("%p %lu %s %s %s stub\n",
489 lpszBuffer, dwBuffSize, debugstr_a(lpszShortName),
490 debugstr_a(lpszLongName), debugstr_a(lpszPathName));
491 return TRUE;
494 /*************************************************************************
495 * PathMakeUniqueNameW [internal]
497 BOOL WINAPI PathMakeUniqueNameW(
498 LPWSTR lpszBuffer,
499 DWORD dwBuffSize,
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));
507 return TRUE;
510 /*************************************************************************
511 * PathMakeUniqueName [SHELL32.47]
513 BOOL WINAPI PathMakeUniqueNameAW(
514 LPVOID lpszBuffer,
515 DWORD dwBuffSize,
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]
528 * NOTES
529 * exported by ordinal
531 BOOL WINAPI PathYetAnotherMakeUniqueName(
532 LPWSTR lpszBuffer,
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));
539 return TRUE;
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);
563 return TRUE;
566 /*************************************************************************
567 * PathQualifyA [SHELL32]
569 BOOL WINAPI PathQualifyA(LPCSTR pszPath)
571 FIXME("%s\n",pszPath);
572 return 0;
575 /*************************************************************************
576 * PathQualifyW [SHELL32]
578 BOOL WINAPI PathQualifyW(LPCWSTR pszPath)
580 FIXME("%s\n",debugstr_w(pszPath));
581 return 0;
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(
598 LPSTR lpszPath,
599 LPCSTR *alpszPaths,
600 DWORD dwFlags)
602 FIXME("(%s,%p,0x%08lx),stub!\n",
603 lpszPath, *alpszPaths, dwFlags);
604 return 0;
607 /*************************************************************************
608 * PathResolveW [SHELL32]
610 BOOL WINAPI PathResolveW(
611 LPWSTR lpszPath,
612 LPCWSTR *alpszPaths,
613 DWORD dwFlags)
615 FIXME("(%s,%p,0x%08lx),stub!\n",
616 debugstr_w(lpszPath), debugstr_w(*alpszPaths), dwFlags);
617 return 0;
620 /*************************************************************************
621 * PathResolve [SHELL32.51]
623 BOOL WINAPI PathResolveAW(
624 LPVOID lpszPath,
625 LPCVOID *alpszPaths,
626 DWORD dwFlags)
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 (
637 LPCSTR lpszPath,
638 LPSTR lpszBuff,
639 DWORD dwBuffSize,
640 DWORD dwFlags)
642 FIXME("%s %p 0x%04lx 0x%04lx stub\n",
643 lpszPath, lpszBuff, dwBuffSize, dwFlags);
644 strcpy(lpszBuff, lpszPath);
645 return 0;
648 /*************************************************************************
649 * PathProcessCommandW
651 HRESULT WINAPI PathProcessCommandW (
652 LPCWSTR lpszPath,
653 LPWSTR lpszBuff,
654 DWORD dwBuffSize,
655 DWORD dwFlags)
657 FIXME("(%s, %p, 0x%04lx, 0x%04lx) stub\n",
658 debugstr_w(lpszPath), lpszBuff, dwBuffSize, dwFlags);
659 strcpyW(lpszBuff, lpszPath);
660 return 0;
663 /*************************************************************************
664 * PathProcessCommand (SHELL32.653)
666 HRESULT WINAPI PathProcessCommandAW (
667 LPCVOID lpszPath,
668 LPVOID lpszBuff,
669 DWORD dwBuffSize,
670 DWORD dwFlags)
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);
688 else
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'};
705 static const WCHAR Administrative_ToolsW[] = {'A','d','m','i','n','i','s','t','r','a','t','i','v','e',' ','T','o','o','l','s','\0'};
706 static const WCHAR All_Users__Application_DataW[] = {'A','l','l',' ','U','s','e','r','s','\\',
707 'A','p','p','l','i','c','a','t','i','o','n',' ','D','a','t','a','\0'};
708 static const WCHAR All_Users__DesktopW[] = {'A','l','l',' ','U','s','e','r','s','\\',
709 'D','e','s','k','t','o','p','\0'};
710 static const WCHAR All_Users__DocumentsW[] = {'A','l','l',' ','U','s','e','r','s','\\',
711 'D','o','c','u','m','e','n','t','s','\0'};
712 static const WCHAR All_Users__Documents__My_MusicW[] = {'A','l','l',' ','U','s','e','r','s','\\',
713 'D','o','c','u','m','e','n','t','s','\\',
714 'M','y',' ','M','u','s','i','c','\0'};
715 static const WCHAR All_Users__Documents__My_PicturesW[] = {'A','l','l',' ','U','s','e','r','s','\\',
716 'D','o','c','u','m','e','n','t','s','\\',
717 'M','y',' ','P','i','c','t','u','r','e','s','\0'};
718 static const WCHAR All_Users__Documents__My_VideoW[] = {'A','l','l',' ','U','s','e','r','s','\\',
719 'D','o','c','u','m','e','n','t','s','\\',
720 'M','y',' ','V','i','d','e','o','\0'};
721 static const WCHAR All_Users__Start_MenuW[] = {'A','l','l',' ','U','s','e','r','s','\\','S','t','a','r','t',' ','M','e','n','u','\0'};
722 static const WCHAR All_Users__Start_Menu__ProgramsW[] = {'A','l','l',' ','U','s','e','r','s','\\','S','t','a','r','t',' ','M','e','n','u','\\','P','r','o','g','r','a','m','s','\0'};
723 static const WCHAR All_Users__Start_Menu__Programs__Administrative_ToolsW[] = {'A','l','l',' ','U','s','e','r','s','\\',
724 'S','t','a','r','t',' ','M','e','n','u','\\','P','r','o','g','r','a','m','s','\\',
725 'A','d','m','i','n','i','s','t','r','a','t','i','v','e',' ','T','o','o','l','s','\0'};
726 static const WCHAR All_Users__Start_Menu__Programs__StartUpW[] = {'A','l','l',' ','U','s','e','r','s','\\',
727 'S','t','a','r','t',' ','M','e','n','u','\\',
728 'P','r','o','g','r','a','m','s','\\',
729 'S','t','a','r','t','U','p','\0'};
730 static const WCHAR All_Users__TemplatesW[] = {'A','l','l',' ','U','s','e','r','s','\\',
731 'T','e','m','p','l','a','t','e','s','\0'};
732 static const WCHAR AppDataW[] = {'A','p','p','D','a','t','a','\0'};
733 static const WCHAR Application_DataW[] = {'A','p','p','l','i','c','a','t','i','o','n',' ','D','a','t','a','\0'};
734 static const WCHAR CacheW[] = {'C','a','c','h','e','\0'};
735 static const WCHAR CD_BurningW[] = {'C','D',' ','B','u','r','n','i','n','g','\0'};
736 static const WCHAR Common_Administrative_ToolsW[] = {'C','o','m','m','o','n',' ','A','d','m','i','n','i','s','t','r','a','t','i','v','e',' ','T','o','o','l','s','\0'};
737 static const WCHAR Common_AppDataW[] = {'C','o','m','m','o','n',' ','A','p','p','D','a','t','a','\0'};
738 static const WCHAR Common_DesktopW[] = {'C','o','m','m','o','n',' ','D','e','s','k','t','o','p','\0'};
739 static const WCHAR Common_DocumentsW[] = {'C','o','m','m','o','n',' ','D','o','c','u','m','e','n','t','s','\0'};
740 static const WCHAR CommonFilesDirW[] = {'C','o','m','m','o','n','F','i','l','e','s','D','i','r','\0'};
741 static const WCHAR CommonMusicW[] = {'C','o','m','m','o','n','M','u','s','i','c','\0'};
742 static const WCHAR CommonPicturesW[] = {'C','o','m','m','o','n','P','i','c','t','u','r','e','s','\0'};
743 static const WCHAR Common_ProgramsW[] = {'C','o','m','m','o','n',' ','P','r','o','g','r','a','m','s','\0'};
744 static const WCHAR Common_StartUpW[] = {'C','o','m','m','o','n',' ','S','t','a','r','t','U','p','\0'};
745 static const WCHAR Common_Start_MenuW[] = {'C','o','m','m','o','n',' ','S','t','a','r','t',' ','M','e','n','u','\0'};
746 static const WCHAR Common_TemplatesW[] = {'C','o','m','m','o','n',' ','T','e','m','p','l','a','t','e','s','\0'};
747 static const WCHAR CommonVideoW[] = {'C','o','m','m','o','n','V','i','d','e','o','\0'};
748 static const WCHAR CookiesW[] = {'C','o','o','k','i','e','s','\0'};
749 static const WCHAR DesktopW[] = {'D','e','s','k','t','o','p','\0'};
750 static const WCHAR Empty_StringW[] = {'\0'};
751 static const WCHAR FavoritesW[] = {'F','a','v','o','r','i','t','e','s','\0'};
752 static const WCHAR FontsW[] = {'F','o','n','t','s','\0'};
753 static const WCHAR HistoryW[] = {'H','i','s','t','o','r','y','\0'};
754 static const WCHAR Local_AppDataW[] = {'L','o','c','a','l',' ','A','p','p','D','a','t','a','\0'};
755 static const WCHAR Local_Settings__Application_DataW[] = {'L','o','c','a','l',' ','S','e','t','t','i','n','g','s','\\',
756 'A','p','p','l','i','c','a','t','i','o','n',' ','D','a','t','a','\0'};
757 static const WCHAR Local_Settings__Application_Data__Microsoft__CD_BurningW[] = {
758 'L','o','c','a','l',' ','S','e','t','t','i','n','g','s','\\',
759 'A','p','p','l','i','c','a','t','i','o','n',' ','D','a','t','a','\\',
760 'M','i','c','r','o','s','o','f','t','\\','C','D',' ','B','u','r','n','i','n','g','\0'};
761 static const WCHAR My_DocumentsW[] = {'M','y',' ','D','o','c','u','m','e','n','t','s','\0'};
762 static const WCHAR My_Documents__My_MusicW[] = {'M','y',' ','D','o','c','u','m','e','n','t','s','\\',
763 'M','y',' ','M','u','s','i','c','\0'};
764 static const WCHAR My_Documents__My_PicturesW[] = {'M','y',' ','D','o','c','u','m','e','n','t','s','\\',
765 'M','y',' ','P','i','c','t','u','r','e','s','\0'};
766 static const WCHAR My_Documents__My_VideoW[] = {'M','y',' ','D','o','c','u','m','e','n','t','s','\\',
767 'M','y',' ','V','i','d','e','o','\0'};
768 static const WCHAR My_MusicW[] = {'M','y',' ','M','u','s','i','c','\0'};
769 static const WCHAR My_PicturesW[] = {'M','y',' ','P','i','c','t','u','r','e','s','\0'};
770 static const WCHAR My_VideoW[] = {'M','y',' ','V','i','d','e','o','\0'};
771 static const WCHAR NetHoodW[] = {'N','e','t','H','o','o','d','\0'};
772 static const WCHAR PersonalW[] = {'P','e','r','s','o','n','a','l','\0'};
773 static const WCHAR PrintHoodW[] = {'P','r','i','n','t','H','o','o','d','\0'};
774 static const WCHAR ProgramFilesDirW[] = {'P','r','o','g','r','a','m','F','i','l','e','s','D','i','r','\0'};
775 static const WCHAR Program_FilesW[] = {'P','r','o','g','r','a','m',' ','F','i','l','e','s','\0'};
776 static const WCHAR Program_Files__Common_FilesW[] = {'P','r','o','g','r','a','m',' ','F','i','l','e','s','\\',
777 'C','o','m','m','o','n',' ','F','i','l','e','s','\0'};
778 static const WCHAR ProgramsW[] = {'P','r','o','g','r','a','m','s','\0'};
779 static const WCHAR RecentW[] = {'R','e','c','e','n','t','\0'};
780 static const WCHAR ResourcesW[] = {'R','e','s','o','u','r','c','e','s','\0'};
781 static const WCHAR SendToW[] = {'S','e','n','d','T','o','\0'};
782 static const WCHAR ShellNewW[] = {'S','h','e','l','l','N','e','w','\0'};
783 static const WCHAR Start_Menu__ProgramsW[] = {'S','t','a','r','t',' ','M','e','n','u','\\','P','r','o','g','r','a','m','s','\0'};
784 static const WCHAR SysDirW[] = {'S','y','s','D','i','r','\0'};
785 static const WCHAR SystemW[] = {'s','y','s','t','e','m','\0'};
786 static const WCHAR StartUpW[] = {'S','t','a','r','t','U','p','\0'};
787 static const WCHAR Start_MenuW[] = {'S','t','a','r','t',' ','M','e','n','u','\0'};
788 static const WCHAR Start_Menu__Programs__Administrative_ToolsW[] = {
789 'S','t','a','r','t',' ','M','e','n','u','\\','P','r','o','g','r','a','m','s','\\',
790 'A','d','m','i','n','i','s','t','r','a','t','i','v','e',' ','T','o','o','l','s','\0'};
791 static const WCHAR Start_Menu__Programs__StartUpW[] = {'S','t','a','r','t',' ','M','e','n','u','\\',
792 'P','r','o','g','r','a','m','s','\\',
793 'S','t','a','r','t','U','p','\0'};
794 static const WCHAR TemplatesW[] = {'T','e','m','p','l','a','t','e','s','\0'};
795 static const WCHAR Temporary_Internet_FilesW[] = {'T','e','m','p','o','r','a','r','y',' ','I','n','t','e','r','n','e','t',' ','F','i','l','e','s','\0'};
796 static const WCHAR WinDirW[] = {'W','i','n','D','i','r','\0'};
797 static const WCHAR WindowsW[] = {'w','i','n','d','o','w','s','\0'};
802 typedef struct
804 DWORD dwFlags;
805 HKEY hRootKey;
806 LPCWSTR szValueName;
807 LPCWSTR szDefaultPath; /* fallback string; sub dir of windows directory */
808 } CSIDL_DATA;
810 #define CSIDL_MYFLAG_SHFOLDER 1
811 #define CSIDL_MYFLAG_SETUP 2
812 #define CSIDL_MYFLAG_CURRVER 4
813 #define CSIDL_MYFLAG_RELATIVE 8
815 #define HKLM HKEY_LOCAL_MACHINE
816 #define HKCU HKEY_CURRENT_USER
817 #define HKEY_DISALLOWED (HKEY)0
818 #define HKEY_UNIMPLEMENTED (HKEY)1
819 #define HKEY_WINDOWSPATH (HKEY)2
820 #define HKEY_NONEXISTENT (HKEY)3
821 static const CSIDL_DATA CSIDL_Data[] =
823 { /* CSIDL_DESKTOP */
824 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
825 HKCU,
826 DesktopW,
827 DesktopW
829 { /* CSIDL_INTERNET */
831 HKEY_DISALLOWED,
832 NULL,
833 NULL
835 { /* CSIDL_PROGRAMS */
836 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
837 HKCU,
838 ProgramsW,
839 Start_Menu__ProgramsW
841 { /* CSIDL_CONTROLS (.CPL files) */
842 CSIDL_MYFLAG_SETUP | CSIDL_MYFLAG_RELATIVE,
843 HKLM,
844 SysDirW,
845 SystemW
847 { /* CSIDL_PRINTERS */
848 CSIDL_MYFLAG_SETUP | CSIDL_MYFLAG_RELATIVE,
849 HKLM,
850 SysDirW,
851 SystemW
853 { /* CSIDL_PERSONAL */
854 CSIDL_MYFLAG_SHFOLDER,
855 HKCU,
856 PersonalW,
857 My_DocumentsW
859 { /* CSIDL_FAVORITES */
860 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
861 HKCU,
862 FavoritesW,
863 FavoritesW
865 { /* CSIDL_STARTUP */
866 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
867 HKCU,
868 StartUpW,
869 Start_Menu__Programs__StartUpW
871 { /* CSIDL_RECENT */
872 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
873 HKCU,
874 RecentW,
875 RecentW
877 { /* CSIDL_SENDTO */
878 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
879 HKCU,
880 SendToW,
881 SendToW
883 { /* CSIDL_BITBUCKET - Recycle Bin */
885 HKEY_DISALLOWED,
886 NULL,
887 NULL,
889 { /* CSIDL_STARTMENU */
890 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
891 HKCU,
892 Start_MenuW,
893 Start_MenuW
895 { /* CSIDL_MYDOCUMENTS */
897 HKEY_UNIMPLEMENTED, /* FIXME */
898 NULL,
899 NULL
901 { /* CSIDL_MYMUSIC */
902 CSIDL_MYFLAG_SHFOLDER,
903 HKCU,
904 My_MusicW,
905 My_Documents__My_MusicW
907 { /* CSIDL_MYVIDEO */
908 CSIDL_MYFLAG_SHFOLDER,
909 HKCU,
910 My_VideoW,
911 My_Documents__My_VideoW
913 { /* unassigned */
915 HKEY_DISALLOWED,
916 NULL,
917 NULL,
919 { /* CSIDL_DESKTOPDIRECTORY */
920 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
921 HKCU,
922 DesktopW,
923 DesktopW
925 { /* CSIDL_DRIVES */
927 HKEY_DISALLOWED,
928 NULL,
929 NULL,
931 { /* CSIDL_NETWORK */
933 HKEY_DISALLOWED,
934 NULL,
935 NULL,
937 { /* CSIDL_NETHOOD */
938 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
939 HKCU,
940 NetHoodW,
941 NetHoodW
943 { /* CSIDL_FONTS */
944 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
945 HKCU,
946 FontsW,
947 FontsW
949 { /* CSIDL_TEMPLATES */
950 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
951 HKCU,
952 TemplatesW,
953 ShellNewW
955 { /* CSIDL_COMMON_STARTMENU */
956 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
957 HKLM,
958 Common_Start_MenuW,
959 All_Users__Start_MenuW
961 { /* CSIDL_COMMON_PROGRAMS */
962 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
963 HKLM,
964 Common_ProgramsW,
965 All_Users__Start_Menu__ProgramsW
967 { /* CSIDL_COMMON_STARTUP */
968 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
969 HKLM,
970 Common_StartUpW,
971 All_Users__Start_Menu__Programs__StartUpW
973 { /* CSIDL_COMMON_DESKTOPDIRECTORY */
974 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
975 HKLM,
976 Common_DesktopW,
977 All_Users__DesktopW
979 { /* CSIDL_APPDATA */
980 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
981 HKCU,
982 AppDataW,
983 Application_DataW
985 { /* CSIDL_PRINTHOOD */
986 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
987 HKCU,
988 PrintHoodW,
989 PrintHoodW
991 { /* CSIDL_LOCAL_APPDATA (win2k only/undocumented) */
992 CSIDL_MYFLAG_SHFOLDER,
993 HKCU,
994 Local_AppDataW,
995 Local_Settings__Application_DataW,
997 { /* CSIDL_ALTSTARTUP */
999 HKEY_NONEXISTENT,
1000 NULL,
1001 NULL
1003 { /* CSIDL_COMMON_ALTSTARTUP */
1005 HKEY_NONEXISTENT,
1006 NULL,
1007 NULL
1009 { /* CSIDL_COMMON_FAVORITES */
1010 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
1011 HKCU,
1012 FavoritesW,
1013 FavoritesW
1015 { /* CSIDL_INTERNET_CACHE (32) */
1016 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
1017 HKCU,
1018 CacheW,
1019 Temporary_Internet_FilesW
1021 { /* CSIDL_COOKIES (33) */
1022 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
1023 HKCU,
1024 CookiesW,
1025 CookiesW
1027 { /* CSIDL_HISTORY (34) */
1028 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
1029 HKCU,
1030 HistoryW,
1031 HistoryW
1033 { /* CSIDL_COMMON_APPDATA */
1034 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
1035 HKLM,
1036 Common_AppDataW,
1037 All_Users__Application_DataW
1039 { /* CSIDL_WINDOWS */
1040 CSIDL_MYFLAG_SETUP,
1041 HKLM,
1042 WinDirW,
1043 WindowsW
1045 { /* CSIDL_SYSTEM */
1046 CSIDL_MYFLAG_SETUP | CSIDL_MYFLAG_RELATIVE,
1047 HKLM,
1048 SysDirW,
1049 SystemW
1051 { /* CSIDL_PROGRAM_FILES */
1052 CSIDL_MYFLAG_CURRVER,
1053 HKLM,
1054 ProgramFilesDirW,
1055 Program_FilesW
1057 { /* CSIDL_MYPICTURES */
1058 CSIDL_MYFLAG_SHFOLDER,
1059 HKCU,
1060 My_PicturesW,
1061 My_Documents__My_PicturesW
1063 { /* CSIDL_PROFILE */
1064 CSIDL_MYFLAG_SETUP | CSIDL_MYFLAG_RELATIVE,
1065 HKLM,
1066 WinDirW, /* correct ? */
1067 Empty_StringW
1069 { /* CSIDL_SYSTEMX86 */
1070 CSIDL_MYFLAG_SETUP | CSIDL_MYFLAG_RELATIVE,
1071 HKLM,
1072 SysDirW,
1073 SystemW
1075 { /* CSIDL_PROGRAM_FILESX86 */
1076 CSIDL_MYFLAG_CURRVER,
1077 HKLM,
1078 ProgramFilesDirW,
1079 Program_FilesW
1081 { /* CSIDL_PROGRAM_FILES_COMMON */
1082 CSIDL_MYFLAG_CURRVER,
1083 HKLM,
1084 CommonFilesDirW,
1085 Program_Files__Common_FilesW /* ? */
1087 { /* CSIDL_PROGRAM_FILES_COMMONX86 */
1088 CSIDL_MYFLAG_CURRVER,
1089 HKLM,
1090 CommonFilesDirW,
1091 Program_Files__Common_FilesW /* ? */
1093 { /* CSIDL_COMMON_TEMPLATES */
1094 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
1095 HKLM,
1096 Common_TemplatesW,
1097 /*"Documents and Settings\\"*/ All_Users__TemplatesW
1099 { /* CSIDL_COMMON_DOCUMENTS */
1100 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
1101 HKLM,
1102 Common_DocumentsW,
1103 /*"Documents and Settings\\"*/ All_Users__DocumentsW
1105 { /* CSIDL_COMMON_ADMINTOOLS */
1106 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
1107 HKLM,
1108 Common_Administrative_ToolsW,
1109 /*"Documents and Settings\\"*/ All_Users__Start_Menu__Programs__Administrative_ToolsW
1111 { /* CSIDL_ADMINTOOLS */
1112 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
1113 HKCU,
1114 Administrative_ToolsW,
1115 Start_Menu__Programs__Administrative_ToolsW
1117 { /* CSIDL_CONNECTIONS */
1119 HKEY_DISALLOWED,
1120 NULL,
1121 NULL
1123 { /* unassigned 32 */
1125 HKEY_DISALLOWED,
1126 NULL,
1127 NULL
1129 { /* unassigned 33 */
1131 HKEY_DISALLOWED,
1132 NULL,
1133 NULL
1135 { /* unassigned 34 */
1137 HKEY_DISALLOWED,
1138 NULL,
1139 NULL
1141 { /* CSIDL_COMMON_MUSIC */
1142 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
1143 HKLM,
1144 CommonMusicW,
1145 /*"Documents and Settings\\"*/ All_Users__Documents__My_MusicW
1147 { /* CSIDL_COMMON_PICTURES */
1148 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
1149 HKLM,
1150 CommonPicturesW,
1151 /*"Documents and Settings\\"*/ All_Users__Documents__My_PicturesW
1153 { /* CSIDL_COMMON_VIDEO */
1154 CSIDL_MYFLAG_SHFOLDER | CSIDL_MYFLAG_RELATIVE,
1155 HKLM,
1156 CommonVideoW,
1157 /*"Documents and Settings\\"*/ All_Users__Documents__My_VideoW
1159 { /* CSIDL_RESOURCES */
1161 HKEY_WINDOWSPATH,
1162 NULL,
1163 ResourcesW
1165 { /* CSIDL_RESOURCES_LOCALIZED */
1167 HKEY_DISALLOWED, /* FIXME */
1168 NULL,
1169 NULL
1171 { /* CSIDL_COMMON_OEM_LINKS */
1173 HKEY_DISALLOWED, /* FIXME */
1174 NULL,
1175 NULL
1177 { /* CSIDL_CDBURN_AREA */
1178 CSIDL_MYFLAG_SHFOLDER,
1179 HKCU,
1180 CD_BurningW,
1181 Local_Settings__Application_Data__Microsoft__CD_BurningW
1183 { /* unassigned 3C */
1185 HKEY_DISALLOWED,
1186 NULL,
1187 NULL
1189 { /* CSIDL_COMPUTERSNEARME */
1191 HKEY_DISALLOWED, /* FIXME */
1192 NULL,
1193 NULL
1195 { /* CSIDL_PROFILES */
1197 HKEY_DISALLOWED, /* FIXME */
1198 NULL,
1199 NULL
1202 #undef HKCU
1203 #undef HKLM
1205 /**********************************************************************/
1207 HRESULT WINAPI SHGetFolderPathW(
1208 HWND hwndOwner,
1209 int csidl,
1210 HANDLE hToken, /* [in] FIXME: get paths for specific user */
1211 DWORD dwFlags, /* [in] FIXME: SHGFP_TYPE_CURRENT|SHGFP_TYPE_DEFAULT */
1212 LPWSTR pszPath)
1214 WCHAR szBuildPath[MAX_PATH];
1215 HKEY hRootKey, hKey;
1216 DWORD dwCsidlFlags;
1217 DWORD dwType, dwDisp, dwPathLen = MAX_PATH;
1218 DWORD folder = csidl & CSIDL_FOLDER_MASK;
1219 WCHAR *p;
1221 TRACE("%p,%p,csidl=0x%04x\n", hwndOwner,pszPath,csidl);
1223 if (!pszPath)
1224 return E_INVALIDARG;
1226 *pszPath = '\0';
1227 if ((folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0])) ||
1228 (CSIDL_Data[folder].hRootKey == HKEY_DISALLOWED))
1229 return E_INVALIDARG;
1230 if (CSIDL_Data[folder].hRootKey == HKEY_UNIMPLEMENTED)
1232 FIXME("folder 0x%04lx unknown, please add.\n", folder);
1233 return E_FAIL;
1235 if (CSIDL_Data[folder].hRootKey == HKEY_NONEXISTENT)
1236 return S_FALSE;
1238 /* Special case for some values that don't exist in registry */
1239 if (CSIDL_Data[folder].hRootKey == HKEY_WINDOWSPATH)
1241 GetWindowsDirectoryW(pszPath, MAX_PATH);
1242 PathAddBackslashW(pszPath);
1243 strcatW(pszPath, CSIDL_Data[folder].szDefaultPath);
1244 return S_OK;
1247 dwCsidlFlags = CSIDL_Data[folder].dwFlags;
1248 hRootKey = CSIDL_Data[folder].hRootKey;
1250 if (dwCsidlFlags & CSIDL_MYFLAG_SHFOLDER)
1252 /* user shell folders */
1253 if (RegCreateKeyExW(hRootKey,szSHUserFolders,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return E_FAIL;
1255 if (RegQueryValueExW(hKey,CSIDL_Data[folder].szValueName,NULL,&dwType,(LPBYTE)pszPath,&dwPathLen))
1257 RegCloseKey(hKey);
1259 /* shell folders */
1260 if (RegCreateKeyExW(hRootKey,szSHFolders,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return E_FAIL;
1262 if (RegQueryValueExW(hKey,CSIDL_Data[folder].szValueName,NULL,&dwType,(LPBYTE)pszPath,&dwPathLen))
1265 /* value not existing */
1266 if (dwCsidlFlags & CSIDL_MYFLAG_RELATIVE)
1268 GetWindowsDirectoryW(pszPath, MAX_PATH);
1269 PathAddBackslashW(pszPath);
1270 strcatW(pszPath, CSIDL_Data[folder].szDefaultPath);
1272 else
1274 GetSystemDirectoryW(pszPath, MAX_PATH);
1275 strcpyW(pszPath + 3, CSIDL_Data[folder].szDefaultPath);
1277 dwType=REG_SZ;
1278 RegSetValueExW(hKey,CSIDL_Data[folder].szValueName,0,REG_SZ,(LPBYTE)pszPath,
1279 (strlenW(pszPath)+1)*sizeof(WCHAR));
1282 RegCloseKey(hKey);
1284 else
1286 LPCWSTR pRegPath;
1288 if (dwCsidlFlags & CSIDL_MYFLAG_SETUP)
1289 pRegPath = szSetup;
1290 else if (dwCsidlFlags & CSIDL_MYFLAG_CURRVER)
1291 pRegPath = szCurrentVersion;
1292 else
1294 ERR("folder settings broken, please correct !\n");
1295 return E_FAIL;
1298 if (RegCreateKeyExW(hRootKey,pRegPath,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return E_FAIL;
1300 if (RegQueryValueExW(hKey,CSIDL_Data[folder].szValueName,NULL,&dwType,(LPBYTE)pszPath,&dwPathLen))
1302 /* value not existing */
1303 if (dwCsidlFlags & CSIDL_MYFLAG_RELATIVE)
1305 GetWindowsDirectoryW(pszPath, MAX_PATH);
1306 PathAddBackslashW(pszPath);
1307 strcatW(pszPath, CSIDL_Data[folder].szDefaultPath);
1309 else
1311 GetSystemDirectoryW(pszPath, MAX_PATH);
1312 strcpyW(pszPath + 3, CSIDL_Data[folder].szDefaultPath);
1314 dwType=REG_SZ;
1315 RegSetValueExW(hKey,CSIDL_Data[folder].szValueName,0,REG_SZ,(LPBYTE)pszPath,
1316 (strlenW(pszPath)+1)*sizeof(WCHAR));
1318 RegCloseKey(hKey);
1321 /* expand paths like %USERPROFILE% */
1322 if (dwType == REG_EXPAND_SZ)
1324 ExpandEnvironmentStringsW(pszPath, szBuildPath, MAX_PATH);
1325 strcpyW(pszPath, szBuildPath);
1328 /* if we don't care about existing directories we are ready */
1329 if(csidl & CSIDL_FLAG_DONT_VERIFY) return S_OK;
1331 if (PathFileExistsW(pszPath)) return S_OK;
1333 /* not existing but we are not allowed to create it */
1334 if (!(csidl & CSIDL_FLAG_CREATE)) return E_FAIL;
1336 /* create directory/directories */
1337 strcpyW(szBuildPath, pszPath);
1338 p = strchrW(szBuildPath, '\\');
1339 while (p)
1341 *p = 0;
1342 if (!PathFileExistsW(szBuildPath))
1344 if (!CreateDirectoryW(szBuildPath,NULL))
1346 ERR("Failed to create directory '%s'.\n", debugstr_w(pszPath));
1347 return E_FAIL;
1350 *p = '\\';
1351 p = strchrW(p+1, '\\');
1353 /* last component must be created too. */
1354 if (!PathFileExistsW(szBuildPath))
1356 if (!CreateDirectoryW(szBuildPath,NULL))
1358 ERR("Failed to create directory '%s'.\n", debugstr_w(pszPath));
1359 return E_FAIL;
1363 TRACE("Created missing system directory '%s'\n", debugstr_w(pszPath));
1364 return S_OK;
1367 /*************************************************************************
1368 * SHGetFolderPathA [SHELL32.@]
1370 HRESULT WINAPI SHGetFolderPathA(
1371 HWND hwndOwner,
1372 int csidl,
1373 HANDLE hToken,
1374 DWORD dwFlags,
1375 LPSTR pszPath)
1377 WCHAR szTemp[MAX_PATH];
1378 HRESULT hr;
1380 if (!pszPath)
1381 return E_INVALIDARG;
1383 *pszPath = '\0';
1384 hr = SHGetFolderPathW(hwndOwner, csidl, hToken, dwFlags, szTemp);
1385 if (SUCCEEDED(hr))
1386 WideCharToMultiByte(CP_ACP, 0, szTemp, -1, pszPath, MAX_PATH, NULL,
1387 NULL);
1389 TRACE("%p,%p,csidl=0x%04x\n",hwndOwner,pszPath,csidl);
1391 return hr;
1394 /*************************************************************************
1395 * SHGetSpecialFolderPathA [SHELL32.@]
1397 BOOL WINAPI SHGetSpecialFolderPathA (
1398 HWND hwndOwner,
1399 LPSTR szPath,
1400 int csidl,
1401 BOOL bCreate)
1403 return (SHGetFolderPathA(
1404 hwndOwner,
1405 csidl + (bCreate ? CSIDL_FLAG_CREATE : 0),
1406 NULL,
1408 szPath)) == S_OK ? TRUE : FALSE;
1411 /*************************************************************************
1412 * SHGetSpecialFolderPathW
1414 BOOL WINAPI SHGetSpecialFolderPathW (
1415 HWND hwndOwner,
1416 LPWSTR szPath,
1417 int csidl,
1418 BOOL bCreate)
1420 return (SHGetFolderPathW(
1421 hwndOwner,
1422 csidl + (bCreate ? CSIDL_FLAG_CREATE : 0),
1423 NULL,
1425 szPath)) == S_OK ? TRUE : FALSE;
1428 /*************************************************************************
1429 * SHGetSpecialFolderPath (SHELL32.175)
1431 BOOL WINAPI SHGetSpecialFolderPathAW (
1432 HWND hwndOwner,
1433 LPVOID szPath,
1434 int csidl,
1435 BOOL bCreate)
1438 if (SHELL_OsIsUnicode())
1439 return SHGetSpecialFolderPathW (hwndOwner, szPath, csidl, bCreate);
1440 return SHGetSpecialFolderPathA (hwndOwner, szPath, csidl, bCreate);
1443 /*************************************************************************
1444 * SHGetSpecialFolderLocation [SHELL32.@]
1446 * gets the folder locations from the registry and creates a pidl
1447 * creates missing reg keys and directories
1449 * PARAMS
1450 * hwndOwner [I]
1451 * nFolder [I] CSIDL_xxxxx
1452 * ppidl [O] PIDL of a special folder
1454 * NOTES
1455 * In NT5, SHGetSpecialFolderLocation needs the <winntdir>/Recent
1456 * directory. If the directory is missing it returns a x80070002.
1457 * In most cases, this forwards to SHGetSpecialFolderPath, but
1458 * CSIDLs with virtual folders (not real paths) must be handled
1459 * here.
1461 HRESULT WINAPI SHGetSpecialFolderLocation(
1462 HWND hwndOwner,
1463 INT nFolder,
1464 LPITEMIDLIST * ppidl)
1466 HRESULT hr = E_INVALIDARG;
1468 TRACE("(%p,0x%x,%p)\n", hwndOwner,nFolder,ppidl);
1470 if (!ppidl)
1471 return E_INVALIDARG;
1473 *ppidl = NULL;
1474 switch (nFolder)
1476 case CSIDL_DESKTOP:
1477 *ppidl = _ILCreateDesktop();
1478 break;
1480 case CSIDL_INTERNET:
1481 *ppidl = _ILCreateIExplore();
1482 break;
1484 case CSIDL_CONTROLS:
1485 *ppidl = _ILCreateControlPanel();
1486 break;
1488 case CSIDL_PRINTERS:
1489 *ppidl = _ILCreatePrinters();
1490 break;
1492 case CSIDL_BITBUCKET:
1493 *ppidl = _ILCreateBitBucket();
1494 break;
1496 case CSIDL_DRIVES:
1497 *ppidl = _ILCreateMyComputer();
1498 break;
1500 case CSIDL_NETWORK:
1501 *ppidl = _ILCreateNetwork();
1502 break;
1504 case CSIDL_ALTSTARTUP:
1505 case CSIDL_COMMON_ALTSTARTUP:
1506 hr = E_FAIL;
1507 break;
1509 case CSIDL_COMPUTERSNEARME:
1510 hr = E_FAIL;
1511 break;
1513 default:
1515 WCHAR szPath[MAX_PATH];
1517 if (SHGetSpecialFolderPathW(hwndOwner, szPath, nFolder, TRUE))
1519 DWORD attributes=0;
1521 TRACE("Value=%s\n", debugstr_w(szPath));
1522 hr = SHILCreateFromPathW(szPath, ppidl, &attributes);
1526 if(*ppidl)
1527 hr = NOERROR;
1529 TRACE("-- (new pidl %p)\n",*ppidl);
1530 return hr;
1533 /*************************************************************************
1534 * SHGetFolderLocation [SHELL32.@]
1536 * NOTES
1537 * the pidl can be a simple one. since we can't get the path out of the pidl
1538 * we have to take all data from the pidl
1539 * Mostly we forward to SHGetSpecialFolderLocation, but a few special cases
1540 * we handle here.
1542 HRESULT WINAPI SHGetFolderLocation(
1543 HWND hwnd,
1544 int csidl,
1545 HANDLE hToken,
1546 DWORD dwFlags,
1547 LPITEMIDLIST *ppidl)
1549 HRESULT hr;
1551 TRACE_(shell)("%p 0x%08x %p 0x%08lx %p\n",
1552 hwnd, csidl, hToken, dwFlags, ppidl);
1554 if (!ppidl)
1555 return E_INVALIDARG;
1557 switch (csidl)
1559 case CSIDL_ALTSTARTUP:
1560 case CSIDL_COMMON_ALTSTARTUP:
1561 *ppidl = NULL;
1562 hr = S_FALSE;
1563 break;
1564 default:
1565 hr = SHGetSpecialFolderLocation(hwnd, csidl, ppidl);
1567 return hr;