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

Last change on this file since 7502 was 7502, checked in by phaller, 24 years ago

Fixed out-of-scope FIXME,TRACE,WARN macros

File size: 42.9 KB
Line 
1/*
2 * Path Functions
3 */
4#ifdef __WIN32OS2__
5#include <odin.h>
6#include <odinwrap.h>
7#include <os2sel.h>
8
9#include <string.h>
10#include <wctype.h>
11#include <wcstr.h>
12#define HAVE_WCTYPE_H
13#include <win\shlwapi.h>
14
15#include <heapstring.h>
16#include <wine\undocshell.h>
17#endif
18
19#include <ctype.h>
20#include <string.h>
21
22#include "winerror.h"
23#include "wine/unicode.h"
24#include "winbase.h"
25#include "wingdi.h"
26#include "winuser.h"
27#include "shlwapi.h"
28#include "debugtools.h"
29
30
31#ifdef __WIN32OS2__
32#undef FIXME
33#ifdef DEBUG
34// PH 2001-11-30
35// this macro definition causes the control leave the scope of a
36// non-curly-braced preceeding if statement. Therefore,
37// if (p!=NULL)
38// TRACE("p->a=%d", p->a)
39// crashes.
40//
41// !!! ENSURE TRACES AND FIXMES WITH PRECEEDING IF STATEMENT
42// !!! ARE PUT INTO CURLY BRACES
43#define FIXME WriteLog("FIXME %s", __FUNCTION__); WriteLog
44#else
45#define FIXME 1 ? (void)0 : (void)((int (*)(char *, ...)) NULL)
46#endif
47#endif
48
49DEFAULT_DEBUG_CHANNEL(shell);
50
51#define isSlash(x) ((x)=='\\' || (x)=='/')
52/*
53 ########## Combining and Constructing paths ##########
54*/
55
56/*************************************************************************
57 * PathAppendA [SHLWAPI.@]
58 *
59 * NOTES
60 * concat path lpszPath2 onto lpszPath1
61 *
62 * FIXME
63 * the resulting path is also canonicalized
64 */
65BOOL WINAPI PathAppendA(
66 LPSTR lpszPath1,
67 LPCSTR lpszPath2)
68{
69 TRACE("%s %s\n",lpszPath1, lpszPath2);
70 while (lpszPath2[0]=='\\') lpszPath2++;
71 PathCombineA(lpszPath1,lpszPath1,lpszPath2);
72 return TRUE;
73}
74
75/*************************************************************************
76 * PathAppendW [SHLWAPI.@]
77 */
78BOOL WINAPI PathAppendW(
79 LPWSTR lpszPath1,
80 LPCWSTR lpszPath2)
81{
82 TRACE("%s %s\n",debugstr_w(lpszPath1), debugstr_w(lpszPath2));
83 while (lpszPath2[0]=='\\') lpszPath2++;
84 PathCombineW(lpszPath1,lpszPath1,lpszPath2);
85 return TRUE;
86}
87
88/*************************************************************************
89 * PathCombineA [SHLWAPI.@]
90 *
91 * NOTES
92 * if lpszFile='.' skip it
93 * szDest can be equal to lpszFile. Thats why we use sTemp
94 *
95 * FIXME
96 * the resulting path is also canonicalized
97 */
98LPSTR WINAPI PathCombineA(
99 LPSTR szDest,
100 LPCSTR lpszDir,
101 LPCSTR lpszFile)
102{
103 char sTemp[MAX_PATH];
104 TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, lpszDir, lpszFile, lpszFile);
105
106
107 if (!lpszFile || !lpszFile[0] || (lpszFile[0]=='.' && !lpszFile[1]) )
108 {
109 strcpy(szDest,lpszDir);
110 return szDest;
111 }
112
113 /* if lpszFile is a complete path don't care about lpszDir */
114 if (PathGetDriveNumberA(lpszFile) != -1)
115 {
116 strcpy(szDest,lpszFile);
117 }
118 else if (lpszFile[0] == '\\' )
119 {
120 strcpy(sTemp,lpszDir);
121 PathStripToRootA(sTemp);
122 strcat(sTemp,lpszFile);
123 strcpy(szDest,sTemp);
124 }
125 else
126 {
127 strcpy(sTemp,lpszDir);
128 PathAddBackslashA(sTemp);
129 strcat(sTemp,lpszFile);
130 strcpy(szDest,sTemp);
131 }
132 return szDest;
133}
134
135/*************************************************************************
136 * PathCombineW [SHLWAPI.@]
137 */
138LPWSTR WINAPI PathCombineW(
139 LPWSTR szDest,
140 LPCWSTR lpszDir,
141 LPCWSTR lpszFile)
142{
143 WCHAR sTemp[MAX_PATH];
144 TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, debugstr_w(lpszDir),
145 lpszFile, debugstr_w(lpszFile));
146
147
148 if (!lpszFile || !lpszFile[0] || (lpszFile[0]==(WCHAR)'.' && !lpszFile[1]) )
149 {
150 strcpyW(szDest,lpszDir);
151 return szDest;
152 }
153
154 /* if lpszFile is a complete path don't care about lpszDir */
155 if (PathGetDriveNumberW(lpszFile) != -1)
156 {
157 strcpyW(szDest,lpszFile);
158 }
159 else if (lpszFile[0] == (WCHAR)'\\' )
160 {
161 strcpyW(sTemp,lpszDir);
162 PathStripToRootW(sTemp);
163 strcatW(sTemp,lpszFile);
164 strcpyW(szDest,sTemp);
165 }
166 else
167 {
168 strcpyW(sTemp,lpszDir);
169 PathAddBackslashW(sTemp);
170 strcatW(sTemp,lpszFile);
171 strcpyW(szDest,sTemp);
172 }
173 return szDest;
174}
175
176/*************************************************************************
177 * PathAddBackslashA [SHLWAPI.@]
178 *
179 * NOTES
180 * append \ if there is none
181 */
182LPSTR WINAPI PathAddBackslashA(LPSTR lpszPath)
183{
184 int len;
185 TRACE("%p->%s\n",lpszPath,lpszPath);
186
187 len = strlen(lpszPath);
188 if (len && lpszPath[len-1]!='\\')
189 {
190 lpszPath[len] = '\\';
191 lpszPath[len+1]= 0x00;
192 return lpszPath+len+1;
193 }
194 return lpszPath+len;
195}
196
197/*************************************************************************
198 * PathAddBackslashW [SHLWAPI.@]
199 */
200LPWSTR WINAPI PathAddBackslashW(LPWSTR lpszPath)
201{
202 int len;
203 TRACE("%p->%s\n",lpszPath,debugstr_w(lpszPath));
204
205 len = strlenW(lpszPath);
206 if (len && lpszPath[len-1]!=(WCHAR)'\\')
207 {
208 lpszPath[len] = (WCHAR)'\\';
209 lpszPath[len+1]= 0x00;
210 return lpszPath+len+1;
211 }
212 return lpszPath+len;
213}
214
215/*************************************************************************
216 * PathBuildRootA [SHLWAPI.@]
217 */
218LPSTR WINAPI PathBuildRootA(LPSTR lpszPath, int drive)
219{
220 TRACE("%p %i\n",lpszPath, drive);
221
222 strcpy(lpszPath,"A:\\");
223 lpszPath[0]+=drive;
224 return lpszPath;
225}
226
227/*************************************************************************
228 * PathBuildRootW [SHLWAPI.@]
229 */
230LPWSTR WINAPI PathBuildRootW(LPWSTR lpszPath, int drive)
231{
232 lpszPath[0] = 'A' + drive;
233 lpszPath[1] = ':';
234 lpszPath[2] = '\\';
235 lpszPath[3] = 0;
236 TRACE("%p %i\n",debugstr_w(lpszPath), drive);
237 return lpszPath;
238}
239
240/*
241 Extracting Component Parts
242*/
243
244/*************************************************************************
245 * PathFindFileNameA [SHLWAPI.@]
246 */
247LPSTR WINAPI PathFindFileNameA(LPCSTR lpszPath)
248{
249 LPCSTR lastSlash = lpszPath;
250
251 TRACE("%s\n",lpszPath);
252 while (*lpszPath)
253 {
254 if ( isSlash(lpszPath[0]) && lpszPath[1])
255 lastSlash = lpszPath+1;
256 lpszPath = CharNextA(lpszPath);
257 }
258 return (LPSTR)lastSlash;
259
260}
261
262/*************************************************************************
263 * PathFindFileNameW [SHLWAPI.@]
264 */
265LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
266{
267 LPCWSTR wslash;
268 wslash = lpszPath;
269
270 TRACE("%s\n",debugstr_w(wslash));
271 while (lpszPath[0])
272 {
273 if (((lpszPath[0]=='\\') || (lpszPath[0]==':')) && lpszPath[1] && lpszPath[1]!='\\')
274 wslash = lpszPath+1;
275 lpszPath = CharNextW(lpszPath);
276 }
277 return (LPWSTR)wslash;
278}
279
280/*************************************************************************
281 * PathFindExtensionA [SHLWAPI.@]
282 *
283 * NOTES
284 * returns pointer to last . in last lpszPath component or at \0.
285 */
286
287LPSTR WINAPI PathFindExtensionA(LPCSTR lpszPath)
288{
289 LPCSTR lastpoint = NULL;
290
291 TRACE("%p %s\n",lpszPath,lpszPath);
292
293 while (*lpszPath)
294 {
295 if (*lpszPath=='\\'||*lpszPath==' ')
296 lastpoint=NULL;
297 if (*lpszPath=='.')
298 lastpoint=lpszPath;
299 lpszPath = CharNextA(lpszPath);
300 }
301 return (LPSTR)(lastpoint?lastpoint:lpszPath);
302}
303
304/*************************************************************************
305 * PathFindExtensionW [SHLWAPI.@]
306 */
307LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath)
308{
309 LPCWSTR lastpoint = NULL;
310
311 TRACE("(%p %s)\n",lpszPath,debugstr_w(lpszPath));
312
313 while (*lpszPath)
314 {
315 if (*lpszPath==(WCHAR)'\\'||*lpszPath==(WCHAR)' ')
316 lastpoint=NULL;
317 if (*lpszPath==(WCHAR)'.')
318 lastpoint=lpszPath;
319 lpszPath = CharNextW(lpszPath);
320 }
321 return (LPWSTR)(lastpoint?lastpoint:lpszPath);
322}
323
324/*************************************************************************
325 * PathGetArgsA [SHLWAPI.@]
326 *
327 * NOTES
328 * look for next arg in string. handle "quoted" strings
329 * returns pointer to argument *AFTER* the space. Or to the \0.
330 *
331 * FIXME
332 * quoting by '\'
333 */
334LPSTR WINAPI PathGetArgsA(LPCSTR lpszPath)
335{
336 BOOL qflag = FALSE;
337
338 TRACE("%s\n",lpszPath);
339
340 while (*lpszPath)
341 {
342 if ((*lpszPath==' ') && !qflag)
343 return (LPSTR)lpszPath+1;
344 if (*lpszPath=='"')
345 qflag=!qflag;
346 lpszPath = CharNextA(lpszPath);
347 }
348 return (LPSTR)lpszPath;
349}
350
351/*************************************************************************
352 * PathGetArgsW [SHLWAPI.@]
353 */
354LPWSTR WINAPI PathGetArgsW(LPCWSTR lpszPath)
355{
356 BOOL qflag = FALSE;
357
358 TRACE("%s\n",debugstr_w(lpszPath));
359
360 while (*lpszPath)
361 {
362 if ((*lpszPath==' ') && !qflag)
363 return (LPWSTR)lpszPath+1;
364 if (*lpszPath=='"')
365 qflag=!qflag;
366 lpszPath = CharNextW(lpszPath);
367 }
368 return (LPWSTR)lpszPath;
369}
370
371/*************************************************************************
372 * PathGetDriveNumberA [SHLWAPI.@]
373 */
374int WINAPI PathGetDriveNumberA(LPCSTR lpszPath)
375{
376 int chr = tolower(lpszPath[0]);
377
378 TRACE ("%s\n",debugstr_a(lpszPath));
379
380 if (!lpszPath || lpszPath[1]!=':' || chr < 'a' || chr > 'z') return -1;
381 return tolower(lpszPath[0]) - 'a' ;
382}
383
384/*************************************************************************
385 * PathGetDriveNumberW [SHLWAPI.@]
386 */
387int WINAPI PathGetDriveNumberW(LPCWSTR lpszPath)
388{
389 int chr = tolowerW(lpszPath[0]);
390
391 TRACE ("%s\n",debugstr_w(lpszPath));
392
393 if (!lpszPath || lpszPath[1]!=':' || chr < 'a' || chr > 'z') return -1;
394 return tolowerW(lpszPath[0]) - 'a' ;
395}
396
397/*************************************************************************
398 * PathRemoveFileSpecA [SHLWAPI.@]
399 *
400 * NOTES
401 * truncates passed argument to a valid path
402 * returns if the string was modified or not.
403 * "\foo\xx\foo"-> "\foo\xx"
404 * "\" -> "\"
405 * "a:\foo" -> "a:\"
406 */
407BOOL WINAPI PathRemoveFileSpecA(LPSTR lpszPath)
408{
409 LPSTR cutplace = lpszPath;
410 BOOL ret = FALSE;
411
412 TRACE("%s\n",lpszPath);
413
414 if(lpszPath)
415 {
416 while (*lpszPath == '\\') cutplace = ++lpszPath;
417
418 while (*lpszPath)
419 {
420 if(lpszPath[0] == '\\') cutplace = lpszPath;
421
422 if(lpszPath[0] == ':')
423 {
424 cutplace = lpszPath + 1;
425 if (lpszPath[1] == '\\') cutplace++;
426 lpszPath++;
427 }
428 lpszPath = CharNextA(lpszPath);
429 if (!lpszPath) break;
430 }
431
432 ret = (*cutplace!='\0');
433 *cutplace = '\0';
434 }
435 return ret;
436}
437
438/*************************************************************************
439 * PathRemoveFileSpecW [SHLWAPI.@]
440 */
441BOOL WINAPI PathRemoveFileSpecW(LPWSTR lpszPath)
442{
443 LPWSTR cutplace = lpszPath;
444 BOOL ret = FALSE;
445
446 TRACE("%s\n",debugstr_w(lpszPath));
447
448 if(lpszPath)
449 {
450 while (*lpszPath == '\\') cutplace = ++lpszPath;
451
452 while (*lpszPath)
453 {
454 if(lpszPath[0] == '\\') cutplace = lpszPath;
455
456 if(lpszPath[0] == ':')
457 {
458 cutplace = lpszPath + 1;
459 if (lpszPath[1] == '\\') cutplace++;
460 lpszPath++;
461 }
462 lpszPath = CharNextW(lpszPath);
463 if (!lpszPath) break;
464 }
465
466 ret = (*cutplace!='\0');
467 *cutplace = '\0';
468 }
469 return ret;
470}
471
472/*************************************************************************
473 * PathStripPathA [SHELLWAPI.@]
474 *
475 * NOTES
476 * removes the path from the beginning of a filename
477 */
478void WINAPI PathStripPathA(LPSTR lpszPath)
479{
480 LPSTR lpszFileName = PathFindFileNameA(lpszPath);
481
482 TRACE("%s\n", lpszPath);
483
484 if(lpszFileName)
485 RtlMoveMemory(lpszPath, lpszFileName, strlen(lpszFileName)+1);
486}
487
488/*************************************************************************
489 * PathStripPathW [SHELLWAPI.@]
490 */
491void WINAPI PathStripPathW(LPWSTR lpszPath)
492{
493 LPWSTR lpszFileName = PathFindFileNameW(lpszPath);
494
495 TRACE("%s\n", debugstr_w(lpszPath));
496 if(lpszFileName)
497 RtlMoveMemory(lpszPath, lpszFileName, (strlenW(lpszFileName)+1)*sizeof(WCHAR));
498}
499
500/*************************************************************************
501 * PathStripToRootA [SHLWAPI.@]
502 */
503BOOL WINAPI PathStripToRootA(LPSTR lpszPath)
504{
505 TRACE("%s\n", lpszPath);
506
507 if (!lpszPath) return FALSE;
508 while(!PathIsRootA(lpszPath))
509 if (!PathRemoveFileSpecA(lpszPath)) return FALSE;
510 return TRUE;
511}
512
513/*************************************************************************
514 * PathStripToRootW [SHLWAPI.@]
515 */
516BOOL WINAPI PathStripToRootW(LPWSTR lpszPath)
517{
518 TRACE("%s\n", debugstr_w(lpszPath));
519
520 if (!lpszPath) return FALSE;
521 while(!PathIsRootW(lpszPath))
522 if (!PathRemoveFileSpecW(lpszPath)) return FALSE;
523 return TRUE;
524}
525
526/*************************************************************************
527 * PathRemoveArgsA [SHLWAPI.@]
528 *
529 */
530void WINAPI PathRemoveArgsA(LPSTR lpszPath)
531{
532 TRACE("%s\n",lpszPath);
533
534 if(lpszPath)
535 {
536 LPSTR lpszArgs = PathGetArgsA(lpszPath);
537 if (!*lpszArgs)
538 {
539 LPSTR lpszLastChar = CharPrevA(lpszPath, lpszArgs);
540 if(*lpszLastChar==' ') *lpszLastChar = '\0';
541 }
542 }
543}
544
545/*************************************************************************
546 * PathRemoveArgsW [SHLWAPI.@]
547 */
548void WINAPI PathRemoveArgsW(LPWSTR lpszPath)
549{
550 TRACE("%s\n", debugstr_w(lpszPath));
551
552 if(lpszPath)
553 {
554 LPWSTR lpszArgs = PathGetArgsW(lpszPath);
555 if (!*lpszArgs)
556 {
557 LPWSTR lpszLastChar = CharPrevW(lpszPath, lpszArgs);
558 if(*lpszLastChar==' ') *lpszLastChar = '\0';
559 }
560 }
561}
562
563/*************************************************************************
564 * PathRemoveExtensionA [SHLWAPI.@]
565 */
566void WINAPI PathRemoveExtensionA(LPSTR lpszPath)
567{
568 LPSTR lpszExtension = PathFindExtensionA(lpszPath);
569
570 TRACE("%s\n", lpszPath);
571
572 if (lpszExtension) *lpszExtension='\0';
573}
574
575/*************************************************************************
576 * PathRemoveExtensionW [SHLWAPI.@]
577 */
578void WINAPI PathRemoveExtensionW(LPWSTR lpszPath)
579{
580 LPWSTR lpszExtension = PathFindExtensionW(lpszPath);
581
582 TRACE("%s\n", debugstr_w(lpszPath));
583
584 if (lpszExtension) *lpszExtension='\0';
585}
586
587/*************************************************************************
588 * PathRemoveBackslashA [SHLWAPI.@]
589 *
590 * If the path ends in a backslash it is replaced by a NULL
591 * and the address of the NULL is returned
592 * Otherwise
593 * the address of the last character is returned.
594 *
595 * FIXME
596 * "c:\": keep backslash
597 */
598LPSTR WINAPI PathRemoveBackslashA( LPSTR lpszPath )
599{
600 int len;
601 LPSTR szTemp = NULL;
602
603 if(lpszPath)
604 {
605 len = strlen(lpszPath);
606 szTemp = CharPrevA(lpszPath, lpszPath+len);
607 if (! PathIsRootA(lpszPath))
608 {
609 if (*szTemp == '\\') *szTemp = '\0';
610 }
611 }
612 return szTemp;
613}
614
615/*************************************************************************
616 * PathRemoveBackslashW [SHLWAPI.@]
617 */
618LPWSTR WINAPI PathRemoveBackslashW( LPWSTR lpszPath )
619{
620 int len;
621 LPWSTR szTemp = NULL;
622
623 if(lpszPath)
624 {
625 len = strlenW(lpszPath);
626 szTemp = CharPrevW(lpszPath, lpszPath+len);
627 if (! PathIsRootW(lpszPath))
628 {
629 if (*szTemp == '\\') *szTemp = '\0';
630 }
631 }
632 return szTemp;
633}
634
635
636/*
637 Path Manipulations
638*/
639
640/*************************************************************************
641 * PathRemoveBlanksA [SHLWAPI.@]
642 *
643 * NOTES
644 * remove spaces from beginning and end of passed string
645 */
646void WINAPI PathRemoveBlanksA(LPSTR str)
647{
648 LPSTR x = str;
649
650 TRACE("%s\n",str);
651
652 if(str)
653 {
654 while (*x==' ') x = CharNextA(x);
655 if (x!=str) strcpy(str,x);
656 x=str+strlen(str)-1;
657 while (*x==' ') x = CharPrevA(str, x);
658 if (*x==' ') *x='\0';
659 }
660}
661
662/*************************************************************************
663 * PathRemoveBlanksW [SHLWAPI.@]
664 */
665void WINAPI PathRemoveBlanksW(LPWSTR str)
666{
667 LPWSTR x = str;
668
669 TRACE("%s\n",debugstr_w(str));
670
671 if(str)
672 {
673 while (*x==' ') x = CharNextW(x);
674 if (x!=str) strcpyW(str,x);
675 x=str+strlenW(str)-1;
676 while (*x==' ') x = CharPrevW(str, x);
677 if (*x==' ') *x='\0';
678 }
679}
680
681/*************************************************************************
682 * PathQuoteSpacesA [SHLWAPI.@]
683 *
684 */
685LPSTR WINAPI PathQuoteSpacesA(LPSTR lpszPath)
686{
687 TRACE("%s\n",lpszPath);
688
689 if(StrChrA(lpszPath,' '))
690 {
691 int len = strlen(lpszPath);
692 RtlMoveMemory(lpszPath+1, lpszPath, len);
693 *(lpszPath++) = '"';
694 lpszPath += len;
695 *(lpszPath++) = '"';
696 *(lpszPath) = '\0';
697 return --lpszPath;
698 }
699 return 0;
700}
701
702/*************************************************************************
703 * PathQuoteSpacesW [SHLWAPI.@]
704 */
705LPWSTR WINAPI PathQuoteSpacesW(LPWSTR lpszPath)
706{
707 TRACE("%s\n",debugstr_w(lpszPath));
708
709 if(StrChrW(lpszPath,' '))
710 {
711 int len = strlenW(lpszPath);
712 RtlMoveMemory(lpszPath+1, lpszPath, len*sizeof(WCHAR));
713 *(lpszPath++) = '"';
714 lpszPath += len;
715 *(lpszPath++) = '"';
716 *(lpszPath) = '\0';
717 return --lpszPath;
718 }
719 return 0;
720}
721
722/*************************************************************************
723 * PathUnquoteSpacesA [SHLWAPI.@]
724 *
725 * NOTES
726 * unquote string (remove ")
727 */
728VOID WINAPI PathUnquoteSpacesA(LPSTR str)
729{
730 DWORD len = strlen(str);
731
732 TRACE("%s\n",str);
733
734 if (*str!='"')
735 return;
736 if (str[len-1]!='"')
737 return;
738 str[len-1]='\0';
739 strcpy(str,str+1);
740 return;
741}
742
743/*************************************************************************
744 * PathUnquoteSpacesW [SHLWAPI.@]
745 */
746VOID WINAPI PathUnquoteSpacesW(LPWSTR str)
747{
748 DWORD len = strlenW(str);
749
750 TRACE("%s\n",debugstr_w(str));
751
752 if (*str!='"')
753 return;
754 if (str[len-1]!='"')
755 return;
756 str[len-1]='\0';
757 strcpyW(str,str+1);
758 return;
759}
760
761/*************************************************************************
762 * PathParseIconLocationA [SHLWAPI.@]
763 */
764int WINAPI PathParseIconLocationA(LPSTR lpszPath)
765{
766 LPSTR lpstrComma = strchr(lpszPath, ',');
767
768 FIXME("%s stub\n", debugstr_a(lpszPath));
769
770 if (lpstrComma && lpstrComma[1])
771 {
772 lpstrComma[0]='\0';
773/* return atoi(&lpstrComma[1]); FIXME */
774 }
775
776 PathUnquoteSpacesA(lpszPath);
777 return 0;
778}
779
780/*************************************************************************
781 * PathParseIconLocationW [SHLWAPI.@]
782 */
783int WINAPI PathParseIconLocationW(LPWSTR lpszPath)
784{
785 LPWSTR lpstrComma = strchrW(lpszPath, ',');
786
787 FIXME("%s stub\n", debugstr_w(lpszPath));
788
789 if (lpstrComma && lpstrComma[1])
790 {
791 lpstrComma[0]='\0';
792/* return _wtoi(&lpstrComma[1]); FIXME */
793 }
794 PathUnquoteSpacesW(lpszPath);
795 return 0;
796}
797
798/*
799 ########## cleaning and resolving paths ##########
800 */
801
802/*************************************************************************
803 * PathFindOnPathA [SHLWAPI.@]
804 */
805BOOL WINAPI PathFindOnPathA(LPSTR sFile, LPCSTR sOtherDirs)
806{
807 FIXME("%s %s\n",sFile, sOtherDirs);
808 return FALSE;
809}
810
811/*************************************************************************
812 * PathFindOnPathW [SHLWAPI.@]
813 */
814BOOL WINAPI PathFindOnPathW(LPWSTR sFile, LPCWSTR sOtherDirs)
815{
816 FIXME("%s %s\n",debugstr_w(sFile), debugstr_w(sOtherDirs));
817 return FALSE;
818}
819
820/*************************************************************************
821 * PathCompactPathExA [SHLWAPI.@]
822 */
823BOOL WINAPI PathCompactPathExA(
824 LPSTR pszOut,
825 LPCSTR pszSrc,
826 UINT cchMax,
827 DWORD dwFlags)
828{
829 FIXME("%p %s 0x%08x 0x%08lx\n", pszOut, pszSrc, cchMax, dwFlags);
830 return FALSE;
831}
832
833/*************************************************************************
834 * PathCompactPathExW [SHLWAPI.@]
835 */
836BOOL WINAPI PathCompactPathExW(
837 LPWSTR pszOut,
838 LPCWSTR pszSrc,
839 UINT cchMax,
840 DWORD dwFlags)
841{
842 FIXME("%p %s 0x%08x 0x%08lx\n", pszOut, debugstr_w(pszSrc), cchMax, dwFlags);
843 return FALSE;
844}
845
846/*
847 ########## Path Testing ##########
848*/
849
850/*************************************************************************
851 * PathIsUNCA [SHLWAPI.@]
852 *
853 * NOTES
854 * PathIsUNC(char*path);
855 */
856BOOL WINAPI PathIsUNCA(LPCSTR lpszPath)
857{
858 TRACE("%s\n",lpszPath);
859
860 return (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\'));
861}
862
863/*************************************************************************
864 * PathIsUNCW [SHLWAPI.@]
865 */
866BOOL WINAPI PathIsUNCW(LPCWSTR lpszPath)
867{
868 TRACE("%s\n",debugstr_w(lpszPath));
869
870 return (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\'));
871}
872
873/*************************************************************************
874 * PathIsRelativeA [SHLWAPI.@]
875 */
876BOOL WINAPI PathIsRelativeA (LPCSTR lpszPath)
877{
878 TRACE("lpszPath=%s\n",lpszPath);
879
880 return (lpszPath && (lpszPath[0]!='\\' && lpszPath[1]!=':'));
881}
882
883/*************************************************************************
884 * PathIsRelativeW [SHLWAPI.@]
885 */
886BOOL WINAPI PathIsRelativeW (LPCWSTR lpszPath)
887{
888 TRACE("lpszPath=%s\n",debugstr_w(lpszPath));
889
890 return (lpszPath && (lpszPath[0]!='\\' && lpszPath[1]!=':'));
891}
892
893/*************************************************************************
894 * PathIsRootA [SHLWAPI.@]
895 *
896 * notes
897 * TRUE if the path points to a root directory
898 */
899BOOL WINAPI PathIsRootA(LPCSTR lpszPath)
900{
901 TRACE("%s\n",lpszPath);
902
903 /* X:\ */
904 if (lpszPath[1]==':' && lpszPath[2]=='\\' && lpszPath[3]=='\0')
905 return TRUE;
906
907 /* "\" */
908 if (lpszPath[0]=='\\' && lpszPath[1]=='\0')
909 return TRUE;
910
911 /* UNC "\\<computer>\<share>" */
912 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
913 {
914 int foundbackslash = 0;
915 lpszPath += 2;
916 while (*lpszPath)
917 {
918 if (*lpszPath=='\\') foundbackslash++;
919 lpszPath = CharNextA(lpszPath);
920 }
921 if (foundbackslash <= 1)
922 return TRUE;
923 }
924 return FALSE;
925}
926
927/*************************************************************************
928 * PathIsRootW [SHLWAPI.@]
929 */
930BOOL WINAPI PathIsRootW(LPCWSTR lpszPath)
931{
932 TRACE("%s\n",debugstr_w(lpszPath));
933
934 /* X:\ */
935 if (lpszPath[1]==':' && lpszPath[2]=='\\' && lpszPath[3]=='\0')
936 return TRUE;
937
938 /* "\" */
939 if (lpszPath[0]=='\\' && lpszPath[1]=='\0')
940 return TRUE;
941
942 /* UNC "\\<computer>\<share>" */
943 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
944 {
945 int foundbackslash = 0;
946 lpszPath += 2;
947 while (*lpszPath)
948 {
949 if (*lpszPath=='\\') foundbackslash++;
950 lpszPath = CharNextW(lpszPath);
951 }
952 if (foundbackslash <= 1)
953 return TRUE;
954 }
955 return FALSE;
956
957}
958
959/*************************************************************************
960 * PathIsDirectoryA [SHLWAPI.@]
961 */
962BOOL WINAPI PathIsDirectoryA(LPCSTR lpszPath)
963{
964 DWORD dwAttr;
965
966 TRACE("%s\n", debugstr_a(lpszPath));
967
968 dwAttr = GetFileAttributesA(lpszPath);
969 return (dwAttr != -1) ? dwAttr & FILE_ATTRIBUTE_DIRECTORY : 0;
970}
971
972/*************************************************************************
973 * PathIsDirectoryW [SHLWAPI.@]
974 */
975BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath)
976{
977 DWORD dwAttr;
978
979 TRACE("%s\n", debugstr_w(lpszPath));
980
981 dwAttr = GetFileAttributesW(lpszPath);
982 return (dwAttr != -1) ? dwAttr & FILE_ATTRIBUTE_DIRECTORY : 0;
983}
984
985/*************************************************************************
986 * PathFileExistsA [SHLWAPI.@]
987 *
988 * NOTES
989 * file_exists(char *fn);
990 */
991BOOL WINAPI PathFileExistsA(LPCSTR lpszPath)
992{
993 TRACE("%s\n",lpszPath);
994 return (GetFileAttributesA(lpszPath)!=-1);
995}
996
997/*************************************************************************
998 * PathFileExistsW [SHLWAPI.@]
999 */
1000BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
1001{
1002 TRACE("%s\n",debugstr_w(lpszPath));
1003 return (GetFileAttributesW(lpszPath)!=-1);
1004}
1005
1006/*************************************************************************
1007 * PathMatchSingleMaskA [internal]
1008 *
1009 * NOTES
1010 * internal (used by PathMatchSpec)
1011 */
1012static BOOL PathMatchSingleMaskA(LPCSTR name, LPCSTR mask)
1013{
1014 while (*name && *mask && *mask!=';')
1015 {
1016 if (*mask=='*')
1017 {
1018 do
1019 {
1020 if (PathMatchSingleMaskA(name,mask+1)) return 1; /* try substrings */
1021 } while (*name++);
1022 return 0;
1023 }
1024 if (toupper(*mask)!=toupper(*name) && *mask!='?') return 0;
1025 name = CharNextA(name);
1026 mask = CharNextA(mask);
1027 }
1028 if (!*name)
1029 {
1030 while (*mask=='*') mask++;
1031 if (!*mask || *mask==';') return 1;
1032 }
1033 return 0;
1034}
1035
1036/*************************************************************************
1037 * PathMatchSingleMaskW [internal]
1038 */
1039static BOOL PathMatchSingleMaskW(LPCWSTR name, LPCWSTR mask)
1040{
1041 while (*name && *mask && *mask!=';')
1042 {
1043 if (*mask=='*')
1044 {
1045 do
1046 {
1047 if (PathMatchSingleMaskW(name,mask+1)) return 1; /* try substrings */
1048 } while (*name++);
1049 return 0;
1050 }
1051 if (toupperW(*mask)!=toupperW(*name) && *mask!='?') return 0;
1052 name = CharNextW(name);
1053 mask = CharNextW(mask);
1054 }
1055 if (!*name)
1056 {
1057 while (*mask=='*') mask++;
1058 if (!*mask || *mask==';') return 1;
1059 }
1060 return 0;
1061}
1062/*************************************************************************
1063 * PathMatchSpecA [SHLWAPI.@]
1064 *
1065 * NOTES
1066 * used from COMDLG32
1067 */
1068BOOL WINAPI PathMatchSpecA(LPCSTR name, LPCSTR mask)
1069{
1070 TRACE("%s %s\n",name,mask);
1071
1072 if (!lstrcmpA( mask, "*.*" )) return 1; /* we don't require a period */
1073
1074 while (*mask)
1075 {
1076 if (PathMatchSingleMaskA(name,mask)) return 1; /* helper function */
1077 while (*mask && *mask!=';') mask = CharNextA(mask);
1078 if (*mask==';')
1079 {
1080 mask++;
1081 while (*mask==' ') mask++; /* masks may be separated by "; " */
1082 }
1083 }
1084 return 0;
1085}
1086
1087/*************************************************************************
1088 * PathMatchSpecW [SHLWAPI.@]
1089 */
1090BOOL WINAPI PathMatchSpecW(LPCWSTR name, LPCWSTR mask)
1091{
1092 static const WCHAR stemp[] = { '*','.','*',0 };
1093 TRACE("%s %s\n",debugstr_w(name),debugstr_w(mask));
1094
1095 if (!lstrcmpW( mask, stemp )) return 1; /* we don't require a period */
1096
1097 while (*mask)
1098 {
1099 if (PathMatchSingleMaskW(name,mask)) return 1; /* helper function */
1100 while (*mask && *mask!=';') mask = CharNextW(mask);
1101 if (*mask==';')
1102 {
1103 mask++;
1104 while (*mask==' ') mask++; /* masks may be separated by "; " */
1105 }
1106 }
1107 return 0;
1108}
1109
1110/*************************************************************************
1111 * PathIsSameRootA [SHLWAPI.@]
1112 *
1113 * FIXME
1114 * what to do with "\path" ??
1115 */
1116BOOL WINAPI PathIsSameRootA(LPCSTR lpszPath1, LPCSTR lpszPath2)
1117{
1118 TRACE("%s %s\n", lpszPath1, lpszPath2);
1119
1120 if (PathIsRelativeA(lpszPath1) || PathIsRelativeA(lpszPath2)) return FALSE;
1121
1122 /* usual path */
1123 if ( toupper(lpszPath1[0])==toupper(lpszPath2[0]) &&
1124 lpszPath1[1]==':' && lpszPath2[1]==':' &&
1125 lpszPath1[2]=='\\' && lpszPath2[2]=='\\')
1126 return TRUE;
1127
1128 /* UNC */
1129 if (lpszPath1[0]=='\\' && lpszPath2[0]=='\\' &&
1130 lpszPath1[1]=='\\' && lpszPath2[1]=='\\')
1131 {
1132 int pos=2, bsfound=0;
1133 while (lpszPath1[pos] && lpszPath2[pos] &&
1134 (lpszPath1[pos] == lpszPath2[pos]))
1135 {
1136 if (lpszPath1[pos]=='\\') bsfound++;
1137 if (bsfound == 2) return TRUE;
1138 pos++; /* fixme: use CharNext*/
1139 }
1140 return (lpszPath1[pos] == lpszPath2[pos]);
1141 }
1142 return FALSE;
1143}
1144
1145/*************************************************************************
1146 * PathIsSameRootW [SHLWAPI.@]
1147 */
1148BOOL WINAPI PathIsSameRootW(LPCWSTR lpszPath1, LPCWSTR lpszPath2)
1149{
1150 TRACE("%s %s\n", debugstr_w(lpszPath1), debugstr_w(lpszPath2));
1151
1152 if (PathIsRelativeW(lpszPath1) || PathIsRelativeW(lpszPath2)) return FALSE;
1153
1154 /* usual path */
1155 if ( toupperW(lpszPath1[0])==toupperW(lpszPath2[0]) &&
1156 lpszPath1[1]==':' && lpszPath2[1]==':' &&
1157 lpszPath1[2]=='\\' && lpszPath2[2]=='\\')
1158 return TRUE;
1159
1160 /* UNC */
1161 if (lpszPath1[0]=='\\' && lpszPath2[0]=='\\' &&
1162 lpszPath1[1]=='\\' && lpszPath2[1]=='\\')
1163 {
1164 int pos=2, bsfound=0;
1165 while (lpszPath1[pos] && lpszPath2[pos] &&
1166 (lpszPath1[pos] == lpszPath2[pos]))
1167 {
1168 if (lpszPath1[pos]=='\\') bsfound++;
1169 if (bsfound == 2) return TRUE;
1170 pos++;/* fixme: use CharNext*/
1171 }
1172 return (lpszPath1[pos] == lpszPath2[pos]);
1173 }
1174 return FALSE;
1175}
1176
1177/*************************************************************************
1178 * PathIsURLA
1179 */
1180BOOL WINAPI PathIsURLA(LPCSTR lpstrPath)
1181{
1182 // 2001-08-30 PH
1183 // SHLWAPI/W95 Code:
1184 //
1185 // if (lpstrPath == NULL)
1186 // return FALSE;
1187 //
1188 // DWORD dwUnknown = SHREG_xxx; // 0x18
1189 // return SHLWAPI_1(lpstrPath, &dwUnknown);
1190
1191
1192 LPSTR lpstrRes;
1193 int iSize, i=0;
1194 static LPSTR SupportedProtocol[] =
1195 {"http","https","ftp","gopher","file","mailto",NULL};
1196
1197 if(!lpstrPath) return FALSE;
1198
1199 /* get protocol */
1200 lpstrRes = strchr(lpstrPath,':');
1201 if(!lpstrRes) return FALSE;
1202 iSize = lpstrRes - lpstrPath;
1203
1204 while(SupportedProtocol[i])
1205 {
1206 if (iSize == strlen(SupportedProtocol[i]))
1207 if(!strncasecmp(lpstrPath, SupportedProtocol[i], iSize))
1208 return TRUE;
1209 i++;
1210 }
1211
1212 return FALSE;
1213}
1214
1215/*************************************************************************
1216 * PathIsURLW
1217 */
1218BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
1219{
1220 LPWSTR lpstrRes;
1221 int iSize, i=0;
1222 static WCHAR SupportedProtocol[7][7] =
1223 {{'h','t','t','p','\0'},{'h','t','t','p','s','\0'},{'f','t','p','\0'},
1224 {'g','o','p','h','e','r','\0'},{'f','i','l','e','\0'},
1225 {'m','a','i','l','t','o','\0'},{0}};
1226
1227 if(!lpstrPath) return FALSE;
1228
1229 /* get protocol */
1230 lpstrRes = strchrW(lpstrPath,':');
1231 if(!lpstrRes) return FALSE;
1232 iSize = lpstrRes - lpstrPath;
1233
1234 while(SupportedProtocol[i])
1235 {
1236 if (iSize == strlenW(SupportedProtocol[i]))
1237 if(!strncmpiW(lpstrPath, SupportedProtocol[i], iSize))
1238 return TRUE;
1239 i++;
1240 }
1241
1242 return FALSE;
1243}
1244
1245
1246/*************************************************************************
1247 * PathIsContentTypeA [SHLWAPI.@]
1248 */
1249BOOL WINAPI PathIsContentTypeA(LPCSTR pszPath, LPCSTR pszContentType)
1250{
1251 FIXME("%s %s\n", pszPath, pszContentType);
1252 return FALSE;
1253}
1254
1255/*************************************************************************
1256 * PathIsContentTypeW [SHLWAPI.@]
1257 */
1258BOOL WINAPI PathIsContentTypeW(LPCWSTR pszPath, LPCWSTR pszContentType)
1259{
1260 FIXME("%s %s\n", debugstr_w(pszPath), debugstr_w(pszContentType));
1261 return FALSE;
1262}
1263
1264/*************************************************************************
1265 * PathIsFileSpecA [SHLWAPI.@]
1266 */
1267BOOL WINAPI PathIsFileSpecA(LPCSTR pszPath)
1268{
1269 FIXME("%s\n", pszPath);
1270 return FALSE;
1271}
1272
1273/*************************************************************************
1274 * PathIsFileSpecW [SHLWAPI.@]
1275 */
1276BOOL WINAPI PathIsFileSpecW(LPCWSTR pszPath)
1277{
1278 FIXME("%s\n", debugstr_w(pszPath));
1279 return FALSE;
1280}
1281
1282/*************************************************************************
1283 * PathIsPrefixA [SHLWAPI.@]
1284 */
1285BOOL WINAPI PathIsPrefixA(LPCSTR pszPrefix, LPCSTR pszPath)
1286{
1287 FIXME("%s %s\n", pszPrefix, pszPath);
1288 return FALSE;
1289}
1290
1291/*************************************************************************
1292 * PathIsPrefixW [SHLWAPI.@]
1293 */
1294BOOL WINAPI PathIsPrefixW(LPCWSTR pszPrefix, LPCWSTR pszPath)
1295{
1296 FIXME("%s %s\n", debugstr_w(pszPrefix), debugstr_w(pszPath));
1297 return FALSE;
1298}
1299
1300/*************************************************************************
1301 * PathIsSystemFolderA [SHLWAPI.@]
1302 */
1303BOOL WINAPI PathIsSystemFolderA(LPCSTR pszPath, DWORD dwAttrb)
1304{
1305 FIXME("%s 0x%08lx\n", pszPath, dwAttrb);
1306 return FALSE;
1307}
1308
1309/*************************************************************************
1310 * PathIsSystemFolderW [SHLWAPI.@]
1311 */
1312BOOL WINAPI PathIsSystemFolderW(LPCWSTR pszPath, DWORD dwAttrb)
1313{
1314 FIXME("%s 0x%08lx\n", debugstr_w(pszPath), dwAttrb);
1315 return FALSE;
1316}
1317
1318/*************************************************************************
1319 * PathIsUNCServerA [SHLWAPI.@]
1320 */
1321BOOL WINAPI PathIsUNCServerA(
1322 LPCSTR pszPath)
1323{
1324 FIXME("%s\n", pszPath);
1325 return FALSE;
1326}
1327
1328/*************************************************************************
1329 * PathIsUNCServerW [SHLWAPI.@]
1330 */
1331BOOL WINAPI PathIsUNCServerW(
1332 LPCWSTR pszPath)
1333{
1334 FIXME("%s\n", debugstr_w(pszPath));
1335 return FALSE;
1336}
1337
1338/*************************************************************************
1339 * PathIsUNCServerShareA [SHLWAPI.@]
1340 */
1341BOOL WINAPI PathIsUNCServerShareA(
1342 LPCSTR pszPath)
1343{
1344 FIXME("%s\n", pszPath);
1345 return FALSE;
1346}
1347
1348/*************************************************************************
1349 * PathIsUNCServerShareW [SHLWAPI.@]
1350 */
1351BOOL WINAPI PathIsUNCServerShareW(
1352 LPCWSTR pszPath)
1353{
1354 FIXME("%s\n", debugstr_w(pszPath));
1355 return FALSE;
1356}
1357
1358/*************************************************************************
1359 * PathCanonicalizeA [SHLWAPI.@]
1360 *
1361 * FIXME
1362 * returnvalue, use CharNext
1363 */
1364
1365BOOL WINAPI PathCanonicalizeA(LPSTR pszBuf, LPCSTR pszPath)
1366{
1367 int OffsetMin = 0, OffsetSrc = 0, OffsetDst = 0, LenSrc = strlen(pszPath);
1368 BOOL bModifyed = FALSE;
1369
1370 TRACE("%p %s\n", pszBuf, pszPath);
1371
1372 pszBuf[OffsetDst]='\0';
1373
1374 /* keep the root of the path */
1375 if( LenSrc && (pszPath[OffsetSrc]=='\\'))
1376 {
1377 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1378 }
1379 else if ( (LenSrc >= 2) && (pszPath[OffsetSrc+1] == ':'))
1380 {
1381 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1382 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1383 if (LenSrc && (pszPath[OffsetSrc] == '\\'))
1384 {
1385 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1386 if (LenSrc == 1 && pszPath[OffsetSrc]=='.')
1387 {
1388 /* C:\. */
1389 OffsetSrc++; LenSrc--; bModifyed = TRUE;
1390 }
1391 else if (LenSrc == 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='.')
1392 {
1393 /* C:\.. */
1394 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1395 }
1396 }
1397 }
1398
1399 /* ".\" at the beginning of the path */
1400 if (LenSrc >= 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='\\')
1401 {
1402 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1403 }
1404
1405 while ( LenSrc )
1406 {
1407 if((LenSrc>=3) && (pszPath[OffsetSrc]=='\\') && (pszPath[OffsetSrc+1]=='.') && (pszPath[OffsetSrc+2]=='.'))
1408 {
1409 /* "\.." found, go one deeper */
1410 while((OffsetDst > OffsetMin) && (pszBuf[OffsetDst]!='\\')) OffsetDst--;
1411 OffsetSrc += 3; LenSrc -= 3; bModifyed = TRUE;
1412 if(OffsetDst == OffsetMin && pszPath[OffsetSrc]=='\\') OffsetSrc++;
1413 pszBuf[OffsetDst] = '\0'; /* important for \..\.. */
1414 }
1415 else if(LenSrc>=2 && pszPath[OffsetSrc]=='\\' && pszPath[OffsetSrc+1]=='.' )
1416 {
1417 /* "\." found, skip it */
1418 OffsetSrc += 2; LenSrc-=2; bModifyed = TRUE;
1419 }
1420 else
1421 {
1422 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; LenSrc--;
1423 }
1424 }
1425 pszBuf[OffsetDst] = '\0';
1426 TRACE("-- %s %u\n", pszBuf, bModifyed);
1427 return bModifyed;
1428}
1429
1430
1431/*************************************************************************
1432 * PathCanonicalizeW [SHLWAPI.@]
1433 *
1434 * FIXME
1435 * returnvalue, use CharNext
1436 */
1437BOOL WINAPI PathCanonicalizeW(LPWSTR pszBuf, LPCWSTR pszPath)
1438{
1439 int OffsetMin = 0, OffsetSrc = 0, OffsetDst = 0, LenSrc = strlenW(pszPath);
1440 BOOL bModifyed = FALSE;
1441
1442 TRACE("%p %s\n", pszBuf, debugstr_w(pszPath));
1443
1444 pszBuf[OffsetDst]='\0';
1445
1446 /* keep the root of the path */
1447 if( LenSrc && (pszPath[OffsetSrc]=='\\'))
1448 {
1449 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1450 }
1451 else if ( (LenSrc >= 2) && (pszPath[OffsetSrc+1] == ':'))
1452 {
1453 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1454 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1455 if (LenSrc && (pszPath[OffsetSrc] == '\\'))
1456 {
1457 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1458 if (LenSrc == 1 && pszPath[OffsetSrc]=='.')
1459 {
1460 /* C:\. */
1461 OffsetSrc++; LenSrc--; bModifyed = TRUE;
1462 }
1463 else if (LenSrc == 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='.')
1464 {
1465 /* C:\.. */
1466 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1467 }
1468 }
1469 }
1470
1471 /* ".\" at the beginning of the path */
1472 if (LenSrc >= 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='\\')
1473 {
1474 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1475 }
1476
1477 while ( LenSrc )
1478 {
1479 if((LenSrc>=3) && (pszPath[OffsetSrc]=='\\') && (pszPath[OffsetSrc+1]=='.') && (pszPath[OffsetSrc+2]=='.'))
1480 {
1481 /* "\.." found, go one deeper */
1482 while((OffsetDst > OffsetMin) && (pszBuf[OffsetDst]!='\\')) OffsetDst--;
1483 OffsetSrc += 3; LenSrc -= 3; bModifyed = TRUE;
1484 if(OffsetDst == OffsetMin && pszPath[OffsetSrc]=='\\') OffsetSrc++;
1485 pszBuf[OffsetDst] = '\0'; /* important for \..\.. */
1486 }
1487 else if(LenSrc>=2 && pszPath[OffsetSrc]=='\\' && pszPath[OffsetSrc+1]=='.' )
1488 {
1489 /* "\." found, skip it */
1490 OffsetSrc += 2; LenSrc-=2; bModifyed = TRUE;
1491 }
1492 else
1493 {
1494 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; LenSrc--;
1495 }
1496 }
1497 pszBuf[OffsetDst] = '\0';
1498 TRACE("-- %s %u\n", debugstr_w(pszBuf), bModifyed);
1499 return bModifyed;
1500}
1501
1502/*************************************************************************
1503 * PathFindNextComponentA [SHLWAPI.@]
1504 *
1505 * NOTES
1506 * special cases:
1507 * "" null
1508 * aa "" (pointer to traling NULL)
1509 * aa\ "" (pointer to traling NULL)
1510 * aa\\ "" (pointer to traling NULL)
1511 * aa\\bb bb
1512 * aa\\\bb \bb
1513 * c:\aa\ "aa\"
1514 * \\aa aa
1515 * \\aa\b aa\b
1516*/
1517LPSTR WINAPI PathFindNextComponentA(LPCSTR pszPath)
1518{
1519 LPSTR pos;
1520
1521 TRACE("%s\n", pszPath);
1522
1523 if(!pszPath || !*pszPath) return NULL;
1524 if(!(pos = StrChrA(pszPath, '\\')))
1525 return (LPSTR) pszPath + strlen(pszPath);
1526 pos++;
1527 if(pos[0] == '\\') pos++;
1528 return pos;
1529}
1530
1531/*************************************************************************
1532 * PathFindNextComponentW [SHLWAPI.@]
1533 */
1534LPWSTR WINAPI PathFindNextComponentW(LPCWSTR pszPath)
1535{
1536 LPWSTR pos;
1537
1538 TRACE("%s\n", debugstr_w(pszPath));
1539
1540 if(!pszPath || !*pszPath) return NULL;
1541 if (!(pos = StrChrW(pszPath, '\\')))
1542 return (LPWSTR) pszPath + strlenW(pszPath);
1543 pos++;
1544 if(pos[0] == '\\') pos++;
1545 return pos;
1546}
1547
1548/*************************************************************************
1549 * PathAddExtensionA [SHLWAPI.@]
1550 *
1551 * NOTES
1552 * it adds never a dot
1553 */
1554
1555BOOL WINAPI PathAddExtensionA(
1556 LPSTR pszPath,
1557 LPCSTR pszExtension)
1558{
1559 if (*pszPath)
1560 {
1561 if (*(PathFindExtensionA(pszPath))) return FALSE;
1562
1563 if (!pszExtension || *pszExtension=='\0')
1564 strcat(pszPath, "exe");
1565 else
1566 strcat(pszPath, pszExtension);
1567 }
1568
1569 return TRUE;
1570}
1571
1572/*************************************************************************
1573 * PathAddExtensionW [SHLWAPI.@]
1574 */
1575BOOL WINAPI PathAddExtensionW(
1576 LPWSTR pszPath,
1577 LPCWSTR pszExtension)
1578{
1579 static const WCHAR ext[] = { 'e','x','e',0 };
1580
1581 if (*pszPath)
1582 {
1583 if (*(PathFindExtensionW(pszPath))) return FALSE;
1584
1585 if (!pszExtension || *pszExtension=='\0')
1586 strcatW(pszPath, ext);
1587 else
1588 strcatW(pszPath, pszExtension);
1589 }
1590 return TRUE;
1591
1592}
1593
1594/*************************************************************************
1595 * PathMakePrettyA [SHLWAPI.@]
1596 */
1597BOOL WINAPI PathMakePrettyA(
1598 LPSTR lpPath)
1599{
1600 FIXME("%s\n", lpPath);
1601 return TRUE;
1602}
1603
1604/*************************************************************************
1605 * PathMakePrettyW [SHLWAPI.@]
1606 */
1607BOOL WINAPI PathMakePrettyW(
1608 LPWSTR lpPath)
1609{
1610 FIXME("%s\n", debugstr_w(lpPath));
1611 return TRUE;
1612
1613}
1614
1615/*************************************************************************
1616 * PathCommonPrefixA [SHLWAPI.@]
1617 */
1618int WINAPI PathCommonPrefixA(
1619 LPCSTR pszFile1,
1620 LPCSTR pszFile2,
1621 LPSTR achPath)
1622{
1623 FIXME("%s %s %p\n", pszFile1, pszFile2, achPath);
1624 return 0;
1625}
1626
1627/*************************************************************************
1628 * PathCommonPrefixW [SHLWAPI.@]
1629 */
1630int WINAPI PathCommonPrefixW(
1631 LPCWSTR pszFile1,
1632 LPCWSTR pszFile2,
1633 LPWSTR achPath)
1634{
1635 FIXME("%s %s %p\n", debugstr_w(pszFile1), debugstr_w(pszFile2),achPath );
1636 return 0;
1637}
1638
1639/*************************************************************************
1640 * PathCompactPathA [SHLWAPI.@]
1641 */
1642BOOL WINAPI PathCompactPathA(HDC hDC, LPSTR pszPath, UINT dx)
1643{
1644 FIXME("0x%08x %s 0x%08x\n", hDC, pszPath, dx);
1645 return FALSE;
1646}
1647
1648/*************************************************************************
1649 * PathCompactPathW [SHLWAPI.@]
1650 */
1651BOOL WINAPI PathCompactPathW(HDC hDC, LPWSTR pszPath, UINT dx)
1652{
1653 FIXME("0x%08x %s 0x%08x\n", hDC, debugstr_w(pszPath), dx);
1654 return FALSE;
1655}
1656
1657/*************************************************************************
1658 * PathGetCharTypeA [SHLWAPI.@]
1659 */
1660UINT WINAPI PathGetCharTypeA(UCHAR ch)
1661{
1662 UINT flags = 0;
1663
1664 TRACE("%c\n", ch);
1665
1666 /* We could use them in filenames, but this would confuse 'ls' */
1667 if (iscntrl(ch))
1668 return GCT_INVALID;
1669 if ((ch == '*') || (ch=='?'))
1670 return GCT_WILD;
1671 if ((ch == '\\') || (ch=='/'))
1672 return GCT_SEPARATOR;
1673 flags = 0;
1674 /* all normal characters, no lower case letters */
1675 if ((ch > ' ') && (ch < 0x7f) && !islower(ch))
1676 flags |= GCT_SHORTCHAR;
1677 /* All other characters are valid in long filenames, even umlauts */
1678 return flags | GCT_LFNCHAR;
1679}
1680
1681/*************************************************************************
1682 * PathGetCharTypeW [SHLWAPI.@]
1683 */
1684UINT WINAPI PathGetCharTypeW(WCHAR ch)
1685{
1686 FIXME("%c, using ascii version\n", ch);
1687 return PathGetCharTypeA(ch);
1688}
1689
1690/*************************************************************************
1691 * PathMakeSystemFolderA [SHLWAPI.@]
1692 */
1693BOOL WINAPI PathMakeSystemFolderA(LPCSTR pszPath)
1694{
1695 FIXME("%s\n", pszPath);
1696 return FALSE;
1697}
1698
1699/*************************************************************************
1700 * PathMakeSystemFolderW [SHLWAPI.@]
1701 */
1702BOOL WINAPI PathMakeSystemFolderW(LPCWSTR pszPath)
1703{
1704 FIXME("%s\n", debugstr_w(pszPath));
1705 return FALSE;
1706}
1707
1708/*************************************************************************
1709 * PathRenameExtensionA [SHLWAPI.@]
1710 */
1711BOOL WINAPI PathRenameExtensionA(LPSTR pszPath, LPCSTR pszExt)
1712{
1713 FIXME("%s %s\n", pszPath, pszExt);
1714 return FALSE;
1715}
1716
1717/*************************************************************************
1718 * PathRenameExtensionW [SHLWAPI.@]
1719 */
1720BOOL WINAPI PathRenameExtensionW(LPWSTR pszPath, LPCWSTR pszExt)
1721{
1722 FIXME("%s %s\n", debugstr_w(pszPath), debugstr_w(pszExt));
1723 return FALSE;
1724}
1725
1726/*************************************************************************
1727 * PathSearchAndQualifyA [SHLWAPI.@]
1728 */
1729BOOL WINAPI PathSearchAndQualifyA(
1730 LPCSTR pszPath,
1731 LPSTR pszBuf,
1732 UINT cchBuf)
1733{
1734 FIXME("%s %s 0x%08x\n", pszPath, pszBuf, cchBuf);
1735 return FALSE;
1736}
1737
1738/*************************************************************************
1739 * PathSearchAndQualifyW [SHLWAPI.@]
1740 */
1741BOOL WINAPI PathSearchAndQualifyW(
1742 LPCWSTR pszPath,
1743 LPWSTR pszBuf,
1744 UINT cchBuf)
1745{
1746 FIXME("%s %s 0x%08x\n", debugstr_w(pszPath), debugstr_w(pszBuf), cchBuf);
1747 return FALSE;
1748}
1749
1750#ifndef __WIN32OS2__
1751/*************************************************************************
1752 * PathSkipRootA [SHLWAPI.@]
1753 */
1754LPSTR WINAPI PathSkipRootA(LPCSTR pszPath)
1755{
1756 FIXME("%s\n", pszPath);
1757 return (LPSTR)pszPath;
1758}
1759
1760/*************************************************************************
1761 * PathSkipRootW [SHLWAPI.@]
1762 */
1763LPWSTR WINAPI PathSkipRootW(LPCWSTR pszPath)
1764{
1765 FIXME("%s\n", debugstr_w(pszPath));
1766 return (LPWSTR)pszPath;
1767}
1768#endif
1769
1770/*************************************************************************
1771 * PathCreateFromUrlA [SHLWAPI.@]
1772 */
1773HRESULT WINAPI PathCreateFromUrlA(
1774 LPCSTR pszUrl,
1775 LPSTR pszPath,
1776 LPDWORD pcchPath,
1777 DWORD dwFlags)
1778{
1779 FIXME("%s %p %p 0x%08lx\n",
1780 pszUrl, pszPath, pcchPath, dwFlags);
1781 return S_OK;
1782}
1783
1784/*************************************************************************
1785 * PathCreateFromUrlW [SHLWAPI.@]
1786 */
1787HRESULT WINAPI PathCreateFromUrlW(
1788 LPCWSTR pszUrl,
1789 LPWSTR pszPath,
1790 LPDWORD pcchPath,
1791 DWORD dwFlags)
1792{
1793 FIXME("%s %p %p 0x%08lx\n",
1794 debugstr_w(pszUrl), pszPath, pcchPath, dwFlags);
1795 return S_OK;
1796}
1797
1798/*************************************************************************
1799 * PathRelativePathToA [SHLWAPI.@]
1800 */
1801BOOL WINAPI PathRelativePathToA(
1802 LPSTR pszPath,
1803 LPCSTR pszFrom,
1804 DWORD dwAttrFrom,
1805 LPCSTR pszTo,
1806 DWORD dwAttrTo)
1807{
1808 FIXME("%s %s 0x%08lx %s 0x%08lx\n",
1809 pszPath, pszFrom, dwAttrFrom, pszTo, dwAttrTo);
1810 return FALSE;
1811}
1812
1813/*************************************************************************
1814 * PathRelativePathToW [SHLWAPI.@]
1815 */
1816BOOL WINAPI PathRelativePathToW(
1817 LPWSTR pszPath,
1818 LPCWSTR pszFrom,
1819 DWORD dwAttrFrom,
1820 LPCWSTR pszTo,
1821 DWORD dwAttrTo)
1822{
1823 FIXME("%s %s 0x%08lx %s 0x%08lx\n",
1824 debugstr_w(pszPath), debugstr_w(pszFrom), dwAttrFrom, debugstr_w(pszTo), dwAttrTo);
1825 return FALSE;
1826}
1827
1828/*************************************************************************
1829 * PathUnmakeSystemFolderA [SHLWAPI.@]
1830 */
1831BOOL WINAPI PathUnmakeSystemFolderA(LPCSTR pszPath)
1832{
1833 FIXME("%s\n", pszPath);
1834 return FALSE;
1835}
1836
1837/*************************************************************************
1838 * PathUnmakeSystemFolderW [SHLWAPI.@]
1839 */
1840BOOL WINAPI PathUnmakeSystemFolderW(LPCWSTR pszPath)
1841{
1842 FIXME("%s\n", debugstr_w(pszPath));
1843 return FALSE;
1844}
1845
1846/*
1847 ########## special ##########
1848*/
1849
1850/*************************************************************************
1851 * PathSetDlgItemPathA [SHLWAPI.@]
1852 *
1853 * NOTES
1854 * use PathCompactPath to make sure, the path fits into the control
1855 */
1856BOOL WINAPI PathSetDlgItemPathA(HWND hDlg, int id, LPCSTR pszPath)
1857{ TRACE("%x %x %s\n",hDlg, id, pszPath);
1858 return SetDlgItemTextA(hDlg, id, pszPath);
1859}
1860
1861/*************************************************************************
1862 * PathSetDlgItemPathW [SHLWAPI.@]
1863 */
1864BOOL WINAPI PathSetDlgItemPathW(HWND hDlg, int id, LPCWSTR pszPath)
1865{ TRACE("%x %x %s\n",hDlg, id, debugstr_w(pszPath));
1866 return SetDlgItemTextW(hDlg, id, pszPath);
1867}
Note: See TracBrowser for help on using the repository browser.