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

Last change on this file since 6650 was 6650, checked in by bird, 24 years ago

Added $Id:$ keyword.

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