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

Revision 539, 8.4 KB checked in by lowjoel, 6 years ago (diff)

Further extend the Application class.

  • 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
40    bool              InitInstance(HINSTANCE hInstance, HWND& hWnd);
41    void              SetWindowFont(HWND hWnd);
42    LRESULT __stdcall WndProc(HWND, UINT, WPARAM, LPARAM);
43
44    /// Creates a temporary directory with the given name. The directory and files in it
45    /// are deleted when this object is destroyed.
46    class TempDir
47    {
48    public:
49        /// Constructor.
50        ///
51        /// \param[in] dirName The path to the directory. This directory will be created.
52        TempDir(std::wstring dirName)
53            : DirName(dirName)
54        {
55            if (std::wstring(L"\\/").find(dirName[dirName.length() - 1]) == std::wstring::npos)
56                dirName += L"\\";
57
58            if (!CreateDirectoryW(dirName.c_str(), NULL))
59                throw GetErrorMessage(GetLastError());
60        }
61
62        ~TempDir()
63        {
64            //Clean up the files in the directory.
65            WIN32_FIND_DATAW findData;
66            ZeroMemory(&findData, sizeof(findData));
67            HANDLE findHandle = FindFirstFileW((DirName + L"*").c_str(), &findData);
68            if (findHandle == INVALID_HANDLE_VALUE)
69                throw GetErrorMessage(GetLastError());
70
71            //Delete!
72            do
73                DeleteFileW((DirName + findData.cFileName).c_str());
74            while (FindNextFileW(findHandle, &findData));
75
76            //Clean up.
77            FindClose(findHandle);
78            RemoveDirectoryW(DirName.c_str());
79        }
80
81    private:
82        std::wstring DirName;
83    };
84
85   
86   
87
88    /// Helper function to set the window font for created windows to the system default.
89    void SetWindowFont(HWND hWnd)
90    {
91        HFONT hWndFont = NULL;
92        if (!hWndFont)
93        {
94            NONCLIENTMETRICS ncm;
95            ::ZeroMemory(&ncm, sizeof(ncm));
96            ncm.cbSize = sizeof(ncm);
97
98            if ( !::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0) )
99            {
100#if WINVER >= 0x0600
101                // a new field has been added to NONCLIENTMETRICS under Vista, so
102                // the call to SystemParametersInfo() fails if we use the struct
103                // size incorporating this new value on an older system -- retry
104                // without it
105                ncm.cbSize -= sizeof(int);
106                if ( !::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0) )
107#endif
108                    return;
109            }
110
111            hWndFont = CreateFontIndirectW(&ncm.lfMessageFont);
112        }
113
114        SendMessage(hWnd, WM_SETFONT, (WPARAM)hWndFont, MAKELPARAM(TRUE, 0));
115    }
116
117    /// Processes messages for the main window.
118    ///
119    /// Current messages processed:
120    /// WM_COMMAND  - process the application menu
121    /// WM_PAINT    - Paint the main window
122    /// WM_DESTROY  - post a quit message and return
123    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
124    {
125        switch (message)
126        {
127        case WM_COMMAND:
128        {
129            /*int wmId    = LOWORD(wParam);
130            switch (wmId)
131            {
132            default:
133               
134            }*/
135            return DefWindowProc(hWnd, message, wParam, lParam);
136        }
137
138        case WM_DESTROY:
139            PostQuitMessage(0);
140            break;
141
142        default:
143            return DefWindowProc(hWnd, message, wParam, lParam);
144        }
145
146        return 0;
147    }
148}
149
150int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/,
151                       LPTSTR /*lpCmdLine*/, int /*nCmdShow*/)
152{
153    //Create the parent window and the child controls
154    ::hInstance = hInstance;
155    Application::Get();
156
157    try
158    {
159        //OK, now we do the hard work. Create a folder to place our payload into
160        wchar_t tempPath[MAX_PATH];
161        DWORD result = GetTempPathW(sizeof(tempPath) / sizeof(tempPath[0]), tempPath);
162        if (!result)
163            throw GetErrorMessage(GetLastError());
164
165        std::wstring tempDir(tempPath, result);
166        if (std::wstring(L"\\/").find(tempDir[tempDir.length() - 1]) == std::wstring::npos)
167            tempDir += L"\\";
168        tempDir += L"eraserInstallBootstrapper\\";
169        TempDir dir(tempDir);
170        ExtractTempFiles(tempDir);
171
172        //Install the .NET framework
173        if (!HasNetFramework())
174            InstallNetFramework(tempDir);
175
176        //Then install Eraser!
177        InstallEraser(tempDir);
178    }
179    catch (const std::wstring& e)
180    {
181        MessageBoxW(Application::Get().GetTopWindow().GetHandle(), e.c_str(),
182            L"Eraser Setup", MB_OK | MB_ICONERROR);
183    }
184
185    return 0;
186}
187
188Application::Application()
189{
190    MainWin.Create();
191}
192
193Application& Application::Get()
194{
195    static Application Instance;
196    return Instance;
197}
198
199MainWindow& Application::GetTopWindow()
200{
201    return MainWin;
202}
203
204void Application::Yield()
205{
206    MSG msg;
207    while (PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) && msg.message != WM_QUIT)
208    {
209        if (GetMessageW(&msg, NULL, 0, 0) == 0)
210            return;
211
212        TranslateMessage(&msg);
213        DispatchMessage(&msg);
214    }
215}
216
217std::wstring Application::GetPath()
218{
219    wchar_t filePath[MAX_PATH];
220    DWORD result = GetModuleFileNameW(hInstance, filePath,
221        sizeof(filePath) / sizeof(filePath[0]));
222
223    if (result == 0)
224        throw GetErrorMessage(GetLastError());
225    return std::wstring(filePath, result);
226}
227
228bool MainWindow::Create()
229{
230    if (!InitInstance())
231        return false;
232
233    HWND hWndPanel = CreateWindowExW(0, STATIC_CLASS, NULL, WS_CHILD | WS_VISIBLE,
234        0, 0, 294, 104, hWnd, NULL, hInstance, NULL);
235    hWndStatusLbl = CreateWindowExW(0, STATIC_CLASS, L"Extracting setup files...",
236        WS_CHILD | WS_VISIBLE, 13, 38, 270, 19, hWndPanel, NULL, hInstance, NULL);
237    hWndProgressBar = CreateWindowExW(0, PROGRESS_CLASS, NULL,
238        WS_CHILD | WS_VISIBLE | PBS_SMOOTH, 13, 13, 270, 24, hWndPanel, NULL,
239        hInstance, NULL);
240    hWndCancelBtn = CreateWindowExW(0, BUTTON_CLASS, L"Cancel", WS_TABSTOP |
241        WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 193, 65, 90, 23, hWndPanel, NULL,
242        hInstance, NULL);
243    if (!hWndPanel || !hWndStatusLbl || !hWndProgressBar || !hWndCancelBtn)
244        return false;
245
246    SetWindowFont(hWndPanel);
247    SetWindowFont(hWndStatusLbl);
248    SetWindowFont(hWndProgressBar);
249    SetWindowFont(hWndCancelBtn);
250    SendMessage(hWndProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 1000));
251
252    ShowWindow(hWnd, SW_SHOWDEFAULT);
253    UpdateWindow(hWnd);
254    return true;
255}
256
257bool MainWindow::InitInstance()
258{
259    WNDCLASSEX wcex;
260    ::ZeroMemory(&wcex, sizeof(wcex));
261
262    wcex.cbSize         = sizeof(WNDCLASSEX);
263    wcex.style          = CS_HREDRAW | CS_VREDRAW;
264    wcex.lpfnWndProc    = WndProc;
265    wcex.cbClsExtra     = 0;
266    wcex.cbWndExtra     = 0;
267    wcex.hInstance      = hInstance;
268    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(BOOTSTRAPPER_ICON));
269    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
270    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
271    wcex.lpszClassName  = szWindowClass;
272    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(BOOTSTRAPPER_ICON));
273    RegisterClassExW(&wcex);
274    InitCommonControls();
275
276    //Create the window
277    hWnd = CreateWindowW(szWindowClass, L"Eraser Setup", WS_CAPTION | WS_SYSMENU,
278        CW_USEDEFAULT, 0, 300, 130, NULL, NULL, hInstance, NULL);
279
280    if (!hWnd)
281        return false;
282
283    //Set default settings (font)
284    SetWindowFont(hWnd);
285    return true;
286}
287
288void MainWindow::SetProgress(float progress)
289{
290    SetWindowLong(hWndProgressBar, GWL_STYLE,
291        GetWindowLong(hWndProgressBar, GWL_STYLE) & (~PBS_MARQUEE));
292    SendMessage(hWndProgressBar, PBM_SETPOS, (int)(progress * 1000), 0);
293}
294
295void MainWindow::SetProgressIndeterminate()
296{
297    SetWindowLong(hWndProgressBar, GWL_STYLE,
298        GetWindowLong(hWndProgressBar, GWL_STYLE) | PBS_MARQUEE);
299    SendMessage(hWndProgressBar, PBM_SETMARQUEE, true, 100);
300}
301
302void MainWindow::SetMessage(std::wstring message)
303{
304}
305
306std::wstring GetErrorMessage(DWORD lastError)
307{
308    unsigned lastBufferSize = 128;
309    wchar_t* buffer = NULL;
310    DWORD result = 0;
311
312    while (result == 0 || result == lastBufferSize - 1)
313    {
314        delete[] buffer;
315        buffer = new wchar_t[lastBufferSize *= 2];
316        result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, lastError, 0, buffer,
317            lastBufferSize, NULL);
318    }
319
320    std::wstring message(buffer);
321    delete[] buffer;
322    return message;
323}
Note: See TracBrowser for help on using the repository browser.