// ==================================================================
//
// Path.h
//
// Created: 03.03.2005
//
// Copyright (C) Peter Hauptmann
//
// ------------------------------------------------------------------
//
/// \page pgDisclaimer Copyright & Disclaimer
///
/// Copyright (C) 2004-2005 Peter Hauptmann
/// all rights reserved
/// more info: http://www.codeproject.com/phShellPath.asp
/// Please contact the author with improvements / modifications.
///
/// Redistribution and use in source and binary forms, with or without
/// modification, are permitted under the following conditions:
/// - Redistribution of source must retain the copyright above,
/// and the disclaimer below.
/// - Modifications to the source should be marked clearly, to be
/// distinguishable from the original sources.
///
/// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
/// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
/// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
/// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
/// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
/// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
/// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
/// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
/// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
/// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
/// SUCH DAMAGE.
///
#ifndef FILE_PH_PATH_H_200506202_INCLUDED_
#define FILE_PH_PATH_H_200506202_INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif
#include <comdef.h> // for _bstr_t extractor only, can be removed if you don't need CPath::GetBStr()
#include "shlwapi.h"
#pragma once
/// The nsPath namespace contains the CPath class and global helper functions.
namespace nsPath
{
// ---------------- DECLARATIONS --------------------------------------------
// ----- CString Helpers ---------
void Trim(CString & s);
TCHAR GetFirstChar(CString const & s); ///< returns the first char of the string, or 0 if the string length is 0.
TCHAR GetLastChar(CString const & s); ///< returns the last char of the string, or 0 if the string length is 0.
TCHAR GetDriveLetter(TCHAR ch);
TCHAR GetDriveLetter(LPCTSTR s);
CString QuoteSpaces(CString const & str);
// ==================================================================
// ERootType
// ------------------------------------------------------------------
///
/// Recognized root types for a path.
/// see nsPath::GetRootType "GetRootType" for more.
///
/// \c len refers to the rootLen parameter optionally returned by \c GetRootType.
///
enum ERootType
{
rtNoRoot = 0, ///< no, or unknown root (\c len = 0)
rtDriveRoot = 1, ///< a drive specification with backslash ("C:\", \c len = 3)
rtDriveCur = 2, ///< a drive specification without backslash ("C:", \c len = 2)
// rtPathRoot = 3, ///< a path root, i.e. staring with a single backslash (nyi, \c len = 1)
rtLongPath = 4, ///< a UNC long path specification (e.g. "\\?\C:\", \c len is length of path root + 4), no distinction for "root / current" is made
rtServerOnly = 5, ///< a server only specification (e.g. "\\fileserv" or "\\fileserv\", \c len is the string length)
rtServerShare = 6, ///< server + share specification ("\\server\share", \c len includes the backslash after share if given)
rtProtocol = 7, ///< protocol, ("http://", \c len includes the "://" part)
rtPseudoProtocol = 8, ///< pseudo protocol (no slahes) ("mailto:", \c len includes the colon)
rtServer = 9, ///< server with share following (for GetRootType(_,_,greedy=false)
};
ERootType GetRootType(LPCTSTR path, int * pLen, bool greedy = true);
// ==================================================================
// nsPath::EPathCleanup
// ------------------------------------------------------------------
/// Flags for nsPath::CPath::Cleanup
///
enum EPathCleanup
{
epcTrim = 1, ///< trim outer whitespace
epcUnquote = 2, ///< remove single or double quotes
epcTrimInQuote = 4, ///< trim whitespaces inside quotes
epcCanonicalize = 8, ///< Canonicalize (collapse "\\..\\" and "\\.\\")
epcRemoveXXL = 16, ///< Remove "\\\\?\\" and "\\\\?\\UNC\\" markers
epcSlashToBackslash = 32, ///< replace forward slashes with backslashes
epcMakePretty = 64, ///< Windows' idea of a pretty path
epcRemoveArgs = 128, ///< calls PathRemoveArgs (before trimming/unquoting)
epcRemoveIconLocation = 256, ///< Remove Icon location from the path
epcExpandEnvStrings = 512, ///< Expand environment strings
epc_Default = epcTrim |
epcUnquote |
epcTrimInQuote |
epcCanonicalize |
epcRemoveXXL |
epcExpandEnvStrings, ///< default for CTors and Assignment operators
};
// ==================================================================
// nsPath::EPathPacking
// ------------------------------------------------------------------
///
/// Flags for nsPath::CPath::GetStr
/// \note
/// eppAutoQuote was ignored in Version 1.2 and before.
/// It is fixed since V.1.3 (August 2005), /// but was removed from
/// epp_Default for backward compatibility
///
enum EPathPacking
{
eppAutoQuote = 1, ///< Quote the path if it contains spaces
eppAutoXXL = 2, ///< If path length is > MAX_PATH, use "\\\\?\\" syntax
eppBackslashToSlash = 4, ///< turn backslashes into forward slashes
epp_Default = eppAutoXXL,
};
// ==================================================================
// nsPath::CPath
// ------------------------------------------------------------------
///
///
///
class CPath
{
protected:
CString m_path;
void CAssign(CString const & src);
public:
//@{ \name Construction
CPath() {}
CPath(LPCSTR path); ///< Assigns \c path. CPath::Clean(epc_Default) is called for cleanup
CPath(LPCWSTR path); ///< Assigns \c path. CPath::Clean(epc_Default) is called for cleanup
CPath(CString const & path); ///< Assigns \c path CPath::Clean(epc_Default) is called for cleanup
CPath(CPath const & path); ///< Assigns \c path to the path. Does \b not modify the assigned path!
CPath(CString const & path, DWORD cleanup); ///< Assigns \c path, using custom cleanup options (see CPath::Clean)
//@}
//@{ \name Assignment
CPath & operator=(LPCSTR rhs); ///< Assigns \c path, and calls CPath::Clean(epc_Default)
CPath & operator=(LPCWSTR rhs); ///< Assigns \c path, and calls CPath::Clean(epc_Default)
CPath & operator=(CString const & rhs); ///< Assigns \c path, and calls CPath::Clean(epc_Default)
CPath & operator=(CPath const & rhs); ///< Assigns \c path Does \b not call CPath::Clean!
CPath & Assign(CString const & str, DWORD cleanup = epc_Default);
//@}
//@{ \name Miscellaneous Query
operator LPCTSTR () const { return m_path.operator LPCTSTR(); }
int GetLength() const { return m_path.GetLength(); } ///< returns the length of the path, in characters
//@}
//@{ \name Path concatenation
CPath & operator &=(LPCTSTR rhs);
CPath & Append(LPCTSTR appendix);
CPath & AddBackslash();
CPath & RemoveBackslash();
//@}
//@{ \name Splitting into Path Segments
CString ShellGetRoot() const;
CPath GetPath(bool includeRoot = true) const;
CString GetName() const;
CString GetTitle() const;
CString GetExtension() const;
ERootType GetRootType(int * len = 0, bool greedy = true) const;
CString GetRoot(ERootType * rt = NULL, bool greedy = true) const;
CString SplitRoot(ERootType * rt = NULL);
int GetDriveNumber();
TCHAR GetDriveLetter();
//@}
//@{ \name Add / Modify / Remove parts
CPath & AddExtension(LPCTSTR extension, int len = -1);
CPath & RemoveExtension();
CPath & RenameExtension(LPCTSTR newExt);
CPath & RemoveFileSpec();
//@}
//@{ \name Cleanup
CPath & Trim();
CPath & Unquote();
CPath & Canonicalize();
CPath & ShrinkXXLPath();
CPath & MakePretty();
CPath & Clean(DWORD cleanup = epc_Default);
//@}
//@{ \name Extractors (with special "packing")
CString GetStr(DWORD packing = epp_Default) const;
_bstr_t GetBStr(DWORD packing = epp_Default) const;
//@}
//@{ \name Static checking (not accessing file system, see also GetRootType)
bool IsValid() const;
bool IsDot() const;
bool IsDotDot() const;
bool IsDotty() const; // IsDot || IsDotDot
bool MatchSpec(LPCTSTR spec);
bool IsContentType(LPCTSTR contentType) { return 0 != ::PathIsContentType(m_path, contentType); } ///< compare content type registered for this file, see also MSDN: PathIsContentType
bool IsFileSpec() { return 0 != ::PathIsFileSpec(m_path); } ///< true if path does not contain backslash, see MSDN: PathIsFileSpec
bool IsPrefix(LPCTSTR prefix) { return 0 != ::PathIsPrefix(m_path, prefix); } ///< checks if the path starts with a prefix like "C:\\", see MSDN: PathIsPrefix
bool IsRelative() { return 0 != ::PathIsRelative(m_path); } ///< returns true if the path is relative, see MSDN: PathIsRelative
bool IsRoot() { return 0 != ::PathIsRoot(m_path); } ///< returns true if path is a directory root, see MSDN: PathIsRoot
bool IsSameRoot(LPCTSTR other) { return 0 != ::PathIsSameRoot(m_path, other); } ///< returns true if the path has the same root as \c otherPath, see MSDN: IsSameRoot
bool IsUNC() { return 0 != ::PathIsUNC(m_path); } ///< returns true if the path is a UNC specification, see MSDN: PathIsUNC
bool IsUNCServer() { return 0 != ::PathIsUNCServer(m_path); } ///< returns true if the path is a UNC server specification, see MSDN: PathIsUNCServer
bool IsUNCServerShare() { return 0 != ::PathIsUNCServerShare(m_path); } ///< returns true if the path is a UNC server + share specification, see MSDN: PathIsUNCServerShare
bool IsURL() { return 0 != ::PathIsURL(m_path); } ///< returns true if the path is an URL, see MSDN: PathIsURL
// bool IsHTMLFile() { return 0 != ::PathIsHTMLFile(m_path); } ///< (missing?) true if content type registered for this file is HTML, see MSDN: PathIsHTMLFile
// bool IsLFNFileSpec() { return 0 != ::PathISLFNFileSpec(m_path); } ///< (missing?) true if file is not a 8.3 file, see MSDN: PathIsLFNFileSpec
// bool IsNetworkPath() { return 0 != ::PathIsNetworkPath(m_path); } ///< (missing?) returns true if the path is on a network, see MSDN: PathIsNetworkPath
//@}
//@{ \name Relative Paths
CPath GetCommonPrefix(LPCTSTR secondPath);
CPath RelativePathTo(LPCTSTR pathTo, bool srcIsDir = true);
bool MakeRelative(CPath const & basePath);
bool MakeAbsolute(CPath const & basePath);
//@}
//@{ \name Dialog control operations
CString GetCompactStr(HDC dc, UINT dx, DWORD eppFlags = 0);
CString GetCompactStr(UINT cchMax, DWORD eppFlags = 0, DWORD flags = 0);
void SetDlgItem(HWND dlg, UINT dlgCtrlID, DWORD eppFlags = 0);
//@}
//@{ \name File System / Environment-Dependent operations
CPath & SearchAndQualify();
CPath & FindOnPath(LPCTSTR * additionalDirs = 0);
bool Exists() const;
bool IsDirectory() const;
bool IsSystemFolder(DWORD attrib = FILE_ATTRIBUTE_SYSTEM) const;
CPath & MakeSystemFolder(bool make = true);
DWORD GetAttributes();
bool GetAttributes(WIN32_FILE_ATTRIBUTE_DATA & fad);
CPath & MakeFullPath();
CPath & ExpandEnvStrings();
bool EnvUnexpandRoot(LPCTSTR envVar);
bool EnvUnexpandDefaultRoots();
long ToRegistry(HKEY baseKey, LPCTSTR subkey, LPCTSTR name, bool replaceEnv = true);
//@}
// TODO: Shell 5.0 support
// V5: CPath & UnexpandEnvStrings();
// V5: LPCTSTR FindSuffixArray(LPCTSTR suffixes, int numSuffixes);
// V5: void PathUndecorate();
// V5: CPath PathCreateFromURL(LPCTSTR path, DWORD dwReserved = 0);
// V5: bool IsDirectoryEmpty() const;
// might be useful for later extensions: PathGetCharType
};
// creation functions:
CPath SplitArgs(CString const & path_args, CString * args = NULL, DWORD cleanup = epc_Default);
CPath SplitIconLocation(CString const & path_icon, int * pIcon = NULL, DWORD cleanup = epc_Default);
CPath BuildRoot(int driveNumber);
CPath GetModuleFileName(HMODULE module = NULL);
CPath GetCurrentDirectory();
CPath FromRegistry(HKEY baseKey, LPCTSTR subkey, LPCTSTR name);
CString ReplaceInvalid(CString const & str, TCHAR replaceChar = '_');
// concatenation
inline CPath operator & (CPath const & lhs, LPCTSTR rhs) { CPath ret = lhs; ret &= rhs; return ret; }
// ---------------- INLIME IMPLEMENTATIONS ----------------------------------
// ==============================================
// GetFirstChar
// ----------------------------------------------
/// \return [TCHAR]: the first char of the string, or 0 if the string length is 0.
/// \note The implementation takes care that the string is not copied when there are no spaces.
inline TCHAR GetFirstChar(CString const & s)
{
if (s.GetLength() == 0)
return 0;
else
return s[0];
}
// ==============================================
// GetLastChar
// ----------------------------------------------
/// \return [TCHAR]: the last character in the string, or 0 if the string length is 0.
/// \par Note
/// \b MBCS: if the string ends with a Multibyte character, this
/// function returns the lead byte of the multibyte sequence.
inline TCHAR GetLastChar(CString const & s)
{
LPCTSTR pstr = s;
LPCTSTR pLastChar = _tcsdec(pstr, pstr + s.GetLength());
if (pLastChar == NULL)
return 0;
else
return *pLastChar;
}
} // namespace nsPath
#endif // FILE_PH_PATH_H_200506202_INCLUDED_