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

Revision 538, 8.2 KB checked in by lowjoel, 6 years ago (diff)

Reshuffle all the global functions into classes. It is way neater now.

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