| OLD | NEW |
| (Empty) |
| 1 #ifdef _WINDOWS | |
| 2 | |
| 3 /* Licensed to the Apache Software Foundation (ASF) under one or more | |
| 4 * contributor license agreements. See the NOTICE file distributed with | |
| 5 * this work for additional information regarding copyright ownership. | |
| 6 * The ASF licenses this file to You under the Apache License, Version 2.0 | |
| 7 * (the "License"); you may not use this file except in compliance with | |
| 8 * the License. You may obtain a copy of the License at | |
| 9 * | |
| 10 * http://www.apache.org/licenses/LICENSE-2.0 | |
| 11 * | |
| 12 * Unless required by applicable law or agreed to in writing, software | |
| 13 * distributed under the License is distributed on an "AS IS" BASIS, | |
| 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 15 * See the License for the specific language governing permissions and | |
| 16 * limitations under the License. | |
| 17 */ | |
| 18 | |
| 19 /* | |
| 20 * | |
| 21 * @author Mladen Turk | |
| 22 * @version $Id: system.c 1442587 2013-02-05 13:49:48Z rjung $ | |
| 23 */ | |
| 24 | |
| 25 #ifndef _WIN32_WINNT | |
| 26 #define _WIN32_WINNT 0x0500 | |
| 27 #endif | |
| 28 #include <winsock2.h> | |
| 29 #include <mswsock.h> | |
| 30 #include <ws2tcpip.h> | |
| 31 #include <tlhelp32.h> | |
| 32 | |
| 33 #include "apr.h" | |
| 34 #include "apr_pools.h" | |
| 35 #include "apr_poll.h" | |
| 36 #include "apr_network_io.h" | |
| 37 #include "apr_arch_misc.h" /* for apr_os_level */ | |
| 38 #include "apr_arch_atime.h" /* for FileTimeToAprTime */ | |
| 39 | |
| 40 #include "tcn.h" | |
| 41 #ifdef HAVE_OPENSSL | |
| 42 #include "ssl_private.h" | |
| 43 #endif | |
| 44 | |
| 45 #pragma warning(push) | |
| 46 #pragma warning(disable : 4201) | |
| 47 #if (_WIN32_WINNT < 0x0501) | |
| 48 #include <winternl.h> | |
| 49 #endif | |
| 50 #include <psapi.h> | |
| 51 #pragma warning(pop) | |
| 52 | |
| 53 | |
| 54 static CRITICAL_SECTION dll_critical_section; /* dll's critical section */ | |
| 55 static HINSTANCE dll_instance = NULL; | |
| 56 static SYSTEM_INFO dll_system_info; | |
| 57 static HANDLE h_kernel = NULL; | |
| 58 static HANDLE h_ntdll = NULL; | |
| 59 static char dll_file_name[MAX_PATH]; | |
| 60 | |
| 61 typedef BOOL (WINAPI *pfnGetSystemTimes)(LPFILETIME, LPFILETIME, LPFILETIME); | |
| 62 static pfnGetSystemTimes fnGetSystemTimes = NULL; | |
| 63 #if (_WIN32_WINNT < 0x0501) | |
| 64 typedef NTSTATUS (WINAPI *pfnNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS,
PVOID, ULONG, PULONG); | |
| 65 static pfnNtQuerySystemInformation fnNtQuerySystemInformation = NULL; | |
| 66 #endif | |
| 67 | |
| 68 BOOL | |
| 69 WINAPI | |
| 70 DllMain( | |
| 71 HINSTANCE instance, | |
| 72 DWORD reason, | |
| 73 LPVOID reserved) | |
| 74 { | |
| 75 | |
| 76 switch (reason) { | |
| 77 /** The DLL is loading due to process | |
| 78 * initialization or a call to LoadLibrary. | |
| 79 */ | |
| 80 case DLL_PROCESS_ATTACH: | |
| 81 InitializeCriticalSection(&dll_critical_section); | |
| 82 dll_instance = instance; | |
| 83 GetSystemInfo(&dll_system_info); | |
| 84 if ((h_kernel = LoadLibrary("kernel32.dll")) != NULL) | |
| 85 fnGetSystemTimes = (pfnGetSystemTimes)GetProcAddress(h_kernel, | |
| 86 "GetSystemTimes"); | |
| 87 if (fnGetSystemTimes == NULL) { | |
| 88 FreeLibrary(h_kernel); | |
| 89 h_kernel = NULL; | |
| 90 #if (_WIN32_WINNT < 0x0501) | |
| 91 if ((h_ntdll = LoadLibrary("ntdll.dll")) != NULL) | |
| 92 fnNtQuerySystemInformation = | |
| 93 (pfnNtQuerySystemInformation)GetProcAddress(h_ntdll, | |
| 94 "NtQuerySystemInformation"); | |
| 95 | |
| 96 if (fnNtQuerySystemInformation == NULL) { | |
| 97 FreeLibrary(h_ntdll); | |
| 98 h_ntdll = NULL; | |
| 99 } | |
| 100 #endif | |
| 101 } | |
| 102 GetModuleFileName(instance, dll_file_name, sizeof(dll_file_name)); | |
| 103 break; | |
| 104 /** The attached process creates a new thread. | |
| 105 */ | |
| 106 case DLL_THREAD_ATTACH: | |
| 107 break; | |
| 108 | |
| 109 /** The thread of the attached process terminates. | |
| 110 */ | |
| 111 case DLL_THREAD_DETACH: | |
| 112 break; | |
| 113 | |
| 114 /** DLL unload due to process termination | |
| 115 * or FreeLibrary. | |
| 116 */ | |
| 117 case DLL_PROCESS_DETACH: | |
| 118 if (h_kernel) | |
| 119 FreeLibrary(h_kernel); | |
| 120 if (h_ntdll) | |
| 121 FreeLibrary(h_ntdll); | |
| 122 DeleteCriticalSection(&dll_critical_section); | |
| 123 break; | |
| 124 | |
| 125 default: | |
| 126 break; | |
| 127 } | |
| 128 | |
| 129 return TRUE; | |
| 130 UNREFERENCED_PARAMETER(reserved); | |
| 131 } | |
| 132 | |
| 133 | |
| 134 TCN_IMPLEMENT_CALL(jstring, OS, syserror)(TCN_STDARGS, jint err) | |
| 135 { | |
| 136 jstring str; | |
| 137 void *buf; | |
| 138 | |
| 139 UNREFERENCED(o); | |
| 140 if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | | |
| 141 FORMAT_MESSAGE_FROM_SYSTEM | | |
| 142 FORMAT_MESSAGE_IGNORE_INSERTS, | |
| 143 NULL, | |
| 144 err, | |
| 145 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | |
| 146 (LPTSTR)&buf, | |
| 147 0, | |
| 148 NULL)) { | |
| 149 str = AJP_TO_JSTRING("Unknown Error"); | |
| 150 } | |
| 151 else { | |
| 152 str = AJP_TO_JSTRING((const char *)buf); | |
| 153 LocalFree(buf); | |
| 154 } | |
| 155 return str; | |
| 156 } | |
| 157 | |
| 158 TCN_IMPLEMENT_CALL(jstring, OS, expand)(TCN_STDARGS, jstring val) | |
| 159 { | |
| 160 jstring str; | |
| 161 jchar buf[TCN_BUFFER_SZ] = L""; | |
| 162 DWORD len; | |
| 163 TCN_ALLOC_WSTRING(val); | |
| 164 | |
| 165 UNREFERENCED(o); | |
| 166 TCN_INIT_WSTRING(val); | |
| 167 | |
| 168 len = ExpandEnvironmentStringsW(J2W(val), buf, TCN_BUFFER_SZ - 1); | |
| 169 if (len > (TCN_BUFFER_SZ - 1)) { | |
| 170 jchar *dbuf = malloc((len + 1) * 2); | |
| 171 ExpandEnvironmentStringsW(J2W(val), dbuf, len); | |
| 172 str = (*e)->NewString(e, dbuf, lstrlenW(dbuf)); | |
| 173 free(dbuf); | |
| 174 } | |
| 175 else | |
| 176 str = (*e)->NewString(e, buf, lstrlenW(buf)); | |
| 177 | |
| 178 TCN_FREE_WSTRING(val); | |
| 179 return str; | |
| 180 } | |
| 181 | |
| 182 #define LOG_MSG_EMERG 0xC0000001L | |
| 183 #define LOG_MSG_ERROR 0xC0000002L | |
| 184 #define LOG_MSG_NOTICE 0x80000003L | |
| 185 #define LOG_MSG_WARN 0x80000004L | |
| 186 #define LOG_MSG_INFO 0x40000005L | |
| 187 #define LOG_MSG_DEBUG 0x00000006L | |
| 188 #define LOG_MSG_DOMAIN "Native" | |
| 189 | |
| 190 static char log_domain[MAX_PATH] = "Native"; | |
| 191 | |
| 192 static void init_log_source(const char *domain) | |
| 193 { | |
| 194 HKEY key; | |
| 195 DWORD ts; | |
| 196 char event_key[MAX_PATH]; | |
| 197 | |
| 198 strcpy(event_key, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Applicatio
n\\"); | |
| 199 strcat(event_key, domain); | |
| 200 if (!RegCreateKey(HKEY_LOCAL_MACHINE, event_key, &key)) { | |
| 201 RegSetValueEx(key, "EventMessageFile", 0, REG_SZ, (LPBYTE)&dll_file_name
[0], | |
| 202 lstrlenA(dll_file_name) + 1); | |
| 203 ts = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_
TYPE; | |
| 204 | |
| 205 RegSetValueEx(key, "TypesSupported", 0, REG_DWORD, (LPBYTE) &ts, sizeof(
DWORD)); | |
| 206 RegCloseKey(key); | |
| 207 } | |
| 208 strcpy(log_domain, domain); | |
| 209 } | |
| 210 | |
| 211 TCN_IMPLEMENT_CALL(void, OS, sysloginit)(TCN_STDARGS, jstring domain) | |
| 212 { | |
| 213 const char *d; | |
| 214 TCN_ALLOC_CSTRING(domain); | |
| 215 | |
| 216 UNREFERENCED(o); | |
| 217 | |
| 218 if ((d = J2S(domain)) == NULL) | |
| 219 d = LOG_MSG_DOMAIN; | |
| 220 init_log_source(d); | |
| 221 | |
| 222 TCN_FREE_CSTRING(domain); | |
| 223 } | |
| 224 | |
| 225 TCN_IMPLEMENT_CALL(void, OS, syslog)(TCN_STDARGS, jint level, | |
| 226 jstring msg) | |
| 227 { | |
| 228 TCN_ALLOC_CSTRING(msg); | |
| 229 DWORD id = LOG_MSG_DEBUG; | |
| 230 WORD il = EVENTLOG_SUCCESS; | |
| 231 HANDLE source; | |
| 232 const char *messages[1]; | |
| 233 UNREFERENCED(o); | |
| 234 | |
| 235 switch (level) { | |
| 236 case TCN_LOG_EMERG: | |
| 237 id = LOG_MSG_EMERG; | |
| 238 il = EVENTLOG_ERROR_TYPE; | |
| 239 break; | |
| 240 case TCN_LOG_ERROR: | |
| 241 id = LOG_MSG_ERROR; | |
| 242 il = EVENTLOG_ERROR_TYPE; | |
| 243 break; | |
| 244 case TCN_LOG_NOTICE: | |
| 245 id = LOG_MSG_NOTICE; | |
| 246 il = EVENTLOG_WARNING_TYPE; | |
| 247 break; | |
| 248 case TCN_LOG_WARN: | |
| 249 id = LOG_MSG_WARN; | |
| 250 il = EVENTLOG_WARNING_TYPE; | |
| 251 break; | |
| 252 case TCN_LOG_INFO: | |
| 253 id = LOG_MSG_INFO; | |
| 254 il = EVENTLOG_INFORMATION_TYPE; | |
| 255 break; | |
| 256 } | |
| 257 | |
| 258 messages[0] = J2S(msg); | |
| 259 source = RegisterEventSource(NULL, log_domain); | |
| 260 | |
| 261 if (source != NULL) { | |
| 262 ReportEvent(source, il, | |
| 263 0, | |
| 264 id, | |
| 265 NULL, | |
| 266 1, 0, | |
| 267 messages, NULL); | |
| 268 DeregisterEventSource(source); | |
| 269 } | |
| 270 | |
| 271 TCN_FREE_CSTRING(msg); | |
| 272 } | |
| 273 | |
| 274 TCN_IMPLEMENT_CALL(jboolean, OS, is)(TCN_STDARGS, jint type) | |
| 275 { | |
| 276 UNREFERENCED_STDARGS; | |
| 277 #ifdef _WIN64 | |
| 278 if (type == 4) | |
| 279 return JNI_TRUE; | |
| 280 else | |
| 281 #endif | |
| 282 if (type == 3) | |
| 283 return JNI_TRUE; | |
| 284 else | |
| 285 return JNI_FALSE; | |
| 286 } | |
| 287 | |
| 288 TCN_IMPLEMENT_CALL(jint, OS, info)(TCN_STDARGS, | |
| 289 jlongArray inf) | |
| 290 { | |
| 291 MEMORYSTATUSEX ms; | |
| 292 ULONGLONG st[4]; | |
| 293 FILETIME ft[4]; | |
| 294 PROCESS_MEMORY_COUNTERS pmc; | |
| 295 jint rv; | |
| 296 int i; | |
| 297 jsize ilen = (*e)->GetArrayLength(e, inf); | |
| 298 jlong *pvals = (*e)->GetLongArrayElements(e, inf, NULL); | |
| 299 | |
| 300 if (ilen < 16) { | |
| 301 return APR_EINVAL; | |
| 302 } | |
| 303 for (i = 0; i < 16; i++) | |
| 304 pvals[i] = 0; | |
| 305 | |
| 306 ms.dwLength = sizeof(MEMORYSTATUSEX); | |
| 307 | |
| 308 UNREFERENCED(o); | |
| 309 if (GlobalMemoryStatusEx(&ms)) { | |
| 310 pvals[0] = (jlong)ms.ullTotalPhys; | |
| 311 pvals[1] = (jlong)ms.ullAvailPhys; | |
| 312 pvals[2] = (jlong)ms.ullTotalPageFile; | |
| 313 pvals[3] = (jlong)ms.ullAvailPageFile; | |
| 314 /* Slots 4 and 5 are for shared memory */ | |
| 315 pvals[6] = (jlong)ms.dwMemoryLoad; | |
| 316 } | |
| 317 else | |
| 318 goto cleanup; | |
| 319 | |
| 320 memset(st, 0, sizeof(st)); | |
| 321 | |
| 322 if (fnGetSystemTimes) { | |
| 323 if ((*fnGetSystemTimes)(&ft[0], &ft[1], &ft[2])) { | |
| 324 st[0] = (((ULONGLONG)ft[0].dwHighDateTime << 32) | ft[0].dwLowDateTi
me) / 10; | |
| 325 st[1] = (((ULONGLONG)ft[1].dwHighDateTime << 32) | ft[1].dwLowDateTi
me) / 10; | |
| 326 st[2] = (((ULONGLONG)ft[2].dwHighDateTime << 32) | ft[2].dwLowDateTi
me) / 10; | |
| 327 } | |
| 328 else | |
| 329 goto cleanup; | |
| 330 } | |
| 331 #if (_WIN32_WINNT < 0x0501) | |
| 332 else if (fnNtQuerySystemInformation) { | |
| 333 BYTE buf[2048]; /* This should ne enough for 32 processors */ | |
| 334 NTSTATUS rs = (*fnNtQuerySystemInformation)(SystemProcessorPerformanceIn
formation, | |
| 335 (LPVOID)buf, 2048, NULL); | |
| 336 if (rs == 0) { | |
| 337 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION pspi = (PSYSTEM_PROCESSOR_
PERFORMANCE_INFORMATION)&buf[0]; | |
| 338 DWORD i; | |
| 339 /* Calculate all processors */ | |
| 340 for (i = 0; i < dll_system_info.dwNumberOfProcessors; i++) { | |
| 341 st[0] += pspi[i].IdleTime.QuadPart / 10; | |
| 342 st[1] += pspi[i].KernelTime.QuadPart / 10; | |
| 343 st[2] += pspi[i].UserTime.QuadPart / 10; | |
| 344 } | |
| 345 } | |
| 346 else | |
| 347 goto cleanup; | |
| 348 } | |
| 349 #endif | |
| 350 pvals[7] = st[0]; | |
| 351 pvals[8] = st[1]; | |
| 352 pvals[9] = st[2]; | |
| 353 | |
| 354 memset(st, 0, sizeof(st)); | |
| 355 if (GetProcessTimes(GetCurrentProcess(), &ft[0], &ft[1], &ft[2], &ft[3])) { | |
| 356 FileTimeToAprTime((apr_time_t *)&st[0], &ft[0]); | |
| 357 st[1] = (((ULONGLONG)ft[2].dwHighDateTime << 32) | ft[2].dwLowDateTime)
/ 10; | |
| 358 st[2] = (((ULONGLONG)ft[3].dwHighDateTime << 32) | ft[3].dwLowDateTime)
/ 10; | |
| 359 } | |
| 360 pvals[10] = st[0]; | |
| 361 pvals[11] = st[1]; | |
| 362 pvals[12] = st[2]; | |
| 363 | |
| 364 if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) { | |
| 365 pvals[13] = pmc.WorkingSetSize; | |
| 366 pvals[14] = pmc.PeakWorkingSetSize; | |
| 367 pvals[15] = pmc.PageFaultCount; | |
| 368 } | |
| 369 | |
| 370 (*e)->ReleaseLongArrayElements(e, inf, pvals, 0); | |
| 371 return APR_SUCCESS; | |
| 372 cleanup: | |
| 373 rv = apr_get_os_error(); | |
| 374 (*e)->ReleaseLongArrayElements(e, inf, pvals, 0); | |
| 375 return rv; | |
| 376 } | |
| 377 | |
| 378 #ifdef HAVE_OPENSSL | |
| 379 | |
| 380 static DWORD WINAPI password_thread(void *data) | |
| 381 { | |
| 382 tcn_pass_cb_t *cb = (tcn_pass_cb_t *)data; | |
| 383 MSG msg; | |
| 384 HWINSTA hwss; | |
| 385 HWINSTA hwsu; | |
| 386 HDESK hwds; | |
| 387 HDESK hwdu; | |
| 388 HWND hwnd; | |
| 389 | |
| 390 /* Ensure connection to service window station and desktop, and | |
| 391 * save their handles. | |
| 392 */ | |
| 393 GetDesktopWindow(); | |
| 394 hwss = GetProcessWindowStation(); | |
| 395 hwds = GetThreadDesktop(GetCurrentThreadId()); | |
| 396 | |
| 397 /* Impersonate the client and connect to the User's | |
| 398 * window station and desktop. | |
| 399 */ | |
| 400 hwsu = OpenWindowStation("WinSta0", FALSE, MAXIMUM_ALLOWED); | |
| 401 if (hwsu == NULL) { | |
| 402 ExitThread(1); | |
| 403 return 1; | |
| 404 } | |
| 405 SetProcessWindowStation(hwsu); | |
| 406 hwdu = OpenDesktop("Default", 0, FALSE, MAXIMUM_ALLOWED); | |
| 407 if (hwdu == NULL) { | |
| 408 SetProcessWindowStation(hwss); | |
| 409 CloseWindowStation(hwsu); | |
| 410 ExitThread(1); | |
| 411 return 1; | |
| 412 } | |
| 413 SetThreadDesktop(hwdu); | |
| 414 | |
| 415 hwnd = CreateDialog(dll_instance, MAKEINTRESOURCE(1001), NULL, NULL); | |
| 416 if (hwnd != NULL) | |
| 417 ShowWindow(hwnd, SW_SHOW); | |
| 418 else { | |
| 419 ExitThread(1); | |
| 420 return 1; | |
| 421 } | |
| 422 while (1) { | |
| 423 if (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE)) { | |
| 424 if (msg.message == WM_KEYUP) { | |
| 425 int nVirtKey = (int)msg.wParam; | |
| 426 if (nVirtKey == VK_ESCAPE) { | |
| 427 DestroyWindow(hwnd); | |
| 428 break; | |
| 429 } | |
| 430 else if (nVirtKey == VK_RETURN) { | |
| 431 HWND he = GetDlgItem(hwnd, 1002); | |
| 432 if (he) { | |
| 433 int n = GetWindowText(he, cb->password, SSL_MAX_PASSWORD
_LEN - 1); | |
| 434 cb->password[n] = '\0'; | |
| 435 } | |
| 436 DestroyWindow(hwnd); | |
| 437 break; | |
| 438 } | |
| 439 } | |
| 440 TranslateMessage(&msg); | |
| 441 DispatchMessage(&msg); | |
| 442 } | |
| 443 else | |
| 444 Sleep(100); | |
| 445 } | |
| 446 /* Restore window station and desktop. | |
| 447 */ | |
| 448 SetThreadDesktop(hwds); | |
| 449 SetProcessWindowStation(hwss); | |
| 450 CloseDesktop(hwdu); | |
| 451 CloseWindowStation(hwsu); | |
| 452 | |
| 453 ExitThread(0); | |
| 454 return 0; | |
| 455 } | |
| 456 | |
| 457 int WIN32_SSL_password_prompt(tcn_pass_cb_t *data) | |
| 458 { | |
| 459 DWORD id; | |
| 460 HANDLE thread; | |
| 461 /* TODO: See how to display this from service mode */ | |
| 462 thread = CreateThread(NULL, 0, | |
| 463 password_thread, data, | |
| 464 0, &id); | |
| 465 WaitForSingleObject(thread, INFINITE); | |
| 466 CloseHandle(thread); | |
| 467 return (int)strlen(data->password); | |
| 468 } | |
| 469 | |
| 470 #endif | |
| 471 | |
| 472 #endif | |
| 473 | |
| OLD | NEW |