1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Igor Sysoev
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev
8e18a033bSKonstantin Ananyev#include <ngx_config.h>
9e18a033bSKonstantin Ananyev#include <ngx_core.h>
10e18a033bSKonstantin Ananyev#include <nginx.h>
11e18a033bSKonstantin Ananyev
12e18a033bSKonstantin Ananyev
13e18a033bSKonstantin Ananyevngx_uint_t  ngx_win32_version;
14e18a033bSKonstantin Ananyevngx_uint_t  ngx_ncpu;
15e18a033bSKonstantin Ananyevngx_uint_t  ngx_max_wsabufs;
16e18a033bSKonstantin Ananyevngx_int_t   ngx_max_sockets;
17e18a033bSKonstantin Ananyevngx_uint_t  ngx_inherited_nonblocking = 1;
18e18a033bSKonstantin Ananyevngx_uint_t  ngx_tcp_nodelay_and_tcp_nopush;
19e18a033bSKonstantin Ananyev
20e18a033bSKonstantin Ananyevchar        ngx_unique[NGX_INT32_LEN + 1];
21e18a033bSKonstantin Ananyev
22e18a033bSKonstantin Ananyev
23e18a033bSKonstantin Ananyevngx_os_io_t ngx_os_io = {
24e18a033bSKonstantin Ananyev    ngx_wsarecv,
25e18a033bSKonstantin Ananyev    ngx_wsarecv_chain,
26e18a033bSKonstantin Ananyev    ngx_udp_wsarecv,
27e18a033bSKonstantin Ananyev    ngx_wsasend,
28e18a033bSKonstantin Ananyev    NULL,
29e18a033bSKonstantin Ananyev    NULL,
30e18a033bSKonstantin Ananyev    ngx_wsasend_chain,
31e18a033bSKonstantin Ananyev    0
32e18a033bSKonstantin Ananyev};
33e18a033bSKonstantin Ananyev
34e18a033bSKonstantin Ananyev
35e18a033bSKonstantin Ananyevtypedef struct {
36e18a033bSKonstantin Ananyev    WORD  wServicePackMinor;
37e18a033bSKonstantin Ananyev    WORD  wSuiteMask;
38e18a033bSKonstantin Ananyev    BYTE  wProductType;
39e18a033bSKonstantin Ananyev} ngx_osviex_stub_t;
40e18a033bSKonstantin Ananyev
41e18a033bSKonstantin Ananyev
42e18a033bSKonstantin Ananyevstatic u_int               osviex;
43e18a033bSKonstantin Ananyevstatic OSVERSIONINFOEX     osvi;
44e18a033bSKonstantin Ananyev
45e18a033bSKonstantin Ananyev/* Should these pointers be per protocol ? */
46e18a033bSKonstantin AnanyevLPFN_ACCEPTEX              ngx_acceptex;
47e18a033bSKonstantin AnanyevLPFN_GETACCEPTEXSOCKADDRS  ngx_getacceptexsockaddrs;
48e18a033bSKonstantin AnanyevLPFN_TRANSMITFILE          ngx_transmitfile;
49e18a033bSKonstantin AnanyevLPFN_TRANSMITPACKETS       ngx_transmitpackets;
50e18a033bSKonstantin AnanyevLPFN_CONNECTEX             ngx_connectex;
51e18a033bSKonstantin AnanyevLPFN_DISCONNECTEX          ngx_disconnectex;
52e18a033bSKonstantin Ananyev
53e18a033bSKonstantin Ananyevstatic GUID ax_guid = WSAID_ACCEPTEX;
54e18a033bSKonstantin Ananyevstatic GUID as_guid = WSAID_GETACCEPTEXSOCKADDRS;
55e18a033bSKonstantin Ananyevstatic GUID tf_guid = WSAID_TRANSMITFILE;
56e18a033bSKonstantin Ananyevstatic GUID tp_guid = WSAID_TRANSMITPACKETS;
57e18a033bSKonstantin Ananyevstatic GUID cx_guid = WSAID_CONNECTEX;
58e18a033bSKonstantin Ananyevstatic GUID dx_guid = WSAID_DISCONNECTEX;
59e18a033bSKonstantin Ananyev
60e18a033bSKonstantin Ananyev
61e18a033bSKonstantin Ananyevngx_int_t
62e18a033bSKonstantin Ananyevngx_os_init(ngx_log_t *log)
63e18a033bSKonstantin Ananyev{
64e18a033bSKonstantin Ananyev    DWORD         bytes;
65e18a033bSKonstantin Ananyev    SOCKET        s;
66e18a033bSKonstantin Ananyev    WSADATA       wsd;
67e18a033bSKonstantin Ananyev    ngx_err_t     err;
68e18a033bSKonstantin Ananyev    ngx_time_t   *tp;
69e18a033bSKonstantin Ananyev    ngx_uint_t    n;
70e18a033bSKonstantin Ananyev    SYSTEM_INFO   si;
71e18a033bSKonstantin Ananyev
72e18a033bSKonstantin Ananyev    /* get Windows version */
73e18a033bSKonstantin Ananyev
74e18a033bSKonstantin Ananyev    ngx_memzero(&osvi, sizeof(OSVERSIONINFOEX));
75e18a033bSKonstantin Ananyev    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
76e18a033bSKonstantin Ananyev
77e18a033bSKonstantin Ananyev#ifdef _MSC_VER
78e18a033bSKonstantin Ananyev#pragma warning(disable:4996)
79e18a033bSKonstantin Ananyev#endif
80e18a033bSKonstantin Ananyev
81e18a033bSKonstantin Ananyev    osviex = GetVersionEx((OSVERSIONINFO *) &osvi);
82e18a033bSKonstantin Ananyev
83e18a033bSKonstantin Ananyev    if (osviex == 0) {
84e18a033bSKonstantin Ananyev        osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
85e18a033bSKonstantin Ananyev        if (GetVersionEx((OSVERSIONINFO *) &osvi) == 0) {
86e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
87e18a033bSKonstantin Ananyev                          "GetVersionEx() failed");
88e18a033bSKonstantin Ananyev            return NGX_ERROR;
89e18a033bSKonstantin Ananyev        }
90e18a033bSKonstantin Ananyev    }
91e18a033bSKonstantin Ananyev
92e18a033bSKonstantin Ananyev#ifdef _MSC_VER
93e18a033bSKonstantin Ananyev#pragma warning(default:4996)
94e18a033bSKonstantin Ananyev#endif
95e18a033bSKonstantin Ananyev
96e18a033bSKonstantin Ananyev    /*
97e18a033bSKonstantin Ananyev     *  Windows 3.1 Win32s   0xxxxx
98e18a033bSKonstantin Ananyev     *
99e18a033bSKonstantin Ananyev     *  Windows 95           140000
100e18a033bSKonstantin Ananyev     *  Windows 98           141000
101e18a033bSKonstantin Ananyev     *  Windows ME           149000
102e18a033bSKonstantin Ananyev     *  Windows NT 3.51      235100
103e18a033bSKonstantin Ananyev     *  Windows NT 4.0       240000
104e18a033bSKonstantin Ananyev     *  Windows NT 4.0 SP5   240050
105e18a033bSKonstantin Ananyev     *  Windows 2000         250000
106e18a033bSKonstantin Ananyev     *  Windows XP           250100
107e18a033bSKonstantin Ananyev     *  Windows 2003         250200
108e18a033bSKonstantin Ananyev     *  Windows Vista/2008   260000
109e18a033bSKonstantin Ananyev     *
110e18a033bSKonstantin Ananyev     *  Windows CE x.x       3xxxxx
111e18a033bSKonstantin Ananyev     */
112e18a033bSKonstantin Ananyev
113e18a033bSKonstantin Ananyev    ngx_win32_version = osvi.dwPlatformId * 100000
114e18a033bSKonstantin Ananyev                        + osvi.dwMajorVersion * 10000
115e18a033bSKonstantin Ananyev                        + osvi.dwMinorVersion * 100;
116e18a033bSKonstantin Ananyev
117e18a033bSKonstantin Ananyev    if (osviex) {
118e18a033bSKonstantin Ananyev        ngx_win32_version += osvi.wServicePackMajor * 10
119e18a033bSKonstantin Ananyev                             + osvi.wServicePackMinor;
120e18a033bSKonstantin Ananyev    }
121e18a033bSKonstantin Ananyev
122e18a033bSKonstantin Ananyev    GetSystemInfo(&si);
123e18a033bSKonstantin Ananyev    ngx_pagesize = si.dwPageSize;
124e18a033bSKonstantin Ananyev    ngx_allocation_granularity = si.dwAllocationGranularity;
125e18a033bSKonstantin Ananyev    ngx_ncpu = si.dwNumberOfProcessors;
126e18a033bSKonstantin Ananyev    ngx_cacheline_size = NGX_CPU_CACHE_LINE;
127e18a033bSKonstantin Ananyev
128e18a033bSKonstantin Ananyev    for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ }
129e18a033bSKonstantin Ananyev
130e18a033bSKonstantin Ananyev    /* delete default "C" locale for _wcsicmp() */
131e18a033bSKonstantin Ananyev    setlocale(LC_ALL, "");
132e18a033bSKonstantin Ananyev
133e18a033bSKonstantin Ananyev
134e18a033bSKonstantin Ananyev    /* init Winsock */
135e18a033bSKonstantin Ananyev
136e18a033bSKonstantin Ananyev    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
137e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
138e18a033bSKonstantin Ananyev                      "WSAStartup() failed");
139e18a033bSKonstantin Ananyev        return NGX_ERROR;
140e18a033bSKonstantin Ananyev    }
141e18a033bSKonstantin Ananyev
142e18a033bSKonstantin Ananyev    if (ngx_win32_version < NGX_WIN_NT) {
143e18a033bSKonstantin Ananyev        ngx_max_wsabufs = 16;
144e18a033bSKonstantin Ananyev        return NGX_OK;
145e18a033bSKonstantin Ananyev    }
146e18a033bSKonstantin Ananyev
147e18a033bSKonstantin Ananyev    /* STUB: ngx_uint_t max */
148e18a033bSKonstantin Ananyev    ngx_max_wsabufs = 1024 * 1024;
149e18a033bSKonstantin Ananyev
150e18a033bSKonstantin Ananyev    /*
151e18a033bSKonstantin Ananyev     * get AcceptEx(), GetAcceptExSockAddrs(), TransmitFile(),
152e18a033bSKonstantin Ananyev     * TransmitPackets(), ConnectEx(), and DisconnectEx() addresses
153e18a033bSKonstantin Ananyev     */
154e18a033bSKonstantin Ananyev
155e18a033bSKonstantin Ananyev    s = ngx_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
156e18a033bSKonstantin Ananyev    if (s == (ngx_socket_t) -1) {
157e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
158e18a033bSKonstantin Ananyev                      ngx_socket_n " failed");
159e18a033bSKonstantin Ananyev        return NGX_ERROR;
160e18a033bSKonstantin Ananyev    }
161e18a033bSKonstantin Ananyev
162e18a033bSKonstantin Ananyev    if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &ax_guid, sizeof(GUID),
163e18a033bSKonstantin Ananyev                 &ngx_acceptex, sizeof(LPFN_ACCEPTEX), &bytes, NULL, NULL)
164e18a033bSKonstantin Ananyev        == -1)
165e18a033bSKonstantin Ananyev    {
166e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
167e18a033bSKonstantin Ananyev                      "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
168e18a033bSKonstantin Ananyev                               "WSAID_ACCEPTEX) failed");
169e18a033bSKonstantin Ananyev    }
170e18a033bSKonstantin Ananyev
171e18a033bSKonstantin Ananyev    if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &as_guid, sizeof(GUID),
172e18a033bSKonstantin Ananyev                 &ngx_getacceptexsockaddrs, sizeof(LPFN_GETACCEPTEXSOCKADDRS),
173e18a033bSKonstantin Ananyev                 &bytes, NULL, NULL)
174e18a033bSKonstantin Ananyev        == -1)
175e18a033bSKonstantin Ananyev    {
176e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
177e18a033bSKonstantin Ananyev                      "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
178e18a033bSKonstantin Ananyev                               "WSAID_GETACCEPTEXSOCKADDRS) failed");
179e18a033bSKonstantin Ananyev    }
180e18a033bSKonstantin Ananyev
181e18a033bSKonstantin Ananyev    if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &tf_guid, sizeof(GUID),
182e18a033bSKonstantin Ananyev                 &ngx_transmitfile, sizeof(LPFN_TRANSMITFILE), &bytes,
183e18a033bSKonstantin Ananyev                 NULL, NULL)
184e18a033bSKonstantin Ananyev        == -1)
185e18a033bSKonstantin Ananyev    {
186e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
187e18a033bSKonstantin Ananyev                      "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
188e18a033bSKonstantin Ananyev                               "WSAID_TRANSMITFILE) failed");
189e18a033bSKonstantin Ananyev    }
190e18a033bSKonstantin Ananyev
191e18a033bSKonstantin Ananyev    if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &tp_guid, sizeof(GUID),
192e18a033bSKonstantin Ananyev                 &ngx_transmitpackets, sizeof(LPFN_TRANSMITPACKETS), &bytes,
193e18a033bSKonstantin Ananyev                 NULL, NULL)
194e18a033bSKonstantin Ananyev        == -1)
195e18a033bSKonstantin Ananyev    {
196e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
197e18a033bSKonstantin Ananyev                      "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
198e18a033bSKonstantin Ananyev                               "WSAID_TRANSMITPACKETS) failed");
199e18a033bSKonstantin Ananyev    }
200e18a033bSKonstantin Ananyev
201e18a033bSKonstantin Ananyev    if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &cx_guid, sizeof(GUID),
202e18a033bSKonstantin Ananyev                 &ngx_connectex, sizeof(LPFN_CONNECTEX), &bytes,
203e18a033bSKonstantin Ananyev                 NULL, NULL)
204e18a033bSKonstantin Ananyev        == -1)
205e18a033bSKonstantin Ananyev    {
206e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
207e18a033bSKonstantin Ananyev                      "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
208e18a033bSKonstantin Ananyev                               "WSAID_CONNECTEX) failed");
209e18a033bSKonstantin Ananyev    }
210e18a033bSKonstantin Ananyev
211e18a033bSKonstantin Ananyev    if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &dx_guid, sizeof(GUID),
212e18a033bSKonstantin Ananyev                 &ngx_disconnectex, sizeof(LPFN_DISCONNECTEX), &bytes,
213e18a033bSKonstantin Ananyev                 NULL, NULL)
214e18a033bSKonstantin Ananyev        == -1)
215e18a033bSKonstantin Ananyev    {
216e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_NOTICE, log, ngx_socket_errno,
217e18a033bSKonstantin Ananyev                      "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER, "
218e18a033bSKonstantin Ananyev                               "WSAID_DISCONNECTEX) failed");
219e18a033bSKonstantin Ananyev    }
220e18a033bSKonstantin Ananyev
221e18a033bSKonstantin Ananyev    if (ngx_close_socket(s) == -1) {
222e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
223e18a033bSKonstantin Ananyev                      ngx_close_socket_n " failed");
224e18a033bSKonstantin Ananyev    }
225e18a033bSKonstantin Ananyev
226e18a033bSKonstantin Ananyev    if (GetEnvironmentVariable("ngx_unique", ngx_unique, NGX_INT32_LEN + 1)
227e18a033bSKonstantin Ananyev        != 0)
228e18a033bSKonstantin Ananyev    {
229e18a033bSKonstantin Ananyev        ngx_process = NGX_PROCESS_WORKER;
230e18a033bSKonstantin Ananyev
231e18a033bSKonstantin Ananyev    } else {
232e18a033bSKonstantin Ananyev        err = ngx_errno;
233e18a033bSKonstantin Ananyev
234e18a033bSKonstantin Ananyev        if (err != ERROR_ENVVAR_NOT_FOUND) {
235e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_EMERG, log, err,
236e18a033bSKonstantin Ananyev                          "GetEnvironmentVariable(\"ngx_unique\") failed");
237e18a033bSKonstantin Ananyev            return NGX_ERROR;
238e18a033bSKonstantin Ananyev        }
239e18a033bSKonstantin Ananyev
240e18a033bSKonstantin Ananyev        ngx_sprintf((u_char *) ngx_unique, "%P%Z", ngx_pid);
241e18a033bSKonstantin Ananyev    }
242e18a033bSKonstantin Ananyev
243e18a033bSKonstantin Ananyev    tp = ngx_timeofday();
244e18a033bSKonstantin Ananyev    srand((ngx_pid << 16) ^ (unsigned) tp->sec ^ tp->msec);
245e18a033bSKonstantin Ananyev
246e18a033bSKonstantin Ananyev    return NGX_OK;
247e18a033bSKonstantin Ananyev}
248e18a033bSKonstantin Ananyev
249e18a033bSKonstantin Ananyev
250e18a033bSKonstantin Ananyevvoid
251e18a033bSKonstantin Ananyevngx_os_status(ngx_log_t *log)
252e18a033bSKonstantin Ananyev{
253e18a033bSKonstantin Ananyev    ngx_osviex_stub_t  *osviex_stub;
254e18a033bSKonstantin Ananyev
255e18a033bSKonstantin Ananyev    ngx_log_error(NGX_LOG_NOTICE, log, 0, NGINX_VER_BUILD);
256e18a033bSKonstantin Ananyev
257e18a033bSKonstantin Ananyev    if (osviex) {
258e18a033bSKonstantin Ananyev
259e18a033bSKonstantin Ananyev        /*
260e18a033bSKonstantin Ananyev         * the MSVC 6.0 SP2 defines wSuiteMask and wProductType
261e18a033bSKonstantin Ananyev         * as WORD wReserved[2]
262e18a033bSKonstantin Ananyev         */
263e18a033bSKonstantin Ananyev        osviex_stub = (ngx_osviex_stub_t *) &osvi.wServicePackMinor;
264e18a033bSKonstantin Ananyev
265e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_INFO, log, 0,
266e18a033bSKonstantin Ananyev                      "OS: %ud build:%ud, \"%s\", suite:%Xd, type:%ud",
267e18a033bSKonstantin Ananyev                      ngx_win32_version, osvi.dwBuildNumber, osvi.szCSDVersion,
268e18a033bSKonstantin Ananyev                      osviex_stub->wSuiteMask, osviex_stub->wProductType);
269e18a033bSKonstantin Ananyev
270e18a033bSKonstantin Ananyev    } else {
271e18a033bSKonstantin Ananyev        if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
272e18a033bSKonstantin Ananyev
273e18a033bSKonstantin Ananyev            /* Win9x build */
274e18a033bSKonstantin Ananyev
275e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_INFO, log, 0,
276e18a033bSKonstantin Ananyev                          "OS: %u build:%ud.%ud.%ud, \"%s\"",
277e18a033bSKonstantin Ananyev                          ngx_win32_version,
278e18a033bSKonstantin Ananyev                          osvi.dwBuildNumber >> 24,
279e18a033bSKonstantin Ananyev                          (osvi.dwBuildNumber >> 16) & 0xff,
280e18a033bSKonstantin Ananyev                          osvi.dwBuildNumber & 0xffff,
281e18a033bSKonstantin Ananyev                          osvi.szCSDVersion);
282e18a033bSKonstantin Ananyev
283e18a033bSKonstantin Ananyev        } else {
284e18a033bSKonstantin Ananyev
285e18a033bSKonstantin Ananyev            /*
286e18a033bSKonstantin Ananyev             * VER_PLATFORM_WIN32_NT
287e18a033bSKonstantin Ananyev             *
288e18a033bSKonstantin Ananyev             * we do not currently support VER_PLATFORM_WIN32_CE
289e18a033bSKonstantin Ananyev             * and we do not support VER_PLATFORM_WIN32s at all
290e18a033bSKonstantin Ananyev             */
291e18a033bSKonstantin Ananyev
292e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_INFO, log, 0, "OS: %ud build:%ud, \"%s\"",
293e18a033bSKonstantin Ananyev                          ngx_win32_version, osvi.dwBuildNumber,
294e18a033bSKonstantin Ananyev                          osvi.szCSDVersion);
295e18a033bSKonstantin Ananyev        }
296e18a033bSKonstantin Ananyev    }
297e18a033bSKonstantin Ananyev}
298