set focus to topmost window
[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 static int config_forAllUsers = 0;
34 static int config_createLinks = 0;
35 static int config_createStartmenu = 1;
36 static int config_createDesktop = 1;
37
38
39 extern char*crndata;
40
41 static char*install_path = "c:\\swftools\\";
42 static char pathBuf[1024];
43 static int do_abort = 0;
44
45 static HWND wnd_params = 0;
46 static HWND wnd_progress = 0;
47 static HWND wnd_finish = 0;
48 static HWND wnd_background = 0;
49
50 static HBITMAP logo;
51
52 #define USER_SETMESSAGE 0x7f01
53
54 struct progress_data {
55     int width,height;
56     int bar_width;
57     int bar_height;
58     int bar_posx;
59     int bar_posy;
60     int pos,step,range;
61     char*text1;
62     char*text2;
63     char*text3;
64     HWND hwndButton;
65     HWND wnd_text3;
66 };
67 struct params_data {
68     int width,height;
69     int ok;
70     HWND installButton;
71     HWND edit;
72     HWND explore;
73 };
74 struct finish_data {
75     int width,height;
76     int ok;
77     char*text;
78     HWND installButton;
79     HWND check1;
80     HWND check2;
81 };
82
83 LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
84 {
85     //printf("%08x, %d %08x %08x\n", hwnd, message, wParam, lParam);
86    
87     /* in order for the delegation below to also work for
88        WM_CREATE, we need to assign our window pointers *before* the
89        CreateWindow returns, because that's when the WM_CREATE event 
90        is sent  */
91
92     if(message == WM_CREATE) {
93         CREATESTRUCT*cs = ((LPCREATESTRUCT)lParam);
94         if(cs->lpCreateParams && !strcmp((char*)cs->lpCreateParams, "params")) {
95             wnd_params = hwnd;
96         }
97         else if(cs->lpCreateParams && !strcmp((char*)cs->lpCreateParams, "progress")) {
98             wnd_progress = hwnd;
99         }
100         else if(cs->lpCreateParams && !strcmp((char*)cs->lpCreateParams, "finish")) {
101             wnd_finish = hwnd;
102         }
103         else if(cs->lpCreateParams && !strcmp((char*)cs->lpCreateParams, "background")) {
104             wnd_background = hwnd;
105         }
106     }
107
108     if(hwnd == 0) {
109         return DefWindowProc(hwnd, message, wParam, lParam);
110     } else if(hwnd == wnd_progress) {
111         static struct progress_data data;
112
113         switch(message)
114         {
115             case USER_SETMESSAGE:
116                 data.text3 = (char*)wParam;
117                 SendMessage(data.wnd_text3, WM_SETTEXT, 0, (LPARAM)data.text3);
118                 return 0;
119             case WM_CREATE: {
120                 memset(&data, 0, sizeof(data));
121                 data.text1 = "Installing SWFTools";
122                 data.text2 = (char*)malloc(strlen(install_path)+250);
123                 data.text3 = "";
124                 sprintf(data.text2, "to %s", install_path);
125                 data.pos = 0;
126                 data.step = 1;
127
128                 CREATESTRUCT*cs = ((LPCREATESTRUCT)lParam);
129                 RECT rc;
130                 GetClientRect (hwnd, &rc);
131                 data.width = rc.right - rc.left;
132                 data.height = rc.bottom - rc.top;
133                 data.bar_width = cs->cx - 17;
134                 data.bar_height= 16;
135                 data.bar_posx = (data.width -data.bar_width)/2;
136                 data.bar_posy = 56;
137                 data.range = 50;
138
139                 data.hwndButton = CreateWindow (
140                         PROGRESS_CLASS,
141                         "Progress",
142                         WS_CHILD | WS_VISIBLE,
143                         data.bar_posx,
144                         data.bar_posy,
145                         data.bar_width, 
146                         data.bar_height,
147                         hwnd,  /* Parent */
148                         0,
149                         cs->hInstance,
150                         NULL
151                         );
152
153                 SendMessage(data.hwndButton, PBM_SETRANGE, 0, (LPARAM) MAKELONG(0,data.range));
154                 SendMessage(data.hwndButton, PBM_SETSTEP, (WPARAM) data.step, 0);
155                 return 0;
156             }   
157             case PBM_STEPIT: {
158                 if(data.pos+data.step < data.range) {
159                     data.pos += data.step;
160                     SendMessage(data.hwndButton, PBM_STEPIT, wParam, lParam);
161                 }
162             }
163             case WM_PAINT: {
164                 TEXTMETRIC    tm;
165                 HDC           hdc;             /* A device context used for drawing */
166                 PAINTSTRUCT   ps;              /* Also used during window drawing */
167                 RECT          rc;              /* A rectangle used during drawing */
168                 
169                 hdc = GetDC(hwnd);
170                 SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
171                 GetTextMetrics(hdc, &tm);
172                 ReleaseDC(hwnd, hdc);
173
174                 hdc = BeginPaint (hwnd, &ps);
175
176                 /*
177                 // draw logo 
178                 HDC memDc=CreateCompatibleDC(hdc);
179                 SelectObject(memDc,logo);
180                 BitBlt(hdc,0,0,406,93,memDc,0,0,SRCCOPY);
181                 DeleteDC(memDc);
182                 // /
183                 */
184
185                 SetBkMode(hdc, TRANSPARENT);
186                 
187                 rc.top = 8; rc.left= 0; rc.right = data.width; rc.bottom = 24;
188                 DrawText(hdc, data.text1, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
189
190                 char buf[256];
191                 char*text = data.text2;
192                 if(tm.tmAveCharWidth * strlen(text) > data.width) {
193                     int chars = (data.width / tm.tmAveCharWidth)-8;
194                     if(chars>240) chars=240;
195                     strncpy(buf, text, chars);
196                     strcpy(&buf[chars],"...");
197                     text = buf;
198                 }
199
200                 rc.top = 32; rc.left= 0; rc.right = data.width; rc.bottom = 48;
201                 DrawText(hdc, text, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
202                 
203                 //rc.top = data.height-32; rc.left= 0; rc.right = data.width; rc.bottom = data.height;
204                 //DrawText(hdc, data.text3, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
205
206                 EndPaint (hwnd, &ps);
207                 return 0;
208             }
209             case WM_DESTROY:
210                 wnd_progress = 0;
211                 return DefWindowProc(hwnd, message, wParam, lParam);
212             default:
213                 return DefWindowProc(hwnd, message, wParam, lParam);
214         }
215     } else if(hwnd == wnd_params) {
216         static struct params_data data;
217         switch(message)
218         {
219             case WM_CREATE: {
220                 memset(&data, 0, sizeof(data));
221                 CREATESTRUCT*cs = ((LPCREATESTRUCT)lParam);
222                 RECT rc;
223                 GetClientRect (hwnd, &rc);
224                 data.width = rc.right - rc.left;
225                 data.height = rc.bottom - rc.top;
226
227                 //EDITTEXT IDD_EDIT,68,8,72,12, ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER  | WS_TABSTOP
228                 data.edit = CreateWindow (
229                         WC_EDIT,
230                         "EditPath",
231                         WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | ES_AUTOHSCROLL,
232                         32, 
233                         48,
234                         (data.width-64)-32*2, 
235                         20,
236                         hwnd,  /* Parent */
237                         (HMENU)0x1234,
238                         cs->hInstance,
239                         NULL
240                         );
241                 
242                 data.explore = CreateWindow (
243                         WC_BUTTON,
244                         "Browse",
245                         WS_CHILD | WS_VISIBLE | WS_TABSTOP,
246                         data.width-32-64,
247                         48,
248                         64, 
249                         20,
250                         hwnd,  /* Parent */
251                         (HMENU)0x9999,
252                         cs->hInstance,
253                         NULL
254                         );
255                 
256                 data.installButton = CreateWindow (
257                         WC_BUTTON,
258                         "Install",
259                         WS_CHILD | WS_VISIBLE | WS_TABSTOP,
260                         (data.width - 80)/2,
261                         data.height - 32*2,
262                         80, 
263                         32,
264                         hwnd,  /* Parent */
265                         (HMENU)0xabcd,
266                         cs->hInstance,
267                         NULL
268                         );
269                 
270                 SendMessage(data.edit, WM_SETTEXT, 0, (LPARAM)install_path);
271                 return 0;
272             }   
273             case USER_SETMESSAGE: {
274                 //install_path = (char*)lParam;
275                 SendMessage(data.edit, WM_SETTEXT, 0, (LPARAM)install_path);
276                 printf("Setting path to %s\n", install_path);
277                 return 0;
278             }
279             case WM_PAINT: {
280                 TEXTMETRIC tm;
281                 HDC hdc;
282                 PAINTSTRUCT ps;
283                 RECT rc;
284                 hdc = GetDC(hwnd);
285                 SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
286                 GetTextMetrics(hdc, &tm);
287                 ReleaseDC(hwnd, hdc);
288                 hdc = BeginPaint (hwnd, &ps);
289                 SetBkMode(hdc, TRANSPARENT);
290                 rc.top = 32; rc.left= 16; rc.right = data.width-32*2; rc.bottom = 20;
291                 DrawText(hdc, "Select Installation directory", -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
292                 EndPaint (hwnd, &ps);
293                 return 0;
294             }
295             case WM_COMMAND: {
296                 if((wParam&0xffff) == 0x9999) {
297                     BROWSEINFOA browse;
298                     memset(&browse, 0, sizeof(browse));
299                     browse.ulFlags = BIF_EDITBOX | BIF_NEWDIALOGSTYLE | BIF_USENEWUI;// | BIF_RETURNONLYFSDIRS; //BIF_VALIDATE
300                     browse.pszDisplayName = (CHAR*)malloc(MAX_PATH);
301                     memset(browse.pszDisplayName, 0, MAX_PATH);
302                     browse.lpszTitle = "Select installation directory";
303                     /*browse.pidlRoot = (ITEMIDLIST*)malloc(sizeof(ITEMIDLIST)*200);
304                     memset((void*)browse.pidlRoot, 0, sizeof(ITEMIDLIST)*200);*/
305                     printf("Start browsing %s\n", browse.pszDisplayName);
306                     //SHGetDesktopFolder
307                     //ParseDisplayName(install_path,0,&browse.pidlRoot,0,0);
308                     //SHParseDisplayName(install_path,0,&browse.pidlRoot,0,0);
309                     //SHBrowseForFolderA(&browse);
310                     browse.pidlRoot = SHBrowseForFolder(&browse);
311                     printf("Browsing returns %s / %08x\n", browse.pszDisplayName, browse.pidlRoot);
312                     if(browse.pszDisplayName) {
313                         if(SHGetPathFromIDList(browse.pidlRoot, browse.pszDisplayName)) {
314                             printf("Path is %s\n", browse.pszDisplayName);
315                             install_path = browse.pszDisplayName;
316                         }
317                     }
318                     SendMessage(data.edit, WM_SETTEXT, 0, (LPARAM)install_path);
319                     return 0;
320                 } else if((wParam&0xffff) == 0xabcd) {
321                     data.ok = 1;
322                     DestroyWindow(hwnd);
323                     return 0;
324                 } else if((wParam&0xffff) == 0x1234) {
325                     SendMessage(data.edit, WM_GETTEXT, sizeof(pathBuf), (LPARAM)&(pathBuf[0]));
326                     if(pathBuf[0]) {
327                         install_path = pathBuf;
328                     }
329                     return 0;
330                 }
331                 return DefWindowProc(hwnd, message, wParam, lParam);
332             }
333             case WM_KEYDOWN: {
334                 if(wParam == 0x49) {
335                     DestroyWindow(hwnd);
336                 }
337                 return 0;
338             }
339             case WM_DESTROY:
340                 if(!data.ok) {
341                     do_abort = 1;
342                     PostQuitMessage (0);
343                 }
344                 wnd_params = 0;
345                 return DefWindowProc(hwnd, message, wParam, lParam);
346             default:
347                 return DefWindowProc(hwnd, message, wParam, lParam);
348         }
349     } else if(hwnd == wnd_finish) {
350         static struct finish_data data;
351         switch(message)
352         {
353             case WM_CREATE: {
354                 RECT rc;
355                 CREATESTRUCT*cs = ((LPCREATESTRUCT)lParam);
356                 GetClientRect (hwnd, &rc);
357                 data.width = rc.right - rc.left;
358                 data.height = rc.bottom - rc.top;
359
360                 data.text = malloc(strlen(install_path)+256);
361                 sprintf(data.text, "SWFTools has been installed into directory\r\n%s\r\nsucessfully.", install_path);
362                 
363                 data.installButton = CreateWindow (
364                         WC_BUTTON,
365                         "Finish",
366                         WS_CHILD | WS_VISIBLE | WS_TABSTOP,
367                         (data.width - 80)/2,
368                         data.height - 32,
369                         80, 
370                         32,
371                         hwnd, 
372                         (HMENU)0xabce,
373                         cs->hInstance,
374                         NULL
375                         );
376         
377                 if(config_createLinks) {
378                     data.check1 = CreateWindow (
379                             WC_BUTTON,
380                             "Create Desktop Shortcut",
381                             WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_CHECKBOX,
382                             32, data.height - 96, 
383                             data.width-32*2, 32, 
384                             hwnd, (HMENU)0xabcf, cs->hInstance, NULL);
385                     
386                     data.check2 = CreateWindow (
387                             WC_BUTTON,
388                             "Create Start Menu Entry",
389                             WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_CHECKBOX,
390                             32, data.height - 64, 
391                             data.width-32*2, 32, 
392                             hwnd, (HMENU)0xabd0, cs->hInstance, NULL);
393                     
394                     SendDlgItemMessage(hwnd, 0xabcf, BM_SETCHECK, config_createStartmenu, 0);
395                     SendDlgItemMessage(hwnd, 0xabd0, BM_SETCHECK, config_createDesktop, 0);
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                     config_createDesktop = SendDlgItemMessage(hwnd, 0xabcf, BM_GETCHECK, 0, 0);
427                     config_createDesktop^=1;
428                     SendDlgItemMessage(hwnd, 0xabcf, BM_SETCHECK, config_createDesktop, 0);
429                     return 0;
430                 }
431                 if((wParam&0xffff) == 0xabd0) {
432                     config_createStartmenu = SendDlgItemMessage(hwnd, 0xabd0, BM_GETCHECK, 0, 0);
433                     config_createStartmenu^=1;
434                     SendDlgItemMessage(hwnd, 0xabd0, BM_SETCHECK, config_createStartmenu, 0);
435                     return 0;
436                 }
437             }
438             case WM_DESTROY: {
439                 free(data.text);data.text = 0;
440                 if(!data.ok) {
441                     do_abort = 1;
442                     PostQuitMessage(0);
443                 }
444                 wnd_finish = 0;
445                 return DefWindowProc(hwnd, message, wParam, lParam);
446             }
447         }
448     } else if(hwnd == wnd_background) {
449         switch(message)
450         {
451             case WM_PAINT: {
452                 HDC hdc;
453                 PAINTSTRUCT ps;
454                 RECT rc;
455                 hdc = BeginPaint(hwnd, &ps);
456                 SetBkMode(hdc, TRANSPARENT);
457
458                 HPEN pen = CreatePen(PS_SOLID, 2, RGB(255, 255, 0));    
459                 HPEN oldPen = (HPEN)SelectObject(hdc, pen);
460
461                 MoveToEx(hdc, 10, 10, 0);
462                 //LineTo(hdc, 100, 100);
463
464                 SelectObject(hdc, oldPen); 
465                 DeleteObject(pen);
466
467                 EndPaint(hwnd, &ps);
468                 return 1;
469             }
470         }
471     }
472     return DefWindowProc(hwnd, message, wParam, lParam);
473 }
474
475 void processMessages()
476 {
477     MSG msg;
478     while(PeekMessage(&msg,NULL,0,0,0))
479     {
480         GetMessage(&msg, NULL, 0, 0);
481         TranslateMessage(&msg);
482         DispatchMessage(&msg);
483     }
484 }
485
486 static char*lastmessage = 0;
487 void myarchivestatus(int type, char*text)
488 {
489     if(text && text[0]=='[')
490         return;
491     //printf("%s\n", text);
492                         
493     SendMessage(wnd_progress, USER_SETMESSAGE, (WPARAM)strdup(text), 0);
494     SendMessage(wnd_progress, WM_PAINT, 0, 0);
495     int t;
496     for(t=0;t<9;t++) {
497         SendMessage(wnd_progress, PBM_STEPIT, 0, 0);
498         /* while we're here, we might also make ourselves useful */
499         processMessages();
500         /* we want the user to see what we're writing, right? */
501         Sleep(30);
502     }
503
504     if(type<0) {
505         while(1) {
506             int ret = MessageBox(0, text, "Error", MB_RETRYCANCEL|MB_ICONERROR);
507             
508             /* there is no MB_CANCEL, so, *sigh*, we have to display
509                the "retry" button. So pretend it's doing anything... */
510             if(ret==IDRETRY)
511                 continue;
512             else
513                 break;
514         }
515     }
516 }
517
518 int addRegistryEntries(char*install_dir)
519 {
520     int ret;
521     ret = setRegistryEntry("Software\\quiss.org\\swftools\\InstallPath", install_dir);
522     if(!ret) return 0;
523     return 1;
524 }
525
526 int CreateShortcut(char*path, char*description, char*filename, char*arguments, int iconindex, char*iconpath, char*workdir)
527 {
528     WCHAR wszFilename[MAX_PATH];
529     IShellLink *ps1 = NULL;
530     IPersistFile *pPf = NULL;
531     HRESULT hr;
532     hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (void*)&ps1);
533     if(FAILED(hr)) return 0;
534     hr = ps1->lpVtbl->QueryInterface(ps1, &IID_IPersistFile, (void **)&pPf);
535     if(FAILED(hr)) return 0;
536     hr = ps1->lpVtbl->SetPath(ps1, path);
537     if(FAILED(hr)) return 0;
538     hr = ps1->lpVtbl->SetDescription(ps1, description);
539     
540     if (arguments) {
541         hr = ps1->lpVtbl->SetArguments(ps1, arguments);
542         if(FAILED(hr)) return 0;
543     }
544     if (iconpath) {
545         hr = ps1->lpVtbl->SetIconLocation(ps1, iconpath, iconindex);
546         if (FAILED(hr)) return 0;
547     }
548     if (workdir) {
549         hr = ps1->lpVtbl->SetWorkingDirectory(ps1, workdir);
550         if (FAILED(hr)) return 0;
551     }
552     MultiByteToWideChar(CP_ACP, 0, filename, -1, wszFilename, MAX_PATH);
553     hr = pPf->lpVtbl->Save(pPf, wszFilename, TRUE);
554     if(FAILED(hr)) {
555         return 0;
556     }
557     pPf->lpVtbl->Release(pPf);
558     ps1->lpVtbl->Release(ps1);
559     return 1;
560 }
561
562
563 static HRESULT (WINAPI *f_SHGetSpecialFolderPath)(HWND hwnd, LPTSTR lpszPath, int nFolder, BOOL fCreate);
564 static char path_startmenu[MAX_PATH];
565 static char path_desktop[MAX_PATH];
566
567 int WINAPI WinMain(HINSTANCE me,HINSTANCE hPrevInst,LPSTR lpszArgs, int nWinMode)
568 {
569     WNDCLASSEX wcl;
570     wcl.hInstance    = me;
571     wcl.lpfnWndProc  = WindowFunc;
572     wcl.lpszClassName= "SWFTools-Install";
573     wcl.style        = CS_HREDRAW | CS_VREDRAW;
574     wcl.hIcon        = LoadIcon(NULL, IDI_APPLICATION);
575     wcl.hIconSm      = LoadIcon(NULL, IDI_APPLICATION);
576     wcl.hCursor      = LoadCursor(NULL, IDC_ARROW);
577     wcl.lpszMenuName = NULL; //no menu
578     wcl.cbClsExtra   = 0;
579     wcl.cbWndExtra   = 0;
580     wcl.hbrBackground= (HBRUSH)GetStockObject(LTGRAY_BRUSH);
581     wcl.cbSize       = sizeof(WNDCLASSEX);
582
583     WNDCLASSEX wcl_text;
584     memcpy(&wcl_text, &wcl, sizeof(WNDCLASSEX));
585     wcl_text.lpszClassName= "TextClass";
586     wcl_text.hbrBackground = GetStockObject(HOLLOW_BRUSH);
587
588     WNDCLASSEX wcl_background;
589     memcpy(&wcl_background, &wcl, sizeof(WNDCLASSEX));
590     wcl_background.lpszClassName= "SWFTools Installer";
591     wcl_background.hbrBackground= CreateSolidBrush(RGB(0, 0, 128));
592   
593     HINSTANCE shell32 = LoadLibrary("shell32.dll");
594     if(!shell32) {
595         MessageBox(0, "Could not load shell32.dll", "Install.exe", MB_OK);
596         return 1;
597     }
598     f_SHGetSpecialFolderPath = (HRESULT (WINAPI*)(HWND,LPTSTR,int,BOOL))GetProcAddress(shell32, "SHGetSpecialFolderPathA");
599     if(!f_SHGetSpecialFolderPath) {
600         MessageBox(0, "Could not load shell32.dll", "Install.exe", MB_OK);
601         return 1;
602     }
603         
604     HRESULT ret = CoInitialize(NULL);
605     if(FAILED(ret)) {
606         MessageBox(0, "Could not initialize COM interface", "Install.exe", MB_OK);
607         return 1;
608     }
609
610     char mypath[MAX_PATH];
611     path_startmenu[0] = 0;
612     path_desktop[0] = 0;
613     if(config_forAllUsers) {
614         f_SHGetSpecialFolderPath(NULL, path_desktop, CSIDL_COMMON_DESKTOPDIRECTORY, 0);
615         f_SHGetSpecialFolderPath(NULL, path_startmenu, CSIDL_COMMON_PROGRAMS, 0);
616     } else {
617         f_SHGetSpecialFolderPath(NULL, path_desktop, CSIDL_DESKTOPDIRECTORY, 0);
618         f_SHGetSpecialFolderPath(NULL, path_startmenu, CSIDL_PROGRAMS, 0);
619     }
620
621     if(!RegisterClassEx(&wcl)) {
622         MessageBox(0, "Could not register window class", "Install.exe", MB_OK);
623         return 1;
624     }
625     if(!RegisterClassEx(&wcl_background)) {
626         MessageBox(0, "Could not register window class 2", "Install.exe", MB_OK);
627         return 1;
628     }
629
630     HWND background = CreateWindow(wcl_background.lpszClassName, "Setup SWFTools",
631                          0, 0, 0, 
632                          GetSystemMetrics(SM_CXFULLSCREEN),
633                          GetSystemMetrics(SM_CYFULLSCREEN),
634                          NULL, NULL, me, 
635                          (void*)"background");
636     
637     if(!background) {
638         MessageBox(0, "Could not create installation background window", "Install.exe", MB_OK);
639         return 1;
640     }
641
642     ShowWindow(background, SW_SHOWMAXIMIZED);
643     SetForegroundWindow(background);
644     UpdateWindow(background);
645
646     RECT r = {0,0,0,0};
647     GetWindowRect(background, &r);
648     int xx = 320, yy = 200;
649     if(r.right - r.left > 320)
650         xx = r.right - r.left;
651     if(r.right - r.left > 200)
652         yy = r.bottom - r.top;
653     
654     logo = LoadBitmap(me, "SWFTOOLS");
655     
656     install_path = getRegistryEntry("Software\\quiss.org\\swftools\\InstallPath");
657     if(!install_path || !install_path[0])
658         install_path = "c:\\swftools\\";
659
660     CoInitialize(0);
661     InitCommonControls();
662     
663     HWND installpath_window = CreateWindow(
664             wcl.lpszClassName,          /* Class name */
665             "SWFTools Installer",       /* Caption */
666             /*WS_CHILD |*/ WS_CAPTION,
667             (xx-320)/2,                 /* Initial x  */
668             (yy-200)/2,                 /* Initial y  */
669             320,                        /* Initial x size */
670             200,                        /* Initial y size */
671             background,                       /* No parent window */
672             NULL,                       /* No menu */
673             me,                         /* This program instance */
674             (void*)"params"             /* Creation parameters */
675             );
676
677     if(!installpath_window) {
678         MessageBox(background, "Could not create installation window", "Install.exe", MB_OK);
679         return 1;
680     }
681
682     ShowWindow (wnd_params, nWinMode);
683     SetFocus(wnd_params);
684     SetForegroundWindow(wnd_params);
685     UpdateWindow (wnd_params);
686    
687     MSG msg;
688     while(wnd_params)
689     {
690         GetMessage(&msg,NULL,0,0);
691         TranslateMessage(&msg);
692         DispatchMessage(&msg);
693     }
694
695     if(do_abort) {
696         MessageBox(background, "Aborting Installation", "Error", MB_OK|MB_ICONERROR);
697         return 1;
698     }
699    
700     /*char buf[1024];
701     sprintf(buf, "Do you want me to install SWFTools into the directory %s now?", install_path);
702     int ret = MessageBox(0, buf, "SWFTools Install", MB_YESNO|MB_ICONQUESTION);
703     if(ret == IDNO)
704         return 0;*/
705     
706     CreateWindow (
707             wcl.lpszClassName,          /* Class name */
708             "Installing...",            /* Caption */
709             //WS_CHILD | WS_CAPTION,
710             WS_CAPTION, 
711             (xx-260)/2, (yy-128)/2,
712             260,                        /* Initial x size */
713             128,                        /* Initial y size */
714             background,                 /* No parent window */
715             NULL,                       /* No menu */
716             me,                         /* This program instance */
717             (void*)"progress"           /* Creation parameters */
718             );
719     ShowWindow (wnd_progress, nWinMode);
720     SetFocus(wnd_progress);
721     SetForegroundWindow(wnd_progress);
722     UpdateWindow (wnd_progress);
723     
724     int success = unpack_archive(crndata, install_path, myarchivestatus);
725    
726     DestroyWindow(wnd_progress);
727
728     while(wnd_progress)
729         processMessages();
730     if(do_abort) {
731         MessageBox(background, "Aborting Installation", "Error", MB_OK|MB_ICONERROR);
732         return 1;
733     }
734     
735     char* pdf2swf_path = concatPaths(install_path, "pdf2swf_gui.exe");
736     FILE*fi = fopen(pdf2swf_path, "rb");
737     if(fi) {
738         config_createLinks = 1;
739         fclose(fi);
740     }
741
742     int h = config_createLinks?200:160;
743     CreateWindow (
744             wcl.lpszClassName,          /* Class name */
745             "Finished",                 /* Caption */
746             /*WS_CHILD |*/ WS_CAPTION,
747             //WS_OVERLAPPEDWINDOW&(~WS_SIZEBOX),        /* Style */
748             (xx-320)/2, (yy-h)/2,
749             320,                        /* Initial x size */
750             h,                        /* Initial y size */
751             background,                 /* No parent window */
752             NULL,                       /* No menu */
753             me,                         /* This program instance */
754             (void*)"finish"             /* Creation parameters */
755             );
756     ShowWindow(wnd_finish, nWinMode);
757     SetFocus(wnd_finish);
758     SetForegroundWindow(wnd_finish);
759     UpdateWindow(wnd_finish);
760
761     while(wnd_finish)
762         processMessages();
763     if(do_abort) {
764         MessageBox(0, "Aborting Installation", "Error", MB_OK|MB_ICONERROR);
765         return 1;
766     }
767
768     if(!addRegistryEntries(install_path)) {
769         MessageBox(0, "Couldn't create Registry Entries", "SWFTools Install", MB_OK|MB_ICONERROR);
770         return 1;
771     }
772
773     if(config_createLinks) {
774         if(config_createDesktop && path_desktop[0]) {
775             char* linkName = concatPaths(path_desktop, "pdf2swf.lnk");
776             if(!CreateShortcut(pdf2swf_path, "pdf2swf", linkName, 0, 0, 0, install_path)) {
777                 MessageBox(0, "Couldn't create desktop shortcut", "Install.exe", MB_OK);
778                 return 1;
779             }
780         }
781         if(config_createStartmenu && path_startmenu[0]) {
782             char* group = concatPaths(path_startmenu, "pdf2swf");
783             CreateDirectory(group, 0);
784             char* linkName = concatPaths(group, "pdf2swf.lnk");
785             if(!CreateShortcut(pdf2swf_path, "pdf2swf", linkName, 0, 0, 0, install_path)) {
786                 MessageBox(0, "Couldn't create start menu entry", "Install.exe", MB_OK);
787                 return 1;
788             }
789         }
790     }
791     exit(0);
792 }
793