summaryrefslogtreecommitdiffstats
path: root/winpr/libwinpr/path/include
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 01:24:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 01:24:41 +0000
commita9bcc81f821d7c66f623779fa5147e728eb3c388 (patch)
tree98676963bcdd537ae5908a067a8eb110b93486a6 /winpr/libwinpr/path/include
parentInitial commit. (diff)
downloadfreerdp3-a9bcc81f821d7c66f623779fa5147e728eb3c388.tar.xz
freerdp3-a9bcc81f821d7c66f623779fa5147e728eb3c388.zip
Adding upstream version 3.3.0+dfsg1.upstream/3.3.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'winpr/libwinpr/path/include')
-rw-r--r--winpr/libwinpr/path/include/PathAllocCombine.c180
-rw-r--r--winpr/libwinpr/path/include/PathCchAddExtension.c101
-rw-r--r--winpr/libwinpr/path/include/PathCchAddSeparator.c64
-rw-r--r--winpr/libwinpr/path/include/PathCchAddSeparatorEx.c66
-rw-r--r--winpr/libwinpr/path/include/PathCchAppend.c131
5 files changed, 542 insertions, 0 deletions
diff --git a/winpr/libwinpr/path/include/PathAllocCombine.c b/winpr/libwinpr/path/include/PathAllocCombine.c
new file mode 100644
index 0000000..abdbd29
--- /dev/null
+++ b/winpr/libwinpr/path/include/PathAllocCombine.c
@@ -0,0 +1,180 @@
+
+/*
+#define DEFINE_UNICODE FALSE
+#define CUR_PATH_SEPARATOR_CHR '\\'
+#define CUR_PATH_SEPARATOR_STR "\\"
+#define PATH_ALLOC_COMBINE PathAllocCombineA
+*/
+
+/**
+ * FIXME: These implementations of the PathAllocCombine functions have
+ * several issues:
+ * - pszPathIn or pszMore may be NULL (but not both)
+ * - no check if pszMore is fully qualified (if so, it must be directly
+ * copied to the output buffer without being combined with pszPathIn.
+ * - if pszMore begins with a _single_ backslash it must be combined with
+ * only the root of the path pointed to by pszPathIn and there's no code
+ * to extract the root of pszPathIn.
+ * - the function will crash with some short string lengths of the parameters
+ */
+
+#if DEFINE_UNICODE
+
+HRESULT PATH_ALLOC_COMBINE(PCWSTR pszPathIn, PCWSTR pszMore, unsigned long dwFlags,
+ PWSTR* ppszPathOut)
+{
+ PWSTR pszPathOut;
+ BOOL backslashIn;
+ BOOL backslashMore;
+ size_t pszMoreLength;
+ size_t pszPathInLength;
+ size_t pszPathOutLength;
+ WLog_WARN(TAG, "has known bugs and needs fixing.");
+
+ if (!ppszPathOut)
+ return E_INVALIDARG;
+
+ if (!pszPathIn && !pszMore)
+ return E_INVALIDARG;
+
+ if (!pszMore)
+ return E_FAIL; /* valid but not implemented, see top comment */
+
+ if (!pszPathIn)
+ return E_FAIL; /* valid but not implemented, see top comment */
+
+ pszPathInLength = _wcslen(pszPathIn);
+ pszMoreLength = _wcslen(pszMore);
+
+ /* prevent segfaults - the complete implementation below is buggy */
+ if (pszPathInLength < 3)
+ return E_FAIL;
+
+ backslashIn = (pszPathIn[pszPathInLength - 1] == CUR_PATH_SEPARATOR_CHR) ? TRUE : FALSE;
+ backslashMore = (pszMore[0] == CUR_PATH_SEPARATOR_CHR) ? TRUE : FALSE;
+
+ if (backslashMore)
+ {
+ if ((pszPathIn[1] == ':') && (pszPathIn[2] == CUR_PATH_SEPARATOR_CHR))
+ {
+ const WCHAR colon[] = { ':', '\0' };
+ size_t sizeOfBuffer;
+ pszPathOutLength = sizeof(WCHAR) + pszMoreLength;
+ sizeOfBuffer = (pszPathOutLength + 1) * sizeof(WCHAR);
+ pszPathOut = (PWSTR)calloc(sizeOfBuffer, sizeof(WCHAR));
+
+ if (!pszPathOut)
+ return E_OUTOFMEMORY;
+
+ _wcsncat(pszPathOut, &pszPathIn[0], 1);
+ _wcsncat(pszPathOut, colon, ARRAYSIZE(colon));
+ _wcsncat(pszPathOut, pszMore, pszMoreLength);
+ *ppszPathOut = pszPathOut;
+ return S_OK;
+ }
+ }
+ else
+ {
+ const WCHAR sep[] = CUR_PATH_SEPARATOR_STR;
+ size_t sizeOfBuffer;
+ pszPathOutLength = pszPathInLength + pszMoreLength;
+ sizeOfBuffer = (pszPathOutLength + 1) * 2;
+ pszPathOut = (PWSTR)calloc(sizeOfBuffer, 2);
+
+ if (!pszPathOut)
+ return E_OUTOFMEMORY;
+
+ _wcsncat(pszPathOut, pszPathIn, pszPathInLength);
+ if (!backslashIn)
+ _wcsncat(pszPathOut, sep, ARRAYSIZE(sep));
+ _wcsncat(pszPathOut, pszMore, pszMoreLength);
+
+ *ppszPathOut = pszPathOut;
+ return S_OK;
+ }
+
+ return E_FAIL;
+}
+
+#else
+
+HRESULT PATH_ALLOC_COMBINE(PCSTR pszPathIn, PCSTR pszMore, unsigned long dwFlags, PSTR* ppszPathOut)
+{
+ PSTR pszPathOut;
+ BOOL backslashIn;
+ BOOL backslashMore;
+ int pszMoreLength;
+ int pszPathInLength;
+ int pszPathOutLength;
+ WLog_WARN(TAG, "has known bugs and needs fixing.");
+
+ if (!ppszPathOut)
+ return E_INVALIDARG;
+
+ if (!pszPathIn && !pszMore)
+ return E_INVALIDARG;
+
+ if (!pszMore)
+ return E_FAIL; /* valid but not implemented, see top comment */
+
+ if (!pszPathIn)
+ return E_FAIL; /* valid but not implemented, see top comment */
+
+ pszPathInLength = strlen(pszPathIn);
+ pszMoreLength = strlen(pszMore);
+
+ /* prevent segfaults - the complete implementation below is buggy */
+ if (pszPathInLength < 3)
+ return E_FAIL;
+
+ backslashIn = (pszPathIn[pszPathInLength - 1] == CUR_PATH_SEPARATOR_CHR) ? TRUE : FALSE;
+ backslashMore = (pszMore[0] == CUR_PATH_SEPARATOR_CHR) ? TRUE : FALSE;
+
+ if (backslashMore)
+ {
+ if ((pszPathIn[1] == ':') && (pszPathIn[2] == CUR_PATH_SEPARATOR_CHR))
+ {
+ size_t sizeOfBuffer;
+ pszPathOutLength = 2 + pszMoreLength;
+ sizeOfBuffer = (pszPathOutLength + 1) * 2;
+ pszPathOut = (PSTR)calloc(sizeOfBuffer, 2);
+
+ if (!pszPathOut)
+ return E_OUTOFMEMORY;
+
+ sprintf_s(pszPathOut, sizeOfBuffer, "%c:%s", pszPathIn[0], pszMore);
+ *ppszPathOut = pszPathOut;
+ return S_OK;
+ }
+ }
+ else
+ {
+ size_t sizeOfBuffer;
+ pszPathOutLength = pszPathInLength + pszMoreLength;
+ sizeOfBuffer = (pszPathOutLength + 1) * 2;
+ pszPathOut = (PSTR)calloc(sizeOfBuffer, 2);
+
+ if (!pszPathOut)
+ return E_OUTOFMEMORY;
+
+ if (backslashIn)
+ sprintf_s(pszPathOut, sizeOfBuffer, "%s%s", pszPathIn, pszMore);
+ else
+ sprintf_s(pszPathOut, sizeOfBuffer, "%s" CUR_PATH_SEPARATOR_STR "%s", pszPathIn,
+ pszMore);
+
+ *ppszPathOut = pszPathOut;
+ return S_OK;
+ }
+
+ return E_FAIL;
+}
+
+#endif
+
+/*
+#undef DEFINE_UNICODE
+#undef CUR_PATH_SEPARATOR_CHR
+#undef CUR_PATH_SEPARATOR_STR
+#undef PATH_ALLOC_COMBINE
+*/
diff --git a/winpr/libwinpr/path/include/PathCchAddExtension.c b/winpr/libwinpr/path/include/PathCchAddExtension.c
new file mode 100644
index 0000000..498cfab
--- /dev/null
+++ b/winpr/libwinpr/path/include/PathCchAddExtension.c
@@ -0,0 +1,101 @@
+
+/*
+#define DEFINE_UNICODE FALSE
+#define CUR_PATH_SEPARATOR_CHR '\\'
+#define PATH_CCH_ADD_EXTENSION PathCchAddExtensionA
+*/
+
+#if DEFINE_UNICODE
+
+HRESULT PATH_CCH_ADD_EXTENSION(PWSTR pszPath, size_t cchPath, PCWSTR pszExt)
+{
+ LPWSTR pDot;
+ BOOL bExtDot;
+ LPWSTR pBackslash;
+ size_t pszExtLength;
+ size_t pszPathLength;
+
+ if (!pszPath)
+ return E_INVALIDARG;
+
+ if (!pszExt)
+ return E_INVALIDARG;
+
+ pszExtLength = _wcslen(pszExt);
+ pszPathLength = _wcslen(pszPath);
+ bExtDot = (pszExt[0] == '.') ? TRUE : FALSE;
+
+ pDot = _wcsrchr(pszPath, '.');
+ pBackslash = _wcsrchr(pszPath, CUR_PATH_SEPARATOR_CHR);
+
+ if (pDot && pBackslash)
+ {
+ if (pDot > pBackslash)
+ return S_FALSE;
+ }
+
+ if (cchPath > pszPathLength + pszExtLength + ((bExtDot) ? 0 : 1))
+ {
+ const WCHAR dot[] = { '.', '\0' };
+ WCHAR* ptr = &pszPath[pszPathLength];
+ *ptr = '\0';
+
+ if (!bExtDot)
+ _wcsncat(ptr, dot, _wcslen(dot));
+ _wcsncat(ptr, pszExt, pszExtLength);
+
+ return S_OK;
+ }
+
+ return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+}
+
+#else
+
+HRESULT PATH_CCH_ADD_EXTENSION(PSTR pszPath, size_t cchPath, PCSTR pszExt)
+{
+ CHAR* pDot;
+ BOOL bExtDot;
+ CHAR* pBackslash;
+ size_t pszExtLength;
+ size_t pszPathLength;
+
+ if (!pszPath)
+ return E_INVALIDARG;
+
+ if (!pszExt)
+ return E_INVALIDARG;
+
+ pszExtLength = strlen(pszExt);
+ pszPathLength = strlen(pszPath);
+ bExtDot = (pszExt[0] == '.') ? TRUE : FALSE;
+
+ pDot = strrchr(pszPath, '.');
+ pBackslash = strrchr(pszPath, CUR_PATH_SEPARATOR_CHR);
+
+ if (pDot && pBackslash)
+ {
+ if (pDot > pBackslash)
+ return S_FALSE;
+ }
+
+ if (cchPath > pszPathLength + pszExtLength + ((bExtDot) ? 0 : 1))
+ {
+ if (bExtDot)
+ sprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, "%s", pszExt);
+ else
+ sprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, ".%s", pszExt);
+
+ return S_OK;
+ }
+
+ return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+}
+
+#endif
+
+/*
+#undef DEFINE_UNICODE
+#undef CUR_PATH_SEPARATOR_CHR
+#undef PATH_CCH_ADD_EXTENSION
+*/
diff --git a/winpr/libwinpr/path/include/PathCchAddSeparator.c b/winpr/libwinpr/path/include/PathCchAddSeparator.c
new file mode 100644
index 0000000..0ef391c
--- /dev/null
+++ b/winpr/libwinpr/path/include/PathCchAddSeparator.c
@@ -0,0 +1,64 @@
+
+/*
+#define DEFINE_UNICODE FALSE
+#define CUR_PATH_SEPARATOR_CHR '\\'
+#define PATH_CCH_ADD_SEPARATOR PathCchAddBackslashA
+*/
+
+#if DEFINE_UNICODE
+
+HRESULT PATH_CCH_ADD_SEPARATOR(PWSTR pszPath, size_t cchPath)
+{
+ size_t pszPathLength;
+
+ if (!pszPath)
+ return E_INVALIDARG;
+
+ pszPathLength = _wcslen(pszPath);
+
+ if (pszPath[pszPathLength - 1] == CUR_PATH_SEPARATOR_CHR)
+ return S_FALSE;
+
+ if (cchPath > (pszPathLength + 1))
+ {
+ pszPath[pszPathLength] = CUR_PATH_SEPARATOR_CHR;
+ pszPath[pszPathLength + 1] = '\0';
+
+ return S_OK;
+ }
+
+ return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+}
+
+#else
+
+HRESULT PATH_CCH_ADD_SEPARATOR(PSTR pszPath, size_t cchPath)
+{
+ size_t pszPathLength;
+
+ if (!pszPath)
+ return E_INVALIDARG;
+
+ pszPathLength = strlen(pszPath);
+
+ if (pszPath[pszPathLength - 1] == CUR_PATH_SEPARATOR_CHR)
+ return S_FALSE;
+
+ if (cchPath > (pszPathLength + 1))
+ {
+ pszPath[pszPathLength] = CUR_PATH_SEPARATOR_CHR;
+ pszPath[pszPathLength + 1] = '\0';
+
+ return S_OK;
+ }
+
+ return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+}
+
+#endif
+
+/*
+#undef DEFINE_UNICODE
+#undef CUR_PATH_SEPARATOR_CHR
+#undef PATH_CCH_ADD_SEPARATOR
+*/
diff --git a/winpr/libwinpr/path/include/PathCchAddSeparatorEx.c b/winpr/libwinpr/path/include/PathCchAddSeparatorEx.c
new file mode 100644
index 0000000..02832d8
--- /dev/null
+++ b/winpr/libwinpr/path/include/PathCchAddSeparatorEx.c
@@ -0,0 +1,66 @@
+
+/*
+#define DEFINE_UNICODE FALSE
+#define CUR_PATH_SEPARATOR_CHR '\\'
+#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddBackslashExA
+*/
+
+#if DEFINE_UNICODE
+
+HRESULT PATH_CCH_ADD_SEPARATOR_EX(PWSTR pszPath, size_t cchPath, PWSTR* ppszEnd,
+ size_t* pcchRemaining)
+{
+ size_t pszPathLength;
+
+ if (!pszPath)
+ return E_INVALIDARG;
+
+ pszPathLength = _wcslen(pszPath);
+
+ if (pszPath[pszPathLength - 1] == CUR_PATH_SEPARATOR_CHR)
+ return S_FALSE;
+
+ if (cchPath > (pszPathLength + 1))
+ {
+ pszPath[pszPathLength] = CUR_PATH_SEPARATOR_CHR;
+ pszPath[pszPathLength + 1] = '\0';
+
+ return S_OK;
+ }
+
+ return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+}
+
+#else
+
+HRESULT PATH_CCH_ADD_SEPARATOR_EX(PSTR pszPath, size_t cchPath, PSTR* ppszEnd,
+ size_t* pcchRemaining)
+{
+ size_t pszPathLength;
+
+ if (!pszPath)
+ return E_INVALIDARG;
+
+ pszPathLength = strlen(pszPath);
+
+ if (pszPath[pszPathLength - 1] == CUR_PATH_SEPARATOR_CHR)
+ return S_FALSE;
+
+ if (cchPath > (pszPathLength + 1))
+ {
+ pszPath[pszPathLength] = CUR_PATH_SEPARATOR_CHR;
+ pszPath[pszPathLength + 1] = '\0';
+
+ return S_OK;
+ }
+
+ return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+}
+
+#endif
+
+/*
+#undef DEFINE_UNICODE
+#undef CUR_PATH_SEPARATOR_CHR
+#undef PATH_CCH_ADD_SEPARATOR_EX
+*/
diff --git a/winpr/libwinpr/path/include/PathCchAppend.c b/winpr/libwinpr/path/include/PathCchAppend.c
new file mode 100644
index 0000000..a4f58cb
--- /dev/null
+++ b/winpr/libwinpr/path/include/PathCchAppend.c
@@ -0,0 +1,131 @@
+
+/*
+#define DEFINE_UNICODE FALSE
+#define CUR_PATH_SEPARATOR_CHR '\\'
+#define CUR_PATH_SEPARATOR_STR "\\"
+#define PATH_CCH_APPEND PathCchAppendA
+*/
+
+#if DEFINE_UNICODE
+
+HRESULT PATH_CCH_APPEND(PWSTR pszPath, size_t cchPath, PCWSTR pszMore)
+{
+ BOOL pathBackslash;
+ BOOL moreBackslash;
+ size_t pszMoreLength;
+ size_t pszPathLength;
+
+ if (!pszPath)
+ return E_INVALIDARG;
+
+ if (!pszMore)
+ return E_INVALIDARG;
+
+ if (cchPath == 0 || cchPath > PATHCCH_MAX_CCH)
+ return E_INVALIDARG;
+
+ pszMoreLength = _wcslen(pszMore);
+ pszPathLength = _wcslen(pszPath);
+
+ pathBackslash = (pszPath[pszPathLength - 1] == CUR_PATH_SEPARATOR_CHR) ? TRUE : FALSE;
+ moreBackslash = (pszMore[0] == CUR_PATH_SEPARATOR_CHR) ? TRUE : FALSE;
+
+ if (pathBackslash && moreBackslash)
+ {
+ if ((pszPathLength + pszMoreLength - 1) < cchPath)
+ {
+ WCHAR* ptr = &pszPath[pszPathLength];
+ *ptr = '\0';
+ _wcsncat(ptr, &pszMore[1], _wcslen(&pszMore[1]));
+ return S_OK;
+ }
+ }
+ else if ((pathBackslash && !moreBackslash) || (!pathBackslash && moreBackslash))
+ {
+ if ((pszPathLength + pszMoreLength) < cchPath)
+ {
+ WCHAR* ptr = &pszPath[pszPathLength];
+ *ptr = '\0';
+ _wcsncat(ptr, pszMore, _wcslen(pszMore));
+ return S_OK;
+ }
+ }
+ else if (!pathBackslash && !moreBackslash)
+ {
+ if ((pszPathLength + pszMoreLength + 1) < cchPath)
+ {
+ const WCHAR sep[] = CUR_PATH_SEPARATOR_STR;
+ WCHAR* ptr = &pszPath[pszPathLength];
+ *ptr = '\0';
+ _wcsncat(ptr, sep, _wcslen(sep));
+ _wcsncat(ptr, pszMore, _wcslen(pszMore));
+ return S_OK;
+ }
+ }
+
+ return HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE);
+}
+
+#else
+
+HRESULT PATH_CCH_APPEND(PSTR pszPath, size_t cchPath, PCSTR pszMore)
+{
+ BOOL pathBackslash = FALSE;
+ BOOL moreBackslash = FALSE;
+ size_t pszMoreLength;
+ size_t pszPathLength;
+
+ if (!pszPath)
+ return E_INVALIDARG;
+
+ if (!pszMore)
+ return E_INVALIDARG;
+
+ if (cchPath == 0 || cchPath > PATHCCH_MAX_CCH)
+ return E_INVALIDARG;
+
+ pszPathLength = strlen(pszPath);
+ if (pszPathLength > 0)
+ pathBackslash = (pszPath[pszPathLength - 1] == CUR_PATH_SEPARATOR_CHR) ? TRUE : FALSE;
+
+ pszMoreLength = strlen(pszMore);
+ if (pszMoreLength > 0)
+ moreBackslash = (pszMore[0] == CUR_PATH_SEPARATOR_CHR) ? TRUE : FALSE;
+
+ if (pathBackslash && moreBackslash)
+ {
+ if ((pszPathLength + pszMoreLength - 1) < cchPath)
+ {
+ sprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, "%s", &pszMore[1]);
+ return S_OK;
+ }
+ }
+ else if ((pathBackslash && !moreBackslash) || (!pathBackslash && moreBackslash))
+ {
+ if ((pszPathLength + pszMoreLength) < cchPath)
+ {
+ sprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, "%s", pszMore);
+ return S_OK;
+ }
+ }
+ else if (!pathBackslash && !moreBackslash)
+ {
+ if ((pszPathLength + pszMoreLength + 1) < cchPath)
+ {
+ sprintf_s(&pszPath[pszPathLength], cchPath - pszPathLength, CUR_PATH_SEPARATOR_STR "%s",
+ pszMore);
+ return S_OK;
+ }
+ }
+
+ return HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE);
+}
+
+#endif
+
+/*
+#undef DEFINE_UNICODE
+#undef CUR_PATH_SEPARATOR_CHR
+#undef CUR_PATH_SEPARATOR_STR
+#undef PATH_CCH_APPEND
+*/