mirror of
https://github.com/chibicitiberiu/rainmeter-studio.git
synced 2024-02-24 04:33:31 +00:00
507 lines
12 KiB
C++
507 lines
12 KiB
C++
/*
|
|
Copyright (C) 2011 Birunthan Mohanathas
|
|
|
|
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "StdAfx.h"
|
|
#include "Application.h"
|
|
#include "DialogBackup.h"
|
|
#include "DialogInstall.h"
|
|
#include "resource.h"
|
|
#include "../Version.h"
|
|
|
|
#define WM_DELAYED_CLOSE WM_APP + 0
|
|
|
|
extern GlobalData g_Data;
|
|
|
|
CDialogBackup* CDialogBackup::c_Dialog = NULL;
|
|
|
|
/*
|
|
** Constructor.
|
|
**
|
|
*/
|
|
CDialogBackup::CDialogBackup(HWND wnd) : CDialog(wnd),
|
|
m_TabBackup(wnd),
|
|
m_ThreadHandle(),
|
|
m_ZipFile(),
|
|
m_WriteBuffer()
|
|
{
|
|
}
|
|
|
|
/*
|
|
** Destructor.
|
|
**
|
|
*/
|
|
CDialogBackup::~CDialogBackup()
|
|
{
|
|
}
|
|
|
|
/*
|
|
** Creates the dialog.
|
|
**
|
|
*/
|
|
void CDialogBackup::Create(HINSTANCE hInstance, LPWSTR lpCmdLine)
|
|
{
|
|
HANDLE hMutex;
|
|
if (IsRunning(L"RainmeterBackup", &hMutex))
|
|
{
|
|
HWND hwnd = FindWindow(L"#32770", L"Backup Rainmeter");
|
|
SetForegroundWindow(hwnd);
|
|
}
|
|
else
|
|
{
|
|
DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_BACKUP_DIALOG), NULL, (DLGPROC)DlgProc, (LPARAM)lpCmdLine);
|
|
ReleaseMutex(hMutex);
|
|
}
|
|
}
|
|
|
|
CDialog::CTab& CDialogBackup::GetActiveTab()
|
|
{
|
|
return m_TabBackup;
|
|
}
|
|
|
|
/*
|
|
** Dialog procedure for the About dialog.
|
|
**
|
|
*/
|
|
INT_PTR CALLBACK CDialogBackup::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (!c_Dialog)
|
|
{
|
|
if (uMsg == WM_INITDIALOG)
|
|
{
|
|
c_Dialog = new CDialogBackup(hWnd);
|
|
return c_Dialog->OnInitDialog(wParam, lParam);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_COMMAND:
|
|
return c_Dialog->OnCommand(wParam, lParam);
|
|
|
|
case WM_CLOSE:
|
|
EndDialog(hWnd, 0);
|
|
return TRUE;
|
|
|
|
case WM_DESTROY:
|
|
delete c_Dialog;
|
|
c_Dialog = NULL;
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
INT_PTR CDialogBackup::OnInitDialog(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HICON hIcon = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_SKININSTALLER), IMAGE_ICON, 16, 16, LR_SHARED);
|
|
SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
|
|
|
|
if (GetOSPlatform() >= OSPLATFORM_VISTA)
|
|
{
|
|
SetDialogFont();
|
|
}
|
|
|
|
HWND item = GetDlgItem(m_Window, IDC_BACKUP_TAB);
|
|
TCITEM tci = {0};
|
|
tci.mask = TCIF_TEXT;
|
|
tci.pszText = L"Backup";
|
|
TabCtrl_InsertItem(item, 0, &tci);
|
|
|
|
m_TabBackup.Activate();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT_PTR CDialogBackup::OnCommand(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_BACKUP_BACKUP_BUTTON:
|
|
StartBackup();
|
|
break;
|
|
|
|
case IDCLOSE:
|
|
if (m_ThreadHandle)
|
|
{
|
|
if (IDYES != MessageBox(NULL, L"The backup is still in progress. Are you sure you want to cancel?", NULL, MB_YESNO | MB_TOPMOST | MB_ICONHAND))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
EndDialog(m_Window, 0);
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CDialogBackup::StartBackup()
|
|
{
|
|
if (!CloseRainmeterIfActive())
|
|
{
|
|
MessageBox(m_Window, L"Unable to close Rainmeter.", L"Backup Rainmeter", MB_ERROR);
|
|
}
|
|
else
|
|
{
|
|
HWND item = GetDlgItem(m_Window, IDC_BACKUP_BACKUP_BUTTON);
|
|
EnableWindow(item, FALSE);
|
|
|
|
item = GetDlgItem(m_TabBackup.GetWindow(), IDC_BACKUP_FILE_TEXT);
|
|
ShowWindow(item, SW_HIDE);
|
|
|
|
item = GetDlgItem(m_TabBackup.GetWindow(), IDC_BACKUP_BROWSE_BUTTON);
|
|
ShowWindow(item, SW_HIDE);
|
|
|
|
item = GetDlgItem(m_TabBackup.GetWindow(), IDC_BACKUP_INPROGRESS_TEXT);
|
|
ShowWindow(item, SW_SHOWNORMAL);
|
|
|
|
item = GetDlgItem(m_TabBackup.GetWindow(), IDC_BACKUP_PROGRESS);
|
|
ShowWindow(item, SW_SHOWNORMAL);
|
|
SendMessage(item, PBM_SETMARQUEE, (WPARAM)TRUE, 0);
|
|
|
|
m_ThreadHandle = (HANDLE)_beginthreadex(NULL, 0, BackupThreadProc, this, 0, NULL);
|
|
if (!m_ThreadHandle)
|
|
{
|
|
MessageBox(m_Window, L"Unable to start backup.", L"Backup Rainmeter", MB_ERROR);
|
|
EndDialog(m_Window, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CDialogBackup::CreateBackup()
|
|
{
|
|
m_WriteBuffer = new char[c_WriteBufferSize];
|
|
|
|
std::wstring addonsPath = g_Data.settingsPath + L"Addons";
|
|
std::wstring pluginsPath = g_Data.settingsPath + L"Plugins";
|
|
std::wstring themesPath = g_Data.settingsPath + L"Themes";
|
|
std::wstring skinsPath = g_Data.skinsPath;
|
|
|
|
// Remove trailing slash if needed
|
|
if (skinsPath.back() == L'\\') skinsPath.resize(skinsPath.length() - 1);
|
|
|
|
m_ZipFile = zipOpen(ConvertToAscii(m_TargetFile.c_str()).c_str(), 0);
|
|
if (!m_ZipFile)
|
|
{
|
|
MessageBox(NULL, L"Unable to access backup .rmskin file.", NULL, MB_OK | MB_TOPMOST);
|
|
return false;
|
|
}
|
|
|
|
// Create and add the options file
|
|
{
|
|
WCHAR tempFile[MAX_PATH];
|
|
GetTempPath(MAX_PATH, tempFile);
|
|
GetTempFileName(tempFile, L"ini", 0, tempFile);
|
|
|
|
WCHAR userName[UNLEN + 1];
|
|
DWORD userNameSize = UNLEN + 1;
|
|
GetUserName(userName, &userNameSize);
|
|
|
|
WritePrivateProfileString(L"rmskin", L"Name", L"Backup", tempFile);
|
|
WritePrivateProfileString(L"rmskin", L"Author", userName, tempFile);
|
|
WritePrivateProfileString(L"rmskin", L"Version", m_BackupTime.c_str(), tempFile);
|
|
WritePrivateProfileString(L"rmskin", L"MinimumRainmeter", L"2.3", tempFile);
|
|
AddFileToBackup(ConvertToAscii(tempFile).c_str(), "RMSKIN.ini");
|
|
DeleteFile(tempFile);
|
|
}
|
|
|
|
if ((_waccess(addonsPath.c_str(), 0) == 0 && !AddFolderToBackup(addonsPath, L"", "Addons", true)) ||
|
|
(_waccess(skinsPath.c_str(), 0) == 0 && !AddFolderToBackup(skinsPath, L"", "Skins", true)) ||
|
|
(_waccess(themesPath.c_str(), 0) == 0 && !AddFolderToBackup(themesPath, L"", "Themes", true)) ||
|
|
#ifdef _WIN64
|
|
(_waccess(pluginsPath.c_str(), 0) == 0 && !AddFolderToBackup(pluginsPath, L"", "Plugins\\64bit", false)))
|
|
#else
|
|
(_waccess(pluginsPath.c_str(), 0) == 0 && !AddFolderToBackup(pluginsPath, L"", "Plugins\\32bit", false)))
|
|
#endif
|
|
{
|
|
// Error message already displayed in AddFolderToBackup()
|
|
return false;
|
|
}
|
|
|
|
if (zipClose(m_ZipFile, NULL) != ZIP_OK)
|
|
{
|
|
MessageBox(NULL, L"Unable to access backup .rmskin file.", NULL, MB_OK | MB_TOPMOST);
|
|
return false;
|
|
}
|
|
|
|
// Add footer
|
|
FILE* file = _wfopen(m_TargetFile.c_str(), L"r+b");
|
|
if (file)
|
|
{
|
|
fseek(file, 0, SEEK_END);
|
|
CDialogInstall::PackageFooter footer = { _ftelli64(file), CDialogInstall::PackageFlag::Backup, "RMSKIN" };
|
|
fwrite(&footer, sizeof(footer), 1, file);
|
|
fclose(file);
|
|
}
|
|
|
|
delete m_WriteBuffer;
|
|
return true;
|
|
}
|
|
|
|
unsigned __stdcall CDialogBackup::BackupThreadProc(void* pParam)
|
|
{
|
|
CDialogBackup* dialog = (CDialogBackup*)pParam;
|
|
|
|
if (dialog->CreateBackup())
|
|
{
|
|
// Stop the progress bar
|
|
HWND item = GetDlgItem(dialog->m_Window, IDC_BACKUP_PROGRESS);
|
|
SendMessage(item, PBM_SETMARQUEE, (WPARAM)FALSE, 0);
|
|
|
|
FlashWindow(dialog->m_Window, TRUE);
|
|
MessageBox(dialog->m_Window, L"The backup is complete.", L"Backup Rainmeter", MB_OK | MB_ICONINFORMATION);
|
|
}
|
|
else
|
|
{
|
|
DeleteFile(dialog->m_TargetFile.c_str());
|
|
}
|
|
|
|
EndDialog(dialog->m_Window, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
uLong filetime(const char *f, tm_zip *tmzip, uLong *dt)
|
|
{
|
|
int ret = 0;
|
|
{
|
|
FILETIME ftLocal;
|
|
HANDLE hFind;
|
|
WIN32_FIND_DATAA ff32;
|
|
|
|
hFind = FindFirstFileA(f, &ff32);
|
|
if (hFind != INVALID_HANDLE_VALUE)
|
|
{
|
|
FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
|
|
FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
|
|
FindClose(hFind);
|
|
ret = 1;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool CDialogBackup::AddFileToBackup(const char* realPath, const char* zipPath)
|
|
{
|
|
zip_fileinfo zi = {0};
|
|
filetime(realPath, &zi.tmz_date, &zi.dosDate);
|
|
|
|
int err = zipOpenNewFileInZip(m_ZipFile, zipPath, &zi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION);
|
|
if (err != ZIP_OK) return false;
|
|
|
|
FILE* fin = fopen(realPath, "rb");
|
|
if (fin)
|
|
{
|
|
size_t readSize;
|
|
do
|
|
{
|
|
//err = ZIP_OK;
|
|
readSize = fread(m_WriteBuffer, 1, c_WriteBufferSize, fin);
|
|
if (readSize < c_WriteBufferSize && feof(fin) == 0)
|
|
{
|
|
err = ZIP_ERRNO;
|
|
}
|
|
else if (readSize > 0)
|
|
{
|
|
err = zipWriteInFileInZip(m_ZipFile, m_WriteBuffer, (UINT)readSize);
|
|
if (err < 0)
|
|
{
|
|
err = ZIP_ERRNO;
|
|
}
|
|
}
|
|
}
|
|
while ((err == ZIP_OK) && (readSize > 0));
|
|
|
|
fclose(fin);
|
|
}
|
|
else
|
|
{
|
|
err = ZIP_ERRNO;
|
|
}
|
|
|
|
if (zipCloseFileInZip(m_ZipFile) != ZIP_OK) return false;
|
|
|
|
return err == ZIP_OK;
|
|
}
|
|
|
|
bool CDialogBackup::AddFolderToBackup(const std::wstring& path, std::wstring base, char* zipPrefix, bool recursive)
|
|
{
|
|
std::wstring filter = path + base;
|
|
filter += L"\\";
|
|
std::string asciiBase = ConvertToAscii(filter.c_str());
|
|
filter += L"*";
|
|
|
|
WIN32_FIND_DATA fd;
|
|
HANDLE hFind = FindFirstFileEx(
|
|
filter.c_str(),
|
|
FindExInfoStandard,
|
|
&fd,
|
|
FindExSearchNameMatch,
|
|
NULL,
|
|
0);
|
|
|
|
if (hFind == INVALID_HANDLE_VALUE) return false;
|
|
|
|
bool ret = true;
|
|
|
|
std::list<std::wstring> folders;
|
|
do
|
|
{
|
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
if (wcscmp(L".", fd.cFileName) != 0 &&
|
|
wcscmp(L"..", fd.cFileName) != 0 &&
|
|
wcscmp(L"Backup", fd.cFileName) != 0 &&
|
|
wcscmp(L"@Backup", fd.cFileName) != 0)
|
|
{
|
|
folders.push_back(fd.cFileName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::string asciiFile = asciiBase + ConvertToAscii(fd.cFileName);
|
|
std::string zipFile = zipPrefix;
|
|
zipFile += &asciiFile[path.length()];
|
|
|
|
ret = AddFileToBackup(asciiFile.c_str(), zipFile.c_str());
|
|
if (!ret)
|
|
{
|
|
std::wstring error = L"Error including the file:\n\n";
|
|
error += path;
|
|
error += base;
|
|
error += L"\\";
|
|
error += fd.cFileName;
|
|
MessageBox(m_Window, error.c_str(), L"Backup Rainmeter", MB_OK | MB_TOPMOST);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
while (FindNextFile(hFind, &fd));
|
|
FindClose(hFind);
|
|
|
|
if (recursive && ret)
|
|
{
|
|
base += L"\\";
|
|
std::list<std::wstring>::const_iterator iter = folders.begin();
|
|
for ( ; iter != folders.end(); ++iter)
|
|
{
|
|
ret = AddFolderToBackup(path, base + (*iter), zipPrefix, recursive);
|
|
if (!ret) break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
//
|
|
// Backup tab
|
|
//
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
/*
|
|
** Constructor.
|
|
**
|
|
*/
|
|
CDialogBackup::CTabBackup::CTabBackup(HWND wnd) : CTab(GetModuleHandle(NULL), wnd, IDD_BACKUP_TABDIALOG, DlgProc)
|
|
{
|
|
}
|
|
|
|
/*
|
|
** Called when tab is displayed.
|
|
**
|
|
*/
|
|
void CDialogBackup::CTabBackup::Initialize()
|
|
{
|
|
m_Initialized = true;
|
|
|
|
WCHAR buffer[MAX_PATH];
|
|
HRESULT hr = SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL, SHGFP_TYPE_CURRENT, buffer);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
c_Dialog->m_TargetFile = buffer;
|
|
|
|
SYSTEMTIME lt;
|
|
GetLocalTime(<);
|
|
_snwprintf_s(buffer, _TRUNCATE, L"%04d.%02d.%02d-%02d.%02d", lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute);
|
|
|
|
c_Dialog->m_BackupTime = buffer;
|
|
|
|
c_Dialog->m_TargetFile += L"\\Backup-";
|
|
c_Dialog->m_TargetFile += c_Dialog->m_BackupTime;
|
|
c_Dialog->m_TargetFile += L".rmskin";
|
|
|
|
HWND item = GetDlgItem(m_Window, IDC_BACKUP_FILE_TEXT);
|
|
SetWindowText(item, c_Dialog->m_TargetFile.c_str());
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Dialog procedure for the Version tab.
|
|
**
|
|
*/
|
|
INT_PTR CALLBACK CDialogBackup::CTabBackup::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_COMMAND:
|
|
return c_Dialog->m_TabBackup.OnCommand(wParam, lParam);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
INT_PTR CDialogBackup::CTabBackup::OnCommand(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_BACKUP_BROWSE_BUTTON:
|
|
{
|
|
WCHAR buffer[MAX_PATH];
|
|
BROWSEINFO bi = {0};
|
|
bi.hwndOwner = c_Dialog->GetWindow();
|
|
bi.ulFlags = BIF_USENEWUI;
|
|
|
|
PIDLIST_ABSOLUTE pidl = SHBrowseForFolder(&bi);
|
|
if (pidl && SHGetPathFromIDList(pidl, buffer))
|
|
{
|
|
c_Dialog->m_TargetFile = buffer;
|
|
SYSTEMTIME lt;
|
|
GetLocalTime(<);
|
|
_snwprintf_s(buffer, _TRUNCATE, L"\\Backup-%02d.%02d.%02d-%02d.%02d.rmskin", lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute);
|
|
c_Dialog->m_TargetFile += buffer;
|
|
|
|
HWND item = GetDlgItem(m_Window, IDC_BACKUP_FILE_TEXT);
|
|
SetWindowText(item, c_Dialog->m_TargetFile.c_str());
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|