From 6ad73caa893d0f90b25b38c9d9350c7dd92a1c55 Mon Sep 17 00:00:00 2001 From: thexai <58434170+thexai@users.noreply.github.com> Date: Sat, 4 Jul 2026 13:30:32 +0200 Subject: [PATCH] gh-152433: Windows: use ``CreateFile2`` on Windows UWP build UWP does not support ``CreateFileW`` because it is only compatible with the Win32 desktop API. --- Include/internal/pycore_fileutils_windows.h | 27 +++++++++++++++++++ ...-07-04-13-33-04.gh-issue-152433.0EUfvN.rst | 1 + Modules/_winapi.c | 5 ++-- Modules/getpath.c | 3 ++- Modules/overlapped.c | 8 ++++-- Modules/posixmodule.c | 22 +++++++-------- 6 files changed, 50 insertions(+), 16 deletions(-) create mode 100644 Misc/NEWS.d/next/Windows/2026-07-04-13-33-04.gh-issue-152433.0EUfvN.rst diff --git a/Include/internal/pycore_fileutils_windows.h b/Include/internal/pycore_fileutils_windows.h index b79aa9fb465376..4a8c4d99baae59 100644 --- a/Include/internal/pycore_fileutils_windows.h +++ b/Include/internal/pycore_fileutils_windows.h @@ -93,6 +93,33 @@ static inline BOOL _Py_GetFileInformationByName_ErrorIsTrustworthy(int error) return FALSE; } +static inline HANDLE _Py_WinCreateFile( + _In_ LPCWSTR lpFileName, + _In_ DWORD dwDesiredAccess, + _In_ DWORD dwShareMode, + _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, + _In_ DWORD dwCreationDisposition, + _In_ DWORD dwFlagsAndAttributes, + _In_opt_ HANDLE hTemplateFile +) +{ +#ifndef MS_WINDOWS_DESKTOP + if (dwShareMode == 0) + dwShareMode = FILE_SHARE_READ; + + CREATEFILE2_EXTENDED_PARAMETERS ext; + ZeroMemory(&ext, sizeof(CREATEFILE2_EXTENDED_PARAMETERS)); + ext.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); + ext.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + ext.dwFileFlags = dwFlagsAndAttributes & 0xFFFF0000; + + return CreateFile2(lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, &ext); +#else + return CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, + dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); +#endif +} + #endif #endif diff --git a/Misc/NEWS.d/next/Windows/2026-07-04-13-33-04.gh-issue-152433.0EUfvN.rst b/Misc/NEWS.d/next/Windows/2026-07-04-13-33-04.gh-issue-152433.0EUfvN.rst new file mode 100644 index 00000000000000..0eb90a73e78463 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2026-07-04-13-33-04.gh-issue-152433.0EUfvN.rst @@ -0,0 +1 @@ +Use ``CreateFile2`` on Windows UWP build. diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 535784adedb24d..ce48a6516d08e5 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -48,6 +48,7 @@ #include #include #include "winreparse.h" +#include "internal/pycore_fileutils_windows.h" // PSAPI_VERSION=2 redirects GetProcessMemoryInfo() to // K32GetProcessMemoryInfo() in kernel32.dll, so we don't need to link @@ -546,7 +547,7 @@ _winapi_CreateFile_impl(PyObject *module, LPCWSTR file_name, } Py_BEGIN_ALLOW_THREADS - handle = CreateFileW(file_name, desired_access, + handle = _Py_WinCreateFile(file_name, desired_access, share_mode, security_attributes, creation_disposition, flags_and_attributes, template_file); @@ -721,7 +722,7 @@ _winapi_CreateJunction_impl(PyObject *module, LPCWSTR src_path, if (!CreateDirectoryW(dst_path, NULL)) goto cleanup; - junction = CreateFileW(dst_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, + junction = _Py_WinCreateFile(dst_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); if (junction == INVALID_HANDLE_VALUE) diff --git a/Modules/getpath.c b/Modules/getpath.c index 0c80678a678dc8..b7b39651cc0dc2 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -14,6 +14,7 @@ #ifdef MS_WINDOWS # include // GetFullPathNameW(), MAX_PATH # include +# include "internal/pycore_fileutils_windows.h" #endif #ifdef __APPLE__ @@ -527,7 +528,7 @@ getpath_realpath(PyObject *Py_UNUSED(self) , PyObject *args) } Py_BEGIN_ALLOW_THREADS - hFile = CreateFileW(path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + hFile = _Py_WinCreateFile(path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (hFile != INVALID_HANDLE_VALUE) { len = GetFinalPathNameByHandleW(hFile, resolved, MAXPATHLEN, VOLUME_NAME_DOS); err = len ? 0 : GetLastError(); diff --git a/Modules/overlapped.c b/Modules/overlapped.c index 255576cc057cdd..b9eddd74411a45 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -14,7 +14,11 @@ #include "Python.h" #include "pycore_tuple.h" // _PyTuple_FromPairSteal -#define WINDOWS_LEAN_AND_MEAN +#ifdef MS_WINDOWS +# define WINDOWS_LEAN_AND_MEAN +# include "internal/pycore_fileutils_windows.h" +#endif + #include #include #include @@ -1635,7 +1639,7 @@ _overlapped_Overlapped_ConnectPipe_impl(OverlappedObject *self, HANDLE PipeHandle; Py_BEGIN_ALLOW_THREADS - PipeHandle = CreateFileW(Address, + PipeHandle = _Py_WinCreateFile(Address, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 57db175336702e..3b5c99085d0cfd 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -2124,7 +2124,7 @@ win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result, flags |= FILE_FLAG_OPEN_REPARSE_POINT; } - hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL); + hFile = _Py_WinCreateFile(path, access, 0, NULL, OPEN_EXISTING, flags, NULL); if (hFile == INVALID_HANDLE_VALUE) { /* Either the path doesn't exist, or the caller lacks access. */ error = GetLastError(); @@ -2159,7 +2159,7 @@ win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result, case ERROR_INVALID_PARAMETER: /* \\.\con requires read or write access. */ - hFile = CreateFileW(path, access | GENERIC_READ, + hFile = _Py_WinCreateFile(path, access | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, flags, NULL); if (hFile == INVALID_HANDLE_VALUE) { @@ -2173,7 +2173,7 @@ win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result, if (traverse) { traverse = FALSE; isUnhandledTag = TRUE; - hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, + hFile = _Py_WinCreateFile(path, access, 0, NULL, OPEN_EXISTING, flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL); } if (hFile == INVALID_HANDLE_VALUE) { @@ -4107,7 +4107,7 @@ os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, result = win32_fchmod(path->fd, mode); } else if (follow_symlinks) { - HANDLE hfile = CreateFileW(path->wide, + HANDLE hfile = _Py_WinCreateFile(path->wide, FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); @@ -5384,7 +5384,7 @@ os__path_isdevdrive_impl(PyObject *module, path_t *path) /* only care about local dev drives */ r = Py_False; } else { - HANDLE hVolume = CreateFileW( + HANDLE hVolume = _Py_WinCreateFile( volume, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, @@ -5532,7 +5532,7 @@ os__getfinalpathname_impl(PyObject *module, path_t *path) PyObject *result; Py_BEGIN_ALLOW_THREADS - hFile = CreateFileW( + hFile = _Py_WinCreateFile( path->wide, 0, /* desired access */ 0, /* share mode */ @@ -5807,7 +5807,7 @@ _testFileTypeByName(LPCWSTR path, int testedType) if (testedType != PY_IFREG && testedType != PY_IFDIR) { flags |= FILE_FLAG_OPEN_REPARSE_POINT; } - HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, + HANDLE hfile = _Py_WinCreateFile(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, flags, NULL); if (hfile != INVALID_HANDLE_VALUE) { BOOL result = _testFileTypeByHandle(hfile, testedType, FALSE); @@ -5863,7 +5863,7 @@ _testFileExistsByName(LPCWSTR path, BOOL followLinks) if (!followLinks) { flags |= FILE_FLAG_OPEN_REPARSE_POINT; } - HANDLE hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, + HANDLE hfile = _Py_WinCreateFile(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, flags, NULL); if (hfile != INVALID_HANDLE_VALUE) { if (followLinks) { @@ -5876,7 +5876,7 @@ _testFileExistsByName(LPCWSTR path, BOOL followLinks) if (!result) { return TRUE; } - hfile = CreateFileW(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, + hfile = _Py_WinCreateFile(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (hfile != INVALID_HANDLE_VALUE) { CloseHandle(hfile); @@ -7172,7 +7172,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS - hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0, + hFile = _Py_WinCreateFile(path->wide, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); Py_END_ALLOW_THREADS @@ -10954,7 +10954,7 @@ os_readlink_impl(PyObject *module, path_t *path, int dir_fd) /* First get a handle to the reparse point */ Py_BEGIN_ALLOW_THREADS - reparse_point_handle = CreateFileW( + reparse_point_handle = _Py_WinCreateFile( path->wide, 0, 0,