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 |