FreeRDP
Loading...
Searching...
No Matches
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#include "../utils.h"
31
32#if defined(WITH_RESOURCE_VERSIONING)
33#define STR(x) #x
34#endif
35
36static const char PATH_SLASH_CHR = '/';
37static const char PATH_SLASH_STR[] = "/";
38
39static const char PATH_BACKSLASH_CHR = '\\';
40static const char PATH_BACKSLASH_STR[] = "\\";
41
42#ifdef _WIN32
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"\\";
47#else
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' };
53#else
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' };
58#endif
59#endif
60
61#ifdef _WIN32
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
66#else
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
71#endif
72
73#include "../log.h"
74#define TAG WINPR_TAG("path")
75
76/*
77 * PathCchAddBackslash
78 */
79
80/* Windows-style Paths */
81
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"
86#undef DEFINE_UNICODE
87#undef CUR_PATH_SEPARATOR_CHR
88#undef PATH_CCH_ADD_SEPARATOR
89
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"
94#undef DEFINE_UNICODE
95#undef CUR_PATH_SEPARATOR_CHR
96#undef PATH_CCH_ADD_SEPARATOR
97
98/* Unix-style Paths */
99
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"
104#undef DEFINE_UNICODE
105#undef CUR_PATH_SEPARATOR_CHR
106#undef PATH_CCH_ADD_SEPARATOR
107
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"
112#undef DEFINE_UNICODE
113#undef CUR_PATH_SEPARATOR_CHR
114#undef PATH_CCH_ADD_SEPARATOR
115
116/* Native-style Paths */
117
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"
122#undef DEFINE_UNICODE
123#undef CUR_PATH_SEPARATOR_CHR
124#undef PATH_CCH_ADD_SEPARATOR
125
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"
130#undef DEFINE_UNICODE
131#undef CUR_PATH_SEPARATOR_CHR
132#undef PATH_CCH_ADD_SEPARATOR
133
134/*
135 * PathCchRemoveBackslash
136 */
137
138HRESULT PathCchRemoveBackslashA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
139{
140 WLog_ERR(TAG, "not implemented");
141 return E_NOTIMPL;
142}
143
144HRESULT PathCchRemoveBackslashW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
145{
146 WLog_ERR(TAG, "not implemented");
147 return E_NOTIMPL;
148}
149
150/*
151 * PathCchAddBackslashEx
152 */
153
154/* Windows-style Paths */
155
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"
160#undef DEFINE_UNICODE
161#undef CUR_PATH_SEPARATOR_CHR
162#undef PATH_CCH_ADD_SEPARATOR_EX
163
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"
168#undef DEFINE_UNICODE
169#undef CUR_PATH_SEPARATOR_CHR
170#undef PATH_CCH_ADD_SEPARATOR_EX
171
172/* Unix-style Paths */
173
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"
178#undef DEFINE_UNICODE
179#undef CUR_PATH_SEPARATOR_CHR
180#undef PATH_CCH_ADD_SEPARATOR_EX
181
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"
186#undef DEFINE_UNICODE
187#undef CUR_PATH_SEPARATOR_CHR
188#undef PATH_CCH_ADD_SEPARATOR_EX
189
190/* Native-style Paths */
191
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"
196#undef DEFINE_UNICODE
197#undef CUR_PATH_SEPARATOR_CHR
198#undef PATH_CCH_ADD_SEPARATOR_EX
199
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"
204#undef DEFINE_UNICODE
205#undef CUR_PATH_SEPARATOR_CHR
206#undef PATH_CCH_ADD_SEPARATOR_EX
207
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)
211{
212 WLog_ERR(TAG, "not implemented");
213 return E_NOTIMPL;
214}
215
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)
219{
220 WLog_ERR(TAG, "not implemented");
221 return E_NOTIMPL;
222}
223
224/*
225 * PathCchAddExtension
226 */
227
228/* Windows-style Paths */
229
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"
234#undef DEFINE_UNICODE
235#undef CUR_PATH_SEPARATOR_CHR
236#undef PATH_CCH_ADD_EXTENSION
237
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"
242#undef DEFINE_UNICODE
243#undef CUR_PATH_SEPARATOR_CHR
244#undef PATH_CCH_ADD_EXTENSION
245
246/* Unix-style Paths */
247
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"
252#undef DEFINE_UNICODE
253#undef CUR_PATH_SEPARATOR_CHR
254#undef PATH_CCH_ADD_EXTENSION
255
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"
260#undef DEFINE_UNICODE
261#undef CUR_PATH_SEPARATOR_CHR
262#undef PATH_CCH_ADD_EXTENSION
263
264/* Native-style Paths */
265
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"
270#undef DEFINE_UNICODE
271#undef CUR_PATH_SEPARATOR_CHR
272#undef PATH_CCH_ADD_EXTENSION
273
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"
278#undef DEFINE_UNICODE
279#undef CUR_PATH_SEPARATOR_CHR
280#undef PATH_CCH_ADD_EXTENSION
281
282/*
283 * PathCchAppend
284 */
285
286/* Windows-style Paths */
287
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"
293#undef DEFINE_UNICODE
294#undef CUR_PATH_SEPARATOR_CHR
295#undef CUR_PATH_SEPARATOR_STR
296#undef PATH_CCH_APPEND
297
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"
303#undef DEFINE_UNICODE
304#undef CUR_PATH_SEPARATOR_CHR
305#undef CUR_PATH_SEPARATOR_STR
306#undef PATH_CCH_APPEND
307
308/* Unix-style Paths */
309
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"
315#undef DEFINE_UNICODE
316#undef CUR_PATH_SEPARATOR_CHR
317#undef CUR_PATH_SEPARATOR_STR
318#undef PATH_CCH_APPEND
319
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"
325#undef DEFINE_UNICODE
326#undef CUR_PATH_SEPARATOR_CHR
327#undef CUR_PATH_SEPARATOR_STR
328#undef PATH_CCH_APPEND
329
330/* Native-style Paths */
331
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"
337#undef DEFINE_UNICODE
338#undef CUR_PATH_SEPARATOR_CHR
339#undef CUR_PATH_SEPARATOR_STR
340#undef PATH_CCH_APPEND
341
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"
347#undef DEFINE_UNICODE
348#undef CUR_PATH_SEPARATOR_CHR
349#undef CUR_PATH_SEPARATOR_STR
350#undef PATH_CCH_APPEND
351
352/*
353 * PathCchAppendEx
354 */
355
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)
358{
359 WLog_ERR(TAG, "not implemented");
360 return E_NOTIMPL;
361}
362
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)
365{
366 WLog_ERR(TAG, "not implemented");
367 return E_NOTIMPL;
368}
369
370/*
371 * PathCchCanonicalize
372 */
373
374HRESULT PathCchCanonicalizeA(WINPR_ATTR_UNUSED PSTR pszPathOut, WINPR_ATTR_UNUSED size_t cchPathOut,
375 WINPR_ATTR_UNUSED PCSTR pszPathIn)
376{
377 WLog_ERR(TAG, "not implemented");
378 return E_NOTIMPL;
379}
380
381HRESULT PathCchCanonicalizeW(WINPR_ATTR_UNUSED PWSTR pszPathOut,
382 WINPR_ATTR_UNUSED size_t cchPathOut,
383 WINPR_ATTR_UNUSED PCWSTR pszPathIn)
384{
385 WLog_ERR(TAG, "not implemented");
386 return E_NOTIMPL;
387}
388
389/*
390 * PathCchCanonicalizeEx
391 */
392
393HRESULT PathCchCanonicalizeExA(WINPR_ATTR_UNUSED PSTR pszPathOut,
394 WINPR_ATTR_UNUSED size_t cchPathOut,
395 WINPR_ATTR_UNUSED PCSTR pszPathIn,
396 WINPR_ATTR_UNUSED unsigned long dwFlags)
397{
398 WLog_ERR(TAG, "not implemented");
399 return E_NOTIMPL;
400}
401
402HRESULT PathCchCanonicalizeExW(WINPR_ATTR_UNUSED PWSTR pszPathOut,
403 WINPR_ATTR_UNUSED size_t cchPathOut,
404 WINPR_ATTR_UNUSED PCWSTR pszPathIn,
405 WINPR_ATTR_UNUSED unsigned long dwFlags)
406{
407 WLog_ERR(TAG, "not implemented");
408 return E_NOTIMPL;
409}
410
411/*
412 * PathAllocCanonicalize
413 */
414
415HRESULT PathAllocCanonicalizeA(WINPR_ATTR_UNUSED PCSTR pszPathIn,
416 WINPR_ATTR_UNUSED unsigned long dwFlags,
417 WINPR_ATTR_UNUSED PSTR* ppszPathOut)
418{
419 WLog_ERR(TAG, "not implemented");
420 return E_NOTIMPL;
421}
422
423HRESULT PathAllocCanonicalizeW(WINPR_ATTR_UNUSED PCWSTR pszPathIn,
424 WINPR_ATTR_UNUSED unsigned long dwFlags,
425 WINPR_ATTR_UNUSED PWSTR* ppszPathOut)
426{
427 WLog_ERR(TAG, "not implemented");
428 return E_NOTIMPL;
429}
430
431/*
432 * PathCchCombine
433 */
434
435HRESULT PathCchCombineA(WINPR_ATTR_UNUSED PSTR pszPathOut, WINPR_ATTR_UNUSED size_t cchPathOut,
436 WINPR_ATTR_UNUSED PCSTR pszPathIn, WINPR_ATTR_UNUSED PCSTR pszMore)
437{
438 WLog_ERR(TAG, "not implemented");
439 return E_NOTIMPL;
440}
441
442HRESULT PathCchCombineW(WINPR_ATTR_UNUSED PWSTR pszPathOut, WINPR_ATTR_UNUSED size_t cchPathOut,
443 WINPR_ATTR_UNUSED PCWSTR pszPathIn, WINPR_ATTR_UNUSED PCWSTR pszMore)
444{
445 WLog_ERR(TAG, "not implemented");
446 return E_NOTIMPL;
447}
448
449/*
450 * PathCchCombineEx
451 */
452
453HRESULT PathCchCombineExA(WINPR_ATTR_UNUSED PSTR pszPathOut, WINPR_ATTR_UNUSED size_t cchPathOut,
454 WINPR_ATTR_UNUSED PCSTR pszPathIn, WINPR_ATTR_UNUSED PCSTR pszMore,
455 WINPR_ATTR_UNUSED unsigned long dwFlags)
456{
457 WLog_ERR(TAG, "not implemented");
458 return E_NOTIMPL;
459}
460
461HRESULT PathCchCombineExW(WINPR_ATTR_UNUSED PWSTR pszPathOut, WINPR_ATTR_UNUSED size_t cchPathOut,
462 WINPR_ATTR_UNUSED PCWSTR pszPathIn, WINPR_ATTR_UNUSED PCWSTR pszMore,
463 WINPR_ATTR_UNUSED unsigned long dwFlags)
464{
465 WLog_ERR(TAG, "not implemented");
466 return E_NOTIMPL;
467}
468
469/*
470 * PathAllocCombine
471 */
472
473/* Windows-style Paths */
474
475#define DEFINE_UNICODE FALSE
476#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
477#define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR
478#define PATH_ALLOC_COMBINE PathAllocCombineA
479#include "include/PathAllocCombine.h"
480#undef DEFINE_UNICODE
481#undef CUR_PATH_SEPARATOR_CHR
482#undef CUR_PATH_SEPARATOR_STR
483#undef PATH_ALLOC_COMBINE
484
485#define DEFINE_UNICODE TRUE
486#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR_W
487#define CUR_PATH_SEPARATOR_STR PATH_BACKSLASH_STR_W
488#define PATH_ALLOC_COMBINE PathAllocCombineW
489#include "include/PathAllocCombine.h"
490#undef DEFINE_UNICODE
491#undef CUR_PATH_SEPARATOR_CHR
492#undef CUR_PATH_SEPARATOR_STR
493#undef PATH_ALLOC_COMBINE
494
495/* Unix-style Paths */
496
497#define DEFINE_UNICODE FALSE
498#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
499#define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR
500#define PATH_ALLOC_COMBINE UnixPathAllocCombineA
501#include "include/PathAllocCombine.h"
502#undef DEFINE_UNICODE
503#undef CUR_PATH_SEPARATOR_CHR
504#undef CUR_PATH_SEPARATOR_STR
505#undef PATH_ALLOC_COMBINE
506
507#define DEFINE_UNICODE TRUE
508#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR_W
509#define CUR_PATH_SEPARATOR_STR PATH_SLASH_STR_W
510#define PATH_ALLOC_COMBINE UnixPathAllocCombineW
511#include "include/PathAllocCombine.h"
512#undef DEFINE_UNICODE
513#undef CUR_PATH_SEPARATOR_CHR
514#undef CUR_PATH_SEPARATOR_STR
515#undef PATH_ALLOC_COMBINE
516
517/* Native-style Paths */
518
519#define DEFINE_UNICODE FALSE
520#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
521#define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR
522#define PATH_ALLOC_COMBINE NativePathAllocCombineA
523#include "include/PathAllocCombine.h"
524#undef DEFINE_UNICODE
525#undef CUR_PATH_SEPARATOR_CHR
526#undef CUR_PATH_SEPARATOR_STR
527#undef PATH_ALLOC_COMBINE
528
529#define DEFINE_UNICODE TRUE
530#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR_W
531#define CUR_PATH_SEPARATOR_STR PATH_SEPARATOR_STR_W
532#define PATH_ALLOC_COMBINE NativePathAllocCombineW
533#include "include/PathAllocCombine.h"
534#undef DEFINE_UNICODE
535#undef CUR_PATH_SEPARATOR_CHR
536#undef CUR_PATH_SEPARATOR_STR
537#undef PATH_ALLOC_COMBINE
538
543HRESULT PathCchFindExtensionA(PCSTR pszPath, size_t cchPath, PCSTR* ppszExt)
544{
545 const char* p = (const char*)pszPath;
546
547 if (!pszPath || !cchPath || !ppszExt)
548 return E_INVALIDARG;
549
550 /* find end of string */
551
552 while (*p && --cchPath)
553 {
554 p++;
555 }
556
557 if (*p)
558 {
559 /* pszPath is not null terminated within the cchPath range */
560 return E_INVALIDARG;
561 }
562
563 /* If no extension is found, ppszExt must point to the string's terminating null */
564 *ppszExt = p;
565
566 /* search backwards for '.' */
567
568 while (p > pszPath)
569 {
570 if (*p == '.')
571 {
572 *ppszExt = (PCSTR)p;
573 break;
574 }
575
576 if ((*p == '\\') || (*p == '/') || (*p == ':'))
577 break;
578
579 p--;
580 }
581
582 return S_OK;
583}
584
585HRESULT PathCchFindExtensionW(WINPR_ATTR_UNUSED PCWSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath,
586 WINPR_ATTR_UNUSED PCWSTR* ppszExt)
587{
588 WLog_ERR(TAG, "not implemented");
589 return E_NOTIMPL;
590}
591
596HRESULT PathCchRenameExtensionA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath,
597 WINPR_ATTR_UNUSED PCSTR pszExt)
598{
599 WLog_ERR(TAG, "not implemented");
600 return E_NOTIMPL;
601}
602
603HRESULT PathCchRenameExtensionW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath,
604 WINPR_ATTR_UNUSED PCWSTR pszExt)
605{
606 WLog_ERR(TAG, "not implemented");
607 return E_NOTIMPL;
608}
609
614HRESULT PathCchRemoveExtensionA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
615{
616 WLog_ERR(TAG, "not implemented");
617 return E_NOTIMPL;
618}
619
620HRESULT PathCchRemoveExtensionW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
621{
622 WLog_ERR(TAG, "not implemented");
623 return E_NOTIMPL;
624}
625
630BOOL PathCchIsRootA(WINPR_ATTR_UNUSED PCSTR pszPath)
631{
632 WLog_ERR(TAG, "not implemented");
633 return FALSE;
634}
635
636BOOL PathCchIsRootW(WINPR_ATTR_UNUSED PCWSTR pszPath)
637{
638 WLog_ERR(TAG, "not implemented");
639 return FALSE;
640}
641
646BOOL PathIsUNCExA(PCSTR pszPath, PCSTR* ppszServer)
647{
648 if (!pszPath)
649 return FALSE;
650
651 if ((pszPath[0] == '\\') && (pszPath[1] == '\\'))
652 {
653 *ppszServer = &pszPath[2];
654 return TRUE;
655 }
656
657 return FALSE;
658}
659
660BOOL PathIsUNCExW(PCWSTR pszPath, PCWSTR* ppszServer)
661{
662 if (!pszPath)
663 return FALSE;
664
665 if ((pszPath[0] == '\\') && (pszPath[1] == '\\'))
666 {
667 *ppszServer = &pszPath[2];
668 return TRUE;
669 }
670
671 return FALSE;
672}
673
678HRESULT PathCchSkipRootA(WINPR_ATTR_UNUSED PCSTR pszPath, WINPR_ATTR_UNUSED PCSTR* ppszRootEnd)
679{
680 WLog_ERR(TAG, "not implemented");
681 return E_NOTIMPL;
682}
683
684HRESULT PathCchSkipRootW(WINPR_ATTR_UNUSED PCWSTR pszPath, WINPR_ATTR_UNUSED PCWSTR* ppszRootEnd)
685{
686 WLog_ERR(TAG, "not implemented");
687 return E_NOTIMPL;
688}
689
694HRESULT PathCchStripToRootA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
695{
696 WLog_ERR(TAG, "not implemented");
697 return E_NOTIMPL;
698}
699
700HRESULT PathCchStripToRootW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
701{
702 WLog_ERR(TAG, "not implemented");
703 return E_NOTIMPL;
704}
705
710HRESULT PathCchStripPrefixA(PSTR pszPath, size_t cchPath)
711{
712 BOOL hasPrefix = 0;
713
714 if (!pszPath)
715 return E_INVALIDARG;
716
717 if (cchPath < 4 || cchPath > PATHCCH_MAX_CCH)
718 return E_INVALIDARG;
719
720 hasPrefix = ((pszPath[0] == '\\') && (pszPath[1] == '\\') && (pszPath[2] == '?') &&
721 (pszPath[3] == '\\'));
722
723 if (hasPrefix)
724 {
725 if (cchPath < 6)
726 return S_FALSE;
727
728 if (IsCharAlpha(pszPath[4]) && (pszPath[5] == ':')) /* like C: */
729 {
730 if (memmove_s(pszPath, cchPath, &pszPath[4], cchPath - 4) < 0)
731 return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
732
733 /* since the passed pszPath must not necessarily be null terminated
734 * and we always have enough space after the strip we can always
735 * ensure the null termination of the stripped result
736 */
737 pszPath[cchPath - 4] = 0;
738 return S_OK;
739 }
740 }
741
742 return S_FALSE;
743}
744
745HRESULT PathCchStripPrefixW(PWSTR pszPath, size_t cchPath)
746{
747 BOOL hasPrefix = 0;
748
749 if (!pszPath)
750 return E_INVALIDARG;
751
752 if (cchPath < 4 || cchPath > PATHCCH_MAX_CCH)
753 return E_INVALIDARG;
754
755 hasPrefix = ((pszPath[0] == '\\') && (pszPath[1] == '\\') && (pszPath[2] == '?') &&
756 (pszPath[3] == '\\'));
757
758 if (hasPrefix)
759 {
760 if (cchPath < 6)
761 return S_FALSE;
762
763 const size_t rc = (_wcslen(&pszPath[4]) + 1);
764 if (cchPath < rc)
765 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
766
767 if (IsCharAlphaW(pszPath[4]) && (pszPath[5] == L':')) /* like C: */
768 {
769 if (wmemmove_s(pszPath, cchPath, &pszPath[4], cchPath - 4) < 0)
770 return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
771 /* since the passed pszPath must not necessarily be null terminated
772 * and we always have enough space after the strip we can always
773 * ensure the null termination of the stripped result
774 */
775 pszPath[cchPath - 4] = 0;
776 return S_OK;
777 }
778 }
779
780 return S_FALSE;
781}
782
787HRESULT PathCchRemoveFileSpecA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
788{
789 WLog_ERR(TAG, "not implemented");
790 return E_NOTIMPL;
791}
792
793HRESULT PathCchRemoveFileSpecW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
794{
795 WLog_ERR(TAG, "not implemented");
796 return E_NOTIMPL;
797}
798
799/*
800 * Path Portability Functions
801 */
802
807HRESULT PathCchConvertStyleA(PSTR pszPath, size_t cchPath, unsigned long dwFlags)
808{
809 if (dwFlags == PATH_STYLE_WINDOWS)
810 {
811 for (size_t index = 0; index < cchPath; index++)
812 {
813 if (pszPath[index] == PATH_SLASH_CHR)
814 pszPath[index] = PATH_BACKSLASH_CHR;
815 }
816 }
817 else if (dwFlags == PATH_STYLE_UNIX)
818 {
819 for (size_t index = 0; index < cchPath; index++)
820 {
821 if (pszPath[index] == PATH_BACKSLASH_CHR)
822 pszPath[index] = PATH_SLASH_CHR;
823 }
824 }
825 else if (dwFlags == PATH_STYLE_NATIVE)
826 {
827 if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR)
828 {
829 /* Unix-style to Windows-style */
830
831 for (size_t index = 0; index < cchPath; index++)
832 {
833 if (pszPath[index] == PATH_SLASH_CHR)
834 pszPath[index] = PATH_BACKSLASH_CHR;
835 }
836 }
837 else if (PATH_SEPARATOR_CHR == PATH_SLASH_CHR)
838 {
839 /* Windows-style to Unix-style */
840
841 for (size_t index = 0; index < cchPath; index++)
842 {
843 if (pszPath[index] == PATH_BACKSLASH_CHR)
844 pszPath[index] = PATH_SLASH_CHR;
845 }
846 }
847 else
848 {
849 /* Unexpected error */
850 return E_FAIL;
851 }
852 }
853 else
854 {
855 /* Gangnam style? */
856 return E_FAIL;
857 }
858
859 return S_OK;
860}
861
862HRESULT PathCchConvertStyleW(PWSTR pszPath, size_t cchPath, unsigned long dwFlags)
863{
864 if (dwFlags == PATH_STYLE_WINDOWS)
865 {
866 for (size_t index = 0; index < cchPath; index++)
867 {
868 if (pszPath[index] == PATH_SLASH_CHR_W)
869 pszPath[index] = PATH_BACKSLASH_CHR_W;
870 }
871 }
872 else if (dwFlags == PATH_STYLE_UNIX)
873 {
874 for (size_t index = 0; index < cchPath; index++)
875 {
876 if (pszPath[index] == PATH_BACKSLASH_CHR_W)
877 pszPath[index] = PATH_SLASH_CHR_W;
878 }
879 }
880 else if (dwFlags == PATH_STYLE_NATIVE)
881 {
882 if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR_W)
883 {
884 /* Unix-style to Windows-style */
885
886 for (size_t index = 0; index < cchPath; index++)
887 {
888 if (pszPath[index] == PATH_SLASH_CHR_W)
889 pszPath[index] = PATH_BACKSLASH_CHR_W;
890 }
891 }
892 else if (PATH_SEPARATOR_CHR == PATH_SLASH_CHR_W)
893 {
894 /* Windows-style to Unix-style */
895
896 for (size_t index = 0; index < cchPath; index++)
897 {
898 if (pszPath[index] == PATH_BACKSLASH_CHR_W)
899 pszPath[index] = PATH_SLASH_CHR_W;
900 }
901 }
902 else
903 {
904 /* Unexpected error */
905 return E_FAIL;
906 }
907 }
908 else
909 {
910 /* Gangnam style? */
911 return E_FAIL;
912 }
913
914 return S_OK;
915}
916
921char PathGetSeparatorA(unsigned long dwFlags)
922{
923 char separator = PATH_SEPARATOR_CHR;
924
925 if (!dwFlags)
926 dwFlags = PATH_STYLE_NATIVE;
927
928 if (dwFlags == PATH_STYLE_WINDOWS)
929 separator = PATH_SEPARATOR_CHR;
930 else if (dwFlags == PATH_STYLE_UNIX)
931 separator = PATH_SEPARATOR_CHR;
932 else if (dwFlags == PATH_STYLE_NATIVE)
933 separator = PATH_SEPARATOR_CHR;
934
935 return separator;
936}
937
938WCHAR PathGetSeparatorW(unsigned long dwFlags)
939{
940 union
941 {
942 WCHAR w;
943 char c[2];
944 } cnv;
945
946 cnv.c[0] = PATH_SEPARATOR_CHR;
947 cnv.c[1] = '\0';
948
949 if (!dwFlags)
950 dwFlags = PATH_STYLE_NATIVE;
951
952 if (dwFlags == PATH_STYLE_WINDOWS)
953 cnv.c[0] = PATH_SEPARATOR_CHR;
954 else if (dwFlags == PATH_STYLE_UNIX)
955 cnv.c[0] = PATH_SEPARATOR_CHR;
956 else if (dwFlags == PATH_STYLE_NATIVE)
957 cnv.c[0] = PATH_SEPARATOR_CHR;
958
959 return cnv.w;
960}
961
965static const CHAR SharedLibraryExtensionDllA[] = "dll";
966static const CHAR SharedLibraryExtensionSoA[] = "so";
967static const CHAR SharedLibraryExtensionDylibA[] = "dylib";
968
969static const CHAR SharedLibraryExtensionDotDllA[] = ".dll";
970static const CHAR SharedLibraryExtensionDotSoA[] = ".so";
971static const CHAR SharedLibraryExtensionDotDylibA[] = ".dylib";
972PCSTR PathGetSharedLibraryExtensionA(unsigned long dwFlags)
973{
974 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
975 {
976 if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
977 {
978 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
979 return SharedLibraryExtensionDotDllA;
980
981 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
982 return SharedLibraryExtensionDotSoA;
983
984 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
985 return SharedLibraryExtensionDotDylibA;
986 }
987 else
988 {
989 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
990 return SharedLibraryExtensionDllA;
991
992 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
993 return SharedLibraryExtensionSoA;
994
995 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
996 return SharedLibraryExtensionDylibA;
997 }
998 }
999
1000 if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1001 {
1002#ifdef _WIN32
1003 return SharedLibraryExtensionDotDllA;
1004#elif defined(__APPLE__)
1005 if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1006 return SharedLibraryExtensionDotSoA;
1007 else
1008 return SharedLibraryExtensionDotDylibA;
1009#else
1010 return SharedLibraryExtensionDotSoA;
1011#endif
1012 }
1013 else
1014 {
1015#ifdef _WIN32
1016 return SharedLibraryExtensionDllA;
1017#elif defined(__APPLE__)
1018 if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1019 return SharedLibraryExtensionSoA;
1020 else
1021 return SharedLibraryExtensionDylibA;
1022#else
1023 return SharedLibraryExtensionSoA;
1024#endif
1025 }
1026}
1027
1028PCWSTR PathGetSharedLibraryExtensionW(unsigned long dwFlags)
1029{
1030 static WCHAR buffer[6][16] = WINPR_C_ARRAY_INIT;
1031 const WCHAR* SharedLibraryExtensionDotDllW = InitializeConstWCharFromUtf8(
1032 SharedLibraryExtensionDotDllA, buffer[0], ARRAYSIZE(buffer[0]));
1033 const WCHAR* SharedLibraryExtensionDotSoW =
1034 InitializeConstWCharFromUtf8(SharedLibraryExtensionDotSoA, buffer[1], ARRAYSIZE(buffer[1]));
1035 const WCHAR* SharedLibraryExtensionDotDylibW = InitializeConstWCharFromUtf8(
1036 SharedLibraryExtensionDotDylibA, buffer[2], ARRAYSIZE(buffer[2]));
1037 const WCHAR* SharedLibraryExtensionDllW =
1038 InitializeConstWCharFromUtf8(SharedLibraryExtensionDllA, buffer[3], ARRAYSIZE(buffer[3]));
1039 const WCHAR* SharedLibraryExtensionSoW =
1040 InitializeConstWCharFromUtf8(SharedLibraryExtensionSoA, buffer[4], ARRAYSIZE(buffer[4]));
1041 const WCHAR* SharedLibraryExtensionDylibW =
1042 InitializeConstWCharFromUtf8(SharedLibraryExtensionDylibA, buffer[5], ARRAYSIZE(buffer[5]));
1043
1044 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
1045 {
1046 if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1047 {
1048 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1049 return SharedLibraryExtensionDotDllW;
1050
1051 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1052 return SharedLibraryExtensionDotSoW;
1053
1054 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1055 return SharedLibraryExtensionDotDylibW;
1056 }
1057 else
1058 {
1059 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1060 return SharedLibraryExtensionDllW;
1061
1062 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1063 return SharedLibraryExtensionSoW;
1064
1065 if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1066 return SharedLibraryExtensionDylibW;
1067 }
1068 }
1069
1070 if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1071 {
1072#ifdef _WIN32
1073 return SharedLibraryExtensionDotDllW;
1074#elif defined(__APPLE__)
1075 if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1076 return SharedLibraryExtensionDotSoW;
1077 else
1078 return SharedLibraryExtensionDotDylibW;
1079#else
1080 return SharedLibraryExtensionDotSoW;
1081#endif
1082 }
1083 else
1084 {
1085#ifdef _WIN32
1086 return SharedLibraryExtensionDllW;
1087#elif defined(__APPLE__)
1088 if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1089 return SharedLibraryExtensionSoW;
1090 else
1091 return SharedLibraryExtensionDylibW;
1092#else
1093 return SharedLibraryExtensionSoW;
1094#endif
1095 }
1096}
1097
1098const char* GetKnownPathIdString(int id)
1099{
1100 switch (id)
1101 {
1102 case KNOWN_PATH_HOME:
1103 return "KNOWN_PATH_HOME";
1104 case KNOWN_PATH_TEMP:
1105 return "KNOWN_PATH_TEMP";
1106 case KNOWN_PATH_XDG_DATA_HOME:
1107 return "KNOWN_PATH_XDG_DATA_HOME";
1108 case KNOWN_PATH_XDG_CONFIG_HOME:
1109 return "KNOWN_PATH_XDG_CONFIG_HOME";
1110 case KNOWN_PATH_XDG_CACHE_HOME:
1111 return "KNOWN_PATH_XDG_CACHE_HOME";
1112 case KNOWN_PATH_XDG_RUNTIME_DIR:
1113 return "KNOWN_PATH_XDG_RUNTIME_DIR";
1114 case KNOWN_PATH_SYSTEM_CONFIG_HOME:
1115 return "KNOWN_PATH_SYSTEM_CONFIG_HOME";
1116 default:
1117 return "KNOWN_PATH_UNKNOWN_ID";
1118 }
1119}
1120
1121static char* concat(const char* path, size_t pathlen, const char* name, size_t namelen)
1122{
1123 const size_t strsize = pathlen + namelen + 2;
1124 char* str = calloc(strsize, sizeof(char));
1125 if (!str)
1126 return nullptr;
1127
1128 winpr_str_append(path, str, strsize, "");
1129 winpr_str_append(name, str, strsize, "");
1130 return str;
1131}
1132
1133BOOL winpr_RemoveDirectory_RecursiveA(LPCSTR lpPathName)
1134{
1135 BOOL ret = FALSE;
1136
1137 if (!lpPathName)
1138 return FALSE;
1139
1140 const size_t pathnamelen = strlen(lpPathName);
1141 const size_t path_slash_len = pathnamelen + 3;
1142 char* path_slash = calloc(pathnamelen + 4, sizeof(char));
1143 if (!path_slash)
1144 return FALSE;
1145 strncat(path_slash, lpPathName, pathnamelen);
1146
1147 const char star[] = "*";
1148 const HRESULT hr = NativePathCchAppendA(path_slash, path_slash_len, star);
1149 HANDLE dir = INVALID_HANDLE_VALUE;
1150 if (FAILED(hr))
1151 goto fail;
1152
1153 {
1154 WIN32_FIND_DATAA findFileData = WINPR_C_ARRAY_INIT;
1155 dir = FindFirstFileA(path_slash, &findFileData);
1156
1157 if (dir == INVALID_HANDLE_VALUE)
1158 goto fail;
1159
1160 ret = TRUE;
1161 path_slash[path_slash_len - 1] = '\0'; /* remove trailing '*' */
1162 do
1163 {
1164 const size_t len = strnlen(findFileData.cFileName, ARRAYSIZE(findFileData.cFileName));
1165
1166 if ((len == 1 && findFileData.cFileName[0] == '.') ||
1167 (len == 2 && findFileData.cFileName[0] == '.' && findFileData.cFileName[1] == '.'))
1168 {
1169 continue;
1170 }
1171
1172 char* fullpath = concat(path_slash, path_slash_len, findFileData.cFileName, len);
1173 if (!fullpath)
1174 goto fail;
1175
1176 if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1177 ret = winpr_RemoveDirectory_RecursiveA(fullpath);
1178 else
1179 {
1180 WINPR_PRAGMA_DIAG_PUSH
1181 WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
1182 ret = DeleteFileA(fullpath);
1183 WINPR_PRAGMA_DIAG_POP
1184 }
1185
1186 free(fullpath);
1187
1188 if (!ret)
1189 break;
1190 } while (ret && FindNextFileA(dir, &findFileData) != 0);
1191 }
1192
1193 if (ret)
1194 {
1195 WINPR_PRAGMA_DIAG_PUSH
1196 WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
1197 if (!RemoveDirectoryA(lpPathName))
1198 ret = FALSE;
1199 WINPR_PRAGMA_DIAG_POP
1200 }
1201
1202fail:
1203 FindClose(dir);
1204 free(path_slash);
1205 return ret;
1206}
1207
1208BOOL winpr_RemoveDirectory_RecursiveW(LPCWSTR lpPathName)
1209{
1210 char* name = ConvertWCharToUtf8Alloc(lpPathName, nullptr);
1211 if (!name)
1212 return FALSE;
1213 const BOOL rc = winpr_RemoveDirectory_RecursiveA(name);
1214 free(name);
1215 return rc;
1216}
1217
1218char* winpr_GetConfigFilePathVA(BOOL system, WINPR_FORMAT_ARG const char* filename, va_list ap)
1219{
1220 eKnownPathTypes id = system ? KNOWN_PATH_SYSTEM_CONFIG_HOME : KNOWN_PATH_XDG_CONFIG_HOME;
1221 const char* vendor = winpr_getApplicationDetailsVendor();
1222 const char* product = winpr_getApplicationDetailsProduct();
1223 const SSIZE_T version = winpr_getApplicationDetailsVersion();
1224
1225 if (!vendor || !product)
1226 return nullptr;
1227
1228 char* config = GetKnownSubPathV(id, "%s", vendor);
1229 if (!config)
1230 return nullptr;
1231
1232 char* base = nullptr;
1233 if (version < 0)
1234 base = GetCombinedPathV(config, "%s", product);
1235 else
1236 base = GetCombinedPathV(config, "%s%" PRIdz, product, version);
1237 free(config);
1238
1239 if (!base)
1240 return nullptr;
1241 char* path = GetCombinedPathVA(base, filename, ap);
1242 free(base);
1243
1244 return path;
1245}
1246
1247char* winpr_GetConfigFilePath(BOOL system, const char* filename)
1248{
1249 if (!filename)
1250 return winpr_GetConfigFilePathV(system, "%s", "");
1251 return winpr_GetConfigFilePathV(system, "%s", filename);
1252}
1253
1254char* winpr_GetConfigFilePathV(BOOL system, const char* filename, ...)
1255{
1256 va_list ap = WINPR_C_ARRAY_INIT;
1257 va_start(ap, filename);
1258 char* str = winpr_GetConfigFilePathVA(system, filename, ap);
1259 va_end(ap);
1260 return str;
1261}