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.

242 lines
7.7 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 1997.
  5. //
  6. // File: PROPBKP.HXX
  7. //
  8. // Contents: Property Store backup
  9. //
  10. // History: 30-May-97 KrishnaN Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #pragma once
  14. #include <twidhash.hxx>
  15. #include <thash.hxx>
  16. #include <driveinf.hxx>
  17. const WCHAR PROP_BKP_FILE[] = L"\\propstor.bkp"; // propstore backup
  18. const WCHAR PROP_BKP_FILE1[] = L"\\propstor.bk1"; // primary store backup
  19. const WCHAR PROP_BKP_FILE2[] = L"\\propstor.bk2"; // secondary store backup
  20. //+-------------------------------------------------------------------------
  21. //
  22. // Class: CPropStoreBackupStream
  23. //
  24. // Purpose: Encapsulates a property store backup stream. It essentially
  25. // opens a physical file and provides read/write/reset on that
  26. // file.
  27. //
  28. // Interface:
  29. //
  30. // History: 30-May-97 KrishnaN Created
  31. // 29-Oct-98 KLam Added disk space to leave to constructor
  32. // Added _cMegToLeaveOnDisk private member
  33. // Added _xDriveInfo private member
  34. //
  35. // Notes: The physical file is always opened with a fixed size. Append only
  36. // implies that a logical page is added to the stream. It does not
  37. // imply that the file is physically extended.
  38. //
  39. //--------------------------------------------------------------------------
  40. //
  41. // The number of pages used that can be backed up in the backup is configurable
  42. // through the registry per catalog. This enables the admin to control the
  43. // overall size of the catalog. The larger the number of pages, the less number
  44. // of intermediate property store commits.
  45. //
  46. #define roundup(a, b) ((a%b) ? (a/b + 1) : (a/b))
  47. const ULONG invalidSector = 0xFFFFFFFF;
  48. const ULONG invalidPage = 0xFFFFFFFF;
  49. class CPageHashTable
  50. {
  51. public:
  52. CPageHashTable(ULONG cHashInit) : _hashTable(cHashInit, TRUE)
  53. {
  54. }
  55. ULONG AddEntry(ULONG ulEntry, ULONG ulValue)
  56. {
  57. CWidValueHashEntry entry((WORKID)ulEntry, ulValue);
  58. return _hashTable.AddEntry(entry);
  59. }
  60. BOOL LookUp(ULONG ulEntry, ULONG &ulValue)
  61. {
  62. CWidValueHashEntry entry((WORKID)ulEntry, 0);
  63. if (!_hashTable.LookUpWorkId(entry))
  64. return FALSE;
  65. ulValue = entry.Value();
  66. return TRUE;
  67. }
  68. void DeleteAllEntries()
  69. {
  70. _hashTable.DeleteAllEntries();
  71. }
  72. private:
  73. TWidHashTable<CWidValueHashEntry> _hashTable;
  74. };
  75. class CPropStoreBackupStream
  76. {
  77. public:
  78. ~CPropStoreBackupStream();
  79. //
  80. // File operations
  81. //
  82. // Open a new or existing file
  83. void OpenForBackup ( const WCHAR* wcsPath,
  84. ULONG modeShare,
  85. ULONG modeCreate,
  86. ULONG ulMaxPages);
  87. // Open an existing file
  88. void OpenForRecovery ( const WCHAR* wcsPath,
  89. ULONG modeShare);
  90. // Close the file
  91. void Close();
  92. // Reset the file
  93. void Reset(ULONG cMaxPages);
  94. // Checks if the file is open
  95. BOOL IsOpen() const { return (INVALID_HANDLE_VALUE != _hFile); }
  96. // Checks if the file is open for recovery
  97. BOOL IsOpenForRecovery() const { return _fOpenForRecovery; }
  98. //
  99. // Page read/write operations
  100. //
  101. // Read the i-th page. The page buffer is assumed to be at least the page size
  102. // recorded in the backup file header.
  103. BOOL ReadPage(ULONG ulPage, ULONG *pulLoc, void *pbPage);
  104. // Get the page's location in prop store so that the caller can get the right
  105. // buffer from the property store.
  106. ULONG GetPageLocation(ULONG ulPage);
  107. // Append a page at the end of the stream. The page buffer is assumed
  108. // to be the size of the operating system page.
  109. BOOL CommitPage(ULONG slot, void const *pbPage);
  110. BOOL CommitPages(ULONG cPages,
  111. ULONG const *pSlots,
  112. void const * const * ppvPages);
  113. BOOL CommitField(ULONG ulPage,
  114. ULONG ulOffset,
  115. ULONG cSize,
  116. void const *pvBuffer);
  117. //
  118. // Query backup file properties
  119. //
  120. ULONG SectorSize() const { return _header.ulSectorSize; }
  121. ULONG PageSize() const { return _header.ulPageSize; }
  122. ULONG MaxPages() const { return _header.cMaxPages; }
  123. ULONG Pages() const { return _cPages; }
  124. ULONG GetSizeInBytes() const { return _cFileSizeInBytes; }
  125. private:
  126. friend CiStorage;
  127. CPropStoreBackupStream( ULONG cbDiskSpaceToLeave );
  128. void Init();
  129. BOOL CommitSector(ULONG ulSector, void const *pbBuffer);
  130. BOOL WriteToFile(ULONG ulStartLoc, ULONG ulNumBytes, void const *pbBuffer);
  131. void ReadFromFile(ULONG ulStartLoc, ULONG ulNumBytes, void *pbBuffer);
  132. inline void ReadSector(ULONG ulSector, PBYTE pbBuffer);
  133. ULONG CountPages();
  134. BOOL IsCorrupt();
  135. void GetSystemParams();
  136. HANDLE _hFile; // physical file
  137. ULONG _cPages; // pages currently backed up
  138. ULONG _cFileSizeInBytes; // physical file size
  139. PBYTE _pSector; // current sector used for I/O in dir section
  140. PBYTE _pBigBuffer; // a large buffer to hold the current sector.
  141. ULONG _ulCurrentSector; // current sector in memory.
  142. BOOL _fOpenForRecovery; // Is file open for recovery?
  143. ULONG _cMegToLeaveOnDisk ; // megabytes not to write to
  144. XPtr<CDriveInfo> _xDriveInfo; // Maintains information about the volume
  145. //
  146. // The following structure will be the backup file's header.
  147. // The backup file, along with other property store files, can
  148. // be moved across processor architectures, so the page and sector
  149. // sizes used at backup write time should be recorded here.
  150. //
  151. struct SHeader
  152. {
  153. ULONG ulSectorSize; // sector size at create time
  154. ULONG ulPageSize; // page size at create time
  155. ULONG cMaxPages; // max pages in backup
  156. ULONG ulDataOffset; // starting point of data pages in file
  157. } _header;
  158. #if CIDBG
  159. ULONG _cPagesBackedUp, _cPagesCommited, _cFlushes, _cFieldsCommited; // some stats
  160. #endif // CIDBG
  161. //
  162. // Computes the offset of the page descriptor in the backup file. This accounts
  163. // for the space occupied by the header and space that might be wasted at the end
  164. // of sectors to achieve alignment.
  165. //
  166. inline ULONG ComputePageDescriptorOffset(ULONG ulSectorSize, ULONG nPage)
  167. {
  168. ULONG cSlots = (roundup(sizeof(SHeader), sizeof(ULONG)) + nPage);
  169. ULONG cSlotsPerSector = ulSectorSize / sizeof(ULONG);
  170. ULONG cSectors = cSlots / cSlotsPerSector;
  171. // space for cSectors PLUS space for the slots overfolowing into the next sector
  172. return cSectors*ulSectorSize + (cSlots % cSlotsPerSector)*sizeof(ULONG);
  173. }
  174. inline ULONG ComputeFirstSectorOfPage(ULONG ulPageLoc)
  175. {
  176. return (_header.ulDataOffset + ulPageLoc*_header.ulPageSize) / _header.ulSectorSize;
  177. }
  178. // Verify that a ULONG is a power of 2. Such a number will have only one 1-bit. So keep
  179. // right shifting until you get the first one bit in the LSB position. The next right
  180. // shift after that should leave a 0.
  181. inline BOOL IsPowerOf2(ULONG ulValue)
  182. {
  183. BOOL fPowerOf2 = (1 & ulValue);
  184. for (short i = 1; i < sizeof(ULONG)*8 && !fPowerOf2; i++)
  185. {
  186. ulValue = ulValue >> 1;
  187. fPowerOf2 = (1 & ulValue);
  188. }
  189. ulValue = ulValue >> 1;
  190. return (fPowerOf2 ? !ulValue : FALSE);
  191. }
  192. CPageHashTable _pageTable;
  193. };