9 #include "wine/unicode.h"
10 #include "wine/undocshell.h"
12 #include "debugtools.h"
14 DEFAULT_DEBUG_CHANNEL(shell);
16 #define isSlash(x) ((x)=='\\' || (x)=='/')
18 ########## Combining and Constructing paths ##########
21 /*************************************************************************
22 * PathAppendA [SHLWAPI.@]
25 * concat path lpszPath2 onto lpszPath1
28 * the resulting path is also canonicalized
30 BOOL WINAPI PathAppendA(
34 TRACE("%s %s\n",lpszPath1, lpszPath2);
35 while (lpszPath2[0]=='\\') lpszPath2++;
36 PathCombineA(lpszPath1,lpszPath1,lpszPath2);
40 /*************************************************************************
41 * PathAppendW [SHLWAPI.@]
43 BOOL WINAPI PathAppendW(
47 TRACE("%s %s\n",debugstr_w(lpszPath1), debugstr_w(lpszPath2));
48 while (lpszPath2[0]=='\\') lpszPath2++;
49 PathCombineW(lpszPath1,lpszPath1,lpszPath2);
53 /*************************************************************************
54 * PathCombineA [SHLWAPI.@]
57 * if lpszFile='.' skip it
58 * szDest can be equal to lpszFile. Thats why we use sTemp
61 * the resulting path is also canonicalized
63 LPSTR WINAPI PathCombineA(
69 TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, lpszDir, lpszFile, lpszFile);
72 if (!lpszFile || !lpszFile[0] || (lpszFile[0]=='.' && !lpszFile[1]) )
74 strcpy(szDest,lpszDir);
78 /* if lpszFile is a complete path don't care about lpszDir */
79 if (PathGetDriveNumberA(lpszFile) != -1)
81 strcpy(szDest,lpszFile);
83 else if (lpszFile[0] == '\\' )
85 strcpy(sTemp,lpszDir);
86 PathStripToRootA(sTemp);
87 strcat(sTemp,lpszFile);
92 strcpy(sTemp,lpszDir);
93 PathAddBackslashA(sTemp);
94 strcat(sTemp,lpszFile);
100 /*************************************************************************
101 * PathCombineW [SHLWAPI.@]
103 LPWSTR WINAPI PathCombineW(
108 WCHAR sTemp[MAX_PATH];
109 TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, debugstr_w(lpszDir),
110 lpszFile, debugstr_w(lpszFile));
113 if (!lpszFile || !lpszFile[0] || (lpszFile[0]==(WCHAR)'.' && !lpszFile[1]) )
115 strcpyW(szDest,lpszDir);
119 /* if lpszFile is a complete path don't care about lpszDir */
120 if (PathGetDriveNumberW(lpszFile) != -1)
122 strcpyW(szDest,lpszFile);
124 else if (lpszFile[0] == (WCHAR)'\\' )
126 strcpyW(sTemp,lpszDir);
127 PathStripToRootW(sTemp);
128 strcatW(sTemp,lpszFile);
129 strcpyW(szDest,sTemp);
133 strcpyW(sTemp,lpszDir);
134 PathAddBackslashW(sTemp);
135 strcatW(sTemp,lpszFile);
136 strcpyW(szDest,sTemp);
141 /*************************************************************************
142 * PathAddBackslashA [SHLWAPI.@]
145 * append \ if there is none
147 LPSTR WINAPI PathAddBackslashA(LPSTR lpszPath)
150 TRACE("%p->%s\n",lpszPath,lpszPath);
152 len = strlen(lpszPath);
153 if (len && lpszPath[len-1]!='\\')
155 lpszPath[len] = '\\';
156 lpszPath[len+1]= 0x00;
157 return lpszPath+len+1;
162 /*************************************************************************
163 * PathAddBackslashW [SHLWAPI.@]
165 LPWSTR WINAPI PathAddBackslashW(LPWSTR lpszPath)
168 TRACE("%p->%s\n",lpszPath,debugstr_w(lpszPath));
170 len = strlenW(lpszPath);
171 if (len && lpszPath[len-1]!=(WCHAR)'\\')
173 lpszPath[len] = (WCHAR)'\\';
174 lpszPath[len+1]= 0x00;
175 return lpszPath+len+1;
180 /*************************************************************************
181 * PathBuildRootA [SHLWAPI.@]
183 LPSTR WINAPI PathBuildRootA(LPSTR lpszPath, int drive)
185 TRACE("%p %i\n",lpszPath, drive);
187 strcpy(lpszPath,"A:\\");
192 /*************************************************************************
193 * PathBuildRootW [SHLWAPI.@]
195 LPWSTR WINAPI PathBuildRootW(LPWSTR lpszPath, int drive)
197 lpszPath[0] = 'A' + drive;
201 TRACE("%p %i\n",debugstr_w(lpszPath), drive);
206 Extracting Component Parts
209 /*************************************************************************
210 * PathFindFileNameA [SHLWAPI.@]
212 LPSTR WINAPI PathFindFileNameA(LPCSTR lpszPath)
214 LPCSTR lastSlash = lpszPath;
216 TRACE("%s\n",lpszPath);
219 if ( isSlash(lpszPath[0]) && lpszPath[1])
220 lastSlash = lpszPath+1;
221 lpszPath = CharNextA(lpszPath);
223 return (LPSTR)lastSlash;
227 /*************************************************************************
228 * PathFindFileNameW [SHLWAPI.@]
230 LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
235 TRACE("%s\n",debugstr_w(wslash));
238 if (((lpszPath[0]=='\\') || (lpszPath[0]==':')) && lpszPath[1] && lpszPath[1]!='\\')
240 lpszPath = CharNextW(lpszPath);
242 return (LPWSTR)wslash;
245 /*************************************************************************
246 * PathFindExtensionA [SHLWAPI.@]
249 * returns pointer to last . in last lpszPath component or at \0.
252 LPSTR WINAPI PathFindExtensionA(LPCSTR lpszPath)
254 LPCSTR lastpoint = NULL;
256 TRACE("%p %s\n",lpszPath,lpszPath);
260 if (*lpszPath=='\\'||*lpszPath==' ')
264 lpszPath = CharNextA(lpszPath);
266 return (LPSTR)(lastpoint?lastpoint:lpszPath);
269 /*************************************************************************
270 * PathFindExtensionW [SHLWAPI.@]
272 LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath)
274 LPCWSTR lastpoint = NULL;
276 TRACE("(%p %s)\n",lpszPath,debugstr_w(lpszPath));
280 if (*lpszPath==(WCHAR)'\\'||*lpszPath==(WCHAR)' ')
282 if (*lpszPath==(WCHAR)'.')
284 lpszPath = CharNextW(lpszPath);
286 return (LPWSTR)(lastpoint?lastpoint:lpszPath);
289 /*************************************************************************
290 * PathGetArgsA [SHLWAPI.@]
293 * look for next arg in string. handle "quoted" strings
294 * returns pointer to argument *AFTER* the space. Or to the \0.
299 LPSTR WINAPI PathGetArgsA(LPCSTR lpszPath)
303 TRACE("%s\n",lpszPath);
307 if ((*lpszPath==' ') && !qflag)
308 return (LPSTR)lpszPath+1;
311 lpszPath = CharNextA(lpszPath);
313 return (LPSTR)lpszPath;
316 /*************************************************************************
317 * PathGetArgsW [SHLWAPI.@]
319 LPWSTR WINAPI PathGetArgsW(LPCWSTR lpszPath)
323 TRACE("%s\n",debugstr_w(lpszPath));
327 if ((*lpszPath==' ') && !qflag)
328 return (LPWSTR)lpszPath+1;
331 lpszPath = CharNextW(lpszPath);
333 return (LPWSTR)lpszPath;
336 /*************************************************************************
337 * PathGetDriveNumberA [SHLWAPI.@]
339 int WINAPI PathGetDriveNumberA(LPCSTR lpszPath)
341 int chr = tolower(lpszPath[0]);
343 TRACE ("%s\n",debugstr_a(lpszPath));
345 if (!lpszPath || lpszPath[1]!=':' || chr < 'a' || chr > 'z') return -1;
346 return tolower(lpszPath[0]) - 'a' ;
349 /*************************************************************************
350 * PathGetDriveNumberW [SHLWAPI.@]
352 int WINAPI PathGetDriveNumberW(LPCWSTR lpszPath)
354 int chr = tolowerW(lpszPath[0]);
356 TRACE ("%s\n",debugstr_w(lpszPath));
358 if (!lpszPath || lpszPath[1]!=':' || chr < 'a' || chr > 'z') return -1;
359 return tolowerW(lpszPath[0]) - 'a' ;
362 /*************************************************************************
363 * PathRemoveFileSpecA [SHLWAPI.@]
366 * truncates passed argument to a valid path
367 * returns if the string was modified or not.
368 * "\foo\xx\foo"-> "\foo\xx"
372 BOOL WINAPI PathRemoveFileSpecA(LPSTR lpszPath)
374 LPSTR cutplace = lpszPath;
377 TRACE("%s\n",lpszPath);
381 while (*lpszPath == '\\') cutplace = ++lpszPath;
385 if(lpszPath[0] == '\\') cutplace = lpszPath;
387 if(lpszPath[0] == ':')
389 cutplace = lpszPath + 1;
390 if (lpszPath[1] == '\\') cutplace++;
393 lpszPath = CharNextA(lpszPath);
394 if (!lpszPath) break;
397 ret = (*cutplace!='\0');
403 /*************************************************************************
404 * PathRemoveFileSpecW [SHLWAPI.@]
406 BOOL WINAPI PathRemoveFileSpecW(LPWSTR lpszPath)
408 LPWSTR cutplace = lpszPath;
411 TRACE("%s\n",debugstr_w(lpszPath));
415 while (*lpszPath == '\\') cutplace = ++lpszPath;
419 if(lpszPath[0] == '\\') cutplace = lpszPath;
421 if(lpszPath[0] == ':')
423 cutplace = lpszPath + 1;
424 if (lpszPath[1] == '\\') cutplace++;
427 lpszPath = CharNextW(lpszPath);
428 if (!lpszPath) break;
431 ret = (*cutplace!='\0');
437 /*************************************************************************
438 * PathStripPathA [SHELLWAPI.@]
441 * removes the path from the beginning of a filename
443 void WINAPI PathStripPathA(LPSTR lpszPath)
445 LPSTR lpszFileName = PathFindFileNameA(lpszPath);
447 TRACE("%s\n", lpszPath);
450 RtlMoveMemory(lpszPath, lpszFileName, strlen(lpszFileName)+1);
453 /*************************************************************************
454 * PathStripPathW [SHELLWAPI.@]
456 void WINAPI PathStripPathW(LPWSTR lpszPath)
458 LPWSTR lpszFileName = PathFindFileNameW(lpszPath);
460 TRACE("%s\n", debugstr_w(lpszPath));
462 RtlMoveMemory(lpszPath, lpszFileName, (strlenW(lpszFileName)+1)*sizeof(WCHAR));
465 /*************************************************************************
466 * PathStripToRootA [SHLWAPI.@]
468 BOOL WINAPI PathStripToRootA(LPSTR lpszPath)
470 TRACE("%s\n", lpszPath);
472 if (!lpszPath) return FALSE;
473 while(!PathIsRootA(lpszPath))
474 if (!PathRemoveFileSpecA(lpszPath)) return FALSE;
478 /*************************************************************************
479 * PathStripToRootW [SHLWAPI.@]
481 BOOL WINAPI PathStripToRootW(LPWSTR lpszPath)
483 TRACE("%s\n", debugstr_w(lpszPath));
485 if (!lpszPath) return FALSE;
486 while(!PathIsRootW(lpszPath))
487 if (!PathRemoveFileSpecW(lpszPath)) return FALSE;
491 /*************************************************************************
492 * PathRemoveArgsA [SHLWAPI.@]
495 void WINAPI PathRemoveArgsA(LPSTR lpszPath)
497 TRACE("%s\n",lpszPath);
501 LPSTR lpszArgs = PathGetArgsA(lpszPath);
504 LPSTR lpszLastChar = CharPrevA(lpszPath, lpszArgs);
505 if(*lpszLastChar==' ') *lpszLastChar = '\0';
510 /*************************************************************************
511 * PathRemoveArgsW [SHLWAPI.@]
513 void WINAPI PathRemoveArgsW(LPWSTR lpszPath)
515 TRACE("%s\n", debugstr_w(lpszPath));
519 LPWSTR lpszArgs = PathGetArgsW(lpszPath);
522 LPWSTR lpszLastChar = CharPrevW(lpszPath, lpszArgs);
523 if(*lpszLastChar==' ') *lpszLastChar = '\0';
528 /*************************************************************************
529 * PathRemoveExtensionA [SHLWAPI.@]
531 void WINAPI PathRemoveExtensionA(LPSTR lpszPath)
533 LPSTR lpszExtension = PathFindExtensionA(lpszPath);
535 TRACE("%s\n", lpszPath);
537 if (lpszExtension) *lpszExtension='\0';
540 /*************************************************************************
541 * PathRemoveExtensionW [SHLWAPI.@]
543 void WINAPI PathRemoveExtensionW(LPWSTR lpszPath)
545 LPWSTR lpszExtension = PathFindExtensionW(lpszPath);
547 TRACE("%s\n", debugstr_w(lpszPath));
549 if (lpszExtension) *lpszExtension='\0';
552 /*************************************************************************
553 * PathRemoveBackslashA [SHLWAPI.@]
555 * If the path ends in a backslash it is replaced by a NULL
556 * and the address of the NULL is returned
558 * the address of the last character is returned.
561 * "c:\": keep backslash
563 LPSTR WINAPI PathRemoveBackslashA( LPSTR lpszPath )
570 len = strlen(lpszPath);
571 szTemp = CharPrevA(lpszPath, lpszPath+len);
572 if (! PathIsRootA(lpszPath))
574 if (*szTemp == '\\') *szTemp = '\0';
580 /*************************************************************************
581 * PathRemoveBackslashW [SHLWAPI.@]
583 LPWSTR WINAPI PathRemoveBackslashW( LPWSTR lpszPath )
586 LPWSTR szTemp = NULL;
590 len = strlenW(lpszPath);
591 szTemp = CharPrevW(lpszPath, lpszPath+len);
592 if (! PathIsRootW(lpszPath))
594 if (*szTemp == '\\') *szTemp = '\0';
605 /*************************************************************************
606 * PathRemoveBlanksA [SHLWAPI.@]
609 * remove spaces from beginning and end of passed string
611 void WINAPI PathRemoveBlanksA(LPSTR str)
619 while (*x==' ') x = CharNextA(x);
620 if (x!=str) strcpy(str,x);
622 while (*x==' ') x = CharPrevA(str, x);
623 if (*x==' ') *x='\0';
627 /*************************************************************************
628 * PathRemoveBlanksW [SHLWAPI.@]
630 void WINAPI PathRemoveBlanksW(LPWSTR str)
634 TRACE("%s\n",debugstr_w(str));
638 while (*x==' ') x = CharNextW(x);
639 if (x!=str) strcpyW(str,x);
640 x=str+strlenW(str)-1;
641 while (*x==' ') x = CharPrevW(str, x);
642 if (*x==' ') *x='\0';
646 /*************************************************************************
647 * PathQuoteSpacesA [SHLWAPI.@]
650 LPSTR WINAPI PathQuoteSpacesA(LPSTR lpszPath)
652 TRACE("%s\n",lpszPath);
654 if(StrChrA(lpszPath,' '))
656 int len = strlen(lpszPath);
657 RtlMoveMemory(lpszPath+1, lpszPath, len);
667 /*************************************************************************
668 * PathQuoteSpacesW [SHLWAPI.@]
670 LPWSTR WINAPI PathQuoteSpacesW(LPWSTR lpszPath)
672 TRACE("%s\n",debugstr_w(lpszPath));
674 if(StrChrW(lpszPath,' '))
676 int len = strlenW(lpszPath);
677 RtlMoveMemory(lpszPath+1, lpszPath, len*sizeof(WCHAR));
687 /*************************************************************************
688 * PathUnquoteSpacesA [SHLWAPI.@]
691 * unquote string (remove ")
693 VOID WINAPI PathUnquoteSpacesA(LPSTR str)
695 DWORD len = strlen(str);
708 /*************************************************************************
709 * PathUnquoteSpacesW [SHLWAPI.@]
711 VOID WINAPI PathUnquoteSpacesW(LPWSTR str)
713 DWORD len = strlenW(str);
715 TRACE("%s\n",debugstr_w(str));
726 /*************************************************************************
727 * PathParseIconLocationA [SHLWAPI.@]
729 int WINAPI PathParseIconLocationA(LPSTR lpszPath)
731 LPSTR lpstrComma = strchr(lpszPath, ',');
733 FIXME("%s stub\n", debugstr_a(lpszPath));
735 if (lpstrComma && lpstrComma[1])
738 /* return atoi(&lpstrComma[1]); FIXME */
741 PathUnquoteSpacesA(lpszPath);
745 /*************************************************************************
746 * PathParseIconLocationW [SHLWAPI.@]
748 int WINAPI PathParseIconLocationW(LPWSTR lpszPath)
750 LPWSTR lpstrComma = strchrW(lpszPath, ',');
752 FIXME("%s stub\n", debugstr_w(lpszPath));
754 if (lpstrComma && lpstrComma[1])
757 /* return _wtoi(&lpstrComma[1]); FIXME */
759 PathUnquoteSpacesW(lpszPath);
764 ########## cleaning and resolving paths ##########
767 /*************************************************************************
768 * PathFindOnPathA [SHLWAPI.@]
770 BOOL WINAPI PathFindOnPathA(LPSTR sFile, LPCSTR sOtherDirs)
772 FIXME("%s %s\n",sFile, sOtherDirs);
776 /*************************************************************************
777 * PathFindOnPathW [SHLWAPI.@]
779 BOOL WINAPI PathFindOnPathW(LPWSTR sFile, LPCWSTR sOtherDirs)
781 FIXME("%s %s\n",debugstr_w(sFile), debugstr_w(sOtherDirs));
785 /*************************************************************************
786 * PathCompactPathExA [SHLWAPI.@]
788 BOOL WINAPI PathCompactPathExA(
794 FIXME("%p %s 0x%08x 0x%08lx\n", pszOut, pszSrc, cchMax, dwFlags);
798 /*************************************************************************
799 * PathCompactPathExW [SHLWAPI.@]
801 BOOL WINAPI PathCompactPathExW(
807 FIXME("%p %s 0x%08x 0x%08lx\n", pszOut, debugstr_w(pszSrc), cchMax, dwFlags);
812 ########## Path Testing ##########
815 /*************************************************************************
816 * PathIsUNCA [SHLWAPI.@]
819 * PathIsUNC(char*path);
821 BOOL WINAPI PathIsUNCA(LPCSTR lpszPath)
823 TRACE("%s\n",lpszPath);
825 return (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\'));
828 /*************************************************************************
829 * PathIsUNCW [SHLWAPI.@]
831 BOOL WINAPI PathIsUNCW(LPCWSTR lpszPath)
833 TRACE("%s\n",debugstr_w(lpszPath));
835 return (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\'));
838 /*************************************************************************
839 * PathIsRelativeA [SHLWAPI.@]
841 BOOL WINAPI PathIsRelativeA (LPCSTR lpszPath)
843 TRACE("lpszPath=%s\n",lpszPath);
845 return (lpszPath && (lpszPath[0]!='\\' && lpszPath[1]!=':'));
848 /*************************************************************************
849 * PathIsRelativeW [SHLWAPI.@]
851 BOOL WINAPI PathIsRelativeW (LPCWSTR lpszPath)
853 TRACE("lpszPath=%s\n",debugstr_w(lpszPath));
855 return (lpszPath && (lpszPath[0]!='\\' && lpszPath[1]!=':'));
858 /*************************************************************************
859 * PathIsRootA [SHLWAPI.@]
862 * TRUE if the path points to a root directory
864 BOOL WINAPI PathIsRootA(LPCSTR lpszPath)
866 TRACE("%s\n",lpszPath);
869 if (lpszPath[1]==':' && lpszPath[2]=='\\' && lpszPath[3]=='\0')
873 if (lpszPath[0]=='\\' && lpszPath[1]=='\0')
876 /* UNC "\\<computer>\<share>" */
877 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
879 int foundbackslash = 0;
883 if (*lpszPath=='\\') foundbackslash++;
884 lpszPath = CharNextA(lpszPath);
886 if (foundbackslash <= 1)
892 /*************************************************************************
893 * PathIsRootW [SHLWAPI.@]
895 BOOL WINAPI PathIsRootW(LPCWSTR lpszPath)
897 TRACE("%s\n",debugstr_w(lpszPath));
900 if (lpszPath[1]==':' && lpszPath[2]=='\\' && lpszPath[3]=='\0')
904 if (lpszPath[0]=='\\' && lpszPath[1]=='\0')
907 /* UNC "\\<computer>\<share>" */
908 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
910 int foundbackslash = 0;
914 if (*lpszPath=='\\') foundbackslash++;
915 lpszPath = CharNextW(lpszPath);
917 if (foundbackslash <= 1)
924 /*************************************************************************
925 * PathIsDirectoryA [SHLWAPI.@]
927 BOOL WINAPI PathIsDirectoryA(LPCSTR lpszPath)
931 TRACE("%s\n", debugstr_a(lpszPath));
933 dwAttr = GetFileAttributesA(lpszPath);
934 return (dwAttr != -1) ? dwAttr & FILE_ATTRIBUTE_DIRECTORY : 0;
937 /*************************************************************************
938 * PathIsDirectoryW [SHLWAPI.@]
940 BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath)
944 TRACE("%s\n", debugstr_w(lpszPath));
946 dwAttr = GetFileAttributesW(lpszPath);
947 return (dwAttr != -1) ? dwAttr & FILE_ATTRIBUTE_DIRECTORY : 0;
950 /*************************************************************************
951 * PathFileExistsA [SHLWAPI.@]
954 * file_exists(char *fn);
956 BOOL WINAPI PathFileExistsA(LPCSTR lpszPath)
958 TRACE("%s\n",lpszPath);
959 return (GetFileAttributesA(lpszPath)!=-1);
962 /*************************************************************************
963 * PathFileExistsW [SHLWAPI.@]
965 BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
967 TRACE("%s\n",debugstr_w(lpszPath));
968 return (GetFileAttributesW(lpszPath)!=-1);
971 /*************************************************************************
972 * PathMatchSingleMaskA [internal]
975 * internal (used by PathMatchSpec)
977 static BOOL PathMatchSingleMaskA(LPCSTR name, LPCSTR mask)
979 while (*name && *mask && *mask!=';')
985 if (PathMatchSingleMaskA(name,mask+1)) return 1; /* try substrings */
989 if (toupper(*mask)!=toupper(*name) && *mask!='?') return 0;
990 name = CharNextA(name);
991 mask = CharNextA(mask);
995 while (*mask=='*') mask++;
996 if (!*mask || *mask==';') return 1;
1001 /*************************************************************************
1002 * PathMatchSingleMaskW [internal]
1004 static BOOL PathMatchSingleMaskW(LPCWSTR name, LPCWSTR mask)
1006 while (*name && *mask && *mask!=';')
1012 if (PathMatchSingleMaskW(name,mask+1)) return 1; /* try substrings */
1016 if (toupperW(*mask)!=toupperW(*name) && *mask!='?') return 0;
1017 name = CharNextW(name);
1018 mask = CharNextW(mask);
1022 while (*mask=='*') mask++;
1023 if (!*mask || *mask==';') return 1;
1027 /*************************************************************************
1028 * PathMatchSpecA [SHLWAPI.@]
1031 * used from COMDLG32
1033 BOOL WINAPI PathMatchSpecA(LPCSTR name, LPCSTR mask)
1035 TRACE("%s %s\n",name,mask);
1037 if (!lstrcmpA( mask, "*.*" )) return 1; /* we don't require a period */
1041 if (PathMatchSingleMaskA(name,mask)) return 1; /* helper function */
1042 while (*mask && *mask!=';') mask = CharNextA(mask);
1046 while (*mask==' ') mask++; /* masks may be separated by "; " */
1052 /*************************************************************************
1053 * PathMatchSpecW [SHLWAPI.@]
1055 BOOL WINAPI PathMatchSpecW(LPCWSTR name, LPCWSTR mask)
1057 static const WCHAR stemp[] = { '*','.','*',0 };
1058 TRACE("%s %s\n",debugstr_w(name),debugstr_w(mask));
1060 if (!lstrcmpW( mask, stemp )) return 1; /* we don't require a period */
1064 if (PathMatchSingleMaskW(name,mask)) return 1; /* helper function */
1065 while (*mask && *mask!=';') mask = CharNextW(mask);
1069 while (*mask==' ') mask++; /* masks may be separated by "; " */
1075 /*************************************************************************
1076 * PathIsSameRootA [SHLWAPI.@]
1079 * what to do with "\path" ??
1081 BOOL WINAPI PathIsSameRootA(LPCSTR lpszPath1, LPCSTR lpszPath2)
1083 TRACE("%s %s\n", lpszPath1, lpszPath2);
1085 if (PathIsRelativeA(lpszPath1) || PathIsRelativeA(lpszPath2)) return FALSE;
1088 if ( toupper(lpszPath1[0])==toupper(lpszPath2[0]) &&
1089 lpszPath1[1]==':' && lpszPath2[1]==':' &&
1090 lpszPath1[2]=='\\' && lpszPath2[2]=='\\')
1094 if (lpszPath1[0]=='\\' && lpszPath2[0]=='\\' &&
1095 lpszPath1[1]=='\\' && lpszPath2[1]=='\\')
1097 int pos=2, bsfound=0;
1098 while (lpszPath1[pos] && lpszPath2[pos] &&
1099 (lpszPath1[pos] == lpszPath2[pos]))
1101 if (lpszPath1[pos]=='\\') bsfound++;
1102 if (bsfound == 2) return TRUE;
1103 pos++; /* fixme: use CharNext*/
1105 return (lpszPath1[pos] == lpszPath2[pos]);
1110 /*************************************************************************
1111 * PathIsSameRootW [SHLWAPI.@]
1113 BOOL WINAPI PathIsSameRootW(LPCWSTR lpszPath1, LPCWSTR lpszPath2)
1115 TRACE("%s %s\n", debugstr_w(lpszPath1), debugstr_w(lpszPath2));
1117 if (PathIsRelativeW(lpszPath1) || PathIsRelativeW(lpszPath2)) return FALSE;
1120 if ( toupperW(lpszPath1[0])==toupperW(lpszPath2[0]) &&
1121 lpszPath1[1]==':' && lpszPath2[1]==':' &&
1122 lpszPath1[2]=='\\' && lpszPath2[2]=='\\')
1126 if (lpszPath1[0]=='\\' && lpszPath2[0]=='\\' &&
1127 lpszPath1[1]=='\\' && lpszPath2[1]=='\\')
1129 int pos=2, bsfound=0;
1130 while (lpszPath1[pos] && lpszPath2[pos] &&
1131 (lpszPath1[pos] == lpszPath2[pos]))
1133 if (lpszPath1[pos]=='\\') bsfound++;
1134 if (bsfound == 2) return TRUE;
1135 pos++;/* fixme: use CharNext*/
1137 return (lpszPath1[pos] == lpszPath2[pos]);
1142 /*************************************************************************
1145 BOOL WINAPI PathIsURLA(LPCSTR lpstrPath)
1149 static LPSTR SupportedProtocol[] =
1150 {"http","https","ftp","gopher","file","mailto",NULL};
1152 if(!lpstrPath) return FALSE;
1155 lpstrRes = strchr(lpstrPath,':');
1156 if(!lpstrRes) return FALSE;
1157 iSize = lpstrRes - lpstrPath;
1159 while(SupportedProtocol[i])
1161 if (iSize == strlen(SupportedProtocol[i]))
1162 if(!strncasecmp(lpstrPath, SupportedProtocol[i], iSize))
1170 /*************************************************************************
1173 BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
1177 static WCHAR SupportedProtocol[7][7] =
1178 {{'h','t','t','p','\0'},{'h','t','t','p','s','\0'},{'f','t','p','\0'},
1179 {'g','o','p','h','e','r','\0'},{'f','i','l','e','\0'},
1180 {'m','a','i','l','t','o','\0'},{0}};
1182 if(!lpstrPath) return FALSE;
1185 lpstrRes = strchrW(lpstrPath,':');
1186 if(!lpstrRes) return FALSE;
1187 iSize = lpstrRes - lpstrPath;
1189 while(SupportedProtocol[i])
1191 if (iSize == strlenW(SupportedProtocol[i]))
1192 if(!strncmpiW(lpstrPath, SupportedProtocol[i], iSize))
1201 /*************************************************************************
1202 * PathIsContentTypeA [SHLWAPI.@]
1204 BOOL WINAPI PathIsContentTypeA(LPCSTR pszPath, LPCSTR pszContentType)
1206 FIXME("%s %s\n", pszPath, pszContentType);
1210 /*************************************************************************
1211 * PathIsContentTypeW [SHLWAPI.@]
1213 BOOL WINAPI PathIsContentTypeW(LPCWSTR pszPath, LPCWSTR pszContentType)
1215 FIXME("%s %s\n", debugstr_w(pszPath), debugstr_w(pszContentType));
1219 /*************************************************************************
1220 * PathIsFileSpecA [SHLWAPI.@]
1222 BOOL WINAPI PathIsFileSpecA(LPCSTR pszPath)
1224 FIXME("%s\n", pszPath);
1228 /*************************************************************************
1229 * PathIsFileSpecW [SHLWAPI.@]
1231 BOOL WINAPI PathIsFileSpecW(LPCWSTR pszPath)
1233 FIXME("%s\n", debugstr_w(pszPath));
1237 /*************************************************************************
1238 * PathIsPrefixA [SHLWAPI.@]
1240 BOOL WINAPI PathIsPrefixA(LPCSTR pszPrefix, LPCSTR pszPath)
1242 FIXME("%s %s\n", pszPrefix, pszPath);
1246 /*************************************************************************
1247 * PathIsPrefixW [SHLWAPI.@]
1249 BOOL WINAPI PathIsPrefixW(LPCWSTR pszPrefix, LPCWSTR pszPath)
1251 FIXME("%s %s\n", debugstr_w(pszPrefix), debugstr_w(pszPath));
1255 /*************************************************************************
1256 * PathIsSystemFolderA [SHLWAPI.@]
1258 BOOL WINAPI PathIsSystemFolderA(LPCSTR pszPath, DWORD dwAttrb)
1260 FIXME("%s 0x%08lx\n", pszPath, dwAttrb);
1264 /*************************************************************************
1265 * PathIsSystemFolderW [SHLWAPI.@]
1267 BOOL WINAPI PathIsSystemFolderW(LPCWSTR pszPath, DWORD dwAttrb)
1269 FIXME("%s 0x%08lx\n", debugstr_w(pszPath), dwAttrb);
1273 /*************************************************************************
1274 * PathIsUNCServerA [SHLWAPI.@]
1276 BOOL WINAPI PathIsUNCServerA(
1279 FIXME("%s\n", pszPath);
1283 /*************************************************************************
1284 * PathIsUNCServerW [SHLWAPI.@]
1286 BOOL WINAPI PathIsUNCServerW(
1289 FIXME("%s\n", debugstr_w(pszPath));
1293 /*************************************************************************
1294 * PathIsUNCServerShareA [SHLWAPI.@]
1296 BOOL WINAPI PathIsUNCServerShareA(
1299 FIXME("%s\n", pszPath);
1303 /*************************************************************************
1304 * PathIsUNCServerShareW [SHLWAPI.@]
1306 BOOL WINAPI PathIsUNCServerShareW(
1309 FIXME("%s\n", debugstr_w(pszPath));
1313 /*************************************************************************
1314 * PathCanonicalizeA [SHLWAPI.@]
1317 * returnvalue, use CharNext
1320 BOOL WINAPI PathCanonicalizeA(LPSTR pszBuf, LPCSTR pszPath)
1322 int OffsetMin = 0, OffsetSrc = 0, OffsetDst = 0, LenSrc = strlen(pszPath);
1323 BOOL bModifyed = FALSE;
1325 TRACE("%p %s\n", pszBuf, pszPath);
1327 pszBuf[OffsetDst]='\0';
1329 /* keep the root of the path */
1330 if( LenSrc && (pszPath[OffsetSrc]=='\\'))
1332 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1334 else if ( (LenSrc >= 2) && (pszPath[OffsetSrc+1] == ':'))
1336 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1337 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1338 if (LenSrc && (pszPath[OffsetSrc] == '\\'))
1340 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1341 if (LenSrc == 1 && pszPath[OffsetSrc]=='.')
1344 OffsetSrc++; LenSrc--; bModifyed = TRUE;
1346 else if (LenSrc == 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='.')
1349 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1354 /* ".\" at the beginning of the path */
1355 if (LenSrc >= 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='\\')
1357 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1362 if((LenSrc>=3) && (pszPath[OffsetSrc]=='\\') && (pszPath[OffsetSrc+1]=='.') && (pszPath[OffsetSrc+2]=='.'))
1364 /* "\.." found, go one deeper */
1365 while((OffsetDst > OffsetMin) && (pszBuf[OffsetDst]!='\\')) OffsetDst--;
1366 OffsetSrc += 3; LenSrc -= 3; bModifyed = TRUE;
1367 if(OffsetDst == OffsetMin && pszPath[OffsetSrc]=='\\') OffsetSrc++;
1368 pszBuf[OffsetDst] = '\0'; /* important for \..\.. */
1370 else if(LenSrc>=2 && pszPath[OffsetSrc]=='\\' && pszPath[OffsetSrc+1]=='.' )
1372 /* "\." found, skip it */
1373 OffsetSrc += 2; LenSrc-=2; bModifyed = TRUE;
1377 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; LenSrc--;
1380 pszBuf[OffsetDst] = '\0';
1381 TRACE("-- %s %u\n", pszBuf, bModifyed);
1386 /*************************************************************************
1387 * PathCanonicalizeW [SHLWAPI.@]
1390 * returnvalue, use CharNext
1392 BOOL WINAPI PathCanonicalizeW(LPWSTR pszBuf, LPCWSTR pszPath)
1394 int OffsetMin = 0, OffsetSrc = 0, OffsetDst = 0, LenSrc = strlenW(pszPath);
1395 BOOL bModifyed = FALSE;
1397 TRACE("%p %s\n", pszBuf, debugstr_w(pszPath));
1399 pszBuf[OffsetDst]='\0';
1401 /* keep the root of the path */
1402 if( LenSrc && (pszPath[OffsetSrc]=='\\'))
1404 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1406 else if ( (LenSrc >= 2) && (pszPath[OffsetSrc+1] == ':'))
1408 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1409 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1410 if (LenSrc && (pszPath[OffsetSrc] == '\\'))
1412 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1413 if (LenSrc == 1 && pszPath[OffsetSrc]=='.')
1416 OffsetSrc++; LenSrc--; bModifyed = TRUE;
1418 else if (LenSrc == 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='.')
1421 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1426 /* ".\" at the beginning of the path */
1427 if (LenSrc >= 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='\\')
1429 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1434 if((LenSrc>=3) && (pszPath[OffsetSrc]=='\\') && (pszPath[OffsetSrc+1]=='.') && (pszPath[OffsetSrc+2]=='.'))
1436 /* "\.." found, go one deeper */
1437 while((OffsetDst > OffsetMin) && (pszBuf[OffsetDst]!='\\')) OffsetDst--;
1438 OffsetSrc += 3; LenSrc -= 3; bModifyed = TRUE;
1439 if(OffsetDst == OffsetMin && pszPath[OffsetSrc]=='\\') OffsetSrc++;
1440 pszBuf[OffsetDst] = '\0'; /* important for \..\.. */
1442 else if(LenSrc>=2 && pszPath[OffsetSrc]=='\\' && pszPath[OffsetSrc+1]=='.' )
1444 /* "\." found, skip it */
1445 OffsetSrc += 2; LenSrc-=2; bModifyed = TRUE;
1449 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; LenSrc--;
1452 pszBuf[OffsetDst] = '\0';
1453 TRACE("-- %s %u\n", debugstr_w(pszBuf), bModifyed);
1457 /*************************************************************************
1458 * PathFindNextComponentA [SHLWAPI.@]
1463 * aa "" (pointer to traling NULL)
1464 * aa\ "" (pointer to traling NULL)
1465 * aa\\ "" (pointer to traling NULL)
1472 LPSTR WINAPI PathFindNextComponentA(LPCSTR pszPath)
1476 TRACE("%s\n", pszPath);
1478 if(!pszPath || !*pszPath) return NULL;
1479 if(!(pos = StrChrA(pszPath, '\\')))
1480 return (LPSTR) pszPath + strlen(pszPath);
1482 if(pos[0] == '\\') pos++;
1486 /*************************************************************************
1487 * PathFindNextComponentW [SHLWAPI.@]
1489 LPWSTR WINAPI PathFindNextComponentW(LPCWSTR pszPath)
1493 TRACE("%s\n", debugstr_w(pszPath));
1495 if(!pszPath || !*pszPath) return NULL;
1496 if (!(pos = StrChrW(pszPath, '\\')))
1497 return (LPWSTR) pszPath + strlenW(pszPath);
1499 if(pos[0] == '\\') pos++;
1503 /*************************************************************************
1504 * PathAddExtensionA [SHLWAPI.@]
1507 * it adds never a dot
1510 BOOL WINAPI PathAddExtensionA(
1512 LPCSTR pszExtension)
1516 if (*(PathFindExtensionA(pszPath))) return FALSE;
1518 if (!pszExtension || *pszExtension=='\0')
1519 strcat(pszPath, "exe");
1521 strcat(pszPath, pszExtension);
1527 /*************************************************************************
1528 * PathAddExtensionW [SHLWAPI.@]
1530 BOOL WINAPI PathAddExtensionW(
1532 LPCWSTR pszExtension)
1534 static const WCHAR ext[] = { 'e','x','e',0 };
1538 if (*(PathFindExtensionW(pszPath))) return FALSE;
1540 if (!pszExtension || *pszExtension=='\0')
1541 strcatW(pszPath, ext);
1543 strcatW(pszPath, pszExtension);
1549 /*************************************************************************
1550 * PathMakePrettyA [SHLWAPI.@]
1552 BOOL WINAPI PathMakePrettyA(
1555 FIXME("%s\n", lpPath);
1559 /*************************************************************************
1560 * PathMakePrettyW [SHLWAPI.@]
1562 BOOL WINAPI PathMakePrettyW(
1565 FIXME("%s\n", debugstr_w(lpPath));
1570 /*************************************************************************
1571 * PathCommonPrefixA [SHLWAPI.@]
1573 int WINAPI PathCommonPrefixA(
1578 FIXME("%s %s %p\n", pszFile1, pszFile2, achPath);
1582 /*************************************************************************
1583 * PathCommonPrefixW [SHLWAPI.@]
1585 int WINAPI PathCommonPrefixW(
1590 FIXME("%s %s %p\n", debugstr_w(pszFile1), debugstr_w(pszFile2),achPath );
1594 /*************************************************************************
1595 * PathCompactPathA [SHLWAPI.@]
1597 BOOL WINAPI PathCompactPathA(HDC hDC, LPSTR pszPath, UINT dx)
1599 FIXME("0x%08x %s 0x%08x\n", hDC, pszPath, dx);
1603 /*************************************************************************
1604 * PathCompactPathW [SHLWAPI.@]
1606 BOOL WINAPI PathCompactPathW(HDC hDC, LPWSTR pszPath, UINT dx)
1608 FIXME("0x%08x %s 0x%08x\n", hDC, debugstr_w(pszPath), dx);
1612 /*************************************************************************
1613 * PathGetCharTypeA [SHLWAPI.@]
1615 UINT WINAPI PathGetCharTypeA(UCHAR ch)
1621 /*************************************************************************
1622 * PathGetCharTypeW [SHLWAPI.@]
1624 UINT WINAPI PathGetCharTypeW(WCHAR ch)
1630 /*************************************************************************
1631 * PathMakeSystemFolderA [SHLWAPI.@]
1633 BOOL WINAPI PathMakeSystemFolderA(LPCSTR pszPath)
1635 FIXME("%s\n", pszPath);
1639 /*************************************************************************
1640 * PathMakeSystemFolderW [SHLWAPI.@]
1642 BOOL WINAPI PathMakeSystemFolderW(LPCWSTR pszPath)
1644 FIXME("%s\n", debugstr_w(pszPath));
1648 /*************************************************************************
1649 * PathRenameExtensionA [SHLWAPI.@]
1651 BOOL WINAPI PathRenameExtensionA(LPSTR pszPath, LPCSTR pszExt)
1653 FIXME("%s %s\n", pszPath, pszExt);
1657 /*************************************************************************
1658 * PathRenameExtensionW [SHLWAPI.@]
1660 BOOL WINAPI PathRenameExtensionW(LPWSTR pszPath, LPCWSTR pszExt)
1662 FIXME("%s %s\n", debugstr_w(pszPath), debugstr_w(pszExt));
1666 /*************************************************************************
1667 * PathSearchAndQualifyA [SHLWAPI.@]
1669 BOOL WINAPI PathSearchAndQualifyA(
1674 FIXME("%s %s 0x%08x\n", pszPath, pszBuf, cchBuf);
1678 /*************************************************************************
1679 * PathSearchAndQualifyW [SHLWAPI.@]
1681 BOOL WINAPI PathSearchAndQualifyW(
1686 FIXME("%s %s 0x%08x\n", debugstr_w(pszPath), debugstr_w(pszBuf), cchBuf);
1690 /*************************************************************************
1691 * PathSkipRootA [SHLWAPI.@]
1693 LPSTR WINAPI PathSkipRootA(LPCSTR pszPath)
1695 FIXME("%s\n", pszPath);
1696 return (LPSTR)pszPath;
1699 /*************************************************************************
1700 * PathSkipRootW [SHLWAPI.@]
1702 LPWSTR WINAPI PathSkipRootW(LPCWSTR pszPath)
1704 FIXME("%s\n", debugstr_w(pszPath));
1705 return (LPWSTR)pszPath;
1708 /*************************************************************************
1709 * PathCreateFromUrlA [SHLWAPI.@]
1711 HRESULT WINAPI PathCreateFromUrlA(
1717 FIXME("%s %p %p 0x%08lx\n",
1718 pszUrl, pszPath, pcchPath, dwFlags);
1722 /*************************************************************************
1723 * PathCreateFromUrlW [SHLWAPI.@]
1725 HRESULT WINAPI PathCreateFromUrlW(
1731 FIXME("%s %p %p 0x%08lx\n",
1732 debugstr_w(pszUrl), pszPath, pcchPath, dwFlags);
1736 /*************************************************************************
1737 * PathRelativePathToA [SHLWAPI.@]
1739 BOOL WINAPI PathRelativePathToA(
1746 FIXME("%s %s 0x%08lx %s 0x%08lx\n",
1747 pszPath, pszFrom, dwAttrFrom, pszTo, dwAttrTo);
1751 /*************************************************************************
1752 * PathRelativePathToW [SHLWAPI.@]
1754 BOOL WINAPI PathRelativePathToW(
1761 FIXME("%s %s 0x%08lx %s 0x%08lx\n",
1762 debugstr_w(pszPath), debugstr_w(pszFrom), dwAttrFrom, debugstr_w(pszTo), dwAttrTo);
1766 /*************************************************************************
1767 * PathUnmakeSystemFolderA [SHLWAPI.@]
1769 BOOL WINAPI PathUnmakeSystemFolderA(LPCSTR pszPath)
1771 FIXME("%s\n", pszPath);
1775 /*************************************************************************
1776 * PathUnmakeSystemFolderW [SHLWAPI.@]
1778 BOOL WINAPI PathUnmakeSystemFolderW(LPCWSTR pszPath)
1780 FIXME("%s\n", debugstr_w(pszPath));
1785 ########## special ##########
1788 /*************************************************************************
1789 * PathSetDlgItemPathA [SHLWAPI.@]
1792 * use PathCompactPath to make sure, the path fits into the control
1794 BOOL WINAPI PathSetDlgItemPathA(HWND hDlg, int id, LPCSTR pszPath)
1795 { TRACE("%x %x %s\n",hDlg, id, pszPath);
1796 return SetDlgItemTextA(hDlg, id, pszPath);
1799 /*************************************************************************
1800 * PathSetDlgItemPathW [SHLWAPI.@]
1802 BOOL WINAPI PathSetDlgItemPathW(HWND hDlg, int id, LPCWSTR pszPath)
1803 { TRACE("%x %x %s\n",hDlg, id, debugstr_w(pszPath));
1804 return SetDlgItemTextW(hDlg, id, pszPath);