blob: 6949fc3a42044381b6f9796050e700d45851aadb [file] [log] [blame]
#include "installOS.h"
#include <windows.h>
#include <commctrl.h>
#include <process.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define INSTALL_ICON 401
/* Global Variables */
_TCHAR dirSeparator = _T('\\');
_TCHAR pathSeparator = _T(';');
_TCHAR* consoleVM = _T("java.exe");
_TCHAR* defaultVM = _T("javaw.exe");
_TCHAR* shippedVMDir = _T("jre\\bin\\");
/* Define the window system arguments for the Java VM. */
static _TCHAR* argVM[] = { NULL };
/* Define local variables for the main window. */
static HWND topWindow = 0;
static WNDPROC oldProc;
/* Define local variables for running the JVM and detecting its exit. */
static int jvmProcess = 0;
static int jvmExitCode = 0;
static int jvmExitTimeout = 100;
static int jvmExitTimerId = 99;
/* Define local variables for handling the splash window and its image. */
static int splashTimerId = 88, inputTimerId = 89;
static HWND label = NULL, progress = NULL;
static COLORREF foreground = 0;
static RECT progressRect = {0, 0, 0, 0}, messageRect = {0, 0, 0, 0};
static int value = 0, maximum = 100;
/* Local functions */
static void CALLBACK detectJvmExit( HWND hwnd, UINT uMsg, UINT id, DWORD dwTime );
static HBITMAP loadSplashImage(_TCHAR *baseDir, _TCHAR *fileName);
static void CALLBACK splashTimeout( HWND hwnd, UINT uMsg, UINT id, DWORD dwTime );
static LRESULT WINAPI WndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
/* Display a Message */
void displayMessage( _TCHAR* message )
{
MessageBox( topWindow, message, officialName, MB_OK );
}
/* Initialize Window System
*
* Create a pop window to display the bitmap image.
*
* Return the window handle as the data for the splash command.
*
*/
void initWindowSystem( int* pArgc, _TCHAR* argv[], int showSplash )
{
/* Create a window that has no decorations. */
InitCommonControls();
topWindow = CreateWindowEx (0,
_T("STATIC"),
officialName,
SS_BITMAP | WS_POPUP,
0,
0,
0,
0,
NULL,
NULL,
GetModuleHandle (NULL),
NULL);
SetClassLong(topWindow, GCL_HICON, (LONG)LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(INSTALL_ICON)));
oldProc = (WNDPROC) GetWindowLong (topWindow, GWL_WNDPROC);
SetWindowLong (topWindow, GWL_WNDPROC, (LONG) WndProc);
}
static void readRect(_TCHAR *str, RECT *rect) {
int x, y, width, height;
_TCHAR *temp = str, *comma;
comma = _tcschr(temp, _T(','));
if (comma == NULL) return;
comma[0] = 0;
x = _ttoi(temp);
temp = comma + 1;
comma = _tcschr(temp, _T(','));
if (comma == NULL) return;
comma[0] = 0;
y = _ttoi(temp);
temp = comma + 1;
comma = _tcschr(temp, _T(','));
if (comma == NULL) return;
comma[0] = 0;
width = _ttoi(temp);
temp = comma + 1;
height = _ttoi(temp);
rect->left = x;
rect->top = y;
rect->right = x + width;
rect->bottom = y + height;
}
static void readColor(_TCHAR *str, COLORREF *color) {
int value = _ttoi(str);
*color = ((value & 0xFF0000) >> 16) | (value & 0xFF00) | ((value & 0xFF) << 16);
}
static void readInput() {
int available;
FILE *fd = stdin;
#ifdef _UNICODE
WCHAR *buffer1 = NULL;
#endif
char *buffer = NULL;
_TCHAR *equals = NULL, *end, *line;
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
available = GetFileSize (hStdin, NULL) - SetFilePointer (hStdin, 0, NULL, FILE_CURRENT);
if (available <= 0) return;
buffer = malloc(available + 1);
if (!ReadFile(hStdin, buffer, available, &available, NULL)) {
return;
}
if (available <= 0) {
free(buffer);
return;
}
buffer[available] = 0;
#ifdef _UNICODE
{
buffer1 = malloc((available + 1) * sizeof(TCHAR));
available = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPCSTR)buffer, available, (LPWSTR)buffer1, available);
buffer1[available] = 0;
line = buffer1;
}
#else
line = buffer;
#endif
while (line != NULL) {
end = _tcschr(line, _T('\n'));
equals = _tcschr(line, _T('='));
if (end != NULL) end[0] = 0;
if (equals != NULL) {
_TCHAR *str = (_TCHAR *)equals + 1;
equals[0] = 0;
if (_tcscmp(line, _T("maximum")) == 0) {
maximum = _ttoi(str);
if (progress) {
SendMessage (progress, PBM_SETRANGE32, 0, maximum);
}
} else if (_tcscmp(line, _T("value")) == 0) {
value = _ttoi(str);
if (progress) {
SendMessage (progress, PBM_SETPOS, value, 0);
}
} else if (_tcscmp(line, _T("progressRect")) == 0) {
readRect(str, &progressRect);
if (progress) {
int flags = SWP_NOZORDER | SWP_DRAWFRAME | SWP_NOACTIVATE;
SetWindowPos (progress, 0, progressRect.left, progressRect.top, progressRect.right - progressRect.left, progressRect.bottom - progressRect.top, flags);
}
} else if (_tcscmp(line, _T("messageRect")) == 0) {
readRect(str, &messageRect);
if (label) {
int flags = SWP_NOZORDER | SWP_DRAWFRAME | SWP_NOACTIVATE;
SetWindowPos (label, 0, messageRect.left, messageRect.top, messageRect.right - messageRect.left, messageRect.bottom - messageRect.top, flags);
}
} else if (_tcscmp(line, _T("foreground")) == 0) {
readColor(str, &foreground);
if (label) {
RECT rect;
GetWindowRect (label, &rect);
MapWindowPoints (0, topWindow, (POINT *)&rect, 2);
InvalidateRect (topWindow, &rect, 1);
}
} else if (_tcscmp(line, _T("message")) == 0) {
if (label) {
RECT rect;
SetWindowText (label, str);
GetWindowRect (label, &rect);
MapWindowPoints (0, topWindow, (POINT *)&rect, 2);
InvalidateRect (topWindow, &rect, 1);
}
}
}
if (end != NULL) line = end + 1;
else line = NULL;
}
free(buffer);
#ifdef _UNICODE
if (buffer1 != NULL) free(buffer1);
#endif
}
static void CALLBACK timerProc( HWND hwnd, UINT uMsg, UINT id, DWORD dwTime ) {
readInput();
if ( isEndSplash() )
{
/* Kill the timer. */
KillTimer( topWindow, splashTimerId );
ShowWindow( topWindow, SW_HIDE );
}
}
/* Show the Splash Window
*
* Open the bitmap, insert into the splash window and display it.
*
*/
int showSplash( _TCHAR* timeoutString, _TCHAR* featureImage )
{
int timeout = 0;
RECT rect;
HBITMAP hBitmap = 0;
HDC hDC;
int depth;
int x, y;
int width, height;
MSG msg;
int q = 0;
/* Determine the splash timeout value (in seconds). */
if (timeoutString != NULL && _tcslen( timeoutString ) > 0)
{
_stscanf( timeoutString, _T("%d"), &timeout );
}
/* Load the bitmap for the feature. */
hDC = GetDC( NULL);
depth = GetDeviceCaps( hDC, BITSPIXEL ) * GetDeviceCaps( hDC, PLANES);
ReleaseDC(NULL, hDC);
if (featureImage != NULL)
hBitmap = LoadImage(NULL, featureImage, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
/* If the bitmap could not be found, return an error. */
if (hBitmap == 0)
return ERROR_FILE_NOT_FOUND;
/* Load the bitmap into the splash popup window. */
SendMessage( topWindow, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hBitmap );
progress = CreateWindowEx (0, _T("msctls_progress32"),
_T(""),
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
0,
0,
0,
0,
topWindow,
NULL,
GetModuleHandle (NULL),
NULL);
label = CreateWindowEx (0, _T("STATIC"),
_T(""),
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
0,
0,
0,
0,
topWindow,
NULL,
GetModuleHandle (NULL),
NULL);
SendMessage (label, WM_SETFONT, (WPARAM)GetStockObject (DEFAULT_GUI_FONT), (LPARAM)1);
/* Centre the splash window and display it. */
GetWindowRect (topWindow, &rect);
width = GetSystemMetrics (SM_CXSCREEN);
height = GetSystemMetrics (SM_CYSCREEN);
x = (width - (rect.right - rect.left)) / 2;
y = (height - (rect.bottom - rect.top)) / 2;
SetWindowPos (topWindow, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
ShowWindow( topWindow, SW_SHOW );
BringWindowToTop( topWindow );
readInput();
SetTimer( topWindow, inputTimerId, 50, timerProc );
/* If a timeout for the splash window was given */
if (timeout != 0)
{
/* Add a timeout (in milliseconds) to bring down the splash screen. */
SetTimer( topWindow, splashTimerId, (timeout * 1000), splashTimeout );
}
while (GetMessage( &msg, NULL, 0, 0 ) && q < 20)
{
TranslateMessage( &msg );
DispatchMessage( &msg );
q++;
}
/* Process messages until the splash window is closed or process is terminated. */
/*
while (GetMessage( &msg, NULL, 0, 0 ))
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
*/
return 0;
}
/* Get the window system specific VM args */
_TCHAR** getArgVM( _TCHAR *vm )
{
return argVM;
}
/* Start the Java VM
*
* This method is called to start the Java virtual machine and to wait until it
* terminates. The function returns the exit code from the JVM.
*/
int startJavaVM( _TCHAR* args[] )
{
MSG msg;
int index, length;
_TCHAR *commandLine, *ch, *space;
/*
* Build the command line. Any argument with spaces must be in
* double quotes in the command line.
*/
length = 0;
for (index = 0; args[index] != NULL; index++)
{
/* String length plus space character */
length += _tcslen( args[ index ] ) + 1;
/* Quotes */
if (_tcschr( args[ index ], _T(' ') ) != NULL) length += 2;
}
commandLine = ch = malloc ( (length + 1) * sizeof(_TCHAR) );
for (index = 0; args[index] != NULL; index++)
{
space = _tcschr( args[ index ], _T(' '));
if (space != NULL) *ch++ = _T('\"');
_tcscpy( ch, args[index] );
ch += _tcslen( args[index] );
if (space != NULL) *ch++ = _T('\"');
*ch++ = _T(' ');
}
*ch = _T('\0');
/*
* Start the Java virtual machine. Use CreateProcess() instead of spawnv()
* otherwise the arguments cannot be freed since spawnv() segments fault.
*/
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
GetStartupInfo(&si);
if (CreateProcess(NULL, commandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
CloseHandle( pi.hThread );
jvmProcess = (int)pi.hProcess;
}
}
free( commandLine );
/* If the child process (JVM) would not start */
if (jvmProcess == -1)
{
/* Return the error number. */
jvmExitCode = errno;
jvmProcess = 0;
}
/* else */
else
{
/* Set a timer to detect JVM process termination. */
SetTimer( topWindow, jvmExitTimerId, jvmExitTimeout, detectJvmExit );
/* Process messages until the JVM terminates.
This launcher process must continue to process events until the JVM exits
or else Windows 2K will hang if the desktop properties (e.g., background) are
changed by the user. Windows does a SendMessage() to every top level window
process, which blocks the caller until the process responds. */
while (jvmProcess != 0)
{
GetMessage( &msg, NULL, 0, 0 );
TranslateMessage( &msg );
DispatchMessage( &msg );
}
/* Kill the timer. */
KillTimer( topWindow, jvmExitTimerId );
}
/* Return the exit code from the JVM. */
return jvmExitCode;
}
/* Local functions */
/* Detect JVM Process Termination */
static void CALLBACK detectJvmExit( HWND hwnd, UINT uMsg, UINT id, DWORD dwTime )
{
DWORD exitCode;
/* If the JVM process has terminated */
if (!GetExitCodeProcess( (HANDLE)jvmProcess, &exitCode ) ||
exitCode != STILL_ACTIVE)
{
/* Save the JVM exit code. This should cause the loop in startJavaVM() to exit. */
jvmExitCode = exitCode;
jvmProcess = 0;
}
}
/* Splash Timeout */
static void CALLBACK splashTimeout( HWND hwnd, UINT uMsg, UINT id, DWORD dwTime )
{
/* Kill the timer. */
KillTimer( topWindow, id );
PostMessage( topWindow, WM_QUIT, 0, 0 );
}
/* Window Procedure for the Spash window.
*
* A special WndProc is needed to return the proper vlaue for WM_NCHITTEST.
* It must also detect the message from the splash window process.
*/
static LRESULT WINAPI WndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_NCHITTEST: return HTCLIENT;
case WM_CLOSE:
PostQuitMessage( 0 );
break;
case WM_CTLCOLORSTATIC:
if ((HWND)lParam == label) {
SetTextColor((HDC)wParam, foreground);
SetBkMode((HDC)wParam, TRANSPARENT);
return (LRESULT)GetStockObject (NULL_BRUSH);
}
break;
}
return CallWindowProc (oldProc, hwnd, uMsg, wParam, lParam);
}
_TCHAR* getTempPath()
{
_TCHAR* buffer = malloc(MAX_PATH*sizeof(_TCHAR));
_TCHAR* tmp;
GetTempPath(MAX_PATH,buffer);
tmp = _ttempnam(buffer,_T_INSTALL("_RITMP"));
_tcscpy(buffer,tmp);
_tcscat(buffer,_T_INSTALL("\\"));
free(tmp);
return buffer;
}