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