///////////////////////////////////////////////////////////////////////////// // RelPath.cpp : Imlementation of relative pathname functions. // #include "pch.h" #include "..\Inc\TCLib.h" #include "RelPath.h" #include "StrManip.h" ///////////////////////////////////////////////////////////////////////////// // Description: Creates a relative path name, if possible. // // Parameters: // bBeginWithDot - Prepends the relative path with the a period and // backslash. While possibly rendundant, this may be useful for some contexts // of relative pathnames. If a relative path cannot be resolved, this // parameter is ignored. // bool TCMakeRelativePath(LPCTSTR pszPath, LPCTSTR pszFrom, LPTSTR pszDest, int cchMaxDest, bool bBeginWithDot) { // Ensure that input paths are absolute TCHAR szPathCopy[_MAX_PATH], szFromCopy[_MAX_PATH]; if (!_tfullpath(szPathCopy, pszPath, sizeofArray(szPathCopy))) return false; if (!_tfullpath(szFromCopy, pszFrom, sizeofArray(szFromCopy))) return false; // Replace (in-place) forward slashes with backslashes in input paths TCReplaceText(szPathCopy, TEXT("/"), TEXT("\\"), szPathCopy, -1); TCReplaceText(szFromCopy, TEXT("/"), TEXT("\\"), szFromCopy, -1); // The From path MUST be a directory, not a filename, so append backslash if (TEXT('\\') != szFromCopy[_tcslen(szFromCopy) - 1]) _tcscat(szFromCopy, TEXT("\\")); // Use COM monikers to create a relative path HRESULT hr; IBindCtxPtr pbc; IMonikerPtr pmkFrom, pmkPath, pmkRelative; LPOLESTR pszRelative = NULL; if (SUCCEEDED(hr = CreateFileMoniker(_bstr_t(szFromCopy), &pmkFrom)) && SUCCEEDED(hr = CreateFileMoniker(_bstr_t(szPathCopy), &pmkPath)) && S_OK == (hr = pmkFrom->RelativePathTo(pmkPath, &pmkRelative)) && SUCCEEDED(hr = CreateBindCtx(0, &pbc)) && SUCCEEDED(hr = pmkRelative->GetDisplayName(pbc, NULL, &pszRelative))) { if (bBeginWithDot) { TC_tcscpyn(pszDest, TEXT(".\\"), cchMaxDest); cchMaxDest -= 2; pszDest += 2; } TC_tcscpyn(pszDest, _bstr_t(pszRelative), cchMaxDest); CoTaskMemFree(pszRelative); return true; } // Could not make a relative path, copy the absolute path TC_tcscpyn(pszDest, szPathCopy, cchMaxDest); return false; }