[libxslt] python: Support Python 3 on Windows



commit 5443ca169cb7517d394ed8c34442c7d94bef6837
Author: Nick Wellnhofer <wellnhofer aevum de>
Date:   Tue Sep 6 13:36:42 2022 +0200

    python: Support Python 3 on Windows
    
    Copy updated implementation of PyFileGET from libxml2.

 python/types.c | 190 +++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 165 insertions(+), 25 deletions(-)
---
diff --git a/python/types.c b/python/types.c
index 1617cb96..651f17dd 100644
--- a/python/types.c
+++ b/python/types.c
@@ -25,42 +25,182 @@ xmlParserInputPtr xmlNoNetExternalEntityLoader(const char *URL,
 
 #if PY_MAJOR_VERSION >= 3
 #include <stdio.h>
+#include <stdint.h>
+
+#ifdef _WIN32
+
+#include <windows.h>
+#include <crtdbg.h>
+
+/* Taken from info on MSDN site, as we may not have the Windows WDK/DDK headers */
+typedef struct _IO_STATUS_BLOCK {
+  union {
+    NTSTATUS Status;
+    PVOID    Pointer;
+  } DUMMYUNIONNAME;
+  ULONG_PTR Information;
+} IO_STATUS_BLOCK;
+
+typedef struct _FILE_ACCESS_INFORMATION {
+  ACCESS_MASK AccessFlags;
+} FILE_ACCESS_INFORMATION;
+
+typedef NTSTATUS (*t_NtQueryInformationFile) (HANDLE           FileHandle,
+                                              IO_STATUS_BLOCK *IoStatusBlock,
+                                              PVOID            FileInformation,
+                                              ULONG            Length,
+                                              int              FileInformationClass); /* this is an Enum */
+
+#if (defined (_MSC_VER) && _MSC_VER >= 1400)
+/*
+ * This is the (empty) invalid parameter handler
+ * that is used for Visual C++ 2005 (and later) builds
+ * so that we can use this instead of the system automatically
+ * aborting the process.
+ *
+ * This is necessary as we use _get_oshandle() to check the validity
+ * of the file descriptors as we close them, so when an invalid file
+ * descriptor is passed into that function as we check on it, we get
+ * -1 as the result, instead of the gspawn helper program aborting.
+ *
+ * Please see http://msdn.microsoft.com/zh-tw/library/ks2530z6%28v=vs.80%29.aspx
+ * for an explanation on this.
+ */
+void
+myInvalidParameterHandler(const wchar_t *expression,
+                          const wchar_t *function,
+                          const wchar_t *file,
+                          unsigned int   line,
+                          uintptr_t      pReserved)
+{
+}
+#endif
+#else
 #include <unistd.h>
 #include <fcntl.h>
+#endif
 
 FILE *
 libxml_PyFileGet(PyObject *f) {
-    int fd, flags;
     FILE *res;
     const char *mode;
+    int fd = PyObject_AsFileDescriptor(f);
+
+#ifdef _WIN32
+    intptr_t w_fh = -1;
+    HMODULE hntdll = NULL;
+    IO_STATUS_BLOCK status_block;
+    FILE_ACCESS_INFORMATION ai;
+    t_NtQueryInformationFile NtQueryInformationFile;
+    BOOL is_read = FALSE;
+    BOOL is_write = FALSE;
+    BOOL is_append = FALSE;
+
+#if (defined (_MSC_VER) && _MSC_VER >= 1400)
+    /* set up our empty invalid parameter handler */
+    _invalid_parameter_handler oldHandler, newHandler;
+    newHandler = myInvalidParameterHandler;
+    oldHandler = _set_invalid_parameter_handler(newHandler);
+
+    /* Disable the message box for assertions. */
+    _CrtSetReportMode(_CRT_ASSERT, 0);
+#endif
+
+    w_fh = _get_osfhandle(fd);
+
+    if (w_fh == -1)
+        return(NULL);
+
+    hntdll = GetModuleHandleW(L"ntdll.dll");
+
+    if (hntdll == NULL)
+        return(NULL);
+XML_IGNORE_FPTR_CAST_WARNINGS
+    NtQueryInformationFile = (t_NtQueryInformationFile)GetProcAddress(hntdll, "NtQueryInformationFile");
+XML_POP_WARNINGS
+
+    if (NtQueryInformationFile != NULL &&
+        (NtQueryInformationFile((HANDLE)w_fh,
+                               &status_block,
+                               &ai,
+                                sizeof(FILE_ACCESS_INFORMATION),
+                                8) == 0)) /* 8 means "FileAccessInformation" */
+        {
+            if (ai.AccessFlags & FILE_READ_DATA)
+                is_read = TRUE;
+            if (ai.AccessFlags & FILE_WRITE_DATA)
+                is_write = TRUE;
+            if (ai.AccessFlags & FILE_APPEND_DATA)
+                is_append = TRUE;
+
+            if (is_write) {
+                if (is_read) {
+                    if (is_append)
+                        mode = "a+";
+                    else
+                        mode = "rw";
+                } else {
+                    if (is_append)
+                        mode = "a";
+                    else
+                        mode = "w";
+                }
+            } else {
+                if (is_append)
+                    mode = "r+";
+                else
+                    mode = "r";
+            }
+        }
+
+    FreeLibrary(hntdll);
+
+    if (!is_write && !is_read) /* also happens if we did not load or run NtQueryInformationFile() 
successfully */
+        return(NULL);
+#else
+    int flags;
 
-    fd = PyObject_AsFileDescriptor(f);
     /*
-     * Get the flags on the fd to understand how it was opened
+     * macOS returns O_RDWR for standard streams, but fails to write to
+     * stdout or stderr when opened with fdopen(dup_fd, "rw").
      */
-    flags = fcntl(fd, F_GETFL, 0);
-    switch (flags & O_ACCMODE) {
-        case O_RDWR:
-           if (flags & O_APPEND)
-               mode = "a+";
-           else
-               mode = "rw";
-           break;
-        case O_RDONLY:
-           if (flags & O_APPEND)
-               mode = "r+";
-           else
-               mode = "r";
-           break;
-       case O_WRONLY:
-           if (flags & O_APPEND)
-               mode = "a";
-           else
-               mode = "w";
-           break;
-       default:
-           return(NULL);
+    switch (fd) {
+        case STDIN_FILENO:
+            mode = "r";
+            break;
+        case STDOUT_FILENO:
+        case STDERR_FILENO:
+            mode = "w";
+            break;
+        default:
+            /*
+             * Get the flags on the fd to understand how it was opened
+             */
+            flags = fcntl(fd, F_GETFL, 0);
+            switch (flags & O_ACCMODE) {
+                case O_RDWR:
+                    if (flags & O_APPEND)
+                        mode = "a+";
+                    else
+                        mode = "rw";
+                    break;
+                case O_RDONLY:
+                    if (flags & O_APPEND)
+                        mode = "r+";
+                    else
+                        mode = "r";
+                    break;
+                case O_WRONLY:
+                    if (flags & O_APPEND)
+                        mode = "a";
+                    else
+                        mode = "w";
+                    break;
+                default:
+                    return(NULL);
+            }
     }
+#endif
 
     /*
      * the FILE struct gets a new fd, so that it can be closed


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]