diff options
author | wtc%google.com <devnull@localhost> | 2007-04-27 20:41:58 +0000 |
---|---|---|
committer | wtc%google.com <devnull@localhost> | 2007-04-27 20:41:58 +0000 |
commit | 45fef6fde2e4642f059093777931f1043fdd77ef (patch) | |
tree | c8a9f98d046c04b49b4d98c492ed576983722b50 | |
parent | c885a42b3d79e813f79c32aa560fb535c925a2f9 (diff) | |
download | nspr-hg-45fef6fde2e4642f059093777931f1043fdd77ef.tar.gz |
Bugzilla bug 363997: when running on Windows Vista, set the sockets in the
compatibility mode so that the new TCP/IP stack in Windows Vista can
interoperate with all the TCP/IP implementations. The patch is contributed
by Seth Spitzer <sspitzer@mozilla.com>. r=wtc,biesi
Modified Files: _win95.h /w95io.c w95sock.c w95thred.c
Tag: NSPR_4_6_BRANCH
-rw-r--r-- | pr/include/md/_win95.h | 2 | ||||
-rw-r--r-- | pr/src/md/windows/w95io.c | 2 | ||||
-rw-r--r-- | pr/src/md/windows/w95sock.c | 112 | ||||
-rw-r--r-- | pr/src/md/windows/w95thred.c | 2 |
4 files changed, 118 insertions, 0 deletions
diff --git a/pr/include/md/_win95.h b/pr/include/md/_win95.h index 9033a524..4569a2a3 100644 --- a/pr/include/md/_win95.h +++ b/pr/include/md/_win95.h @@ -276,6 +276,8 @@ extern PRBool _pr_useUnicode; #endif /* MOZ_UNICODE */ /* --- Socket IO stuff --- */ +extern void _PR_MD_InitSockets(void); +extern void _PR_MD_CleanupSockets(void); #define _MD_EACCES WSAEACCES #define _MD_EADDRINUSE WSAEADDRINUSE #define _MD_EADDRNOTAVAIL WSAEADDRNOTAVAIL diff --git a/pr/src/md/windows/w95io.c b/pr/src/md/windows/w95io.c index 087eac19..f418fce7 100644 --- a/pr/src/md/windows/w95io.c +++ b/pr/src/md/windows/w95io.c @@ -123,6 +123,8 @@ _PR_MD_INIT_IO() _PR_NT_InitSids(); InitUnicodeSupport(); + + _PR_MD_InitSockets(); } PRStatus diff --git a/pr/src/md/windows/w95sock.c b/pr/src/md/windows/w95sock.c index 01c25258..1bcbaf21 100644 --- a/pr/src/md/windows/w95sock.c +++ b/pr/src/md/windows/w95sock.c @@ -53,6 +53,95 @@ static PRInt32 socket_io_wait( /* --- SOCKET IO --------------------------------------------------------- */ +/* + * we only want to call WSAIoctl() on Vista and later + * so don't pay for it at build time (and avoid including winsock2.h) + */ + +/* from ws2def.h */ +#define IOC_IN 0x80000000 /* copy in parameters */ +#define IOC_VENDOR 0x18000000 +#define _WSAIOW(x,y) (IOC_IN|(x)|(y)) +/* from MSWSockDef.h */ +#define SIO_SET_COMPATIBILITY_MODE _WSAIOW(IOC_VENDOR,300) + +typedef enum _WSA_COMPATIBILITY_BEHAVIOR_ID { + WsaBehaviorAll = 0, + WsaBehaviorReceiveBuffering, + WsaBehaviorAutoTuning +} WSA_COMPATIBILITY_BEHAVIOR_ID, *PWSA_COMPATIBILITY_BEHAVIOR_ID; + +/* from sdkddkver.h */ +#define NTDDI_LONGHORN 0x06000000 + +/* from winsock2.h */ +#define WSAEVENT HANDLE + +#define WSAOVERLAPPED OVERLAPPED +typedef struct _OVERLAPPED * LPWSAOVERLAPPED; + +typedef void (CALLBACK * LPWSAOVERLAPPED_COMPLETION_ROUTINE)( + IN DWORD dwError, + IN DWORD cbTransferred, + IN LPWSAOVERLAPPED lpOverlapped, + IN DWORD dwFlags +); + +typedef int (__stdcall * WSAIOCTLPROC) ( + SOCKET s, + DWORD dwIoControlCode, + LPVOID lpvInBuffer, + DWORD cbInBuffer, + LPVOID lpvOutBuffer, + DWORD cbOutBuffer, + LPDWORD lpcbBytesReturned, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine +); + +typedef struct _WSA_COMPATIBILITY_MODE { + WSA_COMPATIBILITY_BEHAVIOR_ID BehaviorId; + ULONG TargetOsVersion; +} WSA_COMPATIBILITY_MODE, *PWSA_COMPATIBILITY_MODE; + +static HMODULE libWinsock2 = NULL; +static WSAIOCTLPROC wsaioctlProc = NULL; +static PRBool socketSetCompatMode = PR_FALSE; + +void _PR_MD_InitSockets(void) +{ + OSVERSIONINFO osvi; + + memset(&osvi, 0, sizeof(osvi)); + osvi.dwOSVersionInfoSize = sizeof(osvi); + GetVersionEx(&osvi); + + /* if Vista or later... */ + if (osvi.dwMajorVersion >= 6) + { + libWinsock2 = LoadLibrary("Ws2_32.dll"); + if (libWinsock2) + { + wsaioctlProc = (WSAIOCTLPROC)GetProcAddress(libWinsock2, + "WSAIoctl"); + if (wsaioctlProc) + { + socketSetCompatMode = PR_TRUE; + } + } + } +} + +void _PR_MD_CleanupSockets(void) +{ + socketSetCompatMode = PR_FALSE; + wsaioctlProc = NULL; + if (libWinsock2) + { + FreeLibrary(libWinsock2); + libWinsock2 = NULL; + } +} PRInt32 _PR_MD_SOCKET(int af, int type, int flags) @@ -78,6 +167,29 @@ _PR_MD_SOCKET(int af, int type, int flags) return -1; } + if ((af == AF_INET || af == AF_INET6) && + type == SOCK_STREAM && socketSetCompatMode) + { + WSA_COMPATIBILITY_MODE mode; + char dummy[4]; + int ret_dummy; + + mode.BehaviorId = WsaBehaviorAutoTuning; + mode.TargetOsVersion = NTDDI_LONGHORN; + if (wsaioctlProc(sock, SIO_SET_COMPATIBILITY_MODE, + (char *)&mode, sizeof(mode), + dummy, 4, &ret_dummy, 0, NULL) == SOCKET_ERROR) + { + int err = WSAGetLastError(); + PR_LOG(_pr_io_lm, PR_LOG_DEBUG, ("WSAIoctl() failed with %d", err)); + + /* SIO_SET_COMPATIBILITY_MODE may not be supported. + ** If the call to WSAIoctl() fails with WSAEOPNOTSUPP, + ** don't close the socket. + */ + } + } + return (PRInt32)sock; } diff --git a/pr/src/md/windows/w95thred.c b/pr/src/md/windows/w95thred.c index a8d5f068..a8d64200 100644 --- a/pr/src/md/windows/w95thred.c +++ b/pr/src/md/windows/w95thred.c @@ -65,6 +65,8 @@ void _PR_MD_CLEANUP_BEFORE_EXIT(void) { _PR_NT_FreeSids(); + _PR_MD_CleanupSockets(); + WSACleanup(); #ifndef _PR_USE_STATIC_TLS |