summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--win32/win32.c15
-rw-r--r--win32/win32.h94
-rw-r--r--win32/win32sck.c16
3 files changed, 121 insertions, 4 deletions
diff --git a/win32/win32.c b/win32/win32.c
index 53962b2e2d..bf91b76226 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -160,6 +160,9 @@ static void win32_csighandler(int sig);
START_EXTERN_C
HANDLE w32_perldll_handle = INVALID_HANDLE_VALUE;
char w32_module_name[MAX_PATH+1];
+#ifdef WIN32_DYN_IOINFO_SIZE
+Size_t w32_ioinfo_size;/* avoid 0 extend op b4 mul, otherwise could be a U8 */
+#endif
END_EXTERN_C
static OSVERSIONINFO g_osver = {0, 0, 0, 0, 0, ""};
@@ -4415,6 +4418,18 @@ Perl_win32_init(int *argcp, char ***argvp)
g_osver.dwOSVersionInfoSize = sizeof(g_osver);
GetVersionEx(&g_osver);
+#ifdef WIN32_DYN_IOINFO_SIZE
+ {
+ Size_t ioinfo_size = _msize((void*)__pioinfo[0]);;
+ if((SSize_t)ioinfo_size <= 0) { /* -1 is err */
+ fprintf(stderr, "panic: invalid size for ioinfo\n"); /* no interp */
+ exit(1);
+ }
+ ioinfo_size /= IOINFO_ARRAY_ELTS;
+ w32_ioinfo_size = ioinfo_size;
+ }
+#endif
+
ansify_path();
}
diff --git a/win32/win32.h b/win32/win32.h
index 19dcbf7540..a521a41a2d 100644
--- a/win32/win32.h
+++ b/win32/win32.h
@@ -507,6 +507,100 @@ void win32_wait_for_children(pTHX);
# define PERL_WAIT_FOR_CHILDREN win32_wait_for_children(aTHX)
#endif
+#ifdef PERL_CORE
+/* C doesn't like repeat struct definitions */
+#if defined(__MINGW32__) && (__MINGW32_MAJOR_VERSION>=3)
+#undef _CRTIMP
+#endif
+#ifndef _CRTIMP
+#define _CRTIMP __declspec(dllimport)
+#endif
+
+
+/* VV 2005 has multiple ioinfo struct definitions through VC 2005's release life
+ * VC 2008-2012 have been stable but do not assume future VCs will have the
+ * same ioinfo struct, just because past struct stability. If research is done
+ * on the CRTs of future VS, the version check can be bumped up so the newer
+ * VC uses a fixed ioinfo size.
+ */
+#if ! (_MSC_VER < 1400 || (_MSC_VER >= 1500 && _MSC_VER <= 1700) \
+ || defined(__MINGW32__))
+/* size of ioinfo struct is determined at runtime */
+# define WIN32_DYN_IOINFO_SIZE
+#endif
+
+#ifndef WIN32_DYN_IOINFO_SIZE
+/*
+ * Control structure for lowio file handles
+ */
+typedef struct {
+ intptr_t osfhnd;/* underlying OS file HANDLE */
+ char osfile; /* attributes of file (e.g., open in text mode?) */
+ char pipech; /* one char buffer for handles opened on pipes */
+ int lockinitflag;
+ CRITICAL_SECTION lock;
+/* this struct defintion breaks ABI compatibility with
+ * not using, cl.exe's native VS version specitfic CRT. */
+# if _MSC_VER >= 1400 && _MSC_VER < 1500
+# error "This ioinfo struct is incomplete for Visual C 2005"
+# endif
+/* VC 2005 CRT has atleast 3 different definitions of this struct based on the
+ * CRT DLL's build number. */
+# if _MSC_VER >= 1500
+# ifndef _SAFECRT_IMPL
+ /* Not used in the safecrt downlevel. We do not define them, so we cannot
+ * use them accidentally */
+ char textmode : 7;/* __IOINFO_TM_ANSI or __IOINFO_TM_UTF8 or __IOINFO_TM_UTF16LE */
+ char unicode : 1; /* Was the file opened as unicode? */
+ char pipech2[2]; /* 2 more peak ahead chars for UNICODE mode */
+ __int64 startpos; /* File position that matches buffer start */
+ BOOL utf8translations; /* Buffer contains translations other than CRLF*/
+ char dbcsBuffer; /* Buffer for the lead byte of dbcs when converting from dbcs to unicode */
+ BOOL dbcsBufferUsed; /* Bool for the lead byte buffer is used or not */
+# endif
+# endif
+} ioinfo;
+#else
+typedef intptr_t ioinfo;
+#endif
+
+/*
+ * Array of arrays of control structures for lowio files.
+ */
+EXTERN_C _CRTIMP ioinfo* __pioinfo[];
+
+/*
+ * Definition of IOINFO_L2E, the log base 2 of the number of elements in each
+ * array of ioinfo structs.
+ */
+#define IOINFO_L2E 5
+
+/*
+ * Definition of IOINFO_ARRAY_ELTS, the number of elements in ioinfo array
+ */
+#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
+
+/*
+ * Access macros for getting at an ioinfo struct and its fields from a
+ * file handle
+ */
+#ifdef WIN32_DYN_IOINFO_SIZE
+# define _pioinfo(i) ((intptr_t *) \
+ (((Size_t)__pioinfo[(i) >> IOINFO_L2E])/* * to head of array ioinfo [] */\
+ /* offset to the head of a particular ioinfo struct */ \
+ + (((i) & (IOINFO_ARRAY_ELTS - 1)) * w32_ioinfo_size)) \
+ )
+/* first slice of ioinfo is always the OS handle */
+# define _osfhnd(i) (*(_pioinfo(i)))
+#else
+# define _pioinfo(i) (__pioinfo[(i) >> IOINFO_L2E] + ((i) & (IOINFO_ARRAY_ELTS - 1)))
+# define _osfhnd(i) (_pioinfo(i)->osfhnd)
+#endif
+
+/* since we are not doing a dup2(), this works fine */
+# define _set_osfhnd(fh, osfh) (void)(_osfhnd(fh) = (intptr_t)osfh)
+#endif /* PERL_CORE */
+
/* IO.xs and POSIX.xs define PERLIO_NOT_STDIO to 1 */
#if defined(PERL_EXT_IO) || defined(PERL_EXT_POSIX)
#undef PERLIO_NOT_STDIO
diff --git a/win32/win32sck.c b/win32/win32sck.c
index 5f98910437..674add2efc 100644
--- a/win32/win32sck.c
+++ b/win32/win32sck.c
@@ -54,6 +54,10 @@ static struct servent* win32_savecopyservent(struct servent*d,
static int wsock_started = 0;
+#ifdef WIN32_DYN_IOINFO_SIZE
+EXTERN_C Size_t w32_ioinfo_size;
+#endif
+
EXTERN_C void
EndSockets(void)
{
@@ -689,8 +693,10 @@ int my_close(int fd)
int err;
err = closesocket(osf);
if (err == 0) {
- (void)close(fd); /* handle already closed, ignore error */
- return 0;
+ assert(_osfhnd(fd) == osf); /* catch a bad ioinfo struct def */
+ /* don't close freed handle */
+ _set_osfhnd(fd, INVALID_HANDLE_VALUE);
+ return close(fd);
}
else if (err == SOCKET_ERROR) {
err = get_last_socket_error();
@@ -717,8 +723,10 @@ my_fclose (FILE *pf)
win32_fflush(pf);
err = closesocket(osf);
if (err == 0) {
- (void)fclose(pf); /* handle already closed, ignore error */
- return 0;
+ assert(_osfhnd(win32_fileno(pf)) == osf); /* catch a bad ioinfo struct def */
+ /* don't close freed handle */
+ _set_osfhnd(win32_fileno(pf), INVALID_HANDLE_VALUE);
+ return fclose(pf);
}
else if (err == SOCKET_ERROR) {
err = get_last_socket_error();