1 /* |
|
2 * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Oracle designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Oracle in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 * or visit www.oracle.com if you need additional information or have any |
|
23 * questions. |
|
24 */ |
|
25 |
|
26 #define _WIN32_WINNT 0x0500 |
|
27 #define WINVER 0x0500 |
|
28 |
|
29 #include "stdafx.h" |
|
30 #include <shlobj.h> |
|
31 #include <atlbase.h> |
|
32 #include <locale.h> |
|
33 |
|
34 CComModule _Module; |
|
35 |
|
36 #include <atlwin.h> |
|
37 #include <sys/types.h> |
|
38 #include <sys/stat.h> |
|
39 #include "Windows.h" |
|
40 #include "WinNT.h" |
|
41 #include <shellapi.h> |
|
42 #include "DownloadDialog.h" |
|
43 #include "DownloadHelper.h" |
|
44 #include "kernel.h" |
|
45 #include "sun_jkernel_DownloadManager.h" |
|
46 #include "sun_jkernel_Bundle.h" |
|
47 #include "sun_jkernel_Mutex.h" |
|
48 #include "sun_jkernel_BackgroundDownloader.h" |
|
49 #include <stdio.h> |
|
50 #include <windows.h> |
|
51 #include <conio.h> |
|
52 #include <tchar.h> |
|
53 #include <tchar.h> |
|
54 #include <sddl.h> |
|
55 #include <Aclapi.h> |
|
56 #include <strsafe.h> |
|
57 |
|
58 BOOL IsPlatformWindowsVista(); |
|
59 |
|
60 #define BUFSIZE 4096 |
|
61 |
|
62 #define JBROKERPIPE "\\\\.\\pipe\\jbrokerpipe" |
|
63 #define JREMAINKEY "SOFTWARE\\JavaSoft\\Java Runtime Environment" |
|
64 #define JRE_VERSION_REGISTRY_KEY JREMAINKEY "\\" VERSION |
|
65 #define ReleaseAndClose(mutex) \ |
|
66 if (mutex != NULL) { \ |
|
67 ReleaseMutex(mutex); \ |
|
68 CloseHandle(mutex); \ |
|
69 mutex = NULL; \ |
|
70 } |
|
71 |
|
72 #define KERNEL_DEBUG false |
|
73 |
|
74 // used to inform kernel that we believe it is running in high integrity |
|
75 #define JBROKER_KEY "-Dkernel.spawned.from.jbroker=true -Dkernel.background.download=false" |
|
76 |
|
77 // this is only available on Vista SDK, hard code it here for now |
|
78 #define LABEL_SECURITY_INFORMATION (0x00000010L) |
|
79 |
|
80 // The LABEL_SECURITY_INFORMATION SDDL SACL to be set for low integrity |
|
81 LPCSTR LOW_INTEGRITY_SDDL_SACL = "S:(ML;;NW;;;LW)"; |
|
82 |
|
83 CDownloadDialog dlg; |
|
84 BOOL createDialog = TRUE; |
|
85 |
|
86 CComAutoCriticalSection m_csCreateDialog; |
|
87 |
|
88 typedef BOOL (WINAPI *LPFNInitializeSecurityDescriptor)( |
|
89 PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision); |
|
90 typedef BOOL (WINAPI *LPFNSetSecurityDescriptorDacl)( |
|
91 PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl, |
|
92 BOOL bDaclDefaulted); |
|
93 |
|
94 typedef BOOL (WINAPI *LPFNConvertStringSecurityDescriptorToSecurityDescriptorA)( |
|
95 LPCSTR StringSecurityDescriptor, DWORD StringSDRevision, |
|
96 PSECURITY_DESCRIPTOR* SecurityDescriptor, |
|
97 PULONG SecurityDescriptorSize); |
|
98 |
|
99 typedef BOOL (WINAPI *LPFNGetSecurityDescriptorSacl)( |
|
100 PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbSaclPresent, |
|
101 PACL* pSacl, LPBOOL lpbSaclDefaulted); |
|
102 |
|
103 typedef DWORD (WINAPI *LPFNSetSecurityInfo)(HANDLE handle, |
|
104 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo, |
|
105 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl); |
|
106 |
|
107 BOOL APIENTRY DllMain( HANDLE hModule, |
|
108 DWORD ul_reason_for_call, |
|
109 LPVOID lpReserved |
|
110 ) |
|
111 { |
|
112 return TRUE; |
|
113 } |
|
114 |
|
115 char* getStringPlatformChars(JNIEnv* env, jstring jstr) { |
|
116 char *result = NULL; |
|
117 size_t len; |
|
118 const jchar* utf16 = env->GetStringChars(jstr, NULL); |
|
119 len = wcstombs(NULL, (const wchar_t*)utf16, env->GetStringLength(jstr) * 4) + 1; |
|
120 if (len == -1) |
|
121 return NULL; |
|
122 result = (char*) malloc(len); |
|
123 if (wcstombs(result, (const wchar_t*)utf16, len) == -1) |
|
124 return NULL; |
|
125 env->ReleaseStringChars(jstr, utf16); |
|
126 return result; |
|
127 } |
|
128 |
|
129 bool SetObjectToLowIntegrity ( HANDLE hObject, |
|
130 SE_OBJECT_TYPE type = SE_KERNEL_OBJECT ) { |
|
131 |
|
132 bool bRet = false; |
|
133 DWORD dwErr = ERROR_SUCCESS; |
|
134 PSECURITY_DESCRIPTOR pSD = NULL; |
|
135 PACL pSacl = NULL; |
|
136 BOOL fSaclPresent = FALSE; |
|
137 BOOL fSaclDefaulted = FALSE; |
|
138 |
|
139 // initialize function pointers |
|
140 HMODULE hModule = LoadLibrary("Advapi32.dll"); |
|
141 |
|
142 // ConvertStringSecurityDescriptorToSecurityDescriptorA |
|
143 LPFNConvertStringSecurityDescriptorToSecurityDescriptorA |
|
144 lpfnConvertStringSecurityDescriptorToSecurityDescriptorA = |
|
145 (LPFNConvertStringSecurityDescriptorToSecurityDescriptorA)GetProcAddress( |
|
146 hModule, |
|
147 "ConvertStringSecurityDescriptorToSecurityDescriptorA"); |
|
148 |
|
149 // GetSecurityDescriptorSacl |
|
150 LPFNGetSecurityDescriptorSacl lpfnGetSecurityDescriptorSacl = |
|
151 (LPFNGetSecurityDescriptorSacl)GetProcAddress(hModule, |
|
152 "GetSecurityDescriptorSacl"); |
|
153 |
|
154 // SetSecurityInfo |
|
155 LPFNSetSecurityInfo lpfnSetSecurityInfo = |
|
156 (LPFNSetSecurityInfo)GetProcAddress(hModule, |
|
157 "SetSecurityInfo"); |
|
158 |
|
159 if (lpfnConvertStringSecurityDescriptorToSecurityDescriptorA == NULL || |
|
160 lpfnGetSecurityDescriptorSacl == NULL || |
|
161 lpfnSetSecurityInfo == NULL) { |
|
162 if (KERNEL_DEBUG) { |
|
163 printf("Fail to initialize function pointer\n"); |
|
164 } |
|
165 FreeLibrary(hModule); |
|
166 return FALSE; |
|
167 } |
|
168 |
|
169 // Set object to lower integrity |
|
170 if ( lpfnConvertStringSecurityDescriptorToSecurityDescriptorA( |
|
171 LOW_INTEGRITY_SDDL_SACL, SDDL_REVISION_1, &pSD, NULL ) ) { |
|
172 if ( lpfnGetSecurityDescriptorSacl( |
|
173 pSD, &fSaclPresent, &pSacl, &fSaclDefaulted ) ) { |
|
174 dwErr = lpfnSetSecurityInfo( |
|
175 hObject, type, LABEL_SECURITY_INFORMATION, |
|
176 NULL, NULL, NULL, pSacl ); |
|
177 |
|
178 bRet = (ERROR_SUCCESS == dwErr); |
|
179 } |
|
180 |
|
181 LocalFree( pSD ); |
|
182 } |
|
183 |
|
184 FreeLibrary(hModule); |
|
185 return bRet; |
|
186 } |
|
187 |
|
188 |
|
189 JNIEXPORT jlong JNICALL Java_sun_jkernel_Mutex_createNativeMutex |
|
190 (JNIEnv *env , jclass cls, jstring id) { |
|
191 SECURITY_ATTRIBUTES sa; |
|
192 PSECURITY_DESCRIPTOR pSD = NULL; |
|
193 BOOL saInitialized = FALSE; |
|
194 |
|
195 // initialize function pointers |
|
196 HMODULE hModule = LoadLibrary("Advapi32.dll"); |
|
197 |
|
198 // InitializeSecurityDescriptor |
|
199 LPFNInitializeSecurityDescriptor lpfnInitializeSecurityDescriptor = |
|
200 (LPFNInitializeSecurityDescriptor)GetProcAddress(hModule, |
|
201 "InitializeSecurityDescriptor"); |
|
202 |
|
203 // SetSecurityDescriptorDacl |
|
204 LPFNSetSecurityDescriptorDacl lpfnSetSecurityDescriptorDacl = |
|
205 (LPFNSetSecurityDescriptorDacl)GetProcAddress(hModule, |
|
206 "SetSecurityDescriptorDacl"); |
|
207 |
|
208 if (lpfnInitializeSecurityDescriptor != NULL && |
|
209 lpfnSetSecurityDescriptorDacl != NULL) { |
|
210 |
|
211 // Initialize a security descriptor. |
|
212 pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, |
|
213 SECURITY_DESCRIPTOR_MIN_LENGTH); |
|
214 if (NULL == pSD) { |
|
215 if (KERNEL_DEBUG) { |
|
216 printf("LocalAlloc Error %u\n", GetLastError()); |
|
217 } |
|
218 FreeLibrary(hModule); |
|
219 return NULL; |
|
220 } |
|
221 |
|
222 if (!lpfnInitializeSecurityDescriptor(pSD, |
|
223 SECURITY_DESCRIPTOR_REVISION)) { |
|
224 if (KERNEL_DEBUG) { |
|
225 printf("InitializeSecurityDescriptor Error %u\n", GetLastError()); |
|
226 } |
|
227 FreeLibrary(hModule); |
|
228 return NULL; |
|
229 |
|
230 } |
|
231 // Add the ACL to the security descriptor. |
|
232 if (!lpfnSetSecurityDescriptorDacl(pSD, |
|
233 TRUE, // bDaclPresent flag |
|
234 NULL, // NULL DACL is assigned to the security descriptor, |
|
235 // which allows all access to the object. |
|
236 // This is to allow the mutex to be accessbile by |
|
237 // all users; The background downloader launched |
|
238 // by the installer will be running as SYSTEM user; |
|
239 // while other java process started by the current |
|
240 // user will be running as the current username. |
|
241 FALSE)) // not a default DACL |
|
242 { |
|
243 if (KERNEL_DEBUG) { |
|
244 printf("SetSecurityDescriptorDacl Error %u\n", |
|
245 GetLastError()); |
|
246 } |
|
247 FreeLibrary(hModule); |
|
248 return NULL; |
|
249 } |
|
250 |
|
251 // Initialize a security attributes structure. |
|
252 sa.nLength = sizeof (SECURITY_ATTRIBUTES); |
|
253 sa.lpSecurityDescriptor = pSD; |
|
254 sa.bInheritHandle = FALSE; |
|
255 |
|
256 saInitialized = TRUE; |
|
257 FreeLibrary(hModule); |
|
258 } |
|
259 |
|
260 HANDLE m = CreateMutex(saInitialized ? &sa : NULL, FALSE, |
|
261 (LPCSTR) getStringPlatformChars(env, id)); |
|
262 if (m == NULL) { |
|
263 if (KERNEL_DEBUG) { |
|
264 printf("CreateMutex Error %u\n", GetLastError()); |
|
265 } |
|
266 } |
|
267 |
|
268 // set the mutex object to low integrity on vista, so the mutex |
|
269 // can be accessed by different integrity level |
|
270 if (IsPlatformWindowsVista()) { |
|
271 if (!SetObjectToLowIntegrity(m)) { |
|
272 if (KERNEL_DEBUG) { |
|
273 printf("Fail to set Mutex object to low integrity\n"); |
|
274 } |
|
275 } |
|
276 } |
|
277 return (jlong)m ; |
|
278 } |
|
279 |
|
280 |
|
281 HANDLE getMutexHandle(JNIEnv *env, jobject mutex) { |
|
282 jfieldID handle = env->GetFieldID(env->GetObjectClass(mutex), "handle", "J"); |
|
283 return (HANDLE) env->GetLongField(mutex, handle); |
|
284 } |
|
285 |
|
286 JNIEXPORT jboolean JNICALL Java_sun_jkernel_Mutex_acquire__I |
|
287 (JNIEnv *env, jobject mutex, jint timeout) { |
|
288 HANDLE hmutex = getMutexHandle(env, mutex); |
|
289 if (hmutex != NULL) { |
|
290 int result = WaitForSingleObject(hmutex, timeout); |
|
291 if (result == WAIT_ABANDONED) |
|
292 result = WaitForSingleObject(hmutex, timeout); |
|
293 return (result == WAIT_OBJECT_0); |
|
294 } |
|
295 else |
|
296 return false; |
|
297 } |
|
298 |
|
299 void ThrowByName(JNIEnv *env, const char *name, const char *msg) { |
|
300 jclass cls = env->FindClass(name); |
|
301 /* if cls is NULL, an exception has already been thrown */ |
|
302 if (cls != NULL) { |
|
303 env->ThrowNew(cls, msg); |
|
304 } |
|
305 /* free the local ref */ |
|
306 env->DeleteLocalRef(cls); |
|
307 } |
|
308 |
|
309 JNIEXPORT void JNICALL Java_sun_jkernel_Mutex_acquire__ |
|
310 (JNIEnv *env, jobject mutex) { |
|
311 if (!Java_sun_jkernel_Mutex_acquire__I(env, mutex, INFINITE)) { |
|
312 // failed to acquire mutex, most likely because it was already disposed |
|
313 ThrowByName(env, "java/lang/IllegalStateException", |
|
314 "error acquiring mutex"); |
|
315 } |
|
316 } |
|
317 |
|
318 JNIEXPORT void JNICALL Java_sun_jkernel_Mutex_release |
|
319 (JNIEnv *env, jobject mutex) { |
|
320 HANDLE hmutex = getMutexHandle(env, mutex); |
|
321 if (hmutex != NULL) |
|
322 ReleaseMutex(hmutex); |
|
323 else |
|
324 ThrowByName(env, "java/lang/IllegalStateException", |
|
325 "releasing disposed mutex"); |
|
326 } |
|
327 |
|
328 JNIEXPORT void JNICALL Java_sun_jkernel_Mutex_destroyNativeMutex |
|
329 (JNIEnv *env, jobject mutex) { |
|
330 HANDLE hmutex = getMutexHandle(env, mutex); |
|
331 if (hmutex != NULL) { |
|
332 Java_sun_jkernel_Mutex_release(env, mutex); |
|
333 CloseHandle(hmutex); |
|
334 } |
|
335 } |
|
336 |
|
337 void createDownloadWindowProc(LPVOID lpParameter) { |
|
338 CDownloadDialog* pDlg = (CDownloadDialog *) lpParameter; |
|
339 |
|
340 pDlg->delayedDoModal(); |
|
341 |
|
342 // dialog destroyed, need to create a new one next time |
|
343 createDialog = TRUE; |
|
344 } |
|
345 |
|
346 |
|
347 void createDownloadWindow(LPVOID lpParameter) { |
|
348 // Create a new thread for download window |
|
349 DWORD dwThreadId = NULL; |
|
350 ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) createDownloadWindowProc, lpParameter, 0, &dwThreadId); |
|
351 } |
|
352 |
|
353 JNIEXPORT void JNICALL Java_sun_jkernel_DownloadManager_bundleInstallComplete |
|
354 (JNIEnv *env, jclass dm) { |
|
355 dlg.bundleInstallComplete(); |
|
356 } |
|
357 |
|
358 JNIEXPORT void JNICALL Java_sun_jkernel_DownloadManager_bundleInstallStart |
|
359 (JNIEnv *env, jclass dm) { |
|
360 |
|
361 dlg.bundleInstallStart(); |
|
362 } |
|
363 |
|
364 typedef HRESULT (WINAPI *LPFNIEIsProtectedModeProcess)(BOOL *pbResult); |
|
365 |
|
366 BOOL isRunningIEProtectedMode() { |
|
367 |
|
368 HMODULE hModule = NULL; |
|
369 LPFNIEIsProtectedModeProcess lpfnIEIsProtectedModeProcess; |
|
370 |
|
371 __try { |
|
372 hModule = LoadLibrary("ieframe.dll"); |
|
373 if (hModule != NULL) { |
|
374 |
|
375 lpfnIEIsProtectedModeProcess = (LPFNIEIsProtectedModeProcess) |
|
376 GetProcAddress(hModule, "IEIsProtectedModeProcess"); |
|
377 |
|
378 if (lpfnIEIsProtectedModeProcess != NULL) { |
|
379 BOOL bProtectedMode = FALSE; |
|
380 HRESULT hr = lpfnIEIsProtectedModeProcess(&bProtectedMode); |
|
381 if ( SUCCEEDED(hr) && bProtectedMode ) { |
|
382 // IE is running in protected mode |
|
383 return TRUE; |
|
384 } else { |
|
385 // IE isn't running in protected mode |
|
386 return FALSE; |
|
387 } |
|
388 } |
|
389 } |
|
390 } __finally { |
|
391 if (hModule != NULL) { |
|
392 FreeLibrary(hModule); |
|
393 } |
|
394 } |
|
395 return FALSE; |
|
396 } |
|
397 |
|
398 /* Return TRUE if current running platform is Windows Vista, FALSE otherwise */ |
|
399 BOOL IsPlatformWindowsVista() { |
|
400 static BOOL initialized = FALSE; |
|
401 static BOOL isVista = FALSE; |
|
402 OSVERSIONINFO osvi; |
|
403 |
|
404 if (initialized) { |
|
405 return isVista; |
|
406 } |
|
407 |
|
408 // Initialize the OSVERSIONINFO structure. |
|
409 ZeroMemory( &osvi, sizeof( osvi ) ); |
|
410 osvi.dwOSVersionInfoSize = sizeof( osvi ); |
|
411 |
|
412 GetVersionEx( &osvi ); // Assume this function succeeds. |
|
413 |
|
414 if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && |
|
415 osvi.dwMajorVersion == 6 ) { |
|
416 isVista = TRUE; |
|
417 } else { |
|
418 isVista = FALSE; |
|
419 } |
|
420 |
|
421 initialized = TRUE; |
|
422 |
|
423 return isVista; |
|
424 } |
|
425 |
|
426 JNIEXPORT jboolean JNICALL Java_sun_jkernel_DownloadManager_isIEProtectedMode |
|
427 (JNIEnv *env, jclass dm) { |
|
428 |
|
429 if (isRunningIEProtectedMode()) { |
|
430 return TRUE; |
|
431 } |
|
432 return FALSE; |
|
433 } |
|
434 |
|
435 JNIEXPORT jboolean JNICALL Java_sun_jkernel_DownloadManager_isWindowsVista |
|
436 (JNIEnv *env, jclass dm) { |
|
437 |
|
438 if (IsPlatformWindowsVista()) { |
|
439 return TRUE; |
|
440 } |
|
441 return FALSE; |
|
442 } |
|
443 |
|
444 int sendMessageToBroker(const char * message) { |
|
445 char ackString[1024]; |
|
446 HANDLE hp = INVALID_HANDLE_VALUE; |
|
447 |
|
448 while (hp == INVALID_HANDLE_VALUE) { |
|
449 hp = CreateNamedPipe(_T(JBROKERPIPE), |
|
450 PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE , |
|
451 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, |
|
452 1, // number of pipes that can exist |
|
453 1024, // output buffer |
|
454 1024, // input buffer |
|
455 0, // timeout |
|
456 NULL); // security attributes |
|
457 |
|
458 if (hp == INVALID_HANDLE_VALUE) { |
|
459 DWORD err = GetLastError(); |
|
460 // we only allow one instance of the pipe; if the instance |
|
461 // already exists, we will get ERROR_ACCESS_DENIED, which means |
|
462 // some other process is using the pipe, so let's try again |
|
463 if (err != ERROR_ACCESS_DENIED && err != ERROR_PIPE_BUSY) { |
|
464 // create pipe failed |
|
465 return 0; |
|
466 } |
|
467 // pipe instance might be in use, keep trying |
|
468 } |
|
469 } |
|
470 |
|
471 // Wait for the client to connect; if it succeeds, |
|
472 // the function returns a nonzero value. If the function |
|
473 // returns zero, GetLastError returns ERROR_PIPE_CONNECTED. |
|
474 BOOL fConnected = ConnectNamedPipe(hp, NULL) ? |
|
475 TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); |
|
476 |
|
477 if (fConnected) |
|
478 { |
|
479 // Send message to the pipe server. |
|
480 DWORD cbWritten; |
|
481 |
|
482 BOOL fSuccess = WriteFile( |
|
483 hp, // pipe handle |
|
484 message, // message |
|
485 (strlen(message)+1)*sizeof(char), // message length |
|
486 &cbWritten, // bytes written |
|
487 NULL); // not overlapped |
|
488 |
|
489 if (!fSuccess) |
|
490 { |
|
491 // WriteFile failed |
|
492 CloseHandle(hp); |
|
493 return 0; |
|
494 } |
|
495 |
|
496 // wait for ack from server |
|
497 DWORD cbRead; |
|
498 TCHAR chBuf[BUFSIZE]; |
|
499 |
|
500 do |
|
501 { |
|
502 // Read from the pipe. |
|
503 fSuccess = ReadFile( |
|
504 hp, // pipe handle |
|
505 chBuf, // buffer to receive reply |
|
506 BUFSIZE*sizeof(TCHAR), // size of buffer |
|
507 &cbRead, // number of bytes read |
|
508 NULL); // not overlapped |
|
509 |
|
510 if (! fSuccess && GetLastError() != ERROR_MORE_DATA) |
|
511 break; |
|
512 |
|
513 sprintf(ackString, "%s", chBuf); |
|
514 |
|
515 |
|
516 } while (!fSuccess); // repeat loop if ERROR_MORE_DATA |
|
517 } |
|
518 |
|
519 CloseHandle(hp); |
|
520 |
|
521 if (strcmp(ackString, "SUCCESS") == 0) { |
|
522 // server completed move command successfully |
|
523 return 1; |
|
524 } |
|
525 |
|
526 return 0; |
|
527 } |
|
528 |
|
529 int sendMoveMessageToBroker(const char * fromPath, const char * userHome) { |
|
530 // Send move message |
|
531 char * movecmd = "MOVEFILE"; |
|
532 |
|
533 char * msg = (char*)malloc((strlen(fromPath) + strlen(movecmd) + |
|
534 strlen(userHome) + 3) * sizeof(char)); |
|
535 |
|
536 sprintf(msg, "%s*%s*%s", movecmd, fromPath, userHome); |
|
537 |
|
538 return sendMessageToBroker(msg); |
|
539 } |
|
540 |
|
541 int sendMoveDirMessageToBroker(const char * fromPath, const char * userHome) { |
|
542 // Send move dir message |
|
543 char * movecmd = "MOVEDIR"; |
|
544 |
|
545 char * msg = (char*)malloc((strlen(fromPath) + strlen(movecmd) + |
|
546 strlen(userHome) + 3) * sizeof(char)); |
|
547 |
|
548 sprintf(msg, "%s*%s*%s", movecmd, fromPath, userHome); |
|
549 |
|
550 return sendMessageToBroker(msg); |
|
551 } |
|
552 |
|
553 |
|
554 int sendKillMessageToBroker() { |
|
555 // Send move message |
|
556 char * killcmd = "KILLBROKER"; |
|
557 return sendMessageToBroker(killcmd); |
|
558 } |
|
559 |
|
560 |
|
561 int sendPerformCompletionMessageToBroker(const char *javaHome) { |
|
562 const char *cmd = "PERFORMCOMPLETION"; |
|
563 |
|
564 int result = sendMessageToBroker(cmd); |
|
565 |
|
566 if (result) |
|
567 sendKillMessageToBroker(); |
|
568 return result; |
|
569 } |
|
570 |
|
571 int getConstantInt(JNIEnv *env, jclass cls, const char *name) { |
|
572 jfieldID handle = env->GetStaticFieldID(cls, name, "I"); |
|
573 return env->GetStaticIntField(cls, handle); |
|
574 } |
|
575 |
|
576 JNIEXPORT void JNICALL Java_sun_jkernel_DownloadManager_displayError |
|
577 (JNIEnv *env, jclass dm, jint code, jstring arg) { |
|
578 int messageId = IDS_FATAL_ERROR; |
|
579 int titleId = IDS_ERROR_CAPTION; |
|
580 if (code == getConstantInt(env, dm, "ERROR_MALFORMED_BUNDLE_PROPERTIES")) |
|
581 messageId = IDS_ERROR_MALFORMED_BUNDLE_PROPERTIES; |
|
582 else if (code == getConstantInt(env, dm, "ERROR_DOWNLOADING_BUNDLE_PROPERTIES")) |
|
583 messageId = IDS_ERROR_DOWNLOADING_BUNDLE_PROPERTIES; |
|
584 else if (code == getConstantInt(env, dm, "ERROR_MALFORMED_URL")) |
|
585 messageId = IDS_ERROR_MALFORMED_URL; |
|
586 char message[BUFFER_SIZE]; |
|
587 char rawMessage[BUFFER_SIZE]; |
|
588 char title[BUFFER_SIZE]; |
|
589 ::LoadString(_Module.GetModuleInstance(), titleId, title, BUFFER_SIZE); |
|
590 ::LoadString(_Module.GetModuleInstance(), messageId, rawMessage, BUFFER_SIZE); |
|
591 if (arg != NULL) { |
|
592 char *chars = getStringPlatformChars(env, arg); |
|
593 sprintf(message, rawMessage, chars); |
|
594 } |
|
595 else |
|
596 strcpy(message, rawMessage); |
|
597 |
|
598 MessageBox(NULL, message, title, MB_OK|MB_TASKMODAL); |
|
599 } |
|
600 |
|
601 JNIEXPORT jboolean JNICALL Java_sun_jkernel_DownloadManager_askUserToRetryDownloadOrQuit |
|
602 (JNIEnv *env, jclass dm, jint code) { |
|
603 |
|
604 int ret; |
|
605 if (code == getConstantInt(env, dm, "ERROR_DISK_FULL")) { |
|
606 ret = dlg.SafeMessageBox(IDS_DISK_FULL_ERROR, |
|
607 IDS_DISK_FULL_ERROR_CAPTION, |
|
608 IDS_ERROR_CAPTION, |
|
609 DIALOG_ERROR_RETRYCANCEL); |
|
610 } else { |
|
611 ret = dlg.SafeMessageBox(IDS_DOWNLOAD_RETRY_TEXT, |
|
612 IDS_DOWNLOAD_RETRY, |
|
613 IDS_ERROR_CAPTION, |
|
614 DIALOG_ERROR_RETRYCANCEL); |
|
615 } |
|
616 if (ret != IDRETRY) { |
|
617 // user choose to exit, return 0 |
|
618 return JNI_FALSE; |
|
619 } |
|
620 |
|
621 // return 1 (retry the download) |
|
622 return JNI_TRUE; |
|
623 } |
|
624 |
|
625 JNIEXPORT void JNICALL Java_sun_jkernel_DownloadManager_startBackgroundDownloadWithBrokerImpl |
|
626 (JNIEnv *env, jclass dm, jstring command) { |
|
627 |
|
628 char* szCommand = getStringPlatformChars(env, command); |
|
629 |
|
630 // Send createprocess message |
|
631 char * createproccmd = "STARTBACKGROUNDDOWNLOAD"; |
|
632 |
|
633 char * msg = (char*)malloc((strlen(createproccmd) + strlen(szCommand) + 2) * sizeof(char)); |
|
634 |
|
635 sprintf(msg, "%s*%s", createproccmd, szCommand); |
|
636 |
|
637 sendMessageToBroker(msg); |
|
638 |
|
639 free(szCommand); |
|
640 } |
|
641 |
|
642 |
|
643 void getParent(TCHAR *path, TCHAR *dest) { |
|
644 char* lastSlash = max(strrchr(path, '\\'), strrchr(path, '/')); |
|
645 if (lastSlash == NULL) { |
|
646 *dest = NULL; |
|
647 return; |
|
648 } |
|
649 if (path != dest) |
|
650 strcpy(dest, path); |
|
651 *lastSlash = NULL; |
|
652 } |
|
653 |
|
654 |
|
655 bool createProcess(const TCHAR *path, const TCHAR *args) { |
|
656 SHELLEXECUTEINFOA shInfo; |
|
657 |
|
658 shInfo.cbSize = sizeof(SHELLEXECUTEINFOA); |
|
659 shInfo.fMask = 0; |
|
660 shInfo.hwnd = NULL; |
|
661 shInfo.lpVerb = "runas"; |
|
662 shInfo.lpFile = path; |
|
663 shInfo.lpParameters = args; |
|
664 shInfo.lpDirectory = NULL; |
|
665 shInfo.nShow = SW_NORMAL; |
|
666 shInfo.hInstApp = NULL; |
|
667 |
|
668 int result = (int) ::ShellExecuteExA(&shInfo); |
|
669 // ShellExecute is documented to return >32 on success, but I'm consistently |
|
670 // getting a return of 1 despite obviously successful results. 1 is not a |
|
671 // documented return code from ShellExecute, and this may have something to |
|
672 // do with the fact that we're using an undocumented verb in the first place |
|
673 // ("runas"). |
|
674 return result > 32 || result == 1; |
|
675 } |
|
676 |
|
677 |
|
678 bool launchJBroker(const char *szJavaHome) { |
|
679 char szPath[2048]; |
|
680 wsprintf(szPath, "%s\\bin\\jbroker.exe", szJavaHome); |
|
681 return createProcess(szPath, NULL); |
|
682 } |
|
683 |
|
684 |
|
685 JNIEXPORT jboolean JNICALL Java_sun_jkernel_DownloadManager_launchJBroker |
|
686 (JNIEnv *env, jclass dm, jstring javaHomePath) { |
|
687 char* szJavaHome = getStringPlatformChars(env, javaHomePath); |
|
688 bool result = launchJBroker(szJavaHome); |
|
689 free(szJavaHome); |
|
690 return result ? TRUE : FALSE; |
|
691 } |
|
692 |
|
693 |
|
694 bool isJBrokerRunning() { |
|
695 HANDLE hMutex = NULL; |
|
696 DWORD ret = 0; |
|
697 |
|
698 if (isRunningIEProtectedMode()) { |
|
699 |
|
700 // check if jbroker process is running |
|
701 // Use OpenMutex since we have limited access rights. |
|
702 // CreateMutex function will fail with ERROR_ACCESS_DENIED in protected mode |
|
703 hMutex = OpenMutex(SYNCHRONIZE, FALSE, "SunJavaBrokerMutex"); |
|
704 |
|
705 ret = ::GetLastError(); |
|
706 |
|
707 if (hMutex != NULL) { |
|
708 CloseHandle(hMutex); |
|
709 } |
|
710 |
|
711 if (ret == ERROR_FILE_NOT_FOUND) |
|
712 { |
|
713 // jbroker not running yet, launch it |
|
714 return FALSE; |
|
715 } |
|
716 |
|
717 return TRUE; |
|
718 |
|
719 } else { |
|
720 hMutex = ::CreateMutex(NULL, TRUE, "SunJavaBrokerMutex"); |
|
721 |
|
722 if ( (hMutex == NULL) || (::GetLastError() == ERROR_ALREADY_EXISTS)) { |
|
723 // jbroker already running |
|
724 if (hMutex != NULL) ::CloseHandle(hMutex); |
|
725 return TRUE; |
|
726 } |
|
727 |
|
728 if (hMutex != NULL) ::CloseHandle(hMutex); |
|
729 |
|
730 return FALSE; |
|
731 } |
|
732 } |
|
733 |
|
734 |
|
735 JNIEXPORT jboolean JNICALL Java_sun_jkernel_DownloadManager_isJBrokerRunning |
|
736 (JNIEnv *env, jclass dm) { |
|
737 return isJBrokerRunning() ? TRUE : FALSE; |
|
738 } |
|
739 |
|
740 |
|
741 JNIEXPORT jboolean JNICALL Java_sun_jkernel_DownloadManager_moveDirWithBrokerImpl |
|
742 (JNIEnv *env, jclass dm, jstring fromPath, jstring userHome) { |
|
743 |
|
744 char* fromPathChars = getStringPlatformChars(env, fromPath); |
|
745 |
|
746 char* userHomeChars = getStringPlatformChars(env, userHome); |
|
747 |
|
748 int ret = sendMoveDirMessageToBroker(fromPathChars, userHomeChars); |
|
749 |
|
750 free(fromPathChars); |
|
751 |
|
752 free(userHomeChars); |
|
753 |
|
754 if (ret == 0) { |
|
755 return FALSE; |
|
756 } |
|
757 return TRUE; |
|
758 } |
|
759 |
|
760 JNIEXPORT jboolean JNICALL Java_sun_jkernel_DownloadManager_moveFileWithBrokerImpl |
|
761 (JNIEnv *env, jclass dm, jstring fromPath, jstring userHome) { |
|
762 |
|
763 char* fromPathChars = getStringPlatformChars(env, fromPath); |
|
764 |
|
765 char* userHomeChars = getStringPlatformChars(env, userHome); |
|
766 |
|
767 int ret = sendMoveMessageToBroker(fromPathChars, userHomeChars); |
|
768 |
|
769 free(fromPathChars); |
|
770 |
|
771 free(userHomeChars); |
|
772 |
|
773 if (ret == 0) { |
|
774 return FALSE; |
|
775 } |
|
776 return TRUE; |
|
777 } |
|
778 |
|
779 /** |
|
780 * Throw an exception with the last Windows error code if available. |
|
781 */ |
|
782 |
|
783 void ThrowByNameWithLastError(JNIEnv *env, char *exception, char* msg) { |
|
784 char fullMsg[1024] = {0}; |
|
785 if (StringCbPrintf(fullMsg, 1024, "%s. Windows error: %d\n", |
|
786 msg, GetLastError()) != S_OK) { |
|
787 |
|
788 // Formatting failed: fall back to msg w/o error code |
|
789 ThrowByName(env, exception, msg); |
|
790 } else { |
|
791 ThrowByName(env, exception, fullMsg); |
|
792 } |
|
793 } |
|
794 |
|
795 /** |
|
796 * Common code for "extra" compression or uncompression. If extra code |
|
797 * not available do nothing but return false. If available, return true |
|
798 * after locating the extra compression library at ".." and the defined |
|
799 * path relative to the native library containing this method's code. |
|
800 * If enabled, compress or uncompress the srcPath file into destpath, |
|
801 * throwing exceptions for errors (see JNI routine docs below for details). |
|
802 */ |
|
803 |
|
804 jboolean extraCommon(BOOL docompress, |
|
805 JNIEnv *env, jclass dm, jstring srcPath, jstring destPath) { |
|
806 #ifdef EXTRA_COMP_INSTALL_PATH |
|
807 const char *operation = (docompress == true) ? "e" : "d"; |
|
808 |
|
809 // This should be shared with the deploy tree and should be defined |
|
810 // in an implementation like LzmaAlone.h. However the deploy build |
|
811 // doesn't exit yet wrt to this function pointer type. |
|
812 |
|
813 typedef int (*EXTRACOMPTRTYPE) (int, const char**); |
|
814 |
|
815 // Function pointer for invoking the encoder/decoder (uncompressor) |
|
816 static volatile EXTRACOMPTRTYPE mptr = NULL; |
|
817 // Volatile boolean becomes true when mptr init is finished |
|
818 |
|
819 // Stringifier macros to get the relative library path |
|
820 |
|
821 #define K_STRING(x) #x |
|
822 #define K_GETSTRING(x) K_STRING(x) |
|
823 |
|
824 char *srcPathChars = getStringPlatformChars(env, srcPath); |
|
825 |
|
826 if (srcPathChars == NULL) { |
|
827 // TODO (for all throw calls). If the class&method are *reliably* |
|
828 // reported to the user these message prefixes are silly. |
|
829 ThrowByName(env, "java/io/IOException", |
|
830 "Bundle.uncompress: GetStringPlatformChars failed"); |
|
831 return true; |
|
832 } |
|
833 |
|
834 char *destPathChars = getStringPlatformChars(env, destPath); |
|
835 if (destPathChars == NULL) { |
|
836 free(srcPathChars); |
|
837 ThrowByName(env, "java/io/IOException", |
|
838 "Bundle.uncompress: GetStringPlatformChars failed"); |
|
839 return true; |
|
840 } |
|
841 if (KERNEL_DEBUG) { |
|
842 printf("LZMA: %s %s to %s\n", operation, srcPathChars, destPathChars); |
|
843 } |
|
844 |
|
845 |
|
846 // This loop avoids a lot of repetitious code for exception handling. |
|
847 // If any loops are put inside this one be careful to properly |
|
848 // handle exceptions within the inner loops. |
|
849 |
|
850 do { |
|
851 |
|
852 if (mptr == NULL) { |
|
853 |
|
854 // Need to locate and link to the extra compression lib, which |
|
855 // has a pathname relative to the directory containing the library |
|
856 // containing this code, which is assumed to be one directory |
|
857 // "below" the JRE base path. That is, the JRE base path is |
|
858 // assumed to be ".." from the path of this library and then |
|
859 // EXTRA_COMP_INSTALL_PATH from the JRE base path is expected to |
|
860 // be the compression lib path. |
|
861 // But this code is defensive and tries not to fail if the |
|
862 // currently executing library is in ".". It will fail in a |
|
863 // case like this if the extra compression lib path isn't |
|
864 // "./EXTRA_CMP_INSTALL_PATH" (or just "EXTRA_CMP_INSTALL_PATH"). |
|
865 // Use macro magic to get the path macro as a string value. |
|
866 |
|
867 const char *libRelativePath = K_GETSTRING(EXTRA_COMP_INSTALL_PATH); |
|
868 |
|
869 // The max length the base JRE path can be to safely concatenate |
|
870 // libRelativePath, a (possible) separator, and a null terminator. |
|
871 int jreMaxPathLength = MAX_PATH - sizeof(libRelativePath) - 2; |
|
872 |
|
873 TCHAR extraLibPath[MAX_PATH] = {0}; |
|
874 HMODULE kernel = GetModuleHandle("jkernel"); |
|
875 if (kernel != NULL) { |
|
876 DWORD result = GetModuleFileName(kernel, extraLibPath, |
|
877 MAX_PATH-1); |
|
878 if (result > 0) { |
|
879 // remove the name of this library (and maybe a |
|
880 // separator) |
|
881 getParent(extraLibPath, extraLibPath); |
|
882 if (extraLibPath[0] != NULL) { |
|
883 // There was a directory containing the library |
|
884 // (probably "<something or nothing\\>bin"), so |
|
885 // remove that to go up to the assumed JRE base path |
|
886 getParent(extraLibPath, extraLibPath); |
|
887 } else { |
|
888 ThrowByName(env, "java/io/IOException", |
|
889 "bundle uncompression: expected lib path component not found"); |
|
890 break; |
|
891 } |
|
892 // This is effectively an assertion that the concat |
|
893 // below cannot overflow |
|
894 if (extraLibPath[0] != NULL) { |
|
895 // Current dir is not ".", so add a separator |
|
896 strcat(extraLibPath, "\\"); |
|
897 } |
|
898 if ((strlen(extraLibPath) + 1) > jreMaxPathLength) { |
|
899 ThrowByName(env, "java/io/IOException", |
|
900 "bundle uncompression: JRE base pathname too long"); |
|
901 break; |
|
902 } |
|
903 strcat(extraLibPath, libRelativePath); |
|
904 } else { |
|
905 ThrowByName(env, "java/io/IOException", |
|
906 "bundle uncompression: GetModuleFileName failed"); |
|
907 break; |
|
908 } |
|
909 } else { |
|
910 ThrowByNameWithLastError(env, "java/io/IOException", |
|
911 "bundle uncompression: GetModuleHandle failed"); |
|
912 break; |
|
913 } |
|
914 |
|
915 // Load the library and develop a pointer to the decoder routine |
|
916 |
|
917 if (KERNEL_DEBUG) { |
|
918 printf("bundle uncompression: extra library path %s\n", |
|
919 extraLibPath); |
|
920 } |
|
921 |
|
922 HMODULE handle = LoadLibrary(extraLibPath); |
|
923 if (handle == NULL) { |
|
924 ThrowByNameWithLastError(env, "java/io/IOException", |
|
925 "bundle uncompression: LoadLibrary failed"); |
|
926 break; |
|
927 } |
|
928 |
|
929 // find the extra uncompression routine |
|
930 |
|
931 mptr = (EXTRACOMPTRTYPE) GetProcAddress(handle, |
|
932 "ExtraCompressionMain"); |
|
933 |
|
934 if (mptr == NULL) { |
|
935 ThrowByNameWithLastError(env, "java/io/IOException", |
|
936 "bundle uncompression: GetProcAddress failed"); |
|
937 break; |
|
938 } |
|
939 } |
|
940 |
|
941 // Create the arguments for the decoder |
|
942 // Decoder options must go *between* the "d" argument and the |
|
943 // source path arguments and don't forget to keep the 1st arg to |
|
944 // (*mptr) the same as the number of elements of args. |
|
945 const char *args[] = { |
|
946 "", // the shared lib makes no attempt access it's "command name" |
|
947 operation, |
|
948 |
|
949 // Special decoder/encoder switch strings would go here |
|
950 |
|
951 // For example: "-d24", to set the dictionary size to 16MB |
|
952 |
|
953 "-q", // Suppress banner msg output |
|
954 |
|
955 // No special option switch strings after here |
|
956 |
|
957 srcPathChars, |
|
958 destPathChars |
|
959 }; |
|
960 int argc = sizeof(args) / sizeof(const char *); |
|
961 if ((*mptr)(argc, args) != 0) { |
|
962 if (KERNEL_DEBUG) { |
|
963 printf("uncompress lib call failed with args: "); |
|
964 for (int i = 0; i < argc; i++) { |
|
965 printf("%s", args[i]); |
|
966 } |
|
967 printf("\n"); |
|
968 } |
|
969 ThrowByName(env, "java/io/IOException", |
|
970 "bundle uncompression: uncompression failed"); |
|
971 break; |
|
972 } |
|
973 } while (false); |
|
974 |
|
975 free(srcPathChars); |
|
976 free(destPathChars); |
|
977 return TRUE; |
|
978 #else |
|
979 if (KERNEL_DEBUG) { |
|
980 printf("LZMA not compiled in!\n"); |
|
981 } |
|
982 |
|
983 return FALSE; |
|
984 #endif // EXTRA_COMP_INSTALL_PATH |
|
985 } |
|
986 |
|
987 /** |
|
988 * Compress file sourcePath with "extra" algorithm (e.g. 7-Zip LZMA) |
|
989 * if available, put the compressed data into file destPath and |
|
990 * return true. If extra compression is not available do nothing |
|
991 * with destPath and return false; |
|
992 * @param srcPath the path of the uncompressed file |
|
993 * @param destPath the path of the compressed file, if used |
|
994 * @return true if the extra algorithm was used and destPath created |
|
995 * |
|
996 * @throws IOException if the extra compression code should be available |
|
997 * but cannot be located or linked to, the destination file already |
|
998 * exists or cannot be opened for writing, or the compression fails |
|
999 */ |
|
1000 JNIEXPORT jboolean JNICALL Java_sun_jkernel_Bundle_extraCompress |
|
1001 (JNIEnv *env, jclass dm, jstring srcPath, jstring destPath) { |
|
1002 return extraCommon(true, env, dm, srcPath, destPath); |
|
1003 } |
|
1004 |
|
1005 /** |
|
1006 * Uncompress file sourcePath with "extra" algorithm (e.g. 7-Zip LZMA) |
|
1007 * if available, put the uncompressed data into file destPath and |
|
1008 * return true. If if the extra algorithm is not available, leave the |
|
1009 * destination path unchanged and return false; |
|
1010 * @param srcPath the path of the file having extra compression |
|
1011 * @param destPath the path of the uncompressed file |
|
1012 * @return true if the extra algorithm was used |
|
1013 * |
|
1014 * @throws IOException if the extra uncompression code should be available |
|
1015 * but cannot be located or linked to, the destination file already |
|
1016 * exists or cannot be opened for writing, or the uncompression fails |
|
1017 */ |
|
1018 |
|
1019 JNIEXPORT jboolean JNICALL Java_sun_jkernel_Bundle_extraUncompress |
|
1020 (JNIEnv *env, jclass dm, jstring srcPath, jstring destPath) { |
|
1021 return extraCommon(false, env, dm, srcPath, destPath); |
|
1022 } |
|
1023 |
|
1024 |
|
1025 JNIEXPORT void JNICALL Java_sun_jkernel_DownloadManager_addToTotalDownloadSize |
|
1026 (JNIEnv *env, jclass dm, jint size) { |
|
1027 dlg.addToTotalContentLength(size); |
|
1028 } |
|
1029 |
|
1030 JNIEXPORT void JNICALL Java_sun_jkernel_DownloadManager_downloadFromURLImpl |
|
1031 (JNIEnv *env, jclass dm, jstring url, jobject file, jstring name, |
|
1032 jboolean showProgress) { |
|
1033 jclass object = env->FindClass("java/lang/Object"); |
|
1034 jmethodID toString = env->GetMethodID(object, "toString", "()Ljava/lang/String;"); |
|
1035 jstring urlString = (jstring) env->CallObjectMethod(url, toString); |
|
1036 char* urlChars = getStringPlatformChars(env, urlString); |
|
1037 if (KERNEL_DEBUG) { |
|
1038 printf("Kernel downloadFromURL: %s\n", urlChars); |
|
1039 } |
|
1040 jstring fileString = (jstring) env->CallObjectMethod(file, toString); |
|
1041 char* fileChars = getStringPlatformChars(env, fileString); |
|
1042 char* nameChars = getStringPlatformChars(env, name); |
|
1043 |
|
1044 JavaVM *jvm; |
|
1045 env->GetJavaVM(&jvm); |
|
1046 |
|
1047 __try |
|
1048 { |
|
1049 |
|
1050 m_csCreateDialog.Lock(); |
|
1051 if (createDialog && showProgress) { |
|
1052 // create download progress dialog in a new thread |
|
1053 dlg.setJavaVM(jvm); |
|
1054 createDownloadWindow(&dlg); |
|
1055 createDialog = FALSE; |
|
1056 } |
|
1057 |
|
1058 } |
|
1059 __finally |
|
1060 { |
|
1061 m_csCreateDialog.Unlock(); |
|
1062 } |
|
1063 |
|
1064 DownloadHelper dh; |
|
1065 |
|
1066 dh.setJavaVM(jvm); |
|
1067 dh.setURL(urlChars); |
|
1068 dh.setFile(fileChars); |
|
1069 dh.setNameText((char*) nameChars); |
|
1070 dh.setShowProgressDialog(showProgress); |
|
1071 dh.setDownloadDialog(&dlg); |
|
1072 |
|
1073 if (dh.doDownload() != S_OK) { |
|
1074 // remove incomplete file |
|
1075 int ret = DeleteFile(fileChars); |
|
1076 } |
|
1077 |
|
1078 free(urlChars); |
|
1079 free(fileChars); |
|
1080 free(nameChars); |
|
1081 } |
|
1082 |
|
1083 |
|
1084 void error(char* msg) { |
|
1085 MessageBox(NULL, msg, "Java Error", MB_OK); |
|
1086 } |
|
1087 |
|
1088 |
|
1089 // Replace the dest file with the src file. Returns zero on success, Windows |
|
1090 // error code otherwise. |
|
1091 int replace(TCHAR* fullDest, TCHAR* fullSrc) { |
|
1092 struct _stat stat; |
|
1093 int result = _stat(fullSrc, &stat); |
|
1094 if (result == 0) { |
|
1095 DeleteFile(fullDest); |
|
1096 if (MoveFile(fullSrc, fullDest)) |
|
1097 return 0; |
|
1098 else |
|
1099 return GetLastError(); |
|
1100 } |
|
1101 else |
|
1102 return ENOENT; // src file not found |
|
1103 } |
|
1104 |
|
1105 |
|
1106 // Replace the dest file with the src file, where both paths are relative to |
|
1107 // the specified root. Returns zero on success, Windows error code otherwise. |
|
1108 int replaceRelative(TCHAR* root, TCHAR* dest, TCHAR* src) { |
|
1109 TCHAR fullDest[MAX_PATH]; |
|
1110 TCHAR fullSrc[MAX_PATH]; |
|
1111 strcpy(fullDest, root); |
|
1112 strcat(fullDest, dest); |
|
1113 strcpy(fullSrc, root); |
|
1114 strcat(fullSrc, src); |
|
1115 return replace(fullDest, fullSrc); |
|
1116 } |
|
1117 |
|
1118 |
|
1119 // Atomically deletes a file tree. Returns zero on success, Windows |
|
1120 // error code otherwise. |
|
1121 int deleteAll(TCHAR* root) { |
|
1122 TCHAR tmp[MAX_PATH]; |
|
1123 if (strlen(root) + 5 > MAX_PATH) |
|
1124 return ERROR_BUFFER_OVERFLOW; |
|
1125 strcpy(tmp, root); |
|
1126 strcat(tmp, ".tmp"); |
|
1127 struct _stat stat; |
|
1128 int result = _stat(tmp, &stat); |
|
1129 if (result == 0) { |
|
1130 result = !deleteAll(tmp); |
|
1131 if (result) |
|
1132 return result; |
|
1133 } |
|
1134 if (!MoveFile(root, tmp)) |
|
1135 return GetLastError(); |
|
1136 struct _SHFILEOPSTRUCTA fileOp; |
|
1137 memset(&fileOp, NULL, sizeof(fileOp)); |
|
1138 fileOp.wFunc = FO_DELETE; |
|
1139 TCHAR pFrom[MAX_PATH + 1]; |
|
1140 strcpy(pFrom, tmp); |
|
1141 pFrom[strlen(pFrom) + 1] = NULL; // extra null to signify that there is only one file in the list |
|
1142 fileOp.pFrom = pFrom; |
|
1143 fileOp.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI; |
|
1144 return SHFileOperation(&fileOp); |
|
1145 } |
|
1146 |
|
1147 |
|
1148 // moves all file with "wait='true'" specified in bundles.xml into their final |
|
1149 // locations. These files are stored under lib/bundles/tmp, e.g. lib/meta-index |
|
1150 // is stored at lib/bundles/tmp/lib/meta-index. |
|
1151 // relativePath is the current relative path we are searching (e.g. "lib" for the |
|
1152 // example above), which begins as the empty string. |
|
1153 int moveDelayedFiles(TCHAR* javaHome, TCHAR* relativePath) { |
|
1154 TCHAR src[MAX_PATH]; |
|
1155 TCHAR* tmp = "lib\\bundles\\tmp"; |
|
1156 if (strlen(javaHome) + strlen(relativePath) + strlen(tmp) > MAX_PATH) { |
|
1157 error("Path too long."); |
|
1158 return ERROR_BUFFER_OVERFLOW; |
|
1159 } |
|
1160 strcpy(src, javaHome); |
|
1161 strcat(src, tmp); |
|
1162 if (relativePath[0] != NULL) { |
|
1163 strcat(src, "\\"); |
|
1164 strcat(src, relativePath); |
|
1165 } |
|
1166 |
|
1167 struct _stat stat; |
|
1168 int result = _stat(src, &stat); |
|
1169 if (result == 0) { |
|
1170 if (stat.st_mode & _S_IFDIR) { // is a directory, loop through contents |
|
1171 strcat(src, "\\*"); |
|
1172 struct _WIN32_FIND_DATAA file; |
|
1173 HANDLE findHandle = FindFirstFile(src, &file); |
|
1174 if (findHandle != INVALID_HANDLE_VALUE) { |
|
1175 do { |
|
1176 if (file.cFileName[0] != '.') { |
|
1177 char child[MAX_PATH]; |
|
1178 strcpy(child, relativePath); |
|
1179 strcat(child, "\\"); |
|
1180 strcat(child, file.cFileName); |
|
1181 moveDelayedFiles(javaHome, child); |
|
1182 } |
|
1183 } |
|
1184 while (FindNextFile(findHandle, &file) != 0); |
|
1185 FindClose(findHandle); |
|
1186 } |
|
1187 } |
|
1188 else { // normal file, move into place |
|
1189 if (strcmp(relativePath, "\\finished")) { |
|
1190 TCHAR dest[MAX_PATH]; |
|
1191 strcpy(dest, javaHome); |
|
1192 strcat(dest, relativePath); |
|
1193 |
|
1194 DeleteFile(dest); // just in case; ignore failures |
|
1195 if (MoveFile(src, dest)) |
|
1196 return 0; |
|
1197 else |
|
1198 return GetLastError(); |
|
1199 } |
|
1200 } |
|
1201 } |
|
1202 return result; |
|
1203 } |
|
1204 |
|
1205 |
|
1206 // activates Class Data Sharing |
|
1207 void activateCDS(const char *javaHome) { |
|
1208 char java[MAX_PATH]; |
|
1209 strcpy(java, javaHome); |
|
1210 strcat(java, "bin\\javaw.exe"); |
|
1211 |
|
1212 STARTUPINFO si; |
|
1213 PROCESS_INFORMATION pi; |
|
1214 ZeroMemory(&si, sizeof(si)); |
|
1215 si.cb = sizeof(si); |
|
1216 ZeroMemory(&pi, sizeof(pi)); |
|
1217 const char *args = " -Xshare:dump"; |
|
1218 const int argLength = 13; |
|
1219 char commandLine[MAX_PATH + argLength + 2]; |
|
1220 strcpy(commandLine, "\""); |
|
1221 strcat(commandLine, java); |
|
1222 strcat(commandLine, "\""); |
|
1223 strcat(commandLine, args); |
|
1224 if (KERNEL_DEBUG) |
|
1225 printf("Exec: %s\n", commandLine); |
|
1226 if (CreateProcess(java, commandLine, NULL, NULL, FALSE, 0, |
|
1227 NULL, NULL, &si, &pi)) { |
|
1228 CloseHandle(pi.hProcess); |
|
1229 CloseHandle(pi.hThread); |
|
1230 } |
|
1231 else |
|
1232 printf("Error initializing Class Data Sharing: %d", GetLastError()); |
|
1233 } |
|
1234 |
|
1235 typedef BOOL (*LPFNInstallJQS)(); |
|
1236 |
|
1237 // activates the Java Quickstart Service |
|
1238 void activateJQS(HMODULE hModule) { |
|
1239 LPFNInstallJQS lpfnInstallJQS; |
|
1240 |
|
1241 if (hModule != NULL) { |
|
1242 lpfnInstallJQS = (LPFNInstallJQS)GetProcAddress(hModule, "InstallJQS"); |
|
1243 if (lpfnInstallJQS != NULL) { |
|
1244 if ((lpfnInstallJQS)() == false && KERNEL_DEBUG) { |
|
1245 printf("InstallJQS returned FALSE\n"); |
|
1246 } |
|
1247 } |
|
1248 } |
|
1249 } |
|
1250 |
|
1251 // determines JAVA_HOME and stores it in the specified buffer. Returns true on success. |
|
1252 BOOL getJavaHome(char* buffer, int bufferSize) { |
|
1253 HMODULE kernel = GetModuleHandle("jkernel"); |
|
1254 if (kernel != NULL) { |
|
1255 DWORD result = GetModuleFileName(kernel, buffer, bufferSize); |
|
1256 if (result > 0) { |
|
1257 getParent(buffer, buffer); // remove "jkernel.dll" |
|
1258 if (buffer[0] != NULL) |
|
1259 getParent(buffer, buffer); // remove "bin" |
|
1260 if (buffer[0] != NULL) { |
|
1261 strcat(buffer, "\\"); |
|
1262 return TRUE; |
|
1263 } |
|
1264 } |
|
1265 } |
|
1266 return FALSE; |
|
1267 } |
|
1268 |
|
1269 typedef unsigned int (WINAPI *LPFNPostPing)(LPVOID err); |
|
1270 HANDLE PostPing(HMODULE hModule, char* fname, DWORD err) |
|
1271 { |
|
1272 LPFNPostPing lpfnPostPing; |
|
1273 HANDLE hThread = NULL; |
|
1274 lpfnPostPing = (LPFNPostPing)GetProcAddress(hModule, fname); |
|
1275 if (lpfnPostPing != NULL) { |
|
1276 printf("############# ERROR CODE: %d\n", err); |
|
1277 hThread = (HANDLE)_beginthreadex(NULL, 0, lpfnPostPing, |
|
1278 (LPVOID)err, 0, NULL); |
|
1279 if (hThread == NULL) |
|
1280 lpfnPostPing((LPVOID)err); |
|
1281 } |
|
1282 return hThread; |
|
1283 } |
|
1284 |
|
1285 void postPingAndWait(char* fname, DWORD err) { |
|
1286 TCHAR path[MAX_PATH]; |
|
1287 if (getJavaHome(path, MAX_PATH)) { |
|
1288 strcat(path, "bin\\regutils.dll"); |
|
1289 HANDLE hThread = NULL; |
|
1290 HMODULE hModule = LoadLibrary(path); |
|
1291 if (hModule != NULL) { |
|
1292 hThread = PostPing(hModule, fname, err); |
|
1293 if (hThread != NULL) { |
|
1294 DWORD dwRet = 0; |
|
1295 WaitForSingleObject(hThread, 60*1000); |
|
1296 GetExitCodeThread(hThread, &dwRet); |
|
1297 CloseHandle(hThread); |
|
1298 } |
|
1299 } |
|
1300 } |
|
1301 else |
|
1302 printf("error determining JAVA_HOME for ping\n"); |
|
1303 } |
|
1304 |
|
1305 JNIEXPORT void JNICALL Java_sun_jkernel_DownloadManager_postDownloadError |
|
1306 (JNIEnv *env, jclass dm, jint error) { |
|
1307 postPingAndWait("PostKernelDLComp", error); |
|
1308 } |
|
1309 |
|
1310 JNIEXPORT void JNICALL Java_sun_jkernel_DownloadManager_postDownloadComplete |
|
1311 (JNIEnv *env, jclass dm) { |
|
1312 Java_sun_jkernel_DownloadManager_postDownloadError(env, dm, ERROR_SUCCESS); |
|
1313 } |
|
1314 |
|
1315 bool spawnedFromJBroker() { |
|
1316 return strstr(GetCommandLine(), JBROKER_KEY) != NULL; |
|
1317 } |
|
1318 |
|
1319 |
|
1320 // Determines if we have sufficient access to go ahead and perform completion. |
|
1321 // This is true either if we are not on Vista (in which case we can't elevate |
|
1322 // privileges anyway and have to hope for the best) or if we are on Vista and |
|
1323 // running at High integrity level. |
|
1324 bool highIntegrity() { |
|
1325 if (!IsPlatformWindowsVista()) |
|
1326 return TRUE; |
|
1327 else { |
|
1328 // directly determining this would require access to Vista-specific |
|
1329 // APIs, which aren't supported by our current build configurations. |
|
1330 // Instead we look for the presence of a flag on the command line to |
|
1331 // indicate that we were launched by the jbroker process. This is |
|
1332 // actually safer, as it prevents us from re-launching another JRE in |
|
1333 // the event that we somehow didn't end up with high integrity. |
|
1334 return spawnedFromJBroker(); |
|
1335 } |
|
1336 } |
|
1337 |
|
1338 JNIEXPORT jint JNICALL Java_sun_jkernel_DownloadManager_getCurrentProcessId |
|
1339 (JNIEnv *env, jclass dm) { |
|
1340 return (jint) GetCurrentProcessId(); |
|
1341 } |
|
1342 |
|
1343 JNIEXPORT jstring JNICALL Java_sun_jkernel_DownloadManager_getVisitorId0 |
|
1344 (JNIEnv *env, jclass dm) { |
|
1345 CRegKey swKey, jsKey, juKey, pKey; |
|
1346 if (swKey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE", KEY_READ) != ERROR_SUCCESS){ |
|
1347 return NULL; |
|
1348 } |
|
1349 |
|
1350 if (jsKey.Open(swKey, "JavaSoft", KEY_READ) != ERROR_SUCCESS){ |
|
1351 return NULL; |
|
1352 } |
|
1353 |
|
1354 if (juKey.Open(jsKey, "Java Update", KEY_READ) != ERROR_SUCCESS){ |
|
1355 return NULL; |
|
1356 } |
|
1357 |
|
1358 if (pKey.Open(juKey, "Policy", KEY_READ) != ERROR_SUCCESS){ |
|
1359 return NULL; |
|
1360 } |
|
1361 |
|
1362 DWORD dwCount = BUFSIZE; |
|
1363 char* keyValue = new char[BUFSIZE]; |
|
1364 if (pKey.QueryValue(keyValue, "VisitorId", &dwCount) != ERROR_SUCCESS){ |
|
1365 return NULL; |
|
1366 } |
|
1367 jstring visitorId = env->NewStringUTF(keyValue); |
|
1368 |
|
1369 return visitorId; |
|
1370 } |
|
1371 |
|
1372 |
|
1373 JNIEXPORT jstring JNICALL Java_sun_jkernel_DownloadManager_getUrlFromRegistry |
|
1374 (JNIEnv *env, jclass dm) { |
|
1375 |
|
1376 CRegKey swKey, jsKey; |
|
1377 if (swKey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE", KEY_READ) != ERROR_SUCCESS){ |
|
1378 return NULL; |
|
1379 } |
|
1380 |
|
1381 if (jsKey.Open(swKey, "JavaSoft", KEY_READ) != ERROR_SUCCESS){ |
|
1382 return NULL; |
|
1383 } |
|
1384 |
|
1385 DWORD dwCount = BUFSIZE; |
|
1386 char * keyValue = new char[BUFSIZE]; |
|
1387 if (jsKey.QueryValue(keyValue, "KernelDownloadUrl", &dwCount) != ERROR_SUCCESS){ |
|
1388 return NULL; |
|
1389 } |
|
1390 |
|
1391 jstring downloadKeyValue = env->NewStringUTF(keyValue); |
|
1392 |
|
1393 return downloadKeyValue; |
|
1394 } |
|
1395 |
|
1396 |
|
1397 |
|
1398 jboolean getBooleanRegistryKey(char *name, jboolean defaultValue) { |
|
1399 // Check DWORD registry key |
|
1400 // HKEY_LOCAL_MACHINE/Software/JavaSoft/<name> |
|
1401 |
|
1402 CRegKey swKey, jsKey; |
|
1403 if (swKey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE", KEY_READ) != ERROR_SUCCESS){ |
|
1404 return NULL; |
|
1405 } |
|
1406 |
|
1407 if (jsKey.Open(swKey, "JavaSoft", KEY_READ) != ERROR_SUCCESS){ |
|
1408 return NULL; |
|
1409 } |
|
1410 |
|
1411 DWORD dwValue = 0; |
|
1412 if (jsKey.QueryValue(dwValue, name) != ERROR_SUCCESS){ |
|
1413 |
|
1414 // Key does not exist, will return default value |
|
1415 return defaultValue; |
|
1416 } |
|
1417 |
|
1418 return dwValue != 0; |
|
1419 } |
|
1420 |
|
1421 |
|
1422 JNIEXPORT jboolean JNICALL Java_sun_jkernel_BackgroundDownloader_getBackgroundDownloadKey |
|
1423 (JNIEnv *env, jclass dm) { |
|
1424 return getBooleanRegistryKey("KernelBackgroundDownload", TRUE); |
|
1425 } |
|
1426 |
|
1427 |
|
1428 JNIEXPORT jboolean JNICALL Java_sun_jkernel_DownloadManager_getDebugKey |
|
1429 (JNIEnv *env, jclass dm) { |
|
1430 return getBooleanRegistryKey("KernelDebug", FALSE); |
|
1431 } |
|
1432 |
|
1433 |
|
1434 // Called by the launcher before the JVM starts. If all kernel bundles have been |
|
1435 // downloaded, this function performs various post-download cleanups such as |
|
1436 // moving the merged rt.jar into place. At the end of cleanup, the JRE should |
|
1437 // be indistinguishable from the non-kernel JRE. |
|
1438 void preJVMStart() { |
|
1439 char rawMsg[BUFFER_SIZE]; |
|
1440 char msg[BUFFER_SIZE]; |
|
1441 HMODULE kernel = GetModuleHandle("jkernel"); |
|
1442 if (kernel != NULL) { |
|
1443 TCHAR javaHome[MAX_PATH]; |
|
1444 DWORD result = GetModuleFileName(kernel, javaHome, MAX_PATH); |
|
1445 if (result > 0) { |
|
1446 getParent(javaHome, javaHome); // remove "jkernel.dll" |
|
1447 if (javaHome[0] != NULL) |
|
1448 getParent(javaHome, javaHome); // remove "bin" |
|
1449 if (javaHome[0] != NULL) { |
|
1450 // should now be pointing to correct java.home |
|
1451 strcat(javaHome, "\\"); |
|
1452 bool jbroker = spawnedFromJBroker(); |
|
1453 HANDLE file; |
|
1454 TCHAR rt[MAX_PATH]; |
|
1455 strcpy(rt, javaHome); |
|
1456 strcat(rt, "lib\\rt.jar"); |
|
1457 HANDLE startMutex = CreateMutex(NULL, FALSE, "jvmStart"); |
|
1458 if (!jbroker) { // else mutex is already held by the pre-jbroker JVM |
|
1459 if (KERNEL_DEBUG) |
|
1460 printf("Locking startMutex\n"); |
|
1461 WaitForSingleObject(startMutex, INFINITE); |
|
1462 if (KERNEL_DEBUG) |
|
1463 printf("Locked startMutex\n"); |
|
1464 // open rt.jar for reading. This prevents other JREs from being |
|
1465 // able to acquire a write lock on rt.jar, which is used as a test |
|
1466 // to ensure that no other JREs are running. |
|
1467 // The failure to close the file handle is intentional -- if we |
|
1468 // close it, there will be a brief window between the close and |
|
1469 // when the JRE reopens it during which another jre could get |
|
1470 // a write lock on it, hosing us. |
|
1471 file = CreateFile(rt, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); |
|
1472 if (file == INVALID_HANDLE_VALUE) { |
|
1473 ReleaseAndClose(startMutex); |
|
1474 return; |
|
1475 } |
|
1476 if (KERNEL_DEBUG) |
|
1477 printf("Opened rt.jar for reading\n"); |
|
1478 } |
|
1479 TCHAR finished[MAX_PATH]; |
|
1480 TCHAR* finishedPath = "lib\\bundles\\tmp\\finished"; |
|
1481 if (strlen(javaHome) + strlen(finishedPath) < MAX_PATH) { |
|
1482 strcpy(finished, javaHome); |
|
1483 strcat(finished, finishedPath); |
|
1484 struct _stat finishedStat; |
|
1485 result = _stat(finished, &finishedStat); |
|
1486 if (result == 0) { // JRE has been fully downloaded but not yet cleaned up |
|
1487 if (KERNEL_DEBUG) |
|
1488 printf("Beginning completion.\n"); |
|
1489 if (!jbroker) |
|
1490 CloseHandle(file); |
|
1491 if (highIntegrity()) { |
|
1492 // attempt to open rt.jar for exclusive write access -- if this succeeds, |
|
1493 // we know no other JREs are running |
|
1494 file = CreateFile(rt, GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, NULL, NULL); |
|
1495 if (file == INVALID_HANDLE_VALUE) { |
|
1496 // must be another JRE running... |
|
1497 ReleaseAndClose(startMutex); |
|
1498 return; |
|
1499 } |
|
1500 if (KERNEL_DEBUG) |
|
1501 printf("Opened rt.jar for writing.\n"); |
|
1502 CloseHandle(file); |
|
1503 if (KERNEL_DEBUG) |
|
1504 printf("Closed rt.jar.\n"); |
|
1505 int result = replaceRelative(javaHome, "lib\\rt.jar", |
|
1506 "lib\\bundles\\tmp\\merged-rt.jar"); |
|
1507 if (result != 0 && result != ENOENT) { |
|
1508 ::LoadString(_Module.GetModuleInstance(), IDS_FILE_UPDATE_ERROR, rawMsg, BUFFER_SIZE); |
|
1509 wsprintf(msg, rawMsg, javaHome, "lib\\rt.jar"); |
|
1510 error(msg); |
|
1511 ReleaseAndClose(startMutex); |
|
1512 return; |
|
1513 } |
|
1514 result = replaceRelative(javaHome, "lib\\resources.jar", |
|
1515 "lib\\bundles\\tmp\\merged-resources.jar"); |
|
1516 if (result != 0 && result != ENOENT) { |
|
1517 ::LoadString(_Module.GetModuleInstance(), IDS_FILE_UPDATE_ERROR, rawMsg, BUFFER_SIZE); |
|
1518 wsprintf(msg, rawMsg, javaHome, "lib\\resources.jar"); |
|
1519 error(msg); |
|
1520 ReleaseAndClose(startMutex); |
|
1521 return; |
|
1522 } |
|
1523 |
|
1524 TCHAR bundles[MAX_PATH]; |
|
1525 strcpy(bundles, javaHome); |
|
1526 strcat(bundles, "lib\\bundles"); |
|
1527 if (moveDelayedFiles(javaHome, "")) { |
|
1528 ::LoadString(_Module.GetModuleInstance(), IDS_FILE_UPDATE_ERROR, msg, BUFFER_SIZE); |
|
1529 error(msg); |
|
1530 ReleaseAndClose(startMutex); |
|
1531 return; |
|
1532 } |
|
1533 |
|
1534 TCHAR kernel[MAX_PATH]; |
|
1535 strcpy(kernel, javaHome); |
|
1536 strcat(kernel, "bin\\kernel"); |
|
1537 result = deleteAll(kernel); |
|
1538 if (result != 0 && result != ENOENT) { |
|
1539 ::LoadString(_Module.GetModuleInstance(), IDS_FILE_DELETE_ERROR, rawMsg, BUFFER_SIZE); |
|
1540 wsprintf(msg, rawMsg, kernel); |
|
1541 error(msg); |
|
1542 ReleaseAndClose(startMutex); |
|
1543 return; |
|
1544 } |
|
1545 |
|
1546 if (deleteAll(bundles)) { |
|
1547 // fail silently, CR #6643218 |
|
1548 printf("deleteAll failed!\n"); |
|
1549 ReleaseAndClose(startMutex); |
|
1550 return; |
|
1551 } |
|
1552 |
|
1553 TCHAR kernelMap[MAX_PATH]; |
|
1554 strcpy(kernelMap, javaHome); |
|
1555 strcat(kernelMap, "lib\\kernel.map"); |
|
1556 result = deleteAll(kernelMap); |
|
1557 if (result != 0 && result != ENOENT) { |
|
1558 ::LoadString(_Module.GetModuleInstance(), IDS_FILE_DELETE_ERROR, rawMsg, BUFFER_SIZE); |
|
1559 wsprintf(msg, rawMsg, kernelMap); |
|
1560 error(msg); |
|
1561 ReleaseAndClose(startMutex); |
|
1562 return; |
|
1563 } |
|
1564 |
|
1565 strcpy(rt, javaHome); |
|
1566 strcat(rt, "bin\\regutils.dll"); |
|
1567 HANDLE hThread = NULL; |
|
1568 HMODULE hModule = LoadLibrary(rt); |
|
1569 if (hModule != NULL) |
|
1570 hThread = PostPing(hModule, "PostKernelComp", ERROR_SUCCESS); |
|
1571 if (KERNEL_DEBUG) |
|
1572 printf("Activating JQS.\n"); |
|
1573 activateJQS(hModule); |
|
1574 |
|
1575 if (KERNEL_DEBUG) |
|
1576 printf("Activating CDS.\n"); |
|
1577 activateCDS(javaHome); |
|
1578 |
|
1579 if (hThread != NULL) { |
|
1580 DWORD dwRet = 0; |
|
1581 WaitForSingleObject(hThread, 60*1000); |
|
1582 GetExitCodeThread(hThread, &dwRet); |
|
1583 CloseHandle(hThread); |
|
1584 } |
|
1585 if (hModule != NULL) |
|
1586 FreeLibrary(hModule); |
|
1587 } else { |
|
1588 bool jbroker = isJBrokerRunning(); |
|
1589 if (!jbroker) { |
|
1590 // remove trailing slash |
|
1591 javaHome[strlen(javaHome) - 1] = 0; |
|
1592 jbroker = launchJBroker(javaHome); |
|
1593 if (!jbroker) { |
|
1594 ::LoadString(_Module.GetModuleInstance(), |
|
1595 IDS_JBROKER_ERROR, |
|
1596 msg, |
|
1597 BUFFER_SIZE); |
|
1598 error(msg); |
|
1599 } |
|
1600 } |
|
1601 if (jbroker) |
|
1602 sendPerformCompletionMessageToBroker(javaHome); |
|
1603 } |
|
1604 } |
|
1605 } |
|
1606 if (KERNEL_DEBUG) |
|
1607 printf("Releasing startMutex.\n"); |
|
1608 ReleaseAndClose(startMutex); |
|
1609 } else { |
|
1610 ::LoadString(_Module.GetModuleInstance(), IDS_JAVA_HOME_ERROR, msg, BUFFER_SIZE); |
|
1611 error(msg); |
|
1612 } |
|
1613 } else { |
|
1614 ::LoadString(_Module.GetModuleInstance(), IDS_KERNEL_HOME_ERROR, msg, BUFFER_SIZE); |
|
1615 error(msg); |
|
1616 } |
|
1617 } else { |
|
1618 ::LoadString(_Module.GetModuleInstance(), IDS_KERNEL_HOME_ERROR, msg, BUFFER_SIZE); |
|
1619 error(msg); |
|
1620 } |
|
1621 } |
|