Index: /release-kits/shared/windows/wrapper/compile.bat
===================================================================
--- /release-kits/shared/windows/wrapper/compile.bat	(revision 16162)
+++ /release-kits/shared/windows/wrapper/compile.bat	(revision 16162)
@@ -0,0 +1,10 @@
+mkdir build
+
+rc wrapper.rc
+move wrapper.RES build\wrapper.res
+
+cl /c -GX wrapper.cpp /out:wrapper.obj
+move wrapper.obj build
+
+link /OUT:build\wrapper.exe build\wrapper.obj build\wrapper.res
+
Index: /release-kits/shared/windows/wrapper/wrapper.cpp
===================================================================
--- /release-kits/shared/windows/wrapper/wrapper.cpp	(revision 16162)
+++ /release-kits/shared/windows/wrapper/wrapper.cpp	(revision 16162)
@@ -0,0 +1,385 @@
+#include <windows.h>
+
+#include <fstream>
+#include <iostream>
+#include <conio.h>
+#include <string>
+#include <time.h>
+#include <shellapi.h>
+#include <direct.h>
+#include "libsearch4j.h"
+
+using namespace std;
+
+//globals
+HBITMAP g_splash = NULL; //the main splash bitmap
+HFONT g_hfFont = NULL; //the main splash bitmap
+char step[10] = "TMP"; //the current step
+char progress[4] = "0"; //progress in the current step
+HWND splashWnd;
+HINSTANCE mainInstance;
+int mainCmdShow;
+bool window_loaded = false;
+
+void set_splash_step( char* new_step ) {
+	strcpy( step, new_step );
+	InvalidateRect(splashWnd, NULL, FALSE);
+	UpdateWindow(splashWnd);
+}
+
+void set_splash_progress( int percent_progress ) {
+	percent_progress = ( percent_progress / 10 ) * 10;
+	char p[4] = {0};
+	strcpy( progress, itoa( percent_progress, p, 10 ) );
+	InvalidateRect(splashWnd, NULL, FALSE);
+	//RedrawWindow(splashWnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW | RDW_UPDATENOW | RDW_INTERNALPAINT);
+	UpdateWindow(splashWnd);
+}
+
+void spoof_progress( int interval ) {
+	int tenPercentWait = interval / 11;
+	for ( int i=0; i <= 100; i+=10 ) {
+		set_splash_progress( i );
+		Sleep( tenPercentWait );
+	}
+}
+
+//extracts a resource in chunks
+int extractResource( const char * basename, const char * type, char * file ) {
+
+	HMODULE hModule = GetModuleHandle(NULL);
+	set_splash_progress( 0 );
+
+	int no_chunks;
+	bool chunk_available = true;
+	for ( no_chunks = 0; chunk_available; no_chunks++ ) {
+
+		//construct the chunk name
+		char chunkname[127] = {0};
+		strcpy( chunkname, basename );
+		strcat( chunkname, "_" );
+		char chunknum[5] = {0};
+		itoa( no_chunks+1, chunknum, 10 );
+		strcat( chunkname, chunknum );
+		
+		if ( FindResource(hModule, chunkname, type) == NULL ) {
+			chunk_available = false;
+		}
+	}
+	
+	for ( int i=0; i<no_chunks; i++ ) {
+	
+		//construct the chunk name
+		char chunkname[127] = {0};
+		strcpy( chunkname, basename );
+		strcat( chunkname, "_" );
+		char chunknum[5] = {0};
+		itoa( i+1, chunknum, 10 );
+		strcat( chunkname, chunknum );
+		
+		//find it
+		HRSRC hRsrc = FindResource(hModule, chunkname, type);
+		if (hRsrc == NULL ) return 1; //couldn't find the chunk
+		
+		//load it
+		HGLOBAL hGlobal = LoadResource(hModule, hRsrc);
+		if (hGlobal == NULL) return 1; //couldn't lock
+		
+		//lock it
+		BYTE* pBytes = (BYTE*) LockResource(hGlobal);
+		if (pBytes == NULL) return 1; //couldn't lock
+		
+		//put it on disk
+		DWORD dwLength = SizeofResource(hModule, hRsrc);
+		ofstream fStream(file, ios::binary | ios::out | ios::app );
+		fStream.write((char*) pBytes, dwLength);
+		fStream.close();
+		
+		//unload
+		UnlockResource(hGlobal);
+		FreeResource(hGlobal);
+		
+		//update the progress
+		set_splash_progress( i * 100 / no_chunks );
+		
+	}
+
+	return 0;
+
+}
+
+//the splash window procedure
+LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
+	switch(msg) {
+
+		case WM_CREATE: {
+			//load in the reusable resources
+			g_splash = LoadBitmap(GetModuleHandle(NULL),"SPLASH");
+			g_hfFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
+			if(g_splash == NULL) {
+				MessageBox(hwnd, "Could not load splash bitmap!", "Error", MB_OK | MB_ICONEXCLAMATION);
+			}
+			
+			//center the window automatically
+			RECT rect;
+			GetWindowRect(hwnd, &rect);
+			int x = (GetSystemMetrics(SM_CXSCREEN) - (rect.right - rect.left)) / 2;
+			int y = (GetSystemMetrics(SM_CYSCREEN) - (rect.bottom - rect.top)) / 2;
+			SetWindowPos(hwnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE);
+		}
+		
+		case WM_PAINT: {
+			// Don't use MessageBox from inside WM_PAINT
+		
+			//load in the correct resources
+			HBITMAP g_progress = NULL;
+			HBITMAP g_step = NULL;
+			char progress_res[20] = "PROGRESS_";
+			strcat( progress_res, progress );
+			char step_res[20] = "STEP_";
+			strcat( step_res, step );
+			g_progress = LoadBitmap(GetModuleHandle(NULL), progress_res );
+			g_step = LoadBitmap(GetModuleHandle(NULL), step_res );
+			if( g_progress == NULL || g_step == NULL ) {
+				MessageBox(hwnd, "Could not load an image!", "Error", MB_OK | MB_ICONEXCLAMATION);
+			}
+		
+			BITMAP bm; //holds info about the width and height
+			PAINTSTRUCT ps;
+			
+			HDC hdc = BeginPaint(hwnd, &ps);
+			HDC hdcMem = CreateCompatibleDC(hdc);
+			
+			//paint the main splash screen
+			GetObject(g_splash, sizeof(bm), &bm);
+			HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, g_splash);
+			BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
+						
+			//paint in the progress
+			GetObject(g_progress, sizeof(bm), &bm);
+			SelectObject(hdcMem, g_progress);
+			BitBlt(hdc, 0, 276, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
+			
+			//paint in the step with transparency
+			GetObject(g_step, sizeof(bm), &bm);
+			SelectObject(hdcMem, g_step);
+			BitBlt(hdc, 0, 276, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCPAINT);
+			
+			//print the step with text
+			RECT rcClient;
+			GetClientRect(hwnd, &rcClient);
+			//DrawText(hdc, "This is the step", -1, &rcClient, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
+			
+			//restore the hdc
+			SelectObject(hdcMem, hbmOld);
+			
+			//release resources
+			DeleteDC(hdcMem);
+			EndPaint(hwnd, &ps);
+			DeleteObject(g_progress);
+			DeleteObject(g_step);
+			
+		}
+		break;
+		
+		/*
+		case WM_LBUTTONDOWN: {
+			DeleteObject(g_splash);
+			PostQuitMessage(0);
+		}
+		break;
+		*/
+		
+		case WM_CLOSE:
+			DestroyWindow(hwnd);
+			break;
+		
+		case WM_DESTROY:
+			DeleteObject(g_splash);
+			PostQuitMessage(0);
+			break;
+		
+		default:
+			return DefWindowProc(hwnd, msg, wParam, lParam);
+	}
+
+	return 0;
+
+}
+
+//function to process the window
+DWORD WINAPI ProcessWindow( LPVOID lpParam ) {
+	
+	const char g_szClassName[] = "splash";
+	WNDCLASSEX wc;
+	MSG Msg;
+
+	//Step 1: Registering the Window Class
+	wc.cbSize = sizeof(WNDCLASSEX);
+	wc.style = 0;
+	wc.lpfnWndProc = WndProc;
+	wc.cbClsExtra = 0;
+	wc.cbWndExtra = 0;
+	wc.hInstance = mainInstance;
+	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
+	wc.lpszMenuName = NULL;
+	wc.lpszClassName = g_szClassName;
+	wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
+	if(!RegisterClassEx(&wc)) {
+		MessageBox(NULL, "Window Registration Failed!", "Error!",
+		MB_ICONEXCLAMATION | MB_OK);
+		return 0;
+	}
+
+	// Step 2: Creating the Window
+	splashWnd = CreateWindowEx( WS_EX_TOOLWINDOW, g_szClassName, "", WS_POPUP | SS_BITMAP, 0, 0, 420, 300, NULL, NULL, mainInstance, NULL);
+	if( splashWnd == NULL ) {
+		MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
+		return 0;
+	}
+	ShowWindow(splashWnd, mainCmdShow);
+	UpdateWindow(splashWnd);
+
+	window_loaded = true;
+	
+	// Step 3: The Message Loop
+	while(GetMessage(&Msg, NULL, 0, 0) > 0) {
+		TranslateMessage(&Msg);
+		DispatchMessage(&Msg);
+	}
+	return 0;
+} 
+
+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
+	
+	const int SPOOF_TIME = 1000;
+	string command;
+	srand( time(0) );
+	mainInstance = hInstance;
+	mainCmdShow = nCmdShow;
+	
+	//start the window
+	HANDLE hThread;
+	DWORD dwThreadId, dwThrdParam = 1;
+	hThread = CreateThread( 
+       NULL,                        // no security attributes 
+       0,                           // use default stack size  
+       ProcessWindow,               // thread function 
+       &dwThrdParam,	            // argument to thread function 
+       0,                           // use default creation flags 
+       &dwThreadId);                // returns the thread identifier 
+	if ( hThread == NULL ) {
+		return -1;
+		//ErrorExit( "CreateThread failed." );
+	}
+	CloseHandle( hThread );
+	
+	while ( !window_loaded ) {
+		Sleep( 100 );
+	}
+	
+	//create the temp folder and change to it
+	set_splash_step( "TMP" );
+	spoof_progress( SPOOF_TIME );
+	char* tmp = getenv( "TMP" );
+	char id[6]; for( int i=0; i<5; i++ ) id[i] = (char)((rand()%26) + 97); id[5] = '\0'; //id for this instance
+	string tempdir = ""; tempdir.append( tmp ); tempdir.append( "\\Greenstone3-" ); tempdir.append( id );
+	_mkdir( tempdir.c_str() );
+	SetCurrentDirectory( tempdir.c_str() );
+	
+	//find java
+	//set_splash_status( hInstance, statusWnd, "STATUS_SEARCHING4J", 1000 );
+	set_splash_step( "SEARCHING" );
+	spoof_progress( SPOOF_TIME );
+	bool use_minimum = true;
+	Jvm minimum;
+	minimum.setVersionFromString( "@java.min.version@" );
+	string hint = "";
+	bool verbose = true;
+	Jvm foundJvm;
+	bool jvmFound = find( foundJvm, use_minimum, minimum, hint, verbose );
+	
+	//if the jvm was not found, try to fix it and find it
+	if ( !jvmFound ) {
+
+		//did not find a good java
+		string message = "Greenstone requires java @java.min.version@ or greater, but ";
+		
+		//tell them if java is absent or just too old
+		if ( find( foundJvm, false, minimum, "", false ) ) {
+			message.append( "your java is too old.");
+		} else {
+			message.append( "java could not be found on your computer." );
+		}
+		message.append( "\n\n" );
+		
+		//is this an installer with the bundled JRE?
+		set_splash_step( "XJAVA" );
+		int extract_result = extractResource( "JAVA", "EXE", "@java.installer@" );
+
+		if ( extract_result == 0 ) {
+			
+			//yes, JRE is bundled
+			message.append( "This installer is bundled with a suitible version of java (bundled.version.java)\n");
+			message.append( "The installer program for this java will now be launched.\n" );
+			string title = "Must install java first";
+			MessageBox(NULL, message.c_str(), title.c_str(), MB_OK);
+			ShellExecute(NULL, "open", "@java.installer@", NULL, NULL, SW_SHOWNORMAL);
+			jvmFound = true; //assume the java installation went well
+			
+		} else {
+			
+			//no, JRE is not bundled
+			set_splash_step( "SEARCHING" );
+			set_splash_progress( 100 ); //we are done searching
+			message.append( "Please install java (@java.min.version@ or newer) and try again.\n" );
+			message.append( "Or, download a Greentsone3 installer with bundled java and use that instead of this one" );
+			string title = "Installation Failed: Couldn't find java";
+			MessageBox(NULL, message.c_str(), title.c_str(), MB_OK);
+		}
+	}
+	
+	
+	//if we have found it by now, launch the installer
+	if ( jvmFound ) {
+				
+		//extract the jar
+		string jarLocation = ""; jarLocation.append( tempdir ); jarLocation.append( "\\greenstone3.jar" );
+		//set_splash_status( hInstance, statusWnd, "STATUS_JAR", 0 );
+		
+		set_splash_step( "XJAR" );
+		extractResource( "JAR", "JAR", (char*) jarLocation.c_str() );
+
+		//launch the jar
+		set_splash_step( "LAUNCHING" );
+		spoof_progress( SPOOF_TIME );
+		string cmd = "\"";
+		cmd.append( foundJvm.getWinExecutable() );
+		cmd.append( "\" -jar greenstone3.jar" );
+		
+		//hide splash screen
+		ShowWindow(splashWnd, SW_HIDE);
+		
+		//run the jar
+		int launch_exit_code = process( cmd, true );
+		
+		//report how it went
+		if ( launch_exit_code != 0 ) {
+			string title = "Installation Error";
+			string message = "The installation exited with an error. Java may not be installed properly, or the installation may have been interrupted partway through. Please try again.";
+			MessageBox(NULL, message.c_str(), title.c_str(), MB_OK);
+		}
+	}
+	
+	//clean up the temp directory
+	_unlink("greenstone3.jar");
+	_unlink("ant.install.log");
+	_unlink("@java.installer@");
+	SetCurrentDirectory("..");
+	_rmdir( tempdir.c_str() );
+
+	return 0;
+	
+}
Index: /release-kits/shared/windows/wrapper/wrapper.rc
===================================================================
--- /release-kits/shared/windows/wrapper/wrapper.rc	(revision 16162)
+++ /release-kits/shared/windows/wrapper/wrapper.rc	(revision 16162)
@@ -0,0 +1,20 @@
+SPLASH BITMAP "splash.bmp"
+PROGRESS_0 BITMAP "progress-0.bmp"
+PROGRESS_10 BITMAP "progress-10.bmp"
+PROGRESS_20 BITMAP "progress-20.bmp"
+PROGRESS_30 BITMAP "progress-30.bmp"
+PROGRESS_40 BITMAP "progress-40.bmp"
+PROGRESS_50 BITMAP "progress-50.bmp"
+PROGRESS_60 BITMAP "progress-60.bmp"
+PROGRESS_70 BITMAP "progress-70.bmp"
+PROGRESS_80 BITMAP "progress-80.bmp"
+PROGRESS_90 BITMAP "progress-90.bmp"
+PROGRESS_100 BITMAP "progress-100.bmp"
+STEP_TMP BITMAP "step-tmp.bmp"
+STEP_SEARCHING BITMAP "step-searching.bmp"
+STEP_XJAVA BITMAP "step-xjava.bmp"
+STEP_XJAR BITMAP "step-xjar.bmp"
+STEP_LAUNCHING BITMAP "step-launching.bmp"
+MAINICON ICON "gs3.ico"
+
+//resources are automatically appended here
