blob: 9975eef613e0b0719e309a2dd60c73bb8e6df704 [file] [log] [blame]
/* 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 "crtdbg.h"
#include "apr_arch_file_io.h"
#include "assert.h"
#include "apr_lib.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;
char *pservpack;
if (pservpack = oslev.szCSDVersion) {
while (*pservpack && !apr_isdigit(*pservpack)) {
pservpack++;
}
if (*pservpack)
servpack = atoi(pservpack);
}
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 {
apr_os_level = APR_WIN_XP;
}
}
#ifndef WINNT
else if (oslev.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
char *prevision;
if (prevision = oslev.szCSDVersion) {
while (*prevision && !apr_isupper(*prevision)) {
prevision++;
}
}
else prevision = "";
if (oslev.dwMinorVersion < 10) {
if (*prevision < 'C')
apr_os_level = APR_WIN_95;
else
apr_os_level = APR_WIN_95_OSR2;
}
else if (oslev.dwMinorVersion < 90) {
if (*prevision < 'A')
apr_os_level = APR_WIN_98;
else
apr_os_level = APR_WIN_98_SE;
}
else {
apr_os_level = APR_WIN_ME;
}
}
#endif
#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
*/
static const char* const lateDllName[DLL_defined] = {
"kernel32", "advapi32", "mswsock", "ws2_32", "shell32", "ntdll.dll" };
static HMODULE lateDllHandle[DLL_defined] = {
NULL, NULL, NULL, NULL, NULL, NULL };
FARPROC apr_load_dll_func(apr_dlltoken_e fnLib, char* fnName, int ordinal)
{
if (!lateDllHandle[fnLib]) {
lateDllHandle[fnLib] = LoadLibrary(lateDllName[fnLib]);
if (!lateDllHandle[fnLib])
return NULL;
}
if (ordinal)
return GetProcAddress(lateDllHandle[fnLib], (char *) ordinal);
else
return GetProcAddress(lateDllHandle[fnLib], fnName);
}
/* 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) {
(GetModuleFileName)(NULL, sbuf, 250);
sprintf(strchr(sbuf, '\0'), ".%d",
(GetCurrentProcessId)());
fh = (CreateFile)(sbuf, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, 0, NULL);
(InitializeCriticalSection)(&cs);
}
}
if (!nh) {
(sprintf)(sbuf, "%08x %08x %08x %s() %s:%d\n",
(DWORD)ha, seq, 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 ((DWORD)ha >= STATUS_WAIT_0
&& (DWORD)ha < STATUS_ABANDONED_WAIT_0) {
hv += (DWORD)ha;
}
else if ((DWORD)ha >= STATUS_ABANDONED_WAIT_0
&& (DWORD)ha < STATUS_USER_APC) {
hv += (DWORD)ha - STATUS_ABANDONED_WAIT_0;
dsc = "Abandoned";
}
else if ((DWORD)ha == WAIT_TIMEOUT) {
dsc = "Timed Out";
}
}
(sprintf)(sbuf, "%08x %08x %08x %s(%s) %s:%d\n",
(DWORD*)*hv, seq, GetCurrentThreadId(),
fn, dsc, fl, ln);
(WriteFile)(fh, sbuf, (DWORD)strlen(sbuf), &wrote, NULL);
} while (--nh);
(LeaveCriticalSection)(&cs);
va_end(a);
}
return ha;
}