added checkboxes, background painting
[swftools.git] / installer / installer.c
1 /* installer.c
2
3    Part of the swftools installer (Main program).
4    
5    Copyright (c) 2004 Matthias Kramm <kramm@quiss.org> 
6  
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
20
21 #include <windows.h>
22 #include <commctrl.h>
23 #include <commdlg.h>
24 #include <shlobj.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27
28 #include "depack.h"
29
30 #include "../config.h" //for swftools version
31 #include "../lib/os.h" //for registry functions
32
33 extern char*crndata;
34
35 static char*install_path = "c:\\swftools\\";
36 static char pathBuf[1024];
37 static int do_abort = 0;
38
39 static HWND wnd_params = 0;
40 static HWND wnd_progress = 0;
41 static HWND wnd_finish = 0;
42 static HWND wnd_background = 0;
43
44 static HBITMAP logo;
45
46 #define USER_SETMESSAGE 0x7f01
47
48 struct progress_data {
49     int width,height;
50     int bar_width;
51     int bar_height;
52     int bar_posx;
53     int bar_posy;
54     int pos,step,range;
55     char*text1;
56     char*text2;
57     char*text3;
58     HWND hwndButton;
59     HWND wnd_text3;
60 };
61 struct params_data {
62     int width,height;
63     int ok;
64     HWND installButton;
65     HWND edit;
66     HWND explore;
67 };
68 struct finish_data {
69     int width,height;
70     int ok;
71     char*text;
72     HWND installButton;
73     HWND check1;
74     HWND check2;
75 };
76
77 LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
78 {
79     //printf("%08x, %d %08x %08x\n", hwnd, message, wParam, lParam);
80    
81     /* in order for the delegation below to also work for
82        WM_CREATE, we need to assign our window pointers *before* the
83        CreateWindow returns, because that's when the WM_CREATE event 
84        is sent  */
85
86     if(message == WM_CREATE) {
87         CREATESTRUCT*cs = ((LPCREATESTRUCT)lParam);
88         if(cs->lpCreateParams && !strcmp((char*)cs->lpCreateParams, "params")) {
89             wnd_params = hwnd;
90         }
91         else if(cs->lpCreateParams && !strcmp((char*)cs->lpCreateParams, "progress")) {
92             wnd_progress = hwnd;
93         }
94         else if(cs->lpCreateParams && !strcmp((char*)cs->lpCreateParams, "finish")) {
95             wnd_finish = hwnd;
96         }
97         else if(cs->lpCreateParams && !strcmp((char*)cs->lpCreateParams, "background")) {
98             wnd_background = hwnd;
99         }
100     }
101
102     if(hwnd == 0) {
103         return DefWindowProc(hwnd, message, wParam, lParam);
104     } else if(hwnd == wnd_progress) {
105         static struct progress_data data;
106
107         switch(message)
108         {
109             case USER_SETMESSAGE:
110                 data.text3 = (char*)wParam;
111                 SendMessage(data.wnd_text3, WM_SETTEXT, 0, (LPARAM)data.text3);
112                 return 0;
113             case WM_CREATE: {
114                 memset(&data, 0, sizeof(data));
115                 data.text1 = "Installing SWFTools";
116                 data.text2 = (char*)malloc(strlen(install_path)+250);
117                 data.text3 = "";
118                 sprintf(data.text2, "to %s", install_path);
119                 data.pos = 0;
120                 data.step = 1;
121
122                 CREATESTRUCT*cs = ((LPCREATESTRUCT)lParam);
123                 RECT rc;
124                 GetClientRect (hwnd, &rc);
125                 data.width = rc.right - rc.left;
126                 data.height = rc.bottom - rc.top;
127                 data.bar_width = cs->cx - 17;
128                 data.bar_height= 16;
129                 data.bar_posx = (data.width -data.bar_width)/2;
130                 data.bar_posy = 56;
131                 data.range = 50;
132
133                 data.hwndButton = CreateWindow (
134                         PROGRESS_CLASS,
135                         "Progress",
136                         WS_CHILD | WS_VISIBLE,
137                         data.bar_posx,
138                         data.bar_posy,
139                         data.bar_width, 
140                         data.bar_height,
141                         hwnd,  /* Parent */
142                         0,
143                         cs->hInstance,
144                         NULL
145                         );
146
147                 SendMessage(data.hwndButton, PBM_SETRANGE, 0, (LPARAM) MAKELONG(0,data.range));
148                 SendMessage(data.hwndButton, PBM_SETSTEP, (WPARAM) data.step, 0);
149                 return 0;
150             }   
151             case PBM_STEPIT: {
152                 if(data.pos+data.step < data.range) {
153                     data.pos += data.step;
154                     SendMessage(data.hwndButton, PBM_STEPIT, wParam, lParam);
155                 }
156             }
157             case WM_PAINT: {
158                 TEXTMETRIC    tm;
159                 HDC           hdc;             /* A device context used for drawing */
160                 PAINTSTRUCT   ps;              /* Also used during window drawing */
161                 RECT          rc;              /* A rectangle used during drawing */
162                 
163                 hdc = GetDC(hwnd);
164                 SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
165                 GetTextMetrics(hdc, &tm);
166                 ReleaseDC(hwnd, hdc);
167
168                 hdc = BeginPaint (hwnd, &ps);
169
170                 /*
171                 // draw logo 
172                 HDC memDc=CreateCompatibleDC(hdc);
173                 SelectObject(memDc,logo);
174                 BitBlt(hdc,0,0,406,93,memDc,0,0,SRCCOPY);
175                 DeleteDC(memDc);
176                 // /
177                 */
178
179                 SetBkMode(hdc, TRANSPARENT);
180                 
181                 rc.top = 8; rc.left= 0; rc.right = data.width; rc.bottom = 24;
182                 DrawText(hdc, data.text1, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
183
184                 char buf[256];
185                 char*text = data.text2;
186                 if(tm.tmAveCharWidth * strlen(text) > data.width) {
187                     int chars = (data.width / tm.tmAveCharWidth)-8;
188                     if(chars>240) chars=240;
189                     strncpy(buf, text, chars);
190                     strcpy(&buf[chars],"...");
191                     text = buf;
192                 }
193
194                 rc.top = 32; rc.left= 0; rc.right = data.width; rc.bottom = 48;
195                 DrawText(hdc, text, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
196                 
197                 //rc.top = data.height-32; rc.left= 0; rc.right = data.width; rc.bottom = data.height;
198                 //DrawText(hdc, data.text3, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
199
200                 EndPaint (hwnd, &ps);
201                 return 0;
202             }
203             case WM_DESTROY:
204                 wnd_progress = 0;
205                 return DefWindowProc(hwnd, message, wParam, lParam);
206             default:
207                 return DefWindowProc(hwnd, message, wParam, lParam);
208         }
209     } else if(hwnd == wnd_params) {
210         static struct params_data data;
211         switch(message)
212         {
213             case WM_CREATE: {
214                 memset(&data, 0, sizeof(data));
215                 CREATESTRUCT*cs = ((LPCREATESTRUCT)lParam);
216                 RECT rc;
217                 GetClientRect (hwnd, &rc);
218                 data.width = rc.right - rc.left;
219                 data.height = rc.bottom - rc.top;
220
221                 //EDITTEXT IDD_EDIT,68,8,72,12, ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER  | WS_TABSTOP
222                 data.edit = CreateWindow (
223                         WC_EDIT,
224                         "EditPath",
225                         WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | ES_AUTOHSCROLL,
226                         32, 
227                         48,
228                         (data.width-64)-32*2, 
229                         20,
230                         hwnd,  /* Parent */
231                         (HMENU)0x1234,
232                         cs->hInstance,
233                         NULL
234                         );
235                 
236                 data.explore = CreateWindow (
237                         WC_BUTTON,
238                         "Browse",
239                         WS_CHILD | WS_VISIBLE | WS_TABSTOP,
240                         data.width-32-64,
241                         48,
242                         64, 
243                         20,
244                         hwnd,  /* Parent */
245                         (HMENU)0x9999,
246                         cs->hInstance,
247                         NULL
248                         );
249                 
250                 data.installButton = CreateWindow (
251                         WC_BUTTON,
252                         "Install",
253                         WS_CHILD | WS_VISIBLE | WS_TABSTOP,
254                         (data.width - 80)/2,
255                         data.height - 32*2,
256                         80, 
257                         32,
258                         hwnd,  /* Parent */
259                         (HMENU)0xabcd,
260                         cs->hInstance,
261                         NULL
262                         );
263                 
264                 SendMessage(data.edit, WM_SETTEXT, 0, (LPARAM)install_path);
265                 return 0;
266             }   
267             case USER_SETMESSAGE: {
268                 //install_path = (char*)lParam;
269                 SendMessage(data.edit, WM_SETTEXT, 0, (LPARAM)install_path);
270                 printf("Setting path to %s\n", install_path);
271                 return 0;
272             }
273             case WM_PAINT: {
274                 TEXTMETRIC tm;
275                 HDC hdc;
276                 PAINTSTRUCT ps;
277                 RECT rc;
278                 hdc = GetDC(hwnd);
279                 SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
280                 GetTextMetrics(hdc, &tm);
281                 ReleaseDC(hwnd, hdc);
282                 hdc = BeginPaint (hwnd, &ps);
283                 SetBkMode(hdc, TRANSPARENT);
284                 rc.top = 32; rc.left= 16; rc.right = data.width-32*2; rc.bottom = 20;
285                 DrawText(hdc, "Select Installation directory", -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
286                 EndPaint (hwnd, &ps);
287                 return 0;
288             }
289             case WM_COMMAND: {
290                 if((wParam&0xffff) == 0x9999) {
291                     BROWSEINFOA browse;
292                     memset(&browse, 0, sizeof(browse));
293                     browse.ulFlags = BIF_EDITBOX | BIF_NEWDIALOGSTYLE | BIF_USENEWUI;// | BIF_RETURNONLYFSDIRS; //BIF_VALIDATE
294                     browse.pszDisplayName = (CHAR*)malloc(MAX_PATH);
295                     memset(browse.pszDisplayName, 0, MAX_PATH);
296                     browse.lpszTitle = "Select installation directory";
297                     /*browse.pidlRoot = (ITEMIDLIST*)malloc(sizeof(ITEMIDLIST)*200);
298                     memset((void*)browse.pidlRoot, 0, sizeof(ITEMIDLIST)*200);*/
299                     printf("Start browsing %s\n", browse.pszDisplayName);
300                     //SHGetDesktopFolder
301                     //ParseDisplayName(install_path,0,&browse.pidlRoot,0,0);
302                     //SHParseDisplayName(install_path,0,&browse.pidlRoot,0,0);
303                     //SHBrowseForFolderA(&browse);
304                     browse.pidlRoot = SHBrowseForFolder(&browse);
305                     printf("Browsing returns %s / %08x\n", browse.pszDisplayName, browse.pidlRoot);
306                     if(browse.pszDisplayName) {
307                         if(SHGetPathFromIDList(browse.pidlRoot, browse.pszDisplayName)) {
308                             printf("Path is %s\n", browse.pszDisplayName);
309                             install_path = browse.pszDisplayName;
310                         }
311                     }
312                     SendMessage(data.edit, WM_SETTEXT, 0, (LPARAM)install_path);
313                     return 0;
314                 } else if((wParam&0xffff) == 0xabcd) {
315                     data.ok = 1;
316                     DestroyWindow(hwnd);
317                     return 0;
318                 } else if((wParam&0xffff) == 0x1234) {
319                     SendMessage(data.edit, WM_GETTEXT, sizeof(pathBuf), (LPARAM)&(pathBuf[0]));
320                     if(pathBuf[0]) {
321                         install_path = pathBuf;
322                     }
323                     return 0;
324                 }
325                 return DefWindowProc(hwnd, message, wParam, lParam);
326             }
327             case WM_KEYDOWN: {
328                 if(wParam == 0x49) {
329                     DestroyWindow(hwnd);
330                 }
331                 return 0;
332             }
333             case WM_DESTROY:
334                 if(!data.ok) {
335                     do_abort = 1;
336                     PostQuitMessage (0);
337                 }
338                 wnd_params = 0;
339                 return DefWindowProc(hwnd, message, wParam, lParam);
340             default:
341                 return DefWindowProc(hwnd, message, wParam, lParam);
342         }
343     } else if(hwnd == wnd_finish) {
344         static struct finish_data data;
345         switch(message)
346         {
347             case WM_CREATE: {
348                 /* TODO:
349
350                    "swftools has been installed into directory %s
351                    successfully"
352
353                    [x] Create Desktop Shortcut
354                    [x] Create Start Menu Entry
355
356                 */
357
358                 RECT rc;
359                 CREATESTRUCT*cs = ((LPCREATESTRUCT)lParam);
360                 GetClientRect (hwnd, &rc);
361                 data.width = rc.right - rc.left;
362                 data.height = rc.bottom - rc.top;
363
364                 data.text = malloc(strlen(install_path)+256);
365                 sprintf(data.text, "SWFTools has been installed into directory\r\n%s\r\nsucessfully.", install_path);
366                 
367                 data.installButton = CreateWindow (
368                         WC_BUTTON,
369                         "Finish",
370                         WS_CHILD | WS_VISIBLE | WS_TABSTOP,
371                         (data.width - 80)/2,
372                         data.height - 32,
373                         80, 
374                         32,
375                         hwnd, 
376                         (HMENU)0xabce,
377                         cs->hInstance,
378                         NULL
379                         );
380                 
381                 data.check1 = CreateWindow (
382                         WC_BUTTON,
383                         "Create Desktop Shortcut",
384                         WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_CHECKBOX,
385                         32, data.height - 96, 
386                         data.width-32*2, 32, 
387                         hwnd, (HMENU)0xabcf, cs->hInstance, NULL);
388                 
389                 data.check2 = CreateWindow (
390                         WC_BUTTON,
391                         "Create Start Menu Entry",
392                         WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_CHECKBOX,
393                         32, data.height - 64, 
394                         data.width-32*2, 32, 
395                         hwnd, (HMENU)0xabd0, cs->hInstance, NULL);
396                 
397             }
398             case WM_PAINT: {
399                 TEXTMETRIC tm;
400                 HDC hdc;
401                 PAINTSTRUCT ps;
402                 RECT rc;
403                 hdc = GetDC(hwnd);
404                 SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
405                 GetTextMetrics(hdc, &tm);
406                 ReleaseDC(hwnd, hdc);
407                 hdc = BeginPaint (hwnd, &ps);
408                 SetBkMode(hdc, TRANSPARENT);
409                 rc.left = 0; 
410                 rc.top = 10;
411                 rc.right = data.width; 
412                 rc.bottom = data.height-40-32;
413                 DrawText(hdc, data.text, -1, &rc, DT_CENTER | DT_VCENTER);
414                 EndPaint (hwnd, &ps);
415                 return 0;
416
417                 return DefWindowProc(hwnd, message, wParam, lParam);
418             }
419             case WM_COMMAND: {
420                 if((wParam&0xffff) == 0xabce) {
421                     data.ok = 1;
422                     DestroyWindow(hwnd);
423                     return 0;
424                 }
425                 if((wParam&0xffff) == 0xabcf) {
426                     return 1;
427                 }
428                 if((wParam&0xffff) == 0xabd0) {
429                     return 0;
430                 }
431             }
432             case WM_DESTROY: {
433                 free(data.text);data.text = 0;
434                 if(!data.ok) {
435                     do_abort = 1;
436                     PostQuitMessage(0);
437                 }
438                 wnd_finish = 0;
439                 return DefWindowProc(hwnd, message, wParam, lParam);
440             }
441         }
442     } else if(hwnd == wnd_background) {
443         switch(message)
444         {
445             case WM_PAINT: {
446                 HDC hdc;
447                 PAINTSTRUCT ps;
448                 RECT rc;
449                 hdc = BeginPaint(hwnd, &ps);
450                 SetBkMode(hdc, TRANSPARENT);
451
452                 HPEN pen = CreatePen(PS_SOLID, 2, RGB(255, 255, 0));    
453                 HPEN oldPen = (HPEN)SelectObject(hdc, pen);
454
455                 MoveToEx(hdc, 10, 10, 0);
456                 LineTo(hdc, 100, 100);
457
458                 SelectObject(hdc, oldPen); 
459                 DeleteObject(pen);
460
461                 EndPaint(hwnd, &ps);
462                 return 1;
463             }
464         }
465     }
466     return DefWindowProc(hwnd, message, wParam, lParam);
467 }
468
469 void processMessages()
470 {
471     MSG msg;
472     while(PeekMessage(&msg,NULL,0,0,0))
473     {
474         GetMessage(&msg, NULL, 0, 0);
475         TranslateMessage(&msg);
476         DispatchMessage(&msg);
477     }
478 }
479
480 static char*lastmessage = 0;
481 void myarchivestatus(int type, char*text)
482 {
483     if(text && text[0]=='[')
484         return;
485     //printf("%s\n", text);
486                         
487     SendMessage(wnd_progress, USER_SETMESSAGE, (WPARAM)strdup(text), 0);
488     SendMessage(wnd_progress, WM_PAINT, 0, 0);
489     int t;
490     for(t=0;t<9;t++) {
491         SendMessage(wnd_progress, PBM_STEPIT, 0, 0);
492         /* while we're here, we might also make ourselves useful */
493         processMessages();
494         /* we want the user to see what we're writing, right? */
495         Sleep(30);
496     }
497
498     if(type<0) {
499         while(1) {
500             int ret = MessageBox(0, text, "Error", MB_RETRYCANCEL|MB_ICONERROR);
501             
502             /* there is no MB_CANCEL, so, *sigh*, we have to display
503                the "retry" button. So pretend it's doing anything... */
504             if(ret==IDRETRY)
505                 continue;
506             else
507                 break;
508         }
509     }
510 }
511
512 int addRegistryEntries(char*install_dir)
513 {
514     int ret;
515     ret = setRegistryEntry("Software\\quiss.org\\swftools\\InstallPath", install_dir);
516     if(!ret) return 0;
517     return 1;
518 }
519
520 int WINAPI WinMain(HINSTANCE me,HINSTANCE hPrevInst,LPSTR lpszArgs, int nWinMode)
521 {
522     WNDCLASSEX wcl;
523     wcl.hInstance    = me;
524     wcl.lpfnWndProc  = WindowFunc;
525     wcl.lpszClassName= "SWFTools-Install";
526     wcl.style        = CS_HREDRAW | CS_VREDRAW;
527     wcl.hIcon        = LoadIcon(NULL, IDI_APPLICATION);
528     wcl.hIconSm      = LoadIcon(NULL, IDI_APPLICATION);
529     wcl.hCursor      = LoadCursor(NULL, IDC_ARROW);
530     wcl.lpszMenuName = NULL; //no menu
531     wcl.cbClsExtra   = 0;
532     wcl.cbWndExtra   = 0;
533     wcl.hbrBackground= (HBRUSH)GetStockObject(LTGRAY_BRUSH);
534     wcl.cbSize       = sizeof(WNDCLASSEX);
535     
536     WNDCLASSEX wcl_text;
537     memcpy(&wcl_text, &wcl, sizeof(WNDCLASSEX));
538     wcl_text.lpszClassName= "TextClass";
539     wcl_text.hbrBackground = GetStockObject(HOLLOW_BRUSH);
540
541     WNDCLASSEX wcl_background;
542     memcpy(&wcl_background, &wcl, sizeof(WNDCLASSEX));
543     wcl_background.lpszClassName= "SWFTools Installer";
544     wcl_background.hbrBackground= CreateSolidBrush(RGB(0, 0, 128));
545     
546
547     if(!RegisterClassEx(&wcl)) {
548         MessageBox(0, "Could not register window class", "Install.exe", MB_OK);
549         return 1;
550     }
551     if(!RegisterClassEx(&wcl_background)) {
552         MessageBox(0, "Could not register window class 2", "Install.exe", MB_OK);
553         return 1;
554     }
555
556     HWND background = CreateWindow(wcl_background.lpszClassName, "Setup SWFTools",
557                          0, 0, 0, 
558                          GetSystemMetrics(SM_CXFULLSCREEN),
559                          GetSystemMetrics(SM_CYFULLSCREEN),
560                          NULL, NULL, me, 
561                          (void*)"background");
562     
563     if(!background) {
564         MessageBox(0, "Could not create installation background window", "Install.exe", MB_OK);
565         return 1;
566     }
567
568     ShowWindow(background, SW_SHOWMAXIMIZED);
569     UpdateWindow(background);
570
571     RECT r = {0,0,0,0};
572     GetWindowRect(background, &r);
573     int xx = 320, yy = 200;
574     if(r.right - r.left > 320)
575         xx = r.right - r.left;
576     if(r.right - r.left > 200)
577         yy = r.bottom - r.top;
578     
579     logo = LoadBitmap(me, "SWFTOOLS");
580     
581     install_path = getRegistryEntry("Software\\quiss.org\\swftools\\InstallPath");
582     if(!install_path || !install_path[0])
583         install_path = "c:\\swftools\\";
584
585     CoInitialize(0);
586     InitCommonControls();
587     
588     HWND installpath_window = CreateWindow(
589             wcl.lpszClassName,          /* Class name */
590             "SWFTools Installer",       /* Caption */
591             WS_CHILD | WS_CAPTION,
592             (xx-320)/2,                 /* Initial x  */
593             (yy-200)/2,                 /* Initial y  */
594             320,                        /* Initial x size */
595             200,                        /* Initial y size */
596             background,                       /* No parent window */
597             NULL,                       /* No menu */
598             me,                         /* This program instance */
599             (void*)"params"             /* Creation parameters */
600             );
601
602     if(!installpath_window) {
603         MessageBox(background, "Could not create installation window", "Install.exe", MB_OK);
604         return 1;
605     }
606
607     ShowWindow (wnd_params, nWinMode);
608     UpdateWindow (wnd_params);
609    
610     MSG msg;
611     while(wnd_params)
612     {
613         GetMessage(&msg,NULL,0,0);
614         TranslateMessage(&msg);
615         DispatchMessage(&msg);
616     }
617
618     if(do_abort) {
619         MessageBox(background, "Aborting Installation", "Error", MB_OK|MB_ICONERROR);
620         return 1;
621     }
622    
623     /*char buf[1024];
624     sprintf(buf, "Do you want me to install SWFTools into the directory %s now?", install_path);
625     int ret = MessageBox(0, buf, "SWFTools Install", MB_YESNO|MB_ICONQUESTION);
626     if(ret == IDNO)
627         return 0;*/
628     
629     CreateWindow (
630             wcl.lpszClassName,          /* Class name */
631             "Installing...",            /* Caption */
632             WS_CHILD | WS_CAPTION,
633             //WS_OVERLAPPEDWINDOW&(~WS_SIZEBOX),        /* Style */
634             (xx-260)/2, (yy-128)/2,
635             260,                        /* Initial x size */
636             128,                        /* Initial y size */
637             background,                 /* No parent window */
638             NULL,                       /* No menu */
639             me,                         /* This program instance */
640             (void*)"progress"           /* Creation parameters */
641             );
642     ShowWindow (wnd_progress, nWinMode);
643     UpdateWindow (wnd_progress);
644     
645     int success = unpack_archive(crndata, install_path, myarchivestatus);
646    
647     DestroyWindow(wnd_progress);
648
649     while(wnd_progress)
650         processMessages();
651     if(do_abort) {
652         MessageBox(background, "Aborting Installation", "Error", MB_OK|MB_ICONERROR);
653         return 1;
654     }
655
656     CreateWindow (
657             wcl.lpszClassName,          /* Class name */
658             "Finished",                 /* Caption */
659             WS_CHILD | WS_CAPTION,
660             //WS_OVERLAPPEDWINDOW&(~WS_SIZEBOX),        /* Style */
661             (xx-320)/2, (yy-160)/2,
662             320,                        /* Initial x size */
663             200,                        /* Initial y size */
664             background,                 /* No parent window */
665             NULL,                       /* No menu */
666             me,                         /* This program instance */
667             (void*)"finish"             /* Creation parameters */
668             );
669     ShowWindow(wnd_finish, nWinMode);
670     UpdateWindow(wnd_finish);
671
672     while(wnd_finish)
673         processMessages();
674     if(do_abort) {
675         MessageBox(0, "Aborting Installation", "Error", MB_OK|MB_ICONERROR);
676         return 1;
677     }
678
679     if(!addRegistryEntries(install_path)) {
680         success = 0;
681         MessageBox(0, "Couldn't create Registry Entries", "SWFTools Install", MB_OK|MB_ICONERROR);
682     }
683
684     if(success) {
685         //char buf[1024];
686         //sprintf(buf, "SWFTools Version %s has been installed into %s successfully", VERSION, install_path);
687         //MessageBox(0, buf, "SWFTools Install", MB_OK|MB_ICONINFORMATION);
688     } else {
689         /* error will already have been notified by either myarchivestatus or some other
690            routine */
691         /*sprintf(buf, "Installation failed\nLast message: %s", lastmessage);
692         ret = MessageBox(0, buf, "SWFTools Install", MB_OK|MB_ICONERROR);*/
693     }
694     exit(0);
695 }
696