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

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

.

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