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

Revision 537, 8.3 KB checked in by lowjoel, 6 years ago (diff)

-Fixed Yield
-Fixed the TempDir? destructor
-Added exception handlers to Main, since it can't throw
-Few warning fixes

  • 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 (std::wstring(L"\\/").find(dirName[dirName.length() - 1]) == std::wstring::npos)
60                dirName += L"\\";
61
62            if (!CreateDirectoryW(dirName.c_str(), NULL))
63                throw GetErrorMessage(GetLastError());
64        }
65
66        ~TempDir()
67        {
68            //Clean up the files in the directory.
69            WIN32_FIND_DATAW findData;
70            ZeroMemory(&findData, sizeof(findData));
71            HANDLE findHandle = FindFirstFileW((DirName + L"*").c_str(), &findData);
72            if (findHandle == INVALID_HANDLE_VALUE)
73                throw GetErrorMessage(GetLastError());
74
75            //Delete!
76            do
77                DeleteFileW((DirName + findData.cFileName).c_str());
78            while (FindNextFileW(findHandle, &findData));
79
80            //Clean up.
81            FindClose(findHandle);
82            RemoveDirectoryW(DirName.c_str());
83        }
84
85    private:
86        std::wstring DirName;
87    };
88
89    /// Registers the main window class and creates it.
90    bool InitInstance(HINSTANCE hInstance, HWND& hWnd)
91    {
92        WNDCLASSEX wcex;
93        ::ZeroMemory(&wcex, sizeof(wcex));
94
95        wcex.cbSize         = sizeof(WNDCLASSEX);
96        wcex.style          = CS_HREDRAW | CS_VREDRAW;
97        wcex.lpfnWndProc    = WndProc;
98        wcex.cbClsExtra     = 0;
99        wcex.cbWndExtra     = 0;
100        wcex.hInstance      = hInstance;
101        wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(BOOTSTRAPPER_ICON));
102        wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
103        wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
104        wcex.lpszClassName  = szWindowClass;
105        wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(BOOTSTRAPPER_ICON));
106        RegisterClassExW(&wcex);
107        InitCommonControls();
108
109        //Create the window
110        hWnd = CreateWindowW(szWindowClass, L"Eraser Setup", WS_CAPTION | WS_SYSMENU,
111            CW_USEDEFAULT, 0, 300, 130, NULL, NULL, hInstance, NULL);
112
113        if (!hWnd)
114            return false;
115
116        //Set default settings (font)
117        SetWindowFont(hWnd);
118        return true;
119    }
120
121    /// Helper function to set the window font for created windows to the system default.
122    void SetWindowFont(HWND hWnd)
123    {
124        HFONT hWndFont = NULL;
125        if (!hWndFont)
126        {
127            NONCLIENTMETRICS ncm;
128            ::ZeroMemory(&ncm, sizeof(ncm));
129            ncm.cbSize = sizeof(ncm);
130
131            if ( !::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0) )
132            {
133#if WINVER >= 0x0600
134                // a new field has been added to NONCLIENTMETRICS under Vista, so
135                // the call to SystemParametersInfo() fails if we use the struct
136                // size incorporating this new value on an older system -- retry
137                // without it
138                ncm.cbSize -= sizeof(int);
139                if ( !::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0) )
140#endif
141                    return;
142            }
143
144            hWndFont = CreateFontIndirectW(&ncm.lfMessageFont);
145        }
146
147        SendMessage(hWnd, WM_SETFONT, (WPARAM)hWndFont, MAKELPARAM(TRUE, 0));
148    }
149
150    /// Processes messages for the main window.
151    ///
152    /// Current messages processed:
153    /// WM_COMMAND  - process the application menu
154    /// WM_PAINT    - Paint the main window
155    /// WM_DESTROY  - post a quit message and return
156    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
157    {
158        switch (message)
159        {
160        case WM_COMMAND:
161        {
162            /*int wmId    = LOWORD(wParam);
163            switch (wmId)
164            {
165            default:
166               
167            }*/
168            return DefWindowProc(hWnd, message, wParam, lParam);
169        }
170
171        case WM_DESTROY:
172            PostQuitMessage(0);
173            break;
174
175        default:
176            return DefWindowProc(hWnd, message, wParam, lParam);
177        }
178
179        return 0;
180    }
181}
182
183int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/,
184                       LPTSTR /*lpCmdLine*/, int nCmdShow)
185{
186    //Create the parent window and the child controls
187    ::hInstance = hInstance;
188    if (!InitInstance(hInstance, hWndParent))
189        return false;
190
191    HWND hWndPanel = CreateWindowExW(0, STATIC_CLASS, NULL, WS_CHILD | WS_VISIBLE,
192        0, 0, 294, 104, hWndParent, NULL, hInstance, NULL);
193    hWndStatusLbl = CreateWindowExW(0, STATIC_CLASS, L"Extracting setup files...",
194        WS_CHILD | WS_VISIBLE, 13, 38, 270, 19, hWndPanel, NULL, hInstance, NULL);
195    hWndProgressBar = CreateWindowExW(0, PROGRESS_CLASS, NULL,
196        WS_CHILD | WS_VISIBLE | PBS_SMOOTH, 13, 13, 270, 24, hWndPanel, NULL,
197        hInstance, NULL);
198    hWndCancelBtn = CreateWindowExW(0, BUTTON_CLASS, L"Cancel", WS_TABSTOP |
199        WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 193, 65, 90, 23, hWndPanel, NULL,
200        hInstance, NULL);
201    if (!hWndPanel || !hWndStatusLbl || !hWndProgressBar || !hWndCancelBtn)
202        return false;
203
204    SetWindowFont(hWndPanel);
205    SetWindowFont(hWndStatusLbl);
206    SetWindowFont(hWndProgressBar);
207    SetWindowFont(hWndCancelBtn);
208    SendMessage(hWndProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 1000));
209
210    ShowWindow(hWndParent, nCmdShow);
211    UpdateWindow(hWndParent);
212
213    try
214    {
215        //OK, now we do the hard work. Create a folder to place our payload into
216        wchar_t tempPath[MAX_PATH];
217        DWORD result = GetTempPathW(sizeof(tempPath) / sizeof(tempPath[0]), tempPath);
218        if (!result)
219            throw GetErrorMessage(GetLastError());
220
221        std::wstring tempDir(tempPath, result);
222        if (std::wstring(L"\\/").find(tempDir[tempDir.length() - 1]) == std::wstring::npos)
223            tempDir += L"\\";
224        tempDir += L"eraserInstallBootstrapper\\";
225        TempDir dir(tempDir);
226        ExtractTempFiles(tempDir);
227
228        //Install the .NET framework
229        if (!HasNetFramework())
230            InstallNetFramework(tempDir);
231
232        //Then install Eraser!
233        InstallEraser(tempDir);
234    }
235    catch (const std::wstring& e)
236    {
237        MessageBoxW(GetTopWindow(), e.c_str(), L"Eraser Setup", MB_OK | MB_ICONERROR);
238    }
239
240    return 0;
241}
242
243HWND GetTopWindow()
244{
245    return hWndParent;
246}
247
248void 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 SetProgressIndeterminate()
256{
257    SetWindowLong(hWndProgressBar, GWL_STYLE,
258        GetWindowLong(hWndProgressBar, GWL_STYLE) | PBS_MARQUEE);
259    SendMessage(hWndProgressBar, PBM_SETMARQUEE, true, 100);
260}
261
262void SetMessage(std::wstring message)
263{
264}
265
266void 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.