summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--python/types.c128
1 files changed, 126 insertions, 2 deletions
diff --git a/python/types.c b/python/types.c
index ed284ec7..75213dd4 100644
--- a/python/types.c
+++ b/python/types.c
@@ -21,16 +21,139 @@
#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;
+ int flags;
FILE *res;
const char *mode;
- fd = PyObject_AsFileDescriptor(f);
+ int fd = PyObject_AsFileDescriptor(f);
+ intptr_t w_fh = -1;
+
+#ifdef _WIN32
+ 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);
+
+ NtQueryInformationFile = (t_NtQueryInformationFile)GetProcAddress(hntdll, "NtQueryInformationFile");
+
+ 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 && is_read)
+ if (is_append)
+ mode = "a+";
+ else
+ mode = "rw";
+
+ if (!is_write && is_read)
+ if (is_append)
+ mode = "r+";
+ else
+ mode = "r";
+
+ if (is_write && !is_read)
+ if (is_append)
+ mode = "a";
+ else
+ mode = "w";
+ }
+
+ FreeLibrary(hntdll);
+
+ if (!is_write && !is_read) /* also happens if we did not load or run NtQueryInformationFile() successfully */
+ return(NULL);
+#else
/*
* Get the flags on the fd to understand how it was opened
*/
@@ -57,6 +180,7 @@ libxml_PyFileGet(PyObject *f) {
default:
return(NULL);
}
+#endif
/*
* the FILE struct gets a new fd, so that it can be closed