source: branches/eraser6/Installer/Bootstrapper/Main.cpp @ 536

Revision 536, 7.9 KB checked in by lowjoel, 6 years ago (diff)

Implemented .NET framework and Eraser installation steps.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 * Copyright 2008 The Eraser Project
4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By:
6 *
7 * This file is part of Eraser.
8 *
9 * Eraser is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
13 *
14 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 *
18 * A copy of the GNU General Public License can be found at
19 * <http://www.gnu.org/licenses/>.
20 */
21
22#include "stdafx.h"
23#include "Bootstrapper.h"
24
25//Common Controls Version 6
26#pragma comment(linker, "\"/manifestdependency:type='Win32' " \
27    "name='Microsoft.Windows.Common-Controls' version='6.0.0.0' "\
28    "processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' "\
29    "language='*'\"")
30
31namespace {
32    //Constants
33    const wchar_t* STATIC_CLASS = L"STATIC";
34    const wchar_t* BUTTON_CLASS = L"BUTTON";
35    const wchar_t* szWindowClass = L"EraserBootstrapper";
36
37    //Static variables
38    HINSTANCE hInstance = NULL;
39    HWND hWndParent = NULL;
40    HWND hWndStatusLbl = NULL;
41    HWND hWndProgressBar = NULL;
42    HWND hWndCancelBtn = NULL;
43
44    bool              InitInstance(HINSTANCE hInstance, HWND& hWnd);
45    void              SetWindowFont(HWND hWnd);
46    LRESULT __stdcall WndProc(HWND, UINT, WPARAM, LPARAM);
47
48    /// Creates a temporary directory with the given name. The directory and files in it
49    /// are deleted when this object is destroyed.
50    class TempDir
51    {
52    public:
53        /// Constructor.
54        ///
55        /// \param[in] dirName The path to the directory. This directory will be created.
56        TempDir(std::wstring dirName)
57            : DirName(dirName)
58        {
59            if (!CreateDirectoryW(dirName.c_str(), NULL))
60                throw GetErrorMessage(GetLastError());
61        }
62
63        ~TempDir()
64        {
65            //Clean up the files in the directory.
66
67
68            RemoveDirectoryW(DirName.c_str());
69        }
70
71    private:
72        std::wstring DirName;
73    };
74
75    /// Registers the main window class and creates it.
76    bool InitInstance(HINSTANCE hInstance, HWND& hWnd)
77    {
78        WNDCLASSEX wcex;
79        ::ZeroMemory(&wcex, sizeof(wcex));
80
81        wcex.cbSize         = sizeof(WNDCLASSEX);
82        wcex.style          = CS_HREDRAW | CS_VREDRAW;
83        wcex.lpfnWndProc    = WndProc;
84        wcex.cbClsExtra     = 0;
85        wcex.cbWndExtra     = 0;
86        wcex.hInstance      = hInstance;
87        wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(BOOTSTRAPPER_ICON));
88        wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
89        wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
90        wcex.lpszClassName  = szWindowClass;
91        wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(BOOTSTRAPPER_ICON));
92        RegisterClassExW(&wcex);
93        InitCommonControls();
94
95        //Create the window
96        hWnd = CreateWindowW(szWindowClass, L"Eraser Setup", WS_CAPTION | WS_SYSMENU,
97            CW_USEDEFAULT, 0, 300, 130, NULL, NULL, hInstance, NULL);
98
99        if (!hWnd)
100            return false;
101
102        //Set default settings (font)
103        SetWindowFont(hWnd);
104        return true;
105    }
106
107    /// Helper function to set the window font for created windows to the system default.
108    void SetWindowFont(HWND hWnd)
109    {
110        HFONT hWndFont = NULL;
111        if (!hWndFont)
112        {
113            NONCLIENTMETRICS ncm;
114            ::ZeroMemory(&ncm, sizeof(ncm));
115            ncm.cbSize = sizeof(ncm);
116
117            if ( !::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0) )
118            {
119#if WINVER >= 0x0600
120                // a new field has been added to NONCLIENTMETRICS under Vista, so
121                // the call to SystemParametersInfo() fails if we use the struct
122                // size incorporating this new value on an older system -- retry
123                // without it
124                ncm.cbSize -= sizeof(int);
125                if ( !::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0) )
126#endif
127                    return;
128            }
129
130            hWndFont = CreateFontIndirectW(&ncm.lfMessageFont);
131        }
132
133        SendMessage(hWnd, WM_SETFONT, (WPARAM)hWndFont, MAKELPARAM(TRUE, 0));
134    }
135
136    /// Processes messages for the main window.
137    ///
138    /// Current messages processed:
139    /// WM_COMMAND  - process the application menu
140    /// WM_PAINT    - Paint the main window
141    /// WM_DESTROY  - post a quit message and return
142    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
143    {
144        switch (message)
145        {
146        case WM_COMMAND:
147        {
148            /*int wmId    = LOWORD(wParam);
149            switch (wmId)
150            {
151            default:
152               
153            }*/
154            return DefWindowProc(hWnd, message, wParam, lParam);
155        }
156
157        case WM_PAINT:
158        {
159            PAINTSTRUCT ps;
160            HDC hdc = BeginPaint(hWnd, &ps);
161
162            // TODO: Add any drawing code here...
163            EndPaint(hWnd, &ps);
164            break;
165        }
166
167        case WM_DESTROY:
168            PostQuitMessage(0);
169            break;
170
171        default:
172            return DefWindowProc(hWnd, message, wParam, lParam);
173        }
174
175        return 0;
176    }
177}
178
179int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/,
180                       LPTSTR /*lpCmdLine*/, int nCmdShow)
181{
182    //Create the parent window and the child controls
183    ::hInstance = hInstance;
184    if (!InitInstance(hInstance, hWndParent))
185        return false;
186
187    HWND hWndPanel = CreateWindowExW(0, STATIC_CLASS, NULL, WS_CHILD | WS_VISIBLE,
188        0, 0, 294, 104, hWndParent, NULL, hInstance, NULL);
189    hWndStatusLbl = CreateWindowExW(0, STATIC_CLASS, L"Extracting setup files...",
190        WS_CHILD | WS_VISIBLE, 13, 38, 270, 19, hWndPanel, NULL, hInstance, NULL);
191    hWndProgressBar = CreateWindowExW(0, PROGRESS_CLASS, NULL,
192        WS_CHILD | WS_VISIBLE | PBS_SMOOTH, 13, 13, 270, 24, hWndPanel, NULL,
193        hInstance, NULL);
194    hWndCancelBtn = CreateWindowExW(0, BUTTON_CLASS, L"Cancel", WS_TABSTOP |
195        WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 193, 65, 90, 23, hWndPanel, NULL,
196        hInstance, NULL);
197    if (!hWndPanel || !hWndStatusLbl || !hWndProgressBar || !hWndCancelBtn)
198        return false;
199
200    SetWindowFont(hWndPanel);
201    SetWindowFont(hWndStatusLbl);
202    SetWindowFont(hWndProgressBar);
203    SetWindowFont(hWndCancelBtn);
204    SendMessage(hWndProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 1000));
205
206    ShowWindow(hWndParent, nCmdShow);
207    UpdateWindow(hWndParent);
208
209    //OK, now we do the hard work. Create a folder to place our payload into
210    wchar_t tempPath[MAX_PATH];
211    DWORD result = GetTempPathW(sizeof(tempPath) / sizeof(tempPath[0]), tempPath);
212    if (!result)
213        throw GetErrorMessage(GetLastError());
214
215    std::wstring tempDir(tempPath, result);
216    if (std::wstring(L"\\/").find(tempDir[tempDir.length() - 1]) == std::wstring::npos)
217        tempDir += L"\\";
218    tempDir += L"eraserInstallBootstrapper\\";
219    TempDir dir(tempDir);
220    ExtractTempFiles(tempDir);
221
222    //Install the .NET framework
223    if (!HasNetFramework())
224        InstallNetFramework(tempDir);
225
226    //Then install Eraser!
227    InstallEraser();
228
229    //Main message loop
230    MSG msg;
231    while (GetMessage(&msg, NULL, 0, 0))
232    {
233        TranslateMessage(&msg);
234        DispatchMessage(&msg);
235    }
236
237    return (int) msg.wParam;
238}
239
240HWND GetTopWindow()
241{
242    return hWndParent;
243}
244
245void SetProgress(float progress)
246{
247    SetWindowLong(hWndProgressBar, GWL_STYLE,
248        GetWindowLong(hWndProgressBar, GWL_STYLE) & (~PBS_MARQUEE));
249    SendMessage(hWndProgressBar, PBM_SETPOS, (int)(progress * 1000), 0);
250}
251
252void SetProgressIndeterminate()
253{
254    SetWindowLong(hWndProgressBar, GWL_STYLE,
255        GetWindowLong(hWndProgressBar, GWL_STYLE) | PBS_MARQUEE);
256    SendMessage(hWndProgressBar, PBM_SETMARQUEE, true, 100);
257}
258
259void SetMessage(std::wstring message)
260{
261}
262
263void Yield()
264{
265    MSG msg;
266    while (PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) && msg.message != WM_QUIT)
267    {
268        TranslateMessage(&msg);
269        DispatchMessage(&msg);
270    }
271}
272
273std::wstring GetApplicationPath()
274{
275    wchar_t filePath[MAX_PATH];
276    DWORD result = GetModuleFileNameW(hInstance, filePath,
277        sizeof(filePath) / sizeof(filePath[0]));
278
279    if (result == 0)
280        throw GetErrorMessage(GetLastError());
281    return std::wstring(filePath, result);
282}
283
284std::wstring GetErrorMessage(DWORD lastError)
285{
286    unsigned lastBufferSize = 128;
287    wchar_t* buffer = NULL;
288    DWORD result = 0;
289
290    while (result == 0 || result == lastBufferSize - 1)
291    {
292        delete[] buffer;
293        buffer = new wchar_t[lastBufferSize *= 2];
294        result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, lastError, 0, buffer,
295            lastBufferSize, NULL);
296    }
297
298    std::wstring message(buffer);
299    delete[] buffer;
300    return message;
301}
Note: See TracBrowser for help on using the repository browser.