summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES5
-rw-r--r--include/arch/win32/apr_arch_misc.h6
-rw-r--r--misc/win32/misc.c36
-rw-r--r--network_io/win32/sockets.c23
4 files changed, 49 insertions, 21 deletions
diff --git a/CHANGES b/CHANGES
index 927c3ffd5..53df1a38c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -47,6 +47,11 @@ Changes for APR 1.7.1
events are emitted on pool clear/destroy for proper accounting.
[Brane Čibej]
+ *) apr_socket_listen: Allow larger listen backlog values on Windows 8+.
+ [Evgeny Kotkov <evgeny.kotkov visualsvn.com>]
+
+ *) Fixed: apr_get_oslevel() was returning APR_WIN_XP on Windows 10
+
Changes for APR 1.7.0
*) apr_dir_read: [Unix] Dropped the preference of the dirread_r() flavor
diff --git a/include/arch/win32/apr_arch_misc.h b/include/arch/win32/apr_arch_misc.h
index 15312adf4..3b80502bd 100644
--- a/include/arch/win32/apr_arch_misc.h
+++ b/include/arch/win32/apr_arch_misc.h
@@ -110,7 +110,11 @@ typedef enum {
APR_WIN_XP_SP2 = 62,
APR_WIN_2003 = 70,
APR_WIN_VISTA = 80,
- APR_WIN_7 = 90
+ APR_WIN_7 = 90,
+ APR_WIN_7_SP1 = 91,
+ APR_WIN_8 = 100,
+ APR_WIN_8_1 = 110,
+ APR_WIN_10 = 120
} apr_oslevel_e;
extern APR_DECLARE_DATA apr_oslevel_e apr_os_level;
diff --git a/misc/win32/misc.c b/misc/win32/misc.c
index fd276c209..bfb7efae5 100644
--- a/misc/win32/misc.c
+++ b/misc/win32/misc.c
@@ -27,25 +27,15 @@ apr_status_t apr_get_oslevel(apr_oslevel_e *level)
{
if (apr_os_level == APR_WIN_UNK)
{
- static OSVERSIONINFO oslev;
- oslev.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx(&oslev);
+ OSVERSIONINFOEXW oslev;
+ oslev.dwOSVersionInfoSize = sizeof(oslev);
+ if (!GetVersionExW((OSVERSIONINFOW*) &oslev)) {
+ return apr_get_os_error();
+ }
if (oslev.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
- static unsigned int servpack = 0;
- TCHAR *pservpack;
- if ((pservpack = oslev.szCSDVersion)) {
- while (*pservpack && !apr_isdigit(*pservpack)) {
- pservpack++;
- }
- if (*pservpack)
-#ifdef _UNICODE
- servpack = _wtoi(pservpack);
-#else
- servpack = atoi(pservpack);
-#endif
- }
+ unsigned int servpack = oslev.wServicePackMajor;
if (oslev.dwMajorVersion < 3) {
apr_os_level = APR_WIN_UNSUP;
@@ -99,11 +89,19 @@ apr_status_t apr_get_oslevel(apr_oslevel_e *level)
else if (oslev.dwMajorVersion == 6) {
if (oslev.dwMinorVersion == 0)
apr_os_level = APR_WIN_VISTA;
+ else if (oslev.dwMinorVersion == 1) {
+ if (servpack < 1)
+ apr_os_level = APR_WIN_7;
+ else
+ apr_os_level = APR_WIN_7_SP1;
+ }
+ else if (oslev.dwMinorVersion == 2)
+ apr_os_level = APR_WIN_8;
else
- apr_os_level = APR_WIN_7;
+ apr_os_level = APR_WIN_8_1;
}
else {
- apr_os_level = APR_WIN_XP;
+ apr_os_level = APR_WIN_10;
}
}
#ifndef WINNT
@@ -151,7 +149,7 @@ apr_status_t apr_get_oslevel(apr_oslevel_e *level)
*level = apr_os_level;
- if (apr_os_level < APR_WIN_UNSUP) {
+ if (apr_os_level <= APR_WIN_UNSUP) {
return APR_EGENERAL;
}
diff --git a/network_io/win32/sockets.c b/network_io/win32/sockets.c
index 04f2d6268..5013bba88 100644
--- a/network_io/win32/sockets.c
+++ b/network_io/win32/sockets.c
@@ -24,6 +24,13 @@
#include "apr_arch_inherit.h"
#include "apr_arch_misc.h"
+/* Borrow the definition of SOMAXCONN_HINT() from Windows SDK 8,
+ * in case the SDK we are building against doesn't have it.
+ */
+#ifndef SOMAXCONN_HINT
+#define SOMAXCONN_HINT(b) (-(b))
+#endif
+
static char generic_inaddr_any[16] = {0}; /* big enough for IPv4 or IPv6 */
static apr_status_t socket_cleanup(void *sock)
@@ -223,7 +230,21 @@ APR_DECLARE(apr_status_t) apr_socket_bind(apr_socket_t *sock,
APR_DECLARE(apr_status_t) apr_socket_listen(apr_socket_t *sock,
apr_int32_t backlog)
{
- if (listen(sock->socketdes, backlog) == SOCKET_ERROR)
+ int backlog_val;
+
+ if (apr_os_level >= APR_WIN_8) {
+ /* Starting from Windows 8, listen() accepts a special SOMAXCONN_HINT()
+ * arg that allows setting the listen backlog value to a larger
+ * value than the predefined Winsock 2 limit (several hundred).
+ * https://blogs.msdn.microsoft.com/winsdk/2015/06/01/winsocks-listen-backlog-offers-more-flexibility-in-windows-8/
+ */
+ backlog_val = SOMAXCONN_HINT(backlog);
+ }
+ else {
+ backlog_val = backlog;
+ }
+
+ if (listen(sock->socketdes, backlog_val) == SOCKET_ERROR)
return apr_get_netos_error();
else
return APR_SUCCESS;