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