Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

728 lines
25 KiB

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. PATH.H
  5. History:
  6. --*/
  7. #ifndef __PATH_H__
  8. #define __PATH_H__
  9. #ifndef _INC_DIRECT
  10. #include <direct.h>
  11. #endif
  12. #ifndef _INC_IO
  13. #include <io.h>
  14. #endif
  15. #ifndef _INC_TCHAR
  16. #include <tchar.h>
  17. #endif
  18. #ifndef _WIN32
  19. #include <ctype.h>
  20. #endif
  21. #ifndef _INC_STAT
  22. #include <stat.h>
  23. #endif
  24. #pragma warning(disable : 4275 4251)
  25. size_t RemoveNewlines(_TCHAR *);
  26. //
  27. // Compatible_GetFileAttributesEx
  28. // g_pGetFileAttributesEx initially points to a function that chooses the new win32 api,
  29. // GetFileAttributesEx if supported, or selects a compatible function that uses FindFirstFile.
  30. //
  31. extern BOOL AFX_DATA (WINAPI *g_pGetFileAttributesEx)( LPCTSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
  32. LPVOID lpFileInformation);
  33. __inline BOOL Compatible_GetFileAttributesEx( LPCTSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
  34. LPVOID lpFileInformation)
  35. {
  36. return (*g_pGetFileAttributesEx)( lpFileName, fInfoLevelId, lpFileInformation);
  37. }
  38. //////////////////////////////////////////////////////////////////////
  39. // Classes defined in this file
  40. // CObject
  41. class CPath;
  42. class CDir;
  43. //////////////////////////////////////////////////////////////////////
  44. // Scan a path in see if it contains special charaters that would
  45. // required it to be quoted:
  46. BOOL ScanPathForSpecialCharacters (const TCHAR *pPath);
  47. //////////////////////////////////////////////////////////////////////
  48. // CPath
  49. class LTAPIENTRY CPath : public CObject
  50. {
  51. DECLARE_DYNAMIC(CPath)
  52. friend class CDir;
  53. friend static VOID ConstructElement(CPath *);
  54. friend static VOID DestructElement(CPath *);
  55. protected:
  56. // Data
  57. CString m_strCanon;
  58. int m_ichLastSlash; // used to quickly extract only dir or filename
  59. BOOL m_Flags;
  60. enum PathFlags
  61. {
  62. eIsActualCase = 1,
  63. eWantsRelative = 2,
  64. };
  65. // Canonicalized representation of pathname.
  66. static CMapStringToString c_DirCaseMap;
  67. public:
  68. // Constructors, destructors, initialization methods
  69. inline CPath() { m_ichLastSlash = -1; m_Flags = 0;}
  70. inline CPath(const CPath & path)
  71. {
  72. m_strCanon = path.m_strCanon;
  73. m_ichLastSlash = path.m_ichLastSlash;
  74. m_Flags = path.m_Flags;
  75. }
  76. virtual ~CPath();
  77. inline BOOL GetAlwaysRelative() const { return ((m_Flags & eWantsRelative) != 0); }
  78. inline void SetAlwaysRelative(BOOL bWantsRel = TRUE) { m_Flags =
  79. (bWantsRel) ? m_Flags | eWantsRelative : m_Flags & ~eWantsRelative;}
  80. inline BOOL IsInit() const { ASSERT(this!=NULL); return (m_ichLastSlash > 0); }
  81. BOOL Create(const TCHAR *);
  82. // Initialize the object, given a filename. The resulting
  83. // canonicalized filename will be relative to the current
  84. // directory. For example, if the current directory is
  85. // C:\TEST and the argument is "FOO.C", the resulting
  86. // canonicalized filename will be "C:\TEST\FOO.C". If the
  87. // argument is "..\FOO.C", the resulting canonicalized
  88. // filename will be "C:\FOO.C".
  89. BOOL CreateFromDirAndFilename(const CDir &, const TCHAR *);
  90. // Initialize the object given a directory (CDir object) and
  91. // a filename. This behaves exactly the same as the Create()
  92. // method, except that the Create() method canonicalizes the
  93. // filename relative to the CURRENT directory, whereas this
  94. // method canonicalizes the filename relative to the SPECIFIED
  95. // directory.
  96. BOOL CreateTemporaryName(const CDir &, BOOL fKeep = TRUE);
  97. // Initialize the object given a directory. The resulting
  98. // object will represent a UNIQUE filename in that directory.
  99. // This is useful for creating temporary filenames.
  100. //
  101. // WARNING
  102. // -------
  103. // After this method returns, the filename represented by this
  104. // object will EXIST ON DISK as a zero length file. This is
  105. // to prevent subsequent calls to this method from returning
  106. // the same filename (this method checks to make sure it
  107. // doesn't return the name of an existing file). IT IS YOUR
  108. // RESPONSIBILITY to delete the file one way or another.
  109. //
  110. // If you don't want this behavior, pass FALSE for 'fKeep',
  111. // and the file will not exist on disk. Be aware, though,
  112. // that if you do this, subsequent calls to this method may
  113. // return the same filename.
  114. BOOL ContainsSpecialCharacters () const
  115. {
  116. return ::ScanPathForSpecialCharacters(m_strCanon);
  117. }
  118. // Scan the pathname for special character. We cache this
  119. // information.
  120. inline CPath & operator =(const CPath & path)
  121. {
  122. ASSERT(path.IsInit());
  123. m_strCanon = path.m_strCanon;
  124. m_ichLastSlash = path.m_ichLastSlash;
  125. m_Flags = path.m_Flags;
  126. return(*this);
  127. }
  128. // Assignment operator.
  129. // Query methods
  130. inline const TCHAR * GetFileName() const
  131. {
  132. ASSERT(IsInit());
  133. ASSERT(m_ichLastSlash==m_strCanon.ReverseFind('\\'));
  134. return ((const TCHAR *)m_strCanon + m_ichLastSlash + 1);
  135. }
  136. // Return a pointer to the filename part of the canonicalized
  137. // pathname, i.e., the filename with no leading drive or path
  138. // information. Return whole string if no backslash (not init).
  139. //
  140. // Please do not write through this pointer, as it is pointing
  141. // to internal data!
  142. VOID PostFixNumber();
  143. // Modifies the path by postfixing a number on the end of the path's
  144. // basename. If there is no number on the end of the path's basename
  145. // then the number 1 is postfixed. Otherwise if there already is a
  146. // number on the end of the path's basename then that number is
  147. // incremented by 1 and postfixed on the end of the basename (less the
  148. // original number).
  149. //
  150. // e.g. foo.cpp -> foo1.cpp -> foo2.cpp -> foo3.cpp
  151. VOID GetBaseNameString(CString &) const;
  152. // Creates a CString representing the base name of the fully
  153. // canonicalized pathname. For example, the base name of
  154. // the pathname "C:\FOO\BAR.C" is "BAR".
  155. //
  156. // This method can't return a pointer to internal data like
  157. // some of the other methods since it would have to remove
  158. // the extension in order to do so.
  159. VOID GetDisplayNameString(
  160. CString &,
  161. int cchMax = 16,
  162. BOOL bTakeAllAsDefault = FALSE
  163. ) const;
  164. // Creates a CString representing the name of the file
  165. // shortened to cchMax CHARACTERS (TCHARs, not bytes) or
  166. // less. Only the actual characters are counted; the
  167. // terminating '\0' is not considered, so
  168. // CString::GetLength() on the result MAY return as much as
  169. // cchMax. If cchMax is less than the length of the base
  170. // filename, the resulting CString will be empty, unless
  171. // bTakeAllAsDefault is TRUE, in which the base name is
  172. // copied in, regardless of length.
  173. //
  174. // As an example, "C:\SOMEDIR\OTHERDIR\SUBDIR\SPECIAL\FOO.C"
  175. // will be shortened to "C:\...\SPECIAL\FOO.C" if cchMax is 25.
  176. inline const TCHAR * GetExtension() const
  177. {
  178. ASSERT(IsInit());
  179. int iDot = m_strCanon.ReverseFind(_T('.'));
  180. if (iDot < m_ichLastSlash)
  181. iDot = m_strCanon.GetLength();
  182. const TCHAR * retval = ((const TCHAR *)m_strCanon) + iDot;
  183. return retval;
  184. }
  185. // Return a pointer to the extension part of the canonicalized
  186. // pathname. Returns a pointer to the '.' character of the
  187. // extension. If the filename doesn't have an extension,
  188. // the pointer returned will point to the terminating '\0'.
  189. //
  190. // Please do not write through this pointer, as it is pointing
  191. // to internal data!
  192. inline const TCHAR * GetFullPath() const { return(m_strCanon); }
  193. // Return a pointer to the full (canonicalized) pathname.
  194. //
  195. // Please do not write through this pointer, as it is pointing
  196. // to internal data!
  197. inline const TCHAR * GetFullPath(CString & strPath) const { return(strPath = m_strCanon); }
  198. inline BOOL IsActualCase() const { ASSERT(this!=NULL); return ((m_Flags & eIsActualCase)!=0); }
  199. void GetActualCase(BOOL bEntirePath = FALSE);
  200. // Adjusts the paths case to match the actual path and filename
  201. // on disk.
  202. void SetActualCase(LPCTSTR pszFileCase);
  203. // Adjusts the paths case to match the actual path and filename
  204. // on disk, where pszFileCase already contains the correct case
  205. // for just the filename portion.
  206. static void ResetDirMap();
  207. inline operator const TCHAR *() const { return(m_strCanon); }
  208. // Return the fully canonicalized filename as a (const TCHAR *).
  209. // Same thing as GetFullPath(), but more convenient in some
  210. // cases.
  211. //
  212. // Please do not write through this pointer, as it is pointing
  213. // to internal data!
  214. inline BOOL IsUNC() const { return(m_strCanon[0] == _T('\\')); }
  215. // Returns TRUE if the pathname is UNC (e.g.,
  216. // "\\server\share\file"), FALSE if not.
  217. inline BOOL IsEmpty() const { return (m_strCanon.IsEmpty()); }
  218. // Comparison methods
  219. int operator ==(const CPath &) const;
  220. // Returns 1 if the two CPaths are identical, 0 if they are
  221. // different.
  222. inline int operator !=(const CPath & path) const { return(!(operator ==(path))); }
  223. // Returns 1 if the two CPaths are different, 0 if they are
  224. // identical.
  225. // Modification methods
  226. VOID ChangeFileName(const TCHAR *);
  227. // Changes the file name to that specified by the
  228. // (const TCHAR *) argument. The directory portion of the
  229. // pathname remains unchanged. DO NOT pass in anything
  230. // other than a simple filename, i.e., do not pass in
  231. // anything with path modifiers.
  232. VOID ChangeExtension(const TCHAR *);
  233. // Changes the extension of the pathname to be that specified
  234. // by the (const TCHAR *) argument. The argument can either be
  235. // of the form ".EXT" or "EXT". If the current pathname has
  236. // no extension, this is equivalent to adding the new extension.
  237. BOOL GetRelativeName (const CDir&, CString&, BOOL bQuote = FALSE, BOOL bIgnoreAlwaysRelative = FALSE) const;
  238. // Makes the path name relative to the supplied directory and
  239. // placed the result in strResult. Function will only go
  240. // down from the supplied directy (no ..'s). Returns TRUE if
  241. // relativization was successful, or FALSE if not (e.g. if
  242. // string doesn't start with ".\" or ..\ or at least \).
  243. //
  244. // Thus, if the base directory is c:\sushi\vcpp32:
  245. //
  246. // s:\sushi\vcpp32\c\fmake.c => s:\sushi\vcpp32\c\fmake.c
  247. // c:\sushi\vcpp32\c\fmake.c => .\fmake.c
  248. // c:\dolftool\bin\cl.exe => \dolftool\bin\cl.exe
  249. // \\danwhite\tmp\test.cpp => \\danwhite\tmp\test.cpp
  250. // Thus, if the base directory is \\danwhite\c$\sushi\vcpp32:
  251. //
  252. // \\danwhite\c$\dolftool\bin\cl.exe => \dolftool\bin\cl.exe
  253. // \\danwhite\tmp\test.cpp => \\danwhite\tmp\test.cpp
  254. // If bQuote is true, then quotes are put around the relative
  255. // file name. (Useful for writing the filename out to a file)
  256. // If (!bIgnoreAlwaysRelative && GetAlwaysRelative()) is TRUE
  257. // and if the file is on the same drive we will ALWAYS
  258. // relativize it. Thus for the base dir c:\sushi\vcpp32
  259. // c:\dolftool\bin\cl.exe => ..\..\dolftool\bin\cl.exe
  260. BOOL CreateFromDirAndRelative (const CDir&, const TCHAR *);
  261. // THIS FUNCTION IS OBSOLETE. New code should use
  262. // CreateFromDirAndFilename(). The only difference between
  263. // that function and this one is that this one will
  264. // automatically remove quotes from around the relative
  265. // path name (if present).
  266. // Miscellaneous methods
  267. inline BOOL IsReadOnlyOnDisk() const
  268. {
  269. HANDLE h;
  270. ASSERT(IsInit());
  271. h = CreateFile(m_strCanon, GENERIC_WRITE,
  272. FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
  273. FILE_ATTRIBUTE_NORMAL, NULL);
  274. if (h == INVALID_HANDLE_VALUE && GetLastError() != ERROR_FILE_NOT_FOUND)
  275. return TRUE;
  276. if (h != INVALID_HANDLE_VALUE)
  277. CloseHandle(h);
  278. return FALSE;
  279. }
  280. // Returns TRUE if the filename represented by this object
  281. // is read-only on disk, FALSE if not. NOT guaranteed to
  282. // work in all circumstances -- for example, will not return
  283. // TRUE for a file on a floppy drive that has been write-
  284. // protected. I don't know of any way to get this information
  285. // from NT (GetFileAttributes doesn't work; GetVolumeInformation
  286. // doesn't work; _access just calls GetFileAttributes; etc.).
  287. // This method WILL correctly detect:
  288. // - Files marked as read-only
  289. // - Files on read-only network drives
  290. inline BOOL ExistsOnDisk() const
  291. {
  292. ASSERT(IsInit());
  293. return(_access(m_strCanon, 00) != -1);
  294. }
  295. // Returns TRUE if the filename represented by this object
  296. // exists on disk, FALSE if not.
  297. inline BOOL CanCreateOnDisk(BOOL fOverwriteOK = FALSE) const
  298. {
  299. ASSERT(IsInit());
  300. if (!fOverwriteOK && ExistsOnDisk())
  301. return(FALSE);
  302. int hFile = _creat(m_strCanon, _S_IREAD | _S_IWRITE);
  303. BOOL fCreate = (hFile != -1);
  304. if (fCreate)
  305. {
  306. VERIFY(_close(hFile) == 0);
  307. VERIFY(_unlink(m_strCanon) == 0);
  308. }
  309. return(fCreate);
  310. }
  311. // Returns TRUE if the filename represented by this object
  312. // can be created on disk, FALSE if not.
  313. inline BOOL DeleteFromDisk() const
  314. {
  315. ASSERT(IsInit());
  316. #ifdef _WIN32
  317. return(DeleteFile((TCHAR *)(const TCHAR *)m_strCanon));
  318. #else
  319. return(remove(m_strCanon) != -1);
  320. #endif
  321. }
  322. // Removes the file represented by this object from the disk.
  323. BOOL GetFileTime(LPFILETIME lpftLastWrite);
  324. BOOL GetFileTime(CString& rstrLastWrite, DWORD dwFlags = DATE_SHORTDATE);
  325. // Returns the last modified time, as either an FILETIME struct or a string
  326. };
  327. // Creation and destruction functions used by CMapPathToOb:
  328. extern const CString AFX_DATA pthEmptyString;
  329. static inline VOID ConstructElement(CPath * pNewData)
  330. {
  331. memcpy(&pNewData->m_strCanon, &pthEmptyString, sizeof(CString));
  332. }
  333. static inline VOID DestructElement(CPath * pOldData)
  334. {
  335. pOldData->m_strCanon.Empty();
  336. }
  337. // File Name Utility Functions
  338. // These are redundant and could be replaced with use of CPath, but are
  339. // kept since they are easier to use and already exist in VRES.
  340. // Remove the drive and directory from a file name.
  341. CString StripPath(LPCTSTR szFilePath);
  342. // Remove the name part of a file path. Return just the drive and directory.
  343. CString StripName(LPCTSTR szFilePath);
  344. // Get only the extension of a file path.
  345. CString GetExtension(LPCTSTR szFilePath);
  346. // Return the path to szFilePath relative to szDirectory. (e.g. if szFilePath
  347. // is "C:\FOO\BAR\CDR.CAR" and szDirectory is "C:\FOO", then "BAR\CDR.CAR"
  348. // is returned. This will never use '..'; if szFilePath is not in szDirectory
  349. // or a sub-directory, then szFilePath is returned unchanged.
  350. //
  351. CString GetRelativeName(LPCTSTR szFilePath, LPCTSTR szDirectory = NULL);
  352. // Makes a file path look like in MRU.
  353. CString GetDisplayName(LPCTSTR szFilePath, int nMaxDisplayLength,
  354. LPCTSTR szDirectory = NULL);
  355. BOOL FileExists(LPCTSTR szFilePath);
  356. BOOL IsFileWritable(LPCTSTR szFilePath);
  357. UINT SushiGetFileTitle(LPCTSTR lpszPathName, LPTSTR lpszTitle, UINT nMax);
  358. //////////////////////////////////////////////////////////////////////
  359. // CDir
  360. //
  361. // The CDir object represents a file system directory on some disk.
  362. //
  363. // A CDir object can be created to represent the current directory,
  364. // to represent the directory of a CPath object (i.e., the directory
  365. // in which a file resides), and to represent a temporary directory.
  366. // Note that a CDir object CANNOT be created given an arbitrary string --
  367. // this is intentional, since this should not be necessary.
  368. //
  369. // The string representation of a CDir object (e.g., operator const TCHAR *())
  370. // MAY or MAY NOT end in '\'. The root directory of a local drive (e.g., C:)
  371. // will end in '\' ("C:\"), while other directories on a local drive will
  372. // not ("C:\OTHERDIR"). The root directory on a REMOTE drive will NOT end
  373. // in '\' ("\\server\share"). Don't make any assumptions about whether or
  374. // not the string representation ends in '\'.
  375. //
  376. // See also several CPath methods which use CDir objects.
  377. class LTAPIENTRY CDir : public CObject
  378. {
  379. DECLARE_DYNAMIC(CDir)
  380. friend class CPath;
  381. friend static VOID ConstructElement(CDir *);
  382. friend static VOID DestructElement(CDir *);
  383. protected:
  384. CString m_strDir;
  385. // Directory name, including drive letter or
  386. // server/share. Do NOT make any assumptions
  387. // about whether or not this ends in '\'!
  388. // Creates multi level directories just fine
  389. BOOL MakeDirectory(LPCTSTR lpszPathName) const;
  390. public:
  391. // Constructors, destructors, initialization methods
  392. inline CDir() {}
  393. inline CDir(const CDir & dir) { m_strDir = dir.m_strDir; }
  394. virtual ~CDir();
  395. BOOL CreateFromCurrent();
  396. // Initialize from the current working directory. This
  397. // may fail if the current working directory is unknown
  398. // or invalid.
  399. BOOL CreateFromPath(const CPath &);
  400. // Initialize based on the directory of the specified
  401. // CPath object. That is, if the CPath object represents
  402. // the file "C:\FOO\BAR\BLIX.C", the resulting directory
  403. // for this object will be "C:\FOO\BAR". Returns FALSE
  404. // on failure.
  405. BOOL CreateFromPath(const TCHAR *pszPath);
  406. // Initialize based on the directory of the specified
  407. // string. That is, if the string contains the file name
  408. // "C:\FOO\BAR\BLIX.C", the generated directory for this
  409. // string will be "C:\FOO\BAR". Returns FALSE on failure.
  410. BOOL CreateTemporaryName();
  411. // Initialize this object to represent a temporary directory
  412. // on disk (e.g., "C:\TMP").
  413. inline BOOL CreateFromString(const TCHAR * sz)
  414. {
  415. return CreateFromStringEx(sz, FALSE);
  416. }
  417. // Create from a string (e.g., "C:\", "C:\TMP", etc.). Please
  418. // do not use this method when another would suffice!
  419. BOOL CreateFromStringEx(const TCHAR * sz, BOOL fRootRelative);
  420. // Create from a string (e.g., "C:\", "C:\TMP", etc.). Please
  421. // do not use this method when another would suffice!
  422. // same as CreateFromString with minor change. Not treating as bug fix to CFS
  423. // due to lateness in VC 4.0 project time
  424. // if fRootRelative true, treat dir ending with colon as relative not root dir
  425. // (actual correct handling)
  426. BOOL ContainsSpecialCharacters () const
  427. {
  428. return ::ScanPathForSpecialCharacters(m_strDir);
  429. }
  430. // Scan the pathname for special character. We cache this information.
  431. inline CDir & operator =(const CDir & dir)
  432. {
  433. m_strDir = dir.m_strDir;
  434. return(*this);
  435. }
  436. // Assignment operator.
  437. // Query methods
  438. inline operator const TCHAR *() const { return(m_strDir); }
  439. // Return the directory name as a (const TCHAR *) string.
  440. inline int GetLength() const { return m_strDir.GetLength(); }
  441. // Returns the length of the directory name
  442. // Miscellaneous methods
  443. BOOL MakeCurrent() const;
  444. // Make this object the current working directory. May fail
  445. // if the directory no longer exists (e.g., a floppy drive).
  446. inline BOOL ExistsOnDisk() const
  447. {
  448. // Tests if the directory exists. We return FALSE
  449. // if <m_strDir> exists but is not a directory
  450. struct _stat statDir;
  451. if (_stat(m_strDir, &statDir) == -1)
  452. return FALSE; // Not found.
  453. else if (!(statDir.st_mode & _S_IFDIR))
  454. return FALSE; // Not a directory.
  455. else
  456. return TRUE;
  457. }
  458. // Returns TRUE if the directory represented by this object
  459. // exists on disk, FALSE if not.
  460. inline BOOL CreateOnDisk() const { return MakeDirectory(m_strDir); }
  461. // Creates the directory on disk. If this fails, returns
  462. // FALSE. If the directory already existed on disk, returns
  463. // TRUE (i.e., that is not an error condition).
  464. inline BOOL RemoveFromDisk() const { return RemoveDirectory(m_strDir); }
  465. // Removes the directory from the disk. If this fails for
  466. // any reason (directory does not exist, directory is not
  467. // empty, etc.), returns FALSE.
  468. BOOL IsRootDir() const;
  469. // Returns TRUE if the directory represented by this object
  470. // is a root directory (e.g., "C:\"), FALSE if not. Note that
  471. // calling this method will NOT tell you whether or not the
  472. // string representation ends in '\', since "\\server\share"
  473. // is a root directory, and does not end in '\'.
  474. inline BOOL IsUNC() const { return(m_strDir[0] == _T('\\')); }
  475. // Returns TRUE if this is a UNC directory, FALSE if not.
  476. VOID AppendSubdirName(const TCHAR *);
  477. // Adds a subdirectory name. For example, if this object
  478. // currently represents "C:\FOO\BAR", and the argument is
  479. // "$AUTSAV$", the resulting object represents
  480. // "C:\FOO\BAR\$AUTSAV$".
  481. //
  482. // WARNING: This method does NO validation of the result --
  483. // it does not check for illegal characters, or for a
  484. // directory name that is too long. In particular, don't
  485. // pass "DIR1/DIR2" as an argument, since no conversion
  486. // (of '/' to '\') will occur.
  487. VOID RemoveLastSubdirName();
  488. // Removes the last component of the directory name. For
  489. // example, if this object currently represents
  490. // "C:\FOO\BAR\$AUTSAV$", after this method it will
  491. // represent "C:\FOO\BAR". If you try to call this method
  492. // when the object represents a root directory (e.g., "C:\"),
  493. // it will ASSERT.
  494. // Comparison methods
  495. int operator ==(const CDir &) const;
  496. // Returns 1 if the two CDirs are identical, 0 if they are
  497. // different.
  498. inline int operator !=(const CDir & dir) const { return(!(operator ==(dir))); }
  499. // Returns 1 if the two CDirs are different, 0 if they are
  500. // identical.
  501. };
  502. // Creation and destruction functions used by CMapDirToOb:
  503. static inline VOID ConstructElement(CDir * pNewData)
  504. {
  505. memcpy(&pNewData->m_strDir, &pthEmptyString, sizeof(CString));
  506. }
  507. static inline VOID DestructElement(CDir * pOldData)
  508. {
  509. pOldData->m_strDir.Empty();
  510. }
  511. ///////////////////////////////////////////////////////////////////////////////
  512. // CCurDir
  513. // This class is used to switch the current drive/directory during the
  514. // life of the object and to restore the previous dirve/directory upon
  515. // destruction.
  516. class LTAPIENTRY CCurDir : CDir
  517. {
  518. public:
  519. CCurDir(const char* szPath, BOOL bFile = FALSE);
  520. CCurDir(const CDir& dir);
  521. CCurDir(); // just saves the current directory and resets it
  522. ~CCurDir();
  523. CDir m_dir;
  524. };
  525. ///////////////////////////////////////////////////////////////////////////////
  526. // CFileOpenReturn
  527. // This class represents the return value from the Common Dialogs
  528. // File.Open. It handles both single and multiple select types.
  529. //
  530. class LTAPIENTRY CFileOpenReturn : CObject
  531. {
  532. BOOL m_bSingle;
  533. BOOL m_bBufferInUse;
  534. BOOL m_bArrayHasChanged;
  535. int m_cbData;
  536. _TCHAR * m_pchData;
  537. // Multiple Files
  538. CPtrArray m_rgszNames;
  539. public:
  540. CFileOpenReturn (const _TCHAR * szRawString = NULL);
  541. ~CFileOpenReturn ();
  542. inline BOOL IsSingle () const;
  543. inline BOOL IsDirty() const;
  544. inline BOOL BufferOverflow () const;
  545. //inline int GetLength () const;
  546. // GetBuffer gives permission for something else to directly change the buffer
  547. // ReleaseBuffer signifies that the something else is done with it.
  548. _TCHAR * GetBuffer (int cbBufferNew);
  549. inline void ReleaseBuffer ();
  550. // allows the object to be re-initialized
  551. void ReInit (const _TCHAR * szRawString);
  552. // This supports the dynamic file extension update in OnFileNameOK().
  553. void ChangeExtension (int i, const CString& szExt);
  554. void CopyBuffer (_TCHAR * szTarget);
  555. // This is the function to use to get at the user's selections,
  556. // whether single or multiple.
  557. BOOL GetPathname (int i, CString& strPath) const;
  558. private:
  559. void GenArrayFromBuffer ();
  560. void GenBufferFromArray ();
  561. void ClearNamesArray ();
  562. void SetBuffer (const _TCHAR * szRawString);
  563. };
  564. inline BOOL CFileOpenReturn::IsSingle () const
  565. {
  566. return m_bSingle;
  567. }
  568. inline BOOL CFileOpenReturn::IsDirty() const
  569. {
  570. return m_bArrayHasChanged;
  571. }
  572. inline BOOL CFileOpenReturn::BufferOverflow () const
  573. {
  574. return m_cbData == 2 && m_pchData[0] == '?';
  575. }
  576. ///// ReleaseBuffer - Tell object we're done changing the buffer
  577. //
  578. // Processes the raw string
  579. //
  580. ///
  581. inline void CFileOpenReturn::ReleaseBuffer ()
  582. {
  583. m_bBufferInUse = FALSE;
  584. GenArrayFromBuffer ();
  585. }
  586. ///////////////////////////////////////////////////////////////////////////////
  587. // Smart case helpers.
  588. // These functions are used to do smart casing of paths and file extensions.
  589. extern BOOL GetActualFileCase( CString& rFilename, LPCTSTR lpszDir = NULL );
  590. extern LPCTSTR GetExtensionCase( LPCTSTR lpszFilename, LPCTSTR lpszExtension );
  591. extern BOOL GetDisplayFile(CString &rFilename, CDC *pDC, int &cxPels); // truncates from left
  592. /////////////////////////////////////////////////////////////////////////////
  593. #pragma warning(default : 4275 4251)
  594. #endif // __PATH_H__