Source code of Windows XP (NT5)
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.

621 lines
17 KiB

  1. // Copyright (c) 1997-1999 Microsoft Corporation
  2. //
  3. // File System services.
  4. //
  5. // 8-14-97 (sburns)
  6. #ifndef FILESYS_HPP_INCLUDED
  7. #define FILESYS_HPP_INCLUDED
  8. // CODEWORK: remove exceptions in favor of an HRESULT orientation.
  9. namespace Burnslib
  10. {
  11. namespace FS
  12. {
  13. // Facilitates walking a directory tree.
  14. // CODEWORK: add methods to extract current file data beyond just the
  15. // name.
  16. class Iterator
  17. {
  18. public:
  19. enum
  20. {
  21. INCLUDE_FILES = 0x0001,
  22. INCLUDE_FOLDERS = 0x0002,
  23. INCLUDE_DOT_PATHS = 0x0004,
  24. // CODEWORK:
  25. // EXPAND_SUBDIRS = 0x0008,
  26. RETURN_FULL_PATHS = 0x0010
  27. };
  28. // Constructs a new instance of an Iterator.
  29. //
  30. // startingPathSpec - fully-qualified path specification of the
  31. // files/directories to be iterated upon. A wildcard
  32. // specification is allowed at the end of the path. E.g.
  33. // "C:\dir\*.txt"
  34. //
  35. // (Without a wildcard expression of some kind, the iteration set will
  36. // be the single file or folder that matches startingPathSpec. This set
  37. // may be further reduced to the empty set if the optionMask eliminates
  38. // the single match.)
  39. //
  40. // optionMask - Options, OR'ed together.
  41. explicit
  42. Iterator(
  43. const String& startingPathSpec,
  44. unsigned optionMask =
  45. INCLUDE_FILES
  46. | INCLUDE_FOLDERS
  47. | INCLUDE_DOT_PATHS
  48. /* | EXPAND_SUBDIRS */
  49. | RETURN_FULL_PATHS);
  50. ~Iterator();
  51. // Restores the iterator to the state that it had upon
  52. // construction.
  53. void
  54. Reset();
  55. // Retrieve the name of the file at the current iterator position. If
  56. // the iterator was constructed with the RETURN_FULL_PATHS Option, then
  57. // the returned string is a fully-qualified path, instead of a path
  58. // relative to the starting path the Iterator was constructed with.
  59. // Returns S_OK on success, S_FALSE if the iteration is empty (there are
  60. // no files), or an error code.
  61. //
  62. // If AtEnd() is true, then the empty string is returned.
  63. //
  64. // result - receives the file path at the current position of the
  65. // iterator, or the empty string if the iteration set is empty, or
  66. // an error occurred.
  67. HRESULT
  68. GetCurrent(String& result);
  69. // Move the current position to the next file, according to the
  70. // iterator filtering options. May cause the iterator to become
  71. // invalid, which can be tested with AtEnd(). Returns S_OK on success
  72. // S_FALSE when the iteration is complete, or an error code.
  73. HRESULT
  74. Increment();
  75. private:
  76. WIN32_FIND_DATA* findData;
  77. HANDLE findHandle;
  78. bool finished;
  79. unsigned options;
  80. String parentFolder;
  81. String startSearchSpec;
  82. void
  83. Finish();
  84. bool
  85. IsNotStarted();
  86. String
  87. ReturnPath();
  88. bool
  89. ShouldSkipCurrent();
  90. HRESULT
  91. Start();
  92. HRESULT
  93. SkipFilteredPaths();
  94. // copying not implemented in the interest of simplicity (could be done
  95. // in theory)
  96. Iterator(const Iterator&);
  97. const Iterator& operator=(const Iterator&);
  98. };
  99. // Simple file-to-file copy.
  100. //
  101. // sourceFile - Fully-qalified path of the file to be copied. This
  102. // path must reference an existing file.
  103. //
  104. // destinationFile - Fully-qualified path of the file to be
  105. // created. This file is always overwritten, if it exists. All
  106. // intermediate subdirectories required are created.
  107. //
  108. // progressCallback - Callback object to receive progress
  109. // notifications. The param argument to the callback's Execute
  110. // method will be an instance of CopyCallbackParam. The method
  111. // should return !0 to abort the copy.
  112. struct CopyCallbackParam
  113. {
  114. String sourceFile;
  115. String destinationFile;
  116. int percentCopied;
  117. };
  118. HRESULT
  119. CopyFile(
  120. const String& sourceFile,
  121. const String& destinationFile,
  122. Callback* progressCallback);
  123. // Creates a directory, including all intermediate subdirectories,
  124. // as necessary. Returns S_FALSE if the path already exists.
  125. //
  126. // path - Fully-qualified path to be created. It must not
  127. // already exist.
  128. HRESULT
  129. CreateFolder(const String& path);
  130. // Opens a file for shared read/write access with normal attributes,
  131. // creating it if it does not already exist.
  132. //
  133. // path - Fully-qualified path of file to open. If path doesn't
  134. // exist, it is created, including intermediate subdirectories.
  135. //
  136. // result - receives the resulting file handle, on success. On falure,
  137. // this is set to INVALID_HANDLE_VALUE
  138. HRESULT
  139. CreateFile(
  140. const String& path,
  141. HANDLE& result,
  142. DWORD desiredAccess = GENERIC_READ | GENERIC_WRITE,
  143. DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE,
  144. DWORD creationDisposition = OPEN_ALWAYS,
  145. DWORD flagsAndAttributes = FILE_ATTRIBUTE_NORMAL);
  146. // Splits a fully-qualified path into its constituent parts.
  147. //
  148. // drive - receives the volume portion (in the form "X:")
  149. //
  150. // parentFolderPath - receives the path of the folder containing the leaf
  151. // file or folder.
  152. //
  153. // leafName - receives the base name of the last file or folder on the
  154. // path.
  155. //
  156. // extension - receives the extension, of the last file or folder on the
  157. // path, including the dot (".ext")
  158. void
  159. SplitPath(
  160. const String& fullpath,
  161. String& drive,
  162. String& parentFolderPath,
  163. String& leafName,
  164. String& extension);
  165. // Appends an unqualified relative path (i.e. system32\cys.exe) to the
  166. // the base path supplied and returns the full path. A '\' will be added
  167. // between the parts if needed. If the base path is not normalized the
  168. // result will not be normalized either.
  169. //
  170. // base - fully-qualified path which will be appended to
  171. //
  172. // additional - unqualified relative path which will be appended
  173. String
  174. AppendPath(
  175. const String& base,
  176. const String& additional);
  177. // Returns the leaf portion of a fully-qualified path, including the
  178. // extension. The path may refer to either a file or a folder. For
  179. // example, "x:\foo\bar.ext" returns "bar.ext"
  180. //
  181. // fullpath - fully-qualified filename.
  182. String
  183. GetPathLeafElement(const String& fullpath);
  184. // Removes the last component of a fully-qualified file name or folder
  185. // name. Includes trailing path separator only if the parent folder is the
  186. // root folder on a volume.
  187. //
  188. // e.g. "x:\foo" returns "x:\", but "x:\foo\bar" returns "x:\foo" (not
  189. // "x:\foo\")
  190. //
  191. // fullpath - fully-qualified filename.
  192. String
  193. GetParentFolder(const String& fullpath);
  194. // Returns the available space, in bytes, to the current user of the
  195. // calling thread (i.e. takes into account user quotas)
  196. //
  197. // path - Fully-qualified path of file/directory for which attributes will
  198. // be retrieved. This need not be the root directory of the volume in
  199. // question.
  200. //
  201. // result - receives the result, the available space in bytes. Set to
  202. // 0 on error.
  203. HRESULT
  204. GetAvailableSpace(const String& path, ULONGLONG& result);
  205. // Returns the root folder path of the given full path, e.g. for
  206. // "C:\foo\bar" returns "C:\"
  207. //
  208. // fullpath - Fully-qualified path of file/directory
  209. String
  210. GetRootFolder(const String& fullpath);
  211. // Reports the current position of the file read/write pointer. Returns
  212. // S_OK on success, or an error code on failure.
  213. //
  214. // handle - valid handle to an opened file
  215. //
  216. // result - receives the file position, set to 0 on error
  217. HRESULT
  218. GetFilePosition(HANDLE handle, LONGLONG& result);
  219. // Returns the total size, in bytes, of the file opened on the provided
  220. // handle.
  221. //
  222. // handle - valid handle to an opened file
  223. //
  224. // result - receives the file size, or 0 on error.
  225. HRESULT
  226. GetFileSize(HANDLE handle, LONGLONG& result);
  227. // Returns the type of the file system of the volume on which the path
  228. // refers. Non-existant paths are considered to have the FAT file system.
  229. //
  230. // path - fully-qualified path, which contains the drive letter of the
  231. // volume
  232. // CODEWORK: how does this behave in the presence of mount points? For
  233. // example, what if a FAT volume is mounted as a subdirectory of an
  234. // NTFS volume?
  235. enum FSType
  236. {
  237. FAT,
  238. CDFS,
  239. NTFS4,
  240. NTFS5
  241. };
  242. FSType
  243. GetFileSystemType(const String& path);
  244. enum PathSyntax
  245. {
  246. SYNTAX_ABSOLUTE_DRIVE, // d:\foo\bar
  247. SYNTAX_ABSOLUTE_DRIVE_WILDCARD, // d:\foo\*.*
  248. SYNTAX_ABSOLUTE_NO_DRIVE, // \foo\bar
  249. SYNTAX_ABSOLUTE_NO_DRIVE_WILDCARD, // \foo\*.*
  250. SYNTAX_RELATIVE_DRIVE, // d:foo\bar
  251. SYNTAX_RELATIVE_DRIVE_WILDCARD, // d:foo\*.*
  252. SYNTAX_RELATIVE_NO_DRIVE, // foo\bar
  253. SYNTAX_RELATIVE_NO_DRIVE_WILDCARD, // foo\*.*
  254. SYNTAX_UNC, // \\machine\share
  255. SYNTAX_UNC_WILDCARD, // \\machine\share\*.*
  256. SYNTAX_UNRECOGNIZED
  257. };
  258. // Parses the supplied string an attempts to validate its syntax. The
  259. // string need not refer to an existing file or directory.
  260. //
  261. // str - the string to be analysed.
  262. PathSyntax
  263. GetPathSyntax(const String& str);
  264. // Populates the given DriveList with elements representing the valid
  265. // drive letters on the local machine. Each element is a string of the
  266. // form "X:" where X is a drive letter.
  267. //
  268. // BackInsertableContainer - any type that supports the construction of
  269. // a back_insert_iterator on itself, and has a value type that can be
  270. // constructed from an PWSTR.
  271. //
  272. // bii - a reference to a back_insert_iterator of the
  273. // BackInsertableContainer template parameter. The simplest way to make
  274. // one of these is to use the back_inserter helper function.
  275. //
  276. // Example:
  277. //
  278. // StringList container;
  279. // hr = FS::GetValidDrives(back_inserter<container>);
  280. //
  281. // StringVector container2;
  282. // hr = FS::GetValidDrives(back_inserter<container2>);
  283. template <class BackInsertableContainer>
  284. HRESULT
  285. GetValidDrives(std::back_insert_iterator<BackInsertableContainer>& bii)
  286. {
  287. HRESULT hr = S_OK;
  288. TCHAR* buf = 0;
  289. do
  290. {
  291. // first call determines the size of the buffer we need.
  292. DWORD bufchars = 0;
  293. hr = Win::GetLogicalDriveStrings(0, 0, bufchars);
  294. BREAK_ON_FAILED_HRESULT(hr);
  295. // add 1 for extra-safe null terminator
  296. size_t bufbytes = (bufchars + 1) * sizeof(TCHAR);
  297. buf = new TCHAR[bufbytes];
  298. memset(buf, 0, bufbytes);
  299. // second call actually retrieves the strings
  300. DWORD unused = 0;
  301. hr = Win::GetLogicalDriveStrings(bufchars, buf, unused);
  302. BREAK_ON_FAILED_HRESULT(hr);
  303. // walk thru buf and chop it into substrings.
  304. for (
  305. TCHAR* sub = _tcschr(buf, 0), *buf2 = buf;
  306. sub && buf2 && buf2[0];
  307. buf2 = sub + 1, sub = _tcschr(buf2, 0))
  308. {
  309. *bii++ = buf2;
  310. }
  311. }
  312. while (0);
  313. delete[] buf;
  314. return hr;
  315. }
  316. // Wrapper of the Win32 API of the same name
  317. //
  318. // path - Fully-qualified path. This path need not exist.
  319. HRESULT
  320. GetVolumePathName(const String& path, String&);
  321. // Returns true if the path refers to an empty or non-existent directory.
  322. //
  323. // path - Fully-qualified path
  324. bool
  325. IsFolderEmpty(const String& path);
  326. // Returns true if parent is the name of a parent directory of the given
  327. // child directory, false if not. A parent directory is defined as one
  328. // that appears closer to the root than a child on the same branch. A
  329. // parent may be any superior directory (e.g. grandparent,
  330. // great-grandparent), not just the immediate superior.
  331. //
  332. // parent - valid, fully-qualified path of supposed parent directory. Need
  333. // not exist.
  334. //
  335. // child - valid, fully-qualified path of child directory. Need not exist.
  336. bool
  337. IsParentFolder(const String& parent, const String& child);
  338. // Checks the validity, but not the existence of, the specified
  339. // file or directory. the path must be absolute and include the
  340. // drive specifier.
  341. //
  342. // path - Fully-qualified path.
  343. bool
  344. IsValidPath(const String& path);
  345. // Moves or renames an existing file or directory.
  346. //
  347. // sourcePath - Fully-qualified path of the file/directory to be
  348. // moved/renamed. This file or directory must exist. If the path refers to
  349. // a directory, the directory and all of its children are moved.
  350. //
  351. // destinationPath - Fully-qualified path of the destination
  352. // file/directory. This path need not be on the same volume as the
  353. // sourcePath, but if it is not, the move will result in a recursive copy
  354. // of the sourcePath.
  355. //
  356. // replaceExisting - If the destinationPath refers to an existing
  357. // file/directory, and this parameter is true, the destinationPath is
  358. // overwritten. Otherwise, if the destinationPath exists, an error is
  359. // returned.
  360. HRESULT
  361. MoveFile(
  362. const String& sourcePath,
  363. const String& destinationPath);
  364. // CODEWORK:
  365. // bool replaceExisting = false);
  366. // "Normalize" a path by parsing any relative path components (like . and
  367. // ..), and return the resulting path. If there are no relative
  368. // components, or if an error occurred, return the same string as the
  369. // input.
  370. //
  371. // Example:
  372. // L"c:\\.\\.\\..\\.\\temp\\.\\foo\\bar\\..\\baz" results in
  373. // L"c:\\temp\\foo\\baz"
  374. //
  375. // abnormalPath - path to parse.
  376. String
  377. NormalizePath(const String& abnormalPath);
  378. // Returns true if the specified file or directory exists.
  379. //
  380. // path - Fully-qualified path.
  381. bool
  382. PathExists(const String& path);
  383. // Returns true if the specified file exists, i.e. the path exists and
  384. // it refers to a file (as opposed to a folder)
  385. bool
  386. FileExists(const String& filePath);
  387. // Reads bytes from the current file pointer of the handle as Unicode
  388. // text (2 bytes/character).
  389. //
  390. // handle - valid, open file handle, with read/write pointer positioned
  391. // to the first byte of the first character to be read.
  392. //
  393. // charactersToRead - number of characters to read. -1 to read all
  394. // characters up to the end of the file or the first null character
  395. // encountered. If this number would cause a read past the end of the
  396. // file, or past a null character, the read will stop at the end of the
  397. // file or null character. In the case of a null character, the file
  398. // read/write pointer will be positioned at the byte following the null
  399. // character.
  400. //
  401. // text - the characters read. A truncated read operation can be detected
  402. // by comparing the length of this string to the charactersToRead
  403. // parameter.
  404. HRESULT
  405. Read(HANDLE handle, int charactersToRead, String& text);
  406. // Reads bytes from the current file pointer of the handle as ANSI
  407. // text.
  408. //
  409. // handle - valid, open file handle, with read/write pointer positioned
  410. // to the first byte of the first character to be read.
  411. //
  412. // bytesToRead - count of the number of bytes (*NOT* characters) to read
  413. //
  414. // text - the bytes read.
  415. HRESULT
  416. Read(HANDLE handle, int bytesToRead, AnsiString& text);
  417. // Positions the file read/write pointer.
  418. //
  419. // handle - Valid, open file handle.
  420. //
  421. // position - new position of the pointer, from the beginning of the
  422. // file.
  423. HRESULT
  424. Seek(HANDLE handle, LONGLONG position);
  425. // Moves the file read/write pointer to the end of the file.
  426. //
  427. // handle - Valid, open file handle.
  428. HRESULT
  429. SeekToEnd(HANDLE handle);
  430. // Writes the supplied string as Unicode text to the file.
  431. //
  432. // handle - Valid, open file handle.
  433. //
  434. // text - the text to be written
  435. HRESULT
  436. Write(HANDLE handle, const String& text);
  437. // appends a crlf
  438. HRESULT
  439. WriteLine(HANDLE handle, const String& text);
  440. // Writes the supplied buffer to the file.
  441. //
  442. // handle - Valid, open file handle.
  443. //
  444. // buf - buffer to write. This is an instance of basic_string<char>
  445. HRESULT
  446. Write(HANDLE handle, const AnsiString& buf);
  447. // appends a crlf
  448. HRESULT
  449. WriteLine(HANDLE handle, const AnsiString& text);
  450. }
  451. }
  452. #endif // FILESYS_HPP_INCLUDED