Coverage Report

Created: 2023-09-25 06:56

/src/FreeRDP/winpr/libwinpr/path/shell.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
 * Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
21
#include <winpr/config.h>
22
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <sys/stat.h>
27
28
#include <winpr/crt.h>
29
#include <winpr/platform.h>
30
#include <winpr/file.h>
31
#include <winpr/tchar.h>
32
#include <winpr/environment.h>
33
34
#include <winpr/path.h>
35
#include <winpr/wlog.h>
36
37
#include "../log.h"
38
#define TAG WINPR_TAG("path.shell")
39
40
#if defined(__IOS__)
41
#include "shell_ios.h"
42
#endif
43
44
#if defined(WIN32)
45
#include <shlobj.h>
46
#else
47
#include <errno.h>
48
#include <dirent.h>
49
#endif
50
51
static char* GetPath_XDG_CONFIG_HOME(void);
52
static char* GetPath_XDG_RUNTIME_DIR(void);
53
54
/**
55
 * SHGetKnownFolderPath function:
56
 * http://msdn.microsoft.com/en-us/library/windows/desktop/bb762188/
57
 */
58
59
/**
60
 * XDG Base Directory Specification:
61
 * http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
62
 */
63
64
char* GetEnvAlloc(LPCSTR lpName)
65
0
{
66
0
  DWORD nSize;
67
0
  DWORD nStatus;
68
0
  char* env = NULL;
69
70
0
  nSize = GetEnvironmentVariableX(lpName, NULL, 0);
71
72
0
  if (nSize > 0)
73
0
  {
74
0
    env = malloc(nSize);
75
76
0
    if (!env)
77
0
      return NULL;
78
79
0
    nStatus = GetEnvironmentVariableX(lpName, env, nSize);
80
81
0
    if (nStatus != (nSize - 1))
82
0
    {
83
0
      free(env);
84
0
      return NULL;
85
0
    }
86
0
  }
87
88
0
  return env;
89
0
}
90
91
static char* GetPath_HOME(void)
92
0
{
93
0
  char* path = NULL;
94
#ifdef _WIN32
95
  path = GetEnvAlloc("UserProfile");
96
#elif defined(__IOS__)
97
  path = ios_get_home();
98
#else
99
0
  path = GetEnvAlloc("HOME");
100
0
#endif
101
0
  return path;
102
0
}
103
104
static char* GetPath_TEMP(void)
105
0
{
106
0
  char* path = NULL;
107
#ifdef _WIN32
108
  path = GetEnvAlloc("TEMP");
109
#elif defined(__IOS__)
110
  path = ios_get_temp();
111
#else
112
0
  path = GetEnvAlloc("TMPDIR");
113
114
0
  if (!path)
115
0
    path = _strdup("/tmp");
116
117
0
#endif
118
0
  return path;
119
0
}
120
121
static char* GetPath_XDG_DATA_HOME(void)
122
0
{
123
0
  char* path = NULL;
124
#if defined(WIN32) || defined(__IOS__)
125
  path = GetPath_XDG_CONFIG_HOME();
126
#else
127
0
  size_t size;
128
0
  char* home = NULL;
129
  /**
130
   * There is a single base directory relative to which user-specific data files should be
131
   * written. This directory is defined by the environment variable $XDG_DATA_HOME.
132
   *
133
   * $XDG_DATA_HOME defines the base directory relative to which user specific data files should
134
   * be stored. If $XDG_DATA_HOME is either not set or empty, a default equal to
135
   * $HOME/.local/share should be used.
136
   */
137
0
  path = GetEnvAlloc("XDG_DATA_HOME");
138
139
0
  if (path)
140
0
    return path;
141
142
0
  home = GetPath_HOME();
143
144
0
  if (!home)
145
0
    return NULL;
146
147
0
  size = strlen(home) + strlen("/.local/share") + 1;
148
0
  path = (char*)malloc(size);
149
150
0
  if (!path)
151
0
  {
152
0
    free(home);
153
0
    return NULL;
154
0
  }
155
156
0
  sprintf_s(path, size, "%s%s", home, "/.local/share");
157
0
  free(home);
158
0
#endif
159
0
  return path;
160
0
}
161
162
static char* GetPath_XDG_CONFIG_HOME(void)
163
0
{
164
0
  char* path = NULL;
165
#if defined(WIN32) && !defined(_UWP)
166
  path = calloc(MAX_PATH, sizeof(char));
167
168
  if (!path)
169
    return NULL;
170
171
  if (FAILED(SHGetFolderPathA(0, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, path)))
172
  {
173
    free(path);
174
    return NULL;
175
  }
176
177
#elif defined(__IOS__)
178
  path = ios_get_data();
179
#else
180
0
  size_t size;
181
0
  char* home = NULL;
182
  /**
183
   * There is a single base directory relative to which user-specific configuration files should
184
   * be written. This directory is defined by the environment variable $XDG_CONFIG_HOME.
185
   *
186
   * $XDG_CONFIG_HOME defines the base directory relative to which user specific configuration
187
   * files should be stored. If $XDG_CONFIG_HOME is either not set or empty, a default equal to
188
   * $HOME/.config should be used.
189
   */
190
0
  path = GetEnvAlloc("XDG_CONFIG_HOME");
191
192
0
  if (path)
193
0
    return path;
194
195
0
  home = GetPath_HOME();
196
197
0
  if (!home)
198
0
    home = GetPath_TEMP();
199
200
0
  if (!home)
201
0
    return NULL;
202
203
0
  size = strlen(home) + strlen("/.config") + 1;
204
0
  path = (char*)malloc(size);
205
206
0
  if (!path)
207
0
  {
208
0
    free(home);
209
0
    return NULL;
210
0
  }
211
212
0
  sprintf_s(path, size, "%s%s", home, "/.config");
213
0
  free(home);
214
0
#endif
215
0
  return path;
216
0
}
217
218
static char* GetPath_XDG_CACHE_HOME(void)
219
0
{
220
0
  char* path = NULL;
221
0
  char* home = NULL;
222
#if defined(WIN32)
223
  home = GetPath_XDG_RUNTIME_DIR();
224
225
  if (home)
226
  {
227
    path = GetCombinedPath(home, "cache");
228
229
    if (!winpr_PathFileExists(path))
230
      if (!CreateDirectoryA(path, NULL))
231
        path = NULL;
232
  }
233
234
  free(home);
235
#elif defined(__IOS__)
236
  path = ios_get_cache();
237
#else
238
0
  size_t size;
239
  /**
240
   * There is a single base directory relative to which user-specific non-essential (cached) data
241
   * should be written. This directory is defined by the environment variable $XDG_CACHE_HOME.
242
   *
243
   * $XDG_CACHE_HOME defines the base directory relative to which user specific non-essential data
244
   * files should be stored. If $XDG_CACHE_HOME is either not set or empty, a default equal to
245
   * $HOME/.cache should be used.
246
   */
247
0
  path = GetEnvAlloc("XDG_CACHE_HOME");
248
249
0
  if (path)
250
0
    return path;
251
252
0
  home = GetPath_HOME();
253
254
0
  if (!home)
255
0
    return NULL;
256
257
0
  size = strlen(home) + strlen("/.cache") + 1;
258
0
  path = (char*)malloc(size);
259
260
0
  if (!path)
261
0
  {
262
0
    free(home);
263
0
    return NULL;
264
0
  }
265
266
0
  sprintf_s(path, size, "%s%s", home, "/.cache");
267
0
  free(home);
268
0
#endif
269
0
  return path;
270
0
}
271
272
char* GetPath_XDG_RUNTIME_DIR(void)
273
0
{
274
0
  char* path = NULL;
275
#if defined(WIN32) && !defined(_UWP)
276
  path = calloc(MAX_PATH, sizeof(char));
277
278
  if (!path)
279
    return NULL;
280
281
  if (FAILED(SHGetFolderPathA(0, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, path)))
282
  {
283
    free(path);
284
    return NULL;
285
  }
286
287
#else
288
  /**
289
   * There is a single base directory relative to which user-specific runtime files and other file
290
   * objects should be placed. This directory is defined by the environment variable
291
   * $XDG_RUNTIME_DIR.
292
   *
293
   * $XDG_RUNTIME_DIR defines the base directory relative to which user-specific non-essential
294
   * runtime files and other file objects (such as sockets, named pipes, ...) should be stored.
295
   * The directory MUST be owned by the user, and he MUST be the only one having read and write
296
   * access to it. Its Unix access mode MUST be 0700.
297
   *
298
   * The lifetime of the directory MUST be bound to the user being logged in. It MUST be created
299
   * when the user first logs in and if the user fully logs out the directory MUST be removed. If
300
   * the user logs in more than once he should get pointed to the same directory, and it is
301
   * mandatory that the directory continues to exist from his first login to his last logout on
302
   * the system, and not removed in between. Files in the directory MUST not survive reboot or a
303
   * full logout/login cycle.
304
   *
305
   * The directory MUST be on a local file system and not shared with any other system. The
306
   * directory MUST by fully-featured by the standards of the operating system. More specifically,
307
   * on Unix-like operating systems AF_UNIX sockets, symbolic links, hard links, proper
308
   * permissions, file locking, sparse files, memory mapping, file change notifications, a
309
   * reliable hard link count must be supported, and no restrictions on the file name character
310
   * set should be imposed. Files in this directory MAY be subjected to periodic clean-up. To
311
   * ensure that your files are not removed, they should have their access time timestamp modified
312
   * at least once every 6 hours of monotonic time or the 'sticky' bit should be set on the file.
313
   *
314
   * If $XDG_RUNTIME_DIR is not set applications should fall back to a replacement directory with
315
   * similar capabilities and print a warning message. Applications should use this directory for
316
   * communication and synchronization purposes and should not place larger files in it, since it
317
   * might reside in runtime memory and cannot necessarily be swapped out to disk.
318
   */
319
0
  path = GetEnvAlloc("XDG_RUNTIME_DIR");
320
0
#endif
321
322
0
  if (path)
323
0
    return path;
324
325
0
  path = GetPath_TEMP();
326
0
  return path;
327
0
}
328
329
char* GetKnownPath(int id)
330
0
{
331
0
  char* path = NULL;
332
333
0
  switch (id)
334
0
  {
335
0
    case KNOWN_PATH_HOME:
336
0
      path = GetPath_HOME();
337
0
      break;
338
339
0
    case KNOWN_PATH_TEMP:
340
0
      path = GetPath_TEMP();
341
0
      break;
342
343
0
    case KNOWN_PATH_XDG_DATA_HOME:
344
0
      path = GetPath_XDG_DATA_HOME();
345
0
      break;
346
347
0
    case KNOWN_PATH_XDG_CONFIG_HOME:
348
0
      path = GetPath_XDG_CONFIG_HOME();
349
0
      break;
350
351
0
    case KNOWN_PATH_XDG_CACHE_HOME:
352
0
      path = GetPath_XDG_CACHE_HOME();
353
0
      break;
354
355
0
    case KNOWN_PATH_XDG_RUNTIME_DIR:
356
0
      path = GetPath_XDG_RUNTIME_DIR();
357
0
      break;
358
359
0
    default:
360
0
      path = NULL;
361
0
      break;
362
0
  }
363
364
0
  if (!path)
365
0
    WLog_WARN(TAG, "Path %s is %p", GetKnownPathIdString(id), path);
366
0
  return path;
367
0
}
368
369
char* GetKnownSubPath(int id, const char* path)
370
0
{
371
0
  char* subPath;
372
0
  char* knownPath;
373
0
  knownPath = GetKnownPath(id);
374
375
0
  if (!knownPath)
376
0
    return NULL;
377
378
0
  subPath = GetCombinedPath(knownPath, path);
379
0
  free(knownPath);
380
0
  return subPath;
381
0
}
382
383
char* GetEnvironmentPath(char* name)
384
0
{
385
0
  char* env = NULL;
386
0
  DWORD nSize;
387
0
  DWORD nStatus;
388
0
  nSize = GetEnvironmentVariableX(name, NULL, 0);
389
390
0
  if (nSize)
391
0
  {
392
0
    env = (LPSTR)malloc(nSize);
393
394
0
    if (!env)
395
0
      return NULL;
396
397
0
    nStatus = GetEnvironmentVariableX(name, env, nSize);
398
399
0
    if (nStatus != (nSize - 1))
400
0
    {
401
0
      free(env);
402
0
      return NULL;
403
0
    }
404
0
  }
405
406
0
  return env;
407
0
}
408
409
char* GetEnvironmentSubPath(char* name, const char* path)
410
0
{
411
0
  char* env;
412
0
  char* subpath;
413
0
  env = GetEnvironmentPath(name);
414
415
0
  if (!env)
416
0
    return NULL;
417
418
0
  subpath = GetCombinedPath(env, path);
419
0
  free(env);
420
0
  return subpath;
421
0
}
422
423
char* GetCombinedPath(const char* basePath, const char* subPath)
424
0
{
425
0
  size_t length;
426
0
  HRESULT status;
427
0
  char* path = NULL;
428
0
  char* subPathCpy = NULL;
429
0
  size_t basePathLength = 0;
430
0
  size_t subPathLength = 0;
431
432
0
  if (basePath)
433
0
    basePathLength = strlen(basePath);
434
435
0
  if (subPath)
436
0
    subPathLength = strlen(subPath);
437
438
0
  length = basePathLength + subPathLength + 1;
439
0
  path = (char*)calloc(1, length + 1);
440
441
0
  if (!path)
442
0
    goto fail;
443
444
0
  if (basePath)
445
0
    CopyMemory(path, basePath, basePathLength);
446
447
0
  if (FAILED(PathCchConvertStyleA(path, basePathLength, PATH_STYLE_NATIVE)))
448
0
    goto fail;
449
450
0
  if (!subPath)
451
0
    return path;
452
453
0
  subPathCpy = _strdup(subPath);
454
455
0
  if (!subPathCpy)
456
0
    goto fail;
457
458
0
  if (FAILED(PathCchConvertStyleA(subPathCpy, subPathLength, PATH_STYLE_NATIVE)))
459
0
    goto fail;
460
461
0
  status = NativePathCchAppendA(path, length + 1, subPathCpy);
462
0
  if (FAILED(status))
463
0
    goto fail;
464
465
0
  free(subPathCpy);
466
0
  return path;
467
468
0
fail:
469
0
  free(path);
470
0
  free(subPathCpy);
471
0
  return NULL;
472
0
}
473
474
BOOL PathMakePathA(LPCSTR path, LPSECURITY_ATTRIBUTES lpAttributes)
475
0
{
476
#if defined(_UWP)
477
  return FALSE;
478
#elif defined(_WIN32)
479
  return (SHCreateDirectoryExA(NULL, path, lpAttributes) == ERROR_SUCCESS);
480
#else
481
0
  const char delim = PathGetSeparatorA(PATH_STYLE_NATIVE);
482
0
  char* dup;
483
0
  char* p;
484
0
  BOOL result = TRUE;
485
  /* we only operate on a non-null, absolute path */
486
#if defined(__OS2__)
487
488
  if (!path)
489
    return FALSE;
490
491
#else
492
493
0
  if (!path || *path != delim)
494
0
    return FALSE;
495
496
0
#endif
497
498
0
  if (!(dup = _strdup(path)))
499
0
    return FALSE;
500
501
#ifdef __OS2__
502
  p = (strlen(dup) > 3) && (dup[1] == ':') && (dup[2] == delim)) ? &dup[3] : dup;
503
504
  while (p)
505
#else
506
0
  for (p = dup; p;)
507
0
#endif
508
0
  {
509
0
    if ((p = strchr(p + 1, delim)))
510
0
      *p = '\0';
511
512
0
    if (mkdir(dup, 0777) != 0)
513
0
      if (errno != EEXIST)
514
0
      {
515
0
        result = FALSE;
516
0
        break;
517
0
      }
518
519
0
    if (p)
520
0
      *p = delim;
521
0
  }
522
523
0
  free(dup);
524
0
  return (result);
525
0
#endif
526
0
}
527
528
BOOL PathMakePathW(LPCWSTR path, LPSECURITY_ATTRIBUTES lpAttributes)
529
0
{
530
#if defined(_UWP)
531
  return FALSE;
532
#elif defined(_WIN32)
533
  return (SHCreateDirectoryExW(NULL, path, lpAttributes) == ERROR_SUCCESS);
534
#else
535
0
  const WCHAR wdelim = PathGetSeparatorW(PATH_STYLE_NATIVE);
536
0
  const char delim = PathGetSeparatorA(PATH_STYLE_NATIVE);
537
0
  char* dup;
538
0
  char* p;
539
0
  BOOL result = TRUE;
540
  /* we only operate on a non-null, absolute path */
541
#if defined(__OS2__)
542
543
  if (!path)
544
    return FALSE;
545
546
#else
547
548
0
  if (!path || *path != wdelim)
549
0
    return FALSE;
550
551
0
#endif
552
553
0
  dup = ConvertWCharToUtf8Alloc(path, NULL);
554
0
  if (!dup)
555
0
    return FALSE;
556
557
#ifdef __OS2__
558
  p = (strlen(dup) > 3) && (dup[1] == ':') && (dup[2] == delim)) ? &dup[3] : dup;
559
560
  while (p)
561
#else
562
0
  for (p = dup; p;)
563
0
#endif
564
0
  {
565
0
    if ((p = strchr(p + 1, delim)))
566
0
      *p = '\0';
567
568
0
    if (mkdir(dup, 0777) != 0)
569
0
      if (errno != EEXIST)
570
0
      {
571
0
        result = FALSE;
572
0
        break;
573
0
      }
574
575
0
    if (p)
576
0
      *p = delim;
577
0
  }
578
579
0
  free(dup);
580
0
  return (result);
581
0
#endif
582
0
}
583
584
#if !defined(_WIN32) || defined(_UWP)
585
586
BOOL PathIsRelativeA(LPCSTR pszPath)
587
0
{
588
0
  if (!pszPath)
589
0
    return FALSE;
590
591
0
  return pszPath[0] != '/';
592
0
}
593
594
BOOL PathIsRelativeW(LPCWSTR pszPath)
595
0
{
596
0
  LPSTR lpFileNameA = NULL;
597
0
  BOOL ret = FALSE;
598
599
0
  if (!pszPath)
600
0
    goto fail;
601
602
0
  lpFileNameA = ConvertWCharToUtf8Alloc(pszPath, NULL);
603
0
  if (!lpFileNameA)
604
0
    goto fail;
605
0
  ret = PathIsRelativeA(lpFileNameA);
606
0
fail:
607
0
  free(lpFileNameA);
608
0
  return ret;
609
0
}
610
611
BOOL PathFileExistsA(LPCSTR pszPath)
612
0
{
613
0
  struct stat stat_info;
614
615
0
  if (stat(pszPath, &stat_info) != 0)
616
0
    return FALSE;
617
618
0
  return TRUE;
619
0
}
620
621
BOOL PathFileExistsW(LPCWSTR pszPath)
622
0
{
623
0
  LPSTR lpFileNameA = NULL;
624
0
  BOOL ret = FALSE;
625
626
0
  if (!pszPath)
627
0
    goto fail;
628
0
  lpFileNameA = ConvertWCharToUtf8Alloc(pszPath, NULL);
629
0
  if (!lpFileNameA)
630
0
    goto fail;
631
632
0
  ret = winpr_PathFileExists(lpFileNameA);
633
0
fail:
634
0
  free(lpFileNameA);
635
0
  return ret;
636
0
}
637
638
BOOL PathIsDirectoryEmptyA(LPCSTR pszPath)
639
0
{
640
0
  struct dirent* dp;
641
0
  int empty = 1;
642
0
  DIR* dir = opendir(pszPath);
643
644
0
  if (dir == NULL) /* Not a directory or doesn't exist */
645
0
    return 1;
646
647
0
  while ((dp = readdir(dir)) != NULL)
648
0
  {
649
0
    if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
650
0
      continue; /* Skip . and .. */
651
652
0
    empty = 0;
653
0
    break;
654
0
  }
655
656
0
  closedir(dir);
657
0
  return empty;
658
0
}
659
660
BOOL PathIsDirectoryEmptyW(LPCWSTR pszPath)
661
0
{
662
0
  LPSTR lpFileNameA = NULL;
663
0
  BOOL ret = FALSE;
664
0
  if (!pszPath)
665
0
    goto fail;
666
0
  lpFileNameA = ConvertWCharToUtf8Alloc(pszPath, NULL);
667
0
  if (!lpFileNameA)
668
0
    goto fail;
669
0
  ret = PathIsDirectoryEmptyA(lpFileNameA);
670
0
fail:
671
0
  free(lpFileNameA);
672
0
  return ret;
673
0
}
674
675
#else
676
677
#ifdef _MSC_VER
678
#pragma comment(lib, "shlwapi.lib")
679
#endif
680
681
#endif
682
683
BOOL winpr_MoveFile(LPCSTR lpExistingFileName, LPCSTR lpNewFileName)
684
0
{
685
0
#ifndef _WIN32
686
0
  return MoveFileA(lpExistingFileName, lpNewFileName);
687
#else
688
  BOOL result = FALSE;
689
  LPWSTR lpExistingFileNameW = NULL;
690
  LPWSTR lpNewFileNameW = NULL;
691
692
  if (!lpExistingFileName || !lpNewFileName)
693
    return FALSE;
694
695
  lpExistingFileNameW = ConvertUtf8ToWCharAlloc(lpExistingFileName, NULL);
696
  if (!lpExistingFileNameW)
697
    goto cleanup;
698
  lpNewFileNameW = ConvertUtf8ToWCharAlloc(lpNewFileName, NULL);
699
  if (!lpNewFileNameW)
700
    goto cleanup;
701
702
  result = MoveFileW(lpExistingFileNameW, lpNewFileNameW);
703
704
cleanup:
705
  free(lpExistingFileNameW);
706
  free(lpNewFileNameW);
707
  return result;
708
#endif
709
0
}
710
711
BOOL winpr_MoveFileEx(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags)
712
0
{
713
0
#ifndef _WIN32
714
0
  return MoveFileExA(lpExistingFileName, lpNewFileName, dwFlags);
715
#else
716
  BOOL result = FALSE;
717
  LPWSTR lpExistingFileNameW = NULL;
718
  LPWSTR lpNewFileNameW = NULL;
719
720
  if (!lpExistingFileName || !lpNewFileName)
721
    return FALSE;
722
723
  lpExistingFileNameW = ConvertUtf8ToWCharAlloc(lpExistingFileName, NULL);
724
  if (!lpExistingFileNameW)
725
    goto cleanup;
726
  lpNewFileNameW = ConvertUtf8ToWCharAlloc(lpNewFileName, NULL);
727
  if (!lpNewFileNameW)
728
    goto cleanup;
729
730
  result = MoveFileExW(lpExistingFileNameW, lpNewFileNameW, dwFlags);
731
732
cleanup:
733
  free(lpExistingFileNameW);
734
  free(lpNewFileNameW);
735
  return result;
736
#endif
737
0
}
738
739
BOOL winpr_DeleteFile(const char* lpFileName)
740
0
{
741
0
#ifndef _WIN32
742
0
  return DeleteFileA(lpFileName);
743
#else
744
  LPWSTR lpFileNameW = NULL;
745
  BOOL result = FALSE;
746
747
  if (lpFileName)
748
  {
749
    lpFileNameW = ConvertUtf8ToWCharAlloc(lpFileName, NULL);
750
    if (!lpFileNameW)
751
      goto cleanup;
752
  }
753
754
  result = DeleteFileW(lpFileNameW);
755
756
cleanup:
757
  free(lpFileNameW);
758
  return result;
759
#endif
760
0
}
761
762
BOOL winpr_RemoveDirectory(LPCSTR lpPathName)
763
0
{
764
0
#ifndef _WIN32
765
0
  return RemoveDirectoryA(lpPathName);
766
#else
767
  LPWSTR lpPathNameW = NULL;
768
  BOOL result = FALSE;
769
770
  if (lpPathName)
771
  {
772
    lpPathNameW = ConvertUtf8ToWCharAlloc(lpPathName, NULL);
773
    if (!lpPathNameW)
774
      goto cleanup;
775
  }
776
777
  result = RemoveDirectoryW(lpPathNameW);
778
779
cleanup:
780
  free(lpPathNameW);
781
  return result;
782
#endif
783
0
}
784
785
BOOL winpr_PathFileExists(const char* pszPath)
786
0
{
787
0
  if (!pszPath)
788
0
    return FALSE;
789
0
#ifndef _WIN32
790
0
  return PathFileExistsA(pszPath);
791
#else
792
  WCHAR* pathW = ConvertUtf8ToWCharAlloc(pszPath, NULL);
793
  BOOL result = FALSE;
794
795
  if (!pathW)
796
    return FALSE;
797
798
  result = PathFileExistsW(pathW);
799
  free(pathW);
800
801
  return result;
802
#endif
803
0
}
804
805
BOOL winpr_PathMakePath(const char* path, LPSECURITY_ATTRIBUTES lpAttributes)
806
0
{
807
0
  if (!path)
808
0
    return FALSE;
809
0
#ifndef _WIN32
810
0
  return PathMakePathA(path, lpAttributes);
811
#else
812
  WCHAR* pathW = ConvertUtf8ToWCharAlloc(path, NULL);
813
  BOOL result = FALSE;
814
815
  if (!pathW)
816
    return FALSE;
817
818
  result = SHCreateDirectoryExW(NULL, pathW, lpAttributes) == ERROR_SUCCESS;
819
  free(pathW);
820
821
  return result;
822
#endif
823
0
}