Removed some of the XXX_reg macros now that we are using the standard
[wine] / dlls / shell32 / shellpath.c
1 /*
2  * Path Functions
3  *
4  * Many of this functions are in SHLWAPI.DLL also
5  *
6  */
7 #include <string.h>
8 #include <ctype.h>
9 #include "debugtools.h"
10 #include "winnls.h"
11 #include "winreg.h"
12
13 #include "shlobj.h"
14 #include "shell32_main.h"
15 #include "windef.h"
16 #include "options.h"
17 #include "wine/winestring.h"
18 #include "wine/undocshell.h"
19 #include "wine/unicode.h"
20 #include "shlwapi.h"
21
22 DEFAULT_DEBUG_CHANNEL(shell);
23
24 #define isSlash(x) ((x)=='\\' || (x)=='/')
25 /*
26         ########## Combining and Constructing paths ##########
27 */
28
29 /*************************************************************************
30  * PathAppendAW         [SHELL32.36]
31  */
32 BOOL WINAPI PathAppendAW(
33         LPVOID lpszPath1,
34         LPCVOID lpszPath2)
35 {
36         if (SHELL_OsIsUnicode())
37           return PathAppendW(lpszPath1, lpszPath2);
38         return PathAppendA(lpszPath1, lpszPath2);
39 }
40
41 /*************************************************************************
42  * PathCombineAW         [SHELL32.37]
43  */
44 LPVOID WINAPI PathCombineAW(
45         LPVOID szDest,
46         LPCVOID lpszDir,
47         LPCVOID lpszFile) 
48 {
49         if (SHELL_OsIsUnicode())
50           return PathCombineW( szDest, lpszDir, lpszFile );
51         return PathCombineA( szDest, lpszDir, lpszFile );
52 }
53
54 /*************************************************************************
55  * PathAddBackslashAW           [SHELL32.32]
56  */
57 LPVOID WINAPI PathAddBackslashAW(LPVOID lpszPath)
58 {
59         if(SHELL_OsIsUnicode())
60           return PathAddBackslashW(lpszPath);
61         return PathAddBackslashA(lpszPath);
62 }
63
64 /*************************************************************************
65  * PathBuildRootAW              [SHELL32.30]
66  */
67 LPVOID WINAPI PathBuildRootAW(LPVOID lpszPath, int drive)
68 {
69         if(SHELL_OsIsUnicode())
70           return PathBuildRootW(lpszPath, drive);
71         return PathBuildRootA(lpszPath, drive);
72 }
73
74 /*
75         Extracting Component Parts
76 */
77
78 /*************************************************************************
79  * PathFindFileNameAW   [SHELL32.34]
80  */
81 LPVOID WINAPI PathFindFileNameAW(LPCVOID lpszPath)
82 {
83         if(SHELL_OsIsUnicode())
84           return PathFindFileNameW(lpszPath);
85         return PathFindFileNameA(lpszPath);
86 }
87
88 /*************************************************************************
89  * PathFindExtensionAW          [SHELL32.31]
90  */
91 LPVOID WINAPI PathFindExtensionAW(LPCVOID lpszPath) 
92 {
93         if (SHELL_OsIsUnicode())
94           return PathFindExtensionW(lpszPath);
95         return PathFindExtensionA(lpszPath);
96
97 }
98
99 /*************************************************************************
100  * PathGetExtensionA            [internal]
101  *
102  * NOTES
103  *  exported by ordinal
104  *  return value points to the first char after the dot
105  */
106 static LPSTR PathGetExtensionA(LPCSTR lpszPath)
107 {
108         TRACE("(%s)\n",lpszPath);
109
110         lpszPath = PathFindExtensionA(lpszPath);
111         return (LPSTR)(*lpszPath?(lpszPath+1):lpszPath);
112 }
113
114 /*************************************************************************
115  * PathGetExtensionW            [internal]
116  */
117 static LPWSTR PathGetExtensionW(LPCWSTR lpszPath)
118 {
119         TRACE("(%s)\n",debugstr_w(lpszPath));
120
121         lpszPath = PathFindExtensionW(lpszPath);
122         return (LPWSTR)(*lpszPath?(lpszPath+1):lpszPath);
123 }
124
125 /*************************************************************************
126  * PathGetExtensionAW           [SHELL32.158]
127  */
128 LPVOID WINAPI PathGetExtensionAW(LPCVOID lpszPath) 
129 {
130         if (SHELL_OsIsUnicode())
131           return PathGetExtensionW(lpszPath);
132         return PathGetExtensionA(lpszPath);
133 }
134
135 /*************************************************************************
136  * PathGetArgsAW        [SHELL32.52]
137  */
138 LPVOID WINAPI PathGetArgsAW(LPVOID lpszPath) 
139 {
140         if (SHELL_OsIsUnicode())
141           return PathGetArgsW(lpszPath);
142         return PathGetArgsA(lpszPath);
143 }
144
145 /*************************************************************************
146  * PathGetDriveNumber   [SHELL32.57]
147  */
148 int WINAPI PathGetDriveNumberAW(LPVOID lpszPath) 
149 {
150         if (SHELL_OsIsUnicode())
151           return PathGetDriveNumberW(lpszPath);
152         return PathGetDriveNumberA(lpszPath);
153 }
154
155 /*************************************************************************
156  * PathRemoveFileSpec [SHELL32.35]
157  */
158 BOOL WINAPI PathRemoveFileSpecAW(LPVOID lpszPath) 
159 {
160         if (SHELL_OsIsUnicode())
161           return PathRemoveFileSpecW(lpszPath);
162         return PathRemoveFileSpecA(lpszPath);
163 }
164
165 /*************************************************************************
166  * PathStripPathAW      [SHELL32.38]
167  */
168 void WINAPI PathStripPathAW(LPVOID lpszPath) 
169 {
170         if (SHELL_OsIsUnicode())
171           return PathStripPathW(lpszPath);
172         return PathStripPathA(lpszPath);
173 }
174
175 /*************************************************************************
176  * PathStripToRootAW    [SHELL32.50]
177  */
178 BOOL WINAPI PathStripToRootAW(LPVOID lpszPath) 
179 {
180         if (SHELL_OsIsUnicode())
181           return PathStripToRootW(lpszPath);
182         return PathStripToRootA(lpszPath);
183 }
184
185 /*************************************************************************
186  * PathRemoveArgsAW     [SHELL32.251]
187  */
188 void WINAPI PathRemoveArgsAW(LPVOID lpszPath) 
189 {
190         if (SHELL_OsIsUnicode())
191           PathRemoveArgsW(lpszPath);
192         PathRemoveArgsA(lpszPath);
193 }
194
195 /*************************************************************************
196  * PathRemoveExtensionAW        [SHELL32.250]
197  */
198 void WINAPI PathRemoveExtensionAW(LPVOID lpszPath) 
199 {
200         if (SHELL_OsIsUnicode())
201           return PathRemoveExtensionW(lpszPath);
202         return PathRemoveExtensionA(lpszPath);
203 }
204
205
206 /*
207         Path Manipulations
208 */
209
210 /*************************************************************************
211  * PathGetShortPathA [internal]
212  */
213 LPSTR WINAPI PathGetShortPathA(LPSTR lpszPath)
214 {
215         FIXME("%s stub\n", lpszPath);
216         return NULL;
217 }
218
219 /*************************************************************************
220  * PathGetShortPathW [internal]
221  */
222 LPWSTR WINAPI PathGetShortPathW(LPWSTR lpszPath)
223 {
224         FIXME("%s stub\n", debugstr_w(lpszPath));
225         return NULL;
226 }
227
228 /*************************************************************************
229  * PathGetShortPathAW [SHELL32.92]
230  */
231 LPVOID WINAPI PathGetShortPathAW(LPVOID lpszPath)
232 {
233         if(SHELL_OsIsUnicode())
234           return PathGetShortPathW(lpszPath);
235         return PathGetShortPathA(lpszPath);
236 }
237
238 /*************************************************************************
239  * PathRemoveBlanksAW [SHELL32.33]
240  */
241 void WINAPI PathRemoveBlanksAW(LPVOID str)
242 {
243         if(SHELL_OsIsUnicode())
244           PathRemoveBlanksW(str);
245         PathRemoveBlanksA(str);
246 }
247
248 /*************************************************************************
249  * PathQuoteSpacesAW [SHELL32.55]
250  */
251 LPVOID WINAPI PathQuoteSpacesAW (LPVOID lpszPath)
252 {
253         if(SHELL_OsIsUnicode())
254           return PathQuoteSpacesW(lpszPath);
255         return PathQuoteSpacesA(lpszPath);
256 }
257
258 /*************************************************************************
259  * PathUnquoteSpacesAW [SHELL32.56]
260  */
261 VOID WINAPI PathUnquoteSpacesAW(LPVOID str) 
262 {
263         if(SHELL_OsIsUnicode())
264           PathUnquoteSpacesW(str);
265         else
266           PathUnquoteSpacesA(str);
267 }
268
269 /*************************************************************************
270  * PathParseIconLocationAW      [SHELL32.249]
271  */
272 int WINAPI PathParseIconLocationAW (LPVOID lpszPath)
273 {
274         if(SHELL_OsIsUnicode())
275           return PathParseIconLocationW(lpszPath);
276         return PathParseIconLocationA(lpszPath);
277 }
278
279 /*
280         ########## Path Testing ##########
281 */
282 /*************************************************************************
283  * PathIsUNCAW          [SHELL32.39]
284  */
285 BOOL WINAPI PathIsUNCAW (LPCVOID lpszPath)
286 {
287         if (SHELL_OsIsUnicode())
288           return PathIsUNCW( lpszPath );
289         return PathIsUNCA( lpszPath );  
290 }
291
292 /*************************************************************************
293  *  PathIsRelativeAW    [SHELL32.40]
294  */
295 BOOL WINAPI PathIsRelativeAW (LPCVOID lpszPath)
296 {
297         if (SHELL_OsIsUnicode())
298           return PathIsRelativeW( lpszPath );
299         return PathIsRelativeA( lpszPath );  
300 }
301
302 /*************************************************************************
303  * PathIsRootAW         [SHELL32.29]
304  */
305 BOOL WINAPI PathIsRootAW(LPCVOID lpszPath) 
306 {
307         if (SHELL_OsIsUnicode())
308           return PathIsRootW(lpszPath);
309         return PathIsRootA(lpszPath);
310 }
311
312 /*************************************************************************
313  *  PathIsExeA          [internal]
314  */
315 static BOOL PathIsExeA (LPCSTR lpszPath)
316 {
317         LPCSTR lpszExtension = PathGetExtensionA(lpszPath);
318         int i = 0;
319         static char * lpszExtensions[6] = {"exe", "com", "pid", "cmd", "bat", NULL };
320         
321         TRACE("path=%s\n",lpszPath);
322
323         for(i=0; lpszExtensions[i]; i++)
324           if (!strcasecmp(lpszExtension,lpszExtensions[i])) return TRUE;
325           
326         return FALSE;
327 }
328
329 /*************************************************************************
330  *  PathIsExeW          [internal]
331  */
332 static BOOL PathIsExeW (LPCWSTR lpszPath)
333 {
334         LPCWSTR lpszExtension = PathGetExtensionW(lpszPath);
335         int i = 0;
336         static WCHAR lpszExtensions[6][4] =
337           {{'e','x','e','\0'}, {'c','o','m','\0'}, {'p','i','d','\0'},
338            {'c','m','d','\0'}, {'b','a','t','\0'}, {'\0'} };
339         
340         TRACE("path=%s\n",debugstr_w(lpszPath));
341
342         for(i=0; lpszExtensions[i]; i++)
343           if (!strcmpiW(lpszExtension,lpszExtensions[i])) return TRUE;
344           
345         return FALSE;
346 }
347
348 /*************************************************************************
349  *  PathIsExeAW         [SHELL32.43]
350  */
351 BOOL WINAPI PathIsExeAW (LPCVOID path)
352 {
353         if (SHELL_OsIsUnicode())
354           return PathIsExeW (path);
355         return PathIsExeA(path);
356 }
357
358 /*************************************************************************
359  * PathIsDirectoryAW    [SHELL32.159]
360  */
361 BOOL WINAPI PathIsDirectoryAW (LPCVOID lpszPath)
362 {
363         if (SHELL_OsIsUnicode())
364           return PathIsDirectoryW (lpszPath);
365         return PathIsDirectoryA (lpszPath);
366 }
367
368 /*************************************************************************
369  * PathFileExistsAW     [SHELL32.45]
370  */ 
371 BOOL WINAPI PathFileExistsAW (LPCVOID lpszPath)
372 {
373         if (SHELL_OsIsUnicode())
374           return PathFileExistsW (lpszPath);
375         return PathFileExistsA (lpszPath);
376 }
377
378 /*************************************************************************
379  * PathMatchSpecAW      [SHELL32.46]
380  */
381 BOOL WINAPI PathMatchSpecAW(LPVOID name, LPVOID mask) 
382 {
383         if (SHELL_OsIsUnicode())
384           return PathMatchSpecW( name, mask );
385         return PathMatchSpecA( name, mask );
386 }
387
388 /*************************************************************************
389  * PathIsSameRootAW     [SHELL32.650]
390  */
391 BOOL WINAPI PathIsSameRootAW(LPCVOID lpszPath1, LPCVOID lpszPath2)
392 {
393         if (SHELL_OsIsUnicode())
394           return PathIsSameRootW(lpszPath1, lpszPath2);
395         return PathIsSameRootA(lpszPath1, lpszPath2);
396 }
397
398 /*************************************************************************
399  * IsLFNDriveA          [SHELL32.119]
400  * 
401  * NOTES
402  *     exported by ordinal Name
403  */
404 BOOL WINAPI IsLFNDriveA(LPCSTR lpszPath) 
405 {
406     DWORD       fnlen;
407
408     if (!GetVolumeInformationA(lpszPath,NULL,0,NULL,&fnlen,NULL,NULL,0))
409         return FALSE;
410     return fnlen>12;
411 }
412
413 /*
414         ########## Creating Something Unique ##########
415 */
416 /*************************************************************************
417  * PathMakeUniqueNameA  [internal]
418  */
419 BOOL WINAPI PathMakeUniqueNameA(
420         LPSTR lpszBuffer,
421         DWORD dwBuffSize, 
422         LPCSTR lpszShortName,
423         LPCSTR lpszLongName,
424         LPCSTR lpszPathName)
425 {
426         FIXME("%p %lu %s %s %s stub\n",
427          lpszBuffer, dwBuffSize, debugstr_a(lpszShortName),
428          debugstr_a(lpszLongName), debugstr_a(lpszPathName));
429         return TRUE;
430 }
431
432 /*************************************************************************
433  * PathMakeUniqueNameW  [internal]
434  */
435 BOOL WINAPI PathMakeUniqueNameW(
436         LPWSTR lpszBuffer,
437         DWORD dwBuffSize, 
438         LPCWSTR lpszShortName,
439         LPCWSTR lpszLongName,
440         LPCWSTR lpszPathName)
441 {
442         FIXME("%p %lu %s %s %s stub\n",
443          lpszBuffer, dwBuffSize, debugstr_w(lpszShortName),
444          debugstr_w(lpszLongName), debugstr_w(lpszPathName));
445         return TRUE;
446 }
447
448 /*************************************************************************
449  * PathMakeUniqueNameAW [SHELL32.47]
450  */
451 BOOL WINAPI PathMakeUniqueNameAW(
452         LPVOID lpszBuffer,
453         DWORD dwBuffSize, 
454         LPCVOID lpszShortName,
455         LPCVOID lpszLongName,
456         LPCVOID lpszPathName)
457 {
458         if (SHELL_OsIsUnicode())
459           return PathMakeUniqueNameW(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
460         return PathMakeUniqueNameA(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
461 }
462
463 /*************************************************************************
464  * PathYetAnotherMakeUniqueNameA [SHELL32.75]
465  * 
466  * NOTES
467  *     exported by ordinal
468  */
469 BOOL WINAPI PathYetAnotherMakeUniqueNameA(
470         LPSTR lpszBuffer,
471         LPCSTR lpszPathName,
472         LPCSTR lpszShortName,
473         LPCSTR lpszLongName)
474 {
475     FIXME("(%p,%p, %p ,%p):stub.\n",
476      lpszBuffer, lpszPathName, lpszShortName, lpszLongName);
477     return TRUE;
478 }
479
480
481 /*
482         ########## cleaning and resolving paths ##########
483  */
484
485 /*************************************************************************
486  * PathFindOnPathAW     [SHELL32]
487  */
488 BOOL WINAPI PathFindOnPathAW(LPVOID sFile, LPCVOID sOtherDirs)
489 {
490         if (SHELL_OsIsUnicode())
491           return PathFindOnPathW(sFile, sOtherDirs);
492         return PathFindOnPathA(sFile, sOtherDirs);
493 }
494
495 /*************************************************************************
496  * PathCleanupSpecAW    [SHELL32]
497  */
498 DWORD WINAPI PathCleanupSpecAW (LPVOID x, LPVOID y)
499 {
500     FIXME("(%p, %p) stub\n",x,y);
501     return TRUE;
502 }
503
504 /*************************************************************************
505  * PathQualifyA         [SHELL32]
506  */
507 BOOL WINAPI PathQualifyA(LPCSTR pszPath) 
508 {
509         FIXME("%s\n",pszPath);
510         return 0;
511 }
512
513 /*************************************************************************
514  * PathQualifyW         [SHELL32]
515  */
516 BOOL WINAPI PathQualifyW(LPCWSTR pszPath) 
517 {
518         FIXME("%s\n",debugstr_w(pszPath));
519         return 0;
520 }
521
522 /*************************************************************************
523  * PathQualifyAW        [SHELL32]
524  */
525 BOOL WINAPI PathQualifyAW(LPCVOID pszPath) 
526 {
527         if (SHELL_OsIsUnicode())
528           return PathQualifyW(pszPath);
529         return PathQualifyA(pszPath);
530 }
531
532 /*************************************************************************
533  * PathResolveA [SHELL32.51]
534  */
535 BOOL WINAPI PathResolveA(
536         LPSTR lpszPath,
537         LPCSTR *alpszPaths, 
538         DWORD dwFlags)
539 {
540         FIXME("(%s,%p,0x%08lx),stub!\n",
541           lpszPath, *alpszPaths, dwFlags);
542         return 0;
543 }
544
545 /*************************************************************************
546  * PathResolveW [SHELL32]
547  */
548 BOOL WINAPI PathResolveW(
549         LPWSTR lpszPath,
550         LPCWSTR *alpszPaths, 
551         DWORD dwFlags)
552 {
553         FIXME("(%s,%p,0x%08lx),stub!\n",
554           debugstr_w(lpszPath), debugstr_w(*alpszPaths), dwFlags);
555         return 0;
556 }
557
558 /*************************************************************************
559  * PathResolveAW [SHELL32]
560  */
561 BOOL WINAPI PathResolveAW(
562         LPVOID lpszPath,
563         LPCVOID *alpszPaths, 
564         DWORD dwFlags)
565 {
566         if (SHELL_OsIsUnicode())
567           return PathResolveW(lpszPath, (LPCWSTR*)alpszPaths, dwFlags);
568         return PathResolveA(lpszPath, (LPCSTR*)alpszPaths, dwFlags);
569 }
570
571 /*************************************************************************
572 *       PathProcessCommandA     [SHELL32.653]
573 */
574 HRESULT WINAPI PathProcessCommandA (
575         LPCSTR lpszPath,
576         LPSTR lpszBuff,
577         DWORD dwBuffSize,
578         DWORD dwFlags)
579 {
580         FIXME("%s %p 0x%04lx 0x%04lx stub\n",
581         lpszPath, lpszBuff, dwBuffSize, dwFlags);
582         strcpy(lpszBuff, lpszPath);
583         return 0;
584 }
585
586 /*************************************************************************
587 *       PathProcessCommandW
588 */
589 HRESULT WINAPI PathProcessCommandW (
590         LPCWSTR lpszPath,
591         LPWSTR lpszBuff,
592         DWORD dwBuffSize,
593         DWORD dwFlags)
594 {
595         FIXME("(%s, %p, 0x%04lx, 0x%04lx) stub\n",
596         debugstr_w(lpszPath), lpszBuff, dwBuffSize, dwFlags);
597         strcpyW(lpszBuff, lpszPath);
598         return 0;
599 }
600
601 /*************************************************************************
602 *       PathProcessCommandAW
603 */
604 HRESULT WINAPI PathProcessCommandAW (
605         LPCVOID lpszPath,
606         LPVOID lpszBuff,
607         DWORD dwBuffSize,
608         DWORD dwFlags)
609 {
610         if (SHELL_OsIsUnicode())
611           return PathProcessCommandW(lpszPath, lpszBuff, dwBuffSize, dwFlags);
612         return PathProcessCommandA(lpszPath, lpszBuff, dwBuffSize, dwFlags);
613 }
614
615 /*
616         ########## special ##########
617 */
618
619 /*************************************************************************
620  * PathSetDlgItemPathAW
621  */
622 BOOL WINAPI PathSetDlgItemPathAW(HWND hDlg, int id, LPCVOID pszPath) 
623 {       if (SHELL_OsIsUnicode())
624           return PathSetDlgItemPathW(hDlg, id, pszPath);
625         return PathSetDlgItemPathA(hDlg, id, pszPath);
626 }
627
628
629 /*************************************************************************
630  * SHGetSpecialFolderPathA [SHELL32.175]
631  * 
632  * converts csidl to path
633  */
634  
635 static char * szSHFolders = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
636 static char * szSHUserFolders = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders";
637 #if 0
638 static char * szEnvUserProfile = "%USERPROFILE%";
639 static char * szEnvSystemRoot = "%SYSTEMROOT%";
640 #endif
641
642 BOOL WINAPI SHGetSpecialFolderPathA (
643         HWND hwndOwner,
644         LPSTR szPath,
645         DWORD csidl,
646         BOOL bCreate)
647 {
648         CHAR    szValueName[MAX_PATH], szDefaultPath[MAX_PATH];
649         HKEY    hRootKey, hKey;
650         BOOL    bRelative = TRUE;
651         DWORD   dwType, dwDisp, dwPathLen = MAX_PATH;
652
653         TRACE("0x%04x,%p,csidl=%lu,0x%04x\n", hwndOwner,szPath,csidl,bCreate);
654
655         /* build default values */
656         switch(csidl)
657         {
658           case CSIDL_APPDATA:
659             hRootKey = HKEY_CURRENT_USER;
660             strcpy (szValueName, "AppData");
661             strcpy (szDefaultPath, "AppData");
662             break;
663
664           case CSIDL_COOKIES:
665             hRootKey = HKEY_CURRENT_USER;
666             strcpy (szValueName, "Cookies");
667             strcpy(szDefaultPath, "Cookies");
668             break;
669
670           case CSIDL_DESKTOPDIRECTORY:
671             hRootKey = HKEY_CURRENT_USER;
672             strcpy(szValueName, "Desktop");
673             strcpy(szDefaultPath, "Desktop");
674             break;
675
676           case CSIDL_COMMON_DESKTOPDIRECTORY:
677             hRootKey = HKEY_LOCAL_MACHINE;
678             strcpy(szValueName, "Common Desktop");
679             strcpy(szDefaultPath, "Desktop");
680             break;
681
682           case CSIDL_FAVORITES:
683             hRootKey = HKEY_CURRENT_USER;
684             strcpy(szValueName, "Favorites");
685             strcpy(szDefaultPath, "Favorites");
686             break;
687
688           case CSIDL_FONTS:
689             hRootKey = HKEY_CURRENT_USER;
690             strcpy(szValueName, "Fonts");
691             strcpy(szDefaultPath, "Fonts");
692             break;
693
694           case CSIDL_HISTORY:
695             hRootKey = HKEY_CURRENT_USER;
696             strcpy(szValueName, "History");
697             strcpy(szDefaultPath, "History");
698             break;
699
700           case CSIDL_NETHOOD:
701             hRootKey = HKEY_CURRENT_USER;
702             strcpy(szValueName, "NetHood");
703             strcpy(szDefaultPath, "NetHood");
704             break;
705
706           case CSIDL_INTERNET_CACHE:
707             hRootKey = HKEY_CURRENT_USER;
708             strcpy(szValueName, "Cache");
709             strcpy(szDefaultPath, "Temporary Internet Files");
710             break;
711
712           case CSIDL_PERSONAL:
713             hRootKey = HKEY_CURRENT_USER;
714             strcpy(szValueName, "Personal");
715             strcpy(szDefaultPath, "My Own Files");
716             bRelative = FALSE;
717             break;
718
719           case CSIDL_PRINTHOOD:
720             hRootKey = HKEY_CURRENT_USER;
721             strcpy(szValueName, "PrintHood");
722             strcpy(szDefaultPath, "PrintHood");
723             break;
724
725           case CSIDL_PROGRAMS:
726             hRootKey = HKEY_CURRENT_USER;
727             strcpy(szValueName, "Programs");
728             strcpy(szDefaultPath, "StartMenu\\Programs");
729             break;
730
731           case CSIDL_COMMON_PROGRAMS:
732             hRootKey = HKEY_LOCAL_MACHINE;
733             strcpy(szValueName, "Common Programs");
734             strcpy(szDefaultPath, "");
735             break;
736
737           case CSIDL_RECENT:
738             hRootKey = HKEY_CURRENT_USER;
739             strcpy(szValueName, "Recent");
740             strcpy(szDefaultPath, "Recent");
741             break;
742
743           case CSIDL_SENDTO:
744             hRootKey = HKEY_CURRENT_USER;
745             strcpy(szValueName, "SendTo");
746             strcpy(szDefaultPath, "SendTo");
747             break;
748
749           case CSIDL_STARTMENU:
750             hRootKey = HKEY_CURRENT_USER;
751             strcpy(szValueName, "StartMenu");
752             strcpy(szDefaultPath, "StartMenu");
753             break;
754
755           case CSIDL_COMMON_STARTMENU:
756             hRootKey = HKEY_LOCAL_MACHINE;
757             strcpy(szValueName, "Common StartMenu");
758             strcpy(szDefaultPath, "StartMenu");
759             break;
760
761           case CSIDL_STARTUP:
762             hRootKey = HKEY_CURRENT_USER;
763             strcpy(szValueName, "Startup");
764             strcpy(szDefaultPath, "StartMenu\\Programs\\Startup");
765             break;
766
767           case CSIDL_COMMON_STARTUP:
768             hRootKey = HKEY_LOCAL_MACHINE;
769             strcpy(szValueName, "Common Startup");
770             strcpy(szDefaultPath, "StartMenu\\Programs\\Startup");
771             break;
772
773           case CSIDL_TEMPLATES:
774             hRootKey = HKEY_CURRENT_USER;
775             strcpy(szValueName, "Templates");
776             strcpy(szDefaultPath, "ShellNew");
777             break;
778
779           default:
780             ERR("folder unknown or not allowed\n");
781             return FALSE;
782         }
783
784         /* user shell folders */
785         if (RegCreateKeyExA(hRootKey,szSHUserFolders,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return FALSE;
786
787         if (RegQueryValueExA(hKey,szValueName,NULL,&dwType,(LPBYTE)szPath,&dwPathLen))
788         {
789           RegCloseKey(hKey);
790
791           /* shell folders */
792           if (RegCreateKeyExA(hRootKey,szSHFolders,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return FALSE;
793
794           if (RegQueryValueExA(hKey,szValueName,NULL,&dwType,(LPBYTE)szPath,&dwPathLen))
795           {
796
797             /* value not existing */
798             if (bRelative)
799             {
800               GetWindowsDirectoryA(szPath, MAX_PATH);
801               PathAddBackslashA(szPath);
802               strcat(szPath, szDefaultPath);
803             }
804             else
805             {
806               strcpy(szPath, "C:\\");   /* fixme ??? */
807               strcat(szPath, szDefaultPath);
808             }
809             RegSetValueExA(hKey,szValueName,0,REG_SZ,(LPBYTE)szPath,strlen(szPath)+1);
810           }
811         }
812         RegCloseKey(hKey);
813
814         /* expand paths like %USERPROFILE% */
815         if (dwType == REG_EXPAND_SZ)
816         {
817           ExpandEnvironmentStringsA(szPath, szDefaultPath, MAX_PATH);
818           strcpy(szPath, szDefaultPath);
819         }
820
821         /* if we don't care about existing directorys we are ready */
822         if(csidl & CSIDL_FLAG_DONT_VERIFY) return TRUE;
823
824         if (PathFileExistsA(szPath)) return TRUE;
825
826         /* not existing but we not allowed to create it */
827         if (!bCreate) return FALSE;
828         
829         if (!CreateDirectoryA(szPath,NULL))
830         {
831           ERR("Failed to create directory '%s'.\n", szPath);
832           return FALSE;
833         }
834
835         MESSAGE("Created not existing system directory '%s'\n", szPath);
836         return TRUE;
837 }
838
839 /*************************************************************************
840  * SHGetSpecialFolderPathW
841  */
842 BOOL WINAPI SHGetSpecialFolderPathW (
843         HWND hwndOwner,
844         LPWSTR szPath,
845         DWORD csidl,
846         BOOL bCreate)
847 {
848         char szTemp[MAX_PATH];
849         
850         if (SHGetSpecialFolderPathA(hwndOwner, szTemp, csidl, bCreate))
851         {
852           lstrcpynAtoW(szPath, szTemp, MAX_PATH);
853         }
854
855         TRACE("0x%04x,%p,csidl=%lu,0x%04x\n", hwndOwner,szPath,csidl,bCreate);
856
857         return TRUE;
858 }
859
860 /*************************************************************************
861  * SHGetSpecialFolderPathAW
862  */
863 BOOL WINAPI SHGetSpecialFolderPathAW (
864         HWND hwndOwner,
865         LPVOID szPath,
866         DWORD csidl,
867         BOOL bCreate)
868
869 {
870         if (SHELL_OsIsUnicode())
871           return SHGetSpecialFolderPathW (hwndOwner, szPath, csidl, bCreate);
872         return SHGetSpecialFolderPathA (hwndOwner, szPath, csidl, bCreate);
873 }
874
875 /*************************************************************************
876  * SHGetFolderPathA                     [SHFOLDER.@]
877  */
878 HRESULT WINAPI SHGetFolderPathA(
879         HWND hwndOwner,
880         int nFolder,
881         HANDLE hToken,  /* FIXME: get paths for specific user */
882         DWORD dwFlags,  /* FIXME: SHGFP_TYPE_CURRENT|SHGFP_TYPE_DEFAULT */
883         LPSTR pszPath)
884 {
885         return (SHGetSpecialFolderPathA(
886                 hwndOwner,
887                 pszPath,
888                 CSIDL_FOLDER_MASK & nFolder,
889                 CSIDL_FLAG_CREATE & nFolder )) ? S_OK : E_FAIL;
890 }
891
892 /*************************************************************************
893  * SHGetFolderPathW                     [SHFOLDER.@]
894  */
895 HRESULT WINAPI SHGetFolderPathW(
896         HWND hwndOwner,
897         int nFolder,
898         HANDLE hToken,
899         DWORD dwFlags,
900         LPWSTR pszPath)
901 {
902         return (SHGetSpecialFolderPathW(
903                 hwndOwner,
904                 pszPath,
905                 CSIDL_FOLDER_MASK & nFolder,
906                 CSIDL_FLAG_CREATE & nFolder )) ? S_OK : E_FAIL;
907 }