diff options
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/PluginUpdater/PluginUpdater_10.vcxproj | 3 | ||||
| -rw-r--r-- | plugins/PluginUpdater/PluginUpdater_10.vcxproj.filters | 7 | ||||
| -rw-r--r-- | plugins/PluginUpdater/PluginUpdater_11.vcxproj | 3 | ||||
| -rw-r--r-- | plugins/PluginUpdater/PluginUpdater_11.vcxproj.filters | 7 | ||||
| -rw-r--r-- | plugins/PluginUpdater/src/Common.h | 44 | ||||
| -rw-r--r-- | plugins/PluginUpdater/src/DlgListNew.cpp | 503 | ||||
| -rw-r--r-- | plugins/PluginUpdater/src/DlgUpdate.cpp (renamed from plugins/PluginUpdater/src/Scanner.cpp) | 506 | ||||
| -rw-r--r-- | plugins/PluginUpdater/src/Notifications.cpp | 620 | 
8 files changed, 837 insertions, 856 deletions
| diff --git a/plugins/PluginUpdater/PluginUpdater_10.vcxproj b/plugins/PluginUpdater/PluginUpdater_10.vcxproj index cf8883ba64..a1ae2d7e2f 100644 --- a/plugins/PluginUpdater/PluginUpdater_10.vcxproj +++ b/plugins/PluginUpdater/PluginUpdater_10.vcxproj @@ -191,6 +191,8 @@    </ItemGroup>
    <ItemGroup>
      <ClCompile Include="src\checksum.cpp" />
 +    <ClCompile Include="src\DlgListNew.cpp" />
 +    <ClCompile Include="src\DlgUpdate.cpp" />
      <ClCompile Include="src\Events.cpp" />
      <ClCompile Include="src\Minizip\ioapi.c">
        <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
 @@ -215,7 +217,6 @@      <ClCompile Include="src\stdafx.cpp">
        <PrecompiledHeader>Create</PrecompiledHeader>
      </ClCompile>
 -    <ClCompile Include="src\Scanner.cpp" />
      <ClCompile Include="src\PluginUpdater.cpp" />
      <ClCompile Include="src\unzipfile.cpp" />
      <ClCompile Include="src\Utils.cpp" />
 diff --git a/plugins/PluginUpdater/PluginUpdater_10.vcxproj.filters b/plugins/PluginUpdater/PluginUpdater_10.vcxproj.filters index ca82a85264..5c464dd0ae 100644 --- a/plugins/PluginUpdater/PluginUpdater_10.vcxproj.filters +++ b/plugins/PluginUpdater/PluginUpdater_10.vcxproj.filters @@ -91,10 +91,13 @@      <ClCompile Include="src\Minizip\unzip.c">
        <Filter>Source Files\Minizip</Filter>
      </ClCompile>
 -    <ClCompile Include="src\Scanner.cpp">
 +    <ClCompile Include="src\stdafx.cpp">
        <Filter>Source Files</Filter>
      </ClCompile>
 -    <ClCompile Include="src\stdafx.cpp">
 +    <ClCompile Include="src\DlgListNew.cpp">
 +      <Filter>Source Files</Filter>
 +    </ClCompile>
 +    <ClCompile Include="src\DlgUpdate.cpp">
        <Filter>Source Files</Filter>
      </ClCompile>
    </ItemGroup>
 diff --git a/plugins/PluginUpdater/PluginUpdater_11.vcxproj b/plugins/PluginUpdater/PluginUpdater_11.vcxproj index 88241dbec3..1a29bced25 100644 --- a/plugins/PluginUpdater/PluginUpdater_11.vcxproj +++ b/plugins/PluginUpdater/PluginUpdater_11.vcxproj @@ -194,6 +194,8 @@    </ItemGroup>
    <ItemGroup>
      <ClCompile Include="src\checksum.cpp" />
 +    <ClCompile Include="src\DlgListNew.cpp" />
 +    <ClCompile Include="src\DlgUpdate.cpp" />
      <ClCompile Include="src\Events.cpp" />
      <ClCompile Include="src\Minizip\ioapi.c">
        <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
 @@ -218,7 +220,6 @@      <ClCompile Include="src\stdafx.cpp">
        <PrecompiledHeader>Create</PrecompiledHeader>
      </ClCompile>
 -    <ClCompile Include="src\Scanner.cpp" />
      <ClCompile Include="src\PluginUpdater.cpp" />
      <ClCompile Include="src\unzipfile.cpp" />
      <ClCompile Include="src\Utils.cpp" />
 diff --git a/plugins/PluginUpdater/PluginUpdater_11.vcxproj.filters b/plugins/PluginUpdater/PluginUpdater_11.vcxproj.filters index 4f6cd1a2b0..5c6b0de410 100644 --- a/plugins/PluginUpdater/PluginUpdater_11.vcxproj.filters +++ b/plugins/PluginUpdater/PluginUpdater_11.vcxproj.filters @@ -91,10 +91,13 @@      <ClCompile Include="src\Minizip\unzip.c">
        <Filter>Source Files\Minizip</Filter>
      </ClCompile>
 -    <ClCompile Include="src\Scanner.cpp">
 +    <ClCompile Include="src\stdafx.cpp">
        <Filter>Source Files</Filter>
      </ClCompile>
 -    <ClCompile Include="src\stdafx.cpp">
 +    <ClCompile Include="src\DlgListNew.cpp">
 +      <Filter>Source Files</Filter>
 +    </ClCompile>
 +    <ClCompile Include="src\DlgUpdate.cpp">
        <Filter>Source Files</Filter>
      </ClCompile>
    </ItemGroup>
 diff --git a/plugins/PluginUpdater/src/Common.h b/plugins/PluginUpdater/src/Common.h index 8c101c5e84..5011421482 100644 --- a/plugins/PluginUpdater/src/Common.h +++ b/plugins/PluginUpdater/src/Common.h @@ -72,9 +72,9 @@ struct FILEURL  struct FILEINFO
  {
 -	TCHAR tszOldName[MAX_PATH], tszNewName[MAX_PATH];
 +	TCHAR   tszOldName[MAX_PATH], tszNewName[MAX_PATH];
  	FILEURL File;
 -	BOOL bEnabled, bDeleteOnly;
 +	BOOL    bEnabled, bDeleteOnly;
  };
  typedef OBJLIST<FILEINFO> FILELIST;
 @@ -147,17 +147,51 @@ INT_PTR MenuCommand(WPARAM wParam,LPARAM lParam);  INT_PTR ShowListCommand(WPARAM wParam,LPARAM lParam);
  INT_PTR EmptyFolder(WPARAM wParam,LPARAM lParam);
 -INT_PTR CALLBACK DlgUpdate(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
 -INT_PTR CALLBACK DlgList(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  INT_PTR CALLBACK DlgMsgPop(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 +int  ImageList_AddIconFromIconLib(HIMAGELIST hIml, const char *name);
 +
  bool unzip(const TCHAR *ptszZipFile, TCHAR *ptszDestPath, TCHAR *ptszBackPath);
  void strdel(TCHAR *parBuffer, int len);
 -//////////////////////////////////////////////////////////
 +///////////////////////////////////////////////////////////////////////////////
 +
 +struct ServListEntry
 +{
 +	ServListEntry(const char* _name, const char* _hash, int _crc) :
 +		m_name( mir_a2t(_name)),
 +		m_bNeedFree(true),
 +		m_crc(_crc)
 +	{
 +		strncpy(m_szHash, _hash, sizeof(m_szHash));
 +	}
 +
 +	ServListEntry(TCHAR* _name) :
 +		m_name(_name),
 +		m_bNeedFree(false)
 +	{
 +	}
 +
 +	~ServListEntry()
 +	{
 +		if (m_bNeedFree)
 +			mir_free(m_name);
 +	}
 +
 +	TCHAR *m_name;
 +	char   m_szHash[32+1];
 +	bool   m_bNeedFree;
 +	int  m_crc;
 +};
 +
 +typedef OBJLIST<ServListEntry> SERVLIST;
 +
 +///////////////////////////////////////////////////////////////////////////////
 +int CalculateModuleHash(const TCHAR *tszFileName, char *dest);
  BOOL IsRunAsAdmin();
  BOOL IsProcessElevated();
 +bool PrepareEscalation();
  int SafeCreateDirectory(const TCHAR *ptszDirName);
  int SafeCopyFile(const TCHAR *ptszSrc, const TCHAR *ptszDst);
 diff --git a/plugins/PluginUpdater/src/DlgListNew.cpp b/plugins/PluginUpdater/src/DlgListNew.cpp new file mode 100644 index 0000000000..3e19a30bd4 --- /dev/null +++ b/plugins/PluginUpdater/src/DlgListNew.cpp @@ -0,0 +1,503 @@ +/*
 +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 void SelectAll(HWND hDlg, bool bEnable)
 +{
 +	OBJLIST<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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()) {
 +		DestroyWindow(hDlg);
 +		return;
 +	}
 +
 +	//////////////////////////////////////////////////////////////////////////////////////
 +	// ok, let's unpack all zips
 +
 +	HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES);
 +	OBJLIST<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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);
 +
 +	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->tszDownloadURL, pFileUrl->tszDiskPath, pFileUrl->CRCsum)){
 +			ListView_SetItemText(hwndList, i, 2, TranslateT("Failed!"));
 +		}
 +		else
 +			ListView_SetItemText(hwndList, i, 2, TranslateT("Succeeded."));
 +	}
 +
 +	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))
 +				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 go to plugins option page?"), SIZEOF(tszBuff));
 +	int rc = MessageBox(NULL, temp.Text, temp.Title, MB_YESNO | MB_ICONQUESTION);
 +	if (rc == IDYES)
 +		CallFunctionAsync(OpenPluginOptions, 0);
 +
 +	if (hPipe)
 +		CloseHandle(hPipe);
 +	CloseWindow(hDlg);
 +	DestroyWindow(hDlg);
 +	hwndDialog = NULL;
 +	return;
 +}
 +
 +/////////////////////////////////////////////////////////////////////////////////////////
 +
 +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) {
 +				TCHAR link[MAX_PATH];
 +				FILEINFO *info = (FILEINFO *)lvi.lParam;
 +
 +				TCHAR tszFileName[MAX_PATH];
 +				_tcscpy(tszFileName, _tcsrchr(info->tszNewName, L'\\') + 1);
 +				TCHAR *p = _tcschr(tszFileName, L'.'); *p = 0;
 +
 +				mir_sntprintf(link, MAX_PATH, L"http://wiki.miranda-ng.org/index.php?title=Plugin:%s", tszFileName);
 +				CallService(MS_UTILS_OPENURL, OUF_TCHAR, (LPARAM) link);
 +			}
 +		}
 +	}
 +
 +	return mir_callNextSubclass(hwnd, PluginListWndProc, msg, wParam, lParam);
 +}
 +
 +static int ListDlg_Resize(HWND, LPARAM, UTILRESIZECONTROL *urc)
 +{
 +	switch (urc->wId) {
 +	case IDC_SELALL:
 +	case IDC_SELNONE:
 +		return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM;
 +
 +	case IDOK:
 +		return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM;
 +	}
 +	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 );
 +		mir_subclassWindow(hwndList, 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("Other");
 +			lvg.iGroupId = 3;
 +			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<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)lParam;
 +			for (int i = 0; i < todo.getCount(); ++i) {
 +				int groupId = 3;
 +				LVITEM lvi = {0};				
 +				lvi.mask = LVIF_PARAM | LVIF_GROUPID | LVIF_TEXT | LVIF_IMAGE;
 +				
 +				if (_tcschr(todo[i].tszOldName, L'\\') != NULL)
 +					groupId = _tcsstr(todo[i].tszOldName, L"Plugins") != NULL ? 1 : 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<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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_SELALL), FALSE);
 +				EnableWindow( GetDlgItem(hDlg, IDC_SELNONE), FALSE);
 +
 +				mir_forkthread(ApplyDownloads, hDlg);
 +				return TRUE;
 +
 +			case IDC_SELALL:
 +				SelectAll(hDlg, true);
 +				break;
 +
 +			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_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<FILEINFO> *)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};
 +	DBVARIANT dbVar = {0};
 +	
 +	TCHAR tszTempPath[MAX_PATH];
 +	DWORD dwLen = GetTempPath(SIZEOF(tszTempPath), tszTempPath);
 +	if (tszTempPath[dwLen-1] == '\\')
 +		tszTempPath[dwLen-1] = 0;
 +
 +	// Load files info
 +	if (db_get_ts(NULL, MODNAME, "UpdateURL", &dbVar)) { // URL is not set
 +		db_set_ts(NULL, MODNAME, "UpdateURL", _T(DEFAULT_UPDATE_URL));
 +		db_get_ts(NULL, MODNAME, "UpdateURL", &dbVar);
 +	}
 +
 +	REPLACEVARSARRAY vars[2];
 +	vars[0].lptzKey = _T("platform");
 +	#ifdef WIN64
 +		vars[0].lptzValue = _T("64");
 +	#else
 +		vars[0].lptzValue = _T("32");
 +	#endif
 +	vars[1].lptzKey = vars[1].lptzValue = 0;
 +
 +	REPLACEVARSDATA dat = { sizeof(REPLACEVARSDATA) };
 +	dat.dwFlags = RVF_TCHAR;
 +	dat.variables = vars;
 +	mir_ptr<TCHAR> tszBaseUrl((TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)dbVar.ptszVal, (LPARAM)&dat));
 +	db_free(&dbVar);
 +
 +	// Download version info
 +	ShowPopup(NULL, TranslateT("Plugin Updater"), TranslateT("Downloading version info..."), 4, 0);
 +
 +	FILEURL pFileUrl;
 +	mir_sntprintf(pFileUrl.tszDownloadURL, SIZEOF(pFileUrl.tszDownloadURL), _T("%s/hashes.zip"), (TCHAR*)tszBaseUrl);
 +	mir_sntprintf(pFileUrl.tszDiskPath, SIZEOF(pFileUrl.tszDiskPath), _T("%s\\hashes.zip"), tszTempPath);
 +	if (!DownloadFile(pFileUrl.tszDownloadURL, pFileUrl.tszDiskPath, 0)) {
 +		ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("An error occured while downloading the update."), 1, 0);
 +		hListThread = NULL;
 +		return;
 +	}
 +
 +	unzip(pFileUrl.tszDiskPath, tszTempPath, NULL);
 +	DeleteFile(pFileUrl.tszDiskPath);
 +
 +	TCHAR tszTmpIni[MAX_PATH] = {0};
 +	mir_sntprintf(tszTmpIni, SIZEOF(tszTmpIni), _T("%s\\hashes.txt"), tszTempPath);
 +	FILE *fp = _tfopen(tszTmpIni, _T("r"));
 +	if (!fp) {
 +		hListThread = NULL;
 +		return;
 +	}
 +
 +	FILELIST *UpdateFiles = new FILELIST(20);
 +	char str[200];
 +	TCHAR *dirname = Utils_ReplaceVarsT(_T("%miranda_path%"));
 +	while(fgets(str, SIZEOF(str), fp) != NULL) {
 +		rtrim(str);
 +		char *p = strchr(str, ' ');
 +		if (p == NULL)
 +			continue;
 +
 +		*p++ = 0;
 +		_strlwr(p);
 +
 +		int dwCrc32;
 +		char *p1 = strchr(p, ' ');
 +		if (p1 == NULL)
 +			dwCrc32 = 0;
 +		else {
 +			*p1++ = 0;
 +			sscanf(p1, "%08x", &dwCrc32);
 +		}
 +		ServListEntry hash(str, p, dwCrc32);
 +
 +		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"), tszBaseUrl, tszRelFileName);
 +		for (tp = _tcschr(FileInfo->File.tszDownloadURL, '\\'); tp != 0; tp = _tcschr(tp, '\\'))
 +			*tp++ = '/';
 +		FileInfo->File.CRCsum = hash.m_crc;
 +		UpdateFiles->insert(FileInfo);
 +	}
 +	fclose(fp);
 +	DeleteFile(tszTmpIni);
 +
 +	mir_free(dirname);
 +
 +	// Show dialog
 +	if (UpdateFiles->getCount() == 0) {
 +		if ( !opts.bSilent)
 +			ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("List is empty."), 2, 0);
 +	}
 +	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);
 +}
 diff --git a/plugins/PluginUpdater/src/Scanner.cpp b/plugins/PluginUpdater/src/DlgUpdate.cpp index eebd69cd62..93ff4fc86b 100644 --- a/plugins/PluginUpdater/src/Scanner.cpp +++ b/plugins/PluginUpdater/src/DlgUpdate.cpp @@ -8,65 +8,308 @@ 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
 +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
 +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"
 +#include "common.h"
 -int CalculateModuleHash(const TCHAR *tszFileName, char *dest);
 +static bool bShowDetails;
 -static BYTE IsPluginDisabled(const char *filename)
 +static void SelectAll(HWND hDlg, bool bEnable)
  {
 -	return db_get_b(NULL, "PluginDisable", filename, 0);
 +	OBJLIST<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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", _T2A(todo[i].tszOldName), todo[i].bEnabled = bEnable);
 +	}
  }
 -static bool Exists(LPCTSTR strName)
 +static void SetStringText(HWND hWnd, size_t i, TCHAR *ptszText)
  {
 -	return GetFileAttributes(strName) != INVALID_FILE_ATTRIBUTES;
 +	ListView_SetItemText(hWnd, i, 1, ptszText);
  }
 -/////////////////////////////////////////////////////////////////////////////////////////
 -
 -struct ServListEntry
 +static void ApplyUpdates(void *param)
  {
 -	ServListEntry(const char* _name, const char* _hash, int _crc) :
 -		m_name( mir_a2t(_name)),
 -		m_bNeedFree(true),
 -		m_crc(_crc)
 -	{
 -		strncpy(m_szHash, _hash, sizeof(m_szHash));
 +	HWND hDlg = (HWND)param;
 +
 +	//////////////////////////////////////////////////////////////////////////////////////
 +	// if we need to escalate priviledges, launch a atub
 +
 +	if ( !PrepareEscalation()) {
 +		DestroyWindow(hDlg);
 +		return;
 +	}
 +
 +	//////////////////////////////////////////////////////////////////////////////////////
 +	// ok, let's unpack all zips
 +
 +	HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES);
 +	OBJLIST<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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);
 +
 +	for (int i=0; i < todo.getCount(); ++i) {
 +		ListView_EnsureVisible(hwndList, i, FALSE);
 +		if ( !todo[i].bEnabled) {
 +			SetStringText(hwndList, i, TranslateT("Skipped."));
 +			continue;
 +		}
 +		if (todo[i].bDeleteOnly) {
 +			SetStringText(hwndList, i, TranslateT("Will be deleted!"));
 +			continue;
 +		}
 +
 +		// download update
 +		SetStringText(hwndList, i, TranslateT("Downloading..."));
 +
 +		FILEURL *pFileUrl = &todo[i].File;
 +		if ( !DownloadFile(pFileUrl->tszDownloadURL, pFileUrl->tszDiskPath, pFileUrl->CRCsum))
 +			SetStringText(hwndList, i, TranslateT("Failed!"));
 +		else
 +			SetStringText(hwndList, i, TranslateT("Succeeded."));
  	}
 -	ServListEntry(TCHAR* _name) :
 -		m_name(_name),
 -		m_bNeedFree(false)
 -	{
 +	if (todo.getCount() == 0) {
 +LBL_Exit:
 +		if (hPipe)
 +			CloseHandle(hPipe);
 +		DestroyWindow(hDlg);
 +		return;
  	}
 -	~ServListEntry()
 -	{
 -		if (m_bNeedFree)
 -			mir_free(m_name);
 +	PopupDataText temp;
 +	temp.Title = TranslateT("Plugin Updater");
 +	temp.Text = tszBuff;
 +	lstrcpyn(tszBuff, TranslateT("Download complete. Start updating? All your data will be saved and Miranda NG will be closed."), SIZEOF(tszBuff));
 +	int rc = MessageBox(NULL, temp.Text, temp.Title, MB_YESNO | MB_ICONQUESTION);
 +	if (rc != IDYES) {
 +		mir_sntprintf(tszBuff, SIZEOF(tszBuff), TranslateT("You have chosen not to install the plugin updates immediately.\nYou can install it manually from this location:\n\n%s"), tszFileTemp);
 +		ShowPopup(0, LPGENT("Plugin Updater"), tszBuff, 2, 0);
 +		goto LBL_Exit;
  	}
 -	TCHAR *m_name;
 -	char   m_szHash[32+1];
 -	bool   m_bNeedFree;
 -	int  m_crc;
 -};
 +	TCHAR *tszMirandaPath = Utils_ReplaceVarsT(_T("%miranda_path%"));
 -static int CompareHashes(const ServListEntry *p1, const ServListEntry *p2)
 +	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))
 +			SafeDeleteFile(p.File.tszDiskPath);  // remove .zip after successful update
 +	}
 +
 +	db_set_b(NULL, MODNAME, "RestartCount", 2);
 +	CallFunctionAsync(RestartMe, 0);
 +	goto LBL_Exit;
 +}
 +
 +static void ResizeVert(HWND hDlg, int yy)
  {
 -	return _tcsicmp(p1->m_name, p2->m_name);
 +	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:
 +		hwndDialog = hDlg;
 +		TranslateDialogDefault( hDlg );
 +		SendMessage(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES);
 +		{
 +			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;
 +
 +			OBJLIST<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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", _T2A(todo[i].tszOldName), true);
 +				ListView_SetCheckState(hwndList, lvI.iItem, todo[i].bEnabled);
 +			}
 +			HWND hwOk = GetDlgItem(hDlg, IDOK);
 +			EnableWindow(hwOk, true);
 +		}
 +
 +		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<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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", _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);
 +				break;
 +
 +			case IDC_SELALL:
 +				SelectAll(hDlg, true);
 +				break;
 +
 +			case IDC_SELNONE:
 +				SelectAll(hDlg, false);
 +				break;
 +
 +			case IDCANCEL:
 +				Utils_SaveWindowPosition(hDlg, NULL, MODNAME, "ConfirmWindow");
 +				DestroyWindow(hDlg);
 +				return TRUE;
 +			}
 +		}
 +		break;
 +
 +	case WM_DESTROY:
 +		Utils_SaveWindowPosition(hDlg, NULL, MODNAME, "ConfirmWindow");
 +		hwndDialog = NULL;
 +		delete (OBJLIST<FILEINFO> *)GetWindowLongPtr(hDlg, GWLP_USERDATA);
 +		SetWindowLongPtr(hDlg, GWLP_USERDATA, 0);
 +		break;
 +	}
 +
 +	return FALSE;
 +}
 +
 +static void __stdcall LaunchDialog(void *param)
 +{
 +	CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_UPDATE), GetDesktopWindow(), DlgUpdate, (LPARAM)param);
  }
  /////////////////////////////////////////////////////////////////////////////////////////
 +// building file list in the separate thread
  struct
  {
 @@ -143,7 +386,12 @@ static bool CheckFileRename(const TCHAR *ptszOldName, TCHAR *pNewName)  	return false;
  }
 -typedef OBJLIST<ServListEntry> SERVLIST;
 +/////////////////////////////////////////////////////////////////////////////////////////
 +
 +static int CompareHashes(const ServListEntry *p1, const ServListEntry *p2)
 +{
 +	return _tcsicmp(p1->m_name, p2->m_name);
 +}
  static bool isValidExtension(const TCHAR *ptszFileName)
  {
 @@ -267,62 +515,6 @@ static void ScanFolder(const TCHAR *tszFolder, size_t cbBaseLen, int level, cons  	FindClose(hFind);
  }
 -static void GetFullComponent(const TCHAR *tszFolder, const TCHAR *tszBaseUrl, SERVLIST& hashes, OBJLIST<FILEINFO> *UpdateFiles)
 -{
 -	// skip updater's own folder
 -	if ( !_tcsicmp(tszFolder, tszRoot))
 -		return;
 -	
 -	TCHAR tszPath[MAX_PATH];
 -	for (int i = 0 ; i < hashes.getCount(); i++)
 -	{
 -		mir_sntprintf(tszPath, SIZEOF(tszPath), _T("%s\\%s"), tszFolder, hashes[i].m_name);
 -		
 -		// this file exist on disk
 -		if (GetFileAttributes(tszPath) != DWORD(-1))
 -			continue;
 -
 -		{
 -			ServListEntry tmp(hashes[i].m_name);
 -			ServListEntry *item = hashes.find(&tmp);
 -
 -			FILEINFO *FileInfo = new FILEINFO;
 -			FileInfo->bDeleteOnly = FALSE;
 -			_tcscpy(FileInfo->tszOldName, item->m_name); // copy the relative old name
 -			_tcscpy(FileInfo->tszNewName, item->m_name);
 -
 -			TCHAR tszFileName[MAX_PATH];
 -			_tcscpy(tszFileName, _tcsrchr(tszPath, L'\\') + 1);
 -			TCHAR *p = _tcschr(tszFileName, L'.'); *p = 0;
 -
 -			TCHAR tszRelFileName[MAX_PATH];
 -			_tcscpy(tszRelFileName, item->m_name);
 -			p = _tcschr(tszRelFileName, L'.'); *p = 0;
 -			p = _tcschr(tszRelFileName, L'\\');
 -			p = (p) ? p+1 : tszRelFileName;
 -			_tcslwr(p);
 -
 -
 -			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"), tszBaseUrl, tszRelFileName);
 -			for (p = _tcschr(FileInfo->File.tszDownloadURL, '\\'); p != 0; p = _tcschr(p, '\\'))
 -				*p++ = '/';
 -			FileInfo->File.CRCsum = item->m_crc;
 -			UpdateFiles->insert(FileInfo);
 -		} // end compare versions
 -	}
 -}
 -
 -static void __stdcall LaunchDialog(void *param)
 -{
 -	CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_UPDATE), GetDesktopWindow(), DlgUpdate, (LPARAM)param);
 -}
 -
 -static void __stdcall LaunchListDialog(void *param)
 -{
 -	CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_LIST), GetDesktopWindow(), DlgList, (LPARAM)param);
 -}
 -
  static void CheckUpdates(void *)
  {
  	char szKey[64] = {0};
 @@ -419,129 +611,6 @@ static void CheckUpdates(void *)  	hCheckThread = NULL;
  }
 -static void GetList(void *)
 -{
 -	char szKey[64] = {0};
 -	DBVARIANT dbVar = {0};
 -	
 -	TCHAR tszTempPath[MAX_PATH];
 -	DWORD dwLen = GetTempPath(SIZEOF(tszTempPath), tszTempPath);
 -	if (tszTempPath[dwLen-1] == '\\')
 -		tszTempPath[dwLen-1] = 0;
 -
 -	// Load files info
 -	if (db_get_ts(NULL, MODNAME, "UpdateURL", &dbVar)) { // URL is not set
 -		db_set_ts(NULL, MODNAME, "UpdateURL", _T(DEFAULT_UPDATE_URL));
 -		db_get_ts(NULL, MODNAME, "UpdateURL", &dbVar);
 -	}
 -
 -	REPLACEVARSARRAY vars[2];
 -	vars[0].lptzKey = _T("platform");
 -	#ifdef WIN64
 -		vars[0].lptzValue = _T("64");
 -	#else
 -		vars[0].lptzValue = _T("32");
 -	#endif
 -	vars[1].lptzKey = vars[1].lptzValue = 0;
 -
 -	REPLACEVARSDATA dat = { sizeof(REPLACEVARSDATA) };
 -	dat.dwFlags = RVF_TCHAR;
 -	dat.variables = vars;
 -	mir_ptr<TCHAR> tszBaseUrl((TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)dbVar.ptszVal, (LPARAM)&dat));
 -	db_free(&dbVar);
 -
 -	// Download version info
 -	ShowPopup(NULL, TranslateT("Plugin Updater"), TranslateT("Downloading version info..."), 4, 0);
 -
 -	FILEURL pFileUrl;
 -	mir_sntprintf(pFileUrl.tszDownloadURL, SIZEOF(pFileUrl.tszDownloadURL), _T("%s/hashes.zip"), (TCHAR*)tszBaseUrl);
 -	mir_sntprintf(pFileUrl.tszDiskPath, SIZEOF(pFileUrl.tszDiskPath), _T("%s\\hashes.zip"), tszTempPath);
 -	if (!DownloadFile(pFileUrl.tszDownloadURL, pFileUrl.tszDiskPath, 0)) {
 -		ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("An error occured while downloading the update."), 1, 0);
 -		hListThread = NULL;
 -		return;
 -	}
 -
 -	unzip(pFileUrl.tszDiskPath, tszTempPath, NULL);
 -	DeleteFile(pFileUrl.tszDiskPath);
 -
 -	TCHAR tszTmpIni[MAX_PATH] = {0};
 -	mir_sntprintf(tszTmpIni, SIZEOF(tszTmpIni), _T("%s\\hashes.txt"), tszTempPath);
 -	FILE *fp = _tfopen(tszTmpIni, _T("r"));
 -	if (!fp) {
 -		hListThread = NULL;
 -		return;
 -	}
 -
 -	//SERVLIST hashes(50, CompareHashes);
 -	FILELIST *UpdateFiles = new FILELIST(20);
 -	char str[200];
 -	TCHAR *dirname = Utils_ReplaceVarsT(_T("%miranda_path%"));
 -	while(fgets(str, SIZEOF(str), fp) != NULL) {
 -		rtrim(str);
 -		char *p = strchr(str, ' ');
 -		if (p == NULL)
 -			continue;
 -
 -		*p++ = 0;
 -		/*if ( !opts.bUpdateIcons && !_strnicmp(str, "icons\\", 6))
 -			continue;*/
 -
 -		_strlwr(p);
 -
 -		int dwCrc32;
 -		char *p1 = strchr(p, ' ');
 -		if (p1 == NULL)
 -			dwCrc32 = 0;
 -		else {
 -			*p1++ = 0;
 -			sscanf(p1, "%08x", &dwCrc32);
 -		}
 -		ServListEntry hash(str, p, dwCrc32);
 -
 -		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"), tszBaseUrl, tszRelFileName);
 -		for (tp = _tcschr(FileInfo->File.tszDownloadURL, '\\'); tp != 0; tp = _tcschr(tp, '\\'))
 -			*tp++ = '/';
 -		FileInfo->File.CRCsum = hash.m_crc;
 -		UpdateFiles->insert(FileInfo);
 -	}
 -	fclose(fp);
 -	DeleteFile(tszTmpIni);
 -
 -	mir_free(dirname);
 -
 -	// Show dialog
 -	if (UpdateFiles->getCount() == 0) {
 -		if ( !opts.bSilent)
 -			ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("List is empty."), 2, 0);
 -	}
 -	else CallFunctionAsync(LaunchListDialog, UpdateFiles);
 -
 -	hListThread = NULL;
 -}
 -
  void DoCheck(int iFlag)
  {
  	if (hCheckThread)
 @@ -556,16 +625,3 @@ void DoCheck(int iFlag)  		db_set_dw(NULL, MODNAME, "LastUpdate", time(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);
 -}
 diff --git a/plugins/PluginUpdater/src/Notifications.cpp b/plugins/PluginUpdater/src/Notifications.cpp index 762cfb0170..b054f76a04 100644 --- a/plugins/PluginUpdater/src/Notifications.cpp +++ b/plugins/PluginUpdater/src/Notifications.cpp @@ -21,7 +21,6 @@ Boston, MA 02111-1307, USA.  HANDLE hPipe = NULL;
  HWND hwndDialog = NULL;
 -static bool bShowDetails;
  void PopupAction(HWND hWnd, BYTE action)
  {
 @@ -263,219 +262,6 @@ bool PrepareEscalation()  	return false;
  }
 -void SelectAll(HWND hDlg, bool bEnable)
 -{
 -	OBJLIST<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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 SetStringText(HWND hWnd, size_t i, TCHAR *ptszText)
 -{
 -	ListView_SetItemText(hWnd, i, 1, ptszText);
 -}
 -
 -static void ApplyUpdates(void *param)
 -{
 -	HWND hDlg = (HWND)param;
 -
 -	//////////////////////////////////////////////////////////////////////////////////////
 -	// if we need to escalate priviledges, launch a atub
 -
 -	if ( !PrepareEscalation()) {
 -		DestroyWindow(hDlg);
 -		return;
 -	}
 -
 -	//////////////////////////////////////////////////////////////////////////////////////
 -	// ok, let's unpack all zips
 -
 -	HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES);
 -	OBJLIST<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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);
 -
 -	for (int i=0; i < todo.getCount(); ++i) {
 -		ListView_EnsureVisible(hwndList, i, FALSE);
 -		if ( !todo[i].bEnabled) {
 -			SetStringText(hwndList, i, TranslateT("Skipped."));
 -			continue;
 -		}
 -		if (todo[i].bDeleteOnly) {
 -			SetStringText(hwndList, i, TranslateT("Will be deleted!"));
 -			continue;
 -		}
 -
 -		// download update
 -		SetStringText(hwndList, i, TranslateT("Downloading..."));
 -
 -		FILEURL *pFileUrl = &todo[i].File;
 -		if ( !DownloadFile(pFileUrl->tszDownloadURL, pFileUrl->tszDiskPath, pFileUrl->CRCsum))
 -			SetStringText(hwndList, i, TranslateT("Failed!"));
 -		else
 -			SetStringText(hwndList, i, TranslateT("Succeeded."));
 -	}
 -
 -	if (todo.getCount() == 0) {
 -LBL_Exit:
 -		if (hPipe)
 -			CloseHandle(hPipe);
 -		DestroyWindow(hDlg);
 -		return;
 -	}
 -
 -	PopupDataText temp;
 -	temp.Title = TranslateT("Plugin Updater");
 -	temp.Text = tszBuff;
 -	lstrcpyn(tszBuff, TranslateT("Download complete. Start updating? All your data will be saved and Miranda NG will be closed."), SIZEOF(tszBuff));
 -	int rc = MessageBox(NULL, temp.Text, temp.Title, MB_YESNO | MB_ICONQUESTION);
 -	if (rc != IDYES) {
 -		mir_sntprintf(tszBuff, SIZEOF(tszBuff), TranslateT("You have chosen not to install the plugin updates immediately.\nYou can install it manually from this location:\n\n%s"), tszFileTemp);
 -		ShowPopup(0, LPGENT("Plugin Updater"), tszBuff, 2, 0);
 -		goto LBL_Exit;
 -	}
 -
 -	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))
 -			SafeDeleteFile(p.File.tszDiskPath);  // remove .zip after successful update
 -	}
 -
 -	db_set_b(NULL, MODNAME, "RestartCount", 2);
 -	CallFunctionAsync(RestartMe, 0);
 -	goto LBL_Exit;
 -}
 -
 -static void ApplyDownloads(void *param)
 -{
 -	HWND hDlg = (HWND)param;
 -
 -	//////////////////////////////////////////////////////////////////////////////////////
 -	// if we need to escalate priviledges, launch a atub
 -
 -	if ( !PrepareEscalation()) {
 -		DestroyWindow(hDlg);
 -		return;
 -	}
 -
 -	//////////////////////////////////////////////////////////////////////////////////////
 -	// ok, let's unpack all zips
 -
 -	HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES);
 -	OBJLIST<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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);
 -
 -	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->tszDownloadURL, pFileUrl->tszDiskPath, pFileUrl->CRCsum)){
 -			ListView_SetItemText(hwndList, i, 2, TranslateT("Failed!"));
 -		}
 -		else
 -			ListView_SetItemText(hwndList, i, 2, TranslateT("Succeeded."));
 -	}
 -
 -	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))
 -				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 go to plugins option page?"), SIZEOF(tszBuff));
 -	int rc = MessageBox(NULL, temp.Text, temp.Title, MB_YESNO | MB_ICONQUESTION);
 -	if (rc == IDYES)
 -		CallFunctionAsync(OpenPluginOptions, 0);
 -
 -	if (hPipe)
 -		CloseHandle(hPipe);
 -	CloseWindow(hDlg);
 -	DestroyWindow(hDlg);
 -	hwndDialog = NULL;
 -	return;
 -}
 -
 -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);
 -}
 -
  int ImageList_AddIconFromIconLib(HIMAGELIST hIml, const char *name)
  {
  	HICON icon = Skin_GetIconByHandle(Skin_GetIconHandle(name));
 @@ -484,412 +270,6 @@ int ImageList_AddIconFromIconLib(HIMAGELIST hIml, const char *name)  	return res;
  }
 -INT_PTR CALLBACK DlgUpdate(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
 -{
 -	HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES);
 -
 -	switch (message) {
 -	case WM_INITDIALOG:
 -		hwndDialog = hDlg;
 -		TranslateDialogDefault( hDlg );
 -		SendMessage(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES);
 -		{
 -			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;
 -
 -			OBJLIST<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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
 -				ListView_SetCheckState(hwndList, lvI.iItem, true);
 -				todo[i].bEnabled = true;
 -			}
 -			HWND hwOk = GetDlgItem(hDlg, IDOK);
 -			EnableWindow(hwOk, true);
 -		}
 -
 -		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<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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_SELALL), FALSE);
 -				EnableWindow( GetDlgItem(hDlg, IDC_SELNONE), FALSE);
 -
 -				mir_forkthread(ApplyUpdates, hDlg);
 -				return TRUE;
 -
 -			case IDC_DETAILS:
 -				bShowDetails = !bShowDetails;
 -				ResizeVert(hDlg, bShowDetails ? 242 : 60);
 -				break;
 -
 -			case IDC_SELALL:
 -				SelectAll(hDlg, true);
 -				break;
 -
 -			case IDC_SELNONE:
 -				SelectAll(hDlg, false);
 -				break;
 -
 -			case IDCANCEL:
 -				Utils_SaveWindowPosition(hDlg, NULL, MODNAME, "ConfirmWindow");
 -				DestroyWindow(hDlg);
 -				return TRUE;
 -			}
 -		}
 -		break;
 -
 -	case WM_DESTROY:
 -		Utils_SaveWindowPosition(hDlg, NULL, MODNAME, "ConfirmWindow");
 -		hwndDialog = NULL;
 -		delete (OBJLIST<FILEINFO> *)GetWindowLongPtr(hDlg, GWLP_USERDATA);
 -		SetWindowLongPtr(hDlg, GWLP_USERDATA, 0);
 -		break;
 -	}
 -
 -	return FALSE;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -
 -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) {
 -				TCHAR link[MAX_PATH];
 -				FILEINFO *info = (FILEINFO *)lvi.lParam;
 -
 -				TCHAR tszFileName[MAX_PATH];
 -				_tcscpy(tszFileName, _tcsrchr(info->tszNewName, L'\\') + 1);
 -				TCHAR *p = _tcschr(tszFileName, L'.'); *p = 0;
 -
 -				mir_sntprintf(link, MAX_PATH, L"http://wiki.miranda-ng.org/index.php?title=Plugin:%s", tszFileName);
 -				CallService(MS_UTILS_OPENURL, OUF_TCHAR, (LPARAM) link);
 -			}
 -		}
 -	}
 -
 -	return mir_callNextSubclass(hwnd, PluginListWndProc, msg, wParam, lParam);
 -}
 -
 -static int ListDlg_Resize(HWND, LPARAM, UTILRESIZECONTROL *urc)
 -{
 -	switch (urc->wId) {
 -	case IDC_SELALL:
 -	case IDC_SELNONE:
 -		return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM;
 -
 -	case IDOK:
 -		return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM;
 -	}
 -	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 );
 -		mir_subclassWindow(hwndList, 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("Other");
 -			lvg.iGroupId = 3;
 -			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<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)lParam;
 -			for (int i = 0; i < todo.getCount(); ++i) {
 -				int groupId = 3;
 -				LVITEM lvi = {0};				
 -				lvi.mask = LVIF_PARAM | LVIF_GROUPID | LVIF_TEXT | LVIF_IMAGE;
 -				
 -				if (_tcschr(todo[i].tszOldName, L'\\') != NULL)
 -					groupId = _tcsstr(todo[i].tszOldName, L"Plugins") != NULL ? 1 : 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<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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_SELALL), FALSE);
 -				EnableWindow( GetDlgItem(hDlg, IDC_SELNONE), FALSE);
 -
 -				mir_forkthread(ApplyDownloads, hDlg);
 -				return TRUE;
 -
 -			case IDC_DETAILS:
 -				bShowDetails = !bShowDetails;
 -				ResizeVert(hDlg, bShowDetails ? 242 : 60);
 -				break;
 -
 -			case IDC_SELALL:
 -				SelectAll(hDlg, true);
 -				break;
 -
 -			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_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<FILEINFO> *)GetWindowLongPtr(hDlg, GWLP_USERDATA);
 -		SetWindowLongPtr(hDlg, GWLP_USERDATA, 0);
 -		break;
 -	}
 -
 -	return FALSE;
 -}
 -
  INT_PTR CALLBACK DlgMsgPop(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  {
  	switch (uMsg) {
 | 
