kernelbase: Duplicate some path handling functions from shlwapi.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
7c02ab5ed1
commit
44ac5af07a
|
@ -1020,16 +1020,16 @@
|
||||||
# @ stub ParseApplicationUserModelId
|
# @ stub ParseApplicationUserModelId
|
||||||
@ stdcall ParseURLA(str ptr) shlwapi.ParseURLA
|
@ stdcall ParseURLA(str ptr) shlwapi.ParseURLA
|
||||||
@ stdcall ParseURLW(wstr ptr) shlwapi.ParseURLW
|
@ stdcall ParseURLW(wstr ptr) shlwapi.ParseURLW
|
||||||
@ stdcall PathAddBackslashA(str) shlwapi.PathAddBackslashA
|
@ stdcall PathAddBackslashA(str)
|
||||||
@ stdcall PathAddBackslashW(wstr) shlwapi.PathAddBackslashW
|
@ stdcall PathAddBackslashW(wstr)
|
||||||
@ stdcall PathAddExtensionA(str str) shlwapi.PathAddExtensionA
|
@ stdcall PathAddExtensionA(str str)
|
||||||
@ stdcall PathAddExtensionW(wstr wstr) shlwapi.PathAddExtensionW
|
@ stdcall PathAddExtensionW(wstr wstr)
|
||||||
@ stdcall PathAllocCanonicalize(wstr long ptr)
|
@ stdcall PathAllocCanonicalize(wstr long ptr)
|
||||||
@ stdcall PathAllocCombine(wstr wstr long ptr)
|
@ stdcall PathAllocCombine(wstr wstr long ptr)
|
||||||
@ stdcall PathAppendA(str str) shlwapi.PathAppendA
|
@ stdcall PathAppendA(str str)
|
||||||
@ stdcall PathAppendW(wstr wstr) shlwapi.PathAppendW
|
@ stdcall PathAppendW(wstr wstr)
|
||||||
@ stdcall PathCanonicalizeA(ptr str) shlwapi.PathCanonicalizeA
|
@ stdcall PathCanonicalizeA(ptr str)
|
||||||
@ stdcall PathCanonicalizeW(ptr wstr) shlwapi.PathCanonicalizeW
|
@ stdcall PathCanonicalizeW(ptr wstr)
|
||||||
@ stdcall PathCchAddBackslash(wstr long)
|
@ stdcall PathCchAddBackslash(wstr long)
|
||||||
@ stdcall PathCchAddBackslashEx(wstr long ptr ptr)
|
@ stdcall PathCchAddBackslashEx(wstr long ptr ptr)
|
||||||
@ stdcall PathCchAddExtension(wstr long wstr)
|
@ stdcall PathCchAddExtension(wstr long wstr)
|
||||||
|
@ -1049,17 +1049,17 @@
|
||||||
@ stdcall PathCchSkipRoot(wstr ptr)
|
@ stdcall PathCchSkipRoot(wstr ptr)
|
||||||
@ stdcall PathCchStripPrefix(wstr long)
|
@ stdcall PathCchStripPrefix(wstr long)
|
||||||
@ stdcall PathCchStripToRoot(wstr long)
|
@ stdcall PathCchStripToRoot(wstr long)
|
||||||
@ stdcall PathCombineA(ptr str str) shlwapi.PathCombineA
|
@ stdcall PathCombineA(ptr str str)
|
||||||
@ stdcall PathCombineW(ptr wstr wstr) shlwapi.PathCombineW
|
@ stdcall PathCombineW(ptr wstr wstr)
|
||||||
@ stdcall PathCommonPrefixA(str str ptr) shlwapi.PathCommonPrefixA
|
@ stdcall PathCommonPrefixA(str str ptr)
|
||||||
@ stdcall PathCommonPrefixW(wstr wstr ptr) shlwapi.PathCommonPrefixW
|
@ stdcall PathCommonPrefixW(wstr wstr ptr)
|
||||||
@ stdcall PathCreateFromUrlA(str ptr ptr long) shlwapi.PathCreateFromUrlA
|
@ stdcall PathCreateFromUrlA(str ptr ptr long) shlwapi.PathCreateFromUrlA
|
||||||
@ stdcall PathCreateFromUrlAlloc(wstr ptr long) shlwapi.PathCreateFromUrlAlloc
|
@ stdcall PathCreateFromUrlAlloc(wstr ptr long) shlwapi.PathCreateFromUrlAlloc
|
||||||
@ stdcall PathCreateFromUrlW(wstr ptr ptr long) shlwapi.PathCreateFromUrlW
|
@ stdcall PathCreateFromUrlW(wstr ptr ptr long) shlwapi.PathCreateFromUrlW
|
||||||
@ stdcall PathFileExistsA(str) shlwapi.PathFileExistsA
|
@ stdcall PathFileExistsA(str) shlwapi.PathFileExistsA
|
||||||
@ stdcall PathFileExistsW(wstr) shlwapi.PathFileExistsW
|
@ stdcall PathFileExistsW(wstr) shlwapi.PathFileExistsW
|
||||||
@ stdcall PathFindExtensionA(str) shlwapi.PathFindExtensionA
|
@ stdcall PathFindExtensionA(str)
|
||||||
@ stdcall PathFindExtensionW(wstr) shlwapi.PathFindExtensionW
|
@ stdcall PathFindExtensionW(wstr)
|
||||||
@ stdcall PathFindFileNameA(str) shlwapi.PathFindFileNameA
|
@ stdcall PathFindFileNameA(str) shlwapi.PathFindFileNameA
|
||||||
@ stdcall PathFindFileNameW(wstr) shlwapi.PathFindFileNameW
|
@ stdcall PathFindFileNameW(wstr) shlwapi.PathFindFileNameW
|
||||||
@ stdcall PathFindNextComponentA(str) shlwapi.PathFindNextComponentA
|
@ stdcall PathFindNextComponentA(str) shlwapi.PathFindNextComponentA
|
||||||
|
@ -1074,21 +1074,21 @@
|
||||||
@ stdcall PathIsFileSpecW(wstr) shlwapi.PathIsFileSpecW
|
@ stdcall PathIsFileSpecW(wstr) shlwapi.PathIsFileSpecW
|
||||||
@ stdcall PathIsLFNFileSpecA(str) shlwapi.PathIsLFNFileSpecA
|
@ stdcall PathIsLFNFileSpecA(str) shlwapi.PathIsLFNFileSpecA
|
||||||
@ stdcall PathIsLFNFileSpecW(wstr) shlwapi.PathIsLFNFileSpecW
|
@ stdcall PathIsLFNFileSpecW(wstr) shlwapi.PathIsLFNFileSpecW
|
||||||
@ stdcall PathIsPrefixA(str str) shlwapi.PathIsPrefixA
|
@ stdcall PathIsPrefixA(str str)
|
||||||
@ stdcall PathIsPrefixW(wstr wstr) shlwapi.PathIsPrefixW
|
@ stdcall PathIsPrefixW(wstr wstr)
|
||||||
@ stdcall PathIsRelativeA(str) shlwapi.PathIsRelativeA
|
@ stdcall PathIsRelativeA(str)
|
||||||
@ stdcall PathIsRelativeW(wstr) shlwapi.PathIsRelativeW
|
@ stdcall PathIsRelativeW(wstr)
|
||||||
@ stdcall PathIsRootA(str) shlwapi.PathIsRootA
|
@ stdcall PathIsRootA(str)
|
||||||
@ stdcall PathIsRootW(wstr) shlwapi.PathIsRootW
|
@ stdcall PathIsRootW(wstr)
|
||||||
@ stdcall PathIsSameRootA(str str) shlwapi.PathIsSameRootA
|
@ stdcall PathIsSameRootA(str str) shlwapi.PathIsSameRootA
|
||||||
@ stdcall PathIsSameRootW(wstr wstr) shlwapi.PathIsSameRootW
|
@ stdcall PathIsSameRootW(wstr wstr) shlwapi.PathIsSameRootW
|
||||||
@ stdcall PathIsUNCA(str) shlwapi.PathIsUNCA
|
@ stdcall PathIsUNCA(str)
|
||||||
@ stdcall PathIsUNCEx(wstr ptr)
|
@ stdcall PathIsUNCEx(wstr ptr)
|
||||||
@ stdcall PathIsUNCServerA(str) shlwapi.PathIsUNCServerA
|
@ stdcall PathIsUNCServerA(str) shlwapi.PathIsUNCServerA
|
||||||
@ stdcall PathIsUNCServerShareA(str) shlwapi.PathIsUNCServerShareA
|
@ stdcall PathIsUNCServerShareA(str)
|
||||||
@ stdcall PathIsUNCServerShareW(wstr) shlwapi.PathIsUNCServerShareW
|
@ stdcall PathIsUNCServerShareW(wstr)
|
||||||
@ stdcall PathIsUNCServerW(wstr) shlwapi.PathIsUNCServerW
|
@ stdcall PathIsUNCServerW(wstr) shlwapi.PathIsUNCServerW
|
||||||
@ stdcall PathIsUNCW(wstr) shlwapi.PathIsUNCW
|
@ stdcall PathIsUNCW(wstr)
|
||||||
@ stdcall PathIsURLA(str) shlwapi.PathIsURLA
|
@ stdcall PathIsURLA(str) shlwapi.PathIsURLA
|
||||||
@ stdcall PathIsURLW(wstr) shlwapi.PathIsURLW
|
@ stdcall PathIsURLW(wstr) shlwapi.PathIsURLW
|
||||||
@ stdcall PathIsValidCharA(long long) shlwapi.PathIsValidCharA
|
@ stdcall PathIsValidCharA(long long) shlwapi.PathIsValidCharA
|
||||||
|
@ -1109,8 +1109,8 @@
|
||||||
@ stdcall PathRemoveBlanksW(wstr) shlwapi.PathRemoveBlanksW
|
@ stdcall PathRemoveBlanksW(wstr) shlwapi.PathRemoveBlanksW
|
||||||
@ stdcall PathRemoveExtensionA(str) shlwapi.PathRemoveExtensionA
|
@ stdcall PathRemoveExtensionA(str) shlwapi.PathRemoveExtensionA
|
||||||
@ stdcall PathRemoveExtensionW(wstr) shlwapi.PathRemoveExtensionW
|
@ stdcall PathRemoveExtensionW(wstr) shlwapi.PathRemoveExtensionW
|
||||||
@ stdcall PathRemoveFileSpecA(str) shlwapi.PathRemoveFileSpecA
|
@ stdcall PathRemoveFileSpecA(str)
|
||||||
@ stdcall PathRemoveFileSpecW(wstr) shlwapi.PathRemoveFileSpecW
|
@ stdcall PathRemoveFileSpecW(wstr)
|
||||||
@ stdcall PathRenameExtensionA(str str) shlwapi.PathRenameExtensionA
|
@ stdcall PathRenameExtensionA(str str) shlwapi.PathRenameExtensionA
|
||||||
@ stdcall PathRenameExtensionW(wstr wstr) shlwapi.PathRenameExtensionW
|
@ stdcall PathRenameExtensionW(wstr wstr) shlwapi.PathRenameExtensionW
|
||||||
@ stdcall PathSearchAndQualifyA(str ptr long) shlwapi.PathSearchAndQualifyA
|
@ stdcall PathSearchAndQualifyA(str ptr long) shlwapi.PathSearchAndQualifyA
|
||||||
|
@ -1120,7 +1120,7 @@
|
||||||
@ stdcall PathStripPathA(str) shlwapi.PathStripPathA
|
@ stdcall PathStripPathA(str) shlwapi.PathStripPathA
|
||||||
@ stdcall PathStripPathW(wstr) shlwapi.PathStripPathW
|
@ stdcall PathStripPathW(wstr) shlwapi.PathStripPathW
|
||||||
@ stdcall PathStripToRootA(str) shlwapi.PathStripToRootA
|
@ stdcall PathStripToRootA(str) shlwapi.PathStripToRootA
|
||||||
@ stdcall PathStripToRootW(wstr) shlwapi.PathStripToRootW
|
@ stdcall PathStripToRootW(wstr)
|
||||||
@ stdcall PathUnExpandEnvStringsA(str ptr long) shlwapi.PathUnExpandEnvStringsA
|
@ stdcall PathUnExpandEnvStringsA(str ptr long) shlwapi.PathUnExpandEnvStringsA
|
||||||
@ stdcall PathUnExpandEnvStringsW(wstr ptr long) shlwapi.PathUnExpandEnvStringsW
|
@ stdcall PathUnExpandEnvStringsW(wstr ptr long) shlwapi.PathUnExpandEnvStringsW
|
||||||
@ stdcall PathUnquoteSpacesA(str) shlwapi.PathUnquoteSpacesA
|
@ stdcall PathUnquoteSpacesA(str) shlwapi.PathUnquoteSpacesA
|
||||||
|
|
|
@ -29,6 +29,13 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(path);
|
WINE_DEFAULT_DEBUG_CHANNEL(path);
|
||||||
|
|
||||||
|
char *char_next(const char *ptr)
|
||||||
|
{
|
||||||
|
if (!*ptr) return (LPSTR)ptr;
|
||||||
|
if (IsDBCSLeadByte( ptr[0] ) && ptr[1]) return (LPSTR)(ptr + 2);
|
||||||
|
return (LPSTR)(ptr + 1);
|
||||||
|
}
|
||||||
|
|
||||||
static SIZE_T strnlenW(const WCHAR *string, SIZE_T maxlen)
|
static SIZE_T strnlenW(const WCHAR *string, SIZE_T maxlen)
|
||||||
{
|
{
|
||||||
SIZE_T i;
|
SIZE_T i;
|
||||||
|
@ -865,3 +872,749 @@ BOOL WINAPI PathIsUNCEx(const WCHAR *path, const WCHAR **server)
|
||||||
if (server) *server = result;
|
if (server) *server = result;
|
||||||
return !!result;
|
return !!result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathIsUNCA(const char *path)
|
||||||
|
{
|
||||||
|
TRACE("%s\n", wine_dbgstr_a(path));
|
||||||
|
|
||||||
|
return path && (path[0] == '\\') && (path[1] == '\\');
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathIsUNCW(const WCHAR *path)
|
||||||
|
{
|
||||||
|
TRACE("%s\n", wine_dbgstr_w(path));
|
||||||
|
|
||||||
|
return path && (path[0] == '\\') && (path[1] == '\\');
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathIsRelativeA(const char *path)
|
||||||
|
{
|
||||||
|
TRACE("%s\n", wine_dbgstr_a(path));
|
||||||
|
|
||||||
|
if (!path || !*path || IsDBCSLeadByte(*path))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return !(*path == '\\' || (*path && path[1] == ':'));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathIsRelativeW(const WCHAR *path)
|
||||||
|
{
|
||||||
|
TRACE("%s\n", wine_dbgstr_w(path));
|
||||||
|
|
||||||
|
if (!path || !*path)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return !(*path == '\\' || (*path && path[1] == ':'));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathIsUNCServerShareA(const char *path)
|
||||||
|
{
|
||||||
|
BOOL seen_slash = FALSE;
|
||||||
|
|
||||||
|
TRACE("%s\n", wine_dbgstr_a(path));
|
||||||
|
|
||||||
|
if (path && *path++ == '\\' && *path++ == '\\')
|
||||||
|
{
|
||||||
|
while (*path)
|
||||||
|
{
|
||||||
|
if (*path == '\\')
|
||||||
|
{
|
||||||
|
if (seen_slash)
|
||||||
|
return FALSE;
|
||||||
|
seen_slash = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = char_next(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return seen_slash;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathIsUNCServerShareW(const WCHAR *path)
|
||||||
|
{
|
||||||
|
BOOL seen_slash = FALSE;
|
||||||
|
|
||||||
|
TRACE("%s\n", wine_dbgstr_w(path));
|
||||||
|
|
||||||
|
if (path && *path++ == '\\' && *path++ == '\\')
|
||||||
|
{
|
||||||
|
while (*path)
|
||||||
|
{
|
||||||
|
if (*path == '\\')
|
||||||
|
{
|
||||||
|
if (seen_slash)
|
||||||
|
return FALSE;
|
||||||
|
seen_slash = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
path++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return seen_slash;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathIsRootA(const char *path)
|
||||||
|
{
|
||||||
|
TRACE("%s\n", wine_dbgstr_a(path));
|
||||||
|
|
||||||
|
if (!path || !*path)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (*path == '\\')
|
||||||
|
{
|
||||||
|
if (!path[1])
|
||||||
|
return TRUE; /* \ */
|
||||||
|
else if (path[1] == '\\')
|
||||||
|
{
|
||||||
|
BOOL seen_slash = FALSE;
|
||||||
|
path += 2;
|
||||||
|
|
||||||
|
/* Check for UNC root path */
|
||||||
|
while (*path)
|
||||||
|
{
|
||||||
|
if (*path == '\\')
|
||||||
|
{
|
||||||
|
if (seen_slash)
|
||||||
|
return FALSE;
|
||||||
|
seen_slash = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = char_next(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (path[1] == ':' && path[2] == '\\' && path[3] == '\0')
|
||||||
|
return TRUE; /* X:\ */
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathIsRootW(const WCHAR *path)
|
||||||
|
{
|
||||||
|
TRACE("%s\n", wine_dbgstr_w(path));
|
||||||
|
|
||||||
|
if (!path || !*path)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (*path == '\\')
|
||||||
|
{
|
||||||
|
if (!path[1])
|
||||||
|
return TRUE; /* \ */
|
||||||
|
else if (path[1] == '\\')
|
||||||
|
{
|
||||||
|
BOOL seen_slash = FALSE;
|
||||||
|
|
||||||
|
path += 2;
|
||||||
|
/* Check for UNC root path */
|
||||||
|
while (*path)
|
||||||
|
{
|
||||||
|
if (*path == '\\')
|
||||||
|
{
|
||||||
|
if (seen_slash)
|
||||||
|
return FALSE;
|
||||||
|
seen_slash = TRUE;
|
||||||
|
}
|
||||||
|
path++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (path[1] == ':' && path[2] == '\\' && path[3] == '\0')
|
||||||
|
return TRUE; /* X:\ */
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathRemoveFileSpecA(char *path)
|
||||||
|
{
|
||||||
|
char *filespec = path;
|
||||||
|
BOOL modified = FALSE;
|
||||||
|
|
||||||
|
TRACE("%s\n", wine_dbgstr_a(path));
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Skip directory or UNC path */
|
||||||
|
if (*path == '\\')
|
||||||
|
filespec = ++path;
|
||||||
|
if (*path == '\\')
|
||||||
|
filespec = ++path;
|
||||||
|
|
||||||
|
while (*path)
|
||||||
|
{
|
||||||
|
if (*path == '\\')
|
||||||
|
filespec = path; /* Skip dir */
|
||||||
|
else if (*path == ':')
|
||||||
|
{
|
||||||
|
filespec = ++path; /* Skip drive */
|
||||||
|
if (*path == '\\')
|
||||||
|
filespec++;
|
||||||
|
}
|
||||||
|
if (!(path = char_next(path)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*filespec)
|
||||||
|
{
|
||||||
|
*filespec = '\0';
|
||||||
|
modified = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathRemoveFileSpecW(WCHAR *path)
|
||||||
|
{
|
||||||
|
WCHAR *filespec = path;
|
||||||
|
BOOL modified = FALSE;
|
||||||
|
|
||||||
|
TRACE("%s\n", wine_dbgstr_w(path));
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Skip directory or UNC path */
|
||||||
|
if (*path == '\\')
|
||||||
|
filespec = ++path;
|
||||||
|
if (*path == '\\')
|
||||||
|
filespec = ++path;
|
||||||
|
|
||||||
|
while (*path)
|
||||||
|
{
|
||||||
|
if (*path == '\\')
|
||||||
|
filespec = path; /* Skip dir */
|
||||||
|
else if (*path == ':')
|
||||||
|
{
|
||||||
|
filespec = ++path; /* Skip drive */
|
||||||
|
if (*path == '\\')
|
||||||
|
filespec++;
|
||||||
|
}
|
||||||
|
|
||||||
|
path++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*filespec)
|
||||||
|
{
|
||||||
|
*filespec = '\0';
|
||||||
|
modified = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathStripToRootA(char *path)
|
||||||
|
{
|
||||||
|
TRACE("%s\n", wine_dbgstr_a(path));
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
while (!PathIsRootA(path))
|
||||||
|
if (!PathRemoveFileSpecA(path))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathStripToRootW(WCHAR *path)
|
||||||
|
{
|
||||||
|
TRACE("%s\n", wine_dbgstr_w(path));
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
while (!PathIsRootW(path))
|
||||||
|
if (!PathRemoveFileSpecW(path))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPSTR WINAPI PathAddBackslashA(char *path)
|
||||||
|
{
|
||||||
|
unsigned int len;
|
||||||
|
char *prev = path;
|
||||||
|
|
||||||
|
TRACE("%s\n", wine_dbgstr_a(path));
|
||||||
|
|
||||||
|
if (!path || (len = strlen(path)) >= MAX_PATH)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
path = char_next(prev);
|
||||||
|
if (*path)
|
||||||
|
prev = path;
|
||||||
|
} while (*path);
|
||||||
|
|
||||||
|
if (*prev != '\\')
|
||||||
|
{
|
||||||
|
*path++ = '\\';
|
||||||
|
*path = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPWSTR WINAPI PathAddBackslashW(WCHAR *path)
|
||||||
|
{
|
||||||
|
unsigned int len;
|
||||||
|
|
||||||
|
TRACE("%s\n", wine_dbgstr_w(path));
|
||||||
|
|
||||||
|
if (!path || (len = strlenW(path)) >= MAX_PATH)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
path += len;
|
||||||
|
if (path[-1] != '\\')
|
||||||
|
{
|
||||||
|
*path++ = '\\';
|
||||||
|
*path = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPSTR WINAPI PathFindExtensionA(const char *path)
|
||||||
|
{
|
||||||
|
const char *lastpoint = NULL;
|
||||||
|
|
||||||
|
TRACE("%s\n", wine_dbgstr_a(path));
|
||||||
|
|
||||||
|
if (path)
|
||||||
|
{
|
||||||
|
while (*path)
|
||||||
|
{
|
||||||
|
if (*path == '\\' || *path == ' ')
|
||||||
|
lastpoint = NULL;
|
||||||
|
else if (*path == '.')
|
||||||
|
lastpoint = path;
|
||||||
|
path = char_next(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (LPSTR)(lastpoint ? lastpoint : path);
|
||||||
|
}
|
||||||
|
|
||||||
|
LPWSTR WINAPI PathFindExtensionW(const WCHAR *path)
|
||||||
|
{
|
||||||
|
const WCHAR *lastpoint = NULL;
|
||||||
|
|
||||||
|
TRACE("%s\n", wine_dbgstr_w(path));
|
||||||
|
|
||||||
|
if (path)
|
||||||
|
{
|
||||||
|
while (*path)
|
||||||
|
{
|
||||||
|
if (*path == '\\' || *path == ' ')
|
||||||
|
lastpoint = NULL;
|
||||||
|
else if (*path == '.')
|
||||||
|
lastpoint = path;
|
||||||
|
path++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (LPWSTR)(lastpoint ? lastpoint : path);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathAddExtensionA(char *path, const char *ext)
|
||||||
|
{
|
||||||
|
unsigned int len;
|
||||||
|
|
||||||
|
TRACE("%s, %s\n", wine_dbgstr_a(path), wine_dbgstr_a(ext));
|
||||||
|
|
||||||
|
if (!path || !ext || *(PathFindExtensionA(path)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
len = strlen(path);
|
||||||
|
if (len + strlen(ext) >= MAX_PATH)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
strcpy(path + len, ext);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathAddExtensionW(WCHAR *path, const WCHAR *ext)
|
||||||
|
{
|
||||||
|
unsigned int len;
|
||||||
|
|
||||||
|
TRACE("%s, %s\n", wine_dbgstr_w(path), wine_dbgstr_w(ext));
|
||||||
|
|
||||||
|
if (!path || !ext || *(PathFindExtensionW(path)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
len = strlenW(path);
|
||||||
|
if (len + strlenW(ext) >= MAX_PATH)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
strcpyW(path + len, ext);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathCanonicalizeW(WCHAR *buffer, const WCHAR *path)
|
||||||
|
{
|
||||||
|
const WCHAR *src = path;
|
||||||
|
WCHAR *dst = buffer;
|
||||||
|
|
||||||
|
TRACE("%p, %s\n", buffer, wine_dbgstr_w(path));
|
||||||
|
|
||||||
|
if (dst)
|
||||||
|
*dst = '\0';
|
||||||
|
|
||||||
|
if (!dst || !path)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*path)
|
||||||
|
{
|
||||||
|
*buffer++ = '\\';
|
||||||
|
*buffer = '\0';
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy path root */
|
||||||
|
if (*src == '\\')
|
||||||
|
{
|
||||||
|
*dst++ = *src++;
|
||||||
|
}
|
||||||
|
else if (*src && src[1] == ':')
|
||||||
|
{
|
||||||
|
/* X:\ */
|
||||||
|
*dst++ = *src++;
|
||||||
|
*dst++ = *src++;
|
||||||
|
if (*src == '\\')
|
||||||
|
*dst++ = *src++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Canonicalize the rest of the path */
|
||||||
|
while (*src)
|
||||||
|
{
|
||||||
|
if (*src == '.')
|
||||||
|
{
|
||||||
|
if (src[1] == '\\' && (src == path || src[-1] == '\\' || src[-1] == ':'))
|
||||||
|
{
|
||||||
|
src += 2; /* Skip .\ */
|
||||||
|
}
|
||||||
|
else if (src[1] == '.' && (dst == buffer || dst[-1] == '\\'))
|
||||||
|
{
|
||||||
|
/* \.. backs up a directory, over the root if it has no \ following X:.
|
||||||
|
* .. is ignored if it would remove a UNC server name or initial \\
|
||||||
|
*/
|
||||||
|
if (dst != buffer)
|
||||||
|
{
|
||||||
|
*dst = '\0'; /* Allow PathIsUNCServerShareA test on lpszBuf */
|
||||||
|
if (dst > buffer + 1 && dst[-1] == '\\' && (dst[-2] != '\\' || dst > buffer + 2))
|
||||||
|
{
|
||||||
|
if (dst[-2] == ':' && (dst > buffer + 3 || dst[-3] == ':'))
|
||||||
|
{
|
||||||
|
dst -= 2;
|
||||||
|
while (dst > buffer && *dst != '\\')
|
||||||
|
dst--;
|
||||||
|
if (*dst == '\\')
|
||||||
|
dst++; /* Reset to last '\' */
|
||||||
|
else
|
||||||
|
dst = buffer; /* Start path again from new root */
|
||||||
|
}
|
||||||
|
else if (dst[-2] != ':' && !PathIsUNCServerShareW(buffer))
|
||||||
|
dst -= 2;
|
||||||
|
}
|
||||||
|
while (dst > buffer && *dst != '\\')
|
||||||
|
dst--;
|
||||||
|
if (dst == buffer)
|
||||||
|
{
|
||||||
|
*dst++ = '\\';
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
src += 2; /* Skip .. in src path */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*dst++ = *src++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*dst++ = *src++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append \ to naked drive specs */
|
||||||
|
if (dst - buffer == 2 && dst[-1] == ':')
|
||||||
|
*dst++ = '\\';
|
||||||
|
*dst++ = '\0';
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathCanonicalizeA(char *buffer, const char *path)
|
||||||
|
{
|
||||||
|
WCHAR pathW[MAX_PATH], bufferW[MAX_PATH];
|
||||||
|
BOOL ret;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
TRACE("%p, %s\n", buffer, wine_dbgstr_a(path));
|
||||||
|
|
||||||
|
if (buffer)
|
||||||
|
*buffer = '\0';
|
||||||
|
|
||||||
|
if (!buffer || !path)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = MultiByteToWideChar(CP_ACP, 0, path, -1, pathW, ARRAY_SIZE(pathW));
|
||||||
|
if (!len)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
ret = PathCanonicalizeW(bufferW, pathW);
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, MAX_PATH, 0, 0);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
WCHAR * WINAPI PathCombineW(WCHAR *dst, const WCHAR *dir, const WCHAR *file)
|
||||||
|
{
|
||||||
|
BOOL use_both = FALSE, strip = FALSE;
|
||||||
|
WCHAR tmp[MAX_PATH];
|
||||||
|
|
||||||
|
TRACE("%p, %s, %s\n", dst, wine_dbgstr_w(dir), wine_dbgstr_w(file));
|
||||||
|
|
||||||
|
/* Invalid parameters */
|
||||||
|
if (!dst)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!dir && !file)
|
||||||
|
{
|
||||||
|
dst[0] = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!file || !*file) && dir)
|
||||||
|
{
|
||||||
|
/* Use dir only */
|
||||||
|
lstrcpynW(tmp, dir, ARRAY_SIZE(tmp));
|
||||||
|
}
|
||||||
|
else if (!dir || !*dir || !PathIsRelativeW(file))
|
||||||
|
{
|
||||||
|
if (!dir || !*dir || *file != '\\' || PathIsUNCW(file))
|
||||||
|
{
|
||||||
|
/* Use file only */
|
||||||
|
lstrcpynW(tmp, file, ARRAY_SIZE(tmp));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
use_both = TRUE;
|
||||||
|
strip = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
use_both = TRUE;
|
||||||
|
|
||||||
|
if (use_both)
|
||||||
|
{
|
||||||
|
lstrcpynW(tmp, dir, ARRAY_SIZE(tmp));
|
||||||
|
if (strip)
|
||||||
|
{
|
||||||
|
PathStripToRootW(tmp);
|
||||||
|
file++; /* Skip '\' */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PathAddBackslashW(tmp) || strlenW(tmp) + strlenW(file) >= MAX_PATH)
|
||||||
|
{
|
||||||
|
dst[0] = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcatW(tmp, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
PathCanonicalizeW(dst, tmp);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPSTR WINAPI PathCombineA(char *dst, const char *dir, const char *file)
|
||||||
|
{
|
||||||
|
WCHAR dstW[MAX_PATH], dirW[MAX_PATH], fileW[MAX_PATH];
|
||||||
|
|
||||||
|
TRACE("%p, %s, %s\n", dst, wine_dbgstr_a(dir), wine_dbgstr_a(file));
|
||||||
|
|
||||||
|
/* Invalid parameters */
|
||||||
|
if (!dst)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dst[0] = 0;
|
||||||
|
|
||||||
|
if (!dir && !file)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (dir && !MultiByteToWideChar(CP_ACP, 0, dir, -1, dirW, ARRAY_SIZE(dirW)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (file && !MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, ARRAY_SIZE(fileW)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (PathCombineW(dstW, dir ? dirW : NULL, file ? fileW : NULL))
|
||||||
|
if (WideCharToMultiByte(CP_ACP, 0, dstW, -1, dst, MAX_PATH, 0, 0))
|
||||||
|
return dst;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathAppendA(char *path, const char *append)
|
||||||
|
{
|
||||||
|
TRACE("%s, %s\n", wine_dbgstr_a(path), wine_dbgstr_a(append));
|
||||||
|
|
||||||
|
if (path && append)
|
||||||
|
{
|
||||||
|
if (!PathIsUNCA(append))
|
||||||
|
while (*append == '\\')
|
||||||
|
append++;
|
||||||
|
|
||||||
|
if (PathCombineA(path, path, append))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathAppendW(WCHAR *path, const WCHAR *append)
|
||||||
|
{
|
||||||
|
TRACE("%s, %s\n", wine_dbgstr_w(path), wine_dbgstr_w(append));
|
||||||
|
|
||||||
|
if (path && append)
|
||||||
|
{
|
||||||
|
if (!PathIsUNCW(append))
|
||||||
|
while (*append == '\\')
|
||||||
|
append++;
|
||||||
|
|
||||||
|
if (PathCombineW(path, path, append))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WINAPI PathCommonPrefixA(const char *file1, const char *file2, char *path)
|
||||||
|
{
|
||||||
|
const char *iter1 = file1;
|
||||||
|
const char *iter2 = file2;
|
||||||
|
unsigned int len = 0;
|
||||||
|
|
||||||
|
TRACE("%s, %s, %p.\n", wine_dbgstr_a(file1), wine_dbgstr_a(file2), path);
|
||||||
|
|
||||||
|
if (path)
|
||||||
|
*path = '\0';
|
||||||
|
|
||||||
|
if (!file1 || !file2)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Handle roots first */
|
||||||
|
if (PathIsUNCA(file1))
|
||||||
|
{
|
||||||
|
if (!PathIsUNCA(file2))
|
||||||
|
return 0;
|
||||||
|
iter1 += 2;
|
||||||
|
iter2 += 2;
|
||||||
|
}
|
||||||
|
else if (PathIsUNCA(file2))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
/* Update len */
|
||||||
|
if ((!*iter1 || *iter1 == '\\') && (!*iter2 || *iter2 == '\\'))
|
||||||
|
len = iter1 - file1; /* Common to this point */
|
||||||
|
|
||||||
|
if (!*iter1 || (tolower(*iter1) != tolower(*iter2)))
|
||||||
|
break; /* Strings differ at this point */
|
||||||
|
|
||||||
|
iter1++;
|
||||||
|
iter2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 2)
|
||||||
|
len++; /* Feature/Bug compatible with Win32 */
|
||||||
|
|
||||||
|
if (len && path)
|
||||||
|
{
|
||||||
|
memcpy(path, file1, len);
|
||||||
|
path[len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WINAPI PathCommonPrefixW(const WCHAR *file1, const WCHAR *file2, WCHAR *path)
|
||||||
|
{
|
||||||
|
const WCHAR *iter1 = file1;
|
||||||
|
const WCHAR *iter2 = file2;
|
||||||
|
unsigned int len = 0;
|
||||||
|
|
||||||
|
TRACE("%s, %s, %p\n", wine_dbgstr_w(file1), wine_dbgstr_w(file2), path);
|
||||||
|
|
||||||
|
if (path)
|
||||||
|
*path = '\0';
|
||||||
|
|
||||||
|
if (!file1 || !file2)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Handle roots first */
|
||||||
|
if (PathIsUNCW(file1))
|
||||||
|
{
|
||||||
|
if (!PathIsUNCW(file2))
|
||||||
|
return 0;
|
||||||
|
iter1 += 2;
|
||||||
|
iter2 += 2;
|
||||||
|
}
|
||||||
|
else if (PathIsUNCW(file2))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
/* Update len */
|
||||||
|
if ((!*iter1 || *iter1 == '\\') && (!*iter2 || *iter2 == '\\'))
|
||||||
|
len = iter1 - file1; /* Common to this point */
|
||||||
|
|
||||||
|
if (!*iter1 || (tolowerW(*iter1) != tolowerW(*iter2)))
|
||||||
|
break; /* Strings differ at this point */
|
||||||
|
|
||||||
|
iter1++;
|
||||||
|
iter2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 2)
|
||||||
|
len++; /* Feature/Bug compatible with Win32 */
|
||||||
|
|
||||||
|
if (len && path)
|
||||||
|
{
|
||||||
|
memcpy(path, file1, len * sizeof(WCHAR));
|
||||||
|
path[len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathIsPrefixA(const char *prefix, const char *path)
|
||||||
|
{
|
||||||
|
TRACE("%s, %s\n", wine_dbgstr_a(prefix), wine_dbgstr_a(path));
|
||||||
|
|
||||||
|
return prefix && path && PathCommonPrefixA(path, prefix, NULL) == (int)strlen(prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI PathIsPrefixW(const WCHAR *prefix, const WCHAR *path)
|
||||||
|
{
|
||||||
|
TRACE("%s, %s\n", wine_dbgstr_w(prefix), wine_dbgstr_w(path));
|
||||||
|
|
||||||
|
return prefix && path && PathCommonPrefixW(path, prefix, NULL) == (int)strlenW(prefix);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue