Leaked source code of windows server 2003
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.

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