root/main/trunk/release-kits/shared/windows/wrapper/wrapper.cpp @ 22223

Revision 22223, 12.7 KB (checked in by sjm84, 10 years ago)

Fixed a bug that caused the installer to crash on Windows Vista and Windows 7

Line 
1#include <windows.h>
2
3#include <fstream>
4#include <iostream>
5#include <conio.h>
6#include <string>
7#include <time.h>
8#include <shellapi.h>
9#include <direct.h>
10
11using namespace std;
12
13#ifndef CDROM
14#include "libsearch4j.h"
15#endif
16
17//globals
18HBITMAP g_splash = NULL; //the main splash bitmap
19HFONT g_hfFont = NULL; //the main splash bitmap
20char step[10] = "TMP"; //the current step
21char progress[4] = "0"; //progress in the current step
22HWND splashWnd;
23HINSTANCE mainInstance;
24int mainCmdShow;
25bool window_loaded = false;
26
27void set_splash_step( char* new_step ) {
28    strcpy( step, new_step );
29    InvalidateRect(splashWnd, NULL, FALSE);
30    UpdateWindow(splashWnd);
31}
32
33void set_splash_progress( int percent_progress ) {
34    percent_progress = ( percent_progress / 10 ) * 10;
35    char p[4] = {0};
36    strcpy( progress, itoa( percent_progress, p, 10 ) );
37    InvalidateRect(splashWnd, NULL, FALSE);
38    //RedrawWindow(splashWnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW | RDW_UPDATENOW | RDW_INTERNALPAINT);
39    UpdateWindow(splashWnd);
40}
41
42void spoof_progress( int interval ) {
43    int tenPercentWait = interval / 11;
44    for ( int i=0; i <= 100; i+=10 ) {
45        set_splash_progress( i );
46        Sleep( tenPercentWait );
47    }
48}
49
50//extracts a resource in chunks
51int extractResource( const char * basename, const char * type, char * file ) {
52
53    HMODULE hModule = GetModuleHandle(NULL);
54    set_splash_progress( 0 );
55
56    int no_chunks;
57    bool chunk_available = true;
58    for ( no_chunks = 0; chunk_available; no_chunks++ ) {
59
60        //construct the chunk name
61        char chunkname[127] = {0};
62        strcpy( chunkname, basename );
63        strcat( chunkname, "_" );
64        char chunknum[5] = {0};
65        itoa( no_chunks+1, chunknum, 10 );
66        strcat( chunkname, chunknum );
67       
68        if ( FindResource(hModule, chunkname, type) == NULL ) {
69            chunk_available = false;
70            break;
71        }
72    }
73   
74    if ( no_chunks == 0 ) {
75        return 1;
76    }
77   
78    for ( int i=0; i<no_chunks; i++ ) {
79   
80        //construct the chunk name
81        char chunkname[127] = {0};
82        strcpy( chunkname, basename );
83        strcat( chunkname, "_" );
84        char chunknum[5] = {0};
85        itoa( i+1, chunknum, 10 );
86        strcat( chunkname, chunknum );
87       
88        //find it
89        HRSRC hRsrc = FindResource(hModule, chunkname, type);
90        if (hRsrc == NULL ) return 1; //couldn't find the chunk
91       
92        //load it
93        HGLOBAL hGlobal = LoadResource(hModule, hRsrc);
94        if (hGlobal == NULL) return 1; //couldn't lock
95       
96        //lock it
97        BYTE* pBytes = (BYTE*) LockResource(hGlobal);
98        if (pBytes == NULL) return 1; //couldn't lock
99       
100        //put it on disk
101        DWORD dwLength = SizeofResource(hModule, hRsrc);
102        ofstream fStream(file, ios::binary | ios::out | ios::app );
103        fStream.write((char*) pBytes, dwLength);
104        fStream.close();
105       
106        //unload
107        UnlockResource(hGlobal);
108        FreeResource(hGlobal);
109       
110        //update the progress
111        set_splash_progress( i * 100 / no_chunks );
112       
113    }
114
115    return 0;
116
117}
118
119//the splash window procedure
120LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
121    switch(msg) {
122
123        case WM_CREATE: {
124            //load in the reusable resources
125            g_splash = LoadBitmap(GetModuleHandle(NULL),"SPLASH");
126            g_hfFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
127            if(g_splash == NULL) {
128                MessageBox(hwnd, "Could not load splash bitmap!", "Error", MB_OK | MB_ICONEXCLAMATION);
129            }
130           
131            //center the window automatically
132            RECT rect;
133            GetWindowRect(hwnd, &rect);
134            int x = (GetSystemMetrics(SM_CXSCREEN) - (rect.right - rect.left)) / 2;
135            int y = (GetSystemMetrics(SM_CYSCREEN) - (rect.bottom - rect.top)) / 2;
136            SetWindowPos(hwnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE);
137        }
138       
139        case WM_PAINT: {
140            // Don't use MessageBox from inside WM_PAINT
141       
142            //load in the correct resources
143            HBITMAP g_progress = NULL;
144            HBITMAP g_step = NULL;
145            char progress_res[20] = "PROGRESS_";
146            strcat( progress_res, progress );
147            char step_res[20] = "STEP_";
148            strcat( step_res, step );
149            g_progress = LoadBitmap(GetModuleHandle(NULL), progress_res );
150            g_step = LoadBitmap(GetModuleHandle(NULL), step_res );
151            if( g_progress == NULL || g_step == NULL ) {
152                //MessageBox(hwnd, "Could not load an image!", "Error", MB_OK | MB_ICONEXCLAMATION);
153            }
154       
155            BITMAP bm; //holds info about the width and height
156            PAINTSTRUCT ps;
157           
158            HDC hdc = BeginPaint(hwnd, &ps);
159            HDC hdcMem = CreateCompatibleDC(hdc);
160           
161            //paint the main splash screen
162            GetObject(g_splash, sizeof(bm), &bm);
163            HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, g_splash);
164            BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
165                       
166            //paint in the progress
167            GetObject(g_progress, sizeof(bm), &bm);
168            SelectObject(hdcMem, g_progress);
169            BitBlt(hdc, 0, 270, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
170           
171            //paint in the step with transparency
172            GetObject(g_step, sizeof(bm), &bm);
173            SelectObject(hdcMem, g_step);
174            BitBlt(hdc, 0, 276, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCPAINT);
175           
176            //print the step with text
177            RECT rcClient;
178            GetClientRect(hwnd, &rcClient);
179            //DrawText(hdc, "This is the step", -1, &rcClient, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
180           
181            //restore the hdc
182            SelectObject(hdcMem, hbmOld);
183           
184            //release resources
185            DeleteDC(hdcMem);
186            EndPaint(hwnd, &ps);
187            DeleteObject(g_progress);
188            DeleteObject(g_step);
189           
190        }
191        break;
192       
193        /*
194        case WM_LBUTTONDOWN: {
195            DeleteObject(g_splash);
196            PostQuitMessage(0);
197        }
198        break;
199        */
200       
201        case WM_CLOSE:
202            DestroyWindow(hwnd);
203            break;
204       
205        case WM_DESTROY:
206            DeleteObject(g_splash);
207            PostQuitMessage(0);
208            break;
209       
210        default:
211            return DefWindowProc(hwnd, msg, wParam, lParam);
212    }
213
214    return 0;
215
216}
217
218//function to process the window
219DWORD WINAPI ProcessWindow( LPVOID lpParam ) {
220   
221    const char g_szClassName[] = "splash";
222    WNDCLASSEX wc;
223    MSG Msg;
224
225    //Step 1: Registering the Window Class
226    wc.cbSize = sizeof(WNDCLASSEX);
227    wc.style = 0;
228    wc.lpfnWndProc = WndProc;
229    wc.cbClsExtra = 0;
230    wc.cbWndExtra = 0;
231    wc.hInstance = mainInstance;
232    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
233    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
234    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
235    wc.lpszMenuName = NULL;
236    wc.lpszClassName = g_szClassName;
237    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
238    if(!RegisterClassEx(&wc)) {
239        MessageBox(NULL, "Window Registration Failed!", "Error!",
240        MB_ICONEXCLAMATION | MB_OK);
241        return 0;
242    }
243
244    // Step 2: Creating the Window
245    splashWnd = CreateWindowEx( WS_EX_TOOLWINDOW, g_szClassName, "", WS_POPUP | SS_BITMAP, 0, 0, 420, 300, NULL, NULL, mainInstance, NULL);
246    if( splashWnd == NULL ) {
247        MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
248        return 0;
249    }
250    ShowWindow(splashWnd, mainCmdShow);
251    UpdateWindow(splashWnd);
252
253    window_loaded = true;
254   
255    // Step 3: The Message Loop
256    while(GetMessage(&Msg, NULL, 0, 0) > 0) {
257        TranslateMessage(&Msg);
258        DispatchMessage(&Msg);
259    }
260    return 0;
261}
262
263int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
264   
265    const int SPOOF_TIME = 1000;
266    string command;
267    srand( time(0) );
268    mainInstance = hInstance;
269    mainCmdShow = nCmdShow;
270   
271    //start the window
272    HANDLE hThread;
273    DWORD dwThreadId, dwThrdParam = 1;
274    hThread = CreateThread(
275       NULL,                        // no security attributes
276       0,                           // use default stack size 
277       ProcessWindow,               // thread function
278       &dwThrdParam,                // argument to thread function
279       0,                           // use default creation flags
280       &dwThreadId);                // returns the thread identifier
281    if ( hThread == NULL ) {
282        return -1;
283        //ErrorExit( "CreateThread failed." );
284    }
285    CloseHandle( hThread );
286   
287    while ( !window_loaded ) {
288        Sleep( 100 );
289    }
290   
291    //create the temp folder and change to it
292    set_splash_step( "TMP" );
293    spoof_progress( SPOOF_TIME );
294   
295    //get the original working directory
296    char* owdChar = _getcwd(NULL, 1024);
297    string owd = "";
298    owd.append( owdChar );
299    free(owdChar);
300   
301    //strip trailing slash
302    if ( owd.substr(owd.length()-1,1).compare( "\\" ) == 0 ) {
303        owd = owd.substr(0, owd.length()-1);
304    }
305       
306    //using the users TMP directory for temp files rather than the current directory so
307    //installation from cdrom works
308    char* tmp = getenv( "TMP" );
309    char id[6]; for( int i=0; i<5; i++ ) id[i] = (char)((rand()%26) + 97); id[5] = '\0'; //id for this instance
310    string tempdir = ""; tempdir.append( tmp ); tempdir.append( "\\Greenstone-" ); tempdir.append( id );
311    const char* tmpdir = tempdir.c_str();
312    if ( _mkdir( tmpdir ) != 0 ) {
313        string title = "Failed to create the temp folder.";
314        string message = "Failed to create the temp folder.\nPlease set the environment variable TMP to a folder you have permission to write to.";
315        //ShowWindow(splashWnd, SW_HIDE); //hide splash screen
316        MessageBox(splashWnd, message.c_str(), title.c_str(), MB_OK);
317        return -1;
318    }
319    //SetFileAttributes(tmpdir, FILE_ATTRIBUTE_HIDDEN);
320    SetCurrentDirectory(tmpdir);
321    // delete tmp; //  should be tmpdir? ??? (deallocate memory)
322   
323    #ifdef CDROM
324
325    //ask if they want to install, then do it if so
326    int choice = MessageBox(splashWnd, "Install Greenstone?", "Greenstone", MB_OKCANCEL | MB_ICONQUESTION );
327    if ( choice == IDOK ) {
328
329        //prepare to launch the jar
330        set_splash_step( "LAUNCHING" );
331        spoof_progress( SPOOF_TIME );
332   
333        string cmd = "\"";
334        cmd.append( owd );
335        cmd.append( "\\Java\\Windows\\jre\\bin\\java.exe\" \"-Dorig.dir=" );
336        cmd.append( owd );
337        cmd.append( "\" -jar \"" );
338        cmd.append( owd );
339        cmd.append( "\\Java\\Jars\\windows.jar\"" );
340        char cmdLpstr[1024];
341        strcpy( cmdLpstr, cmd.c_str() );
342       
343       
344        STARTUPINFO si;
345        PROCESS_INFORMATION pi;
346        memset(&pi, 0, sizeof(pi));
347        memset(&si, 0, sizeof(si));
348        si.cb = sizeof(si);
349        DWORD dwExitCode = -1;
350
351        //hide splash screen
352        ShowWindow(splashWnd, SW_HIDE);
353
354        //launch the jar
355        bool result;
356        result = CreateProcess(NULL, cmdLpstr, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
357
358        WaitForSingleObject(pi.hProcess, INFINITE);
359        GetExitCodeProcess(pi.hProcess, &dwExitCode);
360        CloseHandle(pi.hThread);
361        CloseHandle(pi.hProcess);
362
363    }   
364    #else
365
366    //rip out java archive if it is bundled
367    set_splash_step( "XJAVA" );
368    int javaIsBundled = (extractResource( "JAVA", "EXE", "@java.installer@" ) == 0);
369    if ( javaIsBundled ) {
370        process( "@java.installer@", false );
371    }
372
373    //find java
374    set_splash_step( "SEARCHING" );
375    spoof_progress( SPOOF_TIME );
376    bool use_minimum = true;
377    Jvm minimum;
378    minimum.setVersionFromString( "@java.min.version@" );
379    string phint = "@java.extracted@";
380    string hint = "";
381    bool verbose = true;
382    Jvm foundJvm;
383    bool jvmFound = find( foundJvm, use_minimum, minimum, false, false, phint, hint, verbose );
384   
385    //if the jvm was not found, try to fix it and find it
386    if ( !jvmFound ) {
387
388        //did not find a good java
389        string message = "This version of Greenstone requires java @java.min.version@ or greater, but ";
390       
391        //tell them if java is absent or just too old
392        if ( find( foundJvm, false, minimum, false, false, "", "", false ) ) {
393            message.append( "your java is too old.");
394        } else {
395            message.append( "java could not be found on your computer." );
396        }
397        message.append( "\n" );
398       
399        string title = "Installation Failed: Couldn't find java";
400        //ShowWindow(splashWnd, SW_HIDE); //hide splash screen
401        MessageBox(splashWnd, message.c_str(), title.c_str(), MB_OK);
402
403    //if java was found, carry on
404    } else {
405
406        //extract the jar
407        string jarLocation = "greenstone.jar";
408       
409        set_splash_step( "XJAR" );
410        extractResource( "JAR", "JAR", (char*) jarLocation.c_str() );
411
412        //launch the jar
413        set_splash_step( "LAUNCHING" );
414        spoof_progress( SPOOF_TIME );
415        string cmd = "\"";
416        cmd.append( foundJvm.getWinExecutable() );
417        cmd.append( "\" \"-Dorig.dir=" );
418        cmd.append( owd );
419        cmd.append( "\" -jar greenstone.jar" );
420       
421       
422        //hide splash screen
423        ShowWindow(splashWnd, SW_HIDE);
424       
425        //run the jar
426        int launch_exit_code = process( cmd, true );
427       
428        //report how it went
429        if ( launch_exit_code != 0 ) {
430            string title = "Installation Error";
431            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.";
432            //ShowWindow(splashWnd, SW_HIDE); //hide splash screen
433            MessageBox(NULL, message.c_str(), title.c_str(), MB_OK);
434        }
435    }
436    #endif
437   
438    //clean up the temp directory
439    _unlink( "ant.install.log" );
440    #ifndef CDROM
441    _unlink( "greenstone.jar" );
442    _unlink( "@java.installer@" );
443    process( "cmd.exe /c rd /s /q @java.extracted@", false );
444    #endif
445
446    SetCurrentDirectory( ".." );
447    _rmdir( tempdir.c_str() );
448   
449    return 0;
450   
451}
Note: See TracBrowser for help on using the browser.