From e70263fa09e2b16cd0ab8d45c6cf16e5b9788944 Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Wed, 6 Jun 2012 19:46:34 +0000 Subject: fixed plugin info plusified AssocMgr plugin git-svn-id: http://svn.miranda-ng.org/main/trunk@334 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Alarms/Version.h | 20 + plugins/Alarms/Version.rc | 38 + plugins/Alarms/alarms.cpp | 16 +- plugins/Alarms/alarms_10.vcxproj | 2 + plugins/Alarms/alarms_10.vcxproj.filters | 6 + plugins/Alarms/common.h | 1 + plugins/AssocMgr/assoclist.c | 1102 ------------------ plugins/AssocMgr/assoclist.cpp | 1102 ++++++++++++++++++ plugins/AssocMgr/assoclist.h | 4 +- plugins/AssocMgr/assocmgr.vcxproj | 13 +- plugins/AssocMgr/assocmgr.vcxproj.filters | 19 +- plugins/AssocMgr/common.h | 9 +- plugins/AssocMgr/dde.c | 293 ----- plugins/AssocMgr/dde.cpp | 297 +++++ plugins/AssocMgr/main.c | 154 --- plugins/AssocMgr/main.cpp | 129 +++ plugins/AssocMgr/reg.c | 1298 ---------------------- plugins/AssocMgr/reg.cpp | 1298 ++++++++++++++++++++++ plugins/AssocMgr/test.c | 869 --------------- plugins/AssocMgr/test.cpp | 869 +++++++++++++++ plugins/AssocMgr/utils.c | 199 ---- plugins/AssocMgr/utils.cpp | 201 ++++ plugins/AssocMgr/version.h | 39 +- plugins/AssocMgr/version.rc | 35 +- plugins/FreeImage/Miranda/version.h | 2 +- plugins/StatusPlugins/AdvancedAutoAway/main.cpp | 6 +- plugins/StatusPlugins/AdvancedAutoAway/version.h | 18 +- plugins/StatusPlugins/version.rc | 3 +- 28 files changed, 4025 insertions(+), 4017 deletions(-) create mode 100644 plugins/Alarms/Version.h create mode 100644 plugins/Alarms/Version.rc delete mode 100644 plugins/AssocMgr/assoclist.c create mode 100644 plugins/AssocMgr/assoclist.cpp delete mode 100644 plugins/AssocMgr/dde.c create mode 100644 plugins/AssocMgr/dde.cpp delete mode 100644 plugins/AssocMgr/main.c create mode 100644 plugins/AssocMgr/main.cpp delete mode 100644 plugins/AssocMgr/reg.c create mode 100644 plugins/AssocMgr/reg.cpp delete mode 100644 plugins/AssocMgr/test.c create mode 100644 plugins/AssocMgr/test.cpp delete mode 100644 plugins/AssocMgr/utils.c create mode 100644 plugins/AssocMgr/utils.cpp diff --git a/plugins/Alarms/Version.h b/plugins/Alarms/Version.h new file mode 100644 index 0000000000..45934bc715 --- /dev/null +++ b/plugins/Alarms/Version.h @@ -0,0 +1,20 @@ +#define __MAJOR_VERSION 0 +#define __MINOR_VERSION 4 +#define __RELEASE_NUM 0 +#define __BUILD_NUM 5 + +#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 "Alarms" +#define __INTERNAL_NAME "Alarms" +#define __FILENAME "Alarms.dll" +#define __DESCRIPTION "Set once-off, daily, weekly and weekday alarms." +#define __AUTHOR "Scott Ellis" +#define __AUTHOREMAIL "mail@scottellis.com.au" +#define __AUTHORWEB "http://www.scottellis.com.au" +#define __COPYRIGHT "© 2005 Scott Ellis" diff --git a/plugins/Alarms/Version.rc b/plugins/Alarms/Version.rc new file mode 100644 index 0000000000..e637f0cb33 --- /dev/null +++ b/plugins/Alarms/Version.rc @@ -0,0 +1,38 @@ +// Microsoft Visual C++ generated resource script. +// +#include "afxres.h" +#include "version.h" + +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#endif //_WIN32 + +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/Alarms/alarms.cpp b/plugins/Alarms/alarms.cpp index 626b917178..79cea6c27f 100644 --- a/plugins/Alarms/alarms.cpp +++ b/plugins/Alarms/alarms.cpp @@ -33,13 +33,13 @@ WNDPROC old_clist_wndproc; PLUGININFOEX pluginInfo={ sizeof(PLUGININFOEX), - "Alarms", - PLUGIN_MAKE_VERSION(0,4,0,5), - "Set once-off, daily, weekly and weekday alarms.", - "Scott Ellis", - "mail@scottellis.com.au", - "© 2005 Scott Ellis", - "http://www.scottellis.com.au", + __PLUGIN_NAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), + __DESCRIPTION, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, UNICODE_AWARE, //not transient 0, //doesn't replace anything built-in { 0x4dd7762b, 0xd612, 0x4f84, { 0xaa, 0x86, 0x6, 0x8f, 0x17, 0x85, 0x9b, 0x6d } } // {4DD7762B-D612-4f84-AA86-068F17859B6D} @@ -62,8 +62,6 @@ extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void) return interfaces; } - - static int CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { diff --git a/plugins/Alarms/alarms_10.vcxproj b/plugins/Alarms/alarms_10.vcxproj index 0e4120925a..64a896c41e 100644 --- a/plugins/Alarms/alarms_10.vcxproj +++ b/plugins/Alarms/alarms_10.vcxproj @@ -204,6 +204,7 @@ + @@ -214,6 +215,7 @@ + diff --git a/plugins/Alarms/alarms_10.vcxproj.filters b/plugins/Alarms/alarms_10.vcxproj.filters index 67fab38b2d..113441daf8 100644 --- a/plugins/Alarms/alarms_10.vcxproj.filters +++ b/plugins/Alarms/alarms_10.vcxproj.filters @@ -71,6 +71,9 @@ Header Files + + Header Files + @@ -93,5 +96,8 @@ Resource Files + + Resource Files + \ No newline at end of file diff --git a/plugins/Alarms/common.h b/plugins/Alarms/common.h index 0186d87228..d675ab1bf1 100644 --- a/plugins/Alarms/common.h +++ b/plugins/Alarms/common.h @@ -15,6 +15,7 @@ #include #include "resource.h" +#include "version.h" #include #include diff --git a/plugins/AssocMgr/assoclist.c b/plugins/AssocMgr/assoclist.c deleted file mode 100644 index 26a72a43da..0000000000 --- a/plugins/AssocMgr/assoclist.c +++ /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 = _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); -#if defined(_UNICODE) - ListView_SetUnicodeFormat(hwndList, TRUE); -#endif - 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; -#if defined(_UNICODE) - case WM_NOTIFYFORMAT: - SetWindowLong(hwndDlg, DWLP_MSGRESULT, NFR_UNICODE); - return TRUE; -#endif - 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) { - SetWindowLong(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); - SetWindowLong(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.ptszGroup = _T("Services"); /* autotranslated */ - odp.ptszTitle = _T("Associations"); /* autotranslated */ - odp.flags = ODPF_BOLDGROUPS|ODPF_EXPERTONLY|ODPF_TCHAR; - odp.pfnDlgProc = AssocListOptDlgProc; - CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&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.cpp b/plugins/AssocMgr/assoclist.cpp new file mode 100644 index 0000000000..524bf29152 --- /dev/null +++ b/plugins/AssocMgr/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(TCHAR *pszFileName) +{ + char *pszClassName, *pszFileExt; + TCHAR *p; + INT_PTR res = CALLSERVICE_NOTFOUND; + + /* find extension */ + p = _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(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); +#if defined(_UNICODE) + ListView_SetUnicodeFormat(hwndList, TRUE); +#endif + 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; +#if defined(_UNICODE) + case WM_NOTIFYFORMAT: + SetWindowLong(hwndDlg, DWLP_MSGRESULT, NFR_UNICODE); + return TRUE; +#endif + 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) { + SetWindowLong(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); + SetWindowLong(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.ptszGroup = _T("Services"); /* autotranslated */ + odp.ptszTitle = _T("Associations"); /* autotranslated */ + odp.flags = ODPF_BOLDGROUPS|ODPF_EXPERTONLY|ODPF_TCHAR; + odp.pfnDlgProc = AssocListOptDlgProc; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&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 index 5e8806b828..44d90013e3 100644 --- a/plugins/AssocMgr/assoclist.h +++ b/plugins/AssocMgr/assoclist.h @@ -26,8 +26,8 @@ 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); +INT_PTR InvokeFileHandler(TCHAR *pszFileName); +INT_PTR InvokeUrlHandler(TCHAR *pszUrl); /* Misc */ void InitAssocList(void); void UninitAssocList(void); diff --git a/plugins/AssocMgr/assocmgr.vcxproj b/plugins/AssocMgr/assocmgr.vcxproj index 3c76717f49..44462d6eff 100644 --- a/plugins/AssocMgr/assocmgr.vcxproj +++ b/plugins/AssocMgr/assocmgr.vcxproj @@ -182,12 +182,12 @@ - - - - - - + + + + + + @@ -211,6 +211,7 @@ + diff --git a/plugins/AssocMgr/assocmgr.vcxproj.filters b/plugins/AssocMgr/assocmgr.vcxproj.filters index cfdb339f8c..2053a987d1 100644 --- a/plugins/AssocMgr/assocmgr.vcxproj.filters +++ b/plugins/AssocMgr/assocmgr.vcxproj.filters @@ -17,28 +17,24 @@ {6f8e30e0-bc03-46e7-b039-e0fbd019afb2} txt - - {cc674aae-3e65-4f1c-959f-c95acfe7111a} - *.h - - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files @@ -72,6 +68,9 @@ Resource Files + + Resource Files + diff --git a/plugins/AssocMgr/common.h b/plugins/AssocMgr/common.h index 6f5592f524..b4099847bf 100644 --- a/plugins/AssocMgr/common.h +++ b/plugins/AssocMgr/common.h @@ -19,22 +19,19 @@ along with this program (AssocMgr-License.txt); if not, write to the Free Softwa Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#define MIRANDA_VER 0x0A00 #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 diff --git a/plugins/AssocMgr/dde.c b/plugins/AssocMgr/dde.c deleted file mode 100644 index 0804be855c..0000000000 --- a/plugins/AssocMgr/dde.c +++ /dev/null @@ -1,293 +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(TCHAR *pszFilePath) -{ - /* 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(TCHAR *pszUrl) -{ - /* 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)&hCommand)) { - #if defined(_UNICODE) - /* ANSI execute command can't happen for shell */ - if(IsWindowUnicode((HWND)wParam)) { - #endif - pszCommand=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); - } - #if defined(_UNICODE) - } - #endif - 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)&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)) { - #ifdef _UNICODE - WriteDbBackupData(*param->ppszDbPrefix,dwType,pData,cbData); - #else - if (!(dwType®F_ANSI)) /* sanity check, never happens */ - WriteDbBackupData(*param->ppszDbPrefix,dwType®F_ANSI,pData,cbData); - #endif - } - 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;isizeof(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)) { + #ifdef _UNICODE + WriteDbBackupData(*param->ppszDbPrefix,dwType,pData,cbData); + #else + if (!(dwType®F_ANSI)) /* sanity check, never happens */ + WriteDbBackupData(*param->ppszDbPrefix,dwType®F_ANSI,pData,cbData); + #endif + } + 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/test.cpp b/plugins/AssocMgr/test.cpp new file mode 100644 index 0000000000..73112af5a5 --- /dev/null +++ b/plugins/AssocMgr/test.cpp @@ -0,0 +1,869 @@ +/* + +'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/utils.c b/plugins/AssocMgr/utils.c deleted file mode 100644 index 89e0867a59..0000000000 --- a/plugins/AssocMgr/utils.c +++ /dev/null @@ -1,199 +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 defined(_UNICODE) - if(fUnicode) return mir_wstrdup((WCHAR*)pszStr); - return a2u((char*)pszStr,fMirCp); -#else - if(fUnicode) return u2a((WCHAR*)pszStr,fMirCp); - return mir_strdup((char*)pszStr); -#endif -} - -// mir_free() the return value -void* t2s(const TCHAR *pszStr,DWORD fUnicode,BOOL fMirCp) -{ -#if defined(_UNICODE) - if (!fUnicode) return (void*)u2a(pszStr,fMirCp); - return (void*)mir_wstrdup(pszStr); -#else - if(fUnicode) return (void*)a2u(pszStr,fMirCp); - return (void*)mir_strdup(pszStr); -#endif -} - -/************************* 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=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(MSGBOXPARAMSA *mbp) -{ - 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.cpp b/plugins/AssocMgr/utils.cpp new file mode 100644 index 0000000000..cfc79ba50e --- /dev/null +++ b/plugins/AssocMgr/utils.cpp @@ -0,0 +1,201 @@ +/* + +'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 defined(_UNICODE) + if(fUnicode) return mir_wstrdup((WCHAR*)pszStr); + return a2u((char*)pszStr,fMirCp); +#else + if(fUnicode) return u2a((WCHAR*)pszStr,fMirCp); + return mir_strdup((char*)pszStr); +#endif +} + +// mir_free() the return value +void* t2s(const TCHAR *pszStr,DWORD fUnicode,BOOL fMirCp) +{ +#if defined(_UNICODE) + if (!fUnicode) return (void*)u2a(pszStr,fMirCp); + return (void*)mir_wstrdup(pszStr); +#else + if(fUnicode) return (void*)a2u(pszStr,fMirCp); + return (void*)mir_strdup(pszStr); +#endif +} + +/************************* 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); + mir_free(param); +} + +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/version.h b/plugins/AssocMgr/version.h index ce9485a55f..9d68defbef 100644 --- a/plugins/AssocMgr/version.h +++ b/plugins/AssocMgr/version.h @@ -19,22 +19,23 @@ along with this program (AssocMgr-License.txt); if not, write to the Free Softwa Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define NEEDED_MIRANDA_VERSION PLUGIN_MAKE_VERSION(0,6,0,0) -#define NEEDED_MIRANDA_VERSION_STR "0.6" -#define PLUGIN_VERSION PLUGIN_MAKE_VERSION(0,1,1,0) -#define FILE_VERSION 0,1,1,0 - -#if defined(_DEBUG) - #define FILE_VERSION_STR "0.1.1.1 alpha" -#else - #define FILE_VERSION_STR "0.1.1.0" -#endif - -#define PLUGIN_EMAIL "hrathh users.sourceforge.net" -#define PLUGIN_EMAIL_ATT_POS 7 /* position of the @-sign in the email adress above */ - -#if defined(_UNICODE) - #define PLUGIN_WEBSITE "http://addons.miranda-im.org/details.php?action=viewfile&id=3458" -#else - #define PLUGIN_WEBSITE "http://addons.miranda-im.org/details.php?action=viewfile&id=3457" -#endif +#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 index 4234d8d7ec..b052561f31 100644 --- a/plugins/AssocMgr/version.rc +++ b/plugins/AssocMgr/version.rc @@ -1,5 +1,3 @@ -#ifndef _MAC - #include "version.h" ///////////////////////////////////////////////////////////////////////////// @@ -8,34 +6,27 @@ // VS_VERSION_INFO VERSIONINFO - FILEVERSION FILE_VERSION - PRODUCTVERSION FILE_VERSION - FILEFLAGSMASK 0x0L + FILEVERSION __FILEVERSION_STRING + PRODUCTVERSION __FILEVERSION_STRING + FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif - FILEOS 0x40004L - FILETYPE 0x2L + FILEOS 0x4L + FILETYPE 0x0L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "000004b0" BEGIN - VALUE "Comments", "Licensed under the terms of the GNU General Public License" - VALUE "FileDescription", "File Association Manager Plugin for Miranda IM" - VALUE "FileVersion", FILE_VERSION_STR -#ifdef _UNICODE - VALUE "InternalName", "AssocMgr (Unicode)" -#else - VALUE "InternalName", "AssocMgr" -#endif - VALUE "LegalCopyright", "Copyright © 2005-2007 H. Herkenrath" - VALUE "OriginalFilename", "assocmgr.dll" - VALUE "ProductName", "File Association Manager" - VALUE "ProductVersion", FILE_VERSION_STR + VALUE "FileDescription", __DESCRIPTION + VALUE "InternalName", __PLUGIN_NAME + VALUE "LegalCopyright", __COPYRIGHT + VALUE "OriginalFilename", __FILENAME + VALUE "ProductName", __PLUGIN_NAME END END BLOCK "VarFileInfo" @@ -43,9 +34,3 @@ BEGIN VALUE "Translation", 0x0, 1200 END END - -#endif // !_MAC - - - - diff --git a/plugins/FreeImage/Miranda/version.h b/plugins/FreeImage/Miranda/version.h index 5504fc0c44..e3114530b0 100644 --- a/plugins/FreeImage/Miranda/version.h +++ b/plugins/FreeImage/Miranda/version.h @@ -3,7 +3,7 @@ #define __FILEVERSION_STRING MIRANDA_VERSION_FILEVERSION #define __VERSION_STRING MIRANDA_VERSION_STRING #define __VERSION_DWORD MIRANDA_VERSION_DWORD -#define __PLUGIN_NAME "AdvaImg" +#define __PLUGIN_NAME "Miranda Image services" #define __INTERNAL_NAME "AdvaImg" #define __FILENAME "AdvaImg.dll" #define __DESCRIPTION "Generic image services for Miranda IM." diff --git a/plugins/StatusPlugins/AdvancedAutoAway/main.cpp b/plugins/StatusPlugins/AdvancedAutoAway/main.cpp index f9d1bd04d9..2e4f5f288a 100644 --- a/plugins/StatusPlugins/AdvancedAutoAway/main.cpp +++ b/plugins/StatusPlugins/AdvancedAutoAway/main.cpp @@ -53,11 +53,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) PLUGININFOEX pluginInfoEx={ sizeof(PLUGININFOEX), - #if defined( _UNICODE ) - __PLUGIN_NAME __PLATFORM_NAME " (Unicode)", - #else - __PLUGIN_NAME, - #endif + __PLUGIN_NAME, PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), __DESC, __AUTHOR, diff --git a/plugins/StatusPlugins/AdvancedAutoAway/version.h b/plugins/StatusPlugins/AdvancedAutoAway/version.h index 9c0462460d..efca246872 100644 --- a/plugins/StatusPlugins/AdvancedAutoAway/version.h +++ b/plugins/StatusPlugins/AdvancedAutoAway/version.h @@ -10,18 +10,10 @@ #define __RELEASE_NUM 0 #define __BUILD_NUM 42 -// minimal MirandaIM version number, with which this plugin supposed to work -#define __PROD_MAJOR_VERSION 0 -#define __PROD_MINOR_VERSION 8 -#define __PROD_RELEASE_NUM 0 -#define __PROD_BUILD_NUM 0 -// if your plugin works only with Miranda core beginning from specific revision, you can include this information in Product Version resource -//#define __PROD_REV_NUM 1234 - // stuff that will be used in PluginInfo section and in Version resource #define __PLUGIN_NAME "Advanced Auto Away" #define __FILENAME "AdvancedAutoAway.dll" -#define __DESC "AdvancedAutoAway, an Auto Away module with some more options than the original." +#define __DESC "An Auto Away module with some more options than the original." #define __AUTHOR "P Boon" #define __AUTHOREMAIL "unregistered@users.sourceforge.net" #define __AUTHORWEB "http://www.miranda-im.org/" @@ -46,11 +38,3 @@ #define __VERSION_STRING __STRINGIFY(__FILEVERSION_STRING_DOTS) #endif #endif - -#define __PRODVERSION_STRING __PROD_MAJOR_VERSION,__PROD_MINOR_VERSION,__PROD_RELEASE_NUM,__PROD_BUILD_NUM -#define __PRODVERSION_STRING_DOTS __PROD_MAJOR_VERSION.__PROD_MINOR_VERSION.__PROD_RELEASE_NUM.__PROD_BUILD_NUM -#ifdef __PROD_REV_NUM -#define __PROD_VERSION_STRING __STRINGIFY(__PRODVERSION_STRING_DOTS rev. __PROD_REV_NUM) -#else -#define __PROD_VERSION_STRING __STRINGIFY(__PRODVERSION_STRING_DOTS+) -#endif diff --git a/plugins/StatusPlugins/version.rc b/plugins/StatusPlugins/version.rc index dac86f85a2..8f6f25b2da 100644 --- a/plugins/StatusPlugins/version.rc +++ b/plugins/StatusPlugins/version.rc @@ -7,7 +7,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL VS_VERSION_INFO VERSIONINFO FILEVERSION __FILEVERSION_STRING - PRODUCTVERSION __PRODVERSION_STRING + PRODUCTVERSION __FILEVERSION_STRING FILEFLAGSMASK VS_FFI_FILEFLAGSMASK #ifdef _DEBUG FILEFLAGS VS_FF_DEBUG @@ -30,7 +30,6 @@ BEGIN VALUE "OriginalFilename", __FILENAME VALUE "FileVersion", __VERSION_STRING VALUE "ProductName", "Miranda IM" - VALUE "ProductVersion", __PROD_VERSION_STRING END END BLOCK "VarFileInfo" -- cgit v1.2.3