Added DebugBreak.
[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
13 #include "shlobj.h"
14 #include "shell32_main.h"
15
16 DEFAULT_DEBUG_CHANNEL(shell)
17
18 /*************************************************************************
19  * PathIsRoot [SHELL32.29]
20  */
21 BOOL WINAPI PathIsRootA(LPCSTR x)
22 {       TRACE("%s\n",x);
23         if (*(x+1)==':' && *(x+2)=='\\')                /* "X:\" */
24           return 1;
25         if (*x=='\\')           /* "\" */
26           return 0;
27         if (x[0]=='\\' && x[1]=='\\')           /* UNC "\\<xx>\" */
28         { int   foundbackslash = 0;
29           x=x+2;
30           while (*x)
31           { if (*x++=='\\')
32               foundbackslash++;
33           }
34           if (foundbackslash<=1)        /* max 1 \ more ... */
35             return 1;
36         }
37         return 0;
38 }
39 BOOL WINAPI PathIsRootW(LPCWSTR x) 
40 {       TRACE("%s\n",debugstr_w(x));
41         if (*(x+1)==':' && *(x+2)=='\\')                /* "X:\" */
42           return 1;
43         if (*x == (WCHAR) '\\')         /* "\" */
44           return 0;
45         if (x[0]==(WCHAR)'\\' && x[1]==(WCHAR)'\\')     /* UNC "\\<xx>\" */
46         { int   foundbackslash = 0;
47           x=x+2;
48           while (*x) 
49           { if (*x++==(WCHAR)'\\')
50               foundbackslash++;
51           }
52           if (foundbackslash<=1)        /* max 1 \ more ... */
53             return 1;
54         }
55         return 0;
56 }
57 BOOL WINAPI PathIsRootAW(LPCVOID x) 
58 {       if (VERSION_OsIsUnicode())
59           return PathIsRootW(x);
60         return PathIsRootA(x);
61
62 }
63 /*************************************************************************
64  * PathBuildRoot [SHELL32.30]
65  */
66 LPSTR WINAPI PathBuildRootA(LPSTR root,BYTE drive) {
67   TRACE("%p %i\n",root, drive);
68         strcpy(root,"A:\\");
69         root[0]+=drive;
70         return root;
71 }
72
73 /*************************************************************************
74  * PathFindExtension [SHELL32.31]
75  *
76  * NOTES
77  *     returns pointer to last . in last pathcomponent or at \0.
78  */
79 LPCSTR WINAPI PathFindExtensionA(LPCSTR path) 
80 {       LPCSTR   lastpoint = NULL;
81         TRACE("%p %s\n",path,path);
82         while (*path) 
83         { if (*path=='\\'||*path==' ')
84             lastpoint=NULL;
85           if (*path=='.')
86             lastpoint=path;
87           path++;
88         }
89         return lastpoint?lastpoint:path;
90 }
91 LPCWSTR WINAPI PathFindExtensionW(LPCWSTR path) 
92 {       LPCWSTR   lastpoint = NULL;
93         TRACE("%p L%s\n",path,debugstr_w(path));
94         while (*path)
95         { if (*path==(WCHAR)'\\'||*path==(WCHAR)' ')
96             lastpoint=NULL;
97           if (*path==(WCHAR)'.')
98             lastpoint=path;
99           path++;
100         }
101         return lastpoint?lastpoint:path;
102 }
103 LPCVOID WINAPI PathFindExtensionAW(LPCVOID path) 
104 {       if (VERSION_OsIsUnicode())
105           return PathFindExtensionW(path);
106         return PathFindExtensionA(path);
107
108 }
109
110 /*************************************************************************
111  * PathAddBackslash [SHELL32.32]
112  * 
113  * NOTES
114  *     append \ if there is none
115  */
116 LPSTR WINAPI PathAddBackslashA(LPSTR path)
117 {       int len;
118         TRACE("%p->%s\n",path,path);
119
120         len = strlen(path);
121         if (len && path[len-1]!='\\') 
122         { path[len]  = '\\';
123           path[len+1]= 0x00;
124           return path+len+1;
125         }
126         return path+len;
127 }
128 LPWSTR WINAPI PathAddBackslashW(LPWSTR path)
129 {       int len;
130         TRACE("%p->%s\n",path,debugstr_w(path));
131
132         len = lstrlenW(path);
133         if (len && path[len-1]!=(WCHAR)'\\') 
134         { path[len]  = (WCHAR)'\\';
135           path[len+1]= 0x00;
136           return path+len+1;
137         }
138         return path+len;
139 }
140 LPVOID WINAPI PathAddBackslashAW(LPVOID path)
141 {       if(VERSION_OsIsUnicode())
142           return PathAddBackslashW(path);
143         return PathAddBackslashA(path);
144 }
145
146 /*************************************************************************
147  * PathRemoveBlanks [SHELL32.33]
148  * 
149  * NOTES
150  *     remove spaces from beginning and end of passed string
151  */
152 LPSTR WINAPI PathRemoveBlanksA(LPSTR str)
153 {       LPSTR x = str;
154         TRACE("%s\n",str);
155         while (*x==' ') x++;
156         if (x!=str)
157           strcpy(str,x);
158         if (!*str)
159           return str;
160         x=str+strlen(str)-1;
161         while (*x==' ')
162           x--;
163         if (*x==' ')
164           *x='\0';
165         return x;
166 }
167 LPWSTR WINAPI PathRemoveBlanksW(LPWSTR str)
168 {       LPWSTR x = str;
169         TRACE("%s\n",debugstr_w(str));
170         while (*x==' ') x++;
171         if (x!=str)
172           lstrcpyW(str,x);
173         if (!*str)
174           return str;
175         x=str+lstrlenW(str)-1;
176         while (*x==' ')
177           x--;
178         if (*x==' ')
179           *x='\0';
180         return x;
181 }
182 LPVOID WINAPI PathRemoveBlanksAW(LPVOID str)
183 {       if(VERSION_OsIsUnicode())
184           return PathRemoveBlanksW(str);
185         return PathRemoveBlanksA(str);
186 }
187
188
189
190 /*************************************************************************
191  * PathFindFilename [SHELL32.34]
192  * 
193  * NOTES
194  *     basename(char *fn);
195  */
196 LPCSTR WINAPI PathFindFilenameA(LPCSTR aptr)
197 {       LPCSTR aslash;
198         aslash = aptr;
199
200         TRACE("%s\n",aslash);
201         while (aptr[0]) 
202         { if (((aptr[0]=='\\') || (aptr[0]==':')) && aptr[1] && aptr[1]!='\\')
203               aslash = aptr+1;
204           aptr++;
205         }
206         return aslash;
207
208 }
209 LPCWSTR WINAPI PathFindFilenameW(LPCWSTR wptr)
210 {       LPCWSTR wslash;
211         wslash = wptr;
212
213         TRACE("L%s\n",debugstr_w(wslash));
214         while (wptr[0]) 
215         { if (((wptr[0]=='\\') || (wptr[0]==':')) && wptr[1] && wptr[1]!='\\')
216             wslash = wptr+1;
217           wptr++;
218         }
219         return wslash;  
220 }
221 LPCVOID WINAPI PathFindFilenameAW(LPCVOID fn)
222 {
223         if(VERSION_OsIsUnicode())
224           return PathFindFilenameW(fn);
225         return PathFindFilenameA(fn);
226 }
227
228 /*************************************************************************
229  * PathRemoveFileSpec [SHELL32.35]
230  * 
231  * NOTES
232  *     bool getpath(char *pathname); truncates passed argument to a valid path
233  *     returns if the string was modified or not.
234  *     "\foo\xx\foo"-> "\foo\xx"
235  *     "\" -> "\"
236  *     "a:\foo" -> "a:\"
237  */
238 DWORD WINAPI PathRemoveFileSpecA(LPSTR fn) {
239         LPSTR   x,cutplace;
240   TRACE("%s\n",fn);
241         if (!fn[0])
242                 return 0;
243         x=fn;
244         cutplace = fn;
245         while (*x) {
246                 if (*x=='\\') {
247                         cutplace=x++;
248                         continue;
249                 }
250                 if (*x==':') {
251                         x++;
252                         if (*x=='\\')
253                                 cutplace=++x;
254                         continue; /* already x++ed */
255                 }
256                 x++;
257         }
258         if (!*cutplace)
259                 return 0;
260         if (cutplace==fn) {
261                 if (fn[0]=='\\') {
262                         if (!fn[1])
263                                 return 0;
264                         fn[0]='\0';
265                         return 1;
266                 }
267         }
268         *cutplace='\0';
269         return 1;
270 }
271
272 /*************************************************************************
273  * PathAppend [SHELL32.36]
274  * 
275  * NOTES
276  *     concat_paths(char*target,const char*add);
277  *     concats "target\\add" and writes them to target
278  */
279 LPSTR WINAPI PathAppendA(LPSTR x1,LPSTR x2) {
280   TRACE("%s %s\n",x1,x2);
281   while (x2[0]=='\\') x2++;
282   return PathCombineA(x1,x1,x2);
283 }
284
285 /*************************************************************************
286  * PathCombine [SHELL32.37]
287  * 
288  * NOTES
289  *  if lpszFile='.' skip it
290  *  szDest can be equal to lpszFile. Thats why we use sTemp
291  */
292 LPSTR WINAPI PathCombineA(LPSTR szDest, LPCSTR lpszDir, LPCSTR lpszFile) 
293 {       char sTemp[MAX_PATH];
294         TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, lpszDir, lpszFile, lpszFile);
295         
296         
297         if (!lpszFile || !lpszFile[0] || (lpszFile[0]=='.' && !lpszFile[1]) ) 
298         { strcpy(szDest,lpszDir);
299           return szDest;
300         }
301
302         /*  if lpszFile is a complete path don't care about lpszDir */
303         if (PathIsRootA(lpszFile))
304         { strcpy(szDest,lpszFile);
305         }
306         else
307         { strcpy(sTemp,lpszDir);
308           PathAddBackslashA(sTemp);
309           strcat(sTemp,lpszFile);
310           strcpy(szDest,sTemp);
311         }
312         return szDest;
313 }
314 LPWSTR WINAPI PathCombineW(LPWSTR szDest, LPCWSTR lpszDir, LPCWSTR lpszFile) 
315 {       WCHAR sTemp[MAX_PATH];
316         TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, debugstr_w(lpszDir),
317                          lpszFile, debugstr_w(lpszFile));
318         
319         
320         if (!lpszFile || !lpszFile[0] || (lpszFile[0]==(WCHAR)'.' && !lpszFile[1]) ) 
321         { lstrcpyW(szDest,lpszDir);
322           return szDest;
323         }
324
325         /*  if lpszFile is a complete path don't care about lpszDir */
326         if (PathIsRootW(lpszFile))
327         { lstrcpyW(szDest,lpszFile);
328         }
329         else
330         { lstrcpyW(sTemp,lpszDir);
331           PathAddBackslashW(sTemp);
332           lstrcatW(sTemp,lpszFile);
333           lstrcpyW(szDest,sTemp);
334         }
335         return szDest;
336 }
337 LPVOID WINAPI PathCombineAW(LPVOID szDest, LPCVOID lpszDir, LPCVOID lpszFile) 
338 {       if (VERSION_OsIsUnicode())
339           return PathCombineW( szDest, lpszDir, lpszFile );
340         return PathCombineA( szDest, lpszDir, lpszFile );
341 }
342
343 /*************************************************************************
344  * PathIsUNC [SHELL32.39]
345  * 
346  * NOTES
347  *     PathIsUNC(char*path);
348  */
349 BOOL WINAPI PathIsUNCA(LPCSTR path) 
350 {       TRACE("%s\n",path);
351
352         if ((path[0]=='\\') && (path[1]=='\\'))
353           return TRUE;
354         return FALSE;
355 }
356 BOOL WINAPI PathIsUNCW(LPCWSTR path) 
357 {       TRACE("%s\n",debugstr_w(path));
358
359         if ((path[0]=='\\') && (path[1]=='\\'))
360           return TRUE;
361         return FALSE;
362 }
363 BOOL WINAPI PathIsUNCAW (LPCVOID path)
364 {       if (VERSION_OsIsUnicode())
365           return PathIsUNCW( path );
366         return PathIsUNCA( path );  
367 }
368 /*************************************************************************
369  *  PathIsRelativ [SHELL32.40]
370  * 
371  */
372 BOOL WINAPI PathIsRelativeA (LPCSTR path)
373 {       TRACE("path=%s\n",path);
374
375         if (path && (path[0]!='\\' && path[1]==':'))
376           return TRUE;
377         return FALSE;    
378 }
379 BOOL WINAPI PathIsRelativeW (LPCWSTR path)
380 {       TRACE("path=%s\n",debugstr_w(path));
381
382         if (path && (path[0]!='\\' && path[1]==':'))
383           return TRUE;
384         return FALSE;    
385 }
386 BOOL WINAPI PathIsRelativeAW (LPCVOID path)
387 {       if (VERSION_OsIsUnicode())
388           return PathIsRelativeW( path );
389         return PathIsRelativeA( path );  
390 }
391 /*************************************************************************
392  *  PathIsExe [SHELL32.43]
393  * 
394  */
395 BOOL WINAPI PathIsExeA (LPCSTR path)
396 {       FIXME("path=%s\n",path);
397         return FALSE;
398 }
399 BOOL WINAPI PathIsExeW (LPCWSTR path)
400 {       FIXME("path=%s\n",debugstr_w(path));
401         return FALSE;
402 }
403 BOOL WINAPI PathIsExeAW (LPCVOID path)
404 {       if (VERSION_OsIsUnicode())
405           return PathIsExeW (path);
406         return PathIsExeA(path);
407 }
408
409 /*************************************************************************
410  * PathFileExists [SHELL32.45]
411  * 
412  * NOTES
413  *     file_exists(char *fn);
414  */
415 BOOL WINAPI PathFileExistsA(LPSTR fn) {
416   TRACE("%s\n",fn);
417    if (GetFileAttributesA(fn)==-1)
418         return FALSE;
419     else
420         return TRUE;
421 }
422 /*************************************************************************
423  * PathMatchSpec [SHELL32.46]
424  * 
425  * NOTES
426  *     used from COMDLG32
427  */
428
429 BOOL WINAPI PathMatchSpecA(LPCSTR name, LPCSTR mask) 
430 {       LPCSTR _name;
431
432         TRACE("%s %s stub\n",name,mask);
433
434         _name = name;
435         while (*_name && *mask)
436         { if (*mask ==';')
437           { mask++;
438             _name = name;
439           }
440           else if (*mask == '*')
441           { mask++;
442             while (*mask == '*') mask++;                /* Skip consecutive '*' */
443             if (!*mask || *mask==';') return TRUE;      /* '*' matches everything */
444             while (*_name && (toupper(*_name) != toupper(*mask))) _name++;
445             if (!*_name)
446             { while ( *mask && *mask != ';') mask++;
447               _name = name;
448             }
449           }
450           else if ( (*mask == '?') || (toupper(*mask) == toupper(*_name)) )
451           { mask++;
452             _name++;
453           }
454           else
455           { while ( *mask && *mask != ';') mask++;
456           }
457         }
458         return (!*_name && (!*mask || *mask==';'));
459 }
460 BOOL WINAPI PathMatchSpecW(LPCWSTR name, LPCWSTR mask) 
461 {       WCHAR stemp[4];
462         LPCWSTR _name;
463         
464         TRACE("%s %s stub\n",debugstr_w(name),debugstr_w(mask));
465
466         lstrcpyAtoW(stemp,"*.*");       
467         if (!lstrcmpW( mask, stemp )) return 1;
468
469         _name = name;
470         while (*_name && *mask)
471         { if (*mask ==';')
472           { mask++;
473             _name = name;
474           }
475           else if (*mask == '*')
476           { mask++;
477             while (*mask == '*') mask++;                /* Skip consecutive '*' */
478             if (!*mask || *mask==';') return TRUE;      /* '*' matches everything */
479             while (*_name && (towupper(*_name) != towupper(*mask))) _name++;
480             if (!*_name)
481             { while ( *mask && *mask != ';') mask++;
482               _name = name;
483             }
484           }
485           else if ( (*mask == '?') || (towupper(*mask) == towupper(*_name)) )
486           { mask++;
487             _name++;
488           }
489           else
490           { while ( *mask && *mask != ';') mask++;
491           }
492         }
493         return (!*_name && (!*mask || *mask==';'));
494 }
495 BOOL WINAPI PathMatchSpecAW(LPVOID name, LPVOID mask) 
496 {       if (VERSION_OsIsUnicode())
497           return PathMatchSpecW( name, mask );
498         return PathMatchSpecA( name, mask );
499 }
500 /*************************************************************************
501  * PathSetDlgItemPathAW [SHELL32.48]
502  * NOTES
503  *  use PathCompactPath to make sure, the path fits into the control
504  */
505
506 BOOL WINAPI PathSetDlgItemPathA(HWND hDlg, int id, LPCSTR pszPath) 
507 {       TRACE("%x %x %s\n",hDlg, id, pszPath);
508         return SetDlgItemTextA(hDlg, id, pszPath);
509 }
510 BOOL WINAPI PathSetDlgItemPathW(HWND hDlg, int id, LPCWSTR pszPath) 
511 {       TRACE("%x %x %s\n",hDlg, id, debugstr_w(pszPath));
512         return SetDlgItemTextW(hDlg, id, pszPath);
513 }
514 BOOL WINAPI PathSetDlgItemPathAW(HWND hDlg, int id, LPCVOID pszPath) 
515 {       if (VERSION_OsIsUnicode())
516           return PathSetDlgItemPathW(hDlg, id, pszPath);
517         return PathSetDlgItemPathA(hDlg, id, pszPath);
518 }
519
520 /*************************************************************************
521  * PathQualifyAW [SHELL32.49]
522  */
523
524 BOOL WINAPI PathQualifyA(LPCSTR pszPath) 
525 {       TRACE("%s\n",pszPath);
526         return 0;
527 }
528 BOOL WINAPI PathQualifyW(LPCWSTR pszPath) 
529 {       TRACE("%s\n",debugstr_w(pszPath));
530         return 0;
531 }
532 BOOL WINAPI PathQualifyAW(LPCVOID pszPath) 
533 {       if (VERSION_OsIsUnicode())
534           return PathQualifyW(pszPath);
535         return PathQualifyA(pszPath);
536 }
537
538 /*************************************************************************
539  * PathResolve [SHELL32.51]
540  */
541 DWORD WINAPI PathResolve(LPCSTR s,DWORD x2,DWORD x3) {
542         FIXME("(%s,0x%08lx,0x%08lx),stub!\n",s,x2,x3);
543         return 0;
544 }
545
546 /*************************************************************************
547  * PathGetArgs [SHELL32.52]
548  *
549  * NOTES
550  *     look for next arg in string. handle "quoted" strings
551  *     returns pointer to argument *AFTER* the space. Or to the \0.
552  */
553 LPCSTR WINAPI PathGetArgsA(LPCSTR cmdline) 
554 {       BOOL    qflag = FALSE;
555
556         TRACE("%s\n",cmdline);
557
558         while (*cmdline) 
559         { if ((*cmdline==' ') && !qflag)
560             return cmdline+1;
561           if (*cmdline=='"')
562             qflag=!qflag;
563           cmdline++;
564         }
565         return cmdline;
566
567 }
568 LPCWSTR WINAPI PathGetArgsW(LPCWSTR cmdline) 
569 {       BOOL    qflag = FALSE;
570
571         TRACE("%sL\n",debugstr_w(cmdline));
572
573         while (*cmdline) 
574         { if ((*cmdline==' ') && !qflag)
575             return cmdline+1;
576           if (*cmdline=='"')
577             qflag=!qflag;
578           cmdline++;
579         }
580         return cmdline;
581 }
582 LPCVOID WINAPI PathGetArgsAW(LPVOID cmdline) 
583 {       if (VERSION_OsIsUnicode())
584           return PathGetArgsW(cmdline);
585         return PathGetArgsA(cmdline);
586 }
587 /*************************************************************************
588  * PathQuoteSpaces [SHELL32.55]
589  * 
590  * NOTES
591  *     basename(char *fn);
592  */
593 LPSTR WINAPI PathQuoteSpacesA(LPCSTR aptr)
594 {       FIXME("%s\n",aptr);
595         return 0;
596
597 }
598 LPWSTR WINAPI PathQuoteSpacesW(LPCWSTR wptr)
599 {       FIXME("L%s\n",debugstr_w(wptr));
600         return 0;       
601 }
602 LPVOID WINAPI PathQuoteSpacesAW (LPCVOID fn)
603 {       if(VERSION_OsIsUnicode())
604           return PathQuoteSpacesW(fn);
605         return PathQuoteSpacesA(fn);
606 }
607
608
609 /*************************************************************************
610  * PathUnquoteSpaces [SHELL32.56]
611  * 
612  * NOTES
613  *     unquote string (remove ")
614  */
615 VOID WINAPI PathUnquoteSpacesA(LPSTR str) 
616 {       DWORD      len = lstrlenA(str);
617         TRACE("%s\n",str);
618         if (*str!='"')
619           return;
620         if (str[len-1]!='"')
621           return;
622         str[len-1]='\0';
623         lstrcpyA(str,str+1);
624         return;
625 }
626 VOID WINAPI PathUnquoteSpacesW(LPWSTR str) 
627 {       DWORD len = lstrlenW(str);
628
629         TRACE("%s\n",debugstr_w(str));
630
631         if (*str!='"')
632           return;
633         if (str[len-1]!='"')
634           return;
635         str[len-1]='\0';
636         lstrcpyW(str,str+1);
637         return;
638 }
639 VOID WINAPI PathUnquoteSpacesAW(LPVOID str) 
640 {       if(VERSION_OsIsUnicode())
641           PathUnquoteSpacesW(str);
642         PathUnquoteSpacesA(str);
643 }
644
645
646 /*************************************************************************
647  * PathGetDriveNumber32 [SHELL32.57]
648  *
649  */
650 HRESULT WINAPI PathGetDriveNumber(LPSTR u)
651 {       FIXME("%s stub\n",debugstr_a(u));
652         return 0;
653 }
654
655 /*************************************************************************
656  * PathYetAnotherMakeUniqueName [SHELL32.75]
657  * 
658  * NOTES
659  *     exported by ordinal
660  */
661 BOOL WINAPI PathYetAnotherMakeUniqueNameA(LPDWORD x,LPDWORD y) {
662     FIXME("(%p,%p):stub.\n",x,y);
663     return TRUE;
664 }
665
666 /*************************************************************************
667  * IsLFNDrive [SHELL32.119]
668  * 
669  * NOTES
670  *     exported by ordinal Name
671  */
672 BOOL WINAPI IsLFNDriveA(LPCSTR path) {
673     DWORD       fnlen;
674
675     if (!GetVolumeInformationA(path,NULL,0,NULL,&fnlen,NULL,NULL,0))
676         return FALSE;
677     return fnlen>12;
678 }
679 /*************************************************************************
680  * PathFindOnPath [SHELL32.145]
681  */
682 BOOL WINAPI PathFindOnPathA(LPSTR sFile, LPCSTR sOtherDirs)
683 {       FIXME("%s %s\n",sFile, sOtherDirs);
684         return FALSE;
685 }
686 BOOL WINAPI PathFindOnPathW(LPWSTR sFile, LPCWSTR sOtherDirs)
687 {       FIXME("%s %s\n",debugstr_w(sFile), debugstr_w(sOtherDirs));
688         return FALSE;
689 }
690 BOOL WINAPI PathFindOnPathAW(LPVOID sFile, LPCVOID sOtherDirs)
691 {       if (VERSION_OsIsUnicode())
692           return PathFindOnPathW(sFile, sOtherDirs);
693         return PathFindOnPathA(sFile, sOtherDirs);
694 }
695
696 /*************************************************************************
697  * PathGetExtension [SHELL32.158]
698  *
699  * NOTES
700  *     exported by ordinal
701  */
702 LPCSTR WINAPI PathGetExtensionA(LPCSTR path,DWORD y,DWORD z)
703 {       TRACE("(%s,%08lx,%08lx)\n",path,y,z);
704         path = PathFindExtensionA(path);
705         return *path?(path+1):path;
706 }
707 LPCWSTR WINAPI PathGetExtensionW(LPCWSTR path,DWORD y,DWORD z)
708 {       TRACE("(L%s,%08lx,%08lx)\n",debugstr_w(path),y,z);
709         path = PathFindExtensionW(path);
710         return *path?(path+1):path;
711 }
712 LPCVOID WINAPI PathGetExtensionAW(LPCVOID path,DWORD y,DWORD z) 
713 {       if (VERSION_OsIsUnicode())
714           return PathGetExtensionW(path,y,z);
715         return PathGetExtensionA(path,y,z);
716 }
717
718 /*************************************************************************
719  * SheGetDirW [SHELL32.281]
720  *
721  */
722 HRESULT WINAPI SheGetDirW(LPWSTR u, LPWSTR v)
723 {       FIXME("%p %p stub\n",u,v);
724         return 0;
725 }
726
727 /*************************************************************************
728  * SheChangeDirW [SHELL32.274]
729  *
730  */
731 HRESULT WINAPI SheChangeDirW(LPWSTR u)
732 {       FIXME("(%s),stub\n",debugstr_w(u));
733         return 0;
734 }
735
736 /*************************************************************************
737 *       PathProcessCommand      [SHELL32.653]
738 */
739 HRESULT WINAPI PathProcessCommand (DWORD u, DWORD v, DWORD w, DWORD x)
740 {       FIXME("0x%04lx 0x%04lx 0x%04lx 0x%04lx stub\n",u,v,w,x);
741         return 0;
742 }
743
744 /*************************************************************************
745  * SHGetSpecialFolderPath [SHELL32.175]
746  * 
747  * converts csidl to path
748  * 
749  */
750 BOOL WINAPI SHGetSpecialFolderPathA (DWORD x1,LPSTR szPath,DWORD csidl,DWORD x4) 
751 {       LPITEMIDLIST pidl;
752
753         WARN("(0x%04lx,%p,csidl=%lu,0x%04lx) semi-stub\n", x1,szPath,csidl,x4);
754
755         SHGetSpecialFolderLocation(0, csidl, &pidl);
756         SHGetPathFromIDListA (pidl, szPath);
757         SHFree (pidl);
758         return TRUE;
759 }
760 BOOL WINAPI SHGetSpecialFolderPathW (DWORD x1,LPWSTR szPath, DWORD csidl,DWORD x4) 
761 {       LPITEMIDLIST pidl;
762
763         WARN("(0x%04lx,%p,csidl=%lu,0x%04lx) semi-stub\n", x1,szPath,csidl,x4);
764
765         SHGetSpecialFolderLocation(0, csidl, &pidl);
766         SHGetPathFromIDListW (pidl, szPath);
767         SHFree (pidl);
768         return TRUE;
769 }
770 BOOL WINAPI SHGetSpecialFolderPath (DWORD x1,LPVOID szPath,DWORD csidl,DWORD x4) 
771 {       if (VERSION_OsIsUnicode())
772           return SHGetSpecialFolderPathW ( x1, szPath, csidl, x4);
773         return SHGetSpecialFolderPathA ( x1, szPath, csidl, x4);
774 }