FreeRDP
path.c
1 
20 #include <winpr/config.h>
21 #include <winpr/version.h>
22 #include <winpr/build-config.h>
23 
24 #include <winpr/crt.h>
25 #include <winpr/tchar.h>
26 
27 #include <winpr/path.h>
28 #include <winpr/file.h>
29 
30 #define STR(x) #x
31 
32 #define PATH_SLASH_CHR '/'
33 #define PATH_SLASH_STR "/"
34 
35 #define PATH_BACKSLASH_CHR '\\'
36 #define PATH_BACKSLASH_STR "\\"
37 
38 #ifdef _WIN32
39 #define PATH_SLASH_STR_W L"/"
40 #define PATH_BACKSLASH_STR_W L"\\"
41 #else
42 #define PATH_SLASH_STR_W \
43  { \
44  '/', '\0' \
45  }
46 #define PATH_BACKSLASH_STR_W \
47  { \
48  '\\', '\0' \
49  }
50 #endif
51 
52 #ifdef _WIN32
53 #define PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
54 #define PATH_SEPARATOR_STR PATH_BACKSLASH_STR
55 #define PATH_SEPARATOR_STR_W PATH_BACKSLASH_STR_W
56 #else
57 #define PATH_SEPARATOR_CHR PATH_SLASH_CHR
58 #define PATH_SEPARATOR_STR PATH_SLASH_STR
59 #define PATH_SEPARATOR_STR_W PATH_SLASH_STR_W
60 #endif
61 
62 #define SHARED_LIBRARY_EXT_DLL "dll"
63 #define SHARED_LIBRARY_EXT_SO "so"
64 #define SHARED_LIBRARY_EXT_DYLIB "dylib"
65 
66 #ifdef _WIN32
67 #define SHARED_LIBRARY_EXT SHARED_LIBRARY_EXT_DLL
68 #elif defined(__APPLE__)
69 #define SHARED_LIBRARY_EXT SHARED_LIBRARY_EXT_DYLIB
70 #else
71 #define SHARED_LIBRARY_EXT SHARED_LIBRARY_EXT_SO
72 #endif
73 
74 #include "../log.h"
75 #define TAG WINPR_TAG("path")
76 
77 /*
78  * PathCchAddBackslash
79  */
80 
81 /* Windows-style Paths */
82 
83 #define DEFINE_UNICODE FALSE
84 #define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
85 #define PATH_CCH_ADD_SEPARATOR PathCchAddBackslashA
86 #include "include/PathCchAddSeparator.h"
87 #undef DEFINE_UNICODE
88 #undef CUR_PATH_SEPARATOR_CHR
89 #undef PATH_CCH_ADD_SEPARATOR
90 
91 #define DEFINE_UNICODE TRUE
92 #define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
93 #define PATH_CCH_ADD_SEPARATOR PathCchAddBackslashW
94 #include "include/PathCchAddSeparator.h"
95 #undef DEFINE_UNICODE
96 #undef CUR_PATH_SEPARATOR_CHR
97 #undef PATH_CCH_ADD_SEPARATOR
98 
99 /* Unix-style Paths */
100 
101 #define DEFINE_UNICODE FALSE
102 #define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
103 #define PATH_CCH_ADD_SEPARATOR PathCchAddSlashA
104 #include "include/PathCchAddSeparator.h"
105 #undef DEFINE_UNICODE
106 #undef CUR_PATH_SEPARATOR_CHR
107 #undef PATH_CCH_ADD_SEPARATOR
108 
109 #define DEFINE_UNICODE TRUE
110 #define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
111 #define PATH_CCH_ADD_SEPARATOR PathCchAddSlashW
112 #include "include/PathCchAddSeparator.h"
113 #undef DEFINE_UNICODE
114 #undef CUR_PATH_SEPARATOR_CHR
115 #undef PATH_CCH_ADD_SEPARATOR
116 
117 /* Native-style Paths */
118 
119 #define DEFINE_UNICODE FALSE
120 #define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
121 #define PATH_CCH_ADD_SEPARATOR PathCchAddSeparatorA
122 #include "include/PathCchAddSeparator.h"
123 #undef DEFINE_UNICODE
124 #undef CUR_PATH_SEPARATOR_CHR
125 #undef PATH_CCH_ADD_SEPARATOR
126 
127 #define DEFINE_UNICODE TRUE
128 #define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
129 #define PATH_CCH_ADD_SEPARATOR PathCchAddSeparatorW
130 #include "include/PathCchAddSeparator.h"
131 #undef DEFINE_UNICODE
132 #undef CUR_PATH_SEPARATOR_CHR
133 #undef PATH_CCH_ADD_SEPARATOR
134 
135 /*
136  * PathCchRemoveBackslash
137  */
138 
139 HRESULT PathCchRemoveBackslashA(PSTR pszPath, size_t cchPath)
140 {
141  WLog_ERR(TAG, "not implemented");
142  return E_NOTIMPL;
143 }
144 
145 HRESULT PathCchRemoveBackslashW(PWSTR pszPath, size_t cchPath)
146 {
147  WLog_ERR(TAG, "not implemented");
148  return E_NOTIMPL;
149 }
150 
151 /*
152  * PathCchAddBackslashEx
153  */
154 
155 /* Windows-style Paths */
156 
157 #define DEFINE_UNICODE FALSE
158 #define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
159 #define PATH_CCH_ADD_SEPARATOR_EX PathCchAddBackslashExA
160 #include "include/PathCchAddSeparatorEx.h"
161 #undef DEFINE_UNICODE
162 #undef CUR_PATH_SEPARATOR_CHR
163 #undef PATH_CCH_ADD_SEPARATOR_EX
164 
165 #define DEFINE_UNICODE TRUE
166 #define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
167 #define PATH_CCH_ADD_SEPARATOR_EX PathCchAddBackslashExW
168 #include "include/PathCchAddSeparatorEx.h"
169 #undef DEFINE_UNICODE
170 #undef CUR_PATH_SEPARATOR_CHR
171 #undef PATH_CCH_ADD_SEPARATOR_EX
172 
173 /* Unix-style Paths */
174 
175 #define DEFINE_UNICODE FALSE
176 #define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
177 #define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSlashExA
178 #include "include/PathCchAddSeparatorEx.h"
179 #undef DEFINE_UNICODE
180 #undef CUR_PATH_SEPARATOR_CHR
181 #undef PATH_CCH_ADD_SEPARATOR_EX
182 
183 #define DEFINE_UNICODE TRUE
184 #define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
185 #define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSlashExW
186 #include "include/PathCchAddSeparatorEx.h"
187 #undef DEFINE_UNICODE
188 #undef CUR_PATH_SEPARATOR_CHR
189 #undef PATH_CCH_ADD_SEPARATOR_EX
190 
191 /* Native-style Paths */
192 
193 #define DEFINE_UNICODE FALSE
194 #define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
195 #define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSeparatorExA
196 #include "include/PathCchAddSeparatorEx.h"
197 #undef DEFINE_UNICODE
198 #undef CUR_PATH_SEPARATOR_CHR
199 #undef PATH_CCH_ADD_SEPARATOR_EX
200 
201 #define DEFINE_UNICODE TRUE
202 #define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
203 #define PATH_CCH_ADD_SEPARATOR_EX PathCchAddSeparatorExW
204 #include "include/PathCchAddSeparatorEx.h"
205 #undef DEFINE_UNICODE
206 #undef CUR_PATH_SEPARATOR_CHR
207 #undef PATH_CCH_ADD_SEPARATOR_EX
208 
209 HRESULT PathCchRemoveBackslashExA(PSTR pszPath, size_t cchPath, PSTR* ppszEnd,
210  size_t* pcchRemaining)
211 {
212  WLog_ERR(TAG, "not implemented");
213  return E_NOTIMPL;
214 }
215 
216 HRESULT PathCchRemoveBackslashExW(PWSTR pszPath, size_t cchPath, PWSTR* ppszEnd,
217  size_t* pcchRemaining)
218 {
219  WLog_ERR(TAG, "not implemented");
220  return E_NOTIMPL;
221 }
222 
223 /*
224  * PathCchAddExtension
225  */
226 
227 /* Windows-style Paths */
228 
229 #define DEFINE_UNICODE FALSE
230 #define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
231 #define PATH_CCH_ADD_EXTENSION PathCchAddExtensionA
232 #include "include/PathCchAddExtension.h"
233 #undef DEFINE_UNICODE
234 #undef CUR_PATH_SEPARATOR_CHR
235 #undef PATH_CCH_ADD_EXTENSION
236 
237 #define DEFINE_UNICODE TRUE
238 #define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
239 #define PATH_CCH_ADD_EXTENSION PathCchAddExtensionW
240 #include "include/PathCchAddExtension.h"
241 #undef DEFINE_UNICODE
242 #undef CUR_PATH_SEPARATOR_CHR
243 #undef PATH_CCH_ADD_EXTENSION
244 
245 /* Unix-style Paths */
246 
247 #define DEFINE_UNICODE FALSE
248 #define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
249 #define PATH_CCH_ADD_EXTENSION UnixPathCchAddExtensionA
250 #include "include/PathCchAddExtension.h"
251 #undef DEFINE_UNICODE
252 #undef CUR_PATH_SEPARATOR_CHR
253 #undef PATH_CCH_ADD_EXTENSION
254 
255 #define DEFINE_UNICODE TRUE
256 #define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
257 #define PATH_CCH_ADD_EXTENSION UnixPathCchAddExtensionW
258 #include "include/PathCchAddExtension.h"
259 #undef DEFINE_UNICODE
260 #undef CUR_PATH_SEPARATOR_CHR
261 #undef PATH_CCH_ADD_EXTENSION
262 
263 /* Native-style Paths */
264 
265 #define DEFINE_UNICODE FALSE
266 #define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
267 #define PATH_CCH_ADD_EXTENSION NativePathCchAddExtensionA
268 #include "include/PathCchAddExtension.h"
269 #undef DEFINE_UNICODE
270 #undef CUR_PATH_SEPARATOR_CHR
271 #undef PATH_CCH_ADD_EXTENSION
272 
273 #define DEFINE_UNICODE TRUE
274 #define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
275 #define PATH_CCH_ADD_EXTENSION NativePathCchAddExtensionW
276 #include "include/PathCchAddExtension.h"
277 #undef DEFINE_UNICODE
278 #undef CUR_PATH_SEPARATOR_CHR
279 #undef PATH_CCH_ADD_EXTENSION
280 
281 /*
282  * PathCchAppend
283  */
284 
285 /* Windows-style Paths */
286 
287 #define DEFINE_UNICODE FALSE
288 #define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
289 #define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR
290 #define PATH_CCH_APPEND PathCchAppendA
291 #include "include/PathCchAppend.h"
292 #undef DEFINE_UNICODE
293 #undef CUR_PATH_SEPARATOR_CHR
294 #undef CUR_PATH_SEPARATOR_STR
295 #undef PATH_CCH_APPEND
296 
297 #define DEFINE_UNICODE TRUE
298 #define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
299 #define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR_W
300 #define PATH_CCH_APPEND PathCchAppendW
301 #include "include/PathCchAppend.h"
302 #undef DEFINE_UNICODE
303 #undef CUR_PATH_SEPARATOR_CHR
304 #undef CUR_PATH_SEPARATOR_STR
305 #undef PATH_CCH_APPEND
306 
307 /* Unix-style Paths */
308 
309 #define DEFINE_UNICODE FALSE
310 #define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
311 #define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR
312 #define PATH_CCH_APPEND UnixPathCchAppendA
313 #include "include/PathCchAppend.h"
314 #undef DEFINE_UNICODE
315 #undef CUR_PATH_SEPARATOR_CHR
316 #undef CUR_PATH_SEPARATOR_STR
317 #undef PATH_CCH_APPEND
318 
319 #define DEFINE_UNICODE TRUE
320 #define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
321 #define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR_W
322 #define PATH_CCH_APPEND UnixPathCchAppendW
323 #include "include/PathCchAppend.h"
324 #undef DEFINE_UNICODE
325 #undef CUR_PATH_SEPARATOR_CHR
326 #undef CUR_PATH_SEPARATOR_STR
327 #undef PATH_CCH_APPEND
328 
329 /* Native-style Paths */
330 
331 #define DEFINE_UNICODE FALSE
332 #define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
333 #define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR
334 #define PATH_CCH_APPEND NativePathCchAppendA
335 #include "include/PathCchAppend.h"
336 #undef DEFINE_UNICODE
337 #undef CUR_PATH_SEPARATOR_CHR
338 #undef CUR_PATH_SEPARATOR_STR
339 #undef PATH_CCH_APPEND
340 
341 #define DEFINE_UNICODE TRUE
342 #define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
343 #define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR_W
344 #define PATH_CCH_APPEND NativePathCchAppendW
345 #include "include/PathCchAppend.h"
346 #undef DEFINE_UNICODE
347 #undef CUR_PATH_SEPARATOR_CHR
348 #undef CUR_PATH_SEPARATOR_STR
349 #undef PATH_CCH_APPEND
350 
351 /*
352  * PathCchAppendEx
353  */
354 
355 HRESULT PathCchAppendExA(PSTR pszPath, size_t cchPath, PCSTR pszMore, unsigned long dwFlags)
356 {
357  WLog_ERR(TAG, "not implemented");
358  return E_NOTIMPL;
359 }
360 
361 HRESULT PathCchAppendExW(PWSTR pszPath, size_t cchPath, PCWSTR pszMore, unsigned long dwFlags)
362 {
363  WLog_ERR(TAG, "not implemented");
364  return E_NOTIMPL;
365 }
366 
367 /*
368  * PathCchCanonicalize
369  */
370 
371 HRESULT PathCchCanonicalizeA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn)
372 {
373  WLog_ERR(TAG, "not implemented");
374  return E_NOTIMPL;
375 }
376 
377 HRESULT PathCchCanonicalizeW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn)
378 {
379  WLog_ERR(TAG, "not implemented");
380  return E_NOTIMPL;
381 }
382 
383 /*
384  * PathCchCanonicalizeEx
385  */
386 
387 HRESULT PathCchCanonicalizeExA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn,
388  unsigned long dwFlags)
389 {
390  WLog_ERR(TAG, "not implemented");
391  return E_NOTIMPL;
392 }
393 
394 HRESULT PathCchCanonicalizeExW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn,
395  unsigned long dwFlags)
396 {
397  WLog_ERR(TAG, "not implemented");
398  return E_NOTIMPL;
399 }
400 
401 /*
402  * PathAllocCanonicalize
403  */
404 
405 HRESULT PathAllocCanonicalizeA(PCSTR pszPathIn, unsigned long dwFlags, PSTR* ppszPathOut)
406 {
407  WLog_ERR(TAG, "not implemented");
408  return E_NOTIMPL;
409 }
410 
411 HRESULT PathAllocCanonicalizeW(PCWSTR pszPathIn, unsigned long dwFlags, PWSTR* ppszPathOut)
412 {
413  WLog_ERR(TAG, "not implemented");
414  return E_NOTIMPL;
415 }
416 
417 /*
418  * PathCchCombine
419  */
420 
421 HRESULT PathCchCombineA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn, PCSTR pszMore)
422 {
423  WLog_ERR(TAG, "not implemented");
424  return E_NOTIMPL;
425 }
426 
427 HRESULT PathCchCombineW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn, PCWSTR pszMore)
428 {
429  WLog_ERR(TAG, "not implemented");
430  return E_NOTIMPL;
431 }
432 
433 /*
434  * PathCchCombineEx
435  */
436 
437 HRESULT PathCchCombineExA(PSTR pszPathOut, size_t cchPathOut, PCSTR pszPathIn, PCSTR pszMore,
438  unsigned long dwFlags)
439 {
440  WLog_ERR(TAG, "not implemented");
441  return E_NOTIMPL;
442 }
443 
444 HRESULT PathCchCombineExW(PWSTR pszPathOut, size_t cchPathOut, PCWSTR pszPathIn, PCWSTR pszMore,
445  unsigned long dwFlags)
446 {
447  WLog_ERR(TAG, "not implemented");
448  return E_NOTIMPL;
449 }
450 
451 /*
452  * PathAllocCombine
453  */
454 
455 /* Windows-style Paths */
456 
457 #define DEFINE_UNICODE FALSE
458 #define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
459 #define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR
460 #define PATH_ALLOC_COMBINE PathAllocCombineA
461 #include "include/PathAllocCombine.h"
462 #undef DEFINE_UNICODE
463 #undef CUR_PATH_SEPARATOR_CHR
464 #undef CUR_PATH_SEPARATOR_STR
465 #undef PATH_ALLOC_COMBINE
466 
467 #define DEFINE_UNICODE TRUE
468 #define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
469 #define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR_W
470 #define PATH_ALLOC_COMBINE PathAllocCombineW
471 #include "include/PathAllocCombine.h"
472 #undef DEFINE_UNICODE
473 #undef CUR_PATH_SEPARATOR_CHR
474 #undef CUR_PATH_SEPARATOR_STR
475 #undef PATH_ALLOC_COMBINE
476 
477 /* Unix-style Paths */
478 
479 #define DEFINE_UNICODE FALSE
480 #define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
481 #define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR
482 #define PATH_ALLOC_COMBINE UnixPathAllocCombineA
483 #include "include/PathAllocCombine.h"
484 #undef DEFINE_UNICODE
485 #undef CUR_PATH_SEPARATOR_CHR
486 #undef CUR_PATH_SEPARATOR_STR
487 #undef PATH_ALLOC_COMBINE
488 
489 #define DEFINE_UNICODE TRUE
490 #define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
491 #define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR_W
492 #define PATH_ALLOC_COMBINE UnixPathAllocCombineW
493 #include "include/PathAllocCombine.h"
494 #undef DEFINE_UNICODE
495 #undef CUR_PATH_SEPARATOR_CHR
496 #undef CUR_PATH_SEPARATOR_STR
497 #undef PATH_ALLOC_COMBINE
498 
499 /* Native-style Paths */
500 
501 #define DEFINE_UNICODE FALSE
502 #define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
503 #define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR
504 #define PATH_ALLOC_COMBINE NativePathAllocCombineA
505 #include "include/PathAllocCombine.h"
506 #undef DEFINE_UNICODE
507 #undef CUR_PATH_SEPARATOR_CHR
508 #undef CUR_PATH_SEPARATOR_STR
509 #undef PATH_ALLOC_COMBINE
510 
511 #define DEFINE_UNICODE TRUE
512 #define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
513 #define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR_W
514 #define PATH_ALLOC_COMBINE NativePathAllocCombineW
515 #include "include/PathAllocCombine.h"
516 #undef DEFINE_UNICODE
517 #undef CUR_PATH_SEPARATOR_CHR
518 #undef CUR_PATH_SEPARATOR_STR
519 #undef PATH_ALLOC_COMBINE
520 
525 HRESULT PathCchFindExtensionA(PCSTR pszPath, size_t cchPath, PCSTR* ppszExt)
526 {
527  const char* p = (const char*)pszPath;
528 
529  if (!pszPath || !cchPath || !ppszExt)
530  return E_INVALIDARG;
531 
532  /* find end of string */
533 
534  while (*p && --cchPath)
535  {
536  p++;
537  }
538 
539  if (*p)
540  {
541  /* pszPath is not null terminated within the cchPath range */
542  return E_INVALIDARG;
543  }
544 
545  /* If no extension is found, ppszExt must point to the string's terminating null */
546  *ppszExt = p;
547 
548  /* search backwards for '.' */
549 
550  while (p > pszPath)
551  {
552  if (*p == '.')
553  {
554  *ppszExt = (PCSTR)p;
555  break;
556  }
557 
558  if ((*p == '\\') || (*p == '/') || (*p == ':'))
559  break;
560 
561  p--;
562  }
563 
564  return S_OK;
565 }
566 
567 HRESULT PathCchFindExtensionW(PCWSTR pszPath, size_t cchPath, PCWSTR* ppszExt)
568 {
569  WLog_ERR(TAG, "not implemented");
570  return E_NOTIMPL;
571 }
572 
577 HRESULT PathCchRenameExtensionA(PSTR pszPath, size_t cchPath, PCSTR pszExt)
578 {
579  WLog_ERR(TAG, "not implemented");
580  return E_NOTIMPL;
581 }
582 
583 HRESULT PathCchRenameExtensionW(PWSTR pszPath, size_t cchPath, PCWSTR pszExt)
584 {
585  WLog_ERR(TAG, "not implemented");
586  return E_NOTIMPL;
587 }
588 
593 HRESULT PathCchRemoveExtensionA(PSTR pszPath, size_t cchPath)
594 {
595  WLog_ERR(TAG, "not implemented");
596  return E_NOTIMPL;
597 }
598 
599 HRESULT PathCchRemoveExtensionW(PWSTR pszPath, size_t cchPath)
600 {
601  WLog_ERR(TAG, "not implemented");
602  return E_NOTIMPL;
603 }
604 
609 BOOL PathCchIsRootA(PCSTR pszPath)
610 {
611  WLog_ERR(TAG, "not implemented");
612  return FALSE;
613 }
614 
615 BOOL PathCchIsRootW(PCWSTR pszPath)
616 {
617  WLog_ERR(TAG, "not implemented");
618  return FALSE;
619 }
620 
625 BOOL PathIsUNCExA(PCSTR pszPath, PCSTR* ppszServer)
626 {
627  if (!pszPath)
628  return FALSE;
629 
630  if ((pszPath[0] == '\\') && (pszPath[1] == '\\'))
631  {
632  *ppszServer = &pszPath[2];
633  return TRUE;
634  }
635 
636  return FALSE;
637 }
638 
639 BOOL PathIsUNCExW(PCWSTR pszPath, PCWSTR* ppszServer)
640 {
641  if (!pszPath)
642  return FALSE;
643 
644  if ((pszPath[0] == '\\') && (pszPath[1] == '\\'))
645  {
646  *ppszServer = &pszPath[2];
647  return TRUE;
648  }
649 
650  return FALSE;
651 }
652 
657 HRESULT PathCchSkipRootA(PCSTR pszPath, PCSTR* ppszRootEnd)
658 {
659  WLog_ERR(TAG, "not implemented");
660  return E_NOTIMPL;
661 }
662 
663 HRESULT PathCchSkipRootW(PCWSTR pszPath, PCWSTR* ppszRootEnd)
664 {
665  WLog_ERR(TAG, "not implemented");
666  return E_NOTIMPL;
667 }
668 
673 HRESULT PathCchStripToRootA(PSTR pszPath, size_t cchPath)
674 {
675  WLog_ERR(TAG, "not implemented");
676  return E_NOTIMPL;
677 }
678 
679 HRESULT PathCchStripToRootW(PWSTR pszPath, size_t cchPath)
680 {
681  WLog_ERR(TAG, "not implemented");
682  return E_NOTIMPL;
683 }
684 
689 HRESULT PathCchStripPrefixA(PSTR pszPath, size_t cchPath)
690 {
691  BOOL hasPrefix = 0;
692 
693  if (!pszPath)
694  return E_INVALIDARG;
695 
696  if (cchPath < 4 || cchPath > PATHCCH_MAX_CCH)
697  return E_INVALIDARG;
698 
699  hasPrefix = ((pszPath[0] == '\\') && (pszPath[1] == '\\') && (pszPath[2] == '?') &&
700  (pszPath[3] == '\\'))
701  ? TRUE
702  : FALSE;
703 
704  if (hasPrefix)
705  {
706  if (cchPath < 6)
707  return S_FALSE;
708 
709  if (IsCharAlpha(pszPath[4]) && (pszPath[5] == ':')) /* like C: */
710  {
711  memmove_s(pszPath, cchPath, &pszPath[4], cchPath - 4);
712  /* since the passed pszPath must not necessarily be null terminated
713  * and we always have enough space after the strip we can always
714  * ensure the null termination of the stripped result
715  */
716  pszPath[cchPath - 4] = 0;
717  return S_OK;
718  }
719  }
720 
721  return S_FALSE;
722 }
723 
724 HRESULT PathCchStripPrefixW(PWSTR pszPath, size_t cchPath)
725 {
726  BOOL hasPrefix = 0;
727 
728  if (!pszPath)
729  return E_INVALIDARG;
730 
731  if (cchPath < 4 || cchPath > PATHCCH_MAX_CCH)
732  return E_INVALIDARG;
733 
734  hasPrefix = ((pszPath[0] == '\\') && (pszPath[1] == '\\') && (pszPath[2] == '?') &&
735  (pszPath[3] == '\\'))
736  ? TRUE
737  : FALSE;
738 
739  if (hasPrefix)
740  {
741  if (cchPath < 6)
742  return S_FALSE;
743 
744  const size_t rc = (_wcslen(&pszPath[4]) + 1);
745  if (cchPath < rc)
746  return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
747 
748  if (IsCharAlphaW(pszPath[4]) && (pszPath[5] == L':')) /* like C: */
749  {
750  wmemmove_s(pszPath, cchPath, &pszPath[4], cchPath - 4);
751  /* since the passed pszPath must not necessarily be null terminated
752  * and we always have enough space after the strip we can always
753  * ensure the null termination of the stripped result
754  */
755  pszPath[cchPath - 4] = 0;
756  return S_OK;
757  }
758  }
759 
760  return S_FALSE;
761 }
762 
767 HRESULT PathCchRemoveFileSpecA(PSTR pszPath, size_t cchPath)
768 {
769  WLog_ERR(TAG, "not implemented");
770  return E_NOTIMPL;
771 }
772 
773 HRESULT PathCchRemoveFileSpecW(PWSTR pszPath, size_t cchPath)
774 {
775  WLog_ERR(TAG, "not implemented");
776  return E_NOTIMPL;
777 }
778 
779 /*
780  * Path Portability Functions
781  */
782 
787 HRESULT PathCchConvertStyleA(PSTR pszPath, size_t cchPath, unsigned long dwFlags)
788 {
789  if (dwFlags == PATH_STYLE_WINDOWS)
790  {
791  for (size_t index = 0; index < cchPath; index++)
792  {
793  if (pszPath[index] == PATH_SLASH_CHR)
794  pszPath[index] = PATH_BACKSLASH_CHR;
795  }
796  }
797  else if (dwFlags == PATH_STYLE_UNIX)
798  {
799  for (size_t index = 0; index < cchPath; index++)
800  {
801  if (pszPath[index] == PATH_BACKSLASH_CHR)
802  pszPath[index] = PATH_SLASH_CHR;
803  }
804  }
805  else if (dwFlags == PATH_STYLE_NATIVE)
806  {
807 #if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR)
808  /* Unix-style to Windows-style */
809 
810  for (size_t index = 0; index < cchPath; index++)
811  {
812  if (pszPath[index] == PATH_SLASH_CHR)
813  pszPath[index] = PATH_BACKSLASH_CHR;
814  }
815 #elif (PATH_SEPARATOR_CHR == PATH_SLASH_CHR)
816  /* Windows-style to Unix-style */
817 
818  for (size_t index = 0; index < cchPath; index++)
819  {
820  if (pszPath[index] == PATH_BACKSLASH_CHR)
821  pszPath[index] = PATH_SLASH_CHR;
822  }
823 #else
824  /* Unexpected error */
825  return E_FAIL;
826 #endif
827  }
828  else
829  {
830  /* Gangnam style? */
831  return E_FAIL;
832  }
833 
834  return S_OK;
835 }
836 
837 HRESULT PathCchConvertStyleW(PWSTR pszPath, size_t cchPath, unsigned long dwFlags)
838 {
839  if (dwFlags == PATH_STYLE_WINDOWS)
840  {
841  for (size_t index = 0; index < cchPath; index++)
842  {
843  if (pszPath[index] == PATH_SLASH_CHR)
844  pszPath[index] = PATH_BACKSLASH_CHR;
845  }
846  }
847  else if (dwFlags == PATH_STYLE_UNIX)
848  {
849  for (size_t index = 0; index < cchPath; index++)
850  {
851  if (pszPath[index] == PATH_BACKSLASH_CHR)
852  pszPath[index] = PATH_SLASH_CHR;
853  }
854  }
855  else if (dwFlags == PATH_STYLE_NATIVE)
856  {
857 #if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR)
858  {
859  /* Unix-style to Windows-style */
860 
861  for (size_t index = 0; index < cchPath; index++)
862  {
863  if (pszPath[index] == PATH_SLASH_CHR)
864  pszPath[index] = PATH_BACKSLASH_CHR;
865  }
866  }
867 #elif (PATH_SEPARATOR_CHR == PATH_SLASH_CHR)
868  {
869  /* Windows-style to Unix-style */
870 
871  for (size_t index = 0; index < cchPath; index++)
872  {
873  if (pszPath[index] == PATH_BACKSLASH_CHR)
874  pszPath[index] = PATH_SLASH_CHR;
875  }
876  }
877 #else
878  {
879  /* Unexpected error */
880  return E_FAIL;
881  }
882 #endif
883  }
884  else
885  {
886  /* Gangnam style? */
887  return E_FAIL;
888  }
889 
890  return S_OK;
891 }
892 
897 char PathGetSeparatorA(unsigned long dwFlags)
898 {
899  char separator = PATH_SEPARATOR_CHR;
900 
901  if (!dwFlags)
902  dwFlags = PATH_STYLE_NATIVE;
903 
904  if (dwFlags == PATH_STYLE_WINDOWS)
905  separator = PATH_SEPARATOR_CHR;
906  else if (dwFlags == PATH_STYLE_UNIX)
907  separator = PATH_SEPARATOR_CHR;
908  else if (dwFlags == PATH_STYLE_NATIVE)
909  separator = PATH_SEPARATOR_CHR;
910 
911  return separator;
912 }
913 
914 WCHAR PathGetSeparatorW(unsigned long dwFlags)
915 {
916  union
917  {
918  WCHAR w;
919  char c[2];
920  } cnv;
921 
922  cnv.c[0] = PATH_SEPARATOR_CHR;
923  cnv.c[1] = '\0';
924 
925  if (!dwFlags)
926  dwFlags = PATH_STYLE_NATIVE;
927 
928  if (dwFlags == PATH_STYLE_WINDOWS)
929  cnv.c[0] = PATH_SEPARATOR_CHR;
930  else if (dwFlags == PATH_STYLE_UNIX)
931  cnv.c[0] = PATH_SEPARATOR_CHR;
932  else if (dwFlags == PATH_STYLE_NATIVE)
933  cnv.c[0] = PATH_SEPARATOR_CHR;
934 
935  return cnv.w;
936 }
937 
941 static const CHAR SharedLibraryExtensionDllA[] = "dll";
942 static const CHAR SharedLibraryExtensionSoA[] = "so";
943 static const CHAR SharedLibraryExtensionDylibA[] = "dylib";
944 
945 static const CHAR SharedLibraryExtensionDotDllA[] = ".dll";
946 static const CHAR SharedLibraryExtensionDotSoA[] = ".so";
947 static const CHAR SharedLibraryExtensionDotDylibA[] = ".dylib";
948 PCSTR PathGetSharedLibraryExtensionA(unsigned long dwFlags)
949 {
950  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
951  {
952  if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
953  {
954  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
955  return SharedLibraryExtensionDotDllA;
956 
957  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
958  return SharedLibraryExtensionDotSoA;
959 
960  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
961  return SharedLibraryExtensionDotDylibA;
962  }
963  else
964  {
965  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
966  return SharedLibraryExtensionDllA;
967 
968  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
969  return SharedLibraryExtensionSoA;
970 
971  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
972  return SharedLibraryExtensionDylibA;
973  }
974  }
975 
976  if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
977  {
978 #ifdef _WIN32
979  return SharedLibraryExtensionDotDllA;
980 #elif defined(__APPLE__)
981  if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
982  return SharedLibraryExtensionDotSoA;
983  else
984  return SharedLibraryExtensionDotDylibA;
985 #else
986  return SharedLibraryExtensionDotSoA;
987 #endif
988  }
989  else
990  {
991 #ifdef _WIN32
992  return SharedLibraryExtensionDllA;
993 #elif defined(__APPLE__)
994  if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
995  return SharedLibraryExtensionSoA;
996  else
997  return SharedLibraryExtensionDylibA;
998 #else
999  return SharedLibraryExtensionSoA;
1000 #endif
1001  }
1002 
1003  return NULL;
1004 }
1005 
1006 PCWSTR PathGetSharedLibraryExtensionW(unsigned long dwFlags)
1007 {
1008  static WCHAR buffer[6][16] = { 0 };
1009  const WCHAR* SharedLibraryExtensionDotDllW = InitializeConstWCharFromUtf8(
1010  SharedLibraryExtensionDotDllA, buffer[0], ARRAYSIZE(buffer[0]));
1011  const WCHAR* SharedLibraryExtensionDotSoW =
1012  InitializeConstWCharFromUtf8(SharedLibraryExtensionDotSoA, buffer[1], ARRAYSIZE(buffer[1]));
1013  const WCHAR* SharedLibraryExtensionDotDylibW = InitializeConstWCharFromUtf8(
1014  SharedLibraryExtensionDotDylibA, buffer[2], ARRAYSIZE(buffer[2]));
1015  const WCHAR* SharedLibraryExtensionDllW =
1016  InitializeConstWCharFromUtf8(SharedLibraryExtensionDllA, buffer[3], ARRAYSIZE(buffer[3]));
1017  const WCHAR* SharedLibraryExtensionSoW =
1018  InitializeConstWCharFromUtf8(SharedLibraryExtensionSoA, buffer[4], ARRAYSIZE(buffer[4]));
1019  const WCHAR* SharedLibraryExtensionDylibW =
1020  InitializeConstWCharFromUtf8(SharedLibraryExtensionDylibA, buffer[5], ARRAYSIZE(buffer[5]));
1021 
1022  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
1023  {
1024  if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1025  {
1026  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1027  return SharedLibraryExtensionDotDllW;
1028 
1029  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1030  return SharedLibraryExtensionDotSoW;
1031 
1032  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1033  return SharedLibraryExtensionDotDylibW;
1034  }
1035  else
1036  {
1037  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1038  return SharedLibraryExtensionDllW;
1039 
1040  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1041  return SharedLibraryExtensionSoW;
1042 
1043  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1044  return SharedLibraryExtensionDylibW;
1045  }
1046  }
1047 
1048  if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1049  {
1050 #ifdef _WIN32
1051  return SharedLibraryExtensionDotDllW;
1052 #elif defined(__APPLE__)
1053  if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1054  return SharedLibraryExtensionDotSoW;
1055  else
1056  return SharedLibraryExtensionDotDylibW;
1057 #else
1058  return SharedLibraryExtensionDotSoW;
1059 #endif
1060  }
1061  else
1062  {
1063 #ifdef _WIN32
1064  return SharedLibraryExtensionDllW;
1065 #elif defined(__APPLE__)
1066  if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1067  return SharedLibraryExtensionSoW;
1068  else
1069  return SharedLibraryExtensionDylibW;
1070 #else
1071  return SharedLibraryExtensionSoW;
1072 #endif
1073  }
1074 
1075  return NULL;
1076 }
1077 
1078 const char* GetKnownPathIdString(int id)
1079 {
1080  switch (id)
1081  {
1082  case KNOWN_PATH_HOME:
1083  return "KNOWN_PATH_HOME";
1084  case KNOWN_PATH_TEMP:
1085  return "KNOWN_PATH_TEMP";
1086  case KNOWN_PATH_XDG_DATA_HOME:
1087  return "KNOWN_PATH_XDG_DATA_HOME";
1088  case KNOWN_PATH_XDG_CONFIG_HOME:
1089  return "KNOWN_PATH_XDG_CONFIG_HOME";
1090  case KNOWN_PATH_XDG_CACHE_HOME:
1091  return "KNOWN_PATH_XDG_CACHE_HOME";
1092  case KNOWN_PATH_XDG_RUNTIME_DIR:
1093  return "KNOWN_PATH_XDG_RUNTIME_DIR";
1094  case KNOWN_PATH_SYSTEM_CONFIG_HOME:
1095  return "KNOWN_PATH_SYSTEM_CONFIG_HOME";
1096  default:
1097  return "KNOWN_PATH_UNKNOWN_ID";
1098  }
1099 }
1100 
1101 static WCHAR* concat(const WCHAR* path, size_t pathlen, const WCHAR* name, size_t namelen)
1102 {
1103  WCHAR* str = calloc(pathlen + namelen + 1, sizeof(WCHAR));
1104  if (!str)
1105  return NULL;
1106 
1107  _wcsncat(str, path, pathlen);
1108  _wcsncat(str, name, namelen);
1109  return str;
1110 }
1111 
1112 BOOL winpr_RemoveDirectory_RecursiveA(LPCSTR lpPathName)
1113 {
1114  WCHAR* name = ConvertUtf8ToWCharAlloc(lpPathName, NULL);
1115  if (!name)
1116  return FALSE;
1117  const BOOL rc = winpr_RemoveDirectory_RecursiveW(name);
1118  free(name);
1119  return rc;
1120 }
1121 
1122 BOOL winpr_RemoveDirectory_RecursiveW(LPCWSTR lpPathName)
1123 {
1124  BOOL ret = FALSE;
1125 
1126  if (!lpPathName)
1127  return FALSE;
1128 
1129  const size_t pathnamelen = _wcslen(lpPathName);
1130  const size_t path_slash_len = pathnamelen + 3;
1131  WCHAR* path_slash = calloc(pathnamelen + 4, sizeof(WCHAR));
1132  if (!path_slash)
1133  return FALSE;
1134  _wcsncat(path_slash, lpPathName, pathnamelen);
1135 
1136  WCHAR starbuffer[8] = { 0 };
1137  const WCHAR* star = InitializeConstWCharFromUtf8("*", starbuffer, ARRAYSIZE(starbuffer));
1138  const HRESULT hr = NativePathCchAppendW(path_slash, path_slash_len, star);
1139  HANDLE dir = INVALID_HANDLE_VALUE;
1140  if (FAILED(hr))
1141  goto fail;
1142 
1143  WIN32_FIND_DATAW findFileData = { 0 };
1144  dir = FindFirstFileW(path_slash, &findFileData);
1145 
1146  if (dir == INVALID_HANDLE_VALUE)
1147  goto fail;
1148 
1149  ret = TRUE;
1150  path_slash[path_slash_len - 1] = '\0'; /* remove trailing '*' */
1151  do
1152  {
1153  const size_t len = _wcsnlen(findFileData.cFileName, ARRAYSIZE(findFileData.cFileName));
1154 
1155  if ((len == 1 && findFileData.cFileName[0] == '.') ||
1156  (len == 2 && findFileData.cFileName[0] == '.' && findFileData.cFileName[1] == '.'))
1157  {
1158  continue;
1159  }
1160 
1161  WCHAR* fullpath = concat(path_slash, path_slash_len, findFileData.cFileName, len);
1162  if (!fullpath)
1163  goto fail;
1164 
1165  if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1166  ret = winpr_RemoveDirectory_RecursiveW(fullpath);
1167  else
1168  ret = DeleteFileW(fullpath);
1169 
1170  free(fullpath);
1171 
1172  if (!ret)
1173  break;
1174  } while (ret && FindNextFileW(dir, &findFileData) != 0);
1175 
1176  if (ret)
1177  {
1178  if (!RemoveDirectoryW(lpPathName))
1179  ret = FALSE;
1180  }
1181 
1182 fail:
1183  FindClose(dir);
1184  free(path_slash);
1185  return ret;
1186 }
1187 
1188 char* winpr_GetConfigFilePath(BOOL system, const char* filename)
1189 {
1190  eKnownPathTypes id = system ? KNOWN_PATH_SYSTEM_CONFIG_HOME : KNOWN_PATH_XDG_CONFIG_HOME;
1191 
1192 #if defined(WINPR_USE_VENDOR_PRODUCT_CONFIG_DIR)
1193  char* vendor = GetKnownSubPath(id, WINPR_VENDOR_STRING);
1194  if (!vendor)
1195  return NULL;
1196 #if defined(WITH_RESOURCE_VERSIONING)
1197  const char* prod = WINPR_PRODUCT_STRING STR(WINPR_VERSION_MAJOR);
1198 #else
1199  const char* prod = WINPR_PRODUCT_STRING;
1200 #endif
1201  char* base = GetCombinedPath(vendor, prod);
1202  free(vendor);
1203 #else
1204  char* base = GetKnownSubPath(id, "winpr");
1205 #endif
1206 
1207  if (!base)
1208  return NULL;
1209  if (!filename)
1210  return base;
1211 
1212  char* path = GetCombinedPath(base, filename);
1213  free(base);
1214 
1215  return path;
1216 }