diff options
Diffstat (limited to 'winpr/libwinpr/path/path.c')
-rw-r--r-- | winpr/libwinpr/path/path.c | 1181 |
1 files changed, 1181 insertions, 0 deletions
diff --git a/winpr/libwinpr/path/path.c b/winpr/libwinpr/path/path.c new file mode 100644 index 0000000..82e6be1 --- /dev/null +++ b/winpr/libwinpr/path/path.c @@ -0,0 +1,1181 @@ +/** + * 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. + */ + +#include <winpr/config.h> + +#include <winpr/crt.h> +#include <winpr/tchar.h> + +#include <winpr/path.h> +#include <winpr/file.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 \ + { \ + '/', '\0' \ + } +#define PATH_BACKSLASH_STR_W \ + { \ + '\\', '\0' \ + } +#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 + +#include "../log.h" +#define TAG WINPR_TAG("path") + +/* + * PathCchAddBackslash + */ + +/* Windows-style Paths */ + +#define DEFINE_UNICODE FALSE +#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR +#define PATH_CCH_ADD_SEPARATOR PathCchAddBackslashA +#include "include/PathCchAddSeparator.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_SEPARATOR + +#define DEFINE_UNICODE TRUE +#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR +#define PATH_CCH_ADD_SEPARATOR PathCchAddBackslashW +#include "include/PathCchAddSeparator.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_SEPARATOR + +/* Unix-style Paths */ + +#define DEFINE_UNICODE FALSE +#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR +#define PATH_CCH_ADD_SEPARATOR PathCchAddSlashA +#include "include/PathCchAddSeparator.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_SEPARATOR + +#define DEFINE_UNICODE TRUE +#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR +#define PATH_CCH_ADD_SEPARATOR PathCchAddSlashW +#include "include/PathCchAddSeparator.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_SEPARATOR + +/* Native-style Paths */ + +#define DEFINE_UNICODE FALSE +#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR +#define PATH_CCH_ADD_SEPARATOR PathCchAddSeparatorA +#include "include/PathCchAddSeparator.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_SEPARATOR + +#define DEFINE_UNICODE TRUE +#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR +#define PATH_CCH_ADD_SEPARATOR PathCchAddSeparatorW +#include "include/PathCchAddSeparator.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_SEPARATOR + +/* + * PathCchRemoveBackslash + */ + +HRESULT PathCchRemoveBackslashA(PSTR pszPath, size_t cchPath) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +HRESULT PathCchRemoveBackslashW(PWSTR pszPath, size_t cchPath) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +/* + * PathCchAddBackslashEx + */ + +/* Windows-style Paths */ + +#define DEFINE_UNICODE FALSE +#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR +#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddBackslashExA +#include "include/PathCchAddSeparatorEx.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_SEPARATOR_EX + +#define DEFINE_UNICODE TRUE +#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR +#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddBackslashExW +#include "include/PathCchAddSeparatorEx.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_SEPARATOR_EX + +/* Unix-style Paths */ + +#define DEFINE_UNICODE FALSE +#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR +#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSlashExA +#include "include/PathCchAddSeparatorEx.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_SEPARATOR_EX + +#define DEFINE_UNICODE TRUE +#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR +#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSlashExW +#include "include/PathCchAddSeparatorEx.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_SEPARATOR_EX + +/* Native-style Paths */ + +#define DEFINE_UNICODE FALSE +#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR +#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSeparatorExA +#include "include/PathCchAddSeparatorEx.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_SEPARATOR_EX + +#define DEFINE_UNICODE TRUE +#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR +#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSeparatorExW +#include "include/PathCchAddSeparatorEx.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_SEPARATOR_EX + +HRESULT PathCchRemoveBackslashExA(PSTR pszPath, size_t cchPath, PSTR* ppszEnd, + size_t* pcchRemaining) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +HRESULT PathCchRemoveBackslashExW(PWSTR pszPath, size_t cchPath, PWSTR* ppszEnd, + size_t* pcchRemaining) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +/* + * PathCchAddExtension + */ + +/* Windows-style Paths */ + +#define DEFINE_UNICODE FALSE +#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR +#define PATH_CCH_ADD_EXTENSION PathCchAddExtensionA +#include "include/PathCchAddExtension.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_EXTENSION + +#define DEFINE_UNICODE TRUE +#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR +#define PATH_CCH_ADD_EXTENSION PathCchAddExtensionW +#include "include/PathCchAddExtension.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_EXTENSION + +/* Unix-style Paths */ + +#define DEFINE_UNICODE FALSE +#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR +#define PATH_CCH_ADD_EXTENSION UnixPathCchAddExtensionA +#include "include/PathCchAddExtension.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_EXTENSION + +#define DEFINE_UNICODE TRUE +#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR +#define PATH_CCH_ADD_EXTENSION UnixPathCchAddExtensionW +#include "include/PathCchAddExtension.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_EXTENSION + +/* Native-style Paths */ + +#define DEFINE_UNICODE FALSE +#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR +#define PATH_CCH_ADD_EXTENSION NativePathCchAddExtensionA +#include "include/PathCchAddExtension.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_EXTENSION + +#define DEFINE_UNICODE TRUE +#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR +#define PATH_CCH_ADD_EXTENSION NativePathCchAddExtensionW +#include "include/PathCchAddExtension.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef PATH_CCH_ADD_EXTENSION + +/* + * PathCchAppend + */ + +/* Windows-style Paths */ + +#define DEFINE_UNICODE FALSE +#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR +#define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR +#define PATH_CCH_APPEND PathCchAppendA +#include "include/PathCchAppend.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef CUR_PATH_SEPARATOR_STR +#undef PATH_CCH_APPEND + +#define DEFINE_UNICODE TRUE +#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR +#define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR_W +#define PATH_CCH_APPEND PathCchAppendW +#include "include/PathCchAppend.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef CUR_PATH_SEPARATOR_STR +#undef PATH_CCH_APPEND + +/* Unix-style Paths */ + +#define DEFINE_UNICODE FALSE +#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR +#define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR +#define PATH_CCH_APPEND UnixPathCchAppendA +#include "include/PathCchAppend.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef CUR_PATH_SEPARATOR_STR +#undef PATH_CCH_APPEND + +#define DEFINE_UNICODE TRUE +#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR +#define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR_W +#define PATH_CCH_APPEND UnixPathCchAppendW +#include "include/PathCchAppend.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef CUR_PATH_SEPARATOR_STR +#undef PATH_CCH_APPEND + +/* Native-style Paths */ + +#define DEFINE_UNICODE FALSE +#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR +#define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR +#define PATH_CCH_APPEND NativePathCchAppendA +#include "include/PathCchAppend.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef CUR_PATH_SEPARATOR_STR +#undef PATH_CCH_APPEND + +#define DEFINE_UNICODE TRUE +#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR +#define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR_W +#define PATH_CCH_APPEND NativePathCchAppendW +#include "include/PathCchAppend.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef CUR_PATH_SEPARATOR_STR +#undef PATH_CCH_APPEND + +/* + * PathCchAppendEx + */ + +HRESULT PathCchAppendExA(PSTR pszPath, size_t cchPath, PCSTR pszMore, unsigned long dwFlags) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +HRESULT PathCchAppendExW(PWSTR pszPath, size_t cchPath, PCWSTR pszMore, unsigned long dwFlags) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +/* + * PathCchCanonicalize + */ + +HRESULT PathCchCanonicalizeA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +HRESULT PathCchCanonicalizeW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +/* + * PathCchCanonicalizeEx + */ + +HRESULT PathCchCanonicalizeExA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn, + unsigned long dwFlags) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +HRESULT PathCchCanonicalizeExW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn, + unsigned long dwFlags) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +/* + * PathAllocCanonicalize + */ + +HRESULT PathAllocCanonicalizeA(PCSTR pszPathIn, unsigned long dwFlags, PSTR* ppszPathOut) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +HRESULT PathAllocCanonicalizeW(PCWSTR pszPathIn, unsigned long dwFlags, PWSTR* ppszPathOut) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +/* + * PathCchCombine + */ + +HRESULT PathCchCombineA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn, PCSTR pszMore) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +HRESULT PathCchCombineW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn, PCWSTR pszMore) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +/* + * PathCchCombineEx + */ + +HRESULT PathCchCombineExA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn, PCSTR pszMore, + unsigned long dwFlags) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +HRESULT PathCchCombineExW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn, PCWSTR pszMore, + unsigned long dwFlags) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +/* + * PathAllocCombine + */ + +/* Windows-style Paths */ + +#define DEFINE_UNICODE FALSE +#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR +#define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR +#define PATH_ALLOC_COMBINE PathAllocCombineA +#include "include/PathAllocCombine.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef CUR_PATH_SEPARATOR_STR +#undef PATH_ALLOC_COMBINE + +#define DEFINE_UNICODE TRUE +#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR +#define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR_W +#define PATH_ALLOC_COMBINE PathAllocCombineW +#include "include/PathAllocCombine.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef CUR_PATH_SEPARATOR_STR +#undef PATH_ALLOC_COMBINE + +/* Unix-style Paths */ + +#define DEFINE_UNICODE FALSE +#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR +#define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR +#define PATH_ALLOC_COMBINE UnixPathAllocCombineA +#include "include/PathAllocCombine.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef CUR_PATH_SEPARATOR_STR +#undef PATH_ALLOC_COMBINE + +#define DEFINE_UNICODE TRUE +#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR +#define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR_W +#define PATH_ALLOC_COMBINE UnixPathAllocCombineW +#include "include/PathAllocCombine.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef CUR_PATH_SEPARATOR_STR +#undef PATH_ALLOC_COMBINE + +/* Native-style Paths */ + +#define DEFINE_UNICODE FALSE +#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR +#define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR +#define PATH_ALLOC_COMBINE NativePathAllocCombineA +#include "include/PathAllocCombine.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef CUR_PATH_SEPARATOR_STR +#undef PATH_ALLOC_COMBINE + +#define DEFINE_UNICODE TRUE +#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR +#define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR_W +#define PATH_ALLOC_COMBINE NativePathAllocCombineW +#include "include/PathAllocCombine.c" +#undef DEFINE_UNICODE +#undef CUR_PATH_SEPARATOR_CHR +#undef CUR_PATH_SEPARATOR_STR +#undef PATH_ALLOC_COMBINE + +/** + * PathCchFindExtension + */ + +HRESULT PathCchFindExtensionA(PCSTR pszPath, size_t cchPath, PCSTR* ppszExt) +{ + const char* p = (const char*)pszPath; + + if (!pszPath || !cchPath || !ppszExt) + return E_INVALIDARG; + + /* find end of string */ + + while (*p && --cchPath) + { + p++; + } + + if (*p) + { + /* pszPath is not null terminated within the cchPath range */ + return E_INVALIDARG; + } + + /* If no extension is found, ppszExt must point to the string's terminating null */ + *ppszExt = p; + + /* search backwards for '.' */ + + while (p > pszPath) + { + if (*p == '.') + { + *ppszExt = (PCSTR)p; + break; + } + + if ((*p == '\\') || (*p == '/') || (*p == ':')) + break; + + p--; + } + + return S_OK; +} + +HRESULT PathCchFindExtensionW(PCWSTR pszPath, size_t cchPath, PCWSTR* ppszExt) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +/** + * PathCchRenameExtension + */ + +HRESULT PathCchRenameExtensionA(PSTR pszPath, size_t cchPath, PCSTR pszExt) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +HRESULT PathCchRenameExtensionW(PWSTR pszPath, size_t cchPath, PCWSTR pszExt) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +/** + * PathCchRemoveExtension + */ + +HRESULT PathCchRemoveExtensionA(PSTR pszPath, size_t cchPath) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +HRESULT PathCchRemoveExtensionW(PWSTR pszPath, size_t cchPath) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +/** + * PathCchIsRoot + */ + +BOOL PathCchIsRootA(PCSTR pszPath) +{ + WLog_ERR(TAG, "not implemented"); + return FALSE; +} + +BOOL PathCchIsRootW(PCWSTR pszPath) +{ + WLog_ERR(TAG, "not implemented"); + return FALSE; +} + +/** + * 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) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +HRESULT PathCchSkipRootW(PCWSTR pszPath, PCWSTR* ppszRootEnd) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +/** + * PathCchStripToRoot + */ + +HRESULT PathCchStripToRootA(PSTR pszPath, size_t cchPath) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +HRESULT PathCchStripToRootW(PWSTR pszPath, size_t cchPath) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +/** + * PathCchStripPrefix + */ + +HRESULT PathCchStripPrefixA(PSTR pszPath, size_t cchPath) +{ + BOOL hasPrefix = 0; + + 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 = 0; + + 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) + { + int rc = 0; + if (cchPath < 6) + return S_FALSE; + + rc = (_wcslen(&pszPath[4]) + 1); + if ((rc < 0) || ((INT64)cchPath < rc)) + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + + if (IsCharAlphaW(pszPath[4]) && (pszPath[5] == L':')) /* 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) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +HRESULT PathCchRemoveFileSpecW(PWSTR pszPath, size_t cchPath) +{ + WLog_ERR(TAG, "not implemented"); + return E_NOTIMPL; +} + +/* + * Path Portability Functions + */ + +/** + * PathCchConvertStyle + */ + +HRESULT PathCchConvertStyleA(PSTR pszPath, size_t cchPath, unsigned long dwFlags) +{ + if (dwFlags == PATH_STYLE_WINDOWS) + { + for (size_t index = 0; index < cchPath; index++) + { + if (pszPath[index] == PATH_SLASH_CHR) + pszPath[index] = PATH_BACKSLASH_CHR; + } + } + else if (dwFlags == PATH_STYLE_UNIX) + { + for (size_t 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 (size_t index = 0; index < cchPath; index++) + { + if (pszPath[index] == PATH_SLASH_CHR) + pszPath[index] = PATH_BACKSLASH_CHR; + } +#elif (PATH_SEPARATOR_CHR == PATH_SLASH_CHR) + /* Windows-style to Unix-style */ + + for (size_t index = 0; index < cchPath; index++) + { + if (pszPath[index] == PATH_BACKSLASH_CHR) + pszPath[index] = PATH_SLASH_CHR; + } +#else + /* Unexpected error */ + return E_FAIL; +#endif + } + else + { + /* Gangnam style? */ + return E_FAIL; + } + + return S_OK; +} + +HRESULT PathCchConvertStyleW(PWSTR pszPath, size_t cchPath, unsigned long dwFlags) +{ + if (dwFlags == PATH_STYLE_WINDOWS) + { + for (size_t index = 0; index < cchPath; index++) + { + if (pszPath[index] == PATH_SLASH_CHR) + pszPath[index] = PATH_BACKSLASH_CHR; + } + } + else if (dwFlags == PATH_STYLE_UNIX) + { + for (size_t 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 (size_t index = 0; index < cchPath; index++) + { + if (pszPath[index] == PATH_SLASH_CHR) + pszPath[index] = PATH_BACKSLASH_CHR; + } + } +#elif (PATH_SEPARATOR_CHR == PATH_SLASH_CHR) + { + /* Windows-style to Unix-style */ + + for (size_t index = 0; index < cchPath; index++) + { + if (pszPath[index] == PATH_BACKSLASH_CHR) + pszPath[index] = PATH_SLASH_CHR; + } + } +#else + { + /* Unexpected error */ + return E_FAIL; + } +#endif + } + else + { + /* Gangnam style? */ + return E_FAIL; + } + + 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) +{ + union + { + WCHAR w; + char c[2]; + } cnv; + + cnv.c[0] = PATH_SEPARATOR_CHR; + cnv.c[1] = '\0'; + + if (!dwFlags) + dwFlags = PATH_STYLE_NATIVE; + + if (dwFlags == PATH_STYLE_WINDOWS) + cnv.c[0] = PATH_SEPARATOR_CHR; + else if (dwFlags == PATH_STYLE_UNIX) + cnv.c[0] = PATH_SEPARATOR_CHR; + else if (dwFlags == PATH_STYLE_NATIVE) + cnv.c[0] = PATH_SEPARATOR_CHR; + + return cnv.w; +} + +/** + * PathGetSharedLibraryExtension + */ +static const CHAR SharedLibraryExtensionDllA[] = "dll"; +static const CHAR SharedLibraryExtensionSoA[] = "so"; +static const CHAR SharedLibraryExtensionDylibA[] = "dylib"; + +static const CHAR SharedLibraryExtensionDotDllA[] = ".dll"; +static const CHAR SharedLibraryExtensionDotSoA[] = ".so"; +static const CHAR SharedLibraryExtensionDotDylibA[] = ".dylib"; +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) +{ + WCHAR buffer[6][16] = { 0 }; + const WCHAR* SharedLibraryExtensionDotDllW = InitializeConstWCharFromUtf8( + SharedLibraryExtensionDotDllA, buffer[0], ARRAYSIZE(buffer[0])); + const WCHAR* SharedLibraryExtensionDotSoW = + InitializeConstWCharFromUtf8(SharedLibraryExtensionDotSoA, buffer[1], ARRAYSIZE(buffer[1])); + const WCHAR* SharedLibraryExtensionDotDylibW = InitializeConstWCharFromUtf8( + SharedLibraryExtensionDotDylibA, buffer[2], ARRAYSIZE(buffer[2])); + const WCHAR* SharedLibraryExtensionDllW = + InitializeConstWCharFromUtf8(SharedLibraryExtensionDllA, buffer[3], ARRAYSIZE(buffer[3])); + const WCHAR* SharedLibraryExtensionSoW = + InitializeConstWCharFromUtf8(SharedLibraryExtensionSoA, buffer[4], ARRAYSIZE(buffer[4])); + const WCHAR* SharedLibraryExtensionDylibW = + InitializeConstWCharFromUtf8(SharedLibraryExtensionDylibA, buffer[5], ARRAYSIZE(buffer[5])); + + 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; +} + +const char* GetKnownPathIdString(int id) +{ + switch (id) + { + case KNOWN_PATH_HOME: + return "KNOWN_PATH_HOME"; + case KNOWN_PATH_TEMP: + return "KNOWN_PATH_TEMP"; + case KNOWN_PATH_XDG_DATA_HOME: + return "KNOWN_PATH_XDG_DATA_HOME"; + case KNOWN_PATH_XDG_CONFIG_HOME: + return "KNOWN_PATH_XDG_CONFIG_HOME"; + case KNOWN_PATH_XDG_CACHE_HOME: + return "KNOWN_PATH_XDG_CACHE_HOME"; + case KNOWN_PATH_XDG_RUNTIME_DIR: + return "KNOWN_PATH_XDG_RUNTIME_DIR"; + default: + return "KNOWN_PATH_UNKNOWN_ID"; + } +} + +static WCHAR* concat(const WCHAR* path, size_t pathlen, const WCHAR* name, size_t namelen) +{ + WCHAR* str = calloc(pathlen + namelen + 1, sizeof(WCHAR)); + if (!str) + return NULL; + + _wcsncat(str, path, pathlen); + _wcsncat(str, name, namelen); + return str; +} + +BOOL winpr_RemoveDirectory_RecursiveA(LPCSTR lpPathName) +{ + WCHAR* name = ConvertUtf8ToWCharAlloc(lpPathName, NULL); + if (!name) + return FALSE; + const BOOL rc = winpr_RemoveDirectory_RecursiveW(name); + free(name); + return rc; +} + +BOOL winpr_RemoveDirectory_RecursiveW(LPCWSTR lpPathName) +{ + BOOL ret = FALSE; + + if (!lpPathName) + return FALSE; + + const size_t pathnamelen = _wcslen(lpPathName); + const size_t path_slash_len = pathnamelen + 3; + WCHAR* path_slash = calloc(pathnamelen + 4, sizeof(WCHAR)); + if (!path_slash) + return FALSE; + _wcsncat(path_slash, lpPathName, pathnamelen); + + WCHAR starbuffer[8] = { 0 }; + const WCHAR* star = InitializeConstWCharFromUtf8("*", starbuffer, ARRAYSIZE(starbuffer)); + const HRESULT hr = NativePathCchAppendW(path_slash, path_slash_len, star); + if (FAILED(hr)) + goto fail; + + WIN32_FIND_DATAW findFileData = { 0 }; + HANDLE dir = FindFirstFileW(path_slash, &findFileData); + + if (dir == INVALID_HANDLE_VALUE) + goto fail; + + ret = TRUE; + path_slash[path_slash_len - 1] = '\0'; /* remove trailing '*' */ + do + { + const size_t len = _wcsnlen(findFileData.cFileName, ARRAYSIZE(findFileData.cFileName)); + + if ((len == 1 && findFileData.cFileName[0] == '.') || + (len == 2 && findFileData.cFileName[0] == '.' && findFileData.cFileName[1] == '.')) + { + continue; + } + + WCHAR* fullpath = concat(path_slash, path_slash_len, findFileData.cFileName, len); + if (!fullpath) + goto fail; + + if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + ret = winpr_RemoveDirectory_RecursiveW(fullpath); + else + ret = DeleteFileW(fullpath); + + free(fullpath); + + if (!ret) + break; + } while (ret && FindNextFileW(dir, &findFileData) != 0); + + FindClose(dir); + + if (ret) + { + if (!RemoveDirectoryW(lpPathName)) + ret = FALSE; + } + +fail: + free(path_slash); + return ret; +} |