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