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