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