10 #include "wine/unicode.h"
15 #define NO_SHLWAPI_STREAM
17 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(shell);
22 INT __cdecl _wtoi(LPWSTR string);
24 #define isSlash(x) ((x)=='\\' || (x)=='/')
26 ########## Combining and Constructing paths ##########
29 /*************************************************************************
30 * PathAppendA [SHLWAPI.@]
33 * concat path lpszPath2 onto lpszPath1
36 * the resulting path is also canonicalized
38 BOOL WINAPI PathAppendA(
42 TRACE("%s %s\n",lpszPath1, lpszPath2);
43 while (lpszPath2[0]=='\\') lpszPath2++;
44 PathCombineA(lpszPath1,lpszPath1,lpszPath2);
48 /*************************************************************************
49 * PathAppendW [SHLWAPI.@]
51 BOOL WINAPI PathAppendW(
55 TRACE("%s %s\n",debugstr_w(lpszPath1), debugstr_w(lpszPath2));
56 while (lpszPath2[0]=='\\') lpszPath2++;
57 PathCombineW(lpszPath1,lpszPath1,lpszPath2);
61 /*************************************************************************
62 * PathCombineA [SHLWAPI.@]
65 * if lpszFile='.' skip it
66 * szDest can be equal to lpszFile. Thats why we use sTemp
69 * the resulting path is also canonicalized
71 LPSTR WINAPI PathCombineA(
77 TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, lpszDir, lpszFile, lpszFile);
80 if (!lpszFile || !lpszFile[0] || (lpszFile[0]=='.' && !lpszFile[1]) )
82 strcpy(szDest,lpszDir);
86 /* if lpszFile is a complete path don't care about lpszDir */
87 if (PathGetDriveNumberA(lpszFile) != -1)
89 strcpy(szDest,lpszFile);
91 else if (lpszFile[0] == '\\' )
93 strcpy(sTemp,lpszDir);
94 PathStripToRootA(sTemp);
95 strcat(sTemp,lpszFile);
100 strcpy(sTemp,lpszDir);
101 PathAddBackslashA(sTemp);
102 strcat(sTemp,lpszFile);
103 strcpy(szDest,sTemp);
108 /*************************************************************************
109 * PathCombineW [SHLWAPI.@]
111 LPWSTR WINAPI PathCombineW(
116 WCHAR sTemp[MAX_PATH];
117 TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, debugstr_w(lpszDir),
118 lpszFile, debugstr_w(lpszFile));
121 if (!lpszFile || !lpszFile[0] || (lpszFile[0]==(WCHAR)'.' && !lpszFile[1]) )
123 strcpyW(szDest,lpszDir);
127 /* if lpszFile is a complete path don't care about lpszDir */
128 if (PathGetDriveNumberW(lpszFile) != -1)
130 strcpyW(szDest,lpszFile);
132 else if (lpszFile[0] == (WCHAR)'\\' )
134 strcpyW(sTemp,lpszDir);
135 PathStripToRootW(sTemp);
136 strcatW(sTemp,lpszFile);
137 strcpyW(szDest,sTemp);
141 strcpyW(sTemp,lpszDir);
142 PathAddBackslashW(sTemp);
143 strcatW(sTemp,lpszFile);
144 strcpyW(szDest,sTemp);
149 /*************************************************************************
150 * PathAddBackslashA [SHLWAPI.@]
153 * append \ if there is none
155 LPSTR WINAPI PathAddBackslashA(LPSTR lpszPath)
158 TRACE("%p->%s\n",lpszPath,lpszPath);
160 len = strlen(lpszPath);
161 if (len && lpszPath[len-1]!='\\')
163 lpszPath[len] = '\\';
164 lpszPath[len+1]= 0x00;
165 return lpszPath+len+1;
170 /*************************************************************************
171 * PathAddBackslashW [SHLWAPI.@]
173 LPWSTR WINAPI PathAddBackslashW(LPWSTR lpszPath)
176 TRACE("%p->%s\n",lpszPath,debugstr_w(lpszPath));
178 len = strlenW(lpszPath);
179 if (len && lpszPath[len-1]!=(WCHAR)'\\')
181 lpszPath[len] = (WCHAR)'\\';
182 lpszPath[len+1]= 0x00;
183 return lpszPath+len+1;
188 /*************************************************************************
189 * PathBuildRootA [SHLWAPI.@]
191 LPSTR WINAPI PathBuildRootA(LPSTR lpszPath, int drive)
193 TRACE("%p %i\n",lpszPath, drive);
195 strcpy(lpszPath,"A:\\");
200 /*************************************************************************
201 * PathBuildRootW [SHLWAPI.@]
203 LPWSTR WINAPI PathBuildRootW(LPWSTR lpszPath, int drive)
205 lpszPath[0] = 'A' + drive;
209 TRACE("%p %i\n",debugstr_w(lpszPath), drive);
214 Extracting Component Parts
217 /*************************************************************************
218 * PathFindFileNameA [SHLWAPI.@]
220 LPSTR WINAPI PathFindFileNameA(LPCSTR lpszPath)
222 LPCSTR lastSlash = lpszPath;
224 TRACE("%s\n",lpszPath);
227 if ( isSlash(lpszPath[0]) && lpszPath[1])
228 lastSlash = lpszPath+1;
229 lpszPath = CharNextA(lpszPath);
231 return (LPSTR)lastSlash;
235 /*************************************************************************
236 * PathFindFileNameW [SHLWAPI.@]
238 LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
243 TRACE("%s\n",debugstr_w(wslash));
246 if (((lpszPath[0]=='\\') || (lpszPath[0]==':')) && lpszPath[1] && lpszPath[1]!='\\')
248 lpszPath = CharNextW(lpszPath);
250 return (LPWSTR)wslash;
253 /*************************************************************************
254 * PathFindExtensionA [SHLWAPI.@]
257 * returns pointer to last . in last lpszPath component or at \0.
260 LPSTR WINAPI PathFindExtensionA(LPCSTR lpszPath)
262 LPCSTR lastpoint = NULL;
264 TRACE("%p %s\n",lpszPath,lpszPath);
268 if (*lpszPath=='\\'||*lpszPath==' ')
272 lpszPath = CharNextA(lpszPath);
274 return (LPSTR)(lastpoint?lastpoint:lpszPath);
277 /*************************************************************************
278 * PathFindExtensionW [SHLWAPI.@]
280 LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath)
282 LPCWSTR lastpoint = NULL;
284 TRACE("(%p %s)\n",lpszPath,debugstr_w(lpszPath));
288 if (*lpszPath==(WCHAR)'\\'||*lpszPath==(WCHAR)' ')
290 if (*lpszPath==(WCHAR)'.')
292 lpszPath = CharNextW(lpszPath);
294 return (LPWSTR)(lastpoint?lastpoint:lpszPath);
297 /*************************************************************************
298 * PathGetArgsA [SHLWAPI.@]
301 * look for next arg in string. handle "quoted" strings
302 * returns pointer to argument *AFTER* the space. Or to the \0.
307 LPSTR WINAPI PathGetArgsA(LPCSTR lpszPath)
311 TRACE("%s\n",lpszPath);
315 if ((*lpszPath==' ') && !qflag)
316 return (LPSTR)lpszPath+1;
319 lpszPath = CharNextA(lpszPath);
321 return (LPSTR)lpszPath;
324 /*************************************************************************
325 * PathGetArgsW [SHLWAPI.@]
327 LPWSTR WINAPI PathGetArgsW(LPCWSTR lpszPath)
331 TRACE("%s\n",debugstr_w(lpszPath));
335 if ((*lpszPath==' ') && !qflag)
336 return (LPWSTR)lpszPath+1;
339 lpszPath = CharNextW(lpszPath);
341 return (LPWSTR)lpszPath;
344 /*************************************************************************
345 * PathGetDriveNumberA [SHLWAPI.@]
347 int WINAPI PathGetDriveNumberA(LPCSTR lpszPath)
349 int chr = tolower(lpszPath[0]);
351 TRACE ("%s\n",debugstr_a(lpszPath));
353 if (!lpszPath || lpszPath[1]!=':' || chr < 'a' || chr > 'z') return -1;
354 return tolower(lpszPath[0]) - 'a' ;
357 /*************************************************************************
358 * PathGetDriveNumberW [SHLWAPI.@]
360 int WINAPI PathGetDriveNumberW(LPCWSTR lpszPath)
362 int chr = tolowerW(lpszPath[0]);
364 TRACE ("%s\n",debugstr_w(lpszPath));
366 if (!lpszPath || lpszPath[1]!=':' || chr < 'a' || chr > 'z') return -1;
367 return tolowerW(lpszPath[0]) - 'a' ;
370 /*************************************************************************
371 * PathRemoveFileSpecA [SHLWAPI.@]
374 * truncates passed argument to a valid path
375 * returns if the string was modified or not.
376 * "\foo\xx\foo"-> "\foo\xx"
380 BOOL WINAPI PathRemoveFileSpecA(LPSTR lpszPath)
382 LPSTR cutplace = lpszPath;
385 TRACE("%s\n",lpszPath);
389 while (*lpszPath == '\\') cutplace = ++lpszPath;
393 if(lpszPath[0] == '\\') cutplace = lpszPath;
395 if(lpszPath[0] == ':')
397 cutplace = lpszPath + 1;
398 if (lpszPath[1] == '\\') cutplace++;
401 lpszPath = CharNextA(lpszPath);
402 if (!lpszPath) break;
405 ret = (*cutplace!='\0');
411 /*************************************************************************
412 * PathRemoveFileSpecW [SHLWAPI.@]
414 BOOL WINAPI PathRemoveFileSpecW(LPWSTR lpszPath)
416 LPWSTR cutplace = lpszPath;
419 TRACE("%s\n",debugstr_w(lpszPath));
423 while (*lpszPath == '\\') cutplace = ++lpszPath;
427 if(lpszPath[0] == '\\') cutplace = lpszPath;
429 if(lpszPath[0] == ':')
431 cutplace = lpszPath + 1;
432 if (lpszPath[1] == '\\') cutplace++;
435 lpszPath = CharNextW(lpszPath);
436 if (!lpszPath) break;
439 ret = (*cutplace!='\0');
445 /*************************************************************************
446 * PathStripPathA [SHLWAPI.@]
449 * removes the path from the beginning of a filename
451 void WINAPI PathStripPathA(LPSTR lpszPath)
453 LPSTR lpszFileName = PathFindFileNameA(lpszPath);
455 TRACE("%s\n", lpszPath);
458 RtlMoveMemory(lpszPath, lpszFileName, strlen(lpszFileName)+1);
461 /*************************************************************************
462 * PathStripPathW [SHLWAPI.@]
464 void WINAPI PathStripPathW(LPWSTR lpszPath)
466 LPWSTR lpszFileName = PathFindFileNameW(lpszPath);
468 TRACE("%s\n", debugstr_w(lpszPath));
470 RtlMoveMemory(lpszPath, lpszFileName, (strlenW(lpszFileName)+1)*sizeof(WCHAR));
473 /*************************************************************************
474 * PathStripToRootA [SHLWAPI.@]
476 BOOL WINAPI PathStripToRootA(LPSTR lpszPath)
478 TRACE("%s\n", lpszPath);
480 if (!lpszPath) return FALSE;
481 while(!PathIsRootA(lpszPath))
482 if (!PathRemoveFileSpecA(lpszPath)) return FALSE;
486 /*************************************************************************
487 * PathStripToRootW [SHLWAPI.@]
489 BOOL WINAPI PathStripToRootW(LPWSTR lpszPath)
491 TRACE("%s\n", debugstr_w(lpszPath));
493 if (!lpszPath) return FALSE;
494 while(!PathIsRootW(lpszPath))
495 if (!PathRemoveFileSpecW(lpszPath)) return FALSE;
499 /*************************************************************************
500 * PathRemoveArgsA [SHLWAPI.@]
503 void WINAPI PathRemoveArgsA(LPSTR lpszPath)
505 TRACE("%s\n",lpszPath);
509 LPSTR lpszArgs = PathGetArgsA(lpszPath);
512 LPSTR lpszLastChar = CharPrevA(lpszPath, lpszArgs);
513 if(*lpszLastChar==' ') *lpszLastChar = '\0';
518 /*************************************************************************
519 * PathRemoveArgsW [SHLWAPI.@]
521 void WINAPI PathRemoveArgsW(LPWSTR lpszPath)
523 TRACE("%s\n", debugstr_w(lpszPath));
527 LPWSTR lpszArgs = PathGetArgsW(lpszPath);
530 LPWSTR lpszLastChar = CharPrevW(lpszPath, lpszArgs);
531 if(*lpszLastChar==' ') *lpszLastChar = '\0';
536 /*************************************************************************
537 * PathRemoveExtensionA [SHLWAPI.@]
539 void WINAPI PathRemoveExtensionA(LPSTR lpszPath)
541 LPSTR lpszExtension = PathFindExtensionA(lpszPath);
543 TRACE("%s\n", lpszPath);
545 if (lpszExtension) *lpszExtension='\0';
548 /*************************************************************************
549 * PathRemoveExtensionW [SHLWAPI.@]
551 void WINAPI PathRemoveExtensionW(LPWSTR lpszPath)
553 LPWSTR lpszExtension = PathFindExtensionW(lpszPath);
555 TRACE("%s\n", debugstr_w(lpszPath));
557 if (lpszExtension) *lpszExtension='\0';
560 /*************************************************************************
561 * PathRemoveBackslashA [SHLWAPI.@]
563 * If the path ends in a backslash it is replaced by a NULL
564 * and the address of the NULL is returned
566 * the address of the last character is returned.
569 * "c:\": keep backslash
571 LPSTR WINAPI PathRemoveBackslashA( LPSTR lpszPath )
578 len = strlen(lpszPath);
579 szTemp = CharPrevA(lpszPath, lpszPath+len);
580 if (! PathIsRootA(lpszPath))
582 if (*szTemp == '\\') *szTemp = '\0';
588 /*************************************************************************
589 * PathRemoveBackslashW [SHLWAPI.@]
591 LPWSTR WINAPI PathRemoveBackslashW( LPWSTR lpszPath )
594 LPWSTR szTemp = NULL;
598 len = strlenW(lpszPath);
599 szTemp = CharPrevW(lpszPath, lpszPath+len);
600 if (! PathIsRootW(lpszPath))
602 if (*szTemp == '\\') *szTemp = '\0';
613 /*************************************************************************
614 * PathRemoveBlanksA [SHLWAPI.@]
617 * remove spaces from beginning and end of passed string
619 void WINAPI PathRemoveBlanksA(LPSTR str)
627 while (*x==' ') x = CharNextA(x);
628 if (x!=str) strcpy(str,x);
630 while (*x==' ') x = CharPrevA(str, x);
631 if (*x==' ') *x='\0';
635 /*************************************************************************
636 * PathRemoveBlanksW [SHLWAPI.@]
638 void WINAPI PathRemoveBlanksW(LPWSTR str)
642 TRACE("%s\n",debugstr_w(str));
646 while (*x==' ') x = CharNextW(x);
647 if (x!=str) strcpyW(str,x);
648 x=str+strlenW(str)-1;
649 while (*x==' ') x = CharPrevW(str, x);
650 if (*x==' ') *x='\0';
654 /*************************************************************************
655 * PathQuoteSpacesA [SHLWAPI.@]
658 LPSTR WINAPI PathQuoteSpacesA(LPSTR lpszPath)
660 TRACE("%s\n",lpszPath);
662 if(StrChrA(lpszPath,' '))
664 int len = strlen(lpszPath);
665 RtlMoveMemory(lpszPath+1, lpszPath, len);
675 /*************************************************************************
676 * PathQuoteSpacesW [SHLWAPI.@]
678 LPWSTR WINAPI PathQuoteSpacesW(LPWSTR lpszPath)
680 TRACE("%s\n",debugstr_w(lpszPath));
682 if(StrChrW(lpszPath,' '))
684 int len = strlenW(lpszPath);
685 RtlMoveMemory(lpszPath+1, lpszPath, len*sizeof(WCHAR));
695 /*************************************************************************
696 * PathUnquoteSpacesA [SHLWAPI.@]
699 * unquote string (remove ")
701 VOID WINAPI PathUnquoteSpacesA(LPSTR str)
703 DWORD len = strlen(str);
716 /*************************************************************************
717 * PathUnquoteSpacesW [SHLWAPI.@]
719 VOID WINAPI PathUnquoteSpacesW(LPWSTR str)
721 DWORD len = strlenW(str);
723 TRACE("%s\n",debugstr_w(str));
734 /*************************************************************************
735 * PathParseIconLocationA [SHLWAPI.@]
737 int WINAPI PathParseIconLocationA(LPSTR lpszPath)
739 LPSTR lpstrComma = strchr(lpszPath, ',');
742 TRACE("%s\n", debugstr_a(lpszPath));
744 if (lpstrComma && lpstrComma[1])
747 ret = atoi(&lpstrComma[1]);
750 PathUnquoteSpacesA(lpszPath);
754 /*************************************************************************
755 * PathParseIconLocationW [SHLWAPI.@]
757 int WINAPI PathParseIconLocationW(LPWSTR lpszPath)
759 LPWSTR lpstrComma = strchrW(lpszPath, ',');
762 TRACE("%s\n", debugstr_w(lpszPath));
764 if (lpstrComma && lpstrComma[1])
767 ret = _wtoi(&lpstrComma[1]);
769 PathUnquoteSpacesW(lpszPath);
774 ########## cleaning and resolving paths ##########
777 /*************************************************************************
778 * PathFindOnPathA [SHLWAPI.@]
780 BOOL WINAPI PathFindOnPathA(LPSTR sFile, LPCSTR *sOtherDirs)
782 FIXME("%s %p\n",sFile, sOtherDirs);
786 /*************************************************************************
787 * PathFindOnPathW [SHLWAPI.@]
789 BOOL WINAPI PathFindOnPathW(LPWSTR sFile, LPCWSTR *sOtherDirs)
791 FIXME("%s %p\n",debugstr_w(sFile), sOtherDirs);
795 /*************************************************************************
796 * PathCompactPathExA [SHLWAPI.@]
798 BOOL WINAPI PathCompactPathExA(
804 FIXME("%p %s 0x%08x 0x%08lx\n", pszOut, pszSrc, cchMax, dwFlags);
808 /*************************************************************************
809 * PathCompactPathExW [SHLWAPI.@]
811 BOOL WINAPI PathCompactPathExW(
817 FIXME("%p %s 0x%08x 0x%08lx\n", pszOut, debugstr_w(pszSrc), cchMax, dwFlags);
822 ########## Path Testing ##########
825 /*************************************************************************
826 * PathIsUNCA [SHLWAPI.@]
829 * PathIsUNC(char*path);
831 BOOL WINAPI PathIsUNCA(LPCSTR lpszPath)
833 TRACE("%s\n",lpszPath);
835 return (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\'));
838 /*************************************************************************
839 * PathIsUNCW [SHLWAPI.@]
841 BOOL WINAPI PathIsUNCW(LPCWSTR lpszPath)
843 TRACE("%s\n",debugstr_w(lpszPath));
845 return (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\'));
848 /*************************************************************************
849 * PathIsRelativeA [SHLWAPI.@]
851 BOOL WINAPI PathIsRelativeA (LPCSTR lpszPath)
853 TRACE("lpszPath=%s\n",lpszPath);
855 return (lpszPath && (lpszPath[0]!='\\' && lpszPath[1]!=':'));
858 /*************************************************************************
859 * PathIsRelativeW [SHLWAPI.@]
861 BOOL WINAPI PathIsRelativeW (LPCWSTR lpszPath)
863 TRACE("lpszPath=%s\n",debugstr_w(lpszPath));
865 return (lpszPath && (lpszPath[0]!='\\' && lpszPath[1]!=':'));
868 /*************************************************************************
869 * PathIsRootA [SHLWAPI.@]
872 * TRUE if the path points to a root directory
874 BOOL WINAPI PathIsRootA(LPCSTR lpszPath)
876 TRACE("%s\n",lpszPath);
879 if (lpszPath[1]==':' && lpszPath[2]=='\\' && lpszPath[3]=='\0')
883 if (lpszPath[0]=='\\' && lpszPath[1]=='\0')
886 /* UNC "\\<computer>\<share>" */
887 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
889 int foundbackslash = 0;
893 if (*lpszPath=='\\') foundbackslash++;
894 lpszPath = CharNextA(lpszPath);
896 if (foundbackslash <= 1)
902 /*************************************************************************
903 * PathIsRootW [SHLWAPI.@]
905 BOOL WINAPI PathIsRootW(LPCWSTR lpszPath)
907 TRACE("%s\n",debugstr_w(lpszPath));
910 if (lpszPath[1]==':' && lpszPath[2]=='\\' && lpszPath[3]=='\0')
914 if (lpszPath[0]=='\\' && lpszPath[1]=='\0')
917 /* UNC "\\<computer>\<share>" */
918 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
920 int foundbackslash = 0;
924 if (*lpszPath=='\\') foundbackslash++;
925 lpszPath = CharNextW(lpszPath);
927 if (foundbackslash <= 1)
934 /*************************************************************************
935 * PathIsDirectoryA [SHLWAPI.@]
937 BOOL WINAPI PathIsDirectoryA(LPCSTR lpszPath)
941 TRACE("%s\n", debugstr_a(lpszPath));
943 dwAttr = GetFileAttributesA(lpszPath);
944 return (dwAttr != -1) ? dwAttr & FILE_ATTRIBUTE_DIRECTORY : 0;
947 /*************************************************************************
948 * PathIsDirectoryW [SHLWAPI.@]
950 BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath)
954 TRACE("%s\n", debugstr_w(lpszPath));
956 dwAttr = GetFileAttributesW(lpszPath);
957 return (dwAttr != -1) ? dwAttr & FILE_ATTRIBUTE_DIRECTORY : 0;
960 /*************************************************************************
961 * PathFileExistsA [SHLWAPI.@]
964 * file_exists(char *fn);
966 BOOL WINAPI PathFileExistsA(LPCSTR lpszPath)
968 TRACE("%s\n",lpszPath);
969 return (GetFileAttributesA(lpszPath)!=-1);
972 /*************************************************************************
973 * PathFileExistsW [SHLWAPI.@]
975 BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
977 TRACE("%s\n",debugstr_w(lpszPath));
978 return (GetFileAttributesW(lpszPath)!=-1);
981 /*************************************************************************
982 * PathMatchSingleMaskA [internal]
985 * internal (used by PathMatchSpec)
987 static BOOL PathMatchSingleMaskA(LPCSTR name, LPCSTR mask)
989 while (*name && *mask && *mask!=';')
995 if (PathMatchSingleMaskA(name,mask+1)) return 1; /* try substrings */
999 if (toupper(*mask)!=toupper(*name) && *mask!='?') return 0;
1000 name = CharNextA(name);
1001 mask = CharNextA(mask);
1005 while (*mask=='*') mask++;
1006 if (!*mask || *mask==';') return 1;
1011 /*************************************************************************
1012 * PathMatchSingleMaskW [internal]
1014 static BOOL PathMatchSingleMaskW(LPCWSTR name, LPCWSTR mask)
1016 while (*name && *mask && *mask!=';')
1022 if (PathMatchSingleMaskW(name,mask+1)) return 1; /* try substrings */
1026 if (toupperW(*mask)!=toupperW(*name) && *mask!='?') return 0;
1027 name = CharNextW(name);
1028 mask = CharNextW(mask);
1032 while (*mask=='*') mask++;
1033 if (!*mask || *mask==';') return 1;
1037 /*************************************************************************
1038 * PathMatchSpecA [SHLWAPI.@]
1041 * used from COMDLG32
1043 BOOL WINAPI PathMatchSpecA(LPCSTR name, LPCSTR mask)
1045 TRACE("%s %s\n",name,mask);
1047 if (!lstrcmpA( mask, "*.*" )) return 1; /* we don't require a period */
1051 if (PathMatchSingleMaskA(name,mask)) return 1; /* helper function */
1052 while (*mask && *mask!=';') mask = CharNextA(mask);
1056 while (*mask==' ') mask++; /* masks may be separated by "; " */
1062 /*************************************************************************
1063 * PathMatchSpecW [SHLWAPI.@]
1065 BOOL WINAPI PathMatchSpecW(LPCWSTR name, LPCWSTR mask)
1067 static const WCHAR stemp[] = { '*','.','*',0 };
1068 TRACE("%s %s\n",debugstr_w(name),debugstr_w(mask));
1070 if (!lstrcmpW( mask, stemp )) return 1; /* we don't require a period */
1074 if (PathMatchSingleMaskW(name,mask)) return 1; /* helper function */
1075 while (*mask && *mask!=';') mask = CharNextW(mask);
1079 while (*mask==' ') mask++; /* masks may be separated by "; " */
1085 /*************************************************************************
1086 * PathIsSameRootA [SHLWAPI.@]
1089 * what to do with "\path" ??
1091 BOOL WINAPI PathIsSameRootA(LPCSTR lpszPath1, LPCSTR lpszPath2)
1093 TRACE("%s %s\n", lpszPath1, lpszPath2);
1095 if (PathIsRelativeA(lpszPath1) || PathIsRelativeA(lpszPath2)) return FALSE;
1098 if ( toupper(lpszPath1[0])==toupper(lpszPath2[0]) &&
1099 lpszPath1[1]==':' && lpszPath2[1]==':' &&
1100 lpszPath1[2]=='\\' && lpszPath2[2]=='\\')
1104 if (lpszPath1[0]=='\\' && lpszPath2[0]=='\\' &&
1105 lpszPath1[1]=='\\' && lpszPath2[1]=='\\')
1107 int pos=2, bsfound=0;
1108 while (lpszPath1[pos] && lpszPath2[pos] &&
1109 (lpszPath1[pos] == lpszPath2[pos]))
1111 if (lpszPath1[pos]=='\\') bsfound++;
1112 if (bsfound == 2) return TRUE;
1113 pos++; /* FIXME: use CharNext*/
1115 return (lpszPath1[pos] == lpszPath2[pos]);
1120 /*************************************************************************
1121 * PathIsSameRootW [SHLWAPI.@]
1123 BOOL WINAPI PathIsSameRootW(LPCWSTR lpszPath1, LPCWSTR lpszPath2)
1125 TRACE("%s %s\n", debugstr_w(lpszPath1), debugstr_w(lpszPath2));
1127 if (PathIsRelativeW(lpszPath1) || PathIsRelativeW(lpszPath2)) return FALSE;
1130 if ( toupperW(lpszPath1[0])==toupperW(lpszPath2[0]) &&
1131 lpszPath1[1]==':' && lpszPath2[1]==':' &&
1132 lpszPath1[2]=='\\' && lpszPath2[2]=='\\')
1136 if (lpszPath1[0]=='\\' && lpszPath2[0]=='\\' &&
1137 lpszPath1[1]=='\\' && lpszPath2[1]=='\\')
1139 int pos=2, bsfound=0;
1140 while (lpszPath1[pos] && lpszPath2[pos] &&
1141 (lpszPath1[pos] == lpszPath2[pos]))
1143 if (lpszPath1[pos]=='\\') bsfound++;
1144 if (bsfound == 2) return TRUE;
1145 pos++;/* FIXME: use CharNext*/
1147 return (lpszPath1[pos] == lpszPath2[pos]);
1152 /*************************************************************************
1153 * PathIsURLA (SHLWAPI.@)
1155 BOOL WINAPI PathIsURLA(LPCSTR lpstrPath)
1157 UNKNOWN_SHLWAPI_1 base;
1160 if (!lpstrPath || !*lpstrPath) return FALSE;
1164 res1 = SHLWAPI_1(lpstrPath, &base);
1165 return (base.fcncde) ? TRUE : FALSE;
1168 /*************************************************************************
1169 * PathIsURLW (SHLWAPI.@)
1171 BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
1173 UNKNOWN_SHLWAPI_2 base;
1176 if (!lpstrPath || !*lpstrPath) return FALSE;
1180 res1 = SHLWAPI_2(lpstrPath, &base);
1181 return (base.fcncde) ? TRUE : FALSE;
1185 /*************************************************************************
1186 * PathIsContentTypeA [SHLWAPI.@]
1188 BOOL WINAPI PathIsContentTypeA(LPCSTR pszPath, LPCSTR pszContentType)
1190 FIXME("%s %s\n", pszPath, pszContentType);
1194 /*************************************************************************
1195 * PathIsContentTypeW [SHLWAPI.@]
1197 BOOL WINAPI PathIsContentTypeW(LPCWSTR pszPath, LPCWSTR pszContentType)
1199 FIXME("%s %s\n", debugstr_w(pszPath), debugstr_w(pszContentType));
1203 /*************************************************************************
1204 * PathIsFileSpecA [SHLWAPI.@]
1206 BOOL WINAPI PathIsFileSpecA(LPCSTR pszPath)
1208 FIXME("%s\n", pszPath);
1212 /*************************************************************************
1213 * PathIsFileSpecW [SHLWAPI.@]
1215 BOOL WINAPI PathIsFileSpecW(LPCWSTR pszPath)
1217 FIXME("%s\n", debugstr_w(pszPath));
1221 /*************************************************************************
1222 * PathIsPrefixA [SHLWAPI.@]
1224 BOOL WINAPI PathIsPrefixA(LPCSTR pszPrefix, LPCSTR pszPath)
1226 FIXME("%s %s\n", pszPrefix, pszPath);
1230 /*************************************************************************
1231 * PathIsPrefixW [SHLWAPI.@]
1233 BOOL WINAPI PathIsPrefixW(LPCWSTR pszPrefix, LPCWSTR pszPath)
1235 FIXME("%s %s\n", debugstr_w(pszPrefix), debugstr_w(pszPath));
1239 /*************************************************************************
1240 * PathIsSystemFolderA [SHLWAPI.@]
1242 BOOL WINAPI PathIsSystemFolderA(LPCSTR pszPath, DWORD dwAttrb)
1244 FIXME("%s 0x%08lx\n", pszPath, dwAttrb);
1248 /*************************************************************************
1249 * PathIsSystemFolderW [SHLWAPI.@]
1251 BOOL WINAPI PathIsSystemFolderW(LPCWSTR pszPath, DWORD dwAttrb)
1253 FIXME("%s 0x%08lx\n", debugstr_w(pszPath), dwAttrb);
1257 /*************************************************************************
1258 * PathIsUNCServerA [SHLWAPI.@]
1260 BOOL WINAPI PathIsUNCServerA(
1263 TRACE("%s\n", debugstr_a(lpszPath));
1264 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
1266 int foundbackslash = 0;
1270 if (*lpszPath=='\\') foundbackslash++;
1271 lpszPath = CharNextA(lpszPath);
1273 if (foundbackslash == 0)
1279 /*************************************************************************
1280 * PathIsUNCServerW [SHLWAPI.@]
1282 BOOL WINAPI PathIsUNCServerW(
1285 TRACE("%s\n", debugstr_w(lpszPath));
1286 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
1288 int foundbackslash = 0;
1292 if (*lpszPath=='\\') foundbackslash++;
1293 lpszPath = CharNextW(lpszPath);
1295 if (foundbackslash == 0)
1301 /*************************************************************************
1302 * PathIsUNCServerShareA [SHLWAPI.@]
1304 BOOL WINAPI PathIsUNCServerShareA(
1307 TRACE("%s\n", debugstr_a(lpszPath));
1308 if (!lpszPath) return FALSE;
1309 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
1311 int foundbackslash = 0;
1315 if (*lpszPath=='\\') foundbackslash++;
1316 lpszPath = CharNextA(lpszPath);
1318 if (foundbackslash == 1)
1324 /*************************************************************************
1325 * PathIsUNCServerShareW [SHLWAPI.@]
1327 BOOL WINAPI PathIsUNCServerShareW(
1330 TRACE("%s\n", debugstr_w(lpszPath));
1331 if (!lpszPath) return FALSE;
1332 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
1334 int foundbackslash = 0;
1338 if (*lpszPath=='\\') foundbackslash++;
1339 lpszPath = CharNextW(lpszPath);
1341 if (foundbackslash == 1)
1347 /*************************************************************************
1348 * PathCanonicalizeA [SHLWAPI.@]
1351 * returnvalue, use CharNext
1354 BOOL WINAPI PathCanonicalizeA(LPSTR pszBuf, LPCSTR pszPath)
1356 int OffsetMin = 0, OffsetSrc = 0, OffsetDst = 0, LenSrc = strlen(pszPath);
1357 BOOL bModifyed = FALSE;
1359 TRACE("%p %s\n", pszBuf, pszPath);
1361 pszBuf[OffsetDst]='\0';
1363 /* keep the root of the path */
1364 if( LenSrc && (pszPath[OffsetSrc]=='\\'))
1366 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1368 else if ( (LenSrc >= 2) && (pszPath[OffsetSrc+1] == ':'))
1370 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1371 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1372 if (LenSrc && (pszPath[OffsetSrc] == '\\'))
1374 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1375 if (LenSrc == 1 && pszPath[OffsetSrc]=='.')
1378 OffsetSrc++; LenSrc--; bModifyed = TRUE;
1380 else if (LenSrc == 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='.')
1383 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1388 /* ".\" at the beginning of the path */
1389 if (LenSrc >= 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='\\')
1391 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1396 if((LenSrc>=3) && (pszPath[OffsetSrc]=='\\') && (pszPath[OffsetSrc+1]=='.') && (pszPath[OffsetSrc+2]=='.'))
1398 /* "\.." found, go one deeper */
1399 while((OffsetDst > OffsetMin) && (pszBuf[OffsetDst]!='\\')) OffsetDst--;
1400 OffsetSrc += 3; LenSrc -= 3; bModifyed = TRUE;
1401 if(OffsetDst == OffsetMin && pszPath[OffsetSrc]=='\\') OffsetSrc++;
1402 pszBuf[OffsetDst] = '\0'; /* important for \..\.. */
1404 else if(LenSrc>=2 && pszPath[OffsetSrc]=='\\' && pszPath[OffsetSrc+1]=='.' )
1406 /* "\." found, skip it */
1407 OffsetSrc += 2; LenSrc-=2; bModifyed = TRUE;
1411 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; LenSrc--;
1414 pszBuf[OffsetDst] = '\0';
1415 TRACE("-- %s %u\n", pszBuf, bModifyed);
1420 /*************************************************************************
1421 * PathCanonicalizeW [SHLWAPI.@]
1424 * returnvalue, use CharNext
1426 BOOL WINAPI PathCanonicalizeW(LPWSTR pszBuf, LPCWSTR pszPath)
1428 int OffsetMin = 0, OffsetSrc = 0, OffsetDst = 0, LenSrc = strlenW(pszPath);
1429 BOOL bModifyed = FALSE;
1431 TRACE("%p %s\n", pszBuf, debugstr_w(pszPath));
1433 pszBuf[OffsetDst]='\0';
1435 /* keep the root of the path */
1436 if( LenSrc && (pszPath[OffsetSrc]=='\\'))
1438 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1440 else if ( (LenSrc >= 2) && (pszPath[OffsetSrc+1] == ':'))
1442 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1443 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1444 if (LenSrc && (pszPath[OffsetSrc] == '\\'))
1446 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
1447 if (LenSrc == 1 && pszPath[OffsetSrc]=='.')
1450 OffsetSrc++; LenSrc--; bModifyed = TRUE;
1452 else if (LenSrc == 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='.')
1455 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1460 /* ".\" at the beginning of the path */
1461 if (LenSrc >= 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='\\')
1463 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
1468 if((LenSrc>=3) && (pszPath[OffsetSrc]=='\\') && (pszPath[OffsetSrc+1]=='.') && (pszPath[OffsetSrc+2]=='.'))
1470 /* "\.." found, go one deeper */
1471 while((OffsetDst > OffsetMin) && (pszBuf[OffsetDst]!='\\')) OffsetDst--;
1472 OffsetSrc += 3; LenSrc -= 3; bModifyed = TRUE;
1473 if(OffsetDst == OffsetMin && pszPath[OffsetSrc]=='\\') OffsetSrc++;
1474 pszBuf[OffsetDst] = '\0'; /* important for \..\.. */
1476 else if(LenSrc>=2 && pszPath[OffsetSrc]=='\\' && pszPath[OffsetSrc+1]=='.' )
1478 /* "\." found, skip it */
1479 OffsetSrc += 2; LenSrc-=2; bModifyed = TRUE;
1483 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; LenSrc--;
1486 pszBuf[OffsetDst] = '\0';
1487 TRACE("-- %s %u\n", debugstr_w(pszBuf), bModifyed);
1491 /*************************************************************************
1492 * PathFindNextComponentA [SHLWAPI.@]
1497 * aa "" (pointer to traling NULL)
1498 * aa\ "" (pointer to traling NULL)
1499 * aa\\ "" (pointer to traling NULL)
1506 LPSTR WINAPI PathFindNextComponentA(LPCSTR pszPath)
1510 TRACE("%s\n", pszPath);
1512 if(!pszPath || !*pszPath) return NULL;
1513 if(!(pos = StrChrA(pszPath, '\\')))
1514 return (LPSTR) pszPath + strlen(pszPath);
1516 if(pos[0] == '\\') pos++;
1520 /*************************************************************************
1521 * PathFindNextComponentW [SHLWAPI.@]
1523 LPWSTR WINAPI PathFindNextComponentW(LPCWSTR pszPath)
1527 TRACE("%s\n", debugstr_w(pszPath));
1529 if(!pszPath || !*pszPath) return NULL;
1530 if (!(pos = StrChrW(pszPath, '\\')))
1531 return (LPWSTR) pszPath + strlenW(pszPath);
1533 if(pos[0] == '\\') pos++;
1537 /*************************************************************************
1538 * PathAddExtensionA [SHLWAPI.@]
1541 * it adds never a dot
1544 BOOL WINAPI PathAddExtensionA(
1546 LPCSTR pszExtension)
1550 if (*(PathFindExtensionA(pszPath))) return FALSE;
1552 if (!pszExtension || *pszExtension=='\0')
1553 strcat(pszPath, "exe");
1555 strcat(pszPath, pszExtension);
1561 /*************************************************************************
1562 * PathAddExtensionW [SHLWAPI.@]
1564 BOOL WINAPI PathAddExtensionW(
1566 LPCWSTR pszExtension)
1568 static const WCHAR ext[] = { 'e','x','e',0 };
1572 if (*(PathFindExtensionW(pszPath))) return FALSE;
1574 if (!pszExtension || *pszExtension=='\0')
1575 strcatW(pszPath, ext);
1577 strcatW(pszPath, pszExtension);
1583 /*************************************************************************
1584 * PathMakePrettyA [SHLWAPI.@]
1586 BOOL WINAPI PathMakePrettyA(
1589 FIXME("%s\n", lpPath);
1593 /*************************************************************************
1594 * PathMakePrettyW [SHLWAPI.@]
1596 BOOL WINAPI PathMakePrettyW(
1599 FIXME("%s\n", debugstr_w(lpPath));
1604 /*************************************************************************
1605 * PathCommonPrefixA [SHLWAPI.@]
1607 int WINAPI PathCommonPrefixA(
1612 FIXME("%s %s %p\n", pszFile1, pszFile2, achPath);
1616 /*************************************************************************
1617 * PathCommonPrefixW [SHLWAPI.@]
1619 int WINAPI PathCommonPrefixW(
1624 FIXME("%s %s %p\n", debugstr_w(pszFile1), debugstr_w(pszFile2),achPath );
1628 /*************************************************************************
1629 * PathCompactPathA [SHLWAPI.@]
1631 BOOL WINAPI PathCompactPathA(HDC hDC, LPSTR pszPath, UINT dx)
1633 FIXME("0x%08x %s 0x%08x\n", hDC, pszPath, dx);
1637 /*************************************************************************
1638 * PathCompactPathW [SHLWAPI.@]
1640 BOOL WINAPI PathCompactPathW(HDC hDC, LPWSTR pszPath, UINT dx)
1642 FIXME("0x%08x %s 0x%08x\n", hDC, debugstr_w(pszPath), dx);
1646 /*************************************************************************
1647 * PathGetCharTypeA [SHLWAPI.@]
1649 UINT WINAPI PathGetCharTypeA(UCHAR ch)
1655 /* We could use them in filenames, but this would confuse 'ls' */
1658 if ((ch == '*') || (ch=='?'))
1660 if ((ch == '\\') || (ch=='/'))
1661 return GCT_SEPARATOR;
1663 /* all normal characters, no lower case letters */
1664 if ((ch > ' ') && (ch < 0x7f) && !islower(ch))
1665 flags |= GCT_SHORTCHAR;
1666 /* All other characters are valid in long filenames, even umlauts */
1667 return flags | GCT_LFNCHAR;
1670 /*************************************************************************
1671 * PathGetCharTypeW [SHLWAPI.@]
1673 UINT WINAPI PathGetCharTypeW(WCHAR ch)
1675 FIXME("%c, using ascii version\n", ch);
1676 return PathGetCharTypeA(ch);
1679 /*************************************************************************
1680 * PathMakeSystemFolderA [SHLWAPI.@]
1682 BOOL WINAPI PathMakeSystemFolderA(LPCSTR pszPath)
1684 FIXME("%s\n", pszPath);
1688 /*************************************************************************
1689 * PathMakeSystemFolderW [SHLWAPI.@]
1691 BOOL WINAPI PathMakeSystemFolderW(LPCWSTR pszPath)
1693 FIXME("%s\n", debugstr_w(pszPath));
1697 /*************************************************************************
1698 * PathRenameExtensionA [SHLWAPI.@]
1700 BOOL WINAPI PathRenameExtensionA(LPSTR pszPath, LPCSTR pszExt)
1702 LPSTR pszExtension = PathFindExtensionA(pszPath);
1704 if (!pszExtension) return FALSE;
1705 if (pszExtension-pszPath + strlen(pszExt) > MAX_PATH) return FALSE;
1707 strcpy(pszExtension, pszExt);
1708 TRACE("%s\n", pszPath);
1712 /*************************************************************************
1713 * PathRenameExtensionW [SHLWAPI.@]
1715 BOOL WINAPI PathRenameExtensionW(LPWSTR pszPath, LPCWSTR pszExt)
1717 LPWSTR pszExtension = PathFindExtensionW(pszPath);
1719 if (!pszExtension) return FALSE;
1720 if (pszExtension-pszPath + strlenW(pszExt) > MAX_PATH) return FALSE;
1722 strcpyW(pszExtension, pszExt);
1723 TRACE("%s\n", debugstr_w(pszPath));
1727 /*************************************************************************
1728 * PathSearchAndQualifyA [SHLWAPI.@]
1730 BOOL WINAPI PathSearchAndQualifyA(
1735 FIXME("%s %s 0x%08x\n", pszPath, pszBuf, cchBuf);
1739 /*************************************************************************
1740 * PathSearchAndQualifyW [SHLWAPI.@]
1742 BOOL WINAPI PathSearchAndQualifyW(
1747 FIXME("%s %s 0x%08x\n", debugstr_w(pszPath), debugstr_w(pszBuf), cchBuf);
1751 /*************************************************************************
1752 * PathSkipRootA [SHLWAPI.@]
1754 LPSTR WINAPI PathSkipRootA(LPCSTR pszPath)
1756 FIXME("%s\n", pszPath);
1757 return (LPSTR)pszPath;
1760 /*************************************************************************
1761 * PathSkipRootW [SHLWAPI.@]
1763 LPWSTR WINAPI PathSkipRootW(LPCWSTR pszPath)
1765 FIXME("%s\n", debugstr_w(pszPath));
1766 return (LPWSTR)pszPath;
1769 /*************************************************************************
1770 * PathCreateFromUrlA [SHLWAPI.@]
1772 HRESULT WINAPI PathCreateFromUrlA(
1778 /* extracts thing prior to : in pszURL and checks against:
1782 * about - if match returns E_INVALIDARG
1784 FIXME("%s %p %p 0x%08lx\n",
1785 pszUrl, pszPath, pcchPath, dwFlags);
1786 return E_INVALIDARG;
1789 /*************************************************************************
1790 * PathCreateFromUrlW [SHLWAPI.@]
1792 HRESULT WINAPI PathCreateFromUrlW(
1798 /* extracts thing prior to : in pszURL and checks against:
1802 * about - if match returns E_INVALIDARG
1804 FIXME("%s %p %p 0x%08lx\n",
1805 debugstr_w(pszUrl), pszPath, pcchPath, dwFlags);
1806 return E_INVALIDARG;
1809 /*************************************************************************
1810 * PathRelativePathToA [SHLWAPI.@]
1812 BOOL WINAPI PathRelativePathToA(
1819 FIXME("%s %s 0x%08lx %s 0x%08lx\n",
1820 pszPath, pszFrom, dwAttrFrom, pszTo, dwAttrTo);
1824 /*************************************************************************
1825 * PathRelativePathToW [SHLWAPI.@]
1827 BOOL WINAPI PathRelativePathToW(
1834 FIXME("%s %s 0x%08lx %s 0x%08lx\n",
1835 debugstr_w(pszPath), debugstr_w(pszFrom), dwAttrFrom, debugstr_w(pszTo), dwAttrTo);
1839 /*************************************************************************
1840 * PathUnmakeSystemFolderA [SHLWAPI.@]
1842 BOOL WINAPI PathUnmakeSystemFolderA(LPCSTR pszPath)
1844 FIXME("%s\n", pszPath);
1848 /*************************************************************************
1849 * PathUnmakeSystemFolderW [SHLWAPI.@]
1851 BOOL WINAPI PathUnmakeSystemFolderW(LPCWSTR pszPath)
1853 FIXME("%s\n", debugstr_w(pszPath));
1858 ########## special ##########
1861 /*************************************************************************
1862 * PathSetDlgItemPathA [SHLWAPI.@]
1865 * use PathCompactPath to make sure, the path fits into the control
1867 BOOL WINAPI PathSetDlgItemPathA(HWND hDlg, int id, LPCSTR pszPath)
1868 { TRACE("%x %x %s\n",hDlg, id, pszPath);
1869 return SetDlgItemTextA(hDlg, id, pszPath);
1872 /*************************************************************************
1873 * PathSetDlgItemPathW [SHLWAPI.@]
1875 BOOL WINAPI PathSetDlgItemPathW(HWND hDlg, int id, LPCWSTR pszPath)
1876 { TRACE("%x %x %s\n",hDlg, id, debugstr_w(pszPath));
1877 return SetDlgItemTextW(hDlg, id, pszPath);