Issue #23524: Replace _PyVerify_fd function with calls to _set_thread_local_invalid_parameter_handler.
diff --git a/Python/fileutils.c b/Python/fileutils.c
index 64368f3..bccd321 100644
--- a/Python/fileutils.c
+++ b/Python/fileutils.c
@@ -5,6 +5,7 @@
 #ifdef MS_WINDOWS
 #  include <malloc.h>
 #  include <windows.h>
+extern int winerror_to_errno(int);
 #endif
 
 #ifdef HAVE_LANGINFO_H
@@ -41,9 +42,13 @@
 #if defined(MS_WINDOWS)
     UINT cp;
 #endif
-    if (!_PyVerify_fd(fd) || !isatty(fd)) {
+    int valid;
+    _Py_BEGIN_SUPPRESS_IPH
+    valid = _PyVerify_fd(fd) && isatty(fd);
+    _Py_END_SUPPRESS_IPH
+    if (!valid)
         Py_RETURN_NONE;
-    }
+
 #if defined(MS_WINDOWS)
     if (fd == 0)
         cp = GetConsoleCP();
@@ -610,16 +615,15 @@
 
     if (!_PyVerify_fd(fd))
         h = INVALID_HANDLE_VALUE;
-    else
+    else {
+        _Py_BEGIN_SUPPRESS_IPH
         h = (HANDLE)_get_osfhandle(fd);
-
-    /* Protocol violation: we explicitly clear errno, instead of
-       setting it to a POSIX error. Callers should use GetLastError. */
-    errno = 0;
+        _Py_END_SUPPRESS_IPH
+    }
 
     if (h == INVALID_HANDLE_VALUE) {
-        /* This is really a C library error (invalid file handle).
-           We set the Win32 error to the closes one matching. */
+        /* errno is already set by _get_osfhandle, but we also set
+           the Win32 error for callers who expect that */
         SetLastError(ERROR_INVALID_HANDLE);
         return -1;
     }
@@ -628,8 +632,10 @@
     type = GetFileType(h);
     if (type == FILE_TYPE_UNKNOWN) {
         DWORD error = GetLastError();
-        if (error != 0)
+        if (error != 0) {
+            errno = winerror_to_errno(error);
             return -1;
+        }
         /* else: valid but unknown file */
     }
 
@@ -642,6 +648,9 @@
     }
 
     if (!GetFileInformationByHandle(h, &info)) {
+        /* The Win32 error is already set, but we also set errno for
+           callers who expect it */
+        errno = winerror_to_errno(GetLastError());
         return -1;
     }
 
@@ -735,7 +744,9 @@
         return -1;
     }
 
+    _Py_BEGIN_SUPPRESS_IPH
     handle = (HANDLE)_get_osfhandle(fd);
+    _Py_END_SUPPRESS_IPH
     if (handle == INVALID_HANDLE_VALUE) {
         if (raise)
             PyErr_SetFromErrno(PyExc_OSError);
@@ -810,7 +821,9 @@
         return -1;
     }
 
+    _Py_BEGIN_SUPPRESS_IPH
     handle = (HANDLE)_get_osfhandle(fd);
+    _Py_END_SUPPRESS_IPH
     if (handle == INVALID_HANDLE_VALUE) {
         if (raise)
             PyErr_SetFromErrno(PyExc_OSError);
@@ -1171,6 +1184,7 @@
     }
 #endif
 
+    _Py_BEGIN_SUPPRESS_IPH
     do {
         Py_BEGIN_ALLOW_THREADS
         errno = 0;
@@ -1185,6 +1199,7 @@
         Py_END_ALLOW_THREADS
     } while (n < 0 && err == EINTR &&
             !(async_err = PyErr_CheckSignals()));
+    _Py_END_SUPPRESS_IPH
 
     if (async_err) {
         /* read() was interrupted by a signal (failed with EINTR)
@@ -1219,6 +1234,7 @@
         return -1;
     }
 
+    _Py_BEGIN_SUPPRESS_IPH
 #ifdef MS_WINDOWS
     if (count > 32767 && isatty(fd)) {
         /* Issue #11395: the Windows console returns an error (12: not
@@ -1264,6 +1280,7 @@
             err = errno;
         } while (n < 0 && err == EINTR);
     }
+    _Py_END_SUPPRESS_IPH
 
     if (async_err) {
         /* write() was interrupted by a signal (failed with EINTR)
@@ -1451,7 +1468,9 @@
     }
 
 #ifdef MS_WINDOWS
+    _Py_BEGIN_SUPPRESS_IPH
     handle = (HANDLE)_get_osfhandle(fd);
+    _Py_END_SUPPRESS_IPH
     if (handle == INVALID_HANDLE_VALUE) {
         PyErr_SetFromErrno(PyExc_OSError);
         return -1;
@@ -1461,7 +1480,9 @@
     ftype = GetFileType(handle);
 
     Py_BEGIN_ALLOW_THREADS
+    _Py_BEGIN_SUPPRESS_IPH
     fd = dup(fd);
+    _Py_END_SUPPRESS_IPH
     Py_END_ALLOW_THREADS
     if (fd < 0) {
         PyErr_SetFromErrno(PyExc_OSError);
@@ -1471,13 +1492,17 @@
     /* Character files like console cannot be make non-inheritable */
     if (ftype != FILE_TYPE_CHAR) {
         if (_Py_set_inheritable(fd, 0, NULL) < 0) {
+            _Py_BEGIN_SUPPRESS_IPH
             close(fd);
+            _Py_END_SUPPRESS_IPH
             return -1;
         }
     }
 #elif defined(HAVE_FCNTL_H) && defined(F_DUPFD_CLOEXEC)
     Py_BEGIN_ALLOW_THREADS
+    _Py_BEGIN_SUPPRESS_IPH
     fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
+    _Py_END_SUPPRESS_IPH
     Py_END_ALLOW_THREADS
     if (fd < 0) {
         PyErr_SetFromErrno(PyExc_OSError);
@@ -1486,7 +1511,9 @@
 
 #else
     Py_BEGIN_ALLOW_THREADS
+    _Py_BEGIN_SUPPRESS_IPH
     fd = dup(fd);
+    _Py_END_SUPPRESS_IPH
     Py_END_ALLOW_THREADS
     if (fd < 0) {
         PyErr_SetFromErrno(PyExc_OSError);
@@ -1494,7 +1521,9 @@
     }
 
     if (_Py_set_inheritable(fd, 0, NULL) < 0) {
+        _Py_BEGIN_SUPPRESS_IPH
         close(fd);
+        _Py_END_SUPPRESS_IPH
         return -1;
     }
 #endif
@@ -1508,7 +1537,10 @@
 int
 _Py_get_blocking(int fd)
 {
-    int flags = fcntl(fd, F_GETFL, 0);
+    int flags;
+    _Py_BEGIN_SUPPRESS_IPH
+    flags = fcntl(fd, F_GETFL, 0);
+    _Py_END_SUPPRESS_IPH
     if (flags < 0) {
         PyErr_SetFromErrno(PyExc_OSError);
         return -1;
@@ -1533,16 +1565,20 @@
 #else
     int flags, res;
 
+    _Py_BEGIN_SUPPRESS_IPH
     flags = fcntl(fd, F_GETFL, 0);
-    if (flags < 0)
-        goto error;
+    if (flags >= 0) {
+        if (blocking)
+            flags = flags & (~O_NONBLOCK);
+        else
+            flags = flags | O_NONBLOCK;
 
-    if (blocking)
-        flags = flags & (~O_NONBLOCK);
-    else
-        flags = flags | O_NONBLOCK;
+        res = fcntl(fd, F_SETFL, flags);
+    } else {
+        res = -1;
+    }
+    _Py_END_SUPPRESS_IPH
 
-    res = fcntl(fd, F_SETFL, flags);
     if (res < 0)
         goto error;
 #endif
@@ -1554,25 +1590,7 @@
 }
 #endif
 
-#ifdef _MSC_VER
-#if _MSC_VER >= 1900
-
-/* This function lets the Windows CRT validate the file handle without
-   terminating the process if it's invalid. */
-int
-_PyVerify_fd(int fd)
-{
-    intptr_t osh;
-    /* Fast check for the only condition we know */
-    if (fd < 0) {
-        _set_errno(EBADF);
-        return 0;
-    }
-    osh = _get_osfhandle(fd);
-    return osh != (intptr_t)-1;
-}
-
-#elif _MSC_VER >= 1400
+#if defined _MSC_VER && _MSC_VER >= 1400 && _MSC_VER < 1900
 /* Legacy implementation of _PyVerify_fd while transitioning to
  * MSVC 14.0. This should eventually be removed. (issue23524)
  */
@@ -1651,5 +1669,4 @@
     return 0;
 }
 
-#endif /* _MSC_VER >= 1900 || _MSC_VER >= 1400 */
-#endif /* defined _MSC_VER */
+#endif /* defined _MSC_VER && _MSC_VER >= 1400 && _MSC_VER < 1900 */