Coverage Report

Created: 2026-03-04 06:14

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
205k
#define PATH_SEPARATOR_CHR PATH_SLASH_CHR
68
34.1k
#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
68.3k
#define CUR_PATH_SEPARATOR_CHR PATH_SEPARATOR_CHR
334
34.1k
#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
723
0
  if (hasPrefix)
724
0
  {
725
0
    if (cchPath < 6)
726
0
      return S_FALSE;
727
728
0
    if (IsCharAlpha(pszPath[4]) && (pszPath[5] == ':')) /* like C: */
729
0
    {
730
0
      if (memmove_s(pszPath, cchPath, &pszPath[4], cchPath - 4) < 0)
731
0
        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
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
758
0
  if (hasPrefix)
759
0
  {
760
0
    if (cchPath < 6)
761
0
      return S_FALSE;
762
763
0
    const size_t rc = (_wcslen(&pszPath[4]) + 1);
764
0
    if (cchPath < rc)
765
0
      return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
766
767
0
    if (IsCharAlphaW(pszPath[4]) && (pszPath[5] == L':')) /* like C: */
768
0
    {
769
0
      if (wmemmove_s(pszPath, cchPath, &pszPath[4], cchPath - 4) < 0)
770
0
        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
0
      pszPath[cchPath - 4] = 0;
776
0
      return S_OK;
777
0
    }
778
0
  }
779
780
0
  return S_FALSE;
781
0
}
782
783
/**
784
 * PathCchRemoveFileSpec
785
 */
786
787
HRESULT PathCchRemoveFileSpecA(WINPR_ATTR_UNUSED PSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
788
0
{
789
0
  WLog_ERR(TAG, "not implemented");
790
0
  return E_NOTIMPL;
791
0
}
792
793
HRESULT PathCchRemoveFileSpecW(WINPR_ATTR_UNUSED PWSTR pszPath, WINPR_ATTR_UNUSED size_t cchPath)
794
0
{
795
0
  WLog_ERR(TAG, "not implemented");
796
0
  return E_NOTIMPL;
797
0
}
798
799
/*
800
 * Path Portability Functions
801
 */
802
803
/**
804
 * PathCchConvertStyle
805
 */
806
807
HRESULT PathCchConvertStyleA(PSTR pszPath, size_t cchPath, unsigned long dwFlags)
808
68.3k
{
809
68.3k
  if (dwFlags == PATH_STYLE_WINDOWS)
810
0
  {
811
0
    for (size_t index = 0; index < cchPath; index++)
812
0
    {
813
0
      if (pszPath[index] == PATH_SLASH_CHR)
814
0
        pszPath[index] = PATH_BACKSLASH_CHR;
815
0
    }
816
0
  }
817
68.3k
  else if (dwFlags == PATH_STYLE_UNIX)
818
0
  {
819
0
    for (size_t index = 0; index < cchPath; index++)
820
0
    {
821
0
      if (pszPath[index] == PATH_BACKSLASH_CHR)
822
0
        pszPath[index] = PATH_SLASH_CHR;
823
0
    }
824
0
  }
825
68.3k
  else if (dwFlags == PATH_STYLE_NATIVE)
826
68.3k
  {
827
68.3k
    if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR)
828
0
    {
829
      /* Unix-style to Windows-style */
830
831
0
      for (size_t index = 0; index < cchPath; index++)
832
0
      {
833
0
        if (pszPath[index] == PATH_SLASH_CHR)
834
0
          pszPath[index] = PATH_BACKSLASH_CHR;
835
0
      }
836
0
    }
837
68.3k
    else if (PATH_SEPARATOR_CHR == PATH_SLASH_CHR)
838
68.3k
    {
839
      /* Windows-style to Unix-style */
840
841
1.07M
      for (size_t index = 0; index < cchPath; index++)
842
1.00M
      {
843
1.00M
        if (pszPath[index] == PATH_BACKSLASH_CHR)
844
0
          pszPath[index] = PATH_SLASH_CHR;
845
1.00M
      }
846
68.3k
    }
847
0
    else
848
0
    {
849
      /* Unexpected error */
850
0
      return E_FAIL;
851
0
    }
852
68.3k
  }
853
0
  else
854
0
  {
855
    /* Gangnam style? */
856
0
    return E_FAIL;
857
0
  }
858
859
68.3k
  return S_OK;
860
68.3k
}
861
862
HRESULT PathCchConvertStyleW(PWSTR pszPath, size_t cchPath, unsigned long dwFlags)
863
0
{
864
0
  if (dwFlags == PATH_STYLE_WINDOWS)
865
0
  {
866
0
    for (size_t index = 0; index < cchPath; index++)
867
0
    {
868
0
      if (pszPath[index] == PATH_SLASH_CHR_W)
869
0
        pszPath[index] = PATH_BACKSLASH_CHR_W;
870
0
    }
871
0
  }
872
0
  else if (dwFlags == PATH_STYLE_UNIX)
873
0
  {
874
0
    for (size_t index = 0; index < cchPath; index++)
875
0
    {
876
0
      if (pszPath[index] == PATH_BACKSLASH_CHR_W)
877
0
        pszPath[index] = PATH_SLASH_CHR_W;
878
0
    }
879
0
  }
880
0
  else if (dwFlags == PATH_STYLE_NATIVE)
881
0
  {
882
0
    if (PATH_SEPARATOR_CHR == PATH_BACKSLASH_CHR_W)
883
0
    {
884
      /* Unix-style to Windows-style */
885
886
0
      for (size_t index = 0; index < cchPath; index++)
887
0
      {
888
0
        if (pszPath[index] == PATH_SLASH_CHR_W)
889
0
          pszPath[index] = PATH_BACKSLASH_CHR_W;
890
0
      }
891
0
    }
892
0
    else if (PATH_SEPARATOR_CHR == PATH_SLASH_CHR_W)
893
0
    {
894
      /* Windows-style to Unix-style */
895
896
0
      for (size_t index = 0; index < cchPath; index++)
897
0
      {
898
0
        if (pszPath[index] == PATH_BACKSLASH_CHR_W)
899
0
          pszPath[index] = PATH_SLASH_CHR_W;
900
0
      }
901
0
    }
902
0
    else
903
0
    {
904
      /* Unexpected error */
905
0
      return E_FAIL;
906
0
    }
907
0
  }
908
0
  else
909
0
  {
910
    /* Gangnam style? */
911
0
    return E_FAIL;
912
0
  }
913
914
0
  return S_OK;
915
0
}
916
917
/**
918
 * PathGetSeparator
919
 */
920
921
char PathGetSeparatorA(unsigned long dwFlags)
922
0
{
923
0
  char separator = PATH_SEPARATOR_CHR;
924
925
0
  if (!dwFlags)
926
0
    dwFlags = PATH_STYLE_NATIVE;
927
928
0
  if (dwFlags == PATH_STYLE_WINDOWS)
929
0
    separator = PATH_SEPARATOR_CHR;
930
0
  else if (dwFlags == PATH_STYLE_UNIX)
931
0
    separator = PATH_SEPARATOR_CHR;
932
0
  else if (dwFlags == PATH_STYLE_NATIVE)
933
0
    separator = PATH_SEPARATOR_CHR;
934
935
0
  return separator;
936
0
}
937
938
WCHAR PathGetSeparatorW(unsigned long dwFlags)
939
0
{
940
0
  union
941
0
  {
942
0
    WCHAR w;
943
0
    char c[2];
944
0
  } cnv;
945
946
0
  cnv.c[0] = PATH_SEPARATOR_CHR;
947
0
  cnv.c[1] = '\0';
948
949
0
  if (!dwFlags)
950
0
    dwFlags = PATH_STYLE_NATIVE;
951
952
0
  if (dwFlags == PATH_STYLE_WINDOWS)
953
0
    cnv.c[0] = PATH_SEPARATOR_CHR;
954
0
  else if (dwFlags == PATH_STYLE_UNIX)
955
0
    cnv.c[0] = PATH_SEPARATOR_CHR;
956
0
  else if (dwFlags == PATH_STYLE_NATIVE)
957
0
    cnv.c[0] = PATH_SEPARATOR_CHR;
958
959
0
  return cnv.w;
960
0
}
961
962
/**
963
 * PathGetSharedLibraryExtension
964
 */
965
static const CHAR SharedLibraryExtensionDllA[] = "dll";
966
static const CHAR SharedLibraryExtensionSoA[] = "so";
967
static const CHAR SharedLibraryExtensionDylibA[] = "dylib";
968
969
static const CHAR SharedLibraryExtensionDotDllA[] = ".dll";
970
static const CHAR SharedLibraryExtensionDotSoA[] = ".so";
971
static const CHAR SharedLibraryExtensionDotDylibA[] = ".dylib";
972
PCSTR PathGetSharedLibraryExtensionA(unsigned long dwFlags)
973
0
{
974
0
  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
975
0
  {
976
0
    if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
977
0
    {
978
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
979
0
        return SharedLibraryExtensionDotDllA;
980
981
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
982
0
        return SharedLibraryExtensionDotSoA;
983
984
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
985
0
        return SharedLibraryExtensionDotDylibA;
986
0
    }
987
0
    else
988
0
    {
989
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
990
0
        return SharedLibraryExtensionDllA;
991
992
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
993
0
        return SharedLibraryExtensionSoA;
994
995
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
996
0
        return SharedLibraryExtensionDylibA;
997
0
    }
998
0
  }
999
1000
0
  if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1001
0
  {
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
0
    return SharedLibraryExtensionDotSoA;
1011
0
#endif
1012
0
  }
1013
0
  else
1014
0
  {
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
0
    return SharedLibraryExtensionSoA;
1024
0
#endif
1025
0
  }
1026
0
}
1027
1028
PCWSTR PathGetSharedLibraryExtensionW(unsigned long dwFlags)
1029
0
{
1030
0
  static WCHAR buffer[6][16] = WINPR_C_ARRAY_INIT;
1031
0
  const WCHAR* SharedLibraryExtensionDotDllW = InitializeConstWCharFromUtf8(
1032
0
      SharedLibraryExtensionDotDllA, buffer[0], ARRAYSIZE(buffer[0]));
1033
0
  const WCHAR* SharedLibraryExtensionDotSoW =
1034
0
      InitializeConstWCharFromUtf8(SharedLibraryExtensionDotSoA, buffer[1], ARRAYSIZE(buffer[1]));
1035
0
  const WCHAR* SharedLibraryExtensionDotDylibW = InitializeConstWCharFromUtf8(
1036
0
      SharedLibraryExtensionDotDylibA, buffer[2], ARRAYSIZE(buffer[2]));
1037
0
  const WCHAR* SharedLibraryExtensionDllW =
1038
0
      InitializeConstWCharFromUtf8(SharedLibraryExtensionDllA, buffer[3], ARRAYSIZE(buffer[3]));
1039
0
  const WCHAR* SharedLibraryExtensionSoW =
1040
0
      InitializeConstWCharFromUtf8(SharedLibraryExtensionSoA, buffer[4], ARRAYSIZE(buffer[4]));
1041
0
  const WCHAR* SharedLibraryExtensionDylibW =
1042
0
      InitializeConstWCharFromUtf8(SharedLibraryExtensionDylibA, buffer[5], ARRAYSIZE(buffer[5]));
1043
1044
0
  if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT)
1045
0
  {
1046
0
    if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1047
0
    {
1048
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1049
0
        return SharedLibraryExtensionDotDllW;
1050
1051
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1052
0
        return SharedLibraryExtensionDotSoW;
1053
1054
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1055
0
        return SharedLibraryExtensionDotDylibW;
1056
0
    }
1057
0
    else
1058
0
    {
1059
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DLL)
1060
0
        return SharedLibraryExtensionDllW;
1061
1062
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_SO)
1063
0
        return SharedLibraryExtensionSoW;
1064
1065
0
      if (dwFlags & PATH_SHARED_LIB_EXT_EXPLICIT_DYLIB)
1066
0
        return SharedLibraryExtensionDylibW;
1067
0
    }
1068
0
  }
1069
1070
0
  if (dwFlags & PATH_SHARED_LIB_EXT_WITH_DOT)
1071
0
  {
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
0
    return SharedLibraryExtensionDotSoW;
1081
0
#endif
1082
0
  }
1083
0
  else
1084
0
  {
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
0
    return SharedLibraryExtensionSoW;
1094
0
#endif
1095
0
  }
1096
0
}
1097
1098
const char* GetKnownPathIdString(int id)
1099
0
{
1100
0
  switch (id)
1101
0
  {
1102
0
    case KNOWN_PATH_HOME:
1103
0
      return "KNOWN_PATH_HOME";
1104
0
    case KNOWN_PATH_TEMP:
1105
0
      return "KNOWN_PATH_TEMP";
1106
0
    case KNOWN_PATH_XDG_DATA_HOME:
1107
0
      return "KNOWN_PATH_XDG_DATA_HOME";
1108
0
    case KNOWN_PATH_XDG_CONFIG_HOME:
1109
0
      return "KNOWN_PATH_XDG_CONFIG_HOME";
1110
0
    case KNOWN_PATH_XDG_CACHE_HOME:
1111
0
      return "KNOWN_PATH_XDG_CACHE_HOME";
1112
0
    case KNOWN_PATH_XDG_RUNTIME_DIR:
1113
0
      return "KNOWN_PATH_XDG_RUNTIME_DIR";
1114
0
    case KNOWN_PATH_SYSTEM_CONFIG_HOME:
1115
0
      return "KNOWN_PATH_SYSTEM_CONFIG_HOME";
1116
0
    default:
1117
0
      return "KNOWN_PATH_UNKNOWN_ID";
1118
0
  }
1119
0
}
1120
1121
static char* concat(const char* path, size_t pathlen, const char* name, size_t namelen)
1122
0
{
1123
0
  const size_t strsize = pathlen + namelen + 2;
1124
0
  char* str = calloc(strsize, sizeof(char));
1125
0
  if (!str)
1126
0
    return nullptr;
1127
1128
0
  winpr_str_append(path, str, strsize, "");
1129
0
  winpr_str_append(name, str, strsize, "");
1130
0
  return str;
1131
0
}
1132
1133
BOOL winpr_RemoveDirectory_RecursiveA(LPCSTR lpPathName)
1134
0
{
1135
0
  BOOL ret = FALSE;
1136
1137
0
  if (!lpPathName)
1138
0
    return FALSE;
1139
1140
0
  const size_t pathnamelen = strlen(lpPathName);
1141
0
  const size_t path_slash_len = pathnamelen + 3;
1142
0
  char* path_slash = calloc(pathnamelen + 4, sizeof(char));
1143
0
  if (!path_slash)
1144
0
    return FALSE;
1145
0
  strncat(path_slash, lpPathName, pathnamelen);
1146
1147
0
  const char star[] = "*";
1148
0
  const HRESULT hr = NativePathCchAppendA(path_slash, path_slash_len, star);
1149
0
  HANDLE dir = INVALID_HANDLE_VALUE;
1150
0
  if (FAILED(hr))
1151
0
    goto fail;
1152
1153
0
  {
1154
0
    WIN32_FIND_DATAA findFileData = WINPR_C_ARRAY_INIT;
1155
0
    dir = FindFirstFileA(path_slash, &findFileData);
1156
1157
0
    if (dir == INVALID_HANDLE_VALUE)
1158
0
      goto fail;
1159
1160
0
    ret = TRUE;
1161
0
    path_slash[path_slash_len - 1] = '\0'; /* remove trailing '*' */
1162
0
    do
1163
0
    {
1164
0
      const size_t len = strnlen(findFileData.cFileName, ARRAYSIZE(findFileData.cFileName));
1165
1166
0
      if ((len == 1 && findFileData.cFileName[0] == '.') ||
1167
0
          (len == 2 && findFileData.cFileName[0] == '.' && findFileData.cFileName[1] == '.'))
1168
0
      {
1169
0
        continue;
1170
0
      }
1171
1172
0
      char* fullpath = concat(path_slash, path_slash_len, findFileData.cFileName, len);
1173
0
      if (!fullpath)
1174
0
        goto fail;
1175
1176
0
      if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1177
0
        ret = winpr_RemoveDirectory_RecursiveA(fullpath);
1178
0
      else
1179
0
      {
1180
0
        WINPR_PRAGMA_DIAG_PUSH
1181
0
        WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
1182
0
        ret = DeleteFileA(fullpath);
1183
0
        WINPR_PRAGMA_DIAG_POP
1184
0
      }
1185
1186
0
      free(fullpath);
1187
1188
0
      if (!ret)
1189
0
        break;
1190
0
    } while (ret && FindNextFileA(dir, &findFileData) != 0);
1191
0
  }
1192
1193
0
  if (ret)
1194
0
  {
1195
0
    WINPR_PRAGMA_DIAG_PUSH
1196
0
    WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
1197
0
    if (!RemoveDirectoryA(lpPathName))
1198
0
      ret = FALSE;
1199
0
    WINPR_PRAGMA_DIAG_POP
1200
0
  }
1201
1202
0
fail:
1203
0
  FindClose(dir);
1204
0
  free(path_slash);
1205
0
  return ret;
1206
0
}
1207
1208
BOOL winpr_RemoveDirectory_RecursiveW(LPCWSTR lpPathName)
1209
0
{
1210
0
  char* name = ConvertWCharToUtf8Alloc(lpPathName, nullptr);
1211
0
  if (!name)
1212
0
    return FALSE;
1213
0
  const BOOL rc = winpr_RemoveDirectory_RecursiveA(name);
1214
0
  free(name);
1215
0
  return rc;
1216
0
}
1217
1218
char* winpr_GetConfigFilePathVA(BOOL system, WINPR_FORMAT_ARG const char* filename, va_list ap)
1219
11.3k
{
1220
11.3k
  eKnownPathTypes id = system ? KNOWN_PATH_SYSTEM_CONFIG_HOME : KNOWN_PATH_XDG_CONFIG_HOME;
1221
11.3k
  const char* vendor = winpr_getApplicationDetailsVendor();
1222
11.3k
  const char* product = winpr_getApplicationDetailsProduct();
1223
11.3k
  const SSIZE_T version = winpr_getApplicationDetailsVersion();
1224
1225
11.3k
  if (!vendor || !product)
1226
0
    return nullptr;
1227
1228
11.3k
  char* config = GetKnownSubPathV(id, "%s", vendor);
1229
11.3k
  if (!config)
1230
0
    return nullptr;
1231
1232
11.3k
  char* base = nullptr;
1233
11.3k
  if (version < 0)
1234
11.3k
    base = GetCombinedPathV(config, "%s", product);
1235
0
  else
1236
0
    base = GetCombinedPathV(config, "%s%" PRIdz, product, version);
1237
11.3k
  free(config);
1238
1239
11.3k
  if (!base)
1240
0
    return nullptr;
1241
11.3k
  char* path = GetCombinedPathVA(base, filename, ap);
1242
11.3k
  free(base);
1243
1244
11.3k
  return path;
1245
11.3k
}
1246
1247
char* winpr_GetConfigFilePath(BOOL system, const char* filename)
1248
11.3k
{
1249
11.3k
  if (!filename)
1250
0
    return winpr_GetConfigFilePathV(system, "%s", "");
1251
11.3k
  return winpr_GetConfigFilePathV(system, "%s", filename);
1252
11.3k
}
1253
1254
char* winpr_GetConfigFilePathV(BOOL system, const char* filename, ...)
1255
11.3k
{
1256
11.3k
  va_list ap = WINPR_C_ARRAY_INIT;
1257
11.3k
  va_start(ap, filename);
1258
11.3k
  char* str = winpr_GetConfigFilePathVA(system, filename, ap);
1259
  va_end(ap);
1260
11.3k
  return str;
1261
11.3k
}