From 333c54939f30f1d9d4e00a5141d421ecb5b1f92f Mon Sep 17 00:00:00 2001 From: George Hazan Date: Tue, 17 Jul 2018 23:02:35 +0300 Subject: AssocMgr: - fixes #1506 (AssocMgr: some protocols have icon only if checked); - massive code cleaning; - version bump --- plugins/AssocMgr/src/assoclist.cpp | 426 +++++++++++++++---------------------- plugins/AssocMgr/src/assoclist.h | 24 +++ plugins/AssocMgr/src/reg.cpp | 73 ++++--- plugins/AssocMgr/src/reg.h | 2 +- plugins/AssocMgr/src/version.h | 2 +- 5 files changed, 237 insertions(+), 290 deletions(-) (limited to 'plugins/AssocMgr') diff --git a/plugins/AssocMgr/src/assoclist.cpp b/plugins/AssocMgr/src/assoclist.cpp index 9b2db86cbd..1604ea27ca 100644 --- a/plugins/AssocMgr/src/assoclist.cpp +++ b/plugins/AssocMgr/src/assoclist.cpp @@ -21,26 +21,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "stdafx.h" -// Options -static HANDLE hHookOptInit; - /************************* Assoc List *****************************/ -typedef struct -{ - char *pszClassName; // class name as used in registry and db - wchar_t *pszDescription; - HINSTANCE hInstance; // allowed to be NULL for miranda32.exe - WORD nIconResID; - char *pszService; - WORD flags; // set of FTDF_* and UTDF_* flags - char *pszFileExt; // file type: NULL for url type - char *pszMimeType; // file type: allowed to be NULL - wchar_t *pszVerbDesc; // file type: allowed to be NULL -} ASSOCDATA; - -static ASSOCDATA *pAssocList; // protected by csAssocList -static int nAssocListCount; // protected by csAssocList +static OBJLIST arAssocList(10, PtrKeySortT); static mir_cs csAssocList; /************************* Assoc Enabled **************************/ @@ -135,19 +118,22 @@ static __inline BOOL WasMimeTypeAdded(const char *pszMimeType) void CleanupMimeTypeAddedSettings(void) { int nSettingsCount; - char **ppszSettings, *pszSuffix; - DBVARIANT dbv; - int i, j; + char **ppszSettings; // delete old mime_* settings and unregister the associated mime type if (EnumDbPrefixSettings(MODULENAME, "mime_", &ppszSettings, &nSettingsCount)) { mir_cslock lck(csAssocList); - for (i = 0; i < nSettingsCount; ++i) { - pszSuffix = &ppszSettings[i][5]; - for (j = 0; j < nAssocListCount; ++j) - if (!mir_strcmp(pszSuffix, pAssocList[j].pszMimeType)) + for (int i = 0; i < nSettingsCount; ++i) { + char *pszSuffix = &ppszSettings[i][5]; + ASSOCDATA *p = nullptr; + for (auto &it : arAssocList) + if (!mir_strcmp(pszSuffix, it->pszMimeType)) { + p = it; break; // mime type in current list - if (j == nAssocListCount) { // mime type not in current list + } + + if (p == nullptr) { // mime type not in current list + DBVARIANT dbv; if (!db_get(NULL, MODULENAME, ppszSettings[i], &dbv)) { if (dbv.type == DBVT_ASCIIZ) RemoveRegMimeType(pszSuffix, dbv.pszVal); @@ -190,71 +176,39 @@ static void NotifyAssocChange(BOOL fNow) /************************* Assoc List Utils ***********************/ // this function assumes it has got the csAssocList mutex -static int FindAssocItem(const char *pszClassName) +static ASSOCDATA* FindAssocItem(const char *pszClassName) { - int i; - for (i = 0; i < nAssocListCount; ++i) - if (!mir_strcmp(pszClassName, pAssocList[i].pszClassName)) - return i; - return -1; + for (auto &it : arAssocList) + if (!mir_strcmp(pszClassName, it->pszClassName)) + return it; + + return nullptr; } BOOL IsRegisteredAssocItem(const char *pszClassName) { - int index; mir_cslock lck(csAssocList); - index = FindAssocItem(pszClassName); - return index != -1; -} - - -// this function assumes it has got the csAssocList mutex -static ASSOCDATA* CopyAssocItem(const ASSOCDATA *assoc) -{ - ASSOCDATA *assoc2; - assoc2 = (ASSOCDATA*)mir_alloc(sizeof(ASSOCDATA)); - if (assoc2 == nullptr) return nullptr; - assoc2->pszClassName = mir_strdup(assoc->pszClassName); - assoc2->pszDescription = mir_wstrdup(assoc->pszDescription); - assoc2->hInstance = assoc->hInstance; - assoc2->nIconResID = assoc->nIconResID; - assoc2->pszService = mir_strdup(assoc->pszService); - assoc2->flags = assoc->flags; - assoc2->pszFileExt = mir_strdup(assoc->pszFileExt); - assoc2->pszMimeType = mir_strdup(assoc->pszMimeType); - assoc2->pszVerbDesc = mir_wstrdup(assoc->pszVerbDesc); - if (assoc2->pszClassName == nullptr || assoc2->pszDescription == nullptr || - (assoc2->pszFileExt == nullptr && assoc->pszFileExt != nullptr)) { - mir_free(assoc2->pszClassName); // does NULL check - mir_free(assoc2->pszDescription); // does NULL check - mir_free(assoc2->pszService); // does NULL check - mir_free(assoc2->pszFileExt); // does NULL check - mir_free(assoc2->pszMimeType); // does NULL check - mir_free(assoc2->pszVerbDesc); // does NULL check - mir_free(assoc2); - return nullptr; - } - return assoc2; + return FindAssocItem(pszClassName) != nullptr; } // this function assumes it has got the csAssocList mutex // this function assumes CoInitialize() has been called before -static int ReplaceImageListAssocIcon(HIMAGELIST himl, const ASSOCDATA *assoc, int iPrevIndex) +static int ReplaceImageListAssocIcon(HIMAGELIST himl, ASSOCDATA *assoc, int iPrevIndex) { - HICON hIcon = nullptr; - int index; - if (himl == nullptr) return -1; + if (himl == nullptr) + return -1; // load icon - hIcon = LoadRegClassSmallIcon(assoc->pszClassName); + HICON hIcon = LoadRegClassSmallIcon(assoc); if (hIcon == nullptr) { SHFILEINFOA sfi; if (SHGetFileInfoA((assoc->pszFileExt != nullptr) ? assoc->pszFileExt : "", FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES)) hIcon = sfi.hIcon; // WinXP: this icon is not updated until the process exits } // add icon - if (hIcon == nullptr) return -1; - index = ImageList_ReplaceIcon(himl, iPrevIndex, hIcon); + if (hIcon == nullptr) + return -1; + int index = ImageList_ReplaceIcon(himl, iPrevIndex, hIcon); DestroyIcon(hIcon); return index; } @@ -390,23 +344,15 @@ typedef struct // ownership of pszClassName, pszFileExt, pszVerbDesc and pszMimeType is transfered // to the storage list on success -static BOOL AddNewAssocItem_Worker(char *pszClassName, const TYPEDESCHEAD *tdh, char *pszFileExt, wchar_t *pszVerbDesc, char *pszMimeType) +static bool AddNewAssocItem_Worker(char *pszClassName, const TYPEDESCHEAD *tdh, char *pszFileExt, wchar_t *pszVerbDesc, char *pszMimeType) { - ASSOCDATA *pAssocListBuf, *assoc; - // is already in list? mir_cslock lck(csAssocList); - int index = FindAssocItem(pszClassName); - if (index != -1) return FALSE; - - // resize storage array - pAssocListBuf = (ASSOCDATA*)mir_realloc(pAssocList, (nAssocListCount + 1) * sizeof(ASSOCDATA)); - if (pAssocListBuf == nullptr) - return FALSE; - pAssocList = pAssocListBuf; + if (FindAssocItem(pszClassName) != nullptr) + return false; // init new item - assoc = &pAssocList[nAssocListCount]; + ASSOCDATA *assoc = new ASSOCDATA(); assoc->pszClassName = pszClassName; // no dup here assoc->pszDescription = s2t(tdh->pszDescription, tdh->flags & FTDF_UNICODE, TRUE); // does NULL check assoc->hInstance = tdh->hInstance; // hInstance is allowed to be NULL for miranda32.exe @@ -419,31 +365,27 @@ static BOOL AddNewAssocItem_Worker(char *pszClassName, const TYPEDESCHEAD *tdh, // error check if (assoc->pszDescription == nullptr || (assoc->pszService == nullptr && tdh->pszService != nullptr)) { - mir_free(assoc->pszService); // does NULL check - mir_free(assoc->pszDescription); // does NULL check - return FALSE; + delete assoc; + return false; } // add registry keys if (IsAssocEnabled(assoc)) EnsureAssocRegistered(assoc); - ++nAssocListCount; - NotifyAssocChange(FALSE); - return TRUE; + arAssocList.insert(assoc); + NotifyAssocChange(false); + return true; } // ownership of pszClassName is *not* transferd to storage list -static BOOL RemoveAssocItem_Worker(const char *pszClassName) +static bool RemoveAssocItem_Worker(const char *pszClassName) { - ASSOCDATA *pAssocListBuf, *assoc; - // find index mir_cslock lck(csAssocList); - int index = FindAssocItem(pszClassName); - if (index == -1) - return FALSE; - assoc = &pAssocList[index]; + ASSOCDATA *assoc = FindAssocItem(pszClassName); + if (assoc == nullptr) + return false; // delete registry keys and db setting UnregisterAssoc(assoc); @@ -451,20 +393,8 @@ static BOOL RemoveAssocItem_Worker(const char *pszClassName) RememberMimeTypeAdded(assoc->pszMimeType, assoc->pszFileExt, FALSE); DeleteAssocEnabledSetting(assoc); - // free memory - mir_free(assoc->pszClassName); - mir_free(assoc->pszDescription); - mir_free(assoc->pszService); - mir_free(assoc->pszFileExt); // does NULL check - mir_free(assoc->pszVerbDesc); // does NULL check - mir_free(assoc->pszMimeType); // does NULL check - // resize storage array - if ((index + 1) < nAssocListCount) - memmove(assoc, &pAssocList[index + 1], ((nAssocListCount - index - 1) * sizeof(ASSOCDATA))); - pAssocListBuf = (ASSOCDATA*)mir_realloc(pAssocList, (nAssocListCount - 1) * sizeof(ASSOCDATA)); - if (pAssocListBuf != nullptr) pAssocList = pAssocListBuf; - --nAssocListCount; + arAssocList.remove(assoc); NotifyAssocChange(FALSE); return TRUE; @@ -545,15 +475,12 @@ static INT_PTR ServiceRemoveUrlType(WPARAM, LPARAM lParam) static BOOL InvokeHandler_Worker(const char *pszClassName, const wchar_t *pszParam, INT_PTR *res) { - void *pvParam; - char *pszService; - // find it in list mir_cslock lck(csAssocList); - int index = FindAssocItem(pszClassName); - if (index == -1) - return FALSE; - ASSOCDATA *assoc = &pAssocList[index]; + ASSOCDATA *assoc = FindAssocItem(pszClassName); + if (assoc == nullptr) + return false; + // no service specified? correct registry to use main commandline if (assoc->pszService == nullptr) { EnsureAssocRegistered(assoc); @@ -563,9 +490,10 @@ static BOOL InvokeHandler_Worker(const char *pszClassName, const wchar_t *pszPar *res = 0; // success return TRUE; } + // get params - pszService = mir_strdup(assoc->pszService); - pvParam = t2s(pszParam, assoc->flags & FTDF_UNICODE, FALSE); + char *pszService = mir_strdup(assoc->pszService); + void *pvParam = t2s(pszParam, assoc->flags & FTDF_UNICODE, FALSE); // call service if (pszService != nullptr && pvParam != nullptr) @@ -629,7 +557,7 @@ static int CALLBACK ListViewSortDesc(LPARAM lParam1, LPARAM lParam2, LPARAM lPar int cmp; if (((ASSOCDATA*)lParam1)->pszFileExt != nullptr && ((ASSOCDATA*)lParam2)->pszFileExt != nullptr) cmp = CompareStringA((LCID)lParamSort, 0, ((ASSOCDATA*)lParam1)->pszFileExt, -1, ((ASSOCDATA*)lParam2)->pszFileExt, -1); - else if (((ASSOCDATA*)lParam1)->pszFileExt == ((ASSOCDATA*)lParam2)->pszFileExt) // both NULL + else if (((ASSOCDATA*)lParam1)->pszFileExt.get() == ((ASSOCDATA*)lParam2)->pszFileExt.get()) // both NULL cmp = CompareStringA((LCID)lParamSort, 0, ((ASSOCDATA*)lParam1)->pszClassName, -1, ((ASSOCDATA*)lParam2)->pszClassName, -1); else // different types, incomparable cmp = (((ASSOCDATA*)lParam1)->pszFileExt == nullptr) ? CSTR_LESS_THAN : CSTR_GREATER_THAN; @@ -643,129 +571,129 @@ static int CALLBACK ListViewSortDesc(LPARAM lParam1, LPARAM lParam2, LPARAM lPar static INT_PTR CALLBACK AssocListOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { LVITEM lvi; - ASSOCDATA *assoc; switch (msg) { case WM_INITDIALOG: - { TranslateDialogDefault(hwndDlg); CoInitialize(nullptr); - HWND hwndList = GetDlgItem(hwndDlg, IDC_ASSOCLIST); - - ListView_SetUnicodeFormat(hwndList, TRUE); - - SendDlgItemMessage(hwndDlg, IDC_HEADERTEXT, WM_SETFONT, SendMessage(GetParent(hwndDlg), PSM_GETBOLDFONT, 0, 0), 0); - // checkboxes won't show up on Win95 without IE3+ or 4.70 (plugin opts uses the same) - ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP); - // columns - { - LVCOLUMN lvc; - lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; - lvc.pszText = TranslateT("Type"); - lvc.cx = 170; - ListView_InsertColumn(hwndList, lvc.iSubItem = 0, &lvc); - lvc.pszText = TranslateT("Description"); - ListView_InsertColumn(hwndList, lvc.iSubItem = 1, &lvc); - } - // create image storage - HIMAGELIST himl; - mir_cslock lck(csAssocList); { - HDC hdc = GetDC(hwndList); - if (hdc != nullptr) { // BITSPIXEL is compatible with ILC_COLOR flags - himl = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), GetDeviceCaps(hdc, BITSPIXEL) | ILC_MASK, nAssocListCount, 0); - ReleaseDC(hwndList, hdc); + HWND hwndList = GetDlgItem(hwndDlg, IDC_ASSOCLIST); + + ListView_SetUnicodeFormat(hwndList, TRUE); + + SendDlgItemMessage(hwndDlg, IDC_HEADERTEXT, WM_SETFONT, SendMessage(GetParent(hwndDlg), PSM_GETBOLDFONT, 0, 0), 0); + // checkboxes won't show up on Win95 without IE3+ or 4.70 (plugin opts uses the same) + ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP); + // columns + { + LVCOLUMN lvc; + lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; + lvc.pszText = TranslateT("Type"); + lvc.cx = 170; + ListView_InsertColumn(hwndList, lvc.iSubItem = 0, &lvc); + lvc.pszText = TranslateT("Description"); + ListView_InsertColumn(hwndList, lvc.iSubItem = 1, &lvc); } - else himl = nullptr; - } - ListView_SetImageList(hwndList, himl, LVSIL_SMALL); // autodestroyed - // enum assoc list - lvi.iSubItem = 0; - lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; - for (int i = 0; i < nAssocListCount; ++i) { - assoc = &pAssocList[i]; - lvi.iItem = 0; - lvi.lParam = (LPARAM)CopyAssocItem(assoc); - lvi.pszText = GetAssocTypeDesc(assoc); - lvi.iImage = ReplaceImageListAssocIcon(himl, assoc, -1); - lvi.iItem = ListView_InsertItem(hwndList, &lvi); - if (lvi.iItem != -1) { - ListView_SetItemText(hwndList, lvi.iItem, 1, assoc->pszDescription); - ListView_SetCheckState(hwndList, lvi.iItem, IsAssocEnabled(assoc) && IsAssocRegistered(assoc)); + // create image storage + HIMAGELIST himl; + mir_cslock lck(csAssocList); + { + HDC hdc = GetDC(hwndList); + if (hdc != nullptr) { // BITSPIXEL is compatible with ILC_COLOR flags + himl = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), GetDeviceCaps(hdc, BITSPIXEL) | ILC_MASK, arAssocList.getCount(), 0); + ReleaseDC(hwndList, hdc); + } + else himl = nullptr; } - } - // sort items (before moving to groups) - ListView_SortItems(hwndList, ListViewSortDesc, Langpack_GetDefaultLocale()); - // groups - if (ListView_EnableGroupView(hwndList, TRUE) == 1) { // returns 0 on pre WinXP or if commctls6 are disabled - LVGROUP lvg; - int iItem; - // dummy item for group - lvi.iItem = ListView_GetItemCount(hwndList) - 1; + ListView_SetImageList(hwndList, himl, LVSIL_SMALL); // autodestroyed + // enum assoc list lvi.iSubItem = 0; - lvi.mask = LVIF_PARAM | LVIF_IMAGE; - lvi.iImage = -1; - lvi.lParam = 0; - // insert groups - lvg.cbSize = sizeof(lvg); - lvg.mask = LVGF_HEADER | LVGF_GROUPID; - lvg.iGroupId = 2; - lvg.pszHeader = TranslateT("URLs on websites"); - lvi.iItem = ListView_InsertItem(hwndList, &lvi); - if (lvi.iItem != -1) { - ListView_InsertGroup(hwndList, lvi.iItem, &lvg); - lvg.iGroupId = 1; - lvg.pszHeader = TranslateT("File types"); - iItem = lvi.iItem = ListView_InsertItem(hwndList, &lvi); - if (lvi.iItem != -1) + lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; + for (auto &it : arAssocList) { + lvi.iItem = 0; + lvi.lParam = (LPARAM)new ASSOCDATA(*it); + lvi.pszText = GetAssocTypeDesc(it); + lvi.iImage = ReplaceImageListAssocIcon(himl, it, -1); + lvi.iItem = ListView_InsertItem(hwndList, &lvi); + if (lvi.iItem != -1) { + ListView_SetItemText(hwndList, lvi.iItem, 1, it->pszDescription); + ListView_SetCheckState(hwndList, lvi.iItem, IsAssocEnabled(it) && IsAssocRegistered(it)); + } + } + // sort items (before moving to groups) + ListView_SortItems(hwndList, ListViewSortDesc, Langpack_GetDefaultLocale()); + // groups + if (ListView_EnableGroupView(hwndList, TRUE) == 1) { // returns 0 on pre WinXP or if commctls6 are disabled + LVGROUP lvg; + int iItem; + // dummy item for group + lvi.iItem = ListView_GetItemCount(hwndList) - 1; + lvi.iSubItem = 0; + lvi.mask = LVIF_PARAM | LVIF_IMAGE; + lvi.iImage = -1; + lvi.lParam = 0; + // insert groups + lvg.cbSize = sizeof(lvg); + lvg.mask = LVGF_HEADER | LVGF_GROUPID; + lvg.iGroupId = 2; + lvg.pszHeader = TranslateT("URLs on websites"); + lvi.iItem = ListView_InsertItem(hwndList, &lvi); + if (lvi.iItem != -1) { ListView_InsertGroup(hwndList, lvi.iItem, &lvg); - else ListView_DeleteItem(hwndList, iItem); + lvg.iGroupId = 1; + lvg.pszHeader = TranslateT("File types"); + iItem = lvi.iItem = ListView_InsertItem(hwndList, &lvi); + if (lvi.iItem != -1) + ListView_InsertGroup(hwndList, lvi.iItem, &lvg); + else ListView_DeleteItem(hwndList, iItem); + } + // move to group + lvi.iSubItem = 0; + lvi.mask = LVIF_PARAM | LVIF_GROUPID; + for (lvi.iItem = 0; ListView_GetItem(hwndList, &lvi); ++lvi.iItem) { + ASSOCDATA *assoc = (ASSOCDATA*)lvi.lParam; + if (assoc == nullptr) + continue; // groups + lvi.iGroupId = (assoc->pszFileExt == nullptr) + 1; + ListView_SetItem(hwndList, &lvi); + } } - // move to group - lvi.iSubItem = 0; - lvi.mask = LVIF_PARAM | LVIF_GROUPID; - for (lvi.iItem = 0; ListView_GetItem(hwndList, &lvi); ++lvi.iItem) { - assoc = (ASSOCDATA*)lvi.lParam; - if (assoc == nullptr) continue; // groups - lvi.iGroupId = (assoc->pszFileExt == nullptr) + 1; - ListView_SetItem(hwndList, &lvi); + lvi.iItem = ListView_GetTopIndex(hwndList); + ListView_SetItemState(hwndList, lvi.iItem, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); + ListView_SetColumnWidth(hwndList, 1, LVSCW_AUTOSIZE_USEHEADER); // size to fit window + // only while running + CheckDlgButton(hwndDlg, IDC_ONLYWHILERUNNING, (BOOL)db_get_b(NULL, MODULENAME, "OnlyWhileRunning", SETTING_ONLYWHILERUNNING_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); + + // autostart + wchar_t *pszRunCmd = MakeRunCommand(TRUE, TRUE); + if (pszRunCmd != nullptr) { + CheckDlgButton(hwndDlg, IDC_AUTOSTART, IsRegRunEntry(L"MirandaNG", pszRunCmd) ? BST_CHECKED : BST_UNCHECKED); + mir_free(pszRunCmd); } } - lvi.iItem = ListView_GetTopIndex(hwndList); - ListView_SetItemState(hwndList, lvi.iItem, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); - ListView_SetColumnWidth(hwndList, 1, LVSCW_AUTOSIZE_USEHEADER); // size to fit window - // only while running - CheckDlgButton(hwndDlg, IDC_ONLYWHILERUNNING, (BOOL)db_get_b(NULL, MODULENAME, "OnlyWhileRunning", SETTING_ONLYWHILERUNNING_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); - - // autostart - wchar_t *pszRunCmd = MakeRunCommand(TRUE, TRUE); - if (pszRunCmd != nullptr) { - CheckDlgButton(hwndDlg, IDC_AUTOSTART, IsRegRunEntry(L"MirandaNG", pszRunCmd) ? BST_CHECKED : BST_UNCHECKED); - mir_free(pszRunCmd); - } - } - return TRUE; + return TRUE; case WM_SETTINGCHANGE: case M_REFRESH_ICONS: - { - HWND hwndList = GetDlgItem(hwndDlg, IDC_ASSOCLIST); - HIMAGELIST himl = ListView_GetImageList(hwndList, LVSIL_SMALL); - // enum items - lvi.iSubItem = 0; - lvi.mask = LVIF_PARAM | LVIF_IMAGE; - for (lvi.iItem = 0; ListView_GetItem(hwndList, &lvi); ++lvi.iItem) { - assoc = (ASSOCDATA*)lvi.lParam; - if (assoc == nullptr) continue; // groups - lvi.iImage = ReplaceImageListAssocIcon(himl, assoc, lvi.iImage); - ListView_SetItem(hwndList, &lvi); - } - if (lvi.iItem) { // ListView_Update() blinks - ListView_RedrawItems(hwndList, 0, lvi.iItem - 1); - UpdateWindow(hwndList); + { + HWND hwndList = GetDlgItem(hwndDlg, IDC_ASSOCLIST); + HIMAGELIST himl = ListView_GetImageList(hwndList, LVSIL_SMALL); + // enum items + lvi.iSubItem = 0; + lvi.mask = LVIF_PARAM | LVIF_IMAGE; + for (lvi.iItem = 0; ListView_GetItem(hwndList, &lvi); ++lvi.iItem) { + ASSOCDATA *assoc = (ASSOCDATA*)lvi.lParam; + if (assoc == nullptr) + continue; // groups + lvi.iImage = ReplaceImageListAssocIcon(himl, assoc, lvi.iImage); + ListView_SetItem(hwndList, &lvi); + } + if (lvi.iItem) { // ListView_Update() blinks + ListView_RedrawItems(hwndList, 0, lvi.iItem - 1); + UpdateWindow(hwndList); + } } - } - return TRUE; + return TRUE; case WM_CTLCOLORSTATIC: // use same text color for header as for group boxes (WinXP+) @@ -782,6 +710,19 @@ static INT_PTR CALLBACK AssocListOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wPara } break; + case WM_DESTROY: + { + HWND hwndList = GetDlgItem(hwndDlg, IDC_ASSOCLIST); + lvi.iSubItem = 0; + lvi.mask = LVIF_PARAM; + mir_cslock lck(csAssocList); + for (lvi.iItem = 0; ListView_GetItem(hwndList, &lvi); ++lvi.iItem) { + ASSOCDATA *assoc = (ASSOCDATA*)lvi.lParam; + delete assoc; + } + } + break; + case WM_NCDESTROY: CoUninitialize(); return TRUE; @@ -870,8 +811,9 @@ static INT_PTR CALLBACK AssocListOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wPara lvi.mask = LVIF_PARAM; mir_cslock lck(csAssocList); for (lvi.iItem = 0; ListView_GetItem(hwndList, &lvi); ++lvi.iItem) { - assoc = (ASSOCDATA*)lvi.lParam; - if (assoc == nullptr) continue; // groups + ASSOCDATA *assoc = (ASSOCDATA*)lvi.lParam; + if (assoc == nullptr) + continue; // groups fEnabled = ListView_GetCheckState(hwndList, lvi.iItem); SetAssocEnabled(assoc, fEnabled); @@ -930,11 +872,7 @@ void InitAssocList(void) icc.dwSize = sizeof(icc); icc.dwICC = ICC_LISTVIEW_CLASSES; InitCommonControlsEx(&icc); - hHookOptInit = HookEvent(ME_OPT_INITIALISE, AssocListOptInit); - - // Assoc List - pAssocList = nullptr; - nAssocListCount = 0; + HookEvent(ME_OPT_INITIALISE, AssocListOptInit); // Services CreateServiceFunction(MS_ASSOCMGR_ADDNEWFILETYPE, ServiceAddNewFileType); @@ -986,30 +924,16 @@ void InitAssocList(void) void UninitAssocList(void) { - // Options - UnhookEvent(hHookOptInit); - // Assoc List BYTE fOnlyWhileRunning = db_get_b(NULL, MODULENAME, "OnlyWhileRunning", SETTING_ONLYWHILERUNNING_DEFAULT); - for (int i = 0; i < nAssocListCount; ++i) { - ASSOCDATA *assoc = &pAssocList[i]; - - // remove registry keys + for (auto &it : arAssocList) if (fOnlyWhileRunning) - UnregisterAssoc(assoc); - - mir_free(assoc->pszClassName); - mir_free(assoc->pszDescription); - mir_free(assoc->pszService); - mir_free(assoc->pszFileExt); - mir_free(assoc->pszVerbDesc); - mir_free(assoc->pszMimeType); - } - mir_free(pAssocList); + UnregisterAssoc(it); // remove registry keys // Notify Shell - if (fOnlyWhileRunning && nAssocListCount) + if (fOnlyWhileRunning && arAssocList.getCount()) NotifyAssocChange(TRUE); + arAssocList.destroy(); // unregister open-with app if (fOnlyWhileRunning) { diff --git a/plugins/AssocMgr/src/assoclist.h b/plugins/AssocMgr/src/assoclist.h index 8afaeebe70..08b8d0a34e 100644 --- a/plugins/AssocMgr/src/assoclist.h +++ b/plugins/AssocMgr/src/assoclist.h @@ -21,6 +21,30 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #pragma once +struct ASSOCDATA : public MZeroedObject +{ + ASSOCDATA() {} + + ASSOCDATA(const ASSOCDATA &p) : + pszClassName(mir_strdup(p.pszClassName)), + pszDescription(mir_wstrdup(p.pszDescription)), + pszService(mir_strdup(p.pszService)), + pszFileExt(mir_strdup(p.pszFileExt)), + pszMimeType(mir_strdup(p.pszMimeType)), + pszVerbDesc(mir_wstrdup(p.pszVerbDesc)) + {} + + ptrA pszClassName; // class name as used in registry and db + ptrW pszDescription; + HINSTANCE hInstance; // allowed to be NULL for miranda32.exe + WORD nIconResID; + ptrA pszService; + WORD flags; // set of FTDF_* and UTDF_* flags + ptrA pszFileExt; // file type: NULL for url type + ptrA pszMimeType; // file type: allowed to be NULL + ptrW pszVerbDesc; // file type: allowed to be NULL +}; + /* Assoc Enabled */ void CleanupAssocEnabledSettings(void); /* Mime Reg */ diff --git a/plugins/AssocMgr/src/reg.cpp b/plugins/AssocMgr/src/reg.cpp index 5a96d02582..b6ecad1a0b 100644 --- a/plugins/AssocMgr/src/reg.cpp +++ b/plugins/AssocMgr/src/reg.cpp @@ -754,21 +754,21 @@ BOOL IsRegClass(const char *pszClassName, const wchar_t *pszRunCmd) */ // DestroyIcon() the return value -HICON LoadRegClassSmallIcon(const char *pszClassName) +HICON LoadRegClassSmallIcon(ASSOCDATA *assoc) { - HICON hIcon = nullptr; - HKEY hClassKey, hIconKey; - wchar_t *pszIconLoc, *p; + HICON hIcon = LoadIcon(assoc->hInstance, MAKEINTRESOURCE(assoc->nIconResID)); + if (hIcon != nullptr) + return hIcon; - // using the merged view classes key for reading - // class - if (!RegOpenKeyExA(HKEY_CLASSES_ROOT, pszClassName, 0, KEY_QUERY_VALUE, &hClassKey)) { + // using the merged view classes key for reading class + HKEY hClassKey, hIconKey; + if (!RegOpenKeyExA(HKEY_CLASSES_ROOT, assoc->pszClassName, 0, KEY_QUERY_VALUE, &hClassKey)) { // default icon if (!RegOpenKeyEx(hClassKey, L"DefaultIcon", 0, KEY_QUERY_VALUE, &hIconKey)) { // extract icon - pszIconLoc = GetRegStrValue(hIconKey, nullptr); + wchar_t *pszIconLoc = GetRegStrValue(hIconKey, nullptr); if (pszIconLoc != nullptr) { - p = wcsrchr(pszIconLoc, ','); + wchar_t *p = wcsrchr(pszIconLoc, ','); if (p != nullptr) { *(p++) = 0; ExtractIconEx(pszIconLoc, _wtoi(p), nullptr, &hIcon, 1); @@ -797,13 +797,13 @@ HICON LoadRegClassSmallIcon(const char *pszClassName) BOOL AddRegFileExt(const char *pszFileExt, const char *pszClassName, const char *pszMimeType, BOOL fIsText) { BOOL fSuccess = FALSE; - HKEY hRootKey, hExtKey, hOpenWithKey; // some error checking for disallowed values (to avoid errors in registry) if (strchr(pszFileExt, '\\') != nullptr || strchr(pszFileExt, ' ') != nullptr) return FALSE; // try to open interactive user's classes key + HKEY hRootKey, hExtKey, hOpenWithKey; if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Classes", 0, KEY_CREATE_SUB_KEY, &hRootKey)) hRootKey = HKEY_CLASSES_ROOT; @@ -838,18 +838,17 @@ BOOL AddRegFileExt(const char *pszFileExt, const char *pszClassName, const char void RemoveRegFileExt(const char *pszFileExt, const char *pszClassName) { - HKEY hRootKey, hExtKey, hSubKey; - DWORD nOpenWithCount; - wchar_t *pszPrevClassName = nullptr; BOOL fRestored = FALSE; // try to open interactive user's classes key + HKEY hRootKey, hExtKey, hSubKey; if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Classes", 0, DELETE, &hRootKey)) hRootKey = HKEY_CLASSES_ROOT; // file ext if (!RegOpenKeyExA(hRootKey, pszFileExt, 0, KEY_QUERY_VALUE | KEY_SET_VALUE | DELETE, &hExtKey)) { // class name (the important part) + wchar_t *pszPrevClassName = nullptr; if (!RestoreRegTree(hRootKey, pszFileExt, "bak_")) { pszPrevClassName = GetRegStrValue(hExtKey, nullptr); if (pszPrevClassName != nullptr) { @@ -863,20 +862,25 @@ void RemoveRegFileExt(const char *pszFileExt, const char *pszClassName) mir_free(pszPrevClassName); } } - if (pszPrevClassName == nullptr) RegDeleteValue(hExtKey, nullptr); + + if (pszPrevClassName == nullptr) + RegDeleteValue(hExtKey, nullptr); + // open with progids (remove if empty) - nOpenWithCount = 0; + DWORD nOpenWithCount = 0; if (!RegOpenKeyEx(hExtKey, L"OpenWithProgids", 0, KEY_SET_VALUE | KEY_QUERY_VALUE, &hSubKey)) { // remove current class (if set by another app) RegDeleteValueA(hSubKey, pszClassName); RegQueryInfoKey(hSubKey, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &nOpenWithCount, nullptr, nullptr, nullptr); RegCloseKey(hSubKey); } - if (!nOpenWithCount) RegDeleteKey(hExtKey, L"OpenWithProgids"); // delete if no values + if (!nOpenWithCount) + RegDeleteKey(hExtKey, L"OpenWithProgids"); // delete if no values RegCloseKey(hExtKey); } else DeleteRegTreeBackup(pszFileExt, "bak_"); - if (!fRestored) RegDeleteKeyA(hRootKey, pszFileExt); // try to remove it all + if (!fRestored) + RegDeleteKeyA(hRootKey, pszFileExt); // try to remove it all if (hRootKey != HKEY_CLASSES_ROOT) RegCloseKey(hRootKey); @@ -891,10 +895,9 @@ void RemoveRegFileExt(const char *pszFileExt, const char *pszClassName) BOOL IsRegFileExt(const char *pszFileExt, const char *pszClassName) { BOOL fSuccess = FALSE; - HKEY hExtKey; - // using the merged view classes key for reading - // file ext + // using the merged view classes key for reading file ext + HKEY hExtKey; if (!RegOpenKeyExA(HKEY_CLASSES_ROOT, pszFileExt, 0, KEY_QUERY_VALUE, &hExtKey)) { // class name // it is enough to check if the class is right @@ -915,9 +918,9 @@ BOOL IsRegFileExt(const char *pszFileExt, const char *pszClassName) BOOL AddRegMimeType(const char *pszMimeType, const char *pszFileExt) { BOOL fSuccess = FALSE; - HKEY hRootKey, hDbKey, hTypeKey; // some error checking for disallowed values (to avoid errors in registry) + HKEY hRootKey, hDbKey, hTypeKey; if (strchr(pszMimeType, '\\') != nullptr || strchr(pszMimeType, ' ') != nullptr) return FALSE; @@ -944,22 +947,23 @@ BOOL AddRegMimeType(const char *pszMimeType, const char *pszFileExt) void RemoveRegMimeType(const char *pszMimeType, const char *pszFileExt) { - HKEY hRootKey, hDbKey, hTypeKey; - BOOL fDelete = TRUE; - // try to open interactive user's classes key + HKEY hRootKey, hDbKey, hTypeKey; if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Classes", 0, KEY_QUERY_VALUE, &hRootKey)) hRootKey = HKEY_CLASSES_ROOT; // database if (!RegOpenKeyEx(hRootKey, L"MIME\\Database\\Content Type", 0, DELETE, &hDbKey)) { + BOOL fDelete = TRUE; + // mime type if (!RegOpenKeyExA(hDbKey, pszMimeType, 0, KEY_QUERY_VALUE, &hTypeKey)) { // file ext fDelete = IsRegStrValueA(hTypeKey, L"Extension", pszFileExt); RegCloseKey(hTypeKey); } - if (fDelete) RegDeleteKeyA(hDbKey, pszMimeType); + if (fDelete) + RegDeleteKeyA(hDbKey, pszMimeType); RegCloseKey(hDbKey); } @@ -976,9 +980,8 @@ void RemoveRegMimeType(const char *pszMimeType, const char *pszFileExt) // pszDdeCmd is allowed to be NULL void AddRegOpenWith(const wchar_t *pszAppFileName, BOOL fAllowOpenWith, const wchar_t *pszAppName, const wchar_t *pszIconLoc, const wchar_t *pszRunCmd, const wchar_t *pszDdeCmd, const wchar_t *pszDdeApp, const wchar_t *pszDdeTopic) { - HKEY hRootKey, hAppsKey, hExeKey, hShellKey, hVerbKey, hDdeKey; - // try to open interactive user's classes key + HKEY hRootKey, hAppsKey, hExeKey, hShellKey, hVerbKey, hDdeKey; if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Classes", 0, KEY_QUERY_VALUE, &hRootKey)) hRootKey = HKEY_CLASSES_ROOT; @@ -1029,9 +1032,8 @@ void AddRegOpenWith(const wchar_t *pszAppFileName, BOOL fAllowOpenWith, const wc void RemoveRegOpenWith(const wchar_t *pszAppFileName) { - HKEY hRootKey, hAppsKey, hExeKey, hShellKey, hVerbKey, hDdeKey; - // try to open interactive user's classes key + HKEY hRootKey, hAppsKey, hExeKey, hShellKey, hVerbKey, hDdeKey; if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Classes", 0, KEY_QUERY_VALUE, &hRootKey)) hRootKey = HKEY_CLASSES_ROOT; @@ -1080,9 +1082,8 @@ void RemoveRegOpenWith(const wchar_t *pszAppFileName) void AddRegOpenWithExtEntry(const wchar_t *pszAppFileName, const char *pszFileExt, const wchar_t *pszFileDesc) { - HKEY hRootKey, hAppsKey, hExeKey, hTypesKey; - // try to open interactive user's classes key + HKEY hRootKey, hAppsKey, hExeKey, hTypesKey; if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Classes", 0, KEY_QUERY_VALUE, &hRootKey)) hRootKey = HKEY_CLASSES_ROOT; @@ -1109,9 +1110,8 @@ void AddRegOpenWithExtEntry(const wchar_t *pszAppFileName, const char *pszFileEx void RemoveRegOpenWithExtEntry(const wchar_t *pszAppFileName, const char *pszFileExt) { - HKEY hRootKey, hAppsKey, hExeKey, hTypesKey; - // try to open interactive user's classes key + HKEY hRootKey, hAppsKey, hExeKey, hTypesKey; if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Classes", 0, KEY_QUERY_VALUE, &hRootKey)) hRootKey = HKEY_CLASSES_ROOT; @@ -1142,9 +1142,9 @@ void RemoveRegOpenWithExtEntry(const wchar_t *pszAppFileName, const char *pszFil BOOL AddRegRunEntry(const wchar_t *pszAppName, const wchar_t *pszRunCmd) { BOOL fSuccess = FALSE; - HKEY hRunKey; // run + HKEY hRunKey; if (!RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, nullptr, 0, KEY_SET_VALUE, nullptr, &hRunKey, nullptr)) { // appname fSuccess = !RegSetValueEx(hRunKey, pszAppName, 0, REG_SZ, (BYTE*)pszRunCmd, (int)(mir_wstrlen(pszRunCmd) + 1) * sizeof(wchar_t)); @@ -1155,9 +1155,8 @@ BOOL AddRegRunEntry(const wchar_t *pszAppName, const wchar_t *pszRunCmd) BOOL RemoveRegRunEntry(const wchar_t *pszAppName, const wchar_t *pszRunCmd) { - HKEY hRunKey; - // run + HKEY hRunKey; LONG res = RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hRunKey); if (!res) { // appname @@ -1175,9 +1174,9 @@ BOOL RemoveRegRunEntry(const wchar_t *pszAppName, const wchar_t *pszRunCmd) BOOL IsRegRunEntry(const wchar_t *pszAppName, const wchar_t *pszRunCmd) { BOOL fState = FALSE; - HKEY hRunKey; // Run + HKEY hRunKey; if (!RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_QUERY_VALUE, &hRunKey)) { // appname fState = IsRegStrValue(hRunKey, pszAppName, pszRunCmd); diff --git a/plugins/AssocMgr/src/reg.h b/plugins/AssocMgr/src/reg.h index 5cd27c7a33..e82b4376ea 100644 --- a/plugins/AssocMgr/src/reg.h +++ b/plugins/AssocMgr/src/reg.h @@ -27,7 +27,7 @@ void CleanupRegTreeBackupSettings(void); BOOL AddRegClass(const char *pszClassName,const wchar_t *pszTypeDescription,const wchar_t *pszIconLoc,const wchar_t *pszAppName,const wchar_t *pszRunCmd,const wchar_t *pszDdeCmd,const wchar_t *pszDdeApp,const wchar_t *pszDdeTopic,const wchar_t *pszVerbDesc,BOOL fBrowserAutoOpen,BOOL fUrlProto,BOOL fIsShortcut); BOOL RemoveRegClass(const char *pszClassName); BOOL IsRegClass(const char *pszClassName,const wchar_t *pszRunCmd); -HICON LoadRegClassSmallIcon(const char *pszClassName); +HICON LoadRegClassSmallIcon(struct ASSOCDATA *pszClassName); /* Extension */ BOOL AddRegFileExt(const char *pszFileExt,const char *pszClassName,const char *pszMimeType,BOOL fIsText); void RemoveRegFileExt(const char *pszFileExt,const char *pszClassName); diff --git a/plugins/AssocMgr/src/version.h b/plugins/AssocMgr/src/version.h index 34cd557e93..9aecdd58f2 100644 --- a/plugins/AssocMgr/src/version.h +++ b/plugins/AssocMgr/src/version.h @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define __MAJOR_VERSION 0 #define __MINOR_VERSION 2 #define __RELEASE_NUM 1 -#define __BUILD_NUM 0 +#define __BUILD_NUM 1 #include -- cgit v1.2.3