blob: 50ea6243b19bbb40210d57a20b5b98164f87ae11 [file] [log] [blame]
/*
* Copyright (c) 2014 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eike Stepper - initial API and implementation
*/
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <shlobj.h>
#include <jreinfo.h>
#include "extractor.h"
#include "resources.h"
static _TCHAR* lib = NULL;
static _TCHAR*
getTempFile ()
{
_TCHAR tempFolder[MAX_PATH];
DWORD dwRetVal = GetTempPath (MAX_PATH, tempFolder);
if (dwRetVal == 0 || dwRetVal > MAX_PATH)
{
return NULL;
}
_TCHAR tempFile[MAX_PATH];
if ( GetTempFileName (tempFolder, _T("ext"), 0, tempFile) == 0)
{
return NULL;
}
return _tcsdup (tempFile);
}
/****************************************************************************************
* User Interface
***************************************************************************************/
static BOOL CALLBACK
enumChildWindowsCallback (HWND hWnd, LPARAM lParam)
{
_TCHAR className[MAX_PATH];
className[0] = 0;
GetClassName (hWnd, className, sizeof(className));
className[MAX_PATH - 1] = 0;
if (lstrcmpi (className, _T("SysTreeView32")) == 0)
{
HWND* phWnd = (HWND*) lParam;
if (phWnd)
{
*phWnd = hWnd;
}
return FALSE;
}
return TRUE;
}
static int CALLBACK
browseCallback (HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
static BOOL ensureVisible = FALSE;
switch (uMsg)
{
case BFFM_INITIALIZED:
{
HINSTANCE hInstance = GetModuleHandle (NULL);
HICON hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(ID_ICON));
SendMessage (hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIcon);
ensureVisible = FALSE;
_TCHAR buffer[MAX_PATH];
buffer[0] = 0;
GetCurrentDirectory (MAX_PATH, buffer);
buffer[MAX_PATH - 1] = 0;
// strcat (buffer, _T("\\EclipseInstaller"));
OSVERSIONINFO versionInfo;
versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
if (GetVersionEx (&versionInfo) && versionInfo.dwMajorVersion >= 6 && versionInfo.dwMinorVersion >= 1)
{
ensureVisible = TRUE;
}
SendMessage (hWnd, BFFM_SETSELECTION, TRUE, (LPARAM) buffer);
break;
}
case BFFM_SELCHANGED:
{
if (ensureVisible)
{
ensureVisible = FALSE;
HWND hWndTree = NULL;
EnumChildWindows (hWnd, enumChildWindowsCallback, (LPARAM) &hWndTree);
if (hWndTree)
{
HTREEITEM hTreeItem = TreeView_GetSelection(hWndTree);
if (hTreeItem)
{
TreeView_EnsureVisible(hWndTree, hTreeItem);
}
}
}
break;
}
}
return 0;
}
static BOOL CALLBACK
dialogProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
{
HINSTANCE hInstance = GetModuleHandle (NULL);
HICON hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(ID_ICON));
SendMessage (hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon);
return TRUE;
}
case WM_CLOSE:
EndDialog (hDlg, 0);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
EndDialog (hDlg, 0);
return TRUE;
case IDC_EDIT1:
switch (HIWORD(wParam))
{
case EN_CHANGE:
{
HWND hText = (HWND) lParam;
_TCHAR buffer[MAX_PATH];
GetWindowText (hText, buffer, sizeof(buffer));
printf (_T("%s\n"), buffer);
fflush (stdout);
return TRUE;
}
}
return TRUE;
}
break;
}
return FALSE;
}
static _TCHAR*
browseForFolder (HWND hwndOwner, LPCTSTR lpszTitle)
{
CoInitialize (NULL);
DialogBox(NULL, MAKEINTRESOURCE(ID_DLGBOX2), hwndOwner, (DLGPROC)dialogProc);
_TCHAR* result = NULL;
_TCHAR buffer[MAX_PATH];
BROWSEINFO browseInfo = { 0 };
browseInfo.hwndOwner = hwndOwner;
browseInfo.pszDisplayName = buffer;
browseInfo.pidlRoot = NULL;
browseInfo.lpszTitle = lpszTitle;
browseInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI;
browseInfo.lpfn = browseCallback;
LPITEMIDLIST itemIDList = NULL;
if ((itemIDList = SHBrowseForFolder (&browseInfo)) != NULL)
{
if ( SHGetPathFromIDList (itemIDList, buffer))
{
result = _tcsdup (buffer);
}
CoTaskMemFree (itemIDList);
}
// CoUninitialize ();
return result;
}
/****************************************************************************************
* Product Descriptor Extraction
***************************************************************************************/
typedef struct req_s
{
int format;
int major;
int minor;
int micro;
int bitness;
int jdk;
_TCHAR* launcherPath;
_TCHAR* iniPath;
_TCHAR* productName;
_TCHAR* productURI;
_TCHAR* imageURI;
} REQ;
static BOOL
findDescriptor (_TCHAR* executable, REQ* req)
{
int size = sizeof(marker);
int failure[size];
memset (failure, 0, sizeof(failure));
int i = 1;
int j = 0;
while (i < size)
{
while (j > 0 && marker[j] != marker[i])
{
j = failure[j - 1];
}
if (marker[j] == marker[i])
{
++j;
}
failure[i] = j;
++i;
}
FILE* file = fopen (executable, "rb");
BOOL retcode = FALSE;
byte b;
long pos = 0;
byte libdata[60000];
int libdataSize = 0;
int o;
for (o = 0; o < 3; ++o)
{
int k = 0;
for (;;)
{
if (fread (&b, 1, 1, file) == 0)
{
break;
}
if (o == 2)
{
libdata[libdataSize++] = b;
}
while (k > 0 && marker[k] != b)
{
k = failure[k - 1];
}
if (marker[k] == b)
{
++k;
}
if (k == size)
{
if (o == 0)
{
// We've found the bytes that are embedded into the marker[] array. Skip...
}
else if (o == 1)
{
// We've found the marker that precedes libdata.jar. Skip...
}
else if (o == 2)
{
// Save the captured libdata.jar bytes to a temporary file.
lib = getTempFile ();
FILE *fp = fopen (lib, "wb");
fwrite (libdata, libdataSize - size, 1, fp);
fclose (fp);
// Extract the product descriptor.
int size = 2048;
_TCHAR buffer[size];
fgets (buffer, size, file);
sscanf (buffer, _T("%d"), &req->format);
fgets (buffer, size, file);
sscanf (buffer, _T("%d"), &req->major);
fgets (buffer, size, file);
sscanf (buffer, _T("%d"), &req->minor);
fgets (buffer, size, file);
sscanf (buffer, _T("%d"), &req->micro);
fgets (buffer, size, file);
sscanf (buffer, _T("%d"), &req->bitness);
fgets (buffer, size, file);
sscanf (buffer, _T("%d"), &req->jdk);
fgets (buffer, size, file);
req->launcherPath = _tcsdup (_tcstok (buffer, _T("\n\r")));
fgets (buffer, size, file);
req->iniPath = _tcsdup (_tcstok (buffer, _T("\n\r")));
fgets (buffer, size, file);
req->productName = _tcsdup (_tcstok (buffer, _T("\n\r")));
fgets (buffer, size, file);
req->productURI = _tcsdup (_tcstok (buffer, _T("\n\r")));
fgets (buffer, size, file);
req->imageURI = _tcsdup (_tcstok (buffer, _T("\n\r")));
retcode = TRUE;
}
break;
}
if (retcode)
{
break;
}
++pos;
}
}
fclose (file);
return retcode;
}
/****************************************************************************************
* Java Library Mangement
***************************************************************************************/
static BOOL
execLib (_TCHAR* javaHome, _TCHAR* className, _TCHAR* args)
{
_TCHAR cmdline[2 * MAX_PATH];
sprintf (cmdline, _T("\"%s\\bin\\javaw\" -cp \"%s\" %s %s"), javaHome, lib, className, args);
return WinExec (cmdline, SW_HIDE) > 31;
}
static BOOL
validateJRE (JRE* jre, REQ* req)
{
if (jre->jdk < req->jdk)
{
return FALSE;
}
_TCHAR args[4 * 12];
sprintf (args, _T("%d %d %d %d"), req->major, req->minor, req->micro, req->bitness);
return execLib (jre->javaHome, _T("org.eclipse.oomph.extractor.lib.JREValidator"), args);
}
static BOOL
extractProduct (JRE* jre, _TCHAR* executable, _TCHAR* targetFolder)
{
_TCHAR args[MAX_PATH];
sprintf (args, _T("\"%s\" \"%s\" \"%s\""), executable, targetFolder, jre->javaHome);
return execLib (jre->javaHome, _T("org.eclipse.oomph.extractor.lib.BINExtractor"), args);
}
/****************************************************************************************
* Main Entry Point
***************************************************************************************/
int
main (int argc, char *argv[])
{
BOOL validateJREs = TRUE;
if (argc > 1)
{
_TCHAR* option = argv[1];
if (_tcscmp (option, _T("-web")) == 0)
{
validateJREs = FALSE;
}
}
_TCHAR* executable = argv[0];
REQ req;
if (!findDescriptor (executable, &req))
{
printf (_T("No product descriptor\n"));
return EXIT_FAILURE_PRODUCT_DESCRIPTION;
}
if (validateJREs)
{
JRE* jre = findAllJREs ();
while (jre)
{
if (validateJRE (jre, &req))
{
_TCHAR label[MAX_PATH];
sprintf (label, _T("Select or create an empty folder to extract %s into:"), req.productName);
_TCHAR* targetFolder = browseForFolder (NULL, label);
if (targetFolder == NULL)
{
return EXIT_CANCEL;
}
if (extractProduct (jre, executable, targetFolder))
{
return EXIT_SUCCESS;
}
return EXIT_FAILURE_PRODUCT_EXTRACTION;
}
jre = jre->next;
}
}
_TCHAR url[4 * MAX_PATH];
sprintf (url, _T("cmd /c start http://download.eclipse.org/oomph/jre/?vm=1_%d_%d_%d_%d_%d&pn=%s&pu=%s&pi=%s"), req.major, req.minor, req.micro, req.bitness,
req.jdk, req.productName, req.productURI, req.imageURI);
WinExec (url, SW_HIDE);
return EXIT_FAILURE_JRE_DETECTION;
}