1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "apr_private.h"
18#include "apr_arch_misc.h"
19#include "apr_arch_file_io.h"
20#include "assert.h"
21#include "apr_lib.h"
22#include "tchar.h"
23
24APR_DECLARE_DATA apr_oslevel_e apr_os_level = APR_WIN_UNK;
25
26apr_status_t apr_get_oslevel(apr_oslevel_e *level)
27{
28    if (apr_os_level == APR_WIN_UNK)
29    {
30        static OSVERSIONINFO oslev;
31        oslev.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
32        GetVersionEx(&oslev);
33
34        if (oslev.dwPlatformId == VER_PLATFORM_WIN32_NT)
35        {
36            static unsigned int servpack = 0;
37            TCHAR *pservpack;
38            if ((pservpack = oslev.szCSDVersion)) {
39                while (*pservpack && !apr_isdigit(*pservpack)) {
40                    pservpack++;
41                }
42                if (*pservpack)
43#ifdef _UNICODE
44                    servpack = _wtoi(pservpack);
45#else
46                    servpack = atoi(pservpack);
47#endif
48            }
49
50            if (oslev.dwMajorVersion < 3) {
51                apr_os_level = APR_WIN_UNSUP;
52            }
53            else if (oslev.dwMajorVersion == 3) {
54                if (oslev.dwMajorVersion < 50) {
55                    apr_os_level = APR_WIN_UNSUP;
56                }
57                else if (oslev.dwMajorVersion == 50) {
58                    apr_os_level = APR_WIN_NT_3_5;
59                }
60                else {
61                    apr_os_level = APR_WIN_NT_3_51;
62                }
63            }
64            else if (oslev.dwMajorVersion == 4) {
65                if (servpack < 2)
66                    apr_os_level = APR_WIN_NT_4;
67                else if (servpack <= 2)
68                    apr_os_level = APR_WIN_NT_4_SP2;
69                else if (servpack <= 3)
70                    apr_os_level = APR_WIN_NT_4_SP3;
71                else if (servpack <= 4)
72                    apr_os_level = APR_WIN_NT_4_SP4;
73                else if (servpack <= 5)
74                    apr_os_level = APR_WIN_NT_4_SP5;
75                else
76                    apr_os_level = APR_WIN_NT_4_SP6;
77            }
78            else if (oslev.dwMajorVersion == 5) {
79                if (oslev.dwMinorVersion == 0) {
80                    if (servpack == 0)
81                        apr_os_level = APR_WIN_2000;
82                    else if (servpack == 1)
83                        apr_os_level = APR_WIN_2000_SP1;
84                    else
85                        apr_os_level = APR_WIN_2000_SP2;
86                }
87                else if (oslev.dwMinorVersion == 2) {
88                    apr_os_level = APR_WIN_2003;
89                }
90                else {
91                    if (servpack < 1)
92                        apr_os_level = APR_WIN_XP;
93                    else if (servpack == 1)
94                        apr_os_level = APR_WIN_XP_SP1;
95                    else
96                        apr_os_level = APR_WIN_XP_SP2;
97                }
98            }
99            else if (oslev.dwMajorVersion == 6) {
100                apr_os_level = APR_WIN_VISTA;
101            }
102            else {
103                apr_os_level = APR_WIN_XP;
104            }
105        }
106#ifndef WINNT
107        else if (oslev.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
108            TCHAR *prevision;
109            if (prevision = oslev.szCSDVersion) {
110                while (*prevision && !apr_isupper(*prevision)) {
111                     prevision++;
112                }
113            }
114            else prevision = _T("");
115
116            if (oslev.dwMinorVersion < 10) {
117                if (*prevision < _T('C'))
118                    apr_os_level = APR_WIN_95;
119                else
120                    apr_os_level = APR_WIN_95_OSR2;
121            }
122            else if (oslev.dwMinorVersion < 90) {
123                if (*prevision < _T('A'))
124                    apr_os_level = APR_WIN_98;
125                else
126                    apr_os_level = APR_WIN_98_SE;
127            }
128            else {
129                apr_os_level = APR_WIN_ME;
130            }
131        }
132#endif
133#ifdef _WIN32_WCE
134        else if (oslev.dwPlatformId == VER_PLATFORM_WIN32_CE)
135        {
136            if (oslev.dwMajorVersion < 3) {
137                apr_os_level = APR_WIN_UNSUP;
138            }
139            else {
140                apr_os_level = APR_WIN_CE_3;
141            }
142        }
143#endif
144        else {
145            apr_os_level = APR_WIN_UNSUP;
146        }
147    }
148
149    *level = apr_os_level;
150
151    if (apr_os_level < APR_WIN_UNSUP) {
152        return APR_EGENERAL;
153    }
154
155    return APR_SUCCESS;
156}
157
158
159/* This is the helper code to resolve late bound entry points
160 * missing from one or more releases of the Win32 API
161 */
162
163static const char* const lateDllName[DLL_defined] = {
164    "kernel32", "advapi32", "mswsock",  "ws2_32", "shell32", "ntdll.dll"  };
165static HMODULE lateDllHandle[DLL_defined] = {
166     NULL,       NULL,       NULL,       NULL,     NULL,       NULL       };
167
168FARPROC apr_load_dll_func(apr_dlltoken_e fnLib, char* fnName, int ordinal)
169{
170    if (!lateDllHandle[fnLib]) {
171        lateDllHandle[fnLib] = LoadLibraryA(lateDllName[fnLib]);
172        if (!lateDllHandle[fnLib])
173            return NULL;
174    }
175#if defined(_WIN32_WCE)
176    if (ordinal)
177        return GetProcAddressA(lateDllHandle[fnLib], (const char *)
178                                                     (apr_ssize_t)ordinal);
179    else
180        return GetProcAddressA(lateDllHandle[fnLib], fnName);
181#else
182    if (ordinal)
183        return GetProcAddress(lateDllHandle[fnLib], (const char *)
184                                                    (apr_ssize_t)ordinal);
185    else
186        return GetProcAddress(lateDllHandle[fnLib], fnName);
187#endif
188}
189
190/* Declared in include/arch/win32/apr_dbg_win32_handles.h
191 */
192APR_DECLARE_NONSTD(HANDLE) apr_dbg_log(char* fn, HANDLE ha, char* fl, int ln,
193                                       int nh, /* HANDLE hv, char *dsc */...)
194{
195    static DWORD tlsid = 0xFFFFFFFF;
196    static HANDLE fh = NULL;
197    static long ctr = 0;
198    static CRITICAL_SECTION cs;
199    long seq;
200    DWORD wrote;
201    char *sbuf;
202
203    seq = (InterlockedIncrement)(&ctr);
204
205    if (tlsid == 0xFFFFFFFF) {
206        tlsid = (TlsAlloc)();
207    }
208
209    sbuf = (TlsGetValue)(tlsid);
210    if (!fh || !sbuf) {
211        sbuf = (malloc)(1024);
212        (TlsSetValue)(tlsid, sbuf);
213        sbuf[1023] = '\0';
214        if (!fh) {
215            (GetModuleFileNameA)(NULL, sbuf, 250);
216            sprintf(strchr(sbuf, '\0'), ".%u",
217                    (unsigned int)(GetCurrentProcessId)());
218            fh = (CreateFileA)(sbuf, GENERIC_WRITE, 0, NULL,
219                            CREATE_ALWAYS, 0, NULL);
220            (InitializeCriticalSection)(&cs);
221        }
222    }
223
224    if (!nh) {
225        (sprintf)(sbuf, "%p %08x %08x %s() %s:%d\n",
226                  ha, (unsigned int)seq, (unsigned int)GetCurrentThreadId(),
227                  fn, fl, ln);
228        (EnterCriticalSection)(&cs);
229        (WriteFile)(fh, sbuf, (DWORD)strlen(sbuf), &wrote, NULL);
230        (LeaveCriticalSection)(&cs);
231    }
232    else {
233        va_list a;
234        va_start(a,nh);
235        (EnterCriticalSection)(&cs);
236        do {
237            HANDLE *hv = va_arg(a, HANDLE*);
238            char *dsc = va_arg(a, char*);
239            if (strcmp(dsc, "Signaled") == 0) {
240                if ((apr_ssize_t)ha >= STATUS_WAIT_0
241                       && (apr_ssize_t)ha < STATUS_ABANDONED_WAIT_0) {
242                    hv += (apr_ssize_t)ha;
243                }
244                else if ((apr_ssize_t)ha >= STATUS_ABANDONED_WAIT_0
245                            && (apr_ssize_t)ha < STATUS_USER_APC) {
246                    hv += (apr_ssize_t)ha - STATUS_ABANDONED_WAIT_0;
247                    dsc = "Abandoned";
248                }
249                else if ((apr_ssize_t)ha == WAIT_TIMEOUT) {
250                    dsc = "Timed Out";
251                }
252            }
253            (sprintf)(sbuf, "%p %08x %08x %s(%s) %s:%d\n",
254                      *hv, (unsigned int)seq,
255                      (unsigned int)GetCurrentThreadId(),
256                      fn, dsc, fl, ln);
257            (WriteFile)(fh, sbuf, (DWORD)strlen(sbuf), &wrote, NULL);
258        } while (--nh);
259        (LeaveCriticalSection)(&cs);
260        va_end(a);
261    }
262    return ha;
263}
264