jdk/src/windows/native/sun/jkernel/kernel.cpp
changeset 8249 c3d31a2ce7c6
parent 8248 09e47b898040
parent 8219 4a1c655bfb69
child 8250 a36beda9b9de
equal deleted inserted replaced
8248:09e47b898040 8249:c3d31a2ce7c6
     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 }