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.

2178 lines
46 KiB

  1. /*++
  2. Copyright (c) 1990 - 2000 Microsoft Corporation
  3. Module Name:
  4. filepool.cxx
  5. Abstract:
  6. Contains the routines for handling Filepools for the Spooler. Contains the C++ objects
  7. and the C wrapper functions.
  8. Author:
  9. Bryan Kilian (Bryankil) 5-Apr-2000
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include "filepool.hxx"
  15. VOID FPCloseFiles(struct FileListItem * pItem, BOOL CloseShad);
  16. /*--
  17. Interface Functions:
  18. CreateFilePool
  19. GetFileItemHandle
  20. GetNameFromHandle
  21. GetWriterFromHandle
  22. GetReaderFromHandle
  23. ReleasePoolHandle
  24. DestroyFilePool
  25. --*/
  26. /*********************
  27. * CreateFilePool()
  28. *
  29. * Creates the Filepool.
  30. *
  31. * Arguments:
  32. * OUT FilePool : Pointer to a Filepool handle.
  33. * IN BasePath : String to use as a spool dir.
  34. * IN PreNumStr : String to use as a filename prefix.
  35. * IN SplExt : String to use as a spool extension.
  36. * IN ShdExt : String to use as a shadow file extension.
  37. * IN PoolTimeout : Dword in milliseconds before an idle pool item gets deleted.
  38. * IN MaxFiles : Maximum number of free files in the pool.
  39. *
  40. * The path gets created as <Basepath>\<PreNumStr>XXXXX<SplExt>
  41. *
  42. */
  43. HRESULT CreateFilePool(
  44. HANDLE * FilePoolHandle,
  45. LPCTSTR BasePath,
  46. LPCTSTR PreNumStr,
  47. LPCTSTR SplExt,
  48. LPCTSTR ShdExt,
  49. DWORD PoolTimeout,
  50. DWORD MaxFiles
  51. )
  52. {
  53. HRESULT RetVal = E_FAIL;
  54. class FilePool * FP = NULL;
  55. if (FilePoolHandle && BasePath && PreNumStr && SplExt && ShdExt)
  56. {
  57. MaxFiles = (MaxFiles > 9999) ? 9999 : MaxFiles;
  58. FP = new FilePool(
  59. PoolTimeout,
  60. MaxFiles
  61. );
  62. if ( FP )
  63. {
  64. RetVal = FP->AllocInit(
  65. BasePath,
  66. PreNumStr,
  67. SplExt,
  68. ShdExt
  69. );
  70. if (SUCCEEDED(RetVal))
  71. {
  72. *FilePoolHandle = (HANDLE) FP;
  73. }
  74. else
  75. {
  76. delete FP;
  77. *FilePoolHandle = INVALID_HANDLE_VALUE;
  78. }
  79. }
  80. }
  81. else
  82. {
  83. RetVal = E_INVALIDARG;
  84. }
  85. return RetVal;
  86. }
  87. /*********************
  88. * GetFileItemHandle()
  89. *
  90. * Takes a FilePool Object and An empty Filehandle, and returns
  91. * an open File handle. Use ReleasePoolHandle Once you're finished
  92. * with the file.
  93. *
  94. * Arguments:
  95. * IN FilePool : Handle of a FilePool Object Created with CreateFilePool()
  96. * OUT FileItem : Pointer to a FileItem Handle.
  97. * IN FromFilename : String to use as a filename.
  98. *
  99. * Returns Error if it is passed in an invalid argument, or S_OK if it succeeds.
  100. *
  101. */
  102. HRESULT
  103. GetFileItemHandle(
  104. HANDLE FilePoolHandle,
  105. HANDLE * FileItem,
  106. LPWSTR FromFilename
  107. )
  108. {
  109. class FilePool * FP = NULL;
  110. HRESULT RetVal = E_FAIL;
  111. struct FileListItem * FLItem = NULL;
  112. FP = (class FilePool *)FilePoolHandle;
  113. RetVal = FP->GetWriteFileStruct(&FLItem, FromFilename);
  114. if (SUCCEEDED(RetVal))
  115. {
  116. *FileItem = (HANDLE) FLItem;
  117. }
  118. else
  119. {
  120. *FileItem = INVALID_HANDLE_VALUE;
  121. }
  122. return RetVal;
  123. }
  124. /*********************
  125. * GetNameFromHandle()
  126. *
  127. * Takes a FileItem and a string pointer, and returns
  128. * an allocated string containing the name of the file.
  129. *
  130. * Arguments:
  131. * IN FileItem : Handle of a FileItem, retrieved with GetFileItemHandle()
  132. * OUT FileNameStr : Pointer to a string variable.
  133. * IN IsSpool : BOOL - TRUE - Returns the Spool Filename, FALSE returns the Shadow Filename
  134. *
  135. * Returns Error if it is passed in an invalid argument or if it cannot allocate the string,
  136. * or S_OK if it succeeds.
  137. *
  138. */
  139. HRESULT
  140. GetNameFromHandle(
  141. HANDLE FileItem,
  142. PWSTR * FileNameStr,
  143. BOOL IsSpool
  144. )
  145. {
  146. HRESULT RetVal = S_OK;
  147. struct FileListItem * FPI;
  148. if (FileItem && (FileItem != INVALID_HANDLE_VALUE))
  149. {
  150. FPI = (struct FileListItem *)FileItem;
  151. if (FileNameStr && !*FileNameStr)
  152. {
  153. if (IsSpool)
  154. {
  155. *FileNameStr = AllocSplStr(FPI->SplFilename);
  156. }
  157. else
  158. {
  159. *FileNameStr = AllocSplStr(FPI->ShdFilename);
  160. }
  161. if (!*FileNameStr)
  162. {
  163. RetVal = E_OUTOFMEMORY;
  164. }
  165. }
  166. else
  167. {
  168. RetVal = E_INVALIDARG;
  169. }
  170. }
  171. else
  172. {
  173. RetVal = E_INVALIDARG;
  174. }
  175. return RetVal;
  176. }
  177. /*********************
  178. * GetCurrentWriter()
  179. *
  180. * Takes a FileItem and returns a FileHandle of the current WriteHandle if it exists.
  181. *
  182. * Arguments:
  183. * IN FileItem : FileItem Handle.
  184. * IN IsSpool : BOOL - TRUE: Returns the Spool file handle, FALSE returns the Shadow file handle.
  185. *
  186. * This will not create a writer if it is not yet created, and will also not update the object's flags.
  187. *
  188. * Return: Valid Handle if success or INVALID_HANDLE_VALUE.
  189. */
  190. HANDLE GetCurrentWriter(
  191. HANDLE FileItem,
  192. BOOL IsSpool)
  193. {
  194. struct FileListItem * FPI;
  195. HANDLE RetVal = INVALID_HANDLE_VALUE;
  196. HANDLE Temp = INVALID_HANDLE_VALUE;
  197. if (FileItem)
  198. {
  199. FPI = (struct FileListItem *) FileItem;
  200. FPI->EnterCritSec();
  201. if (IsSpool)
  202. {
  203. Temp = FPI->SplWriteHandle;
  204. }
  205. else
  206. {
  207. Temp = FPI->ShdWriteHandle;
  208. }
  209. FPI->LeaveCritSec();
  210. if (Temp != INVALID_HANDLE_VALUE)
  211. {
  212. RetVal = Temp;
  213. }
  214. }
  215. return RetVal;
  216. }
  217. /*********************
  218. * GetFileCreationInfo
  219. *
  220. * Takes a FileItem and returns a bitmap.
  221. *
  222. * Arguments:
  223. * IN FileItem : FileItem Handle.
  224. * OUT BitMap
  225. *
  226. * Returns bitmap indicating which files needed to be opened. Bitmap reset when
  227. * the pool handle is released.
  228. *
  229. * Return: S_OK if success, otherwise an error value.
  230. */
  231. HRESULT
  232. GetFileCreationInfo(
  233. HANDLE FileItem,
  234. PDWORD BitMap
  235. )
  236. {
  237. struct FileListItem * FPI;
  238. *BitMap = 0;
  239. if (FileItem && (FileItem != INVALID_HANDLE_VALUE))
  240. {
  241. FPI = (struct FileListItem *) FileItem;
  242. *BitMap = FPI->CreateInfo;
  243. return S_OK;
  244. }
  245. return E_FAIL;
  246. }
  247. /*********************
  248. * GetWriterFromHandle()
  249. *
  250. * Takes a FileItem and returns a FileHandle with an open Writer.
  251. *
  252. * Arguments:
  253. * IN FileItem : FileItem Handle.
  254. * OUT File : Pointer to a filehandle.
  255. * IN IsSpool : BOOL - TRUE: Returns the Spool file handle, FALSE returns the Shadow file handle.
  256. *
  257. * This will create a writer if it is not yet created, and will also update the object's flags. It will
  258. * return the current handle if there is one.
  259. *
  260. * Return: S_OK if success, otherwise an error value.
  261. */
  262. HRESULT
  263. GetWriterFromHandle(
  264. HANDLE FileItem,
  265. HANDLE * File,
  266. BOOL IsSpool
  267. )
  268. {
  269. HRESULT RetVal = S_OK;
  270. class FilePool * FP = NULL;
  271. struct FileListItem * FPI;
  272. if (FileItem && File)
  273. {
  274. FPI = (struct FileListItem *) FileItem;
  275. FP = FPI->FP;
  276. *File = INVALID_HANDLE_VALUE;
  277. FPI->EnterCritSec();
  278. if (IsSpool)
  279. {
  280. if (FPI->SplWriteHandle == INVALID_HANDLE_VALUE)
  281. {
  282. RetVal = FP->CreateSplWriter(FPI);
  283. }
  284. }
  285. else
  286. {
  287. if (FPI->ShdWriteHandle == INVALID_HANDLE_VALUE)
  288. {
  289. RetVal = FP->CreateShdWriter(FPI);
  290. }
  291. }
  292. if (SUCCEEDED(RetVal))
  293. {
  294. if (IsSpool)
  295. {
  296. *File = FPI->SplWriteHandle;
  297. FPI->Status |= FP_STATUS_SPL_WRITING;
  298. }
  299. else
  300. {
  301. *File = FPI->ShdWriteHandle;
  302. FPI->Status |= FP_STATUS_SHD_WRITING;
  303. }
  304. }
  305. else
  306. {
  307. RetVal = E_FAIL;
  308. }
  309. FPI->LeaveCritSec();
  310. }
  311. else
  312. {
  313. RetVal = E_INVALIDARG;
  314. }
  315. return RetVal;
  316. }
  317. /*********************
  318. * GetReaderFromHandle()
  319. *
  320. * Takes a FileItem and returns a FileHandle with an open Reader.
  321. *
  322. * Arguments:
  323. * IN FileItem : FileItem Handle.
  324. * OUT File : Pointer to a filehandle.
  325. *
  326. * This will create a Reader if it is not yet created, and will also update the object's flags. It will
  327. * return the current handle if there is one. It will also return the writer if the system is finished with it.
  328. *
  329. * Return: S_OK if success, otherwise an error value.
  330. */
  331. HRESULT
  332. GetReaderFromHandle(
  333. HANDLE FileItem,
  334. HANDLE * File
  335. )
  336. {
  337. HRESULT RetVal = S_OK;
  338. class FilePool * FP = NULL;
  339. struct FileListItem * FPI;
  340. if (FileItem)
  341. {
  342. FPI = (struct FileListItem *) FileItem;
  343. FP = FPI->FP;
  344. // CriticalSection
  345. FPI->EnterCritSec();
  346. if (!(FPI->Status & FP_STATUS_SPL_WRITING) &&
  347. (FPI->SplWriteHandle != INVALID_HANDLE_VALUE) &&
  348. (FPI->SplReadHandle == INVALID_HANDLE_VALUE) )
  349. {
  350. //
  351. // We aren't writing this job anymore, we can reuse the
  352. // write handle for reading.
  353. //
  354. if (!(FPI->Status & FP_STATUS_SPL_READING))
  355. {
  356. if (SetFilePointer(FPI->SplWriteHandle, 0, NULL, FILE_BEGIN) !=
  357. INVALID_SET_FILE_POINTER)
  358. {
  359. *File = FPI->SplWriteHandle;
  360. FPI->Status |= FP_STATUS_SPL_READING;
  361. }
  362. else
  363. {
  364. RetVal = E_FAIL;
  365. }
  366. }
  367. else
  368. {
  369. *File = FPI->SplWriteHandle;
  370. }
  371. }
  372. else
  373. {
  374. //
  375. // We are still writing this job, so we need to use the readhandle.
  376. //
  377. if (FPI->SplReadHandle == INVALID_HANDLE_VALUE)
  378. {
  379. //
  380. // The Reader doesn't already exist, We need to create it.
  381. //
  382. RetVal = FP->CreateSplReader(FPI);
  383. }
  384. if (SUCCEEDED(RetVal))
  385. {
  386. //
  387. // We now have a valid handle
  388. //
  389. *File = FPI->SplReadHandle;
  390. FPI->Status |= FP_STATUS_SPL_READING;
  391. }
  392. else
  393. {
  394. RetVal = E_FAIL;
  395. }
  396. }
  397. FPI->LeaveCritSec();
  398. }
  399. else
  400. {
  401. RetVal = E_INVALIDARG;
  402. }
  403. return RetVal;
  404. }
  405. /*********************
  406. * FishedReading()
  407. *
  408. * Indicates to the object that we are finished with it for reading purposes.
  409. *
  410. * Arguments:
  411. * IN FileItem : Handle of a FileItem.
  412. *
  413. * Returns Error if it is passed in an invalid argument, or S_OK if it succeeds.
  414. *
  415. */
  416. HRESULT
  417. FinishedReading(
  418. HANDLE FileItem
  419. )
  420. {
  421. HRESULT RetVal = S_OK;
  422. struct FileListItem * FPI;
  423. if (FileItem)
  424. {
  425. FPI = (struct FileListItem *) FileItem;
  426. FPI->EnterCritSec();
  427. FPI->Status &= ~FP_STATUS_SPL_READING;
  428. FPI->LeaveCritSec();
  429. }
  430. else
  431. {
  432. RetVal = E_INVALIDARG;
  433. }
  434. return RetVal;
  435. }
  436. /*********************
  437. * FishedWriting()
  438. *
  439. * Indicates to the object that we are finished with it for writing purposes.
  440. *
  441. * Arguments:
  442. * IN FileItem : Handle of a FileItem.
  443. * IN IsSpool : BOOL - TRUE: Affects the Spl file, FALSE: Affects the Shd file.
  444. *
  445. * Returns Error if it is passed in an invalid argument, or S_OK if it succeeds.
  446. *
  447. */
  448. HRESULT
  449. FinishedWriting(
  450. HANDLE FileItem,
  451. BOOL IsSpool
  452. )
  453. {
  454. HRESULT RetVal = S_OK;
  455. struct FileListItem * FPI;
  456. if (FileItem)
  457. {
  458. FPI = (struct FileListItem *) FileItem;
  459. FPI->EnterCritSec();
  460. if (IsSpool)
  461. {
  462. FPI->Status &= ~FP_STATUS_SPL_WRITING;
  463. }
  464. else
  465. {
  466. FPI->Status &= ~FP_STATUS_SHD_WRITING;
  467. }
  468. FPI->LeaveCritSec();
  469. }
  470. else
  471. {
  472. RetVal = E_INVALIDARG;
  473. }
  474. return RetVal;
  475. }
  476. /*********************
  477. * ReleasePoolHandle()
  478. *
  479. * Releases the pool item back to the pool to reuse. The pool will not reuse the item if all the
  480. * filehandles are closed, and also if we have reached our free files limit.
  481. *
  482. * Arguments:
  483. * IN OUT FileItem : Pointer to a FileItem Handle.
  484. *
  485. * Returns Error if it fails, or S_OK if it succeeds. FileItem gets set to INVALID_HANDLE_VALUE if it succeeds.
  486. *
  487. */
  488. HRESULT
  489. ReleasePoolHandle(
  490. HANDLE * FileItem
  491. )
  492. {
  493. HRESULT RetVal = S_OK;
  494. class FilePool * FP = NULL;
  495. struct FileListItem * FPI;
  496. if (FileItem && *FileItem )
  497. {
  498. FPI = (struct FileListItem *) *FileItem;
  499. FP = FPI->FP;
  500. //
  501. // This should not be in the critsec, since we might delete
  502. // the critical section.
  503. //
  504. RetVal = FP->ReleasePoolHandle(FPI);
  505. if (SUCCEEDED(RetVal))
  506. {
  507. *FileItem = INVALID_HANDLE_VALUE;
  508. }
  509. }
  510. else
  511. {
  512. RetVal = E_INVALIDARG;
  513. }
  514. return RetVal;
  515. }
  516. /*********************
  517. * RemoveFromFilePool()
  518. *
  519. * Removes the pool item from the pool completely and frees the associated memory.
  520. *
  521. * Arguments:
  522. * IN OUT FileItem : Pointer to a FileItem Handle.
  523. * IN Delete : BOOL, Tells us whether to delete the files or not.
  524. *
  525. * Returns Error if it fails, or S_OK if it succeeds. FileItem gets set to INVALID_HANDLE_VALUE if it succeeds.
  526. *
  527. */
  528. HRESULT
  529. RemoveFromFilePool(
  530. HANDLE* FileItem,
  531. BOOL Delete
  532. )
  533. {
  534. HRESULT RetVal = S_OK;
  535. class FilePool * FP = NULL;
  536. struct FileListItem * FPI;
  537. if (FileItem && *FileItem )
  538. {
  539. FPI = (struct FileListItem *) *FileItem;
  540. FP = FPI->FP;
  541. RetVal = FP->RemoveFromPool(FPI, Delete);
  542. if (SUCCEEDED(RetVal))
  543. {
  544. *FileItem = INVALID_HANDLE_VALUE;
  545. }
  546. }
  547. else
  548. {
  549. RetVal = E_INVALIDARG;
  550. }
  551. return RetVal;
  552. }
  553. /*********************
  554. * CloseFiles()
  555. *
  556. * Closes the filehandles in the Pool Item (To save memory).
  557. *
  558. * Arguments:
  559. * IN FileItem : FileItem Handle.
  560. * IN CloseShad : Close the shadow file handle too.
  561. *
  562. *
  563. */
  564. VOID
  565. CloseFiles(
  566. HANDLE FileItem,
  567. BOOL CloseShad
  568. )
  569. {
  570. struct FileListItem * FPI;
  571. if (FileItem )
  572. {
  573. FPI = (struct FileListItem *) FileItem;
  574. FPCloseFiles(FPI, CloseShad);
  575. }
  576. }
  577. /*********************
  578. * DestroyFilePool()
  579. *
  580. * Takes a FilePool Object and frees it, optionally deleting the files associated with it.
  581. *
  582. * Arguments:
  583. * IN OUT FilePoolHandle : Pointer to existing Filepool.
  584. * IN DeleteFiles : BOOL - TRUE: Delete the Pool files.
  585. *
  586. * Returns Error if it is passed in an invalid argument, or S_OK if it succeeds.
  587. *
  588. */
  589. HRESULT
  590. DestroyFilePool(
  591. HANDLE* FilePoolHandle,
  592. BOOL DeleteFiles
  593. )
  594. {
  595. HRESULT RetVal = S_OK;
  596. class FilePool * FP = NULL;
  597. if (FilePoolHandle && *FilePoolHandle)
  598. {
  599. FP = (class FilePool *)FilePoolHandle;
  600. FP->DeleteEmptyFilesOnClose = DeleteFiles;
  601. delete FP;
  602. }
  603. else
  604. {
  605. RetVal = E_INVALIDARG;
  606. }
  607. return RetVal;
  608. }
  609. /*********************
  610. * TrimPool()
  611. *
  612. * Takes a FilePool Object and trim the free list, deleting old files.
  613. *
  614. * Arguments:
  615. * IN FilePool : Handle of a FilePool Object Created with CreateFilePool()
  616. *
  617. * Returns TRUE if there are files still in the free list, or FALSE if no files left.
  618. */
  619. BOOL
  620. TrimPool(
  621. HANDLE FilePoolHandle
  622. )
  623. {
  624. class FilePool * FP = NULL;
  625. BOOL Retval = FALSE;
  626. if (FilePoolHandle)
  627. {
  628. FP = (class FilePool *)FilePoolHandle;
  629. Retval = FP->TrimPool();
  630. }
  631. return Retval;
  632. }
  633. /*********************
  634. * ChangeFilePoolBasePath()
  635. *
  636. * Takes a FilePool Object and changes the base path in it. This will be called
  637. * when the spool directory is changed.
  638. *
  639. * Arguments:
  640. * IN FilePool : Handle of a FilePool Object Created with CreateFilePool
  641. * IN BasePath : New base path to use
  642. *
  643. * Returns an HRESULT
  644. */
  645. HRESULT
  646. ChangeFilePoolBasePath(
  647. IN HANDLE *FilePoolHandle,
  648. IN LPCTSTR BasePath
  649. )
  650. {
  651. FilePool *FP = (FilePool *)FilePoolHandle;
  652. HRESULT RetVal = E_INVALIDARG;
  653. LPTSTR FileBase = NULL;
  654. if (FP)
  655. {
  656. if (FileBase = AllocSplStr(BasePath))
  657. {
  658. FP->EnterCritSec();
  659. FreeSplStr(FP->FileBase);
  660. FP->FileBase = FileBase;
  661. FP->LeaveCritSec();
  662. RetVal = S_OK;
  663. }
  664. else
  665. {
  666. RetVal = E_OUTOFMEMORY;
  667. }
  668. }
  669. return RetVal;
  670. }
  671. /*--
  672. Generic Utility Functions
  673. ConvertFileExt
  674. --*/
  675. /*********************
  676. * ConvertFileExt()
  677. *
  678. * Utility function to change one extension to another.
  679. * Requires the extension to only be in the filename once.
  680. *
  681. * Arguments:
  682. * IN OUT FileName : String of Filename to be changed.
  683. * IN ExtFrom : Extension to change.
  684. * IN ExtTo : Extension to change it to.
  685. *
  686. */
  687. HRESULT
  688. ConvertFileExt(
  689. PWSTR Filename,
  690. PCWSTR ExtFrom,
  691. PCWSTR ExtTo
  692. )
  693. {
  694. HRESULT RetVal = E_FAIL;
  695. PWSTR Temp = NULL;
  696. if (Filename && ExtFrom && ExtTo && (wcslen(ExtFrom) == wcslen(ExtTo)) && ExtFrom[0])
  697. {
  698. Temp = wcsstr(Filename, ExtFrom);
  699. if (Temp)
  700. {
  701. //
  702. // This should work in all our cases.
  703. //
  704. wcscpy(Temp, ExtTo);
  705. RetVal = S_OK;
  706. }
  707. }
  708. else
  709. {
  710. RetVal = E_INVALIDARG;
  711. }
  712. return RetVal;
  713. }
  714. /*--
  715. FileItem Management Functions
  716. TruncateFiles
  717. --*/
  718. /*********************
  719. * TruncateFiles()
  720. *
  721. * Takes a File Item and truncates any open files to 0 length.
  722. *
  723. * Arguments:
  724. * IN FileListItem : Item containing the files to truncate.
  725. *
  726. *
  727. */
  728. VOID
  729. TruncateFiles(
  730. struct FileListItem * Item
  731. )
  732. {
  733. BOOL Trunced = FALSE;
  734. if (Item)
  735. {
  736. Item->EnterCritSec();
  737. //
  738. // Reinitialize cache data.
  739. //
  740. Item->CreateInfo = 0;
  741. //
  742. // Truncate the Shadow File
  743. //
  744. if (Item->ShdWriteHandle != INVALID_HANDLE_VALUE)
  745. {
  746. if (SetFilePointer(Item->ShdWriteHandle, 0, NULL, FILE_BEGIN) !=
  747. INVALID_SET_FILE_POINTER)
  748. {
  749. if (!SetEndOfFile(Item->ShdWriteHandle))
  750. {
  751. DBGMSG(DBG_WARN, ("FAILED to set SPL end of file to 0 %d.\n", GetLastError()));
  752. }
  753. }
  754. }
  755. //
  756. // Truncate the Spool File. If the writehandle is closed, use the readhandle.
  757. //
  758. if (Item->SplWriteHandle != INVALID_HANDLE_VALUE)
  759. {
  760. if (SetFilePointer(Item->SplWriteHandle, 0, NULL, FILE_BEGIN) !=
  761. INVALID_SET_FILE_POINTER)
  762. {
  763. if (!SetEndOfFile(Item->SplWriteHandle))
  764. {
  765. DBGMSG(DBG_WARN, ("FAILED to set SPL end of file to 0 %d.\n", GetLastError()));
  766. }
  767. }
  768. }
  769. else if (Item->SplReadHandle != INVALID_HANDLE_VALUE)
  770. {
  771. if (SetFilePointer(Item->SplReadHandle, 0, NULL, FILE_BEGIN) !=
  772. INVALID_SET_FILE_POINTER)
  773. {
  774. if (!SetEndOfFile(Item->SplReadHandle))
  775. {
  776. DBGMSG(DBG_WARN, ("FAILED to set SPL end of file to 0 %d.\n", GetLastError()));
  777. }
  778. }
  779. // There is only one open spool handle at this point so make that
  780. // open handle the writer. This is what the spooler needs when it
  781. // first requests a new pool item. This also saves file I/O if the
  782. // next use of this item doesn't need both writer and reader at the
  783. // same time.
  784. Item->SplWriteHandle = Item->SplReadHandle;
  785. Item->SplReadHandle = INVALID_HANDLE_VALUE;
  786. Trunced = TRUE;
  787. }
  788. if ((Item->SplReadHandle != INVALID_HANDLE_VALUE) && !Trunced)
  789. {
  790. //CloseHandle(Item->SplReadHandle);
  791. SetFilePointer(Item->SplReadHandle, 0, NULL, FILE_BEGIN);
  792. }
  793. Item->LeaveCritSec();
  794. }
  795. }
  796. /*********************
  797. * FPCloseFiles()
  798. *
  799. * Takes a FileList item and closes the files associated with it.
  800. *
  801. * Arguments:
  802. * IN FileListItem : FileItem with files to close.
  803. * IN CloseShad : BOOL - TRUE: Close the Shadow File too.
  804. *
  805. *
  806. */
  807. VOID
  808. FPCloseFiles(
  809. struct FileListItem * pItem,
  810. BOOL CloseShad)
  811. {
  812. if (pItem)
  813. {
  814. pItem->EnterCritSec();
  815. __try
  816. {
  817. if (pItem->SplWriteHandle != INVALID_HANDLE_VALUE)
  818. {
  819. CloseHandle(pItem->SplWriteHandle);
  820. pItem->SplWriteHandle = INVALID_HANDLE_VALUE;
  821. }
  822. }
  823. __except ( EXCEPTION_EXECUTE_HANDLER )
  824. {
  825. DBGMSG(DBG_WARN, ("Hit an Exception Closing SplWriteHandle in FPCloseFiles\n"));
  826. pItem->SplWriteHandle = INVALID_HANDLE_VALUE;
  827. }
  828. __try
  829. {
  830. if (pItem->SplReadHandle != INVALID_HANDLE_VALUE)
  831. {
  832. CloseHandle(pItem->SplReadHandle);
  833. pItem->SplReadHandle = INVALID_HANDLE_VALUE;
  834. }
  835. }
  836. __except ( EXCEPTION_EXECUTE_HANDLER )
  837. {
  838. DBGMSG(DBG_WARN, ("Hit an Exception Closing SplReadHandle in FPCloseFiles\n"));
  839. pItem->SplReadHandle = INVALID_HANDLE_VALUE;
  840. }
  841. if ( CloseShad )
  842. {
  843. __try
  844. {
  845. if (pItem->ShdWriteHandle != INVALID_HANDLE_VALUE)
  846. {
  847. CloseHandle(pItem->ShdWriteHandle);
  848. pItem->ShdWriteHandle = INVALID_HANDLE_VALUE;
  849. }
  850. }
  851. __except ( EXCEPTION_EXECUTE_HANDLER )
  852. {
  853. DBGMSG(DBG_WARN, ("Hit an Exception Closing ShdWriteHandle in FPCloseFiles\n"));
  854. pItem->ShdWriteHandle = INVALID_HANDLE_VALUE;
  855. }
  856. }
  857. pItem->LeaveCritSec();
  858. }
  859. }
  860. /*********************
  861. * DeletePoolFile()
  862. *
  863. * Takes a FilePool Object and trim the free list, deleting old files and freeing memory.
  864. *
  865. * Arguments:
  866. * IN OUT FileListItem : FileItem to delete the files from and free up.
  867. *
  868. * Closes the files, deletes them, frees the memory, and sets the pItem to NULL
  869. *
  870. */
  871. VOID
  872. DeletePoolFile(struct FileListItem ** ppItem)
  873. {
  874. struct FileListItem * pItem;
  875. if (ppItem && *ppItem)
  876. {
  877. pItem = *ppItem;
  878. FPCloseFiles(pItem, TRUE);
  879. DeleteCriticalSection(&pItem->CritSec);
  880. if (pItem->SplFilename)
  881. {
  882. DeleteFile(pItem->SplFilename);
  883. FreeSplMem(pItem->SplFilename);
  884. }
  885. if (pItem->ShdFilename)
  886. {
  887. DeleteFile(pItem->ShdFilename);
  888. FreeSplMem(pItem->ShdFilename);
  889. }
  890. FreeSplMem(pItem);
  891. }
  892. *ppItem = NULL;
  893. }
  894. /*--
  895. List Management Functions
  896. RemoveFromFPList
  897. AddToFPListEnd
  898. AddToFPListHead
  899. --*/
  900. HRESULT
  901. RemoveFromFPList(
  902. struct FileListItem * Item,
  903. struct FileListItem ** Head,
  904. struct FileListItem ** Tail
  905. )
  906. {
  907. struct FileListItem * Check = NULL;
  908. HRESULT RetVal = E_FAIL;
  909. //
  910. // Validate we have valid args.
  911. //
  912. if ( Item && Head && *Head && Tail && *Tail )
  913. {
  914. for ( Check = *Head; Check && (Item != Check); Check = Check->FLNext );
  915. if ( Check )
  916. {
  917. if ( *Head == Check )
  918. {
  919. *Head = Check->FLNext;
  920. }
  921. else
  922. {
  923. Check->FLPrev->FLNext = Check->FLNext;
  924. }
  925. if ( *Tail == Check )
  926. {
  927. *Tail = Check->FLPrev;
  928. }
  929. else
  930. {
  931. Check->FLNext->FLPrev = Check->FLPrev;
  932. }
  933. Check->FLNext = NULL;
  934. Check->FLPrev = NULL;
  935. RetVal = S_OK;
  936. }
  937. else
  938. {
  939. //
  940. // you gave me a pointer to an item not in the list.
  941. //
  942. RetVal = E_POINTER;
  943. }
  944. }
  945. else
  946. {
  947. RetVal = E_INVALIDARG;
  948. }
  949. return RetVal;
  950. }
  951. HRESULT
  952. AddToFPListEnd(
  953. struct FileListItem * Item,
  954. struct FileListItem ** Head,
  955. struct FileListItem ** Tail
  956. )
  957. {
  958. struct FileListItem * Check = NULL;
  959. HRESULT RetVal = E_FAIL;
  960. //
  961. // Validate we have valid args.
  962. //
  963. if ( Item && Head && Tail )
  964. {
  965. if ( *Tail )
  966. {
  967. //
  968. // There are items in the list, add something
  969. // onto the end.
  970. //
  971. Check = *Tail;
  972. Check->FLNext = Item;
  973. Item->FLPrev = Check;
  974. Item->FLNext = NULL;
  975. *Tail = Item;
  976. RetVal = S_OK;
  977. }
  978. else
  979. {
  980. if ( *Head )
  981. {
  982. //
  983. // If we have a head and no tail, something
  984. // is seriously wrong.
  985. //
  986. RetVal = E_FAIL;
  987. }
  988. else
  989. {
  990. //
  991. // Adding the first item into a list.
  992. //
  993. Item->FLNext = NULL;
  994. Item->FLPrev = NULL;
  995. *Head = Item;
  996. *Tail = Item;
  997. RetVal = S_OK;
  998. }
  999. }
  1000. }
  1001. else
  1002. {
  1003. RetVal = E_INVALIDARG;
  1004. }
  1005. return RetVal;
  1006. }
  1007. HRESULT
  1008. AddToFPListHead(
  1009. struct FileListItem * Item,
  1010. struct FileListItem ** Head,
  1011. struct FileListItem ** Tail
  1012. )
  1013. {
  1014. HRESULT RetVal = S_OK;
  1015. if ( Item && Head && Tail )
  1016. {
  1017. if ( *Head )
  1018. {
  1019. Item->FLNext = *Head;
  1020. (*Head)->FLPrev = Item;
  1021. }
  1022. else
  1023. {
  1024. *Tail = Item;
  1025. }
  1026. *Head = Item;
  1027. Item->FLPrev = NULL;
  1028. }
  1029. else
  1030. {
  1031. RetVal = E_INVALIDARG;
  1032. }
  1033. return RetVal;
  1034. }
  1035. VOID
  1036. FreeFPList(
  1037. struct FileListItem ** Head,
  1038. BOOL DeleteFiles
  1039. )
  1040. {
  1041. struct FileListItem * Item = NULL;
  1042. struct FileListItem * Next = NULL;
  1043. if (Head && *Head)
  1044. {
  1045. Item = *Head;
  1046. while (Item)
  1047. {
  1048. Next = Item->FLNext;
  1049. Item->FLNext = NULL;
  1050. Item->FLPrev = NULL;
  1051. if (Item->SplFilename && DeleteFiles)
  1052. {
  1053. DeletePoolFile(&Item);
  1054. Item = Next;
  1055. }
  1056. else
  1057. {
  1058. FPCloseFiles(Item, TRUE);
  1059. DeleteCriticalSection(&Item->CritSec);
  1060. if (Item->SplFilename)
  1061. {
  1062. FreeSplMem(Item->SplFilename);
  1063. }
  1064. if (Item->ShdFilename)
  1065. {
  1066. FreeSplMem(Item->ShdFilename);
  1067. }
  1068. FreeSplMem(Item);
  1069. Item = Next;
  1070. }
  1071. }
  1072. *Head = NULL;
  1073. }
  1074. }
  1075. /*--
  1076. FilePool Class Functions:
  1077. InitFilePoolVars
  1078. FilePool
  1079. ~FilePool
  1080. EnterCritSec
  1081. LeaveCritSec
  1082. GetNextFileName
  1083. CreatePoolFile
  1084. GetWriteFileStruct
  1085. ReleasePoolHandle
  1086. DeletePoolFile
  1087. operator delete
  1088. --*/
  1089. /*********************
  1090. * Filepool::FilePool()
  1091. *
  1092. * See CreateFilePool() Above.
  1093. */
  1094. FilePool::FilePool(
  1095. DWORD PTimeout,
  1096. DWORD MaxFreeFiles
  1097. ) : FreeFiles(NULL), EndFreeFiles(NULL), FileInUse(NULL), EndUsedFiles(NULL),
  1098. CurrentNum(0), PoolTimeout(PTimeout), MaxFiles(MaxFreeFiles), FreeSize(0), UsedSize(0),
  1099. DeleteEmptyFilesOnClose(FALSE)
  1100. {
  1101. SplModes.Mode = GENERIC_READ | GENERIC_WRITE;
  1102. SplModes.Flags = FILE_ATTRIBUTE_NORMAL;
  1103. SplModes.ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
  1104. SplModes.Disp = 0;
  1105. ShdModes.Mode = GENERIC_WRITE;
  1106. ShdModes.Flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN;
  1107. ShdModes.ShareMode = 0;
  1108. ShdModes.Disp = 0;
  1109. }
  1110. /*********************
  1111. * Filepool::AllocInit()
  1112. *
  1113. * See CreateFilePool() Above.
  1114. */
  1115. HRESULT
  1116. FilePool::AllocInit(
  1117. LPCTSTR BasePath,
  1118. LPCTSTR PreNumStr,
  1119. LPCTSTR SplExt,
  1120. LPCTSTR ShdExt
  1121. )
  1122. {
  1123. HRESULT RetVal = S_OK;
  1124. __try
  1125. {
  1126. InitializeCriticalSection(&FilePoolCritSec);
  1127. }
  1128. __except( EXCEPTION_EXECUTE_HANDLER )
  1129. {
  1130. DBGMSG(DBG_WARN, ("FilePool: Failed to Initialise Critical Section.\n"));
  1131. RetVal = E_FAIL;
  1132. }
  1133. if ((RetVal == S_OK) &&
  1134. (FileBase = AllocSplStr(BasePath)) &&
  1135. (FilePreNumStr = AllocSplStr(PreNumStr)) &&
  1136. (SplFileExt = AllocSplStr(SplExt)) &&
  1137. (ShdFileExt = AllocSplStr(ShdExt))
  1138. )
  1139. {
  1140. //
  1141. // We have all of our strings allocated.
  1142. //
  1143. }
  1144. else
  1145. {
  1146. FreeSplStr(FileBase);
  1147. FreeSplStr(FilePreNumStr);
  1148. FreeSplStr(SplFileExt);
  1149. FreeSplStr(ShdFileExt);
  1150. RetVal = E_FAIL;
  1151. }
  1152. return RetVal;
  1153. }
  1154. /*********************
  1155. * Filepool::FilePool()
  1156. *
  1157. * See CreateFilePool() Above.
  1158. */
  1159. FilePool::~FilePool(
  1160. )
  1161. {
  1162. if (FileBase)
  1163. {
  1164. FreeSplMem(FileBase);
  1165. }
  1166. if (FilePreNumStr)
  1167. {
  1168. FreeSplMem(FilePreNumStr);
  1169. }
  1170. if (SplFileExt)
  1171. {
  1172. FreeSplMem(SplFileExt);
  1173. }
  1174. if (ShdFileExt)
  1175. {
  1176. FreeSplMem(ShdFileExt);
  1177. }
  1178. //
  1179. // Free The lists here.
  1180. //
  1181. FreeFPList(&FileInUse, FALSE);
  1182. FreeFPList(&FreeFiles, DeleteEmptyFilesOnClose);
  1183. EndUsedFiles = NULL;
  1184. EndFreeFiles = NULL;
  1185. DeleteCriticalSection(&FilePoolCritSec);
  1186. }
  1187. VOID
  1188. FilePool::EnterCritSec()
  1189. {
  1190. EnterCriticalSection(&FilePoolCritSec);
  1191. }
  1192. VOID
  1193. FilePool::LeaveCritSec()
  1194. {
  1195. LeaveCriticalSection(&FilePoolCritSec);
  1196. }
  1197. VOID
  1198. FileListItem::EnterCritSec()
  1199. {
  1200. EnterCriticalSection(&CritSec);
  1201. }
  1202. VOID
  1203. FileListItem::LeaveCritSec()
  1204. {
  1205. LeaveCriticalSection(&CritSec);
  1206. }
  1207. /*********************
  1208. * FilePool::GetNextFileName()
  1209. *
  1210. * Returns the next open Spool file name. Allocates memory.
  1211. *
  1212. * Arguments:
  1213. *
  1214. * Return:
  1215. * A valid spool file name, or NULL.
  1216. *
  1217. */
  1218. LPWSTR
  1219. FilePool::GetNextFileName(VOID)
  1220. {
  1221. DWORD SizeToAlloc = 0;
  1222. PWSTR FName = NULL;
  1223. SizeToAlloc =
  1224. wcslen(FileBase) + 1 +
  1225. wcslen(FilePreNumStr) + 5 +
  1226. wcslen(SplFileExt) + 1;
  1227. FName = (PWSTR)AllocSplMem(SizeToAlloc * sizeof(WCHAR));
  1228. if (FName)
  1229. {
  1230. DWORD NextNum;
  1231. EnterCritSec();
  1232. NextNum = CurrentNum;
  1233. CurrentNum++;
  1234. if (CurrentNum > 99999)
  1235. {
  1236. CurrentNum = 0;
  1237. }
  1238. LeaveCritSec();
  1239. wsprintf(
  1240. FName,
  1241. L"%ws\\%ws%05d%ws",
  1242. FileBase,
  1243. FilePreNumStr,
  1244. NextNum,
  1245. SplFileExt);
  1246. }
  1247. return FName;
  1248. }
  1249. /*********************
  1250. * FilePool::GetNextFileNameNoAlloc()
  1251. *
  1252. * Returns the next open Spool file name. Uses a buffer.
  1253. * It is only used after a call to GetNextFileName.
  1254. *
  1255. * Arguments:
  1256. * IN OUT Filename : Buffer to copy the name into.
  1257. *
  1258. * Return:
  1259. * None.
  1260. *
  1261. */
  1262. VOID
  1263. FilePool::GetNextFileNameNoAlloc(
  1264. PWSTR Filename
  1265. )
  1266. {
  1267. DWORD NextNum;
  1268. EnterCritSec();
  1269. NextNum = CurrentNum;
  1270. CurrentNum++;
  1271. if (CurrentNum > 99999)
  1272. {
  1273. CurrentNum = 0;
  1274. }
  1275. LeaveCritSec();
  1276. wsprintf(
  1277. Filename,
  1278. L"%ws\\%ws%05d%ws",
  1279. FileBase,
  1280. FilePreNumStr,
  1281. NextNum,
  1282. SplFileExt);
  1283. }
  1284. /*********************
  1285. * Filepool::CreatePoolFile()
  1286. *
  1287. * Takes a pointer to a Filepool item and returns a new one. Can use a filename
  1288. * passed in.
  1289. *
  1290. * Parameters:
  1291. * OUT Item : Pointer to a File Item.
  1292. * IN Filename : Optional Filename. Can be NULL.
  1293. *
  1294. * Returns S_OK if successful.
  1295. */
  1296. HRESULT
  1297. FilePool::CreatePoolFile(
  1298. struct FileListItem ** Item,
  1299. PWSTR Filename
  1300. )
  1301. {
  1302. HRESULT RetVal = E_FAIL;
  1303. struct FileListItem * Temp = NULL;
  1304. DWORD OldNum = 0;
  1305. BOOL CritInitialized = FALSE;
  1306. if ( Item )
  1307. {
  1308. Temp = (struct FileListItem *)AllocSplMem(sizeof(struct FileListItem));
  1309. if ( Temp )
  1310. {
  1311. Temp->FLNext = NULL;
  1312. Temp->FLPrev = NULL;
  1313. OldNum = CurrentNum;
  1314. Temp->TimeStamp = 0;
  1315. Temp->FP = this;
  1316. Temp->CreateInfo = 0;
  1317. __try
  1318. {
  1319. InitializeCriticalSection(&Temp->CritSec);
  1320. CritInitialized = TRUE;
  1321. }
  1322. __except( EXCEPTION_EXECUTE_HANDLER )
  1323. {
  1324. DBGMSG(DBG_WARN, ("FilePool: Failed to Initialise FL Critical Section.\n"));
  1325. RetVal = E_FAIL;
  1326. }
  1327. if (CritInitialized)
  1328. {
  1329. if ( Filename )
  1330. {
  1331. Temp->SplFilename = AllocSplStr(Filename);
  1332. Temp->ShdFilename = AllocSplStr(Filename);
  1333. if (Temp->SplFilename && Temp->ShdFilename)
  1334. {
  1335. *Item = Temp;
  1336. ConvertFileExt(Temp->ShdFilename, SplFileExt, ShdFileExt);
  1337. Temp->SplReadHandle = INVALID_HANDLE_VALUE;
  1338. Temp->SplWriteHandle = INVALID_HANDLE_VALUE;
  1339. Temp->ShdWriteHandle = INVALID_HANDLE_VALUE;
  1340. RetVal = S_OK;
  1341. }
  1342. else
  1343. {
  1344. RetVal = E_OUTOFMEMORY;
  1345. }
  1346. }
  1347. else
  1348. {
  1349. Temp->SplFilename = GetNextFileName();
  1350. if (Temp->SplFilename)
  1351. {
  1352. RetVal = S_OK;
  1353. while (FileExists(Temp->SplFilename))
  1354. {
  1355. GetNextFileNameNoAlloc(Temp->SplFilename);
  1356. if (OldNum == CurrentNum)
  1357. {
  1358. //
  1359. // We went right around.
  1360. //
  1361. RetVal = E_FAIL;
  1362. break;
  1363. }
  1364. }
  1365. if (SUCCEEDED(RetVal))
  1366. {
  1367. Temp->ShdFilename = AllocSplStr(Temp->SplFilename);
  1368. if (Temp->ShdFilename)
  1369. {
  1370. ConvertFileExt(Temp->ShdFilename, SplFileExt, ShdFileExt);
  1371. Temp->SplReadHandle = INVALID_HANDLE_VALUE;
  1372. Temp->SplWriteHandle = INVALID_HANDLE_VALUE;
  1373. Temp->ShdWriteHandle = INVALID_HANDLE_VALUE;
  1374. *Item = Temp;
  1375. RetVal = S_OK;
  1376. }
  1377. }
  1378. }
  1379. }
  1380. }
  1381. }
  1382. }
  1383. else
  1384. {
  1385. RetVal = E_INVALIDARG;
  1386. }
  1387. if (FAILED(RetVal))
  1388. {
  1389. if (Temp)
  1390. {
  1391. DeleteCriticalSection(&Temp->CritSec);
  1392. if (Temp->SplFilename)
  1393. {
  1394. FreeSplMem(Temp->SplFilename);
  1395. }
  1396. if (Temp->ShdFilename)
  1397. {
  1398. FreeSplMem(Temp->ShdFilename);
  1399. }
  1400. FreeSplMem(Temp);
  1401. }
  1402. }
  1403. return RetVal;
  1404. }
  1405. /*********************
  1406. * Filepool::GetWriteFileStruct()
  1407. *
  1408. * See GetFileItemHandle() Above.
  1409. */
  1410. HRESULT
  1411. FilePool::GetWriteFileStruct(
  1412. struct FileListItem ** File,
  1413. PWSTR Filename
  1414. )
  1415. {
  1416. struct FileListItem * Temp = NULL;
  1417. HRESULT RetVal = S_OK;
  1418. HRESULT OurRetVal = S_OK;
  1419. EnterCritSec();
  1420. if ( FreeFiles && !Filename)
  1421. {
  1422. Temp = FreeFiles;
  1423. RetVal = RemoveFromFPList( Temp, &FreeFiles, &EndFreeFiles );
  1424. if (SUCCEEDED(RetVal))
  1425. {
  1426. FreeSize--;
  1427. RetVal = AddToFPListEnd( Temp, &FileInUse, &EndUsedFiles);
  1428. if (FAILED(RetVal))
  1429. {
  1430. //
  1431. // Bad things
  1432. //
  1433. DBGMSG(DBG_WARN, ("Could not add to List End %x\n", RetVal));
  1434. OurRetVal = E_FAIL;
  1435. }
  1436. else
  1437. {
  1438. UsedSize++;
  1439. }
  1440. }
  1441. else
  1442. {
  1443. //
  1444. // Find out what went wrong.
  1445. //
  1446. DBGMSG(DBG_WARN, ("Could not remove Item %x\n", RetVal));
  1447. Temp = NULL;
  1448. OurRetVal = E_FAIL;
  1449. }
  1450. }
  1451. else
  1452. {
  1453. LeaveCritSec();
  1454. RetVal = CreatePoolFile(&Temp, Filename);
  1455. if ( FAILED(RetVal) )
  1456. {
  1457. //
  1458. // Bad Things
  1459. //
  1460. DBGMSG(DBG_WARN, ("Could not create Item %x\n", RetVal));
  1461. OurRetVal = E_FAIL;
  1462. }
  1463. else
  1464. {
  1465. EnterCritSec();
  1466. RetVal = AddToFPListEnd(Temp, &FileInUse, &EndUsedFiles);
  1467. if ( FAILED(RetVal) )
  1468. {
  1469. //
  1470. // Bad Things
  1471. //
  1472. DBGMSG(DBG_WARN, ("Could not add to List End after create %x\n", RetVal));
  1473. OurRetVal = E_FAIL;
  1474. }
  1475. else
  1476. {
  1477. UsedSize++;
  1478. }
  1479. LeaveCritSec();
  1480. }
  1481. EnterCritSec();
  1482. }
  1483. LeaveCritSec();
  1484. if ( FAILED(OurRetVal) )
  1485. {
  1486. //
  1487. // Clean up.
  1488. //
  1489. if ( Temp )
  1490. {
  1491. //
  1492. // We weren't able to add the file to the structure,
  1493. // This should never happen, but if it does, clean up
  1494. // the memory we use.
  1495. //
  1496. DeletePoolFile(&Temp);
  1497. }
  1498. *File = NULL;
  1499. }
  1500. else
  1501. {
  1502. *File = Temp;
  1503. }
  1504. return OurRetVal;
  1505. }
  1506. /*********************
  1507. * Filepool::ReleasePoolHandle()
  1508. *
  1509. * See ReleasePoolHandle() Above.
  1510. */
  1511. HRESULT
  1512. FilePool::ReleasePoolHandle(
  1513. struct FileListItem * File
  1514. )
  1515. {
  1516. BOOL bDeletePoolFile = FALSE;
  1517. HRESULT RetVal = S_OK;
  1518. HRESULT RemRetVal = S_OK;
  1519. if ((File->Status & FP_STATUS_SPL_READING) ||
  1520. (File->Status & FP_STATUS_SPL_WRITING) ||
  1521. (File->Status & FP_STATUS_SHD_WRITING))
  1522. {
  1523. RetVal = E_FAIL;
  1524. //
  1525. // This is a pathological case as we will subsequently leak this handle.
  1526. // Break.
  1527. //
  1528. DBGMSG(DBG_ERROR, ("Tried to release a file with handles in use\n"));
  1529. }
  1530. else
  1531. {
  1532. EnterCritSec();
  1533. RemRetVal = RemoveFromFPList(File, &FileInUse, &EndUsedFiles);
  1534. if (SUCCEEDED(RemRetVal))
  1535. {
  1536. UsedSize--;
  1537. //
  1538. // If the spool directory has changed we need to delete the pool file
  1539. //
  1540. if ( _wcsnicmp(FileBase, File->SplFilename, wcslen(FileBase)) )
  1541. {
  1542. bDeletePoolFile = TRUE;
  1543. }
  1544. }
  1545. LeaveCritSec();
  1546. if (SUCCEEDED(RemRetVal))
  1547. {
  1548. if (bDeletePoolFile == TRUE ||
  1549. FreeSize >= MaxFiles ||
  1550. ((File->SplWriteHandle == INVALID_HANDLE_VALUE) &&
  1551. (File->SplReadHandle == INVALID_HANDLE_VALUE)))
  1552. {
  1553. DeletePoolFile(&File);
  1554. }
  1555. else
  1556. {
  1557. File->TimeStamp = GetTickCount();
  1558. TruncateFiles(File);
  1559. EnterCritSec();
  1560. RetVal = AddToFPListEnd(File, &FreeFiles, &EndFreeFiles);
  1561. if (SUCCEEDED(RetVal))
  1562. {
  1563. FreeSize++;
  1564. }
  1565. LeaveCritSec();
  1566. }
  1567. }
  1568. else
  1569. {
  1570. RetVal = E_INVALIDARG;
  1571. }
  1572. }
  1573. return RetVal;
  1574. }
  1575. /*********************
  1576. * Filepool::CreateSplReader()
  1577. *
  1578. *Used in GetReaderFromHandle.
  1579. */
  1580. HRESULT
  1581. FilePool::CreateSplReader(
  1582. struct FileListItem * Item
  1583. )
  1584. {
  1585. HRESULT RetVal = S_OK;
  1586. HANDLE Temp = INVALID_HANDLE_VALUE;
  1587. Temp = CreateFile( Item->SplFilename,
  1588. SplModes.Mode,
  1589. SplModes.ShareMode,
  1590. NULL,
  1591. OPEN_EXISTING | SplModes.Disp,
  1592. SplModes.Flags,
  1593. NULL);
  1594. if (Temp && (Temp != INVALID_HANDLE_VALUE))
  1595. {
  1596. Item->SplReadHandle = Temp;
  1597. Item->CreateInfo |= FP_SPL_READER_CREATED;
  1598. }
  1599. else
  1600. {
  1601. RetVal = E_FAIL;
  1602. }
  1603. return RetVal;
  1604. }
  1605. /*********************
  1606. * Filepool::CreateSplWriter()
  1607. *
  1608. * Does the CreateFile for the Spool File. Used for GetWriterFromHandle().
  1609. */
  1610. HRESULT
  1611. FilePool::CreateSplWriter(
  1612. struct FileListItem * Item
  1613. )
  1614. {
  1615. HRESULT RetVal = S_OK;
  1616. HANDLE Temp = INVALID_HANDLE_VALUE;
  1617. Temp = CreateFile( Item->SplFilename,
  1618. SplModes.Mode,
  1619. SplModes.ShareMode,
  1620. NULL,
  1621. CREATE_ALWAYS | SplModes.Disp,
  1622. SplModes.Flags,
  1623. NULL);
  1624. if (Temp && (Temp != INVALID_HANDLE_VALUE))
  1625. {
  1626. Item->SplWriteHandle = Temp;
  1627. Item->CreateInfo |= FP_SPL_WRITER_CREATED;
  1628. }
  1629. else
  1630. {
  1631. RetVal = E_FAIL;
  1632. }
  1633. return RetVal;
  1634. }
  1635. /*********************
  1636. * Filepool::CreateShdWriter()
  1637. *
  1638. * Does the CreateFile for the ShadowFile. Used for GetWriterFromHandle().
  1639. */
  1640. HRESULT
  1641. FilePool::CreateShdWriter(
  1642. struct FileListItem * Item
  1643. )
  1644. {
  1645. HRESULT RetVal = S_OK;
  1646. HANDLE Temp = INVALID_HANDLE_VALUE;
  1647. Temp = CreateFile( Item->ShdFilename,
  1648. ShdModes.Mode,
  1649. ShdModes.ShareMode,
  1650. NULL,
  1651. CREATE_ALWAYS | ShdModes.Disp,
  1652. ShdModes.Flags,
  1653. NULL);
  1654. if (Temp && (Temp != INVALID_HANDLE_VALUE))
  1655. {
  1656. Item->ShdWriteHandle = Temp;
  1657. Item->CreateInfo |= FP_SHD_CREATED;
  1658. }
  1659. else
  1660. {
  1661. RetVal = E_FAIL;
  1662. }
  1663. return RetVal;
  1664. }
  1665. /*********************
  1666. * Filepool::RemoveFromPool()
  1667. *
  1668. * See RemoveFromFilePool() Above.
  1669. */
  1670. HRESULT
  1671. FilePool::RemoveFromPool(
  1672. struct FileListItem * File,
  1673. BOOL Delete
  1674. )
  1675. {
  1676. HRESULT RemRetVal = S_OK;
  1677. if ((File->Status & FP_STATUS_SPL_READING) ||
  1678. (File->Status & FP_STATUS_SPL_WRITING) ||
  1679. (File->Status & FP_STATUS_SHD_WRITING))
  1680. {
  1681. RemRetVal = E_FAIL;
  1682. //
  1683. // This is a pathological case as it will cause us to leak a KM handle.
  1684. // Hard break here.
  1685. //
  1686. DBGMSG(DBG_ERROR, ("Tried to release a file with handles in use\n"));
  1687. }
  1688. else
  1689. {
  1690. EnterCritSec();
  1691. RemRetVal = RemoveFromFPList(File, &FileInUse, &EndUsedFiles);
  1692. if (SUCCEEDED(RemRetVal))
  1693. {
  1694. UsedSize--;
  1695. }
  1696. LeaveCritSec();
  1697. if (FAILED(RemRetVal))
  1698. {
  1699. EnterCritSec();
  1700. RemRetVal = RemoveFromFPList(File, &FreeFiles, &EndFreeFiles);
  1701. if (SUCCEEDED(RemRetVal))
  1702. {
  1703. FreeSize--;
  1704. }
  1705. LeaveCritSec();
  1706. }
  1707. if (SUCCEEDED(RemRetVal))
  1708. {
  1709. if (Delete)
  1710. {
  1711. DeletePoolFile(&File);
  1712. }
  1713. else
  1714. {
  1715. FPCloseFiles(File, TRUE);
  1716. DeleteCriticalSection(&File->CritSec);
  1717. if (File->SplFilename)
  1718. {
  1719. FreeSplMem(File->SplFilename);
  1720. }
  1721. if (File->ShdFilename)
  1722. {
  1723. FreeSplMem(File->ShdFilename);
  1724. }
  1725. FreeSplMem(File);
  1726. }
  1727. }
  1728. }
  1729. return RemRetVal;
  1730. }
  1731. /*********************
  1732. * Filepool::TrimPool()
  1733. *
  1734. * See TrimPool() Above.
  1735. */
  1736. BOOL
  1737. FilePool::TrimPool(
  1738. VOID
  1739. )
  1740. {
  1741. DWORD Time = 0;
  1742. BOOL GotToTrim = TRUE;
  1743. struct FileListItem * Temp = NULL;
  1744. struct FileListItem * DeleteFiles = NULL;
  1745. DWORD TrimCount = 0;
  1746. BOOL bFilesToTrim = FALSE;
  1747. Time = GetTickCount();
  1748. EnterCritSec();
  1749. DeleteFiles = FreeFiles;
  1750. while (FreeFiles)
  1751. {
  1752. if ((FreeFiles->TimeStamp > Time) ||
  1753. (Time - FreeFiles->TimeStamp > PoolTimeout))
  1754. {
  1755. //
  1756. // Walk forward until you reach a file that is not too old.
  1757. //
  1758. FreeFiles = FreeFiles->FLNext;
  1759. TrimCount++;
  1760. }
  1761. else
  1762. {
  1763. if (FreeFiles->FLPrev)
  1764. {
  1765. //
  1766. // There are files to delete.
  1767. //
  1768. FreeFiles->FLPrev->FLNext = NULL;
  1769. FreeFiles->FLPrev = NULL;
  1770. }
  1771. else
  1772. {
  1773. //
  1774. // No files have timed out.
  1775. //
  1776. DeleteFiles = NULL;
  1777. }
  1778. break;
  1779. }
  1780. }
  1781. if (!FreeFiles)
  1782. {
  1783. EndFreeFiles = NULL;
  1784. }
  1785. //
  1786. // We need to decrease the FreeSize by the number of elements we are just about
  1787. // to trim off it.
  1788. //
  1789. FreeSize -= TrimCount;
  1790. //
  1791. // We should trim files the next time around if there is a FreeFiles list.
  1792. //
  1793. bFilesToTrim = FreeFiles != NULL;
  1794. LeaveCritSec();
  1795. //
  1796. // Now outside the critsec do the deletions.
  1797. //
  1798. while (DeleteFiles)
  1799. {
  1800. struct FileListItem * Temp = DeleteFiles;
  1801. DeleteFiles = DeleteFiles->FLNext;
  1802. DeletePoolFile(&Temp);
  1803. }
  1804. return bFilesToTrim;
  1805. }
  1806. void*
  1807. FilePool::operator new(
  1808. size_t n
  1809. )
  1810. {
  1811. return AllocSplMem(n);
  1812. }
  1813. void
  1814. FilePool::operator delete(
  1815. void* p,
  1816. size_t n
  1817. )
  1818. {
  1819. if (p)
  1820. {
  1821. FreeSplMem(p);
  1822. }
  1823. }