92b0076c53
And again S_FALSE was incorrectly used to indicate an error. Fix this and be more compatible to the Windows 8 implementation of this function: - return E_INVALIDARG instead of S_FALSE if pszPath is NULL - return E_INVALIDARG instead of S_FALSE if cchPath < 4 - return E_INVALIDARG if cchPath > PATHCCH_MAX_CCH - allow stripping of "\\?\c:" and don't require "\\?\c:\" - verify that the character at the drive letter position is actually an alphabetic character - since the passed pszPath must not necessarily be null terminated and we always have enough space after the memmove we can always ensure the null termination of the stripped result Also extended/fixed the TestPathCchStripPrefixctest
1012 lines
22 KiB
C
1012 lines
22 KiB
C
/**
|
|
* WinPR: Windows Portable Runtime
|
|
* Path Functions
|
|
*
|
|
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <winpr/crt.h>
|
|
#include <winpr/heap.h>
|
|
#include <winpr/tchar.h>
|
|
|
|
#include <winpr/path.h>
|
|
|
|
#define PATH_SLASH_CHR '/'
|
|
#define PATH_SLASH_STR "/"
|
|
|
|
#define PATH_BACKSLASH_CHR '\\'
|
|
#define PATH_BACKSLASH_STR "\\"
|
|
|
|
#ifdef _WIN32
|
|
#define PATH_SLASH_STR_W L"/"
|
|
#define PATH_BACKSLASH_STR_W L"\\"
|
|
#else
|
|
#define PATH_SLASH_STR_W "/"
|
|
#define PATH_BACKSLASH_STR_W "\\"
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
#define PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
|
|
#define PATH_SEPARATOR_STR PATH_BACKSLASH_STR
|
|
#define PATH_SEPARATOR_STR_W PATH_BACKSLASH_STR_W
|
|
#else
|
|
#define PATH_SEPARATOR_CHR PATH_SLASH_CHR
|
|
#define PATH_SEPARATOR_STR PATH_SLASH_STR
|
|
#define PATH_SEPARATOR_STR_W PATH_SLASH_STR_W
|
|
#endif
|
|
|
|
#define SHARED_LIBRARY_EXT_DLL "dll"
|
|
#define SHARED_LIBRARY_EXT_SO "so"
|
|
#define SHARED_LIBRARY_EXT_DYLIB "dylib"
|
|
|
|
#ifdef _WIN32
|
|
#define SHARED_LIBRARY_EXT SHARED_LIBRARY_EXT_DLL
|
|
#elif defined(__APPLE__)
|
|
#define SHARED_LIBRARY_EXT SHARED_LIBRARY_EXT_DYLIB
|
|
#else
|
|
#define SHARED_LIBRARY_EXT SHARED_LIBRARY_EXT_SO
|
|
#endif
|
|
|
|
/*
|
|
* PathCchAddBackslash
|
|
*/
|
|
|
|
/* Windows-style Paths */
|
|
|
|
#define DEFINE_UNICODE FALSE
|
|
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
|
|
#define PATH_CCH_ADD_SEPARATOR PathCchAddBackslashA
|
|
#include "include/PathCchAddSeparator.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_SEPARATOR
|
|
|
|
#define DEFINE_UNICODE TRUE
|
|
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
|
|
#define PATH_CCH_ADD_SEPARATOR PathCchAddBackslashW
|
|
#include "include/PathCchAddSeparator.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_SEPARATOR
|
|
|
|
/* Unix-style Paths */
|
|
|
|
#define DEFINE_UNICODE FALSE
|
|
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
|
|
#define PATH_CCH_ADD_SEPARATOR PathCchAddSlashA
|
|
#include "include/PathCchAddSeparator.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_SEPARATOR
|
|
|
|
#define DEFINE_UNICODE TRUE
|
|
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
|
|
#define PATH_CCH_ADD_SEPARATOR PathCchAddSlashW
|
|
#include "include/PathCchAddSeparator.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_SEPARATOR
|
|
|
|
/* Native-style Paths */
|
|
|
|
#define DEFINE_UNICODE FALSE
|
|
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
|
|
#define PATH_CCH_ADD_SEPARATOR PathCchAddSeparatorA
|
|
#include "include/PathCchAddSeparator.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_SEPARATOR
|
|
|
|
#define DEFINE_UNICODE TRUE
|
|
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
|
|
#define PATH_CCH_ADD_SEPARATOR PathCchAddSeparatorW
|
|
#include "include/PathCchAddSeparator.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_SEPARATOR
|
|
|
|
/*
|
|
* PathCchRemoveBackslash
|
|
*/
|
|
|
|
HRESULT PathCchRemoveBackslashA(PSTR pszPath, size_t cchPath)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
HRESULT PathCchRemoveBackslashW(PWSTR pszPath, size_t cchPath)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* PathCchAddBackslashEx
|
|
*/
|
|
|
|
/* Windows-style Paths */
|
|
|
|
#define DEFINE_UNICODE FALSE
|
|
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
|
|
#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddBackslashExA
|
|
#include "include/PathCchAddSeparatorEx.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_SEPARATOR_EX
|
|
|
|
#define DEFINE_UNICODE TRUE
|
|
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
|
|
#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddBackslashExW
|
|
#include "include/PathCchAddSeparatorEx.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_SEPARATOR_EX
|
|
|
|
/* Unix-style Paths */
|
|
|
|
#define DEFINE_UNICODE FALSE
|
|
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
|
|
#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSlashExA
|
|
#include "include/PathCchAddSeparatorEx.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_SEPARATOR_EX
|
|
|
|
#define DEFINE_UNICODE TRUE
|
|
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
|
|
#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSlashExW
|
|
#include "include/PathCchAddSeparatorEx.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_SEPARATOR_EX
|
|
|
|
/* Native-style Paths */
|
|
|
|
#define DEFINE_UNICODE FALSE
|
|
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
|
|
#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSeparatorExA
|
|
#include "include/PathCchAddSeparatorEx.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_SEPARATOR_EX
|
|
|
|
#define DEFINE_UNICODE TRUE
|
|
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
|
|
#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSeparatorExW
|
|
#include "include/PathCchAddSeparatorEx.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_SEPARATOR_EX
|
|
|
|
HRESULT PathCchRemoveBackslashExA(PSTR pszPath, size_t cchPath, PSTR* ppszEnd, size_t* pcchRemaining)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
HRESULT PathCchRemoveBackslashExW(PWSTR pszPath, size_t cchPath, PWSTR* ppszEnd, size_t* pcchRemaining)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* PathCchAddExtension
|
|
*/
|
|
|
|
/* Windows-style Paths */
|
|
|
|
#define DEFINE_UNICODE FALSE
|
|
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
|
|
#define PATH_CCH_ADD_EXTENSION PathCchAddExtensionA
|
|
#include "include/PathCchAddExtension.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_EXTENSION
|
|
|
|
#define DEFINE_UNICODE TRUE
|
|
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
|
|
#define PATH_CCH_ADD_EXTENSION PathCchAddExtensionW
|
|
#include "include/PathCchAddExtension.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_EXTENSION
|
|
|
|
/* Unix-style Paths */
|
|
|
|
#define DEFINE_UNICODE FALSE
|
|
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
|
|
#define PATH_CCH_ADD_EXTENSION UnixPathCchAddExtensionA
|
|
#include "include/PathCchAddExtension.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_EXTENSION
|
|
|
|
#define DEFINE_UNICODE TRUE
|
|
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
|
|
#define PATH_CCH_ADD_EXTENSION UnixPathCchAddExtensionW
|
|
#include "include/PathCchAddExtension.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_EXTENSION
|
|
|
|
/* Native-style Paths */
|
|
|
|
#define DEFINE_UNICODE FALSE
|
|
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
|
|
#define PATH_CCH_ADD_EXTENSION NativePathCchAddExtensionA
|
|
#include "include/PathCchAddExtension.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_EXTENSION
|
|
|
|
#define DEFINE_UNICODE TRUE
|
|
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
|
|
#define PATH_CCH_ADD_EXTENSION NativePathCchAddExtensionW
|
|
#include "include/PathCchAddExtension.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef PATH_CCH_ADD_EXTENSION
|
|
|
|
/*
|
|
* PathCchAppend
|
|
*/
|
|
|
|
/* Windows-style Paths */
|
|
|
|
#define DEFINE_UNICODE FALSE
|
|
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
|
|
#define _PATH_SEPARATOR_STR PATH_BACKSLASH_STR
|
|
#define PATH_CCH_APPEND PathCchAppendA
|
|
#include "include/PathCchAppend.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef _PATH_SEPARATOR_STR
|
|
#undef PATH_CCH_APPEND
|
|
|
|
#define DEFINE_UNICODE TRUE
|
|
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
|
|
#define _PATH_SEPARATOR_STR PATH_BACKSLASH_STR_W
|
|
#define PATH_CCH_APPEND PathCchAppendW
|
|
#include "include/PathCchAppend.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef _PATH_SEPARATOR_STR
|
|
#undef PATH_CCH_APPEND
|
|
|
|
/* Unix-style Paths */
|
|
|
|
#define DEFINE_UNICODE FALSE
|
|
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
|
|
#define _PATH_SEPARATOR_STR PATH_SLASH_STR
|
|
#define PATH_CCH_APPEND UnixPathCchAppendA
|
|
#include "include/PathCchAppend.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef _PATH_SEPARATOR_STR
|
|
#undef PATH_CCH_APPEND
|
|
|
|
#define DEFINE_UNICODE TRUE
|
|
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
|
|
#define _PATH_SEPARATOR_STR PATH_SLASH_STR_W
|
|
#define PATH_CCH_APPEND UnixPathCchAppendW
|
|
#include "include/PathCchAppend.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef _PATH_SEPARATOR_STR
|
|
#undef PATH_CCH_APPEND
|
|
|
|
/* Native-style Paths */
|
|
|
|
#define DEFINE_UNICODE FALSE
|
|
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
|
|
#define _PATH_SEPARATOR_STR PATH_SEPARATOR_STR
|
|
#define PATH_CCH_APPEND NativePathCchAppendA
|
|
#include "include/PathCchAppend.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef _PATH_SEPARATOR_STR
|
|
#undef PATH_CCH_APPEND
|
|
|
|
#define DEFINE_UNICODE TRUE
|
|
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
|
|
#define _PATH_SEPARATOR_STR PATH_SEPARATOR_STR_W
|
|
#define PATH_CCH_APPEND NativePathCchAppendW
|
|
#include "include/PathCchAppend.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef _PATH_SEPARATOR_STR
|
|
#undef PATH_CCH_APPEND
|
|
|
|
/*
|
|
* PathCchAppendEx
|
|
*/
|
|
|
|
HRESULT PathCchAppendExA(PSTR pszPath, size_t cchPath, PCSTR pszMore, unsigned long dwFlags)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
HRESULT PathCchAppendExW(PWSTR pszPath, size_t cchPath, PCWSTR pszMore, unsigned long dwFlags)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* PathCchCanonicalize
|
|
*/
|
|
|
|
HRESULT PathCchCanonicalizeA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
HRESULT PathCchCanonicalizeW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* PathCchCanonicalizeEx
|
|
*/
|
|
|
|
HRESULT PathCchCanonicalizeExA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn, unsigned long dwFlags)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
HRESULT PathCchCanonicalizeExW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn, unsigned long dwFlags)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* PathAllocCanonicalize
|
|
*/
|
|
|
|
HRESULT PathAllocCanonicalizeA(PCSTR pszPathIn, unsigned long dwFlags, PSTR* ppszPathOut)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
HRESULT PathAllocCanonicalizeW(PCWSTR pszPathIn, unsigned long dwFlags, PWSTR* ppszPathOut)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* PathCchCombine
|
|
*/
|
|
|
|
HRESULT PathCchCombineA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn, PCSTR pszMore)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
HRESULT PathCchCombineW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn, PCWSTR pszMore)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* PathCchCombineEx
|
|
*/
|
|
|
|
HRESULT PathCchCombineExA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn, PCSTR pszMore, unsigned long dwFlags)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
HRESULT PathCchCombineExW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn, PCWSTR pszMore, unsigned long dwFlags)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* PathAllocCombine
|
|
*/
|
|
|
|
/* Windows-style Paths */
|
|
|
|
#define DEFINE_UNICODE FALSE
|
|
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
|
|
#define _PATH_SEPARATOR_STR PATH_BACKSLASH_STR
|
|
#define PATH_ALLOC_COMBINE PathAllocCombineA
|
|
#include "include/PathAllocCombine.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef _PATH_SEPARATOR_STR
|
|
#undef PATH_ALLOC_COMBINE
|
|
|
|
#define DEFINE_UNICODE TRUE
|
|
#define _PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
|
|
#define _PATH_SEPARATOR_STR PATH_BACKSLASH_STR_W
|
|
#define PATH_ALLOC_COMBINE PathAllocCombineW
|
|
#include "include/PathAllocCombine.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef _PATH_SEPARATOR_STR
|
|
#undef PATH_ALLOC_COMBINE
|
|
|
|
/* Unix-style Paths */
|
|
|
|
#define DEFINE_UNICODE FALSE
|
|
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
|
|
#define _PATH_SEPARATOR_STR PATH_SLASH_STR
|
|
#define PATH_ALLOC_COMBINE UnixPathAllocCombineA
|
|
#include "include/PathAllocCombine.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef _PATH_SEPARATOR_STR
|
|
#undef PATH_ALLOC_COMBINE
|
|
|
|
#define DEFINE_UNICODE TRUE
|
|
#define _PATH_SEPARATOR_CHR PATH_SLASH_CHR
|
|
#define _PATH_SEPARATOR_STR PATH_SLASH_STR_W
|
|
#define PATH_ALLOC_COMBINE UnixPathAllocCombineW
|
|
#include "include/PathAllocCombine.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef _PATH_SEPARATOR_STR
|
|
#undef PATH_ALLOC_COMBINE
|
|
|
|
/* Native-style Paths */
|
|
|
|
#define DEFINE_UNICODE FALSE
|
|
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
|
|
#define _PATH_SEPARATOR_STR PATH_SEPARATOR_STR
|
|
#define PATH_ALLOC_COMBINE NativePathAllocCombineA
|
|
#include "include/PathAllocCombine.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef _PATH_SEPARATOR_STR
|
|
#undef PATH_ALLOC_COMBINE
|
|
|
|
#define DEFINE_UNICODE TRUE
|
|
#define _PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
|
|
#define _PATH_SEPARATOR_STR PATH_SEPARATOR_STR_W
|
|
#define PATH_ALLOC_COMBINE NativePathAllocCombineW
|
|
#include "include/PathAllocCombine.c"
|
|
#undef DEFINE_UNICODE
|
|
#undef _PATH_SEPARATOR_CHR
|
|
#undef _PATH_SEPARATOR_STR
|
|
#undef PATH_ALLOC_COMBINE
|
|
|
|
/**
|
|
* PathCchFindExtension
|
|
*/
|
|
|
|
HRESULT PathCchFindExtensionA(PCSTR pszPath, size_t cchPath, PCSTR* ppszExt)
|
|
{
|
|
char* p = (char*) pszPath;
|
|
|
|
/* find end of string */
|
|
|
|
while (*p && cchPath)
|
|
{
|
|
cchPath--;
|
|
p++;
|
|
}
|
|
|
|
/* search backwards for '.' */
|
|
|
|
while (p > pszPath)
|
|
{
|
|
if (*p == '.')
|
|
{
|
|
*ppszExt = (PCSTR) p;
|
|
return S_OK;
|
|
}
|
|
|
|
if ((*p == '\\') || (*p == '/') || (*p == ':'))
|
|
return S_FALSE;
|
|
|
|
p--;
|
|
}
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
HRESULT PathCchFindExtensionW(PCWSTR pszPath, size_t cchPath, PCWSTR* ppszExt)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* PathCchRenameExtension
|
|
*/
|
|
|
|
HRESULT PathCchRenameExtensionA(PSTR pszPath, size_t cchPath, PCSTR pszExt)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
HRESULT PathCchRenameExtensionW(PWSTR pszPath, size_t cchPath, PCWSTR pszExt)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* PathCchRemoveExtension
|
|
*/
|
|
|
|
HRESULT PathCchRemoveExtensionA(PSTR pszPath, size_t cchPath)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
HRESULT PathCchRemoveExtensionW(PWSTR pszPath, size_t cchPath)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* PathCchIsRoot
|
|
*/
|
|
|
|
BOOL PathCchIsRootA(PCSTR pszPath)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
BOOL PathCchIsRootW(PCWSTR pszPath)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* PathIsUNCEx
|
|
*/
|
|
|
|
BOOL PathIsUNCExA(PCSTR pszPath, PCSTR* ppszServer)
|
|
{
|
|
if (!pszPath)
|
|
return FALSE;
|
|
|
|
if ((pszPath[0] == '\\') && (pszPath[1] == '\\'))
|
|
{
|
|
*ppszServer = &pszPath[2];
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL PathIsUNCExW(PCWSTR pszPath, PCWSTR* ppszServer)
|
|
{
|
|
if (!pszPath)
|
|
return FALSE;
|
|
|
|
if ((pszPath[0] == '\\') && (pszPath[1] == '\\'))
|
|
{
|
|
*ppszServer = &pszPath[2];
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* PathCchSkipRoot
|
|
*/
|
|
|
|
HRESULT PathCchSkipRootA(PCSTR pszPath, PCSTR* ppszRootEnd)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
HRESULT PathCchSkipRootW(PCWSTR pszPath, PCWSTR* ppszRootEnd)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* PathCchStripToRoot
|
|
*/
|
|
|
|
HRESULT PathCchStripToRootA(PSTR pszPath, size_t cchPath)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
HRESULT PathCchStripToRootW(PWSTR pszPath, size_t cchPath)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* PathCchStripPrefix
|
|
*/
|
|
|
|
HRESULT PathCchStripPrefixA(PSTR pszPath, size_t cchPath)
|
|
{
|
|
BOOL hasPrefix;
|
|
|
|
if (!pszPath)
|
|
return E_INVALIDARG;
|
|
|
|
if (cchPath < 4 || cchPath > PATHCCH_MAX_CCH)
|
|
return E_INVALIDARG;
|
|
|
|
hasPrefix = ((pszPath[0] == '\\') && (pszPath[1] == '\\') &&
|
|
(pszPath[2] == '?') && (pszPath[3] == '\\')) ? TRUE : FALSE;
|
|
|
|
if (hasPrefix)
|
|
{
|
|
if (cchPath < 6)
|
|
return S_FALSE;
|
|
|
|
if (IsCharAlpha(pszPath[4]) && (pszPath[5] == ':')) /* like C: */
|
|
{
|
|
memmove_s(pszPath, cchPath, &pszPath[4], cchPath - 4);
|
|
/* since the passed pszPath must not necessarily be null terminated
|
|
* and we always have enough space after the strip we can always
|
|
* ensure the null termination of the stripped result
|
|
*/
|
|
pszPath[cchPath - 4] = 0;
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
HRESULT PathCchStripPrefixW(PWSTR pszPath, size_t cchPath)
|
|
{
|
|
BOOL hasPrefix;
|
|
|
|
if (!pszPath)
|
|
return E_INVALIDARG;
|
|
|
|
if (cchPath < 4 || cchPath > PATHCCH_MAX_CCH)
|
|
return E_INVALIDARG;
|
|
|
|
hasPrefix = ((pszPath[0] == '\\') && (pszPath[1] == '\\') &&
|
|
(pszPath[2] == '?') && (pszPath[3] == '\\')) ? TRUE : FALSE;
|
|
|
|
if (hasPrefix)
|
|
{
|
|
if (cchPath < 6)
|
|
return S_FALSE;
|
|
|
|
if (cchPath < (lstrlenW(&pszPath[4]) + 1))
|
|
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
if (IsCharAlpha(pszPath[4]) && (pszPath[5] == ':')) /* like C: */
|
|
{
|
|
wmemmove_s(pszPath, cchPath, &pszPath[4], cchPath - 4);
|
|
/* since the passed pszPath must not necessarily be null terminated
|
|
* and we always have enough space after the strip we can always
|
|
* ensure the null termination of the stripped result
|
|
*/
|
|
pszPath[cchPath - 4] = 0;
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
/**
|
|
* PathCchRemoveFileSpec
|
|
*/
|
|
|
|
HRESULT PathCchRemoveFileSpecA(PSTR pszPath, size_t cchPath)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
HRESULT PathCchRemoveFileSpecW(PWSTR pszPath, size_t cchPath)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Path Portability Functions
|
|
*/
|
|
|
|
/**
|
|
* PathCchConvertStyle
|
|
*/
|
|
|
|
HRESULT PathCchConvertStyleA(PSTR pszPath, size_t cchPath, unsigned long dwFlags)
|
|
{
|
|
size_t index;
|
|
|
|
if (dwFlags == PATH_STYLE_WINDOWS)
|
|
{
|
|
for (index = 0; index < cchPath; index++)
|
|
{
|
|
if (pszPath[index] == PATH_SLASH_CHR)
|
|
pszPath[index] = PATH_BACKSLASH_CHR;
|
|
}
|
|
}
|
|
else if (dwFlags == PATH_STYLE_UNIX)
|
|
{
|
|
for (index = 0; index < cchPath; index++)
|
|
{
|
|
if (pszPath[index] == PATH_BACKSLASH_CHR)
|
|
pszPath[index] = PATH_SLASH_CHR;
|
|
}
|
|
}
|
|
else if (dwFlags == PATH_STYLE_NATIVE)
|
|
{
|
|
if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR)
|
|
{
|
|
/* Unix-style to Windows-style */
|
|
|
|
for (index = 0; index < cchPath; index++)
|
|
{
|
|
if (pszPath[index] == PATH_SLASH_CHR)
|
|
pszPath[index] = PATH_BACKSLASH_CHR;
|
|
}
|
|
}
|
|
else if (PATH_SEPARATOR_CHR == PATH_SLASH_CHR)
|
|
{
|
|
/* Windows-style to Unix-style */
|
|
|
|
for (index = 0; index < cchPath; index++)
|
|
{
|
|
if (pszPath[index] == PATH_BACKSLASH_CHR)
|
|
pszPath[index] = PATH_SLASH_CHR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Unexpected error */
|
|
return S_FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Gangnam style? */
|
|
return S_FALSE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT PathCchConvertStyleW(PWSTR pszPath, size_t cchPath, unsigned long dwFlags)
|
|
{
|
|
size_t index;
|
|
|
|
if (dwFlags == PATH_STYLE_WINDOWS)
|
|
{
|
|
for (index = 0; index < cchPath; index++)
|
|
{
|
|
if (pszPath[index] == PATH_SLASH_CHR)
|
|
pszPath[index] = PATH_BACKSLASH_CHR;
|
|
}
|
|
}
|
|
else if (dwFlags == PATH_STYLE_UNIX)
|
|
{
|
|
for (index = 0; index < cchPath; index++)
|
|
{
|
|
if (pszPath[index] == PATH_BACKSLASH_CHR)
|
|
pszPath[index] = PATH_SLASH_CHR;
|
|
}
|
|
}
|
|
else if (dwFlags == PATH_STYLE_NATIVE)
|
|
{
|
|
if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR)
|
|
{
|
|
/* Unix-style to Windows-style */
|
|
|
|
for (index = 0; index < cchPath; index++)
|
|
{
|
|
if (pszPath[index] == PATH_SLASH_CHR)
|
|
pszPath[index] = PATH_BACKSLASH_CHR;
|
|
}
|
|
}
|
|
else if (PATH_SEPARATOR_CHR == PATH_SLASH_CHR)
|
|
{
|
|
/* Windows-style to Unix-style */
|
|
|
|
for (index = 0; index < cchPath; index++)
|
|
{
|
|
if (pszPath[index] == PATH_BACKSLASH_CHR)
|
|
pszPath[index] = PATH_SLASH_CHR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Unexpected error */
|
|
return S_FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Gangnam style? */
|
|
return S_FALSE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/**
|
|
* PathGetSeparator
|
|
*/
|
|
|
|
char PathGetSeparatorA(unsigned long dwFlags)
|
|
{
|
|
char separator = PATH_SEPARATOR_CHR;
|
|
|
|
if (!dwFlags)
|
|
dwFlags = PATH_STYLE_NATIVE;
|
|
|
|
if (dwFlags == PATH_STYLE_WINDOWS)
|
|
separator = PATH_SEPARATOR_CHR;
|
|
else if (dwFlags == PATH_STYLE_UNIX)
|
|
separator = PATH_SEPARATOR_CHR;
|
|
else if (dwFlags == PATH_STYLE_NATIVE)
|
|
separator = PATH_SEPARATOR_CHR;
|
|
|
|
return separator;
|
|
}
|
|
|
|
WCHAR PathGetSeparatorW(unsigned long dwFlags)
|
|
{
|
|
WCHAR separator = PATH_SEPARATOR_CHR;
|
|
|
|
if (!dwFlags)
|
|
dwFlags = PATH_STYLE_NATIVE;
|
|
|
|
if (dwFlags == PATH_STYLE_WINDOWS)
|
|
separator = PATH_SEPARATOR_CHR;
|
|
else if (dwFlags == PATH_STYLE_UNIX)
|
|
separator = PATH_SEPARATOR_CHR;
|
|
else if (dwFlags == PATH_STYLE_NATIVE)
|
|
separator = PATH_SEPARATOR_CHR;
|
|
|
|
return separator;
|
|
}
|
|
|
|
/**
|
|
* PathGetSharedLibraryExtension
|
|
*/
|
|
|
|
static const CHAR SharedLibraryExtensionDllA[] = "dll";
|
|
static const CHAR SharedLibraryExtensionSoA[] = "so";
|
|
static const CHAR SharedLibraryExtensionDylibA[] = "dylib";
|
|
|
|
static const WCHAR SharedLibraryExtensionDllW[] = { 'd','l','l','\0' };
|
|
static const WCHAR SharedLibraryExtensionSoW[] = { 's','o','\0' };
|
|
static const WCHAR SharedLibraryExtensionDylibW[] = { 'd','y','l','i','b','\0' };
|
|
|
|
static const CHAR SharedLibraryExtensionDotDllA[] = ".dll";
|
|
static const CHAR SharedLibraryExtensionDotSoA[] = ".so";
|
|
static const CHAR SharedLibraryExtensionDotDylibA[] = ".dylib";
|
|
|
|
static const WCHAR SharedLibraryExtensionDotDllW[] = { '.','d','l','l','\0' };
|
|
static const WCHAR SharedLibraryExtensionDotSoW[] = { '.','s','o','\0' };
|
|
static const WCHAR SharedLibraryExtensionDotDylibW[] = { '.','d','y','l','i','b','\0' };
|
|
|
|
PCSTR PathGetSharedLibraryExtensionA(unsigned long dwFlags)
|
|
{
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
|
|
{
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
|
|
{
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
|
|
return SharedLibraryExtensionDotDllA;
|
|
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
|
|
return SharedLibraryExtensionDotSoA;
|
|
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
|
|
return SharedLibraryExtensionDotDylibA;
|
|
}
|
|
else
|
|
{
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
|
|
return SharedLibraryExtensionDllA;
|
|
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
|
|
return SharedLibraryExtensionSoA;
|
|
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
|
|
return SharedLibraryExtensionDylibA;
|
|
}
|
|
}
|
|
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
|
|
{
|
|
#ifdef _WIN32
|
|
return SharedLibraryExtensionDotDllA;
|
|
#elif defined(__APPLE__)
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
|
|
return SharedLibraryExtensionDotSoA;
|
|
else
|
|
return SharedLibraryExtensionDotDylibA;
|
|
#else
|
|
return SharedLibraryExtensionDotSoA;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#ifdef _WIN32
|
|
return SharedLibraryExtensionDllA;
|
|
#elif defined(__APPLE__)
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
|
|
return SharedLibraryExtensionSoA;
|
|
else
|
|
return SharedLibraryExtensionDylibA;
|
|
#else
|
|
return SharedLibraryExtensionSoA;
|
|
#endif
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
PCWSTR PathGetSharedLibraryExtensionW(unsigned long dwFlags)
|
|
{
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
|
|
{
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
|
|
{
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
|
|
return SharedLibraryExtensionDotDllW;
|
|
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
|
|
return SharedLibraryExtensionDotSoW;
|
|
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
|
|
return SharedLibraryExtensionDotDylibW;
|
|
}
|
|
else
|
|
{
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
|
|
return SharedLibraryExtensionDllW;
|
|
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
|
|
return SharedLibraryExtensionSoW;
|
|
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
|
|
return SharedLibraryExtensionDylibW;
|
|
}
|
|
}
|
|
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
|
|
{
|
|
#ifdef _WIN32
|
|
return SharedLibraryExtensionDotDllW;
|
|
#elif defined(__APPLE__)
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
|
|
return SharedLibraryExtensionDotSoW;
|
|
else
|
|
return SharedLibraryExtensionDotDylibW;
|
|
#else
|
|
return SharedLibraryExtensionDotSoW;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#ifdef _WIN32
|
|
return SharedLibraryExtensionDllW;
|
|
#elif defined(__APPLE__)
|
|
if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
|
|
return SharedLibraryExtensionSoW;
|
|
else
|
|
return SharedLibraryExtensionDylibW;
|
|
#else
|
|
return SharedLibraryExtensionSoW;
|
|
#endif
|
|
}
|
|
|
|
return NULL;
|
|
}
|