Path.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. // ==================================================================
  2. //
  3. // Path.h
  4. //
  5. // Created: 03.03.2005
  6. //
  7. // Copyright (C) Peter Hauptmann
  8. //
  9. // ------------------------------------------------------------------
  10. //
  11. /// \page pgDisclaimer Copyright & Disclaimer
  12. ///
  13. /// Copyright (C) 2004-2005 Peter Hauptmann
  14. /// all rights reserved
  15. /// more info: http://www.codeproject.com/phShellPath.asp
  16. /// Please contact the author with improvements / modifications.
  17. ///
  18. /// Redistribution and use in source and binary forms, with or without
  19. /// modification, are permitted under the following conditions:
  20. /// - Redistribution of source must retain the copyright above,
  21. /// and the disclaimer below.
  22. /// - Modifications to the source should be marked clearly, to be
  23. /// distinguishable from the original sources.
  24. ///
  25. /// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  26. /// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27. /// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28. /// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  29. /// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30. /// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31. /// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32. /// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33. /// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34. /// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35. /// SUCH DAMAGE.
  36. ///
  37. #ifndef FILE_PH_PATH_H_200506202_INCLUDED_
  38. #define FILE_PH_PATH_H_200506202_INCLUDED_
  39. #if _MSC_VER > 1000
  40. #pragma once
  41. #endif
  42. #include <comdef.h> // for _bstr_t extractor only, can be removed if you don't need CPath::GetBStr()
  43. #include "shlwapi.h"
  44. #pragma once
  45. /// The nsPath namespace contains the CPath class and global helper functions.
  46. namespace nsPath
  47. {
  48. // ---------------- DECLARATIONS --------------------------------------------
  49. // ----- CString Helpers ---------
  50. void Trim(CString & s);
  51. TCHAR GetFirstChar(CString const & s); ///< returns the first char of the string, or 0 if the string length is 0.
  52. TCHAR GetLastChar(CString const & s); ///< returns the last char of the string, or 0 if the string length is 0.
  53. TCHAR GetDriveLetter(TCHAR ch);
  54. TCHAR GetDriveLetter(LPCTSTR s);
  55. CString QuoteSpaces(CString const & str);
  56. // ==================================================================
  57. // ERootType
  58. // ------------------------------------------------------------------
  59. ///
  60. /// Recognized root types for a path.
  61. /// see nsPath::GetRootType "GetRootType" for more.
  62. ///
  63. /// \c len refers to the rootLen parameter optionally returned by \c GetRootType.
  64. ///
  65. enum ERootType
  66. {
  67. rtNoRoot = 0, ///< no, or unknown root (\c len = 0)
  68. rtDriveRoot = 1, ///< a drive specification with backslash ("C:\", \c len = 3)
  69. rtDriveCur = 2, ///< a drive specification without backslash ("C:", \c len = 2)
  70. // rtPathRoot = 3, ///< a path root, i.e. staring with a single backslash (nyi, \c len = 1)
  71. 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
  72. rtServerOnly = 5, ///< a server only specification (e.g. "\\fileserv" or "\\fileserv\", \c len is the string length)
  73. rtServerShare = 6, ///< server + share specification ("\\server\share", \c len includes the backslash after share if given)
  74. rtProtocol = 7, ///< protocol, ("http://", \c len includes the "://" part)
  75. rtPseudoProtocol = 8, ///< pseudo protocol (no slahes) ("mailto:", \c len includes the colon)
  76. rtServer = 9, ///< server with share following (for GetRootType(_,_,greedy=false)
  77. };
  78. ERootType GetRootType(LPCTSTR path, int * pLen, bool greedy = true);
  79. // ==================================================================
  80. // nsPath::EPathCleanup
  81. // ------------------------------------------------------------------
  82. /// Flags for nsPath::CPath::Cleanup
  83. ///
  84. enum EPathCleanup
  85. {
  86. epcTrim = 1, ///< trim outer whitespace
  87. epcUnquote = 2, ///< remove single or double quotes
  88. epcTrimInQuote = 4, ///< trim whitespaces inside quotes
  89. epcCanonicalize = 8, ///< Canonicalize (collapse "\\..\\" and "\\.\\")
  90. epcRemoveXXL = 16, ///< Remove "\\\\?\\" and "\\\\?\\UNC\\" markers
  91. epcSlashToBackslash = 32, ///< replace forward slashes with backslashes
  92. epcMakePretty = 64, ///< Windows' idea of a pretty path
  93. epcRemoveArgs = 128, ///< calls PathRemoveArgs (before trimming/unquoting)
  94. epcRemoveIconLocation = 256, ///< Remove Icon location from the path
  95. epcExpandEnvStrings = 512, ///< Expand environment strings
  96. epc_Default = epcTrim |
  97. epcUnquote |
  98. epcTrimInQuote |
  99. epcCanonicalize |
  100. epcRemoveXXL |
  101. epcExpandEnvStrings, ///< default for CTors and Assignment operators
  102. };
  103. // ==================================================================
  104. // nsPath::EPathPacking
  105. // ------------------------------------------------------------------
  106. ///
  107. /// Flags for nsPath::CPath::GetStr
  108. /// \note
  109. /// eppAutoQuote was ignored in Version 1.2 and before.
  110. /// It is fixed since V.1.3 (August 2005), /// but was removed from
  111. /// epp_Default for backward compatibility
  112. ///
  113. enum EPathPacking
  114. {
  115. eppAutoQuote = 1, ///< Quote the path if it contains spaces
  116. eppAutoXXL = 2, ///< If path length is > MAX_PATH, use "\\\\?\\" syntax
  117. eppBackslashToSlash = 4, ///< turn backslashes into forward slashes
  118. epp_Default = eppAutoXXL,
  119. };
  120. // ==================================================================
  121. // nsPath::CPath
  122. // ------------------------------------------------------------------
  123. ///
  124. ///
  125. ///
  126. class CPath
  127. {
  128. protected:
  129. CString m_path;
  130. void CAssign(CString const & src);
  131. public:
  132. //@{ \name Construction
  133. CPath() {}
  134. CPath(LPCSTR path); ///< Assigns \c path. CPath::Clean(epc_Default) is called for cleanup
  135. CPath(LPCWSTR path); ///< Assigns \c path. CPath::Clean(epc_Default) is called for cleanup
  136. CPath(CString const & path); ///< Assigns \c path CPath::Clean(epc_Default) is called for cleanup
  137. CPath(CPath const & path); ///< Assigns \c path to the path. Does \b not modify the assigned path!
  138. CPath(CString const & path, DWORD cleanup); ///< Assigns \c path, using custom cleanup options (see CPath::Clean)
  139. //@}
  140. //@{ \name Assignment
  141. CPath & operator=(LPCSTR rhs); ///< Assigns \c path, and calls CPath::Clean(epc_Default)
  142. CPath & operator=(LPCWSTR rhs); ///< Assigns \c path, and calls CPath::Clean(epc_Default)
  143. CPath & operator=(CString const & rhs); ///< Assigns \c path, and calls CPath::Clean(epc_Default)
  144. CPath & operator=(CPath const & rhs); ///< Assigns \c path Does \b not call CPath::Clean!
  145. CPath & Assign(CString const & str, DWORD cleanup = epc_Default);
  146. //@}
  147. //@{ \name Miscellaneous Query
  148. operator LPCTSTR () const { return m_path.operator LPCTSTR(); }
  149. int GetLength() const { return m_path.GetLength(); } ///< returns the length of the path, in characters
  150. //@}
  151. //@{ \name Path concatenation
  152. CPath & operator &=(LPCTSTR rhs);
  153. CPath & Append(LPCTSTR appendix);
  154. CPath & AddBackslash();
  155. CPath & RemoveBackslash();
  156. //@}
  157. //@{ \name Splitting into Path Segments
  158. CString ShellGetRoot() const;
  159. CPath GetPath(bool includeRoot = true) const;
  160. CString GetName() const;
  161. CString GetTitle() const;
  162. CString GetExtension() const;
  163. ERootType GetRootType(int * len = 0, bool greedy = true) const;
  164. CString GetRoot(ERootType * rt = NULL, bool greedy = true) const;
  165. CString SplitRoot(ERootType * rt = NULL);
  166. int GetDriveNumber();
  167. TCHAR GetDriveLetter();
  168. //@}
  169. //@{ \name Add / Modify / Remove parts
  170. CPath & AddExtension(LPCTSTR extension, int len = -1);
  171. CPath & RemoveExtension();
  172. CPath & RenameExtension(LPCTSTR newExt);
  173. CPath & RemoveFileSpec();
  174. //@}
  175. //@{ \name Cleanup
  176. CPath & Trim();
  177. CPath & Unquote();
  178. CPath & Canonicalize();
  179. CPath & ShrinkXXLPath();
  180. CPath & MakePretty();
  181. CPath & Clean(DWORD cleanup = epc_Default);
  182. //@}
  183. //@{ \name Extractors (with special "packing")
  184. CString GetStr(DWORD packing = epp_Default) const;
  185. _bstr_t GetBStr(DWORD packing = epp_Default) const;
  186. //@}
  187. //@{ \name Static checking (not accessing file system, see also GetRootType)
  188. bool IsValid() const;
  189. bool IsDot() const;
  190. bool IsDotDot() const;
  191. bool IsDotty() const; // IsDot || IsDotDot
  192. bool MatchSpec(LPCTSTR spec);
  193. bool IsContentType(LPCTSTR contentType) { return 0 != ::PathIsContentType(m_path, contentType); } ///< compare content type registered for this file, see also MSDN: PathIsContentType
  194. bool IsFileSpec() { return 0 != ::PathIsFileSpec(m_path); } ///< true if path does not contain backslash, see MSDN: PathIsFileSpec
  195. bool IsPrefix(LPCTSTR prefix) { return 0 != ::PathIsPrefix(m_path, prefix); } ///< checks if the path starts with a prefix like "C:\\", see MSDN: PathIsPrefix
  196. bool IsRelative() { return 0 != ::PathIsRelative(m_path); } ///< returns true if the path is relative, see MSDN: PathIsRelative
  197. bool IsRoot() { return 0 != ::PathIsRoot(m_path); } ///< returns true if path is a directory root, see MSDN: PathIsRoot
  198. 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
  199. bool IsUNC() { return 0 != ::PathIsUNC(m_path); } ///< returns true if the path is a UNC specification, see MSDN: PathIsUNC
  200. bool IsUNCServer() { return 0 != ::PathIsUNCServer(m_path); } ///< returns true if the path is a UNC server specification, see MSDN: PathIsUNCServer
  201. bool IsUNCServerShare() { return 0 != ::PathIsUNCServerShare(m_path); } ///< returns true if the path is a UNC server + share specification, see MSDN: PathIsUNCServerShare
  202. bool IsURL() { return 0 != ::PathIsURL(m_path); } ///< returns true if the path is an URL, see MSDN: PathIsURL
  203. // bool IsHTMLFile() { return 0 != ::PathIsHTMLFile(m_path); } ///< (missing?) true if content type registered for this file is HTML, see MSDN: PathIsHTMLFile
  204. // bool IsLFNFileSpec() { return 0 != ::PathISLFNFileSpec(m_path); } ///< (missing?) true if file is not a 8.3 file, see MSDN: PathIsLFNFileSpec
  205. // bool IsNetworkPath() { return 0 != ::PathIsNetworkPath(m_path); } ///< (missing?) returns true if the path is on a network, see MSDN: PathIsNetworkPath
  206. //@}
  207. //@{ \name Relative Paths
  208. CPath GetCommonPrefix(LPCTSTR secondPath);
  209. CPath RelativePathTo(LPCTSTR pathTo, bool srcIsDir = true);
  210. bool MakeRelative(CPath const & basePath);
  211. bool MakeAbsolute(CPath const & basePath);
  212. //@}
  213. //@{ \name Dialog control operations
  214. CString GetCompactStr(HDC dc, UINT dx, DWORD eppFlags = 0);
  215. CString GetCompactStr(UINT cchMax, DWORD eppFlags = 0, DWORD flags = 0);
  216. void SetDlgItem(HWND dlg, UINT dlgCtrlID, DWORD eppFlags = 0);
  217. //@}
  218. //@{ \name File System / Environment-Dependent operations
  219. CPath & SearchAndQualify();
  220. CPath & FindOnPath(LPCTSTR * additionalDirs = 0);
  221. bool Exists() const;
  222. bool IsDirectory() const;
  223. bool IsSystemFolder(DWORD attrib = FILE_ATTRIBUTE_SYSTEM) const;
  224. CPath & MakeSystemFolder(bool make = true);
  225. DWORD GetAttributes();
  226. bool GetAttributes(WIN32_FILE_ATTRIBUTE_DATA & fad);
  227. CPath & MakeFullPath();
  228. CPath & ExpandEnvStrings();
  229. bool EnvUnexpandRoot(LPCTSTR envVar);
  230. bool EnvUnexpandDefaultRoots();
  231. long ToRegistry(HKEY baseKey, LPCTSTR subkey, LPCTSTR name, bool replaceEnv = true);
  232. //@}
  233. // TODO: Shell 5.0 support
  234. // V5: CPath & UnexpandEnvStrings();
  235. // V5: LPCTSTR FindSuffixArray(LPCTSTR suffixes, int numSuffixes);
  236. // V5: void PathUndecorate();
  237. // V5: CPath PathCreateFromURL(LPCTSTR path, DWORD dwReserved = 0);
  238. // V5: bool IsDirectoryEmpty() const;
  239. // might be useful for later extensions: PathGetCharType
  240. };
  241. // creation functions:
  242. CPath SplitArgs(CString const & path_args, CString * args = NULL, DWORD cleanup = epc_Default);
  243. CPath SplitIconLocation(CString const & path_icon, int * pIcon = NULL, DWORD cleanup = epc_Default);
  244. CPath BuildRoot(int driveNumber);
  245. CPath GetModuleFileName(HMODULE module = NULL);
  246. CPath GetCurrentDirectory();
  247. CPath FromRegistry(HKEY baseKey, LPCTSTR subkey, LPCTSTR name);
  248. CString ReplaceInvalid(CString const & str, TCHAR replaceChar = '_');
  249. // concatenation
  250. inline CPath operator & (CPath const & lhs, LPCTSTR rhs) { CPath ret = lhs; ret &= rhs; return ret; }
  251. // ---------------- INLIME IMPLEMENTATIONS ----------------------------------
  252. // ==============================================
  253. // GetFirstChar
  254. // ----------------------------------------------
  255. /// \return [TCHAR]: the first char of the string, or 0 if the string length is 0.
  256. /// \note The implementation takes care that the string is not copied when there are no spaces.
  257. inline TCHAR GetFirstChar(CString const & s)
  258. {
  259. if (s.GetLength() == 0)
  260. return 0;
  261. else
  262. return s[0];
  263. }
  264. // ==============================================
  265. // GetLastChar
  266. // ----------------------------------------------
  267. /// \return [TCHAR]: the last character in the string, or 0 if the string length is 0.
  268. /// \par Note
  269. /// \b MBCS: if the string ends with a Multibyte character, this
  270. /// function returns the lead byte of the multibyte sequence.
  271. inline TCHAR GetLastChar(CString const & s)
  272. {
  273. LPCTSTR pstr = s;
  274. LPCTSTR pLastChar = _tcsdec(pstr, pstr + s.GetLength());
  275. if (pLastChar == NULL)
  276. return 0;
  277. else
  278. return *pLastChar;
  279. }
  280. } // namespace nsPath
  281. #endif // FILE_PH_PATH_H_200506202_INCLUDED_