Coverage Report

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