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

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

Fix of broken build due to WINE sync

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