summaryrefslogtreecommitdiff
path: root/path.c
diff options
context:
space:
mode:
Diffstat (limited to 'path.c')
-rw-r--r--path.c1080
1 files changed, 540 insertions, 540 deletions
diff --git a/path.c b/path.c
index b829c68..325a78a 100644
--- a/path.c
+++ b/path.c
@@ -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