From 5500b21532dfe16253820b109df71f8f5d3006f7 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Wed, 4 Jul 2012 08:25:18 +0000 Subject: AssocMgr: changed folder structure git-svn-id: http://svn.miranda-ng.org/main/trunk@751 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/AssocMgr/Info_Src.txt | 30 - plugins/AssocMgr/License_Appendix.txt | 64 -- plugins/AssocMgr/assoclist.cpp | 1102 -------------------- plugins/AssocMgr/assoclist.h | 33 - plugins/AssocMgr/assocmgr-translation.txt | 41 - plugins/AssocMgr/assocmgr.vcxproj | 50 +- plugins/AssocMgr/assocmgr.vcxproj.filters | 34 +- plugins/AssocMgr/common.h | 57 -- plugins/AssocMgr/dde.cpp | 295 ------ plugins/AssocMgr/dde.h | 30 - plugins/AssocMgr/docs/Info_Src.txt | 30 + plugins/AssocMgr/docs/License_Appendix.txt | 64 ++ plugins/AssocMgr/docs/assocmgr-translation.txt | 41 + plugins/AssocMgr/main.cpp | 121 --- plugins/AssocMgr/reg.cpp | 1295 ------------------------ plugins/AssocMgr/reg.h | 51 - plugins/AssocMgr/res/resource.rc | 117 +++ plugins/AssocMgr/res/version.rc | 36 + plugins/AssocMgr/resource.h | 24 - plugins/AssocMgr/resource.rc | 117 --- plugins/AssocMgr/src/assoclist.cpp | 1102 ++++++++++++++++++++ plugins/AssocMgr/src/assoclist.h | 33 + plugins/AssocMgr/src/common.h | 57 ++ plugins/AssocMgr/src/dde.cpp | 295 ++++++ plugins/AssocMgr/src/dde.h | 30 + plugins/AssocMgr/src/main.cpp | 121 +++ plugins/AssocMgr/src/reg.cpp | 1295 ++++++++++++++++++++++++ plugins/AssocMgr/src/reg.h | 51 + plugins/AssocMgr/src/resource.h | 24 + plugins/AssocMgr/src/test.cpp | 869 ++++++++++++++++ plugins/AssocMgr/src/test.h | 24 + plugins/AssocMgr/src/utils.cpp | 194 ++++ plugins/AssocMgr/src/utils.h | 39 + plugins/AssocMgr/src/version.h | 41 + plugins/AssocMgr/test.cpp | 869 ---------------- plugins/AssocMgr/test.h | 24 - plugins/AssocMgr/utils.cpp | 194 ---- plugins/AssocMgr/utils.h | 39 - plugins/AssocMgr/version.h | 41 - plugins/AssocMgr/version.rc | 36 - 40 files changed, 4505 insertions(+), 4505 deletions(-) delete mode 100644 plugins/AssocMgr/Info_Src.txt delete mode 100644 plugins/AssocMgr/License_Appendix.txt delete mode 100644 plugins/AssocMgr/assoclist.cpp delete mode 100644 plugins/AssocMgr/assoclist.h delete mode 100644 plugins/AssocMgr/assocmgr-translation.txt delete mode 100644 plugins/AssocMgr/common.h delete mode 100644 plugins/AssocMgr/dde.cpp delete mode 100644 plugins/AssocMgr/dde.h create mode 100644 plugins/AssocMgr/docs/Info_Src.txt create mode 100644 plugins/AssocMgr/docs/License_Appendix.txt create mode 100644 plugins/AssocMgr/docs/assocmgr-translation.txt delete mode 100644 plugins/AssocMgr/main.cpp delete mode 100644 plugins/AssocMgr/reg.cpp delete mode 100644 plugins/AssocMgr/reg.h create mode 100644 plugins/AssocMgr/res/resource.rc create mode 100644 plugins/AssocMgr/res/version.rc delete mode 100644 plugins/AssocMgr/resource.h delete mode 100644 plugins/AssocMgr/resource.rc create mode 100644 plugins/AssocMgr/src/assoclist.cpp create mode 100644 plugins/AssocMgr/src/assoclist.h create mode 100644 plugins/AssocMgr/src/common.h create mode 100644 plugins/AssocMgr/src/dde.cpp create mode 100644 plugins/AssocMgr/src/dde.h create mode 100644 plugins/AssocMgr/src/main.cpp create mode 100644 plugins/AssocMgr/src/reg.cpp create mode 100644 plugins/AssocMgr/src/reg.h create mode 100644 plugins/AssocMgr/src/resource.h create mode 100644 plugins/AssocMgr/src/test.cpp create mode 100644 plugins/AssocMgr/src/test.h create mode 100644 plugins/AssocMgr/src/utils.cpp create mode 100644 plugins/AssocMgr/src/utils.h create mode 100644 plugins/AssocMgr/src/version.h delete mode 100644 plugins/AssocMgr/test.cpp delete mode 100644 plugins/AssocMgr/test.h delete mode 100644 plugins/AssocMgr/utils.cpp delete mode 100644 plugins/AssocMgr/utils.h delete mode 100644 plugins/AssocMgr/version.h delete mode 100644 plugins/AssocMgr/version.rc (limited to 'plugins/AssocMgr') diff --git a/plugins/AssocMgr/Info_Src.txt b/plugins/AssocMgr/Info_Src.txt deleted file mode 100644 index 655c2f66f7..0000000000 --- a/plugins/AssocMgr/Info_Src.txt +++ /dev/null @@ -1,30 +0,0 @@ - -File Association Manager 0.1.1.0 for Miranda IM 0.6+ ------------------------------------------------------------------------- - Source Code - -Reminder: -'File Association Manager' is released under the terms of the -GNU General Public License. -See 'AssocMgr-License.txt' for more details. -'File Association Manager' is copyright 2005-2007 by H. Herkenrath. - -Please notify me of any changes that improve -'File Association Manager' or add new features. -If you have any questions on the code, feel free -to contact me at my email address. - - H. Herkenrath (hrathh at users.sourceforge.net) - - -Notes ------------------------------------------------------------------------- -The following files need to be changed to bump the version number: - -Info_Src.txt (1 place) -version.h (4 places) -m_assocmgr.h (1 place) -m_assocmgr.inc (1 place) -docs\AssocMgr-Readme.txt (3 places) -docs\AssocMgr-Translation.txt (2 places) -docs\AssocMgr-Developer.txt (1 place) diff --git a/plugins/AssocMgr/License_Appendix.txt b/plugins/AssocMgr/License_Appendix.txt deleted file mode 100644 index c590c3f5fb..0000000000 --- a/plugins/AssocMgr/License_Appendix.txt +++ /dev/null @@ -1,64 +0,0 @@ - -Excecpt of GNU General Public License (Appendix): - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/plugins/AssocMgr/assoclist.cpp b/plugins/AssocMgr/assoclist.cpp deleted file mode 100644 index 4ccb5645fe..0000000000 --- a/plugins/AssocMgr/assoclist.cpp +++ /dev/null @@ -1,1102 +0,0 @@ -/* - -'File Association Manager'-Plugin for Miranda IM - -Copyright (C) 2005-2007 H. Herkenrath - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program (AssocMgr-License.txt); if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "common.h" - -/* Options */ -extern HINSTANCE hInst; -static HANDLE hHookOptInit; -/* Services */ -static HANDLE hServiceAddFile, hServiceRemoveFile, hServiceAddUrl, hServiceRemoveUrl; - -/************************* Assoc List *****************************/ - -typedef struct { - char *pszClassName; /* class name as used in registry and db */ - TCHAR *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 */ - TCHAR *pszVerbDesc; /* file type: allowed to be NULL */ -} ASSOCDATA; - -static ASSOCDATA *pAssocList; /* protected by csAssocList */ -static int nAssocListCount; /* protected by csAssocList */ -static CRITICAL_SECTION csAssocList; - -/************************* Assoc Enabled **************************/ - -static BOOL IsAssocEnabled(const ASSOCDATA *assoc) -{ - char szSetting[MAXMODULELABELLENGTH]; - mir_snprintf(szSetting, sizeof(szSetting), "enabled_%s", assoc->pszClassName); - return DBGetContactSettingByte(NULL, "AssocMgr", szSetting, (BYTE)!(assoc->flags&FTDF_DEFAULTDISABLED))!= 0; -} - -static void SetAssocEnabled(const ASSOCDATA *assoc, BOOL fEnabled) -{ - char szSetting[MAXMODULELABELLENGTH]; - TCHAR szDLL[MAX_PATH], szBuf[MAX_PATH]; - mir_snprintf(szSetting, sizeof(szSetting), "enabled_%s", assoc->pszClassName); - DBWriteContactSettingByte(NULL, "AssocMgr", szSetting, (BYTE)fEnabled); - /* dll name for uninstall */ - if(assoc->hInstance!= NULL && assoc->hInstance!= hInst && assoc->hInstance!= GetModuleHandle(NULL)) - if(GetModuleFileName(assoc->hInstance, szBuf, SIZEOF(szBuf))) - if(CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)szBuf, (LPARAM)szDLL)) { - mir_snprintf(szSetting, sizeof(szSetting), "module_%s", assoc->pszClassName); - DBWriteContactSettingTString(NULL, "AssocMgr", szSetting, szDLL); - } -} - -static void DeleteAssocEnabledSetting(const ASSOCDATA *assoc) -{ - char szSetting[MAXMODULELABELLENGTH]; - mir_snprintf(szSetting, sizeof(szSetting), "enabled_%s", assoc->pszClassName); - DBDeleteContactSetting(NULL, "AssocMgr", szSetting); - /* dll name for uninstall */ - mir_snprintf(szSetting, sizeof(szSetting), "module_%s", assoc->pszClassName); - DBDeleteContactSetting(NULL, "AssocMgr", szSetting); -} - -void CleanupAssocEnabledSettings(void) -{ - int nSettingsCount; - char **ppszSettings, *pszSuffix; - DBVARIANT dbv; - int i; - HANDLE hFile; - TCHAR szDLL[MAX_PATH]; - char szSetting[MAXMODULELABELLENGTH]; - - /* delete old enabled_* settings if associated plugin no longer present */ - if(EnumDbPrefixSettings("AssocMgr", "enabled_", &ppszSettings, &nSettingsCount)) { - EnterCriticalSection(&csAssocList); - for(i = 0;ipszClassName = mir_strdup(assoc->pszClassName); - assoc2->pszDescription = mir_tstrdup(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_tstrdup(assoc->pszVerbDesc); - if(assoc2->pszClassName == NULL || assoc2->pszDescription == NULL || - (assoc2->pszFileExt == NULL && assoc->pszFileExt!= NULL)) { - 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 NULL; - } - return assoc2; -} - -// 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) -{ - HICON hIcon = NULL; - int index; - if(himl == NULL) return -1; - - /* load icon */ - hIcon = LoadRegClassSmallIcon(assoc->pszClassName); - if(hIcon == NULL) { - SHFILEINFOA sfi; - if(SHGetFileInfoA((assoc->pszFileExt!= NULL)?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 == NULL) return -1; - index = ImageList_ReplaceIcon(himl, iPrevIndex, hIcon); - DestroyIcon(hIcon); - return index; -} - -// the return value does not need to be freed -// this function assumes it has got the csAssocList mutex -static TCHAR* GetAssocTypeDesc(const ASSOCDATA *assoc) -{ - static TCHAR szDesc[32]; - if(assoc->pszFileExt == NULL) mir_sntprintf(szDesc, SIZEOF(szDesc), TranslateT("%hs:"), assoc->pszClassName); - else mir_sntprintf(szDesc, SIZEOF(szDesc), TranslateT("%hs files"), assoc->pszFileExt); - return szDesc; -} - -// this function assumes it has got the csAssocList mutex -static BOOL IsAssocRegistered(const ASSOCDATA *assoc) -{ - BOOL fSuccess = FALSE, fIsUrl, fUseMainCmdLine; - TCHAR *pszRunCmd; - - fIsUrl = (assoc->pszFileExt == NULL); - fUseMainCmdLine = (assoc->pszService == NULL); - - /* class */ - pszRunCmd = MakeRunCommand(fUseMainCmdLine, !fUseMainCmdLine); - if(pszRunCmd!= NULL) - fSuccess = IsRegClass(assoc->pszClassName, pszRunCmd); - mir_free(pszRunCmd); /* does NULL check */ - /* file ext */ - if (!fIsUrl) - fSuccess = IsRegFileExt(assoc->pszFileExt, assoc->pszClassName); - - return fSuccess; -} - -// this function assumes it has got the csAssocList mutex -// call GetLastError() on error to get more error details -static BOOL EnsureAssocRegistered(const ASSOCDATA *assoc) -{ - BOOL fSuccess = FALSE, fIsUrl, fUseMainCmdLine; - TCHAR *pszIconLoc, *pszRunCmd, *pszDdeCmd, *pszAppFileName; - - fIsUrl = (assoc->pszFileExt == NULL); - fUseMainCmdLine = (assoc->pszService == NULL); - - pszRunCmd = MakeRunCommand(fUseMainCmdLine, !fUseMainCmdLine); - if(pszRunCmd!= NULL) { - fSuccess = TRUE; /* tentatively */ - /* do not overwrite user customized settings */ - if (!IsRegClass(assoc->pszClassName, pszRunCmd)) { - /* class icon */ - if (!assoc->nIconResID && fIsUrl) pszIconLoc = MakeIconLocation(NULL, 0); /* miranda logo */ - else if (!assoc->nIconResID) pszIconLoc = MakeIconLocation(hInst, IDI_MIRANDAFILE); /* generic file */ - else pszIconLoc = MakeIconLocation(assoc->hInstance, assoc->nIconResID); - /* register class */ - if(fUseMainCmdLine) pszDdeCmd = NULL; - else pszDdeCmd = fIsUrl?DDEURLCMD:DDEFILECMD; - fSuccess = AddRegClass(assoc->pszClassName, assoc->pszDescription, pszIconLoc, _T(MIRANDANAME), pszRunCmd, pszDdeCmd, DDEAPP, DDETOPIC, assoc->pszVerbDesc, assoc->flags&FTDF_BROWSERAUTOOPEN, fIsUrl, assoc->flags&FTDF_ISSHORTCUT); - mir_free(pszIconLoc); /* does NULL check */ - /* file type */ - if(fSuccess && !fIsUrl) { - /* register mime type */ - if(assoc->pszMimeType!= NULL) - if(AddRegMimeType(assoc->pszMimeType, assoc->pszFileExt, assoc->pszDescription)) - RememberMimeTypeAdded(assoc->pszMimeType, assoc->pszFileExt, TRUE); - /* register file ext */ - fSuccess = AddRegFileExt(assoc->pszFileExt, assoc->pszClassName, assoc->pszMimeType, assoc->flags&FTDF_ISTEXT); - /* register open-with */ - pszAppFileName = MakeAppFileName(fUseMainCmdLine); - if(pszAppFileName!= NULL) - AddRegOpenWithExtEntry(pszAppFileName, assoc->pszFileExt, assoc->pszDescription); - mir_free(pszAppFileName); /* does NULL check */ - } - } - mir_free(pszRunCmd); - } - else SetLastError(ERROR_OUTOFMEMORY); - return fSuccess; -} - -// this function assumes it has got the csAssocList mutex -// call GetLastError() on error to get more error details -static BOOL UnregisterAssoc(const ASSOCDATA *assoc) -{ - BOOL fIsUrl, fUseMainCmdLine; - TCHAR *pszAppFileName, *pszRunCmd; - - fIsUrl = (assoc->pszFileExt == NULL); - fUseMainCmdLine = (assoc->pszService == NULL); - - /* class might have been registered by another instance */ - pszRunCmd = MakeRunCommand(fUseMainCmdLine, !fUseMainCmdLine); - if(pszRunCmd!= NULL && !IsRegClass(assoc->pszClassName, pszRunCmd)) { - mir_free(pszRunCmd); - return TRUE; /* succeed anyway */ - } - mir_free(pszRunCmd); /* does NULL check */ - - /* file type */ - if (!fIsUrl) { - /* file extension */ - RemoveRegFileExt(assoc->pszFileExt, assoc->pszClassName); - /* mime type */ - if(assoc->pszMimeType!= NULL) - if(WasMimeTypeAdded(assoc->pszMimeType)) { - RemoveRegMimeType(assoc->pszMimeType, assoc->pszFileExt); - RememberMimeTypeAdded(assoc->pszMimeType, assoc->pszFileExt, FALSE); - } - /* open-with entry */ - pszAppFileName = MakeAppFileName(fUseMainCmdLine); - if(pszAppFileName!= NULL) - RemoveRegOpenWithExtEntry(pszAppFileName, assoc->pszFileExt); - mir_free(pszAppFileName); /* does NULL check */ - } - return RemoveRegClass(assoc->pszClassName); -} - -/************************* Assoc List Workers *********************/ - -/* this structure represents the head of both - * FILETYPEDESC and URLTYPEDESC structures. - * the head is identical for both structures. */ -typedef struct { - int cbSize; /* either sizeof(FILETYPEDESC) or sizeof(URLTYPEDESC) */ - const void *pszDescription; - HINSTANCE hInstance; - UINT nIconResID; - const char *pszService; - DWORD flags; -} TYPEDESCHEAD; - -// 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, TCHAR *pszVerbDesc, char *pszMimeType) -{ - ASSOCDATA *pAssocListBuf, *assoc; - int index; - - /* is already in list? */ - EnterCriticalSection(&csAssocList); - index = FindAssocItem(pszClassName); - if(index!= -1) return FALSE; - - /* resize storage array */ - pAssocListBuf = (ASSOCDATA*)mir_realloc(pAssocList, (nAssocListCount+1)*sizeof(ASSOCDATA)); - if(pAssocListBuf == NULL) { - LeaveCriticalSection(&csAssocList); - return FALSE; - } - pAssocList = pAssocListBuf; - - /* init new item */ - assoc = &pAssocList[nAssocListCount]; - 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 */ - assoc->nIconResID = (WORD)tdh->nIconResID; /* default icon selected later on */ - assoc->pszService = mir_strdup(tdh->pszService); /* does NULL check */ - assoc->flags = (WORD)tdh->flags; - assoc->pszFileExt = pszFileExt; - assoc->pszMimeType = pszMimeType; - assoc->pszVerbDesc = pszVerbDesc; - - /* error check */ - if(assoc->pszDescription == NULL || (assoc->pszService == NULL && tdh->pszService!= NULL)) { - mir_free(assoc->pszService); /* does NULL check */ - mir_free(assoc->pszDescription); /* does NULL check */ - LeaveCriticalSection(&csAssocList); - return FALSE; - } - - /* add registry keys */ - if(IsAssocEnabled(assoc)) - EnsureAssocRegistered(assoc); - - ++nAssocListCount; - NotifyAssocChange(FALSE); - return TRUE; -} - -// ownership of pszClassName is *not* transferd to storage list -static BOOL RemoveAssocItem_Worker(const char *pszClassName) -{ - ASSOCDATA *pAssocListBuf, *assoc; - int index; - - /* find index */ - EnterCriticalSection(&csAssocList); - index = FindAssocItem(pszClassName); - if(index == -1) { - LeaveCriticalSection(&csAssocList); - return FALSE; - } - assoc = &pAssocList[index]; - - /* delete registry keys and db setting */ - UnregisterAssoc(assoc); - if(assoc->pszMimeType!= NULL) - 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)cbSizepszFileExt == NULL || ftd->pszFileExt[0]!= '.') - return 2; - - pszFileExt = mir_strdup(ftd->pszFileExt); - pszClassName = MakeFileClassName(ftd->pszFileExt); - if(pszFileExt!= NULL && pszClassName!= NULL) { - pszVerbDesc = s2t(ftd->ptszVerbDesc, ftd->flags&FTDF_UNICODE, TRUE); /* does NULL check */ - pszMimeType = mir_strdup(ftd->pszMimeType); /* does NULL check */ - if(AddNewAssocItem_Worker(pszClassName, (TYPEDESCHEAD*)ftd, pszFileExt, pszVerbDesc, pszMimeType)) - /* no need to free pszClassName, pszFileExt, pszVerbDesc and pszMimeType, - * as their ownership got transfered to storage list */ - return 0; - } - mir_free(pszClassName); /* does NULL check */ - mir_free(pszFileExt); /* does NULL check */ - return 3; -} - -static INT_PTR ServiceRemoveFileType(WPARAM wParam, LPARAM lParam) -{ - char *pszClassName; - UNREFERENCED_PARAMETER(wParam); - - if ((char*)lParam == NULL) return 2; - pszClassName = MakeFileClassName((char*)lParam); - if(pszClassName!= NULL) - if(RemoveAssocItem_Worker(pszClassName)) { - mir_free(pszClassName); - return 0; - } - mir_free(pszClassName); /* does NULL check */ - return 3; -} - -static INT_PTR ServiceAddNewUrlType(WPARAM wParam, LPARAM lParam) -{ - const URLTYPEDESC *utd = (URLTYPEDESC*)lParam; - char *pszClassName; - UNREFERENCED_PARAMETER(wParam); - - if(utd->cbSize < sizeof(URLTYPEDESC)) - return 1; - if(utd->pszService == NULL) - return 2; - if(utd->pszProtoPrefix == NULL || utd->pszProtoPrefix[lstrlenA(utd->pszProtoPrefix)-1]!= ':') - return 2; - - pszClassName = MakeUrlClassName(utd->pszProtoPrefix); - if(pszClassName!= NULL) - if(AddNewAssocItem_Worker(pszClassName, (TYPEDESCHEAD*)utd, NULL, NULL, NULL)) - /* no need to free pszClassName, as its - * ownership got transfered to storage list */ - return 0; - mir_free(pszClassName); /* does NULL check */ - return 3; -} - -static INT_PTR ServiceRemoveUrlType(WPARAM wParam, LPARAM lParam) -{ - char *pszClassName; - UNREFERENCED_PARAMETER(wParam); - - if ((char*)lParam == NULL) return 2; - pszClassName = MakeUrlClassName((char*)lParam); - if(pszClassName!= NULL) - if(RemoveAssocItem_Worker(pszClassName)) { - mir_free(pszClassName); - return 0; - } - mir_free(pszClassName); /* does NULL check */ - return 3; -} - -/************************* Open Handler ***************************/ - -static BOOL InvokeHandler_Worker(const char *pszClassName, const TCHAR *pszParam, INT_PTR *res) -{ - void *pvParam; - char *pszService; - int index; - ASSOCDATA *assoc; - - /* find it in list */ - EnterCriticalSection(&csAssocList); - index = FindAssocItem(pszClassName); - if(index == -1) { - LeaveCriticalSection(&csAssocList); - return FALSE; - } - assoc = &pAssocList[index]; - /* no service specified? correct registry to use main commandline */ - if(assoc->pszService == NULL) { - EnsureAssocRegistered(assoc); - NotifyAssocChange(FALSE); - /* try main command line */ - if ((int)ShellExecute(NULL, NULL, pszParam, NULL, NULL, SW_SHOWNORMAL) >= 32) - *res = 0; /* success */ - return TRUE; - } - /* get params */ - pszService = mir_strdup(assoc->pszService); - pvParam = t2s(pszParam, assoc->flags&FTDF_UNICODE, FALSE); - LeaveCriticalSection(&csAssocList); - - /* call service */ - if(pszService!= NULL && pvParam!= NULL) - *res = CallService(pszService, 0, (LPARAM)pvParam); - mir_free(pszService); /* does NULL check */ - mir_free(pvParam); /* does NULL check */ - return TRUE; -} - -INT_PTR InvokeFileHandler(const TCHAR *pszFileName) -{ - char *pszClassName, *pszFileExt; - TCHAR *p; - INT_PTR res = CALLSERVICE_NOTFOUND; - - /* find extension */ - p = (TCHAR*)_tcsrchr(pszFileName, _T('.')); - if(p!= NULL) { - pszFileExt = t2a(p); - if(pszFileExt!= NULL) { - /* class name */ - pszClassName = MakeFileClassName(pszFileExt); - if(pszClassName!= NULL) - if (!InvokeHandler_Worker(pszClassName, pszFileName, &res)) { - /* correct registry on error (no longer in list) */ - RemoveRegFileExt(pszFileExt, pszClassName); - RemoveRegClass(pszClassName); - } - mir_free(pszClassName); /* does NULL check */ - mir_free(pszFileExt); - } - } - return res; -} - -INT_PTR InvokeUrlHandler(const TCHAR *pszUrl) -{ - char *pszClassName, *pszProtoPrefix, *p; - INT_PTR res = CALLSERVICE_NOTFOUND; - - /* find prefix */ - pszProtoPrefix = t2a(pszUrl); - if(pszProtoPrefix!= NULL) { - p = strchr(pszProtoPrefix, _T(':')); - if(p!= NULL) { - *(++p) = 0; /* remove trailing : */ - /* class name */ - pszClassName = MakeUrlClassName(pszProtoPrefix); - if(pszClassName!= NULL) - if (!InvokeHandler_Worker(pszClassName, pszUrl, &res)) - /* correct registry on error (no longer in list) */ - RemoveRegClass(pszClassName); - mir_free(pszClassName); /* does NULL check */ - } - mir_free(pszProtoPrefix); - } - return res; -} - -/************************* Options ********************************/ - -static int CALLBACK ListViewSortDesc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) -{ - int cmp; - if (((ASSOCDATA*)lParam1)->pszFileExt!= NULL && ((ASSOCDATA*)lParam2)->pszFileExt!= NULL) - cmp = CompareStringA((LCID)lParamSort, 0, ((ASSOCDATA*)lParam1)->pszFileExt, -1, ((ASSOCDATA*)lParam2)->pszFileExt, -1); - else if (((ASSOCDATA*)lParam1)->pszFileExt == ((ASSOCDATA*)lParam2)->pszFileExt) /* both NULL */ - cmp = CompareStringA((LCID)lParamSort, 0, ((ASSOCDATA*)lParam1)->pszClassName, -1, ((ASSOCDATA*)lParam2)->pszClassName, -1); - else /* different types, incomparable */ - cmp = (((ASSOCDATA*)lParam1)->pszFileExt == NULL)?CSTR_LESS_THAN:CSTR_GREATER_THAN; - if(cmp == CSTR_EQUAL) - cmp = CompareString((LCID)lParamSort, 0, ((ASSOCDATA*)lParam1)->pszDescription, -1, ((ASSOCDATA*)lParam2)->pszDescription, -1); - if(cmp!= 0) cmp -= 2; /* maintain CRT conventions */ - return cmp; -} - -#define M_REFRESH_ICONS (WM_APP+1) -static INT_PTR CALLBACK AssocListOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch(msg) { - case WM_INITDIALOG: - { HWND hwndList; - HIMAGELIST himl; - LVITEM lvi; - ASSOCDATA *assoc; - int i; - TranslateDialogDefault(hwndDlg); - CoInitialize(NULL); - 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 */ - EnterCriticalSection(&csAssocList); - { HDC hdc; - hdc = GetDC(hwndList); - if(hdc!= NULL) { /* 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); - } else himl = NULL; - } - ListView_SetImageList(hwndList, himl, LVSIL_SMALL); /* autodestroyed */ - /* enum assoc list */ - lvi.iSubItem = 0; - lvi.mask = LVIF_TEXT|LVIF_PARAM|LVIF_IMAGE; - for(i = 0;ipszDescription); - ListView_SetCheckState(hwndList, lvi.iItem, IsAssocEnabled(assoc) && IsAssocRegistered(assoc)); - } - } - /* sort items (before moving to groups) */ - ListView_SortItems(hwndList, ListViewSortDesc, (LPARAM)CallService(MS_LANGPACK_GETLOCALE, 0, 0)); - /* 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 = (WCHAR*)TranslateW(L"URLs on Websites"); - lvi.iItem = ListView_InsertItem(hwndList, &lvi); - if(lvi.iItem!= -1) { - ListView_InsertGroup(hwndList, lvi.iItem, &lvg); - lvg.iGroupId = 1; - lvg.pszHeader = (WCHAR*)TranslateW(L"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) { - assoc = (ASSOCDATA*)lvi.lParam; - if(assoc == NULL) continue; /* groups */ - lvi.iGroupId = (assoc->pszFileExt == NULL)+1; - ListView_SetItem(hwndList, &lvi); - } - } - LeaveCriticalSection(&csAssocList); - 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)DBGetContactSettingByte(NULL, "AssocMgr", "OnlyWhileRunning", SETTING_ONLYWHILERUNNING_DEFAULT)); - /* autostart */ - { TCHAR *pszRunCmd; - pszRunCmd = MakeRunCommand(TRUE, TRUE); - if(pszRunCmd!= NULL) { - CheckDlgButton(hwndDlg, IDC_AUTOSTART, IsRegRunEntry(_T("MirandaIM"), pszRunCmd)); - mir_free(pszRunCmd); - } - } - return TRUE; - } - case WM_SETTINGCHANGE: - case M_REFRESH_ICONS: - { LVITEM lvi; - HIMAGELIST himl; - ASSOCDATA *assoc; - HWND hwndList; - hwndList = GetDlgItem(hwndDlg, IDC_ASSOCLIST); - 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 == NULL) 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; - } - case WM_CTLCOLORSTATIC: - /* use same text color for header as for group boxes (WinXP+) */ - if(GetDlgCtrlID((HWND)lParam) == IDC_HEADERTEXT) { - HMODULE hUxThemeDLL; - HBRUSH hBrush; - hUxThemeDLL = LoadLibraryA("UXTHEME"); /* all ascii, already loaded */ - lParam = (LPARAM)GetDlgItem(hwndDlg, IDC_MISCLABEL); - hBrush = (HBRUSH)SendMessage(hwndDlg, msg, wParam, lParam); - if(hUxThemeDLL!= NULL) { - HTHEME (WINAPI *pfnGetWindowTheme)(HWND); - HRESULT (WINAPI *pfnGetThemeColor)(HTHEME, int, int, int, COLORREF*); - COLORREF clr; - *(PROC*)&pfnGetWindowTheme = GetProcAddress(hUxThemeDLL, "GetWindowTheme"); - *(PROC*)&pfnGetThemeColor = GetProcAddress(hUxThemeDLL, "GetThemeColor"); - if(pfnGetWindowTheme!= NULL && pfnGetThemeColor!= NULL) { - HTHEME hTheme; - hTheme = pfnGetWindowTheme((HWND)lParam); - if(hTheme!= NULL) - if (!pfnGetThemeColor(hTheme, BP_GROUPBOX, GBS_NORMAL, TMT_TEXTCOLOR, &clr)) { - SetBkMode((HDC)wParam, TRANSPARENT); - SetTextColor((HDC)wParam, clr); - } - } - FreeLibrary(hUxThemeDLL); - } - return (BOOL)hBrush; - } - break; - case WM_NCDESTROY: - CoUninitialize(); - return TRUE; - case WM_COMMAND: - /* enable apply */ - PostMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - - case WM_NOTIFYFORMAT: - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, NFR_UNICODE); - return TRUE; - - case WM_NOTIFY: - { NMHDR *nmhdr = (NMHDR*)lParam; - switch(nmhdr->idFrom) { - case IDC_ASSOCLIST: - switch(nmhdr->code) { - case LVN_DELETEITEM: /* also called on WM_DESTROY */ - { LVITEM lvi; - lvi.mask = LVIF_PARAM; - lvi.iSubItem = 0; - lvi.iItem = ((NMLISTVIEW*)lParam)->iItem; - /* free memory */ - if(ListView_GetItem(nmhdr->hwndFrom, &lvi)) - mir_free((ASSOCDATA*)lvi.lParam); /* does NULL check */ - return TRUE; - } - case LVN_ITEMCHANGED: - /* enable apply (not while loading) */ - if(IsWindowVisible(nmhdr->hwndFrom)) - PostMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - return TRUE; - case LVN_KEYDOWN: - /* workaround for WinXP (ListView with groups): - * eat keyboard navigation that goes beyond the first item in list - * as it would scroll out of scope in this case - * bug should not be present using WinVista and higher */ - switch(((NMLVKEYDOWN*)lParam)->wVKey) { - case VK_UP: - { LVITEM lvi; - lvi.iSubItem = 0; - lvi.mask = LVIF_PARAM; - lvi.iItem = ListView_GetNextItem(nmhdr->hwndFrom, -1, LVNI_FOCUSED); - lvi.iItem = ListView_GetNextItem(nmhdr->hwndFrom, lvi.iItem, LVNI_ABOVE); - if(lvi.iItem!= -1) - if(ListView_GetItem(nmhdr->hwndFrom, &lvi)) - if ((ASSOCDATA*)lvi.lParam == NULL) /* groups */ - lvi.iItem = -1; - if(lvi.iItem == -1) { - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); /* eat it */ - return TRUE; - } - break; - } - case VK_PRIOR: - { LVITEM lvi; - lvi.iSubItem = 0; - lvi.mask = LVIF_PARAM; - lvi.iItem = ListView_GetNextItem(nmhdr->hwndFrom, -1, LVNI_FOCUSED); - lvi.iItem-= ListView_GetCountPerPage(nmhdr->hwndFrom); - if(lvi.iItem>= 0) - if(ListView_GetItem(nmhdr->hwndFrom, &lvi)) - if ((ASSOCDATA*)lvi.lParam == NULL) /* groups */ - lvi.iItem = -1; - if(lvi.iItem<0) { - ListView_SetItemState(nmhdr->hwndFrom, 0, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED); - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); /* eat it */ - return TRUE; - } - break; - } - } - break; - } - break; - case 0: - switch(nmhdr->code) { - case PSN_APPLY: - { HWND hwndList; - LVITEM lvi; - BOOL fEnabled, fRegFailed = FALSE; - ASSOCDATA *assoc; - - /* only while running */ - DBWriteContactSettingByte(NULL, "AssocMgr", "OnlyWhileRunning", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_ONLYWHILERUNNING)!= 0)); - - /* save enabled assoc items */ - hwndList = GetDlgItem(hwndDlg, IDC_ASSOCLIST); - lvi.iSubItem = 0; - lvi.mask = LVIF_PARAM; - EnterCriticalSection(&csAssocList); - for(lvi.iItem = 0;ListView_GetItem(hwndList, &lvi);++lvi.iItem) { - assoc = (ASSOCDATA*)lvi.lParam; - if(assoc == NULL) continue; /* groups */ - fEnabled = ListView_GetCheckState(hwndList, lvi.iItem); - SetAssocEnabled(assoc, fEnabled); - - /* re-register registery keys */ - if(fEnabled?!EnsureAssocRegistered(assoc):!UnregisterAssoc(assoc)) { - char *pszErr; - pszErr = GetWinErrorDescription(GetLastError()); - ShowInfoMessage(NIIF_ERROR, Translate("File Association Error"), Translate("There was an error writing to the registry to modify the file/url associations.\nReason: %s"), (pszErr!= NULL)?pszErr:Translate("Unknown")); - mir_free(pszErr); /* does NULL check */ - fRegFailed = TRUE; /* just show one time */ - } - } - LeaveCriticalSection(&csAssocList); - NotifyAssocChange(TRUE); - PostMessage(hwndDlg, M_REFRESH_ICONS, 0, 0); - if(fRegFailed) { - } - /* autostart */ - { TCHAR *pszRunCmd; - pszRunCmd = MakeRunCommand(TRUE, TRUE); - fRegFailed = FALSE; - if(pszRunCmd!= NULL) { - fEnabled = IsDlgButtonChecked(hwndDlg, IDC_AUTOSTART); - if(fEnabled?!AddRegRunEntry(_T("MirandaIM"), pszRunCmd):!RemoveRegRunEntry(_T("MirandaIM"), pszRunCmd)) { - char *pszErr; - pszErr = GetWinErrorDescription(GetLastError()); - ShowInfoMessage(NIIF_ERROR, Translate("Autostart Error"), Translate("There was an error writing to the registry to modify the autostart list.\n\nReason: %s"), (pszErr!= NULL)?pszErr:Translate("Unknown")); - mir_free(pszErr); /* does NULL check */ - fRegFailed = TRUE; /* just show one time */ - } - mir_free(pszRunCmd); - } - } - return TRUE; - } - } /* code */ - break; - } /* idFrom */ - break; - } /* WM_NOTIFY */ - } - return FALSE; -} - -static int AssocListOptInit(WPARAM wParam, LPARAM lParam) -{ - OPTIONSDIALOGPAGE odp = { 0 }; - odp.cbSize = sizeof(odp); - odp.hInstance = hInst; - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ASSOCLIST); - odp.position = 900000100; /* network opts = 900000000 */ - odp.pszGroup = LPGEN("Services"); /* autotranslated */ - odp.pszTitle = LPGEN("Associations"); /* autotranslated */ - odp.flags = ODPF_BOLDGROUPS | ODPF_EXPERTONLY; - odp.pfnDlgProc = AssocListOptDlgProc; - Options_AddPage(wParam, &odp); - return 0; -} - -/************************* Misc ***********************************/ - -void InitAssocList(void) -{ - /* Options */ - INITCOMMONCONTROLSEX icc; - icc.dwSize = sizeof(icc); - icc.dwICC = ICC_LISTVIEW_CLASSES; - InitCommonControlsEx(&icc); - hHookOptInit = HookEvent(ME_OPT_INITIALISE, AssocListOptInit); - - /* Assoc List */ - pAssocList = NULL; - nAssocListCount = 0; - InitializeCriticalSection(&csAssocList); - - /* Services */ - hServiceAddFile = CreateServiceFunction(MS_ASSOCMGR_ADDNEWFILETYPE, ServiceAddNewFileType); - hServiceRemoveFile = CreateServiceFunction(MS_ASSOCMGR_REMOVEFILETYPE, ServiceRemoveFileType); - hServiceAddUrl = CreateServiceFunction(MS_ASSOCMGR_ADDNEWURLTYPE, ServiceAddNewUrlType); - hServiceRemoveUrl = CreateServiceFunction(MS_ASSOCMGR_REMOVEURLTYPE, ServiceRemoveUrlType); - - /* Notify Shell */ - nNotifyTimerID = 0; - InitializeCriticalSection(&csNotifyTimer); - - /* register open-with app */ - { TCHAR *pszAppFileName, *pszIconLoc, *pszRunCmd; - pszIconLoc = MakeIconLocation(NULL, 0); - - // miranda32.exe - pszAppFileName = MakeAppFileName(TRUE); - pszRunCmd = MakeRunCommand(TRUE, FALSE); - if(pszAppFileName!= NULL && pszRunCmd!= NULL) - AddRegOpenWith(pszAppFileName, FALSE, _T(MIRANDANAME), pszIconLoc, pszRunCmd, NULL, NULL, NULL); - mir_free(pszRunCmd); /* does NULL check */ - mir_free(pszAppFileName); /* does NULL check */ - // assocmgr.dll - pszAppFileName = MakeAppFileName(FALSE); - pszRunCmd = MakeRunCommand(FALSE, TRUE); - if(pszAppFileName!= NULL && pszRunCmd!= NULL) - AddRegOpenWith(pszAppFileName, TRUE, _T(MIRANDANAME), pszIconLoc, pszRunCmd, DDEFILECMD, DDEAPP, DDETOPIC); - mir_free(pszRunCmd); /* does NULL check */ - mir_free(pszAppFileName); /* does NULL check */ - - mir_free(pszIconLoc); /* does NULL check */ - } - - /* default items */ - { FILETYPEDESC ftd; - ftd.cbSize = sizeof(FILETYPEDESC); - ftd.pszFileExt = ".dat"; - ftd.pszMimeType = NULL; - ftd.ptszDescription = TranslateT("Miranda IM Database"); - ftd.hInstance = hInst; - ftd.nIconResID = IDI_MIRANDAFILE; - ftd.ptszVerbDesc = NULL; - ftd.pszService = NULL; - ftd.flags = FTDF_DEFAULTDISABLED|FTDF_TCHAR; - ServiceAddNewFileType(0, (LPARAM)&ftd); - } -} - -void UninitAssocList(void) -{ - BYTE fOnlyWhileRunning; - ASSOCDATA *assoc; - int i; - - /* Options */ - UnhookEvent(hHookOptInit); - - /* Services */ - DestroyServiceFunction(hServiceAddFile); - DestroyServiceFunction(hServiceRemoveFile); - DestroyServiceFunction(hServiceAddUrl); - DestroyServiceFunction(hServiceRemoveUrl); - - /* Assoc List */ - fOnlyWhileRunning = DBGetContactSettingByte(NULL, "AssocMgr", "OnlyWhileRunning", SETTING_ONLYWHILERUNNING_DEFAULT); - for(i = 0;ipszClassName); - 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 */ - } - mir_free(pAssocList); - DeleteCriticalSection(&csAssocList); - - /* Notify Shell */ - if(fOnlyWhileRunning && nAssocListCount) - NotifyAssocChange(TRUE); - DeleteCriticalSection(&csNotifyTimer); - - /* unregister open-with app */ - if(fOnlyWhileRunning) { - TCHAR *pszAppFileName; - // miranda32.exe - pszAppFileName = MakeAppFileName(TRUE); - if(pszAppFileName!= NULL) - RemoveRegOpenWith(pszAppFileName); - pszAppFileName = MakeAppFileName(FALSE); - // assocmgr.dll - if(pszAppFileName!= NULL) - RemoveRegOpenWith(pszAppFileName); - mir_free(pszAppFileName); /* does NULL check */ - } -} \ No newline at end of file diff --git a/plugins/AssocMgr/assoclist.h b/plugins/AssocMgr/assoclist.h deleted file mode 100644 index 5e8806b828..0000000000 --- a/plugins/AssocMgr/assoclist.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - -'File Association Manager'-Plugin for Miranda IM - -Copyright (C) 2005-2007 H. Herkenrath - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program (AssocMgr-License.txt); if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -/* Assoc Enabled */ -void CleanupAssocEnabledSettings(void); -/* Mime Reg */ -void CleanupMimeTypeAddedSettings(void); -/* Assoc List Utils */ -BOOL IsRegisteredAssocItem(const char *pszClassName); -/* Open Handler */ -INT_PTR InvokeFileHandler(const TCHAR *pszFileName); -INT_PTR InvokeUrlHandler(const TCHAR *pszUrl); -/* Misc */ -void InitAssocList(void); -void UninitAssocList(void); diff --git a/plugins/AssocMgr/assocmgr-translation.txt b/plugins/AssocMgr/assocmgr-translation.txt deleted file mode 100644 index b00a8c3269..0000000000 --- a/plugins/AssocMgr/assocmgr-translation.txt +++ /dev/null @@ -1,41 +0,0 @@ -; Common strings that belong to many files -;[] - -; ../../plugins/AssocMgr/assoclist.cpp -;[%hs files] -;[%hs:] -;[Associations] -;[Autostart Error] -;[Description] -;[File Association Error] -;[Miranda IM Database] -;[Services] -;[There was an error writing to the registry to modify the autostart list.\n\nReason: %s] -;[There was an error writing to the registry to modify the file/url associations.\nReason: %s] -;[Type] -;[Unknown] - -; ../../plugins/AssocMgr/dde.cpp -;[Miranda IM could not open URL] -;[Miranda IM could not open file] -;[Miranda IM was not able to open \""TCHAR_STR_PARAM"\".\n\nThe file could not be processed.] -;[Miranda IM was not able to open \""TCHAR_STR_PARAM"\".\n\nThe given URL is invalid and can not be parsed.] -;[Miranda IM was not able to open \""TCHAR_STR_PARAM"\".\n\nThere is no registered handler for this URL type.] -;[Miranda IM was not able to open \""TCHAR_STR_PARAM"\".\n\nThere is no registered handler for this file type.] - -; ../../plugins/AssocMgr/resource.rc -;[&Start Miranda IM automatically when the Computer starts (using current profile)] -;[Miscellaneous] -;[Only associate with Miranda IM while it is &running] -;[Registered associations for Miranda IM:] - -; ../../plugins/AssocMgr/test.cpp -;[&Add to Contact List...] -;[&Install] -;[AIM Link Protocol] -;[Gadu-Gadu Link Protocol] -;[ICQ Link Shortcut] -;[Jabber Link Protocol] -;[MSN Link Protocol] -;[Miranda Installer Package (demo purpose)] -;[Yahoo Link Protocol] diff --git a/plugins/AssocMgr/assocmgr.vcxproj b/plugins/AssocMgr/assocmgr.vcxproj index 457f753647..1d591fdad1 100644 --- a/plugins/AssocMgr/assocmgr.vcxproj +++ b/plugins/AssocMgr/assocmgr.vcxproj @@ -78,14 +78,14 @@ true EditAndContinue ..\..\include;..\ExternalAPI;%(AdditionalIncludeDirectories) - _DEBUG;UNICODE;WIN32;_WINDOWS;_USRDLL;STRICT;ASSOCMGR_EXPORTS;%(PreprocessorDefinitions) + WIN32;_DEBUG;_WINDOWS;_USRDLL;ASSOCMGR_EXPORTS;%(PreprocessorDefinitions) EnableFastChecks Use common.h ..\..\include\msapi - _DEBUG;_UNICODE;UNICODE;%(PreprocessorDefinitions) + _DEBUG;%(PreprocessorDefinitions) true @@ -106,14 +106,14 @@ Level3 ProgramDatabase ..\..\include;..\ExternalAPI;%(AdditionalIncludeDirectories) - _DEBUG;UNICODE;WIN64;_WINDOWS;_USRDLL;STRICT;ASSOCMGR_EXPORTS;%(PreprocessorDefinitions) + WIN64;_DEBUG;_WINDOWS;_USRDLL;ASSOCMGR_EXPORTS;%(PreprocessorDefinitions) EnableFastChecks Use common.h ..\..\include\msapi - _DEBUG;_UNICODE;UNICODE;%(PreprocessorDefinitions) + _DEBUG;%(PreprocessorDefinitions) true @@ -134,14 +134,14 @@ Full Level3 ..\..\include;..\ExternalAPI;%(AdditionalIncludeDirectories) - NDEBUG;UNICODE;WIN32;_WINDOWS;_USRDLL;STRICT;ASSOCMGR_EXPORTS;%(PreprocessorDefinitions) + WIN32;NDEBUG;_WINDOWS;_USRDLL;ASSOCMGR_EXPORTS;%(PreprocessorDefinitions) Size Use common.h ..\..\include\msapi - NDEBUG;_UNICODE;UNICODE;%(PreprocessorDefinitions) + NDEBUG;%(PreprocessorDefinitions) true @@ -164,14 +164,14 @@ Full Level3 ..\..\include;..\ExternalAPI;%(AdditionalIncludeDirectories) - NDEBUG;UNICODE;WIN64;_WINDOWS;_USRDLL;STRICT;ASSOCMGR_EXPORTS;%(PreprocessorDefinitions) + WIN64;NDEBUG;_WINDOWS;_USRDLL;ASSOCMGR_EXPORTS;%(PreprocessorDefinitions) Size Use common.h ..\..\include\msapi - NDEBUG;_UNICODE;UNICODE;%(PreprocessorDefinitions) + NDEBUG;%(PreprocessorDefinitions) true @@ -187,24 +187,24 @@ - - - + + + Create - - - + + + - - - - - - - - + + + + + + + + @@ -213,11 +213,11 @@ - - + + - + diff --git a/plugins/AssocMgr/assocmgr.vcxproj.filters b/plugins/AssocMgr/assocmgr.vcxproj.filters index 295050b0e0..85dfe0caf0 100644 --- a/plugins/AssocMgr/assocmgr.vcxproj.filters +++ b/plugins/AssocMgr/assocmgr.vcxproj.filters @@ -19,53 +19,53 @@ - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Header Files - + Header Files - + Header Files - + Header Files - + Header Files - + Header Files - + Resource Files - + Resource Files - + Resource Files @@ -88,10 +88,10 @@ Documentation - + Documentation - + Documentation diff --git a/plugins/AssocMgr/common.h b/plugins/AssocMgr/common.h deleted file mode 100644 index 9f6c0b7505..0000000000 --- a/plugins/AssocMgr/common.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - -'File Association Manager'-Plugin for Miranda IM - -Copyright (C) 2005-2007 H. Herkenrath - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program (AssocMgr-License.txt); if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#define _CRT_SECURE_NO_WARNINGS -#define _WIN32_WINNT 0x0600 -#define __RPCASYNC_H__ /* VC6 has a mistake in there (warning) */ -#include -#pragma warning(disable:4201) /* nonstandard extension used : nameless struct/union */ -#pragma warning(disable:4115) /* V6 has a mistake in there (warning) */ -#include /* for SHChangeNotify() */ -#pragma warning(default:4115) -#include -#pragma warning(default:4201) -#include -#include /* for mir_snprintf() */ -#include -#include -#include - -#define MIRANDA_VER 0x0A00 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "win2k.h" - -#define ASSOCMGR_NOHELPERFUNCTIONS -#include "m_assocmgr.h" -#include "utils.h" -#include "reg.h" -#include "assoclist.h" -#include "dde.h" -#include "test.h" -#include "resource.h" diff --git a/plugins/AssocMgr/dde.cpp b/plugins/AssocMgr/dde.cpp deleted file mode 100644 index a8328b4d34..0000000000 --- a/plugins/AssocMgr/dde.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/* - -'File Association Manager'-Plugin for Miranda IM - -Copyright (C) 2005-2007 H. Herkenrath - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program (AssocMgr-License.txt); if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "common.h" - -/* Conversation */ -extern HINSTANCE hInst; -static HWND hwndDdeMsg; -/* Misc */ -static HANDLE hHookModulesLoaded,hHookPreShutdown; - -/************************* Open Handler ***************************/ - -// pszFilePath needs to be allocated using mir_alloc() -static void __stdcall FileActionAsync(void *param) -{ - TCHAR *pszFilePath = (TCHAR*)param; - /* invoke main handler */ - switch(InvokeFileHandler(pszFilePath)) { /* pszFilePath is always a long path name */ - case 0: /* success */ break; - case CALLSERVICE_NOTFOUND: - ShowInfoMessage(NIIF_ERROR,Translate("Miranda IM could not open file"),Translate("Miranda IM was not able to open \""TCHAR_STR_PARAM"\".\n\nThere is no registered handler for this file type."),pszFilePath); - break; - default: - ShowInfoMessage(NIIF_ERROR,Translate("Miranda IM could not open file"),Translate("Miranda IM was not able to open \""TCHAR_STR_PARAM"\".\n\nThe file could not be processed."),pszFilePath); - } - mir_free(pszFilePath); /* async param */ -} - -// pszUrl needs to be allocated using mir_alloc() -static void __stdcall UrlActionAsync(void *param) -{ - TCHAR *pszUrl = (TCHAR*)param; - /* invoke main handler */ - switch(InvokeUrlHandler(pszUrl)) { - case 0: /* success */ break; - case CALLSERVICE_NOTFOUND: - ShowInfoMessage(NIIF_ERROR,Translate("Miranda IM could not open URL"),Translate("Miranda IM was not able to open \""TCHAR_STR_PARAM"\".\n\nThere is no registered handler for this URL type."),pszUrl); - break; - default: - ShowInfoMessage(NIIF_ERROR,Translate("Miranda IM could not open URL"),Translate("Miranda IM was not able to open \""TCHAR_STR_PARAM"\".\n\nThe given URL is invalid and can not be parsed."),pszUrl); - } - mir_free(pszUrl); /* async param */ -} - -/************************* Conversation ***************************/ - -#define DDEMESSAGETIMEOUT 30000 -#define WNDCLASS_DDEMSGWINDOW _T("MirandaDdeMsgWindow") - -// returned pointer points into a substring of ppszString -// returns an empty string if the string does not have enough arguments -static TCHAR* GetExecuteParam(TCHAR **ppszString) -{ - TCHAR *pszParam,*p; - BOOL fQuoted; - - fQuoted=(**ppszString==_T('"')); - pszParam=*ppszString; - if(fQuoted) pszParam++; - p=_tcschr(pszParam,(TCHAR)(fQuoted?_T('"'):_T(','))); - if(p!=NULL) { - *(p++)=0; - if(fQuoted && *p==_T(',')) p++; - } else p=&pszParam[lstrlen(pszParam)]; - *ppszString=p; - return pszParam; -} - -static LRESULT CALLBACK DdeMessageWindow(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) -{ - switch(msg) { - case WM_DDE_INITIATE: - { ATOM hSzApp,hSzTopic; - hSzApp=LOWORD(lParam); /* no UnpackDDElParam() here */ - hSzTopic=HIWORD(lParam); - if ((hSzApp==GlobalFindAtom(DDEAPP) && hSzTopic==GlobalFindAtom(DDETOPIC)) || !hSzApp) { - hSzApp=GlobalAddAtom(DDEAPP); - hSzTopic=GlobalAddAtom(DDETOPIC); - if(hSzApp && hSzTopic) - /* PackDDElParam() only for posted msgs */ - SendMessage((HWND)wParam,WM_DDE_ACK,(WPARAM)hwnd,MAKELPARAM(hSzApp,hSzTopic)); - if(hSzApp) GlobalDeleteAtom(hSzApp); - if(hSzTopic) GlobalDeleteAtom(hSzTopic); - } - return 0; - } - case WM_DDE_EXECUTE: /* posted message */ - { HGLOBAL hCommand; - TCHAR *pszCommand; - DDEACK ack; - ZeroMemory(&ack,sizeof(ack)); - if(UnpackDDElParam(msg,lParam,NULL,(PUINT_PTR)&hCommand)) { - - /* ANSI execute command can't happen for shell */ - if(IsWindowUnicode((HWND)wParam)) { - - pszCommand = (TCHAR*)GlobalLock(hCommand); - if(pszCommand!=NULL) { - TCHAR *pszAction,*pszArg; - pszAction=GetExecuteParam(&pszCommand); - pszArg=mir_tstrdup(GetExecuteParam(&pszCommand)); - if(pszArg!=NULL) { - /* we are inside miranda here, we make it async so the shell does - * not timeout regardless what the plugins try to do. */ - if (!lstrcmpi(pszAction,_T("file"))) - ack.fAck=(short)(CallFunctionAsync(FileActionAsync,pszArg)!=0); - else if (!lstrcmpi(pszAction,_T("url"))) - ack.fAck=(short)(CallFunctionAsync(UrlActionAsync,pszArg)!=0); - if (!ack.fAck) mir_free(pszArg); /* otherwise freed by asyncproc */ - } - GlobalUnlock(hCommand); - } - - } - - lParam=ReuseDDElParam(lParam,msg,WM_DDE_ACK,*(PUINT)&ack,(UINT)hCommand); - if (!PostMessage((HWND)wParam,WM_DDE_ACK,(WPARAM)hwnd,lParam)) { - GlobalFree(hCommand); - FreeDDElParam(WM_DDE_ACK,lParam); - } - } - return 0; - } - case WM_DDE_TERMINATE: - PostMessage((HWND)wParam,msg,(WPARAM)hwnd,0); /* ack reply */ - return 0; - case WM_DDE_REQUEST: - case WM_DDE_ADVISE: - case WM_DDE_UNADVISE: - case WM_DDE_POKE: - /* fail safely for those to avoid memory leak in lParam */ - { ATOM hSzItem; - DDEACK ack; - ZeroMemory(&ack,sizeof(ack)); - if(UnpackDDElParam(msg,lParam,NULL,(PUINT_PTR)&hSzItem)) { - lParam=ReuseDDElParam(lParam,msg,WM_DDE_ACK,*(PUINT)&ack,(UINT)hSzItem); - if (!PostMessage((HWND)wParam,WM_DDE_ACK,(WPARAM)hwnd,lParam)) { - if(hSzItem) GlobalDeleteAtom(hSzItem); - FreeDDElParam(WM_DDE_ACK,lParam); - } - } - return 0; - } - } - return DefWindowProc(hwnd,msg,wParam,lParam); -} - -// CloseHandle() the return value -static HANDLE StartupMainProcess(TCHAR *pszDatabasePath) -{ - TCHAR *p,szPath[MAX_PATH]; - PROCESS_INFORMATION pi; - STARTUPINFO si; - - /* we are inside RunDll32 here */ - if (!GetModuleFileName(hInst,szPath,SIZEOF(szPath))) return NULL; - p=_tcsrchr(szPath,_T('\\')); - if(p!=NULL) { *p=0; p=_tcsrchr(szPath,_T('\\')); } - if(p==NULL) return NULL; - lstrcpy(++p,_T("miranda32.exe")); - - /* inherit startup data from RunDll32 process */ - GetStartupInfo(&si); - if (!CreateProcess(szPath,pszDatabasePath,NULL,NULL,TRUE,GetPriorityClass(GetCurrentProcess()),NULL,NULL,&si,&pi)) - return NULL; - CloseHandle(pi.hThread); - return pi.hProcess; -} - -#ifdef __cplusplus -extern "C" { -#endif - -// entry point for RunDll32, this is also WaitForDDEW -__declspec(dllexport) void CALLBACK WaitForDDE(HWND hwnd,HINSTANCE hinstExe,TCHAR *pszCmdLine,int nCmdShow) -{ - HANDLE pHandles[2]; - DWORD dwTick; - UNREFERENCED_PARAMETER(hinstExe); - UNREFERENCED_PARAMETER(nCmdShow); /* obeys nCmdShow using GetStartupInfo() */ - UNREFERENCED_PARAMETER(hwnd); - - /* wait for dde window to be available (avoiding race condition) */ - pHandles[0]=CreateEvent(NULL,TRUE,FALSE,WNDCLASS_DDEMSGWINDOW); - if(pHandles[0]!=NULL) { - pHandles[1]=StartupMainProcess(pszCmdLine); /* obeys nCmdShow using GetStartupInfo() */ - if(pHandles[1]!=NULL) { - dwTick=GetTickCount(); - /* either process terminated or dde window created */ - if(WaitForMultipleObjects(SIZEOF(pHandles),pHandles,FALSE,DDEMESSAGETIMEOUT)==WAIT_OBJECT_0) { - dwTick=GetTickCount()-dwTick; - if(dwTick + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/plugins/AssocMgr/docs/assocmgr-translation.txt b/plugins/AssocMgr/docs/assocmgr-translation.txt new file mode 100644 index 0000000000..b00a8c3269 --- /dev/null +++ b/plugins/AssocMgr/docs/assocmgr-translation.txt @@ -0,0 +1,41 @@ +; Common strings that belong to many files +;[] + +; ../../plugins/AssocMgr/assoclist.cpp +;[%hs files] +;[%hs:] +;[Associations] +;[Autostart Error] +;[Description] +;[File Association Error] +;[Miranda IM Database] +;[Services] +;[There was an error writing to the registry to modify the autostart list.\n\nReason: %s] +;[There was an error writing to the registry to modify the file/url associations.\nReason: %s] +;[Type] +;[Unknown] + +; ../../plugins/AssocMgr/dde.cpp +;[Miranda IM could not open URL] +;[Miranda IM could not open file] +;[Miranda IM was not able to open \""TCHAR_STR_PARAM"\".\n\nThe file could not be processed.] +;[Miranda IM was not able to open \""TCHAR_STR_PARAM"\".\n\nThe given URL is invalid and can not be parsed.] +;[Miranda IM was not able to open \""TCHAR_STR_PARAM"\".\n\nThere is no registered handler for this URL type.] +;[Miranda IM was not able to open \""TCHAR_STR_PARAM"\".\n\nThere is no registered handler for this file type.] + +; ../../plugins/AssocMgr/resource.rc +;[&Start Miranda IM automatically when the Computer starts (using current profile)] +;[Miscellaneous] +;[Only associate with Miranda IM while it is &running] +;[Registered associations for Miranda IM:] + +; ../../plugins/AssocMgr/test.cpp +;[&Add to Contact List...] +;[&Install] +;[AIM Link Protocol] +;[Gadu-Gadu Link Protocol] +;[ICQ Link Shortcut] +;[Jabber Link Protocol] +;[MSN Link Protocol] +;[Miranda Installer Package (demo purpose)] +;[Yahoo Link Protocol] diff --git a/plugins/AssocMgr/main.cpp b/plugins/AssocMgr/main.cpp deleted file mode 100644 index e6095c25c4..0000000000 --- a/plugins/AssocMgr/main.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - -'File Association Manager'-Plugin for Miranda IM - -Copyright (C) 2005-2007 H. Herkenrath - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program (AssocMgr-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 "version.h" - -HINSTANCE hInst; -static HANDLE hHookModulesLoaded; -int hLangpack; - -PLUGININFOEX pluginInfo={ - sizeof(PLUGININFOEX), - __PLUGIN_NAME, - PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), - __DESCRIPTION, - __AUTHOR, - __AUTHOREMAIL, - __COPYRIGHT, - __AUTHORWEB, - UNICODE_AWARE, - // {52685CD7-0EC7-44c1-A1A6-381612418202} - {0x52685cd7,0xec7,0x44c1,{0xa1,0xa6,0x38,0x16,0x12,0x41,0x82,0x2}} -}; -static const MUUID interfaces[]={MIID_ASSOCMGR,MIID_AUTORUN,MIID_LAST}; - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - hInst = hinstDLL; - return TRUE; -} - -static void InstallFile(const TCHAR *pszFileName,const TCHAR *pszDestSubDir) -{ - TCHAR szFileFrom[MAX_PATH+1],szFileTo[MAX_PATH+1],*p; - HANDLE hFile; - - if (!GetModuleFileName(hInst,szFileFrom,SIZEOF(szFileFrom)-lstrlen(pszFileName))) - return; - p=_tcsrchr(szFileFrom,_T('\\')); - if(p!=NULL) *(++p)=0; - lstrcat(szFileFrom,pszFileName); /* buffer safe */ - - hFile=CreateFile(szFileFrom,0,FILE_SHARE_READ,0,OPEN_EXISTING,0,0); - if(hFile==INVALID_HANDLE_VALUE) return; - CloseHandle(hFile); - - if (!GetModuleFileNameWorkaround(NULL,szFileTo,SIZEOF(szFileTo)-lstrlen(pszDestSubDir)-lstrlen(pszFileName))) - return; - p=_tcsrchr(szFileTo,_T('\\')); - if(p!=NULL) *(++p)=0; - lstrcat(szFileTo,pszDestSubDir); /* buffer safe */ - CreateDirectory(szFileTo,NULL); - lstrcat(szFileTo,pszFileName); /* buffer safe */ - - if (!MoveFile(szFileFrom,szFileTo) && GetLastError()==ERROR_ALREADY_EXISTS) { - DeleteFile(szFileTo); - MoveFile(szFileFrom,szFileTo); - } -} - -static int AssocMgrModulesLoaded(WPARAM wParam,LPARAM lParam) -{ - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - if(ServiceExists("DBEditorpp/RegisterSingleModule")) - CallService("DBEditorpp/RegisterSingleModule",(WPARAM)"AssocMgr",0); - InitTest(); - return 0; -} - -extern "C" __declspec(dllexport) const PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) -{ - return &pluginInfo; -} - -extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void) -{ - return interfaces; -} - -extern "C" __declspec(dllexport) int Load(void) -{ - mir_getLP(&pluginInfo); - - InitAssocList(); - InitDde(); - - /* installation */ - InstallFile(_T("AssocMgr-Readme.txt"),_T("Docs\\")); - InstallFile(_T("AssocMgr-License.txt"),_T("Docs\\")); - InstallFile(_T("AssocMgr-SDK.zip"),_T("Docs\\")); - hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,AssocMgrModulesLoaded); - return 0; -} - -extern "C" __declspec(dllexport) int Unload(void) -{ - UninitTest(); - UninitDde(); - UninitAssocList(); - UnhookEvent(hHookModulesLoaded); - return 0; -} \ No newline at end of file diff --git a/plugins/AssocMgr/reg.cpp b/plugins/AssocMgr/reg.cpp deleted file mode 100644 index 92451a52d3..0000000000 --- a/plugins/AssocMgr/reg.cpp +++ /dev/null @@ -1,1295 +0,0 @@ -/* - -'File Association Manager'-Plugin for Miranda IM - -Copyright (C) 2005-2007 H. Herkenrath - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program (AssocMgr-License.txt); if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "common.h" - -#ifdef _DEBUG -/* Debug: Ensure all registry calls do succeed and have valid parameters. - * Shows a details message box otherwise. */ -static __inline LONG regchk(LONG res,const char *pszFunc,const void *pszInfo,BOOL fInfoUnicode,const char *pszFile,unsigned int nLine) -{ - if(res!=ERROR_SUCCESS && res!=ERROR_FILE_NOT_FOUND && res!=ERROR_NO_MORE_ITEMS) { - TCHAR szMsg[1024],*pszInfo2; - char *pszErr; - pszErr=GetWinErrorDescription(res); - pszInfo2=s2t(pszInfo,fInfoUnicode,FALSE); /* does NULL check */ - mir_sntprintf(szMsg,SIZEOF(szMsg),_T("Access failed:\n%.64hs(%.128s)\n%.250hs(%u)\n%.256hs (%u)"),pszFunc,pszInfo2,pszFile,nLine,pszErr,res); - MessageBox(NULL,szMsg,_T("Registry Warning"),MB_OK|MB_ICONINFORMATION|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL); - if(pszErr!=NULL) LocalFree(pszErr); - mir_free(pszInfo2); /* does NULL check */ - } - return res; -} -#undef RegCloseKey -#define RegCloseKey(hKey) \ - regchk(RegCloseKey(hKey),"RegCloseKey",NULL,FALSE,__FILE__,__LINE__) -#undef RegOpenKeyExA -#define RegOpenKeyExA(hKey,szSubkey,opt,rights,phKey) \ - regchk(RegOpenKeyExA(hKey,szSubkey,opt,rights,phKey),"RegOpenKeyExA",szSubkey,FALSE,__FILE__,__LINE__) -#undef RegCreateKeyExA -#define RegCreateKeyExA(hKey,szSubkey,x,y,opt,rights,sec,phKey,pDisp) \ - regchk(RegCreateKeyExA(hKey,szSubkey,x,y,opt,rights,sec,phKey,pDisp),"RegCreateKeyExA",szSubkey,FALSE,__FILE__,__LINE__) -#undef RegDeleteKeyA -#define RegDeleteKeyA(hKey,szName) \ - regchk(RegDeleteKeyA(hKey,szName),"RegDeleteKeyA",szName,FALSE,__FILE__,__LINE__) -#undef RegSetValueExA -#define RegSetValueExA(hSubKey,szName,x,type,pVal,size) \ - regchk(RegSetValueExA(hSubKey,szName,x,type,pVal,size),"RegSetValueExA",szName,FALSE,__FILE__,__LINE__) -#undef RegQueryValueExA -#define RegQueryValueExA(hKey,szName,x,pType,pVal,pSize) \ - regchk(RegQueryValueExA(hKey,szName,x,pType,pVal,pSize),"RegQueryValueExA",szName,FALSE,__FILE__,__LINE__) -#undef RegQueryInfoKeyA -#define RegQueryInfoKeyA(hKey,x,y,z,pnKeys,pnKeyLen,a,pnVals,pnNames,pnValLen,sec,pTime) \ - regchk(RegQueryInfoKeyA(hKey,x,y,z,pnKeys,pnKeyLen,a,pnVals,pnNames,pnValLen,sec,pTime),"RegQueryInfoKeyA",NULL,FALSE,__FILE__,__LINE__) -#undef RegEnumKeyExA -#define RegEnumKeyExA(hKey,idx,pName,pnName,x,y,z,pTime) \ - regchk(RegEnumKeyExA(hKey,idx,pName,pnName,x,y,z,pTime),"RegEnumKeyExA",NULL,FALSE,__FILE__,__LINE__) -#undef RegDeleteValueA -#define RegDeleteValueA(hKey,szName) \ - regchk(RegDeleteValueA(hKey,szName),"RegDeleteValueA",szName,FALSE,__FILE__,__LINE__) -#undef RegOpenKeyExW -#define RegOpenKeyExW(hKey,szSubkey,x,sam,phKey) \ - regchk(RegOpenKeyExW(hKey,szSubkey,x,sam,phKey),"RegOpenKeyExW",szSubkey,TRUE,__FILE__,__LINE__) -#undef RegCreateKeyExW -#define RegCreateKeyExW(hKey,szSubkey,x,y,z,rights,p,phKey,q) \ - regchk(RegCreateKeyExW(hKey,szSubkey,x,y,z,rights,p,phKey,q),"RegCreateKeyExW",szSubkey,TRUE,__FILE__,__LINE__) -#undef RegDeleteKeyW -#define RegDeleteKeyW(hKey,szName) \ - regchk(RegDeleteKeyW(hKey,szName),"RegDeleteKeyW",szName,TRUE,__FILE__,__LINE__) -#undef RegSetValueExW -#define RegSetValueExW(hSubKey,szName,x,type,pVal,size) \ - regchk(RegSetValueExW(hSubKey,szName,x,type,pVal,size),"RegSetValueExW",szName,TRUE,__FILE__,__LINE__) -#undef RegQueryValueExW -#define RegQueryValueExW(hKey,szName,x,pType,pVal,pSize) \ - regchk(RegQueryValueExW(hKey,szName,x,pType,pVal,pSize),"RegQueryValueExW",szName,TRUE,__FILE__,__LINE__) -#undef RegQueryInfoKeyW -#define RegQueryInfoKeyW(hKey,x,y,z,pnKeys,pnKeyLen,a,pnVals,pnNames,pnValLen,sec,pTime) \ - regchk(RegQueryInfoKeyW(hKey,x,y,z,pnKeys,pnKeyLen,a,pnVals,pnNames,pnValLen,sec,pTime),"RegQueryInfoKeyW",NULL,TRUE,__FILE__,__LINE__) -#undef RegEnumKeyExW -#define RegEnumKeyExW(hKey,idx,pName,pnName,x,y,z,pTime) \ - regchk(RegEnumKeyExW(hKey,idx,pName,pnName,x,y,z,pTime),"RegEnumKeyExW",NULL,TRUE,__FILE__,__LINE__) -#undef RegDeleteValueW -#define RegDeleteValueW(hKey,szName) \ - regchk(RegDeleteValueW(hKey,szName),"RegDeleteValueW",szName,TRUE,__FILE__,__LINE__) -#endif // _DEBUG - -/************************* Strings ********************************/ - -// mir_free() the return value -char *MakeFileClassName(const char *pszFileExt) -{ - char *pszClass; - pszClass=(char*)mir_alloc((lstrlenA(pszFileExt)+12)*sizeof(TCHAR)); - if(pszClass!=NULL) - /* using correctly formated PROGID */ - wsprintfA(pszClass,"miranda%sfile",pszFileExt); /* includes dot, buffer safe */ - return pszClass; -} - -// mir_free() the return value -char *MakeUrlClassName(const char *pszUrl) -{ - char *pszClass; - pszClass=mir_strdup(pszUrl); - if(pszClass!=NULL) - /* remove trailing : */ - pszClass[lstrlenA(pszClass)-1]=0; - return pszClass; -} - -static BOOL IsFileClassName(char *pszClassName, char **ppszFileExt) -{ - *ppszFileExt = strchr(pszClassName,'.'); - return *ppszFileExt!=NULL; -} - -// mir_free() the return value -TCHAR *MakeRunCommand(BOOL fMirExe,BOOL fFixedDbProfile) -{ - extern HINSTANCE hInst; - TCHAR szExe[MAX_PATH],*pszFmt,*pszRunCmd=NULL; - char szDbFile[MAX_PATH]; - int cch; - if (!fFixedDbProfile || !CallService(MS_DB_GETPROFILENAME,SIZEOF(szDbFile),(LPARAM)szDbFile)) - if(GetModuleFileNameWorkaround(fMirExe?NULL:hInst,szExe,SIZEOF(szExe))) { - /* db file */ - if (!fFixedDbProfile) - lstrcpyA(szDbFile,"%1"); /* buffer safe */ - /* size */ - cch=lstrlen(szExe)+lstrlenA(szDbFile); - if(fMirExe) { - /* run command for miranda32.exe */ - cch+=7; - pszFmt=_T("\"%s\" \"%hs\""); - } else { - DWORD len; - /* run command for rundll32.exe calling WaitForDDE */ - cch+=28; - pszFmt=_T("rundll32.exe %s,WaitForDDE \"%hs\""); - /* ensure the command line is not too long */ - GetShortPathName(szExe,szExe,SIZEOF(szExe)); - /* surround by quotes if failed */ - len=lstrlen(szExe); - if(_tcschr(szExe,_T(' '))!=NULL && (len+2)sizeof(TCHAR)) { - pszVal=(TCHAR*)mir_alloc(dwSize+sizeof(TCHAR)); - if(pszVal!=NULL) { - /* get value */ - if (!RegQueryValueEx(hKey,pszValName,NULL,&dwType,(BYTE*)pszVal,&dwSize)) { - pszVal[dwSize/sizeof(TCHAR)]=0; - if(dwType==REG_EXPAND_SZ) { - dwSize=MAX_PATH; - pszVal2=(TCHAR*)mir_alloc(dwSize*sizeof(TCHAR)); - if(ExpandEnvironmentStrings(pszVal,pszVal2,dwSize)) { - mir_free(pszVal); - return pszVal2; - } - mir_free(pszVal2); - } else if(dwType==REG_SZ) - return pszVal; - } - mir_free(pszVal); - } - } - return NULL; -} - -// hKey must have been opened with KEY_QUERY_VALUE access right -static BOOL IsRegStrValue(HKEY hKey,const TCHAR *pszValName,const TCHAR *pszCmpVal) -{ - BOOL fSame=FALSE; - TCHAR *pszVal; - pszVal=GetRegStrValue(hKey,pszValName); - if(pszVal!=NULL) { - fSame=!lstrcmp(pszVal,pszCmpVal); - mir_free(pszVal); - } - return fSame; -} - -// hKey must have been opened with KEY_QUERY_VALUE access right -static BOOL IsRegStrValueA(HKEY hKey,const TCHAR *pszValName,const char *pszCmpVal) -{ - BOOL fSame=FALSE; - TCHAR *pszVal; - char *pszValA; - pszVal=GetRegStrValue(hKey,pszValName); - if(pszVal!=NULL) { - pszValA=t2a(pszVal); - if(pszValA!=NULL) - fSame=!lstrcmpA(pszValA,pszCmpVal); - mir_free(pszValA); /* does NULL check */ - mir_free(pszVal); - } - return fSame; -} - -/************************* Backup to DB ***************************/ - -#define REGF_ANSI 0x80000000 /* this bit is set in dwType for ANSI registry data */ - -// pData must always be Unicode data, registry supports Unicode even on Win95 -static void WriteDbBackupData(const char *pszSetting,DWORD dwType,BYTE *pData,DWORD cbData) -{ - DBCONTACTWRITESETTING dbcws; - dbcws.szModule="AssocMgr"; - dbcws.szSetting=pszSetting; - dbcws.value.type=DBVT_BLOB; - dbcws.value.cpbVal=(WORD)(cbData+sizeof(DWORD)); - dbcws.value.pbVal=(BYTE*)mir_alloc(cbData+sizeof(DWORD)); - if(dbcws.value.pbVal==NULL) return; - *(DWORD*)dbcws.value.pbVal=dwType; - CopyMemory(dbcws.value.pbVal+sizeof(DWORD),pData,cbData); - CallService(MS_DB_CONTACT_WRITESETTING,0,(LPARAM)&dbcws); - mir_free(dbcws.value.pbVal); -} - -// mir_free() the value returned in ppData -static BOOL ReadDbBackupData(const char *pszSetting,DWORD *pdwType,BYTE **ppData,DWORD *pcbData) -{ - DBCONTACTGETSETTING dbcgs; - DBVARIANT dbv; - dbcgs.szModule="AssocMgr"; - dbcgs.szSetting=pszSetting; - dbcgs.pValue=&dbv; - if (!CallService(MS_DB_CONTACT_GETSETTING,0,(LPARAM)&dbcgs)) { - if(dbv.type==DBVT_BLOB && dbv.cpbVal>=sizeof(DWORD)) { - *pdwType=*(DWORD*)dbv.pbVal; - *ppData=dbv.pbVal; - *pcbData=dbv.cpbVal-sizeof(DWORD); - MoveMemory(*ppData,*ppData+sizeof(DWORD),*pcbData); - return TRUE; - } - CallService(MS_DB_CONTACT_FREEVARIANT,0,(LPARAM)&dbv); - } - return FALSE; -} - -struct BackupRegTreeParam { - char **ppszDbPrefix; - DWORD *pdwDbPrefixSize; - int level; -}; - -static void BackupRegTree_Worker(HKEY hKey,const char *pszSubKey,struct BackupRegTreeParam *param) -{ - LONG res; - DWORD nMaxSubKeyLen,nMaxValNameLen,nMaxValSize; - DWORD index,cchName,dwType,cbData; - BYTE *pData; - char *pszName; - register TCHAR *ptszName; - DWORD nDbPrefixLen; - if ((res=RegOpenKeyExA(hKey,pszSubKey,0,KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS,&hKey))==ERROR_SUCCESS) { - if ((res=RegQueryInfoKey(hKey,NULL,NULL,NULL,NULL,&nMaxSubKeyLen,NULL,NULL,&nMaxValNameLen,&nMaxValSize,NULL,NULL))==ERROR_SUCCESS) { - if(nMaxSubKeyLen>nMaxValNameLen) nMaxValNameLen=nMaxSubKeyLen; - /* prepare buffer */ - nDbPrefixLen=(DWORD)lstrlenA(*param->ppszDbPrefix)+lstrlenA(pszSubKey)+1; - cchName=nDbPrefixLen+nMaxValNameLen+3; - if(cchName>*param->pdwDbPrefixSize) { - pszName=(char*)mir_realloc(*param->ppszDbPrefix,cchName); - if(pszName==NULL) return; - *param->ppszDbPrefix=pszName; - *param->pdwDbPrefixSize=cchName; - } - lstrcatA(lstrcatA(*param->ppszDbPrefix,pszSubKey),"\\"); /* buffer safe */ - /* enum values */ - pszName=(char*)mir_alloc(nMaxValNameLen+1); - if(nMaxValSize==0) nMaxValSize=1; - pData=(BYTE*)mir_alloc(nMaxValSize); - if(pszName!=NULL && pData!=NULL) { - index=0; - while(!res) { - cchName=nMaxValNameLen+1; - cbData=nMaxValSize; - if ((res=RegEnumValueA(hKey,index++,pszName,&cchName,NULL,NULL,NULL,NULL))==ERROR_SUCCESS) { - (*param->ppszDbPrefix)[nDbPrefixLen]=0; - lstrcatA(*param->ppszDbPrefix,pszName); /* buffer safe */ - ptszName=a2t(pszName); - if(ptszName!=NULL) { - if (!RegQueryValueEx(hKey,ptszName,NULL,&dwType,pData,&cbData)) { - - WriteDbBackupData(*param->ppszDbPrefix,dwType,pData,cbData); - - } - mir_free(ptszName); - } - } - } - if(res==ERROR_NO_MORE_ITEMS) res=ERROR_SUCCESS; - } - mir_free(pData); /* does NULL check */ - /* enum subkeys */ - if(param->level<32 && pszName!=NULL) { - ++param->level; /* can be max 32 levels deep (after prefix), restriction of RegCreateKeyEx() */ - index=0; - while(!res) { - cchName=nMaxSubKeyLen+1; - if ((res=RegEnumKeyExA(hKey,index++,pszName,&cchName,NULL,NULL,NULL,NULL))==ERROR_SUCCESS) { - (*param->ppszDbPrefix)[nDbPrefixLen]=0; - BackupRegTree_Worker(hKey,pszName,param); /* recursion */ - } - } - } - if(res==ERROR_NO_MORE_ITEMS) res=ERROR_SUCCESS; - mir_free(pszName); /* does NULL check */ - } - RegCloseKey(hKey); - } -} - -static void BackupRegTree(HKEY hKey,const char *pszSubKey,const char *pszDbPrefix) -{ - struct BackupRegTreeParam param; - DWORD dwDbPrefixSize; - param.level=0; - param.pdwDbPrefixSize=&dwDbPrefixSize; - param.ppszDbPrefix=(char**)&pszDbPrefix; - pszDbPrefix=mir_strdup(pszDbPrefix); - if(pszDbPrefix!=NULL) { - dwDbPrefixSize=lstrlenA(pszDbPrefix)+1; - BackupRegTree_Worker(hKey,pszSubKey,¶m); - mir_free((char*)pszDbPrefix); - } -} - -static LONG RestoreRegTree(HKEY hKey,const char *pszSubKey,const char *pszDbPrefix) -{ - char **ppszSettings,*pszSuffix,*pszPrefixWithSubKey; - int nSettingsCount,i,nDbPrefixLen,nPrefixWithSubKeyLen; - char *pslash=NULL,*pnext,*pkeys; - char *pszValName; - WCHAR *pwszValName; - HKEY hSubKey; - DWORD dwType,cbData; - BYTE *pData; - LONG res; - - nDbPrefixLen=lstrlenA(pszDbPrefix); - nPrefixWithSubKeyLen=nDbPrefixLen+lstrlenA(pszSubKey)+1; - pszPrefixWithSubKey=(char*)mir_alloc(nPrefixWithSubKeyLen+1); - if(pszPrefixWithSubKey==NULL) return ERROR_OUTOFMEMORY; - lstrcatA(lstrcatA(lstrcpyA(pszPrefixWithSubKey,pszDbPrefix),pszSubKey),"\\"); /* buffer safe */ - res=ERROR_NO_MORE_ITEMS; - if(pszPrefixWithSubKey!=NULL) { - if(EnumDbPrefixSettings("AssocMgr",pszPrefixWithSubKey,&ppszSettings,&nSettingsCount)) { - for(i=0;i + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Englisch (GB) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE MOVEABLE PURE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE MOVEABLE PURE +BEGIN + "#include \r\n" + "\0" +END + +3 TEXTINCLUDE MOVEABLE PURE +BEGIN + "#include ""version.rc""\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_OPT_ASSOCLIST DIALOGEX 0, 0, 301, 227 +STYLE DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Registered associations for Miranda IM:", + IDC_HEADERTEXT,3,0,295,8,SS_NOPREFIX + CONTROL "",IDC_ASSOCLIST,"SysListView32",LVS_REPORT | + LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | + WS_BORDER | WS_TABSTOP,3,10,295,169 + GROUPBOX "Miscellaneous",IDC_MISCLABEL,3,183,295,41,WS_GROUP + CONTROL "&Start Miranda IM automatically when the Computer starts (using current profile)", + IDC_AUTOSTART,"Button",BS_AUTOCHECKBOX | BS_TOP | + WS_TABSTOP,10,195,284,10 + CONTROL "Only associate with Miranda IM while it is &running", + IDC_ONLYWHILERUNNING,"Button",BS_AUTOCHECKBOX | BS_TOP | + WS_TABSTOP,10,208,284,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MIRANDA ICON DISCARDABLE "res/miranda.ico" +IDI_MIRANDAFILE ICON DISCARDABLE "res/mirandafile.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_OPT_ASSOCLIST, DIALOG + BEGIN + VERTGUIDE, 3 + VERTGUIDE, 10 + VERTGUIDE, 294 + VERTGUIDE, 298 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Englisch (GB) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#include "version.rc" + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/AssocMgr/res/version.rc b/plugins/AssocMgr/res/version.rc new file mode 100644 index 0000000000..b052561f31 --- /dev/null +++ b/plugins/AssocMgr/res/version.rc @@ -0,0 +1,36 @@ +#include "version.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION __FILEVERSION_STRING + PRODUCTVERSION __FILEVERSION_STRING + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x0L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "FileDescription", __DESCRIPTION + VALUE "InternalName", __PLUGIN_NAME + VALUE "LegalCopyright", __COPYRIGHT + VALUE "OriginalFilename", __FILENAME + VALUE "ProductName", __PLUGIN_NAME + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END diff --git a/plugins/AssocMgr/resource.h b/plugins/AssocMgr/resource.h deleted file mode 100644 index 2eda2da237..0000000000 --- a/plugins/AssocMgr/resource.h +++ /dev/null @@ -1,24 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by resource.rc -// -#define IDI_MIRANDA 101 -#define IDI_MIRANDAFILE 102 -#define IDD_OPT_ASSOCLIST 103 -#define IDC_HEADERTEXT 1001 -#define IDC_ASSOCLIST 1002 -#define IDC_AUTOSTART 1003 -#define IDC_ONLYWHILERUNNING 1004 -#define IDC_MISCLABEL 1005 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NO_MFC 1 -#define _APS_NEXT_RESOURCE_VALUE 104 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1006 -#define _APS_NEXT_SYMED_VALUE 2001 -#endif -#endif diff --git a/plugins/AssocMgr/resource.rc b/plugins/AssocMgr/resource.rc deleted file mode 100644 index 8c87596f46..0000000000 --- a/plugins/AssocMgr/resource.rc +++ /dev/null @@ -1,117 +0,0 @@ -//Microsoft Developer Studio generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// Englisch (GB) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE MOVEABLE PURE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE MOVEABLE PURE -BEGIN - "#include \r\n" - "\0" -END - -3 TEXTINCLUDE MOVEABLE PURE -BEGIN - "#include ""version.rc""\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_OPT_ASSOCLIST DIALOGEX 0, 0, 301, 227 -STYLE DS_FIXEDSYS | WS_CHILD -EXSTYLE WS_EX_CONTROLPARENT -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Registered associations for Miranda IM:", - IDC_HEADERTEXT,3,0,295,8,SS_NOPREFIX - CONTROL "",IDC_ASSOCLIST,"SysListView32",LVS_REPORT | - LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | - WS_BORDER | WS_TABSTOP,3,10,295,169 - GROUPBOX "Miscellaneous",IDC_MISCLABEL,3,183,295,41,WS_GROUP - CONTROL "&Start Miranda IM automatically when the Computer starts (using current profile)", - IDC_AUTOSTART,"Button",BS_AUTOCHECKBOX | BS_TOP | - WS_TABSTOP,10,195,284,10 - CONTROL "Only associate with Miranda IM while it is &running", - IDC_ONLYWHILERUNNING,"Button",BS_AUTOCHECKBOX | BS_TOP | - WS_TABSTOP,10,208,284,10 -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_MIRANDA ICON DISCARDABLE "res/miranda.ico" -IDI_MIRANDAFILE ICON DISCARDABLE "res/mirandafile.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO DISCARDABLE -BEGIN - IDD_OPT_ASSOCLIST, DIALOG - BEGIN - VERTGUIDE, 3 - VERTGUIDE, 10 - VERTGUIDE, 294 - VERTGUIDE, 298 - END -END -#endif // APSTUDIO_INVOKED - -#endif // Englisch (GB) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// -#include "version.rc" - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/plugins/AssocMgr/src/assoclist.cpp b/plugins/AssocMgr/src/assoclist.cpp new file mode 100644 index 0000000000..4ccb5645fe --- /dev/null +++ b/plugins/AssocMgr/src/assoclist.cpp @@ -0,0 +1,1102 @@ +/* + +'File Association Manager'-Plugin for Miranda IM + +Copyright (C) 2005-2007 H. Herkenrath + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program (AssocMgr-License.txt); if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "common.h" + +/* Options */ +extern HINSTANCE hInst; +static HANDLE hHookOptInit; +/* Services */ +static HANDLE hServiceAddFile, hServiceRemoveFile, hServiceAddUrl, hServiceRemoveUrl; + +/************************* Assoc List *****************************/ + +typedef struct { + char *pszClassName; /* class name as used in registry and db */ + TCHAR *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 */ + TCHAR *pszVerbDesc; /* file type: allowed to be NULL */ +} ASSOCDATA; + +static ASSOCDATA *pAssocList; /* protected by csAssocList */ +static int nAssocListCount; /* protected by csAssocList */ +static CRITICAL_SECTION csAssocList; + +/************************* Assoc Enabled **************************/ + +static BOOL IsAssocEnabled(const ASSOCDATA *assoc) +{ + char szSetting[MAXMODULELABELLENGTH]; + mir_snprintf(szSetting, sizeof(szSetting), "enabled_%s", assoc->pszClassName); + return DBGetContactSettingByte(NULL, "AssocMgr", szSetting, (BYTE)!(assoc->flags&FTDF_DEFAULTDISABLED))!= 0; +} + +static void SetAssocEnabled(const ASSOCDATA *assoc, BOOL fEnabled) +{ + char szSetting[MAXMODULELABELLENGTH]; + TCHAR szDLL[MAX_PATH], szBuf[MAX_PATH]; + mir_snprintf(szSetting, sizeof(szSetting), "enabled_%s", assoc->pszClassName); + DBWriteContactSettingByte(NULL, "AssocMgr", szSetting, (BYTE)fEnabled); + /* dll name for uninstall */ + if(assoc->hInstance!= NULL && assoc->hInstance!= hInst && assoc->hInstance!= GetModuleHandle(NULL)) + if(GetModuleFileName(assoc->hInstance, szBuf, SIZEOF(szBuf))) + if(CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)szBuf, (LPARAM)szDLL)) { + mir_snprintf(szSetting, sizeof(szSetting), "module_%s", assoc->pszClassName); + DBWriteContactSettingTString(NULL, "AssocMgr", szSetting, szDLL); + } +} + +static void DeleteAssocEnabledSetting(const ASSOCDATA *assoc) +{ + char szSetting[MAXMODULELABELLENGTH]; + mir_snprintf(szSetting, sizeof(szSetting), "enabled_%s", assoc->pszClassName); + DBDeleteContactSetting(NULL, "AssocMgr", szSetting); + /* dll name for uninstall */ + mir_snprintf(szSetting, sizeof(szSetting), "module_%s", assoc->pszClassName); + DBDeleteContactSetting(NULL, "AssocMgr", szSetting); +} + +void CleanupAssocEnabledSettings(void) +{ + int nSettingsCount; + char **ppszSettings, *pszSuffix; + DBVARIANT dbv; + int i; + HANDLE hFile; + TCHAR szDLL[MAX_PATH]; + char szSetting[MAXMODULELABELLENGTH]; + + /* delete old enabled_* settings if associated plugin no longer present */ + if(EnumDbPrefixSettings("AssocMgr", "enabled_", &ppszSettings, &nSettingsCount)) { + EnterCriticalSection(&csAssocList); + for(i = 0;ipszClassName = mir_strdup(assoc->pszClassName); + assoc2->pszDescription = mir_tstrdup(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_tstrdup(assoc->pszVerbDesc); + if(assoc2->pszClassName == NULL || assoc2->pszDescription == NULL || + (assoc2->pszFileExt == NULL && assoc->pszFileExt!= NULL)) { + 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 NULL; + } + return assoc2; +} + +// 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) +{ + HICON hIcon = NULL; + int index; + if(himl == NULL) return -1; + + /* load icon */ + hIcon = LoadRegClassSmallIcon(assoc->pszClassName); + if(hIcon == NULL) { + SHFILEINFOA sfi; + if(SHGetFileInfoA((assoc->pszFileExt!= NULL)?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 == NULL) return -1; + index = ImageList_ReplaceIcon(himl, iPrevIndex, hIcon); + DestroyIcon(hIcon); + return index; +} + +// the return value does not need to be freed +// this function assumes it has got the csAssocList mutex +static TCHAR* GetAssocTypeDesc(const ASSOCDATA *assoc) +{ + static TCHAR szDesc[32]; + if(assoc->pszFileExt == NULL) mir_sntprintf(szDesc, SIZEOF(szDesc), TranslateT("%hs:"), assoc->pszClassName); + else mir_sntprintf(szDesc, SIZEOF(szDesc), TranslateT("%hs files"), assoc->pszFileExt); + return szDesc; +} + +// this function assumes it has got the csAssocList mutex +static BOOL IsAssocRegistered(const ASSOCDATA *assoc) +{ + BOOL fSuccess = FALSE, fIsUrl, fUseMainCmdLine; + TCHAR *pszRunCmd; + + fIsUrl = (assoc->pszFileExt == NULL); + fUseMainCmdLine = (assoc->pszService == NULL); + + /* class */ + pszRunCmd = MakeRunCommand(fUseMainCmdLine, !fUseMainCmdLine); + if(pszRunCmd!= NULL) + fSuccess = IsRegClass(assoc->pszClassName, pszRunCmd); + mir_free(pszRunCmd); /* does NULL check */ + /* file ext */ + if (!fIsUrl) + fSuccess = IsRegFileExt(assoc->pszFileExt, assoc->pszClassName); + + return fSuccess; +} + +// this function assumes it has got the csAssocList mutex +// call GetLastError() on error to get more error details +static BOOL EnsureAssocRegistered(const ASSOCDATA *assoc) +{ + BOOL fSuccess = FALSE, fIsUrl, fUseMainCmdLine; + TCHAR *pszIconLoc, *pszRunCmd, *pszDdeCmd, *pszAppFileName; + + fIsUrl = (assoc->pszFileExt == NULL); + fUseMainCmdLine = (assoc->pszService == NULL); + + pszRunCmd = MakeRunCommand(fUseMainCmdLine, !fUseMainCmdLine); + if(pszRunCmd!= NULL) { + fSuccess = TRUE; /* tentatively */ + /* do not overwrite user customized settings */ + if (!IsRegClass(assoc->pszClassName, pszRunCmd)) { + /* class icon */ + if (!assoc->nIconResID && fIsUrl) pszIconLoc = MakeIconLocation(NULL, 0); /* miranda logo */ + else if (!assoc->nIconResID) pszIconLoc = MakeIconLocation(hInst, IDI_MIRANDAFILE); /* generic file */ + else pszIconLoc = MakeIconLocation(assoc->hInstance, assoc->nIconResID); + /* register class */ + if(fUseMainCmdLine) pszDdeCmd = NULL; + else pszDdeCmd = fIsUrl?DDEURLCMD:DDEFILECMD; + fSuccess = AddRegClass(assoc->pszClassName, assoc->pszDescription, pszIconLoc, _T(MIRANDANAME), pszRunCmd, pszDdeCmd, DDEAPP, DDETOPIC, assoc->pszVerbDesc, assoc->flags&FTDF_BROWSERAUTOOPEN, fIsUrl, assoc->flags&FTDF_ISSHORTCUT); + mir_free(pszIconLoc); /* does NULL check */ + /* file type */ + if(fSuccess && !fIsUrl) { + /* register mime type */ + if(assoc->pszMimeType!= NULL) + if(AddRegMimeType(assoc->pszMimeType, assoc->pszFileExt, assoc->pszDescription)) + RememberMimeTypeAdded(assoc->pszMimeType, assoc->pszFileExt, TRUE); + /* register file ext */ + fSuccess = AddRegFileExt(assoc->pszFileExt, assoc->pszClassName, assoc->pszMimeType, assoc->flags&FTDF_ISTEXT); + /* register open-with */ + pszAppFileName = MakeAppFileName(fUseMainCmdLine); + if(pszAppFileName!= NULL) + AddRegOpenWithExtEntry(pszAppFileName, assoc->pszFileExt, assoc->pszDescription); + mir_free(pszAppFileName); /* does NULL check */ + } + } + mir_free(pszRunCmd); + } + else SetLastError(ERROR_OUTOFMEMORY); + return fSuccess; +} + +// this function assumes it has got the csAssocList mutex +// call GetLastError() on error to get more error details +static BOOL UnregisterAssoc(const ASSOCDATA *assoc) +{ + BOOL fIsUrl, fUseMainCmdLine; + TCHAR *pszAppFileName, *pszRunCmd; + + fIsUrl = (assoc->pszFileExt == NULL); + fUseMainCmdLine = (assoc->pszService == NULL); + + /* class might have been registered by another instance */ + pszRunCmd = MakeRunCommand(fUseMainCmdLine, !fUseMainCmdLine); + if(pszRunCmd!= NULL && !IsRegClass(assoc->pszClassName, pszRunCmd)) { + mir_free(pszRunCmd); + return TRUE; /* succeed anyway */ + } + mir_free(pszRunCmd); /* does NULL check */ + + /* file type */ + if (!fIsUrl) { + /* file extension */ + RemoveRegFileExt(assoc->pszFileExt, assoc->pszClassName); + /* mime type */ + if(assoc->pszMimeType!= NULL) + if(WasMimeTypeAdded(assoc->pszMimeType)) { + RemoveRegMimeType(assoc->pszMimeType, assoc->pszFileExt); + RememberMimeTypeAdded(assoc->pszMimeType, assoc->pszFileExt, FALSE); + } + /* open-with entry */ + pszAppFileName = MakeAppFileName(fUseMainCmdLine); + if(pszAppFileName!= NULL) + RemoveRegOpenWithExtEntry(pszAppFileName, assoc->pszFileExt); + mir_free(pszAppFileName); /* does NULL check */ + } + return RemoveRegClass(assoc->pszClassName); +} + +/************************* Assoc List Workers *********************/ + +/* this structure represents the head of both + * FILETYPEDESC and URLTYPEDESC structures. + * the head is identical for both structures. */ +typedef struct { + int cbSize; /* either sizeof(FILETYPEDESC) or sizeof(URLTYPEDESC) */ + const void *pszDescription; + HINSTANCE hInstance; + UINT nIconResID; + const char *pszService; + DWORD flags; +} TYPEDESCHEAD; + +// 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, TCHAR *pszVerbDesc, char *pszMimeType) +{ + ASSOCDATA *pAssocListBuf, *assoc; + int index; + + /* is already in list? */ + EnterCriticalSection(&csAssocList); + index = FindAssocItem(pszClassName); + if(index!= -1) return FALSE; + + /* resize storage array */ + pAssocListBuf = (ASSOCDATA*)mir_realloc(pAssocList, (nAssocListCount+1)*sizeof(ASSOCDATA)); + if(pAssocListBuf == NULL) { + LeaveCriticalSection(&csAssocList); + return FALSE; + } + pAssocList = pAssocListBuf; + + /* init new item */ + assoc = &pAssocList[nAssocListCount]; + 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 */ + assoc->nIconResID = (WORD)tdh->nIconResID; /* default icon selected later on */ + assoc->pszService = mir_strdup(tdh->pszService); /* does NULL check */ + assoc->flags = (WORD)tdh->flags; + assoc->pszFileExt = pszFileExt; + assoc->pszMimeType = pszMimeType; + assoc->pszVerbDesc = pszVerbDesc; + + /* error check */ + if(assoc->pszDescription == NULL || (assoc->pszService == NULL && tdh->pszService!= NULL)) { + mir_free(assoc->pszService); /* does NULL check */ + mir_free(assoc->pszDescription); /* does NULL check */ + LeaveCriticalSection(&csAssocList); + return FALSE; + } + + /* add registry keys */ + if(IsAssocEnabled(assoc)) + EnsureAssocRegistered(assoc); + + ++nAssocListCount; + NotifyAssocChange(FALSE); + return TRUE; +} + +// ownership of pszClassName is *not* transferd to storage list +static BOOL RemoveAssocItem_Worker(const char *pszClassName) +{ + ASSOCDATA *pAssocListBuf, *assoc; + int index; + + /* find index */ + EnterCriticalSection(&csAssocList); + index = FindAssocItem(pszClassName); + if(index == -1) { + LeaveCriticalSection(&csAssocList); + return FALSE; + } + assoc = &pAssocList[index]; + + /* delete registry keys and db setting */ + UnregisterAssoc(assoc); + if(assoc->pszMimeType!= NULL) + 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)cbSizepszFileExt == NULL || ftd->pszFileExt[0]!= '.') + return 2; + + pszFileExt = mir_strdup(ftd->pszFileExt); + pszClassName = MakeFileClassName(ftd->pszFileExt); + if(pszFileExt!= NULL && pszClassName!= NULL) { + pszVerbDesc = s2t(ftd->ptszVerbDesc, ftd->flags&FTDF_UNICODE, TRUE); /* does NULL check */ + pszMimeType = mir_strdup(ftd->pszMimeType); /* does NULL check */ + if(AddNewAssocItem_Worker(pszClassName, (TYPEDESCHEAD*)ftd, pszFileExt, pszVerbDesc, pszMimeType)) + /* no need to free pszClassName, pszFileExt, pszVerbDesc and pszMimeType, + * as their ownership got transfered to storage list */ + return 0; + } + mir_free(pszClassName); /* does NULL check */ + mir_free(pszFileExt); /* does NULL check */ + return 3; +} + +static INT_PTR ServiceRemoveFileType(WPARAM wParam, LPARAM lParam) +{ + char *pszClassName; + UNREFERENCED_PARAMETER(wParam); + + if ((char*)lParam == NULL) return 2; + pszClassName = MakeFileClassName((char*)lParam); + if(pszClassName!= NULL) + if(RemoveAssocItem_Worker(pszClassName)) { + mir_free(pszClassName); + return 0; + } + mir_free(pszClassName); /* does NULL check */ + return 3; +} + +static INT_PTR ServiceAddNewUrlType(WPARAM wParam, LPARAM lParam) +{ + const URLTYPEDESC *utd = (URLTYPEDESC*)lParam; + char *pszClassName; + UNREFERENCED_PARAMETER(wParam); + + if(utd->cbSize < sizeof(URLTYPEDESC)) + return 1; + if(utd->pszService == NULL) + return 2; + if(utd->pszProtoPrefix == NULL || utd->pszProtoPrefix[lstrlenA(utd->pszProtoPrefix)-1]!= ':') + return 2; + + pszClassName = MakeUrlClassName(utd->pszProtoPrefix); + if(pszClassName!= NULL) + if(AddNewAssocItem_Worker(pszClassName, (TYPEDESCHEAD*)utd, NULL, NULL, NULL)) + /* no need to free pszClassName, as its + * ownership got transfered to storage list */ + return 0; + mir_free(pszClassName); /* does NULL check */ + return 3; +} + +static INT_PTR ServiceRemoveUrlType(WPARAM wParam, LPARAM lParam) +{ + char *pszClassName; + UNREFERENCED_PARAMETER(wParam); + + if ((char*)lParam == NULL) return 2; + pszClassName = MakeUrlClassName((char*)lParam); + if(pszClassName!= NULL) + if(RemoveAssocItem_Worker(pszClassName)) { + mir_free(pszClassName); + return 0; + } + mir_free(pszClassName); /* does NULL check */ + return 3; +} + +/************************* Open Handler ***************************/ + +static BOOL InvokeHandler_Worker(const char *pszClassName, const TCHAR *pszParam, INT_PTR *res) +{ + void *pvParam; + char *pszService; + int index; + ASSOCDATA *assoc; + + /* find it in list */ + EnterCriticalSection(&csAssocList); + index = FindAssocItem(pszClassName); + if(index == -1) { + LeaveCriticalSection(&csAssocList); + return FALSE; + } + assoc = &pAssocList[index]; + /* no service specified? correct registry to use main commandline */ + if(assoc->pszService == NULL) { + EnsureAssocRegistered(assoc); + NotifyAssocChange(FALSE); + /* try main command line */ + if ((int)ShellExecute(NULL, NULL, pszParam, NULL, NULL, SW_SHOWNORMAL) >= 32) + *res = 0; /* success */ + return TRUE; + } + /* get params */ + pszService = mir_strdup(assoc->pszService); + pvParam = t2s(pszParam, assoc->flags&FTDF_UNICODE, FALSE); + LeaveCriticalSection(&csAssocList); + + /* call service */ + if(pszService!= NULL && pvParam!= NULL) + *res = CallService(pszService, 0, (LPARAM)pvParam); + mir_free(pszService); /* does NULL check */ + mir_free(pvParam); /* does NULL check */ + return TRUE; +} + +INT_PTR InvokeFileHandler(const TCHAR *pszFileName) +{ + char *pszClassName, *pszFileExt; + TCHAR *p; + INT_PTR res = CALLSERVICE_NOTFOUND; + + /* find extension */ + p = (TCHAR*)_tcsrchr(pszFileName, _T('.')); + if(p!= NULL) { + pszFileExt = t2a(p); + if(pszFileExt!= NULL) { + /* class name */ + pszClassName = MakeFileClassName(pszFileExt); + if(pszClassName!= NULL) + if (!InvokeHandler_Worker(pszClassName, pszFileName, &res)) { + /* correct registry on error (no longer in list) */ + RemoveRegFileExt(pszFileExt, pszClassName); + RemoveRegClass(pszClassName); + } + mir_free(pszClassName); /* does NULL check */ + mir_free(pszFileExt); + } + } + return res; +} + +INT_PTR InvokeUrlHandler(const TCHAR *pszUrl) +{ + char *pszClassName, *pszProtoPrefix, *p; + INT_PTR res = CALLSERVICE_NOTFOUND; + + /* find prefix */ + pszProtoPrefix = t2a(pszUrl); + if(pszProtoPrefix!= NULL) { + p = strchr(pszProtoPrefix, _T(':')); + if(p!= NULL) { + *(++p) = 0; /* remove trailing : */ + /* class name */ + pszClassName = MakeUrlClassName(pszProtoPrefix); + if(pszClassName!= NULL) + if (!InvokeHandler_Worker(pszClassName, pszUrl, &res)) + /* correct registry on error (no longer in list) */ + RemoveRegClass(pszClassName); + mir_free(pszClassName); /* does NULL check */ + } + mir_free(pszProtoPrefix); + } + return res; +} + +/************************* Options ********************************/ + +static int CALLBACK ListViewSortDesc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) +{ + int cmp; + if (((ASSOCDATA*)lParam1)->pszFileExt!= NULL && ((ASSOCDATA*)lParam2)->pszFileExt!= NULL) + cmp = CompareStringA((LCID)lParamSort, 0, ((ASSOCDATA*)lParam1)->pszFileExt, -1, ((ASSOCDATA*)lParam2)->pszFileExt, -1); + else if (((ASSOCDATA*)lParam1)->pszFileExt == ((ASSOCDATA*)lParam2)->pszFileExt) /* both NULL */ + cmp = CompareStringA((LCID)lParamSort, 0, ((ASSOCDATA*)lParam1)->pszClassName, -1, ((ASSOCDATA*)lParam2)->pszClassName, -1); + else /* different types, incomparable */ + cmp = (((ASSOCDATA*)lParam1)->pszFileExt == NULL)?CSTR_LESS_THAN:CSTR_GREATER_THAN; + if(cmp == CSTR_EQUAL) + cmp = CompareString((LCID)lParamSort, 0, ((ASSOCDATA*)lParam1)->pszDescription, -1, ((ASSOCDATA*)lParam2)->pszDescription, -1); + if(cmp!= 0) cmp -= 2; /* maintain CRT conventions */ + return cmp; +} + +#define M_REFRESH_ICONS (WM_APP+1) +static INT_PTR CALLBACK AssocListOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) { + case WM_INITDIALOG: + { HWND hwndList; + HIMAGELIST himl; + LVITEM lvi; + ASSOCDATA *assoc; + int i; + TranslateDialogDefault(hwndDlg); + CoInitialize(NULL); + 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 */ + EnterCriticalSection(&csAssocList); + { HDC hdc; + hdc = GetDC(hwndList); + if(hdc!= NULL) { /* 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); + } else himl = NULL; + } + ListView_SetImageList(hwndList, himl, LVSIL_SMALL); /* autodestroyed */ + /* enum assoc list */ + lvi.iSubItem = 0; + lvi.mask = LVIF_TEXT|LVIF_PARAM|LVIF_IMAGE; + for(i = 0;ipszDescription); + ListView_SetCheckState(hwndList, lvi.iItem, IsAssocEnabled(assoc) && IsAssocRegistered(assoc)); + } + } + /* sort items (before moving to groups) */ + ListView_SortItems(hwndList, ListViewSortDesc, (LPARAM)CallService(MS_LANGPACK_GETLOCALE, 0, 0)); + /* 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 = (WCHAR*)TranslateW(L"URLs on Websites"); + lvi.iItem = ListView_InsertItem(hwndList, &lvi); + if(lvi.iItem!= -1) { + ListView_InsertGroup(hwndList, lvi.iItem, &lvg); + lvg.iGroupId = 1; + lvg.pszHeader = (WCHAR*)TranslateW(L"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) { + assoc = (ASSOCDATA*)lvi.lParam; + if(assoc == NULL) continue; /* groups */ + lvi.iGroupId = (assoc->pszFileExt == NULL)+1; + ListView_SetItem(hwndList, &lvi); + } + } + LeaveCriticalSection(&csAssocList); + 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)DBGetContactSettingByte(NULL, "AssocMgr", "OnlyWhileRunning", SETTING_ONLYWHILERUNNING_DEFAULT)); + /* autostart */ + { TCHAR *pszRunCmd; + pszRunCmd = MakeRunCommand(TRUE, TRUE); + if(pszRunCmd!= NULL) { + CheckDlgButton(hwndDlg, IDC_AUTOSTART, IsRegRunEntry(_T("MirandaIM"), pszRunCmd)); + mir_free(pszRunCmd); + } + } + return TRUE; + } + case WM_SETTINGCHANGE: + case M_REFRESH_ICONS: + { LVITEM lvi; + HIMAGELIST himl; + ASSOCDATA *assoc; + HWND hwndList; + hwndList = GetDlgItem(hwndDlg, IDC_ASSOCLIST); + 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 == NULL) 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; + } + case WM_CTLCOLORSTATIC: + /* use same text color for header as for group boxes (WinXP+) */ + if(GetDlgCtrlID((HWND)lParam) == IDC_HEADERTEXT) { + HMODULE hUxThemeDLL; + HBRUSH hBrush; + hUxThemeDLL = LoadLibraryA("UXTHEME"); /* all ascii, already loaded */ + lParam = (LPARAM)GetDlgItem(hwndDlg, IDC_MISCLABEL); + hBrush = (HBRUSH)SendMessage(hwndDlg, msg, wParam, lParam); + if(hUxThemeDLL!= NULL) { + HTHEME (WINAPI *pfnGetWindowTheme)(HWND); + HRESULT (WINAPI *pfnGetThemeColor)(HTHEME, int, int, int, COLORREF*); + COLORREF clr; + *(PROC*)&pfnGetWindowTheme = GetProcAddress(hUxThemeDLL, "GetWindowTheme"); + *(PROC*)&pfnGetThemeColor = GetProcAddress(hUxThemeDLL, "GetThemeColor"); + if(pfnGetWindowTheme!= NULL && pfnGetThemeColor!= NULL) { + HTHEME hTheme; + hTheme = pfnGetWindowTheme((HWND)lParam); + if(hTheme!= NULL) + if (!pfnGetThemeColor(hTheme, BP_GROUPBOX, GBS_NORMAL, TMT_TEXTCOLOR, &clr)) { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, clr); + } + } + FreeLibrary(hUxThemeDLL); + } + return (BOOL)hBrush; + } + break; + case WM_NCDESTROY: + CoUninitialize(); + return TRUE; + case WM_COMMAND: + /* enable apply */ + PostMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_NOTIFYFORMAT: + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, NFR_UNICODE); + return TRUE; + + case WM_NOTIFY: + { NMHDR *nmhdr = (NMHDR*)lParam; + switch(nmhdr->idFrom) { + case IDC_ASSOCLIST: + switch(nmhdr->code) { + case LVN_DELETEITEM: /* also called on WM_DESTROY */ + { LVITEM lvi; + lvi.mask = LVIF_PARAM; + lvi.iSubItem = 0; + lvi.iItem = ((NMLISTVIEW*)lParam)->iItem; + /* free memory */ + if(ListView_GetItem(nmhdr->hwndFrom, &lvi)) + mir_free((ASSOCDATA*)lvi.lParam); /* does NULL check */ + return TRUE; + } + case LVN_ITEMCHANGED: + /* enable apply (not while loading) */ + if(IsWindowVisible(nmhdr->hwndFrom)) + PostMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + return TRUE; + case LVN_KEYDOWN: + /* workaround for WinXP (ListView with groups): + * eat keyboard navigation that goes beyond the first item in list + * as it would scroll out of scope in this case + * bug should not be present using WinVista and higher */ + switch(((NMLVKEYDOWN*)lParam)->wVKey) { + case VK_UP: + { LVITEM lvi; + lvi.iSubItem = 0; + lvi.mask = LVIF_PARAM; + lvi.iItem = ListView_GetNextItem(nmhdr->hwndFrom, -1, LVNI_FOCUSED); + lvi.iItem = ListView_GetNextItem(nmhdr->hwndFrom, lvi.iItem, LVNI_ABOVE); + if(lvi.iItem!= -1) + if(ListView_GetItem(nmhdr->hwndFrom, &lvi)) + if ((ASSOCDATA*)lvi.lParam == NULL) /* groups */ + lvi.iItem = -1; + if(lvi.iItem == -1) { + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); /* eat it */ + return TRUE; + } + break; + } + case VK_PRIOR: + { LVITEM lvi; + lvi.iSubItem = 0; + lvi.mask = LVIF_PARAM; + lvi.iItem = ListView_GetNextItem(nmhdr->hwndFrom, -1, LVNI_FOCUSED); + lvi.iItem-= ListView_GetCountPerPage(nmhdr->hwndFrom); + if(lvi.iItem>= 0) + if(ListView_GetItem(nmhdr->hwndFrom, &lvi)) + if ((ASSOCDATA*)lvi.lParam == NULL) /* groups */ + lvi.iItem = -1; + if(lvi.iItem<0) { + ListView_SetItemState(nmhdr->hwndFrom, 0, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED); + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); /* eat it */ + return TRUE; + } + break; + } + } + break; + } + break; + case 0: + switch(nmhdr->code) { + case PSN_APPLY: + { HWND hwndList; + LVITEM lvi; + BOOL fEnabled, fRegFailed = FALSE; + ASSOCDATA *assoc; + + /* only while running */ + DBWriteContactSettingByte(NULL, "AssocMgr", "OnlyWhileRunning", (BYTE)(IsDlgButtonChecked(hwndDlg, IDC_ONLYWHILERUNNING)!= 0)); + + /* save enabled assoc items */ + hwndList = GetDlgItem(hwndDlg, IDC_ASSOCLIST); + lvi.iSubItem = 0; + lvi.mask = LVIF_PARAM; + EnterCriticalSection(&csAssocList); + for(lvi.iItem = 0;ListView_GetItem(hwndList, &lvi);++lvi.iItem) { + assoc = (ASSOCDATA*)lvi.lParam; + if(assoc == NULL) continue; /* groups */ + fEnabled = ListView_GetCheckState(hwndList, lvi.iItem); + SetAssocEnabled(assoc, fEnabled); + + /* re-register registery keys */ + if(fEnabled?!EnsureAssocRegistered(assoc):!UnregisterAssoc(assoc)) { + char *pszErr; + pszErr = GetWinErrorDescription(GetLastError()); + ShowInfoMessage(NIIF_ERROR, Translate("File Association Error"), Translate("There was an error writing to the registry to modify the file/url associations.\nReason: %s"), (pszErr!= NULL)?pszErr:Translate("Unknown")); + mir_free(pszErr); /* does NULL check */ + fRegFailed = TRUE; /* just show one time */ + } + } + LeaveCriticalSection(&csAssocList); + NotifyAssocChange(TRUE); + PostMessage(hwndDlg, M_REFRESH_ICONS, 0, 0); + if(fRegFailed) { + } + /* autostart */ + { TCHAR *pszRunCmd; + pszRunCmd = MakeRunCommand(TRUE, TRUE); + fRegFailed = FALSE; + if(pszRunCmd!= NULL) { + fEnabled = IsDlgButtonChecked(hwndDlg, IDC_AUTOSTART); + if(fEnabled?!AddRegRunEntry(_T("MirandaIM"), pszRunCmd):!RemoveRegRunEntry(_T("MirandaIM"), pszRunCmd)) { + char *pszErr; + pszErr = GetWinErrorDescription(GetLastError()); + ShowInfoMessage(NIIF_ERROR, Translate("Autostart Error"), Translate("There was an error writing to the registry to modify the autostart list.\n\nReason: %s"), (pszErr!= NULL)?pszErr:Translate("Unknown")); + mir_free(pszErr); /* does NULL check */ + fRegFailed = TRUE; /* just show one time */ + } + mir_free(pszRunCmd); + } + } + return TRUE; + } + } /* code */ + break; + } /* idFrom */ + break; + } /* WM_NOTIFY */ + } + return FALSE; +} + +static int AssocListOptInit(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = { 0 }; + odp.cbSize = sizeof(odp); + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ASSOCLIST); + odp.position = 900000100; /* network opts = 900000000 */ + odp.pszGroup = LPGEN("Services"); /* autotranslated */ + odp.pszTitle = LPGEN("Associations"); /* autotranslated */ + odp.flags = ODPF_BOLDGROUPS | ODPF_EXPERTONLY; + odp.pfnDlgProc = AssocListOptDlgProc; + Options_AddPage(wParam, &odp); + return 0; +} + +/************************* Misc ***********************************/ + +void InitAssocList(void) +{ + /* Options */ + INITCOMMONCONTROLSEX icc; + icc.dwSize = sizeof(icc); + icc.dwICC = ICC_LISTVIEW_CLASSES; + InitCommonControlsEx(&icc); + hHookOptInit = HookEvent(ME_OPT_INITIALISE, AssocListOptInit); + + /* Assoc List */ + pAssocList = NULL; + nAssocListCount = 0; + InitializeCriticalSection(&csAssocList); + + /* Services */ + hServiceAddFile = CreateServiceFunction(MS_ASSOCMGR_ADDNEWFILETYPE, ServiceAddNewFileType); + hServiceRemoveFile = CreateServiceFunction(MS_ASSOCMGR_REMOVEFILETYPE, ServiceRemoveFileType); + hServiceAddUrl = CreateServiceFunction(MS_ASSOCMGR_ADDNEWURLTYPE, ServiceAddNewUrlType); + hServiceRemoveUrl = CreateServiceFunction(MS_ASSOCMGR_REMOVEURLTYPE, ServiceRemoveUrlType); + + /* Notify Shell */ + nNotifyTimerID = 0; + InitializeCriticalSection(&csNotifyTimer); + + /* register open-with app */ + { TCHAR *pszAppFileName, *pszIconLoc, *pszRunCmd; + pszIconLoc = MakeIconLocation(NULL, 0); + + // miranda32.exe + pszAppFileName = MakeAppFileName(TRUE); + pszRunCmd = MakeRunCommand(TRUE, FALSE); + if(pszAppFileName!= NULL && pszRunCmd!= NULL) + AddRegOpenWith(pszAppFileName, FALSE, _T(MIRANDANAME), pszIconLoc, pszRunCmd, NULL, NULL, NULL); + mir_free(pszRunCmd); /* does NULL check */ + mir_free(pszAppFileName); /* does NULL check */ + // assocmgr.dll + pszAppFileName = MakeAppFileName(FALSE); + pszRunCmd = MakeRunCommand(FALSE, TRUE); + if(pszAppFileName!= NULL && pszRunCmd!= NULL) + AddRegOpenWith(pszAppFileName, TRUE, _T(MIRANDANAME), pszIconLoc, pszRunCmd, DDEFILECMD, DDEAPP, DDETOPIC); + mir_free(pszRunCmd); /* does NULL check */ + mir_free(pszAppFileName); /* does NULL check */ + + mir_free(pszIconLoc); /* does NULL check */ + } + + /* default items */ + { FILETYPEDESC ftd; + ftd.cbSize = sizeof(FILETYPEDESC); + ftd.pszFileExt = ".dat"; + ftd.pszMimeType = NULL; + ftd.ptszDescription = TranslateT("Miranda IM Database"); + ftd.hInstance = hInst; + ftd.nIconResID = IDI_MIRANDAFILE; + ftd.ptszVerbDesc = NULL; + ftd.pszService = NULL; + ftd.flags = FTDF_DEFAULTDISABLED|FTDF_TCHAR; + ServiceAddNewFileType(0, (LPARAM)&ftd); + } +} + +void UninitAssocList(void) +{ + BYTE fOnlyWhileRunning; + ASSOCDATA *assoc; + int i; + + /* Options */ + UnhookEvent(hHookOptInit); + + /* Services */ + DestroyServiceFunction(hServiceAddFile); + DestroyServiceFunction(hServiceRemoveFile); + DestroyServiceFunction(hServiceAddUrl); + DestroyServiceFunction(hServiceRemoveUrl); + + /* Assoc List */ + fOnlyWhileRunning = DBGetContactSettingByte(NULL, "AssocMgr", "OnlyWhileRunning", SETTING_ONLYWHILERUNNING_DEFAULT); + for(i = 0;ipszClassName); + 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 */ + } + mir_free(pAssocList); + DeleteCriticalSection(&csAssocList); + + /* Notify Shell */ + if(fOnlyWhileRunning && nAssocListCount) + NotifyAssocChange(TRUE); + DeleteCriticalSection(&csNotifyTimer); + + /* unregister open-with app */ + if(fOnlyWhileRunning) { + TCHAR *pszAppFileName; + // miranda32.exe + pszAppFileName = MakeAppFileName(TRUE); + if(pszAppFileName!= NULL) + RemoveRegOpenWith(pszAppFileName); + pszAppFileName = MakeAppFileName(FALSE); + // assocmgr.dll + if(pszAppFileName!= NULL) + RemoveRegOpenWith(pszAppFileName); + mir_free(pszAppFileName); /* does NULL check */ + } +} \ No newline at end of file diff --git a/plugins/AssocMgr/src/assoclist.h b/plugins/AssocMgr/src/assoclist.h new file mode 100644 index 0000000000..5e8806b828 --- /dev/null +++ b/plugins/AssocMgr/src/assoclist.h @@ -0,0 +1,33 @@ +/* + +'File Association Manager'-Plugin for Miranda IM + +Copyright (C) 2005-2007 H. Herkenrath + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program (AssocMgr-License.txt); if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* Assoc Enabled */ +void CleanupAssocEnabledSettings(void); +/* Mime Reg */ +void CleanupMimeTypeAddedSettings(void); +/* Assoc List Utils */ +BOOL IsRegisteredAssocItem(const char *pszClassName); +/* Open Handler */ +INT_PTR InvokeFileHandler(const TCHAR *pszFileName); +INT_PTR InvokeUrlHandler(const TCHAR *pszUrl); +/* Misc */ +void InitAssocList(void); +void UninitAssocList(void); diff --git a/plugins/AssocMgr/src/common.h b/plugins/AssocMgr/src/common.h new file mode 100644 index 0000000000..9f6c0b7505 --- /dev/null +++ b/plugins/AssocMgr/src/common.h @@ -0,0 +1,57 @@ +/* + +'File Association Manager'-Plugin for Miranda IM + +Copyright (C) 2005-2007 H. Herkenrath + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program (AssocMgr-License.txt); if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#define _CRT_SECURE_NO_WARNINGS +#define _WIN32_WINNT 0x0600 +#define __RPCASYNC_H__ /* VC6 has a mistake in there (warning) */ +#include +#pragma warning(disable:4201) /* nonstandard extension used : nameless struct/union */ +#pragma warning(disable:4115) /* V6 has a mistake in there (warning) */ +#include /* for SHChangeNotify() */ +#pragma warning(default:4115) +#include +#pragma warning(default:4201) +#include +#include /* for mir_snprintf() */ +#include +#include +#include + +#define MIRANDA_VER 0x0A00 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "win2k.h" + +#define ASSOCMGR_NOHELPERFUNCTIONS +#include "m_assocmgr.h" +#include "utils.h" +#include "reg.h" +#include "assoclist.h" +#include "dde.h" +#include "test.h" +#include "resource.h" diff --git a/plugins/AssocMgr/src/dde.cpp b/plugins/AssocMgr/src/dde.cpp new file mode 100644 index 0000000000..a8328b4d34 --- /dev/null +++ b/plugins/AssocMgr/src/dde.cpp @@ -0,0 +1,295 @@ +/* + +'File Association Manager'-Plugin for Miranda IM + +Copyright (C) 2005-2007 H. Herkenrath + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program (AssocMgr-License.txt); if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "common.h" + +/* Conversation */ +extern HINSTANCE hInst; +static HWND hwndDdeMsg; +/* Misc */ +static HANDLE hHookModulesLoaded,hHookPreShutdown; + +/************************* Open Handler ***************************/ + +// pszFilePath needs to be allocated using mir_alloc() +static void __stdcall FileActionAsync(void *param) +{ + TCHAR *pszFilePath = (TCHAR*)param; + /* invoke main handler */ + switch(InvokeFileHandler(pszFilePath)) { /* pszFilePath is always a long path name */ + case 0: /* success */ break; + case CALLSERVICE_NOTFOUND: + ShowInfoMessage(NIIF_ERROR,Translate("Miranda IM could not open file"),Translate("Miranda IM was not able to open \""TCHAR_STR_PARAM"\".\n\nThere is no registered handler for this file type."),pszFilePath); + break; + default: + ShowInfoMessage(NIIF_ERROR,Translate("Miranda IM could not open file"),Translate("Miranda IM was not able to open \""TCHAR_STR_PARAM"\".\n\nThe file could not be processed."),pszFilePath); + } + mir_free(pszFilePath); /* async param */ +} + +// pszUrl needs to be allocated using mir_alloc() +static void __stdcall UrlActionAsync(void *param) +{ + TCHAR *pszUrl = (TCHAR*)param; + /* invoke main handler */ + switch(InvokeUrlHandler(pszUrl)) { + case 0: /* success */ break; + case CALLSERVICE_NOTFOUND: + ShowInfoMessage(NIIF_ERROR,Translate("Miranda IM could not open URL"),Translate("Miranda IM was not able to open \""TCHAR_STR_PARAM"\".\n\nThere is no registered handler for this URL type."),pszUrl); + break; + default: + ShowInfoMessage(NIIF_ERROR,Translate("Miranda IM could not open URL"),Translate("Miranda IM was not able to open \""TCHAR_STR_PARAM"\".\n\nThe given URL is invalid and can not be parsed."),pszUrl); + } + mir_free(pszUrl); /* async param */ +} + +/************************* Conversation ***************************/ + +#define DDEMESSAGETIMEOUT 30000 +#define WNDCLASS_DDEMSGWINDOW _T("MirandaDdeMsgWindow") + +// returned pointer points into a substring of ppszString +// returns an empty string if the string does not have enough arguments +static TCHAR* GetExecuteParam(TCHAR **ppszString) +{ + TCHAR *pszParam,*p; + BOOL fQuoted; + + fQuoted=(**ppszString==_T('"')); + pszParam=*ppszString; + if(fQuoted) pszParam++; + p=_tcschr(pszParam,(TCHAR)(fQuoted?_T('"'):_T(','))); + if(p!=NULL) { + *(p++)=0; + if(fQuoted && *p==_T(',')) p++; + } else p=&pszParam[lstrlen(pszParam)]; + *ppszString=p; + return pszParam; +} + +static LRESULT CALLBACK DdeMessageWindow(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) +{ + switch(msg) { + case WM_DDE_INITIATE: + { ATOM hSzApp,hSzTopic; + hSzApp=LOWORD(lParam); /* no UnpackDDElParam() here */ + hSzTopic=HIWORD(lParam); + if ((hSzApp==GlobalFindAtom(DDEAPP) && hSzTopic==GlobalFindAtom(DDETOPIC)) || !hSzApp) { + hSzApp=GlobalAddAtom(DDEAPP); + hSzTopic=GlobalAddAtom(DDETOPIC); + if(hSzApp && hSzTopic) + /* PackDDElParam() only for posted msgs */ + SendMessage((HWND)wParam,WM_DDE_ACK,(WPARAM)hwnd,MAKELPARAM(hSzApp,hSzTopic)); + if(hSzApp) GlobalDeleteAtom(hSzApp); + if(hSzTopic) GlobalDeleteAtom(hSzTopic); + } + return 0; + } + case WM_DDE_EXECUTE: /* posted message */ + { HGLOBAL hCommand; + TCHAR *pszCommand; + DDEACK ack; + ZeroMemory(&ack,sizeof(ack)); + if(UnpackDDElParam(msg,lParam,NULL,(PUINT_PTR)&hCommand)) { + + /* ANSI execute command can't happen for shell */ + if(IsWindowUnicode((HWND)wParam)) { + + pszCommand = (TCHAR*)GlobalLock(hCommand); + if(pszCommand!=NULL) { + TCHAR *pszAction,*pszArg; + pszAction=GetExecuteParam(&pszCommand); + pszArg=mir_tstrdup(GetExecuteParam(&pszCommand)); + if(pszArg!=NULL) { + /* we are inside miranda here, we make it async so the shell does + * not timeout regardless what the plugins try to do. */ + if (!lstrcmpi(pszAction,_T("file"))) + ack.fAck=(short)(CallFunctionAsync(FileActionAsync,pszArg)!=0); + else if (!lstrcmpi(pszAction,_T("url"))) + ack.fAck=(short)(CallFunctionAsync(UrlActionAsync,pszArg)!=0); + if (!ack.fAck) mir_free(pszArg); /* otherwise freed by asyncproc */ + } + GlobalUnlock(hCommand); + } + + } + + lParam=ReuseDDElParam(lParam,msg,WM_DDE_ACK,*(PUINT)&ack,(UINT)hCommand); + if (!PostMessage((HWND)wParam,WM_DDE_ACK,(WPARAM)hwnd,lParam)) { + GlobalFree(hCommand); + FreeDDElParam(WM_DDE_ACK,lParam); + } + } + return 0; + } + case WM_DDE_TERMINATE: + PostMessage((HWND)wParam,msg,(WPARAM)hwnd,0); /* ack reply */ + return 0; + case WM_DDE_REQUEST: + case WM_DDE_ADVISE: + case WM_DDE_UNADVISE: + case WM_DDE_POKE: + /* fail safely for those to avoid memory leak in lParam */ + { ATOM hSzItem; + DDEACK ack; + ZeroMemory(&ack,sizeof(ack)); + if(UnpackDDElParam(msg,lParam,NULL,(PUINT_PTR)&hSzItem)) { + lParam=ReuseDDElParam(lParam,msg,WM_DDE_ACK,*(PUINT)&ack,(UINT)hSzItem); + if (!PostMessage((HWND)wParam,WM_DDE_ACK,(WPARAM)hwnd,lParam)) { + if(hSzItem) GlobalDeleteAtom(hSzItem); + FreeDDElParam(WM_DDE_ACK,lParam); + } + } + return 0; + } + } + return DefWindowProc(hwnd,msg,wParam,lParam); +} + +// CloseHandle() the return value +static HANDLE StartupMainProcess(TCHAR *pszDatabasePath) +{ + TCHAR *p,szPath[MAX_PATH]; + PROCESS_INFORMATION pi; + STARTUPINFO si; + + /* we are inside RunDll32 here */ + if (!GetModuleFileName(hInst,szPath,SIZEOF(szPath))) return NULL; + p=_tcsrchr(szPath,_T('\\')); + if(p!=NULL) { *p=0; p=_tcsrchr(szPath,_T('\\')); } + if(p==NULL) return NULL; + lstrcpy(++p,_T("miranda32.exe")); + + /* inherit startup data from RunDll32 process */ + GetStartupInfo(&si); + if (!CreateProcess(szPath,pszDatabasePath,NULL,NULL,TRUE,GetPriorityClass(GetCurrentProcess()),NULL,NULL,&si,&pi)) + return NULL; + CloseHandle(pi.hThread); + return pi.hProcess; +} + +#ifdef __cplusplus +extern "C" { +#endif + +// entry point for RunDll32, this is also WaitForDDEW +__declspec(dllexport) void CALLBACK WaitForDDE(HWND hwnd,HINSTANCE hinstExe,TCHAR *pszCmdLine,int nCmdShow) +{ + HANDLE pHandles[2]; + DWORD dwTick; + UNREFERENCED_PARAMETER(hinstExe); + UNREFERENCED_PARAMETER(nCmdShow); /* obeys nCmdShow using GetStartupInfo() */ + UNREFERENCED_PARAMETER(hwnd); + + /* wait for dde window to be available (avoiding race condition) */ + pHandles[0]=CreateEvent(NULL,TRUE,FALSE,WNDCLASS_DDEMSGWINDOW); + if(pHandles[0]!=NULL) { + pHandles[1]=StartupMainProcess(pszCmdLine); /* obeys nCmdShow using GetStartupInfo() */ + if(pHandles[1]!=NULL) { + dwTick=GetTickCount(); + /* either process terminated or dde window created */ + if(WaitForMultipleObjects(SIZEOF(pHandles),pHandles,FALSE,DDEMESSAGETIMEOUT)==WAIT_OBJECT_0) { + dwTick=GetTickCount()-dwTick; + if(dwTicksizeof(TCHAR)) { + pszVal=(TCHAR*)mir_alloc(dwSize+sizeof(TCHAR)); + if(pszVal!=NULL) { + /* get value */ + if (!RegQueryValueEx(hKey,pszValName,NULL,&dwType,(BYTE*)pszVal,&dwSize)) { + pszVal[dwSize/sizeof(TCHAR)]=0; + if(dwType==REG_EXPAND_SZ) { + dwSize=MAX_PATH; + pszVal2=(TCHAR*)mir_alloc(dwSize*sizeof(TCHAR)); + if(ExpandEnvironmentStrings(pszVal,pszVal2,dwSize)) { + mir_free(pszVal); + return pszVal2; + } + mir_free(pszVal2); + } else if(dwType==REG_SZ) + return pszVal; + } + mir_free(pszVal); + } + } + return NULL; +} + +// hKey must have been opened with KEY_QUERY_VALUE access right +static BOOL IsRegStrValue(HKEY hKey,const TCHAR *pszValName,const TCHAR *pszCmpVal) +{ + BOOL fSame=FALSE; + TCHAR *pszVal; + pszVal=GetRegStrValue(hKey,pszValName); + if(pszVal!=NULL) { + fSame=!lstrcmp(pszVal,pszCmpVal); + mir_free(pszVal); + } + return fSame; +} + +// hKey must have been opened with KEY_QUERY_VALUE access right +static BOOL IsRegStrValueA(HKEY hKey,const TCHAR *pszValName,const char *pszCmpVal) +{ + BOOL fSame=FALSE; + TCHAR *pszVal; + char *pszValA; + pszVal=GetRegStrValue(hKey,pszValName); + if(pszVal!=NULL) { + pszValA=t2a(pszVal); + if(pszValA!=NULL) + fSame=!lstrcmpA(pszValA,pszCmpVal); + mir_free(pszValA); /* does NULL check */ + mir_free(pszVal); + } + return fSame; +} + +/************************* Backup to DB ***************************/ + +#define REGF_ANSI 0x80000000 /* this bit is set in dwType for ANSI registry data */ + +// pData must always be Unicode data, registry supports Unicode even on Win95 +static void WriteDbBackupData(const char *pszSetting,DWORD dwType,BYTE *pData,DWORD cbData) +{ + DBCONTACTWRITESETTING dbcws; + dbcws.szModule="AssocMgr"; + dbcws.szSetting=pszSetting; + dbcws.value.type=DBVT_BLOB; + dbcws.value.cpbVal=(WORD)(cbData+sizeof(DWORD)); + dbcws.value.pbVal=(BYTE*)mir_alloc(cbData+sizeof(DWORD)); + if(dbcws.value.pbVal==NULL) return; + *(DWORD*)dbcws.value.pbVal=dwType; + CopyMemory(dbcws.value.pbVal+sizeof(DWORD),pData,cbData); + CallService(MS_DB_CONTACT_WRITESETTING,0,(LPARAM)&dbcws); + mir_free(dbcws.value.pbVal); +} + +// mir_free() the value returned in ppData +static BOOL ReadDbBackupData(const char *pszSetting,DWORD *pdwType,BYTE **ppData,DWORD *pcbData) +{ + DBCONTACTGETSETTING dbcgs; + DBVARIANT dbv; + dbcgs.szModule="AssocMgr"; + dbcgs.szSetting=pszSetting; + dbcgs.pValue=&dbv; + if (!CallService(MS_DB_CONTACT_GETSETTING,0,(LPARAM)&dbcgs)) { + if(dbv.type==DBVT_BLOB && dbv.cpbVal>=sizeof(DWORD)) { + *pdwType=*(DWORD*)dbv.pbVal; + *ppData=dbv.pbVal; + *pcbData=dbv.cpbVal-sizeof(DWORD); + MoveMemory(*ppData,*ppData+sizeof(DWORD),*pcbData); + return TRUE; + } + CallService(MS_DB_CONTACT_FREEVARIANT,0,(LPARAM)&dbv); + } + return FALSE; +} + +struct BackupRegTreeParam { + char **ppszDbPrefix; + DWORD *pdwDbPrefixSize; + int level; +}; + +static void BackupRegTree_Worker(HKEY hKey,const char *pszSubKey,struct BackupRegTreeParam *param) +{ + LONG res; + DWORD nMaxSubKeyLen,nMaxValNameLen,nMaxValSize; + DWORD index,cchName,dwType,cbData; + BYTE *pData; + char *pszName; + register TCHAR *ptszName; + DWORD nDbPrefixLen; + if ((res=RegOpenKeyExA(hKey,pszSubKey,0,KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS,&hKey))==ERROR_SUCCESS) { + if ((res=RegQueryInfoKey(hKey,NULL,NULL,NULL,NULL,&nMaxSubKeyLen,NULL,NULL,&nMaxValNameLen,&nMaxValSize,NULL,NULL))==ERROR_SUCCESS) { + if(nMaxSubKeyLen>nMaxValNameLen) nMaxValNameLen=nMaxSubKeyLen; + /* prepare buffer */ + nDbPrefixLen=(DWORD)lstrlenA(*param->ppszDbPrefix)+lstrlenA(pszSubKey)+1; + cchName=nDbPrefixLen+nMaxValNameLen+3; + if(cchName>*param->pdwDbPrefixSize) { + pszName=(char*)mir_realloc(*param->ppszDbPrefix,cchName); + if(pszName==NULL) return; + *param->ppszDbPrefix=pszName; + *param->pdwDbPrefixSize=cchName; + } + lstrcatA(lstrcatA(*param->ppszDbPrefix,pszSubKey),"\\"); /* buffer safe */ + /* enum values */ + pszName=(char*)mir_alloc(nMaxValNameLen+1); + if(nMaxValSize==0) nMaxValSize=1; + pData=(BYTE*)mir_alloc(nMaxValSize); + if(pszName!=NULL && pData!=NULL) { + index=0; + while(!res) { + cchName=nMaxValNameLen+1; + cbData=nMaxValSize; + if ((res=RegEnumValueA(hKey,index++,pszName,&cchName,NULL,NULL,NULL,NULL))==ERROR_SUCCESS) { + (*param->ppszDbPrefix)[nDbPrefixLen]=0; + lstrcatA(*param->ppszDbPrefix,pszName); /* buffer safe */ + ptszName=a2t(pszName); + if(ptszName!=NULL) { + if (!RegQueryValueEx(hKey,ptszName,NULL,&dwType,pData,&cbData)) { + + WriteDbBackupData(*param->ppszDbPrefix,dwType,pData,cbData); + + } + mir_free(ptszName); + } + } + } + if(res==ERROR_NO_MORE_ITEMS) res=ERROR_SUCCESS; + } + mir_free(pData); /* does NULL check */ + /* enum subkeys */ + if(param->level<32 && pszName!=NULL) { + ++param->level; /* can be max 32 levels deep (after prefix), restriction of RegCreateKeyEx() */ + index=0; + while(!res) { + cchName=nMaxSubKeyLen+1; + if ((res=RegEnumKeyExA(hKey,index++,pszName,&cchName,NULL,NULL,NULL,NULL))==ERROR_SUCCESS) { + (*param->ppszDbPrefix)[nDbPrefixLen]=0; + BackupRegTree_Worker(hKey,pszName,param); /* recursion */ + } + } + } + if(res==ERROR_NO_MORE_ITEMS) res=ERROR_SUCCESS; + mir_free(pszName); /* does NULL check */ + } + RegCloseKey(hKey); + } +} + +static void BackupRegTree(HKEY hKey,const char *pszSubKey,const char *pszDbPrefix) +{ + struct BackupRegTreeParam param; + DWORD dwDbPrefixSize; + param.level=0; + param.pdwDbPrefixSize=&dwDbPrefixSize; + param.ppszDbPrefix=(char**)&pszDbPrefix; + pszDbPrefix=mir_strdup(pszDbPrefix); + if(pszDbPrefix!=NULL) { + dwDbPrefixSize=lstrlenA(pszDbPrefix)+1; + BackupRegTree_Worker(hKey,pszSubKey,¶m); + mir_free((char*)pszDbPrefix); + } +} + +static LONG RestoreRegTree(HKEY hKey,const char *pszSubKey,const char *pszDbPrefix) +{ + char **ppszSettings,*pszSuffix,*pszPrefixWithSubKey; + int nSettingsCount,i,nDbPrefixLen,nPrefixWithSubKeyLen; + char *pslash=NULL,*pnext,*pkeys; + char *pszValName; + WCHAR *pwszValName; + HKEY hSubKey; + DWORD dwType,cbData; + BYTE *pData; + LONG res; + + nDbPrefixLen=lstrlenA(pszDbPrefix); + nPrefixWithSubKeyLen=nDbPrefixLen+lstrlenA(pszSubKey)+1; + pszPrefixWithSubKey=(char*)mir_alloc(nPrefixWithSubKeyLen+1); + if(pszPrefixWithSubKey==NULL) return ERROR_OUTOFMEMORY; + lstrcatA(lstrcatA(lstrcpyA(pszPrefixWithSubKey,pszDbPrefix),pszSubKey),"\\"); /* buffer safe */ + res=ERROR_NO_MORE_ITEMS; + if(pszPrefixWithSubKey!=NULL) { + if(EnumDbPrefixSettings("AssocMgr",pszPrefixWithSubKey,&ppszSettings,&nSettingsCount)) { + for(i=0;i +#include +#include + +#include "m_assocmgr.h" +static HANDLE hHookModulesLoaded; +static HANDLE hServiceParseLink; + +static int ServiceParseAimLink(WPARAM wParam,LPARAM lParam) +{ + char *arg=(char*)lParam; + UNREFERENCED_PARAMETER(wParam); + if(arg==NULL) return 1; /* sanity check */ + /* skip leading prefix */ + arg=strchr(arg,':'); + if(arg==NULL) return 1; /* parse failed */ + for (++arg;*arg=='/';++arg); + /* + add user: aim:addbuddy?screenname=NICK&groupname=GROUP + send message: aim:goim?screenname=NICK&message=MSG + open chatroom: aim:gochat?roomname=ROOM&exchange=NUM + */ + /* add a contact to the list */ + if (!_strnicmp(arg,"addbuddy?",9)) { + char *tok,*sn=NULL,*group=NULL; + ADDCONTACTSTRUCT acs; + PROTOSEARCHRESULT psr; + if (*(arg+=9)==0) return 1; /* parse failed */ + tok=strtok(arg,"&"); /* first token */ + while(tok!=NULL) { + if (!_strnicmp(tok,"screenname=",11) && *(tok+11)!=0) + sn=Netlib_UrlDecode(tok+11); + if (!_strnicmp(tok,"groupname=",10) && *(tok+10)!=0) + group=Netlib_UrlDecode(tok+10); /* group is currently ignored */ + tok=strtok(NULL,"&"); /* next token */ + } + if(sn==NULL) return 1; /* parse failed */ + if(find_contact(sn)==NULL) { /* does not yet check if sn is current user */ + acs.handleType=HANDLE_SEARCHRESULT; + acs.szProto=AIM_PROTOCOL_NAME; + acs.psr=&psr; + ZeroMemory(&psr,sizeof(PROTOSEARCHRESULT)); + psr.cbSize=sizeof(PROTOSEARCHRESULT); + psr.nick=sn; + CallService(MS_ADDCONTACT_SHOW,(WPARAM)NULL,(LPARAM)&acs); + } + return 0; + } + /* send a message to a contact */ + else if (!_strnicmp(arg,"goim?",5)) { + char *tok,*sn=NULL,*msg=NULL; + HANDLE hContact; + if (*(arg+=5)==0) return 1; /* parse failed */ + tok=strtok(arg,"&"); /* first token */ + while(tok!=NULL) { + if (!_strnicmp(tok,"screenname=",11) && *(tok+11)!=0) + sn=Netlib_UrlDecode(tok+11); + if (!_strnicmp(tok,"message=",8) && *(tok+8)!=0) + msg=Netlib_UrlDecode(tok+8); + tok=strtok(NULL,"&"); /* next token */ + } + if(sn==NULL) return 1; /* parse failed */ + if(ServiceExists(MS_MSG_SENDMESSAGE)) { + hContact=find_contact(sn); + if(hContact==NULL) { + hContact=add_contact(sn); /* does not yet check if sn is current user */ + if(hContact!=NULL) + DBWriteContactSettingByte(hContact,MOD_KEY_CL,AIM_KEY_NL,1); + } + if(hContact!=NULL) + CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact,(LPARAM)msg); + } + return 0; + } + /* open a chatroom */ + else if (!_strnicmp(arg,"gochat?",7)) { + char *tok,*rm=NULL; + int exchange=0; + if (*(arg+=7)==0) return 1; /* parse failed */ + tok=strtok(arg,"&"); /* first token */ + while(tok!=NULL) { + if (!_strnicmp(tok,"roomname=",9) && *(tok+9)!=0) + rm=Netlib_UrlDecode(tok+9); + if (!_strnicmp(tok,"exchange=",9)) + exchange=atoi(Netlib_UrlDecode(tok+9)); + tok=strtok(NULL,"&"); /* next token */ + } + if(rm==NULL || exchange<=0) return 1; /* parse failed */ + aim_gchat_joinrequest(rm,exchange); + return 0; + } + return 1; /* parse failed */ +} + +static int AimLinksModulesLoaded(WPARAM wParam,LPARAM lParam) +{ + char service_name[MAXMODULELABELLENGTH]; + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + mir_snprintf(service_name,sizeof(service_name),"%s%s",AIM_PROTOCOL_NAME,"ParseAimLink"); + /* or "AOL Instant Messenger Links" */ + AssocMgr_AddNewUrlType("aim:",Translate("AIM Link Protocol"),conn.hInstance,IDI_AOL,service_name,0); + return 0; +} + +void aim_links_init() +{ + char service_name[MAXMODULELABELLENGTH]; + //LOG(LOG_DEBUG,"Links: init"); + mir_snprintf(service_name,sizeof(service_name),"%s%s",AIM_PROTOCOL_NAME,"ParseAimLink"); + hServiceParseLink=CreateServiceFunction(service_name,ServiceParseAimLink); + hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,AimLinksModulesLoaded); +} + +void aim_links_destroy() +{ + //LOG(LOG_DEBUG,"Links: destroy"); + UnhookEvent(hHookModulesLoaded); + DestroyServiceFunction(hServiceParseLink); +} +#endif + +// ----------------------------------------- + +#ifdef ICQ_SUPPORT_TEST + +#define gpszICQProtoName "ICQ" +#define IDI_ICQ 101 +#define hInst GetModuleHandleA("ICQ") +static __inline HANDLE HContactFromUIN(DWORD dwUIN,int *Added) { dwUIN; Added; return (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); } +static __inline HANDLE ICQFindFirstContact(void) { return NULL; } +static __inline HANDLE ICQFindNextContact(HANDLE hContact) { hContact; return NULL; } +static __inline void AddToCache(HANDLE hContact,DWORD dwUin) { hContact; dwUin; } +static __inline DWORD ICQGetContactSettingUIN(HANDLE hContact) { hContact; return 0; } +static __inline HANDLE HandleFromCacheByUin(DWORD dwUin) { dwUin; return NULL; } +#include +#include +#include +typedef struct { + PROTOSEARCHRESULT hdr; + DWORD uin; + BYTE auth; + char* uid; +} ICQSEARCHRESULT; + +#include "m_assocmgr.h" +static HANDLE hHookModulesLoaded; +static HANDLE hServiceOpenFile; + +static void TrimString(char *str) +{ + int len,start; + len=lstrlenA(str); + while(str[0]!='\0' && (unsigned char)str[len-1]<=' ') str[--len]=0; + for(start=0;str[start] && (unsigned char)str[start]<=' ';++start); + MoveMemory(str,str+start,len-start+1); +} + +static BOOL IsEmpty(const char *str) +{ + int i; + for(i=0;str[i]!='\0';i++) + if(str[i]!=' ' && str[i]!='\r' && str[i]!='\n') + return FALSE; + return TRUE; +} + +#define ICQFILE_MESSAGEUSER 1 +#define ICQFILE_ADDUSER 2 +typedef struct { + int type; + char uin[64]; + char email[128]; + char nick[128]; + char firstName[64]; + char lastName[64]; +} ICQFILEINFO; + +static HANDLE IsHContactFromUIN(DWORD uin) +{ + HANDLE hContact; + DWORD dwUin; + hContact=HandleFromCacheByUin(uin); + if(hContact!=NULL) return hContact; + hContact=ICQFindFirstContact(); + while(hContact!=NULL) { + dwUin=ICQGetContactSettingUIN(hContact); + if(dwUin==uin) { + AddToCache(hContact,dwUin); + return hContact; + } + hContact=ICQFindNextContact(hContact); + } + return NULL; +} + +static void AddIcqUser(ICQFILEINFO *info) +{ + ADDCONTACTSTRUCT acs; + ICQSEARCHRESULT psr; + DWORD uin; + /* check that uin does not belong to current user */ + uin=atoi(info->uin); + if(uin!=0 && uin!=ICQGetContactSettingUIN(NULL)) { + /* not yet present? */ + if(IsHContactFromUIN(uin)==NULL) { + acs.handleType=HANDLE_SEARCHRESULT; + acs.szProto=gpszICQProtoName; + acs.psr=(PROTOSEARCHRESULT*)&psr; + ZeroMemory(&psr,sizeof(ICQSEARCHRESULT)); + psr.hdr.cbSize=sizeof(ICQSEARCHRESULT); + if(info->nick[0]) psr.hdr.nick=info->nick; + else psr.hdr.nick=info->uin; + if(info->email[0]) psr.hdr.email=info->email; + if(info->firstName[0]) psr.hdr.firstName=info->firstName; + if(info->lastName[0]) psr.hdr.lastName=info->lastName; + psr.uin=uin; + psr.auth=1; /* authentication needed flag */ + psr.uid=NULL; /* icq contact */ + CallService(MS_ADDCONTACT_SHOW,(WPARAM)NULL,(LPARAM)&acs); + } + } +} + +static void MessageIcqUser(ICQFILEINFO *info) +{ + HANDLE hContact; + if(ServiceExists(MS_MSG_SENDMESSAGE)) { + hContact=HContactFromUIN(atoi(info->uin),NULL); /* adds the contact if needed */ + if(hContact!=NULL) + CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact,(LPARAM)NULL); + } +} + +static int IcqOpenFile(WPARAM wParam,LPARAM lParam) +{ + TCHAR *pszFile=(TCHAR*)lParam; /* TCHAR is specified on AssocMgr_AddNewFileTypeT() */ + FILE *fp; + ICQFILEINFO info; + char line[4096],*sep; + UNREFERENCED_PARAMETER(wParam); + /* + send message: + [ICQ Message User] + UIN=1234567 + + add user: + (all the .uin files I've seen only have UIN= in them) + [ICQ User] + UIN=1234567 + Email= + NickName= + FirstName= + LastName= + */ + if(pszFile==NULL) return 1; /* sanity check */ + fp=_tfopen(pszFile,_T("rt")); + if(fp==NULL) return 1; /* open failed */ + info.type=0; + while(!feof(fp)) { + if(fgets(line,sizeof(line),fp)==NULL) break; + TrimString(line); + if(IsEmpty(line)) continue; + if(line[0]=='[') { + ZeroMemory(&info,sizeof(info)); + if (!lstrcmpiA(line,"[ICQ Message User]")) + info.type=ICQFILE_MESSAGEUSER; + else if (!lstrcmpiA(line,"[ICQ User]")) + info.type=ICQFILE_ADDUSER; + continue; + } + if(info.type==0) continue; + sep=strchr(line,'='); + if(sep==NULL) { info.type=0; break; } /* format error */ + *(sep++)='\0'; + if (!lstrcmpA("UIN",line)) lstrcpynA(info.uin,sep,sizeof(info.uin)); /* buffer safe */ + else if (!lstrcmpA("Email",line)) lstrcpynA(info.email,sep,sizeof(info.email)); /* buffer safe */ + else if (!lstrcmpA("NickName",line)) lstrcpynA(info.nick,sep,sizeof(info.nick)); /* buffer safe */ + else if (!lstrcmpA("FirstName",line)) lstrcpynA(info.firstName,sep,sizeof(info.firstName)); /* buffer safe */ + else if (!lstrcmpA("LastName",line)) lstrcpynA(info.lastName,sep,sizeof(info.lastName)); /* buffer safe */ + } + fclose(fp); + switch(info.type) { + case ICQFILE_MESSAGEUSER: MessageIcqUser(&info); return 0; + case ICQFILE_ADDUSER: AddIcqUser(&info); return 0; + default: return 1; /* open failed */ + } +} + +static int IcqFilesModulesLoaded(WPARAM wParam,LPARAM lParam) +{ + char szService[MAX_PATH+32]; + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + strcat(strcpy(szService,gpszICQProtoName),"OpenFile"); + /* .icq files are not used, just by the ProtoLink plugin */ + //AssocMgr_AddNewFileTypeT(".icq","application/x-icq",TranslateT("ICQ Link Shortcut"),TranslateT("&Add to Contact List..."),hInst,IDI_ICQ,szService,FTDF_BROWSERAUTOOPEN|FTDF_ISTEXT|FTDF_ISSHORTCUT|FTDF_DEFAULTDISABLED); + AssocMgr_AddNewFileTypeT(".uin","application/x-icq",TranslateT("ICQ Link Shortcut"),TranslateT("&Add to Contact List..."),hInst,IDI_ICQ,szService,FTDF_BROWSERAUTOOPEN|FTDF_ISTEXT|FTDF_ISSHORTCUT); + return 0; +} + +void InitIcqFiles(void) +{ + char szService[MAX_PATH+32]; + strcat(strcpy(szService,gpszICQProtoName),"OpenFile"); + hServiceOpenFile=CreateServiceFunction(szService,IcqOpenFile); + hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,IcqFilesModulesLoaded); +} + +void UninitIcqFiles(void) +{ + UnhookEvent(hHookModulesLoaded); + DestroyServiceFunction(hServiceOpenFile); +} + +#undef hInst +#endif + +// ----------------------------------------- + +#ifdef YAHOO_SUPPORT_TEST + +#define yahooProtocolName "YAHOO" +#define IDI_YAHOO 10101 +#define hinstance GetModuleHandleA("YAHOO") +static __inline HANDLE getbuddyH(const char *yahoo_id) { yahoo_id; return NULL; } +static __inline HANDLE add_buddy(const char *yahoo_id,const char *yahoo_name,DWORD flags) { yahoo_id; yahoo_name; flags; return (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); } +#include +#include +#include + +#include "m_assocmgr.h" +static HANDLE hHookModulesLoaded; +static HANDLE hServiceParseYmsgrLink; + +static int ServiceParseYmsgrLink(WPARAM wParam,LPARAM lParam) +{ + char *arg=(char*)lParam; + UNREFERENCED_PARAMETER(wParam); + if(arg==NULL) return 1; /* sanity check */ + /* + add user: ymsgr:addfriend?ID + send message: ymsgr:sendim?ID&m=MESSAGE + add chatroom: ymsgr:chat?ROOM + */ + /* skip leading prefix */ + arg=strchr(arg,':'); + if(arg==NULL) return 1; /* parse failed */ + for (++arg;*arg=='/';++arg); + /* add a contact to the list */ + if (!_strnicmp(arg,"addfriend?",10)) { + char *tok,*id=NULL; + ADDCONTACTSTRUCT acs; + PROTOSEARCHRESULT psr; + if (*(arg+=10)==0) return 1; /* parse failed */ + tok=strtok(arg,"&"); /* first token */ + if(tok!=NULL) id=Netlib_UrlDecode(tok); + if(id==NULL || *id==0) return 1; /* parse failed */ + if(getbuddyH(id)==NULL) { /* does not yet check if id is current user */ + acs.handleType=HANDLE_SEARCHRESULT; + acs.szProto=yahooProtocolName; + acs.psr=&psr; + ZeroMemory(&psr,sizeof(PROTOSEARCHRESULT)); + psr.cbSize=sizeof(PROTOSEARCHRESULT); + psr.nick=id; + CallService(MS_ADDCONTACT_SHOW,(WPARAM)NULL,(LPARAM)&acs); + } + return 0; + } + /* send a message to a contact */ + else if (!_strnicmp(arg,"sendim?",7)) { + char *tok,*id=NULL,*msg=NULL; + HANDLE hContact; + if (*(arg+=7)==0) return 1; /* parse failed */ + tok=strtok(arg,"&"); /* first token */ + if(tok!=NULL) id=tok; + while(tok!=NULL) { + if (!_strnicmp(tok,"m=",2) && *(tok+2)!=0) + msg=Netlib_UrlDecode(tok+2); + tok=strtok(NULL,"&"); /* next token */ + } + if(id==NULL || *id==0) return 1; /* parse failed */ + if(ServiceExists(MS_MSG_SENDMESSAGE)) { /* does not yet check if sn is current user */ + hContact=add_buddy(id,id,PALF_TEMPORARY); /* ensure contact is on list */ + if(hContact!=NULL) + CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact,(LPARAM)msg); + } + return 0; + } + /* open a chatroom */ + else if (!_strnicmp(arg,"chat?",5)) { + char *tok,*rm=NULL; + if (*(arg+=5)==0) return 1; /* parse failed */ + tok=strtok(arg,"&"); /* first token */ + if(tok!=NULL) rm=Netlib_UrlDecode(tok); + if(rm==NULL) return 1; /* parse failed */ + /* not yet implemented (rm contains name of chatroom)*/ + return 0; + } + return 1; /* parse failed */ +} + +static int YmsgrLinksModulesLoaded(WPARAM wParam,LPARAM lParam) +{ + char szService[MAXMODULELABELLENGTH]; + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + mir_snprintf(szService,sizeof(szService),"%s%s",yahooProtocolName,"ParseYmsgrLink"); + AssocMgr_AddNewUrlType("ymsgr:",Translate("Yahoo Link Protocol"),hinstance,IDI_YAHOO,szService,0); + return 0; +} + +void YmsgrLinksInit(void) +{ + char szService[MAXMODULELABELLENGTH]; + mir_snprintf(szService,sizeof(szService),"%s%s",yahooProtocolName,"ParseYmsgrLink"); + hServiceParseYmsgrLink=CreateServiceFunction(szService,ServiceParseYmsgrLink); + hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,YmsgrLinksModulesLoaded); +} + +void YmsgrLinksUninit(void) +{ + UnhookEvent(hHookModulesLoaded); + DestroyServiceFunction(hServiceParseYmsgrLink); +} + +#undef hinstance +#endif + +// ----------------------------------------- + +#ifdef MSN_SUPPORT_TEST + +#define msnProtocolName "MSN" +#define IDI_MSN 101 +#define hInst GetModuleHandleA("MSN") +static __inline HANDLE MSN_HContactFromEmailT(const char *msnEmail) { msnEmail; return NULL; } +static __inline HANDLE MSN_HContactFromEmail(const char *msnEmail,const char *msnNick,int addIfNeeded,int temporary) { msnEmail; msnNick; addIfNeeded; temporary; return (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); } +#include +#include +#include + +#include "m_assocmgr.h" +static HANDLE hHookModulesLoaded; +static HANDLE hServiceParseMsnimLink; + +static int ServiceParseMsnimLink(WPARAM wParam,LPARAM lParam) +{ + char *arg=(char*)lParam; + UNREFERENCED_PARAMETER(wParam); + if(arg==NULL) return 1; /* sanity check */ + /* + add user: msnim:add?contact=netpassport@emailaddress.com + send message: msnim:chat?contact=netpassport@emailaddress.com + voice chat: msnim:voice?contact=netpassport@emailaddress.com + video chat: msnim:video?contact=netpassport@emailaddress.com + */ + /* skip leading prefix */ + arg=strchr(arg,':'); + if(arg==NULL) return 1; /* parse failed */ + for (++arg;*arg=='/';++arg); + /* add a contact to the list */ + if (!_strnicmp(arg,"add?",4)) { + char *tok,*email=NULL; + ADDCONTACTSTRUCT acs; + PROTOSEARCHRESULT psr; + if (*(arg+=4)==0) return 1; /* parse failed */ + tok=strtok(arg,"&"); /* first token */ + while(tok!=NULL) { + if (!_strnicmp(tok,"contact=",8) && *(tok+11)!=0) + email=Netlib_UrlDecode(tok+11); + tok=strtok(NULL,"&"); /* next token */ + } + if(email==NULL || *email==0) return 1; /* parse failed */ + if(MSN_HContactFromEmailT(email)==NULL) { /* does not yet check if email is current user */ + acs.handleType=HANDLE_SEARCHRESULT; + acs.szProto=AIM_PROTOCOL_NAME; + acs.psr=&psr; + ZeroMemory(&psr,sizeof(PROTOSEARCHRESULT)); + psr.cbSize=sizeof(PROTOSEARCHRESULT); + psr.nick=email; + psr.email=email; + CallService(MS_ADDCONTACT_SHOW,(WPARAM)NULL,(LPARAM)&acs); + } + return 0; + } + /* send a message to a contact */ + /* "voice" and "video" not yet implemented, perform same action as "chat" */ + else if (!_strnicmp(arg,"chat?",5) || !_strnicmp(arg,"voice?",6) || !_strnicmp(arg,"video?",6)) { + char *tok,*email=NULL; + HANDLE hContact; + if (*(arg+=5)==0) return 1; /* parse failed */ + if (*arg=='?' && *(++arg)==0) return 1; /* for "voice?" and "video?" */ + tok=strtok(arg,"&"); /* first token */ + while(tok!=NULL) { + if (!_strnicmp(tok,"contact=",8) && *(tok+11)!=0) + email=Netlib_UrlDecode(tok+11); + tok=strtok(NULL,"&"); /* next token */ + } + if(email==NULL || *email==0) return 1; /* parse failed */ + if(ServiceExists(MS_MSG_SENDMESSAGE)) { + hContact=MSN_HContactFromEmail(email,email,TRUE,TRUE); /* does not yet check if email is current user */ + if(hContact!=NULL) + CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact,(LPARAM)NULL); + } + return 0; + } + return 1; /* parse failed */ +} + +static int MsnLinksModulesLoaded(WPARAM wParam,LPARAM lParam) +{ + char szService[MAXMODULELABELLENGTH]; + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + mir_snprintf(szService,sizeof(szService),"%s%s",msnProtocolName,"ParseMsnimLink"); + AssocMgr_AddNewUrlType("msnim:",Translate("MSN Link Protocol"),hInst,IDI_MSN,szService,0); + return 0; +} + +int LoadMsnLinks(void) +{ + char szService[MAXMODULELABELLENGTH]; + mir_snprintf(szService,sizeof(szService),"%s%s",msnProtocolName,"ParseMsnimLink"); + hServiceParseMsnimLink=CreateServiceFunction(szService,ServiceParseMsnimLink); + hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,MsnLinksModulesLoaded); + return 0; +} + +void UnloadMsnLinks(void) +{ + UnhookEvent(hHookModulesLoaded); + DestroyServiceFunction(hServiceParseMsnimLink); +} + +#undef hInst +#endif + +// ----------------------------------------- + +#ifdef GG_SUPPORT_TEST + +#define GG_PROTO "GG" +#define IDI_GG 251 +#define hInstance GetModuleHandleA("GG") +typedef DWORD uin_t; +static __inline HANDLE gg_getcontact(uin_t uin,int create,int inlist,char *szNick) { uin; create; inlist; szNick; return (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); } +#include +#include +#include + +#include "m_assocmgr.h" +static HANDLE hHookModulesLoaded; +static HANDLE hServiceParseLink; + +static int ServiceParseLink(WPARAM wParam,LPARAM lParam) +{ + char *arg=(char*)lParam; + UNREFERENCED_PARAMETER(wParam); + if(arg==NULL) return 1; /* sanity check */ + /* send message: gg:UID */ + /* skip leading prefix */ + arg=strchr(arg,':'); + if(arg==NULL) return 1; /* parse failed */ + for (++arg;*arg=='/';++arg); + /* send a message to a contact */ + { HANDLE hContact; + if(ServiceExists(MS_MSG_SENDMESSAGE)) { + hContact=gg_getcontact(atoi(arg),TRUE,FALSE,arg); + if(hContact!=NULL) + CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact,(LPARAM)NULL); + } + } + return 0; +} + +static int LinksModulesLoaded(WPARAM wParam,LPARAM lParam) +{ + char szService[MAXMODULELABELLENGTH]; + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + mir_snprintf(szService,sizeof(szService),"%s%s",GG_PROTO,"ParseMsnimLink"); + AssocMgr_AddNewUrlType("gg:",Translate("Gadu-Gadu Link Protocol"),hInstance,IDI_GG,szService,0); + return 0; +} + +void gg_registerlinks(void) +{ + char szService[MAXMODULELABELLENGTH]; + mir_snprintf(szService,sizeof(szService),"%s%s",GG_PROTO,"ParseLink"); + hServiceParseLink=CreateServiceFunction(szService,ServiceParseLink); + hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,LinksModulesLoaded); +} + +void gg_unregisterlinks(void) +{ + UnhookEvent(hHookModulesLoaded); + DestroyServiceFunction(hServiceParseLink); +} + +#undef hInstance +#endif + +// ----------------------------------------- + +#ifdef JABBER_SUPPORT_TEST + +#define jabberProtoName "JABBER" +#define IDI_JABBER 102 +#define hInst GetModuleHandleA("JABBER") +static __inline HANDLE JabberHContactFromJID(const char *jid) { jid; return NULL; } +static __inline HANDLE JabberDBCreateContact(char *jid,char *nick,BOOL temporary,BOOL stripResource) { jid; nick; temporary; stripResource; return (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); } +#include +#include +#include + +#include "m_assocmgr.h" +static HANDLE hHookModulesLoaded; +static HANDLE hServiceParseXmppURI; + +static int ServiceParseXmppURI(WPARAM wParam,LPARAM lParam) +{ + char *arg=(char*)lParam; + char *jid; + UNREFERENCED_PARAMETER(wParam); + if(arg==NULL) return 1; /* sanity check */ + /* skip leading prefix */ + arg=strchr(arg,':'); + if(arg==NULL) return 1; /* parse failed */ + for (++arg;*arg=='/';++arg); + /* + complete specification: http://www.xmpp.org/extensions/xep-0147.html + send message: xmpp:JID?message;subject=TEXT&body=TEXT + add user: xmpp:JID?roster + remove user: xmpp:JID?remove + */ + /* user id */ + arg=strchr(jid=arg,'?'); + if(arg==NULL) arg+=lstrlenA(arg); /* points to terminating nul */ + else *(arg++)=0; + if (*jid==0) return 1; /* parse failed */ + /* send a message to a contact */ + else if (*arg==0 || (!_strnicmp(arg,"message",7) && (*(arg+7)==';' || *(arg+7)==0))) { + char *tok,*subj=NULL,*body=NULL; + HANDLE hContact; + char msg[1024]; + arg+=7; + while(*arg==';') ++arg; + tok=strtok(arg,"&"); /* first token */ + while(tok!=NULL) { + if (!_strnicmp(tok,"subject=",8) && *(tok+8)!=0) + subj=Netlib_UrlDecode(tok+8); + if (!_strnicmp(tok,"body=",5) && *(tok+5)!=0) + body=Netlib_UrlDecode(tok+5); + tok=strtok(NULL,"&"); /* next token */ + } + if(ServiceExists(MS_MSG_SENDMESSAGE)) { + hContact=JabberDBCreateContact(jid,jid,TRUE,FALSE); + if(subj!=NULL && body!=NULL) { + mir_snprintf(msg,sizeof(msg),"%.128s %s",subj,body); + body=msg; + } else if(body==NULL) body=subj; + if(hContact!=NULL) + CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact,(LPARAM)body); + } + return 0; + } + /* add user to contact list */ + else if (!_strnicmp(arg,"roster",6) && (*(arg+6)==';' || *(arg+6)==0)) { + ADDCONTACTSTRUCT acs; + PROTOSEARCHRESULT psr; + if(JabberHContactFromJID(jid)==NULL) { /* does not yet check if jid belongs to current user */ + acs.handleType=HANDLE_SEARCHRESULT; + acs.szProto=jabberProtoName; + acs.psr=&psr; + ZeroMemory(&psr,sizeof(PROTOSEARCHRESULT)); + psr.cbSize=sizeof(PROTOSEARCHRESULT); + psr.nick=jid; + CallService(MS_ADDCONTACT_SHOW,(WPARAM)NULL,(LPARAM)&acs); + } + return 0; + } + /* remove user from contact list */ + else if (!_strnicmp(arg,"remove",6) && (*(arg+6)==';' || *(arg+6)==0)) { + HANDLE hContact; + hContact=JabberHContactFromJID(jid); + if(hContact==NULL) /* not yet implemented: show standard miranda dialog here */ + CallService(MS_DB_CONTACT_DELETE,(WPARAM)hContact,0); + return 0; + } + /* add user subscription */ + else if (!_strnicmp(arg,"subscribe",9) && (*(arg+9)==';' || *(arg+9)==0)) { + /* not yet implemented */ + return 0; + } + /* remove user subscription */ + else if (!_strnicmp(arg,"unsubscribe",11) && (*(arg+11)==';' || *(arg+11)==0)) { + /* not yet implemented */ + return 0; + } + return 1; /* parse failed */ +} + +static int JabberLinksModulesLoaded(WPARAM wParam,LPARAM lParam) +{ + char szService[MAXMODULELABELLENGTH]; + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + mir_snprintf(szService,sizeof(szService),"%s%s",jabberProtoName,"ParseXmppURI"); + AssocMgr_AddNewUrlType("xmpp:",Translate("Jabber Link Protocol"),hInst,IDI_JABBER,szService,0); + return 0; +} + +int JabberLinksInit() +{ + char szService[MAXMODULELABELLENGTH]; + mir_snprintf(szService,sizeof(szService),"%s%s",jabberProtoName,"ParseXmppURI"); + hServiceParseXmppURI=CreateServiceFunction(szService,ServiceParseXmppURI); + hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,JabberLinksModulesLoaded); + return 0; +} + +int JabberLinksUninit() +{ + UnhookEvent(hHookModulesLoaded); + DestroyServiceFunction(hServiceParseXmppURI); + return 0; +} + +#undef hInst +#endif + +// ----------------------------------------- + +/* +static HANDLE hServiceTest; +static int TestingService(WPARAM wParam,LPARAM lParam) +{ + UNREFERENCED_PARAMETER(wParam); + MessageBoxEx(NULL,(TCHAR*)lParam,_T("Testing Service"),MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL,LANGIDFROMLCID((LCID)CallService(MS_LANGPACK_GETLOCALE,0,0))); + return 0; +} +*/ + +void InitTest(void) +{ + #ifdef AIM_SUPPORT_TEST + conn.hInstance=GetModuleHandleA("AIM"); + aim_links_init(); + #endif + #ifdef ICQ_SUPPORT_TEST + InitIcqFiles(); + #endif + #ifdef YAHOO_SUPPORT_TEST + YmsgrLinksInit(); + #endif + #ifdef MSN_SUPPORT_TEST + LoadMsnLinks(); + #endif + #ifdef GG_SUPPORT_TEST + gg_registerlinks(); + #endif + #ifdef JABBER_SUPPORT_TEST + JabberLinksInit(); + #endif + //hServiceTest=CreateServiceFunction("AssocMgr/TestingService",TestingService); + //AssocMgr_AddNewFileTypeT(".mir",NULL,TranslateT("Miranda Installer Package (demo purpose)"),TranslateT("&Install"),hInst,IDI_MIRANDAFILE,"AssocMgr/TestingService",0); +} + +void UninitTest(void) +{ + #ifdef AIM_SUPPORT_TEST + aim_links_destroy(); + #endif + #ifdef ICQ_SUPPORT_TEST + UninitIcqFiles(); + #endif + #ifdef YAHOO_SUPPORT_TEST + YmsgrLinksUninit(); + #endif + #ifdef MSN_SUPPORT_TEST + UnloadMsnLinks(); + #endif + #ifdef GG_SUPPORT_TEST + gg_unregisterlinks(); + #endif + #ifdef JABBER_SUPPORT_TEST + JabberLinksUninit(); + #endif + //DestroyServiceFunction(hServiceTest); +} diff --git a/plugins/AssocMgr/src/test.h b/plugins/AssocMgr/src/test.h new file mode 100644 index 0000000000..638dea164b --- /dev/null +++ b/plugins/AssocMgr/src/test.h @@ -0,0 +1,24 @@ +/* + +'File Association Manager'-Plugin for Miranda IM + +Copyright (C) 2005-2007 H. Herkenrath + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program (AssocMgr-License.txt); if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* Misc */ +void InitTest(void); +void UninitTest(void); diff --git a/plugins/AssocMgr/src/utils.cpp b/plugins/AssocMgr/src/utils.cpp new file mode 100644 index 0000000000..e6414eeb02 --- /dev/null +++ b/plugins/AssocMgr/src/utils.cpp @@ -0,0 +1,194 @@ +/* + +'File Association Manager'-Plugin for Miranda IM + +Copyright (C) 2005-2007 H. Herkenrath + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program (AssocMgr-License.txt); if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "common.h" + +DWORD WINAPI GetModuleFileNameWorkaround(HMODULE hModule,TCHAR *pszFileName,DWORD nSize) +{ + /* GetModuleFileName() commonly crashes when hModule=NULL and + * miranda32.exe was compiled without version resource */ + if(hModule==NULL) hModule=GetModuleHandle(NULL); + if(hModule==NULL) return 0; + return GetModuleFileName(hModule,pszFileName,nSize); +} + +/************************* String Conv ****************************/ + +// mir_free() the return value +WCHAR* a2u(const char *pszAnsi,BOOL fMirCp) +{ + UINT codepage,cch; + WCHAR *psz; + + if(pszAnsi==NULL) return NULL; + codepage=fMirCp?CallService(MS_LANGPACK_GETCODEPAGE,0,0):CP_ACP; + cch=MultiByteToWideChar(codepage,0,pszAnsi,-1,NULL,0); + if (!cch) return NULL; + + psz=(WCHAR*)mir_alloc(cch*sizeof(WCHAR)); + if(psz!=NULL && !MultiByteToWideChar(codepage,0,pszAnsi,-1,psz,cch)) { + mir_free(psz); + return NULL; + } + return psz; +} + +// mir_free() the return value +char* u2a(const WCHAR *pszUnicode,BOOL fMirCp) +{ + UINT codepage,cch; + char *psz; + DWORD flags; + + if(pszUnicode==NULL) return NULL; + codepage=fMirCp?CallService(MS_LANGPACK_GETCODEPAGE,0,0):CP_ACP; + /* without WC_COMPOSITECHECK some characters might get out strange (see MS blog) */ + cch=WideCharToMultiByte(codepage,flags=WC_COMPOSITECHECK,pszUnicode,-1,NULL,0,NULL,NULL); + if (!cch) cch=WideCharToMultiByte(codepage,flags=0,pszUnicode,-1,NULL,0,NULL,NULL); + if (!cch) return NULL; + + psz=(char*)mir_alloc(cch); + if(psz!=NULL && !WideCharToMultiByte(codepage,flags,pszUnicode,-1,psz,cch,NULL,NULL)) { + mir_free(psz); + return NULL; + } + return psz; +} + +// mir_free() the return value +TCHAR* s2t(const void *pszStr,DWORD fUnicode,BOOL fMirCp) +{ + + if(fUnicode) return mir_wstrdup((WCHAR*)pszStr); + return a2u((char*)pszStr,fMirCp); + +} + +// mir_free() the return value +void* t2s(const TCHAR *pszStr,DWORD fUnicode,BOOL fMirCp) +{ + + if (!fUnicode) return (void*)u2a(pszStr,fMirCp); + return (void*)mir_wstrdup(pszStr); + +} + +/************************* Database *******************************/ + +struct EnumPrefixSettingsParams { + char **settings; + int nSettingsCount; + const char *pszPrefix; + int nPrefixLen; +}; + +static int EnumPrefixSettingsProc(const char *pszSetting,LPARAM lParam) +{ + struct EnumPrefixSettingsParams *param=(struct EnumPrefixSettingsParams*)lParam; + if (!strncmp(pszSetting,param->pszPrefix,param->nPrefixLen)) { + char **buf; + /* resize storage array */ + buf = (char**)mir_realloc(param->settings,(param->nSettingsCount+1)*sizeof(char*)); + if(buf!=NULL) { + param->settings=buf; + buf[param->nSettingsCount]=mir_strdup(pszSetting); + if(buf[param->nSettingsCount]!=NULL) ++param->nSettingsCount; + } + } + return 0; +} + +// mir_free() the returned pSettings after use +BOOL EnumDbPrefixSettings(const char *pszModule,const char *pszSettingPrefix,char ***pSettings,int *pnSettingsCount) +{ + DBCONTACTENUMSETTINGS dbces; + struct EnumPrefixSettingsParams param; + dbces.szModule=pszModule; + dbces.pfnEnumProc=EnumPrefixSettingsProc; + dbces.lParam=(LPARAM)¶m; + param.settings=NULL; + param.nSettingsCount=0; + param.pszPrefix=pszSettingPrefix; + param.nPrefixLen=lstrlenA(pszSettingPrefix); + CallService(MS_DB_CONTACT_ENUMSETTINGS,0,(LPARAM)&dbces); + *pnSettingsCount=param.nSettingsCount; + *pSettings=param.settings; + return param.nSettingsCount!=0; +} + +/************************* Error Output ***************************/ + +static void MessageBoxIndirectFree(void *param) +{ + MSGBOXPARAMSA *mbp = (MSGBOXPARAMSA*)param; + MessageBoxIndirectA(mbp); + mir_free((char*)mbp->lpszCaption); /* does NULL check */ + mir_free((char*)mbp->lpszText); /* does NULL check */ + mir_free(mbp); +} + +void ShowInfoMessage(BYTE flags,const char *pszTitle,const char *pszTextFmt,...) +{ + char szText[256]; /* max for systray */ + MSGBOXPARAMSA *mbp; + + va_list va; + va_start(va,pszTextFmt); + mir_vsnprintf(szText,SIZEOF(szText),pszTextFmt,va); + va_end(va); + + if(ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) { + MIRANDASYSTRAYNOTIFY msn; + msn.cbSize=sizeof(msn); + msn.szProto=NULL; + msn.szInfoTitle=(char*)pszTitle; + msn.szInfo=(char*)szText; + msn.uTimeout=30000; /* max timeout */ + msn.dwInfoFlags=flags; + if (!CallServiceSync(MS_CLIST_SYSTRAY_NOTIFY,0,(LPARAM)&msn)) + return; /* success */ + } + + mbp=(MSGBOXPARAMSA*)mir_calloc(sizeof(*mbp)); + if(mbp==NULL) return; + mbp->cbSize=sizeof(*mbp); + mbp->lpszCaption=mir_strdup(pszTitle); + mbp->lpszText=mir_strdup(szText); + mbp->dwStyle=MB_OK|MB_SETFOREGROUND|MB_TASKMODAL; + mbp->dwLanguageId=LANGIDFROMLCID((LCID)CallService(MS_LANGPACK_GETLOCALE,0,0)); + switch(flags&NIIF_ICON_MASK) { + case NIIF_INFO: mbp->dwStyle|=MB_ICONINFORMATION; break; + case NIIF_WARNING: mbp->dwStyle|=MB_ICONWARNING; break; + case NIIF_ERROR: mbp->dwStyle|=MB_ICONERROR; + } + mir_forkthread(MessageBoxIndirectFree, mbp); +} + +// LocalFree() the return value +char* GetWinErrorDescription(DWORD dwLastError) +{ + char *buf=NULL; + DWORD flags=FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM; + if (!FormatMessageA(flags,NULL,dwLastError,LANGIDFROMLCID((LCID)CallService(MS_LANGPACK_GETLOCALE,0,0)),(char*)&buf,0,NULL)) + if(GetLastError()==ERROR_RESOURCE_LANG_NOT_FOUND) + FormatMessageA(flags,NULL,dwLastError,0,(char*)&buf,0,NULL); + return buf; +} diff --git a/plugins/AssocMgr/src/utils.h b/plugins/AssocMgr/src/utils.h new file mode 100644 index 0000000000..f65a29ebec --- /dev/null +++ b/plugins/AssocMgr/src/utils.h @@ -0,0 +1,39 @@ +/* + +'File Association Manager'-Plugin for Miranda IM + +Copyright (C) 2005-2007 H. Herkenrath + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program (AssocMgr-License.txt); if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +DWORD WINAPI GetModuleFileNameWorkaround(HMODULE hModule,TCHAR *pszFileName,DWORD nSize); + +/* String Conv */ +WCHAR* a2u(const char *pszAnsi,BOOL fMirCp); +char* u2a(const WCHAR *pszUnicode,BOOL fMirCp); +TCHAR* s2t(const void *pszStr,DWORD fUnicode,BOOL fMirCp); +void* t2s(const TCHAR *pszStr,DWORD fUnicode,BOOL fMirCp); + + #define t2a(s) u2a(s,FALSE) + #define a2t(s) a2u(s,FALSE) + + +/* Database */ +BOOL EnumDbPrefixSettings(const char *pszModule,const char *pszSettingPrefix,char ***pSettings,int *pnSettingsCount); + +/* Error Output */ +void ShowInfoMessage(BYTE flags,const char *pszTitle,const char *pszTextFmt,...); +char* GetWinErrorDescription(DWORD dwLastError); diff --git a/plugins/AssocMgr/src/version.h b/plugins/AssocMgr/src/version.h new file mode 100644 index 0000000000..9d68defbef --- /dev/null +++ b/plugins/AssocMgr/src/version.h @@ -0,0 +1,41 @@ +/* + +'File Association Manager'-Plugin for Miranda IM + +Copyright (C) 2005-2007 H. Herkenrath + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program (AssocMgr-License.txt); if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#define __MAJOR_VERSION 0 +#define __MINOR_VERSION 1 +#define __RELEASE_NUM 1 +#define __BUILD_NUM 0 + +#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM +#define __FILEVERSION_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM + +#define __STRINGIFY_IMPL(x) #x +#define __STRINGIFY(x) __STRINGIFY_IMPL(x) +#define __VERSION_STRING __STRINGIFY(__FILEVERSION_DOTS) + +#define __PLUGIN_NAME "File Association Manager" +#define __INTERNAL_NAME "AssocMgr" +#define __FILENAME "AssocMgr.dll" +#define __DESCRIPTION "Handles file type associations and URLs like aim, ymsgr, xmpp, wpmsg, gg, tlen." +#define __AUTHOR "H. Herkenrath" +#define __AUTHOREMAIL "hrathh@users.sourceforge.net" +#define __AUTHORWEB "http://addons.miranda-im.org/details.php?action=viewfile&id=3457" +#define __COPYRIGHT "© 2005-2007 H. Herkenrath" diff --git a/plugins/AssocMgr/test.cpp b/plugins/AssocMgr/test.cpp deleted file mode 100644 index 73112af5a5..0000000000 --- a/plugins/AssocMgr/test.cpp +++ /dev/null @@ -1,869 +0,0 @@ -/* - -'File Association Manager'-Plugin for Miranda IM - -Copyright (C) 2005-2007 H. Herkenrath - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program (AssocMgr-License.txt); if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -// -- Includes -#include "common.h" - -/* -#define AIM_SUPPORT_TEST -#define ICQ_SUPPORT_TEST -#define YAHOO_SUPPORT_TEST -#define MSN_SUPPORT_TEST -#define GG_SUPPORT_TEST -#define JABBER_SUPPORT_TEST -*/ - -// ----------------------------------------- - -extern HINSTANCE hInst; - -/* a copy of those in m_assocmgr.h, as we did not #include those helpers */ -__inline static int AssocMgr_AddNewFileTypeT(const char *ext,const char *mime,const TCHAR *desc,const TCHAR *verb,HINSTANCE hinst,UINT iconid,const char *service,DWORD flags) -{ - FILETYPEDESC ftd; - ftd.cbSize=sizeof(FILETYPEDESC); - ftd.pszFileExt=ext; - ftd.pszMimeType=mime; - ftd.ptszDescription=desc; - ftd.hInstance=hinst; - ftd.nIconResID=iconid; - ftd.ptszVerbDesc=verb; - ftd.pszService=service; - ftd.flags=flags|FTDF_TCHAR; - return CallService(MS_ASSOCMGR_ADDNEWFILETYPE,0,(LPARAM)&ftd); -} - -static int __inline AssocMgr_AddNewUrlType(const char *prefix,const char *desc,HINSTANCE hinst,UINT iconid,const char *service,DWORD flags) -{ - URLTYPEDESC utd; - utd.cbSize=sizeof(URLTYPEDESC); - utd.pszProtoPrefix=prefix; - utd.pszDescription=desc; - utd.hInstance=hinst; - utd.nIconResID=iconid; - utd.pszService=service; - utd.flags=flags&~UTDF_UNICODE; - return CallService(MS_ASSOCMGR_ADDNEWURLTYPE,0,(LPARAM)&utd); -} - -// ----------------------------------------- - -#ifdef AIM_SUPPORT_TEST - -#define AIM_PROTOCOL_NAME "AIM" -#define IDI_AOL 28 -#define MOD_KEY_CL "CList" -#define AIM_KEY_NL "NotOnList" -struct oscar_data { HINSTANCE hInstance; } static conn; -static __inline HANDLE find_contact(const char *nick) { nick; return NULL; } -static __inline HANDLE add_contact(const char *nick) { nick; return (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); } -static __inline void aim_gchat_joinrequest(const char *room, int exchange) { room; exchange; MessageBoxA(NULL,"Join group chat!",room,MB_OK); return; } -#include -#include -#include - -#include "m_assocmgr.h" -static HANDLE hHookModulesLoaded; -static HANDLE hServiceParseLink; - -static int ServiceParseAimLink(WPARAM wParam,LPARAM lParam) -{ - char *arg=(char*)lParam; - UNREFERENCED_PARAMETER(wParam); - if(arg==NULL) return 1; /* sanity check */ - /* skip leading prefix */ - arg=strchr(arg,':'); - if(arg==NULL) return 1; /* parse failed */ - for (++arg;*arg=='/';++arg); - /* - add user: aim:addbuddy?screenname=NICK&groupname=GROUP - send message: aim:goim?screenname=NICK&message=MSG - open chatroom: aim:gochat?roomname=ROOM&exchange=NUM - */ - /* add a contact to the list */ - if (!_strnicmp(arg,"addbuddy?",9)) { - char *tok,*sn=NULL,*group=NULL; - ADDCONTACTSTRUCT acs; - PROTOSEARCHRESULT psr; - if (*(arg+=9)==0) return 1; /* parse failed */ - tok=strtok(arg,"&"); /* first token */ - while(tok!=NULL) { - if (!_strnicmp(tok,"screenname=",11) && *(tok+11)!=0) - sn=Netlib_UrlDecode(tok+11); - if (!_strnicmp(tok,"groupname=",10) && *(tok+10)!=0) - group=Netlib_UrlDecode(tok+10); /* group is currently ignored */ - tok=strtok(NULL,"&"); /* next token */ - } - if(sn==NULL) return 1; /* parse failed */ - if(find_contact(sn)==NULL) { /* does not yet check if sn is current user */ - acs.handleType=HANDLE_SEARCHRESULT; - acs.szProto=AIM_PROTOCOL_NAME; - acs.psr=&psr; - ZeroMemory(&psr,sizeof(PROTOSEARCHRESULT)); - psr.cbSize=sizeof(PROTOSEARCHRESULT); - psr.nick=sn; - CallService(MS_ADDCONTACT_SHOW,(WPARAM)NULL,(LPARAM)&acs); - } - return 0; - } - /* send a message to a contact */ - else if (!_strnicmp(arg,"goim?",5)) { - char *tok,*sn=NULL,*msg=NULL; - HANDLE hContact; - if (*(arg+=5)==0) return 1; /* parse failed */ - tok=strtok(arg,"&"); /* first token */ - while(tok!=NULL) { - if (!_strnicmp(tok,"screenname=",11) && *(tok+11)!=0) - sn=Netlib_UrlDecode(tok+11); - if (!_strnicmp(tok,"message=",8) && *(tok+8)!=0) - msg=Netlib_UrlDecode(tok+8); - tok=strtok(NULL,"&"); /* next token */ - } - if(sn==NULL) return 1; /* parse failed */ - if(ServiceExists(MS_MSG_SENDMESSAGE)) { - hContact=find_contact(sn); - if(hContact==NULL) { - hContact=add_contact(sn); /* does not yet check if sn is current user */ - if(hContact!=NULL) - DBWriteContactSettingByte(hContact,MOD_KEY_CL,AIM_KEY_NL,1); - } - if(hContact!=NULL) - CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact,(LPARAM)msg); - } - return 0; - } - /* open a chatroom */ - else if (!_strnicmp(arg,"gochat?",7)) { - char *tok,*rm=NULL; - int exchange=0; - if (*(arg+=7)==0) return 1; /* parse failed */ - tok=strtok(arg,"&"); /* first token */ - while(tok!=NULL) { - if (!_strnicmp(tok,"roomname=",9) && *(tok+9)!=0) - rm=Netlib_UrlDecode(tok+9); - if (!_strnicmp(tok,"exchange=",9)) - exchange=atoi(Netlib_UrlDecode(tok+9)); - tok=strtok(NULL,"&"); /* next token */ - } - if(rm==NULL || exchange<=0) return 1; /* parse failed */ - aim_gchat_joinrequest(rm,exchange); - return 0; - } - return 1; /* parse failed */ -} - -static int AimLinksModulesLoaded(WPARAM wParam,LPARAM lParam) -{ - char service_name[MAXMODULELABELLENGTH]; - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - mir_snprintf(service_name,sizeof(service_name),"%s%s",AIM_PROTOCOL_NAME,"ParseAimLink"); - /* or "AOL Instant Messenger Links" */ - AssocMgr_AddNewUrlType("aim:",Translate("AIM Link Protocol"),conn.hInstance,IDI_AOL,service_name,0); - return 0; -} - -void aim_links_init() -{ - char service_name[MAXMODULELABELLENGTH]; - //LOG(LOG_DEBUG,"Links: init"); - mir_snprintf(service_name,sizeof(service_name),"%s%s",AIM_PROTOCOL_NAME,"ParseAimLink"); - hServiceParseLink=CreateServiceFunction(service_name,ServiceParseAimLink); - hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,AimLinksModulesLoaded); -} - -void aim_links_destroy() -{ - //LOG(LOG_DEBUG,"Links: destroy"); - UnhookEvent(hHookModulesLoaded); - DestroyServiceFunction(hServiceParseLink); -} -#endif - -// ----------------------------------------- - -#ifdef ICQ_SUPPORT_TEST - -#define gpszICQProtoName "ICQ" -#define IDI_ICQ 101 -#define hInst GetModuleHandleA("ICQ") -static __inline HANDLE HContactFromUIN(DWORD dwUIN,int *Added) { dwUIN; Added; return (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); } -static __inline HANDLE ICQFindFirstContact(void) { return NULL; } -static __inline HANDLE ICQFindNextContact(HANDLE hContact) { hContact; return NULL; } -static __inline void AddToCache(HANDLE hContact,DWORD dwUin) { hContact; dwUin; } -static __inline DWORD ICQGetContactSettingUIN(HANDLE hContact) { hContact; return 0; } -static __inline HANDLE HandleFromCacheByUin(DWORD dwUin) { dwUin; return NULL; } -#include -#include -#include -typedef struct { - PROTOSEARCHRESULT hdr; - DWORD uin; - BYTE auth; - char* uid; -} ICQSEARCHRESULT; - -#include "m_assocmgr.h" -static HANDLE hHookModulesLoaded; -static HANDLE hServiceOpenFile; - -static void TrimString(char *str) -{ - int len,start; - len=lstrlenA(str); - while(str[0]!='\0' && (unsigned char)str[len-1]<=' ') str[--len]=0; - for(start=0;str[start] && (unsigned char)str[start]<=' ';++start); - MoveMemory(str,str+start,len-start+1); -} - -static BOOL IsEmpty(const char *str) -{ - int i; - for(i=0;str[i]!='\0';i++) - if(str[i]!=' ' && str[i]!='\r' && str[i]!='\n') - return FALSE; - return TRUE; -} - -#define ICQFILE_MESSAGEUSER 1 -#define ICQFILE_ADDUSER 2 -typedef struct { - int type; - char uin[64]; - char email[128]; - char nick[128]; - char firstName[64]; - char lastName[64]; -} ICQFILEINFO; - -static HANDLE IsHContactFromUIN(DWORD uin) -{ - HANDLE hContact; - DWORD dwUin; - hContact=HandleFromCacheByUin(uin); - if(hContact!=NULL) return hContact; - hContact=ICQFindFirstContact(); - while(hContact!=NULL) { - dwUin=ICQGetContactSettingUIN(hContact); - if(dwUin==uin) { - AddToCache(hContact,dwUin); - return hContact; - } - hContact=ICQFindNextContact(hContact); - } - return NULL; -} - -static void AddIcqUser(ICQFILEINFO *info) -{ - ADDCONTACTSTRUCT acs; - ICQSEARCHRESULT psr; - DWORD uin; - /* check that uin does not belong to current user */ - uin=atoi(info->uin); - if(uin!=0 && uin!=ICQGetContactSettingUIN(NULL)) { - /* not yet present? */ - if(IsHContactFromUIN(uin)==NULL) { - acs.handleType=HANDLE_SEARCHRESULT; - acs.szProto=gpszICQProtoName; - acs.psr=(PROTOSEARCHRESULT*)&psr; - ZeroMemory(&psr,sizeof(ICQSEARCHRESULT)); - psr.hdr.cbSize=sizeof(ICQSEARCHRESULT); - if(info->nick[0]) psr.hdr.nick=info->nick; - else psr.hdr.nick=info->uin; - if(info->email[0]) psr.hdr.email=info->email; - if(info->firstName[0]) psr.hdr.firstName=info->firstName; - if(info->lastName[0]) psr.hdr.lastName=info->lastName; - psr.uin=uin; - psr.auth=1; /* authentication needed flag */ - psr.uid=NULL; /* icq contact */ - CallService(MS_ADDCONTACT_SHOW,(WPARAM)NULL,(LPARAM)&acs); - } - } -} - -static void MessageIcqUser(ICQFILEINFO *info) -{ - HANDLE hContact; - if(ServiceExists(MS_MSG_SENDMESSAGE)) { - hContact=HContactFromUIN(atoi(info->uin),NULL); /* adds the contact if needed */ - if(hContact!=NULL) - CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact,(LPARAM)NULL); - } -} - -static int IcqOpenFile(WPARAM wParam,LPARAM lParam) -{ - TCHAR *pszFile=(TCHAR*)lParam; /* TCHAR is specified on AssocMgr_AddNewFileTypeT() */ - FILE *fp; - ICQFILEINFO info; - char line[4096],*sep; - UNREFERENCED_PARAMETER(wParam); - /* - send message: - [ICQ Message User] - UIN=1234567 - - add user: - (all the .uin files I've seen only have UIN= in them) - [ICQ User] - UIN=1234567 - Email= - NickName= - FirstName= - LastName= - */ - if(pszFile==NULL) return 1; /* sanity check */ - fp=_tfopen(pszFile,_T("rt")); - if(fp==NULL) return 1; /* open failed */ - info.type=0; - while(!feof(fp)) { - if(fgets(line,sizeof(line),fp)==NULL) break; - TrimString(line); - if(IsEmpty(line)) continue; - if(line[0]=='[') { - ZeroMemory(&info,sizeof(info)); - if (!lstrcmpiA(line,"[ICQ Message User]")) - info.type=ICQFILE_MESSAGEUSER; - else if (!lstrcmpiA(line,"[ICQ User]")) - info.type=ICQFILE_ADDUSER; - continue; - } - if(info.type==0) continue; - sep=strchr(line,'='); - if(sep==NULL) { info.type=0; break; } /* format error */ - *(sep++)='\0'; - if (!lstrcmpA("UIN",line)) lstrcpynA(info.uin,sep,sizeof(info.uin)); /* buffer safe */ - else if (!lstrcmpA("Email",line)) lstrcpynA(info.email,sep,sizeof(info.email)); /* buffer safe */ - else if (!lstrcmpA("NickName",line)) lstrcpynA(info.nick,sep,sizeof(info.nick)); /* buffer safe */ - else if (!lstrcmpA("FirstName",line)) lstrcpynA(info.firstName,sep,sizeof(info.firstName)); /* buffer safe */ - else if (!lstrcmpA("LastName",line)) lstrcpynA(info.lastName,sep,sizeof(info.lastName)); /* buffer safe */ - } - fclose(fp); - switch(info.type) { - case ICQFILE_MESSAGEUSER: MessageIcqUser(&info); return 0; - case ICQFILE_ADDUSER: AddIcqUser(&info); return 0; - default: return 1; /* open failed */ - } -} - -static int IcqFilesModulesLoaded(WPARAM wParam,LPARAM lParam) -{ - char szService[MAX_PATH+32]; - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - strcat(strcpy(szService,gpszICQProtoName),"OpenFile"); - /* .icq files are not used, just by the ProtoLink plugin */ - //AssocMgr_AddNewFileTypeT(".icq","application/x-icq",TranslateT("ICQ Link Shortcut"),TranslateT("&Add to Contact List..."),hInst,IDI_ICQ,szService,FTDF_BROWSERAUTOOPEN|FTDF_ISTEXT|FTDF_ISSHORTCUT|FTDF_DEFAULTDISABLED); - AssocMgr_AddNewFileTypeT(".uin","application/x-icq",TranslateT("ICQ Link Shortcut"),TranslateT("&Add to Contact List..."),hInst,IDI_ICQ,szService,FTDF_BROWSERAUTOOPEN|FTDF_ISTEXT|FTDF_ISSHORTCUT); - return 0; -} - -void InitIcqFiles(void) -{ - char szService[MAX_PATH+32]; - strcat(strcpy(szService,gpszICQProtoName),"OpenFile"); - hServiceOpenFile=CreateServiceFunction(szService,IcqOpenFile); - hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,IcqFilesModulesLoaded); -} - -void UninitIcqFiles(void) -{ - UnhookEvent(hHookModulesLoaded); - DestroyServiceFunction(hServiceOpenFile); -} - -#undef hInst -#endif - -// ----------------------------------------- - -#ifdef YAHOO_SUPPORT_TEST - -#define yahooProtocolName "YAHOO" -#define IDI_YAHOO 10101 -#define hinstance GetModuleHandleA("YAHOO") -static __inline HANDLE getbuddyH(const char *yahoo_id) { yahoo_id; return NULL; } -static __inline HANDLE add_buddy(const char *yahoo_id,const char *yahoo_name,DWORD flags) { yahoo_id; yahoo_name; flags; return (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); } -#include -#include -#include - -#include "m_assocmgr.h" -static HANDLE hHookModulesLoaded; -static HANDLE hServiceParseYmsgrLink; - -static int ServiceParseYmsgrLink(WPARAM wParam,LPARAM lParam) -{ - char *arg=(char*)lParam; - UNREFERENCED_PARAMETER(wParam); - if(arg==NULL) return 1; /* sanity check */ - /* - add user: ymsgr:addfriend?ID - send message: ymsgr:sendim?ID&m=MESSAGE - add chatroom: ymsgr:chat?ROOM - */ - /* skip leading prefix */ - arg=strchr(arg,':'); - if(arg==NULL) return 1; /* parse failed */ - for (++arg;*arg=='/';++arg); - /* add a contact to the list */ - if (!_strnicmp(arg,"addfriend?",10)) { - char *tok,*id=NULL; - ADDCONTACTSTRUCT acs; - PROTOSEARCHRESULT psr; - if (*(arg+=10)==0) return 1; /* parse failed */ - tok=strtok(arg,"&"); /* first token */ - if(tok!=NULL) id=Netlib_UrlDecode(tok); - if(id==NULL || *id==0) return 1; /* parse failed */ - if(getbuddyH(id)==NULL) { /* does not yet check if id is current user */ - acs.handleType=HANDLE_SEARCHRESULT; - acs.szProto=yahooProtocolName; - acs.psr=&psr; - ZeroMemory(&psr,sizeof(PROTOSEARCHRESULT)); - psr.cbSize=sizeof(PROTOSEARCHRESULT); - psr.nick=id; - CallService(MS_ADDCONTACT_SHOW,(WPARAM)NULL,(LPARAM)&acs); - } - return 0; - } - /* send a message to a contact */ - else if (!_strnicmp(arg,"sendim?",7)) { - char *tok,*id=NULL,*msg=NULL; - HANDLE hContact; - if (*(arg+=7)==0) return 1; /* parse failed */ - tok=strtok(arg,"&"); /* first token */ - if(tok!=NULL) id=tok; - while(tok!=NULL) { - if (!_strnicmp(tok,"m=",2) && *(tok+2)!=0) - msg=Netlib_UrlDecode(tok+2); - tok=strtok(NULL,"&"); /* next token */ - } - if(id==NULL || *id==0) return 1; /* parse failed */ - if(ServiceExists(MS_MSG_SENDMESSAGE)) { /* does not yet check if sn is current user */ - hContact=add_buddy(id,id,PALF_TEMPORARY); /* ensure contact is on list */ - if(hContact!=NULL) - CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact,(LPARAM)msg); - } - return 0; - } - /* open a chatroom */ - else if (!_strnicmp(arg,"chat?",5)) { - char *tok,*rm=NULL; - if (*(arg+=5)==0) return 1; /* parse failed */ - tok=strtok(arg,"&"); /* first token */ - if(tok!=NULL) rm=Netlib_UrlDecode(tok); - if(rm==NULL) return 1; /* parse failed */ - /* not yet implemented (rm contains name of chatroom)*/ - return 0; - } - return 1; /* parse failed */ -} - -static int YmsgrLinksModulesLoaded(WPARAM wParam,LPARAM lParam) -{ - char szService[MAXMODULELABELLENGTH]; - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - mir_snprintf(szService,sizeof(szService),"%s%s",yahooProtocolName,"ParseYmsgrLink"); - AssocMgr_AddNewUrlType("ymsgr:",Translate("Yahoo Link Protocol"),hinstance,IDI_YAHOO,szService,0); - return 0; -} - -void YmsgrLinksInit(void) -{ - char szService[MAXMODULELABELLENGTH]; - mir_snprintf(szService,sizeof(szService),"%s%s",yahooProtocolName,"ParseYmsgrLink"); - hServiceParseYmsgrLink=CreateServiceFunction(szService,ServiceParseYmsgrLink); - hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,YmsgrLinksModulesLoaded); -} - -void YmsgrLinksUninit(void) -{ - UnhookEvent(hHookModulesLoaded); - DestroyServiceFunction(hServiceParseYmsgrLink); -} - -#undef hinstance -#endif - -// ----------------------------------------- - -#ifdef MSN_SUPPORT_TEST - -#define msnProtocolName "MSN" -#define IDI_MSN 101 -#define hInst GetModuleHandleA("MSN") -static __inline HANDLE MSN_HContactFromEmailT(const char *msnEmail) { msnEmail; return NULL; } -static __inline HANDLE MSN_HContactFromEmail(const char *msnEmail,const char *msnNick,int addIfNeeded,int temporary) { msnEmail; msnNick; addIfNeeded; temporary; return (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); } -#include -#include -#include - -#include "m_assocmgr.h" -static HANDLE hHookModulesLoaded; -static HANDLE hServiceParseMsnimLink; - -static int ServiceParseMsnimLink(WPARAM wParam,LPARAM lParam) -{ - char *arg=(char*)lParam; - UNREFERENCED_PARAMETER(wParam); - if(arg==NULL) return 1; /* sanity check */ - /* - add user: msnim:add?contact=netpassport@emailaddress.com - send message: msnim:chat?contact=netpassport@emailaddress.com - voice chat: msnim:voice?contact=netpassport@emailaddress.com - video chat: msnim:video?contact=netpassport@emailaddress.com - */ - /* skip leading prefix */ - arg=strchr(arg,':'); - if(arg==NULL) return 1; /* parse failed */ - for (++arg;*arg=='/';++arg); - /* add a contact to the list */ - if (!_strnicmp(arg,"add?",4)) { - char *tok,*email=NULL; - ADDCONTACTSTRUCT acs; - PROTOSEARCHRESULT psr; - if (*(arg+=4)==0) return 1; /* parse failed */ - tok=strtok(arg,"&"); /* first token */ - while(tok!=NULL) { - if (!_strnicmp(tok,"contact=",8) && *(tok+11)!=0) - email=Netlib_UrlDecode(tok+11); - tok=strtok(NULL,"&"); /* next token */ - } - if(email==NULL || *email==0) return 1; /* parse failed */ - if(MSN_HContactFromEmailT(email)==NULL) { /* does not yet check if email is current user */ - acs.handleType=HANDLE_SEARCHRESULT; - acs.szProto=AIM_PROTOCOL_NAME; - acs.psr=&psr; - ZeroMemory(&psr,sizeof(PROTOSEARCHRESULT)); - psr.cbSize=sizeof(PROTOSEARCHRESULT); - psr.nick=email; - psr.email=email; - CallService(MS_ADDCONTACT_SHOW,(WPARAM)NULL,(LPARAM)&acs); - } - return 0; - } - /* send a message to a contact */ - /* "voice" and "video" not yet implemented, perform same action as "chat" */ - else if (!_strnicmp(arg,"chat?",5) || !_strnicmp(arg,"voice?",6) || !_strnicmp(arg,"video?",6)) { - char *tok,*email=NULL; - HANDLE hContact; - if (*(arg+=5)==0) return 1; /* parse failed */ - if (*arg=='?' && *(++arg)==0) return 1; /* for "voice?" and "video?" */ - tok=strtok(arg,"&"); /* first token */ - while(tok!=NULL) { - if (!_strnicmp(tok,"contact=",8) && *(tok+11)!=0) - email=Netlib_UrlDecode(tok+11); - tok=strtok(NULL,"&"); /* next token */ - } - if(email==NULL || *email==0) return 1; /* parse failed */ - if(ServiceExists(MS_MSG_SENDMESSAGE)) { - hContact=MSN_HContactFromEmail(email,email,TRUE,TRUE); /* does not yet check if email is current user */ - if(hContact!=NULL) - CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact,(LPARAM)NULL); - } - return 0; - } - return 1; /* parse failed */ -} - -static int MsnLinksModulesLoaded(WPARAM wParam,LPARAM lParam) -{ - char szService[MAXMODULELABELLENGTH]; - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - mir_snprintf(szService,sizeof(szService),"%s%s",msnProtocolName,"ParseMsnimLink"); - AssocMgr_AddNewUrlType("msnim:",Translate("MSN Link Protocol"),hInst,IDI_MSN,szService,0); - return 0; -} - -int LoadMsnLinks(void) -{ - char szService[MAXMODULELABELLENGTH]; - mir_snprintf(szService,sizeof(szService),"%s%s",msnProtocolName,"ParseMsnimLink"); - hServiceParseMsnimLink=CreateServiceFunction(szService,ServiceParseMsnimLink); - hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,MsnLinksModulesLoaded); - return 0; -} - -void UnloadMsnLinks(void) -{ - UnhookEvent(hHookModulesLoaded); - DestroyServiceFunction(hServiceParseMsnimLink); -} - -#undef hInst -#endif - -// ----------------------------------------- - -#ifdef GG_SUPPORT_TEST - -#define GG_PROTO "GG" -#define IDI_GG 251 -#define hInstance GetModuleHandleA("GG") -typedef DWORD uin_t; -static __inline HANDLE gg_getcontact(uin_t uin,int create,int inlist,char *szNick) { uin; create; inlist; szNick; return (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); } -#include -#include -#include - -#include "m_assocmgr.h" -static HANDLE hHookModulesLoaded; -static HANDLE hServiceParseLink; - -static int ServiceParseLink(WPARAM wParam,LPARAM lParam) -{ - char *arg=(char*)lParam; - UNREFERENCED_PARAMETER(wParam); - if(arg==NULL) return 1; /* sanity check */ - /* send message: gg:UID */ - /* skip leading prefix */ - arg=strchr(arg,':'); - if(arg==NULL) return 1; /* parse failed */ - for (++arg;*arg=='/';++arg); - /* send a message to a contact */ - { HANDLE hContact; - if(ServiceExists(MS_MSG_SENDMESSAGE)) { - hContact=gg_getcontact(atoi(arg),TRUE,FALSE,arg); - if(hContact!=NULL) - CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact,(LPARAM)NULL); - } - } - return 0; -} - -static int LinksModulesLoaded(WPARAM wParam,LPARAM lParam) -{ - char szService[MAXMODULELABELLENGTH]; - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - mir_snprintf(szService,sizeof(szService),"%s%s",GG_PROTO,"ParseMsnimLink"); - AssocMgr_AddNewUrlType("gg:",Translate("Gadu-Gadu Link Protocol"),hInstance,IDI_GG,szService,0); - return 0; -} - -void gg_registerlinks(void) -{ - char szService[MAXMODULELABELLENGTH]; - mir_snprintf(szService,sizeof(szService),"%s%s",GG_PROTO,"ParseLink"); - hServiceParseLink=CreateServiceFunction(szService,ServiceParseLink); - hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,LinksModulesLoaded); -} - -void gg_unregisterlinks(void) -{ - UnhookEvent(hHookModulesLoaded); - DestroyServiceFunction(hServiceParseLink); -} - -#undef hInstance -#endif - -// ----------------------------------------- - -#ifdef JABBER_SUPPORT_TEST - -#define jabberProtoName "JABBER" -#define IDI_JABBER 102 -#define hInst GetModuleHandleA("JABBER") -static __inline HANDLE JabberHContactFromJID(const char *jid) { jid; return NULL; } -static __inline HANDLE JabberDBCreateContact(char *jid,char *nick,BOOL temporary,BOOL stripResource) { jid; nick; temporary; stripResource; return (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); } -#include -#include -#include - -#include "m_assocmgr.h" -static HANDLE hHookModulesLoaded; -static HANDLE hServiceParseXmppURI; - -static int ServiceParseXmppURI(WPARAM wParam,LPARAM lParam) -{ - char *arg=(char*)lParam; - char *jid; - UNREFERENCED_PARAMETER(wParam); - if(arg==NULL) return 1; /* sanity check */ - /* skip leading prefix */ - arg=strchr(arg,':'); - if(arg==NULL) return 1; /* parse failed */ - for (++arg;*arg=='/';++arg); - /* - complete specification: http://www.xmpp.org/extensions/xep-0147.html - send message: xmpp:JID?message;subject=TEXT&body=TEXT - add user: xmpp:JID?roster - remove user: xmpp:JID?remove - */ - /* user id */ - arg=strchr(jid=arg,'?'); - if(arg==NULL) arg+=lstrlenA(arg); /* points to terminating nul */ - else *(arg++)=0; - if (*jid==0) return 1; /* parse failed */ - /* send a message to a contact */ - else if (*arg==0 || (!_strnicmp(arg,"message",7) && (*(arg+7)==';' || *(arg+7)==0))) { - char *tok,*subj=NULL,*body=NULL; - HANDLE hContact; - char msg[1024]; - arg+=7; - while(*arg==';') ++arg; - tok=strtok(arg,"&"); /* first token */ - while(tok!=NULL) { - if (!_strnicmp(tok,"subject=",8) && *(tok+8)!=0) - subj=Netlib_UrlDecode(tok+8); - if (!_strnicmp(tok,"body=",5) && *(tok+5)!=0) - body=Netlib_UrlDecode(tok+5); - tok=strtok(NULL,"&"); /* next token */ - } - if(ServiceExists(MS_MSG_SENDMESSAGE)) { - hContact=JabberDBCreateContact(jid,jid,TRUE,FALSE); - if(subj!=NULL && body!=NULL) { - mir_snprintf(msg,sizeof(msg),"%.128s %s",subj,body); - body=msg; - } else if(body==NULL) body=subj; - if(hContact!=NULL) - CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact,(LPARAM)body); - } - return 0; - } - /* add user to contact list */ - else if (!_strnicmp(arg,"roster",6) && (*(arg+6)==';' || *(arg+6)==0)) { - ADDCONTACTSTRUCT acs; - PROTOSEARCHRESULT psr; - if(JabberHContactFromJID(jid)==NULL) { /* does not yet check if jid belongs to current user */ - acs.handleType=HANDLE_SEARCHRESULT; - acs.szProto=jabberProtoName; - acs.psr=&psr; - ZeroMemory(&psr,sizeof(PROTOSEARCHRESULT)); - psr.cbSize=sizeof(PROTOSEARCHRESULT); - psr.nick=jid; - CallService(MS_ADDCONTACT_SHOW,(WPARAM)NULL,(LPARAM)&acs); - } - return 0; - } - /* remove user from contact list */ - else if (!_strnicmp(arg,"remove",6) && (*(arg+6)==';' || *(arg+6)==0)) { - HANDLE hContact; - hContact=JabberHContactFromJID(jid); - if(hContact==NULL) /* not yet implemented: show standard miranda dialog here */ - CallService(MS_DB_CONTACT_DELETE,(WPARAM)hContact,0); - return 0; - } - /* add user subscription */ - else if (!_strnicmp(arg,"subscribe",9) && (*(arg+9)==';' || *(arg+9)==0)) { - /* not yet implemented */ - return 0; - } - /* remove user subscription */ - else if (!_strnicmp(arg,"unsubscribe",11) && (*(arg+11)==';' || *(arg+11)==0)) { - /* not yet implemented */ - return 0; - } - return 1; /* parse failed */ -} - -static int JabberLinksModulesLoaded(WPARAM wParam,LPARAM lParam) -{ - char szService[MAXMODULELABELLENGTH]; - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); - mir_snprintf(szService,sizeof(szService),"%s%s",jabberProtoName,"ParseXmppURI"); - AssocMgr_AddNewUrlType("xmpp:",Translate("Jabber Link Protocol"),hInst,IDI_JABBER,szService,0); - return 0; -} - -int JabberLinksInit() -{ - char szService[MAXMODULELABELLENGTH]; - mir_snprintf(szService,sizeof(szService),"%s%s",jabberProtoName,"ParseXmppURI"); - hServiceParseXmppURI=CreateServiceFunction(szService,ServiceParseXmppURI); - hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,JabberLinksModulesLoaded); - return 0; -} - -int JabberLinksUninit() -{ - UnhookEvent(hHookModulesLoaded); - DestroyServiceFunction(hServiceParseXmppURI); - return 0; -} - -#undef hInst -#endif - -// ----------------------------------------- - -/* -static HANDLE hServiceTest; -static int TestingService(WPARAM wParam,LPARAM lParam) -{ - UNREFERENCED_PARAMETER(wParam); - MessageBoxEx(NULL,(TCHAR*)lParam,_T("Testing Service"),MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL,LANGIDFROMLCID((LCID)CallService(MS_LANGPACK_GETLOCALE,0,0))); - return 0; -} -*/ - -void InitTest(void) -{ - #ifdef AIM_SUPPORT_TEST - conn.hInstance=GetModuleHandleA("AIM"); - aim_links_init(); - #endif - #ifdef ICQ_SUPPORT_TEST - InitIcqFiles(); - #endif - #ifdef YAHOO_SUPPORT_TEST - YmsgrLinksInit(); - #endif - #ifdef MSN_SUPPORT_TEST - LoadMsnLinks(); - #endif - #ifdef GG_SUPPORT_TEST - gg_registerlinks(); - #endif - #ifdef JABBER_SUPPORT_TEST - JabberLinksInit(); - #endif - //hServiceTest=CreateServiceFunction("AssocMgr/TestingService",TestingService); - //AssocMgr_AddNewFileTypeT(".mir",NULL,TranslateT("Miranda Installer Package (demo purpose)"),TranslateT("&Install"),hInst,IDI_MIRANDAFILE,"AssocMgr/TestingService",0); -} - -void UninitTest(void) -{ - #ifdef AIM_SUPPORT_TEST - aim_links_destroy(); - #endif - #ifdef ICQ_SUPPORT_TEST - UninitIcqFiles(); - #endif - #ifdef YAHOO_SUPPORT_TEST - YmsgrLinksUninit(); - #endif - #ifdef MSN_SUPPORT_TEST - UnloadMsnLinks(); - #endif - #ifdef GG_SUPPORT_TEST - gg_unregisterlinks(); - #endif - #ifdef JABBER_SUPPORT_TEST - JabberLinksUninit(); - #endif - //DestroyServiceFunction(hServiceTest); -} diff --git a/plugins/AssocMgr/test.h b/plugins/AssocMgr/test.h deleted file mode 100644 index 638dea164b..0000000000 --- a/plugins/AssocMgr/test.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - -'File Association Manager'-Plugin for Miranda IM - -Copyright (C) 2005-2007 H. Herkenrath - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program (AssocMgr-License.txt); if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -/* Misc */ -void InitTest(void); -void UninitTest(void); diff --git a/plugins/AssocMgr/utils.cpp b/plugins/AssocMgr/utils.cpp deleted file mode 100644 index e6414eeb02..0000000000 --- a/plugins/AssocMgr/utils.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - -'File Association Manager'-Plugin for Miranda IM - -Copyright (C) 2005-2007 H. Herkenrath - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program (AssocMgr-License.txt); if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "common.h" - -DWORD WINAPI GetModuleFileNameWorkaround(HMODULE hModule,TCHAR *pszFileName,DWORD nSize) -{ - /* GetModuleFileName() commonly crashes when hModule=NULL and - * miranda32.exe was compiled without version resource */ - if(hModule==NULL) hModule=GetModuleHandle(NULL); - if(hModule==NULL) return 0; - return GetModuleFileName(hModule,pszFileName,nSize); -} - -/************************* String Conv ****************************/ - -// mir_free() the return value -WCHAR* a2u(const char *pszAnsi,BOOL fMirCp) -{ - UINT codepage,cch; - WCHAR *psz; - - if(pszAnsi==NULL) return NULL; - codepage=fMirCp?CallService(MS_LANGPACK_GETCODEPAGE,0,0):CP_ACP; - cch=MultiByteToWideChar(codepage,0,pszAnsi,-1,NULL,0); - if (!cch) return NULL; - - psz=(WCHAR*)mir_alloc(cch*sizeof(WCHAR)); - if(psz!=NULL && !MultiByteToWideChar(codepage,0,pszAnsi,-1,psz,cch)) { - mir_free(psz); - return NULL; - } - return psz; -} - -// mir_free() the return value -char* u2a(const WCHAR *pszUnicode,BOOL fMirCp) -{ - UINT codepage,cch; - char *psz; - DWORD flags; - - if(pszUnicode==NULL) return NULL; - codepage=fMirCp?CallService(MS_LANGPACK_GETCODEPAGE,0,0):CP_ACP; - /* without WC_COMPOSITECHECK some characters might get out strange (see MS blog) */ - cch=WideCharToMultiByte(codepage,flags=WC_COMPOSITECHECK,pszUnicode,-1,NULL,0,NULL,NULL); - if (!cch) cch=WideCharToMultiByte(codepage,flags=0,pszUnicode,-1,NULL,0,NULL,NULL); - if (!cch) return NULL; - - psz=(char*)mir_alloc(cch); - if(psz!=NULL && !WideCharToMultiByte(codepage,flags,pszUnicode,-1,psz,cch,NULL,NULL)) { - mir_free(psz); - return NULL; - } - return psz; -} - -// mir_free() the return value -TCHAR* s2t(const void *pszStr,DWORD fUnicode,BOOL fMirCp) -{ - - if(fUnicode) return mir_wstrdup((WCHAR*)pszStr); - return a2u((char*)pszStr,fMirCp); - -} - -// mir_free() the return value -void* t2s(const TCHAR *pszStr,DWORD fUnicode,BOOL fMirCp) -{ - - if (!fUnicode) return (void*)u2a(pszStr,fMirCp); - return (void*)mir_wstrdup(pszStr); - -} - -/************************* Database *******************************/ - -struct EnumPrefixSettingsParams { - char **settings; - int nSettingsCount; - const char *pszPrefix; - int nPrefixLen; -}; - -static int EnumPrefixSettingsProc(const char *pszSetting,LPARAM lParam) -{ - struct EnumPrefixSettingsParams *param=(struct EnumPrefixSettingsParams*)lParam; - if (!strncmp(pszSetting,param->pszPrefix,param->nPrefixLen)) { - char **buf; - /* resize storage array */ - buf = (char**)mir_realloc(param->settings,(param->nSettingsCount+1)*sizeof(char*)); - if(buf!=NULL) { - param->settings=buf; - buf[param->nSettingsCount]=mir_strdup(pszSetting); - if(buf[param->nSettingsCount]!=NULL) ++param->nSettingsCount; - } - } - return 0; -} - -// mir_free() the returned pSettings after use -BOOL EnumDbPrefixSettings(const char *pszModule,const char *pszSettingPrefix,char ***pSettings,int *pnSettingsCount) -{ - DBCONTACTENUMSETTINGS dbces; - struct EnumPrefixSettingsParams param; - dbces.szModule=pszModule; - dbces.pfnEnumProc=EnumPrefixSettingsProc; - dbces.lParam=(LPARAM)¶m; - param.settings=NULL; - param.nSettingsCount=0; - param.pszPrefix=pszSettingPrefix; - param.nPrefixLen=lstrlenA(pszSettingPrefix); - CallService(MS_DB_CONTACT_ENUMSETTINGS,0,(LPARAM)&dbces); - *pnSettingsCount=param.nSettingsCount; - *pSettings=param.settings; - return param.nSettingsCount!=0; -} - -/************************* Error Output ***************************/ - -static void MessageBoxIndirectFree(void *param) -{ - MSGBOXPARAMSA *mbp = (MSGBOXPARAMSA*)param; - MessageBoxIndirectA(mbp); - mir_free((char*)mbp->lpszCaption); /* does NULL check */ - mir_free((char*)mbp->lpszText); /* does NULL check */ - mir_free(mbp); -} - -void ShowInfoMessage(BYTE flags,const char *pszTitle,const char *pszTextFmt,...) -{ - char szText[256]; /* max for systray */ - MSGBOXPARAMSA *mbp; - - va_list va; - va_start(va,pszTextFmt); - mir_vsnprintf(szText,SIZEOF(szText),pszTextFmt,va); - va_end(va); - - if(ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) { - MIRANDASYSTRAYNOTIFY msn; - msn.cbSize=sizeof(msn); - msn.szProto=NULL; - msn.szInfoTitle=(char*)pszTitle; - msn.szInfo=(char*)szText; - msn.uTimeout=30000; /* max timeout */ - msn.dwInfoFlags=flags; - if (!CallServiceSync(MS_CLIST_SYSTRAY_NOTIFY,0,(LPARAM)&msn)) - return; /* success */ - } - - mbp=(MSGBOXPARAMSA*)mir_calloc(sizeof(*mbp)); - if(mbp==NULL) return; - mbp->cbSize=sizeof(*mbp); - mbp->lpszCaption=mir_strdup(pszTitle); - mbp->lpszText=mir_strdup(szText); - mbp->dwStyle=MB_OK|MB_SETFOREGROUND|MB_TASKMODAL; - mbp->dwLanguageId=LANGIDFROMLCID((LCID)CallService(MS_LANGPACK_GETLOCALE,0,0)); - switch(flags&NIIF_ICON_MASK) { - case NIIF_INFO: mbp->dwStyle|=MB_ICONINFORMATION; break; - case NIIF_WARNING: mbp->dwStyle|=MB_ICONWARNING; break; - case NIIF_ERROR: mbp->dwStyle|=MB_ICONERROR; - } - mir_forkthread(MessageBoxIndirectFree, mbp); -} - -// LocalFree() the return value -char* GetWinErrorDescription(DWORD dwLastError) -{ - char *buf=NULL; - DWORD flags=FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM; - if (!FormatMessageA(flags,NULL,dwLastError,LANGIDFROMLCID((LCID)CallService(MS_LANGPACK_GETLOCALE,0,0)),(char*)&buf,0,NULL)) - if(GetLastError()==ERROR_RESOURCE_LANG_NOT_FOUND) - FormatMessageA(flags,NULL,dwLastError,0,(char*)&buf,0,NULL); - return buf; -} diff --git a/plugins/AssocMgr/utils.h b/plugins/AssocMgr/utils.h deleted file mode 100644 index f65a29ebec..0000000000 --- a/plugins/AssocMgr/utils.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - -'File Association Manager'-Plugin for Miranda IM - -Copyright (C) 2005-2007 H. Herkenrath - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program (AssocMgr-License.txt); if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -DWORD WINAPI GetModuleFileNameWorkaround(HMODULE hModule,TCHAR *pszFileName,DWORD nSize); - -/* String Conv */ -WCHAR* a2u(const char *pszAnsi,BOOL fMirCp); -char* u2a(const WCHAR *pszUnicode,BOOL fMirCp); -TCHAR* s2t(const void *pszStr,DWORD fUnicode,BOOL fMirCp); -void* t2s(const TCHAR *pszStr,DWORD fUnicode,BOOL fMirCp); - - #define t2a(s) u2a(s,FALSE) - #define a2t(s) a2u(s,FALSE) - - -/* Database */ -BOOL EnumDbPrefixSettings(const char *pszModule,const char *pszSettingPrefix,char ***pSettings,int *pnSettingsCount); - -/* Error Output */ -void ShowInfoMessage(BYTE flags,const char *pszTitle,const char *pszTextFmt,...); -char* GetWinErrorDescription(DWORD dwLastError); diff --git a/plugins/AssocMgr/version.h b/plugins/AssocMgr/version.h deleted file mode 100644 index 9d68defbef..0000000000 --- a/plugins/AssocMgr/version.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - -'File Association Manager'-Plugin for Miranda IM - -Copyright (C) 2005-2007 H. Herkenrath - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program (AssocMgr-License.txt); if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#define __MAJOR_VERSION 0 -#define __MINOR_VERSION 1 -#define __RELEASE_NUM 1 -#define __BUILD_NUM 0 - -#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM -#define __FILEVERSION_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM - -#define __STRINGIFY_IMPL(x) #x -#define __STRINGIFY(x) __STRINGIFY_IMPL(x) -#define __VERSION_STRING __STRINGIFY(__FILEVERSION_DOTS) - -#define __PLUGIN_NAME "File Association Manager" -#define __INTERNAL_NAME "AssocMgr" -#define __FILENAME "AssocMgr.dll" -#define __DESCRIPTION "Handles file type associations and URLs like aim, ymsgr, xmpp, wpmsg, gg, tlen." -#define __AUTHOR "H. Herkenrath" -#define __AUTHOREMAIL "hrathh@users.sourceforge.net" -#define __AUTHORWEB "http://addons.miranda-im.org/details.php?action=viewfile&id=3457" -#define __COPYRIGHT "© 2005-2007 H. Herkenrath" diff --git a/plugins/AssocMgr/version.rc b/plugins/AssocMgr/version.rc deleted file mode 100644 index b052561f31..0000000000 --- a/plugins/AssocMgr/version.rc +++ /dev/null @@ -1,36 +0,0 @@ -#include "version.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION __FILEVERSION_STRING - PRODUCTVERSION __FILEVERSION_STRING - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x0L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000004b0" - BEGIN - VALUE "FileDescription", __DESCRIPTION - VALUE "InternalName", __PLUGIN_NAME - VALUE "LegalCopyright", __COPYRIGHT - VALUE "OriginalFilename", __FILENAME - VALUE "ProductName", __PLUGIN_NAME - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0, 1200 - END -END -- cgit v1.2.3