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.

381 lines
10 KiB

  1. // Copyright (c) 1996-1999 Microsoft Corporation
  2. //+============================================================================
  3. //
  4. // File: LogHead.cxx
  5. //
  6. // Classes: CLogFileHeader
  7. //
  8. // This class represents the header (the first sector) of the Tracking
  9. // (Workstation) Service's log file.
  10. //
  11. //+============================================================================
  12. #include "pch.cxx"
  13. #pragma hdrstop
  14. #include "trkwks.hxx"
  15. //+----------------------------------------------------------------------------
  16. //
  17. // Method: Initialize
  18. //
  19. // Synopsis: Initialize the header class. We allocate a buffer here to
  20. // hold sectors. This is the only allocation we perform
  21. // in this class.
  22. //
  23. // Inputs: [cbSector] (in)
  24. // The size of the file sectors.
  25. //
  26. // Output: None
  27. //
  28. //+----------------------------------------------------------------------------
  29. void
  30. CLogFileHeader::Initialize( ULONG cbSector )
  31. {
  32. TrkAssert( 0 != cbSector );
  33. TrkAssert( NULL == _hFile );
  34. // Initialize flags
  35. _fDirty = FALSE;
  36. // Store the input
  37. if( sizeof(*_plogheader) + CB_EXTENDED_HEADER > cbSector )
  38. {
  39. TrkLog(( TRKDBG_ERROR, TEXT("Sector size isn't large enough for log header") ));
  40. TrkRaiseWin32Error( ERROR_BAD_CONFIGURATION );
  41. }
  42. _cbSector = cbSector;
  43. // Allocate a buffer to hold the header sector
  44. if( NULL != _plogheader && _cbSector != cbSector )
  45. {
  46. delete [] _plogheader;
  47. _plogheader = NULL;
  48. }
  49. if( NULL == _plogheader )
  50. {
  51. _plogheader = reinterpret_cast<LogHeader*>( new BYTE[ cbSector ] );
  52. if( NULL == _plogheader )
  53. {
  54. TrkLog((TRKDBG_ERROR, TEXT("Couldn't alloc %d bytes in CLogFileHeader::Initialize"), cbSector ));
  55. TrkRaiseWin32Error( ERROR_NOT_ENOUGH_MEMORY );
  56. }
  57. }
  58. // The "extended header" is that portion beyond the regular header
  59. _pextendedheader = &_plogheader[1];
  60. } // CLogFileHeader::Initialize
  61. //+----------------------------------------------------------------------------
  62. //
  63. // Method: UnInitialize
  64. //
  65. // Synopsis: Free the sector buffer.
  66. //
  67. // Inputs: None
  68. //
  69. // Output: None
  70. //
  71. //+----------------------------------------------------------------------------
  72. void
  73. CLogFileHeader::UnInitialize()
  74. {
  75. if( NULL != _plogheader )
  76. {
  77. if( IsOpen() )
  78. OnClose();
  79. LogHeader *plogheader = _plogheader;
  80. _plogheader = NULL;
  81. delete [] plogheader;
  82. }
  83. } // CLogFileHeader::UnInitialize()
  84. //+----------------------------------------------------------------------------
  85. //
  86. // Method: LoadHeader
  87. //
  88. // Synopsis: Load the header sector from the log file.
  89. //
  90. // Inputs: None
  91. //
  92. // Output: None
  93. //
  94. //+----------------------------------------------------------------------------
  95. void
  96. CLogFileHeader::LoadHeader( HANDLE hFile )
  97. {
  98. NTSTATUS status;
  99. LARGE_INTEGER liOffset;
  100. IO_STATUS_BLOCK IoStatusBlock;
  101. // _hFile must not be set until we've successfully loaded the header.
  102. TrkAssert( NULL == _hFile );
  103. // Read the header sector from the file
  104. liOffset.QuadPart = 0;
  105. status = NtReadFile( hFile, NULL, NULL, NULL,
  106. &IoStatusBlock, _plogheader, _cbSector,
  107. &liOffset, NULL );
  108. if ( STATUS_PENDING == status )
  109. {
  110. // Wait for the operation to complete. The resulting status
  111. // will be put in the IOSB
  112. status = NtWaitForSingleObject( hFile, FALSE, NULL );
  113. if( NT_SUCCESS(status) )
  114. status = IoStatusBlock.Status;
  115. }
  116. // Validate the results of the read
  117. if ( !NT_SUCCESS(status) )
  118. {
  119. TrkLog((TRKDBG_ERROR, TEXT("Failed NtReadFile (%08x)"), status ));
  120. if(STATUS_VOLUME_DISMOUNTED == status)
  121. {
  122. TrkRaiseNtStatus(status);
  123. }
  124. else
  125. {
  126. TrkRaiseException( TRK_E_CORRUPT_LOG );
  127. }
  128. }
  129. if( NULL != g_ptrkwks ) // NULL when called by dltadmin.exe
  130. g_ptrkwks->_entropy.Put();
  131. if( _cbSector != IoStatusBlock.Information )
  132. {
  133. TrkLog((TRKDBG_ERROR, TEXT("Couldn't read header from log") ));
  134. TrkRaiseException( TRK_E_CORRUPT_LOG );
  135. }
  136. _hFile = hFile;
  137. } // CLogFileHeader::LoadHeader()
  138. //+----------------------------------------------------------------------------
  139. //
  140. // Method: ReadExtended
  141. //
  142. // Synopsis: Read bytes from the extended header to the caller's
  143. // buffer.
  144. //
  145. // Inputs: [iOffset] (in)
  146. // 0-relative offset into the extended header.
  147. // [pv] (out)
  148. // Buffer to receive the extended header bytes
  149. // [cb] (in)
  150. // Size of this extended header segment.
  151. //
  152. // Outputs: None
  153. //
  154. //+----------------------------------------------------------------------------
  155. void
  156. CLogFileHeader::ReadExtended( ULONG iOffset, void *pv, ULONG cb )
  157. {
  158. TrkAssert( NULL != _plogheader );
  159. RaiseIfNotOpen();
  160. // Validate the request
  161. if( sizeof(*_plogheader) + iOffset + cb > _cbSector )
  162. {
  163. TrkLog((TRKDBG_ERROR, TEXT("Attempt to read too much data from the extended log header (%d bytes at %d)\n"),
  164. iOffset, cb ));
  165. TrkAssert( !TEXT("Invalid parameters to CLogFileHeader::ReadExtended") );
  166. TrkRaiseException( TRK_E_CORRUPT_LOG );
  167. }
  168. // Read the bytes
  169. memcpy( pv, &static_cast<BYTE*>(_pextendedheader)[ iOffset ], cb );
  170. } // CLogFileHeader::ReadExtended()
  171. //+----------------------------------------------------------------------------
  172. //
  173. // Method: WriteExtended
  174. //
  175. // Synopsis: Writes bytes to the caller-specified portion of the log's
  176. // extended header area.
  177. //
  178. // Inputs: [iOffset] (in)
  179. // 0-relative index into the extended header
  180. // [pv] (in)
  181. // The bytes to write.
  182. // [cb] (in)
  183. // The number of bytes to write.
  184. //
  185. // Output: None
  186. //
  187. //+----------------------------------------------------------------------------
  188. void
  189. CLogFileHeader::WriteExtended( ULONG iOffset, const void *pv, ULONG cb )
  190. {
  191. TrkAssert( NULL != _plogheader );
  192. TrkAssert( sizeof(*_plogheader) + iOffset + cb <= 512 );
  193. RaiseIfNotOpen();
  194. // Validate the request
  195. if( sizeof(*_plogheader) + iOffset + cb > _cbSector )
  196. {
  197. TrkLog((TRKDBG_ERROR, TEXT("Attempt to read too much data from the extended log header (%d bytes at %d)\n"),
  198. iOffset, cb ));
  199. TrkAssert( !TEXT("Invalid parameters to CLogFileHeader::WriteExtended") );
  200. TrkRaiseException( TRK_E_CORRUPT_LOG );
  201. }
  202. // Write the bytes
  203. memcpy( &static_cast<BYTE*>(_pextendedheader)[ iOffset ], pv, cb );
  204. SetDirty();
  205. } // CLogFileHeader::WriteExtended
  206. //+----------------------------------------------------------------------------
  207. //
  208. // Method: SetExpansionData
  209. //
  210. // Synopsis: Write information about an expansion to the log header.
  211. //
  212. // Inputs: [cbLogFile] (in)
  213. // The current size of the file.
  214. // [ilogStart] (in)
  215. // The index of the current starting point in the circular
  216. // linked-list.
  217. // [ilogEnd] (in)
  218. // The index of the current ending point in the circular
  219. // linked-list.
  220. //
  221. // Outputs: None
  222. //
  223. //+----------------------------------------------------------------------------
  224. void
  225. CLogFileHeader::SetExpansionData( ULONG cbLogFile, ULONG ilogStart, ULONG ilogEnd )
  226. {
  227. TrkAssert( NULL != _plogheader );
  228. RaiseIfNotOpen();
  229. // Save the expansion data
  230. _plogheader->expand.cbFile = cbLogFile;
  231. _plogheader->expand.ilogStart = ilogStart;
  232. _plogheader->expand.ilogEnd = ilogEnd;
  233. // Flush straight to disk
  234. Flush( );
  235. } // CLogFileHeader::SetExpansionData()
  236. //+----------------------------------------------------------------------------
  237. //
  238. // Method: Flush
  239. //
  240. // Synopsis: Flush the current header sector to the underlying file.
  241. //
  242. // Inputs: [FlushFlags] (in)
  243. // From the FLUSH_* defines. Used to indicate if we
  244. // should flush regardless of the dirty flag, and if
  245. // we should flush to cache or to disk.
  246. //
  247. // Outputs: None
  248. //
  249. //+----------------------------------------------------------------------------
  250. void
  251. CLogFileHeader::Flush( )
  252. {
  253. NTSTATUS status = STATUS_SUCCESS;
  254. RaiseIfNotOpen();
  255. // Is there anything loaded to even flush?
  256. if( NULL != _hFile )
  257. {
  258. IO_STATUS_BLOCK IoStatusBlock;
  259. TrkAssert( NULL != _plogheader );
  260. // Is the in-memory header dirty?
  261. if( _fDirty )
  262. {
  263. LARGE_INTEGER liOffset;
  264. TrkAssert( NULL != _hFile );
  265. // Write the header sector to the file
  266. liOffset.QuadPart = 0;
  267. status = NtWriteFile( _hFile, NULL, NULL, NULL,
  268. &IoStatusBlock, _plogheader, _cbSector,
  269. &liOffset, NULL );
  270. if ( STATUS_PENDING == status )
  271. {
  272. // Wait for the operation to complete. The resulting status
  273. // will be put in the IOSB
  274. status = NtWaitForSingleObject( _hFile, FALSE, NULL );
  275. if( NT_SUCCESS(status) )
  276. status = IoStatusBlock.Status;
  277. }
  278. // Validate the results of the write
  279. if ( !NT_SUCCESS(status) )
  280. {
  281. TrkLog((TRKDBG_ERROR, TEXT("Couldn't write the log file header")));
  282. TrkRaiseNtStatus( status );
  283. }
  284. if( NULL != g_ptrkwks ) // NULL when called by dltadmin.exe
  285. g_ptrkwks->_entropy.Put();
  286. if( _cbSector != IoStatusBlock.Information )
  287. {
  288. TrkLog((TRKDBG_ERROR, TEXT("Couldn't write all of the log file header (%d)"),
  289. IoStatusBlock.Information ));
  290. TrkRaiseException( TRK_E_CORRUPT_LOG );
  291. }
  292. SetDirty( FALSE );
  293. } // if( _fDirty || FLUSH_UNCONDITIONALLY == flush_type )
  294. } // if( NULL != _hFile )
  295. } // CLogFileHeader::Flush