diff options
-rw-r--r-- | win32/win32.c | 15 | ||||
-rw-r--r-- | win32/win32.h | 94 | ||||
-rw-r--r-- | win32/win32sck.c | 16 |
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(); |