From d3ea6d2693b3e93c9dc62c75db2a9d5a67b9bce0 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Mon, 21 Jul 2014 14:45:09 +0000 Subject: PostMessage should be used to send messages to another thread git-svn-id: http://svn.miranda-ng.org/main/trunk@9904 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/PluginUpdater/src/DlgListNew.cpp | 976 ++++++++--------- plugins/PluginUpdater/src/DlgUpdate.cpp | 1526 +++++++++++++-------------- plugins/PluginUpdater/src/Notifications.cpp | 546 +++++----- 3 files changed, 1524 insertions(+), 1524 deletions(-) diff --git a/plugins/PluginUpdater/src/DlgListNew.cpp b/plugins/PluginUpdater/src/DlgListNew.cpp index bd1e0c122d..45cd3ddb64 100644 --- a/plugins/PluginUpdater/src/DlgListNew.cpp +++ b/plugins/PluginUpdater/src/DlgListNew.cpp @@ -1,489 +1,489 @@ -/* -Copyright (C) 2010 Mataes - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - -#include "common.h" - -static HWND hwndDialog; -HANDLE hListThread; - -static void SelectAll(HWND hDlg, bool bEnable) -{ - OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); - - for (int i=0; i < todo.getCount(); i++) { - ListView_SetCheckState(hwndList, i, bEnable); - todo[i].bEnabled = bEnable; - } -} - -static void ApplyDownloads(void *param) -{ - HWND hDlg = (HWND)param; - - ////////////////////////////////////////////////////////////////////////////////////// - // if we need to escalate priviledges, launch a atub - - if (!PrepareEscalation()) { - SendMessage(hDlg, WM_CLOSE, 0, 0); - return; - } - - ////////////////////////////////////////////////////////////////////////////////////// - // ok, let's unpack all zips - - AutoHandle pipe(hPipe); - HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); - OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - TCHAR tszBuff[2048], tszFileTemp[MAX_PATH], tszFileBack[MAX_PATH]; - - mir_sntprintf(tszFileBack, SIZEOF(tszFileBack), _T("%s\\Backups"), tszRoot); - SafeCreateDirectory(tszFileBack); - - mir_sntprintf(tszFileTemp, SIZEOF(tszFileTemp), _T("%s\\Temp"), tszRoot); - SafeCreateDirectory(tszFileTemp); - - HANDLE nlc = NULL; - for (int i=0; i < todo.getCount(); ++i) { - ListView_EnsureVisible(hwndList, i, FALSE); - if (!todo[i].bEnabled) { - ListView_SetItemText(hwndList, i, 2, TranslateT("Skipped.")); - continue; - } - - // download update - ListView_SetItemText(hwndList, i, 2, TranslateT("Downloading...")); - - FILEURL *pFileUrl = &todo[i].File; - if (!DownloadFile(pFileUrl, nlc)) { - ListView_SetItemText(hwndList, i, 2, TranslateT("Failed!")); - } - else - ListView_SetItemText(hwndList, i, 2, TranslateT("Succeeded.")); - } - Netlib_CloseHandle(nlc); - - if (todo.getCount() > 0) { - ShowPopup(0, LPGENT("Plugin Updater"), TranslateT("Download complete"), 2, 0); - - TCHAR *tszMirandaPath = Utils_ReplaceVarsT(_T("%miranda_path%")); - - for (int i = 0; i < todo.getCount(); i++) { - if (!todo[i].bEnabled) - continue; - - TCHAR tszBackFile[MAX_PATH]; - FILEINFO& p = todo[i]; - if (p.bDeleteOnly) { // we need only to backup the old file - TCHAR *ptszRelPath = p.tszNewName + _tcslen(tszMirandaPath) + 1; - mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, ptszRelPath); - BackupFile(p.tszNewName, tszBackFile); - continue; - } - - // if file name differs, we also need to backup the old file here - // otherwise it would be replaced by unzip - if ( _tcsicmp(p.tszOldName, p.tszNewName)) { - TCHAR tszSrcPath[MAX_PATH]; - mir_sntprintf(tszSrcPath, SIZEOF(tszSrcPath), _T("%s\\%s"), tszMirandaPath, p.tszOldName); - mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, p.tszOldName); - BackupFile(tszSrcPath, tszBackFile); - } - - if ( unzip(p.File.tszDiskPath, tszMirandaPath, tszFileBack,false)) - SafeDeleteFile(p.File.tszDiskPath); // remove .zip after successful update - } - } - - PopupDataText temp; - temp.Title = TranslateT("Plugin Updater"); - temp.Text = tszBuff; - lstrcpyn(tszBuff, TranslateT("Download complete. Do you want to go to plugins option page?"), SIZEOF(tszBuff)); - int rc = MessageBox(hDlg, temp.Text, temp.Title, MB_YESNO | MB_ICONQUESTION); - if (rc == IDYES) - CallFunctionAsync(OpenPluginOptions, 0); - - SendMessage(hDlg, WM_CLOSE, 0, 0); - return; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -static WNDPROC oldWndProc = NULL; - -static LRESULT CALLBACK PluginListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (msg == WM_LBUTTONDOWN) { - LVHITTESTINFO hi; - hi.pt.x = LOWORD(lParam); hi.pt.y = HIWORD(lParam); - ListView_SubItemHitTest(hwnd, &hi); - if (hi.iSubItem == 1) { - LVITEM lvi = {0}; - lvi.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_GROUPID; - lvi.stateMask = -1; - lvi.iItem = hi.iItem; - if (ListView_GetItem(hwnd, &lvi) && lvi.iGroupId == 1) { - FILEINFO *info = (FILEINFO *)lvi.lParam; - - TCHAR tszFileName[MAX_PATH]; - _tcscpy(tszFileName, _tcsrchr(info->tszNewName, L'\\') + 1); - TCHAR *p = _tcschr(tszFileName, L'.'); *p = 0; - - TCHAR link[MAX_PATH]; - mir_sntprintf(link, MAX_PATH, _T("http://miranda-ng.org/p/%s"), tszFileName); - CallService(MS_UTILS_OPENURL, OUF_TCHAR, (LPARAM) link); - } - } - } - - return CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam); -} - -static int ListDlg_Resize(HWND, LPARAM, UTILRESIZECONTROL *urc) -{ - switch (urc->wId) { - case IDC_SELNONE: - case IDOK: - return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM; - - case IDC_UPDATETEXT: - return RD_ANCHORX_CENTRE; - } - return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; -} - -INT_PTR CALLBACK DlgList(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); - - switch (message) { - case WM_INITDIALOG: - hwndDialog = hDlg; - TranslateDialogDefault( hDlg ); - oldWndProc = (WNDPROC)SetWindowLongPtr(hwndList, GWLP_WNDPROC, (LONG_PTR)PluginListWndProc); - - SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)Skin_GetIcon("plg_list", 1)); - SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)Skin_GetIcon("plg_list")); - { - HIMAGELIST hIml = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 4, 0); - ImageList_AddIconFromIconLib(hIml, "info"); - ListView_SetImageList(hwndList, hIml, LVSIL_SMALL); - - OSVERSIONINFO osver = { sizeof(osver) }; - if (GetVersionEx(&osver) && osver.dwMajorVersion >= 6) { - wchar_t szPath[MAX_PATH]; - GetModuleFileName(NULL, szPath, SIZEOF(szPath)); - TCHAR *ext = _tcsrchr(szPath, '.'); - if (ext != NULL) - *ext = '\0'; - _tcscat(szPath, _T(".test")); - HANDLE hFile = CreateFile(szPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) - // Running Windows Vista or later (major version >= 6). - Button_SetElevationRequiredState(GetDlgItem(hDlg, IDOK), !IsProcessElevated()); - else { - CloseHandle(hFile); - DeleteFile(szPath); - } - } - RECT r; - GetClientRect(hwndList, &r); - - /// - LVCOLUMN lvc = {0}; - lvc.mask = LVCF_WIDTH | LVCF_TEXT; - //lvc.fmt = LVCFMT_LEFT; - - lvc.pszText = TranslateT("Component Name"); - lvc.cx = 220; // width of column in pixels - ListView_InsertColumn(hwndList, 0, &lvc); - - lvc.pszText = L""; - lvc.cx = 32 - GetSystemMetrics(SM_CXVSCROLL); // width of column in pixels - ListView_InsertColumn(hwndList, 1, &lvc); - - lvc.pszText = TranslateT("State"); - lvc.cx = 100 - GetSystemMetrics(SM_CXVSCROLL); // width of column in pixels - ListView_InsertColumn(hwndList, 2, &lvc); - - /// - LVGROUP lvg; - lvg.cbSize = sizeof(LVGROUP); - lvg.mask = LVGF_HEADER | LVGF_GROUPID; - - lvg.pszHeader = TranslateT("Plugins"); - lvg.iGroupId = 1; - ListView_InsertGroup(hwndList, 0, &lvg); - - lvg.pszHeader = TranslateT("Icons"); - lvg.iGroupId = 2; - ListView_InsertGroup(hwndList, 0, &lvg); - - lvg.pszHeader = TranslateT("Languages"); - lvg.iGroupId = 3; - ListView_InsertGroup(hwndList, 0, &lvg); - - lvg.pszHeader = TranslateT("Other"); - lvg.iGroupId = 4; - ListView_InsertGroup(hwndList, 0, &lvg); - - ListView_EnableGroupView(hwndList, TRUE); - - /// - SendMessage(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES | LVS_EX_CHECKBOXES | LVS_EX_LABELTIP); - ListView_DeleteAllItems(hwndList); - - /// - OBJLIST &todo = *(OBJLIST *)lParam; - for (int i = 0; i < todo.getCount(); ++i) { - LVITEM lvi = {0}; - lvi.mask = LVIF_PARAM | LVIF_GROUPID | LVIF_TEXT | LVIF_IMAGE; - - int groupId = 4; - if (_tcschr(todo[i].tszOldName, L'\\') != NULL) - groupId = (_tcsstr(todo[i].tszOldName, _T("Plugins")) != NULL) ? 1 : ((_tcsstr(todo[i].tszOldName, _T("Languages")) != NULL) ? 3 : 2); - - lvi.iItem = i; - lvi.lParam = (LPARAM)&todo[i]; - lvi.iGroupId = groupId; - lvi.iImage = -1; - lvi.pszText = todo[i].tszOldName; - int iRow = ListView_InsertItem(hwndList, &lvi); - - if (iRow != -1) { - lvi.iItem = iRow; - if (groupId == 1) { - lvi.mask = LVIF_IMAGE; - lvi.iSubItem = 1; - lvi.iImage = 0; - ListView_SetItem(hwndList, &lvi); - } - } - todo[i].bEnabled = false; - } - HWND hwOk = GetDlgItem(hDlg, IDOK); - EnableWindow(hwOk, false); - } - - // do this after filling list - enables 'ITEMCHANGED' below - SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam); - Utils_RestoreWindowPosition(hDlg, 0, MODNAME, "ListWindow"); - return TRUE; - - case WM_NOTIFY: - if (((LPNMHDR) lParam)->hwndFrom == hwndList) { - switch (((LPNMHDR) lParam)->code) { - case LVN_ITEMCHANGED: - if (GetWindowLongPtr(hDlg, GWLP_USERDATA)) { - NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam; - - LVITEM lvI = {0}; - lvI.iItem = nmlv->iItem; - lvI.iSubItem = 0; - lvI.mask = LVIF_PARAM; - ListView_GetItem(hwndList, &lvI); - - OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - if ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK) { - todo[lvI.iItem].bEnabled = ListView_GetCheckState(hwndList, nmlv->iItem); - - bool enableOk = false; - for (int i=0; i < todo.getCount(); ++i) { - if (todo[i].bEnabled) { - enableOk = true; - break; - } - } - HWND hwOk = GetDlgItem(hDlg, IDOK); - EnableWindow(hwOk, enableOk ? TRUE : FALSE); - } - } - break; - } - } - break; - - case WM_COMMAND: - if (HIWORD( wParam ) == BN_CLICKED) { - switch(LOWORD(wParam)) { - case IDOK: - EnableWindow( GetDlgItem(hDlg, IDOK), FALSE); - EnableWindow( GetDlgItem(hDlg, IDC_SELNONE), FALSE); - - mir_forkthread(ApplyDownloads, hDlg); - return TRUE; - - case IDC_SELNONE: - SelectAll(hDlg, false); - break; - - case IDCANCEL: - DestroyWindow(hDlg); - return TRUE; - } - } - break; - - case WM_SIZE: // make the dlg resizeable - if (!IsIconic(hDlg)) { - UTILRESIZEDIALOG urd = { sizeof(urd) }; - urd.hInstance = hInst; - urd.hwndDlg = hDlg; - urd.lpTemplate = MAKEINTRESOURCEA(IDD_LIST); - urd.pfnResizer = ListDlg_Resize; - CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd); - } - break; - - case WM_GETMINMAXINFO: - { - LPMINMAXINFO mmi = (LPMINMAXINFO)lParam; - - // The minimum width in points - mmi->ptMinTrackSize.x = 370; - // The minimum height in points - mmi->ptMinTrackSize.y = 300; - } - break; - - case WM_CLOSE: - DestroyWindow(hDlg); - break; - - case WM_DESTROY: - Utils_SaveWindowPosition(hDlg, NULL, MODNAME, "ListWindow"); - Skin_ReleaseIcon((HICON)SendMessage(hDlg, WM_SETICON, ICON_BIG, 0)); - Skin_ReleaseIcon((HICON)SendMessage(hDlg, WM_SETICON, ICON_SMALL, 0)); - hwndDialog = NULL; - delete (OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - SetWindowLongPtr(hDlg, GWLP_USERDATA, 0); - break; - } - - return FALSE; -} - -static void __stdcall LaunchListDialog(void *param) -{ - CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_LIST), GetDesktopWindow(), DlgList, (LPARAM)param); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// building file list in the separate thread - -static void GetList(void *) -{ - char szKey[64] = {0}; - - TCHAR tszTempPath[MAX_PATH]; - DWORD dwLen = GetTempPath(SIZEOF(tszTempPath), tszTempPath); - if (tszTempPath[dwLen-1] == '\\') - tszTempPath[dwLen-1] = 0; - - ptrT updateUrl( GetDefaultUrl()), baseUrl; - SERVLIST hashes(50, CompareHashes); - if (!ParseHashes(updateUrl, baseUrl, hashes)) { - hListThread = NULL; - return; - } - - FILELIST *UpdateFiles = new FILELIST(20); - TCHAR *dirname = Utils_ReplaceVarsT(_T("%miranda_path%")); - - for (int i=0; i < hashes.getCount(); i++) { - ServListEntry &hash = hashes[i]; - - TCHAR tszPath[MAX_PATH]; - mir_sntprintf(tszPath, SIZEOF(tszPath), _T("%s\\%s"), dirname, hash.m_name); - - if (GetFileAttributes(tszPath) != DWORD(-1)) - continue; - - FILEINFO *FileInfo = new FILEINFO; - FileInfo->bDeleteOnly = FALSE; - _tcscpy(FileInfo->tszOldName, hash.m_name); // copy the relative old name - _tcscpy(FileInfo->tszNewName, hash.m_name); - - TCHAR tszFileName[MAX_PATH]; - _tcscpy(tszFileName, _tcsrchr(tszPath, L'\\') + 1); - TCHAR *tp = _tcschr(tszFileName, L'.'); *tp = 0; - - TCHAR tszRelFileName[MAX_PATH]; - _tcscpy(tszRelFileName, hash.m_name); - tp = _tcsrchr(tszRelFileName, L'.'); if (tp) *tp = 0; - tp = _tcschr(tszRelFileName, L'\\'); if (tp) tp++; else tp = tszRelFileName; - _tcslwr(tp); - - mir_sntprintf(FileInfo->File.tszDiskPath, SIZEOF(FileInfo->File.tszDiskPath), _T("%s\\Temp\\%s.zip"), tszRoot, tszFileName); - mir_sntprintf(FileInfo->File.tszDownloadURL, SIZEOF(FileInfo->File.tszDownloadURL), _T("%s/%s.zip"), baseUrl, tszRelFileName); - for (tp = _tcschr(FileInfo->File.tszDownloadURL, '\\'); tp != 0; tp = _tcschr(tp, '\\')) - *tp++ = '/'; - FileInfo->File.CRCsum = hash.m_crc; - UpdateFiles->insert(FileInfo); - } - - mir_free(dirname); - - // Show dialog - if (UpdateFiles->getCount() == 0) { - if (!opts.bSilent) - ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("List is empty."), 2, 0); - delete UpdateFiles; - } - else CallFunctionAsync(LaunchListDialog, UpdateFiles); - - hListThread = NULL; -} - -void DoGetList(int iFlag) -{ - if (hListThread) - ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("List loading already started!"), 2, 0); - else if (hwndDialog) { - ShowWindow(hwndDialog, SW_SHOW); - SetForegroundWindow(hwndDialog); - SetFocus(hwndDialog); - } - else if (iFlag) - hListThread = mir_forkthread(GetList, 0); -} - -void UninitListNew() -{ - if (hwndDialog != NULL) - DestroyWindow(hwndDialog); -} - -INT_PTR ShowListCommand(WPARAM,LPARAM) -{ - opts.bSilent = false; - DoGetList(true); - return 0; -} - -void InitListNew() -{ - CreateServiceFunction(MODNAME"/ShowList", ShowListCommand); -} - -void UnloadListNew() -{ - if (hListThread) - hListThread = NULL; +/* +Copyright (C) 2010 Mataes + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#include "common.h" + +static HWND hwndDialog; +HANDLE hListThread; + +static void SelectAll(HWND hDlg, bool bEnable) +{ + OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); + HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); + + for (int i=0; i < todo.getCount(); i++) { + ListView_SetCheckState(hwndList, i, bEnable); + todo[i].bEnabled = bEnable; + } +} + +static void ApplyDownloads(void *param) +{ + HWND hDlg = (HWND)param; + + ////////////////////////////////////////////////////////////////////////////////////// + // if we need to escalate priviledges, launch a atub + + if (!PrepareEscalation()) { + PostMessage(hDlg, WM_CLOSE, 0, 0); + return; + } + + ////////////////////////////////////////////////////////////////////////////////////// + // ok, let's unpack all zips + + AutoHandle pipe(hPipe); + HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); + OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); + TCHAR tszBuff[2048], tszFileTemp[MAX_PATH], tszFileBack[MAX_PATH]; + + mir_sntprintf(tszFileBack, SIZEOF(tszFileBack), _T("%s\\Backups"), tszRoot); + SafeCreateDirectory(tszFileBack); + + mir_sntprintf(tszFileTemp, SIZEOF(tszFileTemp), _T("%s\\Temp"), tszRoot); + SafeCreateDirectory(tszFileTemp); + + HANDLE nlc = NULL; + for (int i=0; i < todo.getCount(); ++i) { + ListView_EnsureVisible(hwndList, i, FALSE); + if (!todo[i].bEnabled) { + ListView_SetItemText(hwndList, i, 2, TranslateT("Skipped.")); + continue; + } + + // download update + ListView_SetItemText(hwndList, i, 2, TranslateT("Downloading...")); + + FILEURL *pFileUrl = &todo[i].File; + if (!DownloadFile(pFileUrl, nlc)) { + ListView_SetItemText(hwndList, i, 2, TranslateT("Failed!")); + } + else + ListView_SetItemText(hwndList, i, 2, TranslateT("Succeeded.")); + } + Netlib_CloseHandle(nlc); + + if (todo.getCount() > 0) { + ShowPopup(0, LPGENT("Plugin Updater"), TranslateT("Download complete"), 2, 0); + + TCHAR *tszMirandaPath = Utils_ReplaceVarsT(_T("%miranda_path%")); + + for (int i = 0; i < todo.getCount(); i++) { + if (!todo[i].bEnabled) + continue; + + TCHAR tszBackFile[MAX_PATH]; + FILEINFO& p = todo[i]; + if (p.bDeleteOnly) { // we need only to backup the old file + TCHAR *ptszRelPath = p.tszNewName + _tcslen(tszMirandaPath) + 1; + mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, ptszRelPath); + BackupFile(p.tszNewName, tszBackFile); + continue; + } + + // if file name differs, we also need to backup the old file here + // otherwise it would be replaced by unzip + if ( _tcsicmp(p.tszOldName, p.tszNewName)) { + TCHAR tszSrcPath[MAX_PATH]; + mir_sntprintf(tszSrcPath, SIZEOF(tszSrcPath), _T("%s\\%s"), tszMirandaPath, p.tszOldName); + mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, p.tszOldName); + BackupFile(tszSrcPath, tszBackFile); + } + + if ( unzip(p.File.tszDiskPath, tszMirandaPath, tszFileBack,false)) + SafeDeleteFile(p.File.tszDiskPath); // remove .zip after successful update + } + } + + PopupDataText temp; + temp.Title = TranslateT("Plugin Updater"); + temp.Text = tszBuff; + lstrcpyn(tszBuff, TranslateT("Download complete. Do you want to go to plugins option page?"), SIZEOF(tszBuff)); + int rc = MessageBox(hDlg, temp.Text, temp.Title, MB_YESNO | MB_ICONQUESTION); + if (rc == IDYES) + CallFunctionAsync(OpenPluginOptions, 0); + + PostMessage(hDlg, WM_CLOSE, 0, 0); + return; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static WNDPROC oldWndProc = NULL; + +static LRESULT CALLBACK PluginListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (msg == WM_LBUTTONDOWN) { + LVHITTESTINFO hi; + hi.pt.x = LOWORD(lParam); hi.pt.y = HIWORD(lParam); + ListView_SubItemHitTest(hwnd, &hi); + if (hi.iSubItem == 1) { + LVITEM lvi = {0}; + lvi.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_GROUPID; + lvi.stateMask = -1; + lvi.iItem = hi.iItem; + if (ListView_GetItem(hwnd, &lvi) && lvi.iGroupId == 1) { + FILEINFO *info = (FILEINFO *)lvi.lParam; + + TCHAR tszFileName[MAX_PATH]; + _tcscpy(tszFileName, _tcsrchr(info->tszNewName, L'\\') + 1); + TCHAR *p = _tcschr(tszFileName, L'.'); *p = 0; + + TCHAR link[MAX_PATH]; + mir_sntprintf(link, MAX_PATH, _T("http://miranda-ng.org/p/%s"), tszFileName); + CallService(MS_UTILS_OPENURL, OUF_TCHAR, (LPARAM) link); + } + } + } + + return CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam); +} + +static int ListDlg_Resize(HWND, LPARAM, UTILRESIZECONTROL *urc) +{ + switch (urc->wId) { + case IDC_SELNONE: + case IDOK: + return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM; + + case IDC_UPDATETEXT: + return RD_ANCHORX_CENTRE; + } + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; +} + +INT_PTR CALLBACK DlgList(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); + + switch (message) { + case WM_INITDIALOG: + hwndDialog = hDlg; + TranslateDialogDefault( hDlg ); + oldWndProc = (WNDPROC)SetWindowLongPtr(hwndList, GWLP_WNDPROC, (LONG_PTR)PluginListWndProc); + + SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)Skin_GetIcon("plg_list", 1)); + SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)Skin_GetIcon("plg_list")); + { + HIMAGELIST hIml = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 4, 0); + ImageList_AddIconFromIconLib(hIml, "info"); + ListView_SetImageList(hwndList, hIml, LVSIL_SMALL); + + OSVERSIONINFO osver = { sizeof(osver) }; + if (GetVersionEx(&osver) && osver.dwMajorVersion >= 6) { + wchar_t szPath[MAX_PATH]; + GetModuleFileName(NULL, szPath, SIZEOF(szPath)); + TCHAR *ext = _tcsrchr(szPath, '.'); + if (ext != NULL) + *ext = '\0'; + _tcscat(szPath, _T(".test")); + HANDLE hFile = CreateFile(szPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + // Running Windows Vista or later (major version >= 6). + Button_SetElevationRequiredState(GetDlgItem(hDlg, IDOK), !IsProcessElevated()); + else { + CloseHandle(hFile); + DeleteFile(szPath); + } + } + RECT r; + GetClientRect(hwndList, &r); + + /// + LVCOLUMN lvc = {0}; + lvc.mask = LVCF_WIDTH | LVCF_TEXT; + //lvc.fmt = LVCFMT_LEFT; + + lvc.pszText = TranslateT("Component Name"); + lvc.cx = 220; // width of column in pixels + ListView_InsertColumn(hwndList, 0, &lvc); + + lvc.pszText = L""; + lvc.cx = 32 - GetSystemMetrics(SM_CXVSCROLL); // width of column in pixels + ListView_InsertColumn(hwndList, 1, &lvc); + + lvc.pszText = TranslateT("State"); + lvc.cx = 100 - GetSystemMetrics(SM_CXVSCROLL); // width of column in pixels + ListView_InsertColumn(hwndList, 2, &lvc); + + /// + LVGROUP lvg; + lvg.cbSize = sizeof(LVGROUP); + lvg.mask = LVGF_HEADER | LVGF_GROUPID; + + lvg.pszHeader = TranslateT("Plugins"); + lvg.iGroupId = 1; + ListView_InsertGroup(hwndList, 0, &lvg); + + lvg.pszHeader = TranslateT("Icons"); + lvg.iGroupId = 2; + ListView_InsertGroup(hwndList, 0, &lvg); + + lvg.pszHeader = TranslateT("Languages"); + lvg.iGroupId = 3; + ListView_InsertGroup(hwndList, 0, &lvg); + + lvg.pszHeader = TranslateT("Other"); + lvg.iGroupId = 4; + ListView_InsertGroup(hwndList, 0, &lvg); + + ListView_EnableGroupView(hwndList, TRUE); + + /// + SendMessage(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES | LVS_EX_CHECKBOXES | LVS_EX_LABELTIP); + ListView_DeleteAllItems(hwndList); + + /// + OBJLIST &todo = *(OBJLIST *)lParam; + for (int i = 0; i < todo.getCount(); ++i) { + LVITEM lvi = {0}; + lvi.mask = LVIF_PARAM | LVIF_GROUPID | LVIF_TEXT | LVIF_IMAGE; + + int groupId = 4; + if (_tcschr(todo[i].tszOldName, L'\\') != NULL) + groupId = (_tcsstr(todo[i].tszOldName, _T("Plugins")) != NULL) ? 1 : ((_tcsstr(todo[i].tszOldName, _T("Languages")) != NULL) ? 3 : 2); + + lvi.iItem = i; + lvi.lParam = (LPARAM)&todo[i]; + lvi.iGroupId = groupId; + lvi.iImage = -1; + lvi.pszText = todo[i].tszOldName; + int iRow = ListView_InsertItem(hwndList, &lvi); + + if (iRow != -1) { + lvi.iItem = iRow; + if (groupId == 1) { + lvi.mask = LVIF_IMAGE; + lvi.iSubItem = 1; + lvi.iImage = 0; + ListView_SetItem(hwndList, &lvi); + } + } + todo[i].bEnabled = false; + } + HWND hwOk = GetDlgItem(hDlg, IDOK); + EnableWindow(hwOk, false); + } + + // do this after filling list - enables 'ITEMCHANGED' below + SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam); + Utils_RestoreWindowPosition(hDlg, 0, MODNAME, "ListWindow"); + return TRUE; + + case WM_NOTIFY: + if (((LPNMHDR) lParam)->hwndFrom == hwndList) { + switch (((LPNMHDR) lParam)->code) { + case LVN_ITEMCHANGED: + if (GetWindowLongPtr(hDlg, GWLP_USERDATA)) { + NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam; + + LVITEM lvI = {0}; + lvI.iItem = nmlv->iItem; + lvI.iSubItem = 0; + lvI.mask = LVIF_PARAM; + ListView_GetItem(hwndList, &lvI); + + OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); + if ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK) { + todo[lvI.iItem].bEnabled = ListView_GetCheckState(hwndList, nmlv->iItem); + + bool enableOk = false; + for (int i=0; i < todo.getCount(); ++i) { + if (todo[i].bEnabled) { + enableOk = true; + break; + } + } + HWND hwOk = GetDlgItem(hDlg, IDOK); + EnableWindow(hwOk, enableOk ? TRUE : FALSE); + } + } + break; + } + } + break; + + case WM_COMMAND: + if (HIWORD( wParam ) == BN_CLICKED) { + switch(LOWORD(wParam)) { + case IDOK: + EnableWindow( GetDlgItem(hDlg, IDOK), FALSE); + EnableWindow( GetDlgItem(hDlg, IDC_SELNONE), FALSE); + + mir_forkthread(ApplyDownloads, hDlg); + return TRUE; + + case IDC_SELNONE: + SelectAll(hDlg, false); + break; + + case IDCANCEL: + DestroyWindow(hDlg); + return TRUE; + } + } + break; + + case WM_SIZE: // make the dlg resizeable + if (!IsIconic(hDlg)) { + UTILRESIZEDIALOG urd = { sizeof(urd) }; + urd.hInstance = hInst; + urd.hwndDlg = hDlg; + urd.lpTemplate = MAKEINTRESOURCEA(IDD_LIST); + urd.pfnResizer = ListDlg_Resize; + CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd); + } + break; + + case WM_GETMINMAXINFO: + { + LPMINMAXINFO mmi = (LPMINMAXINFO)lParam; + + // The minimum width in points + mmi->ptMinTrackSize.x = 370; + // The minimum height in points + mmi->ptMinTrackSize.y = 300; + } + break; + + case WM_CLOSE: + DestroyWindow(hDlg); + break; + + case WM_DESTROY: + Utils_SaveWindowPosition(hDlg, NULL, MODNAME, "ListWindow"); + Skin_ReleaseIcon((HICON)SendMessage(hDlg, WM_SETICON, ICON_BIG, 0)); + Skin_ReleaseIcon((HICON)SendMessage(hDlg, WM_SETICON, ICON_SMALL, 0)); + hwndDialog = NULL; + delete (OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); + SetWindowLongPtr(hDlg, GWLP_USERDATA, 0); + break; + } + + return FALSE; +} + +static void __stdcall LaunchListDialog(void *param) +{ + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_LIST), GetDesktopWindow(), DlgList, (LPARAM)param); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// building file list in the separate thread + +static void GetList(void *) +{ + char szKey[64] = {0}; + + TCHAR tszTempPath[MAX_PATH]; + DWORD dwLen = GetTempPath(SIZEOF(tszTempPath), tszTempPath); + if (tszTempPath[dwLen-1] == '\\') + tszTempPath[dwLen-1] = 0; + + ptrT updateUrl( GetDefaultUrl()), baseUrl; + SERVLIST hashes(50, CompareHashes); + if (!ParseHashes(updateUrl, baseUrl, hashes)) { + hListThread = NULL; + return; + } + + FILELIST *UpdateFiles = new FILELIST(20); + TCHAR *dirname = Utils_ReplaceVarsT(_T("%miranda_path%")); + + for (int i=0; i < hashes.getCount(); i++) { + ServListEntry &hash = hashes[i]; + + TCHAR tszPath[MAX_PATH]; + mir_sntprintf(tszPath, SIZEOF(tszPath), _T("%s\\%s"), dirname, hash.m_name); + + if (GetFileAttributes(tszPath) != DWORD(-1)) + continue; + + FILEINFO *FileInfo = new FILEINFO; + FileInfo->bDeleteOnly = FALSE; + _tcscpy(FileInfo->tszOldName, hash.m_name); // copy the relative old name + _tcscpy(FileInfo->tszNewName, hash.m_name); + + TCHAR tszFileName[MAX_PATH]; + _tcscpy(tszFileName, _tcsrchr(tszPath, L'\\') + 1); + TCHAR *tp = _tcschr(tszFileName, L'.'); *tp = 0; + + TCHAR tszRelFileName[MAX_PATH]; + _tcscpy(tszRelFileName, hash.m_name); + tp = _tcsrchr(tszRelFileName, L'.'); if (tp) *tp = 0; + tp = _tcschr(tszRelFileName, L'\\'); if (tp) tp++; else tp = tszRelFileName; + _tcslwr(tp); + + mir_sntprintf(FileInfo->File.tszDiskPath, SIZEOF(FileInfo->File.tszDiskPath), _T("%s\\Temp\\%s.zip"), tszRoot, tszFileName); + mir_sntprintf(FileInfo->File.tszDownloadURL, SIZEOF(FileInfo->File.tszDownloadURL), _T("%s/%s.zip"), baseUrl, tszRelFileName); + for (tp = _tcschr(FileInfo->File.tszDownloadURL, '\\'); tp != 0; tp = _tcschr(tp, '\\')) + *tp++ = '/'; + FileInfo->File.CRCsum = hash.m_crc; + UpdateFiles->insert(FileInfo); + } + + mir_free(dirname); + + // Show dialog + if (UpdateFiles->getCount() == 0) { + if (!opts.bSilent) + ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("List is empty."), 2, 0); + delete UpdateFiles; + } + else CallFunctionAsync(LaunchListDialog, UpdateFiles); + + hListThread = NULL; +} + +void DoGetList(int iFlag) +{ + if (hListThread) + ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("List loading already started!"), 2, 0); + else if (hwndDialog) { + ShowWindow(hwndDialog, SW_SHOW); + SetForegroundWindow(hwndDialog); + SetFocus(hwndDialog); + } + else if (iFlag) + hListThread = mir_forkthread(GetList, 0); +} + +void UninitListNew() +{ + if (hwndDialog != NULL) + DestroyWindow(hwndDialog); +} + +INT_PTR ShowListCommand(WPARAM,LPARAM) +{ + opts.bSilent = false; + DoGetList(true); + return 0; +} + +void InitListNew() +{ + CreateServiceFunction(MODNAME"/ShowList", ShowListCommand); +} + +void UnloadListNew() +{ + if (hListThread) + hListThread = NULL; } \ No newline at end of file diff --git a/plugins/PluginUpdater/src/DlgUpdate.cpp b/plugins/PluginUpdater/src/DlgUpdate.cpp index 711bfcd57b..258efd4389 100644 --- a/plugins/PluginUpdater/src/DlgUpdate.cpp +++ b/plugins/PluginUpdater/src/DlgUpdate.cpp @@ -1,764 +1,764 @@ -/* -Copyright (C) 2010 Mataes - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - -#include "common.h" - -#define UM_ERROR (WM_USER+1) - -static bool bShowDetails; -static HWND hwndDialog; -HANDLE hCheckThread; - -static void SelectAll(HWND hDlg, bool bEnable) -{ - OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); - - for (int i=0; i < todo.getCount(); i++) { - ListView_SetCheckState(hwndList, i, bEnable); - db_set_b(NULL, MODNAME "Files", StrToLower(_T2A(todo[i].tszOldName)), todo[i].bEnabled = bEnable); - } -} - -static void SetStringText(HWND hWnd, size_t i, TCHAR *ptszText) -{ - ListView_SetItemText(hWnd, i, 1, ptszText); -} - -static void ApplyUpdates(void *param) -{ - HWND hDlg = (HWND)param; - OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - if (todo.getCount() == 0) { - return; - } - - // 1) If we need to escalate priviledges, launch a stub - if (!PrepareEscalation()) { - SendMessage(hDlg, WM_CLOSE, 0, 0); - return; - } - - AutoHandle pipe(hPipe); - HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); - TCHAR tszFileTemp[MAX_PATH], tszFileBack[MAX_PATH]; - - mir_sntprintf(tszFileBack, SIZEOF(tszFileBack), _T("%s\\Backups"), tszRoot); - SafeCreateDirectory(tszFileBack); - - mir_sntprintf(tszFileTemp, SIZEOF(tszFileTemp), _T("%s\\Temp"), tszRoot); - SafeCreateDirectory(tszFileTemp); - - // 2) Download all plugins - HANDLE nlc = NULL; - for (int i=0; i < todo.getCount(); i++) { - ListView_EnsureVisible(hwndList, i, FALSE); - if (!todo[i].bEnabled) { - SetStringText(hwndList, i, TranslateT("Skipped.")); - } - else if (todo[i].bDeleteOnly) { - SetStringText(hwndList, i, TranslateT("Will be deleted!")); - } - else { - // download update - SetStringText(hwndList, i, TranslateT("Downloading...")); - - FILEURL *pFileUrl = &todo[i].File; - if (!DownloadFile(pFileUrl, nlc)) { - SetStringText(hwndList, i, TranslateT("Failed!")); - - // interrupt update as we require all components to be updated - Netlib_CloseHandle(nlc); - PostMessage(hDlg, UM_ERROR, 0, 0); - SkinPlaySound("updatefailed"); - return; - } - SetStringText(hwndList, i, TranslateT("Succeeded.")); - } - } - Netlib_CloseHandle(nlc); - - // 3) Unpack all zips - TCHAR *tszMirandaPath = Utils_ReplaceVarsT(_T("%miranda_path%")); - for (int i = 0; i < todo.getCount(); i++) { - if (todo[i].bEnabled) { - TCHAR tszBackFile[MAX_PATH]; - FILEINFO& p = todo[i]; - if (p.bDeleteOnly) { - // we need only to backup the old file - TCHAR *ptszRelPath = p.tszNewName + _tcslen(tszMirandaPath) + 1; - mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, ptszRelPath); - BackupFile(p.tszNewName, tszBackFile); - } - else { - // if file name differs, we also need to backup the old file here - // otherwise it would be replaced by unzip - if ( _tcsicmp(p.tszOldName, p.tszNewName)) { - TCHAR tszSrcPath[MAX_PATH]; - mir_sntprintf(tszSrcPath, SIZEOF(tszSrcPath), _T("%s\\%s"), tszMirandaPath, p.tszOldName); - mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, p.tszOldName); - BackupFile(tszSrcPath, tszBackFile); - } - - if ( unzip(p.File.tszDiskPath, tszMirandaPath, tszFileBack,true)) - SafeDeleteFile(p.File.tszDiskPath); // remove .zip after successful update - } - } - } - SkinPlaySound("updatecompleted"); - -#if MIRANDA_VER < 0x0A00 - // 4) Change title of clist - ptrT title = db_get_tsa(NULL, "CList", "TitleText"); - if (!_tcsicmp(title, _T("Miranda IM"))) - db_set_ts(NULL, "CList", "TitleText", _T("Miranda NG")); -#endif - - opts.bForceRedownload = false; - db_unset(NULL, MODNAME, "ForceRedownload"); - - db_set_b(NULL, MODNAME, "RestartCount", 5); - - // 5) Prepare Restart - int rc = MessageBox(hDlg, TranslateT("Update complete. Press Yes to restart Miranda now or No to postpone a restart until the exit."), TranslateT("Plugin Updater"), MB_YESNO | MB_ICONQUESTION); - SendMessage(hDlg, WM_CLOSE, 0, 0); - if (rc == IDYES) - CallFunctionAsync(RestartMe, 0); -} - -static void ResizeVert(HWND hDlg, int yy) -{ - RECT r = { 0, 0, 244, yy }; - MapDialogRect(hDlg, &r); - r.bottom += GetSystemMetrics(SM_CYSMCAPTION); - SetWindowPos(hDlg, 0, 0, 0, r.right, r.bottom, SWP_NOMOVE | SWP_NOZORDER); -} - -static INT_PTR CALLBACK DlgUpdate(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); - - switch (message) { - case WM_INITDIALOG: - TranslateDialogDefault(hDlg); - SendMessage(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES); - SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)Skin_GetIcon("check_update")); - SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)Skin_GetIcon("check_update", 1)); - { - OSVERSIONINFO osver = { sizeof(osver) }; - if (GetVersionEx(&osver) && osver.dwMajorVersion >= 6) - { - wchar_t szPath[MAX_PATH]; - GetModuleFileName(NULL, szPath, SIZEOF(szPath)); - TCHAR *ext = _tcsrchr(szPath, '.'); - if (ext != NULL) - *ext = '\0'; - _tcscat(szPath, _T(".test")); - HANDLE hFile = CreateFile(szPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) - // Running Windows Vista or later (major version >= 6). - Button_SetElevationRequiredState(GetDlgItem(hDlg, IDOK), !IsProcessElevated()); - else - { - CloseHandle(hFile); - DeleteFile(szPath); - } - } - RECT r; - GetClientRect(hwndList, &r); - - LVCOLUMN lvc = {0}; - // Initialize the LVCOLUMN structure. - // The mask specifies that the format, width, text, and - // subitem members of the structure are valid. - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; - lvc.fmt = LVCFMT_LEFT; - - lvc.iSubItem = 0; - lvc.pszText = TranslateT("Component Name"); - lvc.cx = 220; // width of column in pixels - ListView_InsertColumn(hwndList, 0, &lvc); - - lvc.iSubItem = 1; - lvc.pszText = TranslateT("State"); - lvc.cx = 120 - GetSystemMetrics(SM_CXVSCROLL); // width of column in pixels - ListView_InsertColumn(hwndList, 1, &lvc); - - //enumerate plugins, fill in list - //bool one_enabled = false; - ListView_DeleteAllItems(hwndList); - - // Some code to create the list-view control. - // Initialize LVITEM members that are common to all items. - LVITEM lvI = {0}; - lvI.mask = LVIF_TEXT | LVIF_PARAM | LVIF_NORECOMPUTE;// | LVIF_IMAGE; - - bool enableOk = false; - OBJLIST &todo = *(OBJLIST *)lParam; - for (int i = 0; i < todo.getCount(); ++i) { - lvI.mask = LVIF_TEXT | LVIF_PARAM;// | LVIF_IMAGE; - lvI.iSubItem = 0; - lvI.lParam = (LPARAM)&todo[i]; - lvI.pszText = todo[i].tszOldName; - lvI.iItem = i; - ListView_InsertItem(hwndList, &lvI); - - // remember whether the user has decided not to update this component with this particular new version - todo[i].bEnabled = db_get_b(NULL, MODNAME "Files", StrToLower(_T2A(todo[i].tszOldName)), true); - ListView_SetCheckState(hwndList, lvI.iItem, todo[i].bEnabled); - if (todo[i].bEnabled) - enableOk = true; - } - HWND hwOk = GetDlgItem(hDlg, IDOK); - EnableWindow(hwOk, enableOk); - } - - bShowDetails = false; - ResizeVert(hDlg, 60); - - // do this after filling list - enables 'ITEMCHANGED' below - SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam); - Utils_RestoreWindowPositionNoSize(hDlg, 0, MODNAME, "ConfirmWindow"); - return TRUE; - - case WM_NOTIFY: - if (((LPNMHDR) lParam)->hwndFrom == hwndList) { - switch (((LPNMHDR) lParam)->code) { - case LVN_ITEMCHANGED: - if (GetWindowLongPtr(hDlg, GWLP_USERDATA)) { - NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam; - - LVITEM lvI = {0}; - lvI.iItem = nmlv->iItem; - lvI.iSubItem = 0; - lvI.mask = LVIF_PARAM; - ListView_GetItem(hwndList, &lvI); - - OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - if ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK) { - todo[lvI.iItem].bEnabled = ListView_GetCheckState(hwndList, nmlv->iItem); - db_set_b(NULL, MODNAME "Files", StrToLower(_T2A(todo[lvI.iItem].tszOldName)), todo[lvI.iItem].bEnabled); - - bool enableOk = false; - for (int i=0; i < todo.getCount(); ++i) { - if (todo[i].bEnabled) { - enableOk = true; - break; - } - } - HWND hwOk = GetDlgItem(hDlg, IDOK); - EnableWindow(hwOk, enableOk ? TRUE : FALSE); - } - } - break; - } - } - break; - - case WM_COMMAND: - if (HIWORD( wParam ) == BN_CLICKED) { - switch(LOWORD(wParam)) { - case IDOK: - EnableWindow( GetDlgItem(hDlg, IDOK), FALSE); - EnableWindow( GetDlgItem(hDlg, IDC_SELALL), FALSE); - EnableWindow( GetDlgItem(hDlg, IDC_SELNONE), FALSE); - - mir_forkthread(ApplyUpdates, hDlg); - return TRUE; - - case IDC_DETAILS: - bShowDetails = !bShowDetails; - ResizeVert(hDlg, bShowDetails ? 242 : 60); - SetDlgItemText(hDlg, IDC_DETAILS, (bShowDetails ? TranslateT("<< Details") : TranslateT("Details >>"))); - break; - - case IDC_SELALL: - SelectAll(hDlg, true); - break; - - case IDC_SELNONE: - SelectAll(hDlg, false); - break; - - case IDCANCEL: - DestroyWindow(hDlg); - return TRUE; - } - } - break; - - case UM_ERROR: - MessageBox(hDlg, TranslateT("Update failed! One of the components wasn't downloaded correctly. Try it again later."), TranslateT("Plugin Updater"), MB_OK | MB_ICONERROR); - DestroyWindow(hDlg); - break; - - case WM_CLOSE: - DestroyWindow(hDlg); - break; - - case WM_DESTROY: - Skin_ReleaseIcon((HICON)SendMessage(hDlg, WM_SETICON, ICON_SMALL, 0)); - Utils_SaveWindowPosition(hDlg, NULL, MODNAME, "ConfirmWindow"); - hwndDialog = NULL; - opts.bSilent = true; - delete (OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - SetWindowLongPtr(hDlg, GWLP_USERDATA, 0); - #if MIRANDA_VER >= 0x0A00 - db_set_dw(NULL, MODNAME, "LastUpdate", time(NULL)); - #endif - mir_forkthread(InitTimer, (void*)0); - break; - } - - return FALSE; -} - -static LRESULT CALLBACK PopupDlgProcRestart(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) { - case WM_COMMAND: - case WM_CONTEXTMENU: - PUDeletePopup(hDlg); - - if (uMsg == WM_COMMAND) { - TCHAR tszText[200]; - mir_sntprintf(tszText, SIZEOF(tszText), _T("%s\n\n%s"), TranslateT("You need to restart your Miranda to apply installed updates."), TranslateT("Would you like to restart it now?")); - - if (MessageBox(hDlg, tszText, TranslateT("Plugin Updater"), MB_YESNO | MB_ICONQUESTION) == IDYES) - CallFunctionAsync(RestartMe, 0); - } - - return TRUE; - } - - return DefWindowProc(hDlg, uMsg, wParam, lParam); -} - -static void DlgUpdateSilent(void *lParam) -{ - OBJLIST &UpdateFiles = *(OBJLIST *)lParam; - if (UpdateFiles.getCount() == 0) { - delete &UpdateFiles; - return; - } - - // 1) If we need to escalate priviledges, launch a stub - if (!PrepareEscalation()) { - delete &UpdateFiles; - return; - } - - AutoHandle pipe(hPipe); - TCHAR tszFileTemp[MAX_PATH], tszFileBack[MAX_PATH]; - - mir_sntprintf(tszFileBack, SIZEOF(tszFileBack), _T("%s\\Backups"), tszRoot); - SafeCreateDirectory(tszFileBack); - - mir_sntprintf(tszFileTemp, SIZEOF(tszFileTemp), _T("%s\\Temp"), tszRoot); - SafeCreateDirectory(tszFileTemp); - - // 2) Download all plugins - HANDLE nlc = NULL; - // Count all updates that have been enabled - int count = 0; - for (int i = 0; i < UpdateFiles.getCount(); i++) { - if (db_get_b(NULL, MODNAME "Files", StrToLower(_T2A(UpdateFiles[i].tszOldName)), 1) && !UpdateFiles[i].bDeleteOnly) { - // download update - FILEURL *pFileUrl = &UpdateFiles[i].File; - if (!DownloadFile(pFileUrl, nlc)) { - // interrupt update as we require all components to be updated - Netlib_CloseHandle(nlc); - SkinPlaySound("updatefailed"); - delete &UpdateFiles; - return; - } - count++; - } - - } - Netlib_CloseHandle(nlc); - - if (count == 0) { - delete &UpdateFiles; - return; - } - - // 3) Unpack all zips - TCHAR *tszMirandaPath = Utils_ReplaceVarsT(_T("%miranda_path%")); - for (int i = 0; i < UpdateFiles.getCount(); i++) { - if (db_get_b(NULL, MODNAME "Files", StrToLower(_T2A(UpdateFiles[i].tszOldName)), 1)) { - TCHAR tszBackFile[MAX_PATH]; - FILEINFO& p = UpdateFiles[i]; - if (p.bDeleteOnly) { // we need only to backup the old file - TCHAR *ptszRelPath = p.tszNewName + _tcslen(tszMirandaPath) + 1; - mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, ptszRelPath); - BackupFile(p.tszNewName, tszBackFile); - } - else { - // if file name differs, we also need to backup the old file here - // otherwise it would be replaced by unzip - if (_tcsicmp(p.tszOldName, p.tszNewName)) { - TCHAR tszSrcPath[MAX_PATH]; - mir_sntprintf(tszSrcPath, SIZEOF(tszSrcPath), _T("%s\\%s"), tszMirandaPath, p.tszOldName); - mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, p.tszOldName); - BackupFile(tszSrcPath, tszBackFile); - } - - if (unzip(p.File.tszDiskPath, tszMirandaPath, tszFileBack, true)) - SafeDeleteFile(p.File.tszDiskPath); // remove .zip after successful update - } - } - } - delete &UpdateFiles; - SkinPlaySound("updatecompleted"); - -#if MIRANDA_VER < 0x0A00 - // 4) Change title of clist - ptrT title = db_get_tsa(NULL, "CList", "TitleText"); - if (!_tcsicmp(title, _T("Miranda IM"))) - db_set_ts(NULL, "CList", "TitleText", _T("Miranda NG")); -#endif - - opts.bForceRedownload = false; - db_unset(NULL, MODNAME, "ForceRedownload"); - - db_set_b(NULL, MODNAME, "RestartCount", 5); - db_set_b(NULL, MODNAME, "NeedRestart", 1); - - // 5) Prepare Restart - TCHAR tszTitle[100]; - mir_sntprintf(tszTitle, SIZEOF(tszTitle), TranslateT("%d component(s) was updated"), count); - - if (ServiceExists(MS_POPUP_ADDPOPUPT) && db_get_b(NULL, "Popup", "ModuleIsEnabled", 1)) { - POPUPDATAT_V2 pd = { 0 }; - pd.cbSize = sizeof(pd); - pd.lchContact = NULL; - pd.lchIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); - pd.colorBack = pd.colorText = 0; - pd.iSeconds = -1; - pd.PluginWindowProc = PopupDlgProcRestart; - - lstrcpyn(pd.lptzText, TranslateT("You need to restart your Miranda to apply installed updates."), MAX_SECONDLINE); - lstrcpyn(pd.lptzContactName, tszTitle, MAX_CONTACTNAME); - - CallService(MS_POPUP_ADDPOPUPT, (WPARAM)&pd, APF_NEWDATA); - } else { - bool notified = false; - - if (ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) { - MIRANDASYSTRAYNOTIFY err; - err.szProto = MODULEA; - err.cbSize = sizeof(err); - err.dwInfoFlags = NIIF_INTERN_UNICODE | NIIF_INFO; - err.tszInfoTitle = tszTitle; - err.tszInfo = TranslateT("You need to restart your Miranda to apply installed updates."); - err.uTimeout = 30000; - - notified = !CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&err); - } - - if (!notified) { - // Error, let's try to show MessageBox as last way to inform user about successful update - TCHAR tszText[200]; - mir_sntprintf(tszText, SIZEOF(tszText), _T("%s\n\n%s"), TranslateT("You need to restart your Miranda to apply installed updates."), TranslateT("Would you like to restart it now?")); - - if (MessageBox(NULL, tszText, tszTitle, MB_ICONINFORMATION | MB_YESNO) == IDYES) - CallFunctionAsync(RestartMe, 0); - } - } -} - -static void __stdcall LaunchDialog(void *param) -{ - if (opts.bSilentMode && opts.bSilent) - mir_forkthread(DlgUpdateSilent, param); - else - hwndDialog = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_UPDATE), GetDesktopWindow(), DlgUpdate, (LPARAM)param); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// building file list in the separate thread - -struct -{ - TCHAR *oldName, *newName; -} -static renameTable[] = -{ - { _T("svc_dbepp.dll"), _T("Plugins\\dbeditorpp.dll") }, - { _T("svc_crshdmp.dll"), _T("Plugins\\crashdumper.dll") }, - { _T("svc_vi.dll"), _T("Plugins\\versioninfo.dll") }, - { _T("crashrpt.dll"), _T("Plugins\\crashdumper.dll") }, - { _T("advsplashscreen.dll"), _T("Plugins\\splashscreen.dll") }, - { _T("import_sa.dll"), _T("Plugins\\import.dll") }, - { _T("newnr.dll"), _T("Plugins\\notesreminders.dll") }, - { _T("dbtool.exe"), _T("Plugins\\dbchecker.dll") }, - { _T("dbtool_sa.exe"), _T("Plugins\\dbchecker.dll") }, - { _T("bclist.dll"), _T("Plugins\\clist_blind.dll") }, - { _T("otr.dll"), _T("Plugins\\mirotr.dll") }, - { _T("ttnotify.dll"), _T("Plugins\\tooltipnotify.dll") }, - { _T("newstatusnotify.dll"), _T("Plugins\\newxstatusnotify.dll") }, - { _T("rss.dll"), _T("Plugins\\newsaggregator.dll") }, - { _T("dbx_3x.dll"), _T("Plugins\\dbx_mmap.dll") }, - - #if MIRANDA_VER >= 0x0A00 - { _T("dbx_mmap_sa.dll"), _T("Plugins\\dbx_mmap.dll") }, - { _T("dbx_tree.dll"), _T("Plugins\\dbx_mmap.dll") }, - { _T("rc4.dll"), NULL }, - { _T("athena.dll"), NULL }, - #endif - - { _T("proto_newsaggr.dll"), _T("Icons\\proto_newsaggregator.dll") }, - { _T("clienticons_*.dll"), _T("Icons\\fp_icons.dll") }, - { _T("fp_*.dll"), _T("Icons\\fp_icons.dll") }, - - { _T("langpack_*.txt"), _T("Languages\\*") }, - - { _T("clist_classic.dll"), NULL }, - { _T("chat.dll"), NULL }, - { _T("gender.dll"), NULL }, - { _T("srmm.dll"), NULL }, - { _T("extraicons.dll"), NULL }, - { _T("langman.dll"), NULL }, - { _T("metacontacts.dll"), NULL }, -}; - -static bool CheckFileRename(const TCHAR *ptszOldName, TCHAR *pNewName) -{ - for (int i = 0; i < SIZEOF(renameTable); i++) { - if (!wildcmpit(ptszOldName, renameTable[i].oldName)) - continue; - - TCHAR *ptszDest = renameTable[i].newName; - if (ptszDest == NULL) - *pNewName = 0; - else { - _tcsncpy_s(pNewName, MAX_PATH, ptszDest, _TRUNCATE); - size_t cbLen = _tcslen(ptszDest) - 1; - if (pNewName[cbLen] == '*') - _tcsncpy_s(pNewName + cbLen, MAX_PATH - cbLen, ptszOldName, _TRUNCATE); - } - return true; - } - - return false; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -static bool isValidExtension(const TCHAR *ptszFileName) -{ - const TCHAR *pExt = _tcsrchr(ptszFileName, '.'); - - return (pExt != NULL) && (!_tcsicmp(pExt, _T(".dll")) || !_tcsicmp(pExt, _T(".exe")) || !_tcsicmp(pExt, _T(".txt"))); -} - -static int ScanFolder(const TCHAR *tszFolder, size_t cbBaseLen, int level, const TCHAR *tszBaseUrl, SERVLIST& hashes, OBJLIST *UpdateFiles) -{ - int count = 0; - - // skip updater's own folder - if (!_tcsicmp(tszFolder, tszRoot)) - return count; - - TCHAR tszBuf[MAX_PATH]; - mir_sntprintf(tszBuf, SIZEOF(tszBuf), _T("%s\\*"), tszFolder); - - WIN32_FIND_DATA ffd; - HANDLE hFind = FindFirstFile(tszBuf, &ffd); - if (hFind == INVALID_HANDLE_VALUE) - return count; - - do { - if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - if (_tcscmp(ffd.cFileName, _T(".")) && _tcscmp(ffd.cFileName, _T(".."))) { - // we need to skip profile folder - TCHAR tszProfilePath[MAX_PATH]; - CallService(MS_DB_GETPROFILEPATHT, SIZEOF(tszProfilePath), (LPARAM)tszProfilePath); - - mir_sntprintf(tszBuf, SIZEOF(tszBuf), _T("%s\\%s"), tszFolder, ffd.cFileName); - if (0 != _tcsicmp(tszBuf, tszProfilePath)) - count += ScanFolder(tszBuf, cbBaseLen, level+1, tszBaseUrl, hashes, UpdateFiles); - } - } - else if (isValidExtension(ffd.cFileName)) { - // calculate the current file's relative name and store it into tszNewName - TCHAR tszNewName[MAX_PATH]; - if (!CheckFileRename(ffd.cFileName, tszNewName)) { - if (level == 0) - _tcsncpy(tszNewName, ffd.cFileName, MAX_PATH); - else - mir_sntprintf(tszNewName, SIZEOF(tszNewName), _T("%s\\%s"), tszFolder+cbBaseLen, ffd.cFileName); - } - - bool bHasNewVersion = true; - TCHAR *ptszUrl; - int MyCRC = 0; - mir_sntprintf(tszBuf, SIZEOF(tszBuf), _T("%s\\%s"), tszFolder, ffd.cFileName); - - // this file is not marked for deletion - if (tszNewName[0]) { - TCHAR *pName = tszNewName; - ServListEntry *item = hashes.find((ServListEntry*)&pName); - if (item == NULL) { - TCHAR *p = _tcsrchr(tszNewName, '.'); - if (p[-1] != 'w' && p[-1] != 'W') - continue; - - int iPos = int(p - tszNewName)-1; - strdel(p-1, 1); - if ((item = hashes.find((ServListEntry*)&pName)) == NULL) - continue; - - strdel(tszNewName+iPos, 1); - } - - ptszUrl = item->m_name; - // No need to hash a file if we are forcing a redownload anyway - if (!opts.bForceRedownload) { - // try to hash the file - char szMyHash[33]; - __try { - CalculateModuleHash(tszBuf, szMyHash); - bHasNewVersion = strcmp(szMyHash, item->m_szHash) != 0; - } - __except(EXCEPTION_EXECUTE_HANDLER) { - ZeroMemory(szMyHash, 0); - // smth went wrong, reload a file from scratch - } - } - - MyCRC = item->m_crc; - } - else // file was marked for deletion, add it to the list anyway - ptszUrl = _T(""); - - // Compare versions - if (bHasNewVersion) { // Yeah, we've got new version. - FILEINFO *FileInfo = new FILEINFO; - _tcscpy(FileInfo->tszOldName, tszBuf+cbBaseLen); // copy the relative old name - if (tszNewName[0] == 0) { - FileInfo->bDeleteOnly = TRUE; - _tcscpy(FileInfo->tszNewName, tszBuf); // save the full old name for deletion - } - else { - FileInfo->bDeleteOnly = FALSE; - _tcsncpy(FileInfo->tszNewName, ptszUrl, SIZEOF(FileInfo->tszNewName)); - } - - _tcscpy(tszBuf, ptszUrl); - TCHAR *p = _tcsrchr(tszBuf, '.'); - if (p) *p = 0; - p = _tcsrchr(tszBuf, '\\'); - p = (p) ? p+1 : tszBuf; - _tcslwr(p); - - mir_sntprintf(FileInfo->File.tszDiskPath, SIZEOF(FileInfo->File.tszDiskPath), _T("%s\\Temp\\%s.zip"), tszRoot, p); - mir_sntprintf(FileInfo->File.tszDownloadURL, SIZEOF(FileInfo->File.tszDownloadURL), _T("%s/%s.zip"), tszBaseUrl, tszBuf); - for (p = _tcschr(FileInfo->File.tszDownloadURL, '\\'); p != 0; p = _tcschr(p, '\\')) - *p++ = '/'; - - FileInfo->File.CRCsum = MyCRC; - UpdateFiles->insert(FileInfo); - - if (!opts.bSilent || db_get_b(NULL, MODNAME "Files", StrToLower(_T2A(FileInfo->tszNewName)), true)) - count++; - } // end compare versions - } - } - while (FindNextFile(hFind, &ffd) != 0); - - FindClose(hFind); - return count; -} - -static void CheckUpdates(void *) -{ - char szKey[64] = {0}; - - TCHAR tszTempPath[MAX_PATH]; - DWORD dwLen = GetTempPath(SIZEOF(tszTempPath), tszTempPath); - if (tszTempPath[dwLen-1] == '\\') - tszTempPath[dwLen-1] = 0; - - ptrT updateUrl(GetDefaultUrl()), baseUrl; - - SERVLIST hashes(50, CompareHashes); - bool success = ParseHashes(updateUrl, baseUrl, hashes); - if (success) { - FILELIST *UpdateFiles = new FILELIST(20); - VARST dirname( _T("%miranda_path%")); - int count = ScanFolder(dirname, lstrlen(dirname)+1, 0, baseUrl, hashes, UpdateFiles); - - // Show dialog - if (count == 0) { - if (!opts.bSilent) - ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("No updates found."), 2, 0); - delete UpdateFiles; - opts.bSilent = true; - } - else CallFunctionAsync(LaunchDialog, UpdateFiles); - } - else opts.bSilent = true; - - mir_forkthread(InitTimer, (void*)(success ? 0 : 2)); - - hashes.destroy(); - hCheckThread = NULL; -} - -void DoCheck() -{ - if (hCheckThread) - ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("Update checking already started!"), 2, 0); - else if (hwndDialog) { - ShowWindow(hwndDialog, SW_SHOW); - SetForegroundWindow(hwndDialog); - SetFocus(hwndDialog); - } else { - #if MIRANDA_VER >= 0x0A00 - db_set_dw(NULL, MODNAME, "LastUpdate", time(NULL)); - #endif - hCheckThread = mir_forkthread(CheckUpdates, 0); - } -} - -void UninitCheck() -{ - if (hwndDialog != NULL) - DestroyWindow(hwndDialog); -} - -INT_PTR MenuCommand(WPARAM,LPARAM) -{ - opts.bSilent = false; - DoCheck(); - return 0; -} - -void InitCheck() -{ - CreateServiceFunction(MODNAME"/CheckUpdates", MenuCommand); -} - -void UnloadCheck() -{ - if (hCheckThread) - hCheckThread = NULL; +/* +Copyright (C) 2010 Mataes + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#include "common.h" + +#define UM_ERROR (WM_USER+1) + +static bool bShowDetails; +static HWND hwndDialog; +HANDLE hCheckThread; + +static void SelectAll(HWND hDlg, bool bEnable) +{ + OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); + HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); + + for (int i=0; i < todo.getCount(); i++) { + ListView_SetCheckState(hwndList, i, bEnable); + db_set_b(NULL, MODNAME "Files", StrToLower(_T2A(todo[i].tszOldName)), todo[i].bEnabled = bEnable); + } +} + +static void SetStringText(HWND hWnd, size_t i, TCHAR *ptszText) +{ + ListView_SetItemText(hWnd, i, 1, ptszText); +} + +static void ApplyUpdates(void *param) +{ + HWND hDlg = (HWND)param; + OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); + if (todo.getCount() == 0) { + return; + } + + // 1) If we need to escalate priviledges, launch a stub + if (!PrepareEscalation()) { + PostMessage(hDlg, WM_CLOSE, 0, 0); + return; + } + + AutoHandle pipe(hPipe); + HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); + TCHAR tszFileTemp[MAX_PATH], tszFileBack[MAX_PATH]; + + mir_sntprintf(tszFileBack, SIZEOF(tszFileBack), _T("%s\\Backups"), tszRoot); + SafeCreateDirectory(tszFileBack); + + mir_sntprintf(tszFileTemp, SIZEOF(tszFileTemp), _T("%s\\Temp"), tszRoot); + SafeCreateDirectory(tszFileTemp); + + // 2) Download all plugins + HANDLE nlc = NULL; + for (int i=0; i < todo.getCount(); i++) { + ListView_EnsureVisible(hwndList, i, FALSE); + if (!todo[i].bEnabled) { + SetStringText(hwndList, i, TranslateT("Skipped.")); + } + else if (todo[i].bDeleteOnly) { + SetStringText(hwndList, i, TranslateT("Will be deleted!")); + } + else { + // download update + SetStringText(hwndList, i, TranslateT("Downloading...")); + + FILEURL *pFileUrl = &todo[i].File; + if (!DownloadFile(pFileUrl, nlc)) { + SetStringText(hwndList, i, TranslateT("Failed!")); + + // interrupt update as we require all components to be updated + Netlib_CloseHandle(nlc); + PostMessage(hDlg, UM_ERROR, 0, 0); + SkinPlaySound("updatefailed"); + return; + } + SetStringText(hwndList, i, TranslateT("Succeeded.")); + } + } + Netlib_CloseHandle(nlc); + + // 3) Unpack all zips + TCHAR *tszMirandaPath = Utils_ReplaceVarsT(_T("%miranda_path%")); + for (int i = 0; i < todo.getCount(); i++) { + if (todo[i].bEnabled) { + TCHAR tszBackFile[MAX_PATH]; + FILEINFO& p = todo[i]; + if (p.bDeleteOnly) { + // we need only to backup the old file + TCHAR *ptszRelPath = p.tszNewName + _tcslen(tszMirandaPath) + 1; + mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, ptszRelPath); + BackupFile(p.tszNewName, tszBackFile); + } + else { + // if file name differs, we also need to backup the old file here + // otherwise it would be replaced by unzip + if ( _tcsicmp(p.tszOldName, p.tszNewName)) { + TCHAR tszSrcPath[MAX_PATH]; + mir_sntprintf(tszSrcPath, SIZEOF(tszSrcPath), _T("%s\\%s"), tszMirandaPath, p.tszOldName); + mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, p.tszOldName); + BackupFile(tszSrcPath, tszBackFile); + } + + if ( unzip(p.File.tszDiskPath, tszMirandaPath, tszFileBack,true)) + SafeDeleteFile(p.File.tszDiskPath); // remove .zip after successful update + } + } + } + SkinPlaySound("updatecompleted"); + +#if MIRANDA_VER < 0x0A00 + // 4) Change title of clist + ptrT title = db_get_tsa(NULL, "CList", "TitleText"); + if (!_tcsicmp(title, _T("Miranda IM"))) + db_set_ts(NULL, "CList", "TitleText", _T("Miranda NG")); +#endif + + opts.bForceRedownload = false; + db_unset(NULL, MODNAME, "ForceRedownload"); + + db_set_b(NULL, MODNAME, "RestartCount", 5); + + // 5) Prepare Restart + int rc = MessageBox(hDlg, TranslateT("Update complete. Press Yes to restart Miranda now or No to postpone a restart until the exit."), TranslateT("Plugin Updater"), MB_YESNO | MB_ICONQUESTION); + PostMessage(hDlg, WM_CLOSE, 0, 0); + if (rc == IDYES) + CallFunctionAsync(RestartMe, 0); +} + +static void ResizeVert(HWND hDlg, int yy) +{ + RECT r = { 0, 0, 244, yy }; + MapDialogRect(hDlg, &r); + r.bottom += GetSystemMetrics(SM_CYSMCAPTION); + SetWindowPos(hDlg, 0, 0, 0, r.right, r.bottom, SWP_NOMOVE | SWP_NOZORDER); +} + +static INT_PTR CALLBACK DlgUpdate(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); + + switch (message) { + case WM_INITDIALOG: + TranslateDialogDefault(hDlg); + SendMessage(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES); + SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)Skin_GetIcon("check_update")); + SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)Skin_GetIcon("check_update", 1)); + { + OSVERSIONINFO osver = { sizeof(osver) }; + if (GetVersionEx(&osver) && osver.dwMajorVersion >= 6) + { + wchar_t szPath[MAX_PATH]; + GetModuleFileName(NULL, szPath, SIZEOF(szPath)); + TCHAR *ext = _tcsrchr(szPath, '.'); + if (ext != NULL) + *ext = '\0'; + _tcscat(szPath, _T(".test")); + HANDLE hFile = CreateFile(szPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + // Running Windows Vista or later (major version >= 6). + Button_SetElevationRequiredState(GetDlgItem(hDlg, IDOK), !IsProcessElevated()); + else + { + CloseHandle(hFile); + DeleteFile(szPath); + } + } + RECT r; + GetClientRect(hwndList, &r); + + LVCOLUMN lvc = {0}; + // Initialize the LVCOLUMN structure. + // The mask specifies that the format, width, text, and + // subitem members of the structure are valid. + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; + lvc.fmt = LVCFMT_LEFT; + + lvc.iSubItem = 0; + lvc.pszText = TranslateT("Component Name"); + lvc.cx = 220; // width of column in pixels + ListView_InsertColumn(hwndList, 0, &lvc); + + lvc.iSubItem = 1; + lvc.pszText = TranslateT("State"); + lvc.cx = 120 - GetSystemMetrics(SM_CXVSCROLL); // width of column in pixels + ListView_InsertColumn(hwndList, 1, &lvc); + + //enumerate plugins, fill in list + //bool one_enabled = false; + ListView_DeleteAllItems(hwndList); + + // Some code to create the list-view control. + // Initialize LVITEM members that are common to all items. + LVITEM lvI = {0}; + lvI.mask = LVIF_TEXT | LVIF_PARAM | LVIF_NORECOMPUTE;// | LVIF_IMAGE; + + bool enableOk = false; + OBJLIST &todo = *(OBJLIST *)lParam; + for (int i = 0; i < todo.getCount(); ++i) { + lvI.mask = LVIF_TEXT | LVIF_PARAM;// | LVIF_IMAGE; + lvI.iSubItem = 0; + lvI.lParam = (LPARAM)&todo[i]; + lvI.pszText = todo[i].tszOldName; + lvI.iItem = i; + ListView_InsertItem(hwndList, &lvI); + + // remember whether the user has decided not to update this component with this particular new version + todo[i].bEnabled = db_get_b(NULL, MODNAME "Files", StrToLower(_T2A(todo[i].tszOldName)), true); + ListView_SetCheckState(hwndList, lvI.iItem, todo[i].bEnabled); + if (todo[i].bEnabled) + enableOk = true; + } + HWND hwOk = GetDlgItem(hDlg, IDOK); + EnableWindow(hwOk, enableOk); + } + + bShowDetails = false; + ResizeVert(hDlg, 60); + + // do this after filling list - enables 'ITEMCHANGED' below + SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam); + Utils_RestoreWindowPositionNoSize(hDlg, 0, MODNAME, "ConfirmWindow"); + return TRUE; + + case WM_NOTIFY: + if (((LPNMHDR) lParam)->hwndFrom == hwndList) { + switch (((LPNMHDR) lParam)->code) { + case LVN_ITEMCHANGED: + if (GetWindowLongPtr(hDlg, GWLP_USERDATA)) { + NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam; + + LVITEM lvI = {0}; + lvI.iItem = nmlv->iItem; + lvI.iSubItem = 0; + lvI.mask = LVIF_PARAM; + ListView_GetItem(hwndList, &lvI); + + OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); + if ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK) { + todo[lvI.iItem].bEnabled = ListView_GetCheckState(hwndList, nmlv->iItem); + db_set_b(NULL, MODNAME "Files", StrToLower(_T2A(todo[lvI.iItem].tszOldName)), todo[lvI.iItem].bEnabled); + + bool enableOk = false; + for (int i=0; i < todo.getCount(); ++i) { + if (todo[i].bEnabled) { + enableOk = true; + break; + } + } + HWND hwOk = GetDlgItem(hDlg, IDOK); + EnableWindow(hwOk, enableOk ? TRUE : FALSE); + } + } + break; + } + } + break; + + case WM_COMMAND: + if (HIWORD( wParam ) == BN_CLICKED) { + switch(LOWORD(wParam)) { + case IDOK: + EnableWindow( GetDlgItem(hDlg, IDOK), FALSE); + EnableWindow( GetDlgItem(hDlg, IDC_SELALL), FALSE); + EnableWindow( GetDlgItem(hDlg, IDC_SELNONE), FALSE); + + mir_forkthread(ApplyUpdates, hDlg); + return TRUE; + + case IDC_DETAILS: + bShowDetails = !bShowDetails; + ResizeVert(hDlg, bShowDetails ? 242 : 60); + SetDlgItemText(hDlg, IDC_DETAILS, (bShowDetails ? TranslateT("<< Details") : TranslateT("Details >>"))); + break; + + case IDC_SELALL: + SelectAll(hDlg, true); + break; + + case IDC_SELNONE: + SelectAll(hDlg, false); + break; + + case IDCANCEL: + DestroyWindow(hDlg); + return TRUE; + } + } + break; + + case UM_ERROR: + MessageBox(hDlg, TranslateT("Update failed! One of the components wasn't downloaded correctly. Try it again later."), TranslateT("Plugin Updater"), MB_OK | MB_ICONERROR); + DestroyWindow(hDlg); + break; + + case WM_CLOSE: + DestroyWindow(hDlg); + break; + + case WM_DESTROY: + Skin_ReleaseIcon((HICON)SendMessage(hDlg, WM_SETICON, ICON_SMALL, 0)); + Utils_SaveWindowPosition(hDlg, NULL, MODNAME, "ConfirmWindow"); + hwndDialog = NULL; + opts.bSilent = true; + delete (OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); + SetWindowLongPtr(hDlg, GWLP_USERDATA, 0); + #if MIRANDA_VER >= 0x0A00 + db_set_dw(NULL, MODNAME, "LastUpdate", time(NULL)); + #endif + mir_forkthread(InitTimer, (void*)0); + break; + } + + return FALSE; +} + +static LRESULT CALLBACK PopupDlgProcRestart(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case WM_COMMAND: + case WM_CONTEXTMENU: + PUDeletePopup(hDlg); + + if (uMsg == WM_COMMAND) { + TCHAR tszText[200]; + mir_sntprintf(tszText, SIZEOF(tszText), _T("%s\n\n%s"), TranslateT("You need to restart your Miranda to apply installed updates."), TranslateT("Would you like to restart it now?")); + + if (MessageBox(hDlg, tszText, TranslateT("Plugin Updater"), MB_YESNO | MB_ICONQUESTION) == IDYES) + CallFunctionAsync(RestartMe, 0); + } + + return TRUE; + } + + return DefWindowProc(hDlg, uMsg, wParam, lParam); +} + +static void DlgUpdateSilent(void *lParam) +{ + OBJLIST &UpdateFiles = *(OBJLIST *)lParam; + if (UpdateFiles.getCount() == 0) { + delete &UpdateFiles; + return; + } + + // 1) If we need to escalate priviledges, launch a stub + if (!PrepareEscalation()) { + delete &UpdateFiles; + return; + } + + AutoHandle pipe(hPipe); + TCHAR tszFileTemp[MAX_PATH], tszFileBack[MAX_PATH]; + + mir_sntprintf(tszFileBack, SIZEOF(tszFileBack), _T("%s\\Backups"), tszRoot); + SafeCreateDirectory(tszFileBack); + + mir_sntprintf(tszFileTemp, SIZEOF(tszFileTemp), _T("%s\\Temp"), tszRoot); + SafeCreateDirectory(tszFileTemp); + + // 2) Download all plugins + HANDLE nlc = NULL; + // Count all updates that have been enabled + int count = 0; + for (int i = 0; i < UpdateFiles.getCount(); i++) { + if (db_get_b(NULL, MODNAME "Files", StrToLower(_T2A(UpdateFiles[i].tszOldName)), 1) && !UpdateFiles[i].bDeleteOnly) { + // download update + FILEURL *pFileUrl = &UpdateFiles[i].File; + if (!DownloadFile(pFileUrl, nlc)) { + // interrupt update as we require all components to be updated + Netlib_CloseHandle(nlc); + SkinPlaySound("updatefailed"); + delete &UpdateFiles; + return; + } + count++; + } + + } + Netlib_CloseHandle(nlc); + + if (count == 0) { + delete &UpdateFiles; + return; + } + + // 3) Unpack all zips + TCHAR *tszMirandaPath = Utils_ReplaceVarsT(_T("%miranda_path%")); + for (int i = 0; i < UpdateFiles.getCount(); i++) { + if (db_get_b(NULL, MODNAME "Files", StrToLower(_T2A(UpdateFiles[i].tszOldName)), 1)) { + TCHAR tszBackFile[MAX_PATH]; + FILEINFO& p = UpdateFiles[i]; + if (p.bDeleteOnly) { // we need only to backup the old file + TCHAR *ptszRelPath = p.tszNewName + _tcslen(tszMirandaPath) + 1; + mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, ptszRelPath); + BackupFile(p.tszNewName, tszBackFile); + } + else { + // if file name differs, we also need to backup the old file here + // otherwise it would be replaced by unzip + if (_tcsicmp(p.tszOldName, p.tszNewName)) { + TCHAR tszSrcPath[MAX_PATH]; + mir_sntprintf(tszSrcPath, SIZEOF(tszSrcPath), _T("%s\\%s"), tszMirandaPath, p.tszOldName); + mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, p.tszOldName); + BackupFile(tszSrcPath, tszBackFile); + } + + if (unzip(p.File.tszDiskPath, tszMirandaPath, tszFileBack, true)) + SafeDeleteFile(p.File.tszDiskPath); // remove .zip after successful update + } + } + } + delete &UpdateFiles; + SkinPlaySound("updatecompleted"); + +#if MIRANDA_VER < 0x0A00 + // 4) Change title of clist + ptrT title = db_get_tsa(NULL, "CList", "TitleText"); + if (!_tcsicmp(title, _T("Miranda IM"))) + db_set_ts(NULL, "CList", "TitleText", _T("Miranda NG")); +#endif + + opts.bForceRedownload = false; + db_unset(NULL, MODNAME, "ForceRedownload"); + + db_set_b(NULL, MODNAME, "RestartCount", 5); + db_set_b(NULL, MODNAME, "NeedRestart", 1); + + // 5) Prepare Restart + TCHAR tszTitle[100]; + mir_sntprintf(tszTitle, SIZEOF(tszTitle), TranslateT("%d component(s) was updated"), count); + + if (ServiceExists(MS_POPUP_ADDPOPUPT) && db_get_b(NULL, "Popup", "ModuleIsEnabled", 1)) { + POPUPDATAT_V2 pd = { 0 }; + pd.cbSize = sizeof(pd); + pd.lchContact = NULL; + pd.lchIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); + pd.colorBack = pd.colorText = 0; + pd.iSeconds = -1; + pd.PluginWindowProc = PopupDlgProcRestart; + + lstrcpyn(pd.lptzText, TranslateT("You need to restart your Miranda to apply installed updates."), MAX_SECONDLINE); + lstrcpyn(pd.lptzContactName, tszTitle, MAX_CONTACTNAME); + + CallService(MS_POPUP_ADDPOPUPT, (WPARAM)&pd, APF_NEWDATA); + } else { + bool notified = false; + + if (ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) { + MIRANDASYSTRAYNOTIFY err; + err.szProto = MODULEA; + err.cbSize = sizeof(err); + err.dwInfoFlags = NIIF_INTERN_UNICODE | NIIF_INFO; + err.tszInfoTitle = tszTitle; + err.tszInfo = TranslateT("You need to restart your Miranda to apply installed updates."); + err.uTimeout = 30000; + + notified = !CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&err); + } + + if (!notified) { + // Error, let's try to show MessageBox as last way to inform user about successful update + TCHAR tszText[200]; + mir_sntprintf(tszText, SIZEOF(tszText), _T("%s\n\n%s"), TranslateT("You need to restart your Miranda to apply installed updates."), TranslateT("Would you like to restart it now?")); + + if (MessageBox(NULL, tszText, tszTitle, MB_ICONINFORMATION | MB_YESNO) == IDYES) + CallFunctionAsync(RestartMe, 0); + } + } +} + +static void __stdcall LaunchDialog(void *param) +{ + if (opts.bSilentMode && opts.bSilent) + mir_forkthread(DlgUpdateSilent, param); + else + hwndDialog = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_UPDATE), GetDesktopWindow(), DlgUpdate, (LPARAM)param); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// building file list in the separate thread + +struct +{ + TCHAR *oldName, *newName; +} +static renameTable[] = +{ + { _T("svc_dbepp.dll"), _T("Plugins\\dbeditorpp.dll") }, + { _T("svc_crshdmp.dll"), _T("Plugins\\crashdumper.dll") }, + { _T("svc_vi.dll"), _T("Plugins\\versioninfo.dll") }, + { _T("crashrpt.dll"), _T("Plugins\\crashdumper.dll") }, + { _T("advsplashscreen.dll"), _T("Plugins\\splashscreen.dll") }, + { _T("import_sa.dll"), _T("Plugins\\import.dll") }, + { _T("newnr.dll"), _T("Plugins\\notesreminders.dll") }, + { _T("dbtool.exe"), _T("Plugins\\dbchecker.dll") }, + { _T("dbtool_sa.exe"), _T("Plugins\\dbchecker.dll") }, + { _T("bclist.dll"), _T("Plugins\\clist_blind.dll") }, + { _T("otr.dll"), _T("Plugins\\mirotr.dll") }, + { _T("ttnotify.dll"), _T("Plugins\\tooltipnotify.dll") }, + { _T("newstatusnotify.dll"), _T("Plugins\\newxstatusnotify.dll") }, + { _T("rss.dll"), _T("Plugins\\newsaggregator.dll") }, + { _T("dbx_3x.dll"), _T("Plugins\\dbx_mmap.dll") }, + + #if MIRANDA_VER >= 0x0A00 + { _T("dbx_mmap_sa.dll"), _T("Plugins\\dbx_mmap.dll") }, + { _T("dbx_tree.dll"), _T("Plugins\\dbx_mmap.dll") }, + { _T("rc4.dll"), NULL }, + { _T("athena.dll"), NULL }, + #endif + + { _T("proto_newsaggr.dll"), _T("Icons\\proto_newsaggregator.dll") }, + { _T("clienticons_*.dll"), _T("Icons\\fp_icons.dll") }, + { _T("fp_*.dll"), _T("Icons\\fp_icons.dll") }, + + { _T("langpack_*.txt"), _T("Languages\\*") }, + + { _T("clist_classic.dll"), NULL }, + { _T("chat.dll"), NULL }, + { _T("gender.dll"), NULL }, + { _T("srmm.dll"), NULL }, + { _T("extraicons.dll"), NULL }, + { _T("langman.dll"), NULL }, + { _T("metacontacts.dll"), NULL }, +}; + +static bool CheckFileRename(const TCHAR *ptszOldName, TCHAR *pNewName) +{ + for (int i = 0; i < SIZEOF(renameTable); i++) { + if (!wildcmpit(ptszOldName, renameTable[i].oldName)) + continue; + + TCHAR *ptszDest = renameTable[i].newName; + if (ptszDest == NULL) + *pNewName = 0; + else { + _tcsncpy_s(pNewName, MAX_PATH, ptszDest, _TRUNCATE); + size_t cbLen = _tcslen(ptszDest) - 1; + if (pNewName[cbLen] == '*') + _tcsncpy_s(pNewName + cbLen, MAX_PATH - cbLen, ptszOldName, _TRUNCATE); + } + return true; + } + + return false; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static bool isValidExtension(const TCHAR *ptszFileName) +{ + const TCHAR *pExt = _tcsrchr(ptszFileName, '.'); + + return (pExt != NULL) && (!_tcsicmp(pExt, _T(".dll")) || !_tcsicmp(pExt, _T(".exe")) || !_tcsicmp(pExt, _T(".txt"))); +} + +static int ScanFolder(const TCHAR *tszFolder, size_t cbBaseLen, int level, const TCHAR *tszBaseUrl, SERVLIST& hashes, OBJLIST *UpdateFiles) +{ + int count = 0; + + // skip updater's own folder + if (!_tcsicmp(tszFolder, tszRoot)) + return count; + + TCHAR tszBuf[MAX_PATH]; + mir_sntprintf(tszBuf, SIZEOF(tszBuf), _T("%s\\*"), tszFolder); + + WIN32_FIND_DATA ffd; + HANDLE hFind = FindFirstFile(tszBuf, &ffd); + if (hFind == INVALID_HANDLE_VALUE) + return count; + + do { + if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + if (_tcscmp(ffd.cFileName, _T(".")) && _tcscmp(ffd.cFileName, _T(".."))) { + // we need to skip profile folder + TCHAR tszProfilePath[MAX_PATH]; + CallService(MS_DB_GETPROFILEPATHT, SIZEOF(tszProfilePath), (LPARAM)tszProfilePath); + + mir_sntprintf(tszBuf, SIZEOF(tszBuf), _T("%s\\%s"), tszFolder, ffd.cFileName); + if (0 != _tcsicmp(tszBuf, tszProfilePath)) + count += ScanFolder(tszBuf, cbBaseLen, level+1, tszBaseUrl, hashes, UpdateFiles); + } + } + else if (isValidExtension(ffd.cFileName)) { + // calculate the current file's relative name and store it into tszNewName + TCHAR tszNewName[MAX_PATH]; + if (!CheckFileRename(ffd.cFileName, tszNewName)) { + if (level == 0) + _tcsncpy(tszNewName, ffd.cFileName, MAX_PATH); + else + mir_sntprintf(tszNewName, SIZEOF(tszNewName), _T("%s\\%s"), tszFolder+cbBaseLen, ffd.cFileName); + } + + bool bHasNewVersion = true; + TCHAR *ptszUrl; + int MyCRC = 0; + mir_sntprintf(tszBuf, SIZEOF(tszBuf), _T("%s\\%s"), tszFolder, ffd.cFileName); + + // this file is not marked for deletion + if (tszNewName[0]) { + TCHAR *pName = tszNewName; + ServListEntry *item = hashes.find((ServListEntry*)&pName); + if (item == NULL) { + TCHAR *p = _tcsrchr(tszNewName, '.'); + if (p[-1] != 'w' && p[-1] != 'W') + continue; + + int iPos = int(p - tszNewName)-1; + strdel(p-1, 1); + if ((item = hashes.find((ServListEntry*)&pName)) == NULL) + continue; + + strdel(tszNewName+iPos, 1); + } + + ptszUrl = item->m_name; + // No need to hash a file if we are forcing a redownload anyway + if (!opts.bForceRedownload) { + // try to hash the file + char szMyHash[33]; + __try { + CalculateModuleHash(tszBuf, szMyHash); + bHasNewVersion = strcmp(szMyHash, item->m_szHash) != 0; + } + __except(EXCEPTION_EXECUTE_HANDLER) { + ZeroMemory(szMyHash, 0); + // smth went wrong, reload a file from scratch + } + } + + MyCRC = item->m_crc; + } + else // file was marked for deletion, add it to the list anyway + ptszUrl = _T(""); + + // Compare versions + if (bHasNewVersion) { // Yeah, we've got new version. + FILEINFO *FileInfo = new FILEINFO; + _tcscpy(FileInfo->tszOldName, tszBuf+cbBaseLen); // copy the relative old name + if (tszNewName[0] == 0) { + FileInfo->bDeleteOnly = TRUE; + _tcscpy(FileInfo->tszNewName, tszBuf); // save the full old name for deletion + } + else { + FileInfo->bDeleteOnly = FALSE; + _tcsncpy(FileInfo->tszNewName, ptszUrl, SIZEOF(FileInfo->tszNewName)); + } + + _tcscpy(tszBuf, ptszUrl); + TCHAR *p = _tcsrchr(tszBuf, '.'); + if (p) *p = 0; + p = _tcsrchr(tszBuf, '\\'); + p = (p) ? p+1 : tszBuf; + _tcslwr(p); + + mir_sntprintf(FileInfo->File.tszDiskPath, SIZEOF(FileInfo->File.tszDiskPath), _T("%s\\Temp\\%s.zip"), tszRoot, p); + mir_sntprintf(FileInfo->File.tszDownloadURL, SIZEOF(FileInfo->File.tszDownloadURL), _T("%s/%s.zip"), tszBaseUrl, tszBuf); + for (p = _tcschr(FileInfo->File.tszDownloadURL, '\\'); p != 0; p = _tcschr(p, '\\')) + *p++ = '/'; + + FileInfo->File.CRCsum = MyCRC; + UpdateFiles->insert(FileInfo); + + if (!opts.bSilent || db_get_b(NULL, MODNAME "Files", StrToLower(_T2A(FileInfo->tszNewName)), true)) + count++; + } // end compare versions + } + } + while (FindNextFile(hFind, &ffd) != 0); + + FindClose(hFind); + return count; +} + +static void CheckUpdates(void *) +{ + char szKey[64] = {0}; + + TCHAR tszTempPath[MAX_PATH]; + DWORD dwLen = GetTempPath(SIZEOF(tszTempPath), tszTempPath); + if (tszTempPath[dwLen-1] == '\\') + tszTempPath[dwLen-1] = 0; + + ptrT updateUrl(GetDefaultUrl()), baseUrl; + + SERVLIST hashes(50, CompareHashes); + bool success = ParseHashes(updateUrl, baseUrl, hashes); + if (success) { + FILELIST *UpdateFiles = new FILELIST(20); + VARST dirname( _T("%miranda_path%")); + int count = ScanFolder(dirname, lstrlen(dirname)+1, 0, baseUrl, hashes, UpdateFiles); + + // Show dialog + if (count == 0) { + if (!opts.bSilent) + ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("No updates found."), 2, 0); + delete UpdateFiles; + opts.bSilent = true; + } + else CallFunctionAsync(LaunchDialog, UpdateFiles); + } + else opts.bSilent = true; + + mir_forkthread(InitTimer, (void*)(success ? 0 : 2)); + + hashes.destroy(); + hCheckThread = NULL; +} + +void DoCheck() +{ + if (hCheckThread) + ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("Update checking already started!"), 2, 0); + else if (hwndDialog) { + ShowWindow(hwndDialog, SW_SHOW); + SetForegroundWindow(hwndDialog); + SetFocus(hwndDialog); + } else { + #if MIRANDA_VER >= 0x0A00 + db_set_dw(NULL, MODNAME, "LastUpdate", time(NULL)); + #endif + hCheckThread = mir_forkthread(CheckUpdates, 0); + } +} + +void UninitCheck() +{ + if (hwndDialog != NULL) + DestroyWindow(hwndDialog); +} + +INT_PTR MenuCommand(WPARAM,LPARAM) +{ + opts.bSilent = false; + DoCheck(); + return 0; +} + +void InitCheck() +{ + CreateServiceFunction(MODNAME"/CheckUpdates", MenuCommand); +} + +void UnloadCheck() +{ + if (hCheckThread) + hCheckThread = NULL; } \ No newline at end of file diff --git a/plugins/PluginUpdater/src/Notifications.cpp b/plugins/PluginUpdater/src/Notifications.cpp index d49c0d55b7..4a9108a5e8 100644 --- a/plugins/PluginUpdater/src/Notifications.cpp +++ b/plugins/PluginUpdater/src/Notifications.cpp @@ -1,273 +1,273 @@ -/* -Copyright (C) 2010 Mataes - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - -#include "common.h" - -HANDLE hPipe = NULL; - -void PopupAction(HWND hWnd, BYTE action) -{ - switch (action) { - case PCA_CLOSEPOPUP: - break; - case PCA_DONOTHING: - return; - } - PUDeletePopup(hWnd); -} - -static LRESULT CALLBACK PopupDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) { - case UM_POPUPACTION: - if (HIWORD(wParam) == BN_CLICKED) { - LPMSGPOPUPDATA pmpd = (LPMSGPOPUPDATA)PUGetPluginData(hDlg); - if (pmpd) { - switch (LOWORD(wParam)) { - case IDYES: - if (IsWindow(pmpd->hDialog)) - SendMessage(pmpd->hDialog, WM_CLOSE, 0, 0); - PUDeletePopup(hDlg); - break; - - case IDNO: - if (IsWindow(pmpd->hDialog)) - SendMessage(pmpd->hDialog, WM_CLOSE, 0, 0); - PUDeletePopup(hDlg); - break; - } - } - } - break; - - case UM_FREEPLUGINDATA: - { - LPMSGPOPUPDATA pmpd = (LPMSGPOPUPDATA)PUGetPluginData(hDlg); - if (pmpd > 0) - mir_free(pmpd); - return TRUE; //TRUE or FALSE is the same, it gets ignored. - } - break; - } - - return DefWindowProc(hDlg, uMsg, wParam, lParam); -} - -static LRESULT CALLBACK PopupDlgProc2(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) { - case WM_COMMAND: - PopupAction(hDlg, PopupOptions.LeftClickAction); - break; - - case WM_CONTEXTMENU: - PopupAction(hDlg, PopupOptions.RightClickAction); - break; - - case UM_FREEPLUGINDATA: - { - LPMSGPOPUPDATA pmpd = (LPMSGPOPUPDATA)PUGetPluginData(hDlg); - if (pmpd > 0) - mir_free(pmpd); - return TRUE; //TRUE or FALSE is the same, it gets ignored. - } - break; - } - - return DefWindowProc(hDlg, uMsg, wParam, lParam); -} - -static void MakePopupAction(POPUPACTION &pa, int id) -{ - pa.cbSize = sizeof(POPUPACTION); - pa.flags = PAF_ENABLED; - pa.wParam = MAKEWORD(id, BN_CLICKED); - pa.lParam = 0; - switch (id) { - case IDYES: - pa.lchIcon = Skin_GetIcon("btn_ok"); - strncpy_s(pa.lpzTitle, MODNAME"/Yes", MAX_ACTIONTITLE); - break; - - case IDNO: - pa.lchIcon = Skin_GetIcon("btn_cancel"); - strncpy_s(pa.lpzTitle, MODNAME"/No", MAX_ACTIONTITLE); - break; - } -} - -void ShowPopup(HWND hDlg, LPCTSTR ptszTitle, LPCTSTR ptszText, int Number, int ActType, bool NoMessageBox) -{ - if (ServiceExists(MS_POPUP_ADDPOPUPT) && db_get_b(NULL, "Popup", "ModuleIsEnabled", 1)) { - LPMSGPOPUPDATA pmpd = (LPMSGPOPUPDATA)mir_alloc(sizeof(MSGPOPUPDATA)); - if (!pmpd) - return; - - POPUPDATAT_V2 pd = { 0 }; - pd.cbSize = sizeof(pd); - pd.lchContact = NULL; //(HANDLE)wParam; - pd.lchIcon = LoadSkinnedIcon(PopupsList[Number].Icon); - pd.PluginWindowProc = (Number == 0 && ActType != 0) ? PopupDlgProc : PopupDlgProc2; - pd.PluginData = pmpd; - pd.iSeconds = (Number == 0) ? -1 : PopupOptions.Timeout; - pd.hNotification = NULL; - pd.lpActions = pmpd->pa; - - lstrcpyn(pd.lptzText, TranslateTS(ptszText), MAX_SECONDLINE); - lstrcpyn(pd.lptzContactName, TranslateTS(ptszTitle), MAX_CONTACTNAME); - - switch (PopupOptions.DefColors) { - case byCOLOR_WINDOWS: - pd.colorBack = GetSysColor(COLOR_BTNFACE); - pd.colorText = GetSysColor(COLOR_WINDOWTEXT); - break; - case byCOLOR_OWN: - pd.colorBack = PopupsList[Number].colorBack; - pd.colorText = PopupsList[Number].colorText; - break; - case byCOLOR_POPUP: - pd.colorBack = pd.colorText = 0; - break; - } - - pmpd->hDialog = hDlg; - - if (ActType == 1) { - MakePopupAction(pmpd->pa[pd.actionCount++], IDYES); - MakePopupAction(pmpd->pa[pd.actionCount++], IDNO); - } - - CallService(MS_POPUP_ADDPOPUPT, (WPARAM)&pd, APF_NEWDATA); - } else if (!NoMessageBox) { - char setting[100]; - mir_snprintf(setting, SIZEOF(setting), "Popups%dM", Number); - if (db_get_b(NULL, MODNAME, setting, DEFAULT_MESSAGE_ENABLED)) { - int iMsgType; - switch( Number ) { - case 1: iMsgType = MB_ICONSTOP; break; - case 2: iMsgType = MB_ICONINFORMATION; break; - case 3: iMsgType = MB_ICONQUESTION; break; - case 4: return; - default: iMsgType = 0; - } - MessageBox(hDlg, TranslateTS(ptszText), TranslateTS(ptszTitle), iMsgType); - } - } -} - -INT_PTR CALLBACK DlgDownload(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) { - case WM_INITDIALOG: - SetWindowText(GetDlgItem(hDlg, IDC_LABEL), tszDialogMsg); - SetWindowLongPtr(GetDlgItem(hDlg, IDC_PB), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hDlg, IDC_PB), GWL_STYLE) | PBS_MARQUEE); - SendMessage(GetDlgItem(hDlg, IDC_PB), PBM_SETMARQUEE, 1, 50); - return TRUE; - } - return FALSE; -} - -INT_PTR CALLBACK DlgDownloadPop(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) { - case WM_INITDIALOG: - PopupDataText *temp = (PopupDataText*)lParam; - ShowPopup(hDlg, temp->Title, temp->Text, 3, 0); - return TRUE; - } - return FALSE; -} - -bool PrepareEscalation() -{ - // First try to create a file near Miranda32.exe - TCHAR szPath[MAX_PATH]; - GetModuleFileName(NULL, szPath, SIZEOF(szPath)); - TCHAR *ext = _tcsrchr(szPath, '.'); - if (ext != NULL) - *ext = '\0'; - _tcscat(szPath, _T(".test")); - HANDLE hFile = CreateFile(szPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile != INVALID_HANDLE_VALUE) { - // we are admins or UAC is disable, cool - CloseHandle(hFile); - DeleteFile(szPath); - return true; - } - - // Check the current process's "run as administrator" status. - if ( IsRunAsAdmin()) - return true; - - // Elevate the process. Create a pipe for a stub first - TCHAR tszPipeName[MAX_PATH]; - mir_sntprintf(tszPipeName, MAX_PATH, _T("\\\\.\\pipe\\Miranda_Pu_%d"), GetCurrentProcessId()); - hPipe = CreateNamedPipe(tszPipeName, PIPE_ACCESS_DUPLEX, PIPE_READMODE_BYTE | PIPE_WAIT, 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL); - if (hPipe == INVALID_HANDLE_VALUE) { - hPipe = NULL; - return false; - } - - TCHAR cmdLine[100], *p; - GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)); - if ((p = _tcsrchr(szPath, '\\')) != 0) - _tcscpy(p+1, _T("pu_stub.exe")); - mir_sntprintf(cmdLine, SIZEOF(cmdLine), _T("%d"), GetCurrentProcessId()); - - // Launch a stub - SHELLEXECUTEINFO sei = { sizeof(sei) }; - sei.lpVerb = L"runas"; - sei.lpFile = szPath; - sei.lpParameters = cmdLine; - sei.hwnd = NULL; - sei.nShow = SW_NORMAL; - if (ShellExecuteEx(&sei)) { - if (hPipe != NULL) - ConnectNamedPipe(hPipe, NULL); - return true; - } - - DWORD dwError = GetLastError(); - if (dwError == ERROR_CANCELLED) - { - // The user refused to allow privileges elevation. - // Do nothing ... - } - return false; -} - -int ImageList_AddIconFromIconLib(HIMAGELIST hIml, const char *name) -{ - HICON icon = Skin_GetIconByHandle(Skin_GetIconHandle(name)); - int res = ImageList_AddIcon(hIml, icon); - Skin_ReleaseIcon(icon); - return res; -} - -INT_PTR CALLBACK DlgMsgPop(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) { - case WM_INITDIALOG: - PopupDataText *temp = (PopupDataText*)lParam; - ShowPopup(hDlg, temp->Title, temp->Text, 0, 1); - return TRUE; - } - ShowWindow(hDlg, SW_HIDE); - return FALSE; -} +/* +Copyright (C) 2010 Mataes + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#include "common.h" + +HANDLE hPipe = NULL; + +void PopupAction(HWND hWnd, BYTE action) +{ + switch (action) { + case PCA_CLOSEPOPUP: + break; + case PCA_DONOTHING: + return; + } + PUDeletePopup(hWnd); +} + +static LRESULT CALLBACK PopupDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case UM_POPUPACTION: + if (HIWORD(wParam) == BN_CLICKED) { + LPMSGPOPUPDATA pmpd = (LPMSGPOPUPDATA)PUGetPluginData(hDlg); + if (pmpd) { + switch (LOWORD(wParam)) { + case IDYES: + if (IsWindow(pmpd->hDialog)) + PostMessage(pmpd->hDialog, WM_CLOSE, 0, 0); + PUDeletePopup(hDlg); + break; + + case IDNO: + if (IsWindow(pmpd->hDialog)) + PostMessage(pmpd->hDialog, WM_CLOSE, 0, 0); + PUDeletePopup(hDlg); + break; + } + } + } + break; + + case UM_FREEPLUGINDATA: + { + LPMSGPOPUPDATA pmpd = (LPMSGPOPUPDATA)PUGetPluginData(hDlg); + if (pmpd > 0) + mir_free(pmpd); + return TRUE; //TRUE or FALSE is the same, it gets ignored. + } + break; + } + + return DefWindowProc(hDlg, uMsg, wParam, lParam); +} + +static LRESULT CALLBACK PopupDlgProc2(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case WM_COMMAND: + PopupAction(hDlg, PopupOptions.LeftClickAction); + break; + + case WM_CONTEXTMENU: + PopupAction(hDlg, PopupOptions.RightClickAction); + break; + + case UM_FREEPLUGINDATA: + { + LPMSGPOPUPDATA pmpd = (LPMSGPOPUPDATA)PUGetPluginData(hDlg); + if (pmpd > 0) + mir_free(pmpd); + return TRUE; //TRUE or FALSE is the same, it gets ignored. + } + break; + } + + return DefWindowProc(hDlg, uMsg, wParam, lParam); +} + +static void MakePopupAction(POPUPACTION &pa, int id) +{ + pa.cbSize = sizeof(POPUPACTION); + pa.flags = PAF_ENABLED; + pa.wParam = MAKEWORD(id, BN_CLICKED); + pa.lParam = 0; + switch (id) { + case IDYES: + pa.lchIcon = Skin_GetIcon("btn_ok"); + strncpy_s(pa.lpzTitle, MODNAME"/Yes", MAX_ACTIONTITLE); + break; + + case IDNO: + pa.lchIcon = Skin_GetIcon("btn_cancel"); + strncpy_s(pa.lpzTitle, MODNAME"/No", MAX_ACTIONTITLE); + break; + } +} + +void ShowPopup(HWND hDlg, LPCTSTR ptszTitle, LPCTSTR ptszText, int Number, int ActType, bool NoMessageBox) +{ + if (ServiceExists(MS_POPUP_ADDPOPUPT) && db_get_b(NULL, "Popup", "ModuleIsEnabled", 1)) { + LPMSGPOPUPDATA pmpd = (LPMSGPOPUPDATA)mir_alloc(sizeof(MSGPOPUPDATA)); + if (!pmpd) + return; + + POPUPDATAT_V2 pd = { 0 }; + pd.cbSize = sizeof(pd); + pd.lchContact = NULL; //(HANDLE)wParam; + pd.lchIcon = LoadSkinnedIcon(PopupsList[Number].Icon); + pd.PluginWindowProc = (Number == 0 && ActType != 0) ? PopupDlgProc : PopupDlgProc2; + pd.PluginData = pmpd; + pd.iSeconds = (Number == 0) ? -1 : PopupOptions.Timeout; + pd.hNotification = NULL; + pd.lpActions = pmpd->pa; + + lstrcpyn(pd.lptzText, TranslateTS(ptszText), MAX_SECONDLINE); + lstrcpyn(pd.lptzContactName, TranslateTS(ptszTitle), MAX_CONTACTNAME); + + switch (PopupOptions.DefColors) { + case byCOLOR_WINDOWS: + pd.colorBack = GetSysColor(COLOR_BTNFACE); + pd.colorText = GetSysColor(COLOR_WINDOWTEXT); + break; + case byCOLOR_OWN: + pd.colorBack = PopupsList[Number].colorBack; + pd.colorText = PopupsList[Number].colorText; + break; + case byCOLOR_POPUP: + pd.colorBack = pd.colorText = 0; + break; + } + + pmpd->hDialog = hDlg; + + if (ActType == 1) { + MakePopupAction(pmpd->pa[pd.actionCount++], IDYES); + MakePopupAction(pmpd->pa[pd.actionCount++], IDNO); + } + + CallService(MS_POPUP_ADDPOPUPT, (WPARAM)&pd, APF_NEWDATA); + } else if (!NoMessageBox) { + char setting[100]; + mir_snprintf(setting, SIZEOF(setting), "Popups%dM", Number); + if (db_get_b(NULL, MODNAME, setting, DEFAULT_MESSAGE_ENABLED)) { + int iMsgType; + switch( Number ) { + case 1: iMsgType = MB_ICONSTOP; break; + case 2: iMsgType = MB_ICONINFORMATION; break; + case 3: iMsgType = MB_ICONQUESTION; break; + case 4: return; + default: iMsgType = 0; + } + MessageBox(hDlg, TranslateTS(ptszText), TranslateTS(ptszTitle), iMsgType); + } + } +} + +INT_PTR CALLBACK DlgDownload(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + case WM_INITDIALOG: + SetWindowText(GetDlgItem(hDlg, IDC_LABEL), tszDialogMsg); + SetWindowLongPtr(GetDlgItem(hDlg, IDC_PB), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hDlg, IDC_PB), GWL_STYLE) | PBS_MARQUEE); + SendMessage(GetDlgItem(hDlg, IDC_PB), PBM_SETMARQUEE, 1, 50); + return TRUE; + } + return FALSE; +} + +INT_PTR CALLBACK DlgDownloadPop(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case WM_INITDIALOG: + PopupDataText *temp = (PopupDataText*)lParam; + ShowPopup(hDlg, temp->Title, temp->Text, 3, 0); + return TRUE; + } + return FALSE; +} + +bool PrepareEscalation() +{ + // First try to create a file near Miranda32.exe + TCHAR szPath[MAX_PATH]; + GetModuleFileName(NULL, szPath, SIZEOF(szPath)); + TCHAR *ext = _tcsrchr(szPath, '.'); + if (ext != NULL) + *ext = '\0'; + _tcscat(szPath, _T(".test")); + HANDLE hFile = CreateFile(szPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile != INVALID_HANDLE_VALUE) { + // we are admins or UAC is disable, cool + CloseHandle(hFile); + DeleteFile(szPath); + return true; + } + + // Check the current process's "run as administrator" status. + if ( IsRunAsAdmin()) + return true; + + // Elevate the process. Create a pipe for a stub first + TCHAR tszPipeName[MAX_PATH]; + mir_sntprintf(tszPipeName, MAX_PATH, _T("\\\\.\\pipe\\Miranda_Pu_%d"), GetCurrentProcessId()); + hPipe = CreateNamedPipe(tszPipeName, PIPE_ACCESS_DUPLEX, PIPE_READMODE_BYTE | PIPE_WAIT, 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL); + if (hPipe == INVALID_HANDLE_VALUE) { + hPipe = NULL; + return false; + } + + TCHAR cmdLine[100], *p; + GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)); + if ((p = _tcsrchr(szPath, '\\')) != 0) + _tcscpy(p+1, _T("pu_stub.exe")); + mir_sntprintf(cmdLine, SIZEOF(cmdLine), _T("%d"), GetCurrentProcessId()); + + // Launch a stub + SHELLEXECUTEINFO sei = { sizeof(sei) }; + sei.lpVerb = L"runas"; + sei.lpFile = szPath; + sei.lpParameters = cmdLine; + sei.hwnd = NULL; + sei.nShow = SW_NORMAL; + if (ShellExecuteEx(&sei)) { + if (hPipe != NULL) + ConnectNamedPipe(hPipe, NULL); + return true; + } + + DWORD dwError = GetLastError(); + if (dwError == ERROR_CANCELLED) + { + // The user refused to allow privileges elevation. + // Do nothing ... + } + return false; +} + +int ImageList_AddIconFromIconLib(HIMAGELIST hIml, const char *name) +{ + HICON icon = Skin_GetIconByHandle(Skin_GetIconHandle(name)); + int res = ImageList_AddIcon(hIml, icon); + Skin_ReleaseIcon(icon); + return res; +} + +INT_PTR CALLBACK DlgMsgPop(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case WM_INITDIALOG: + PopupDataText *temp = (PopupDataText*)lParam; + ShowPopup(hDlg, temp->Title, temp->Text, 0, 1); + return TRUE; + } + ShowWindow(hDlg, SW_HIDE); + return FALSE; +} -- cgit v1.2.3