Coverage Report

Created: 2026-07-30 07:07

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