1 /* ----------------------------------------------------------------------------
2    (c) The University of Glasgow 2006, Lifted from Bases
3 
4    Useful Win32 bits
5    ------------------------------------------------------------------------- */
6 
7 #if defined(_WIN32)
8 
9 #include "HsBase.h"
10 #include <stdbool.h>
11 #include <stdint.h>
12 /* Using Secure APIs */
13 #define MINGW_HAS_SECURE_API 1
14 #include <wchar.h>
15 #include <windows.h>
16 
17 /* Copied from getTempFileNameErrorNo in base's cbits/Win32Utils.c in GHC 8.10.
18    Check there for any bugfixes first and please keep in sync when making
19    changes.  */
20 
__get_temp_file_name(wchar_t * pathName,wchar_t * prefix,wchar_t * suffix,uint32_t uUnique,wchar_t * tempFileName)21 bool __get_temp_file_name (wchar_t* pathName, wchar_t* prefix,
22                            wchar_t* suffix, uint32_t uUnique,
23                            wchar_t* tempFileName)
24 {
25   int retry = 5;
26   bool success = false;
27   while (retry > 0 && !success)
28     {
29       // TODO: This needs to handle long file names.
30       if (!GetTempFileNameW(pathName, prefix, uUnique, tempFileName))
31         {
32           maperrno();
33           return false;
34         }
35 
36       wchar_t* drive = malloc (sizeof(wchar_t) * _MAX_DRIVE);
37       wchar_t* dir   = malloc (sizeof(wchar_t) * _MAX_DIR);
38       wchar_t* fname = malloc (sizeof(wchar_t) * _MAX_FNAME);
39       if (_wsplitpath_s (tempFileName, drive, _MAX_DRIVE, dir, _MAX_DIR,
40                          fname, _MAX_FNAME, NULL, 0) != 0)
41         {
42           success = false;
43           maperrno ();
44         }
45       else
46         {
47           wchar_t* temp = _wcsdup (tempFileName);
48           if (wcsnlen(drive, _MAX_DRIVE) == 0)
49             swprintf_s(tempFileName, MAX_PATH, L"%s\%s%s",
50                       dir, fname, suffix);
51           else
52             swprintf_s(tempFileName, MAX_PATH, L"%s\%s\%s%s",
53                       drive, dir, fname, suffix);
54           success
55              = MoveFileExW(temp, tempFileName, MOVEFILE_WRITE_THROUGH
56                                                | MOVEFILE_COPY_ALLOWED) != 0;
57           errno = 0;
58           if (!success && (GetLastError () != ERROR_FILE_EXISTS || --retry < 0))
59             {
60               success = false;
61               maperrno ();
62               DeleteFileW (temp);
63             }
64 
65 
66           free(temp);
67         }
68 
69       free(drive);
70       free(dir);
71       free(fname);
72     }
73 
74   return success;
75 }
76 #endif