9 #include "wine/unicode.h"
14 #include "debugtools.h"
17 DEFAULT_DEBUG_CHANNEL(shell);
19 #define isSlash(x) ((x)=='\\' || (x)=='/')
21 ########## Combining and Constructing paths ##########
24 /*************************************************************************
25 * PathAppendA [SHLWAPI.@]
28 * concat path lpszPath2 onto lpszPath1
31 * the resulting path is also canonicalized
33 BOOL WINAPI PathAppendA(
37 TRACE("%s %s\n",lpszPath1, lpszPath2);
38 while (lpszPath2[0]=='\\') lpszPath2++;
39 PathCombineA(lpszPath1,lpszPath1,lpszPath2);
43 /*************************************************************************
44 * PathAppendW [SHLWAPI.@]
46 BOOL WINAPI PathAppendW(
50 TRACE("%s %s\n",debugstr_w(lpszPath1), debugstr_w(lpszPath2));
51 while (lpszPath2[0]=='\\') lpszPath2++;
52 PathCombineW(lpszPath1,lpszPath1,lpszPath2);
56 /*************************************************************************
57 * PathCombineA [SHLWAPI.@]
60 * if lpszFile='.' skip it
61 * szDest can be equal to lpszFile. Thats why we use sTemp
64 * the resulting path is also canonicalized
66 LPSTR WINAPI PathCombineA(
72 TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, lpszDir, lpszFile, lpszFile);
75 if (!lpszFile || !lpszFile[0] || (lpszFile[0]=='.' && !lpszFile[1]) )
77 strcpy(szDest,lpszDir);
81 /* if lpszFile is a complete path don't care about lpszDir */
82 if (PathGetDriveNumberA(lpszFile) != -1)
84 strcpy(szDest,lpszFile);
86 else if (lpszFile[0] == '\\' )
88 strcpy(sTemp,lpszDir);
89 PathStripToRootA(sTemp);
90 strcat(sTemp,lpszFile);
95 strcpy(sTemp,lpszDir);
96 PathAddBackslashA(sTemp);
97 strcat(sTemp,lpszFile);
103 /*************************************************************************
104 * PathCombineW [SHLWAPI.@]
106 LPWSTR WINAPI PathCombineW(
111 WCHAR sTemp[MAX_PATH];
112 TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, debugstr_w(lpszDir),
113 lpszFile, debugstr_w(lpszFile));
116 if (!lpszFile || !lpszFile[0] || (lpszFile[0]==(WCHAR)'.' && !lpszFile[1]) )
118 strcpyW(szDest,lpszDir);
122 /* if lpszFile is a complete path don't care about lpszDir */
123 if (PathGetDriveNumberW(lpszFile) != -1)
125 strcpyW(szDest,lpszFile);
127 else if (lpszFile[0] == (WCHAR)'\\' )
129 strcpyW(sTemp,lpszDir);
130 PathStripToRootW(sTemp);
131 strcatW(sTemp,lpszFile);
132 strcpyW(szDest,sTemp);
136 strcpyW(sTemp,lpszDir);
137 PathAddBackslashW(sTemp);
138 strcatW(sTemp,lpszFile);
139 strcpyW(szDest,sTemp);
144 /*************************************************************************
145 * PathAddBackslashA [SHLWAPI.@]
148 * append \ if there is none
150 LPSTR WINAPI PathAddBackslashA(LPSTR lpszPath)
153 TRACE("%p->%s\n",lpszPath,lpszPath);
155 len = strlen(lpszPath);
156 if (len && lpszPath[len-1]!='\\')
158 lpszPath[len] = '\\';
159 lpszPath[len+1]= 0x00;
160 return lpszPath+len+1;
165 /*************************************************************************
166 * PathAddBackslashW [SHLWAPI.@]
168 LPWSTR WINAPI PathAddBackslashW(LPWSTR lpszPath)
171 TRACE("%p->%s\n",lpszPath,debugstr_w(lpszPath));
173 len = strlenW(lpszPath);
174 if (len && lpszPath[len-1]!=(WCHAR)'\\')
176 lpszPath[len] = (WCHAR)'\\';
177 lpszPath[len+1]= 0x00;
178 return lpszPath+len+1;
183 /*************************************************************************
184 * PathBuildRootA [SHLWAPI.@]
186 LPSTR WINAPI PathBuildRootA(LPSTR lpszPath, int drive)
188 TRACE("%p %i\n",lpszPath, drive);
190 strcpy(lpszPath,"A:\\");
195 /*************************************************************************
196 * PathBuildRootW [SHLWAPI.@]
198 LPWSTR WINAPI PathBuildRootW(LPWSTR lpszPath, int drive)
200 lpszPath[0] = 'A' + drive;
204 TRACE("%p %i\n",debugstr_w(lpszPath), drive);
209 Extracting Component Parts
212 /*************************************************************************
213 * PathFindFileNameA [SHLWAPI.@]
215 LPSTR WINAPI PathFindFileNameA(LPCSTR lpszPath)
217 LPCSTR lastSlash = lpszPath;
219 TRACE("%s\n",lpszPath);
222 if ( isSlash(lpszPath[0]) && lpszPath[1])
223 lastSlash = lpszPath+1;
224 lpszPath = CharNextA(lpszPath);
226 return (LPSTR)lastSlash;
230 /*************************************************************************
231 * PathFindFileNameW [SHLWAPI.@]
233 LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
238 TRACE("%s\n",debugstr_w(wslash));
241 if (((lpszPath[0]=='\\') || (lpszPath[0]==':')) && lpszPath[1] && lpszPath[1]!='\\')
243 lpszPath = CharNextW(lpszPath);
245 return (LPWSTR)wslash;
248 /*************************************************************************
249 * PathFindExtensionA [SHLWAPI.@]
252 * returns pointer to last . in last lpszPath component or at \0.
255 LPSTR WINAPI PathFindExtensionA(LPCSTR lpszPath)
257 LPCSTR lastpoint = NULL;
259 TRACE("%p %s\n",lpszPath,lpszPath);
263 if (*lpszPath=='\\'||*lpszPath==' ')
267 lpszPath = CharNextA(lpszPath);
269 return (LPSTR)(lastpoint?lastpoint:lpszPath);
272 /*************************************************************************
273 * PathFindExtensionW [SHLWAPI.@]
275 LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath)
277 LPCWSTR lastpoint = NULL;
279 TRACE("(%p %s)\n",lpszPath,debugstr_w(lpszPath));
283 if (*lpszPath==(WCHAR)'\\'||*lpszPath==(WCHAR)' ')
285 if (*lpszPath==(WCHAR)'.')
287 lpszPath = CharNextW(lpszPath);
289 return (LPWSTR)(lastpoint?lastpoint:lpszPath);
292 /*************************************************************************
293 * PathGetArgsA [SHLWAPI.@]
296 * look for next arg in string. handle "quoted" strings
297 * returns pointer to argument *AFTER* the space. Or to the \0.
302 LPSTR WINAPI PathGetArgsA(LPCSTR lpszPath)
306 TRACE("%s\n",lpszPath);
310 if ((*lpszPath==' ') && !qflag)
311 return (LPSTR)lpszPath+1;
314 lpszPath = CharNextA(lpszPath);
316 return (LPSTR)lpszPath;
319 /*************************************************************************
320 * PathGetArgsW [SHLWAPI.@]
322 LPWSTR WINAPI PathGetArgsW(LPCWSTR lpszPath)
326 TRACE("%s\n",debugstr_w(lpszPath));
330 if ((*lpszPath==' ') && !qflag)
331 return (LPWSTR)lpszPath+1;
334 lpszPath = CharNextW(lpszPath);
336 return (LPWSTR)lpszPath;
339 /*************************************************************************
340 * PathGetDriveNumberA [SHLWAPI.@]
342 int WINAPI PathGetDriveNumberA(LPCSTR lpszPath)
344 int chr = tolower(lpszPath[0]);
346 TRACE ("%s\n",debugstr_a(lpszPath));
348 if (!lpszPath || lpszPath[1]!=':' || chr < 'a' || chr > 'z') return -1;
349 return tolower(lpszPath[0]) - 'a' ;
352 /*************************************************************************
353 * PathGetDriveNumberW [SHLWAPI.@]
355 int WINAPI PathGetDriveNumberW(LPCWSTR lpszPath)
357 int chr = tolowerW(lpszPath[0]);
359 TRACE ("%s\n",debugstr_w(lpszPath));
361 if (!lpszPath || lpszPath[1]!=':' || chr < 'a' || chr > 'z') return -1;
362 return tolowerW(lpszPath[0]) - 'a' ;
365 /*************************************************************************
366 * PathRemoveFileSpecA [SHLWAPI.@]
369 * truncates passed argument to a valid path
370 * returns if the string was modified or not.
371 * "\foo\xx\foo"-> "\foo\xx"
375 BOOL WINAPI PathRemoveFileSpecA(LPSTR lpszPath)
377 LPSTR cutplace = lpszPath;
380 TRACE("%s\n",lpszPath);
384 while (*lpszPath == '\\') cutplace = ++lpszPath;
388 if(lpszPath[0] == '\\') cutplace = lpszPath;
390 if(lpszPath[0] == ':')
392 cutplace = lpszPath + 1;
393 if (lpszPath[1] == '\\') cutplace++;
396 lpszPath = CharNextA(lpszPath);
397 if (!lpszPath) break;
400 ret = (*cutplace!='\0');
406 /*************************************************************************
407 * PathRemoveFileSpecW [SHLWAPI.@]
409 BOOL WINAPI PathRemoveFileSpecW(LPWSTR lpszPath)
411 LPWSTR cutplace = lpszPath;
414 TRACE("%s\n",debugstr_w(lpszPath));
418 while (*lpszPath == '\\') cutplace = ++lpszPath;
422 if(lpszPath[0] == '\\') cutplace = lpszPath;
424 if(lpszPath[0] == ':')
426 cutplace = lpszPath + 1;
427 if (lpszPath[1] == '\\') cutplace++;
430 lpszPath = CharNextW(lpszPath);
431 if (!lpszPath) break;
434 ret = (*cutplace!='\0');
440 /*************************************************************************
441 * PathStripPathA [SHLWAPI.@]
444 * removes the path from the beginning of a filename
446 void WINAPI PathStripPathA(LPSTR lpszPath)
448 LPSTR lpszFileName = PathFindFileNameA(lpszPath);
450 TRACE("%s\n", lpszPath);
453 RtlMoveMemory(lpszPath, lpszFileName, strlen(lpszFileName)+1);
456 /*************************************************************************
457 * PathStripPathW [SHLWAPI.@]
459 void WINAPI PathStripPathW(LPWSTR lpszPath)
461 LPWSTR lpszFileName = PathFindFileNameW(lpszPath);
463 TRACE("%s\n", debugstr_w(lpszPath));
465 RtlMoveMemory(lpszPath, lpszFileName, (strlenW(lpszFileName)+1)*sizeof(WCHAR));
468 /*************************************************************************
469 * PathStripToRootA [SHLWAPI.@]
471 BOOL WINAPI PathStripToRootA(LPSTR lpszPath)
473 TRACE("%s\n", lpszPath);
475 if (!lpszPath) return FALSE;
476 while(!PathIsRootA(lpszPath))
477 if (!PathRemoveFileSpecA(lpszPath)) return FALSE;
481 /*************************************************************************
482 * PathStripToRootW [SHLWAPI.@]
484 BOOL WINAPI PathStripToRootW(LPWSTR lpszPath)
486 TRACE("%s\n", debugstr_w(lpszPath));
488 if (!lpszPath) return FALSE;
489 while(!PathIsRootW(lpszPath))
490 if (!PathRemoveFileSpecW(lpszPath)) return FALSE;
494 /*************************************************************************
495 * PathRemoveArgsA [SHLWAPI.@]
498 void WINAPI PathRemoveArgsA(LPSTR lpszPath)
500 TRACE("%s\n",lpszPath);
504 LPSTR lpszArgs = PathGetArgsA(lpszPath);
507 LPSTR lpszLastChar = CharPrevA(lpszPath, lpszArgs);
508 if(*lpszLastChar==' ') *lpszLastChar = '\0';
513 /*************************************************************************
514 * PathRemoveArgsW [SHLWAPI.@]
516 void WINAPI PathRemoveArgsW(LPWSTR lpszPath)
518 TRACE("%s\n", debugstr_w(lpszPath));
522 LPWSTR lpszArgs = PathGetArgsW(lpszPath);
525 LPWSTR lpszLastChar = CharPrevW(lpszPath, lpszArgs);
526 if(*lpszLastChar==' ') *lpszLastChar = '\0';
531 /*************************************************************************
532 * PathRemoveExtensionA [SHLWAPI.@]
534 void WINAPI PathRemoveExtensionA(LPSTR lpszPath)
536 LPSTR lpszExtension = PathFindExtensionA(lpszPath);
538 TRACE("%s\n", lpszPath);
540 if (lpszExtension) *lpszExtension='\0';
543 /*************************************************************************
544 * PathRemoveExtensionW [SHLWAPI.@]
546 void WINAPI PathRemoveExtensionW(LPWSTR lpszPath)
548 LPWSTR lpszExtension = PathFindExtensionW(lpszPath);
550 TRACE("%s\n", debugstr_w(lpszPath));
552 if (lpszExtension) *lpszExtension='\0';
555 /*************************************************************************
556 * PathRemoveBackslashA [SHLWAPI.@]
558 * If the path ends in a backslash it is replaced by a NULL
559 * and the address of the NULL is returned
561 * the address of the last character is returned.
564 * "c:\": keep backslash
566 LPSTR WINAPI PathRemoveBackslashA( LPSTR lpszPath )
573 len = strlen(lpszPath);
574 szTemp = CharPrevA(lpszPath, lpszPath+len);
575 if (! PathIsRootA(lpszPath))
577 if (*szTemp == '\\') *szTemp = '\0';
583 /*************************************************************************
584 * PathRemoveBackslashW [SHLWAPI.@]
586 LPWSTR WINAPI PathRemoveBackslashW( LPWSTR lpszPath )
589 LPWSTR szTemp = NULL;
593 len = strlenW(lpszPath);
594 szTemp = CharPrevW(lpszPath, lpszPath+len);
595 if (! PathIsRootW(lpszPath))
597 if (*szTemp == '\\') *szTemp = '\0';
608 /*************************************************************************
609 * PathRemoveBlanksA [SHLWAPI.@]
612 * remove spaces from beginning and end of passed string
614 void WINAPI PathRemoveBlanksA(LPSTR str)
622 while (*x==' ') x = CharNextA(x);
623 if (x!=str) strcpy(str,x);
625 while (*x==' ') x = CharPrevA(str, x);
626 if (*x==' ') *x='\0';
630 /*************************************************************************
631 * PathRemoveBlanksW [SHLWAPI.@]
633 void WINAPI PathRemoveBlanksW(LPWSTR str)
637 TRACE("%s\n",debugstr_w(str));
641 while (*x==' ') x = CharNextW(x);
642 if (x!=str) strcpyW(str,x);
643 x=str+strlenW(str)-1;
644 while (*x==' ') x = CharPrevW(str, x);
645 if (*x==' ') *x='\0';
649 /*************************************************************************
650 * PathQuoteSpacesA [SHLWAPI.@]
653 LPSTR WINAPI PathQuoteSpacesA(LPSTR lpszPath)
655 TRACE("%s\n",lpszPath);
657 if(StrChrA(lpszPath,' '))
659 int len = strlen(lpszPath);
660 RtlMoveMemory(lpszPath+1, lpszPath, len);
670 /*************************************************************************
671 * PathQuoteSpacesW [SHLWAPI.@]
673 LPWSTR WINAPI PathQuoteSpacesW(LPWSTR lpszPath)
675 TRACE("%s\n",debugstr_w(lpszPath));
677 if(StrChrW(lpszPath,' '))
679 int len = strlenW(lpszPath);
680 RtlMoveMemory(lpszPath+1, lpszPath, len*sizeof(WCHAR));
690 /*************************************************************************
691 * PathUnquoteSpacesA [SHLWAPI.@]
694 * unquote string (remove ")
696 VOID WINAPI PathUnquoteSpacesA(LPSTR str)
698 DWORD len = strlen(str);
711 /*************************************************************************
712 * PathUnquoteSpacesW [SHLWAPI.@]
714 VOID WINAPI PathUnquoteSpacesW(LPWSTR str)
716 DWORD len = strlenW(str);
718 TRACE("%s\n",debugstr_w(str));
729 /*************************************************************************
730 * PathParseIconLocationA [SHLWAPI.@]
732 int WINAPI PathParseIconLocationA(LPSTR lpszPath)
734 LPSTR lpstrComma = strchr(lpszPath, ',');
736 FIXME("%s stub\n", debugstr_a(lpszPath));
738 if (lpstrComma && lpstrComma[1])
741 /* return atoi(&lpstrComma[1]); FIXME */
744 PathUnquoteSpacesA(lpszPath);
748 /*************************************************************************
749 * PathParseIconLocationW [SHLWAPI.@]
751 int WINAPI PathParseIconLocationW(LPWSTR lpszPath)
753 LPWSTR lpstrComma = strchrW(lpszPath, ',');
755 FIXME("%s stub\n", debugstr_w(lpszPath));
757 if (lpstrComma && lpstrComma[1])
760 /* return _wtoi(&lpstrComma[1]); FIXME */
762 PathUnquoteSpacesW(lpszPath);
767 ########## cleaning and resolving paths ##########
770 /*************************************************************************
771 * PathFindOnPathA [SHLWAPI.@]
773 BOOL WINAPI PathFindOnPathA(LPSTR sFile, LPCSTR sOtherDirs)
775 FIXME("%s %s\n",sFile, sOtherDirs);
779 /*************************************************************************
780 * PathFindOnPathW [SHLWAPI.@]
782 BOOL WINAPI PathFindOnPathW(LPWSTR sFile, LPCWSTR sOtherDirs)
784 FIXME("%s %s\n",debugstr_w(sFile), debugstr_w(sOtherDirs));
788 /*************************************************************************
789 * PathCompactPathExA [SHLWAPI.@]
791 BOOL WINAPI PathCompactPathExA(
797 FIXME("%p %s 0x%08x 0x%08lx\n", pszOut, pszSrc, cchMax, dwFlags);
801 /*************************************************************************
802 * PathCompactPathExW [SHLWAPI.@]
804 BOOL WINAPI PathCompactPathExW(
810 FIXME("%p %s 0x%08x 0x%08lx\n", pszOut, debugstr_w(pszSrc), cchMax, dwFlags);
815 ########## Path Testing ##########
818 /*************************************************************************
819 * PathIsUNCA [SHLWAPI.@]
822 * PathIsUNC(char*path);
824 BOOL WINAPI PathIsUNCA(LPCSTR lpszPath)
826 TRACE("%s\n",lpszPath);
828 return (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\'));
831 /*************************************************************************
832 * PathIsUNCW [SHLWAPI.@]
834 BOOL WINAPI PathIsUNCW(LPCWSTR lpszPath)
836 TRACE("%s\n",debugstr_w(lpszPath));
838 return (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\'));
841 /*************************************************************************
842 * PathIsRelativeA [SHLWAPI.@]
844 BOOL WINAPI PathIsRelativeA (LPCSTR lpszPath)
846 TRACE("lpszPath=%s\n",lpszPath);
848 return (lpszPath && (lpszPath[0]!='\\' && lpszPath[1]!=':'));
851 /*************************************************************************
852 * PathIsRelativeW [SHLWAPI.@]
854 BOOL WINAPI PathIsRelativeW (LPCWSTR lpszPath)
856 TRACE("lpszPath=%s\n",debugstr_w(lpszPath));
858 return (lpszPath && (lpszPath[0]!='\\' && lpszPath[1]!=':'));
861 /*************************************************************************
862 * PathIsRootA [SHLWAPI.@]
865 * TRUE if the path points to a root directory
867 BOOL WINAPI PathIsRootA(LPCSTR lpszPath)
869 TRACE("%s\n",lpszPath);
872 if (lpszPath[1]==':' && lpszPath[2]=='\\' && lpszPath[3]=='\0')
876 if (lpszPath[0]=='\\' && lpszPath[1]=='\0')
879 /* UNC "\\<computer>\<share>" */
880 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
882 int foundbackslash = 0;
886 if (*lpszPath=='\\') foundbackslash++;
887 lpszPath = CharNextA(lpszPath);
889 if (foundbackslash <= 1)
895 /*************************************************************************
896 * PathIsRootW [SHLWAPI.@]
898 BOOL WINAPI PathIsRootW(LPCWSTR lpszPath)
900 TRACE("%s\n",debugstr_w(lpszPath));
903 if (lpszPath[1]==':' && lpszPath[2]=='\\' && lpszPath[3]=='\0')
907 if (lpszPath[0]=='\\' && lpszPath[1]=='\0')
910 /* UNC "\\<computer>\<share>" */
911 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
913 int foundbackslash = 0;
917 if (*lpszPath=='\\') foundbackslash++;
918 lpszPath = CharNextW(lpszPath);
920 if (foundbackslash <= 1)
927 /*************************************************************************
928 * PathIsDirectoryA [SHLWAPI.@]
930 BOOL WINAPI PathIsDirectoryA(LPCSTR lpszPath)
934 TRACE("%s\n", debugstr_a(lpszPath));
936 dwAttr = GetFileAttributesA(lpszPath);
937 return (dwAttr != -1) ? dwAttr & FILE_ATTRIBUTE_DIRECTORY : 0;
940 /*************************************************************************
941 * PathIsDirectoryW [SHLWAPI.@]
943 BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath)
947 TRACE("%s\n", debugstr_w(lpszPath));
949 dwAttr = GetFileAttributesW(lpszPath);
950 return (dwAttr != -1) ? dwAttr & FILE_ATTRIBUTE_DIRECTORY : 0;
953 /*************************************************************************
954 * PathFileExistsA [SHLWAPI.@]
957 * file_exists(char *fn);
959 BOOL WINAPI PathFileExistsA(LPCSTR lpszPath)
961 TRACE("%s\n",lpszPath);
962 return (GetFileAttributesA(lpszPath)!=-1);
965 /*************************************************************************
966 * PathFileExistsW [SHLWAPI.@]
968 BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
970 TRACE("%s\n",debugstr_w(lpszPath));
971 return (GetFileAttributesW(lpszPath)!=-1);
974 /*************************************************************************
975 * PathMatchSingleMaskA [internal]
978 * internal (used by PathMatchSpec)
980 static BOOL PathMatchSingleMaskA(LPCSTR name, LPCSTR mask)
982 while (*name && *mask && *mask!=';')
988 if (PathMatchSingleMaskA(name,mask+1)) return 1; /* try substrings */
992 if (toupper(*mask)!=toupper(*name) && *mask!='?') return 0;
993 name = CharNextA(name);
994 mask = CharNextA(mask);
998 while (*mask=='*') mask++;
999 if (!*mask || *mask==';') return 1;
1004 /*************************************************************************
1005 * PathMatchSingleMaskW [internal]
1007 static BOOL PathMatchSingleMaskW(LPCWSTR name, LPCWSTR mask)
1009 while (*name && *mask && *mask!=';')
1015 if (PathMatchSingleMaskW(name,mask+1)) return 1; /* try substrings */
1019 if (toupperW(*mask)!=toupperW(*name) && *mask!='?') return 0;
1020 name = CharNextW(name);
1021 mask = CharNextW(mask);
1025 while (*mask=='*') mask++;
1026 if (!*mask || *mask==';') return 1;
1030 /*************************************************************************
1031 * PathMatchSpecA [SHLWAPI.@]
1034 * used from COMDLG32
1036 BOOL WINAPI PathMatchSpecA(LPCSTR name, LPCSTR mask)
1038 TRACE("%s %s\n",name,mask);
1040 if (!lstrcmpA( mask, "*.*" )) return 1; /* we don't require a period */
1044 if (PathMatchSingleMaskA(name,mask)) return 1; /* helper function */
1045 while (*mask && *mask!=';') mask = CharNextA(mask);
1049 while (*mask==' ') mask++; /* masks may be separated by "; " */
1055 /*************************************************************************
1056 * PathMatchSpecW [SHLWAPI.@]
1058 BOOL WINAPI PathMatchSpecW(LPCWSTR name, LPCWSTR mask)
1060 static const WCHAR stemp[] = { '*','.','*',0 };
1061 TRACE("%s %s\n",debugstr_w(name),debugstr_w(mask));
1063 if (!lstrcmpW( mask, stemp )) return 1; /* we don't require a period */
1067 if (PathMatchSingleMaskW(name,mask)) return 1; /* helper function */
1068 while (*mask && *mask!=';') mask = CharNextW(mask);
1072 while (*mask==' ') mask++; /* masks may be separated by "; " */
1078 /*************************************************************************
1079 * PathIsSameRootA [SHLWAPI.@]
1082 * what to do with "\path" ??
1084 BOOL WINAPI PathIsSameRootA(LPCSTR lpszPath1, LPCSTR lpszPath2)
1086 TRACE("%s %s\n", lpszPath1, lpszPath2);
1088 if (PathIsRelativeA(lpszPath1) || PathIsRelativeA(lpszPath2)) return FALSE;
1091 if ( toupper(lpszPath1[0])==toupper(lpszPath2[0]) &&
1092 lpszPath1[1]==':' && lpszPath2[1]==':' &&
1093 lpszPath1[2]=='\\' && lpszPath2[2]=='\\')
1097 if (lpszPath1[0]=='\\' && lpszPath2[0]=='\\' &&
1098 lpszPath1[1]=='\\' && lpszPath2[1]=='\\')
1100 int pos=2, bsfound=0;
1101 while (lpszPath1[pos] && lpszPath2[pos] &&
1102 (lpszPath1[pos] == lpszPath2[pos]))
1104 if (lpszPath1[pos]=='\\') bsfound++;
1105 if (bsfound == 2) return TRUE;
1106 pos++; /* fixme: use CharNext*/
1108 return (lpszPath1[pos] == lpszPath2[pos]);
1113 /*************************************************************************
1114 * PathIsSameRootW [SHLWAPI.@]
1116 BOOL WINAPI PathIsSameRootW(LPCWSTR lpszPath1, LPCWSTR lpszPath2)
1118 TRACE("%s %s\n", debugstr_w(lpszPath1), debugstr_w(lpszPath2));
1120 if (PathIsRelativeW(lpszPath1) || PathIsRelativeW(lpszPath2)) return FALSE;
1123 if ( toupperW(lpszPath1[0])==toupperW(lpszPath2[0]) &&
1124 lpszPath1[1]==':' && lpszPath2[1]==':' &&
1125 lpszPath1[2]=='\\' && lpszPath2[2]=='\\')
1129 if (lpszPath1[0]=='\\' && lpszPath2[0]=='\\' &&
1130 lpszPath1[1]=='\\' && lpszPath2[1]=='\\')
1132 int pos=2, bsfound=0;
1133 while (lpszPath1[pos] && lpszPath2[pos] &&
1134 (lpszPath1[pos] == lpszPath2[pos]))
1136 if (lpszPath1[pos]=='\\') bsfound++;
1137 if (bsfound == 2) return TRUE;
1138 pos++;/* fixme: use CharNext*/
1140 return (lpszPath1[pos] == lpszPath2[pos]);
1145 /*************************************************************************
1146 * PathIsURLA (SHLWAPI.@)
1148 BOOL WINAPI PathIsURLA(LPCSTR lpstrPath)
1152 static LPSTR SupportedProtocol[] =
1153 {"http","https","ftp","gopher","file","mailto",NULL};
1155 if(!lpstrPath) return FALSE;
1158 lpstrRes = strchr(lpstrPath,':');
1159 if(!lpstrRes) return FALSE;
1160 iSize = lpstrRes - lpstrPath;
1162 while(SupportedProtocol[i])
1164 if (iSize == strlen(SupportedProtocol[i]))
1165 if(!strncasecmp(lpstrPath, SupportedProtocol[i], iSize))
1173 /*************************************************************************
1174 * PathIsURLW (SHLWAPI.@)
1176 BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
1180 static WCHAR SupportedProtocol[7][7] =
1181 {{'h','t','t','p','\0'},{'h','t','t','p','s','\0'},{'f','t','p','\0'},
1182 {'g','o','p','h','e','r','\0'},{'f','i','l','e','\0'},
1183 {'m','a','i','l','t','o','\0'},{0}};
1185 if(!lpstrPath) return FALSE;
1188 lpstrRes = strchrW(lpstrPath,':');
1189 if(!lpstrRes) return FALSE;
1190 iSize = lpstrRes - lpstrPath;
1192 while(SupportedProtocol[i])
1194 if (iSize == strlenW(SupportedProtocol[i]))
1195 if(!strncmpiW(lpstrPath, SupportedProtocol[i], iSize))
1204 /*************************************************************************
1205 * PathIsContentTypeA [SHLWAPI.@]
1207 BOOL WINAPI PathIsContentTypeA(LPCSTR pszPath, LPCSTR pszContentType)
1209 FIXME("%s %s\n", pszPath, pszContentType);
1213 /*************************************************************************
1214 * PathIsContentTypeW [SHLWAPI.@]
1216 BOOL WINAPI PathIsContentTypeW(LPCWSTR pszPath, LPCWSTR pszContentType)
1218 FIXME("%s %s\n", debugstr_w(pszPath), debugstr_w(pszContentType));
1222 /*************************************************************************
1223 * PathIsFileSpecA [SHLWAPI.@]
1225 BOOL WINAPI PathIsFileSpecA(LPCSTR pszPath)
1227 FIXME("%s\n", pszPath);
1231 /*************************************************************************
1232 * PathIsFileSpecW [SHLWAPI.@]
1234 BOOL WINAPI PathIsFileSpecW(LPCWSTR pszPath)
1236 FIXME("%s\n", debugstr_w(pszPath));
1240 /*************************************************************************
1241 * PathIsPrefixA [SHLWAPI.@]
1243 BOOL WINAPI PathIsPrefixA(LPCSTR pszPrefix, LPCSTR pszPath)
1245 FIXME("%s %s\n", pszPrefix, pszPath);
1249 /*************************************************************************
1250 * PathIsPrefixW [SHLWAPI.@]
1252 BOOL WINAPI PathIsPrefixW(LPCWSTR pszPrefix, LPCWSTR pszPath)
1254 FIXME("%s %s\n", debugstr_w(pszPrefix), debugstr_w(pszPath));
1258 /*************************************************************************
1259 * PathIsSystemFolderA [SHLWAPI.@]
1261 BOOL WINAPI PathIsSystemFolderA(LPCSTR pszPath, DWORD dwAttrb)
1263 FIXME("%s 0x%08lx\n", pszPath, dwAttrb);
1267 /*************************************************************************
1268 * PathIsSystemFolderW [SHLWAPI.@]
1270 BOOL WINAPI PathIsSystemFolderW(LPCWSTR pszPath, DWORD dwAttrb)
1272 FIXME("%s 0x%08lx\n", debugstr_w(pszPath), dwAttrb);
1276 /*************************************************************************
1277 * PathIsUNCServerA [SHLWAPI.@]
1279 BOOL WINAPI PathIsUNCServerA(
1282 FIXME("%s\n", pszPath);
1286 /*************************************************************************
1287 * PathIsUNCServerW [SHLWAPI.@]
1289 BOOL WINAPI PathIsUNCServerW(
1292 FIXME("%s\n", debugstr_w(pszPath));
1296 /*************************************************************************
1297 * PathIsUNCServerShareA [SHLWAPI.@]
1299 BOOL WINAPI PathIsUNCServerShareA(
1302 FIXME("%s\n", pszPath);
1306 /*************************************************************************
1307 * PathIsUNCServerShareW [SHLWAPI.@]
1309 BOOL WINAPI PathIsUNCServerShareW(
1312 FIXME("%s\n", debugstr_w(pszPath));
1316 /*************************************************************************
1317 * PathCanonicalizeA [SHLWAPI.@]
1320 * returnvalue, use CharNext
1323 BOOL WINAPI PathCanonicalizeA(LPSTR pszBuf, LPCSTR pszPath)
1325 int OffsetMin = 0, OffsetSrc = 0, OffsetDst = 0, LenSrc = strlen(pszPath);
1326 BOOL bModifyed = FALSE;
1328 TRACE("%p %s\n", pszBuf, pszPath);
1330 pszBuf[OffsetDst]='\0';
1332 /* keep the root of the path */
1333 if( LenSrc && (pszPath[OffsetSrc]=='\\'))
1335 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1337 else if ( (LenSrc >= 2) && (pszPath[OffsetSrc+1] == ':'))
1339 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1340 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1341 if (LenSrc && (pszPath[OffsetSrc] == '\\'))
1343 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1344 if (LenSrc == 1 && pszPath[OffsetSrc]=='.')
1347 OffsetSrc++; LenSrc--; bModifyed = TRUE;
1349 else if (LenSrc == 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='.')
1352 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1357 /* ".\" at the beginning of the path */
1358 if (LenSrc >= 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='\\')
1360 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1365 if((LenSrc>=3) && (pszPath[OffsetSrc]=='\\') && (pszPath[OffsetSrc+1]=='.') && (pszPath[OffsetSrc+2]=='.'))
1367 /* "\.." found, go one deeper */
1368 while((OffsetDst > OffsetMin) && (pszBuf[OffsetDst]!='\\')) OffsetDst--;
1369 OffsetSrc += 3; LenSrc -= 3; bModifyed = TRUE;
1370 if(OffsetDst == OffsetMin && pszPath[OffsetSrc]=='\\') OffsetSrc++;
1371 pszBuf[OffsetDst] = '\0'; /* important for \..\.. */
1373 else if(LenSrc>=2 && pszPath[OffsetSrc]=='\\' && pszPath[OffsetSrc+1]=='.' )
1375 /* "\." found, skip it */
1376 OffsetSrc += 2; LenSrc-=2; bModifyed = TRUE;
1380 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; LenSrc--;
1383 pszBuf[OffsetDst] = '\0';
1384 TRACE("-- %s %u\n", pszBuf, bModifyed);
1389 /*************************************************************************
1390 * PathCanonicalizeW [SHLWAPI.@]
1393 * returnvalue, use CharNext
1395 BOOL WINAPI PathCanonicalizeW(LPWSTR pszBuf, LPCWSTR pszPath)
1397 int OffsetMin = 0, OffsetSrc = 0, OffsetDst = 0, LenSrc = strlenW(pszPath);
1398 BOOL bModifyed = FALSE;
1400 TRACE("%p %s\n", pszBuf, debugstr_w(pszPath));
1402 pszBuf[OffsetDst]='\0';
1404 /* keep the root of the path */
1405 if( LenSrc && (pszPath[OffsetSrc]=='\\'))
1407 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1409 else if ( (LenSrc >= 2) && (pszPath[OffsetSrc+1] == ':'))
1411 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1412 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1413 if (LenSrc && (pszPath[OffsetSrc] == '\\'))
1415 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1416 if (LenSrc == 1 && pszPath[OffsetSrc]=='.')
1419 OffsetSrc++; LenSrc--; bModifyed = TRUE;
1421 else if (LenSrc == 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='.')
1424 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1429 /* ".\" at the beginning of the path */
1430 if (LenSrc >= 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='\\')
1432 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1437 if((LenSrc>=3) && (pszPath[OffsetSrc]=='\\') && (pszPath[OffsetSrc+1]=='.') && (pszPath[OffsetSrc+2]=='.'))
1439 /* "\.." found, go one deeper */
1440 while((OffsetDst > OffsetMin) && (pszBuf[OffsetDst]!='\\')) OffsetDst--;
1441 OffsetSrc += 3; LenSrc -= 3; bModifyed = TRUE;
1442 if(OffsetDst == OffsetMin && pszPath[OffsetSrc]=='\\') OffsetSrc++;
1443 pszBuf[OffsetDst] = '\0'; /* important for \..\.. */
1445 else if(LenSrc>=2 && pszPath[OffsetSrc]=='\\' && pszPath[OffsetSrc+1]=='.' )
1447 /* "\." found, skip it */
1448 OffsetSrc += 2; LenSrc-=2; bModifyed = TRUE;
1452 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; LenSrc--;
1455 pszBuf[OffsetDst] = '\0';
1456 TRACE("-- %s %u\n", debugstr_w(pszBuf), bModifyed);
1460 /*************************************************************************
1461 * PathFindNextComponentA [SHLWAPI.@]
1466 * aa "" (pointer to traling NULL)
1467 * aa\ "" (pointer to traling NULL)
1468 * aa\\ "" (pointer to traling NULL)
1475 LPSTR WINAPI PathFindNextComponentA(LPCSTR pszPath)
1479 TRACE("%s\n", pszPath);
1481 if(!pszPath || !*pszPath) return NULL;
1482 if(!(pos = StrChrA(pszPath, '\\')))
1483 return (LPSTR) pszPath + strlen(pszPath);
1485 if(pos[0] == '\\') pos++;
1489 /*************************************************************************
1490 * PathFindNextComponentW [SHLWAPI.@]
1492 LPWSTR WINAPI PathFindNextComponentW(LPCWSTR pszPath)
1496 TRACE("%s\n", debugstr_w(pszPath));
1498 if(!pszPath || !*pszPath) return NULL;
1499 if (!(pos = StrChrW(pszPath, '\\')))
1500 return (LPWSTR) pszPath + strlenW(pszPath);
1502 if(pos[0] == '\\') pos++;
1506 /*************************************************************************
1507 * PathAddExtensionA [SHLWAPI.@]
1510 * it adds never a dot
1513 BOOL WINAPI PathAddExtensionA(
1515 LPCSTR pszExtension)
1519 if (*(PathFindExtensionA(pszPath))) return FALSE;
1521 if (!pszExtension || *pszExtension=='\0')
1522 strcat(pszPath, "exe");
1524 strcat(pszPath, pszExtension);
1530 /*************************************************************************
1531 * PathAddExtensionW [SHLWAPI.@]
1533 BOOL WINAPI PathAddExtensionW(
1535 LPCWSTR pszExtension)
1537 static const WCHAR ext[] = { 'e','x','e',0 };
1541 if (*(PathFindExtensionW(pszPath))) return FALSE;
1543 if (!pszExtension || *pszExtension=='\0')
1544 strcatW(pszPath, ext);
1546 strcatW(pszPath, pszExtension);
1552 /*************************************************************************
1553 * PathMakePrettyA [SHLWAPI.@]
1555 BOOL WINAPI PathMakePrettyA(
1558 FIXME("%s\n", lpPath);
1562 /*************************************************************************
1563 * PathMakePrettyW [SHLWAPI.@]
1565 BOOL WINAPI PathMakePrettyW(
1568 FIXME("%s\n", debugstr_w(lpPath));
1573 /*************************************************************************
1574 * PathCommonPrefixA [SHLWAPI.@]
1576 int WINAPI PathCommonPrefixA(
1581 FIXME("%s %s %p\n", pszFile1, pszFile2, achPath);
1585 /*************************************************************************
1586 * PathCommonPrefixW [SHLWAPI.@]
1588 int WINAPI PathCommonPrefixW(
1593 FIXME("%s %s %p\n", debugstr_w(pszFile1), debugstr_w(pszFile2),achPath );
1597 /*************************************************************************
1598 * PathCompactPathA [SHLWAPI.@]
1600 BOOL WINAPI PathCompactPathA(HDC hDC, LPSTR pszPath, UINT dx)
1602 FIXME("0x%08x %s 0x%08x\n", hDC, pszPath, dx);
1606 /*************************************************************************
1607 * PathCompactPathW [SHLWAPI.@]
1609 BOOL WINAPI PathCompactPathW(HDC hDC, LPWSTR pszPath, UINT dx)
1611 FIXME("0x%08x %s 0x%08x\n", hDC, debugstr_w(pszPath), dx);
1615 /*************************************************************************
1616 * PathGetCharTypeA [SHLWAPI.@]
1618 UINT WINAPI PathGetCharTypeA(UCHAR ch)
1624 /* We could use them in filenames, but this would confuse 'ls' */
1627 if ((ch == '*') || (ch=='?'))
1629 if ((ch == '\\') || (ch=='/'))
1630 return GCT_SEPARATOR;
1632 /* all normal characters, no lower case letters */
1633 if ((ch > ' ') && (ch < 0x7f) && !islower(ch))
1634 flags |= GCT_SHORTCHAR;
1635 /* All other characters are valid in long filenames, even umlauts */
1636 return flags | GCT_LFNCHAR;
1639 /*************************************************************************
1640 * PathGetCharTypeW [SHLWAPI.@]
1642 UINT WINAPI PathGetCharTypeW(WCHAR ch)
1644 FIXME("%c, using ascii version\n", ch);
1645 return PathGetCharTypeA(ch);
1648 /*************************************************************************
1649 * PathMakeSystemFolderA [SHLWAPI.@]
1651 BOOL WINAPI PathMakeSystemFolderA(LPCSTR pszPath)
1653 FIXME("%s\n", pszPath);
1657 /*************************************************************************
1658 * PathMakeSystemFolderW [SHLWAPI.@]
1660 BOOL WINAPI PathMakeSystemFolderW(LPCWSTR pszPath)
1662 FIXME("%s\n", debugstr_w(pszPath));
1666 /*************************************************************************
1667 * PathRenameExtensionA [SHLWAPI.@]
1669 BOOL WINAPI PathRenameExtensionA(LPSTR pszPath, LPCSTR pszExt)
1671 FIXME("%s %s\n", pszPath, pszExt);
1675 /*************************************************************************
1676 * PathRenameExtensionW [SHLWAPI.@]
1678 BOOL WINAPI PathRenameExtensionW(LPWSTR pszPath, LPCWSTR pszExt)
1680 FIXME("%s %s\n", debugstr_w(pszPath), debugstr_w(pszExt));
1684 /*************************************************************************
1685 * PathSearchAndQualifyA [SHLWAPI.@]
1687 BOOL WINAPI PathSearchAndQualifyA(
1692 FIXME("%s %s 0x%08x\n", pszPath, pszBuf, cchBuf);
1696 /*************************************************************************
1697 * PathSearchAndQualifyW [SHLWAPI.@]
1699 BOOL WINAPI PathSearchAndQualifyW(
1704 FIXME("%s %s 0x%08x\n", debugstr_w(pszPath), debugstr_w(pszBuf), cchBuf);
1708 /*************************************************************************
1709 * PathSkipRootA [SHLWAPI.@]
1711 LPSTR WINAPI PathSkipRootA(LPCSTR pszPath)
1713 FIXME("%s\n", pszPath);
1714 return (LPSTR)pszPath;
1717 /*************************************************************************
1718 * PathSkipRootW [SHLWAPI.@]
1720 LPWSTR WINAPI PathSkipRootW(LPCWSTR pszPath)
1722 FIXME("%s\n", debugstr_w(pszPath));
1723 return (LPWSTR)pszPath;
1726 /*************************************************************************
1727 * PathCreateFromUrlA [SHLWAPI.@]
1729 HRESULT WINAPI PathCreateFromUrlA(
1735 FIXME("%s %p %p 0x%08lx\n",
1736 pszUrl, pszPath, pcchPath, dwFlags);
1740 /*************************************************************************
1741 * PathCreateFromUrlW [SHLWAPI.@]
1743 HRESULT WINAPI PathCreateFromUrlW(
1749 FIXME("%s %p %p 0x%08lx\n",
1750 debugstr_w(pszUrl), pszPath, pcchPath, dwFlags);
1754 /*************************************************************************
1755 * PathRelativePathToA [SHLWAPI.@]
1757 BOOL WINAPI PathRelativePathToA(
1764 FIXME("%s %s 0x%08lx %s 0x%08lx\n",
1765 pszPath, pszFrom, dwAttrFrom, pszTo, dwAttrTo);
1769 /*************************************************************************
1770 * PathRelativePathToW [SHLWAPI.@]
1772 BOOL WINAPI PathRelativePathToW(
1779 FIXME("%s %s 0x%08lx %s 0x%08lx\n",
1780 debugstr_w(pszPath), debugstr_w(pszFrom), dwAttrFrom, debugstr_w(pszTo), dwAttrTo);
1784 /*************************************************************************
1785 * PathUnmakeSystemFolderA [SHLWAPI.@]
1787 BOOL WINAPI PathUnmakeSystemFolderA(LPCSTR pszPath)
1789 FIXME("%s\n", pszPath);
1793 /*************************************************************************
1794 * PathUnmakeSystemFolderW [SHLWAPI.@]
1796 BOOL WINAPI PathUnmakeSystemFolderW(LPCWSTR pszPath)
1798 FIXME("%s\n", debugstr_w(pszPath));
1803 ########## special ##########
1806 /*************************************************************************
1807 * PathSetDlgItemPathA [SHLWAPI.@]
1810 * use PathCompactPath to make sure, the path fits into the control
1812 BOOL WINAPI PathSetDlgItemPathA(HWND hDlg, int id, LPCSTR pszPath)
1813 { TRACE("%x %x %s\n",hDlg, id, pszPath);
1814 return SetDlgItemTextA(hDlg, id, pszPath);
1817 /*************************************************************************
1818 * PathSetDlgItemPathW [SHLWAPI.@]
1820 BOOL WINAPI PathSetDlgItemPathW(HWND hDlg, int id, LPCWSTR pszPath)
1821 { TRACE("%x %x %s\n",hDlg, id, debugstr_w(pszPath));
1822 return SetDlgItemTextW(hDlg, id, pszPath);