Coverage Report

Created: 2025-10-10 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/winpr/libwinpr/path/shell.c
Line
Count
Source
1
/**
2
 * WinPR: Windows Portable Runtime
3
 * Path Functions
4
 *
5
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 * 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
157k
{
88
157k
  DWORD nSize = 0;
89
157k
  DWORD nStatus = 0;
90
157k
  char* env = NULL;
91
92
157k
  nSize = GetEnvironmentVariableX(lpName, NULL, 0);
93
94
157k
  if (nSize > 0)
95
104k
  {
96
104k
    env = malloc(nSize);
97
98
104k
    if (!env)
99
0
      return NULL;
100
101
104k
    nStatus = GetEnvironmentVariableX(lpName, env, nSize);
102
103
104k
    if (nStatus != (nSize - 1))
104
0
    {
105
0
      free(env);
106
0
      return NULL;
107
0
    }
108
104k
  }
109
110
157k
  return env;
111
157k
}
112
113
static char* GetPath_HOME(void)
114
104k
{
115
104k
  char* path = NULL;
116
#ifdef _WIN32
117
  path = GetEnvAlloc("UserProfile");
118
#elif defined(__IOS__)
119
  path = ios_get_home();
120
#else
121
104k
  path = GetEnvAlloc("HOME");
122
104k
#endif
123
104k
  return path;
124
104k
}
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
52.4k
{
186
52.4k
  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
52.4k
  size_t size = 0;
195
52.4k
  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
52.4k
  path = GetEnvAlloc("XDG_CONFIG_HOME");
205
206
52.4k
  if (path)
207
0
    return path;
208
209
52.4k
  home = GetPath_HOME();
210
211
52.4k
  if (!home)
212
0
    home = GetPath_TEMP();
213
214
52.4k
  if (!home)
215
0
    return NULL;
216
217
52.4k
  size = strlen(home) + strlen("/.config") + 1;
218
52.4k
  path = (char*)malloc(size);
219
220
52.4k
  if (!path)
221
0
  {
222
0
    free(home);
223
0
    return NULL;
224
0
  }
225
226
52.4k
  (void)sprintf_s(path, size, "%s%s", home, "/.config");
227
52.4k
  free(home);
228
52.4k
#endif
229
52.4k
  return path;
230
52.4k
}
231
232
static char* GetPath_SYSTEM_CONFIG_HOME(void)
233
238k
{
234
238k
  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
238k
  path = _strdup(WINPR_INSTALL_SYSCONFDIR);
243
238k
#endif
244
238k
  return path;
245
238k
}
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
343k
{
353
343k
  char* path = NULL;
354
355
343k
  switch (id)
356
343k
  {
357
52.4k
    case KNOWN_PATH_HOME:
358
52.4k
      path = GetPath_HOME();
359
52.4k
      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
52.4k
    case KNOWN_PATH_XDG_CONFIG_HOME:
370
52.4k
      path = GetPath_XDG_CONFIG_HOME();
371
52.4k
      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
238k
    case KNOWN_PATH_SYSTEM_CONFIG_HOME:
382
238k
      path = GetPath_SYSTEM_CONFIG_HOME();
383
238k
      break;
384
385
0
    default:
386
0
      path = NULL;
387
0
      break;
388
343k
  }
389
390
343k
  if (!path)
391
0
    WLog_WARN(TAG, "Path %s is %p", GetKnownPathIdString(WINPR_ASSERTING_INT_CAST(int, id)),
392
343k
              path);
393
343k
  return path;
394
343k
}
395
396
char* GetKnownSubPath(eKnownPathTypes id, const char* path)
397
291k
{
398
291k
  char* knownPath = GetKnownPath(id);
399
291k
  if (!knownPath)
400
0
    return NULL;
401
402
291k
  char* subPath = GetCombinedPath(knownPath, path);
403
291k
  free(knownPath);
404
291k
  return subPath;
405
291k
}
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
582k
{
449
582k
  HRESULT status = 0;
450
582k
  char* subPathCpy = NULL;
451
582k
  size_t basePathLength = 0;
452
582k
  size_t subPathLength = 0;
453
454
582k
  if (basePath)
455
582k
    basePathLength = strlen(basePath);
456
457
582k
  if (subPath)
458
582k
    subPathLength = strlen(subPath);
459
460
582k
  const size_t length = basePathLength + subPathLength + 1;
461
582k
  char* path = (char*)calloc(1, length + 1);
462
463
582k
  if (!path)
464
0
    goto fail;
465
466
582k
  if (basePath)
467
582k
    CopyMemory(path, basePath, basePathLength);
468
469
582k
  if (FAILED(PathCchConvertStyleA(path, basePathLength, PATH_STYLE_NATIVE)))
470
0
    goto fail;
471
472
582k
  if (!subPath)
473
0
    return path;
474
475
582k
  subPathCpy = _strdup(subPath);
476
477
582k
  if (!subPathCpy)
478
0
    goto fail;
479
480
582k
  if (FAILED(PathCchConvertStyleA(subPathCpy, subPathLength, PATH_STYLE_NATIVE)))
481
0
    goto fail;
482
483
582k
  status = NativePathCchAppendA(path, length + 1, subPathCpy);
484
582k
  if (FAILED(status))
485
0
    goto fail;
486
487
582k
  free(subPathCpy);
488
582k
  return path;
489
490
0
fail:
491
0
  free(path);
492
0
  free(subPathCpy);
493
0
  return NULL;
494
582k
}
495
496
BOOL PathMakePathA(LPCSTR path, WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpAttributes)
497
0
{
498
#if defined(_UWP)
499
  return FALSE;
500
#elif defined(_WIN32)
501
  return (SHCreateDirectoryExA(NULL, path, lpAttributes) == ERROR_SUCCESS);
502
#else
503
0
  const char delim = PathGetSeparatorA(PATH_STYLE_NATIVE);
504
0
  char* dup = NULL;
505
0
  BOOL result = TRUE;
506
  /* we only operate on a non-null, absolute path */
507
#if defined(__OS2__)
508
509
  if (!path)
510
    return FALSE;
511
512
#else
513
514
0
  if (!path || *path != delim)
515
0
    return FALSE;
516
517
0
#endif
518
519
0
  if (!(dup = _strdup(path)))
520
0
    return FALSE;
521
522
#ifdef __OS2__
523
  p = (strlen(dup) > 3) && (dup[1] == ':') && (dup[2] == delim)) ? &dup[3] : dup;
524
525
  while (p)
526
#else
527
0
  for (char* p = dup; p;)
528
0
#endif
529
0
  {
530
0
    if ((p = strchr(p + 1, delim)))
531
0
      *p = '\0';
532
533
0
    if (mkdir(dup, 0777) != 0)
534
0
      if (errno != EEXIST)
535
0
      {
536
0
        result = FALSE;
537
0
        break;
538
0
      }
539
540
0
    if (p)
541
0
      *p = delim;
542
0
  }
543
544
0
  free(dup);
545
0
  return (result);
546
0
#endif
547
0
}
548
549
BOOL PathMakePathW(LPCWSTR path, WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpAttributes)
550
0
{
551
#if defined(_UWP)
552
  return FALSE;
553
#elif defined(_WIN32)
554
  return (SHCreateDirectoryExW(NULL, path, lpAttributes) == ERROR_SUCCESS);
555
#else
556
0
  const WCHAR wdelim = PathGetSeparatorW(PATH_STYLE_NATIVE);
557
0
  const char delim = PathGetSeparatorA(PATH_STYLE_NATIVE);
558
0
  char* dup = NULL;
559
0
  BOOL result = TRUE;
560
  /* we only operate on a non-null, absolute path */
561
#if defined(__OS2__)
562
563
  if (!path)
564
    return FALSE;
565
566
#else
567
568
0
  if (!path || *path != wdelim)
569
0
    return FALSE;
570
571
0
#endif
572
573
0
  dup = ConvertWCharToUtf8Alloc(path, NULL);
574
0
  if (!dup)
575
0
    return FALSE;
576
577
#ifdef __OS2__
578
  p = (strlen(dup) > 3) && (dup[1] == ':') && (dup[2] == delim)) ? &dup[3] : dup;
579
580
  while (p)
581
#else
582
0
  for (char* p = dup; p;)
583
0
#endif
584
0
  {
585
0
    if ((p = strchr(p + 1, delim)))
586
0
      *p = '\0';
587
588
0
    if (mkdir(dup, 0777) != 0)
589
0
      if (errno != EEXIST)
590
0
      {
591
0
        result = FALSE;
592
0
        break;
593
0
      }
594
595
0
    if (p)
596
0
      *p = delim;
597
0
  }
598
599
0
  free(dup);
600
0
  return (result);
601
0
#endif
602
0
}
603
604
#if !defined(_WIN32) || defined(_UWP)
605
606
BOOL PathIsRelativeA(LPCSTR pszPath)
607
0
{
608
0
  if (!pszPath)
609
0
    return FALSE;
610
611
0
  return pszPath[0] != '/';
612
0
}
613
614
BOOL PathIsRelativeW(LPCWSTR pszPath)
615
0
{
616
0
  LPSTR lpFileNameA = NULL;
617
0
  BOOL ret = FALSE;
618
619
0
  if (!pszPath)
620
0
    goto fail;
621
622
0
  lpFileNameA = ConvertWCharToUtf8Alloc(pszPath, NULL);
623
0
  if (!lpFileNameA)
624
0
    goto fail;
625
0
  ret = PathIsRelativeA(lpFileNameA);
626
0
fail:
627
0
  free(lpFileNameA);
628
0
  return ret;
629
0
}
630
631
BOOL PathFileExistsA(LPCSTR pszPath)
632
0
{
633
0
  struct stat stat_info;
634
635
0
  if (stat(pszPath, &stat_info) != 0)
636
0
    return FALSE;
637
638
0
  return TRUE;
639
0
}
640
641
BOOL PathFileExistsW(LPCWSTR pszPath)
642
0
{
643
0
  LPSTR lpFileNameA = NULL;
644
0
  BOOL ret = FALSE;
645
646
0
  if (!pszPath)
647
0
    goto fail;
648
0
  lpFileNameA = ConvertWCharToUtf8Alloc(pszPath, NULL);
649
0
  if (!lpFileNameA)
650
0
    goto fail;
651
652
0
  ret = winpr_PathFileExists(lpFileNameA);
653
0
fail:
654
0
  free(lpFileNameA);
655
0
  return ret;
656
0
}
657
658
BOOL PathIsDirectoryEmptyA(LPCSTR pszPath)
659
0
{
660
0
  struct dirent* dp = NULL;
661
0
  int empty = 1;
662
0
  DIR* dir = opendir(pszPath);
663
664
0
  if (dir == NULL) /* Not a directory or doesn't exist */
665
0
    return 1;
666
667
  // NOLINTNEXTLINE(concurrency-mt-unsafe)
668
0
  while ((dp = readdir(dir)) != NULL)
669
0
  {
670
0
    if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
671
0
      continue; /* Skip . and .. */
672
673
0
    empty = 0;
674
0
    break;
675
0
  }
676
677
0
  closedir(dir);
678
0
  return empty;
679
0
}
680
681
BOOL PathIsDirectoryEmptyW(LPCWSTR pszPath)
682
0
{
683
0
  LPSTR lpFileNameA = NULL;
684
0
  BOOL ret = FALSE;
685
0
  if (!pszPath)
686
0
    goto fail;
687
0
  lpFileNameA = ConvertWCharToUtf8Alloc(pszPath, NULL);
688
0
  if (!lpFileNameA)
689
0
    goto fail;
690
0
  ret = PathIsDirectoryEmptyA(lpFileNameA);
691
0
fail:
692
0
  free(lpFileNameA);
693
0
  return ret;
694
0
}
695
696
#endif
697
698
BOOL winpr_MoveFile(LPCSTR lpExistingFileName, LPCSTR lpNewFileName)
699
0
{
700
0
  return winpr_MoveFileEx(lpExistingFileName, lpNewFileName, 0);
701
0
}
702
703
BOOL winpr_MoveFileEx(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags)
704
0
{
705
0
#ifndef _WIN32
706
0
  struct stat st;
707
0
  int ret = 0;
708
0
  ret = stat(lpNewFileName, &st);
709
710
0
  if ((dwFlags & MOVEFILE_REPLACE_EXISTING) == 0)
711
0
  {
712
0
    if (ret == 0)
713
0
    {
714
0
      SetLastError(ERROR_ALREADY_EXISTS);
715
0
      return FALSE;
716
0
    }
717
0
  }
718
0
  else
719
0
  {
720
0
    if (ret == 0 && (st.st_mode & S_IWUSR) == 0)
721
0
    {
722
0
      SetLastError(ERROR_ACCESS_DENIED);
723
0
      return FALSE;
724
0
    }
725
0
  }
726
727
0
  ret = rename(lpExistingFileName, lpNewFileName);
728
729
0
  if (ret != 0)
730
0
    SetLastError(map_posix_err(errno));
731
732
0
  return ret == 0;
733
#else
734
  BOOL result = FALSE;
735
  LPWSTR lpExistingFileNameW = NULL;
736
  LPWSTR lpNewFileNameW = NULL;
737
738
  if (!lpExistingFileName || !lpNewFileName)
739
    return FALSE;
740
741
  lpExistingFileNameW = ConvertUtf8ToWCharAlloc(lpExistingFileName, NULL);
742
  if (!lpExistingFileNameW)
743
    goto cleanup;
744
  lpNewFileNameW = ConvertUtf8ToWCharAlloc(lpNewFileName, NULL);
745
  if (!lpNewFileNameW)
746
    goto cleanup;
747
748
  result = MoveFileExW(lpExistingFileNameW, lpNewFileNameW, dwFlags);
749
750
cleanup:
751
  free(lpExistingFileNameW);
752
  free(lpNewFileNameW);
753
  return result;
754
#endif
755
0
}
756
757
BOOL winpr_DeleteFile(const char* lpFileName)
758
0
{
759
0
#ifndef _WIN32
760
0
  if (!lpFileName)
761
0
    return FALSE;
762
763
0
  const int status = unlink(lpFileName);
764
0
  return (status != -1) ? TRUE : FALSE;
765
#else
766
  LPWSTR lpFileNameW = NULL;
767
  BOOL result = FALSE;
768
769
  if (lpFileName)
770
    lpFileNameW = ConvertUtf8ToWCharAlloc(lpFileName, NULL);
771
772
  if (!lpFileNameW)
773
    goto cleanup;
774
775
  result = DeleteFileW(lpFileNameW);
776
777
cleanup:
778
  free(lpFileNameW);
779
  return result;
780
#endif
781
0
}
782
783
BOOL winpr_RemoveDirectory(LPCSTR lpPathName)
784
0
{
785
0
#ifndef _WIN32
786
0
  int ret = rmdir(lpPathName);
787
788
0
  if (ret != 0)
789
0
    SetLastError(map_posix_err(errno));
790
0
  else
791
0
    SetLastError(STATUS_SUCCESS);
792
793
0
  return ret == 0;
794
#else
795
  LPWSTR lpPathNameW = NULL;
796
  BOOL result = FALSE;
797
798
  if (lpPathName)
799
    lpPathNameW = ConvertUtf8ToWCharAlloc(lpPathName, NULL);
800
801
  if (!lpPathNameW)
802
    goto cleanup;
803
804
  result = RemoveDirectoryW(lpPathNameW);
805
806
cleanup:
807
  free(lpPathNameW);
808
  return result;
809
#endif
810
0
}
811
812
BOOL winpr_PathFileExists(const char* pszPath)
813
0
{
814
0
  if (!pszPath)
815
0
    return FALSE;
816
0
#ifndef _WIN32
817
0
  return PathFileExistsA(pszPath);
818
#else
819
  WCHAR* pathW = ConvertUtf8ToWCharAlloc(pszPath, NULL);
820
  BOOL result = FALSE;
821
822
  if (!pathW)
823
    return FALSE;
824
825
  result = PathFileExistsW(pathW);
826
  free(pathW);
827
828
  return result;
829
#endif
830
0
}
831
832
BOOL winpr_PathMakePath(const char* path, LPSECURITY_ATTRIBUTES lpAttributes)
833
0
{
834
0
  if (!path)
835
0
    return FALSE;
836
0
#ifndef _WIN32
837
0
  return PathMakePathA(path, lpAttributes);
838
#else
839
  WCHAR* pathW = ConvertUtf8ToWCharAlloc(path, NULL);
840
  BOOL result = FALSE;
841
842
  if (!pathW)
843
    return FALSE;
844
845
  result = SHCreateDirectoryExW(NULL, pathW, lpAttributes) == ERROR_SUCCESS;
846
  free(pathW);
847
848
  return result;
849
#endif
850
0
}