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.

1251 lines
24 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. return GetFileAttributesA (FileName) != 0xffffffff;
  124. }
  125. OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  126. FindHandle = FindFirstFileA(FileName, &ourFindData);
  127. if (FindHandle == INVALID_HANDLE_VALUE) {
  128. Error = GetLastError();
  129. } else {
  130. FindClose(FindHandle);
  131. *FindData = ourFindData;
  132. Error = NO_ERROR;
  133. }
  134. SetErrorMode(OldMode);
  135. SetLastError(Error);
  136. return (Error == NO_ERROR);
  137. }
  138. BOOL
  139. DoesFileExistExW (
  140. IN PCWSTR FileName,
  141. OUT PWIN32_FIND_DATAW FindData OPTIONAL
  142. )
  143. /*++
  144. Routine Description:
  145. Determine if a file exists and is accessible.
  146. Errormode is set (and then restored) so the user will not see
  147. any pop-ups.
  148. Arguments:
  149. FileName - supplies full path of file to check for existance.
  150. FindData - if specified, receives find data for the file.
  151. Return Value:
  152. TRUE if the file exists and is accessible.
  153. FALSE if not. GetLastError() returns extended error info.
  154. --*/
  155. {
  156. WIN32_FIND_DATAW ourFindData;
  157. HANDLE FindHandle;
  158. UINT OldMode;
  159. DWORD Error;
  160. if (!FindData) {
  161. return GetFileAttributesW (FileName) != 0xffffffff;
  162. }
  163. OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  164. FindHandle = FindFirstFileW(FileName,&ourFindData);
  165. if (FindHandle == INVALID_HANDLE_VALUE) {
  166. Error = GetLastError();
  167. } else {
  168. FindClose(FindHandle);
  169. *FindData = ourFindData;
  170. Error = NO_ERROR;
  171. }
  172. SetErrorMode(OldMode);
  173. SetLastError(Error);
  174. return (Error == NO_ERROR);
  175. }
  176. /*++
  177. Routine Description:
  178. PathIsDirectory determines if a path identifies an accessible directory.
  179. Arguments:
  180. PathSpec - Specifies the full path.
  181. Return Value:
  182. TRUE if the path identifies a directory.
  183. FALSE if not. GetLastError() returns extended error info.
  184. --*/
  185. BOOL
  186. PathIsDirectoryA (
  187. IN PCSTR PathSpec
  188. )
  189. {
  190. DWORD attribs;
  191. MYASSERT (PathSpec);
  192. if (!PathSpec) {
  193. return FALSE;
  194. }
  195. attribs = GetFileAttributesA (PathSpec);
  196. return attribs != (DWORD)-1 && (attribs & FILE_ATTRIBUTE_DIRECTORY);
  197. }
  198. BOOL
  199. PathIsDirectoryW (
  200. IN PCWSTR PathSpec
  201. )
  202. {
  203. DWORD attribs;
  204. MYASSERT (PathSpec);
  205. if (!PathSpec) {
  206. return FALSE;
  207. }
  208. attribs = GetFileAttributesW (PathSpec);
  209. return attribs != (DWORD)-1 && (attribs & FILE_ATTRIBUTE_DIRECTORY);
  210. }
  211. PVOID
  212. MapFileIntoMemoryExA (
  213. IN PCSTR FileName,
  214. OUT PHANDLE FileHandle,
  215. OUT PHANDLE MapHandle,
  216. IN BOOL WriteAccess
  217. )
  218. /*++
  219. Routine Description:
  220. MapFileIntoMemoryA and MapFileIntoMemoryW map a file into memory. It does that
  221. by opening the file, creating a mapping object and mapping opened file into
  222. created mapping object. It returnes the address where the file is mapped and
  223. also sets FileHandle and MapHandle variables to be used in order to unmap the
  224. file when work is done.
  225. Arguments:
  226. FileName - the name of the file to be mapped into memory
  227. FileHandle - will end keeping the file handle if the file was opened successfully
  228. MapHandle - will end keeping the mapping object handle if this object was created successfully
  229. Return Value:
  230. NULL if function fails, a valid memory address if successfull
  231. Comments:
  232. If the return value is NULL you should call UnmapFile to release all allocated resources
  233. --*/
  234. {
  235. PVOID fileImage = NULL;
  236. //verify function parameters
  237. if ((FileHandle == NULL) || (MapHandle == NULL)) {
  238. return NULL;
  239. }
  240. //first thing. Try to open the file, read-only
  241. *FileHandle = CreateFileA (
  242. FileName,
  243. WriteAccess?GENERIC_READ|GENERIC_WRITE:GENERIC_READ,
  244. FILE_SHARE_READ,
  245. NULL,
  246. OPEN_EXISTING,
  247. FILE_ATTRIBUTE_NORMAL,
  248. NULL
  249. );
  250. if (*FileHandle == INVALID_HANDLE_VALUE) {
  251. return NULL;
  252. }
  253. //now try to create a mapping object, read-only
  254. *MapHandle = CreateFileMappingA (*FileHandle, NULL, WriteAccess?PAGE_READWRITE:PAGE_READONLY, 0, 0, NULL);
  255. if (*MapHandle == NULL) {
  256. return NULL;
  257. }
  258. //one more thing to do: map view of file
  259. fileImage = MapViewOfFile (*MapHandle, WriteAccess?FILE_MAP_WRITE:FILE_MAP_READ, 0, 0, 0);
  260. return fileImage;
  261. }
  262. PVOID
  263. MapFileIntoMemoryExW (
  264. IN PCWSTR FileName,
  265. OUT PHANDLE FileHandle,
  266. OUT PHANDLE MapHandle,
  267. IN BOOL WriteAccess
  268. )
  269. /*++
  270. Routine Description:
  271. MapFileIntoMemoryA and MapFileIntoMemoryW map a file into memory. It does that
  272. by opening the file, creating a mapping object and mapping opened file into
  273. created mapping object. It returnes the address where the file is mapped and
  274. also sets FileHandle and MapHandle variables to be used in order to unmap the
  275. file when work is done.
  276. Arguments:
  277. FileName - the name of the file to be mapped into memory
  278. FileHandle - will end keeping the file handle if the file was opened successfully
  279. MapHandle - will end keeping the mapping object handle if this object was created successfully
  280. Return Value:
  281. NULL if function fails, a valid memory address if successfull
  282. Comments:
  283. If the return value is NULL you should call UnmapFile to release all allocated resources
  284. --*/
  285. {
  286. PVOID fileImage = NULL;
  287. //verify function parameters
  288. if ((FileHandle == NULL) || (MapHandle == NULL)) {
  289. return NULL;
  290. }
  291. //first thing. Try to open the file, read-only
  292. *FileHandle = CreateFileW (
  293. FileName,
  294. WriteAccess?GENERIC_READ|GENERIC_WRITE:GENERIC_READ,
  295. FILE_SHARE_READ,
  296. NULL,
  297. OPEN_EXISTING,
  298. FILE_ATTRIBUTE_NORMAL,
  299. NULL
  300. );
  301. if (*FileHandle == INVALID_HANDLE_VALUE) {
  302. return NULL;
  303. }
  304. //now try to create a mapping object, read-only
  305. *MapHandle = CreateFileMappingW (*FileHandle, NULL, WriteAccess?PAGE_READWRITE:PAGE_READONLY, 0, 0, NULL);
  306. if (*MapHandle == NULL) {
  307. return NULL;
  308. }
  309. //one more thing to do: map view of file
  310. fileImage = MapViewOfFile (*MapHandle, WriteAccess?FILE_MAP_WRITE:FILE_MAP_READ, 0, 0, 0);
  311. return fileImage;
  312. }
  313. #if 0
  314. BOOL
  315. UnmapFile (
  316. IN PCVOID FileImage,
  317. IN HANDLE MapHandle,
  318. IN HANDLE FileHandle
  319. )
  320. /*++
  321. Routine Description:
  322. UnmapFile is used to release all resources allocated by MapFileIntoMemory.
  323. Arguments:
  324. FileImage - image of the mapped file as returned by MapFileIntoMemory
  325. MapHandle - handle of the mapping object as returned by MapFileIntoMemory
  326. FileHandle - handle of the file as returned by MapFileIntoMemory
  327. Return Value:
  328. TRUE if successfull, FALSE if not
  329. --*/
  330. {
  331. BOOL result = TRUE;
  332. //if FileImage is a valid pointer then try to unmap file
  333. if (FileImage != NULL) {
  334. if (UnmapViewOfFile (FileImage) == 0) {
  335. result = FALSE;
  336. }
  337. }
  338. //if mapping object is valid then try to delete it
  339. if (MapHandle != NULL) {
  340. if (CloseHandle (MapHandle) == 0) {
  341. result = FALSE;
  342. }
  343. }
  344. //if file handle is valid then try to close the file
  345. if (FileHandle != INVALID_HANDLE_VALUE) {
  346. if (CloseHandle (FileHandle) == 0) {
  347. result = FALSE;
  348. }
  349. }
  350. return result;
  351. }
  352. #endif
  353. BOOL
  354. BfGetTempFileNameA (
  355. OUT PSTR Buffer,
  356. IN UINT BufferTchars
  357. )
  358. {
  359. CHAR tempPath[MAX_MBCHAR_PATH];
  360. CHAR tempFile[MAX_MBCHAR_PATH];
  361. UINT tchars;
  362. if (!GetTempPathA (ARRAYSIZE(tempPath), tempPath)) {
  363. return FALSE;
  364. }
  365. if (BufferTchars >= MAX_PATH) {
  366. if (!GetTempFileNameA (tempPath, "tmp", 0, Buffer)) {
  367. return FALSE;
  368. }
  369. } else {
  370. if (!GetTempFileNameA (tempPath, "tmp", 0, tempFile)) {
  371. return FALSE;
  372. }
  373. tchars = TcharCountA (tempFile);
  374. if (tchars > BufferTchars) {
  375. DEBUGMSG ((DBG_ERROR, "Can't get temp file name -- buffer too small"));
  376. return FALSE;
  377. }
  378. CopyMemory (Buffer, tempFile, tchars * sizeof (CHAR));
  379. }
  380. return TRUE;
  381. }
  382. BOOL
  383. BfGetTempFileNameW (
  384. OUT PWSTR Buffer,
  385. IN UINT BufferTchars
  386. )
  387. {
  388. WCHAR tempPath[MAX_WCHAR_PATH];
  389. WCHAR tempFile[MAX_WCHAR_PATH];
  390. UINT tchars;
  391. if (!GetTempPathW (ARRAYSIZE(tempPath), tempPath)) {
  392. return FALSE;
  393. }
  394. if (BufferTchars >= MAX_PATH) {
  395. if (!GetTempFileNameW (tempPath, L"tmp", 0, Buffer)) {
  396. return FALSE;
  397. }
  398. } else {
  399. if (!GetTempFileNameW (tempPath, L"tmp", 0, tempFile)) {
  400. return FALSE;
  401. }
  402. tchars = TcharCountW (tempFile);
  403. if (tchars > BufferTchars) {
  404. DEBUGMSG ((DBG_ERROR, "Can't get temp file name -- buffer too small"));
  405. return FALSE;
  406. }
  407. CopyMemory (Buffer, tempFile, tchars * sizeof (WCHAR));
  408. }
  409. return TRUE;
  410. }
  411. HANDLE
  412. BfGetTempFile (
  413. VOID
  414. )
  415. {
  416. CHAR tempFile[MAX_MBCHAR_PATH];
  417. HANDLE file;
  418. if (!BfGetTempFileNameA (tempFile, ARRAYSIZE(tempFile))) {
  419. return NULL;
  420. }
  421. file = CreateFile (
  422. tempFile,
  423. GENERIC_READ|GENERIC_WRITE,
  424. 0,
  425. NULL,
  426. CREATE_ALWAYS,
  427. FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE,
  428. NULL
  429. );
  430. if (file == INVALID_HANDLE_VALUE) {
  431. file = NULL;
  432. }
  433. return file;
  434. }
  435. BOOL
  436. BfSetFilePointer (
  437. IN HANDLE File,
  438. IN LONGLONG Offset
  439. )
  440. {
  441. LARGE_INTEGER li;
  442. li.QuadPart = Offset;
  443. li.LowPart = SetFilePointer (File, li.LowPart, &li.HighPart, FILE_BEGIN);
  444. if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
  445. li.QuadPart = -1;
  446. }
  447. return li.QuadPart != -1;
  448. }
  449. HANDLE
  450. BfOpenFileA (
  451. IN PCSTR FileName
  452. )
  453. {
  454. HANDLE handle;
  455. handle = CreateFileA (
  456. FileName,
  457. GENERIC_READ|GENERIC_WRITE,
  458. 0,
  459. NULL,
  460. OPEN_EXISTING,
  461. FILE_ATTRIBUTE_NORMAL,
  462. NULL
  463. );
  464. if (handle == INVALID_HANDLE_VALUE) {
  465. handle = NULL;
  466. }
  467. return handle;
  468. }
  469. HANDLE
  470. BfOpenFileW (
  471. IN PCWSTR FileName
  472. )
  473. {
  474. HANDLE handle;
  475. handle = CreateFileW (
  476. FileName,
  477. GENERIC_READ|GENERIC_WRITE,
  478. 0,
  479. NULL,
  480. OPEN_EXISTING,
  481. FILE_ATTRIBUTE_NORMAL,
  482. NULL
  483. );
  484. if (handle == INVALID_HANDLE_VALUE) {
  485. handle = NULL;
  486. }
  487. return handle;
  488. }
  489. HANDLE
  490. BfCreateFileA (
  491. IN PCSTR FileName
  492. )
  493. {
  494. HANDLE handle;
  495. handle = CreateFileA (
  496. FileName,
  497. GENERIC_READ|GENERIC_WRITE,
  498. 0,
  499. NULL,
  500. CREATE_ALWAYS,
  501. FILE_ATTRIBUTE_NORMAL,
  502. NULL
  503. );
  504. if (handle == INVALID_HANDLE_VALUE) {
  505. handle = NULL;
  506. }
  507. return handle;
  508. }
  509. HANDLE
  510. BfCreateFileW (
  511. IN PCWSTR FileName
  512. )
  513. {
  514. HANDLE handle;
  515. handle = CreateFileW (
  516. FileName,
  517. GENERIC_READ|GENERIC_WRITE,
  518. 0,
  519. NULL,
  520. CREATE_ALWAYS,
  521. FILE_ATTRIBUTE_NORMAL,
  522. NULL
  523. );
  524. if (handle == INVALID_HANDLE_VALUE) {
  525. handle = NULL;
  526. }
  527. return handle;
  528. }
  529. HANDLE
  530. BfCreateSharedFileA (
  531. IN PCSTR FileName
  532. )
  533. {
  534. HANDLE handle;
  535. handle = CreateFileA (
  536. FileName,
  537. GENERIC_READ|GENERIC_WRITE,
  538. FILE_SHARE_READ|FILE_SHARE_WRITE,
  539. NULL,
  540. CREATE_ALWAYS,
  541. FILE_ATTRIBUTE_NORMAL,
  542. NULL
  543. );
  544. if (handle == INVALID_HANDLE_VALUE) {
  545. handle = NULL;
  546. }
  547. return handle;
  548. }
  549. HANDLE
  550. BfCreateSharedFileW (
  551. IN PCWSTR FileName
  552. )
  553. {
  554. HANDLE handle;
  555. handle = CreateFileW (
  556. FileName,
  557. GENERIC_READ|GENERIC_WRITE,
  558. FILE_SHARE_READ|FILE_SHARE_WRITE,
  559. NULL,
  560. CREATE_ALWAYS,
  561. FILE_ATTRIBUTE_NORMAL,
  562. NULL
  563. );
  564. if (handle == INVALID_HANDLE_VALUE) {
  565. handle = NULL;
  566. }
  567. return handle;
  568. }
  569. BOOL
  570. BfSetSizeOfFile (
  571. HANDLE File,
  572. LONGLONG Size
  573. )
  574. {
  575. if (!BfSetFilePointer (File, Size)) {
  576. return FALSE;
  577. }
  578. return SetEndOfFile (File);
  579. }
  580. BOOL
  581. BfGoToEndOfFile (
  582. IN HANDLE File,
  583. OUT PLONGLONG FileSize OPTIONAL
  584. )
  585. {
  586. LARGE_INTEGER li;
  587. li.HighPart = 0;
  588. li.LowPart = SetFilePointer (File, 0, &li.HighPart, FILE_END);
  589. if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
  590. li.QuadPart = -1;
  591. } else if (FileSize) {
  592. *FileSize = li.QuadPart;
  593. }
  594. return li.QuadPart != -1;
  595. }
  596. BOOL
  597. BfGetFilePointer (
  598. IN HANDLE File,
  599. OUT PLONGLONG FilePointer OPTIONAL
  600. )
  601. {
  602. LARGE_INTEGER li;
  603. li.HighPart = 0;
  604. li.LowPart = SetFilePointer (File, 0, &li.HighPart, FILE_CURRENT);
  605. if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
  606. li.QuadPart = -1;
  607. } else if (FilePointer) {
  608. *FilePointer = li.QuadPart;
  609. }
  610. return li.QuadPart != -1;
  611. }
  612. BOOL
  613. BfReadFile (
  614. IN HANDLE File,
  615. OUT PBYTE Buffer,
  616. IN UINT BytesToRead
  617. )
  618. {
  619. DWORD bytesRead;
  620. if (!ReadFile (File, Buffer, BytesToRead, &bytesRead, NULL)) {
  621. return FALSE;
  622. }
  623. return bytesRead == BytesToRead;
  624. }
  625. BOOL
  626. BfWriteFile (
  627. IN HANDLE File,
  628. OUT PCBYTE Buffer,
  629. IN UINT BytesToWrite
  630. )
  631. {
  632. DWORD bytesWritten;
  633. if (!WriteFile (File, Buffer, BytesToWrite, &bytesWritten, NULL)) {
  634. return FALSE;
  635. }
  636. return bytesWritten == BytesToWrite;
  637. }
  638. BOOL
  639. BfCreateDirectoryA (
  640. IN PCSTR FullPath
  641. )
  642. {
  643. PSTR pathCopy;
  644. PSTR p;
  645. BOOL b = TRUE;
  646. pathCopy = DuplicatePathStringA (FullPath, 0);
  647. //
  648. // Advance past first directory
  649. //
  650. if (pathCopy[1] == ':' && pathCopy[2] == '\\') {
  651. //
  652. // <drive>:\ case
  653. //
  654. p = _mbschr (&pathCopy[3], '\\');
  655. } else if (pathCopy[0] == '\\' && pathCopy[1] == '\\') {
  656. //
  657. // UNC case
  658. //
  659. p = _mbschr (pathCopy + 2, '\\');
  660. if (p) {
  661. p = _mbschr (p + 1, '\\');
  662. if (p) {
  663. p++;
  664. }
  665. }
  666. } else {
  667. //
  668. // Relative dir case
  669. //
  670. p = _mbschr (pathCopy, '\\');
  671. }
  672. //
  673. // Make all directories along the path
  674. //
  675. while (p) {
  676. *p = 0;
  677. b = CreateDirectoryA (pathCopy, NULL);
  678. if (!b && GetLastError() == ERROR_ALREADY_EXISTS) {
  679. b = TRUE;
  680. }
  681. if (!b) {
  682. break;
  683. }
  684. *p = '\\';
  685. p = _mbschr (p + 1, '\\');
  686. }
  687. //
  688. // At last, make the FullPath directory
  689. //
  690. if (b) {
  691. b = CreateDirectoryA (pathCopy, NULL);
  692. if (!b && GetLastError() == ERROR_ALREADY_EXISTS) {
  693. b = TRUE;
  694. }
  695. }
  696. FreePathStringA (pathCopy);
  697. return b;
  698. }
  699. BOOL
  700. BfCreateDirectoryW (
  701. IN PCWSTR FullPath
  702. )
  703. {
  704. PWSTR pathCopy;
  705. PWSTR p;
  706. BOOL b = TRUE;
  707. pathCopy = DuplicatePathStringW (FullPath, 0);
  708. //
  709. // Advance past first directory
  710. //
  711. if (pathCopy[1] == L':' && pathCopy[2] == L'\\') {
  712. //
  713. // <drive>:\ case
  714. //
  715. p = wcschr (&pathCopy[3], L'\\');
  716. } else if (pathCopy[0] == L'\\' && pathCopy[1] == L'\\') {
  717. //
  718. // UNC case
  719. //
  720. p = wcschr (pathCopy + 2, L'\\');
  721. if (p) {
  722. p = wcschr (p + 1, L'\\');
  723. if (p) {
  724. p++;
  725. }
  726. }
  727. } else {
  728. //
  729. // Relative dir case
  730. //
  731. p = wcschr (pathCopy, L'\\');
  732. }
  733. //
  734. // Make all directories along the path
  735. //
  736. while (p) {
  737. *p = 0;
  738. b = CreateDirectoryW (pathCopy, NULL);
  739. if (!b && GetLastError() == ERROR_ALREADY_EXISTS) {
  740. b = TRUE;
  741. }
  742. if (!b) {
  743. break;
  744. }
  745. *p = L'\\';
  746. p = wcschr (p + 1, L'\\');
  747. }
  748. //
  749. // At last, make the FullPath directory
  750. //
  751. if (b) {
  752. b = CreateDirectoryW (pathCopy, NULL);
  753. if (!b && GetLastError() == ERROR_ALREADY_EXISTS) {
  754. b = TRUE;
  755. }
  756. }
  757. FreePathStringW (pathCopy);
  758. return b;
  759. }
  760. LONGLONG
  761. BfGetFileSizeA (
  762. IN PCSTR FileName
  763. )
  764. {
  765. WIN32_FIND_DATAA fd;
  766. LONGLONG l;
  767. if (!DoesFileExistExA (FileName, &fd)) {
  768. return 0;
  769. }
  770. l = ((LONGLONG) fd.nFileSizeHigh << 32) | fd.nFileSizeLow;
  771. return l;
  772. }
  773. PSTR
  774. pGetFirstSegA (
  775. IN PCSTR SrcFileName
  776. )
  777. {
  778. if (SrcFileName [0] == '\\') {
  779. SrcFileName ++;
  780. if (SrcFileName [0] == '\\') {
  781. SrcFileName ++;
  782. }
  783. return (_mbschr (SrcFileName, '\\'));
  784. } else {
  785. return (_mbschr (SrcFileName, '\\'));
  786. }
  787. }
  788. BOOL
  789. pGetLongFileNameWorkerA (
  790. IN PCSTR SrcFileName,
  791. IN PGROWBUFFER GrowBuf
  792. )
  793. {
  794. PSTR beginSegPtr;
  795. PSTR endSegPtr;
  796. WIN32_FIND_DATAA findData;
  797. CHAR savedChar;
  798. beginSegPtr = pGetFirstSegA (SrcFileName);
  799. if (!beginSegPtr) {
  800. GbAppendStringA (GrowBuf, SrcFileName);
  801. return TRUE;
  802. }
  803. beginSegPtr = _mbsinc (beginSegPtr);
  804. GbAppendStringABA (GrowBuf, SrcFileName, beginSegPtr);
  805. while (beginSegPtr) {
  806. endSegPtr = _mbschr (beginSegPtr, '\\');
  807. if (!endSegPtr) {
  808. endSegPtr = GetEndOfStringA (beginSegPtr);
  809. MYASSERT (endSegPtr);
  810. }
  811. savedChar = *endSegPtr;
  812. *endSegPtr = 0;
  813. if (DoesFileExistExA (SrcFileName, &findData)) {
  814. GbAppendStringA (GrowBuf, findData.cFileName);
  815. } else {
  816. GbAppendStringABA (GrowBuf, beginSegPtr, endSegPtr);
  817. }
  818. *endSegPtr = savedChar;
  819. if (savedChar) {
  820. beginSegPtr = _mbsinc (endSegPtr);
  821. GbAppendStringABA (GrowBuf, endSegPtr, beginSegPtr);
  822. } else {
  823. beginSegPtr = NULL;
  824. }
  825. }
  826. return TRUE;
  827. }
  828. PCSTR
  829. BfGetLongFileNameA (
  830. IN PCSTR SrcFileName
  831. )
  832. {
  833. GROWBUFFER growBuf = INIT_GROWBUFFER;
  834. PSTR srcFileName;
  835. PCSTR result = NULL;
  836. srcFileName = (PSTR)SanitizePathA (SrcFileName);
  837. if (pGetLongFileNameWorkerA (srcFileName, &growBuf)) {
  838. result = DuplicatePathStringA (growBuf.Buf, 0);
  839. GbFree (&growBuf);
  840. }
  841. FreePathStringA (srcFileName);
  842. return result;
  843. }
  844. BOOL
  845. BfGetLongFileNameExA (
  846. IN PCSTR SrcFileName,
  847. IN PGROWBUFFER GrowBuff
  848. )
  849. {
  850. PSTR srcFileName;
  851. BOOL result;
  852. srcFileName = (PSTR)SanitizePathA (SrcFileName);
  853. result = pGetLongFileNameWorkerA (srcFileName, GrowBuff);
  854. FreePathStringA (srcFileName);
  855. return result;
  856. }
  857. PWSTR
  858. pGetFirstSegW (
  859. IN PCWSTR SrcFileName
  860. )
  861. {
  862. if (SrcFileName [0] == L'\\') {
  863. SrcFileName ++;
  864. if (SrcFileName [0] == L'\\') {
  865. SrcFileName ++;
  866. }
  867. return (wcschr (SrcFileName, L'\\'));
  868. } else {
  869. return (wcschr (SrcFileName, L'\\'));
  870. }
  871. }
  872. BOOL
  873. pGetLongFileNameWorkerW (
  874. IN PCWSTR SrcFileName,
  875. IN PGROWBUFFER GrowBuf
  876. )
  877. {
  878. PWSTR beginSegPtr;
  879. PWSTR endSegPtr;
  880. WIN32_FIND_DATAW findData;
  881. WCHAR savedChar;
  882. beginSegPtr = pGetFirstSegW (SrcFileName);
  883. if (!beginSegPtr) {
  884. GbAppendStringW (GrowBuf, SrcFileName);
  885. return TRUE;
  886. }
  887. beginSegPtr ++;
  888. GbAppendStringABW (GrowBuf, SrcFileName, beginSegPtr);
  889. while (beginSegPtr) {
  890. endSegPtr = wcschr (beginSegPtr, L'\\');
  891. if (!endSegPtr) {
  892. endSegPtr = GetEndOfStringW (beginSegPtr);
  893. MYASSERT (endSegPtr);
  894. }
  895. savedChar = *endSegPtr;
  896. *endSegPtr = 0;
  897. if (DoesFileExistExW (SrcFileName, &findData)) {
  898. GbAppendStringW (GrowBuf, findData.cFileName);
  899. } else {
  900. GbAppendStringABW (GrowBuf, beginSegPtr, endSegPtr);
  901. }
  902. *endSegPtr = savedChar;
  903. if (savedChar) {
  904. beginSegPtr = endSegPtr + 1;
  905. GbAppendStringABW (GrowBuf, endSegPtr, beginSegPtr);
  906. } else {
  907. beginSegPtr = NULL;
  908. }
  909. }
  910. return TRUE;
  911. }
  912. PCWSTR
  913. BfGetLongFileNameW (
  914. IN PCWSTR SrcFileName
  915. )
  916. {
  917. GROWBUFFER growBuf = INIT_GROWBUFFER;
  918. PWSTR srcFileName;
  919. PCWSTR result = NULL;
  920. srcFileName = (PWSTR)SanitizePathW (SrcFileName);
  921. if (pGetLongFileNameWorkerW (srcFileName, &growBuf)) {
  922. result = DuplicatePathStringW ((PCWSTR)growBuf.Buf, 0);
  923. GbFree (&growBuf);
  924. }
  925. FreePathStringW (srcFileName);
  926. return result;
  927. }
  928. BOOL
  929. BfGetLongFileNameExW (
  930. IN PCWSTR SrcFileName,
  931. IN PGROWBUFFER GrowBuff
  932. )
  933. {
  934. PWSTR srcFileName;
  935. BOOL result;
  936. srcFileName = (PWSTR)SanitizePathW (SrcFileName);
  937. result = pGetLongFileNameWorkerW (srcFileName, GrowBuff);
  938. FreePathStringW (srcFileName);
  939. return result;
  940. }