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

Last change on this file since 8047 was 8047, checked in by sandervl, 23 years ago

PH: PathIsURLA/W fixes for Flask

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