Coverage Report

Created: 2025-07-01 06:46

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