source: trunk/src/shlwapi/path.c@ 3700

Last change on this file since 3700 was 3700, checked in by phaller, 25 years ago

Fix build problems

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