diff options
Diffstat (limited to 'path.c')
-rw-r--r-- | path.c | 1080 |
1 files changed, 540 insertions, 540 deletions
@@ -1,541 +1,541 @@ -/*
-
-"Spam Filter"-Plugin for Miranda IM
-
-Copyright 2003-2006 Heiko 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 ("SpamFilter-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"
-
-
-// -----------------------------------------
-
-
-BOOL PPreparePathForWrite(HWND hwndDlg, const WCHAR* pszPath, BOOL bAskDirCreate, BOOL bContainsFileName)
-{
- // Using SHPathPrepareForWrite on Win2000+ (best, only if avail)
- {
- HRESULT (STDAPICALLTYPE *MySHPathPrepareForWrite)(HWND, IUnknown*, LPCTSTR, DWORD);
-
- #if defined(UNICODE)
- *(FARPROC*)&MySHPathPrepareForWrite = GetProcAddress(GetModuleHandle(_T("USER32")), "SHPathPrepareForWriteW");
- #else
- *(FARPROC*)&MySHPathPrepareForWrite = GetProcAddress(GetModuleHandle(_T("USER32")), "SHPathPrepareForWriteA");
- #endif
-
- if (MySHPathPrepareForWrite)
- {
- DWORD dwFlags = SHPPFW_NOWRITECHECK; // Not impl anyway
-
- if (bContainsFileName)
- dwFlags |= SHPPFW_IGNOREFILENAME;
-
- dwFlags |= bAskDirCreate ? SHPPFW_ASKDIRCREATE : SHPPFW_DIRCREATE;
-
- return SUCCEEDED(MySHPathPrepareForWrite(hwndDlg, NULL, (LPCTSTR)pszPath, dwFlags));
- }
- }
-
- // Emulating SHPathPrepareForWrite:
- // Using SHCreateDirectoryEx on WinME
- // And: Using emulated version of SHCreateDirectoryEx on Win95/98
- {
- WCHAR* pszDir;
- BOOL bReturn = FALSE;
-
- pszDir = mir_wstrdup(pszPath);
- if (!pszDir) return FALSE;
-
- if (bContainsFileName)
- PathRemoveFileSpec((LPWSTR)pszDir);
-
- // No dialog is emulated, instead always behave as
- // if "No" was clicked
- if (bAskDirCreate)
- return FALSE;
-
- // Create all sub directories
- {
- int (STDAPICALLTYPE *MySHCreateDirectoryEx)(HWND, LPCTSTR, SECURITY_ATTRIBUTES*);
-
- #if defined(UNICODE)
- *(FARPROC*)&MySHCreateDirectoryEx = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHELL32")), "SHCreateDirectoryExW");
- #else
- *(FARPROC*)&MySHCreateDirectoryEx = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHELL32")), "SHCreateDirectoryExA");
- #endif
-
- if (MySHCreateDirectoryEx)
- {
- int iRet = (SHCreateDirectoryEx(hwndDlg, pszDir, NULL) == ERROR_SUCCESS);
- bReturn = ((iRet == ERROR_SUCCESS) || (iRet == ERROR_ALREADY_EXISTS));
-
- } else {
-
- int iSlashOcc;
- int iAbsSlashOcc;
- WCHAR* pszSlash;
- WCHAR szDirTemp[MAX_PATH];
- WCHAR szDirOutput[MAX_PATH];
-
- ZeroMemory(&szDirTemp, sizeof(szDirTemp));
- ZeroMemory(&szDirOutput, sizeof(szDirOutput));
-
- // Skip drive letter
- pszSlash = StrChr(pszDir, _T('\\')); // Search for the first :'\\'
-
- if (pszSlash != NULL) // does not contain any slashs
- {
- iSlashOcc = (int)(pszSlash-pszDir+1); // Pointer arithmetic
- StrCpyN(szDirTemp, pszDir+iSlashOcc, lstrlen(pszDir)-iSlashOcc); // Pointer arithmetic
- iAbsSlashOcc = iSlashOcc;
-
- bReturn = TRUE;
- pszSlash = szDirTemp;
- while (pszSlash)
- {
- pszSlash = StrChr(szDirTemp, _T('\\'));
-
- iSlashOcc = (int)(pszSlash-szDirTemp+1); // Pointer arithmetic
- iAbsSlashOcc = iAbsSlashOcc + iSlashOcc;
-
- StrCpyN(szDirOutput, pszPath, iAbsSlashOcc); // Pointer arithmetic
-
- StrCpyN(szDirTemp, szDirTemp+iSlashOcc, lstrlen(szDirTemp)-iSlashOcc); // Pointer arithmetic
- ZeroMemory((PBYTE)szDirTemp+((lstrlen(szDirTemp)-iSlashOcc)*sizeof(WCHAR)), iSlashOcc*sizeof(WCHAR));
-
- bReturn = (CreateDirectory(szDirOutput, NULL) && bReturn);
- }
- }
- }
- }
-
- mir_free(pszDir);
- return bReturn;
- }
-}
-
-
-BOOL PIsValidFile(const WCHAR* pszFileName, const WCHAR* aszFileExtensions[], int nFileExtensions, const WCHAR* aszContentTypes[], int nContentTypes)
-{
- BOOL bIsOk = FALSE;
- int i;
-
- if (!pszFileName) return FALSE;
-
- // Check file extensions
- for (i=0; i<nFileExtensions; i++)
- {
- bIsOk = (StrCmpI(PathFindExtension(pszFileName), aszFileExtensions[i]) == 0);
- if (bIsOk) break;
- }
-
- if (!bIsOk)
- {
- // Check content types
- for (i=0; i<nContentTypes; i++)
- {
- bIsOk = PathIsContentType(pszFileName, aszContentTypes[i]);
- if (bIsOk) break;
- }
-
- if (!bIsOk)
- return FALSE;
- }
-
- // Check if the file name is actually a directory
- if (PathIsDirectory(pszFileName))
- return FALSE;
-
- // Finally check if file is present
- return PathFileExists(pszFileName);
-}
-
-
-void PMakePathPretty(WCHAR* pszPath, DWORD dwFlags)
-{
- WCHAR szBuf[MAX_PATH];
- WCHAR szRelativeTo[MAX_PATH];
-
- if (!pszPath)
- return;
-
- if (!PConstructLocalPath(szRelativeTo, CSIDL_EXT_EXECUTABLE, NULL, NULL, NULL))
- szRelativeTo[0] = _T('\0');
-
- // Create absolute path if path is relative
- if (PathIsRelative(pszPath))
- {
- if (PathCombine(szBuf, szRelativeTo, pszPath))
- {
- mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
- dwFlags |= PC_ABSOLUTERELATIVE; // Convert back after making pretty
- }
- }
-
- // Make pretty
- {
- if (PathCanonicalize(szBuf, pszPath))
- mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
-
- // Convert slightly wrong chars
- ReplaceSubStringWithStringBuf(pszPath, 0, _T("/"), _T("\\"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszPath, 0, _T("\\\\"), _T("\\"), TRUE, FALSE);
- ReplaceSubStringWithStringBuf(pszPath, 0, _T("\""), NULL, TRUE, FALSE);
-
- /*
- {
- int i;
-
- // Remove wildcard characters
- if (dwFlags&PC_ALLOW_WILDCARDS)
- for (i=lstrlen(pszPath); i>=0; i--)
- if (PathGetCharType(pszPath[i])&GCT_WILD)
- RemoveSubStr(pszPath, i, 1);
-
- // Remove disallowed TCHARs
- for (i=lstrlen(pszPath); i>=0; i--)
- if (PathGetCharType(pszPath[i])&GCT_INVALID)
- RemoveSubStr(pszPath, i, 1);
- }
- */
-
- PathRemoveBlanks(pszPath);
- PathUnquoteSpaces(pszPath);
-
- // Upper case drive TCHAR
- if (PathGetDriveNumber(pszPath) != -1)
- CharUpperBuff(pszPath, 1);
-
- // Make it use the long path name (Win98+/Win2000+)
- {
- DWORD (WINAPI *MyGetLongPathName)(LPCTSTR, LPCTSTR, DWORD);
-
- #if defined(UNICODE)
- *(FARPROC*)&MyGetLongPathName = GetProcAddress(GetModuleHandle(_T("KERNEL32")), "GetLongPathNameW");
- #else
- *(FARPROC*)&MyGetLongPathName = GetProcAddress(GetModuleHandle(_T("KERNEL32")), "GetLongPathNameA");
- #endif
-
- if (MyGetLongPathName)
- {
- if (MyGetLongPathName(pszPath, pszPath, MAX_PATH) == 0)
- {
- // Try to remove file name and see if it works then
- mir_sntprintf(szBuf, ARRAYSIZE(szBuf), _T("%s"), pszPath);
-
- if (PathRemoveFileSpec(szBuf) && (MyGetLongPathName(szBuf, szBuf, ARRAYSIZE(szBuf)) != 0))
- {
- PathAppend(szBuf, PathFindFileName(pszPath));
- mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
- }
- }
- }
- }
-
- // Lower case path if all upper case (only if user activated this feature for Windows-Explorer)
- {
- SHELLFLAGSTATE sfs;
- SHGetSettings(&sfs, SSF_DONTPRETTYPATH);
-
- if (!sfs.fDontPrettyPath)
- PathMakePretty(pszPath);
- }
- }
-
- // Make relative
- if (dwFlags&PC_ABSOLUTERELATIVE)
- {
- if (PathRelativePathTo(szBuf, szRelativeTo, FILE_ATTRIBUTE_DIRECTORY, pszPath, FILE_ATTRIBUTE_NORMAL))
- {
- mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
-
- // Remove backslash in front -> does not belong there (causes by PathRelativePathTo)
- if ((pszPath[0] == _T('\\')) || (pszPath[0] == _T('/')))
- MoveMemory(pszPath, CharNext(pszPath), (lstrlen(CharNext(pszPath))+1)*sizeof(WCHAR));
- }
-
- // Miranda Utils contains a quite less featured implementation of relative paths
- // (not all cases are captured, does not support Unicode, too)
- //if (CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)pszPath, (LPARAM)szBuf) == 0)
- // mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
- }
-
- // Environment strings
- if (dwFlags&PC_ENVIRONMENTSTRINGS)
- {
- BOOL (STDAPICALLTYPE *MyPathUnExpandEnvStrings)(LPCTSTR, LPTSTR, UINT);
-
- // PathUnExpandEnvStrings is Win98/2000+
- #if defined(UNICODE)
- *(FARPROC*)&MyPathUnExpandEnvStrings = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHLWAPI")), "PathUnExpandEnvStringsW");
- #else
- *(FARPROC*)&MyPathUnExpandEnvStrings = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHLWAPI")), "PathUnExpandEnvStringsA");
- #endif
-
- if (MyPathUnExpandEnvStrings)
- if (MyPathUnExpandEnvStrings(pszPath, szBuf, MAX_PATH))
- mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
- }
-}
-
-
-DWORD PMakePathUsable(WCHAR* pszPath)
-{
- WCHAR szBuf[MAX_PATH];
- DWORD dwFlags = 0;
-
- if (!pszPath)
- return dwFlags;
-
- PathUnquoteSpaces(pszPath);
-
- // Environment strings
- {
- if (ExpandEnvironmentStrings(pszPath, szBuf, ARRAYSIZE(szBuf)) != 0)
- {
- // Success?
- if (StrCmp(pszPath, szBuf) != 0)
- dwFlags |= PC_ENVIRONMENTSTRINGS;
-
- mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
- }
- }
-
- // Absolute/relative path
- {
- WCHAR szRelativeTo[MAX_PATH];
- PConstructLocalPath(szRelativeTo, CSIDL_EXT_EXECUTABLE, NULL, NULL, NULL);
-
- // Miranda Utils contains not a very good implementation of relative paths
- // (not all cases are captured)
- //(CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)szBuf, (LPARAM)pszPath) != lstrlenA(szBuf))
-
- // Create absolute path if path is relative
- if (PathIsRelative(pszPath))
- {
- if (PathCombine(szBuf, szRelativeTo, pszPath))
- {
- dwFlags |= PC_ABSOLUTERELATIVE;
- mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf);
- }
- }
- }
-
- return dwFlags;
-}
-
-
-
-BOOL PConstructLocalPath(WCHAR* pszReturn, int nMainFolder, const WCHAR* pszSubFolders, const WCHAR* pszFileName, const WCHAR* pszOptFileExtension)
-{
- // pszReturn muss MAX_PATH groß sein
- if (!pszReturn) return FALSE;
-
- pszReturn[0] = _T('\0');
-
- switch (nMainFolder)
- {
- case CSIDL_EXT_MIRANDAPROFILE:
- {
- // Profile directory of Miranda's database
- WCHAR szBuf[MAX_PATH];
-
- if (CallService(MS_DB_GETPROFILEPATH, (WPARAM)ARRAYSIZE(szBuf), (LPARAM)szBuf) != 0)
- return FALSE;
-
- #if defined(UNICODE)
- {
- WCHAR* pszBuf = (WCHAR*)mir_utf8encodeW(szBuf);
- if (!pszBuf) return FALSE;
-
- mir_sntprintf(pszReturn, MAX_PATH, _T("%s"), pszBuf);
- mir_free(pszBuf);
- }
- #else
- mir_sntprintf(pszReturn, MAX_PATH, _T("%s"), szBuf);
- #endif
-
- break;
- }
-
- case CSIDL_EXT_MODULE:
- {
- // Current DLL's directory
- if (GetModuleFileName(hInstance, pszReturn, MAX_PATH) == 0)
- return FALSE;
-
- PathRemoveFileSpec(pszReturn);
- break;
- }
-
- case CSIDL_EXT_EXECUTABLE:
- {
- // Current executable path
- if (GetModuleFileName(NULL, pszReturn, MAX_PATH) == 0)
- return FALSE;
-
- PathRemoveFileSpec(pszReturn);
- break;
- }
-
- case CSIDL_EXT_TEMP:
- {
- // Temp directory
- if (GetTempPath(MAX_PATH, pszReturn) == 0)
- return FALSE;
- break;
- }
-
- case CSIDL_EXT_CURRENT:
- {
- // Current directory
- if (GetCurrentDirectory(MAX_PATH, pszReturn) == 0)
- return FALSE;
- break;
- }
-
- default:
- {
- // CSIDL directory
- if (!SHGetSpecialFolderPath(NULL, pszReturn, nMainFolder, FALSE))
- return FALSE;
-
- break;
- }
- }
-
- if (!PathAddBackslash(pszReturn))
- return FALSE;
-
- if (pszSubFolders)
- {
- if (!PathAppend(pszReturn, pszSubFolders))
- return FALSE;
-
- if (!PathAddBackslash(pszReturn))
- return FALSE;
- }
-
- if (pszFileName)
- if (!PathAppend(pszReturn, pszFileName))
- return FALSE;
-
- if (pszFileName && pszOptFileExtension)
- if (!PathAddExtension(pszReturn, pszOptFileExtension))
- return FALSE;
-
- return TRUE;
-}
-
-// Move files or whole folder from module to destination directory
-BOOL PInstallFile(const WCHAR* pszFileName, const WCHAR* pszDestDir)
-{
- BOOL bReturn;
- WCHAR szFileFrom[MAX_PATH+1];
- WCHAR szFileTo[MAX_PATH+1];
-
- if (!pszFileName) return FALSE;
- PConstructLocalPath(szFileFrom, CSIDL_EXT_MODULE, NULL, pszFileName, NULL);
- if (!PathFileExists(szFileFrom)) return FALSE;
- mir_sntprintf(szFileTo, ARRAYSIZE(szFileTo), _T("%s"), pszDestDir);
-
- if (PathIsDirectory(szFileFrom))
- {
- SHFILEOPSTRUCT sfo;
-
- ZeroMemory(&sfo, sizeof(sfo));
- sfo.fFlags = FOF_MULTIDESTFILES|FOF_NOERRORUI|FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_SILENT;
- sfo.wFunc = FO_MOVE;
- szFileFrom[lstrlen(szFileFrom)+1] = _T('\0');
- sfo.pFrom = szFileFrom;
- szFileTo[lstrlen(szFileTo)+1] = _T('\0');
- sfo.pTo = szFileTo;
- bReturn = (SHFileOperation(&sfo) == 0);
-
- } else {
- PathAppend(szFileTo, pszFileName);
-
- DeleteFile(szFileTo);
- bReturn = MoveFile(szFileFrom, szFileTo); // MoveFile does only support directories limitedly
- }
-
- return bReturn;
-}
-
-BOOL PInstallDLLFile(const WCHAR* pszFileName, BOOL bIgnoreLanguage, BOOL bIgnoreOpSystem)
-{
- DWORD dwErr;
- WCHAR szSrcDir[MAX_PATH];
- WCHAR szDestDir[MAX_PATH];
- WCHAR szTmpFile[MAX_PATH];
- UINT uTmpFileSize = ARRAYSIZE(szTmpFile);
-
- if (!pszFileName) return FALSE;
-
- // Test if file-to-be-installed exists
- PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, pszFileName, NULL);
- if (!PathFileExists(szSrcDir)) return FALSE;
-
- // Source: module dir (Plugins directory)
- PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, NULL, NULL);
-
- // Destination: app dir
- PConstructLocalPath(szDestDir, CSIDL_EXT_EXECUTABLE, NULL, NULL, NULL);
-
- // Install DLL using version verfication
- szTmpFile[0] = _T('\0'); // needs to be empty (docs)
- dwErr = VerInstallFile(0, (WCHAR*)pszFileName, (WCHAR*)pszFileName, szSrcDir, szDestDir, szDestDir, szTmpFile, &uTmpFileSize);
- if (!(dwErr&VIF_WRITEPROT) && !(dwErr&VIF_SRCOLD))
- {
- // Ignore language/codepage of the DLL (install anyway) -> useful for DLLs without user interface
- if (bIgnoreLanguage)
- if ((dwErr&VIF_DIFFLANG) && (dwErr&VIF_DIFFCODEPG))
- dwErr = VerInstallFile(VIFF_FORCEINSTALL, (WCHAR*)pszFileName, (WCHAR*)pszFileName, szSrcDir, szDestDir, szDestDir, szTmpFile, &uTmpFileSize);
-
- // Ignore operating system of the DLL (install anyway) -> useful for DLLs that work anyway
- if (bIgnoreOpSystem)
- if (dwErr&VIF_DIFFTYPE)
- dwErr = VerInstallFile(VIFF_FORCEINSTALL, (WCHAR*)pszFileName, (WCHAR*)pszFileName, szSrcDir, szDestDir, szDestDir, szTmpFile, &uTmpFileSize);
- }
-
- // Delete temp file
- if ((dwErr&VIF_TEMPFILE) && !(dwErr&VIF_BUFFTOOSMALL)) // buffer too small for temp file
- DeleteFile(szTmpFile);
-
- // Test for success
- PConstructLocalPath(szDestDir, CSIDL_EXT_EXECUTABLE, NULL, pszFileName, NULL);
- if (PathFileExists(szDestDir))
- {
- PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, pszFileName, NULL);
- DeleteFile(szSrcDir);
- return TRUE;
- }
-
- // Debug output
- OutputDebugString(_T("Spam Filter: VersionInfo DLL (VERSION.DLL) could not be used to install DLL file.\r\n"));
-
- // Source: module dir (Plugins directory)
- PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, pszFileName, NULL);
- // Destination: app dir
- PConstructLocalPath(szDestDir, CSIDL_EXT_EXECUTABLE, NULL, pszFileName, NULL);
-
- // Copy without version checking [danger!]
- DeleteFile(szDestDir);
- return MoveFile(szSrcDir, szDestDir);
+/* + +"Spam Filter"-Plugin for Miranda IM + +Copyright 2003-2006 Heiko 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 ("SpamFilter-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" + + +// ----------------------------------------- + + +BOOL PPreparePathForWrite(HWND hwndDlg, const WCHAR* pszPath, BOOL bAskDirCreate, BOOL bContainsFileName) +{ + // Using SHPathPrepareForWrite on Win2000+ (best, only if avail) + { + HRESULT (STDAPICALLTYPE *MySHPathPrepareForWrite)(HWND, IUnknown*, LPCTSTR, DWORD); + + #if defined(UNICODE) + *(FARPROC*)&MySHPathPrepareForWrite = GetProcAddress(GetModuleHandle(_T("USER32")), "SHPathPrepareForWriteW"); + #else + *(FARPROC*)&MySHPathPrepareForWrite = GetProcAddress(GetModuleHandle(_T("USER32")), "SHPathPrepareForWriteA"); + #endif + + if (MySHPathPrepareForWrite) + { + DWORD dwFlags = SHPPFW_NOWRITECHECK; // Not impl anyway + + if (bContainsFileName) + dwFlags |= SHPPFW_IGNOREFILENAME; + + dwFlags |= bAskDirCreate ? SHPPFW_ASKDIRCREATE : SHPPFW_DIRCREATE; + + return SUCCEEDED(MySHPathPrepareForWrite(hwndDlg, NULL, (LPCTSTR)pszPath, dwFlags)); + } + } + + // Emulating SHPathPrepareForWrite: + // Using SHCreateDirectoryEx on WinME + // And: Using emulated version of SHCreateDirectoryEx on Win95/98 + { + WCHAR* pszDir; + BOOL bReturn = FALSE; + + pszDir = mir_wstrdup(pszPath); + if (!pszDir) return FALSE; + + if (bContainsFileName) + PathRemoveFileSpec((LPWSTR)pszDir); + + // No dialog is emulated, instead always behave as + // if "No" was clicked + if (bAskDirCreate) + return FALSE; + + // Create all sub directories + { + int (STDAPICALLTYPE *MySHCreateDirectoryEx)(HWND, LPCTSTR, SECURITY_ATTRIBUTES*); + + #if defined(UNICODE) + *(FARPROC*)&MySHCreateDirectoryEx = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHELL32")), "SHCreateDirectoryExW"); + #else + *(FARPROC*)&MySHCreateDirectoryEx = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHELL32")), "SHCreateDirectoryExA"); + #endif + + if (MySHCreateDirectoryEx) + { + int iRet = (SHCreateDirectoryEx(hwndDlg, pszDir, NULL) == ERROR_SUCCESS); + bReturn = ((iRet == ERROR_SUCCESS) || (iRet == ERROR_ALREADY_EXISTS)); + + } else { + + int iSlashOcc; + int iAbsSlashOcc; + WCHAR* pszSlash; + WCHAR szDirTemp[MAX_PATH]; + WCHAR szDirOutput[MAX_PATH]; + + ZeroMemory(&szDirTemp, sizeof(szDirTemp)); + ZeroMemory(&szDirOutput, sizeof(szDirOutput)); + + // Skip drive letter + pszSlash = StrChr(pszDir, _T('\\')); // Search for the first :'\\' + + if (pszSlash != NULL) // does not contain any slashs + { + iSlashOcc = (int)(pszSlash-pszDir+1); // Pointer arithmetic + StrCpyN(szDirTemp, pszDir+iSlashOcc, lstrlen(pszDir)-iSlashOcc); // Pointer arithmetic + iAbsSlashOcc = iSlashOcc; + + bReturn = TRUE; + pszSlash = szDirTemp; + while (pszSlash) + { + pszSlash = StrChr(szDirTemp, _T('\\')); + + iSlashOcc = (int)(pszSlash-szDirTemp+1); // Pointer arithmetic + iAbsSlashOcc = iAbsSlashOcc + iSlashOcc; + + StrCpyN(szDirOutput, pszPath, iAbsSlashOcc); // Pointer arithmetic + + StrCpyN(szDirTemp, szDirTemp+iSlashOcc, lstrlen(szDirTemp)-iSlashOcc); // Pointer arithmetic + ZeroMemory((PBYTE)szDirTemp+((lstrlen(szDirTemp)-iSlashOcc)*sizeof(WCHAR)), iSlashOcc*sizeof(WCHAR)); + + bReturn = (CreateDirectory(szDirOutput, NULL) && bReturn); + } + } + } + } + + mir_free(pszDir); + return bReturn; + } +} + + +BOOL PIsValidFile(const WCHAR* pszFileName, const WCHAR* aszFileExtensions[], int nFileExtensions, const WCHAR* aszContentTypes[], int nContentTypes) +{ + BOOL bIsOk = FALSE; + int i; + + if (!pszFileName) return FALSE; + + // Check file extensions + for (i=0; i<nFileExtensions; i++) + { + bIsOk = (StrCmpI(PathFindExtension(pszFileName), aszFileExtensions[i]) == 0); + if (bIsOk) break; + } + + if (!bIsOk) + { + // Check content types + for (i=0; i<nContentTypes; i++) + { + bIsOk = PathIsContentType(pszFileName, aszContentTypes[i]); + if (bIsOk) break; + } + + if (!bIsOk) + return FALSE; + } + + // Check if the file name is actually a directory + if (PathIsDirectory(pszFileName)) + return FALSE; + + // Finally check if file is present + return PathFileExists(pszFileName); +} + + +void PMakePathPretty(WCHAR* pszPath, DWORD dwFlags) +{ + WCHAR szBuf[MAX_PATH]; + WCHAR szRelativeTo[MAX_PATH]; + + if (!pszPath) + return; + + if (!PConstructLocalPath(szRelativeTo, CSIDL_EXT_EXECUTABLE, NULL, NULL, NULL)) + szRelativeTo[0] = _T('\0'); + + // Create absolute path if path is relative + if (PathIsRelative(pszPath)) + { + if (PathCombine(szBuf, szRelativeTo, pszPath)) + { + mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf); + dwFlags |= PC_ABSOLUTERELATIVE; // Convert back after making pretty + } + } + + // Make pretty + { + if (PathCanonicalize(szBuf, pszPath)) + mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf); + + // Convert slightly wrong chars + ReplaceSubStringWithStringBuf(pszPath, 0, _T("/"), _T("\\"), TRUE, FALSE); + ReplaceSubStringWithStringBuf(pszPath, 0, _T("\\\\"), _T("\\"), TRUE, FALSE); + ReplaceSubStringWithStringBuf(pszPath, 0, _T("\""), NULL, TRUE, FALSE); + + /* + { + int i; + + // Remove wildcard characters + if (dwFlags&PC_ALLOW_WILDCARDS) + for (i=lstrlen(pszPath); i>=0; i--) + if (PathGetCharType(pszPath[i])&GCT_WILD) + RemoveSubStr(pszPath, i, 1); + + // Remove disallowed TCHARs + for (i=lstrlen(pszPath); i>=0; i--) + if (PathGetCharType(pszPath[i])&GCT_INVALID) + RemoveSubStr(pszPath, i, 1); + } + */ + + PathRemoveBlanks(pszPath); + PathUnquoteSpaces(pszPath); + + // Upper case drive TCHAR + if (PathGetDriveNumber(pszPath) != -1) + CharUpperBuff(pszPath, 1); + + // Make it use the long path name (Win98+/Win2000+) + { + DWORD (WINAPI *MyGetLongPathName)(LPCTSTR, LPCTSTR, DWORD); + + #if defined(UNICODE) + *(FARPROC*)&MyGetLongPathName = GetProcAddress(GetModuleHandle(_T("KERNEL32")), "GetLongPathNameW"); + #else + *(FARPROC*)&MyGetLongPathName = GetProcAddress(GetModuleHandle(_T("KERNEL32")), "GetLongPathNameA"); + #endif + + if (MyGetLongPathName) + { + if (MyGetLongPathName(pszPath, pszPath, MAX_PATH) == 0) + { + // Try to remove file name and see if it works then + mir_sntprintf(szBuf, ARRAYSIZE(szBuf), _T("%s"), pszPath); + + if (PathRemoveFileSpec(szBuf) && (MyGetLongPathName(szBuf, szBuf, ARRAYSIZE(szBuf)) != 0)) + { + PathAppend(szBuf, PathFindFileName(pszPath)); + mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf); + } + } + } + } + + // Lower case path if all upper case (only if user activated this feature for Windows-Explorer) + { + SHELLFLAGSTATE sfs; + SHGetSettings(&sfs, SSF_DONTPRETTYPATH); + + if (!sfs.fDontPrettyPath) + PathMakePretty(pszPath); + } + } + + // Make relative + if (dwFlags&PC_ABSOLUTERELATIVE) + { + if (PathRelativePathTo(szBuf, szRelativeTo, FILE_ATTRIBUTE_DIRECTORY, pszPath, FILE_ATTRIBUTE_NORMAL)) + { + mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf); + + // Remove backslash in front -> does not belong there (causes by PathRelativePathTo) + if ((pszPath[0] == _T('\\')) || (pszPath[0] == _T('/'))) + MoveMemory(pszPath, CharNext(pszPath), (lstrlen(CharNext(pszPath))+1)*sizeof(WCHAR)); + } + + // Miranda Utils contains a quite less featured implementation of relative paths + // (not all cases are captured, does not support Unicode, too) + //if (CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)pszPath, (LPARAM)szBuf) == 0) + // mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf); + } + + // Environment strings + if (dwFlags&PC_ENVIRONMENTSTRINGS) + { + BOOL (STDAPICALLTYPE *MyPathUnExpandEnvStrings)(LPCTSTR, LPTSTR, UINT); + + // PathUnExpandEnvStrings is Win98/2000+ + #if defined(UNICODE) + *(FARPROC*)&MyPathUnExpandEnvStrings = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHLWAPI")), "PathUnExpandEnvStringsW"); + #else + *(FARPROC*)&MyPathUnExpandEnvStrings = (FARPROC)GetProcAddress(GetModuleHandle(_T("SHLWAPI")), "PathUnExpandEnvStringsA"); + #endif + + if (MyPathUnExpandEnvStrings) + if (MyPathUnExpandEnvStrings(pszPath, szBuf, MAX_PATH)) + mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf); + } +} + + +DWORD PMakePathUsable(WCHAR* pszPath) +{ + WCHAR szBuf[MAX_PATH]; + DWORD dwFlags = 0; + + if (!pszPath) + return dwFlags; + + PathUnquoteSpaces(pszPath); + + // Environment strings + { + if (ExpandEnvironmentStrings(pszPath, szBuf, ARRAYSIZE(szBuf)) != 0) + { + // Success? + if (StrCmp(pszPath, szBuf) != 0) + dwFlags |= PC_ENVIRONMENTSTRINGS; + + mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf); + } + } + + // Absolute/relative path + { + WCHAR szRelativeTo[MAX_PATH]; + PConstructLocalPath(szRelativeTo, CSIDL_EXT_EXECUTABLE, NULL, NULL, NULL); + + // Miranda Utils contains not a very good implementation of relative paths + // (not all cases are captured) + //(CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)szBuf, (LPARAM)pszPath) != lstrlenA(szBuf)) + + // Create absolute path if path is relative + if (PathIsRelative(pszPath)) + { + if (PathCombine(szBuf, szRelativeTo, pszPath)) + { + dwFlags |= PC_ABSOLUTERELATIVE; + mir_sntprintf(pszPath, MAX_PATH, _T("%s"), szBuf); + } + } + } + + return dwFlags; +} + + + +BOOL PConstructLocalPath(WCHAR* pszReturn, int nMainFolder, const WCHAR* pszSubFolders, const WCHAR* pszFileName, const WCHAR* pszOptFileExtension) +{ + // pszReturn muss MAX_PATH groß sein + if (!pszReturn) return FALSE; + + pszReturn[0] = _T('\0'); + + switch (nMainFolder) + { + case CSIDL_EXT_MIRANDAPROFILE: + { + // Profile directory of Miranda's database + WCHAR szBuf[MAX_PATH]; + + if (CallService(MS_DB_GETPROFILEPATH, (WPARAM)ARRAYSIZE(szBuf), (LPARAM)szBuf) != 0) + return FALSE; + + #if defined(UNICODE) + { + WCHAR* pszBuf = (WCHAR*)mir_utf8encodeW(szBuf); + if (!pszBuf) return FALSE; + + mir_sntprintf(pszReturn, MAX_PATH, _T("%s"), pszBuf); + mir_free(pszBuf); + } + #else + mir_sntprintf(pszReturn, MAX_PATH, _T("%s"), szBuf); + #endif + + break; + } + + case CSIDL_EXT_MODULE: + { + // Current DLL's directory + if (GetModuleFileName(hInstance, pszReturn, MAX_PATH) == 0) + return FALSE; + + PathRemoveFileSpec(pszReturn); + break; + } + + case CSIDL_EXT_EXECUTABLE: + { + // Current executable path + if (GetModuleFileName(NULL, pszReturn, MAX_PATH) == 0) + return FALSE; + + PathRemoveFileSpec(pszReturn); + break; + } + + case CSIDL_EXT_TEMP: + { + // Temp directory + if (GetTempPath(MAX_PATH, pszReturn) == 0) + return FALSE; + break; + } + + case CSIDL_EXT_CURRENT: + { + // Current directory + if (GetCurrentDirectory(MAX_PATH, pszReturn) == 0) + return FALSE; + break; + } + + default: + { + // CSIDL directory + if (!SHGetSpecialFolderPath(NULL, pszReturn, nMainFolder, FALSE)) + return FALSE; + + break; + } + } + + if (!PathAddBackslash(pszReturn)) + return FALSE; + + if (pszSubFolders) + { + if (!PathAppend(pszReturn, pszSubFolders)) + return FALSE; + + if (!PathAddBackslash(pszReturn)) + return FALSE; + } + + if (pszFileName) + if (!PathAppend(pszReturn, pszFileName)) + return FALSE; + + if (pszFileName && pszOptFileExtension) + if (!PathAddExtension(pszReturn, pszOptFileExtension)) + return FALSE; + + return TRUE; +} + +// Move files or whole folder from module to destination directory +BOOL PInstallFile(const WCHAR* pszFileName, const WCHAR* pszDestDir) +{ + BOOL bReturn; + WCHAR szFileFrom[MAX_PATH+1]; + WCHAR szFileTo[MAX_PATH+1]; + + if (!pszFileName) return FALSE; + PConstructLocalPath(szFileFrom, CSIDL_EXT_MODULE, NULL, pszFileName, NULL); + if (!PathFileExists(szFileFrom)) return FALSE; + mir_sntprintf(szFileTo, ARRAYSIZE(szFileTo), _T("%s"), pszDestDir); + + if (PathIsDirectory(szFileFrom)) + { + SHFILEOPSTRUCT sfo; + + ZeroMemory(&sfo, sizeof(sfo)); + sfo.fFlags = FOF_MULTIDESTFILES|FOF_NOERRORUI|FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_SILENT; + sfo.wFunc = FO_MOVE; + szFileFrom[lstrlen(szFileFrom)+1] = _T('\0'); + sfo.pFrom = szFileFrom; + szFileTo[lstrlen(szFileTo)+1] = _T('\0'); + sfo.pTo = szFileTo; + bReturn = (SHFileOperation(&sfo) == 0); + + } else { + PathAppend(szFileTo, pszFileName); + + DeleteFile(szFileTo); + bReturn = MoveFile(szFileFrom, szFileTo); // MoveFile does only support directories limitedly + } + + return bReturn; +} + +BOOL PInstallDLLFile(const WCHAR* pszFileName, BOOL bIgnoreLanguage, BOOL bIgnoreOpSystem) +{ + DWORD dwErr; + WCHAR szSrcDir[MAX_PATH]; + WCHAR szDestDir[MAX_PATH]; + WCHAR szTmpFile[MAX_PATH]; + UINT uTmpFileSize = ARRAYSIZE(szTmpFile); + + if (!pszFileName) return FALSE; + + // Test if file-to-be-installed exists + PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, pszFileName, NULL); + if (!PathFileExists(szSrcDir)) return FALSE; + + // Source: module dir (Plugins directory) + PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, NULL, NULL); + + // Destination: app dir + PConstructLocalPath(szDestDir, CSIDL_EXT_EXECUTABLE, NULL, NULL, NULL); + + // Install DLL using version verfication + szTmpFile[0] = _T('\0'); // needs to be empty (docs) + dwErr = VerInstallFile(0, (WCHAR*)pszFileName, (WCHAR*)pszFileName, szSrcDir, szDestDir, szDestDir, szTmpFile, &uTmpFileSize); + if (!(dwErr&VIF_WRITEPROT) && !(dwErr&VIF_SRCOLD)) + { + // Ignore language/codepage of the DLL (install anyway) -> useful for DLLs without user interface + if (bIgnoreLanguage) + if ((dwErr&VIF_DIFFLANG) && (dwErr&VIF_DIFFCODEPG)) + dwErr = VerInstallFile(VIFF_FORCEINSTALL, (WCHAR*)pszFileName, (WCHAR*)pszFileName, szSrcDir, szDestDir, szDestDir, szTmpFile, &uTmpFileSize); + + // Ignore operating system of the DLL (install anyway) -> useful for DLLs that work anyway + if (bIgnoreOpSystem) + if (dwErr&VIF_DIFFTYPE) + dwErr = VerInstallFile(VIFF_FORCEINSTALL, (WCHAR*)pszFileName, (WCHAR*)pszFileName, szSrcDir, szDestDir, szDestDir, szTmpFile, &uTmpFileSize); + } + + // Delete temp file + if ((dwErr&VIF_TEMPFILE) && !(dwErr&VIF_BUFFTOOSMALL)) // buffer too small for temp file + DeleteFile(szTmpFile); + + // Test for success + PConstructLocalPath(szDestDir, CSIDL_EXT_EXECUTABLE, NULL, pszFileName, NULL); + if (PathFileExists(szDestDir)) + { + PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, pszFileName, NULL); + DeleteFile(szSrcDir); + return TRUE; + } + + // Debug output + OutputDebugString(_T("Spam Filter: VersionInfo DLL (VERSION.DLL) could not be used to install DLL file.\r\n")); + + // Source: module dir (Plugins directory) + PConstructLocalPath(szSrcDir, CSIDL_EXT_MODULE, NULL, pszFileName, NULL); + // Destination: app dir + PConstructLocalPath(szDestDir, CSIDL_EXT_EXECUTABLE, NULL, pszFileName, NULL); + + // Copy without version checking [danger!] + DeleteFile(szDestDir); + return MoveFile(szSrcDir, szDestDir); }
\ No newline at end of file |