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