diff options
author | George Hazan <ghazan@miranda.im> | 2019-09-15 18:36:20 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2019-09-15 18:36:20 +0300 |
commit | 26f471496af2a42967ed322e9b52a93fba553e14 (patch) | |
tree | 29d1900d2b9d0957a8520a61544e0b45711ba7dd /plugins/PluginUpdater/src/DlgListNew.cpp | |
parent | f34a9cbf015c2bb6bd6359c7f68aa0d26656c4f3 (diff) |
PluginUpdater:
- fixes #2057 (PluginUpdater: add search box);
- missing components dialog moved to UI classes;
- version bump
Diffstat (limited to 'plugins/PluginUpdater/src/DlgListNew.cpp')
-rw-r--r-- | plugins/PluginUpdater/src/DlgListNew.cpp | 479 |
1 files changed, 241 insertions, 238 deletions
diff --git a/plugins/PluginUpdater/src/DlgListNew.cpp b/plugins/PluginUpdater/src/DlgListNew.cpp index 0088c4e983..fc256092df 100644 --- a/plugins/PluginUpdater/src/DlgListNew.cpp +++ b/plugins/PluginUpdater/src/DlgListNew.cpp @@ -22,79 +22,10 @@ Boston, MA 02111-1307, USA. static HWND hwndDialog;
static HANDLE hListThread;
-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, todo[i].bEnabled = bEnable);
-}
-
-static void ApplyDownloads(void *param)
-{
- Thread_SetName("PluginUpdater: ApplyDownloads");
-
- 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<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)GetWindowLongPtr(hDlg, GWLP_USERDATA);
- //create needed folders after escalating priviledges. Folders creates when we actually install updates
- wchar_t tszFileTemp[MAX_PATH], tszFileBack[MAX_PATH];
-
- mir_snwprintf(tszFileBack, L"%s\\Backups", g_tszRoot);
- SafeCreateDirectory(tszFileBack);
-
- mir_snwprintf(tszFileTemp, L"%s\\Temp", g_tszRoot);
- SafeCreateDirectory(tszFileTemp);
-
- VARSW tszMirandaPath(L"%miranda_path%");
-
- HNETLIBCONN nlc = nullptr;
- for (int i = 0; i < todo.getCount(); ++i) {
- auto &p = todo[i];
- ListView_EnsureVisible(hwndList, i, FALSE);
- if (p.bEnabled) {
- // download update
- ListView_SetItemText(hwndList, i, 1, TranslateT("Downloading..."));
-
- if (DownloadFile(&p.File, nlc)) {
- ListView_SetItemText(hwndList, i, 1, TranslateT("Succeeded."));
- if (unzip(p.File.tszDiskPath, tszMirandaPath, tszFileBack, false))
- SafeDeleteFile(p.File.tszDiskPath); // remove .zip after successful update
- db_unset(0, DB_MODULE_NEW_FILES, _T2A(p.tszOldName));
- }
- else ListView_SetItemText(hwndList, i, 1, TranslateT("Failed!"));
- }
- else ListView_SetItemText(hwndList, i, 1, TranslateT("Skipped."));
- }
- Netlib_CloseHandle(nlc);
-
- ShowPopup(TranslateT("Plugin Updater"), TranslateT("Download complete"), POPUP_TYPE_INFO);
-
- int rc = MessageBox(hDlg, TranslateT("Download complete. Do you want to go to plugins option page?"), TranslateT("Plugin Updater"), MB_YESNO | MB_ICONQUESTION);
- if (rc == IDYES)
- CallFunctionAsync(OpenPluginOptions, nullptr);
-
- PostMessage(hDlg, WM_CLOSE, 0, 0);
-}
+static void ApplyDownloads(void *param);
/////////////////////////////////////////////////////////////////////////////////////////
-static WNDPROC oldWndProc = nullptr;
-
static LRESULT CALLBACK PluginListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_LBUTTONDOWN) {
@@ -120,20 +51,7 @@ static LRESULT CALLBACK PluginListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LP }
}
- 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;
+ return mir_callNextSubclass(hwnd, PluginListWndProc, msg, wParam, lParam);
}
int ImageList_AddIconFromIconLib(HIMAGELIST hIml, int i)
@@ -144,196 +62,281 @@ int ImageList_AddIconFromIconLib(HIMAGELIST hIml, int i) return res;
}
-INT_PTR CALLBACK DlgList(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+class CMissingPLuginsDlg : public CDlgBase
{
- HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES);
-
- switch (message) {
- case WM_INITDIALOG:
- TranslateDialogDefault(hDlg);
- oldWndProc = (WNDPROC)SetWindowLongPtr(hwndList, GWLP_WNDPROC, (LONG_PTR)PluginListWndProc);
-
- Window_SetIcon_IcoLib(hDlg, iconList[2].hIcolib);
- {
- HIMAGELIST hIml = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 4, 0);
- ImageList_AddIconFromIconLib(hIml, 1);
- ListView_SetImageList(hwndList, hIml, LVSIL_SMALL);
-
- if (IsWinVer7Plus()) {
- wchar_t szPath[MAX_PATH];
- GetModuleFileNameW(nullptr, szPath, _countof(szPath));
- wchar_t *ext = wcsrchr(szPath, '.');
- if (ext != nullptr)
- *ext = '\0';
- wcscat(szPath, L".test");
- HANDLE hFile = CreateFileW(szPath, GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
- if (hFile == INVALID_HANDLE_VALUE)
- Button_SetElevationRequiredState(GetDlgItem(hDlg, IDOK), !IsProcessElevated());
- else {
- CloseHandle(hFile);
- DeleteFile(szPath);
- }
+ OBJLIST<FILEINFO> *todo;
+ CCtrlEdit m_filter;
+ CCtrlListView m_list;
+ CCtrlButton btnOk, btnNone;
+
+ void FillList(const wchar_t *pwszFilter)
+ {
+ m_list.DeleteAllItems();
+
+ LVITEM lvi = { 0 };
+ lvi.mask = LVIF_PARAM | LVIF_GROUPID | LVIF_TEXT | LVIF_IMAGE;
+
+ bool enableOk = false;
+ for (auto &p : *todo) {
+ if (pwszFilter) {
+ wchar_t pathLwr[MAX_PATH];
+ wcsncpy_s(pathLwr, p->tszNewName, _TRUNCATE);
+ wcslwr(pathLwr);
+ if (!wcsstr(pathLwr, pwszFilter))
+ continue;
}
- //////////////////////////////////////////////////////////////////////////////////////
- LVCOLUMN lvc = { 0 };
- lvc.mask = LVCF_WIDTH | LVCF_TEXT;
+ int groupId = 4;
+ if (wcschr(p->tszOldName, L'\\') != nullptr)
+ groupId = (wcsstr(p->tszOldName, L"Plugins") != nullptr) ? 1 : ((wcsstr(p->tszOldName, L"Languages") != nullptr) ? 3 : 2);
+
+ lvi.iItem = todo->indexOf(&p);
+ lvi.lParam = (LPARAM)p;
+ lvi.iGroupId = groupId;
+ lvi.iImage = ((groupId == 1) ? 0 : -1);
+ lvi.pszText = p->tszOldName;
+ m_list.InsertItem(&lvi);
- lvc.pszText = TranslateT("Component Name");
- lvc.cx = 220; // width of column in pixels
- ListView_InsertColumn(hwndList, 0, &lvc);
+ if (p->bEnabled) {
+ enableOk = true;
+ m_list.SetCheckState(lvi.iItem, 1);
+ }
+ }
- lvc.pszText = TranslateT("State");
- lvc.cx = 100; // width of column in pixels
- ListView_InsertColumn(hwndList, 1, &lvc);
+ btnOk.Enable(enableOk);
+ }
- //////////////////////////////////////////////////////////////////////////////////////
- LVGROUP lvg;
- lvg.cbSize = sizeof(LVGROUP);
- lvg.mask = LVGF_HEADER | LVGF_GROUPID;
+ void SelectAll(bool bEnable)
+ {
+ for (int i = 0; i < todo->getCount(); i++)
+ m_list.SetCheckState(i, (*todo)[i].bEnabled = bEnable);
+ }
- lvg.pszHeader = TranslateT("Plugins");
- lvg.iGroupId = 1;
- ListView_InsertGroup(hwndList, 0, &lvg);
+public:
+ CMissingPLuginsDlg(OBJLIST<FILEINFO> *param) :
+ CDlgBase(g_plugin, IDD_MISSINGPLUGINS),
+ todo(param),
+ btnOk(this, IDOK),
+ btnNone(this, IDC_SELNONE),
+ m_list(this, IDC_LIST_UPDATES),
+ m_filter(this, IDC_SEARCH)
+ {
+ m_autoClose = CLOSE_ON_CANCEL;
+ SetParent(GetDesktopWindow());
+ SetMinSize(370, 300);
+
+ btnOk.OnClick = Callback(this, &CMissingPLuginsDlg::onClick_Ok);
+ btnNone.OnClick = Callback(this, &CMissingPLuginsDlg::onClick_None);
+
+ m_filter.OnChange = Callback(this, &CMissingPLuginsDlg::onChange_Filter);
+ m_list.OnItemChanged = Callback(this, &CMissingPLuginsDlg::onItemChanged);
+ }
- lvg.pszHeader = TranslateT("Icons");
- lvg.iGroupId = 2;
- ListView_InsertGroup(hwndList, 0, &lvg);
+ bool OnInitDialog() override
+ {
+ hwndDialog = m_hwnd;
+ mir_subclassWindow(m_list.GetHwnd(), PluginListWndProc);
+
+ Window_SetIcon_IcoLib(m_hwnd, iconList[2].hIcolib);
+
+ HIMAGELIST hIml = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 4, 0);
+ ImageList_AddIconFromIconLib(hIml, 1);
+ m_list.SetImageList(hIml, LVSIL_SMALL);
+
+ if (IsWinVer7Plus()) {
+ wchar_t szPath[MAX_PATH];
+ GetModuleFileNameW(nullptr, szPath, _countof(szPath));
+ wchar_t *ext = wcsrchr(szPath, '.');
+ if (ext != nullptr)
+ *ext = '\0';
+ wcscat(szPath, L".test");
+ HANDLE hFile = CreateFileW(szPath, GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
+ if (hFile == INVALID_HANDLE_VALUE)
+ Button_SetElevationRequiredState(GetDlgItem(m_hwnd, IDOK), !IsProcessElevated());
+ else {
+ CloseHandle(hFile);
+ DeleteFile(szPath);
+ }
+ }
- lvg.pszHeader = TranslateT("Languages");
- lvg.iGroupId = 3;
- ListView_InsertGroup(hwndList, 0, &lvg);
+ //////////////////////////////////////////////////////////////////////////////////////
+ LVCOLUMN lvc = { 0 };
+ lvc.mask = LVCF_WIDTH | LVCF_TEXT;
- lvg.pszHeader = TranslateT("Other");
- lvg.iGroupId = 4;
- ListView_InsertGroup(hwndList, 0, &lvg);
+ lvc.pszText = TranslateT("Component Name");
+ lvc.cx = 220; // width of column in pixels
+ m_list.InsertColumn(0, &lvc);
- ListView_EnableGroupView(hwndList, TRUE);
+ lvc.pszText = TranslateT("State");
+ lvc.cx = 100; // width of column in pixels
+ m_list.InsertColumn(1, &lvc);
- //////////////////////////////////////////////////////////////////////////////////////
- SendMessage(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES | LVS_EX_CHECKBOXES | LVS_EX_LABELTIP);
- ListView_DeleteAllItems(hwndList);
+ //////////////////////////////////////////////////////////////////////////////////////
+ LVGROUP lvg;
+ lvg.cbSize = sizeof(LVGROUP);
+ lvg.mask = LVGF_HEADER | LVGF_GROUPID;
+
+ lvg.pszHeader = TranslateT("Plugins");
+ lvg.iGroupId = 1;
+ m_list.InsertGroup(0, &lvg);
+
+ lvg.pszHeader = TranslateT("Icons");
+ lvg.iGroupId = 2;
+ m_list.InsertGroup(0, &lvg);
+
+ lvg.pszHeader = TranslateT("Languages");
+ lvg.iGroupId = 3;
+ m_list.InsertGroup(0, &lvg);
+
+ lvg.pszHeader = TranslateT("Other");
+ lvg.iGroupId = 4;
+ m_list.InsertGroup(0, &lvg);
+
+ m_list.EnableGroupView(true);
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ m_list.SendMsg(LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES | LVS_EX_CHECKBOXES | LVS_EX_LABELTIP);
+
+ FillList(nullptr);
+
+ // do this after filling list - enables 'ITEMCHANGED' below
+ Utils_RestoreWindowPosition(m_hwnd, 0, MODULENAME, "ListWindow");
+ return true;
+ }
+
+ void OnDestroy() override
+ {
+ Utils_SaveWindowPosition(m_hwnd, NULL, MODULENAME, "ListWindow");
+ Window_FreeIcon_IcoLib(m_hwnd);
+ hwndDialog = nullptr;
+ delete (OBJLIST<FILEINFO> *)GetWindowLongPtr(m_hwnd, GWLP_USERDATA);
+ }
+
+ int Resizer(UTILRESIZECONTROL *urc) override
+ {
+ switch (urc->wId) {
+ case IDC_SELNONE:
+ case IDOK:
+ return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM;
+
+ case IDC_SEARCH:
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP;
+
+ case IDC_UPDATETEXT:
+ return RD_ANCHORX_CENTRE;
+ }
+ return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT;
+ }
+
+ void onItemChanged(CCtrlListView::TEventInfo *ev)
+ {
+ NMLISTVIEW *nmlv = ev->nmlv;
+ if ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK) {
+ LVITEM lvI = { 0 };
+ lvI.iItem = nmlv->iItem;
+ lvI.iSubItem = 0;
+ lvI.mask = LVIF_PARAM;
+ m_list.GetItem(&lvI);
+
+ FILEINFO *p = (FILEINFO *)lvI.lParam;
+ p->bEnabled = m_list.GetCheckState(nmlv->iItem);
- //////////////////////////////////////////////////////////////////////////////////////
bool enableOk = false;
- OBJLIST<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)lParam;
- for (auto &p : todo) {
- LVITEM lvi = { 0 };
- lvi.mask = LVIF_PARAM | LVIF_GROUPID | LVIF_TEXT | LVIF_IMAGE;
-
- int groupId = 4;
- if (wcschr(p->tszOldName, L'\\') != nullptr)
- groupId = (wcsstr(p->tszOldName, L"Plugins") != nullptr) ? 1 : ((wcsstr(p->tszOldName, L"Languages") != nullptr) ? 3 : 2);
-
- lvi.iItem = todo.indexOf(&p);
- lvi.lParam = (LPARAM)p;
- lvi.iGroupId = groupId;
- lvi.iImage = ((groupId == 1) ? 0 : -1);
- lvi.pszText = p->tszOldName;
- ListView_InsertItem(hwndList, &lvi);
-
- if (p->bEnabled) {
+ for (auto &it : *todo) {
+ if (it->bEnabled) {
enableOk = true;
- ListView_SetCheckState(hwndList, lvi.iItem, 1);
+ break;
}
}
- if (enableOk)
- EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
+
+ btnOk.Enable(enableOk);
}
+ }
- // do this after filling list - enables 'ITEMCHANGED' below
- SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam);
- Utils_RestoreWindowPosition(hDlg, 0, MODULENAME, "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;
- if ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK) {
- 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);
- FILEINFO *p = (FILEINFO*)lvI.lParam;
- p->bEnabled = ListView_GetCheckState(hwndList, nmlv->iItem);
-
- bool enableOk = false;
- for (auto &it : todo) {
- if (it->bEnabled) {
- enableOk = true;
- break;
- }
- }
- EnableWindow(GetDlgItem(hDlg, IDOK), enableOk ? TRUE : FALSE);
- }
- }
- break;
- }
+ void onClick_Ok(CCtrlButton *)
+ {
+ btnOk.Disable();
+ btnNone.Disable();
+ mir_forkthread(ApplyDownloads, this);
+ }
+
+ void onClick_None(CCtrlButton *)
+ {
+ SelectAll(false);
+ }
+
+ void onChange_Filter(CCtrlEdit *)
+ {
+ wchar_t wszText[100];
+ m_filter.GetText(wszText, _countof(wszText));
+ if (wszText[0] == 0)
+ FillList(nullptr);
+ else {
+ wcslwr(wszText);
+ FillList(wszText);
}
- 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);
+ void Unpack()
+ {
+ AutoHandle pipe(hPipe);
- mir_forkthread(ApplyDownloads, hDlg);
- return TRUE;
+ // create needed folders after escalating priviledges. Folders creates when we actually install updates
+ wchar_t tszFileTemp[MAX_PATH], tszFileBack[MAX_PATH];
- case IDC_SELNONE:
- SelectAll(hDlg, false);
- break;
+ mir_snwprintf(tszFileBack, L"%s\\Backups", g_tszRoot);
+ SafeCreateDirectory(tszFileBack);
- case IDCANCEL:
- DestroyWindow(hDlg);
- return TRUE;
- }
- }
- break;
+ mir_snwprintf(tszFileTemp, L"%s\\Temp", g_tszRoot);
+ SafeCreateDirectory(tszFileTemp);
- case WM_SIZE: // make the dlg resizeable
- if (!IsIconic(hDlg))
- Utils_ResizeDialog(hDlg, g_plugin.getInst(), MAKEINTRESOURCEA(IDD_LIST), ListDlg_Resize);
- break;
+ VARSW tszMirandaPath(L"%miranda_path%");
- case WM_GETMINMAXINFO:
- {
- LPMINMAXINFO mmi = (LPMINMAXINFO)lParam;
+ HNETLIBCONN nlc = nullptr;
+ for (int i = 0; i < todo->getCount(); ++i) {
+ auto &p = (*todo)[i];
+ m_list.EnsureVisible(i, FALSE);
+ if (p.bEnabled) {
+ // download update
+ m_list.SetItemText(i, 1, TranslateT("Downloading..."));
- // The minimum width in points
- mmi->ptMinTrackSize.x = 370;
- // The minimum height in points
- mmi->ptMinTrackSize.y = 300;
+ if (DownloadFile(&p.File, nlc)) {
+ m_list.SetItemText(i, 1, TranslateT("Succeeded."));
+ if (unzip(p.File.tszDiskPath, tszMirandaPath, tszFileBack, false))
+ SafeDeleteFile(p.File.tszDiskPath); // remove .zip after successful update
+ db_unset(0, DB_MODULE_NEW_FILES, _T2A(p.tszOldName));
+ }
+ else m_list.SetItemText(i, 1, TranslateT("Failed!"));
+ }
+ else m_list.SetItemText(i, 1, TranslateT("Skipped."));
}
- break;
+ Netlib_CloseHandle(nlc);
- case WM_CLOSE:
- DestroyWindow(hDlg);
- break;
+ ShowPopup(TranslateT("Plugin Updater"), TranslateT("Download complete"), POPUP_TYPE_INFO);
- case WM_DESTROY:
- Utils_SaveWindowPosition(hDlg, NULL, MODULENAME, "ListWindow");
- Window_FreeIcon_IcoLib(hDlg);
- hwndDialog = nullptr;
- delete (OBJLIST<FILEINFO> *)GetWindowLongPtr(hDlg, GWLP_USERDATA);
- SetWindowLongPtr(hDlg, GWLP_USERDATA, 0);
- break;
+ int rc = MessageBox(m_hwnd, TranslateT("Download complete. Do you want to go to plugins option page?"), TranslateT("Plugin Updater"), MB_YESNO | MB_ICONQUESTION);
+ if (rc == IDYES)
+ CallFunctionAsync(OpenPluginOptions, nullptr);
+
+ Close();
}
+};
- return FALSE;
+static void ApplyDownloads(void *param)
+{
+ Thread_SetName("PluginUpdater: ApplyDownloads");
+ auto *pDlg = (CMissingPLuginsDlg *)param;
+
+ // if we need to escalate priviledges, launch a atub
+ if (PrepareEscalation())
+ pDlg->Unpack();
+
+ pDlg->Close();
}
static void __stdcall LaunchListDialog(void *param)
{
- hwndDialog = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_LIST), GetDesktopWindow(), DlgList, (LPARAM)param);
+ (new CMissingPLuginsDlg((OBJLIST<FILEINFO> *)param))->Show();
}
static FILEINFO* ServerEntryToFileInfo(const ServListEntry &hash, const wchar_t* tszBaseUrl, const wchar_t* tszPath)
|