Coverage Report

Created: 2025-07-01 06:46

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