Coverage Report

Created: 2026-02-26 06:50

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
#if defined(WITH_RESOURCE_VERSIONING)
33
#define STR(x) #x
34
#endif
35
36
static const char PATH_SLASH_CHR = '/';
37
static const char PATH_SLASH_STR[] = "/";
38
39
static const char PATH_BACKSLASH_CHR = '\\';
40
static const char PATH_BACKSLASH_STR[] = "\\";
41
42
#ifdef _WIN32
43
static const WCHAR PATH_SLASH_CHR_W = L'/';
44
static const WCHAR PATH_BACKSLASH_CHR_W = L'\\';
45
static const WCHAR PATH_SLASH_STR_W[] = L"/";
46
static const WCHAR PATH_BACKSLASH_STR_W[] = L"\\";
47
#else
48
#if defined(__BIG_ENDIAN__)
49
static const WCHAR PATH_SLASH_CHR_W = 0x2f00;
50
static const WCHAR PATH_BACKSLASH_CHR_W = 0x5c00;
51
static const WCHAR PATH_SLASH_STR_W[] = { 0x2f00, '\0' };
52
static const WCHAR PATH_BACKSLASH_STR_W[] = { 0x5c00, '\0' };
53
#else
54
static const WCHAR PATH_SLASH_CHR_W = '/';
55
static const WCHAR PATH_BACKSLASH_CHR_W = '\\';
56
static const WCHAR PATH_SLASH_STR_W[] = { '/', '\0' };
57
static 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
198k
#define PATH_SEPARATOR_CHR PATH_SLASH_CHR
68
33.0k
#define PATH_SEPARATOR_STR PATH_SLASH_STR
69
0
#define PATH_SEPARATOR_CHR_W PATH_SLASH_CHR_W
70
0
#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
0
#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
0
#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
0
#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
0
#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
0
#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
0
#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
138
HRESULT PathCchRemoveBackslashA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
139
0
{
140
0
  WLog_ERR(TAG, "not implemented");
141
0
  return E_NOTIMPL;
142
0
}
143
144
HRESULT PathCchRemoveBackslashW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
145
0
{
146
0
  WLog_ERR(TAG, "not implemented");
147
0
  return E_NOTIMPL;
148
0
}
149
150
/*
151
 * PathCchAddBackslashEx
152
 */
153
154
/* Windows-style Paths */
155
156
#define DEFINE_UNICODE FALSE
157
0
#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
0
#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
0
#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
0
#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
0
#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
0
#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
208
HRESULT 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
0
{
212
0
  WLog_ERR(TAG, "not implemented");
213
0
  return E_NOTIMPL;
214
0
}
215
216
HRESULT 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
0
{
220
0
  WLog_ERR(TAG, "not implemented");
221
0
  return E_NOTIMPL;
222
0
}
223
224
/*
225
 * PathCchAddExtension
226
 */
227
228
/* Windows-style Paths */
229
230
#define DEFINE_UNICODE FALSE
231
0
#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
0
#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
0
#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
0
#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
0
#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
0
#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
0
#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
290
0
#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
0
#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR_W
300
0
#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
0
#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
312
0
#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
0
#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR_W
322
0
#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
66.1k
#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
334
33.0k
#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
0
#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR_W
344
0
#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
356
HRESULT 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
0
{
359
0
  WLog_ERR(TAG, "not implemented");
360
0
  return E_NOTIMPL;
361
0
}
362
363
HRESULT 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
0
{
366
0
  WLog_ERR(TAG, "not implemented");
367
0
  return E_NOTIMPL;
368
0
}
369
370
/*
371
 * PathCchCanonicalize
372
 */
373
374
HRESULT PathCchCanonicalizeA(WINPR_ATTR_UNUSED PSTR pszPathOut, WINPR_ATTR_UNUSED size_t cchPathOut,
375
                             WINPR_ATTR_UNUSED PCSTR pszPathIn)
376
0
{
377
0
  WLog_ERR(TAG, "not implemented");
378
0
  return E_NOTIMPL;
379
0
}
380
381
HRESULT PathCchCanonicalizeW(WINPR_ATTR_UNUSED PWSTR pszPathOut,
382
                             WINPR_ATTR_UNUSED size_t cchPathOut,
383
                             WINPR_ATTR_UNUSED PCWSTR pszPathIn)
384
0
{
385
0
  WLog_ERR(TAG, "not implemented");
386
0
  return E_NOTIMPL;
387
0
}
388
389
/*
390
 * PathCchCanonicalizeEx
391
 */
392
393
HRESULT 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
0
{
398
0
  WLog_ERR(TAG, "not implemented");
399
0
  return E_NOTIMPL;
400
0
}
401
402
HRESULT 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
0
{
407
0
  WLog_ERR(TAG, "not implemented");
408
0
  return E_NOTIMPL;
409
0
}
410
411
/*
412
 * PathAllocCanonicalize
413
 */
414
415
HRESULT PathAllocCanonicalizeA(WINPR_ATTR_UNUSED PCSTR pszPathIn,
416
                               WINPR_ATTR_UNUSED unsigned long dwFlags,
417
                               WINPR_ATTR_UNUSED PSTR* ppszPathOut)
418
0
{
419
0
  WLog_ERR(TAG, "not implemented");
420
0
  return E_NOTIMPL;
421
0
}
422
423
HRESULT PathAllocCanonicalizeW(WINPR_ATTR_UNUSED PCWSTR pszPathIn,
424
                               WINPR_ATTR_UNUSED unsigned long dwFlags,
425
                               WINPR_ATTR_UNUSED PWSTR* ppszPathOut)
426
0
{
427
0
  WLog_ERR(TAG, "not implemented");
428
0
  return E_NOTIMPL;
429
0
}
430
431
/*
432
 * PathCchCombine
433
 */
434
435
HRESULT PathCchCombineA(WINPR_ATTR_UNUSED PSTR pszPathOut, WINPR_ATTR_UNUSED size_t cchPathOut,
436
                        WINPR_ATTR_UNUSED PCSTR pszPathIn, WINPR_ATTR_UNUSED PCSTR pszMore)
437
0
{
438
0
  WLog_ERR(TAG, "not implemented");
439
0
  return E_NOTIMPL;
440
0
}
441
442
HRESULT PathCchCombineW(WINPR_ATTR_UNUSED PWSTR pszPathOut, WINPR_ATTR_UNUSED size_t cchPathOut,
443
                        WINPR_ATTR_UNUSED PCWSTR pszPathIn, WINPR_ATTR_UNUSED PCWSTR pszMore)
444
0
{
445
0
  WLog_ERR(TAG, "not implemented");
446
0
  return E_NOTIMPL;
447
0
}
448
449
/*
450
 * PathCchCombineEx
451
 */
452
453
HRESULT 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
0
{
457
0
  WLog_ERR(TAG, "not implemented");
458
0
  return E_NOTIMPL;
459
0
}
460
461
HRESULT 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
0
{
465
0
  WLog_ERR(TAG, "not implemented");
466
0
  return E_NOTIMPL;
467
0
}
468
469
/*
470
 * PathAllocCombine
471
 */
472
473
/* Windows-style Paths */
474
475
#define DEFINE_UNICODE FALSE
476
0
#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR
477
0
#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
0
#define CUR_PATH_SEPARATOR_CHR PATH_BACKSLASH_CHR_W
487
0
#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
0
#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR
499
0
#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
0
#define CUR_PATH_SEPARATOR_CHR PATH_SLASH_CHR_W
509
0
#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
0
#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
521
0
#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
0
#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR_W
531
0
#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
539
/**
540
 * PathCchFindExtension
541
 */
542
543
HRESULT PathCchFindExtensionA(PCSTR pszPath, size_t cchPath, PCSTR* ppszExt)
544
0
{
545
0
  const char* p = (const char*)pszPath;
546
547
0
  if (!pszPath || !cchPath || !ppszExt)
548
0
    return E_INVALIDARG;
549
550
  /* find end of string */
551
552
0
  while (*p && --cchPath)
553
0
  {
554
0
    p++;
555
0
  }
556
557
0
  if (*p)
558
0
  {
559
    /* pszPath is not null terminated within the cchPath range */
560
0
    return E_INVALIDARG;
561
0
  }
562
563
  /* If no extension is found, ppszExt must point to the string's terminating null */
564
0
  *ppszExt = p;
565
566
  /* search backwards for '.' */
567
568
0
  while (p > pszPath)
569
0
  {
570
0
    if (*p == '.')
571
0
    {
572
0
      *ppszExt = (PCSTR)p;
573
0
      break;
574
0
    }
575
576
0
    if ((*p == '\\') || (*p == '/') || (*p == ':'))
577
0
      break;
578
579
0
    p--;
580
0
  }
581
582
0
  return S_OK;
583
0
}
584
585
HRESULT PathCchFindExtensionW(WINPR_ATTR_UNUSED PCWSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath,
586
                              WINPR_ATTR_UNUSED PCWSTR* ppszExt)
587
0
{
588
0
  WLog_ERR(TAG, "not implemented");
589
0
  return E_NOTIMPL;
590
0
}
591
592
/**
593
 * PathCchRenameExtension
594
 */
595
596
HRESULT PathCchRenameExtensionA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath,
597
                                WINPR_ATTR_UNUSED PCSTR pszExt)
598
0
{
599
0
  WLog_ERR(TAG, "not implemented");
600
0
  return E_NOTIMPL;
601
0
}
602
603
HRESULT PathCchRenameExtensionW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath,
604
                                WINPR_ATTR_UNUSED PCWSTR pszExt)
605
0
{
606
0
  WLog_ERR(TAG, "not implemented");
607
0
  return E_NOTIMPL;
608
0
}
609
610
/**
611
 * PathCchRemoveExtension
612
 */
613
614
HRESULT PathCchRemoveExtensionA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
615
0
{
616
0
  WLog_ERR(TAG, "not implemented");
617
0
  return E_NOTIMPL;
618
0
}
619
620
HRESULT PathCchRemoveExtensionW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
621
0
{
622
0
  WLog_ERR(TAG, "not implemented");
623
0
  return E_NOTIMPL;
624
0
}
625
626
/**
627
 * PathCchIsRoot
628
 */
629
630
BOOL PathCchIsRootA(WINPR_ATTR_UNUSED PCSTR pszPath)
631
0
{
632
0
  WLog_ERR(TAG, "not implemented");
633
0
  return FALSE;
634
0
}
635
636
BOOL PathCchIsRootW(WINPR_ATTR_UNUSED PCWSTR pszPath)
637
0
{
638
0
  WLog_ERR(TAG, "not implemented");
639
0
  return FALSE;
640
0
}
641
642
/**
643
 * PathIsUNCEx
644
 */
645
646
BOOL PathIsUNCExA(PCSTR pszPath, PCSTR* ppszServer)
647
0
{
648
0
  if (!pszPath)
649
0
    return FALSE;
650
651
0
  if ((pszPath[0] == '\\') && (pszPath[1] == '\\'))
652
0
  {
653
0
    *ppszServer = &pszPath[2];
654
0
    return TRUE;
655
0
  }
656
657
0
  return FALSE;
658
0
}
659
660
BOOL PathIsUNCExW(PCWSTR pszPath, PCWSTR* ppszServer)
661
0
{
662
0
  if (!pszPath)
663
0
    return FALSE;
664
665
0
  if ((pszPath[0] == '\\') && (pszPath[1] == '\\'))
666
0
  {
667
0
    *ppszServer = &pszPath[2];
668
0
    return TRUE;
669
0
  }
670
671
0
  return FALSE;
672
0
}
673
674
/**
675
 * PathCchSkipRoot
676
 */
677
678
HRESULT PathCchSkipRootA(WINPR_ATTR_UNUSED PCSTR pszPath, WINPR_ATTR_UNUSED PCSTR* ppszRootEnd)
679
0
{
680
0
  WLog_ERR(TAG, "not implemented");
681
0
  return E_NOTIMPL;
682
0
}
683
684
HRESULT PathCchSkipRootW(WINPR_ATTR_UNUSED PCWSTR pszPath, WINPR_ATTR_UNUSED PCWSTR* ppszRootEnd)
685
0
{
686
0
  WLog_ERR(TAG, "not implemented");
687
0
  return E_NOTIMPL;
688
0
}
689
690
/**
691
 * PathCchStripToRoot
692
 */
693
694
HRESULT PathCchStripToRootA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
695
0
{
696
0
  WLog_ERR(TAG, "not implemented");
697
0
  return E_NOTIMPL;
698
0
}
699
700
HRESULT PathCchStripToRootW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
701
0
{
702
0
  WLog_ERR(TAG, "not implemented");
703
0
  return E_NOTIMPL;
704
0
}
705
706
/**
707
 * PathCchStripPrefix
708
 */
709
710
HRESULT PathCchStripPrefixA(PSTR pszPath, size_t cchPath)
711
0
{
712
0
  BOOL hasPrefix = 0;
713
714
0
  if (!pszPath)
715
0
    return E_INVALIDARG;
716
717
0
  if (cchPath < 4 || cchPath > PATHCCH_MAX_CCH)
718
0
    return E_INVALIDARG;
719
720
0
  hasPrefix = ((pszPath[0] == '\\') && (pszPath[1] == '\\') && (pszPath[2] == '?') &&
721
0
               (pszPath[3] == '\\'))
722
0
                  ? TRUE
723
0
                  : FALSE;
724
725
0
  if (hasPrefix)
726
0
  {
727
0
    if (cchPath < 6)
728
0
      return S_FALSE;
729
730
0
    if (IsCharAlpha(pszPath[4]) && (pszPath[5] == ':')) /* like C: */
731
0
    {
732
0
      memmove_s(pszPath, cchPath, &pszPath[4], cchPath - 4);
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
0
      pszPath[cchPath - 4] = 0;
738
0
      return S_OK;
739
0
    }
740
0
  }
741
742
0
  return S_FALSE;
743
0
}
744
745
HRESULT PathCchStripPrefixW(PWSTR pszPath, size_t cchPath)
746
0
{
747
0
  BOOL hasPrefix = 0;
748
749
0
  if (!pszPath)
750
0
    return E_INVALIDARG;
751
752
0
  if (cchPath < 4 || cchPath > PATHCCH_MAX_CCH)
753
0
    return E_INVALIDARG;
754
755
0
  hasPrefix = ((pszPath[0] == '\\') && (pszPath[1] == '\\') && (pszPath[2] == '?') &&
756
0
               (pszPath[3] == '\\'))
757
0
                  ? TRUE
758
0
                  : FALSE;
759
760
0
  if (hasPrefix)
761
0
  {
762
0
    if (cchPath < 6)
763
0
      return S_FALSE;
764
765
0
    const size_t rc = (_wcslen(&pszPath[4]) + 1);
766
0
    if (cchPath < rc)
767
0
      return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
768
769
0
    if (IsCharAlphaW(pszPath[4]) && (pszPath[5] == L':')) /* like C: */
770
0
    {
771
0
      wmemmove_s(pszPath, cchPath, &pszPath[4], cchPath - 4);
772
      /* since the passed pszPath must not necessarily be null terminated
773
       * and we always have enough space after the strip we can always
774
       * ensure the null termination of the stripped result
775
       */
776
0
      pszPath[cchPath - 4] = 0;
777
0
      return S_OK;
778
0
    }
779
0
  }
780
781
0
  return S_FALSE;
782
0
}
783
784
/**
785
 * PathCchRemoveFileSpec
786
 */
787
788
HRESULT PathCchRemoveFileSpecA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
789
0
{
790
0
  WLog_ERR(TAG, "not implemented");
791
0
  return E_NOTIMPL;
792
0
}
793
794
HRESULT PathCchRemoveFileSpecW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
795
0
{
796
0
  WLog_ERR(TAG, "not implemented");
797
0
  return E_NOTIMPL;
798
0
}
799
800
/*
801
 * Path Portability Functions
802
 */
803
804
/**
805
 * PathCchConvertStyle
806
 */
807
808
HRESULT PathCchConvertStyleA(PSTR pszPath, size_t cchPath, unsigned long dwFlags)
809
66.1k
{
810
66.1k
  if (dwFlags == PATH_STYLE_WINDOWS)
811
0
  {
812
0
    for (size_t index = 0; index < cchPath; index++)
813
0
    {
814
0
      if (pszPath[index] == PATH_SLASH_CHR)
815
0
        pszPath[index] = PATH_BACKSLASH_CHR;
816
0
    }
817
0
  }
818
66.1k
  else if (dwFlags == PATH_STYLE_UNIX)
819
0
  {
820
0
    for (size_t index = 0; index < cchPath; index++)
821
0
    {
822
0
      if (pszPath[index] == PATH_BACKSLASH_CHR)
823
0
        pszPath[index] = PATH_SLASH_CHR;
824
0
    }
825
0
  }
826
66.1k
  else if (dwFlags == PATH_STYLE_NATIVE)
827
66.1k
  {
828
66.1k
    if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR)
829
0
    {
830
      /* Unix-style to Windows-style */
831
832
0
      for (size_t index = 0; index < cchPath; index++)
833
0
      {
834
0
        if (pszPath[index] == PATH_SLASH_CHR)
835
0
          pszPath[index] = PATH_BACKSLASH_CHR;
836
0
      }
837
0
    }
838
66.1k
    else if (PATH_SEPARATOR_CHR == PATH_SLASH_CHR)
839
66.1k
    {
840
      /* Windows-style to Unix-style */
841
842
1.03M
      for (size_t index = 0; index < cchPath; index++)
843
969k
      {
844
969k
        if (pszPath[index] == PATH_BACKSLASH_CHR)
845
0
          pszPath[index] = PATH_SLASH_CHR;
846
969k
      }
847
66.1k
    }
848
0
    else
849
0
    {
850
      /* Unexpected error */
851
0
      return E_FAIL;
852
0
    }
853
66.1k
  }
854
0
  else
855
0
  {
856
    /* Gangnam style? */
857
0
    return E_FAIL;
858
0
  }
859
860
66.1k
  return S_OK;
861
66.1k
}
862
863
HRESULT PathCchConvertStyleW(PWSTR pszPath, size_t cchPath, unsigned long dwFlags)
864
0
{
865
0
  if (dwFlags == PATH_STYLE_WINDOWS)
866
0
  {
867
0
    for (size_t index = 0; index < cchPath; index++)
868
0
    {
869
0
      if (pszPath[index] == PATH_SLASH_CHR_W)
870
0
        pszPath[index] = PATH_BACKSLASH_CHR_W;
871
0
    }
872
0
  }
873
0
  else if (dwFlags == PATH_STYLE_UNIX)
874
0
  {
875
0
    for (size_t index = 0; index < cchPath; index++)
876
0
    {
877
0
      if (pszPath[index] == PATH_BACKSLASH_CHR_W)
878
0
        pszPath[index] = PATH_SLASH_CHR_W;
879
0
    }
880
0
  }
881
0
  else if (dwFlags == PATH_STYLE_NATIVE)
882
0
  {
883
0
    if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR_W)
884
0
    {
885
      /* Unix-style to Windows-style */
886
887
0
      for (size_t index = 0; index < cchPath; index++)
888
0
      {
889
0
        if (pszPath[index] == PATH_SLASH_CHR_W)
890
0
          pszPath[index] = PATH_BACKSLASH_CHR_W;
891
0
      }
892
0
    }
893
0
    else if (PATH_SEPARATOR_CHR == PATH_SLASH_CHR_W)
894
0
    {
895
      /* Windows-style to Unix-style */
896
897
0
      for (size_t index = 0; index < cchPath; index++)
898
0
      {
899
0
        if (pszPath[index] == PATH_BACKSLASH_CHR_W)
900
0
          pszPath[index] = PATH_SLASH_CHR_W;
901
0
      }
902
0
    }
903
0
    else
904
0
    {
905
      /* Unexpected error */
906
0
      return E_FAIL;
907
0
    }
908
0
  }
909
0
  else
910
0
  {
911
    /* Gangnam style? */
912
0
    return E_FAIL;
913
0
  }
914
915
0
  return S_OK;
916
0
}
917
918
/**
919
 * PathGetSeparator
920
 */
921
922
char PathGetSeparatorA(unsigned long dwFlags)
923
0
{
924
0
  char separator = PATH_SEPARATOR_CHR;
925
926
0
  if (!dwFlags)
927
0
    dwFlags = PATH_STYLE_NATIVE;
928
929
0
  if (dwFlags == PATH_STYLE_WINDOWS)
930
0
    separator = PATH_SEPARATOR_CHR;
931
0
  else if (dwFlags == PATH_STYLE_UNIX)
932
0
    separator = PATH_SEPARATOR_CHR;
933
0
  else if (dwFlags == PATH_STYLE_NATIVE)
934
0
    separator = PATH_SEPARATOR_CHR;
935
936
0
  return separator;
937
0
}
938
939
WCHAR PathGetSeparatorW(unsigned long dwFlags)
940
0
{
941
0
  union
942
0
  {
943
0
    WCHAR w;
944
0
    char c[2];
945
0
  } cnv;
946
947
0
  cnv.c[0] = PATH_SEPARATOR_CHR;
948
0
  cnv.c[1] = '\0';
949
950
0
  if (!dwFlags)
951
0
    dwFlags = PATH_STYLE_NATIVE;
952
953
0
  if (dwFlags == PATH_STYLE_WINDOWS)
954
0
    cnv.c[0] = PATH_SEPARATOR_CHR;
955
0
  else if (dwFlags == PATH_STYLE_UNIX)
956
0
    cnv.c[0] = PATH_SEPARATOR_CHR;
957
0
  else if (dwFlags == PATH_STYLE_NATIVE)
958
0
    cnv.c[0] = PATH_SEPARATOR_CHR;
959
960
0
  return cnv.w;
961
0
}
962
963
/**
964
 * PathGetSharedLibraryExtension
965
 */
966
static const CHAR SharedLibraryExtensionDllA[] = "dll";
967
static const CHAR SharedLibraryExtensionSoA[] = "so";
968
static const CHAR SharedLibraryExtensionDylibA[] = "dylib";
969
970
static const CHAR SharedLibraryExtensionDotDllA[] = ".dll";
971
static const CHAR SharedLibraryExtensionDotSoA[] = ".so";
972
static const CHAR SharedLibraryExtensionDotDylibA[] = ".dylib";
973
PCSTR PathGetSharedLibraryExtensionA(unsigned long dwFlags)
974
0
{
975
0
  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
976
0
  {
977
0
    if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
978
0
    {
979
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
980
0
        return SharedLibraryExtensionDotDllA;
981
982
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
983
0
        return SharedLibraryExtensionDotSoA;
984
985
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
986
0
        return SharedLibraryExtensionDotDylibA;
987
0
    }
988
0
    else
989
0
    {
990
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
991
0
        return SharedLibraryExtensionDllA;
992
993
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
994
0
        return SharedLibraryExtensionSoA;
995
996
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
997
0
        return SharedLibraryExtensionDylibA;
998
0
    }
999
0
  }
1000
1001
0
  if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1002
0
  {
1003
#ifdef _WIN32
1004
    return SharedLibraryExtensionDotDllA;
1005
#elif defined(__APPLE__)
1006
    if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1007
      return SharedLibraryExtensionDotSoA;
1008
    else
1009
      return SharedLibraryExtensionDotDylibA;
1010
#else
1011
0
    return SharedLibraryExtensionDotSoA;
1012
0
#endif
1013
0
  }
1014
0
  else
1015
0
  {
1016
#ifdef _WIN32
1017
    return SharedLibraryExtensionDllA;
1018
#elif defined(__APPLE__)
1019
    if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1020
      return SharedLibraryExtensionSoA;
1021
    else
1022
      return SharedLibraryExtensionDylibA;
1023
#else
1024
0
    return SharedLibraryExtensionSoA;
1025
0
#endif
1026
0
  }
1027
1028
0
  return NULL;
1029
0
}
1030
1031
PCWSTR PathGetSharedLibraryExtensionW(unsigned long dwFlags)
1032
0
{
1033
0
  static WCHAR buffer[6][16] = WINPR_C_ARRAY_INIT;
1034
0
  const WCHAR* SharedLibraryExtensionDotDllW = InitializeConstWCharFromUtf8(
1035
0
      SharedLibraryExtensionDotDllA, buffer[0], ARRAYSIZE(buffer[0]));
1036
0
  const WCHAR* SharedLibraryExtensionDotSoW =
1037
0
      InitializeConstWCharFromUtf8(SharedLibraryExtensionDotSoA, buffer[1], ARRAYSIZE(buffer[1]));
1038
0
  const WCHAR* SharedLibraryExtensionDotDylibW = InitializeConstWCharFromUtf8(
1039
0
      SharedLibraryExtensionDotDylibA, buffer[2], ARRAYSIZE(buffer[2]));
1040
0
  const WCHAR* SharedLibraryExtensionDllW =
1041
0
      InitializeConstWCharFromUtf8(SharedLibraryExtensionDllA, buffer[3], ARRAYSIZE(buffer[3]));
1042
0
  const WCHAR* SharedLibraryExtensionSoW =
1043
0
      InitializeConstWCharFromUtf8(SharedLibraryExtensionSoA, buffer[4], ARRAYSIZE(buffer[4]));
1044
0
  const WCHAR* SharedLibraryExtensionDylibW =
1045
0
      InitializeConstWCharFromUtf8(SharedLibraryExtensionDylibA, buffer[5], ARRAYSIZE(buffer[5]));
1046
1047
0
  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
1048
0
  {
1049
0
    if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1050
0
    {
1051
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1052
0
        return SharedLibraryExtensionDotDllW;
1053
1054
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1055
0
        return SharedLibraryExtensionDotSoW;
1056
1057
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1058
0
        return SharedLibraryExtensionDotDylibW;
1059
0
    }
1060
0
    else
1061
0
    {
1062
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1063
0
        return SharedLibraryExtensionDllW;
1064
1065
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1066
0
        return SharedLibraryExtensionSoW;
1067
1068
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1069
0
        return SharedLibraryExtensionDylibW;
1070
0
    }
1071
0
  }
1072
1073
0
  if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1074
0
  {
1075
#ifdef _WIN32
1076
    return SharedLibraryExtensionDotDllW;
1077
#elif defined(__APPLE__)
1078
    if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1079
      return SharedLibraryExtensionDotSoW;
1080
    else
1081
      return SharedLibraryExtensionDotDylibW;
1082
#else
1083
0
    return SharedLibraryExtensionDotSoW;
1084
0
#endif
1085
0
  }
1086
0
  else
1087
0
  {
1088
#ifdef _WIN32
1089
    return SharedLibraryExtensionDllW;
1090
#elif defined(__APPLE__)
1091
    if (dwFlags & PATH_SHARED_LIB_EXT_APPLE_SO)
1092
      return SharedLibraryExtensionSoW;
1093
    else
1094
      return SharedLibraryExtensionDylibW;
1095
#else
1096
0
    return SharedLibraryExtensionSoW;
1097
0
#endif
1098
0
  }
1099
1100
0
  return NULL;
1101
0
}
1102
1103
const char* GetKnownPathIdString(int id)
1104
0
{
1105
0
  switch (id)
1106
0
  {
1107
0
    case KNOWN_PATH_HOME:
1108
0
      return "KNOWN_PATH_HOME";
1109
0
    case KNOWN_PATH_TEMP:
1110
0
      return "KNOWN_PATH_TEMP";
1111
0
    case KNOWN_PATH_XDG_DATA_HOME:
1112
0
      return "KNOWN_PATH_XDG_DATA_HOME";
1113
0
    case KNOWN_PATH_XDG_CONFIG_HOME:
1114
0
      return "KNOWN_PATH_XDG_CONFIG_HOME";
1115
0
    case KNOWN_PATH_XDG_CACHE_HOME:
1116
0
      return "KNOWN_PATH_XDG_CACHE_HOME";
1117
0
    case KNOWN_PATH_XDG_RUNTIME_DIR:
1118
0
      return "KNOWN_PATH_XDG_RUNTIME_DIR";
1119
0
    case KNOWN_PATH_SYSTEM_CONFIG_HOME:
1120
0
      return "KNOWN_PATH_SYSTEM_CONFIG_HOME";
1121
0
    default:
1122
0
      return "KNOWN_PATH_UNKNOWN_ID";
1123
0
  }
1124
0
}
1125
1126
static char* concat(const char* path, size_t pathlen, const char* name, size_t namelen)
1127
0
{
1128
0
  const size_t strsize = pathlen + namelen + 2;
1129
0
  char* str = calloc(strsize, sizeof(char));
1130
0
  if (!str)
1131
0
    return NULL;
1132
1133
0
  winpr_str_append(path, str, strsize, "");
1134
0
  winpr_str_append(name, str, strsize, "");
1135
0
  return str;
1136
0
}
1137
1138
BOOL winpr_RemoveDirectory_RecursiveA(LPCSTR lpPathName)
1139
0
{
1140
0
  BOOL ret = FALSE;
1141
1142
0
  if (!lpPathName)
1143
0
    return FALSE;
1144
1145
0
  const size_t pathnamelen = strlen(lpPathName);
1146
0
  const size_t path_slash_len = pathnamelen + 3;
1147
0
  char* path_slash = calloc(pathnamelen + 4, sizeof(char));
1148
0
  if (!path_slash)
1149
0
    return FALSE;
1150
0
  strncat(path_slash, lpPathName, pathnamelen);
1151
1152
0
  const char star[] = "*";
1153
0
  const HRESULT hr = NativePathCchAppendA(path_slash, path_slash_len, star);
1154
0
  HANDLE dir = INVALID_HANDLE_VALUE;
1155
0
  if (FAILED(hr))
1156
0
    goto fail;
1157
1158
0
  {
1159
0
    WIN32_FIND_DATAA findFileData = WINPR_C_ARRAY_INIT;
1160
0
    dir = FindFirstFileA(path_slash, &findFileData);
1161
1162
0
    if (dir == INVALID_HANDLE_VALUE)
1163
0
      goto fail;
1164
1165
0
    ret = TRUE;
1166
0
    path_slash[path_slash_len - 1] = '\0'; /* remove trailing '*' */
1167
0
    do
1168
0
    {
1169
0
      const size_t len = strnlen(findFileData.cFileName, ARRAYSIZE(findFileData.cFileName));
1170
1171
0
      if ((len == 1 && findFileData.cFileName[0] == '.') ||
1172
0
          (len == 2 && findFileData.cFileName[0] == '.' && findFileData.cFileName[1] == '.'))
1173
0
      {
1174
0
        continue;
1175
0
      }
1176
1177
0
      char* fullpath = concat(path_slash, path_slash_len, findFileData.cFileName, len);
1178
0
      if (!fullpath)
1179
0
        goto fail;
1180
1181
0
      if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1182
0
        ret = winpr_RemoveDirectory_RecursiveA(fullpath);
1183
0
      else
1184
0
      {
1185
0
        WINPR_PRAGMA_DIAG_PUSH
1186
0
        WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
1187
0
        ret = DeleteFileA(fullpath);
1188
0
        WINPR_PRAGMA_DIAG_POP
1189
0
      }
1190
1191
0
      free(fullpath);
1192
1193
0
      if (!ret)
1194
0
        break;
1195
0
    } while (ret && FindNextFileA(dir, &findFileData) != 0);
1196
0
  }
1197
1198
0
  if (ret)
1199
0
  {
1200
0
    WINPR_PRAGMA_DIAG_PUSH
1201
0
    WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
1202
0
    if (!RemoveDirectoryA(lpPathName))
1203
0
      ret = FALSE;
1204
0
    WINPR_PRAGMA_DIAG_POP
1205
0
  }
1206
1207
0
fail:
1208
0
  FindClose(dir);
1209
0
  free(path_slash);
1210
0
  return ret;
1211
0
}
1212
1213
BOOL winpr_RemoveDirectory_RecursiveW(LPCWSTR lpPathName)
1214
0
{
1215
0
  char* name = ConvertWCharToUtf8Alloc(lpPathName, NULL);
1216
0
  if (!name)
1217
0
    return FALSE;
1218
0
  const BOOL rc = winpr_RemoveDirectory_RecursiveA(name);
1219
0
  free(name);
1220
0
  return rc;
1221
0
}
1222
1223
char* winpr_GetConfigFilePathVA(BOOL system, WINPR_FORMAT_ARG const char* filename, va_list ap)
1224
11.0k
{
1225
11.0k
  eKnownPathTypes id = system ? KNOWN_PATH_SYSTEM_CONFIG_HOME : KNOWN_PATH_XDG_CONFIG_HOME;
1226
11.0k
  const char* vendor = winpr_getApplicationDetailsVendor();
1227
11.0k
  const char* product = winpr_getApplicationDetailsProduct();
1228
11.0k
  const SSIZE_T version = winpr_getApplicationDetailsVersion();
1229
1230
11.0k
  if (!vendor || !product)
1231
0
    return NULL;
1232
1233
11.0k
  char* config = GetKnownSubPathV(id, "%s", vendor);
1234
11.0k
  if (!config)
1235
0
    return NULL;
1236
1237
11.0k
  char* base = NULL;
1238
11.0k
  if (version < 0)
1239
11.0k
    base = GetCombinedPathV(config, "%s", product);
1240
0
  else
1241
0
    base = GetCombinedPathV(config, "%s%" PRIdz, product, version);
1242
11.0k
  free(config);
1243
1244
11.0k
  if (!base)
1245
0
    return NULL;
1246
11.0k
  char* path = GetCombinedPathVA(base, filename, ap);
1247
11.0k
  free(base);
1248
1249
11.0k
  return path;
1250
11.0k
}
1251
1252
char* winpr_GetConfigFilePath(BOOL system, const char* filename)
1253
11.0k
{
1254
11.0k
  if (!filename)
1255
0
    return winpr_GetConfigFilePathV(system, "%s", "");
1256
11.0k
  return winpr_GetConfigFilePathV(system, "%s", filename);
1257
11.0k
}
1258
1259
char* winpr_GetConfigFilePathV(BOOL system, const char* filename, ...)
1260
11.0k
{
1261
11.0k
  va_list ap = WINPR_C_ARRAY_INIT;
1262
11.0k
  va_start(ap, filename);
1263
11.0k
  char* str = winpr_GetConfigFilePathVA(system, filename, ap);
1264
  va_end(ap);
1265
11.0k
  return str;
1266
11.0k
}