/* 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. */ /* * * @author Mladen Turk * @version $Revision: 524383 $, $Date: 2007-03-31 09:34:01 +0200 (Sat, 31 Mar 2007) $ */ #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0500 #endif #include #include #include #include "apr.h" #include "apr_pools.h" #include "apr_poll.h" #include "apr_network_io.h" #include "apr_arch_misc.h" /* for apr_os_level */ #include "apr_arch_atime.h" /* for FileTimeToAprTime */ #include "tcn.h" #ifdef HAVE_OPENSSL #include "ssl_private.h" #endif #pragma warning(push) #pragma warning(disable : 4201) #if (_WIN32_WINNT < 0x0501) #include #endif #include #pragma warning(pop) static CRITICAL_SECTION dll_critical_section; /* dll's critical section */ static HINSTANCE dll_instance = NULL; static SYSTEM_INFO dll_system_info; static HANDLE h_kernel = NULL; static HANDLE h_ntdll = NULL; static char dll_file_name[MAX_PATH]; typedef BOOL (WINAPI *pfnGetSystemTimes)(LPFILETIME, LPFILETIME, LPFILETIME); static pfnGetSystemTimes fnGetSystemTimes = NULL; #if (_WIN32_WINNT < 0x0501) typedef NTSTATUS (WINAPI *pfnNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); static pfnNtQuerySystemInformation fnNtQuerySystemInformation = NULL; #endif BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, LPVOID reserved) { switch (reason) { /** The DLL is loading due to process * initialization or a call to LoadLibrary. */ case DLL_PROCESS_ATTACH: InitializeCriticalSection(&dll_critical_section); dll_instance = instance; GetSystemInfo(&dll_system_info); if ((h_kernel = LoadLibrary("kernel32.dll")) != NULL) fnGetSystemTimes = (pfnGetSystemTimes)GetProcAddress(h_kernel, "GetSystemTimes"); if (fnGetSystemTimes == NULL) { FreeLibrary(h_kernel); h_kernel = NULL; #if (_WIN32_WINNT < 0x0501) if ((h_ntdll = LoadLibrary("ntdll.dll")) != NULL) fnNtQuerySystemInformation = (pfnNtQuerySystemInformation)GetProcAddress(h_ntdll, "NtQuerySystemInformation"); if (fnNtQuerySystemInformation == NULL) { FreeLibrary(h_ntdll); h_ntdll = NULL; } #endif } GetModuleFileName(instance, dll_file_name, sizeof(dll_file_name)); break; /** The attached process creates a new thread. */ case DLL_THREAD_ATTACH: break; /** The thread of the attached process terminates. */ case DLL_THREAD_DETACH: break; /** DLL unload due to process termination * or FreeLibrary. */ case DLL_PROCESS_DETACH: if (h_kernel) FreeLibrary(h_kernel); if (h_ntdll) FreeLibrary(h_ntdll); DeleteCriticalSection(&dll_critical_section); break; default: break; } return TRUE; UNREFERENCED_PARAMETER(reserved); } TCN_IMPLEMENT_CALL(jstring, OS, syserror)(TCN_STDARGS, jint err) { jstring str; void *buf; UNREFERENCED(o); if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buf, 0, NULL)) { str = AJP_TO_JSTRING("Unknown Error"); } else { str = AJP_TO_JSTRING((const char *)buf); LocalFree(buf); } return str; } TCN_IMPLEMENT_CALL(jstring, OS, expand)(TCN_STDARGS, jstring val) { jstring str; jchar buf[TCN_BUFFER_SZ] = L""; DWORD len; TCN_ALLOC_WSTRING(val); UNREFERENCED(o); TCN_INIT_WSTRING(val); len = ExpandEnvironmentStringsW(J2W(val), buf, TCN_BUFFER_SZ - 1); if (len > (TCN_BUFFER_SZ - 1)) { jchar *dbuf = malloc((len + 1) * 2); ExpandEnvironmentStringsW(J2W(val), dbuf, len); str = (*e)->NewString(e, dbuf, wcslen(dbuf)); free(dbuf); } else str = (*e)->NewString(e, buf, wcslen(buf)); TCN_FREE_WSTRING(val); return str; } #define LOG_MSG_EMERG 0xC0000001L #define LOG_MSG_ERROR 0xC0000002L #define LOG_MSG_NOTICE 0x80000003L #define LOG_MSG_WARN 0x80000004L #define LOG_MSG_INFO 0x40000005L #define LOG_MSG_DEBUG 0x00000006L #define LOG_MSG_DOMAIN "Native" static char log_domain[MAX_PATH] = "Native"; static void init_log_source(const char *domain) { HKEY key; DWORD ts; char event_key[MAX_PATH]; strcpy(event_key, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\"); strcat(event_key, domain); if (!RegCreateKey(HKEY_LOCAL_MACHINE, event_key, &key)) { RegSetValueEx(key, "EventMessageFile", 0, REG_SZ, (LPBYTE)&dll_file_name[0], strlen(dll_file_name) + 1); ts = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; RegSetValueEx(key, "TypesSupported", 0, REG_DWORD, (LPBYTE) &ts, sizeof(DWORD)); RegCloseKey(key); } strcpy(log_domain, domain); } TCN_IMPLEMENT_CALL(void, OS, sysloginit)(TCN_STDARGS, jstring domain) { const char *d; TCN_ALLOC_CSTRING(domain); UNREFERENCED(o); if ((d = J2S(domain)) == NULL) d = LOG_MSG_DOMAIN; init_log_source(d); TCN_FREE_CSTRING(domain); } TCN_IMPLEMENT_CALL(void, OS, syslog)(TCN_STDARGS, jint level, jstring msg) { TCN_ALLOC_CSTRING(msg); DWORD id = LOG_MSG_DEBUG; WORD il = EVENTLOG_SUCCESS; HANDLE source; const char *messages[1]; UNREFERENCED(o); switch (level) { case TCN_LOG_EMERG: id = LOG_MSG_EMERG; il = EVENTLOG_ERROR_TYPE; break; case TCN_LOG_ERROR: id = LOG_MSG_ERROR; il = EVENTLOG_ERROR_TYPE; break; case TCN_LOG_NOTICE: id = LOG_MSG_NOTICE; il = EVENTLOG_WARNING_TYPE; break; case TCN_LOG_WARN: id = LOG_MSG_WARN; il = EVENTLOG_WARNING_TYPE; break; case TCN_LOG_INFO: id = LOG_MSG_INFO; il = EVENTLOG_INFORMATION_TYPE; break; } messages[0] = J2S(msg); source = RegisterEventSource(NULL, log_domain); if (source != NULL) { ReportEvent(source, il, 0, id, NULL, 1, 0, messages, NULL); DeregisterEventSource(source); } TCN_FREE_CSTRING(msg); } TCN_IMPLEMENT_CALL(jboolean, OS, is)(TCN_STDARGS, jint type) { UNREFERENCED_STDARGS; #ifdef _WIN64 if (type == 4) return JNI_TRUE; else #endif if (type == 3) return JNI_TRUE; else return JNI_FALSE; } TCN_IMPLEMENT_CALL(jint, OS, info)(TCN_STDARGS, jlongArray inf) { MEMORYSTATUSEX ms; ULONGLONG st[4]; FILETIME ft[4]; PROCESS_MEMORY_COUNTERS pmc; jint rv; int i; jsize ilen = (*e)->GetArrayLength(e, inf); jlong *pvals = (*e)->GetLongArrayElements(e, inf, NULL); if (ilen < 16) { return APR_EINVAL; } for (i = 0; i < 16; i++) pvals[i] = 0; ms.dwLength = sizeof(MEMORYSTATUSEX); UNREFERENCED(o); if (GlobalMemoryStatusEx(&ms)) { pvals[0] = (jlong)ms.ullTotalPhys; pvals[1] = (jlong)ms.ullAvailPhys; pvals[2] = (jlong)ms.ullTotalPageFile; pvals[3] = (jlong)ms.ullAvailPageFile; /* Slots 4 and 5 are for shared memory */ pvals[6] = (jlong)ms.dwMemoryLoad; } else goto cleanup; memset(st, 0, sizeof(st)); if (fnGetSystemTimes) { if ((*fnGetSystemTimes)(&ft[0], &ft[1], &ft[2])) { st[0] = (((ULONGLONG)ft[0].dwHighDateTime << 32) | ft[0].dwLowDateTime) / 10; st[1] = (((ULONGLONG)ft[1].dwHighDateTime << 32) | ft[1].dwLowDateTime) / 10; st[2] = (((ULONGLONG)ft[2].dwHighDateTime << 32) | ft[2].dwLowDateTime) / 10; } else goto cleanup; } #if (_WIN32_WINNT < 0x0501) else if (fnNtQuerySystemInformation) { BYTE buf[2048]; /* This should ne enough for 32 processors */ NTSTATUS rs = (*fnNtQuerySystemInformation)(SystemProcessorPerformanceInformation, (LPVOID)buf, 2048, NULL); if (rs == 0) { PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION pspi = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)&buf[0]; DWORD i; /* Calculate all processors */ for (i = 0; i < dll_system_info.dwNumberOfProcessors; i++) { st[0] += pspi[i].IdleTime.QuadPart / 10; st[1] += pspi[i].KernelTime.QuadPart / 10; st[2] += pspi[i].UserTime.QuadPart / 10; } } else goto cleanup; } #endif pvals[7] = st[0]; pvals[8] = st[1]; pvals[9] = st[2]; memset(st, 0, sizeof(st)); if (GetProcessTimes(GetCurrentProcess(), &ft[0], &ft[1], &ft[2], &ft[3])) { FileTimeToAprTime((apr_time_t *)&st[0], &ft[0]); st[1] = (((ULONGLONG)ft[2].dwHighDateTime << 32) | ft[2].dwLowDateTime) / 10; st[2] = (((ULONGLONG)ft[3].dwHighDateTime << 32) | ft[3].dwLowDateTime) / 10; } pvals[10] = st[0]; pvals[11] = st[1]; pvals[12] = st[2]; if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) { pvals[13] = pmc.WorkingSetSize; pvals[14] = pmc.PeakWorkingSetSize; pvals[15] = pmc.PageFaultCount; } (*e)->ReleaseLongArrayElements(e, inf, pvals, 0); return APR_SUCCESS; cleanup: rv = apr_get_os_error(); (*e)->ReleaseLongArrayElements(e, inf, pvals, 0); return rv; } #ifdef HAVE_OPENSSL static DWORD WINAPI password_thread(void *data) { tcn_pass_cb_t *cb = (tcn_pass_cb_t *)data; MSG msg; HWINSTA hwss; HWINSTA hwsu; HDESK hwds; HDESK hwdu; HWND hwnd; /* Ensure connection to service window station and desktop, and * save their handles. */ GetDesktopWindow(); hwss = GetProcessWindowStation(); hwds = GetThreadDesktop(GetCurrentThreadId()); /* Impersonate the client and connect to the User's * window station and desktop. */ hwsu = OpenWindowStation("WinSta0", FALSE, MAXIMUM_ALLOWED); if (hwsu == NULL) { ExitThread(1); return 1; } SetProcessWindowStation(hwsu); hwdu = OpenDesktop("Default", 0, FALSE, MAXIMUM_ALLOWED); if (hwdu == NULL) { SetProcessWindowStation(hwss); CloseWindowStation(hwsu); ExitThread(1); return 1; } SetThreadDesktop(hwdu); hwnd = CreateDialog(dll_instance, MAKEINTRESOURCE(1001), NULL, NULL); if (hwnd != NULL) ShowWindow(hwnd, SW_SHOW); else { ExitThread(1); return 1; } while (1) { if (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE)) { if (msg.message == WM_KEYUP) { int nVirtKey = (int)msg.wParam; if (nVirtKey == VK_ESCAPE) { DestroyWindow(hwnd); break; } else if (nVirtKey == VK_RETURN) { HWND he = GetDlgItem(hwnd, 1002); if (he) { int n = GetWindowText(he, cb->password, SSL_MAX_PASSWORD_LEN - 1); cb->password[n] = '\0'; } DestroyWindow(hwnd); break; } } TranslateMessage(&msg); DispatchMessage(&msg); } else Sleep(100); } /* Restore window station and desktop. */ SetThreadDesktop(hwds); SetProcessWindowStation(hwss); CloseDesktop(hwdu); CloseWindowStation(hwsu); ExitThread(0); return 0; } int WIN32_SSL_password_prompt(tcn_pass_cb_t *data) { DWORD id; HANDLE thread; /* TODO: See how to display this from service mode */ thread = CreateThread(NULL, 0, password_thread, data, 0, &id); WaitForSingleObject(thread, INFINITE); CloseHandle(thread); return (int)strlen(data->password); } #endif