d. We\'ll fake out an fdopen and see
// if we can prevent perl from trying to do stdio on sockets.
//

//EXTERN_C int __cdecl _alloc_osfhnd(void);
//EXTERN_C int __cdecl _set_osfhnd(int fh, long value);
EXTERN_C void __cdecl _lock_fhandle(int);
EXTERN_C void __cdecl _unlock_fhandle(int);
EXTERN_C void __cdecl _unlock(int);

#if defined _MT || defined __MSVCRT__
#define MSVCRT_THREADS
#endif

typedef struct	{
    long 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 */
#ifdef MSVCRT_THREADS
    int lockinitflag;
    CRITICAL_SECTION lock;
#endif
}	ioinfo;

#if !defined _CRTIMP
#define _CRTIMP __declspec(dllimport)
#endif

EXTERN_C _CRTIMP ioinfo * __pioinfo[];

#define IOINFO_L2E			5
#define IOINFO_ARRAY_ELTS	(1 << IOINFO_L2E)
#define _pioinfo(i)	(__pioinfo[i >> IOINFO_L2E] + (i & (IOINFO_ARRAY_ELTS - 1)))

#define _osfhnd(i)  (_pioinfo(i)->osfhnd)
#define _osfile(i)  (_pioinfo(i)->osfile)
#define _pipech(i)  (_pioinfo(i)->pipech)

#define FOPEN			0x01	/* file handle open */
#define FNOINHERIT		0x10	/* file handle opened O_NOINHERIT */
#define FAPPEND			0x20	/* file handle opened O_APPEND */
#define FDEV			0x40	/* file handle refers to device */
#define FTEXT			0x80	/* file handle is in text mode */

#define _set_osfhnd(fh, osfh) (void)(_osfhnd(fh) = osfh)

static int
_alloc_osfhnd(void)
{
    HANDLE hF = CreateFile("NUL", 0, 0, NULL, OPEN_ALWAYS, 0, NULL);
    int fh = _open_osfhandle((long)hF, 0);
    CloseHandle(hF);
    if (fh == -1)
        return fh;
#ifdef MSVCRT_THREADS
    EnterCriticalSection(&(_pioinfo(fh)->lock));
#endif
    return fh;
}

static int
my_open_osfhandle(long osfhandle, int flags)
{
    int fh;
    char fileflags;		/* _osfile flags */

    /* copy relevant flags from second parameter */
    fileflags = FDEV;

    if (flags & O_APPEND)
	fileflags |= FAPPEND;

    if (flags & O_TEXT)
	fileflags |= FTEXT;

    if (flags & O_NOINHERIT)
	fileflags |= FNOINHERIT;

    /* attempt to allocate a C Runtime file handle */
    if ((fh = _alloc_osfhnd()) == -1) {
	errno = EMFILE;		/* too many open files */
	_doserrno = 0L;		/* not an OS error */
	return -1;		/* return error to caller */
    }

    /* the file is open. now, set the info in _osfhnd array */
    _set_osfhnd(fh, osfhandle);

    fileflags |= FOPEN;		/* mark as open */

    _osfile(fh) = fileflags;	/* set osfile entry */
#ifdef MSVCRT_THREADS
    LeaveCriticalSection(&_pioinfo(fh)->lock);
#endif

    return fh;			/* return handle */
}

#undef getsockopt

static int
is_socket(SOCKET fd)
{
    char sockbuf[80];
    int optlen;
    int retval;

    optlen = sizeof(sockbuf);
    retval = getsockopt(fd, SOL_SOCKET, SO_TYPE, sockbuf, &optlen);
    if (retval == SOCKET_ERROR) {
	int iRet;

	iRet = WSAGetLastError();
	if (iRet == WSAENOTSOCK || iRet == WSANOTINITIALISED)
	    return FALSE;
    }

    //
    // If we get here, then fd is actually a socket.
    //

    return TRUE;
}

