| /* Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "apr_private.h" |
| #include "apr_arch_misc.h" |
| #include "apr_arch_file_io.h" |
| #include "assert.h" |
| #include "apr_lib.h" |
| #include "tchar.h" |
| |
| APR_DECLARE_DATA apr_oslevel_e apr_os_level = APR_WIN_UNK; |
| |
| 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); |
| |
| 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 |
| } |
| |
| if (oslev.dwMajorVersion < 3) { |
| apr_os_level = APR_WIN_UNSUP; |
| } |
| else if (oslev.dwMajorVersion == 3) { |
| if (oslev.dwMajorVersion < 50) { |
| apr_os_level = APR_WIN_UNSUP; |
| } |
| else if (oslev.dwMajorVersion == 50) { |
| apr_os_level = APR_WIN_NT_3_5; |
| } |
| else { |
| apr_os_level = APR_WIN_NT_3_51; |
| } |
| } |
| else if (oslev.dwMajorVersion == 4) { |
| if (servpack < 2) |
| apr_os_level = APR_WIN_NT_4; |
| else if (servpack <= 2) |
| apr_os_level = APR_WIN_NT_4_SP2; |
| else if (servpack <= 3) |
| apr_os_level = APR_WIN_NT_4_SP3; |
| else if (servpack <= 4) |
| apr_os_level = APR_WIN_NT_4_SP4; |
| else if (servpack <= 5) |
| apr_os_level = APR_WIN_NT_4_SP5; |
| else |
| apr_os_level = APR_WIN_NT_4_SP6; |
| } |
| else if (oslev.dwMajorVersion == 5) { |
| if (oslev.dwMinorVersion == 0) { |
| if (servpack == 0) |
| apr_os_level = APR_WIN_2000; |
| else if (servpack == 1) |
| apr_os_level = APR_WIN_2000_SP1; |
| else |
| apr_os_level = APR_WIN_2000_SP2; |
| } |
| else if (oslev.dwMinorVersion == 2) { |
| apr_os_level = APR_WIN_2003; |
| } |
| else { |
| if (servpack < 1) |
| apr_os_level = APR_WIN_XP; |
| else if (servpack == 1) |
| apr_os_level = APR_WIN_XP_SP1; |
| else |
| apr_os_level = APR_WIN_XP_SP2; |
| } |
| } |
| else if (oslev.dwMajorVersion == 6) { |
| if (oslev.dwMinorVersion == 0) |
| apr_os_level = APR_WIN_VISTA; |
| else if (oslev.dwMinorVersion == 1) |
| apr_os_level = APR_WIN_7; |
| else |
| apr_os_level = APR_WIN_8; |
| } |
| else { |
| apr_os_level = APR_WIN_XP; |
| } |
| } |
| #ifdef _WIN32_WCE |
| else if (oslev.dwPlatformId == VER_PLATFORM_WIN32_CE) |
| { |
| if (oslev.dwMajorVersion < 3) { |
| apr_os_level = APR_WIN_UNSUP; |
| } |
| else { |
| apr_os_level = APR_WIN_CE_3; |
| } |
| } |
| #endif |
| else { |
| apr_os_level = APR_WIN_UNSUP; |
| } |
| } |
| |
| *level = apr_os_level; |
| |
| if (apr_os_level < APR_WIN_UNSUP) { |
| return APR_EGENERAL; |
| } |
| |
| return APR_SUCCESS; |
| } |
| |
| |
| /* This is the helper code to resolve late bound entry points |
| * missing from one or more releases of the Win32 API |
| */ |
| |
| typedef struct win32_late_dll_t { |
| const apr_wchar_t *dll_name; |
| HMODULE dll_handle; |
| } win32_late_dll_t; |
| |
| static win32_late_dll_t late_dll[DLL_defined] = { |
| {L"kernel32", NULL}, |
| {L"advapi32", NULL}, |
| {L"mswsock", NULL}, |
| {L"ws2_32", NULL}, |
| {L"shell32", NULL}, |
| {L"ntdll.dll", NULL}, |
| {L"Iphplapi", NULL} |
| }; |
| |
| FARPROC apr_load_dll_func(apr_dlltoken_e fnLib, char* fnName, int ordinal) |
| { |
| if (!late_dll[fnLib].dll_handle) { |
| late_dll[fnLib].dll_handle = LoadLibraryW(late_dll[fnLib].dll_name); |
| if (!late_dll[fnLib].dll_handle) |
| return NULL; |
| } |
| #if defined(_WIN32_WCE) |
| if (ordinal) |
| return GetProcAddressA(late_dll[fnLib].dll_handle, |
| (const char *) (apr_ssize_t)ordinal); |
| else |
| return GetProcAddressA(late_dll[fnLib].dll_handle, fnName); |
| #else |
| if (ordinal) |
| return GetProcAddress(late_dll[fnLib].dll_handle, |
| (const char *) (apr_ssize_t)ordinal); |
| else |
| return GetProcAddress(late_dll[fnLib].dll_handle, fnName); |
| #endif |
| } |
| |
| /* Declared in include/arch/win32/apr_dbg_win32_handles.h |
| */ |
| APR_DECLARE_NONSTD(HANDLE) apr_dbg_log(char* fn, HANDLE ha, char* fl, int ln, |
| int nh, /* HANDLE hv, char *dsc */...) |
| { |
| static DWORD tlsid = 0xFFFFFFFF; |
| static HANDLE fh = NULL; |
| static long ctr = 0; |
| static CRITICAL_SECTION cs; |
| long seq; |
| DWORD wrote; |
| char *sbuf; |
| |
| seq = (InterlockedIncrement)(&ctr); |
| |
| if (tlsid == 0xFFFFFFFF) { |
| tlsid = (TlsAlloc)(); |
| } |
| |
| sbuf = (TlsGetValue)(tlsid); |
| if (!fh || !sbuf) { |
| sbuf = (malloc)(1024); |
| (TlsSetValue)(tlsid, sbuf); |
| sbuf[1023] = '\0'; |
| if (!fh) { |
| (GetModuleFileNameA)(NULL, sbuf, 250); |
| sprintf(strchr(sbuf, '\0'), ".%u", |
| (unsigned int)(GetCurrentProcessId)()); |
| fh = (CreateFileA)(sbuf, GENERIC_WRITE, 0, NULL, |
| CREATE_ALWAYS, 0, NULL); |
| (InitializeCriticalSection)(&cs); |
| } |
| } |
| |
| if (!nh) { |
| (sprintf)(sbuf, "%p %08x %08x %s() %s:%d\n", |
| ha, (unsigned int)seq, (unsigned int)GetCurrentThreadId(), |
| fn, fl, ln); |
| (EnterCriticalSection)(&cs); |
| (WriteFile)(fh, sbuf, (DWORD)strlen(sbuf), &wrote, NULL); |
| (LeaveCriticalSection)(&cs); |
| } |
| else { |
| va_list a; |
| va_start(a,nh); |
| (EnterCriticalSection)(&cs); |
| do { |
| HANDLE *hv = va_arg(a, HANDLE*); |
| char *dsc = va_arg(a, char*); |
| if (strcmp(dsc, "Signaled") == 0) { |
| if ((apr_ssize_t)ha >= STATUS_WAIT_0 |
| && (apr_ssize_t)ha < STATUS_ABANDONED_WAIT_0) { |
| hv += (apr_ssize_t)ha; |
| } |
| else if ((apr_ssize_t)ha >= STATUS_ABANDONED_WAIT_0 |
| && (apr_ssize_t)ha < STATUS_USER_APC) { |
| hv += (apr_ssize_t)ha - STATUS_ABANDONED_WAIT_0; |
| dsc = "Abandoned"; |
| } |
| else if ((apr_ssize_t)ha == WAIT_TIMEOUT) { |
| dsc = "Timed Out"; |
| } |
| } |
| (sprintf)(sbuf, "%p %08x %08x %s(%s) %s:%d\n", |
| *hv, (unsigned int)seq, |
| (unsigned int)GetCurrentThreadId(), |
| fn, dsc, fl, ln); |
| (WriteFile)(fh, sbuf, (DWORD)strlen(sbuf), &wrote, NULL); |
| } while (--nh); |
| (LeaveCriticalSection)(&cs); |
| va_end(a); |
| } |
| return ha; |
| } |