20#include <winpr/config.h>
21#include <winpr/version.h>
22#include <winpr/build-config.h>
25#include <winpr/tchar.h>
27#include <winpr/path.h>
28#include <winpr/file.h>
33#if defined(WITH_CWALK)
37#ifndef PATHCCH_MAX_CCH
38#define PATHCCH_MAX_CCH 0x8000
41static const char PATH_SLASH_CHR =
'/';
42static const char PATH_SLASH_STR[] =
"/";
44static const char PATH_BACKSLASH_CHR =
'\\';
47static const char PATH_BACKSLASH_STR[] =
"\\";
48static const WCHAR PATH_BACKSLASH_STR_W[] = L
"\\";
49static const WCHAR PATH_SLASH_CHR_W = L
'/';
50static const WCHAR PATH_BACKSLASH_CHR_W = L
'\\';
51static const WCHAR PATH_SLASH_STR_W[] = L
"/";
53#if defined(__BIG_ENDIAN__)
54static const WCHAR PATH_SLASH_CHR_W = 0x2f00;
55static const WCHAR PATH_BACKSLASH_CHR_W = 0x5c00;
56static const WCHAR PATH_SLASH_STR_W[] = { 0x2f00,
'\0' };
58static const WCHAR PATH_SLASH_CHR_W =
'/';
59static const WCHAR PATH_BACKSLASH_CHR_W =
'\\';
60static const WCHAR PATH_SLASH_STR_W[] = {
'/',
'\0' };
63#if !defined(WITHOUT_WINPR_3x_DEPRECATED)
64#if defined(__BIG_ENDIAN__)
65static const WCHAR PATH_BACKSLASH_STR_W[] = { 0x5c00,
'\0' };
67static const WCHAR PATH_BACKSLASH_STR_W[] = {
'\\',
'\0' };
69static const char PATH_BACKSLASH_STR[] =
"\\";
75#define PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
76#define PATH_SEPARATOR_STR PATH_BACKSLASH_STR
77#define PATH_SEPARATOR_CHR_W PATH_BACKSLASH_CHR_W
78#define PATH_SEPARATOR_STR_W PATH_BACKSLASH_STR_W
80#define PATH_SEPARATOR_CHR PATH_SLASH_CHR
81#define PATH_SEPARATOR_STR PATH_SLASH_STR
82#define PATH_SEPARATOR_CHR_W PATH_SLASH_CHR_W
83#define PATH_SEPARATOR_STR_W PATH_SLASH_STR_W
86#if !defined(WITHOUT_WINPR_3x_DEPRECATED)
88#define TAG WINPR_TAG("path")
91#if !defined(WITHOUT_WINPR_3x_DEPRECATED)
98#define DEFINE_UNICODE FALSE
99#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
100#define PATH_CCH_ADD_SEPARATOR PathCchAddBackslashA
101#include "include/PathCchAddSeparator.h"
103#undef CUR_PATH_SEPARATOR_CHR
104#undef PATH_CCH_ADD_SEPARATOR
106#define DEFINE_UNICODE TRUE
107#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR_W
108#define PATH_CCH_ADD_SEPARATOR PathCchAddBackslashW
109#include "include/PathCchAddSeparator.h"
111#undef CUR_PATH_SEPARATOR_CHR
112#undef PATH_CCH_ADD_SEPARATOR
116#define DEFINE_UNICODE FALSE
117#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
118#define PATH_CCH_ADD_SEPARATOR PathCchAddSlashA
119#include "include/PathCchAddSeparator.h"
121#undef CUR_PATH_SEPARATOR_CHR
122#undef PATH_CCH_ADD_SEPARATOR
124#define DEFINE_UNICODE TRUE
125#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR_W
126#define PATH_CCH_ADD_SEPARATOR PathCchAddSlashW
127#include "include/PathCchAddSeparator.h"
129#undef CUR_PATH_SEPARATOR_CHR
130#undef PATH_CCH_ADD_SEPARATOR
134#define DEFINE_UNICODE FALSE
135#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
136#define PATH_CCH_ADD_SEPARATOR PathCchAddSeparatorA
137#include "include/PathCchAddSeparator.h"
139#undef CUR_PATH_SEPARATOR_CHR
140#undef PATH_CCH_ADD_SEPARATOR
142#define DEFINE_UNICODE TRUE
143#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR_W
144#define PATH_CCH_ADD_SEPARATOR PathCchAddSeparatorW
145#include "include/PathCchAddSeparator.h"
147#undef CUR_PATH_SEPARATOR_CHR
148#undef PATH_CCH_ADD_SEPARATOR
154HRESULT PathCchRemoveBackslashA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath)
156 WLog_ERR(TAG,
"not implemented");
160HRESULT PathCchRemoveBackslashW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath)
162 WLog_ERR(TAG,
"not implemented");
172#define DEFINE_UNICODE FALSE
173#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
174#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddBackslashExA
175#include "include/PathCchAddSeparatorEx.h"
177#undef CUR_PATH_SEPARATOR_CHR
178#undef PATH_CCH_ADD_SEPARATOR_EX
180#define DEFINE_UNICODE TRUE
181#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR_W
182#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddBackslashExW
183#include "include/PathCchAddSeparatorEx.h"
185#undef CUR_PATH_SEPARATOR_CHR
186#undef PATH_CCH_ADD_SEPARATOR_EX
190#define DEFINE_UNICODE FALSE
191#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
192#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSlashExA
193#include "include/PathCchAddSeparatorEx.h"
195#undef CUR_PATH_SEPARATOR_CHR
196#undef PATH_CCH_ADD_SEPARATOR_EX
198#define DEFINE_UNICODE TRUE
199#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR_W
200#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSlashExW
201#include "include/PathCchAddSeparatorEx.h"
203#undef CUR_PATH_SEPARATOR_CHR
204#undef PATH_CCH_ADD_SEPARATOR_EX
208#define DEFINE_UNICODE FALSE
209#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
210#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSeparatorExA
211#include "include/PathCchAddSeparatorEx.h"
213#undef CUR_PATH_SEPARATOR_CHR
214#undef PATH_CCH_ADD_SEPARATOR_EX
216#define DEFINE_UNICODE TRUE
217#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR_W
218#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSeparatorExW
219#include "include/PathCchAddSeparatorEx.h"
221#undef CUR_PATH_SEPARATOR_CHR
222#undef PATH_CCH_ADD_SEPARATOR_EX
224HRESULT PathCchRemoveBackslashExA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath,
225 WINPR_ATTR_UNUSED PSTR* ppszEnd,
226 WINPR_ATTR_UNUSED
size_t* pcchRemaining)
228 WLog_ERR(TAG,
"not implemented");
232HRESULT PathCchRemoveBackslashExW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath,
233 WINPR_ATTR_UNUSED PWSTR* ppszEnd,
234 WINPR_ATTR_UNUSED
size_t* pcchRemaining)
236 WLog_ERR(TAG,
"not implemented");
246#define DEFINE_UNICODE FALSE
247#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
248#define PATH_CCH_ADD_EXTENSION PathCchAddExtensionA
249#include "include/PathCchAddExtension.h"
251#undef CUR_PATH_SEPARATOR_CHR
252#undef PATH_CCH_ADD_EXTENSION
254#define DEFINE_UNICODE TRUE
255#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR_W
256#define PATH_CCH_ADD_EXTENSION PathCchAddExtensionW
257#include "include/PathCchAddExtension.h"
259#undef CUR_PATH_SEPARATOR_CHR
260#undef PATH_CCH_ADD_EXTENSION
266#define DEFINE_UNICODE FALSE
267#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
268#define PATH_CCH_ADD_EXTENSION UnixPathCchAddExtensionA
269#include "include/PathCchAddExtension.h"
271#undef CUR_PATH_SEPARATOR_CHR
272#undef PATH_CCH_ADD_EXTENSION
274#define DEFINE_UNICODE TRUE
275#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR_W
276#define PATH_CCH_ADD_EXTENSION UnixPathCchAddExtensionW
277#include "include/PathCchAddExtension.h"
279#undef CUR_PATH_SEPARATOR_CHR
280#undef PATH_CCH_ADD_EXTENSION
284#define DEFINE_UNICODE FALSE
285#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
286#define PATH_CCH_ADD_EXTENSION NativePathCchAddExtensionA
287#include "include/PathCchAddExtension.h"
289#undef CUR_PATH_SEPARATOR_CHR
290#undef PATH_CCH_ADD_EXTENSION
292#define DEFINE_UNICODE TRUE
293#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR_W
294#define PATH_CCH_ADD_EXTENSION NativePathCchAddExtensionW
295#include "include/PathCchAddExtension.h"
297#undef CUR_PATH_SEPARATOR_CHR
298#undef PATH_CCH_ADD_EXTENSION
305#if !defined(WITHOUT_WINPR_3x_DEPRECATED)
306#define DEFINE_UNICODE FALSE
307#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
308#define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR
309#define PATH_CCH_APPEND PathCchAppendA
310#include "include/PathCchAppend.h"
312#undef CUR_PATH_SEPARATOR_CHR
313#undef CUR_PATH_SEPARATOR_STR
314#undef PATH_CCH_APPEND
316#define DEFINE_UNICODE TRUE
317#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR_W
318#define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR_W
319#define PATH_CCH_APPEND PathCchAppendW
320#include "include/PathCchAppend.h"
322#undef CUR_PATH_SEPARATOR_CHR
323#undef CUR_PATH_SEPARATOR_STR
324#undef PATH_CCH_APPEND
328#define DEFINE_UNICODE FALSE
329#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
330#define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR
331#define PATH_CCH_APPEND UnixPathCchAppendA
332#include "include/PathCchAppend.h"
334#undef CUR_PATH_SEPARATOR_CHR
335#undef CUR_PATH_SEPARATOR_STR
336#undef PATH_CCH_APPEND
338#define DEFINE_UNICODE TRUE
339#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR_W
340#define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR_W
341#define PATH_CCH_APPEND UnixPathCchAppendW
342#include "include/PathCchAppend.h"
344#undef CUR_PATH_SEPARATOR_CHR
345#undef CUR_PATH_SEPARATOR_STR
346#undef PATH_CCH_APPEND
351#define DEFINE_UNICODE FALSE
352#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
353#define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR
354#define PATH_CCH_APPEND NativePathCchAppendA
355#include "include/PathCchAppend.h"
357#undef CUR_PATH_SEPARATOR_CHR
358#undef CUR_PATH_SEPARATOR_STR
359#undef PATH_CCH_APPEND
361#define DEFINE_UNICODE TRUE
362#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR_W
363#define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR_W
364#define PATH_CCH_APPEND NativePathCchAppendW
365#include "include/PathCchAppend.h"
367#undef CUR_PATH_SEPARATOR_CHR
368#undef CUR_PATH_SEPARATOR_STR
369#undef PATH_CCH_APPEND
371#if !defined(WITHOUT_WINPR_3x_DEPRECATED)
376HRESULT PathCchAppendExA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath,
377 WINPR_ATTR_UNUSED PCSTR pszMore, WINPR_ATTR_UNUSED
unsigned long dwFlags)
379 WLog_ERR(TAG,
"not implemented");
383HRESULT PathCchAppendExW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath,
384 WINPR_ATTR_UNUSED PCWSTR pszMore, WINPR_ATTR_UNUSED
unsigned long dwFlags)
386 WLog_ERR(TAG,
"not implemented");
394#if !defined(WITH_CWALK)
395static void replace(
char* str,
size_t slen,
const char* pattern)
397 const size_t len = strlen(pattern);
400 char* cur = strstr(str, pattern);
404 const char* src = &cur[len];
406 const size_t rem = strnlen(src, slen) + 1;
407 memmove(&cur[1], src, rem);
412static BOOL replace_dotdot(
char* str,
size_t slen)
414 const char pattern[] =
"/../";
415 const size_t len = strlen(pattern);
418 char* cur = strstr(str, pattern);
423 const char* end = &cur[len];
434 const size_t rem = strnlen(end, slen) + 1;
435 memmove(&start[1], end, rem);
440static BOOL replace_trailing_dotdot(
char* str,
size_t slen)
442 const size_t len = strnlen(str, slen);
446 if (strcmp(&str[len - 3],
"/..") != 0)
449 char* start = &str[len - 4];
465char* winpr_PathCanonicalize(
const char* path)
469 const size_t len = strlen(path);
470#if defined(WITH_CWALK)
471 char* str = calloc(len + 1,
sizeof(
char));
474 (void)cwk_path_normalize(path, str, len + 1);
477 char* str = strndup(path, len);
480 replace(str, len,
"/./");
481 replace(str, len,
"//");
482 if (!replace_dotdot(str, len) || !replace_trailing_dotdot(str, len))
489 while ((slen = strnlen(str, len)) > 1)
491 if ((str[slen - 1] ==
'.') || (str[slen - 1] ==
'/'))
492 str[slen - 1] =
'\0';
501#if !defined(WITHOUT_WINPR_3x_DEPRECATED)
506HRESULT PathCchCanonicalizeA(PSTR pszPathOut,
size_t cchPathOut, PCSTR pszPathIn)
508 char* out = winpr_PathCanonicalize(pszPathIn);
510 return E_OUTOFMEMORY;
511 const size_t len = strnlen(out, cchPathOut);
512 if (len >= cchPathOut)
517 strncpy(pszPathOut, out, cchPathOut);
522HRESULT PathCchCanonicalizeW(PWSTR pszPathOut,
size_t cchPathOut, PCWSTR pszPathIn)
525 return E_OUTOFMEMORY;
526 char* str = ConvertWCharToUtf8Alloc(pszPathIn,
nullptr);
528 return E_OUTOFMEMORY;
530 char* out = calloc(cchPathOut,
sizeof(CHAR));
534 return E_OUTOFMEMORY;
537 HRESULT hr = PathCchCanonicalizeA(out, cchPathOut, str);
539 (void)ConvertUtf8NToWChar(out, cchPathOut, pszPathOut, cchPathOut);
548HRESULT PathCchCanonicalizeExA(WINPR_ATTR_UNUSED PSTR pszPathOut,
549 WINPR_ATTR_UNUSED
size_t cchPathOut,
550 WINPR_ATTR_UNUSED PCSTR pszPathIn,
551 WINPR_ATTR_UNUSED
unsigned long dwFlags)
554 WLog_WARN(TAG,
"flags 0x%08lx not implemented", dwFlags);
555 return PathCchCanonicalizeA(pszPathOut, cchPathOut, pszPathIn);
558HRESULT PathCchCanonicalizeExW(WINPR_ATTR_UNUSED PWSTR pszPathOut,
559 WINPR_ATTR_UNUSED
size_t cchPathOut,
560 WINPR_ATTR_UNUSED PCWSTR pszPathIn,
561 WINPR_ATTR_UNUSED
unsigned long dwFlags)
564 WLog_WARN(TAG,
"flags 0x%08lx not implemented", dwFlags);
565 return PathCchCanonicalizeW(pszPathOut, cchPathOut, pszPathIn);
572HRESULT PathAllocCanonicalizeA(PCSTR pszPathIn,
unsigned long dwFlags, PSTR* ppszPathOut)
577 return E_OUTOFMEMORY;
579 WLog_WARN(TAG,
"flags 0x%08lx not implemented", dwFlags);
580 *ppszPathOut = winpr_PathCanonicalize(pszPathIn);
582 return E_OUTOFMEMORY;
586HRESULT PathAllocCanonicalizeW(PCWSTR pszPathIn,
unsigned long dwFlags, PWSTR* ppszPathOut)
591 return E_OUTOFMEMORY;
592 char* str = ConvertWCharToUtf8Alloc(pszPathIn,
nullptr);
594 return E_OUTOFMEMORY;
597 HRESULT hr = PathAllocCanonicalizeA(str, dwFlags, &out);
599 *ppszPathOut = ConvertUtf8ToWCharAlloc(out,
nullptr);
608#if !defined(WITHOUT_WINPR_3x_DEPRECATED)
613HRESULT PathCchCombineA(WINPR_ATTR_UNUSED PSTR pszPathOut, WINPR_ATTR_UNUSED
size_t cchPathOut,
614 WINPR_ATTR_UNUSED PCSTR pszPathIn, WINPR_ATTR_UNUSED PCSTR pszMore)
616 WLog_ERR(TAG,
"not implemented");
620HRESULT PathCchCombineW(WINPR_ATTR_UNUSED PWSTR pszPathOut, WINPR_ATTR_UNUSED
size_t cchPathOut,
621 WINPR_ATTR_UNUSED PCWSTR pszPathIn, WINPR_ATTR_UNUSED PCWSTR pszMore)
623 WLog_ERR(TAG,
"not implemented");
631HRESULT PathCchCombineExA(WINPR_ATTR_UNUSED PSTR pszPathOut, WINPR_ATTR_UNUSED
size_t cchPathOut,
632 WINPR_ATTR_UNUSED PCSTR pszPathIn, WINPR_ATTR_UNUSED PCSTR pszMore,
633 WINPR_ATTR_UNUSED
unsigned long dwFlags)
635 WLog_ERR(TAG,
"not implemented");
639HRESULT PathCchCombineExW(WINPR_ATTR_UNUSED PWSTR pszPathOut, WINPR_ATTR_UNUSED
size_t cchPathOut,
640 WINPR_ATTR_UNUSED PCWSTR pszPathIn, WINPR_ATTR_UNUSED PCWSTR pszMore,
641 WINPR_ATTR_UNUSED
unsigned long dwFlags)
643 WLog_ERR(TAG,
"not implemented");
653#define DEFINE_UNICODE FALSE
654#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
655#define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR
656#define PATH_ALLOC_COMBINE PathAllocCombineA
657#include "include/PathAllocCombine.h"
659#undef CUR_PATH_SEPARATOR_CHR
660#undef CUR_PATH_SEPARATOR_STR
661#undef PATH_ALLOC_COMBINE
663#define DEFINE_UNICODE TRUE
664#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR_W
665#define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR_W
666#define PATH_ALLOC_COMBINE PathAllocCombineW
667#include "include/PathAllocCombine.h"
669#undef CUR_PATH_SEPARATOR_CHR
670#undef CUR_PATH_SEPARATOR_STR
671#undef PATH_ALLOC_COMBINE
677#define DEFINE_UNICODE FALSE
678#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
679#define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR
680#define PATH_ALLOC_COMBINE UnixPathAllocCombineA
681#include "include/PathAllocCombine.h"
683#undef CUR_PATH_SEPARATOR_CHR
684#undef CUR_PATH_SEPARATOR_STR
685#undef PATH_ALLOC_COMBINE
687#define DEFINE_UNICODE TRUE
688#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR_W
689#define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR_W
690#define PATH_ALLOC_COMBINE UnixPathAllocCombineW
691#include "include/PathAllocCombine.h"
693#undef CUR_PATH_SEPARATOR_CHR
694#undef CUR_PATH_SEPARATOR_STR
695#undef PATH_ALLOC_COMBINE
699#define DEFINE_UNICODE FALSE
700#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
701#define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR
702#define PATH_ALLOC_COMBINE NativePathAllocCombineA
703#include "include/PathAllocCombine.h"
705#undef CUR_PATH_SEPARATOR_CHR
706#undef CUR_PATH_SEPARATOR_STR
707#undef PATH_ALLOC_COMBINE
709#define DEFINE_UNICODE TRUE
710#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR_W
711#define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR_W
712#define PATH_ALLOC_COMBINE NativePathAllocCombineW
713#include "include/PathAllocCombine.h"
715#undef CUR_PATH_SEPARATOR_CHR
716#undef CUR_PATH_SEPARATOR_STR
717#undef PATH_ALLOC_COMBINE
719#if !defined(WITHOUT_WINPR_3x_DEPRECATED)
725HRESULT PathCchFindExtensionA(PCSTR pszPath,
size_t cchPath, PCSTR* ppszExt)
727 const char* p = (
const char*)pszPath;
729 if (!pszPath || !cchPath || !ppszExt)
734 while (*p && --cchPath)
758 if ((*p ==
'\\') || (*p ==
'/') || (*p ==
':'))
767HRESULT PathCchFindExtensionW(WINPR_ATTR_UNUSED PCWSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath,
768 WINPR_ATTR_UNUSED PCWSTR* ppszExt)
770 WLog_ERR(TAG,
"not implemented");
778HRESULT PathCchRenameExtensionA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath,
779 WINPR_ATTR_UNUSED PCSTR pszExt)
781 WLog_ERR(TAG,
"not implemented");
785HRESULT PathCchRenameExtensionW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath,
786 WINPR_ATTR_UNUSED PCWSTR pszExt)
788 WLog_ERR(TAG,
"not implemented");
796HRESULT PathCchRemoveExtensionA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath)
798 WLog_ERR(TAG,
"not implemented");
802HRESULT PathCchRemoveExtensionW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath)
804 WLog_ERR(TAG,
"not implemented");
812BOOL PathCchIsRootA(WINPR_ATTR_UNUSED PCSTR pszPath)
814 WLog_ERR(TAG,
"not implemented");
818BOOL PathCchIsRootW(WINPR_ATTR_UNUSED PCWSTR pszPath)
820 WLog_ERR(TAG,
"not implemented");
828BOOL PathIsUNCExA(PCSTR pszPath, PCSTR* ppszServer)
833 if ((pszPath[0] ==
'\\') && (pszPath[1] ==
'\\'))
835 *ppszServer = &pszPath[2];
842BOOL PathIsUNCExW(PCWSTR pszPath, PCWSTR* ppszServer)
847 if ((pszPath[0] ==
'\\') && (pszPath[1] ==
'\\'))
849 *ppszServer = &pszPath[2];
860HRESULT PathCchSkipRootA(WINPR_ATTR_UNUSED PCSTR pszPath, WINPR_ATTR_UNUSED PCSTR* ppszRootEnd)
862 WLog_ERR(TAG,
"not implemented");
866HRESULT PathCchSkipRootW(WINPR_ATTR_UNUSED PCWSTR pszPath, WINPR_ATTR_UNUSED PCWSTR* ppszRootEnd)
868 WLog_ERR(TAG,
"not implemented");
876HRESULT PathCchStripToRootA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath)
878 WLog_ERR(TAG,
"not implemented");
882HRESULT PathCchStripToRootW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath)
884 WLog_ERR(TAG,
"not implemented");
892HRESULT PathCchStripPrefixA(PSTR pszPath,
size_t cchPath)
899 if (cchPath < 4 || cchPath > PATHCCH_MAX_CCH)
902 hasPrefix = ((pszPath[0] ==
'\\') && (pszPath[1] ==
'\\') && (pszPath[2] ==
'?') &&
903 (pszPath[3] ==
'\\'));
910 if (IsCharAlpha(pszPath[4]) && (pszPath[5] ==
':'))
912 if (memmove_s(pszPath, cchPath, &pszPath[4], cchPath - 4) < 0)
913 return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
919 pszPath[cchPath - 4] = 0;
927HRESULT PathCchStripPrefixW(PWSTR pszPath,
size_t cchPath)
934 if (cchPath < 4 || cchPath > PATHCCH_MAX_CCH)
937 hasPrefix = ((pszPath[0] ==
'\\') && (pszPath[1] ==
'\\') && (pszPath[2] ==
'?') &&
938 (pszPath[3] ==
'\\'));
945 const size_t rc = (_wcslen(&pszPath[4]) + 1);
947 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
949 if (IsCharAlphaW(pszPath[4]) && (pszPath[5] == L
':'))
951 if (wmemmove_s(pszPath, cchPath, &pszPath[4], cchPath - 4) < 0)
952 return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
957 pszPath[cchPath - 4] = 0;
969HRESULT PathCchRemoveFileSpecA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath)
971 WLog_ERR(TAG,
"not implemented");
975HRESULT PathCchRemoveFileSpecW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath)
977 WLog_ERR(TAG,
"not implemented");
990HRESULT PathCchConvertStyleA(PSTR pszPath,
size_t cchPath,
unsigned long dwFlags)
992 if (dwFlags == PATH_STYLE_WINDOWS)
994 for (
size_t index = 0; index < cchPath; index++)
996 if (pszPath[index] == PATH_SLASH_CHR)
997 pszPath[index] = PATH_BACKSLASH_CHR;
1000 else if (dwFlags == PATH_STYLE_UNIX)
1002 for (
size_t index = 0; index < cchPath; index++)
1004 if (pszPath[index] == PATH_BACKSLASH_CHR)
1005 pszPath[index] = PATH_SLASH_CHR;
1008 else if (dwFlags == PATH_STYLE_NATIVE)
1010 if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR)
1014 for (
size_t index = 0; index < cchPath; index++)
1016 if (pszPath[index] == PATH_SLASH_CHR)
1017 pszPath[index] = PATH_BACKSLASH_CHR;
1020 else if (PATH_SEPARATOR_CHR == PATH_SLASH_CHR)
1024 for (
size_t index = 0; index < cchPath; index++)
1026 if (pszPath[index] == PATH_BACKSLASH_CHR)
1027 pszPath[index] = PATH_SLASH_CHR;
1045HRESULT PathCchConvertStyleW(PWSTR pszPath,
size_t cchPath,
unsigned long dwFlags)
1047 if (dwFlags == PATH_STYLE_WINDOWS)
1049 for (
size_t index = 0; index < cchPath; index++)
1051 if (pszPath[index] == PATH_SLASH_CHR_W)
1052 pszPath[index] = PATH_BACKSLASH_CHR_W;
1055 else if (dwFlags == PATH_STYLE_UNIX)
1057 for (
size_t index = 0; index < cchPath; index++)
1059 if (pszPath[index] == PATH_BACKSLASH_CHR_W)
1060 pszPath[index] = PATH_SLASH_CHR_W;
1063 else if (dwFlags == PATH_STYLE_NATIVE)
1065 if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR_W)
1069 for (
size_t index = 0; index < cchPath; index++)
1071 if (pszPath[index] == PATH_SLASH_CHR_W)
1072 pszPath[index] = PATH_BACKSLASH_CHR_W;
1075 else if (PATH_SEPARATOR_CHR == PATH_SLASH_CHR_W)
1079 for (
size_t index = 0; index < cchPath; index++)
1081 if (pszPath[index] == PATH_BACKSLASH_CHR_W)
1082 pszPath[index] = PATH_SLASH_CHR_W;
1104char PathGetSeparatorA(
unsigned long dwFlags)
1106 if (dwFlags == PATH_STYLE_WINDOWS)
1107 return PATH_BACKSLASH_CHR;
1108 if (dwFlags == PATH_STYLE_UNIX)
1109 return PATH_SLASH_CHR;
1111 return PATH_SEPARATOR_CHR;
1114WCHAR PathGetSeparatorW(
unsigned long dwFlags)
1116 if (dwFlags == PATH_STYLE_WINDOWS)
1117 return PATH_BACKSLASH_CHR_W;
1118 if (dwFlags == PATH_STYLE_UNIX)
1119 return PATH_SLASH_CHR_W;
1121 return PATH_SEPARATOR_CHR;
1127static const CHAR SharedLibraryExtensionDllA[] =
"dll";
1128static const CHAR SharedLibraryExtensionSoA[] =
"so";
1129static const CHAR SharedLibraryExtensionDylibA[] =
"dylib";
1131static const CHAR SharedLibraryExtensionDotDllA[] =
".dll";
1132static const CHAR SharedLibraryExtensionDotSoA[] =
".so";
1133static const CHAR SharedLibraryExtensionDotDylibA[] =
".dylib";
1134PCSTR PathGetSharedLibraryExtensionA(
unsigned long dwFlags)
1136 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
1138 if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1140 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1141 return SharedLibraryExtensionDotDllA;
1143 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1144 return SharedLibraryExtensionDotSoA;
1146 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1147 return SharedLibraryExtensionDotDylibA;
1151 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1152 return SharedLibraryExtensionDllA;
1154 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1155 return SharedLibraryExtensionSoA;
1157 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1158 return SharedLibraryExtensionDylibA;
1162 if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1165 return SharedLibraryExtensionDotDllA;
1166#elif defined(__APPLE__)
1167 if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1168 return SharedLibraryExtensionDotSoA;
1170 return SharedLibraryExtensionDotDylibA;
1172 return SharedLibraryExtensionDotSoA;
1178 return SharedLibraryExtensionDllA;
1179#elif defined(__APPLE__)
1180 if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1181 return SharedLibraryExtensionSoA;
1183 return SharedLibraryExtensionDylibA;
1185 return SharedLibraryExtensionSoA;
1190PCWSTR PathGetSharedLibraryExtensionW(
unsigned long dwFlags)
1192 static WCHAR buffer[6][16] = WINPR_C_ARRAY_INIT;
1193 const WCHAR* SharedLibraryExtensionDotDllW = InitializeConstWCharFromUtf8(
1194 SharedLibraryExtensionDotDllA, buffer[0], ARRAYSIZE(buffer[0]));
1195 const WCHAR* SharedLibraryExtensionDotSoW =
1196 InitializeConstWCharFromUtf8(SharedLibraryExtensionDotSoA, buffer[1], ARRAYSIZE(buffer[1]));
1197 const WCHAR* SharedLibraryExtensionDotDylibW = InitializeConstWCharFromUtf8(
1198 SharedLibraryExtensionDotDylibA, buffer[2], ARRAYSIZE(buffer[2]));
1199 const WCHAR* SharedLibraryExtensionDllW =
1200 InitializeConstWCharFromUtf8(SharedLibraryExtensionDllA, buffer[3], ARRAYSIZE(buffer[3]));
1201 const WCHAR* SharedLibraryExtensionSoW =
1202 InitializeConstWCharFromUtf8(SharedLibraryExtensionSoA, buffer[4], ARRAYSIZE(buffer[4]));
1203 const WCHAR* SharedLibraryExtensionDylibW =
1204 InitializeConstWCharFromUtf8(SharedLibraryExtensionDylibA, buffer[5], ARRAYSIZE(buffer[5]));
1206 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
1208 if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1210 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1211 return SharedLibraryExtensionDotDllW;
1213 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1214 return SharedLibraryExtensionDotSoW;
1216 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1217 return SharedLibraryExtensionDotDylibW;
1221 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1222 return SharedLibraryExtensionDllW;
1224 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1225 return SharedLibraryExtensionSoW;
1227 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1228 return SharedLibraryExtensionDylibW;
1232 if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1235 return SharedLibraryExtensionDotDllW;
1236#elif defined(__APPLE__)
1237 if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1238 return SharedLibraryExtensionDotSoW;
1240 return SharedLibraryExtensionDotDylibW;
1242 return SharedLibraryExtensionDotSoW;
1248 return SharedLibraryExtensionDllW;
1249#elif defined(__APPLE__)
1250 if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1251 return SharedLibraryExtensionSoW;
1253 return SharedLibraryExtensionDylibW;
1255 return SharedLibraryExtensionSoW;
1260const char* GetKnownPathIdString(
int id)
1264 case KNOWN_PATH_HOME:
1265 return "KNOWN_PATH_HOME";
1266 case KNOWN_PATH_TEMP:
1267 return "KNOWN_PATH_TEMP";
1268 case KNOWN_PATH_XDG_DATA_HOME:
1269 return "KNOWN_PATH_XDG_DATA_HOME";
1270 case KNOWN_PATH_XDG_CONFIG_HOME:
1271 return "KNOWN_PATH_XDG_CONFIG_HOME";
1272 case KNOWN_PATH_XDG_CACHE_HOME:
1273 return "KNOWN_PATH_XDG_CACHE_HOME";
1274 case KNOWN_PATH_XDG_RUNTIME_DIR:
1275 return "KNOWN_PATH_XDG_RUNTIME_DIR";
1276 case KNOWN_PATH_SYSTEM_CONFIG_HOME:
1277 return "KNOWN_PATH_SYSTEM_CONFIG_HOME";
1279 return "KNOWN_PATH_UNKNOWN_ID";
1283static char* concat(
const char* path,
size_t pathlen,
const char* name,
size_t namelen)
1285 const size_t strsize = pathlen + namelen + 2;
1286 char* str = calloc(strsize,
sizeof(
char));
1290 winpr_str_append(path, str, strsize,
"");
1291 winpr_str_append(name, str, strsize,
"");
1295BOOL winpr_RemoveDirectory_RecursiveA(LPCSTR lpPathName)
1302 const size_t pathnamelen = strlen(lpPathName);
1303 const size_t path_slash_len = pathnamelen + 3;
1304 char* path_slash = calloc(pathnamelen + 4,
sizeof(
char));
1307 strncat(path_slash, lpPathName, pathnamelen);
1309 const char star[] =
"*";
1310 const HRESULT hr = NativePathCchAppendA(path_slash, path_slash_len, star);
1311 HANDLE dir = INVALID_HANDLE_VALUE;
1317 dir = FindFirstFileA(path_slash, &findFileData);
1319 if (dir == INVALID_HANDLE_VALUE)
1323 path_slash[path_slash_len - 1] =
'\0';
1326 const size_t len = strnlen(findFileData.cFileName, ARRAYSIZE(findFileData.cFileName));
1328 if ((len == 1 && findFileData.cFileName[0] ==
'.') ||
1329 (len == 2 && findFileData.cFileName[0] ==
'.' && findFileData.cFileName[1] ==
'.'))
1334 char* fullpath = concat(path_slash, path_slash_len, findFileData.cFileName, len);
1338 if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1339 ret = winpr_RemoveDirectory_RecursiveA(fullpath);
1342 WINPR_PRAGMA_DIAG_PUSH
1343 WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
1344 ret = winpr_DeleteFile(fullpath);
1345 WINPR_PRAGMA_DIAG_POP
1352 }
while (ret && FindNextFileA(dir, &findFileData) != 0);
1357 if (!winpr_RemoveDirectory(lpPathName))
1367BOOL winpr_RemoveDirectory_RecursiveW(LPCWSTR lpPathName)
1369 char* name = ConvertWCharToUtf8Alloc(lpPathName,
nullptr);
1372 const BOOL rc = winpr_RemoveDirectory_RecursiveA(name);
1377char* winpr_GetConfigFilePathVA(BOOL system, WINPR_FORMAT_ARG
const char* filename, va_list ap)
1379 eKnownPathTypes
id = system ? KNOWN_PATH_SYSTEM_CONFIG_HOME : KNOWN_PATH_XDG_CONFIG_HOME;
1380 const char* vendor = winpr_getApplicationDetailsVendor();
1381 const char* product = winpr_getApplicationDetailsProduct();
1382 const SSIZE_T version = winpr_getApplicationDetailsVersion();
1384 if (!vendor || !product)
1387 char* config = GetKnownSubPathV(
id,
"%s", vendor);
1391 char* base =
nullptr;
1393 base = GetCombinedPathV(config,
"%s", product);
1395 base = GetCombinedPathV(config,
"%s%" PRIdz, product, version);
1400 char* path = GetCombinedPathVA(base, filename, ap);
1406char* winpr_GetConfigFilePath(BOOL system,
const char* filename)
1409 return winpr_GetConfigFilePathV(system,
"%s",
"");
1410 return winpr_GetConfigFilePathV(system,
"%s", filename);
1413char* winpr_GetConfigFilePathV(BOOL system,
const char* filename, ...)
1415 va_list ap = WINPR_C_ARRAY_INIT;
1416 va_start(ap, filename);
1417 char* str = winpr_GetConfigFilePathVA(system, filename, ap);