File.cpp 21 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /******************************************************************************
  19. *
  20. * FILE
  21. * $Archive: /Commando/Code/Launcher/Toolkit/Storage/File.cpp $
  22. *
  23. * DESCRIPTION
  24. * File functionality for WIN32
  25. *
  26. * PROGRAMMER
  27. * Denzil E. Long, Jr.
  28. * $Author: Denzil_l $
  29. *
  30. * VERSION INFO
  31. * $Modtime: 9/23/00 6:19p $
  32. * $Revision: 1 $
  33. *
  34. ******************************************************************************/
  35. #include "File.h"
  36. #include <Debug\DebugPrint.h>
  37. #include <assert.h>
  38. // This should be whatever the file system uses for invalid files
  39. const HANDLE File::INVALID_HANDLE = INVALID_HANDLE_VALUE;
  40. /******************************************************************************
  41. *
  42. * NAME
  43. * File
  44. *
  45. * DESCRIPTION
  46. * Default constructor
  47. *
  48. * INPUTS
  49. * NONE
  50. *
  51. * RETURN
  52. * NONE
  53. *
  54. ******************************************************************************/
  55. File::File()
  56. : mRights(Rights_ReadOnly),
  57. mHandle(INVALID_HANDLE)
  58. {
  59. }
  60. /******************************************************************************
  61. *
  62. * NAME
  63. * File
  64. *
  65. * DESCRIPTION
  66. * Create a file instance with the specified name and access rights.
  67. *
  68. * INPUTS
  69. * Name - Name of file
  70. * Rights - Access rights
  71. *
  72. * RETURN
  73. * NONE
  74. *
  75. ******************************************************************************/
  76. File::File(const Char* name, ERights rights)
  77. : mRights(rights),
  78. mHandle(INVALID_HANDLE)
  79. {
  80. SetName(name);
  81. }
  82. /******************************************************************************
  83. *
  84. * NAME
  85. * File
  86. *
  87. * DESCRIPTION
  88. * Create a file instance with the specified name and access rights.
  89. *
  90. * INPUTS
  91. * Name - Name of file
  92. * Rights - Access rights
  93. *
  94. * RETURN
  95. * NONE
  96. *
  97. ******************************************************************************/
  98. File::File(const UString& name, ERights rights)
  99. : mName(name),
  100. mRights(rights),
  101. mHandle(INVALID_HANDLE)
  102. {
  103. }
  104. /******************************************************************************
  105. *
  106. * NAME
  107. * ~File
  108. *
  109. * DESCRIPTION
  110. * Destroy a file representation.
  111. *
  112. * INPUTS
  113. * NONE
  114. *
  115. * RESULT
  116. * NONE
  117. *
  118. ******************************************************************************/
  119. File::~File()
  120. {
  121. // Close any open file.
  122. Close();
  123. }
  124. /******************************************************************************
  125. *
  126. * NAME
  127. * GetName
  128. *
  129. * DESCRIPTION
  130. * Retrieve name of file
  131. *
  132. * INPUTS
  133. * NONE
  134. *
  135. * RETURN
  136. * Name - Name of file.
  137. *
  138. ******************************************************************************/
  139. const UString& File::GetName(void) const
  140. {
  141. return mName;
  142. }
  143. /******************************************************************************
  144. *
  145. * NAME
  146. * SetName
  147. *
  148. * DESCRIPTION
  149. * Associate a filename to the file class. Any operations will be performed
  150. * on the associated file with the specified name.
  151. *
  152. * INPUTS
  153. * Filename - Name of file to associate.
  154. *
  155. * RESULT
  156. * NONE
  157. *
  158. ******************************************************************************/
  159. void File::SetName(const UString& name)
  160. {
  161. mName = name;
  162. }
  163. /******************************************************************************
  164. *
  165. * NAME
  166. * GetRights
  167. *
  168. * DESCRIPTION
  169. * Retrieve file access rights
  170. *
  171. * INPUTS
  172. * NONE
  173. *
  174. * RETURN
  175. * Rights - Current access rights for file
  176. *
  177. ******************************************************************************/
  178. ERights File::GetRights(void) const
  179. {
  180. return mRights;
  181. }
  182. /******************************************************************************
  183. *
  184. * NAME
  185. * SetRights
  186. *
  187. * DESCRIPTION
  188. * Set file access rights
  189. *
  190. * INPUTS
  191. * Rights - New rights
  192. *
  193. * RESULT
  194. * NONE
  195. *
  196. ******************************************************************************/
  197. void File::SetRights(ERights rights)
  198. {
  199. mRights = rights;
  200. }
  201. /******************************************************************************
  202. *
  203. * NAME
  204. * IsAvailable
  205. *
  206. * DESCRIPTION
  207. * Checks if the associated file is available for access. If the force
  208. * flag is true then the file is check for availabilty until it is found
  209. * or the proceedure is aborted via OnError().
  210. *
  211. * INPUTS
  212. * Force - Force file availability flag.
  213. *
  214. * RESULT
  215. * Success - Success/Failure condition flag.
  216. *
  217. ******************************************************************************/
  218. bool File::IsAvailable(bool force)
  219. {
  220. // If the filename is invalid then the file is not available.
  221. if (mName.Length() == 0)
  222. {
  223. return false;
  224. }
  225. // If the file is open then it must be available.
  226. if (IsOpen())
  227. {
  228. return true;
  229. }
  230. // If this is a forced open then go through the standard file open
  231. // procedure so that the abort/retry logic gets called.
  232. if (force == true)
  233. {
  234. Open(GetRights());
  235. Close();
  236. return true;
  237. }
  238. char name[MAX_PATH];
  239. mName.ConvertToANSI(name, sizeof(name));
  240. // Attempt to open the file
  241. mHandle = CreateFile(name, GENERIC_READ, FILE_SHARE_READ,
  242. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  243. // If the open failed then the file is not available.
  244. if (mHandle == INVALID_HANDLE)
  245. {
  246. return false;
  247. }
  248. // Close the file.
  249. CloseHandle(mHandle);
  250. mHandle = INVALID_HANDLE;
  251. return true;
  252. }
  253. /******************************************************************************
  254. *
  255. * NAME
  256. * IsOpen
  257. *
  258. * DESCRIPTION
  259. * Check if the file is open.
  260. *
  261. * INPUTS
  262. * NONE
  263. *
  264. * RETURN
  265. * Opened - File is opened if true; otherwise false
  266. *
  267. ******************************************************************************/
  268. bool File::IsOpen(void) const
  269. {
  270. return ((mHandle != INVALID_HANDLE) ? true : false);
  271. }
  272. /******************************************************************************
  273. *
  274. * NAME
  275. * Open
  276. *
  277. * DESCRIPTION
  278. * Opens the file associated with this file class.
  279. *
  280. * INPUTS
  281. * Rights - Access rights for the file to open.
  282. *
  283. * RESULT
  284. * Success - Success/Failure condition flag.
  285. *
  286. ******************************************************************************/
  287. File::EFileError File::Open(ERights rights)
  288. {
  289. // Close any currently opened file
  290. Close();
  291. // If the filename is invalid then there is no way to open the file.
  292. if (mName.Length() == 0)
  293. {
  294. OnFileError(FileError_FNF, false);
  295. return FileError_FNF;
  296. }
  297. mRights = rights;
  298. char name[MAX_PATH];
  299. mName.ConvertToANSI(name, sizeof(name));
  300. // Continue attempting open until successful or aborted.
  301. for (;;)
  302. {
  303. switch (rights)
  304. {
  305. // Read only access
  306. case Rights_ReadOnly:
  307. mHandle = CreateFile(name, GENERIC_READ, FILE_SHARE_READ,
  308. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  309. break;
  310. // Write only access
  311. case Rights_WriteOnly:
  312. mHandle = CreateFile(name, GENERIC_WRITE, 0,
  313. NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  314. break;
  315. // Read and Write access
  316. case Rights_ReadWrite:
  317. mHandle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0,
  318. NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  319. break;
  320. // Unknown rights access violation
  321. default:
  322. OnFileError(FileError_Access, false);
  323. return FileError_Access;
  324. break;
  325. }
  326. // Check for open failure
  327. if (mHandle == INVALID_HANDLE)
  328. {
  329. PrintWin32Error("File::Open(%S)", mName.Get());
  330. if (GetLastError() == ERROR_FILE_NOT_FOUND)
  331. {
  332. if (OnFileError(FileError_FNF, true) == false)
  333. {
  334. return FileError_FNF;
  335. }
  336. else
  337. {
  338. continue;
  339. }
  340. }
  341. else
  342. {
  343. OnFileError(FileError_Open, false);
  344. return FileError_Open;
  345. }
  346. }
  347. break;
  348. }
  349. return FileError_None;
  350. }
  351. /******************************************************************************
  352. *
  353. * NAME
  354. * Open
  355. *
  356. * DESCRIPTION
  357. * Associate a file then open that file.
  358. *
  359. * INPUTS
  360. * Filename - Name of file to open.
  361. * Rights - Access rights to file.
  362. *
  363. * RESULT
  364. * Success - Success/Failure condition flag.
  365. *
  366. ******************************************************************************/
  367. File::EFileError File::Open(const UString& name, ERights rights)
  368. {
  369. // Associate the file then attempt to open it.
  370. SetName(name);
  371. return Open(rights);
  372. }
  373. /******************************************************************************
  374. *
  375. * NAME
  376. * Close
  377. *
  378. * DESCRIPTION
  379. * Close access to the file.
  380. *
  381. * INPUTS
  382. * NONE
  383. *
  384. * RESULT
  385. * NONE
  386. *
  387. ******************************************************************************/
  388. void File::Close(void)
  389. {
  390. if (IsOpen())
  391. {
  392. CloseHandle(mHandle);
  393. mHandle = INVALID_HANDLE;
  394. }
  395. }
  396. /******************************************************************************
  397. *
  398. * NAME
  399. * Create
  400. *
  401. * DESCRIPTION
  402. * Creates a file on the local file system with a filename previously
  403. * associated with a call to SetName().
  404. *
  405. * INPUTS
  406. * NONE
  407. *
  408. * RESULT
  409. * Success - Success/Failure condition flag.
  410. *
  411. ******************************************************************************/
  412. File::EFileError File::Create(void)
  413. {
  414. // Close any previous handle
  415. Close();
  416. // Open the file for writing
  417. EFileError error = Open(Rights_WriteOnly);
  418. if (error == FileError_None)
  419. {
  420. Close();
  421. }
  422. return error;
  423. }
  424. /******************************************************************************
  425. *
  426. * NAME
  427. * Delete
  428. *
  429. * DESCRIPTION
  430. * Deletes the file on the local file system with the name previously
  431. * associated by calling SetName().
  432. *
  433. * INPUTS
  434. * NONE
  435. *
  436. * RESULT
  437. * Success - Success/Failure condition flag.
  438. *
  439. ******************************************************************************/
  440. File::EFileError File::Delete(void)
  441. {
  442. // Make sure the file is closed.
  443. Close();
  444. // The file must be available before it can be deleted.
  445. if (IsAvailable() == false)
  446. {
  447. return FileError_FNF;
  448. }
  449. else
  450. {
  451. // Delete the file. Pass error conditions to OnError()
  452. char name[MAX_PATH];
  453. mName.ConvertToANSI(name, sizeof(name));
  454. if (!DeleteFile(name))
  455. {
  456. OnFileError(FileError_Fault, false);
  457. return FileError_Fault;
  458. }
  459. }
  460. return FileError_None;
  461. }
  462. /******************************************************************************
  463. *
  464. * NAME
  465. * Load
  466. *
  467. * DESCRIPTION
  468. * The entire contents of the file is loaded into the specified buffer.
  469. *
  470. * INPUTS
  471. * outBuffer - Buffer with file contents.
  472. *
  473. * RESULT
  474. *
  475. ******************************************************************************/
  476. File::EFileError File::Load(void*& outBuffer, UInt32& outSize)
  477. {
  478. outBuffer = NULL;
  479. outSize = 0;
  480. // Enforce access control
  481. if (mRights == Rights_WriteOnly)
  482. {
  483. OnFileError(FileError_Access, false);
  484. return FileError_Access;
  485. }
  486. EFileError result = FileError_None;
  487. // Open the file here if it isn't already.
  488. bool openedHere = false;
  489. if (IsOpen() == false)
  490. {
  491. result = Open(GetRights());
  492. if (result != FileError_None)
  493. {
  494. return result;
  495. }
  496. // The file was opened here.
  497. openedHere = true;
  498. }
  499. // Get the size of the file
  500. UInt32 size = GetFileSize(mHandle, NULL);
  501. if (size == 0xFFFFFFFF)
  502. {
  503. PrintWin32Error("File::Load(%S) - GetFileSize", mName.Get());
  504. result = FileError_Fault;
  505. OnFileError(result, false);
  506. }
  507. if (result == FileError_None)
  508. {
  509. // Allocate buffer to hold file contents
  510. outBuffer = malloc(size);
  511. outSize = size;
  512. // If allocation succeded then load file data.
  513. if (outBuffer != NULL)
  514. {
  515. // Fill the buffer with the file contents
  516. while (size > 0)
  517. {
  518. unsigned long bytesRead = 0;
  519. // Read in some bytes.
  520. if (ReadFile(mHandle, outBuffer, size, &bytesRead, NULL) == 0)
  521. {
  522. result = FileError_Read;
  523. if (OnFileError(result, true) == false)
  524. {
  525. break;
  526. }
  527. result = FileError_None;
  528. }
  529. size -= bytesRead;
  530. if (bytesRead == 0)
  531. {
  532. break;
  533. }
  534. }
  535. }
  536. else
  537. {
  538. result = FileError_Nomem;
  539. OnFileError(result, false);
  540. }
  541. }
  542. // Close the file if we opened it here.
  543. if (openedHere == true)
  544. {
  545. Close();
  546. }
  547. return result;
  548. }
  549. /******************************************************************************
  550. *
  551. * NAME
  552. * Save
  553. *
  554. * DESCRIPTION
  555. * Save data to the file.
  556. *
  557. * INPUTS
  558. * Buffer - Pointer to data to write.
  559. * Size - Number of bytes to write.
  560. *
  561. * RESULT
  562. *
  563. ******************************************************************************/
  564. File::EFileError File::Save(const void* buffer, UInt32 size)
  565. {
  566. // Enforce access control
  567. if (mRights == Rights_ReadOnly)
  568. {
  569. OnFileError(FileError_Access, false);
  570. return FileError_Access;
  571. }
  572. EFileError result = FileError_None;
  573. // Open the file if it isn't already.
  574. bool openedHere = false;
  575. if (IsOpen() == false)
  576. {
  577. result = Open(GetRights());
  578. if (result == FileError_None)
  579. {
  580. openedHere = true;
  581. }
  582. }
  583. if (result == FileError_None)
  584. {
  585. SetMarker(0, EStreamFrom::FromStart);
  586. // Write the data to the file.
  587. unsigned long bytesWritten = 0;
  588. if (WriteFile(mHandle, buffer, size, &bytesWritten, NULL) == 0)
  589. {
  590. result = FileError_Write;
  591. OnFileError(result, false);
  592. }
  593. else
  594. {
  595. SetEndOfFile(mHandle);
  596. }
  597. }
  598. // If we opened the file here then we must close it here.
  599. if (openedHere == true)
  600. {
  601. Close();
  602. }
  603. // Return the number of actual butes written.
  604. return result;
  605. }
  606. /******************************************************************************
  607. *
  608. * NAME
  609. * OnFileError(Error, CanRetry)
  610. *
  611. * DESCRIPTION
  612. *
  613. * INPUTS
  614. * Error - Error condition code.
  615. * CanRetry - Retry allowed flag. If this is false then retrys are not
  616. * permitted for this failure condition.
  617. *
  618. * RESULT
  619. * Retry - Retry flag.
  620. *
  621. ******************************************************************************/
  622. #pragma warning(disable:4100)
  623. bool File::OnFileError(EFileError error, bool)
  624. {
  625. #ifdef _DEBUG
  626. const char* _errorNames[] =
  627. {
  628. "FileError_None",
  629. "FileError_FNF",
  630. "FileError_Access",
  631. "FileError_Open",
  632. "FileError_Read",
  633. "FileError_Write",
  634. "FileError_Seek",
  635. "FileError_Nomem",
  636. "FileError_Fault",
  637. };
  638. DebugPrint("File::OnFileError(%S) - %s\n", mName.Get(), _errorNames[error]);
  639. #endif
  640. return false;
  641. }
  642. /******************************************************************************
  643. *
  644. * NAME
  645. * GetLength
  646. *
  647. * DESCRIPTION
  648. * Get the size of the file and return it to the caller.
  649. *
  650. * INPUTS
  651. * NONE
  652. *
  653. * RESULT
  654. * Length of the file in bytes.
  655. *
  656. ******************************************************************************/
  657. UInt32 File::GetLength(void)
  658. {
  659. // If the file is not open then it must be opened first.
  660. bool openedHere = false;
  661. if (IsOpen() == false)
  662. {
  663. if (Open(GetRights()) != FileError_None)
  664. {
  665. return 0xFFFFFFFF;
  666. }
  667. openedHere = true;
  668. }
  669. UInt32 length = GetFileSize(mHandle, NULL);
  670. if (length == 0xFFFFFFFF)
  671. {
  672. OnFileError(FileError_Fault, false);
  673. }
  674. // If the file was opened here then we need to close it.
  675. if (openedHere == true)
  676. {
  677. Close();
  678. }
  679. return length;
  680. }
  681. /******************************************************************************
  682. *
  683. * NAME
  684. * SetLength
  685. *
  686. * DESCRIPTION
  687. * Set the length of the streamable file.
  688. *
  689. * INPUTS
  690. * Length - Length of stream in bytes
  691. *
  692. * RESULT
  693. * NONE
  694. *
  695. ******************************************************************************/
  696. void File::SetLength(UInt32 length)
  697. {
  698. // Get the current file position
  699. UInt32 position = SetFilePointer(mHandle, 0, NULL, FILE_CURRENT);
  700. // Extend the file size by positioning the Win32 file pointer to the
  701. // specified location then setting the end of file.
  702. SetFilePointer(mHandle, length, NULL, FILE_BEGIN);
  703. SetEndOfFile(mHandle);
  704. // Restore file position
  705. SetFilePointer(mHandle, position, NULL, FILE_BEGIN);
  706. }
  707. /******************************************************************************
  708. *
  709. * NAME
  710. * GetMarker
  711. *
  712. * DESCRIPTION
  713. * Returns the current position in the file stream.
  714. *
  715. * INPUTS
  716. * NONE
  717. *
  718. * RESULT
  719. * Current position in file
  720. *
  721. ******************************************************************************/
  722. UInt32 File::GetMarker(void)
  723. {
  724. return SetFilePointer(mHandle, 0, NULL, FILE_CURRENT);
  725. }
  726. /******************************************************************************
  727. *
  728. * NAME
  729. * SetMarker
  730. *
  731. * DESCRIPTION
  732. * Position the marker within the file stream.
  733. *
  734. * INPUTS
  735. * Offset - Offset to adjust marker by
  736. * From -
  737. *
  738. * RESULT
  739. * NONE
  740. *
  741. ******************************************************************************/
  742. void File::SetMarker(Int32 offset, EStreamFrom from)
  743. {
  744. // The file must be open before we can seek into it.
  745. if (IsOpen() == false)
  746. {
  747. OnFileError(FileError_Seek, false);
  748. }
  749. else
  750. {
  751. unsigned long dir;
  752. switch (from)
  753. {
  754. default:
  755. case Stream::FromStart:
  756. dir = FILE_BEGIN;
  757. break;
  758. case Stream::FromMarker:
  759. dir = FILE_CURRENT;
  760. break;
  761. case Stream::FromEnd:
  762. dir = FILE_END;
  763. break;
  764. }
  765. offset = SetFilePointer(mHandle, offset, NULL, dir);
  766. if (offset == 0xFFFFFFFF)
  767. {
  768. OnFileError(FileError_Seek, false);
  769. }
  770. }
  771. }
  772. /******************************************************************************
  773. *
  774. * NAME
  775. * AtEnd
  776. *
  777. * DESCRIPTION
  778. * Test if at the end of stream.
  779. *
  780. * INPUTS
  781. * NONE
  782. *
  783. * RESULT
  784. * End - True if at end; otherwise False.
  785. *
  786. ******************************************************************************/
  787. bool File::AtEnd(void)
  788. {
  789. return (GetMarker() >= GetLength());
  790. }
  791. /******************************************************************************
  792. *
  793. * NAME
  794. * GetBytes
  795. *
  796. * DESCRIPTION
  797. * Retrieve an arbitrary number of bytes from the file stream.
  798. *
  799. * INPUTS
  800. * Buffer - Pointer to buffer to receive data
  801. * Bytes - Number of bytes to read
  802. *
  803. * RESULT
  804. * Read - Number of bytes actually read.
  805. *
  806. ******************************************************************************/
  807. UInt32 File::GetBytes(void* ptr, UInt32 bytes)
  808. {
  809. // Parameter check; Null pointers are bad!
  810. assert(ptr != NULL);
  811. // Enforce rights control
  812. if (GetRights() == Rights_WriteOnly)
  813. {
  814. OnFileError(FileError_Access, false);
  815. return 0;
  816. }
  817. // Open the file if it isn't already
  818. if (IsOpen() == false)
  819. {
  820. if (Open(GetRights()) != FileError_None)
  821. {
  822. return 0;
  823. }
  824. }
  825. // Zero total bytes read count
  826. UInt32 totalRead = 0;
  827. UInt32 bytesToRead = bytes;
  828. while (bytesToRead > 0)
  829. {
  830. unsigned long read;
  831. if (ReadFile(mHandle, ptr, bytesToRead, &read, NULL) == 0)
  832. {
  833. if (OnFileError(FileError_Read, true) == false)
  834. {
  835. return 0;
  836. }
  837. }
  838. // End of file condition?
  839. if (read == 0)
  840. {
  841. break;
  842. }
  843. // Adjust counts
  844. bytesToRead -= read;
  845. totalRead += read;
  846. }
  847. return totalRead;
  848. }
  849. /******************************************************************************
  850. *
  851. * NAME
  852. * PutBytes(Buffer, Bytes)
  853. *
  854. * DESCRIPTION
  855. * Write an arbitrary number of bytes to the stream
  856. *
  857. * INPUTS
  858. * Buffer - Pointer to buffer containing data to write
  859. * Bytes - Number of bytes to transfer
  860. *
  861. * RESULT
  862. * Actual number of bytes written
  863. *
  864. ******************************************************************************/
  865. UInt32 File::PutBytes(const void* ptr, UInt32 bytes)
  866. {
  867. // Parameter check; Null pointers are bad!
  868. assert(ptr != NULL);
  869. // Enforce access control
  870. if (GetRights() == Rights_ReadOnly)
  871. {
  872. OnFileError(FileError_Access, false);
  873. return 0;
  874. }
  875. // The file must already be open.
  876. if (IsOpen() == false)
  877. {
  878. if (Open(GetRights()) != FileError_None)
  879. {
  880. return 0;
  881. }
  882. }
  883. // Zero total bytes written count
  884. UInt32 totalWritten = 0;
  885. UInt32 bytesToWrite = bytes;
  886. while (bytesToWrite > 0)
  887. {
  888. unsigned long written;
  889. if (WriteFile(mHandle, ptr, bytes, &written, NULL) == 0)
  890. {
  891. if (OnFileError(FileError_Write, true) == false)
  892. {
  893. return 0;
  894. }
  895. }
  896. bytesToWrite -= written;
  897. totalWritten += written;
  898. }
  899. return totalWritten;
  900. }
  901. /******************************************************************************
  902. *
  903. * NAME
  904. * PeekBytes(Buffer, Bytes)
  905. *
  906. * DESCRIPTION
  907. * Retrieve bytes from the stream without moving the position marker.
  908. *
  909. * INPUTS
  910. * Buffer - Pointer to buffer to receive data
  911. * Bytes - Number of bytes to retrieve
  912. *
  913. * RESULT
  914. * Actual number of bytes transfered
  915. *
  916. ******************************************************************************/
  917. UInt32 File::PeekBytes(void* ptr, UInt32 bytes)
  918. {
  919. // Parameter check; NULL pointers are bad!
  920. assert(ptr != NULL);
  921. // Get current position
  922. UInt32 pos = GetMarker();
  923. // Get bytes
  924. UInt32 bytesPeeked = GetBytes(ptr, bytes);
  925. // Restore previous position
  926. SetMarker(pos, Stream::FromStart);
  927. return bytesPeeked;
  928. }
  929. /******************************************************************************
  930. *
  931. * NAME
  932. *
  933. * DESCRIPTION
  934. *
  935. * INPUTS
  936. *
  937. * RESULT
  938. *
  939. ******************************************************************************/
  940. void File::Flush(void)
  941. {
  942. }