Coverage Report

Created: 2024-05-20 06:11

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