CreateFileA and CreateFileW are forbidden calls in UWP. CreateFile2 is close enough, some parameters are passed in a structure and it requires a WCHAR filename. Given the original stat uses the "multibyte code page currently in use" [1], the char should be converted using CP_ACP [2].
[1] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/stat-functions [2] https://learn.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-multibytetowidechar#parameters --- lib/spawni.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/stat.c | 35 +++++++++++++++++++++++++++++++++++ lib/utime.c | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) diff --git a/lib/spawni.c b/lib/spawni.c index cc9511fdd8..27397cc688 100644 --- a/lib/spawni.c +++ b/lib/spawni.c @@ -402,6 +402,7 @@ open_handle (const char *name, int flags, mode_t mode) sec_attr.nLength = sizeof (SECURITY_ATTRIBUTES); sec_attr.lpSecurityDescriptor = NULL; sec_attr.bInheritHandle = TRUE; +# if !defined WINAPI_FAMILY || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) HANDLE handle = CreateFile (rname, ((flags & (O_WRONLY | O_RDWR)) != 0 @@ -427,6 +428,54 @@ open_handle (const char *name, int flags, mode_t mode) | ((flags & O_SEQUENTIAL ) != 0 ? FILE_FLAG_SEQUENTIAL_SCAN : 0) | ((flags & O_RANDOM) != 0 ? FILE_FLAG_RANDOM_ACCESS : 0), NULL); +# else /* ! WINAPI_PARTITION_DESKTOP */ + /* Only CreateFile2 is available in UWP builds. + <https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2> + <https://learn.microsoft.com/en-us/uwp/win32-and-com/win32-apis#apis-from-api-ms-win-core-file-l1-2-1dll> */ + HANDLE handle = INVALID_HANDLE_VALUE; + int wlen = MultiByteToWideChar (CP_ACP, 0, rname, -1, NULL, 0); + if (wlen > 0) + { + WCHAR *wrname = malloca (wlen * sizeof (WCHAR)); + if (wrname != NULL) + { + MultiByteToWideChar (CP_ACP, 0, rname, -1, wrname, wlen); + + CREATEFILE2_EXTENDED_PARAMETERS createExParams; + createExParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); + createExParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + /* FILE_FLAG_BACKUP_SEMANTICS is useful for opening directories, + which is out-of-scope here. */ + /* FILE_FLAG_POSIX_SEMANTICS (treat file names that differ only + in case as different) makes sense only when applied to *all* + filesystem operations. */ + /* FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS */ + createExParams.dwFileFlags = 0 + | ((flags & O_TEMPORARY) != 0 ? FILE_FLAG_DELETE_ON_CLOSE : 0) + | ((flags & O_SEQUENTIAL ) != 0 ? FILE_FLAG_SEQUENTIAL_SCAN : 0) + | ((flags & O_RANDOM) != 0 ? FILE_FLAG_RANDOM_ACCESS : 0); + createExParams.dwSecurityQosFlags = 0; + createExParams.lpSecurityAttributes = &sec_attr; + createExParams.hTemplateFile = NULL; + + handle = + CreateFile2 (wrname, + ((flags & (O_WRONLY | O_RDWR)) != 0 + ? GENERIC_READ | GENERIC_WRITE + : GENERIC_READ), + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + ((flags & O_CREAT) != 0 + ? ((flags & O_EXCL) != 0 + ? CREATE_NEW + : ((flags & O_TRUNC) != 0 ? CREATE_ALWAYS : OPEN_ALWAYS)) + : ((flags & O_TRUNC) != 0 + ? TRUNCATE_EXISTING + : OPEN_EXISTING)), + &createExParams); + freea(wrname); + } + } +# endif /* ! WINAPI_PARTITION_DESKTOP */ if (handle == INVALID_HANDLE_VALUE) switch (GetLastError ()) { diff --git a/lib/stat.c b/lib/stat.c index 7987e26583..a8fcc84792 100644 --- a/lib/stat.c +++ b/lib/stat.c @@ -197,6 +197,7 @@ rpl_stat (char const *name, struct stat *buf) { /* Approach based on the file. */ +# if !defined WINAPI_FAMILY || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) /* Open a handle to the file. CreateFile <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilea> @@ -212,6 +213,40 @@ rpl_stat (char const *name, struct stat *buf) filesystem operations. */ FILE_FLAG_BACKUP_SEMANTICS /* | FILE_FLAG_POSIX_SEMANTICS */, NULL); +# else /* ! WINAPI_PARTITION_DESKTOP */ + /* Only CreateFile2 is available in UWP builds. + <https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2> + <https://learn.microsoft.com/en-us/uwp/win32-and-com/win32-apis#apis-from-api-ms-win-core-file-l1-2-1dll> */ + HANDLE h = INVALID_HANDLE_VALUE; + int wlen = MultiByteToWideChar (CP_ACP, 0, rname, -1, NULL, 0); + if (wlen > 0) + { + WCHAR *wrname = malloca (wlen * sizeof (WCHAR)); + if (wrname != NULL) + { + MultiByteToWideChar (CP_ACP, 0, rname, -1, wrname, wlen); + + CREATEFILE2_EXTENDED_PARAMETERS createExParams; + createExParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); + createExParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + /* FILE_FLAG_POSIX_SEMANTICS (treat file names that differ only + in case as different) makes sense only when applied to *all* + filesystem operations. */ + createExParams.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS /* | FILE_FLAG_POSIX_SEMANTICS */; + createExParams.dwSecurityQosFlags = 0; + createExParams.lpSecurityAttributes = NULL; + createExParams.hTemplateFile = NULL; + + h = + CreateFile2 (wrname, + FILE_READ_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + OPEN_EXISTING, + &createExParams); + freea(wrname); + } + } +# endif /* ! WINAPI_PARTITION_DESKTOP */ if (h != INVALID_HANDLE_VALUE) { ret = _gl_fstat_by_handle (h, rname, buf); diff --git a/lib/utime.c b/lib/utime.c index 3cf1840feb..bc3b253d49 100644 --- a/lib/utime.c +++ b/lib/utime.c @@ -86,6 +86,7 @@ _gl_utimens_windows (const char *name, struct timespec ts[2]) DWORD error; +# if !defined WINAPI_FAMILY || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) /* Open a handle to the file. CreateFile <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilea> @@ -101,6 +102,40 @@ _gl_utimens_windows (const char *name, struct timespec ts[2]) filesystem operations. */ FILE_FLAG_BACKUP_SEMANTICS /* | FILE_FLAG_POSIX_SEMANTICS */, NULL); +# else /* ! WINAPI_PARTITION_DESKTOP */ + /* Only CreateFile2 is available in UWP builds. + <https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2> + <https://learn.microsoft.com/en-us/uwp/win32-and-com/win32-apis#apis-from-api-ms-win-core-file-l1-2-1dll> */ + HANDLE handle = INVALID_HANDLE_VALUE; + int wlen = MultiByteToWideChar (CP_ACP, 0, rname, -1, NULL, 0); + if (wlen > 0) + { + WCHAR *wrname = malloca (wlen * sizeof (WCHAR)); + if (wrname != NULL) + { + MultiByteToWideChar (CP_ACP, 0, rname, -1, wrname, wlen); + + CREATEFILE2_EXTENDED_PARAMETERS createExParams; + createExParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); + createExParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + /* FILE_FLAG_POSIX_SEMANTICS (treat file names that differ only + in case as different) makes sense only when applied to *all* + filesystem operations. */ + createExParams.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS /* | FILE_FLAG_POSIX_SEMANTICS */; + createExParams.dwSecurityQosFlags = 0; + createExParams.lpSecurityAttributes = NULL; + createExParams.hTemplateFile = NULL; + + handle = + CreateFile2 (wrname, + FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + OPEN_EXISTING, + &createExParams); + freea(wrname); + } + } +# endif /* ! WINAPI_PARTITION_DESKTOP */ if (handle == INVALID_HANDLE_VALUE) { error = GetLastError (); -- 2.39.2
