+/* installer.c
+
+ Part of the swftools installer (Main program).
+
+ Copyright (c) 2004 Matthias Kramm <kramm@quiss.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <windows.h>
+#include <commctrl.h>
+#include <commdlg.h>
+#include <shlobj.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "depack.h"
+
+#include "../config.h" //for swftools version
+#include "../lib/os.h" //for registry functions
+
+extern char*crndata;
+
+static char*install_path = "c:\\swftools\\";
+static char pathBuf[1024];
+static int do_abort = 0;
+
+static HWND wnd_progress = 0;
+static HWND wnd_params = 0;
+
+static HBITMAP logo;
+
+#define USER_SETMESSAGE 0x7f01
+
+struct progress_data {
+ int width,height;
+ int bar_width;
+ int bar_height;
+ int bar_posx;
+ int bar_posy;
+ int pos,step,range;
+ char*text1;
+ char*text2;
+ char*text3;
+ HWND hwndButton;
+ HWND wnd_text3;
+};
+struct params_data {
+ int width,height;
+ int ok;
+ HWND installButton;
+ HWND edit;
+ HWND explore;
+};
+
+LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ //printf("%08x, %d %08x %08x\n", hwnd, message, wParam, lParam);
+
+ /* in order for the delegation below to also work for
+ WM_CREATE, we need to assign our window pointers *before* the
+ CreateWindow returns, because that's when the WM_CREATE event
+ is sent */
+ if(message == WM_CREATE) {
+ CREATESTRUCT*cs = ((LPCREATESTRUCT)lParam);
+ if(cs->lpCreateParams && !strcmp((char*)cs->lpCreateParams, "params")) {
+ wnd_params = hwnd;
+ }
+ if(cs->lpCreateParams && !strcmp((char*)cs->lpCreateParams, "progress")) {
+ wnd_progress = hwnd;
+ }
+ }
+
+ if(hwnd == 0) {
+ return DefWindowProc(hwnd, message, wParam, lParam);
+ } else if(hwnd == wnd_progress) {
+ static struct progress_data data;
+
+ switch(message)
+ {
+ case USER_SETMESSAGE:
+ data.text3 = (char*)wParam;
+ SendMessage(data.wnd_text3, WM_SETTEXT, 0, (LPARAM)data.text3);
+ return 0;
+ case WM_CREATE: {
+ memset(&data, 0, sizeof(data));
+ data.text1 = "Installing SWFTools";
+ data.text2 = (char*)malloc(strlen(install_path)+250);
+ sprintf(data.text2, "to %s", install_path);
+ data.pos = 0;
+ data.step = 1;
+
+ CREATESTRUCT*cs = ((LPCREATESTRUCT)lParam);
+ RECT rc;
+ GetClientRect (hwnd, &rc);
+ data.width = rc.right - rc.left;
+ data.height = rc.bottom - rc.top;
+ data.bar_width = cs->cx - 17;
+ data.bar_height= 16;
+ data.bar_posx = (data.width -data.bar_width)/2;
+ data.bar_posy = 56;
+ data.range = 50;
+
+ data.hwndButton = CreateWindow (
+ PROGRESS_CLASS,
+ "Progress",
+ WS_CHILD | WS_VISIBLE,
+ data.bar_posx,
+ data.bar_posy,
+ data.bar_width,
+ data.bar_height,
+ hwnd, /* Parent */
+ (HMENU)1,
+ cs->hInstance,
+ NULL
+ );
+
+ data.wnd_text3 = CreateWindow (
+ WC_STATIC,
+ "text3",
+ WS_CHILD | WS_VISIBLE,
+ data.bar_posx,
+ 72,
+ (rc.right - rc.left - data.bar_posx*2),
+ 20,
+ hwnd, /* Parent */
+ (HMENU)1,
+ cs->hInstance,
+ NULL
+ );
+ SendMessage(data.wnd_text3, WM_SETTEXT, 0, (LPARAM)"");
+
+ SendMessage(data.hwndButton, PBM_SETRANGE, 0, (LPARAM) MAKELONG(0,data.range));
+ SendMessage(data.hwndButton, PBM_SETSTEP, (WPARAM) data.step, 0);
+ return 0;
+ }
+ case PBM_STEPIT: {
+ if(data.pos+data.step < data.range) {
+ data.pos += data.step;
+ SendMessage(data.hwndButton, PBM_STEPIT, wParam, lParam);
+ }
+ }
+ case WM_PAINT: {
+ TEXTMETRIC tm;
+ HDC hdc; /* A device context used for drawing */
+ PAINTSTRUCT ps; /* Also used during window drawing */
+ RECT rc; /* A rectangle used during drawing */
+
+ hdc = GetDC(hwnd);
+ SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
+ GetTextMetrics(hdc, &tm);
+ ReleaseDC(hwnd, hdc);
+
+ hdc = BeginPaint (hwnd, &ps);
+
+ /*
+ // draw logo
+ HDC memDc=CreateCompatibleDC(hdc);
+ SelectObject(memDc,logo);
+ BitBlt(hdc,0,0,406,93,memDc,0,0,SRCCOPY);
+ DeleteDC(memDc);
+ // /
+ */
+
+ SetBkMode(hdc, TRANSPARENT);
+
+ rc.top = 8; rc.left= 0; rc.right = data.width; rc.bottom = 24;
+ DrawText(hdc, data.text1, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
+
+ char buf[256];
+ char*text = data.text2;
+ if(tm.tmAveCharWidth * strlen(text) > data.width) {
+ int chars = (data.width / tm.tmAveCharWidth)-8;
+ if(chars>240) chars=240;
+ strncpy(buf, text, chars);
+ strcpy(&buf[chars],"...");
+ text = buf;
+ }
+
+ rc.top = 32; rc.left= 0; rc.right = data.width; rc.bottom = 48;
+ DrawText(hdc, text, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
+
+ EndPaint (hwnd, &ps);
+ return 0;
+ }
+ case WM_DESTROY:
+ wnd_progress = 0;
+ return DefWindowProc(hwnd, message, wParam, lParam);
+ default:
+ return DefWindowProc(hwnd, message, wParam, lParam);
+ }
+ } else if(hwnd == wnd_params) {
+ static struct params_data data;
+ switch(message)
+ {
+ case WM_CREATE: {
+ memset(&data, 0, sizeof(data));
+ CREATESTRUCT*cs = ((LPCREATESTRUCT)lParam);
+ RECT rc;
+ GetClientRect (hwnd, &rc);
+ data.width = rc.right - rc.left;
+ data.height = rc.bottom - rc.top;
+
+ //EDITTEXT IDD_EDIT,68,8,72,12, ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP
+ HWND text = CreateWindow(
+ WC_STATIC,
+ "Select Installation Directory:",
+ WS_CHILD | WS_VISIBLE,
+ 32,
+ 16,
+ data.width-32*2,
+ 20,
+ hwnd, /* Parent */
+ 0,
+ cs->hInstance,
+ NULL
+ );
+
+ data.edit = CreateWindow (
+ WC_EDIT,
+ "EditPath",
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | ES_AUTOHSCROLL,
+ 32,
+ 48,
+ (data.width-64)-32*2,
+ 20,
+ hwnd, /* Parent */
+ (HMENU)0x1234,
+ cs->hInstance,
+ NULL
+ );
+
+ data.explore = CreateWindow (
+ WC_BUTTON,
+ "Browse",
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP,
+ data.width-32-64,
+ 48,
+ 64,
+ 20,
+ hwnd, /* Parent */
+ (HMENU)0x9999,
+ cs->hInstance,
+ NULL
+ );
+
+ data.installButton = CreateWindow (
+ WC_BUTTON,
+ "Install",
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP,
+ (data.width - 80)/2,
+ data.height - 32*2,
+ 80,
+ 32,
+ hwnd, /* Parent */
+ (HMENU)0xabcd,
+ cs->hInstance,
+ NULL
+ );
+
+ SendMessage(data.edit, WM_SETTEXT, 0, (LPARAM)install_path);
+ return 0;
+ }
+ case USER_SETMESSAGE: {
+ //install_path = (char*)lParam;
+ SendMessage(data.edit, WM_SETTEXT, 0, (LPARAM)install_path);
+ printf("Setting path to %s\n", install_path);
+ return 0;
+ }
+ case WM_PAINT: {
+ return DefWindowProc(hwnd, message, wParam, lParam);
+ }
+ case WM_COMMAND: {
+ if((wParam&0xffff) == 0x9999) {
+ BROWSEINFOA browse;
+ memset(&browse, 0, sizeof(browse));
+ browse.ulFlags = BIF_EDITBOX | BIF_NEWDIALOGSTYLE | BIF_USENEWUI;// | BIF_RETURNONLYFSDIRS; //BIF_VALIDATE
+ browse.pszDisplayName = (CHAR*)malloc(MAX_PATH);
+ memset(browse.pszDisplayName, 0, MAX_PATH);
+ browse.lpszTitle = "Select installation directory";
+ /*browse.pidlRoot = (ITEMIDLIST*)malloc(sizeof(ITEMIDLIST)*200);
+ memset((void*)browse.pidlRoot, 0, sizeof(ITEMIDLIST)*200);*/
+ printf("Start browsing %s\n", browse.pszDisplayName);
+ //SHGetDesktopFolder
+ //ParseDisplayName(install_path,0,&browse.pidlRoot,0,0);
+ //SHParseDisplayName(install_path,0,&browse.pidlRoot,0,0);
+ //SHBrowseForFolderA(&browse);
+ browse.pidlRoot = SHBrowseForFolder(&browse);
+ printf("Browsing returns %s / %08x\n", browse.pszDisplayName, browse.pidlRoot);
+ if(browse.pszDisplayName) {
+ if(SHGetPathFromIDList(browse.pidlRoot, browse.pszDisplayName)) {
+ printf("Path is %s\n", browse.pszDisplayName);
+ install_path = browse.pszDisplayName;
+ }
+ }
+ SendMessage(data.edit, WM_SETTEXT, 0, (LPARAM)install_path);
+ return 0;
+ } else if((wParam&0xffff) == 0xabcd) {
+ data.ok = 1;
+ DestroyWindow(wnd_params);
+ return 0;
+ } else if((wParam&0xffff) == 0x1234) {
+ SendMessage(data.edit, WM_GETTEXT, sizeof(pathBuf), (LPARAM)&(pathBuf[0]));
+ if(pathBuf[0]) {
+ install_path = pathBuf;
+ printf("Path edited: now \"%s\"\n", install_path);
+ }
+ return 0;
+ }
+ return DefWindowProc(hwnd, message, wParam, lParam);
+ }
+ case WM_KEYDOWN: {
+ if(wParam == 0x49) {
+ DestroyWindow(wnd_params);
+ }
+ return 0;
+ }
+ case WM_DESTROY:
+ if(!data.ok) {
+ do_abort = 1;
+ PostQuitMessage (0);
+ }
+ wnd_params = 0;
+ return DefWindowProc(hwnd, message, wParam, lParam);
+ default:
+ return DefWindowProc(hwnd, message, wParam, lParam);
+ }
+ }
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+void processMessages()
+{
+ MSG msg;
+ while(PeekMessage(&msg,NULL,0,0,0))
+ {
+ GetMessage(&msg, NULL, 0, 0);
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+}
+
+static char*lastmessage = 0;
+void myarchivestatus(int type, char*text)
+{
+ if(text && text[0]=='[')
+ return;
+ //printf("%s\n", text);
+
+ SendMessage(wnd_progress, USER_SETMESSAGE, (WPARAM)strdup(text), 0);
+ SendMessage(wnd_progress, WM_PAINT, 0, 0);
+ int t;
+ for(t=0;t<9;t++) {
+ SendMessage(wnd_progress, PBM_STEPIT, 0, 0);
+ /* while we're here, we might also make ourselves useful */
+ processMessages();
+ /* we want the user to see what we're writing, right? */
+ Sleep(30);
+ }
+
+ if(type<0) {
+ while(1) {
+ int ret = MessageBox(0, text, "Error", MB_RETRYCANCEL|MB_ICONERROR);
+
+ /* there is no MB_CANCEL, so, *sigh*, we have to display
+ the "retry" button. So pretend it's doing anything... */
+ if(ret==IDRETRY)
+ continue;
+ else
+ break;
+ }
+ }
+}
+
+int addRegistryEntries(char*install_dir)
+{
+ int ret;
+ ret = setRegistryEntry("Software\\quiss.org\\swftools\\InstallPath", install_dir);
+ if(!ret) return 0;
+ return 1;
+}
+
+int WINAPI WinMain(HINSTANCE me,HINSTANCE hPrevInst,LPSTR lpszArgs, int nWinMode)
+{
+ WNDCLASSEX wcl;
+
+ wcl.hInstance = me;
+ wcl.lpszClassName= "SWFTools-Installer";
+ wcl.lpfnWndProc = WindowFunc;
+ wcl.style = CS_HREDRAW | CS_VREDRAW;
+ wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ wcl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
+ wcl.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wcl.lpszMenuName = NULL; //no menu
+ wcl.cbClsExtra = 0;
+ wcl.cbWndExtra = 0;
+ //wcl.hbrBackground= (HBRUSH) GetStockObject(DKGRAY_BRUSH);
+ //wcl.hbrBackground= (HBRUSH) GetStockObject (WHITE_BRUSH);
+ wcl.hbrBackground= (HBRUSH) GetStockObject(LTGRAY_BRUSH);
+ //wcl.hbrBackground= (HBRUSH) GetStockObject (GRAY_BRUSH);
+ wcl.cbSize = sizeof(WNDCLASSEX);
+
+ if(!RegisterClassEx(&wcl)) {
+ return 0;
+ }
+
+ logo = LoadBitmap(me, "SWFTOOLS");
+
+ install_path = getRegistryEntry("Software\\quiss.org\\swftools\\InstallPath");
+ if(!install_path || !install_path[0])
+ install_path = "c:\\swftools\\";
+
+ CoInitialize(0);
+ InitCommonControls();
+
+ CreateWindow (
+ wcl.lpszClassName, /* Class name */
+ "SWFTools Installer", /* Caption */
+ WS_OVERLAPPEDWINDOW&(~WS_SIZEBOX), /* Style */
+ CW_USEDEFAULT, /* Initial x (use default) */
+ CW_USEDEFAULT, /* Initial y (use default) */
+ 320, /* Initial x size */
+ 200, /* Initial y size */
+ NULL, /* No parent window */
+ NULL, /* No menu */
+ me, /* This program instance */
+ (void*)"params" /* Creation parameters */
+ );
+
+ ShowWindow (wnd_params, nWinMode);
+ UpdateWindow (wnd_params);
+
+ MSG msg;
+ while(wnd_params)
+ {
+ GetMessage(&msg,NULL,0,0);
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ if(do_abort)
+ return 0;
+
+ /*char buf[1024];
+ sprintf(buf, "Do you want me to install SWFTools into the directory %s now?", install_path);
+ int ret = MessageBox(0, buf, "SWFTools Install", MB_YESNO|MB_ICONQUESTION);
+ if(ret == IDNO)
+ return 0;*/
+
+ CreateWindow (
+ wcl.lpszClassName, /* Class name */
+ "Installing...", /* Caption */
+ WS_OVERLAPPEDWINDOW&(~WS_SIZEBOX), /* Style */
+ CW_USEDEFAULT, /* Initial x (use default) */
+ CW_USEDEFAULT, /* Initial y (use default) */
+ 260, /* Initial x size */
+ 128, /* Initial y size */
+ NULL, /* No parent window */
+ NULL, /* No menu */
+ me, /* This program instance */
+ (void*)"progress" /* Creation parameters */
+ );
+ ShowWindow (wnd_progress, nWinMode);
+ UpdateWindow (wnd_progress);
+
+ int success = unpack_archive(crndata, install_path, myarchivestatus);
+
+ DestroyWindow(wnd_progress);
+
+ while(wnd_progress)
+ processMessages();
+
+ if(!addRegistryEntries(install_path)) {
+ success = 0;
+ MessageBox(0, "Couldn't create Registry Entries", "SWFTools Install", MB_OK|MB_ICONERROR);
+ }
+
+ if(success) {
+ char buf[1024];
+ sprintf(buf, "SWFTools Version %s has been installed into %s successfully", VERSION, install_path);
+ MessageBox(0, buf, "SWFTools Install", MB_OK|MB_ICONINFORMATION);
+ } else {
+ /* error will already have been notified by either myarchivestatus or some other
+ routine */
+ /*sprintf(buf, "Installation failed\nLast message: %s", lastmessage);
+ ret = MessageBox(0, buf, "SWFTools Install", MB_OK|MB_ICONERROR);*/
+ }
+ exit(0);
+}
+
+
+