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>
32#if defined(WITH_CWALK)
36static const char PATH_SLASH_CHR =
'/';
37static const char PATH_SLASH_STR[] =
"/";
39static const char PATH_BACKSLASH_CHR =
'\\';
40static const char PATH_BACKSLASH_STR[] =
"\\";
43static const WCHAR PATH_SLASH_CHR_W = L
'/';
44static const WCHAR PATH_BACKSLASH_CHR_W = L
'\\';
45static const WCHAR PATH_SLASH_STR_W[] = L
"/";
46static const WCHAR PATH_BACKSLASH_STR_W[] = L
"\\";
48#if defined(__BIG_ENDIAN__)
49static const WCHAR PATH_SLASH_CHR_W = 0x2f00;
50static const WCHAR PATH_BACKSLASH_CHR_W = 0x5c00;
51static const WCHAR PATH_SLASH_STR_W[] = { 0x2f00,
'\0' };
52static const WCHAR PATH_BACKSLASH_STR_W[] = { 0x5c00,
'\0' };
54static const WCHAR PATH_SLASH_CHR_W =
'/';
55static const WCHAR PATH_BACKSLASH_CHR_W =
'\\';
56static const WCHAR PATH_SLASH_STR_W[] = {
'/',
'\0' };
57static const WCHAR PATH_BACKSLASH_STR_W[] = {
'\\',
'\0' };
62#define PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
63#define PATH_SEPARATOR_STR PATH_BACKSLASH_STR
64#define PATH_SEPARATOR_CHR_W PATH_BACKSLASH_CHR_W
65#define PATH_SEPARATOR_STR_W PATH_BACKSLASH_STR_W
67#define PATH_SEPARATOR_CHR PATH_SLASH_CHR
68#define PATH_SEPARATOR_STR PATH_SLASH_STR
69#define PATH_SEPARATOR_CHR_W PATH_SLASH_CHR_W
70#define PATH_SEPARATOR_STR_W PATH_SLASH_STR_W
74#define TAG WINPR_TAG("path")
82#define DEFINE_UNICODE FALSE
83#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
84#define PATH_CCH_ADD_SEPARATOR PathCchAddBackslashA
85#include "include/PathCchAddSeparator.h"
87#undef CUR_PATH_SEPARATOR_CHR
88#undef PATH_CCH_ADD_SEPARATOR
90#define DEFINE_UNICODE TRUE
91#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR_W
92#define PATH_CCH_ADD_SEPARATOR PathCchAddBackslashW
93#include "include/PathCchAddSeparator.h"
95#undef CUR_PATH_SEPARATOR_CHR
96#undef PATH_CCH_ADD_SEPARATOR
100#define DEFINE_UNICODE FALSE
101#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
102#define PATH_CCH_ADD_SEPARATOR PathCchAddSlashA
103#include "include/PathCchAddSeparator.h"
105#undef CUR_PATH_SEPARATOR_CHR
106#undef PATH_CCH_ADD_SEPARATOR
108#define DEFINE_UNICODE TRUE
109#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR_W
110#define PATH_CCH_ADD_SEPARATOR PathCchAddSlashW
111#include "include/PathCchAddSeparator.h"
113#undef CUR_PATH_SEPARATOR_CHR
114#undef PATH_CCH_ADD_SEPARATOR
118#define DEFINE_UNICODE FALSE
119#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
120#define PATH_CCH_ADD_SEPARATOR PathCchAddSeparatorA
121#include "include/PathCchAddSeparator.h"
123#undef CUR_PATH_SEPARATOR_CHR
124#undef PATH_CCH_ADD_SEPARATOR
126#define DEFINE_UNICODE TRUE
127#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR_W
128#define PATH_CCH_ADD_SEPARATOR PathCchAddSeparatorW
129#include "include/PathCchAddSeparator.h"
131#undef CUR_PATH_SEPARATOR_CHR
132#undef PATH_CCH_ADD_SEPARATOR
138HRESULT PathCchRemoveBackslashA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath)
140 WLog_ERR(TAG,
"not implemented");
144HRESULT PathCchRemoveBackslashW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath)
146 WLog_ERR(TAG,
"not implemented");
156#define DEFINE_UNICODE FALSE
157#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
158#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddBackslashExA
159#include "include/PathCchAddSeparatorEx.h"
161#undef CUR_PATH_SEPARATOR_CHR
162#undef PATH_CCH_ADD_SEPARATOR_EX
164#define DEFINE_UNICODE TRUE
165#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR_W
166#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddBackslashExW
167#include "include/PathCchAddSeparatorEx.h"
169#undef CUR_PATH_SEPARATOR_CHR
170#undef PATH_CCH_ADD_SEPARATOR_EX
174#define DEFINE_UNICODE FALSE
175#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
176#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSlashExA
177#include "include/PathCchAddSeparatorEx.h"
179#undef CUR_PATH_SEPARATOR_CHR
180#undef PATH_CCH_ADD_SEPARATOR_EX
182#define DEFINE_UNICODE TRUE
183#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR_W
184#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSlashExW
185#include "include/PathCchAddSeparatorEx.h"
187#undef CUR_PATH_SEPARATOR_CHR
188#undef PATH_CCH_ADD_SEPARATOR_EX
192#define DEFINE_UNICODE FALSE
193#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
194#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSeparatorExA
195#include "include/PathCchAddSeparatorEx.h"
197#undef CUR_PATH_SEPARATOR_CHR
198#undef PATH_CCH_ADD_SEPARATOR_EX
200#define DEFINE_UNICODE TRUE
201#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR_W
202#define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSeparatorExW
203#include "include/PathCchAddSeparatorEx.h"
205#undef CUR_PATH_SEPARATOR_CHR
206#undef PATH_CCH_ADD_SEPARATOR_EX
208HRESULT PathCchRemoveBackslashExA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath,
209 WINPR_ATTR_UNUSED PSTR* ppszEnd,
210 WINPR_ATTR_UNUSED
size_t* pcchRemaining)
212 WLog_ERR(TAG,
"not implemented");
216HRESULT PathCchRemoveBackslashExW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath,
217 WINPR_ATTR_UNUSED PWSTR* ppszEnd,
218 WINPR_ATTR_UNUSED
size_t* pcchRemaining)
220 WLog_ERR(TAG,
"not implemented");
230#define DEFINE_UNICODE FALSE
231#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
232#define PATH_CCH_ADD_EXTENSION PathCchAddExtensionA
233#include "include/PathCchAddExtension.h"
235#undef CUR_PATH_SEPARATOR_CHR
236#undef PATH_CCH_ADD_EXTENSION
238#define DEFINE_UNICODE TRUE
239#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR_W
240#define PATH_CCH_ADD_EXTENSION PathCchAddExtensionW
241#include "include/PathCchAddExtension.h"
243#undef CUR_PATH_SEPARATOR_CHR
244#undef PATH_CCH_ADD_EXTENSION
248#define DEFINE_UNICODE FALSE
249#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
250#define PATH_CCH_ADD_EXTENSION UnixPathCchAddExtensionA
251#include "include/PathCchAddExtension.h"
253#undef CUR_PATH_SEPARATOR_CHR
254#undef PATH_CCH_ADD_EXTENSION
256#define DEFINE_UNICODE TRUE
257#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR_W
258#define PATH_CCH_ADD_EXTENSION UnixPathCchAddExtensionW
259#include "include/PathCchAddExtension.h"
261#undef CUR_PATH_SEPARATOR_CHR
262#undef PATH_CCH_ADD_EXTENSION
266#define DEFINE_UNICODE FALSE
267#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
268#define PATH_CCH_ADD_EXTENSION NativePathCchAddExtensionA
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_SEPARATOR_CHR_W
276#define PATH_CCH_ADD_EXTENSION NativePathCchAddExtensionW
277#include "include/PathCchAddExtension.h"
279#undef CUR_PATH_SEPARATOR_CHR
280#undef PATH_CCH_ADD_EXTENSION
288#define DEFINE_UNICODE FALSE
289#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
290#define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR
291#define PATH_CCH_APPEND PathCchAppendA
292#include "include/PathCchAppend.h"
294#undef CUR_PATH_SEPARATOR_CHR
295#undef CUR_PATH_SEPARATOR_STR
296#undef PATH_CCH_APPEND
298#define DEFINE_UNICODE TRUE
299#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR_W
300#define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR_W
301#define PATH_CCH_APPEND PathCchAppendW
302#include "include/PathCchAppend.h"
304#undef CUR_PATH_SEPARATOR_CHR
305#undef CUR_PATH_SEPARATOR_STR
306#undef PATH_CCH_APPEND
310#define DEFINE_UNICODE FALSE
311#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
312#define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR
313#define PATH_CCH_APPEND UnixPathCchAppendA
314#include "include/PathCchAppend.h"
316#undef CUR_PATH_SEPARATOR_CHR
317#undef CUR_PATH_SEPARATOR_STR
318#undef PATH_CCH_APPEND
320#define DEFINE_UNICODE TRUE
321#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR_W
322#define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR_W
323#define PATH_CCH_APPEND UnixPathCchAppendW
324#include "include/PathCchAppend.h"
326#undef CUR_PATH_SEPARATOR_CHR
327#undef CUR_PATH_SEPARATOR_STR
328#undef PATH_CCH_APPEND
332#define DEFINE_UNICODE FALSE
333#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
334#define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR
335#define PATH_CCH_APPEND NativePathCchAppendA
336#include "include/PathCchAppend.h"
338#undef CUR_PATH_SEPARATOR_CHR
339#undef CUR_PATH_SEPARATOR_STR
340#undef PATH_CCH_APPEND
342#define DEFINE_UNICODE TRUE
343#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR_W
344#define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR_W
345#define PATH_CCH_APPEND NativePathCchAppendW
346#include "include/PathCchAppend.h"
348#undef CUR_PATH_SEPARATOR_CHR
349#undef CUR_PATH_SEPARATOR_STR
350#undef PATH_CCH_APPEND
356HRESULT PathCchAppendExA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath,
357 WINPR_ATTR_UNUSED PCSTR pszMore, WINPR_ATTR_UNUSED
unsigned long dwFlags)
359 WLog_ERR(TAG,
"not implemented");
363HRESULT PathCchAppendExW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath,
364 WINPR_ATTR_UNUSED PCWSTR pszMore, WINPR_ATTR_UNUSED
unsigned long dwFlags)
366 WLog_ERR(TAG,
"not implemented");
372#if !defined(WITH_CWALK)
373static void replace(
char* str,
size_t slen,
const char* pattern)
375 const size_t len = strlen(pattern);
378 char* cur = strstr(str, pattern);
382 const char* src = &cur[len];
384 const size_t rem = strnlen(src, slen) + 1;
385 memmove(&cur[1], src, rem);
390static BOOL replace_dotdot(
char* str,
size_t slen)
392 const char pattern[] =
"/../";
393 const size_t len = strlen(pattern);
396 char* cur = strstr(str, pattern);
401 const char* end = &cur[len];
412 const size_t rem = strnlen(end, slen) + 1;
413 memmove(&start[1], end, rem);
418static BOOL replace_trailing_dotdot(
char* str,
size_t slen)
420 const size_t len = strnlen(str, slen);
424 if (strcmp(&str[len - 3],
"/..") != 0)
427 char* start = &str[len - 4];
443static char* canonicalize(
const char* path)
447 const size_t len = strlen(path);
448#if defined(WITH_CWALK)
449 char* str = calloc(len + 1,
sizeof(
char));
452 (void)cwk_path_normalize(path, str, len + 1);
455 char* str = strndup(path, len);
458 replace(str, len,
"/./");
459 replace(str, len,
"//");
460 if (!replace_dotdot(str, len) || !replace_trailing_dotdot(str, len))
467 while ((slen = strnlen(str, len)) > 1)
469 if ((str[slen - 1] ==
'.') || (str[slen - 1] ==
'/'))
470 str[slen - 1] =
'\0';
483HRESULT PathCchCanonicalizeA(PSTR pszPathOut,
size_t cchPathOut, PCSTR pszPathIn)
485 char* out = canonicalize(pszPathIn);
487 return E_OUTOFMEMORY;
488 const size_t len = strnlen(out, cchPathOut);
489 if (len >= cchPathOut)
494 strncpy(pszPathOut, out, cchPathOut);
499HRESULT PathCchCanonicalizeW(PWSTR pszPathOut,
size_t cchPathOut, PCWSTR pszPathIn)
502 return E_OUTOFMEMORY;
503 char* str = ConvertWCharToUtf8Alloc(pszPathIn,
nullptr);
505 return E_OUTOFMEMORY;
507 char* out = calloc(cchPathOut,
sizeof(CHAR));
511 return E_OUTOFMEMORY;
514 HRESULT hr = PathCchCanonicalizeA(out, cchPathOut, str);
516 (void)ConvertUtf8NToWChar(out, cchPathOut, pszPathOut, cchPathOut);
525HRESULT PathCchCanonicalizeExA(WINPR_ATTR_UNUSED PSTR pszPathOut,
526 WINPR_ATTR_UNUSED
size_t cchPathOut,
527 WINPR_ATTR_UNUSED PCSTR pszPathIn,
528 WINPR_ATTR_UNUSED
unsigned long dwFlags)
531 WLog_WARN(TAG,
"flags 0x%08lx not implemented", dwFlags);
532 return PathCchCanonicalizeA(pszPathOut, cchPathOut, pszPathIn);
535HRESULT PathCchCanonicalizeExW(WINPR_ATTR_UNUSED PWSTR pszPathOut,
536 WINPR_ATTR_UNUSED
size_t cchPathOut,
537 WINPR_ATTR_UNUSED PCWSTR pszPathIn,
538 WINPR_ATTR_UNUSED
unsigned long dwFlags)
541 WLog_WARN(TAG,
"flags 0x%08lx not implemented", dwFlags);
542 return PathCchCanonicalizeW(pszPathOut, cchPathOut, pszPathIn);
549HRESULT PathAllocCanonicalizeA(PCSTR pszPathIn,
unsigned long dwFlags, PSTR* ppszPathOut)
554 return E_OUTOFMEMORY;
556 WLog_WARN(TAG,
"flags 0x%08lx not implemented", dwFlags);
557 *ppszPathOut = canonicalize(pszPathIn);
559 return E_OUTOFMEMORY;
563HRESULT PathAllocCanonicalizeW(PCWSTR pszPathIn,
unsigned long dwFlags, PWSTR* ppszPathOut)
568 return E_OUTOFMEMORY;
569 char* str = ConvertWCharToUtf8Alloc(pszPathIn,
nullptr);
571 return E_OUTOFMEMORY;
574 HRESULT hr = PathAllocCanonicalizeA(str, dwFlags, &out);
576 *ppszPathOut = ConvertUtf8ToWCharAlloc(out,
nullptr);
588HRESULT PathCchCombineA(WINPR_ATTR_UNUSED PSTR pszPathOut, WINPR_ATTR_UNUSED
size_t cchPathOut,
589 WINPR_ATTR_UNUSED PCSTR pszPathIn, WINPR_ATTR_UNUSED PCSTR pszMore)
591 WLog_ERR(TAG,
"not implemented");
595HRESULT PathCchCombineW(WINPR_ATTR_UNUSED PWSTR pszPathOut, WINPR_ATTR_UNUSED
size_t cchPathOut,
596 WINPR_ATTR_UNUSED PCWSTR pszPathIn, WINPR_ATTR_UNUSED PCWSTR pszMore)
598 WLog_ERR(TAG,
"not implemented");
606HRESULT PathCchCombineExA(WINPR_ATTR_UNUSED PSTR pszPathOut, WINPR_ATTR_UNUSED
size_t cchPathOut,
607 WINPR_ATTR_UNUSED PCSTR pszPathIn, WINPR_ATTR_UNUSED PCSTR pszMore,
608 WINPR_ATTR_UNUSED
unsigned long dwFlags)
610 WLog_ERR(TAG,
"not implemented");
614HRESULT PathCchCombineExW(WINPR_ATTR_UNUSED PWSTR pszPathOut, WINPR_ATTR_UNUSED
size_t cchPathOut,
615 WINPR_ATTR_UNUSED PCWSTR pszPathIn, WINPR_ATTR_UNUSED PCWSTR pszMore,
616 WINPR_ATTR_UNUSED
unsigned long dwFlags)
618 WLog_ERR(TAG,
"not implemented");
628#define DEFINE_UNICODE FALSE
629#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
630#define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR
631#define PATH_ALLOC_COMBINE PathAllocCombineA
632#include "include/PathAllocCombine.h"
634#undef CUR_PATH_SEPARATOR_CHR
635#undef CUR_PATH_SEPARATOR_STR
636#undef PATH_ALLOC_COMBINE
638#define DEFINE_UNICODE TRUE
639#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR_W
640#define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR_W
641#define PATH_ALLOC_COMBINE PathAllocCombineW
642#include "include/PathAllocCombine.h"
644#undef CUR_PATH_SEPARATOR_CHR
645#undef CUR_PATH_SEPARATOR_STR
646#undef PATH_ALLOC_COMBINE
650#define DEFINE_UNICODE FALSE
651#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
652#define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR
653#define PATH_ALLOC_COMBINE UnixPathAllocCombineA
654#include "include/PathAllocCombine.h"
656#undef CUR_PATH_SEPARATOR_CHR
657#undef CUR_PATH_SEPARATOR_STR
658#undef PATH_ALLOC_COMBINE
660#define DEFINE_UNICODE TRUE
661#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR_W
662#define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR_W
663#define PATH_ALLOC_COMBINE UnixPathAllocCombineW
664#include "include/PathAllocCombine.h"
666#undef CUR_PATH_SEPARATOR_CHR
667#undef CUR_PATH_SEPARATOR_STR
668#undef PATH_ALLOC_COMBINE
672#define DEFINE_UNICODE FALSE
673#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
674#define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR
675#define PATH_ALLOC_COMBINE NativePathAllocCombineA
676#include "include/PathAllocCombine.h"
678#undef CUR_PATH_SEPARATOR_CHR
679#undef CUR_PATH_SEPARATOR_STR
680#undef PATH_ALLOC_COMBINE
682#define DEFINE_UNICODE TRUE
683#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR_W
684#define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR_W
685#define PATH_ALLOC_COMBINE NativePathAllocCombineW
686#include "include/PathAllocCombine.h"
688#undef CUR_PATH_SEPARATOR_CHR
689#undef CUR_PATH_SEPARATOR_STR
690#undef PATH_ALLOC_COMBINE
696HRESULT PathCchFindExtensionA(PCSTR pszPath,
size_t cchPath, PCSTR* ppszExt)
698 const char* p = (
const char*)pszPath;
700 if (!pszPath || !cchPath || !ppszExt)
705 while (*p && --cchPath)
729 if ((*p ==
'\\') || (*p ==
'/') || (*p ==
':'))
738HRESULT PathCchFindExtensionW(WINPR_ATTR_UNUSED PCWSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath,
739 WINPR_ATTR_UNUSED PCWSTR* ppszExt)
741 WLog_ERR(TAG,
"not implemented");
749HRESULT PathCchRenameExtensionA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath,
750 WINPR_ATTR_UNUSED PCSTR pszExt)
752 WLog_ERR(TAG,
"not implemented");
756HRESULT PathCchRenameExtensionW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath,
757 WINPR_ATTR_UNUSED PCWSTR pszExt)
759 WLog_ERR(TAG,
"not implemented");
767HRESULT PathCchRemoveExtensionA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath)
769 WLog_ERR(TAG,
"not implemented");
773HRESULT PathCchRemoveExtensionW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath)
775 WLog_ERR(TAG,
"not implemented");
783BOOL PathCchIsRootA(WINPR_ATTR_UNUSED PCSTR pszPath)
785 WLog_ERR(TAG,
"not implemented");
789BOOL PathCchIsRootW(WINPR_ATTR_UNUSED PCWSTR pszPath)
791 WLog_ERR(TAG,
"not implemented");
799BOOL PathIsUNCExA(PCSTR pszPath, PCSTR* ppszServer)
804 if ((pszPath[0] ==
'\\') && (pszPath[1] ==
'\\'))
806 *ppszServer = &pszPath[2];
813BOOL PathIsUNCExW(PCWSTR pszPath, PCWSTR* ppszServer)
818 if ((pszPath[0] ==
'\\') && (pszPath[1] ==
'\\'))
820 *ppszServer = &pszPath[2];
831HRESULT PathCchSkipRootA(WINPR_ATTR_UNUSED PCSTR pszPath, WINPR_ATTR_UNUSED PCSTR* ppszRootEnd)
833 WLog_ERR(TAG,
"not implemented");
837HRESULT PathCchSkipRootW(WINPR_ATTR_UNUSED PCWSTR pszPath, WINPR_ATTR_UNUSED PCWSTR* ppszRootEnd)
839 WLog_ERR(TAG,
"not implemented");
847HRESULT PathCchStripToRootA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath)
849 WLog_ERR(TAG,
"not implemented");
853HRESULT PathCchStripToRootW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath)
855 WLog_ERR(TAG,
"not implemented");
863HRESULT PathCchStripPrefixA(PSTR pszPath,
size_t cchPath)
870 if (cchPath < 4 || cchPath > PATHCCH_MAX_CCH)
873 hasPrefix = ((pszPath[0] ==
'\\') && (pszPath[1] ==
'\\') && (pszPath[2] ==
'?') &&
874 (pszPath[3] ==
'\\'));
881 if (IsCharAlpha(pszPath[4]) && (pszPath[5] ==
':'))
883 if (memmove_s(pszPath, cchPath, &pszPath[4], cchPath - 4) < 0)
884 return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
890 pszPath[cchPath - 4] = 0;
898HRESULT PathCchStripPrefixW(PWSTR pszPath,
size_t cchPath)
905 if (cchPath < 4 || cchPath > PATHCCH_MAX_CCH)
908 hasPrefix = ((pszPath[0] ==
'\\') && (pszPath[1] ==
'\\') && (pszPath[2] ==
'?') &&
909 (pszPath[3] ==
'\\'));
916 const size_t rc = (_wcslen(&pszPath[4]) + 1);
918 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
920 if (IsCharAlphaW(pszPath[4]) && (pszPath[5] == L
':'))
922 if (wmemmove_s(pszPath, cchPath, &pszPath[4], cchPath - 4) < 0)
923 return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
928 pszPath[cchPath - 4] = 0;
940HRESULT PathCchRemoveFileSpecA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath)
942 WLog_ERR(TAG,
"not implemented");
946HRESULT PathCchRemoveFileSpecW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED
size_t cchPath)
948 WLog_ERR(TAG,
"not implemented");
960HRESULT PathCchConvertStyleA(PSTR pszPath,
size_t cchPath,
unsigned long dwFlags)
962 if (dwFlags == PATH_STYLE_WINDOWS)
964 for (
size_t index = 0; index < cchPath; index++)
966 if (pszPath[index] == PATH_SLASH_CHR)
967 pszPath[index] = PATH_BACKSLASH_CHR;
970 else if (dwFlags == PATH_STYLE_UNIX)
972 for (
size_t index = 0; index < cchPath; index++)
974 if (pszPath[index] == PATH_BACKSLASH_CHR)
975 pszPath[index] = PATH_SLASH_CHR;
978 else if (dwFlags == PATH_STYLE_NATIVE)
980 if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR)
984 for (
size_t index = 0; index < cchPath; index++)
986 if (pszPath[index] == PATH_SLASH_CHR)
987 pszPath[index] = PATH_BACKSLASH_CHR;
990 else if (PATH_SEPARATOR_CHR == PATH_SLASH_CHR)
994 for (
size_t index = 0; index < cchPath; index++)
996 if (pszPath[index] == PATH_BACKSLASH_CHR)
997 pszPath[index] = PATH_SLASH_CHR;
1015HRESULT PathCchConvertStyleW(PWSTR pszPath,
size_t cchPath,
unsigned long dwFlags)
1017 if (dwFlags == PATH_STYLE_WINDOWS)
1019 for (
size_t index = 0; index < cchPath; index++)
1021 if (pszPath[index] == PATH_SLASH_CHR_W)
1022 pszPath[index] = PATH_BACKSLASH_CHR_W;
1025 else if (dwFlags == PATH_STYLE_UNIX)
1027 for (
size_t index = 0; index < cchPath; index++)
1029 if (pszPath[index] == PATH_BACKSLASH_CHR_W)
1030 pszPath[index] = PATH_SLASH_CHR_W;
1033 else if (dwFlags == PATH_STYLE_NATIVE)
1035 if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR_W)
1039 for (
size_t index = 0; index < cchPath; index++)
1041 if (pszPath[index] == PATH_SLASH_CHR_W)
1042 pszPath[index] = PATH_BACKSLASH_CHR_W;
1045 else if (PATH_SEPARATOR_CHR == PATH_SLASH_CHR_W)
1049 for (
size_t index = 0; index < cchPath; index++)
1051 if (pszPath[index] == PATH_BACKSLASH_CHR_W)
1052 pszPath[index] = PATH_SLASH_CHR_W;
1074char PathGetSeparatorA(
unsigned long dwFlags)
1076 if (dwFlags == PATH_STYLE_WINDOWS)
1077 return PATH_BACKSLASH_CHR;
1078 if (dwFlags == PATH_STYLE_UNIX)
1079 return PATH_SLASH_CHR;
1081 return PATH_SEPARATOR_CHR;
1084WCHAR PathGetSeparatorW(
unsigned long dwFlags)
1086 if (dwFlags == PATH_STYLE_WINDOWS)
1087 return PATH_BACKSLASH_CHR_W;
1088 if (dwFlags == PATH_STYLE_UNIX)
1089 return PATH_SLASH_CHR_W;
1091 return PATH_SEPARATOR_CHR;
1097static const CHAR SharedLibraryExtensionDllA[] =
"dll";
1098static const CHAR SharedLibraryExtensionSoA[] =
"so";
1099static const CHAR SharedLibraryExtensionDylibA[] =
"dylib";
1101static const CHAR SharedLibraryExtensionDotDllA[] =
".dll";
1102static const CHAR SharedLibraryExtensionDotSoA[] =
".so";
1103static const CHAR SharedLibraryExtensionDotDylibA[] =
".dylib";
1104PCSTR PathGetSharedLibraryExtensionA(
unsigned long dwFlags)
1106 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
1108 if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1110 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1111 return SharedLibraryExtensionDotDllA;
1113 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1114 return SharedLibraryExtensionDotSoA;
1116 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1117 return SharedLibraryExtensionDotDylibA;
1121 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1122 return SharedLibraryExtensionDllA;
1124 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1125 return SharedLibraryExtensionSoA;
1127 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1128 return SharedLibraryExtensionDylibA;
1132 if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1135 return SharedLibraryExtensionDotDllA;
1136#elif defined(__APPLE__)
1137 if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1138 return SharedLibraryExtensionDotSoA;
1140 return SharedLibraryExtensionDotDylibA;
1142 return SharedLibraryExtensionDotSoA;
1148 return SharedLibraryExtensionDllA;
1149#elif defined(__APPLE__)
1150 if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1151 return SharedLibraryExtensionSoA;
1153 return SharedLibraryExtensionDylibA;
1155 return SharedLibraryExtensionSoA;
1160PCWSTR PathGetSharedLibraryExtensionW(
unsigned long dwFlags)
1162 static WCHAR buffer[6][16] = WINPR_C_ARRAY_INIT;
1163 const WCHAR* SharedLibraryExtensionDotDllW = InitializeConstWCharFromUtf8(
1164 SharedLibraryExtensionDotDllA, buffer[0], ARRAYSIZE(buffer[0]));
1165 const WCHAR* SharedLibraryExtensionDotSoW =
1166 InitializeConstWCharFromUtf8(SharedLibraryExtensionDotSoA, buffer[1], ARRAYSIZE(buffer[1]));
1167 const WCHAR* SharedLibraryExtensionDotDylibW = InitializeConstWCharFromUtf8(
1168 SharedLibraryExtensionDotDylibA, buffer[2], ARRAYSIZE(buffer[2]));
1169 const WCHAR* SharedLibraryExtensionDllW =
1170 InitializeConstWCharFromUtf8(SharedLibraryExtensionDllA, buffer[3], ARRAYSIZE(buffer[3]));
1171 const WCHAR* SharedLibraryExtensionSoW =
1172 InitializeConstWCharFromUtf8(SharedLibraryExtensionSoA, buffer[4], ARRAYSIZE(buffer[4]));
1173 const WCHAR* SharedLibraryExtensionDylibW =
1174 InitializeConstWCharFromUtf8(SharedLibraryExtensionDylibA, buffer[5], ARRAYSIZE(buffer[5]));
1176 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
1178 if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1180 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1181 return SharedLibraryExtensionDotDllW;
1183 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1184 return SharedLibraryExtensionDotSoW;
1186 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1187 return SharedLibraryExtensionDotDylibW;
1191 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1192 return SharedLibraryExtensionDllW;
1194 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1195 return SharedLibraryExtensionSoW;
1197 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1198 return SharedLibraryExtensionDylibW;
1202 if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1205 return SharedLibraryExtensionDotDllW;
1206#elif defined(__APPLE__)
1207 if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1208 return SharedLibraryExtensionDotSoW;
1210 return SharedLibraryExtensionDotDylibW;
1212 return SharedLibraryExtensionDotSoW;
1218 return SharedLibraryExtensionDllW;
1219#elif defined(__APPLE__)
1220 if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1221 return SharedLibraryExtensionSoW;
1223 return SharedLibraryExtensionDylibW;
1225 return SharedLibraryExtensionSoW;
1230const char* GetKnownPathIdString(
int id)
1234 case KNOWN_PATH_HOME:
1235 return "KNOWN_PATH_HOME";
1236 case KNOWN_PATH_TEMP:
1237 return "KNOWN_PATH_TEMP";
1238 case KNOWN_PATH_XDG_DATA_HOME:
1239 return "KNOWN_PATH_XDG_DATA_HOME";
1240 case KNOWN_PATH_XDG_CONFIG_HOME:
1241 return "KNOWN_PATH_XDG_CONFIG_HOME";
1242 case KNOWN_PATH_XDG_CACHE_HOME:
1243 return "KNOWN_PATH_XDG_CACHE_HOME";
1244 case KNOWN_PATH_XDG_RUNTIME_DIR:
1245 return "KNOWN_PATH_XDG_RUNTIME_DIR";
1246 case KNOWN_PATH_SYSTEM_CONFIG_HOME:
1247 return "KNOWN_PATH_SYSTEM_CONFIG_HOME";
1249 return "KNOWN_PATH_UNKNOWN_ID";
1253static char* concat(
const char* path,
size_t pathlen,
const char* name,
size_t namelen)
1255 const size_t strsize = pathlen + namelen + 2;
1256 char* str = calloc(strsize,
sizeof(
char));
1260 winpr_str_append(path, str, strsize,
"");
1261 winpr_str_append(name, str, strsize,
"");
1265BOOL winpr_RemoveDirectory_RecursiveA(LPCSTR lpPathName)
1272 const size_t pathnamelen = strlen(lpPathName);
1273 const size_t path_slash_len = pathnamelen + 3;
1274 char* path_slash = calloc(pathnamelen + 4,
sizeof(
char));
1277 strncat(path_slash, lpPathName, pathnamelen);
1279 const char star[] =
"*";
1280 const HRESULT hr = NativePathCchAppendA(path_slash, path_slash_len, star);
1281 HANDLE dir = INVALID_HANDLE_VALUE;
1287 dir = FindFirstFileA(path_slash, &findFileData);
1289 if (dir == INVALID_HANDLE_VALUE)
1293 path_slash[path_slash_len - 1] =
'\0';
1296 const size_t len = strnlen(findFileData.cFileName, ARRAYSIZE(findFileData.cFileName));
1298 if ((len == 1 && findFileData.cFileName[0] ==
'.') ||
1299 (len == 2 && findFileData.cFileName[0] ==
'.' && findFileData.cFileName[1] ==
'.'))
1304 char* fullpath = concat(path_slash, path_slash_len, findFileData.cFileName, len);
1308 if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1309 ret = winpr_RemoveDirectory_RecursiveA(fullpath);
1312 WINPR_PRAGMA_DIAG_PUSH
1313 WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
1314 ret = winpr_DeleteFile(fullpath);
1315 WINPR_PRAGMA_DIAG_POP
1322 }
while (ret && FindNextFileA(dir, &findFileData) != 0);
1327 if (!winpr_RemoveDirectory(lpPathName))
1337BOOL winpr_RemoveDirectory_RecursiveW(LPCWSTR lpPathName)
1339 char* name = ConvertWCharToUtf8Alloc(lpPathName,
nullptr);
1342 const BOOL rc = winpr_RemoveDirectory_RecursiveA(name);
1347char* winpr_GetConfigFilePathVA(BOOL system, WINPR_FORMAT_ARG
const char* filename, va_list ap)
1349 eKnownPathTypes
id = system ? KNOWN_PATH_SYSTEM_CONFIG_HOME : KNOWN_PATH_XDG_CONFIG_HOME;
1350 const char* vendor = winpr_getApplicationDetailsVendor();
1351 const char* product = winpr_getApplicationDetailsProduct();
1352 const SSIZE_T version = winpr_getApplicationDetailsVersion();
1354 if (!vendor || !product)
1357 char* config = GetKnownSubPathV(
id,
"%s", vendor);
1361 char* base =
nullptr;
1363 base = GetCombinedPathV(config,
"%s", product);
1365 base = GetCombinedPathV(config,
"%s%" PRIdz, product, version);
1370 char* path = GetCombinedPathVA(base, filename, ap);
1376char* winpr_GetConfigFilePath(BOOL system,
const char* filename)
1379 return winpr_GetConfigFilePathV(system,
"%s",
"");
1380 return winpr_GetConfigFilePathV(system,
"%s", filename);
1383char* winpr_GetConfigFilePathV(BOOL system,
const char* filename, ...)
1385 va_list ap = WINPR_C_ARRAY_INIT;
1386 va_start(ap, filename);
1387 char* str = winpr_GetConfigFilePathVA(system, filename, ap);