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/AssocMgr/reg.cpp | 1298 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1298 insertions(+) create mode 100644 plugins/AssocMgr/reg.cpp (limited to 'plugins/AssocMgr/reg.cpp') diff --git a/plugins/AssocMgr/reg.cpp b/plugins/AssocMgr/reg.cpp new file mode 100644 index 0000000000..6d10421493 --- /dev/null +++ b/plugins/AssocMgr/reg.cpp @@ -0,0 +1,1298 @@ +/* + +'File Association Manager'-Plugin for Miranda IM + +Copyright (C) 2005-2007 H. Herkenrath + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program (AssocMgr-License.txt); if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "common.h" + +#ifdef _DEBUG +/* Debug: Ensure all registry calls do succeed and have valid parameters. + * Shows a details message box otherwise. */ +static __inline LONG regchk(LONG res,const char *pszFunc,const void *pszInfo,BOOL fInfoUnicode,const char *pszFile,unsigned int nLine) +{ + if(res!=ERROR_SUCCESS && res!=ERROR_FILE_NOT_FOUND && res!=ERROR_NO_MORE_ITEMS) { + TCHAR szMsg[1024],*pszInfo2; + char *pszErr; + pszErr=GetWinErrorDescription(res); + pszInfo2=s2t(pszInfo,fInfoUnicode,FALSE); /* does NULL check */ + mir_sntprintf(szMsg,SIZEOF(szMsg),_T("Access failed:\n%.64hs(%.128s)\n%.250hs(%u)\n%.256hs (%u)"),pszFunc,pszInfo2,pszFile,nLine,pszErr,res); + MessageBox(NULL,szMsg,_T("Registry Warning"),MB_OK|MB_ICONINFORMATION|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL); + if(pszErr!=NULL) LocalFree(pszErr); + mir_free(pszInfo2); /* does NULL check */ + } + return res; +} +#undef RegCloseKey +#define RegCloseKey(hKey) \ + regchk(RegCloseKey(hKey),"RegCloseKey",NULL,FALSE,__FILE__,__LINE__) +#undef RegOpenKeyExA +#define RegOpenKeyExA(hKey,szSubkey,opt,rights,phKey) \ + regchk(RegOpenKeyExA(hKey,szSubkey,opt,rights,phKey),"RegOpenKeyExA",szSubkey,FALSE,__FILE__,__LINE__) +#undef RegCreateKeyExA +#define RegCreateKeyExA(hKey,szSubkey,x,y,opt,rights,sec,phKey,pDisp) \ + regchk(RegCreateKeyExA(hKey,szSubkey,x,y,opt,rights,sec,phKey,pDisp),"RegCreateKeyExA",szSubkey,FALSE,__FILE__,__LINE__) +#undef RegDeleteKeyA +#define RegDeleteKeyA(hKey,szName) \ + regchk(RegDeleteKeyA(hKey,szName),"RegDeleteKeyA",szName,FALSE,__FILE__,__LINE__) +#undef RegSetValueExA +#define RegSetValueExA(hSubKey,szName,x,type,pVal,size) \ + regchk(RegSetValueExA(hSubKey,szName,x,type,pVal,size),"RegSetValueExA",szName,FALSE,__FILE__,__LINE__) +#undef RegQueryValueExA +#define RegQueryValueExA(hKey,szName,x,pType,pVal,pSize) \ + regchk(RegQueryValueExA(hKey,szName,x,pType,pVal,pSize),"RegQueryValueExA",szName,FALSE,__FILE__,__LINE__) +#undef RegQueryInfoKeyA +#define RegQueryInfoKeyA(hKey,x,y,z,pnKeys,pnKeyLen,a,pnVals,pnNames,pnValLen,sec,pTime) \ + regchk(RegQueryInfoKeyA(hKey,x,y,z,pnKeys,pnKeyLen,a,pnVals,pnNames,pnValLen,sec,pTime),"RegQueryInfoKeyA",NULL,FALSE,__FILE__,__LINE__) +#undef RegEnumKeyExA +#define RegEnumKeyExA(hKey,idx,pName,pnName,x,y,z,pTime) \ + regchk(RegEnumKeyExA(hKey,idx,pName,pnName,x,y,z,pTime),"RegEnumKeyExA",NULL,FALSE,__FILE__,__LINE__) +#undef RegDeleteValueA +#define RegDeleteValueA(hKey,szName) \ + regchk(RegDeleteValueA(hKey,szName),"RegDeleteValueA",szName,FALSE,__FILE__,__LINE__) +#undef RegOpenKeyExW +#define RegOpenKeyExW(hKey,szSubkey,x,sam,phKey) \ + regchk(RegOpenKeyExW(hKey,szSubkey,x,sam,phKey),"RegOpenKeyExW",szSubkey,TRUE,__FILE__,__LINE__) +#undef RegCreateKeyExW +#define RegCreateKeyExW(hKey,szSubkey,x,y,z,rights,p,phKey,q) \ + regchk(RegCreateKeyExW(hKey,szSubkey,x,y,z,rights,p,phKey,q),"RegCreateKeyExW",szSubkey,TRUE,__FILE__,__LINE__) +#undef RegDeleteKeyW +#define RegDeleteKeyW(hKey,szName) \ + regchk(RegDeleteKeyW(hKey,szName),"RegDeleteKeyW",szName,TRUE,__FILE__,__LINE__) +#undef RegSetValueExW +#define RegSetValueExW(hSubKey,szName,x,type,pVal,size) \ + regchk(RegSetValueExW(hSubKey,szName,x,type,pVal,size),"RegSetValueExW",szName,TRUE,__FILE__,__LINE__) +#undef RegQueryValueExW +#define RegQueryValueExW(hKey,szName,x,pType,pVal,pSize) \ + regchk(RegQueryValueExW(hKey,szName,x,pType,pVal,pSize),"RegQueryValueExW",szName,TRUE,__FILE__,__LINE__) +#undef RegQueryInfoKeyW +#define RegQueryInfoKeyW(hKey,x,y,z,pnKeys,pnKeyLen,a,pnVals,pnNames,pnValLen,sec,pTime) \ + regchk(RegQueryInfoKeyW(hKey,x,y,z,pnKeys,pnKeyLen,a,pnVals,pnNames,pnValLen,sec,pTime),"RegQueryInfoKeyW",NULL,TRUE,__FILE__,__LINE__) +#undef RegEnumKeyExW +#define RegEnumKeyExW(hKey,idx,pName,pnName,x,y,z,pTime) \ + regchk(RegEnumKeyExW(hKey,idx,pName,pnName,x,y,z,pTime),"RegEnumKeyExW",NULL,TRUE,__FILE__,__LINE__) +#undef RegDeleteValueW +#define RegDeleteValueW(hKey,szName) \ + regchk(RegDeleteValueW(hKey,szName),"RegDeleteValueW",szName,TRUE,__FILE__,__LINE__) +#endif // _DEBUG + +/************************* Strings ********************************/ + +// mir_free() the return value +char *MakeFileClassName(const char *pszFileExt) +{ + char *pszClass; + pszClass=(char*)mir_alloc((lstrlenA(pszFileExt)+12)*sizeof(TCHAR)); + if(pszClass!=NULL) + /* using correctly formated PROGID */ + wsprintfA(pszClass,"miranda%sfile",pszFileExt); /* includes dot, buffer safe */ + return pszClass; +} + +// mir_free() the return value +char *MakeUrlClassName(const char *pszUrl) +{ + char *pszClass; + pszClass=mir_strdup(pszUrl); + if(pszClass!=NULL) + /* remove trailing : */ + pszClass[lstrlenA(pszClass)-1]=0; + return pszClass; +} + +static BOOL IsFileClassName(char *pszClassName, char **ppszFileExt) +{ + *ppszFileExt=strchr(pszClassName,'.'); + return *ppszFileExt!=NULL; +} + +// mir_free() the return value +TCHAR *MakeRunCommand(BOOL fMirExe,BOOL fFixedDbProfile) +{ + extern HINSTANCE hInst; + TCHAR szExe[MAX_PATH],*pszFmt,*pszRunCmd=NULL; + char szDbFile[MAX_PATH]; + int cch; + if (!fFixedDbProfile || !CallService(MS_DB_GETPROFILENAME,SIZEOF(szDbFile),(LPARAM)szDbFile)) + if(GetModuleFileNameWorkaround(fMirExe?NULL:hInst,szExe,SIZEOF(szExe))) { + /* db file */ + if (!fFixedDbProfile) + lstrcpyA(szDbFile,"%1"); /* buffer safe */ + /* size */ + cch=lstrlen(szExe)+lstrlenA(szDbFile); + if(fMirExe) { + /* run command for miranda32.exe */ + cch+=7; + pszFmt=_T("\"%s\" \"%hs\""); + } else { + DWORD len; + /* run command for rundll32.exe calling WaitForDDE */ + cch+=28; + pszFmt=_T("rundll32.exe %s,WaitForDDE \"%hs\""); + /* ensure the command line is not too long */ + GetShortPathName(szExe,szExe,SIZEOF(szExe)); + /* surround by quotes if failed */ + len=lstrlen(szExe); + if(_tcschr(szExe,_T(' '))!=NULL && (len+2)sizeof(TCHAR)) { + pszVal=(TCHAR*)mir_alloc(dwSize+sizeof(TCHAR)); + if(pszVal!=NULL) { + /* get value */ + if (!RegQueryValueEx(hKey,pszValName,NULL,&dwType,(BYTE*)pszVal,&dwSize)) { + pszVal[dwSize/sizeof(TCHAR)]=0; + if(dwType==REG_EXPAND_SZ) { + dwSize=MAX_PATH; + pszVal2=(TCHAR*)mir_alloc(dwSize*sizeof(TCHAR)); + if(ExpandEnvironmentStrings(pszVal,pszVal2,dwSize)) { + mir_free(pszVal); + return pszVal2; + } + mir_free(pszVal2); + } else if(dwType==REG_SZ) + return pszVal; + } + mir_free(pszVal); + } + } + return NULL; +} + +// hKey must have been opened with KEY_QUERY_VALUE access right +static BOOL IsRegStrValue(HKEY hKey,const TCHAR *pszValName,const TCHAR *pszCmpVal) +{ + BOOL fSame=FALSE; + TCHAR *pszVal; + pszVal=GetRegStrValue(hKey,pszValName); + if(pszVal!=NULL) { + fSame=!lstrcmp(pszVal,pszCmpVal); + mir_free(pszVal); + } + return fSame; +} + +// hKey must have been opened with KEY_QUERY_VALUE access right +static BOOL IsRegStrValueA(HKEY hKey,const TCHAR *pszValName,const char *pszCmpVal) +{ + BOOL fSame=FALSE; + TCHAR *pszVal; + char *pszValA; + pszVal=GetRegStrValue(hKey,pszValName); + if(pszVal!=NULL) { + pszValA=t2a(pszVal); + if(pszValA!=NULL) + fSame=!lstrcmpA(pszValA,pszCmpVal); + mir_free(pszValA); /* does NULL check */ + mir_free(pszVal); + } + return fSame; +} + +/************************* Backup to DB ***************************/ + +#define REGF_ANSI 0x80000000 /* this bit is set in dwType for ANSI registry data */ + +// pData must always be Unicode data, registry supports Unicode even on Win95 +static void WriteDbBackupData(const char *pszSetting,DWORD dwType,BYTE *pData,DWORD cbData) +{ + DBCONTACTWRITESETTING dbcws; + dbcws.szModule="AssocMgr"; + dbcws.szSetting=pszSetting; + dbcws.value.type=DBVT_BLOB; + dbcws.value.cpbVal=(WORD)(cbData+sizeof(DWORD)); + dbcws.value.pbVal=(BYTE*)mir_alloc(cbData+sizeof(DWORD)); + if(dbcws.value.pbVal==NULL) return; + *(DWORD*)dbcws.value.pbVal=dwType; + CopyMemory(dbcws.value.pbVal+sizeof(DWORD),pData,cbData); + CallService(MS_DB_CONTACT_WRITESETTING,0,(LPARAM)&dbcws); + mir_free(dbcws.value.pbVal); +} + +// mir_free() the value returned in ppData +static BOOL ReadDbBackupData(const char *pszSetting,DWORD *pdwType,BYTE **ppData,DWORD *pcbData) +{ + DBCONTACTGETSETTING dbcgs; + DBVARIANT dbv; + dbcgs.szModule="AssocMgr"; + dbcgs.szSetting=pszSetting; + dbcgs.pValue=&dbv; + if (!CallService(MS_DB_CONTACT_GETSETTING,0,(LPARAM)&dbcgs)) { + if(dbv.type==DBVT_BLOB && dbv.cpbVal>=sizeof(DWORD)) { + *pdwType=*(DWORD*)dbv.pbVal; + *ppData=dbv.pbVal; + *pcbData=dbv.cpbVal-sizeof(DWORD); + MoveMemory(*ppData,*ppData+sizeof(DWORD),*pcbData); + return TRUE; + } + CallService(MS_DB_CONTACT_FREEVARIANT,0,(LPARAM)&dbv); + } + return FALSE; +} + +struct BackupRegTreeParam { + char **ppszDbPrefix; + DWORD *pdwDbPrefixSize; + int level; +}; + +static void BackupRegTree_Worker(HKEY hKey,const char *pszSubKey,struct BackupRegTreeParam *param) +{ + LONG res; + DWORD nMaxSubKeyLen,nMaxValNameLen,nMaxValSize; + DWORD index,cchName,dwType,cbData; + BYTE *pData; + char *pszName; + register TCHAR *ptszName; + DWORD nDbPrefixLen; + if ((res=RegOpenKeyExA(hKey,pszSubKey,0,KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS,&hKey))==ERROR_SUCCESS) { + if ((res=RegQueryInfoKey(hKey,NULL,NULL,NULL,NULL,&nMaxSubKeyLen,NULL,NULL,&nMaxValNameLen,&nMaxValSize,NULL,NULL))==ERROR_SUCCESS) { + if(nMaxSubKeyLen>nMaxValNameLen) nMaxValNameLen=nMaxSubKeyLen; + /* prepare buffer */ + nDbPrefixLen=(DWORD)lstrlenA(*param->ppszDbPrefix)+lstrlenA(pszSubKey)+1; + cchName=nDbPrefixLen+nMaxValNameLen+3; + if(cchName>*param->pdwDbPrefixSize) { + pszName=(char*)mir_realloc(*param->ppszDbPrefix,cchName); + if(pszName==NULL) return; + *param->ppszDbPrefix=pszName; + *param->pdwDbPrefixSize=cchName; + } + lstrcatA(lstrcatA(*param->ppszDbPrefix,pszSubKey),"\\"); /* buffer safe */ + /* enum values */ + pszName=(char*)mir_alloc(nMaxValNameLen+1); + if(nMaxValSize==0) nMaxValSize=1; + pData=(BYTE*)mir_alloc(nMaxValSize); + if(pszName!=NULL && pData!=NULL) { + index=0; + while(!res) { + cchName=nMaxValNameLen+1; + cbData=nMaxValSize; + if ((res=RegEnumValueA(hKey,index++,pszName,&cchName,NULL,NULL,NULL,NULL))==ERROR_SUCCESS) { + (*param->ppszDbPrefix)[nDbPrefixLen]=0; + lstrcatA(*param->ppszDbPrefix,pszName); /* buffer safe */ + ptszName=a2t(pszName); + if(ptszName!=NULL) { + if (!RegQueryValueEx(hKey,ptszName,NULL,&dwType,pData,&cbData)) { + #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