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

Last change on this file since 7820 was 7820, checked in by sandervl, 24 years ago

Wine resync

File size: 43.2 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 return (base.fcncde) ? TRUE : FALSE;
1166}
1167
1168/*************************************************************************
1169 * PathIsURLW (SHLWAPI.@)
1170 */
1171BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
1172{
1173 UNKNOWN_SHLWAPI_2 base;
1174 DWORD res1;
1175
1176 if (!lpstrPath || !*lpstrPath) return FALSE;
1177
1178 /* get protocol */
1179 base.size = 24;
1180 res1 = SHLWAPI_2(lpstrPath, &base);
1181 return (base.fcncde) ? TRUE : FALSE;
1182}
1183
1184
1185/*************************************************************************
1186 * PathIsContentTypeA [SHLWAPI.@]
1187 */
1188BOOL WINAPI PathIsContentTypeA(LPCSTR pszPath, LPCSTR pszContentType)
1189{
1190 FIXME("%s %s\n", pszPath, pszContentType);
1191 return FALSE;
1192}
1193
1194/*************************************************************************
1195 * PathIsContentTypeW [SHLWAPI.@]
1196 */
1197BOOL WINAPI PathIsContentTypeW(LPCWSTR pszPath, LPCWSTR pszContentType)
1198{
1199 FIXME("%s %s\n", debugstr_w(pszPath), debugstr_w(pszContentType));
1200 return FALSE;
1201}
1202
1203/*************************************************************************
1204 * PathIsFileSpecA [SHLWAPI.@]
1205 */
1206BOOL WINAPI PathIsFileSpecA(LPCSTR pszPath)
1207{
1208 FIXME("%s\n", pszPath);
1209 return FALSE;
1210}
1211
1212/*************************************************************************
1213 * PathIsFileSpecW [SHLWAPI.@]
1214 */
1215BOOL WINAPI PathIsFileSpecW(LPCWSTR pszPath)
1216{
1217 FIXME("%s\n", debugstr_w(pszPath));
1218 return FALSE;
1219}
1220
1221/*************************************************************************
1222 * PathIsPrefixA [SHLWAPI.@]
1223 */
1224BOOL WINAPI PathIsPrefixA(LPCSTR pszPrefix, LPCSTR pszPath)
1225{
1226 FIXME("%s %s\n", pszPrefix, pszPath);
1227 return FALSE;
1228}
1229
1230/*************************************************************************
1231 * PathIsPrefixW [SHLWAPI.@]
1232 */
1233BOOL WINAPI PathIsPrefixW(LPCWSTR pszPrefix, LPCWSTR pszPath)
1234{
1235 FIXME("%s %s\n", debugstr_w(pszPrefix), debugstr_w(pszPath));
1236 return FALSE;
1237}
1238
1239/*************************************************************************
1240 * PathIsSystemFolderA [SHLWAPI.@]
1241 */
1242BOOL WINAPI PathIsSystemFolderA(LPCSTR pszPath, DWORD dwAttrb)
1243{
1244 FIXME("%s 0x%08lx\n", pszPath, dwAttrb);
1245 return FALSE;
1246}
1247
1248/*************************************************************************
1249 * PathIsSystemFolderW [SHLWAPI.@]
1250 */
1251BOOL WINAPI PathIsSystemFolderW(LPCWSTR pszPath, DWORD dwAttrb)
1252{
1253 FIXME("%s 0x%08lx\n", debugstr_w(pszPath), dwAttrb);
1254 return FALSE;
1255}
1256
1257/*************************************************************************
1258 * PathIsUNCServerA [SHLWAPI.@]
1259 */
1260BOOL WINAPI PathIsUNCServerA(
1261 LPCSTR lpszPath)
1262{
1263 TRACE("%s\n", debugstr_a(lpszPath));
1264 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
1265 {
1266 int foundbackslash = 0;
1267 lpszPath += 2;
1268 while (*lpszPath)
1269 {
1270 if (*lpszPath=='\\') foundbackslash++;
1271 lpszPath = CharNextA(lpszPath);
1272 }
1273 if (foundbackslash == 0)
1274 return TRUE;
1275 }
1276 return FALSE;
1277}
1278
1279/*************************************************************************
1280 * PathIsUNCServerW [SHLWAPI.@]
1281 */
1282BOOL WINAPI PathIsUNCServerW(
1283 LPCWSTR lpszPath)
1284{
1285 TRACE("%s\n", debugstr_w(lpszPath));
1286 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
1287 {
1288 int foundbackslash = 0;
1289 lpszPath += 2;
1290 while (*lpszPath)
1291 {
1292 if (*lpszPath=='\\') foundbackslash++;
1293 lpszPath = CharNextW(lpszPath);
1294 }
1295 if (foundbackslash == 0)
1296 return TRUE;
1297 }
1298 return FALSE;
1299}
1300
1301/*************************************************************************
1302 * PathIsUNCServerShareA [SHLWAPI.@]
1303 */
1304BOOL WINAPI PathIsUNCServerShareA(
1305 LPCSTR lpszPath)
1306{
1307 TRACE("%s\n", debugstr_a(lpszPath));
1308 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
1309 {
1310 int foundbackslash = 0;
1311 lpszPath += 2;
1312 while (*lpszPath)
1313 {
1314 if (*lpszPath=='\\') foundbackslash++;
1315 lpszPath = CharNextA(lpszPath);
1316 }
1317 if (foundbackslash == 1)
1318 return TRUE;
1319 }
1320 return FALSE;
1321}
1322
1323/*************************************************************************
1324 * PathIsUNCServerShareW [SHLWAPI.@]
1325 */
1326BOOL WINAPI PathIsUNCServerShareW(
1327 LPCWSTR lpszPath)
1328{
1329 TRACE("%s\n", debugstr_w(lpszPath));
1330 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
1331 {
1332 int foundbackslash = 0;
1333 lpszPath += 2;
1334 while (*lpszPath)
1335 {
1336 if (*lpszPath=='\\') foundbackslash++;
1337 lpszPath = CharNextW(lpszPath);
1338 }
1339 if (foundbackslash == 1)
1340 return TRUE;
1341 }
1342 return FALSE;
1343}
1344
1345/*************************************************************************
1346 * PathCanonicalizeA [SHLWAPI.@]
1347 *
1348 * FIXME
1349 * returnvalue, use CharNext
1350 */
1351
1352BOOL WINAPI PathCanonicalizeA(LPSTR pszBuf, LPCSTR pszPath)
1353{
1354 int OffsetMin = 0, OffsetSrc = 0, OffsetDst = 0, LenSrc = strlen(pszPath);
1355 BOOL bModifyed = FALSE;
1356
1357 TRACE("%p %s\n", pszBuf, pszPath);
1358
1359 pszBuf[OffsetDst]='\0';
1360
1361 /* keep the root of the path */
1362 if( LenSrc && (pszPath[OffsetSrc]=='\\'))
1363 {
1364 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1365 }
1366 else if ( (LenSrc >= 2) && (pszPath[OffsetSrc+1] == ':'))
1367 {
1368 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1369 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1370 if (LenSrc && (pszPath[OffsetSrc] == '\\'))
1371 {
1372 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1373 if (LenSrc == 1 && pszPath[OffsetSrc]=='.')
1374 {
1375 /* C:\. */
1376 OffsetSrc++; LenSrc--; bModifyed = TRUE;
1377 }
1378 else if (LenSrc == 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='.')
1379 {
1380 /* C:\.. */
1381 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1382 }
1383 }
1384 }
1385
1386 /* ".\" at the beginning of the path */
1387 if (LenSrc >= 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='\\')
1388 {
1389 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1390 }
1391
1392 while ( LenSrc )
1393 {
1394 if((LenSrc>=3) && (pszPath[OffsetSrc]=='\\') && (pszPath[OffsetSrc+1]=='.') && (pszPath[OffsetSrc+2]=='.'))
1395 {
1396 /* "\.." found, go one deeper */
1397 while((OffsetDst > OffsetMin) && (pszBuf[OffsetDst]!='\\')) OffsetDst--;
1398 OffsetSrc += 3; LenSrc -= 3; bModifyed = TRUE;
1399 if(OffsetDst == OffsetMin && pszPath[OffsetSrc]=='\\') OffsetSrc++;
1400 pszBuf[OffsetDst] = '\0'; /* important for \..\.. */
1401 }
1402 else if(LenSrc>=2 && pszPath[OffsetSrc]=='\\' && pszPath[OffsetSrc+1]=='.' )
1403 {
1404 /* "\." found, skip it */
1405 OffsetSrc += 2; LenSrc-=2; bModifyed = TRUE;
1406 }
1407 else
1408 {
1409 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; LenSrc--;
1410 }
1411 }
1412 pszBuf[OffsetDst] = '\0';
1413 TRACE("-- %s %u\n", pszBuf, bModifyed);
1414 return bModifyed;
1415}
1416
1417
1418/*************************************************************************
1419 * PathCanonicalizeW [SHLWAPI.@]
1420 *
1421 * FIXME
1422 * returnvalue, use CharNext
1423 */
1424BOOL WINAPI PathCanonicalizeW(LPWSTR pszBuf, LPCWSTR pszPath)
1425{
1426 int OffsetMin = 0, OffsetSrc = 0, OffsetDst = 0, LenSrc = strlenW(pszPath);
1427 BOOL bModifyed = FALSE;
1428
1429 TRACE("%p %s\n", pszBuf, debugstr_w(pszPath));
1430
1431 pszBuf[OffsetDst]='\0';
1432
1433 /* keep the root of the path */
1434 if( LenSrc && (pszPath[OffsetSrc]=='\\'))
1435 {
1436 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1437 }
1438 else if ( (LenSrc >= 2) && (pszPath[OffsetSrc+1] == ':'))
1439 {
1440 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1441 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1442 if (LenSrc && (pszPath[OffsetSrc] == '\\'))
1443 {
1444 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1445 if (LenSrc == 1 && pszPath[OffsetSrc]=='.')
1446 {
1447 /* C:\. */
1448 OffsetSrc++; LenSrc--; bModifyed = TRUE;
1449 }
1450 else if (LenSrc == 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='.')
1451 {
1452 /* C:\.. */
1453 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1454 }
1455 }
1456 }
1457
1458 /* ".\" at the beginning of the path */
1459 if (LenSrc >= 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='\\')
1460 {
1461 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1462 }
1463
1464 while ( LenSrc )
1465 {
1466 if((LenSrc>=3) && (pszPath[OffsetSrc]=='\\') && (pszPath[OffsetSrc+1]=='.') && (pszPath[OffsetSrc+2]=='.'))
1467 {
1468 /* "\.." found, go one deeper */
1469 while((OffsetDst > OffsetMin) && (pszBuf[OffsetDst]!='\\')) OffsetDst--;
1470 OffsetSrc += 3; LenSrc -= 3; bModifyed = TRUE;
1471 if(OffsetDst == OffsetMin && pszPath[OffsetSrc]=='\\') OffsetSrc++;
1472 pszBuf[OffsetDst] = '\0'; /* important for \..\.. */
1473 }
1474 else if(LenSrc>=2 && pszPath[OffsetSrc]=='\\' && pszPath[OffsetSrc+1]=='.' )
1475 {
1476 /* "\." found, skip it */
1477 OffsetSrc += 2; LenSrc-=2; bModifyed = TRUE;
1478 }
1479 else
1480 {
1481 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; LenSrc--;
1482 }
1483 }
1484 pszBuf[OffsetDst] = '\0';
1485 TRACE("-- %s %u\n", debugstr_w(pszBuf), bModifyed);
1486 return bModifyed;
1487}
1488
1489/*************************************************************************
1490 * PathFindNextComponentA [SHLWAPI.@]
1491 *
1492 * NOTES
1493 * special cases:
1494 * "" null
1495 * aa "" (pointer to traling NULL)
1496 * aa\ "" (pointer to traling NULL)
1497 * aa\\ "" (pointer to traling NULL)
1498 * aa\\bb bb
1499 * aa\\\bb \bb
1500 * c:\aa\ "aa\"
1501 * \\aa aa
1502 * \\aa\b aa\b
1503*/
1504LPSTR WINAPI PathFindNextComponentA(LPCSTR pszPath)
1505{
1506 LPSTR pos;
1507
1508 TRACE("%s\n", pszPath);
1509
1510 if(!pszPath || !*pszPath) return NULL;
1511 if(!(pos = StrChrA(pszPath, '\\')))
1512 return (LPSTR) pszPath + strlen(pszPath);
1513 pos++;
1514 if(pos[0] == '\\') pos++;
1515 return pos;
1516}
1517
1518/*************************************************************************
1519 * PathFindNextComponentW [SHLWAPI.@]
1520 */
1521LPWSTR WINAPI PathFindNextComponentW(LPCWSTR pszPath)
1522{
1523 LPWSTR pos;
1524
1525 TRACE("%s\n", debugstr_w(pszPath));
1526
1527 if(!pszPath || !*pszPath) return NULL;
1528 if (!(pos = StrChrW(pszPath, '\\')))
1529 return (LPWSTR) pszPath + strlenW(pszPath);
1530 pos++;
1531 if(pos[0] == '\\') pos++;
1532 return pos;
1533}
1534
1535/*************************************************************************
1536 * PathAddExtensionA [SHLWAPI.@]
1537 *
1538 * NOTES
1539 * it adds never a dot
1540 */
1541
1542BOOL WINAPI PathAddExtensionA(
1543 LPSTR pszPath,
1544 LPCSTR pszExtension)
1545{
1546 if (*pszPath)
1547 {
1548 if (*(PathFindExtensionA(pszPath))) return FALSE;
1549
1550 if (!pszExtension || *pszExtension=='\0')
1551 strcat(pszPath, "exe");
1552 else
1553 strcat(pszPath, pszExtension);
1554 }
1555
1556 return TRUE;
1557}
1558
1559/*************************************************************************
1560 * PathAddExtensionW [SHLWAPI.@]
1561 */
1562BOOL WINAPI PathAddExtensionW(
1563 LPWSTR pszPath,
1564 LPCWSTR pszExtension)
1565{
1566 static const WCHAR ext[] = { 'e','x','e',0 };
1567
1568 if (*pszPath)
1569 {
1570 if (*(PathFindExtensionW(pszPath))) return FALSE;
1571
1572 if (!pszExtension || *pszExtension=='\0')
1573 strcatW(pszPath, ext);
1574 else
1575 strcatW(pszPath, pszExtension);
1576 }
1577 return TRUE;
1578
1579}
1580
1581/*************************************************************************
1582 * PathMakePrettyA [SHLWAPI.@]
1583 */
1584BOOL WINAPI PathMakePrettyA(
1585 LPSTR lpPath)
1586{
1587 FIXME("%s\n", lpPath);
1588 return TRUE;
1589}
1590
1591/*************************************************************************
1592 * PathMakePrettyW [SHLWAPI.@]
1593 */
1594BOOL WINAPI PathMakePrettyW(
1595 LPWSTR lpPath)
1596{
1597 FIXME("%s\n", debugstr_w(lpPath));
1598 return TRUE;
1599
1600}
1601
1602/*************************************************************************
1603 * PathCommonPrefixA [SHLWAPI.@]
1604 */
1605int WINAPI PathCommonPrefixA(
1606 LPCSTR pszFile1,
1607 LPCSTR pszFile2,
1608 LPSTR achPath)
1609{
1610 FIXME("%s %s %p\n", pszFile1, pszFile2, achPath);
1611 return 0;
1612}
1613
1614/*************************************************************************
1615 * PathCommonPrefixW [SHLWAPI.@]
1616 */
1617int WINAPI PathCommonPrefixW(
1618 LPCWSTR pszFile1,
1619 LPCWSTR pszFile2,
1620 LPWSTR achPath)
1621{
1622 FIXME("%s %s %p\n", debugstr_w(pszFile1), debugstr_w(pszFile2),achPath );
1623 return 0;
1624}
1625
1626/*************************************************************************
1627 * PathCompactPathA [SHLWAPI.@]
1628 */
1629BOOL WINAPI PathCompactPathA(HDC hDC, LPSTR pszPath, UINT dx)
1630{
1631 FIXME("0x%08x %s 0x%08x\n", hDC, pszPath, dx);
1632 return FALSE;
1633}
1634
1635/*************************************************************************
1636 * PathCompactPathW [SHLWAPI.@]
1637 */
1638BOOL WINAPI PathCompactPathW(HDC hDC, LPWSTR pszPath, UINT dx)
1639{
1640 FIXME("0x%08x %s 0x%08x\n", hDC, debugstr_w(pszPath), dx);
1641 return FALSE;
1642}
1643
1644/*************************************************************************
1645 * PathGetCharTypeA [SHLWAPI.@]
1646 */
1647UINT WINAPI PathGetCharTypeA(UCHAR ch)
1648{
1649 UINT flags = 0;
1650
1651 TRACE("%c\n", ch);
1652
1653 /* We could use them in filenames, but this would confuse 'ls' */
1654 if (iscntrl(ch))
1655 return GCT_INVALID;
1656 if ((ch == '*') || (ch=='?'))
1657 return GCT_WILD;
1658 if ((ch == '\\') || (ch=='/'))
1659 return GCT_SEPARATOR;
1660 flags = 0;
1661 /* all normal characters, no lower case letters */
1662 if ((ch > ' ') && (ch < 0x7f) && !islower(ch))
1663 flags |= GCT_SHORTCHAR;
1664 /* All other characters are valid in long filenames, even umlauts */
1665 return flags | GCT_LFNCHAR;
1666}
1667
1668/*************************************************************************
1669 * PathGetCharTypeW [SHLWAPI.@]
1670 */
1671UINT WINAPI PathGetCharTypeW(WCHAR ch)
1672{
1673 FIXME("%c, using ascii version\n", ch);
1674 return PathGetCharTypeA(ch);
1675}
1676
1677/*************************************************************************
1678 * PathMakeSystemFolderA [SHLWAPI.@]
1679 */
1680BOOL WINAPI PathMakeSystemFolderA(LPCSTR pszPath)
1681{
1682 FIXME("%s\n", pszPath);
1683 return FALSE;
1684}
1685
1686/*************************************************************************
1687 * PathMakeSystemFolderW [SHLWAPI.@]
1688 */
1689BOOL WINAPI PathMakeSystemFolderW(LPCWSTR pszPath)
1690{
1691 FIXME("%s\n", debugstr_w(pszPath));
1692 return FALSE;
1693}
1694
1695/*************************************************************************
1696 * PathRenameExtensionA [SHLWAPI.@]
1697 */
1698BOOL WINAPI PathRenameExtensionA(LPSTR pszPath, LPCSTR pszExt)
1699{
1700 LPSTR pszExtension = PathFindExtensionA(pszPath);
1701
1702 if (!pszExtension) return FALSE;
1703 if (pszExtension-pszPath + strlen(pszExt) > MAX_PATH) return FALSE;
1704
1705 strcpy(pszExtension, pszExt);
1706 TRACE("%s\n", pszPath);
1707 return TRUE;
1708}
1709
1710/*************************************************************************
1711 * PathRenameExtensionW [SHLWAPI.@]
1712 */
1713BOOL WINAPI PathRenameExtensionW(LPWSTR pszPath, LPCWSTR pszExt)
1714{
1715 LPWSTR pszExtension = PathFindExtensionW(pszPath);
1716
1717 if (!pszExtension) return FALSE;
1718 if (pszExtension-pszPath + strlenW(pszExt) > MAX_PATH) return FALSE;
1719
1720 strcpyW(pszExtension, pszExt);
1721 TRACE("%s\n", debugstr_w(pszPath));
1722 return TRUE;
1723}
1724
1725/*************************************************************************
1726 * PathSearchAndQualifyA [SHLWAPI.@]
1727 */
1728BOOL WINAPI PathSearchAndQualifyA(
1729 LPCSTR pszPath,
1730 LPSTR pszBuf,
1731 UINT cchBuf)
1732{
1733 FIXME("%s %s 0x%08x\n", pszPath, pszBuf, cchBuf);
1734 return FALSE;
1735}
1736
1737/*************************************************************************
1738 * PathSearchAndQualifyW [SHLWAPI.@]
1739 */
1740BOOL WINAPI PathSearchAndQualifyW(
1741 LPCWSTR pszPath,
1742 LPWSTR pszBuf,
1743 UINT cchBuf)
1744{
1745 FIXME("%s %s 0x%08x\n", debugstr_w(pszPath), debugstr_w(pszBuf), cchBuf);
1746 return FALSE;
1747}
1748
1749#ifndef __WIN32OS2__
1750/*************************************************************************
1751 * PathSkipRootA [SHLWAPI.@]
1752 */
1753LPSTR WINAPI PathSkipRootA(LPCSTR pszPath)
1754{
1755 FIXME("%s\n", pszPath);
1756 return (LPSTR)pszPath;
1757}
1758
1759/*************************************************************************
1760 * PathSkipRootW [SHLWAPI.@]
1761 */
1762LPWSTR WINAPI PathSkipRootW(LPCWSTR pszPath)
1763{
1764 FIXME("%s\n", debugstr_w(pszPath));
1765 return (LPWSTR)pszPath;
1766}
1767#endif
1768
1769/*************************************************************************
1770 * PathCreateFromUrlA [SHLWAPI.@]
1771 */
1772HRESULT WINAPI PathCreateFromUrlA(
1773 LPCSTR pszUrl,
1774 LPSTR pszPath,
1775 LPDWORD pcchPath,
1776 DWORD dwFlags)
1777{
1778 /* extracts thing prior to : in pszURL and checks against:
1779 * https
1780 * shell
1781 * local
1782 * about - if match returns E_INVALIDARG
1783 */
1784 FIXME("%s %p %p 0x%08lx\n",
1785 pszUrl, pszPath, pcchPath, dwFlags);
1786 return E_INVALIDARG;
1787}
1788
1789/*************************************************************************
1790 * PathCreateFromUrlW [SHLWAPI.@]
1791 */
1792HRESULT WINAPI PathCreateFromUrlW(
1793 LPCWSTR pszUrl,
1794 LPWSTR pszPath,
1795 LPDWORD pcchPath,
1796 DWORD dwFlags)
1797{
1798 /* extracts thing prior to : in pszURL and checks against:
1799 * https
1800 * shell
1801 * local
1802 * about - if match returns E_INVALIDARG
1803 */
1804 FIXME("%s %p %p 0x%08lx\n",
1805 debugstr_w(pszUrl), pszPath, pcchPath, dwFlags);
1806 return E_INVALIDARG;
1807}
1808
1809/*************************************************************************
1810 * PathRelativePathToA [SHLWAPI.@]
1811 */
1812BOOL WINAPI PathRelativePathToA(
1813 LPSTR pszPath,
1814 LPCSTR pszFrom,
1815 DWORD dwAttrFrom,
1816 LPCSTR pszTo,
1817 DWORD dwAttrTo)
1818{
1819 FIXME("%s %s 0x%08lx %s 0x%08lx\n",
1820 pszPath, pszFrom, dwAttrFrom, pszTo, dwAttrTo);
1821 return FALSE;
1822}
1823
1824/*************************************************************************
1825 * PathRelativePathToW [SHLWAPI.@]
1826 */
1827BOOL WINAPI PathRelativePathToW(
1828 LPWSTR pszPath,
1829 LPCWSTR pszFrom,
1830 DWORD dwAttrFrom,
1831 LPCWSTR pszTo,
1832 DWORD dwAttrTo)
1833{
1834 FIXME("%s %s 0x%08lx %s 0x%08lx\n",
1835 debugstr_w(pszPath), debugstr_w(pszFrom), dwAttrFrom, debugstr_w(pszTo), dwAttrTo);
1836 return FALSE;
1837}
1838
1839/*************************************************************************
1840 * PathUnmakeSystemFolderA [SHLWAPI.@]
1841 */
1842BOOL WINAPI PathUnmakeSystemFolderA(LPCSTR pszPath)
1843{
1844 FIXME("%s\n", pszPath);
1845 return FALSE;
1846}
1847
1848/*************************************************************************
1849 * PathUnmakeSystemFolderW [SHLWAPI.@]
1850 */
1851BOOL WINAPI PathUnmakeSystemFolderW(LPCWSTR pszPath)
1852{
1853 FIXME("%s\n", debugstr_w(pszPath));
1854 return FALSE;
1855}
1856
1857/*
1858 ########## special ##########
1859*/
1860
1861/*************************************************************************
1862 * PathSetDlgItemPathA [SHLWAPI.@]
1863 *
1864 * NOTES
1865 * use PathCompactPath to make sure, the path fits into the control
1866 */
1867BOOL WINAPI PathSetDlgItemPathA(HWND hDlg, int id, LPCSTR pszPath)
1868{ TRACE("%x %x %s\n",hDlg, id, pszPath);
1869 return SetDlgItemTextA(hDlg, id, pszPath);
1870}
1871
1872/*************************************************************************
1873 * PathSetDlgItemPathW [SHLWAPI.@]
1874 */
1875BOOL WINAPI PathSetDlgItemPathW(HWND hDlg, int id, LPCWSTR pszPath)
1876{ TRACE("%x %x %s\n",hDlg, id, debugstr_w(pszPath));
1877 return SetDlgItemTextW(hDlg, id, pszPath);
1878}
Note: See TracBrowser for help on using the repository browser.