/* 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; HWND hwndDialog = NULL; static bool bShowDetails; 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)) EndDialog(pmpd->hDialog, LOWORD(wParam)); PUDeletePopup(hDlg); break; case IDNO: if (IsWindow(pmpd->hDialog)) EndDialog(pmpd->hDialog, LOWORD(wParam)); 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) { if ( !ServiceExists(MS_POPUP_ADDPOPUP) || !db_get_b(NULL, "Popup", "ModuleIsEnabled", 1) ) { 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); } return; } 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); 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; } if (Number == 0 && ActType != 0) pd.PluginWindowProc = PopupDlgProc; else pd.PluginWindowProc = PopupDlgProc2; pd.PluginData = pmpd; if (Number == 0) pd.iSeconds = -1; else pd.iSeconds = PopupOptions.Timeout; pd.hNotification = NULL; pd.lpActions = pmpd->pa; pmpd->hDialog = hDlg; switch (ActType) { case 0: break; case 1: MakePopupAction(pmpd->pa[pd.actionCount++], IDYES); MakePopupAction(pmpd->pa[pd.actionCount++], IDNO); break; } CallService(MS_POPUP_ADDPOPUPT, (WPARAM) &pd, APF_NEWDATA); } 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 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) { // 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]; _stprintf_s(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; } wchar_t cmdLine[100], *p; GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)); if ((p = wcsrchr(szPath, '\\')) != 0) wcscpy(p+1, L"pu_stub.exe"); mir_sntprintf(cmdLine, SIZEOF(cmdLine), L"%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; } 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 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 &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); 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 &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); 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)); int res = ImageList_AddIcon(hIml, icon); Skin_ReleaseIcon(icon); 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 &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 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 &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_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 *)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)LoadSkinnedIconBig(SKINICON_OTHER_OPTIONS)); SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadSkinnedIcon(SKINICON_OTHER_OPTIONS)); { 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 = L"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 = LPGENT("Plugins"); lvg.iGroupId = 1; ListView_InsertGroup(hwndList, 0, &lvg); lvg.pszHeader = LPGENT("Icons"); lvg.iGroupId = 2; ListView_InsertGroup(hwndList, 0, &lvg); lvg.pszHeader = LPGENT("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 &todo = *(OBJLIST *)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 &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_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 *)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) { case WM_INITDIALOG: PopupDataText *temp = (PopupDataText*)lParam; ShowPopup(hDlg, temp->Title, temp->Text, 0, 1); return TRUE; } ShowWindow(hDlg, SW_HIDE); return FALSE; }