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.

279 lines
7.8 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997-1998.
  5. //
  6. // File: usnvol.cxx
  7. //
  8. // Contents: Usn volume info
  9. //
  10. // History: 07-May-97 SitaramR Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <pch.cxx>
  14. #pragma hdrstop
  15. #include <ntopen.hxx>
  16. #include "usnvol.hxx"
  17. //+---------------------------------------------------------------------------
  18. //
  19. // Member: CUsnVolume::CUsnVolume
  20. //
  21. // Synopsis: Constructor
  22. //
  23. // Arguments: [wcDriveLetter] -- Drive letter
  24. // [volumeId] -- Volume id
  25. //
  26. // History: 07-May-97 SitaramR Created
  27. //
  28. //----------------------------------------------------------------------------
  29. CUsnVolume::CUsnVolume( WCHAR wcDriveLetter, VOLUMEID volumeId )
  30. : _hVolume(INVALID_HANDLE_VALUE),
  31. _wcDriveLetter(wcDriveLetter),
  32. _usnMaxRead(0),
  33. _volumeId(volumeId),
  34. _fileIdRoot(fileIdInvalid),
  35. _fFsctlPending(FALSE),
  36. _fOnline(TRUE)
  37. {
  38. Win4Assert( volumeId != CI_VOLID_USN_NOT_ENABLED );
  39. //
  40. // Find the file id of root of volume
  41. //
  42. WCHAR wszRootPath[] = L"a:\\.";
  43. wszRootPath[0] = wcDriveLetter;
  44. HANDLE rootHandle = CiNtOpen( wszRootPath,
  45. FILE_READ_ATTRIBUTES | SYNCHRONIZE,
  46. FILE_SHARE_READ | FILE_SHARE_WRITE,
  47. 0 );
  48. SHandle xHandle( rootHandle );
  49. IO_STATUS_BLOCK iosb;
  50. ULONGLONG readBuffer[200];
  51. NTSTATUS status = NtFsControlFile( rootHandle,
  52. NULL,
  53. NULL,
  54. NULL,
  55. &iosb,
  56. FSCTL_READ_FILE_USN_DATA,
  57. NULL,
  58. NULL,
  59. &readBuffer,
  60. sizeof(readBuffer) );
  61. if ( NT_SUCCESS( status ) )
  62. status = iosb.Status;
  63. if ( NT_SUCCESS( status ) )
  64. {
  65. USN_RECORD *pUsnRec = (USN_RECORD *)((PCHAR) &readBuffer);
  66. //
  67. // Root is its own parent
  68. //
  69. Win4Assert( pUsnRec->FileReferenceNumber == pUsnRec->ParentFileReferenceNumber );
  70. _fileIdRoot = pUsnRec->FileReferenceNumber;
  71. }
  72. else
  73. {
  74. ciDebugOut(( DEB_ERROR, "Unable to read usn info of root, 0x%x\n", status ));
  75. THROW( CException( status ) );
  76. }
  77. //
  78. // Create the volume handle that will be used for usn fsctls
  79. //
  80. WCHAR wszVolumePath[] = L"\\\\.\\a:";
  81. wszVolumePath[4] = wcDriveLetter;
  82. _hVolume = CreateFile( wszVolumePath,
  83. GENERIC_READ | GENERIC_WRITE,
  84. FILE_SHARE_READ | FILE_SHARE_WRITE,
  85. NULL,
  86. OPEN_EXISTING,
  87. FILE_FLAG_OVERLAPPED,
  88. NULL );
  89. if ( _hVolume == INVALID_HANDLE_VALUE )
  90. {
  91. ciDebugOut(( DEB_ERROR, "Usn volume open failed, 0x%x", GetLastError() ));
  92. THROW( CException() );
  93. }
  94. //
  95. // Get the Journal ID
  96. //
  97. USN_JOURNAL_DATA UsnJournalInfo;
  98. status = NtFsControlFile( _hVolume,
  99. NULL,
  100. NULL,
  101. NULL,
  102. &iosb,
  103. FSCTL_QUERY_USN_JOURNAL,
  104. 0,
  105. 0,
  106. &UsnJournalInfo,
  107. sizeof(UsnJournalInfo) );
  108. if ( status == STATUS_PENDING )
  109. {
  110. Win4Assert( !"Synchronous usn read returned status_pending" );
  111. _JournalID = 0;
  112. }
  113. else
  114. {
  115. if ( NT_SUCCESS( status ) )
  116. status = iosb.Status;
  117. if ( NT_SUCCESS(status) )
  118. _JournalID = UsnJournalInfo.UsnJournalID;
  119. else
  120. _JournalID = 0;
  121. }
  122. }
  123. //+---------------------------------------------------------------------------
  124. //
  125. // Member: CUsnVolume::~CUsnVolume
  126. //
  127. // Synopsis: Destructor
  128. //
  129. // History: 07-May-97 SitaramR Created
  130. //
  131. //----------------------------------------------------------------------------
  132. CUsnVolume::~CUsnVolume()
  133. {
  134. Win4Assert( _hVolume != INVALID_HANDLE_VALUE );
  135. CancelFsctl();
  136. CloseHandle( _hVolume );
  137. }
  138. //+---------------------------------------------------------------------------
  139. //
  140. // Member: CUsnVolume::CancelFsctl
  141. //
  142. // Synopsis: Cancels any pending fsctls
  143. //
  144. // History: 05-Jul-97 SitaramR Created
  145. //
  146. //----------------------------------------------------------------------------
  147. void CUsnVolume::CancelFsctl()
  148. {
  149. if ( _fFsctlPending )
  150. {
  151. IO_STATUS_BLOCK iosb;
  152. NTSTATUS status = NtCancelIoFile( _hVolume, &iosb );
  153. if ( STATUS_SUCCESS != status )
  154. {
  155. ciDebugOut(( DEB_ERROR,
  156. "NtCancelIoFile pending usn fsctl failed: %#x\n",
  157. status ));
  158. }
  159. _evtFsctl.Wait( INFINITE );
  160. _fFsctlPending = FALSE;
  161. }
  162. }
  163. //+---------------------------------------------------------------------------
  164. //
  165. // Member: CUsnVolume::PercentRead, public
  166. //
  167. // Synopsis: Compute current position in USN Journal
  168. //
  169. // Returns: Percentage through readable portion of USN Journal.
  170. //
  171. // History: 22-Jun-98 KyleP Created
  172. //
  173. //----------------------------------------------------------------------------
  174. ULONG CUsnVolume::PercentRead()
  175. {
  176. USN usnPct;
  177. if ( 0 == _usnMaxRead )
  178. {
  179. usnPct = 0;
  180. }
  181. else
  182. {
  183. USN_JOURNAL_DATA UsnJournalInfo;
  184. IO_STATUS_BLOCK iosb;
  185. NTSTATUS Status = NtFsControlFile( _hVolume,
  186. NULL,
  187. NULL,
  188. NULL,
  189. &iosb,
  190. FSCTL_QUERY_USN_JOURNAL,
  191. 0,
  192. 0,
  193. &UsnJournalInfo,
  194. sizeof(UsnJournalInfo) );
  195. if ( Status == STATUS_PENDING )
  196. {
  197. Win4Assert( !"Synchronous usn read returned status_pending" );
  198. usnPct = 0;
  199. }
  200. else
  201. {
  202. if ( NT_SUCCESS( Status ) )
  203. Status = iosb.Status;
  204. if ( NT_SUCCESS(Status) )
  205. {
  206. //
  207. // Don't go negative. If we've ran off the end (and will get
  208. // STATUS_JOURNAL_ENTRY_DELETED when reading the journal)
  209. // just report 0%
  210. //
  211. if ( _usnMaxRead >= UsnJournalInfo.FirstUsn )
  212. {
  213. USN usnNum;
  214. usnNum = _usnMaxRead - UsnJournalInfo.FirstUsn;
  215. //
  216. // Add 1 to avoid divide-by-zero errors.
  217. //
  218. USN usnDen = UsnJournalInfo.NextUsn - UsnJournalInfo.FirstUsn + 1;
  219. usnPct = usnNum * 100 / usnDen;
  220. }
  221. else
  222. usnPct = 0;
  223. }
  224. else
  225. usnPct = 0;
  226. }
  227. }
  228. Win4Assert( usnPct >= 0 && usnPct <= 100 );
  229. return (ULONG)usnPct;
  230. }