Like the AUTORADIOBUTTON, the parent of a RADIOBUTTON style button
[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 #include "crtdll.h"
14
15 #include "shlobj.h"
16 #include "shell32_main.h"
17 #include "windef.h"
18 #include "options.h"
19 #include "wine/undocshell.h"
20 #include "shlwapi.h"
21
22 DEFAULT_DEBUG_CHANNEL(shell)
23
24 /*
25         Combining and Constructing paths
26 */
27
28 /*************************************************************************
29  * PathAppendA          [SHLWAPI.@]
30  * 
31  * NOTES
32  *  concat path lpszPath2 onto lpszPath1
33  *
34  * FIXME
35  *  the resulting path is also canonicalized
36  */
37 LPSTR WINAPI PathAppendA(
38         LPSTR lpszPath1,
39         LPCSTR lpszPath2) 
40 {
41         TRACE("%s %s\n",lpszPath1, lpszPath2);
42         while (lpszPath2[0]=='\\') lpszPath2++;
43         return PathCombineA(lpszPath1,lpszPath1,lpszPath2);
44 }
45
46 /*************************************************************************
47  * PathAppendW          [SHLWAPI.@]
48  */
49 LPSTR WINAPI PathAppendW(
50         LPWSTR lpszPath1,
51         LPCWSTR lpszPath2) 
52 {
53         FIXME("%s %s\n",debugstr_w(lpszPath1), debugstr_w(lpszPath2));
54         return NULL;
55 }
56
57 /*************************************************************************
58  * PathAppendAW         [SHELL32.36]
59  */
60 LPVOID WINAPI PathAppendAW(
61         LPVOID lpszPath1,
62         LPCVOID lpszPath2)
63 {
64         if (VERSION_OsIsUnicode())
65           return PathAppendW(lpszPath1, lpszPath2);
66         return PathAppendA(lpszPath1, lpszPath2);
67 }
68
69 /*************************************************************************
70  * PathCombineA         [SHLWAPI.@]
71  * 
72  * NOTES
73  *  if lpszFile='.' skip it
74  *  szDest can be equal to lpszFile. Thats why we use sTemp
75  *
76  * FIXME
77  *  the resulting path is also canonicalized
78  *  If lpszSrcPath2 starts with a backslash it is appended 
79  *  to the root of lpszSrcPath1.
80  */
81 LPSTR WINAPI PathCombineA(
82         LPSTR szDest,
83         LPCSTR lpszDir,
84         LPCSTR lpszFile) 
85 {
86         char sTemp[MAX_PATH];
87         TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, lpszDir, lpszFile, lpszFile);
88         
89         
90         if (!lpszFile || !lpszFile[0] || (lpszFile[0]=='.' && !lpszFile[1]) ) 
91         {
92           strcpy(szDest,lpszDir);
93           return szDest;
94         }
95
96         /*  if lpszFile is a complete path don't care about lpszDir */
97         if (PathIsRootA(lpszFile))
98         {
99           strcpy(szDest,lpszFile);
100         }
101         else
102         {
103           strcpy(sTemp,lpszDir);
104           PathAddBackslashA(sTemp);
105           strcat(sTemp,lpszFile);
106           strcpy(szDest,sTemp);
107         }
108         return szDest;
109 }
110
111 /*************************************************************************
112  * PathCombineW          [SHLWAPI.@]
113  */
114 LPWSTR WINAPI PathCombineW(
115         LPWSTR szDest,
116         LPCWSTR lpszDir,
117         LPCWSTR lpszFile) 
118 {
119         WCHAR sTemp[MAX_PATH];
120         TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, debugstr_w(lpszDir),
121                          lpszFile, debugstr_w(lpszFile));
122         
123         
124         if (!lpszFile || !lpszFile[0] || (lpszFile[0]==(WCHAR)'.' && !lpszFile[1]) ) 
125         {
126           CRTDLL_wcscpy(szDest,lpszDir);
127           return szDest;
128         }
129
130         /*  if lpszFile is a complete path don't care about lpszDir */
131         if (PathIsRootW(lpszFile))
132         {
133           CRTDLL_wcscpy(szDest,lpszFile);
134         }
135         else
136         {
137           CRTDLL_wcscpy(sTemp,lpszDir);
138           PathAddBackslashW(sTemp);
139           CRTDLL_wcscat(sTemp,lpszFile);
140           CRTDLL_wcscpy(szDest,sTemp);
141         }
142         return szDest;
143 }
144
145 /*************************************************************************
146  * PathCombineAW         [SHELL32.37]
147  */
148 LPVOID WINAPI PathCombineAW(
149         LPVOID szDest,
150         LPCVOID lpszDir,
151         LPCVOID lpszFile) 
152 {
153         if (VERSION_OsIsUnicode())
154           return PathCombineW( szDest, lpszDir, lpszFile );
155         return PathCombineA( szDest, lpszDir, lpszFile );
156 }
157
158 /*************************************************************************
159  * PathAddBackslashA    [SHLWAPI.@]
160  *
161  * NOTES
162  *     append \ if there is none
163  */
164 LPSTR WINAPI PathAddBackslashA(LPSTR lpszPath)
165 {
166         int len;
167         TRACE("%p->%s\n",lpszPath,lpszPath);
168
169         len = strlen(lpszPath);
170         if (len && lpszPath[len-1]!='\\') 
171         {
172           lpszPath[len]  = '\\';
173           lpszPath[len+1]= 0x00;
174           return lpszPath+len+1;
175         }
176         return lpszPath+len;
177 }
178
179 /*************************************************************************
180  * PathAddBackslashW    [SHLWAPI.@]
181  */
182 LPWSTR WINAPI PathAddBackslashW(LPWSTR lpszPath)
183 {
184         int len;
185         TRACE("%p->%s\n",lpszPath,debugstr_w(lpszPath));
186
187         len = CRTDLL_wcslen(lpszPath);
188         if (len && lpszPath[len-1]!=(WCHAR)'\\') 
189         {
190           lpszPath[len]  = (WCHAR)'\\';
191           lpszPath[len+1]= 0x00;
192           return lpszPath+len+1;
193         }
194         return lpszPath+len;
195 }
196
197 /*************************************************************************
198  * PathAddBackslashAW           [SHELL32.32]
199  */
200 LPVOID WINAPI PathAddBackslashAW(LPVOID lpszPath)
201 {
202         if(VERSION_OsIsUnicode())
203           return PathAddBackslashW(lpszPath);
204         return PathAddBackslashA(lpszPath);
205 }
206
207 /*************************************************************************
208  * PathBuildRootA               [SHLWAPI.@]
209  */
210 LPSTR WINAPI PathBuildRootA(LPSTR lpszPath, int drive) 
211 {
212         TRACE("%p %i\n",lpszPath, drive);
213
214         strcpy(lpszPath,"A:\\");
215         lpszPath[0]+=drive;
216         return lpszPath;
217 }
218
219 /*************************************************************************
220  * PathBuildRootW               [SHLWAPI.@]
221  */
222 LPWSTR WINAPI PathBuildRootW(LPWSTR lpszPath, int drive) 
223 {
224         TRACE("%p %i\n",debugstr_w(lpszPath), drive);
225
226         lstrcpyAtoW(lpszPath,"A:\\");
227         lpszPath[0]+=drive;
228         return lpszPath;
229 }
230
231 /*************************************************************************
232  * PathBuildRootAW              [SHELL32.30]
233  */
234 LPVOID WINAPI PathBuildRootAW(LPVOID lpszPath, int drive)
235 {
236         if(VERSION_OsIsUnicode())
237           return PathBuildRootW(lpszPath, drive);
238         return PathBuildRootA(lpszPath, drive);
239 }
240
241 /*
242         Extracting Component Parts
243 */
244
245 /*************************************************************************
246  * PathFindFileNameA    [SHLWAPI.@]
247  */
248 LPSTR WINAPI PathFindFileNameA(LPCSTR lpszPath)
249 {
250         LPCSTR aslash;
251         aslash = lpszPath;
252
253         TRACE("%s\n",aslash);
254         while (lpszPath[0]) 
255         {
256           if (((lpszPath[0]=='\\') || (lpszPath[0]==':')) && lpszPath[1] && lpszPath[1]!='\\')
257               aslash = lpszPath+1;
258           lpszPath++;
259         }
260         return (LPSTR)aslash;
261
262 }
263
264 /*************************************************************************
265  * PathFindFileNameW    [SHLWAPI.@]
266  */
267 LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
268 {
269         LPCWSTR wslash;
270         wslash = lpszPath;
271
272         TRACE("%s\n",debugstr_w(wslash));
273         while (lpszPath[0]) 
274         {
275           if (((lpszPath[0]=='\\') || (lpszPath[0]==':')) && lpszPath[1] && lpszPath[1]!='\\')
276             wslash = lpszPath+1;
277           lpszPath++;
278         }
279         return (LPWSTR)wslash;  
280 }
281
282 /*************************************************************************
283  * PathFindFileNameAW   [SHELL32.34]
284  */
285 LPVOID WINAPI PathFindFileNameAW(LPCVOID lpszPath)
286 {
287         if(VERSION_OsIsUnicode())
288           return PathFindFileNameW(lpszPath);
289         return PathFindFileNameA(lpszPath);
290 }
291
292 /*************************************************************************
293  * PathFindExtensionA   [SHLWAPI.@]
294  *
295  * NOTES
296  *     returns pointer to last . in last lpszPath component or at \0.
297  */
298
299 LPSTR WINAPI PathFindExtensionA(LPCSTR lpszPath) 
300 {
301         LPCSTR   lastpoint = NULL;
302
303         TRACE("%p %s\n",lpszPath,lpszPath);
304
305         while (*lpszPath) 
306         {
307           if (*lpszPath=='\\'||*lpszPath==' ')
308             lastpoint=NULL;
309           if (*lpszPath=='.')
310             lastpoint=lpszPath;
311           lpszPath++;
312         }
313         return (LPSTR)(lastpoint?lastpoint:lpszPath);
314 }
315
316 /*************************************************************************
317  * PathFindExtensionW   [SHLWAPI.@]
318  */
319 LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath) 
320 {
321         LPCWSTR   lastpoint = NULL;
322
323         TRACE("(%p %s)\n",lpszPath,debugstr_w(lpszPath));
324
325         while (*lpszPath)
326         {
327           if (*lpszPath==(WCHAR)'\\'||*lpszPath==(WCHAR)' ')
328             lastpoint=NULL;
329           if (*lpszPath==(WCHAR)'.')
330             lastpoint=lpszPath;
331           lpszPath++;
332         }
333         return (LPWSTR)(lastpoint?lastpoint:lpszPath);
334 }
335
336 /*************************************************************************
337  * PathFindExtensionAW          [SHELL32.31]
338  */
339 LPVOID WINAPI PathFindExtensionAW(LPCVOID lpszPath) 
340 {
341         if (VERSION_OsIsUnicode())
342           return PathFindExtensionW(lpszPath);
343         return PathFindExtensionA(lpszPath);
344
345 }
346
347 /*************************************************************************
348  * PathGetExtensionA            [internal]
349  *
350  * NOTES
351  *  exported by ordinal
352  *  return value points to the first char after the dot
353  */
354 LPSTR WINAPI PathGetExtensionA(LPCSTR lpszPath)
355 {
356         TRACE("(%s)\n",lpszPath);
357
358         lpszPath = PathFindExtensionA(lpszPath);
359         return (LPSTR)(*lpszPath?(lpszPath+1):lpszPath);
360 }
361
362 /*************************************************************************
363  * PathGetExtensionW            [internal]
364  */
365 LPWSTR WINAPI PathGetExtensionW(LPCWSTR lpszPath)
366 {
367         TRACE("(%s)\n",debugstr_w(lpszPath));
368
369         lpszPath = PathFindExtensionW(lpszPath);
370         return (LPWSTR)(*lpszPath?(lpszPath+1):lpszPath);
371 }
372
373 /*************************************************************************
374  * PathGetExtensionAW           [SHELL32.158]
375  */
376 LPVOID WINAPI PathGetExtensionAW(LPCVOID lpszPath) 
377 {
378         if (VERSION_OsIsUnicode())
379           return PathGetExtensionW(lpszPath);
380         return PathGetExtensionA(lpszPath);
381 }
382
383 /*************************************************************************
384  * PathGetArgsA         [SHLWAPI.@]
385  *
386  * NOTES
387  *     look for next arg in string. handle "quoted" strings
388  *     returns pointer to argument *AFTER* the space. Or to the \0.
389  *
390  * FIXME
391  *     quoting by '\'
392  */
393 LPSTR WINAPI PathGetArgsA(LPCSTR lpszPath) 
394 {
395         BOOL    qflag = FALSE;
396
397         TRACE("%s\n",lpszPath);
398
399         while (*lpszPath) 
400         {
401           if ((*lpszPath==' ') && !qflag)
402             return (LPSTR)lpszPath+1;
403           if (*lpszPath=='"')
404             qflag=!qflag;
405           lpszPath++;
406         }
407         return (LPSTR)lpszPath;
408
409 }
410
411 /*************************************************************************
412  * PathGetArgsW         [SHLWAPI.@]
413  */
414 LPWSTR WINAPI PathGetArgsW(LPCWSTR lpszPath) 
415 {
416         BOOL    qflag = FALSE;
417
418         TRACE("%s\n",debugstr_w(lpszPath));
419
420         while (*lpszPath) 
421         {
422           if ((*lpszPath==' ') && !qflag)
423             return (LPWSTR)lpszPath+1;
424           if (*lpszPath=='"')
425             qflag=!qflag;
426           lpszPath++;
427         }
428         return (LPWSTR)lpszPath;
429 }
430
431 /*************************************************************************
432  * PathGetArgsAW        [SHELL32.52]
433  */
434 LPVOID WINAPI PathGetArgsAW(LPVOID lpszPath) 
435 {
436         if (VERSION_OsIsUnicode())
437           return PathGetArgsW(lpszPath);
438         return PathGetArgsA(lpszPath);
439 }
440
441 /*************************************************************************
442  * PathGetDriveNumberA  [SHLWAPI.@]
443  */
444 int WINAPI PathGetDriveNumberA(LPCSTR lpszPath)
445 {
446         int chr = tolower(lpszPath[0]);
447         
448         TRACE ("%s\n",debugstr_a(lpszPath));
449
450         if (!lpszPath || lpszPath[1]!=':' || chr < 'a' || chr > 'z') return -1;
451         return tolower(lpszPath[0]) - 'a' ;
452 }
453
454 /*************************************************************************
455  * PathGetDriveNumberW  [SHLWAPI.@]
456  */
457 int WINAPI PathGetDriveNumberW(LPCWSTR lpszPath)
458 {
459         int chr = towlower(lpszPath[0]);
460         
461         TRACE ("%s\n",debugstr_w(lpszPath));
462
463         if (!lpszPath || lpszPath[1]!=':' || chr < 'a' || chr > 'z') return -1;
464         return tolower(lpszPath[0]) - 'a' ;
465 }
466
467 /*************************************************************************
468  * PathGetDriveNumber   [SHELL32.57]
469  */
470 int WINAPI PathGetDriveNumberAW(LPVOID lpszPath) 
471 {
472         if (VERSION_OsIsUnicode())
473           return PathGetDriveNumberW(lpszPath);
474         return PathGetDriveNumberA(lpszPath);
475 }
476
477 /*************************************************************************
478  * PathRemoveFileSpecA  [SHLWAPI.@]
479  * 
480  * NOTES
481  *     truncates passed argument to a valid path
482  *     returns if the string was modified or not.
483  *     "\foo\xx\foo"-> "\foo\xx"
484  *     "\" -> "\"
485  *     "a:\foo" -> "a:\"
486  */
487 BOOL WINAPI PathRemoveFileSpecA(LPSTR lpszPath)
488 {
489         LPSTR cutplace;
490
491         TRACE("%s\n",lpszPath);
492
493         if (!lpszPath[0]) return 0;
494
495         cutplace = PathFindFileNameA(lpszPath);
496         if (cutplace)
497         {
498           *cutplace='\0';
499           if (PathIsRootA(lpszPath))
500           {
501             PathAddBackslashA(lpszPath);
502           }
503           else
504           {
505             PathRemoveBackslashA(lpszPath);
506           }
507           return TRUE;
508         }
509         return FALSE;
510 }
511
512 /*************************************************************************
513  * PathRemoveFileSpecW  [SHLWAPI.@]
514  */
515 BOOL WINAPI PathRemoveFileSpecW(LPWSTR lpszPath)
516 {
517         LPWSTR cutplace;
518
519         TRACE("%s\n",debugstr_w(lpszPath));
520
521         if (!lpszPath[0]) return 0;
522         cutplace = PathFindFileNameW(lpszPath);
523         if (cutplace)
524         {
525           *cutplace='\0';
526           if (PathIsRootW(lpszPath))
527           {
528             PathAddBackslashW(lpszPath);
529           }
530           else
531           {
532             PathRemoveBackslashW(lpszPath);
533           }
534           return TRUE;
535         }
536         return FALSE;
537 }
538
539 /*************************************************************************
540  * PathRemoveFileSpec [SHELL32.35]
541  */
542 BOOL WINAPI PathRemoveFileSpecAW(LPVOID lpszPath) 
543 {
544         if (VERSION_OsIsUnicode())
545           return PathRemoveFileSpecW(lpszPath);
546         return PathRemoveFileSpecA(lpszPath);
547 }
548
549 /*************************************************************************
550  * PathStripPathA       [SHELLWAPI.@]
551  * 
552  * NOTES
553  *  removes the path from the beginning of a filename
554  */
555 void WINAPI PathStripPathA(LPSTR lpszPath)
556 {
557         LPSTR lpszFileName = PathFindFileNameA(lpszPath);
558
559         TRACE("%s\n", lpszPath);
560
561         if(lpszFileName)
562           RtlMoveMemory(lpszPath, lpszFileName, strlen(lpszFileName)); 
563 }
564
565 /*************************************************************************
566  * PathStripPathW       [SHELLWAPI.@]
567  */
568 void WINAPI PathStripPathW(LPWSTR lpszPath)
569 {
570         LPWSTR lpszFileName = PathFindFileNameW(lpszPath);
571
572         TRACE("%s\n", debugstr_w(lpszPath));
573         if(lpszFileName)
574           RtlMoveMemory(lpszPath, lpszFileName, lstrlenW(lpszFileName)*sizeof(WCHAR)); 
575 }
576
577 /*************************************************************************
578  * PathStripPathAW      [SHELL32.38]
579  */
580 void WINAPI PathStripPathAW(LPVOID lpszPath) 
581 {
582         if (VERSION_OsIsUnicode())
583           return PathStripPathW(lpszPath);
584         return PathStripPathA(lpszPath);
585 }
586
587 /*************************************************************************
588  * PathStripToRootA     [SHLWAPI.@]
589  */
590 BOOL WINAPI PathStripToRootA(LPSTR lpszPath)
591 {
592         TRACE("%s\n", lpszPath);
593
594         /* X:\ */
595         if (lpszPath[1]==':' && lpszPath[2]=='\\')
596         {
597           lpszPath[3]='\0';
598           return TRUE;
599         }
600
601         /* "\" */
602         if (lpszPath[0]=='\\')
603         {
604           lpszPath[1]='\0';
605           return TRUE;
606         }
607
608         /* UNC "\\<computer>\<share>" */
609         if (lpszPath[0]=='\\' && lpszPath[1]=='\\')             
610         {
611           int foundbackslash = 0;
612           lpszPath += 2;
613           while (*lpszPath)
614           {
615             if (*lpszPath=='\\') foundbackslash++;
616             if (foundbackslash==2)
617             {
618               *lpszPath = '\0';
619               return TRUE;
620             }
621             lpszPath++;
622           }
623         }
624
625         return FALSE;
626 }
627
628 /*************************************************************************
629  * PathStripToRootW     [SHLWAPI.@]
630  */
631 BOOL WINAPI PathStripToRootW(LPWSTR lpszPath)
632 {
633         TRACE("%s\n", debugstr_w(lpszPath));
634
635         /* X:\ */
636         if (lpszPath[1]==':' && lpszPath[2]=='\\')
637         {
638           lpszPath[3]='\0';
639           return TRUE;
640         }
641
642         /* "\" */
643         if (lpszPath[0]=='\\')
644         {
645           lpszPath[1]='\0';
646           return TRUE;
647         }
648
649         /* UNC "\\<computer>\<share>" */
650         if (lpszPath[0]=='\\' && lpszPath[1]=='\\')             
651         {
652           int foundbackslash = 0;
653           lpszPath += 2;
654           while (*lpszPath)
655           {
656             if (*lpszPath=='\\') foundbackslash++;
657             if (foundbackslash==2)
658             {
659               *lpszPath = '\0';
660               return TRUE;
661             }
662             lpszPath++;
663           }
664         }
665
666         return FALSE;
667 }
668
669 /*************************************************************************
670  * PathStripToRootAW    [SHELL32.50]
671  */
672 BOOL WINAPI PathStripToRootAW(LPVOID lpszPath) 
673 {
674         if (VERSION_OsIsUnicode())
675           return PathStripToRootW(lpszPath);
676         return PathStripToRootA(lpszPath);
677 }
678
679 /*************************************************************************
680  * PathRemoveArgsA      [SHLWAPI.@]
681  */
682 void WINAPI PathRemoveArgsA(LPSTR lpszPath)
683 {
684         LPSTR lpszArgs = PathGetArgsA(lpszPath);
685
686         TRACE("%s\n", lpszPath);
687
688         if (lpszArgs) *(--lpszArgs)='\0';
689 }
690
691 /*************************************************************************
692  * PathRemoveArgsW      [SHLWAPI.@]
693  */
694 void WINAPI PathRemoveArgsW(LPWSTR lpszPath)
695 {
696         LPWSTR lpszArgs = PathGetArgsW(lpszPath);
697
698         TRACE("%s\n", debugstr_w(lpszPath));
699
700         if (lpszArgs) *(--lpszArgs)='\0';
701 }
702
703 /*************************************************************************
704  * PathRemoveArgsAW     [SHELL32.251]
705  */
706 void WINAPI PathRemoveArgsAW(LPVOID lpszPath) 
707 {
708         if (VERSION_OsIsUnicode())
709           return PathRemoveArgsW(lpszPath);
710         return PathRemoveArgsA(lpszPath);
711 }
712
713 /*************************************************************************
714  * PathRemoveExtensionA         [SHLWAPI.@]
715  */
716 void WINAPI PathRemoveExtensionA(LPSTR lpszPath)
717 {
718         LPSTR lpszExtension = PathFindExtensionA(lpszPath);
719
720         TRACE("%s\n", lpszPath);
721
722         if (lpszExtension) *lpszExtension='\0';
723 }
724
725 /*************************************************************************
726  * PathRemoveExtensionW         [SHLWAPI.@]
727  */
728 void WINAPI PathRemoveExtensionW(LPWSTR lpszPath)
729 {
730         LPWSTR lpszExtension = PathFindExtensionW(lpszPath);
731
732         TRACE("%s\n", debugstr_w(lpszPath));
733
734         if (lpszExtension) *lpszExtension='\0';
735 }
736
737 /*************************************************************************
738  * PathRemoveExtensionAW        [SHELL32.250]
739  */
740 void WINAPI PathRemoveExtensionAW(LPVOID lpszPath) 
741 {
742         if (VERSION_OsIsUnicode())
743           return PathRemoveExtensionW(lpszPath);
744         return PathRemoveExtensionA(lpszPath);
745 }
746
747 /*************************************************************************
748  * PathRemoveBackslashA [SHLWAPI.@]
749  *
750  * If the path ends in a backslash it is replaced by a NULL
751  * and the address of the NULL is returned
752  * Otherwise 
753  * the address of the last character is returned.
754  *
755  */
756 LPSTR WINAPI PathRemoveBackslashA( LPSTR lpszPath )
757 {
758         LPSTR p = lpszPath;
759         
760         while (*lpszPath) p = lpszPath++;
761         if ( *p == (CHAR)'\\') *p = (CHAR)'\0';
762         return p;
763 }
764
765 /*************************************************************************
766  * PathRemoveBackslashW [SHLWAPI.@]
767  */
768 LPWSTR WINAPI PathRemoveBackslashW( LPWSTR lpszPath )
769 {
770         LPWSTR p = lpszPath;
771         
772         while (*lpszPath); p = lpszPath++;
773         if ( *p == (WCHAR)'\\') *p = (WCHAR)'\0';
774         return p;
775 }
776
777 /*
778         Path Manipulations
779 */
780
781 /*************************************************************************
782  * PathGetShortPathA [internal]
783  */
784 LPSTR WINAPI PathGetShortPathA(LPSTR lpszPath)
785 {
786         FIXME("%s stub\n", lpszPath);
787         return NULL;
788 }
789
790 /*************************************************************************
791  * PathGetShortPathW [internal]
792  */
793 LPWSTR WINAPI PathGetShortPathW(LPWSTR lpszPath)
794 {
795         FIXME("%s stub\n", debugstr_w(lpszPath));
796         return NULL;
797 }
798
799 /*************************************************************************
800  * PathGetShortPathAW [SHELL32.92]
801  */
802 LPVOID WINAPI PathGetShortPathAW(LPVOID lpszPath)
803 {
804         if(VERSION_OsIsUnicode())
805           return PathGetShortPathW(lpszPath);
806         return PathGetShortPathA(lpszPath);
807 }
808
809 /*************************************************************************
810  * PathRemoveBlanksA [SHLWAPI.@]
811  * 
812  * NOTES
813  *     remove spaces from beginning and end of passed string
814  */
815 LPSTR WINAPI PathRemoveBlanksA(LPSTR str)
816 {
817         LPSTR x = str;
818
819         TRACE("%s\n",str);
820
821         while (*x==' ') x++;
822         if (x!=str)
823           strcpy(str,x);
824         if (!*str)
825           return str;
826         x=str+strlen(str)-1;
827         while (*x==' ')
828           x--;
829         if (*x==' ')
830           *x='\0';
831         return x;
832 }
833
834 /*************************************************************************
835  * PathRemoveBlanksW [SHLWAPI.@]
836  */
837 LPWSTR WINAPI PathRemoveBlanksW(LPWSTR str)
838 {
839         LPWSTR x = str;
840
841         TRACE("%s\n",debugstr_w(str));
842
843         while (*x==' ') x++;
844         if (x!=str)
845           CRTDLL_wcscpy(str,x);
846         if (!*str)
847           return str;
848         x=str+CRTDLL_wcslen(str)-1;
849         while (*x==' ')
850           x--;
851         if (*x==' ')
852           *x='\0';
853         return x;
854 }
855
856 /*************************************************************************
857  * PathRemoveBlanksAW [SHELL32.33]
858  */
859 LPVOID WINAPI PathRemoveBlanksAW(LPVOID str)
860 {
861         if(VERSION_OsIsUnicode())
862           return PathRemoveBlanksW(str);
863         return PathRemoveBlanksA(str);
864 }
865
866 /*************************************************************************
867  * PathQuoteSpacesA [SHLWAPI.@]
868  * 
869  * NOTES
870  */
871 LPSTR WINAPI PathQuoteSpacesA(LPCSTR lpszPath)
872 {
873         FIXME("%s\n",lpszPath);
874         return 0;
875 }
876
877 /*************************************************************************
878  * PathQuoteSpacesW [SHLWAPI.@]
879  */
880 LPWSTR WINAPI PathQuoteSpacesW(LPCWSTR lpszPath)
881 {
882         FIXME("%s\n",debugstr_w(lpszPath));
883         return 0;       
884 }
885
886 /*************************************************************************
887  * PathQuoteSpacesAW [SHELL32.55]
888  */
889 LPVOID WINAPI PathQuoteSpacesAW (LPCVOID lpszPath)
890 {
891         if(VERSION_OsIsUnicode())
892           return PathQuoteSpacesW(lpszPath);
893         return PathQuoteSpacesA(lpszPath);
894 }
895
896 /*************************************************************************
897  * PathUnquoteSpacesA [SHLWAPI.@]
898  * 
899  * NOTES
900  *     unquote string (remove ")
901  */
902 VOID WINAPI PathUnquoteSpacesA(LPSTR str) 
903 {
904         DWORD len = lstrlenA(str);
905
906         TRACE("%s\n",str);
907
908         if (*str!='"')
909           return;
910         if (str[len-1]!='"')
911           return;
912         str[len-1]='\0';
913         lstrcpyA(str,str+1);
914         return;
915 }
916
917 /*************************************************************************
918  * PathUnquoteSpacesW [SHLWAPI.@]
919  */
920 VOID WINAPI PathUnquoteSpacesW(LPWSTR str) 
921 {
922         DWORD len = CRTDLL_wcslen(str);
923
924         TRACE("%s\n",debugstr_w(str));
925
926         if (*str!='"')
927           return;
928         if (str[len-1]!='"')
929           return;
930         str[len-1]='\0';
931         CRTDLL_wcscpy(str,str+1);
932         return;
933 }
934
935 /*************************************************************************
936  * PathUnquoteSpacesAW [SHELL32.56]
937  */
938 VOID WINAPI PathUnquoteSpacesAW(LPVOID str) 
939 {
940         if(VERSION_OsIsUnicode())
941           PathUnquoteSpacesW(str);
942         else
943           PathUnquoteSpacesA(str);
944 }
945
946 /*************************************************************************
947  * PathParseIconLocationA       [SHLWAPI.@]
948  */
949 int WINAPI PathParseIconLocationA(LPSTR lpszPath)
950 {
951         LPSTR lpstrComma = strchr(lpszPath, ',');
952         
953         FIXME("%s stub\n", debugstr_a(lpszPath));
954
955         if (lpstrComma && lpstrComma[1])
956         {
957           lpstrComma[0]='\0';
958 /*        return atoi(&lpstrComma[1]);  FIXME */
959         }
960         return 0;
961 }
962
963 /*************************************************************************
964  * PathParseIconLocationW       [SHLWAPI.@]
965  */
966 int WINAPI PathParseIconLocationW(LPWSTR lpszPath)
967 {
968         LPWSTR lpstrComma = CRTDLL_wcschr(lpszPath, ',');
969         
970         FIXME("%s stub\n", debugstr_w(lpszPath));
971
972         if (lpstrComma && lpstrComma[1])
973         {
974           lpstrComma[0]='\0';
975 /*        return _wtoi(&lpstrComma[1]); FIXME */
976         }
977         return 0;
978 }
979
980 /*************************************************************************
981  * PathParseIconLocationAW      [SHELL32.249]
982  */
983 int WINAPI PathParseIconLocationAW (LPVOID lpszPath)
984 {
985         if(VERSION_OsIsUnicode())
986           return PathParseIconLocationW(lpszPath);
987         return PathParseIconLocationA(lpszPath);
988 }
989
990 /*
991         Path Testing
992 */
993 /*************************************************************************
994  * PathIsUNCA           [SHLWAPI.@]
995  * 
996  * NOTES
997  *     PathIsUNC(char*path);
998  */
999 BOOL WINAPI PathIsUNCA(LPCSTR lpszPath) 
1000 {
1001         TRACE("%s\n",lpszPath);
1002
1003         return (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\'));
1004 }
1005
1006 /*************************************************************************
1007  * PathIsUNCW           [SHLWAPI.@]
1008  */
1009 BOOL WINAPI PathIsUNCW(LPCWSTR lpszPath) 
1010 {
1011         TRACE("%s\n",debugstr_w(lpszPath));
1012
1013         return (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\'));
1014 }
1015
1016 /*************************************************************************
1017  * PathIsUNCAW          [SHELL32.39]
1018  */
1019 BOOL WINAPI PathIsUNCAW (LPCVOID lpszPath)
1020 {
1021         if (VERSION_OsIsUnicode())
1022           return PathIsUNCW( lpszPath );
1023         return PathIsUNCA( lpszPath );  
1024 }
1025
1026 /*************************************************************************
1027  *  PathIsRelativeA     [SHLWAPI.@]
1028  */
1029 BOOL WINAPI PathIsRelativeA (LPCSTR lpszPath)
1030 {
1031         TRACE("lpszPath=%s\n",lpszPath);
1032
1033         return (lpszPath && (lpszPath[0]!='\\' && lpszPath[1]!=':'));
1034 }
1035
1036 /*************************************************************************
1037  *  PathIsRelativeW     [SHLWAPI.@]
1038  */
1039 BOOL WINAPI PathIsRelativeW (LPCWSTR lpszPath)
1040 {
1041         TRACE("lpszPath=%s\n",debugstr_w(lpszPath));
1042
1043         return (lpszPath && (lpszPath[0]!='\\' && lpszPath[1]!=':'));
1044 }
1045
1046 /*************************************************************************
1047  *  PathIsRelativeAW    [SHELL32.40]
1048  */
1049 BOOL WINAPI PathIsRelativeAW (LPCVOID lpszPath)
1050 {
1051         if (VERSION_OsIsUnicode())
1052           return PathIsRelativeW( lpszPath );
1053         return PathIsRelativeA( lpszPath );  
1054 }
1055
1056 /*************************************************************************
1057  * PathIsRootA          [SHLWAPI.@]
1058  *
1059  * notes
1060  *  TRUE if the path points to a root directory
1061  */
1062 BOOL WINAPI PathIsRootA(LPCSTR lpszPath)
1063 {
1064         TRACE("%s\n",lpszPath);
1065
1066         /* X:\ */
1067         if (lpszPath[1]==':' && lpszPath[2]=='\\' && lpszPath[3]=='\0')
1068           return TRUE;
1069
1070         /* "\" */
1071         if (lpszPath[0]=='\\' && lpszPath[1]=='\0')
1072           return TRUE;
1073
1074         /* UNC "\\<computer>\<share>" */
1075         if (lpszPath[0]=='\\' && lpszPath[1]=='\\')             
1076         {
1077           int foundbackslash = 0;
1078           lpszPath += 2;
1079           while (*lpszPath)
1080           {
1081             if (*(lpszPath++)=='\\') foundbackslash++;
1082           }
1083           if (foundbackslash==1)
1084             return TRUE;
1085         }
1086         return FALSE;
1087 }
1088
1089 /*************************************************************************
1090  * PathIsRootW          [SHLWAPI.@]
1091  */
1092 BOOL WINAPI PathIsRootW(LPCWSTR lpszPath) 
1093 {
1094         TRACE("%s\n",debugstr_w(lpszPath));
1095
1096         /* X:\ */
1097         if (lpszPath[1]==':' && lpszPath[2]=='\\' && lpszPath[3]=='\0')
1098           return TRUE;
1099
1100         /* "\" */
1101         if (lpszPath[0]=='\\' && lpszPath[1]=='\0')
1102           return TRUE;
1103
1104         /* UNC "\\<computer>\<share>" */
1105         if (lpszPath[0]=='\\' && lpszPath[1]=='\\')             
1106         {
1107           int foundbackslash = 0;
1108           lpszPath += 2;
1109           while (*lpszPath)
1110           {
1111             if (*(lpszPath++)=='\\') foundbackslash++;
1112           }
1113           if (foundbackslash==1)
1114             return TRUE;
1115         }
1116         return FALSE;
1117
1118 }
1119
1120 /*************************************************************************
1121  * PathIsRootAW         [SHELL32.29]
1122  */
1123 BOOL WINAPI PathIsRootAW(LPCVOID lpszPath) 
1124 {
1125         if (VERSION_OsIsUnicode())
1126           return PathIsRootW(lpszPath);
1127         return PathIsRootA(lpszPath);
1128 }
1129
1130 /*************************************************************************
1131  *  PathIsExeA          [internal]
1132  */
1133 BOOL WINAPI PathIsExeA (LPCSTR lpszPath)
1134 {
1135         LPCSTR lpszExtension = PathGetExtensionA(lpszPath);
1136         int i = 0;
1137         static char * lpszExtensions[6] = {"exe", "com", "pid", "cmd", "bat", NULL };
1138         
1139         TRACE("path=%s\n",lpszPath);
1140
1141         for(i=0; lpszExtensions[i]; i++)
1142           if (!strcasecmp(lpszExtension,lpszExtensions[i])) return TRUE;
1143           
1144         return FALSE;
1145 }
1146
1147 /*************************************************************************
1148  *  PathIsExeW          [internal]
1149  */
1150 BOOL WINAPI PathIsExeW (LPCWSTR lpszPath)
1151 {
1152         LPCWSTR lpszExtension = PathGetExtensionW(lpszPath);
1153         int i = 0;
1154         static WCHAR lpszExtensions[6][4] =
1155           {{'e','x','e','\0'}, {'c','o','m','\0'}, {'p','i','d','\0'},
1156            {'c','m','d','\0'}, {'b','a','t','\0'}, {'\0'} };
1157         
1158         TRACE("path=%s\n",debugstr_w(lpszPath));
1159
1160         for(i=0; lpszExtensions[i]; i++)
1161           if (!CRTDLL__wcsicmp(lpszExtension,lpszExtensions[i])) return TRUE;
1162           
1163         return FALSE;
1164 }
1165
1166 /*************************************************************************
1167  *  PathIsExeAW         [SHELL32.43]
1168  */
1169 BOOL WINAPI PathIsExeAW (LPCVOID path)
1170 {
1171         if (VERSION_OsIsUnicode())
1172           return PathIsExeW (path);
1173         return PathIsExeA(path);
1174 }
1175
1176 /*************************************************************************
1177  * PathIsDirectoryA     [SHLWAPI.@]
1178  */
1179 BOOL WINAPI PathIsDirectoryA(LPCSTR lpszPath)
1180 {
1181         HANDLE hFile;
1182         WIN32_FIND_DATAA stffile;
1183         
1184         TRACE("%s\n", debugstr_a(lpszPath));
1185
1186         hFile = FindFirstFileA(lpszPath, &stffile);
1187
1188         if ( hFile != INVALID_HANDLE_VALUE )
1189         {
1190           FindClose (hFile);
1191           return (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
1192         }
1193
1194         return FALSE;   
1195 }
1196
1197 /*************************************************************************
1198  * PathIsDirectoryW     [SHLWAPI.@]
1199  */
1200 BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath)
1201 {
1202         HANDLE hFile;
1203         WIN32_FIND_DATAW stffile;
1204         
1205         TRACE("%s\n", debugstr_w(lpszPath));
1206
1207         hFile = FindFirstFileW(lpszPath, &stffile);
1208
1209         if ( hFile != INVALID_HANDLE_VALUE )
1210         {
1211           FindClose (hFile);
1212           return (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
1213         }
1214
1215         return FALSE;   
1216 }
1217
1218 /*************************************************************************
1219  * PathIsDirectoryAW    [SHELL32.159]
1220  */
1221 BOOL WINAPI PathIsDirectoryAW (LPCVOID lpszPath)
1222 {
1223         if (VERSION_OsIsUnicode())
1224           return PathIsDirectoryW (lpszPath);
1225         return PathIsDirectoryA (lpszPath);
1226 }
1227
1228 /*************************************************************************
1229  * PathFileExistsA      [SHLWAPI.@]
1230  * 
1231  * NOTES
1232  *     file_exists(char *fn);
1233  */
1234 BOOL WINAPI PathFileExistsA(LPCSTR lpszPath) 
1235 {
1236         TRACE("%s\n",lpszPath);
1237         return  (GetFileAttributesA(lpszPath)!=-1);
1238 }
1239
1240 /*************************************************************************
1241  * PathFileExistsW      [SHLWAPI.@]
1242  */
1243 BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath) 
1244 {
1245         TRACE("%s\n",debugstr_w(lpszPath));
1246         return  (GetFileAttributesW(lpszPath)!=-1);
1247 }
1248
1249 /*************************************************************************
1250  * PathFileExistsAW     [SHELL32.45]
1251  */ 
1252 BOOL WINAPI PathFileExistsAW (LPCVOID lpszPath)
1253 {
1254         if (VERSION_OsIsUnicode())
1255           return PathFileExistsW (lpszPath);
1256         return PathFileExistsA (lpszPath);
1257 }
1258
1259 /*************************************************************************
1260  * PathMatchSingleMaskA [internal]
1261  * 
1262  * NOTES
1263  *     internal (used by PathMatchSpec)
1264  */
1265 static BOOL PathMatchSingleMaskA(LPCSTR name, LPCSTR mask)
1266 {
1267         while (*name && *mask && *mask!=';') 
1268         {
1269           if (*mask=='*') 
1270           {
1271             do 
1272             {
1273               if (PathMatchSingleMaskA(name,mask+1)) return 1;  /* try substrings */
1274             } while (*name++);
1275             return 0;
1276           }
1277           if (toupper(*mask)!=toupper(*name) && *mask!='?') return 0;
1278           name++;
1279           mask++;
1280         }
1281         if (!*name) 
1282         {
1283           while (*mask=='*') mask++;
1284           if (!*mask || *mask==';') return 1;
1285         }
1286         return 0;
1287 }
1288
1289 /*************************************************************************
1290  * PathMatchSingleMaskW [internal]
1291  */
1292 static BOOL PathMatchSingleMaskW(LPCWSTR name, LPCWSTR mask)
1293 {
1294         while (*name && *mask && *mask!=';') 
1295         {
1296           if (*mask=='*') 
1297           {
1298             do 
1299             {
1300               if (PathMatchSingleMaskW(name,mask+1)) return 1;  /* try substrings */
1301             } while (*name++);
1302             return 0;
1303           }
1304           if (towupper(*mask)!=towupper(*name) && *mask!='?') return 0;
1305           name++;
1306           mask++;
1307         }
1308         if (!*name) 
1309         {
1310           while (*mask=='*') mask++;
1311           if (!*mask || *mask==';') return 1;
1312         }
1313         return 0;
1314 }
1315 /*************************************************************************
1316  * PathMatchSpecA       [SHLWAPI.@]
1317  * 
1318  * NOTES
1319  *     used from COMDLG32
1320  */
1321 BOOL WINAPI PathMatchSpecA(LPCSTR name, LPCSTR mask) 
1322 {
1323         TRACE("%s %s\n",name,mask);
1324
1325         if (!lstrcmpA( mask, "*.*" )) return 1;   /* we don't require a period */
1326
1327         while (*mask) 
1328         {
1329           if (PathMatchSingleMaskA(name,mask)) return 1;    /* helper function */
1330           while (*mask && *mask!=';') mask++;
1331           if (*mask==';') 
1332           {
1333             mask++;
1334             while (*mask==' ') mask++;      /*  masks may be separated by "; " */
1335           }
1336         }
1337         return 0;
1338 }
1339
1340 /*************************************************************************
1341  * PathMatchSpecW       [SHLWAPI.@]
1342  */
1343 BOOL WINAPI PathMatchSpecW(LPCWSTR name, LPCWSTR mask) 
1344 {
1345         WCHAR stemp[4];
1346         TRACE("%s %s\n",debugstr_w(name),debugstr_w(mask));
1347
1348         lstrcpyAtoW(stemp,"*.*");       
1349         if (!lstrcmpW( mask, stemp )) return 1;   /* we don't require a period */
1350
1351         while (*mask) 
1352         {
1353           if (PathMatchSingleMaskW(name,mask)) return 1;    /* helper function */
1354           while (*mask && *mask!=';') mask++;
1355           if (*mask==';') 
1356           {
1357             mask++;
1358             while (*mask==' ') mask++;       /* masks may be separated by "; " */
1359           }
1360         }
1361         return 0;
1362 }
1363
1364 /*************************************************************************
1365  * PathMatchSpecAW      [SHELL32.46]
1366  */
1367 BOOL WINAPI PathMatchSpecAW(LPVOID name, LPVOID mask) 
1368 {
1369         if (VERSION_OsIsUnicode())
1370           return PathMatchSpecW( name, mask );
1371         return PathMatchSpecA( name, mask );
1372 }
1373
1374 /*************************************************************************
1375  * PathIsSameRootA      [SHLWAPI.@]
1376  *
1377  * FIXME
1378  *  what to do with "\path" ??
1379  */
1380 BOOL WINAPI PathIsSameRootA(LPCSTR lpszPath1, LPCSTR lpszPath2)
1381 {
1382         TRACE("%s %s\n", lpszPath1, lpszPath2);
1383         
1384         if (PathIsRelativeA(lpszPath1) || PathIsRelativeA(lpszPath2)) return FALSE;
1385
1386         /* usual path */
1387         if ( toupper(lpszPath1[0])==toupper(lpszPath2[0]) &&
1388              lpszPath1[1]==':' && lpszPath2[1]==':' &&
1389              lpszPath1[2]=='\\' && lpszPath2[2]=='\\')
1390           return TRUE;
1391
1392         /* UNC */
1393         if (lpszPath1[0]=='\\' && lpszPath2[0]=='\\' &&
1394             lpszPath1[1]=='\\' && lpszPath2[1]=='\\')
1395         {
1396           int pos=2, bsfound=0;
1397           while (lpszPath1[pos] && lpszPath2[pos] &&
1398                 (lpszPath1[pos] == lpszPath2[pos]))
1399           {
1400             if (lpszPath1[pos]=='\\') bsfound++;
1401             if (bsfound == 2) return TRUE;
1402             pos++;
1403           }
1404           return (lpszPath1[pos] == lpszPath2[pos]);
1405         }
1406         return FALSE;
1407 }
1408
1409 /*************************************************************************
1410  * PathIsSameRootW      [SHLWAPI.@]
1411  */
1412 BOOL WINAPI PathIsSameRootW(LPCWSTR lpszPath1, LPCWSTR lpszPath2)
1413 {
1414         TRACE("%s %s\n", debugstr_w(lpszPath1), debugstr_w(lpszPath2));
1415         
1416         if (PathIsRelativeW(lpszPath1) || PathIsRelativeW(lpszPath2)) return FALSE;
1417
1418         /* usual path */
1419         if ( towupper(lpszPath1[0])==towupper(lpszPath2[0]) &&
1420              lpszPath1[1]==':' && lpszPath2[1]==':' &&
1421              lpszPath1[2]=='\\' && lpszPath2[2]=='\\')
1422           return TRUE;
1423
1424         /* UNC */
1425         if (lpszPath1[0]=='\\' && lpszPath2[0]=='\\' &&
1426             lpszPath1[1]=='\\' && lpszPath2[1]=='\\')
1427         {
1428           int pos=2, bsfound=0;
1429           while (lpszPath1[pos] && lpszPath2[pos] &&
1430                 (lpszPath1[pos] == lpszPath2[pos]))
1431           {
1432             if (lpszPath1[pos]=='\\') bsfound++;
1433             if (bsfound == 2) return TRUE;
1434             pos++;
1435           }
1436           return (lpszPath1[pos] == lpszPath2[pos]);
1437         }
1438         return FALSE;
1439 }
1440
1441 /*************************************************************************
1442  * PathIsSameRootAW     [SHELL32.650]
1443  */
1444 BOOL WINAPI PathIsSameRootAW(LPCVOID lpszPath1, LPCVOID lpszPath2)
1445 {
1446         if (VERSION_OsIsUnicode())
1447           return PathIsSameRootW(lpszPath1, lpszPath2);
1448         return PathIsSameRootA(lpszPath1, lpszPath2);
1449 }
1450
1451 /*************************************************************************
1452  * PathIsURLA
1453  */
1454 BOOL WINAPI PathIsURLA(LPCSTR lpstrPath)
1455 {
1456         LPSTR lpstrRes;
1457         int iSize, i=0;
1458         static LPSTR SupportedProtocol[] = 
1459           {"http","https","ftp","gopher","file","mailto",NULL};
1460
1461         if(!lpstrPath) return FALSE;
1462
1463         /* get protocol        */
1464         lpstrRes = strchr(lpstrPath,':');
1465         if(!lpstrRes) return FALSE;
1466         iSize = lpstrRes - lpstrPath;
1467
1468         while(SupportedProtocol[i])
1469         {
1470           if (iSize == strlen(SupportedProtocol[i]))
1471             if(!strncasecmp(lpstrPath, SupportedProtocol[i], iSize));
1472               return TRUE;
1473           i++;
1474         }
1475
1476         return FALSE;
1477 }  
1478
1479 /*************************************************************************
1480  * PathIsURLW
1481  */
1482 BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
1483 {
1484         LPWSTR lpstrRes;
1485         int iSize, i=0;
1486         static WCHAR SupportedProtocol[7][7] = 
1487           {{'h','t','t','p','\0'},{'h','t','t','p','s','\0'},{'f','t','p','\0'},
1488           {'g','o','p','h','e','r','\0'},{'f','i','l','e','\0'},
1489           {'m','a','i','l','t','o','\0'},{0}};
1490
1491         if(!lpstrPath) return FALSE;
1492
1493         /* get protocol        */
1494         lpstrRes = CRTDLL_wcschr(lpstrPath,':');
1495         if(!lpstrRes) return FALSE;
1496         iSize = lpstrRes - lpstrPath;
1497
1498         while(SupportedProtocol[i])
1499         {
1500           if (iSize == CRTDLL_wcslen(SupportedProtocol[i]))
1501             if(!CRTDLL__wcsnicmp(lpstrPath, SupportedProtocol[i], iSize));
1502               return TRUE;
1503           i++;
1504         }
1505
1506         return FALSE;
1507 }  
1508
1509 /*************************************************************************
1510  * IsLFNDriveA          [SHELL32.119]
1511  * 
1512  * NOTES
1513  *     exported by ordinal Name
1514  */
1515 BOOL WINAPI IsLFNDriveA(LPCSTR lpszPath) 
1516 {
1517     DWORD       fnlen;
1518
1519     if (!GetVolumeInformationA(lpszPath,NULL,0,NULL,&fnlen,NULL,NULL,0))
1520         return FALSE;
1521     return fnlen>12;
1522 }
1523
1524 /*
1525         Creating Something Unique
1526 */
1527 /*************************************************************************
1528  * PathMakeUniqueNameA  [internal]
1529  */
1530 BOOL WINAPI PathMakeUniqueNameA(
1531         LPSTR lpszBuffer,
1532         DWORD dwBuffSize, 
1533         LPCSTR lpszShortName,
1534         LPCSTR lpszLongName,
1535         LPCSTR lpszPathName)
1536 {
1537         FIXME("%p %lu %s %s %s stub\n",
1538          lpszBuffer, dwBuffSize, debugstr_a(lpszShortName),
1539          debugstr_a(lpszLongName), debugstr_a(lpszPathName));
1540         return TRUE;
1541 }
1542
1543 /*************************************************************************
1544  * PathMakeUniqueNameW  [internal]
1545  */
1546 BOOL WINAPI PathMakeUniqueNameW(
1547         LPWSTR lpszBuffer,
1548         DWORD dwBuffSize, 
1549         LPCWSTR lpszShortName,
1550         LPCWSTR lpszLongName,
1551         LPCWSTR lpszPathName)
1552 {
1553         FIXME("%p %lu %s %s %s stub\n",
1554          lpszBuffer, dwBuffSize, debugstr_w(lpszShortName),
1555          debugstr_w(lpszLongName), debugstr_w(lpszPathName));
1556         return TRUE;
1557 }
1558
1559 /*************************************************************************
1560  * PathMakeUniqueNameAW [SHELL32.47]
1561  */
1562 BOOL WINAPI PathMakeUniqueNameAW(
1563         LPVOID lpszBuffer,
1564         DWORD dwBuffSize, 
1565         LPCVOID lpszShortName,
1566         LPCVOID lpszLongName,
1567         LPCVOID lpszPathName)
1568 {
1569         if (VERSION_OsIsUnicode())
1570           return PathMakeUniqueNameW(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
1571         return PathMakeUniqueNameA(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
1572 }
1573
1574 /*************************************************************************
1575  * PathYetAnotherMakeUniqueNameA [SHELL32.75]
1576  * 
1577  * NOTES
1578  *     exported by ordinal
1579  */
1580 BOOL WINAPI PathYetAnotherMakeUniqueNameA(
1581         LPSTR lpszBuffer,
1582         LPCSTR lpszPathName,
1583         LPCSTR lpszShortName,
1584         LPCSTR lpszLongName)
1585 {
1586     FIXME("(%p,%p, %p ,%p):stub.\n",
1587      lpszBuffer, lpszPathName, lpszShortName, lpszLongName);
1588     return TRUE;
1589 }
1590
1591
1592 /*
1593         cleaning and resolving paths 
1594  */
1595
1596 /*************************************************************************
1597  * PathFindOnPathA      [SHELL32.145]
1598  */
1599 BOOL WINAPI PathFindOnPathA(LPSTR sFile, LPCSTR sOtherDirs)
1600 {
1601         FIXME("%s %s\n",sFile, sOtherDirs);
1602         return FALSE;
1603 }
1604
1605 /*************************************************************************
1606  * PathFindOnPathW      [SHELL32]
1607  */
1608 BOOL WINAPI PathFindOnPathW(LPWSTR sFile, LPCWSTR sOtherDirs)
1609 {
1610         FIXME("%s %s\n",debugstr_w(sFile), debugstr_w(sOtherDirs));
1611         return FALSE;
1612 }
1613
1614 /*************************************************************************
1615  * PathFindOnPathAW     [SHELL32]
1616  */
1617 BOOL WINAPI PathFindOnPathAW(LPVOID sFile, LPCVOID sOtherDirs)
1618 {
1619         if (VERSION_OsIsUnicode())
1620           return PathFindOnPathW(sFile, sOtherDirs);
1621         return PathFindOnPathA(sFile, sOtherDirs);
1622 }
1623
1624 /*************************************************************************
1625  * PathCleanupSpecA     [SHELL32.171]
1626  */
1627 DWORD WINAPI PathCleanupSpecA(LPSTR x, LPSTR y)
1628 {
1629         FIXME("(%p %s, %p %s) stub\n",x,debugstr_a(x),y,debugstr_a(y));
1630         return TRUE;
1631 }
1632
1633 /*************************************************************************
1634  * PathCleanupSpecA     [SHELL32]
1635  */
1636 DWORD WINAPI PathCleanupSpecW(LPWSTR x, LPWSTR y)
1637 {
1638         FIXME("(%p %s, %p %s) stub\n",x,debugstr_w(x),y,debugstr_w(y));
1639         return TRUE;
1640 }
1641
1642 /*************************************************************************
1643  * PathCleanupSpecAW    [SHELL32]
1644  */
1645 DWORD WINAPI PathCleanupSpecAW (LPVOID x, LPVOID y)
1646 {
1647         if (VERSION_OsIsUnicode())
1648           return PathCleanupSpecW(x,y);
1649         return PathCleanupSpecA(x,y);
1650 }
1651
1652 /*************************************************************************
1653  * PathQualifyA         [SHELL32]
1654  */
1655 BOOL WINAPI PathQualifyA(LPCSTR pszPath) 
1656 {
1657         FIXME("%s\n",pszPath);
1658         return 0;
1659 }
1660
1661 /*************************************************************************
1662  * PathQualifyW         [SHELL32]
1663  */
1664 BOOL WINAPI PathQualifyW(LPCWSTR pszPath) 
1665 {
1666         FIXME("%s\n",debugstr_w(pszPath));
1667         return 0;
1668 }
1669
1670 /*************************************************************************
1671  * PathQualifyAW        [SHELL32]
1672  */
1673 BOOL WINAPI PathQualifyAW(LPCVOID pszPath) 
1674 {
1675         if (VERSION_OsIsUnicode())
1676           return PathQualifyW(pszPath);
1677         return PathQualifyA(pszPath);
1678 }
1679
1680 /*************************************************************************
1681  * PathResolveA [SHELL32.51]
1682  */
1683 BOOL WINAPI PathResolveA(
1684         LPSTR lpszPath,
1685         LPCSTR *alpszPaths, 
1686         DWORD dwFlags)
1687 {
1688         FIXME("(%s,%p,0x%08lx),stub!\n",
1689           lpszPath, *alpszPaths, dwFlags);
1690         return 0;
1691 }
1692
1693 /*************************************************************************
1694  * PathResolveW [SHELL32]
1695  */
1696 BOOL WINAPI PathResolveW(
1697         LPWSTR lpszPath,
1698         LPCWSTR *alpszPaths, 
1699         DWORD dwFlags)
1700 {
1701         FIXME("(%s,%p,0x%08lx),stub!\n",
1702           debugstr_w(lpszPath), debugstr_w(*alpszPaths), dwFlags);
1703         return 0;
1704 }
1705
1706 /*************************************************************************
1707  * PathResolveAW [SHELL32]
1708  */
1709 BOOL WINAPI PathResolveAW(
1710         LPVOID lpszPath,
1711         LPCVOID *alpszPaths, 
1712         DWORD dwFlags)
1713 {
1714         if (VERSION_OsIsUnicode())
1715           return PathResolveW(lpszPath, (LPCWSTR*)alpszPaths, dwFlags);
1716         return PathResolveA(lpszPath, (LPCSTR*)alpszPaths, dwFlags);
1717 }
1718
1719 /*************************************************************************
1720 *       PathProcessCommandA     [SHELL32.653]
1721 */
1722 HRESULT WINAPI PathProcessCommandA (
1723         LPCSTR lpszPath,
1724         LPSTR lpszBuff,
1725         DWORD dwBuffSize,
1726         DWORD dwFlags)
1727 {
1728         FIXME("%s %p 0x%04lx 0x%04lx stub\n",
1729         lpszPath, lpszBuff, dwBuffSize, dwFlags);
1730         lstrcpyA(lpszBuff, lpszPath);
1731         return 0;
1732 }
1733
1734 /*************************************************************************
1735 *       PathProcessCommandW
1736 */
1737 HRESULT WINAPI PathProcessCommandW (
1738         LPCWSTR lpszPath,
1739         LPWSTR lpszBuff,
1740         DWORD dwBuffSize,
1741         DWORD dwFlags)
1742 {
1743         FIXME("(%s, %p, 0x%04lx, 0x%04lx) stub\n",
1744         debugstr_w(lpszPath), lpszBuff, dwBuffSize, dwFlags);
1745         lstrcpyW(lpszBuff, lpszPath);
1746         return 0;
1747 }
1748
1749 /*************************************************************************
1750 *       PathProcessCommandAW
1751 */
1752 HRESULT WINAPI PathProcessCommandAW (
1753         LPCVOID lpszPath,
1754         LPVOID lpszBuff,
1755         DWORD dwBuffSize,
1756         DWORD dwFlags)
1757 {
1758         if (VERSION_OsIsUnicode())
1759           return PathProcessCommandW(lpszPath, lpszBuff, dwBuffSize, dwFlags);
1760         return PathProcessCommandA(lpszPath, lpszBuff, dwBuffSize, dwFlags);
1761 }
1762
1763 /*
1764         special
1765 */
1766
1767 /*************************************************************************
1768  * PathSetDlgItemPathA
1769  *
1770  * NOTES
1771  *  use PathCompactPath to make sure, the path fits into the control
1772  */
1773 BOOL WINAPI PathSetDlgItemPathA(HWND hDlg, int id, LPCSTR pszPath) 
1774 {       TRACE("%x %x %s\n",hDlg, id, pszPath);
1775         return SetDlgItemTextA(hDlg, id, pszPath);
1776 }
1777
1778 /*************************************************************************
1779  * PathSetDlgItemPathW
1780  */
1781 BOOL WINAPI PathSetDlgItemPathW(HWND hDlg, int id, LPCWSTR pszPath) 
1782 {       TRACE("%x %x %s\n",hDlg, id, debugstr_w(pszPath));
1783         return SetDlgItemTextW(hDlg, id, pszPath);
1784 }
1785
1786 /*************************************************************************
1787  * PathSetDlgItemPathAW
1788  */
1789 BOOL WINAPI PathSetDlgItemPathAW(HWND hDlg, int id, LPCVOID pszPath) 
1790 {       if (VERSION_OsIsUnicode())
1791           return PathSetDlgItemPathW(hDlg, id, pszPath);
1792         return PathSetDlgItemPathA(hDlg, id, pszPath);
1793 }
1794
1795
1796 /*************************************************************************
1797  * SHGetSpecialFolderPathA [SHELL32.175]
1798  * 
1799  * converts csidl to path
1800  * 
1801  */
1802  
1803 static char * szSHFolders = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
1804 static char * szSHUserFolders = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders";
1805
1806 BOOL WINAPI SHGetSpecialFolderPathA (
1807         HWND hwndOwner,
1808         LPSTR szPath,
1809         DWORD csidl,
1810         BOOL bCreate)
1811 {
1812         CHAR    szValueName[MAX_PATH], szDefaultPath[MAX_PATH];
1813         HKEY    hRootKey, hKey;
1814         BOOL    bRelative = TRUE;
1815         DWORD   dwType, dwDisp, dwPathLen = MAX_PATH;
1816
1817         TRACE("0x%04x,%p,csidl=%lu,0x%04x\n", hwndOwner,szPath,csidl,bCreate);
1818
1819         /* build default values */
1820         switch(csidl)
1821         {
1822           case CSIDL_APPDATA:
1823             hRootKey = HKEY_CURRENT_USER;
1824             strcpy (szValueName, "AppData");
1825             strcpy (szDefaultPath, "AppData");
1826             break;
1827
1828           case CSIDL_COOKIES:
1829             hRootKey = HKEY_CURRENT_USER;
1830             strcpy (szValueName, "Cookies");
1831             strcpy(szDefaultPath, "Cookies");
1832             break;
1833
1834           case CSIDL_DESKTOPDIRECTORY:
1835             hRootKey = HKEY_CURRENT_USER;
1836             strcpy(szValueName, "Desktop");
1837             strcpy(szDefaultPath, "Desktop");
1838             break;
1839
1840           case CSIDL_COMMON_DESKTOPDIRECTORY:
1841             hRootKey = HKEY_LOCAL_MACHINE;
1842             strcpy(szValueName, "Common Desktop");
1843             strcpy(szDefaultPath, "Desktop");
1844             break;
1845
1846           case CSIDL_FAVORITES:
1847             hRootKey = HKEY_CURRENT_USER;
1848             strcpy(szValueName, "Favorites");
1849             strcpy(szDefaultPath, "Favorites");
1850             break;
1851
1852           case CSIDL_FONTS:
1853             hRootKey = HKEY_CURRENT_USER;
1854             strcpy(szValueName, "Fonts");
1855             strcpy(szDefaultPath, "Fonts");
1856             break;
1857
1858           case CSIDL_HISTORY:
1859             hRootKey = HKEY_CURRENT_USER;
1860             strcpy(szValueName, "History");
1861             strcpy(szDefaultPath, "History");
1862             break;
1863
1864           case CSIDL_NETHOOD:
1865             hRootKey = HKEY_CURRENT_USER;
1866             strcpy(szValueName, "NetHood");
1867             strcpy(szDefaultPath, "NetHood");
1868             break;
1869
1870           case CSIDL_INTERNET_CACHE:
1871             hRootKey = HKEY_CURRENT_USER;
1872             strcpy(szValueName, "Cache");
1873             strcpy(szDefaultPath, "Temporary Internet Files");
1874             break;
1875
1876           case CSIDL_PERSONAL:
1877             hRootKey = HKEY_CURRENT_USER;
1878             strcpy(szValueName, "Personal");
1879             strcpy(szDefaultPath, "My Own Files");
1880             bRelative = FALSE;
1881             break;
1882
1883           case CSIDL_PRINTHOOD:
1884             hRootKey = HKEY_CURRENT_USER;
1885             strcpy(szValueName, "PrintHood");
1886             strcpy(szDefaultPath, "PrintHood");
1887             break;
1888
1889           case CSIDL_PROGRAMS:
1890             hRootKey = HKEY_CURRENT_USER;
1891             strcpy(szValueName, "Programs");
1892             strcpy(szDefaultPath, "StartMenu\\Programs");
1893             break;
1894
1895           case CSIDL_COMMON_PROGRAMS:
1896             hRootKey = HKEY_LOCAL_MACHINE;
1897             strcpy(szValueName, "Common Programs");
1898             strcpy(szDefaultPath, "");
1899             break;
1900
1901           case CSIDL_RECENT:
1902             hRootKey = HKEY_CURRENT_USER;
1903             strcpy(szValueName, "Recent");
1904             strcpy(szDefaultPath, "Recent");
1905             break;
1906
1907           case CSIDL_SENDTO:
1908             hRootKey = HKEY_CURRENT_USER;
1909             strcpy(szValueName, "SendTo");
1910             strcpy(szDefaultPath, "SendTo");
1911             break;
1912
1913           case CSIDL_STARTMENU:
1914             hRootKey = HKEY_CURRENT_USER;
1915             strcpy(szValueName, "StartMenu");
1916             strcpy(szDefaultPath, "StartMenu");
1917             break;
1918
1919           case CSIDL_COMMON_STARTMENU:
1920             hRootKey = HKEY_LOCAL_MACHINE;
1921             strcpy(szValueName, "Common StartMenu");
1922             strcpy(szDefaultPath, "StartMenu");
1923             break;
1924
1925           case CSIDL_STARTUP:
1926             hRootKey = HKEY_CURRENT_USER;
1927             strcpy(szValueName, "Startup");
1928             strcpy(szDefaultPath, "StartMenu\\Programs\\Startup");
1929             break;
1930
1931           case CSIDL_COMMON_STARTUP:
1932             hRootKey = HKEY_LOCAL_MACHINE;
1933             strcpy(szValueName, "Common Startup");
1934             strcpy(szDefaultPath, "StartMenu\\Programs\\Startup");
1935             break;
1936
1937           case CSIDL_TEMPLATES:
1938             hRootKey = HKEY_CURRENT_USER;
1939             strcpy(szValueName, "Templates");
1940             strcpy(szDefaultPath, "ShellNew");
1941             break;
1942
1943           default:
1944             ERR("folder unknown or not allowed\n");
1945             return FALSE;
1946         }
1947
1948         /* user shell folders */
1949         if (RegCreateKeyExA(hRootKey,szSHUserFolders,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return FALSE;
1950
1951         if (RegQueryValueExA(hKey,szValueName,NULL,&dwType,(LPBYTE)szPath,&dwPathLen))
1952         {
1953           RegCloseKey(hKey);
1954
1955           /* shell folders */
1956           if (RegCreateKeyExA(hRootKey,szSHFolders,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return FALSE;
1957
1958           if (RegQueryValueExA(hKey,szValueName,NULL,&dwType,(LPBYTE)szPath,&dwPathLen))
1959           {
1960
1961             /* value not existing */
1962             if (bRelative)
1963             {
1964               GetWindowsDirectoryA(szPath, MAX_PATH);
1965               PathAddBackslashA(szPath);
1966               strcat(szPath, szDefaultPath);
1967             }
1968             else
1969             {
1970               strcpy(szPath, "C:\\");   /* fixme ??? */
1971               strcat(szPath, szDefaultPath);
1972             }
1973             RegSetValueExA(hKey,szValueName,0,REG_SZ,(LPBYTE)szPath,strlen(szPath)+1);
1974           }
1975         }
1976         RegCloseKey(hKey);
1977
1978         if (bCreate && CreateDirectoryA(szPath,NULL))
1979         {
1980             MESSAGE("Created not existing system directory '%s'\n", szPath);
1981         }
1982
1983         return TRUE;
1984 }
1985
1986 /*************************************************************************
1987  * SHGetSpecialFolderPathW
1988  */
1989 BOOL WINAPI SHGetSpecialFolderPathW (
1990         HWND hwndOwner,
1991         LPWSTR szPath,
1992         DWORD csidl,
1993         BOOL bCreate)
1994 {
1995         char szTemp[MAX_PATH];
1996         
1997         if (SHGetSpecialFolderPathA(hwndOwner, szTemp, csidl, bCreate))
1998         {
1999           lstrcpynAtoW(szPath, szTemp, MAX_PATH);
2000         }
2001
2002         TRACE("0x%04x,%p,csidl=%lu,0x%04x\n", hwndOwner,szPath,csidl,bCreate);
2003
2004         return TRUE;
2005 }
2006
2007 /*************************************************************************
2008  * SHGetSpecialFolderPathAW
2009  */
2010 BOOL WINAPI SHGetSpecialFolderPathAW (
2011         HWND hwndOwner,
2012         LPVOID szPath,
2013         DWORD csidl,
2014         BOOL bCreate)
2015
2016 {
2017         if (VERSION_OsIsUnicode())
2018           return SHGetSpecialFolderPathW (hwndOwner, szPath, csidl, bCreate);
2019         return SHGetSpecialFolderPathA (hwndOwner, szPath, csidl, bCreate);
2020 }
2021
2022 /*************************************************************************
2023  * PathCanonicalizeA
2024  *
2025  *  FIXME
2026  *   returnvalue
2027  */
2028  
2029 BOOL WINAPI PathCanonicalizeA(LPSTR pszBuf, LPCSTR pszPath)
2030 {
2031         int OffsetMin = 0, OffsetSrc = 0, OffsetDst = 0, LenSrc = strlen(pszPath);
2032         BOOL bModifyed = FALSE;
2033
2034         TRACE("%p %s\n", pszBuf, pszPath);
2035         
2036         pszBuf[OffsetDst]='\0';
2037
2038         /* keep the root of the path */
2039         if( LenSrc && (pszPath[OffsetSrc]=='\\'))
2040         {
2041           pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
2042         }
2043         else if ( (LenSrc >= 2) && (pszPath[OffsetSrc+1] == ':'))
2044         {
2045           pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
2046           pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
2047           if (LenSrc && (pszPath[OffsetSrc] == '\\'))
2048           {
2049             pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
2050             if (LenSrc == 1 && pszPath[OffsetSrc]=='.')
2051             {
2052               /* C:\. */
2053               OffsetSrc++; LenSrc--; bModifyed = TRUE;
2054             } 
2055             else if (LenSrc == 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='.')
2056             {
2057               /* C:\.. */
2058               OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
2059             } 
2060           }
2061         }
2062         
2063         /* ".\" at the beginning of the path */
2064         if (LenSrc >= 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='\\')
2065         {
2066           OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
2067         } 
2068         
2069         while ( LenSrc )
2070         {
2071           if((LenSrc>=3) && (pszPath[OffsetSrc]=='\\') && (pszPath[OffsetSrc+1]=='.') && (pszPath[OffsetSrc+2]=='.'))
2072           {
2073             /* "\.." found, go one deeper */
2074             while((OffsetDst > OffsetMin) && (pszBuf[OffsetDst]!='\\')) OffsetDst--;
2075             OffsetSrc += 3; LenSrc -= 3; bModifyed = TRUE;
2076             if(OffsetDst == OffsetMin && pszPath[OffsetSrc]=='\\') OffsetSrc++;
2077             pszBuf[OffsetDst] = '\0';                   /* important for \..\.. */
2078           }
2079           else if(LenSrc>=2 && pszPath[OffsetSrc]=='\\' && pszPath[OffsetSrc+1]=='.' )
2080           {
2081             /* "\." found, skip it */
2082             OffsetSrc += 2; LenSrc-=2; bModifyed = TRUE;
2083           }
2084           else
2085           {
2086             pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; LenSrc--;
2087           }
2088         }
2089         pszBuf[OffsetDst] = '\0';
2090         TRACE("-- %s %u\n", pszBuf, bModifyed);
2091         return bModifyed;
2092 }
2093
2094
2095 /*************************************************************************
2096  * PathCanonicalizeW
2097  *
2098  *  FIXME
2099  *   returnvalue
2100  */
2101 BOOL WINAPI PathCanonicalizeW(LPWSTR pszBuf, LPCWSTR pszPath)
2102 {
2103         int OffsetMin = 0, OffsetSrc = 0, OffsetDst = 0, LenSrc = lstrlenW(pszPath);
2104         BOOL bModifyed = FALSE;
2105
2106         TRACE("%p %s\n", pszBuf, debugstr_w(pszPath));
2107         
2108         pszBuf[OffsetDst]='\0';
2109
2110         /* keep the root of the path */
2111         if( LenSrc && (pszPath[OffsetSrc]=='\\'))
2112         {
2113           pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
2114         }
2115         else if ( (LenSrc >= 2) && (pszPath[OffsetSrc+1] == ':'))
2116         {
2117           pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
2118           pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
2119           if (LenSrc && (pszPath[OffsetSrc] == '\\'))
2120           {
2121             pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
2122             if (LenSrc == 1 && pszPath[OffsetSrc]=='.')
2123             {
2124               /* C:\. */
2125               OffsetSrc++; LenSrc--; bModifyed = TRUE;
2126             } 
2127             else if (LenSrc == 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='.')
2128             {
2129               /* C:\.. */
2130               OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
2131             } 
2132           }
2133         }
2134         
2135         /* ".\" at the beginning of the path */
2136         if (LenSrc >= 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='\\')
2137         {
2138           OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
2139         } 
2140         
2141         while ( LenSrc )
2142         {
2143           if((LenSrc>=3) && (pszPath[OffsetSrc]=='\\') && (pszPath[OffsetSrc+1]=='.') && (pszPath[OffsetSrc+2]=='.'))
2144           {
2145             /* "\.." found, go one deeper */
2146             while((OffsetDst > OffsetMin) && (pszBuf[OffsetDst]!='\\')) OffsetDst--;
2147             OffsetSrc += 3; LenSrc -= 3; bModifyed = TRUE;
2148             if(OffsetDst == OffsetMin && pszPath[OffsetSrc]=='\\') OffsetSrc++;
2149             pszBuf[OffsetDst] = '\0';                   /* important for \..\.. */
2150           }
2151           else if(LenSrc>=2 && pszPath[OffsetSrc]=='\\' && pszPath[OffsetSrc+1]=='.' )
2152           {
2153             /* "\." found, skip it */
2154             OffsetSrc += 2; LenSrc-=2; bModifyed = TRUE;
2155           }
2156           else
2157           {
2158             pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; LenSrc--;
2159           }
2160         }
2161         pszBuf[OffsetDst] = '\0';
2162         TRACE("-- %s %u\n", debugstr_w(pszBuf), bModifyed);
2163         return bModifyed;
2164 }
2165
2166 /*************************************************************************
2167  * PathFindNextComponentA
2168  */
2169 LPSTR WINAPI PathFindNextComponentA(LPCSTR pszPath)
2170 {
2171         while( *pszPath )
2172         {
2173           if(*pszPath++=='\\')
2174             return (LPSTR)((*pszPath)? pszPath : NULL);
2175         }
2176         return NULL;
2177 }
2178
2179 /*************************************************************************
2180  * PathFindNextComponentW
2181  */
2182 LPWSTR WINAPI PathFindNextComponentW(LPCWSTR pszPath)
2183 {
2184         while( *pszPath )
2185         {
2186           if(*pszPath++=='\\')
2187             return (LPWSTR)((*pszPath)? pszPath : NULL);
2188         }
2189         return NULL;
2190 }