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.

1513 lines
30 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. basefile.c
  5. Abstract:
  6. Contains simple wrappers for commonly used file i/o functions.
  7. Author:
  8. Marc R. Whitten (marcw) 02-Sep-1999
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. #include "pch.h"
  13. //
  14. // Includes
  15. //
  16. // None
  17. #define DBG_BASEFILE "File Utils"
  18. //
  19. // Strings
  20. //
  21. // None
  22. //
  23. // Constants
  24. //
  25. // None
  26. //
  27. // Macros
  28. //
  29. // None
  30. //
  31. // Types
  32. //
  33. // None
  34. //
  35. // Globals
  36. //
  37. // None
  38. //
  39. // Macro expansion list
  40. //
  41. // None
  42. //
  43. // Private function prototypes
  44. //
  45. // None
  46. //
  47. // Macro expansion definition
  48. //
  49. // None
  50. //
  51. // Code
  52. //
  53. BOOL
  54. WriteFileStringA (
  55. IN HANDLE File,
  56. IN PCSTR String
  57. )
  58. /*++
  59. Routine Description:
  60. Writes a DBCS string to the specified file.
  61. Arguments:
  62. File - Specifies the file handle that was opened with write access.
  63. String - Specifies the nul-terminated string to write to the file.
  64. Return Value:
  65. TRUE if successful, FALSE if an error occurred. Call GetLastError
  66. for error condition.
  67. --*/
  68. {
  69. DWORD DontCare;
  70. return WriteFile (File, String, ByteCountA (String), &DontCare, NULL);
  71. }
  72. BOOL
  73. WriteFileStringW (
  74. IN HANDLE File,
  75. IN PCWSTR String
  76. )
  77. /*++
  78. Routine Description:
  79. Converts a UNICODE string to DBCS, then Writes it to the specified file.
  80. Arguments:
  81. File - Specifies the file handle that was opened with write access.
  82. String - Specifies the UNICODE nul-terminated string to convert and
  83. write to the file.
  84. Return Value:
  85. TRUE if successful, FALSE if an error occurred. Call GetLastError for
  86. error condition.
  87. --*/
  88. {
  89. DWORD DontCare;
  90. PCSTR AnsiVersion;
  91. BOOL b;
  92. AnsiVersion = ConvertWtoA (String);
  93. if (!AnsiVersion) {
  94. return FALSE;
  95. }
  96. b = WriteFile (File, AnsiVersion, ByteCountA (AnsiVersion), &DontCare, NULL);
  97. FreeConvertedStr (AnsiVersion);
  98. return b;
  99. }
  100. BOOL
  101. DoesFileExistExA(
  102. IN PCSTR FileName,
  103. OUT PWIN32_FIND_DATAA FindData OPTIONAL
  104. )
  105. /*++
  106. Routine Description:
  107. Determine if a file exists and is accessible.
  108. Errormode is set (and then restored) so the user will not see
  109. any pop-ups.
  110. Arguments:
  111. FileName - supplies full path of file to check for existance.
  112. FindData - if specified, receives find data for the file.
  113. Return Value:
  114. TRUE if the file exists and is accessible.
  115. FALSE if not. GetLastError() returns extended error info.
  116. --*/
  117. {
  118. WIN32_FIND_DATAA ourFindData;
  119. HANDLE FindHandle;
  120. UINT OldMode;
  121. DWORD Error;
  122. if (!FindData) {
  123. // Win95 GetFileAttributes does not return a failure if FileName is NULL
  124. if (FileName == NULL) {
  125. return FALSE;
  126. } else {
  127. return GetFileAttributesA (FileName) != 0xffffffff;
  128. }
  129. }
  130. OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  131. FindHandle = FindFirstFileA(FileName, &ourFindData);
  132. if (FindHandle == INVALID_HANDLE_VALUE) {
  133. Error = GetLastError();
  134. } else {
  135. FindClose(FindHandle);
  136. *FindData = ourFindData;
  137. Error = NO_ERROR;
  138. }
  139. SetErrorMode(OldMode);
  140. SetLastError(Error);
  141. return (Error == NO_ERROR);
  142. }
  143. BOOL
  144. DoesFileExistExW (
  145. IN PCWSTR FileName,
  146. OUT PWIN32_FIND_DATAW FindData OPTIONAL
  147. )
  148. /*++
  149. Routine Description:
  150. Determine if a file exists and is accessible.
  151. Errormode is set (and then restored) so the user will not see
  152. any pop-ups.
  153. Arguments:
  154. FileName - supplies full path of file to check for existance.
  155. FindData - if specified, receives find data for the file.
  156. Return Value:
  157. TRUE if the file exists and is accessible.
  158. FALSE if not. GetLastError() returns extended error info.
  159. --*/
  160. {
  161. WIN32_FIND_DATAW ourFindData;
  162. HANDLE FindHandle;
  163. UINT OldMode;
  164. DWORD Error;
  165. if (!FindData) {
  166. // Win95 GetFileAttributes does not return a failure if FileName is NULL
  167. if (FileName == NULL) {
  168. return FALSE;
  169. } else {
  170. return GetFileAttributesW (FileName) != 0xffffffff;
  171. }
  172. }
  173. OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  174. FindHandle = FindFirstFileW(FileName,&ourFindData);
  175. if (FindHandle == INVALID_HANDLE_VALUE) {
  176. Error = GetLastError();
  177. } else {
  178. FindClose(FindHandle);
  179. *FindData = ourFindData;
  180. Error = NO_ERROR;
  181. }
  182. SetErrorMode(OldMode);
  183. SetLastError(Error);
  184. return (Error == NO_ERROR);
  185. }
  186. /*++
  187. Routine Description:
  188. PathIsDirectory determines if a path identifies an accessible directory.
  189. Arguments:
  190. PathSpec - Specifies the full path.
  191. Return Value:
  192. TRUE if the path identifies a directory.
  193. FALSE if not. GetLastError() returns extended error info.
  194. --*/
  195. BOOL
  196. BfPathIsDirectoryA (
  197. IN PCSTR PathSpec
  198. )
  199. {
  200. DWORD attribs;
  201. MYASSERT (PathSpec);
  202. if (!PathSpec) {
  203. return FALSE;
  204. }
  205. attribs = GetFileAttributesA (PathSpec);
  206. return attribs != (DWORD)-1 && (attribs & FILE_ATTRIBUTE_DIRECTORY);
  207. }
  208. BOOL
  209. BfPathIsDirectoryW (
  210. IN PCWSTR PathSpec
  211. )
  212. {
  213. DWORD attribs;
  214. MYASSERT (PathSpec);
  215. if (!PathSpec) {
  216. return FALSE;
  217. }
  218. attribs = GetFileAttributesW (PathSpec);
  219. return attribs != (DWORD)-1 && (attribs & FILE_ATTRIBUTE_DIRECTORY);
  220. }
  221. PVOID
  222. MapFileIntoMemoryExA (
  223. IN PCSTR FileName,
  224. OUT PHANDLE FileHandle,
  225. OUT PHANDLE MapHandle,
  226. IN BOOL WriteAccess
  227. )
  228. /*++
  229. Routine Description:
  230. MapFileIntoMemoryA and MapFileIntoMemoryW map a file into memory. It does that
  231. by opening the file, creating a mapping object and mapping opened file into
  232. created mapping object. It returnes the address where the file is mapped and
  233. also sets FileHandle and MapHandle variables to be used in order to unmap the
  234. file when work is done.
  235. Arguments:
  236. FileName - the name of the file to be mapped into memory
  237. FileHandle - will end keeping the file handle if the file was opened successfully
  238. MapHandle - will end keeping the mapping object handle if this object was created successfully
  239. Return Value:
  240. NULL if function fails, a valid memory address if successfull
  241. Comments:
  242. If the return value is NULL you should call UnmapFile to release all allocated resources
  243. --*/
  244. {
  245. PVOID fileImage = NULL;
  246. //verify function parameters
  247. if ((FileHandle == NULL) || (MapHandle == NULL)) {
  248. return NULL;
  249. }
  250. //first thing. Try to open the file, read-only
  251. *FileHandle = CreateFileA (
  252. FileName,
  253. WriteAccess?GENERIC_READ|GENERIC_WRITE:GENERIC_READ,
  254. FILE_SHARE_READ,
  255. NULL,
  256. OPEN_EXISTING,
  257. FILE_ATTRIBUTE_NORMAL,
  258. NULL
  259. );
  260. if (*FileHandle == INVALID_HANDLE_VALUE) {
  261. *FileHandle = NULL;
  262. return NULL;
  263. }
  264. //now try to create a mapping object, read-only
  265. *MapHandle = CreateFileMappingA (*FileHandle, NULL, WriteAccess?PAGE_READWRITE:PAGE_READONLY, 0, 0, NULL);
  266. if (*MapHandle == NULL) {
  267. CloseHandle (*FileHandle);
  268. *FileHandle = NULL;
  269. return NULL;
  270. }
  271. //one more thing to do: map view of file
  272. fileImage = MapViewOfFile (*MapHandle, WriteAccess?FILE_MAP_WRITE:FILE_MAP_READ, 0, 0, 0);
  273. return fileImage;
  274. }
  275. PVOID
  276. MapFileIntoMemoryExW (
  277. IN PCWSTR FileName,
  278. OUT PHANDLE FileHandle,
  279. OUT PHANDLE MapHandle,
  280. IN BOOL WriteAccess
  281. )
  282. /*++
  283. Routine Description:
  284. MapFileIntoMemoryA and MapFileIntoMemoryW map a file into memory. It does that
  285. by opening the file, creating a mapping object and mapping opened file into
  286. created mapping object. It returnes the address where the file is mapped and
  287. also sets FileHandle and MapHandle variables to be used in order to unmap the
  288. file when work is done.
  289. Arguments:
  290. FileName - the name of the file to be mapped into memory
  291. FileHandle - will end keeping the file handle if the file was opened successfully
  292. MapHandle - will end keeping the mapping object handle if this object was created successfully
  293. Return Value:
  294. NULL if function fails, a valid memory address if successfull
  295. Comments:
  296. If the return value is NULL you should call UnmapFile to release all allocated resources
  297. --*/
  298. {
  299. PVOID fileImage = NULL;
  300. //verify function parameters
  301. if ((FileHandle == NULL) || (MapHandle == NULL)) {
  302. return NULL;
  303. }
  304. //first thing. Try to open the file, read-only
  305. *FileHandle = CreateFileW (
  306. FileName,
  307. WriteAccess?GENERIC_READ|GENERIC_WRITE:GENERIC_READ,
  308. FILE_SHARE_READ,
  309. NULL,
  310. OPEN_EXISTING,
  311. FILE_ATTRIBUTE_NORMAL,
  312. NULL
  313. );
  314. if (*FileHandle == INVALID_HANDLE_VALUE) {
  315. *FileHandle = NULL;
  316. return NULL;
  317. }
  318. //now try to create a mapping object, read-only
  319. *MapHandle = CreateFileMappingW (*FileHandle, NULL, WriteAccess?PAGE_READWRITE:PAGE_READONLY, 0, 0, NULL);
  320. if (*MapHandle == NULL) {
  321. CloseHandle (*FileHandle);
  322. *FileHandle = NULL;
  323. return NULL;
  324. }
  325. //one more thing to do: map view of file
  326. fileImage = MapViewOfFile (*MapHandle, WriteAccess?FILE_MAP_WRITE:FILE_MAP_READ, 0, 0, 0);
  327. return fileImage;
  328. }
  329. BOOL
  330. UnmapFile (
  331. IN PCVOID FileImage,
  332. IN HANDLE MapHandle,
  333. IN HANDLE FileHandle
  334. )
  335. /*++
  336. Routine Description:
  337. UnmapFile is used to release all resources allocated by MapFileIntoMemory.
  338. Arguments:
  339. FileImage - image of the mapped file as returned by MapFileIntoMemory
  340. MapHandle - handle of the mapping object as returned by MapFileIntoMemory
  341. FileHandle - handle of the file as returned by MapFileIntoMemory
  342. Return Value:
  343. TRUE if successfull, FALSE if not
  344. --*/
  345. {
  346. BOOL result = TRUE;
  347. //if FileImage is a valid pointer then try to unmap file
  348. if (FileImage != NULL) {
  349. if (UnmapViewOfFile (FileImage) == 0) {
  350. result = FALSE;
  351. }
  352. }
  353. //if mapping object is valid then try to delete it
  354. if (MapHandle != NULL) {
  355. if (CloseHandle (MapHandle) == 0) {
  356. result = FALSE;
  357. }
  358. }
  359. //if file handle is valid then try to close the file
  360. if (FileHandle != INVALID_HANDLE_VALUE) {
  361. if (CloseHandle (FileHandle) == 0) {
  362. result = FALSE;
  363. }
  364. }
  365. return result;
  366. }
  367. BOOL
  368. BfGetTempFileNameExA (
  369. OUT PSTR Buffer,
  370. IN UINT BufferTchars,
  371. IN PCSTR Prefix
  372. )
  373. {
  374. CHAR tempPath[MAX_MBCHAR_PATH];
  375. CHAR tempFile[MAX_MBCHAR_PATH];
  376. UINT tchars;
  377. PSTR p;
  378. if (!GetTempPathA (ARRAYSIZE(tempPath), tempPath)) {
  379. return FALSE;
  380. }
  381. p = _mbsrchr (tempPath, '\\');
  382. if (p && !p[1]) {
  383. *p = 0;
  384. }
  385. if (!DoesFileExistA (tempPath)) {
  386. BfCreateDirectoryA (tempPath);
  387. }
  388. if (BufferTchars >= MAX_PATH) {
  389. if (!GetTempFileNameA (tempPath, Prefix, 0, Buffer)) {
  390. return FALSE;
  391. }
  392. } else {
  393. if (!GetTempFileNameA (tempPath, Prefix, 0, tempFile)) {
  394. DWORD err = GetLastError ();
  395. return FALSE;
  396. }
  397. tchars = TcharCountA (tempFile) + 1;
  398. if (tchars > BufferTchars) {
  399. DEBUGMSG ((DBG_ERROR, "Can't get temp file name -- buffer too small"));
  400. return FALSE;
  401. }
  402. CopyMemory (Buffer, tempFile, tchars * sizeof (CHAR));
  403. }
  404. return TRUE;
  405. }
  406. BOOL
  407. BfGetTempFileNameExW (
  408. OUT PWSTR Buffer,
  409. IN UINT BufferTchars,
  410. IN PCWSTR Prefix
  411. )
  412. {
  413. WCHAR tempPath[MAX_WCHAR_PATH];
  414. WCHAR tempFile[MAX_WCHAR_PATH];
  415. UINT tchars;
  416. PWSTR p;
  417. if (!GetTempPathW (ARRAYSIZE(tempPath), tempPath)) {
  418. return FALSE;
  419. }
  420. p = wcsrchr (tempPath, '\\');
  421. if (p && !p[1]) {
  422. *p = 0;
  423. }
  424. if (BufferTchars >= MAX_PATH) {
  425. if (!GetTempFileNameW (tempPath, Prefix, 0, Buffer)) {
  426. return FALSE;
  427. }
  428. } else {
  429. if (!GetTempFileNameW (tempPath, Prefix, 0, tempFile)) {
  430. return FALSE;
  431. }
  432. tchars = TcharCountW (tempFile);
  433. if (tchars > BufferTchars) {
  434. DEBUGMSG ((DBG_ERROR, "Can't get temp file name -- buffer too small"));
  435. return FALSE;
  436. }
  437. CopyMemory (Buffer, tempFile, tchars * sizeof (WCHAR));
  438. }
  439. return TRUE;
  440. }
  441. BOOL
  442. BfGetTempDirectoryExA (
  443. OUT PSTR Buffer,
  444. IN UINT BufferTchars,
  445. IN PCSTR Prefix
  446. )
  447. {
  448. BOOL result = FALSE;
  449. result = BfGetTempFileNameExA (Buffer, BufferTchars, Prefix);
  450. if (result) {
  451. if (!DeleteFileA (Buffer)) {
  452. return FALSE;
  453. }
  454. if (!CreateDirectoryA (Buffer, NULL)) {
  455. return FALSE;
  456. }
  457. }
  458. return result;
  459. }
  460. BOOL
  461. BfGetTempDirectoryExW (
  462. OUT PWSTR Buffer,
  463. IN UINT BufferTchars,
  464. IN PCWSTR Prefix
  465. )
  466. {
  467. BOOL result = FALSE;
  468. result = BfGetTempFileNameExW (Buffer, BufferTchars, Prefix);
  469. if (result) {
  470. if (!DeleteFileW (Buffer)) {
  471. return FALSE;
  472. }
  473. if (!CreateDirectoryW (Buffer, NULL)) {
  474. return FALSE;
  475. }
  476. }
  477. return result;
  478. }
  479. HANDLE
  480. BfGetTempFile (
  481. VOID
  482. )
  483. {
  484. CHAR tempFile[MAX_MBCHAR_PATH];
  485. HANDLE file;
  486. if (!BfGetTempFileNameA (tempFile, ARRAYSIZE(tempFile))) {
  487. return NULL;
  488. }
  489. file = CreateFileA (
  490. tempFile,
  491. GENERIC_READ|GENERIC_WRITE,
  492. 0,
  493. NULL,
  494. CREATE_ALWAYS,
  495. FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE,
  496. NULL
  497. );
  498. if (file == INVALID_HANDLE_VALUE) {
  499. file = NULL;
  500. }
  501. return file;
  502. }
  503. BOOL
  504. BfSetFilePointer (
  505. IN HANDLE File,
  506. IN LONGLONG Offset
  507. )
  508. {
  509. LARGE_INTEGER li;
  510. li.QuadPart = Offset;
  511. li.LowPart = SetFilePointer (File, li.LowPart, &li.HighPart, FILE_BEGIN);
  512. if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
  513. li.QuadPart = -1;
  514. }
  515. return li.QuadPart != -1;
  516. }
  517. HANDLE
  518. BfOpenReadFileA (
  519. IN PCSTR FileName
  520. )
  521. {
  522. HANDLE handle;
  523. handle = CreateFileA (
  524. FileName,
  525. GENERIC_READ,
  526. FILE_SHARE_READ|FILE_SHARE_WRITE,
  527. NULL,
  528. OPEN_EXISTING,
  529. FILE_ATTRIBUTE_NORMAL,
  530. NULL
  531. );
  532. if (handle == INVALID_HANDLE_VALUE) {
  533. handle = NULL;
  534. }
  535. return handle;
  536. }
  537. HANDLE
  538. BfOpenReadFileW (
  539. IN PCWSTR FileName
  540. )
  541. {
  542. HANDLE handle;
  543. handle = CreateFileW (
  544. FileName,
  545. GENERIC_READ,
  546. FILE_SHARE_READ|FILE_SHARE_WRITE,
  547. NULL,
  548. OPEN_EXISTING,
  549. FILE_ATTRIBUTE_NORMAL,
  550. NULL
  551. );
  552. if (handle == INVALID_HANDLE_VALUE) {
  553. handle = NULL;
  554. }
  555. return handle;
  556. }
  557. HANDLE
  558. BfOpenFileA (
  559. IN PCSTR FileName
  560. )
  561. {
  562. HANDLE handle;
  563. handle = CreateFileA (
  564. FileName,
  565. GENERIC_READ|GENERIC_WRITE,
  566. 0,
  567. NULL,
  568. OPEN_EXISTING,
  569. FILE_ATTRIBUTE_NORMAL,
  570. NULL
  571. );
  572. if (handle == INVALID_HANDLE_VALUE) {
  573. handle = NULL;
  574. }
  575. return handle;
  576. }
  577. HANDLE
  578. BfOpenFileW (
  579. IN PCWSTR FileName
  580. )
  581. {
  582. HANDLE handle;
  583. handle = CreateFileW (
  584. FileName,
  585. GENERIC_READ|GENERIC_WRITE,
  586. 0,
  587. NULL,
  588. OPEN_EXISTING,
  589. FILE_ATTRIBUTE_NORMAL,
  590. NULL
  591. );
  592. if (handle == INVALID_HANDLE_VALUE) {
  593. handle = NULL;
  594. }
  595. return handle;
  596. }
  597. HANDLE
  598. BfCreateFileA (
  599. IN PCSTR FileName
  600. )
  601. {
  602. HANDLE handle;
  603. handle = CreateFileA (
  604. FileName,
  605. GENERIC_READ|GENERIC_WRITE,
  606. 0,
  607. NULL,
  608. CREATE_ALWAYS,
  609. FILE_ATTRIBUTE_NORMAL,
  610. NULL
  611. );
  612. if (handle == INVALID_HANDLE_VALUE) {
  613. handle = NULL;
  614. }
  615. return handle;
  616. }
  617. HANDLE
  618. BfCreateFileW (
  619. IN PCWSTR FileName
  620. )
  621. {
  622. HANDLE handle;
  623. handle = CreateFileW (
  624. FileName,
  625. GENERIC_READ|GENERIC_WRITE,
  626. 0,
  627. NULL,
  628. CREATE_ALWAYS,
  629. FILE_ATTRIBUTE_NORMAL,
  630. NULL
  631. );
  632. if (handle == INVALID_HANDLE_VALUE) {
  633. handle = NULL;
  634. }
  635. return handle;
  636. }
  637. HANDLE
  638. BfCreateSharedFileA (
  639. IN PCSTR FileName
  640. )
  641. {
  642. HANDLE handle;
  643. handle = CreateFileA (
  644. FileName,
  645. GENERIC_READ|GENERIC_WRITE,
  646. FILE_SHARE_READ|FILE_SHARE_WRITE,
  647. NULL,
  648. CREATE_ALWAYS,
  649. FILE_ATTRIBUTE_NORMAL,
  650. NULL
  651. );
  652. if (handle == INVALID_HANDLE_VALUE) {
  653. handle = NULL;
  654. }
  655. return handle;
  656. }
  657. HANDLE
  658. BfCreateSharedFileW (
  659. IN PCWSTR FileName
  660. )
  661. {
  662. HANDLE handle;
  663. handle = CreateFileW (
  664. FileName,
  665. GENERIC_READ|GENERIC_WRITE,
  666. FILE_SHARE_READ|FILE_SHARE_WRITE,
  667. NULL,
  668. CREATE_ALWAYS,
  669. FILE_ATTRIBUTE_NORMAL,
  670. NULL
  671. );
  672. if (handle == INVALID_HANDLE_VALUE) {
  673. handle = NULL;
  674. }
  675. return handle;
  676. }
  677. BOOL
  678. BfSetSizeOfFile (
  679. HANDLE File,
  680. LONGLONG Size
  681. )
  682. {
  683. if (!BfSetFilePointer (File, Size)) {
  684. return FALSE;
  685. }
  686. return SetEndOfFile (File);
  687. }
  688. BOOL
  689. BfGoToEndOfFile (
  690. IN HANDLE File,
  691. OUT PLONGLONG FileSize OPTIONAL
  692. )
  693. {
  694. LARGE_INTEGER li;
  695. li.HighPart = 0;
  696. li.LowPart = SetFilePointer (File, 0, &li.HighPart, FILE_END);
  697. if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
  698. li.QuadPart = -1;
  699. } else if (FileSize) {
  700. *FileSize = li.QuadPart;
  701. }
  702. return li.QuadPart != -1;
  703. }
  704. BOOL
  705. BfGetFilePointer (
  706. IN HANDLE File,
  707. OUT PLONGLONG FilePointer OPTIONAL
  708. )
  709. {
  710. LARGE_INTEGER li;
  711. li.HighPart = 0;
  712. li.LowPart = SetFilePointer (File, 0, &li.HighPart, FILE_CURRENT);
  713. if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
  714. li.QuadPart = -1;
  715. } else if (FilePointer) {
  716. *FilePointer = li.QuadPart;
  717. }
  718. return li.QuadPart != -1;
  719. }
  720. BOOL
  721. BfReadFile (
  722. IN HANDLE File,
  723. OUT PBYTE Buffer,
  724. IN UINT BytesToRead
  725. )
  726. {
  727. DWORD bytesRead;
  728. if (!ReadFile (File, Buffer, BytesToRead, &bytesRead, NULL)) {
  729. return FALSE;
  730. }
  731. return bytesRead == BytesToRead;
  732. }
  733. BOOL
  734. BfWriteFile (
  735. IN HANDLE File,
  736. OUT PCBYTE Buffer,
  737. IN UINT BytesToWrite
  738. )
  739. {
  740. DWORD bytesWritten;
  741. if (!WriteFile (File, Buffer, BytesToWrite, &bytesWritten, NULL)) {
  742. return FALSE;
  743. }
  744. return bytesWritten == BytesToWrite;
  745. }
  746. BOOL
  747. BfCreateDirectoryExA (
  748. IN PCSTR FullPath,
  749. IN BOOL CreateLastSegment
  750. )
  751. {
  752. PSTR pathCopy;
  753. PSTR p;
  754. BOOL b = TRUE;
  755. pathCopy = DuplicatePathStringA (FullPath, 0);
  756. //
  757. // Advance past first directory
  758. //
  759. if (pathCopy[1] == ':' && pathCopy[2] == '\\') {
  760. //
  761. // <drive>:\ case
  762. //
  763. p = _mbschr (&pathCopy[3], '\\');
  764. } else if (pathCopy[0] == '\\' && pathCopy[1] == '\\') {
  765. //
  766. // UNC case
  767. //
  768. p = _mbschr (pathCopy + 2, '\\');
  769. if (p) {
  770. p = _mbschr (p + 1, '\\');
  771. if (p) {
  772. p = _mbschr (p + 1, '\\');
  773. }
  774. }
  775. } else {
  776. //
  777. // Relative dir case
  778. //
  779. p = _mbschr (pathCopy, '\\');
  780. }
  781. //
  782. // Make all directories along the path
  783. //
  784. while (p) {
  785. *p = 0;
  786. b = CreateDirectoryA (pathCopy, NULL);
  787. if (!b && GetLastError() == ERROR_ALREADY_EXISTS) {
  788. b = TRUE;
  789. }
  790. if (!b) {
  791. LOG ((LOG_ERROR, "Can't create %s", pathCopy));
  792. break;
  793. }
  794. *p = '\\';
  795. p = _mbschr (p + 1, '\\');
  796. }
  797. //
  798. // At last, make the FullPath directory
  799. //
  800. if (b && CreateLastSegment) {
  801. b = CreateDirectoryA (pathCopy, NULL);
  802. if (!b && GetLastError() == ERROR_ALREADY_EXISTS) {
  803. b = TRUE;
  804. }
  805. }
  806. FreePathStringA (pathCopy);
  807. return b;
  808. }
  809. BOOL
  810. BfCreateDirectoryExW (
  811. IN PCWSTR FullPath,
  812. IN BOOL CreateLastSegment
  813. )
  814. {
  815. PWSTR pathCopy;
  816. PWSTR p;
  817. BOOL b = TRUE;
  818. pathCopy = DuplicatePathStringW (FullPath, 0);
  819. //
  820. // Advance past first directory
  821. //
  822. if (pathCopy[1] == L':' && pathCopy[2] == L'\\') {
  823. //
  824. // <drive>:\ case
  825. //
  826. p = wcschr (&pathCopy[3], L'\\');
  827. } else if (pathCopy[0] == L'\\' && pathCopy[1] == L'\\') {
  828. //
  829. // UNC case
  830. //
  831. p = wcschr (pathCopy + 2, L'\\');
  832. if (p) {
  833. p = wcschr (p + 1, L'\\');
  834. if (p) {
  835. p = wcschr (p + 1, L'\\');
  836. }
  837. }
  838. } else {
  839. //
  840. // Relative dir case
  841. //
  842. p = wcschr (pathCopy, L'\\');
  843. }
  844. //
  845. // Make all directories along the path
  846. //
  847. while (p) {
  848. *p = 0;
  849. b = CreateDirectoryW (pathCopy, NULL);
  850. if (!b && GetLastError() == ERROR_ALREADY_EXISTS) {
  851. b = TRUE;
  852. }
  853. if (!b) {
  854. break;
  855. }
  856. *p = L'\\';
  857. p = wcschr (p + 1, L'\\');
  858. }
  859. //
  860. // At last, make the FullPath directory
  861. //
  862. if (b && CreateLastSegment) {
  863. b = CreateDirectoryW (pathCopy, NULL);
  864. if (!b && GetLastError() == ERROR_ALREADY_EXISTS) {
  865. b = TRUE;
  866. }
  867. }
  868. FreePathStringW (pathCopy);
  869. return b;
  870. }
  871. LONGLONG
  872. BfGetFileSizeA (
  873. IN PCSTR FileName
  874. )
  875. {
  876. WIN32_FIND_DATAA fd;
  877. LONGLONG l;
  878. if (!DoesFileExistExA (FileName, &fd)) {
  879. return 0;
  880. }
  881. l = ((LONGLONG) fd.nFileSizeHigh << 32) | fd.nFileSizeLow;
  882. return l;
  883. }
  884. LONGLONG
  885. BfGetFileSizeW (
  886. IN PCWSTR FileName
  887. )
  888. {
  889. WIN32_FIND_DATAW fd;
  890. LONGLONG l;
  891. if (!DoesFileExistExW (FileName, &fd)) {
  892. return 0;
  893. }
  894. l = ((LONGLONG) fd.nFileSizeHigh << 32) | fd.nFileSizeLow;
  895. return l;
  896. }
  897. PSTR
  898. pGetFirstSegA (
  899. IN PCSTR SrcFileName
  900. )
  901. {
  902. if (SrcFileName [0] == '\\') {
  903. SrcFileName ++;
  904. if (SrcFileName [0] == '\\') {
  905. SrcFileName ++;
  906. }
  907. return (_mbschr (SrcFileName, '\\'));
  908. } else {
  909. return (_mbschr (SrcFileName, '\\'));
  910. }
  911. }
  912. BOOL
  913. pGetLongFileNameWorkerA (
  914. IN PCSTR SrcFileName,
  915. IN PGROWBUFFER GrowBuf
  916. )
  917. {
  918. PSTR beginSegPtr;
  919. PSTR endSegPtr;
  920. WIN32_FIND_DATAA findData;
  921. CHAR savedChar;
  922. beginSegPtr = pGetFirstSegA (SrcFileName);
  923. if (!beginSegPtr) {
  924. GbAppendStringA (GrowBuf, SrcFileName);
  925. return TRUE;
  926. }
  927. beginSegPtr = _mbsinc (beginSegPtr);
  928. GbAppendStringABA (GrowBuf, SrcFileName, beginSegPtr);
  929. while (beginSegPtr) {
  930. endSegPtr = _mbschr (beginSegPtr, '\\');
  931. if (!endSegPtr) {
  932. endSegPtr = GetEndOfStringA (beginSegPtr);
  933. MYASSERT (endSegPtr);
  934. }
  935. savedChar = *endSegPtr;
  936. *endSegPtr = 0;
  937. if (DoesFileExistExA (SrcFileName, &findData)) {
  938. if (StringIMatchA (findData.cFileName, ".")) {
  939. GbAppendStringA (GrowBuf, beginSegPtr);
  940. } else {
  941. GbAppendStringA (GrowBuf, findData.cFileName);
  942. }
  943. } else {
  944. GbAppendStringABA (GrowBuf, beginSegPtr, endSegPtr);
  945. }
  946. *endSegPtr = savedChar;
  947. if (savedChar) {
  948. beginSegPtr = _mbsinc (endSegPtr);
  949. GbAppendStringABA (GrowBuf, endSegPtr, beginSegPtr);
  950. } else {
  951. beginSegPtr = NULL;
  952. }
  953. }
  954. return TRUE;
  955. }
  956. PCSTR
  957. BfGetLongFileNameA (
  958. IN PCSTR SrcFileName
  959. )
  960. {
  961. GROWBUFFER growBuf = INIT_GROWBUFFER;
  962. PSTR srcFileName;
  963. PCSTR result = NULL;
  964. srcFileName = (PSTR)SanitizePathA (SrcFileName);
  965. if (pGetLongFileNameWorkerA (srcFileName, &growBuf)) {
  966. result = DuplicatePathStringA (growBuf.Buf, 0);
  967. GbFree (&growBuf);
  968. }
  969. FreePathStringA (srcFileName);
  970. return result;
  971. }
  972. BOOL
  973. BfGetLongFileNameExA (
  974. IN PCSTR SrcFileName,
  975. IN PGROWBUFFER GrowBuff
  976. )
  977. {
  978. PSTR srcFileName;
  979. BOOL result;
  980. srcFileName = (PSTR)SanitizePathA (SrcFileName);
  981. result = pGetLongFileNameWorkerA (srcFileName, GrowBuff);
  982. FreePathStringA (srcFileName);
  983. return result;
  984. }
  985. PWSTR
  986. pGetFirstSegW (
  987. IN PCWSTR SrcFileName
  988. )
  989. {
  990. if (SrcFileName [0] == L'\\') {
  991. SrcFileName ++;
  992. if (SrcFileName [0] == L'\\') {
  993. SrcFileName ++;
  994. }
  995. return (wcschr (SrcFileName, L'\\'));
  996. } else {
  997. return (wcschr (SrcFileName, L'\\'));
  998. }
  999. }
  1000. BOOL
  1001. pGetLongFileNameWorkerW (
  1002. IN PCWSTR SrcFileName,
  1003. IN PGROWBUFFER GrowBuf
  1004. )
  1005. {
  1006. PWSTR beginSegPtr;
  1007. PWSTR endSegPtr;
  1008. WIN32_FIND_DATAW findData;
  1009. WCHAR savedChar;
  1010. beginSegPtr = pGetFirstSegW (SrcFileName);
  1011. if (!beginSegPtr) {
  1012. GbAppendStringW (GrowBuf, SrcFileName);
  1013. return TRUE;
  1014. }
  1015. beginSegPtr ++;
  1016. GbAppendStringABW (GrowBuf, SrcFileName, beginSegPtr);
  1017. while (beginSegPtr) {
  1018. endSegPtr = wcschr (beginSegPtr, L'\\');
  1019. if (!endSegPtr) {
  1020. endSegPtr = GetEndOfStringW (beginSegPtr);
  1021. MYASSERT (endSegPtr);
  1022. }
  1023. savedChar = *endSegPtr;
  1024. *endSegPtr = 0;
  1025. if (DoesFileExistExW (SrcFileName, &findData)) {
  1026. GbAppendStringW (GrowBuf, findData.cFileName);
  1027. } else {
  1028. GbAppendStringABW (GrowBuf, beginSegPtr, endSegPtr);
  1029. }
  1030. *endSegPtr = savedChar;
  1031. if (savedChar) {
  1032. beginSegPtr = endSegPtr + 1;
  1033. GbAppendStringABW (GrowBuf, endSegPtr, beginSegPtr);
  1034. } else {
  1035. beginSegPtr = NULL;
  1036. }
  1037. }
  1038. return TRUE;
  1039. }
  1040. PCWSTR
  1041. BfGetLongFileNameW (
  1042. IN PCWSTR SrcFileName
  1043. )
  1044. {
  1045. GROWBUFFER growBuf = INIT_GROWBUFFER;
  1046. PWSTR srcFileName;
  1047. PCWSTR result = NULL;
  1048. srcFileName = (PWSTR)SanitizePathW (SrcFileName);
  1049. if (pGetLongFileNameWorkerW (srcFileName, &growBuf)) {
  1050. result = DuplicatePathStringW ((PCWSTR)growBuf.Buf, 0);
  1051. GbFree (&growBuf);
  1052. }
  1053. FreePathStringW (srcFileName);
  1054. return result;
  1055. }
  1056. BOOL
  1057. BfGetLongFileNameExW (
  1058. IN PCWSTR SrcFileName,
  1059. IN PGROWBUFFER GrowBuff
  1060. )
  1061. {
  1062. PWSTR srcFileName;
  1063. BOOL result;
  1064. srcFileName = (PWSTR)SanitizePathW (SrcFileName);
  1065. result = pGetLongFileNameWorkerW (srcFileName, GrowBuff);
  1066. FreePathStringW (srcFileName);
  1067. return result;
  1068. }
  1069. BOOL
  1070. BfCopyAndFlushFileA (
  1071. IN PCSTR SrcFileName,
  1072. IN PCSTR DestFileName,
  1073. IN BOOL FailIfExists
  1074. )
  1075. {
  1076. BYTE buffer[4096];
  1077. HANDLE srcHandle;
  1078. HANDLE destHandle;
  1079. DWORD bytesRead = 4096;
  1080. DWORD bytesWritten;
  1081. BOOL error = FALSE;
  1082. BOOL result = FALSE;
  1083. srcHandle = BfOpenReadFileA (SrcFileName);
  1084. if (srcHandle) {
  1085. if (FailIfExists && DoesFileExistA (DestFileName)) {
  1086. SetLastError (ERROR_ALREADY_EXISTS);
  1087. } else {
  1088. destHandle = BfCreateFileA (DestFileName);
  1089. if (destHandle) {
  1090. while (bytesRead == 4096) {
  1091. if (!ReadFile (srcHandle, buffer, 4096, &bytesRead, NULL)) {
  1092. error = TRUE;
  1093. break;
  1094. }
  1095. if (bytesRead == 0) {
  1096. break;
  1097. }
  1098. if (!WriteFile (destHandle, buffer, bytesRead, &bytesWritten, NULL)) {
  1099. error = TRUE;
  1100. break;
  1101. }
  1102. if (bytesRead != bytesWritten) {
  1103. error = TRUE;
  1104. break;
  1105. }
  1106. }
  1107. if (!error) {
  1108. result = TRUE;
  1109. }
  1110. if (result) {
  1111. FlushFileBuffers (destHandle);
  1112. }
  1113. CloseHandle (destHandle);
  1114. }
  1115. }
  1116. CloseHandle (srcHandle);
  1117. }
  1118. return result;
  1119. }
  1120. BOOL
  1121. BfCopyAndFlushFileW (
  1122. IN PCWSTR SrcFileName,
  1123. IN PCWSTR DestFileName,
  1124. IN BOOL FailIfExists
  1125. )
  1126. {
  1127. BYTE buffer[4096];
  1128. HANDLE srcHandle;
  1129. HANDLE destHandle;
  1130. DWORD bytesRead = 4096;
  1131. DWORD bytesWritten;
  1132. BOOL error = FALSE;
  1133. BOOL result = FALSE;
  1134. srcHandle = BfOpenReadFileW (SrcFileName);
  1135. if (srcHandle) {
  1136. if (FailIfExists && DoesFileExistW (DestFileName)) {
  1137. SetLastError (ERROR_ALREADY_EXISTS);
  1138. } else {
  1139. destHandle = BfCreateFileW (DestFileName);
  1140. if (destHandle) {
  1141. while (bytesRead == 4096) {
  1142. if (!ReadFile (srcHandle, buffer, 4096, &bytesRead, NULL)) {
  1143. error = TRUE;
  1144. break;
  1145. }
  1146. if (bytesRead == 0) {
  1147. break;
  1148. }
  1149. if (!WriteFile (destHandle, buffer, bytesRead, &bytesWritten, NULL)) {
  1150. error = TRUE;
  1151. break;
  1152. }
  1153. if (bytesRead != bytesWritten) {
  1154. error = TRUE;
  1155. break;
  1156. }
  1157. }
  1158. if (!error) {
  1159. result = TRUE;
  1160. }
  1161. if (result) {
  1162. FlushFileBuffers (destHandle);
  1163. }
  1164. CloseHandle (destHandle);
  1165. }
  1166. }
  1167. CloseHandle (srcHandle);
  1168. }
  1169. return result;
  1170. }