9 #include "wine/unicode.h"
14 #include "debugtools.h"
17 DEFAULT_DEBUG_CHANNEL(shell);
19 INT __cdecl _wtoi(LPWSTR string);
21 #define isSlash(x) ((x)=='\\' || (x)=='/')
23 ########## Combining and Constructing paths ##########
26 /*************************************************************************
27 * PathAppendA [SHLWAPI.@]
30 * concat path lpszPath2 onto lpszPath1
33 * the resulting path is also canonicalized
35 BOOL WINAPI PathAppendA(
39 TRACE("%s %s\n",lpszPath1, lpszPath2);
40 while (lpszPath2[0]=='\\') lpszPath2++;
41 PathCombineA(lpszPath1,lpszPath1,lpszPath2);
45 /*************************************************************************
46 * PathAppendW [SHLWAPI.@]
48 BOOL WINAPI PathAppendW(
52 TRACE("%s %s\n",debugstr_w(lpszPath1), debugstr_w(lpszPath2));
53 while (lpszPath2[0]=='\\') lpszPath2++;
54 PathCombineW(lpszPath1,lpszPath1,lpszPath2);
58 /*************************************************************************
59 * PathCombineA [SHLWAPI.@]
62 * if lpszFile='.' skip it
63 * szDest can be equal to lpszFile. Thats why we use sTemp
66 * the resulting path is also canonicalized
68 LPSTR WINAPI PathCombineA(
74 TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, lpszDir, lpszFile, lpszFile);
77 if (!lpszFile || !lpszFile[0] || (lpszFile[0]=='.' && !lpszFile[1]) )
79 strcpy(szDest,lpszDir);
83 /* if lpszFile is a complete path don't care about lpszDir */
84 if (PathGetDriveNumberA(lpszFile) != -1)
86 strcpy(szDest,lpszFile);
88 else if (lpszFile[0] == '\\' )
90 strcpy(sTemp,lpszDir);
91 PathStripToRootA(sTemp);
92 strcat(sTemp,lpszFile);
97 strcpy(sTemp,lpszDir);
98 PathAddBackslashA(sTemp);
99 strcat(sTemp,lpszFile);
100 strcpy(szDest,sTemp);
105 /*************************************************************************
106 * PathCombineW [SHLWAPI.@]
108 LPWSTR WINAPI PathCombineW(
113 WCHAR sTemp[MAX_PATH];
114 TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, debugstr_w(lpszDir),
115 lpszFile, debugstr_w(lpszFile));
118 if (!lpszFile || !lpszFile[0] || (lpszFile[0]==(WCHAR)'.' && !lpszFile[1]) )
120 strcpyW(szDest,lpszDir);
124 /* if lpszFile is a complete path don't care about lpszDir */
125 if (PathGetDriveNumberW(lpszFile) != -1)
127 strcpyW(szDest,lpszFile);
129 else if (lpszFile[0] == (WCHAR)'\\' )
131 strcpyW(sTemp,lpszDir);
132 PathStripToRootW(sTemp);
133 strcatW(sTemp,lpszFile);
134 strcpyW(szDest,sTemp);
138 strcpyW(sTemp,lpszDir);
139 PathAddBackslashW(sTemp);
140 strcatW(sTemp,lpszFile);
141 strcpyW(szDest,sTemp);
146 /*************************************************************************
147 * PathAddBackslashA [SHLWAPI.@]
150 * append \ if there is none
152 LPSTR WINAPI PathAddBackslashA(LPSTR lpszPath)
155 TRACE("%p->%s\n",lpszPath,lpszPath);
157 len = strlen(lpszPath);
158 if (len && lpszPath[len-1]!='\\')
160 lpszPath[len] = '\\';
161 lpszPath[len+1]= 0x00;
162 return lpszPath+len+1;
167 /*************************************************************************
168 * PathAddBackslashW [SHLWAPI.@]
170 LPWSTR WINAPI PathAddBackslashW(LPWSTR lpszPath)
173 TRACE("%p->%s\n",lpszPath,debugstr_w(lpszPath));
175 len = strlenW(lpszPath);
176 if (len && lpszPath[len-1]!=(WCHAR)'\\')
178 lpszPath[len] = (WCHAR)'\\';
179 lpszPath[len+1]= 0x00;
180 return lpszPath+len+1;
185 /*************************************************************************
186 * PathBuildRootA [SHLWAPI.@]
188 LPSTR WINAPI PathBuildRootA(LPSTR lpszPath, int drive)
190 TRACE("%p %i\n",lpszPath, drive);
192 strcpy(lpszPath,"A:\\");
197 /*************************************************************************
198 * PathBuildRootW [SHLWAPI.@]
200 LPWSTR WINAPI PathBuildRootW(LPWSTR lpszPath, int drive)
202 lpszPath[0] = 'A' + drive;
206 TRACE("%p %i\n",debugstr_w(lpszPath), drive);
211 Extracting Component Parts
214 /*************************************************************************
215 * PathFindFileNameA [SHLWAPI.@]
217 LPSTR WINAPI PathFindFileNameA(LPCSTR lpszPath)
219 LPCSTR lastSlash = lpszPath;
221 TRACE("%s\n",lpszPath);
224 if ( isSlash(lpszPath[0]) && lpszPath[1])
225 lastSlash = lpszPath+1;
226 lpszPath = CharNextA(lpszPath);
228 return (LPSTR)lastSlash;
232 /*************************************************************************
233 * PathFindFileNameW [SHLWAPI.@]
235 LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
240 TRACE("%s\n",debugstr_w(wslash));
243 if (((lpszPath[0]=='\\') || (lpszPath[0]==':')) && lpszPath[1] && lpszPath[1]!='\\')
245 lpszPath = CharNextW(lpszPath);
247 return (LPWSTR)wslash;
250 /*************************************************************************
251 * PathFindExtensionA [SHLWAPI.@]
254 * returns pointer to last . in last lpszPath component or at \0.
257 LPSTR WINAPI PathFindExtensionA(LPCSTR lpszPath)
259 LPCSTR lastpoint = NULL;
261 TRACE("%p %s\n",lpszPath,lpszPath);
265 if (*lpszPath=='\\'||*lpszPath==' ')
269 lpszPath = CharNextA(lpszPath);
271 return (LPSTR)(lastpoint?lastpoint:lpszPath);
274 /*************************************************************************
275 * PathFindExtensionW [SHLWAPI.@]
277 LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath)
279 LPCWSTR lastpoint = NULL;
281 TRACE("(%p %s)\n",lpszPath,debugstr_w(lpszPath));
285 if (*lpszPath==(WCHAR)'\\'||*lpszPath==(WCHAR)' ')
287 if (*lpszPath==(WCHAR)'.')
289 lpszPath = CharNextW(lpszPath);
291 return (LPWSTR)(lastpoint?lastpoint:lpszPath);
294 /*************************************************************************
295 * PathGetArgsA [SHLWAPI.@]
298 * look for next arg in string. handle "quoted" strings
299 * returns pointer to argument *AFTER* the space. Or to the \0.
304 LPSTR WINAPI PathGetArgsA(LPCSTR lpszPath)
308 TRACE("%s\n",lpszPath);
312 if ((*lpszPath==' ') && !qflag)
313 return (LPSTR)lpszPath+1;
316 lpszPath = CharNextA(lpszPath);
318 return (LPSTR)lpszPath;
321 /*************************************************************************
322 * PathGetArgsW [SHLWAPI.@]
324 LPWSTR WINAPI PathGetArgsW(LPCWSTR lpszPath)
328 TRACE("%s\n",debugstr_w(lpszPath));
332 if ((*lpszPath==' ') && !qflag)
333 return (LPWSTR)lpszPath+1;
336 lpszPath = CharNextW(lpszPath);
338 return (LPWSTR)lpszPath;
341 /*************************************************************************
342 * PathGetDriveNumberA [SHLWAPI.@]
344 int WINAPI PathGetDriveNumberA(LPCSTR lpszPath)
346 int chr = tolower(lpszPath[0]);
348 TRACE ("%s\n",debugstr_a(lpszPath));
350 if (!lpszPath || lpszPath[1]!=':' || chr < 'a' || chr > 'z') return -1;
351 return tolower(lpszPath[0]) - 'a' ;
354 /*************************************************************************
355 * PathGetDriveNumberW [SHLWAPI.@]
357 int WINAPI PathGetDriveNumberW(LPCWSTR lpszPath)
359 int chr = tolowerW(lpszPath[0]);
361 TRACE ("%s\n",debugstr_w(lpszPath));
363 if (!lpszPath || lpszPath[1]!=':' || chr < 'a' || chr > 'z') return -1;
364 return tolowerW(lpszPath[0]) - 'a' ;
367 /*************************************************************************
368 * PathRemoveFileSpecA [SHLWAPI.@]
371 * truncates passed argument to a valid path
372 * returns if the string was modified or not.
373 * "\foo\xx\foo"-> "\foo\xx"
377 BOOL WINAPI PathRemoveFileSpecA(LPSTR lpszPath)
379 LPSTR cutplace = lpszPath;
382 TRACE("%s\n",lpszPath);
386 while (*lpszPath == '\\') cutplace = ++lpszPath;
390 if(lpszPath[0] == '\\') cutplace = lpszPath;
392 if(lpszPath[0] == ':')
394 cutplace = lpszPath + 1;
395 if (lpszPath[1] == '\\') cutplace++;
398 lpszPath = CharNextA(lpszPath);
399 if (!lpszPath) break;
402 ret = (*cutplace!='\0');
408 /*************************************************************************
409 * PathRemoveFileSpecW [SHLWAPI.@]
411 BOOL WINAPI PathRemoveFileSpecW(LPWSTR lpszPath)
413 LPWSTR cutplace = lpszPath;
416 TRACE("%s\n",debugstr_w(lpszPath));
420 while (*lpszPath == '\\') cutplace = ++lpszPath;
424 if(lpszPath[0] == '\\') cutplace = lpszPath;
426 if(lpszPath[0] == ':')
428 cutplace = lpszPath + 1;
429 if (lpszPath[1] == '\\') cutplace++;
432 lpszPath = CharNextW(lpszPath);
433 if (!lpszPath) break;
436 ret = (*cutplace!='\0');
442 /*************************************************************************
443 * PathStripPathA [SHLWAPI.@]
446 * removes the path from the beginning of a filename
448 void WINAPI PathStripPathA(LPSTR lpszPath)
450 LPSTR lpszFileName = PathFindFileNameA(lpszPath);
452 TRACE("%s\n", lpszPath);
455 RtlMoveMemory(lpszPath, lpszFileName, strlen(lpszFileName)+1);
458 /*************************************************************************
459 * PathStripPathW [SHLWAPI.@]
461 void WINAPI PathStripPathW(LPWSTR lpszPath)
463 LPWSTR lpszFileName = PathFindFileNameW(lpszPath);
465 TRACE("%s\n", debugstr_w(lpszPath));
467 RtlMoveMemory(lpszPath, lpszFileName, (strlenW(lpszFileName)+1)*sizeof(WCHAR));
470 /*************************************************************************
471 * PathStripToRootA [SHLWAPI.@]
473 BOOL WINAPI PathStripToRootA(LPSTR lpszPath)
475 TRACE("%s\n", lpszPath);
477 if (!lpszPath) return FALSE;
478 while(!PathIsRootA(lpszPath))
479 if (!PathRemoveFileSpecA(lpszPath)) return FALSE;
483 /*************************************************************************
484 * PathStripToRootW [SHLWAPI.@]
486 BOOL WINAPI PathStripToRootW(LPWSTR lpszPath)
488 TRACE("%s\n", debugstr_w(lpszPath));
490 if (!lpszPath) return FALSE;
491 while(!PathIsRootW(lpszPath))
492 if (!PathRemoveFileSpecW(lpszPath)) return FALSE;
496 /*************************************************************************
497 * PathRemoveArgsA [SHLWAPI.@]
500 void WINAPI PathRemoveArgsA(LPSTR lpszPath)
502 TRACE("%s\n",lpszPath);
506 LPSTR lpszArgs = PathGetArgsA(lpszPath);
509 LPSTR lpszLastChar = CharPrevA(lpszPath, lpszArgs);
510 if(*lpszLastChar==' ') *lpszLastChar = '\0';
515 /*************************************************************************
516 * PathRemoveArgsW [SHLWAPI.@]
518 void WINAPI PathRemoveArgsW(LPWSTR lpszPath)
520 TRACE("%s\n", debugstr_w(lpszPath));
524 LPWSTR lpszArgs = PathGetArgsW(lpszPath);
527 LPWSTR lpszLastChar = CharPrevW(lpszPath, lpszArgs);
528 if(*lpszLastChar==' ') *lpszLastChar = '\0';
533 /*************************************************************************
534 * PathRemoveExtensionA [SHLWAPI.@]
536 void WINAPI PathRemoveExtensionA(LPSTR lpszPath)
538 LPSTR lpszExtension = PathFindExtensionA(lpszPath);
540 TRACE("%s\n", lpszPath);
542 if (lpszExtension) *lpszExtension='\0';
545 /*************************************************************************
546 * PathRemoveExtensionW [SHLWAPI.@]
548 void WINAPI PathRemoveExtensionW(LPWSTR lpszPath)
550 LPWSTR lpszExtension = PathFindExtensionW(lpszPath);
552 TRACE("%s\n", debugstr_w(lpszPath));
554 if (lpszExtension) *lpszExtension='\0';
557 /*************************************************************************
558 * PathRemoveBackslashA [SHLWAPI.@]
560 * If the path ends in a backslash it is replaced by a NULL
561 * and the address of the NULL is returned
563 * the address of the last character is returned.
566 * "c:\": keep backslash
568 LPSTR WINAPI PathRemoveBackslashA( LPSTR lpszPath )
575 len = strlen(lpszPath);
576 szTemp = CharPrevA(lpszPath, lpszPath+len);
577 if (! PathIsRootA(lpszPath))
579 if (*szTemp == '\\') *szTemp = '\0';
585 /*************************************************************************
586 * PathRemoveBackslashW [SHLWAPI.@]
588 LPWSTR WINAPI PathRemoveBackslashW( LPWSTR lpszPath )
591 LPWSTR szTemp = NULL;
595 len = strlenW(lpszPath);
596 szTemp = CharPrevW(lpszPath, lpszPath+len);
597 if (! PathIsRootW(lpszPath))
599 if (*szTemp == '\\') *szTemp = '\0';
610 /*************************************************************************
611 * PathRemoveBlanksA [SHLWAPI.@]
614 * remove spaces from beginning and end of passed string
616 void WINAPI PathRemoveBlanksA(LPSTR str)
624 while (*x==' ') x = CharNextA(x);
625 if (x!=str) strcpy(str,x);
627 while (*x==' ') x = CharPrevA(str, x);
628 if (*x==' ') *x='\0';
632 /*************************************************************************
633 * PathRemoveBlanksW [SHLWAPI.@]
635 void WINAPI PathRemoveBlanksW(LPWSTR str)
639 TRACE("%s\n",debugstr_w(str));
643 while (*x==' ') x = CharNextW(x);
644 if (x!=str) strcpyW(str,x);
645 x=str+strlenW(str)-1;
646 while (*x==' ') x = CharPrevW(str, x);
647 if (*x==' ') *x='\0';
651 /*************************************************************************
652 * PathQuoteSpacesA [SHLWAPI.@]
655 LPSTR WINAPI PathQuoteSpacesA(LPSTR lpszPath)
657 TRACE("%s\n",lpszPath);
659 if(StrChrA(lpszPath,' '))
661 int len = strlen(lpszPath);
662 RtlMoveMemory(lpszPath+1, lpszPath, len);
672 /*************************************************************************
673 * PathQuoteSpacesW [SHLWAPI.@]
675 LPWSTR WINAPI PathQuoteSpacesW(LPWSTR lpszPath)
677 TRACE("%s\n",debugstr_w(lpszPath));
679 if(StrChrW(lpszPath,' '))
681 int len = strlenW(lpszPath);
682 RtlMoveMemory(lpszPath+1, lpszPath, len*sizeof(WCHAR));
692 /*************************************************************************
693 * PathUnquoteSpacesA [SHLWAPI.@]
696 * unquote string (remove ")
698 VOID WINAPI PathUnquoteSpacesA(LPSTR str)
700 DWORD len = strlen(str);
713 /*************************************************************************
714 * PathUnquoteSpacesW [SHLWAPI.@]
716 VOID WINAPI PathUnquoteSpacesW(LPWSTR str)
718 DWORD len = strlenW(str);
720 TRACE("%s\n",debugstr_w(str));
731 /*************************************************************************
732 * PathParseIconLocationA [SHLWAPI.@]
734 int WINAPI PathParseIconLocationA(LPSTR lpszPath)
736 LPSTR lpstrComma = strchr(lpszPath, ',');
739 TRACE("%s\n", debugstr_a(lpszPath));
741 if (lpstrComma && lpstrComma[1])
744 ret = atoi(&lpstrComma[1]);
747 PathUnquoteSpacesA(lpszPath);
751 /*************************************************************************
752 * PathParseIconLocationW [SHLWAPI.@]
754 int WINAPI PathParseIconLocationW(LPWSTR lpszPath)
756 LPWSTR lpstrComma = strchrW(lpszPath, ',');
759 TRACE("%s\n", debugstr_w(lpszPath));
761 if (lpstrComma && lpstrComma[1])
764 ret = _wtoi(&lpstrComma[1]);
766 PathUnquoteSpacesW(lpszPath);
771 ########## cleaning and resolving paths ##########
774 /*************************************************************************
775 * PathFindOnPathA [SHLWAPI.@]
777 BOOL WINAPI PathFindOnPathA(LPSTR sFile, LPCSTR sOtherDirs)
779 FIXME("%s %s\n",sFile, sOtherDirs);
783 /*************************************************************************
784 * PathFindOnPathW [SHLWAPI.@]
786 BOOL WINAPI PathFindOnPathW(LPWSTR sFile, LPCWSTR sOtherDirs)
788 FIXME("%s %s\n",debugstr_w(sFile), debugstr_w(sOtherDirs));
792 /*************************************************************************
793 * PathCompactPathExA [SHLWAPI.@]
795 BOOL WINAPI PathCompactPathExA(
801 FIXME("%p %s 0x%08x 0x%08lx\n", pszOut, pszSrc, cchMax, dwFlags);
805 /*************************************************************************
806 * PathCompactPathExW [SHLWAPI.@]
808 BOOL WINAPI PathCompactPathExW(
814 FIXME("%p %s 0x%08x 0x%08lx\n", pszOut, debugstr_w(pszSrc), cchMax, dwFlags);
819 ########## Path Testing ##########
822 /*************************************************************************
823 * PathIsUNCA [SHLWAPI.@]
826 * PathIsUNC(char*path);
828 BOOL WINAPI PathIsUNCA(LPCSTR lpszPath)
830 TRACE("%s\n",lpszPath);
832 return (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\'));
835 /*************************************************************************
836 * PathIsUNCW [SHLWAPI.@]
838 BOOL WINAPI PathIsUNCW(LPCWSTR lpszPath)
840 TRACE("%s\n",debugstr_w(lpszPath));
842 return (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\'));
845 /*************************************************************************
846 * PathIsRelativeA [SHLWAPI.@]
848 BOOL WINAPI PathIsRelativeA (LPCSTR lpszPath)
850 TRACE("lpszPath=%s\n",lpszPath);
852 return (lpszPath && (lpszPath[0]!='\\' && lpszPath[1]!=':'));
855 /*************************************************************************
856 * PathIsRelativeW [SHLWAPI.@]
858 BOOL WINAPI PathIsRelativeW (LPCWSTR lpszPath)
860 TRACE("lpszPath=%s\n",debugstr_w(lpszPath));
862 return (lpszPath && (lpszPath[0]!='\\' && lpszPath[1]!=':'));
865 /*************************************************************************
866 * PathIsRootA [SHLWAPI.@]
869 * TRUE if the path points to a root directory
871 BOOL WINAPI PathIsRootA(LPCSTR lpszPath)
873 TRACE("%s\n",lpszPath);
876 if (lpszPath[1]==':' && lpszPath[2]=='\\' && lpszPath[3]=='\0')
880 if (lpszPath[0]=='\\' && lpszPath[1]=='\0')
883 /* UNC "\\<computer>\<share>" */
884 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
886 int foundbackslash = 0;
890 if (*lpszPath=='\\') foundbackslash++;
891 lpszPath = CharNextA(lpszPath);
893 if (foundbackslash <= 1)
899 /*************************************************************************
900 * PathIsRootW [SHLWAPI.@]
902 BOOL WINAPI PathIsRootW(LPCWSTR lpszPath)
904 TRACE("%s\n",debugstr_w(lpszPath));
907 if (lpszPath[1]==':' && lpszPath[2]=='\\' && lpszPath[3]=='\0')
911 if (lpszPath[0]=='\\' && lpszPath[1]=='\0')
914 /* UNC "\\<computer>\<share>" */
915 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
917 int foundbackslash = 0;
921 if (*lpszPath=='\\') foundbackslash++;
922 lpszPath = CharNextW(lpszPath);
924 if (foundbackslash <= 1)
931 /*************************************************************************
932 * PathIsDirectoryA [SHLWAPI.@]
934 BOOL WINAPI PathIsDirectoryA(LPCSTR lpszPath)
938 TRACE("%s\n", debugstr_a(lpszPath));
940 dwAttr = GetFileAttributesA(lpszPath);
941 return (dwAttr != -1) ? dwAttr & FILE_ATTRIBUTE_DIRECTORY : 0;
944 /*************************************************************************
945 * PathIsDirectoryW [SHLWAPI.@]
947 BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath)
951 TRACE("%s\n", debugstr_w(lpszPath));
953 dwAttr = GetFileAttributesW(lpszPath);
954 return (dwAttr != -1) ? dwAttr & FILE_ATTRIBUTE_DIRECTORY : 0;
957 /*************************************************************************
958 * PathFileExistsA [SHLWAPI.@]
961 * file_exists(char *fn);
963 BOOL WINAPI PathFileExistsA(LPCSTR lpszPath)
965 TRACE("%s\n",lpszPath);
966 return (GetFileAttributesA(lpszPath)!=-1);
969 /*************************************************************************
970 * PathFileExistsW [SHLWAPI.@]
972 BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
974 TRACE("%s\n",debugstr_w(lpszPath));
975 return (GetFileAttributesW(lpszPath)!=-1);
978 /*************************************************************************
979 * PathMatchSingleMaskA [internal]
982 * internal (used by PathMatchSpec)
984 static BOOL PathMatchSingleMaskA(LPCSTR name, LPCSTR mask)
986 while (*name && *mask && *mask!=';')
992 if (PathMatchSingleMaskA(name,mask+1)) return 1; /* try substrings */
996 if (toupper(*mask)!=toupper(*name) && *mask!='?') return 0;
997 name = CharNextA(name);
998 mask = CharNextA(mask);
1002 while (*mask=='*') mask++;
1003 if (!*mask || *mask==';') return 1;
1008 /*************************************************************************
1009 * PathMatchSingleMaskW [internal]
1011 static BOOL PathMatchSingleMaskW(LPCWSTR name, LPCWSTR mask)
1013 while (*name && *mask && *mask!=';')
1019 if (PathMatchSingleMaskW(name,mask+1)) return 1; /* try substrings */
1023 if (toupperW(*mask)!=toupperW(*name) && *mask!='?') return 0;
1024 name = CharNextW(name);
1025 mask = CharNextW(mask);
1029 while (*mask=='*') mask++;
1030 if (!*mask || *mask==';') return 1;
1034 /*************************************************************************
1035 * PathMatchSpecA [SHLWAPI.@]
1038 * used from COMDLG32
1040 BOOL WINAPI PathMatchSpecA(LPCSTR name, LPCSTR mask)
1042 TRACE("%s %s\n",name,mask);
1044 if (!lstrcmpA( mask, "*.*" )) return 1; /* we don't require a period */
1048 if (PathMatchSingleMaskA(name,mask)) return 1; /* helper function */
1049 while (*mask && *mask!=';') mask = CharNextA(mask);
1053 while (*mask==' ') mask++; /* masks may be separated by "; " */
1059 /*************************************************************************
1060 * PathMatchSpecW [SHLWAPI.@]
1062 BOOL WINAPI PathMatchSpecW(LPCWSTR name, LPCWSTR mask)
1064 static const WCHAR stemp[] = { '*','.','*',0 };
1065 TRACE("%s %s\n",debugstr_w(name),debugstr_w(mask));
1067 if (!lstrcmpW( mask, stemp )) return 1; /* we don't require a period */
1071 if (PathMatchSingleMaskW(name,mask)) return 1; /* helper function */
1072 while (*mask && *mask!=';') mask = CharNextW(mask);
1076 while (*mask==' ') mask++; /* masks may be separated by "; " */
1082 /*************************************************************************
1083 * PathIsSameRootA [SHLWAPI.@]
1086 * what to do with "\path" ??
1088 BOOL WINAPI PathIsSameRootA(LPCSTR lpszPath1, LPCSTR lpszPath2)
1090 TRACE("%s %s\n", lpszPath1, lpszPath2);
1092 if (PathIsRelativeA(lpszPath1) || PathIsRelativeA(lpszPath2)) return FALSE;
1095 if ( toupper(lpszPath1[0])==toupper(lpszPath2[0]) &&
1096 lpszPath1[1]==':' && lpszPath2[1]==':' &&
1097 lpszPath1[2]=='\\' && lpszPath2[2]=='\\')
1101 if (lpszPath1[0]=='\\' && lpszPath2[0]=='\\' &&
1102 lpszPath1[1]=='\\' && lpszPath2[1]=='\\')
1104 int pos=2, bsfound=0;
1105 while (lpszPath1[pos] && lpszPath2[pos] &&
1106 (lpszPath1[pos] == lpszPath2[pos]))
1108 if (lpszPath1[pos]=='\\') bsfound++;
1109 if (bsfound == 2) return TRUE;
1110 pos++; /* fixme: use CharNext*/
1112 return (lpszPath1[pos] == lpszPath2[pos]);
1117 /*************************************************************************
1118 * PathIsSameRootW [SHLWAPI.@]
1120 BOOL WINAPI PathIsSameRootW(LPCWSTR lpszPath1, LPCWSTR lpszPath2)
1122 TRACE("%s %s\n", debugstr_w(lpszPath1), debugstr_w(lpszPath2));
1124 if (PathIsRelativeW(lpszPath1) || PathIsRelativeW(lpszPath2)) return FALSE;
1127 if ( toupperW(lpszPath1[0])==toupperW(lpszPath2[0]) &&
1128 lpszPath1[1]==':' && lpszPath2[1]==':' &&
1129 lpszPath1[2]=='\\' && lpszPath2[2]=='\\')
1133 if (lpszPath1[0]=='\\' && lpszPath2[0]=='\\' &&
1134 lpszPath1[1]=='\\' && lpszPath2[1]=='\\')
1136 int pos=2, bsfound=0;
1137 while (lpszPath1[pos] && lpszPath2[pos] &&
1138 (lpszPath1[pos] == lpszPath2[pos]))
1140 if (lpszPath1[pos]=='\\') bsfound++;
1141 if (bsfound == 2) return TRUE;
1142 pos++;/* fixme: use CharNext*/
1144 return (lpszPath1[pos] == lpszPath2[pos]);
1149 /*************************************************************************
1150 * PathIsURLA (SHLWAPI.@)
1152 BOOL WINAPI PathIsURLA(LPCSTR lpstrPath)
1156 static LPSTR SupportedProtocol[] =
1157 {"http","https","ftp","gopher","file","mailto",NULL};
1159 if(!lpstrPath) return FALSE;
1162 lpstrRes = strchr(lpstrPath,':');
1163 if(!lpstrRes) return FALSE;
1164 iSize = lpstrRes - lpstrPath;
1166 while(SupportedProtocol[i])
1168 if (iSize == strlen(SupportedProtocol[i]))
1169 if(!strncasecmp(lpstrPath, SupportedProtocol[i], iSize))
1177 /*************************************************************************
1178 * PathIsURLW (SHLWAPI.@)
1180 BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
1184 static WCHAR SupportedProtocol[7][7] =
1185 {{'h','t','t','p','\0'},{'h','t','t','p','s','\0'},{'f','t','p','\0'},
1186 {'g','o','p','h','e','r','\0'},{'f','i','l','e','\0'},
1187 {'m','a','i','l','t','o','\0'},{0}};
1189 if(!lpstrPath) return FALSE;
1192 lpstrRes = strchrW(lpstrPath,':');
1193 if(!lpstrRes) return FALSE;
1194 iSize = lpstrRes - lpstrPath;
1196 while(SupportedProtocol[i])
1198 if (iSize == strlenW(SupportedProtocol[i]))
1199 if(!strncmpiW(lpstrPath, SupportedProtocol[i], iSize))
1208 /*************************************************************************
1209 * PathIsContentTypeA [SHLWAPI.@]
1211 BOOL WINAPI PathIsContentTypeA(LPCSTR pszPath, LPCSTR pszContentType)
1213 FIXME("%s %s\n", pszPath, pszContentType);
1217 /*************************************************************************
1218 * PathIsContentTypeW [SHLWAPI.@]
1220 BOOL WINAPI PathIsContentTypeW(LPCWSTR pszPath, LPCWSTR pszContentType)
1222 FIXME("%s %s\n", debugstr_w(pszPath), debugstr_w(pszContentType));
1226 /*************************************************************************
1227 * PathIsFileSpecA [SHLWAPI.@]
1229 BOOL WINAPI PathIsFileSpecA(LPCSTR pszPath)
1231 FIXME("%s\n", pszPath);
1235 /*************************************************************************
1236 * PathIsFileSpecW [SHLWAPI.@]
1238 BOOL WINAPI PathIsFileSpecW(LPCWSTR pszPath)
1240 FIXME("%s\n", debugstr_w(pszPath));
1244 /*************************************************************************
1245 * PathIsPrefixA [SHLWAPI.@]
1247 BOOL WINAPI PathIsPrefixA(LPCSTR pszPrefix, LPCSTR pszPath)
1249 FIXME("%s %s\n", pszPrefix, pszPath);
1253 /*************************************************************************
1254 * PathIsPrefixW [SHLWAPI.@]
1256 BOOL WINAPI PathIsPrefixW(LPCWSTR pszPrefix, LPCWSTR pszPath)
1258 FIXME("%s %s\n", debugstr_w(pszPrefix), debugstr_w(pszPath));
1262 /*************************************************************************
1263 * PathIsSystemFolderA [SHLWAPI.@]
1265 BOOL WINAPI PathIsSystemFolderA(LPCSTR pszPath, DWORD dwAttrb)
1267 FIXME("%s 0x%08lx\n", pszPath, dwAttrb);
1271 /*************************************************************************
1272 * PathIsSystemFolderW [SHLWAPI.@]
1274 BOOL WINAPI PathIsSystemFolderW(LPCWSTR pszPath, DWORD dwAttrb)
1276 FIXME("%s 0x%08lx\n", debugstr_w(pszPath), dwAttrb);
1280 /*************************************************************************
1281 * PathIsUNCServerA [SHLWAPI.@]
1283 BOOL WINAPI PathIsUNCServerA(
1286 TRACE("%s\n", debugstr_a(lpszPath));
1287 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
1289 int foundbackslash = 0;
1293 if (*lpszPath=='\\') foundbackslash++;
1294 lpszPath = CharNextA(lpszPath);
1296 if (foundbackslash == 0)
1302 /*************************************************************************
1303 * PathIsUNCServerW [SHLWAPI.@]
1305 BOOL WINAPI PathIsUNCServerW(
1308 TRACE("%s\n", debugstr_w(lpszPath));
1309 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
1311 int foundbackslash = 0;
1315 if (*lpszPath=='\\') foundbackslash++;
1316 lpszPath = CharNextW(lpszPath);
1318 if (foundbackslash == 0)
1324 /*************************************************************************
1325 * PathIsUNCServerShareA [SHLWAPI.@]
1327 BOOL WINAPI PathIsUNCServerShareA(
1330 TRACE("%s\n", debugstr_a(lpszPath));
1331 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
1333 int foundbackslash = 0;
1337 if (*lpszPath=='\\') foundbackslash++;
1338 lpszPath = CharNextA(lpszPath);
1340 if (foundbackslash == 1)
1346 /*************************************************************************
1347 * PathIsUNCServerShareW [SHLWAPI.@]
1349 BOOL WINAPI PathIsUNCServerShareW(
1352 TRACE("%s\n", debugstr_w(lpszPath));
1353 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
1355 int foundbackslash = 0;
1359 if (*lpszPath=='\\') foundbackslash++;
1360 lpszPath = CharNextW(lpszPath);
1362 if (foundbackslash == 1)
1368 /*************************************************************************
1369 * PathCanonicalizeA [SHLWAPI.@]
1372 * returnvalue, use CharNext
1375 BOOL WINAPI PathCanonicalizeA(LPSTR pszBuf, LPCSTR pszPath)
1377 int OffsetMin = 0, OffsetSrc = 0, OffsetDst = 0, LenSrc = strlen(pszPath);
1378 BOOL bModifyed = FALSE;
1380 TRACE("%p %s\n", pszBuf, pszPath);
1382 pszBuf[OffsetDst]='\0';
1384 /* keep the root of the path */
1385 if( LenSrc && (pszPath[OffsetSrc]=='\\'))
1387 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1389 else if ( (LenSrc >= 2) && (pszPath[OffsetSrc+1] == ':'))
1391 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1392 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1393 if (LenSrc && (pszPath[OffsetSrc] == '\\'))
1395 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1396 if (LenSrc == 1 && pszPath[OffsetSrc]=='.')
1399 OffsetSrc++; LenSrc--; bModifyed = TRUE;
1401 else if (LenSrc == 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='.')
1404 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1409 /* ".\" at the beginning of the path */
1410 if (LenSrc >= 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='\\')
1412 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1417 if((LenSrc>=3) && (pszPath[OffsetSrc]=='\\') && (pszPath[OffsetSrc+1]=='.') && (pszPath[OffsetSrc+2]=='.'))
1419 /* "\.." found, go one deeper */
1420 while((OffsetDst > OffsetMin) && (pszBuf[OffsetDst]!='\\')) OffsetDst--;
1421 OffsetSrc += 3; LenSrc -= 3; bModifyed = TRUE;
1422 if(OffsetDst == OffsetMin && pszPath[OffsetSrc]=='\\') OffsetSrc++;
1423 pszBuf[OffsetDst] = '\0'; /* important for \..\.. */
1425 else if(LenSrc>=2 && pszPath[OffsetSrc]=='\\' && pszPath[OffsetSrc+1]=='.' )
1427 /* "\." found, skip it */
1428 OffsetSrc += 2; LenSrc-=2; bModifyed = TRUE;
1432 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; LenSrc--;
1435 pszBuf[OffsetDst] = '\0';
1436 TRACE("-- %s %u\n", pszBuf, bModifyed);
1441 /*************************************************************************
1442 * PathCanonicalizeW [SHLWAPI.@]
1445 * returnvalue, use CharNext
1447 BOOL WINAPI PathCanonicalizeW(LPWSTR pszBuf, LPCWSTR pszPath)
1449 int OffsetMin = 0, OffsetSrc = 0, OffsetDst = 0, LenSrc = strlenW(pszPath);
1450 BOOL bModifyed = FALSE;
1452 TRACE("%p %s\n", pszBuf, debugstr_w(pszPath));
1454 pszBuf[OffsetDst]='\0';
1456 /* keep the root of the path */
1457 if( LenSrc && (pszPath[OffsetSrc]=='\\'))
1459 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1461 else if ( (LenSrc >= 2) && (pszPath[OffsetSrc+1] == ':'))
1463 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1464 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1465 if (LenSrc && (pszPath[OffsetSrc] == '\\'))
1467 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1468 if (LenSrc == 1 && pszPath[OffsetSrc]=='.')
1471 OffsetSrc++; LenSrc--; bModifyed = TRUE;
1473 else if (LenSrc == 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='.')
1476 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1481 /* ".\" at the beginning of the path */
1482 if (LenSrc >= 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='\\')
1484 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1489 if((LenSrc>=3) && (pszPath[OffsetSrc]=='\\') && (pszPath[OffsetSrc+1]=='.') && (pszPath[OffsetSrc+2]=='.'))
1491 /* "\.." found, go one deeper */
1492 while((OffsetDst > OffsetMin) && (pszBuf[OffsetDst]!='\\')) OffsetDst--;
1493 OffsetSrc += 3; LenSrc -= 3; bModifyed = TRUE;
1494 if(OffsetDst == OffsetMin && pszPath[OffsetSrc]=='\\') OffsetSrc++;
1495 pszBuf[OffsetDst] = '\0'; /* important for \..\.. */
1497 else if(LenSrc>=2 && pszPath[OffsetSrc]=='\\' && pszPath[OffsetSrc+1]=='.' )
1499 /* "\." found, skip it */
1500 OffsetSrc += 2; LenSrc-=2; bModifyed = TRUE;
1504 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; LenSrc--;
1507 pszBuf[OffsetDst] = '\0';
1508 TRACE("-- %s %u\n", debugstr_w(pszBuf), bModifyed);
1512 /*************************************************************************
1513 * PathFindNextComponentA [SHLWAPI.@]
1518 * aa "" (pointer to traling NULL)
1519 * aa\ "" (pointer to traling NULL)
1520 * aa\\ "" (pointer to traling NULL)
1527 LPSTR WINAPI PathFindNextComponentA(LPCSTR pszPath)
1531 TRACE("%s\n", pszPath);
1533 if(!pszPath || !*pszPath) return NULL;
1534 if(!(pos = StrChrA(pszPath, '\\')))
1535 return (LPSTR) pszPath + strlen(pszPath);
1537 if(pos[0] == '\\') pos++;
1541 /*************************************************************************
1542 * PathFindNextComponentW [SHLWAPI.@]
1544 LPWSTR WINAPI PathFindNextComponentW(LPCWSTR pszPath)
1548 TRACE("%s\n", debugstr_w(pszPath));
1550 if(!pszPath || !*pszPath) return NULL;
1551 if (!(pos = StrChrW(pszPath, '\\')))
1552 return (LPWSTR) pszPath + strlenW(pszPath);
1554 if(pos[0] == '\\') pos++;
1558 /*************************************************************************
1559 * PathAddExtensionA [SHLWAPI.@]
1562 * it adds never a dot
1565 BOOL WINAPI PathAddExtensionA(
1567 LPCSTR pszExtension)
1571 if (*(PathFindExtensionA(pszPath))) return FALSE;
1573 if (!pszExtension || *pszExtension=='\0')
1574 strcat(pszPath, "exe");
1576 strcat(pszPath, pszExtension);
1582 /*************************************************************************
1583 * PathAddExtensionW [SHLWAPI.@]
1585 BOOL WINAPI PathAddExtensionW(
1587 LPCWSTR pszExtension)
1589 static const WCHAR ext[] = { 'e','x','e',0 };
1593 if (*(PathFindExtensionW(pszPath))) return FALSE;
1595 if (!pszExtension || *pszExtension=='\0')
1596 strcatW(pszPath, ext);
1598 strcatW(pszPath, pszExtension);
1604 /*************************************************************************
1605 * PathMakePrettyA [SHLWAPI.@]
1607 BOOL WINAPI PathMakePrettyA(
1610 FIXME("%s\n", lpPath);
1614 /*************************************************************************
1615 * PathMakePrettyW [SHLWAPI.@]
1617 BOOL WINAPI PathMakePrettyW(
1620 FIXME("%s\n", debugstr_w(lpPath));
1625 /*************************************************************************
1626 * PathCommonPrefixA [SHLWAPI.@]
1628 int WINAPI PathCommonPrefixA(
1633 FIXME("%s %s %p\n", pszFile1, pszFile2, achPath);
1637 /*************************************************************************
1638 * PathCommonPrefixW [SHLWAPI.@]
1640 int WINAPI PathCommonPrefixW(
1645 FIXME("%s %s %p\n", debugstr_w(pszFile1), debugstr_w(pszFile2),achPath );
1649 /*************************************************************************
1650 * PathCompactPathA [SHLWAPI.@]
1652 BOOL WINAPI PathCompactPathA(HDC hDC, LPSTR pszPath, UINT dx)
1654 FIXME("0x%08x %s 0x%08x\n", hDC, pszPath, dx);
1658 /*************************************************************************
1659 * PathCompactPathW [SHLWAPI.@]
1661 BOOL WINAPI PathCompactPathW(HDC hDC, LPWSTR pszPath, UINT dx)
1663 FIXME("0x%08x %s 0x%08x\n", hDC, debugstr_w(pszPath), dx);
1667 /*************************************************************************
1668 * PathGetCharTypeA [SHLWAPI.@]
1670 UINT WINAPI PathGetCharTypeA(UCHAR ch)
1676 /* We could use them in filenames, but this would confuse 'ls' */
1679 if ((ch == '*') || (ch=='?'))
1681 if ((ch == '\\') || (ch=='/'))
1682 return GCT_SEPARATOR;
1684 /* all normal characters, no lower case letters */
1685 if ((ch > ' ') && (ch < 0x7f) && !islower(ch))
1686 flags |= GCT_SHORTCHAR;
1687 /* All other characters are valid in long filenames, even umlauts */
1688 return flags | GCT_LFNCHAR;
1691 /*************************************************************************
1692 * PathGetCharTypeW [SHLWAPI.@]
1694 UINT WINAPI PathGetCharTypeW(WCHAR ch)
1696 FIXME("%c, using ascii version\n", ch);
1697 return PathGetCharTypeA(ch);
1700 /*************************************************************************
1701 * PathMakeSystemFolderA [SHLWAPI.@]
1703 BOOL WINAPI PathMakeSystemFolderA(LPCSTR pszPath)
1705 FIXME("%s\n", pszPath);
1709 /*************************************************************************
1710 * PathMakeSystemFolderW [SHLWAPI.@]
1712 BOOL WINAPI PathMakeSystemFolderW(LPCWSTR pszPath)
1714 FIXME("%s\n", debugstr_w(pszPath));
1718 /*************************************************************************
1719 * PathRenameExtensionA [SHLWAPI.@]
1721 BOOL WINAPI PathRenameExtensionA(LPSTR pszPath, LPCSTR pszExt)
1723 FIXME("%s %s\n", pszPath, pszExt);
1727 /*************************************************************************
1728 * PathRenameExtensionW [SHLWAPI.@]
1730 BOOL WINAPI PathRenameExtensionW(LPWSTR pszPath, LPCWSTR pszExt)
1732 FIXME("%s %s\n", debugstr_w(pszPath), debugstr_w(pszExt));
1736 /*************************************************************************
1737 * PathSearchAndQualifyA [SHLWAPI.@]
1739 BOOL WINAPI PathSearchAndQualifyA(
1744 FIXME("%s %s 0x%08x\n", pszPath, pszBuf, cchBuf);
1748 /*************************************************************************
1749 * PathSearchAndQualifyW [SHLWAPI.@]
1751 BOOL WINAPI PathSearchAndQualifyW(
1756 FIXME("%s %s 0x%08x\n", debugstr_w(pszPath), debugstr_w(pszBuf), cchBuf);
1760 /*************************************************************************
1761 * PathSkipRootA [SHLWAPI.@]
1763 LPSTR WINAPI PathSkipRootA(LPCSTR pszPath)
1765 FIXME("%s\n", pszPath);
1766 return (LPSTR)pszPath;
1769 /*************************************************************************
1770 * PathSkipRootW [SHLWAPI.@]
1772 LPWSTR WINAPI PathSkipRootW(LPCWSTR pszPath)
1774 FIXME("%s\n", debugstr_w(pszPath));
1775 return (LPWSTR)pszPath;
1778 /*************************************************************************
1779 * PathCreateFromUrlA [SHLWAPI.@]
1781 HRESULT WINAPI PathCreateFromUrlA(
1787 FIXME("%s %p %p 0x%08lx\n",
1788 pszUrl, pszPath, pcchPath, dwFlags);
1792 /*************************************************************************
1793 * PathCreateFromUrlW [SHLWAPI.@]
1795 HRESULT WINAPI PathCreateFromUrlW(
1801 FIXME("%s %p %p 0x%08lx\n",
1802 debugstr_w(pszUrl), pszPath, pcchPath, dwFlags);
1806 /*************************************************************************
1807 * PathRelativePathToA [SHLWAPI.@]
1809 BOOL WINAPI PathRelativePathToA(
1816 FIXME("%s %s 0x%08lx %s 0x%08lx\n",
1817 pszPath, pszFrom, dwAttrFrom, pszTo, dwAttrTo);
1821 /*************************************************************************
1822 * PathRelativePathToW [SHLWAPI.@]
1824 BOOL WINAPI PathRelativePathToW(
1831 FIXME("%s %s 0x%08lx %s 0x%08lx\n",
1832 debugstr_w(pszPath), debugstr_w(pszFrom), dwAttrFrom, debugstr_w(pszTo), dwAttrTo);
1836 /*************************************************************************
1837 * PathUnmakeSystemFolderA [SHLWAPI.@]
1839 BOOL WINAPI PathUnmakeSystemFolderA(LPCSTR pszPath)
1841 FIXME("%s\n", pszPath);
1845 /*************************************************************************
1846 * PathUnmakeSystemFolderW [SHLWAPI.@]
1848 BOOL WINAPI PathUnmakeSystemFolderW(LPCWSTR pszPath)
1850 FIXME("%s\n", debugstr_w(pszPath));
1855 ########## special ##########
1858 /*************************************************************************
1859 * PathSetDlgItemPathA [SHLWAPI.@]
1862 * use PathCompactPath to make sure, the path fits into the control
1864 BOOL WINAPI PathSetDlgItemPathA(HWND hDlg, int id, LPCSTR pszPath)
1865 { TRACE("%x %x %s\n",hDlg, id, pszPath);
1866 return SetDlgItemTextA(hDlg, id, pszPath);
1869 /*************************************************************************
1870 * PathSetDlgItemPathW [SHLWAPI.@]
1872 BOOL WINAPI PathSetDlgItemPathW(HWND hDlg, int id, LPCWSTR pszPath)
1873 { TRACE("%x %x %s\n",hDlg, id, debugstr_w(pszPath));
1874 return SetDlgItemTextW(hDlg, id, pszPath);