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.

750 lines
18 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. usn.c
  5. Abstract:
  6. This file contains code for commands that affect
  7. the usn journal.
  8. Author:
  9. Wesley Witt [wesw] 1-March-2000
  10. Revision History:
  11. --*/
  12. #include <precomp.h>
  13. #define MAX_USN_DATA 4096
  14. INT
  15. UsnHelp(
  16. IN INT argc,
  17. IN PWSTR argv[]
  18. )
  19. {
  20. DisplayMsg( MSG_USAGE_USN );
  21. return EXIT_CODE_SUCCESS;
  22. }
  23. __inline PUSN_RECORD
  24. NextUsnRecord(
  25. const PUSN_RECORD input
  26. )
  27. {
  28. ULONGLONG output;
  29. // Get the base address of the current record.
  30. (PUSN_RECORD) output = input;
  31. // Add the size of the record (structure + file name after the end
  32. // of the structure).
  33. output += input->RecordLength;
  34. // Round up the record size to match the 64-bit alignment, if the
  35. // size is not already a multiple of 8. Perform a bitwise AND
  36. // operation here instead of division because it is much faster than
  37. // division. However, the bitwise AND operation only works because
  38. // the divisor 8 is a power of 2.
  39. if (output & 8-1) {
  40. // Round down to nearest multiple of 8.
  41. output &= -8;
  42. // Then add 8.
  43. output += 8;
  44. }
  45. return((PUSN_RECORD) output);
  46. }
  47. VOID
  48. DisplayUsnRecord(
  49. const PUSN_RECORD UsnRecord
  50. )
  51. {
  52. WCHAR DateString[128];
  53. WCHAR TimeString[128];
  54. TIME_FIELDS TimeFields;
  55. SYSTEMTIME SystemTime;
  56. RtlTimeToTimeFields(&UsnRecord->TimeStamp, &TimeFields);
  57. SystemTime.wYear = TimeFields.Year ;
  58. SystemTime.wMonth = TimeFields.Month ;
  59. SystemTime.wDayOfWeek = TimeFields.Weekday ;
  60. SystemTime.wDay = TimeFields.Day ;
  61. SystemTime.wHour = TimeFields.Hour ;
  62. SystemTime.wMinute = TimeFields.Minute ;
  63. SystemTime.wSecond = TimeFields.Second ;
  64. SystemTime.wMilliseconds = TimeFields.Milliseconds;
  65. GetDateFormat( LOCALE_USER_DEFAULT,
  66. DATE_SHORTDATE,
  67. &SystemTime,
  68. NULL,
  69. DateString,
  70. sizeof( DateString ) / sizeof( DateString[0] ));
  71. GetTimeFormat( LOCALE_USER_DEFAULT,
  72. FALSE,
  73. &SystemTime,
  74. NULL,
  75. TimeString,
  76. sizeof( TimeString ) / sizeof( TimeString[0] ));
  77. DisplayMsg(
  78. MSG_USNRECORD,
  79. UsnRecord->MajorVersion,
  80. UsnRecord->MinorVersion,
  81. QuadToPaddedHexText( UsnRecord->FileReferenceNumber ),
  82. QuadToPaddedHexText( UsnRecord->ParentFileReferenceNumber ),
  83. QuadToPaddedHexText( UsnRecord->Usn ),
  84. QuadToPaddedHexText( UsnRecord->TimeStamp.QuadPart ),
  85. TimeString, DateString,
  86. UsnRecord->Reason,
  87. UsnRecord->SourceInfo,
  88. UsnRecord->SecurityId,
  89. UsnRecord->FileAttributes,
  90. UsnRecord->FileNameLength,
  91. UsnRecord->FileNameOffset,
  92. UsnRecord->FileNameLength/sizeof(WCHAR),
  93. UsnRecord->FileName
  94. );
  95. }
  96. INT
  97. CreateUsnJournal(
  98. IN INT argc,
  99. IN PWSTR argv[]
  100. )
  101. /*++
  102. Routine Description:
  103. This routine create the USN journal for the volume specified.
  104. Arguments:
  105. argc - The argument count.
  106. argv - Array of Strings of the form :
  107. ' fscutl crusnj m=<max-value> a=<alloc-delta> <volume pathname>'.
  108. Return Value:
  109. None
  110. --*/
  111. {
  112. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  113. WCHAR FileName[MAX_PATH];
  114. BOOL Status;
  115. DWORD BytesReturned;
  116. CREATE_USN_JOURNAL_DATA InBuffer;
  117. ULONGLONG MaxSize;
  118. ULONGLONG AllocDelta;
  119. PWSTR EndPtr;
  120. INT ExitCode = EXIT_CODE_SUCCESS;
  121. try {
  122. if (argc != 3) {
  123. DisplayMsg( MSG_USAGE_CREATEUSN );
  124. if (argc != 0) {
  125. ExitCode = EXIT_CODE_FAILURE;
  126. }
  127. leave;
  128. }
  129. if (!IsVolumeLocalNTFS( argv[2][0] )) {
  130. DisplayMsg( MSG_NTFS_REQUIRED );
  131. ExitCode = EXIT_CODE_FAILURE;
  132. leave;
  133. }
  134. wcscpy( FileName, L"\\\\.\\" );
  135. wcscat( FileName, argv[2] );
  136. FileHandle = CreateFile(
  137. FileName,
  138. GENERIC_WRITE,
  139. FILE_SHARE_READ | FILE_SHARE_WRITE,
  140. NULL,
  141. OPEN_EXISTING,
  142. FILE_ATTRIBUTE_NORMAL,
  143. NULL
  144. );
  145. if (FileHandle == INVALID_HANDLE_VALUE) {
  146. DisplayError();
  147. ExitCode = EXIT_CODE_FAILURE;
  148. leave;
  149. }
  150. if (_wcsnicmp( argv[0], L"m=", 2)
  151. || wcslen( argv[0] ) == 2) {
  152. DisplayMsg( MSG_INVALID_PARAMETER, argv[0] );
  153. DisplayMsg( MSG_USAGE_CREATEUSN );
  154. ExitCode = EXIT_CODE_FAILURE;
  155. leave;
  156. }
  157. if (_wcsnicmp( argv[1], L"a=", 2)
  158. || wcslen( argv[1] ) == 2) {
  159. DisplayMsg( MSG_INVALID_PARAMETER, argv[1] );
  160. DisplayMsg( MSG_USAGE_CREATEUSN );
  161. ExitCode = EXIT_CODE_FAILURE;
  162. leave;
  163. }
  164. MaxSize = My_wcstoui64( argv[0] + 2, &EndPtr, 0 );
  165. if (UnsignedI64NumberCheck( MaxSize, EndPtr )) {
  166. DisplayMsg( MSG_INVALID_PARAMETER, argv[0] );
  167. DisplayMsg( MSG_USAGE_CREATEUSN );
  168. ExitCode = EXIT_CODE_FAILURE;
  169. leave;
  170. }
  171. AllocDelta = My_wcstoui64( argv[1] + 2, &EndPtr, 0 );
  172. if (UnsignedI64NumberCheck( AllocDelta, EndPtr )) {
  173. DisplayMsg( MSG_INVALID_PARAMETER, argv[1] );
  174. DisplayMsg( MSG_USAGE_CREATEUSN );
  175. ExitCode = EXIT_CODE_FAILURE;
  176. leave;
  177. }
  178. InBuffer.MaximumSize = MaxSize;
  179. InBuffer.AllocationDelta = AllocDelta;
  180. Status = DeviceIoControl(
  181. FileHandle,
  182. FSCTL_CREATE_USN_JOURNAL,
  183. &InBuffer,
  184. sizeof(InBuffer),
  185. NULL,
  186. 0,
  187. &BytesReturned,
  188. (LPOVERLAPPED)NULL
  189. );
  190. if (!Status) {
  191. DisplayError();
  192. ExitCode = EXIT_CODE_FAILURE;
  193. leave;
  194. }
  195. } finally {
  196. if (FileHandle != INVALID_HANDLE_VALUE) {
  197. CloseHandle( FileHandle );
  198. }
  199. }
  200. return ExitCode;
  201. }
  202. INT
  203. QueryUsnJournal(
  204. IN INT argc,
  205. IN PWSTR argv[]
  206. )
  207. /*++
  208. Routine Description:
  209. This routine queries the USN journal for the volume specified.
  210. Arguments:
  211. argc - The argument count.
  212. argv - Array of Strings of the form :
  213. ' fscutl queryusnj <volume pathname>'.
  214. Return Value:
  215. None
  216. --*/
  217. {
  218. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  219. WCHAR FileName[MAX_PATH];
  220. BOOL Status;
  221. DWORD BytesReturned;
  222. USN_JOURNAL_DATA UsnJournalData;
  223. INT ExitCode = EXIT_CODE_SUCCESS;
  224. try {
  225. if (argc != 1) {
  226. DisplayMsg( MSG_USAGE_QUERYUSN );
  227. if (argc != 0) {
  228. ExitCode = EXIT_CODE_FAILURE;
  229. }
  230. leave;
  231. }
  232. if (!IsVolumeLocalNTFS( argv[0][0] )) {
  233. DisplayMsg( MSG_NTFS_REQUIRED );
  234. ExitCode = EXIT_CODE_FAILURE;
  235. leave;
  236. }
  237. wcscpy( FileName, L"\\\\.\\" );
  238. wcscat( FileName, argv[0] );
  239. FileHandle = CreateFile(
  240. FileName,
  241. GENERIC_READ,
  242. FILE_SHARE_READ | FILE_SHARE_WRITE,
  243. NULL,
  244. OPEN_EXISTING,
  245. FILE_ATTRIBUTE_NORMAL,
  246. NULL
  247. );
  248. if (FileHandle == INVALID_HANDLE_VALUE) {
  249. DisplayError();
  250. ExitCode = EXIT_CODE_FAILURE;
  251. leave;
  252. }
  253. Status = DeviceIoControl(
  254. FileHandle,
  255. FSCTL_QUERY_USN_JOURNAL,
  256. NULL,
  257. 0,
  258. &UsnJournalData,
  259. sizeof(USN_JOURNAL_DATA),
  260. &BytesReturned,
  261. (LPOVERLAPPED)NULL
  262. );
  263. if (!Status) {
  264. DisplayError();
  265. ExitCode = EXIT_CODE_FAILURE;
  266. leave;
  267. }
  268. DisplayMsg(
  269. MSG_QUERYUSN,
  270. QuadToPaddedHexText( UsnJournalData.UsnJournalID ),
  271. QuadToPaddedHexText( UsnJournalData.FirstUsn ),
  272. QuadToPaddedHexText( UsnJournalData.NextUsn ),
  273. QuadToPaddedHexText( UsnJournalData.LowestValidUsn ),
  274. QuadToPaddedHexText( UsnJournalData.MaxUsn ),
  275. QuadToPaddedHexText( UsnJournalData.MaximumSize ),
  276. QuadToPaddedHexText( UsnJournalData.AllocationDelta )
  277. );
  278. } finally {
  279. if (FileHandle != INVALID_HANDLE_VALUE) {
  280. CloseHandle( FileHandle );
  281. }
  282. }
  283. return ExitCode;
  284. }
  285. INT
  286. DeleteUsnJournal(
  287. IN INT argc,
  288. IN PWSTR argv[]
  289. )
  290. /*++
  291. Routine Description:
  292. This routine deletes the USN journal for the volume specified.
  293. Arguments:
  294. argc - The argument count.
  295. argv - Array of Strings of the form :
  296. ' fscutl delusnj <flags> <volume pathname>'.
  297. Return Value:
  298. None
  299. --*/
  300. {
  301. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  302. WCHAR FileName[MAX_PATH];
  303. BOOL Status;
  304. DWORD BytesReturned;
  305. DELETE_USN_JOURNAL_DATA DeleteUsnJournalData;
  306. USN_JOURNAL_DATA UsnJournalData;
  307. INT i;
  308. INT ExitCode = EXIT_CODE_SUCCESS;
  309. try {
  310. if (argc < 2) {
  311. DisplayMsg( MSG_USAGE_DELETEUSN );
  312. if (argc != 0) {
  313. ExitCode = EXIT_CODE_FAILURE;
  314. }
  315. leave;
  316. }
  317. if (!IsVolumeLocalNTFS( argv[argc-1][0] )) {
  318. DisplayMsg( MSG_NTFS_REQUIRED );
  319. ExitCode = EXIT_CODE_FAILURE;
  320. leave;
  321. }
  322. wcscpy( FileName, L"\\\\.\\" );
  323. wcscat( FileName, argv[argc-1] );
  324. FileHandle = CreateFile(
  325. FileName,
  326. GENERIC_WRITE,
  327. FILE_SHARE_READ | FILE_SHARE_WRITE,
  328. NULL,
  329. OPEN_EXISTING,
  330. FILE_ATTRIBUTE_NORMAL,
  331. NULL
  332. );
  333. if (FileHandle == INVALID_HANDLE_VALUE) {
  334. DisplayError();
  335. ExitCode = EXIT_CODE_FAILURE;
  336. leave;
  337. }
  338. Status = DeviceIoControl(
  339. FileHandle,
  340. FSCTL_QUERY_USN_JOURNAL,
  341. NULL,
  342. 0,
  343. &UsnJournalData,
  344. sizeof(USN_JOURNAL_DATA),
  345. &BytesReturned,
  346. (LPOVERLAPPED)NULL
  347. );
  348. if (!Status) {
  349. DisplayError();
  350. ExitCode = EXIT_CODE_FAILURE;
  351. leave;
  352. }
  353. DeleteUsnJournalData.DeleteFlags = USN_DELETE_FLAG_DELETE ;
  354. for (i = 0; i < argc - 1; i++) {
  355. if (argv[i][0] == L'/' && wcslen( argv[i] ) == 2) {
  356. switch (towupper( argv[i][1] ) ) {
  357. case L'D':
  358. DeleteUsnJournalData.DeleteFlags |= USN_DELETE_FLAG_DELETE ;
  359. continue;
  360. case L'N':
  361. DeleteUsnJournalData.DeleteFlags |= USN_DELETE_FLAG_NOTIFY ;
  362. continue;
  363. }
  364. }
  365. DisplayMsg( MSG_INVALID_PARAMETER, argv[i] );
  366. DisplayMsg( MSG_USAGE_DELETEUSN );
  367. ExitCode = EXIT_CODE_FAILURE;
  368. leave;
  369. }
  370. DeleteUsnJournalData.UsnJournalID = UsnJournalData.UsnJournalID;
  371. Status = DeviceIoControl(
  372. FileHandle,
  373. FSCTL_DELETE_USN_JOURNAL,
  374. &DeleteUsnJournalData,
  375. sizeof(DELETE_USN_JOURNAL_DATA),
  376. NULL,
  377. 0,
  378. &BytesReturned,
  379. (LPOVERLAPPED)NULL
  380. );
  381. if (!Status) {
  382. DisplayError();
  383. ExitCode = EXIT_CODE_FAILURE;
  384. leave;
  385. }
  386. } finally {
  387. if (FileHandle != INVALID_HANDLE_VALUE) {
  388. CloseHandle( FileHandle );
  389. }
  390. }
  391. return ExitCode;
  392. }
  393. INT
  394. EnumUsnData(
  395. IN INT argc,
  396. IN PWSTR argv[]
  397. )
  398. /*++
  399. Routine Description:
  400. This routine enumerated the USN data associated with the volume
  401. specified.
  402. Arguments:
  403. argc - The argument count.
  404. argv - Array of Strings of the form :
  405. ' fscutl enusndata <file ref#> <lowUsn> <highUsn> <pathname>'.
  406. Return Value:
  407. None
  408. --*/
  409. {
  410. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  411. WCHAR FileName[MAX_PATH];
  412. BOOL Status;
  413. DWORD BytesReturned;
  414. MFT_ENUM_DATA MftEnumData;
  415. PVOID lpOutBuffer;
  416. DWORD nOutBufferSize;
  417. PUSN_RECORD UsnRecord;
  418. WORD Index;
  419. LONG Length;
  420. PWSTR EndStr;
  421. INT ExitCode = EXIT_CODE_SUCCESS;
  422. try {
  423. if (argc != 4) {
  424. DisplayMsg( MSG_USAGE_ENUMDATA );
  425. if (argc != 0) {
  426. ExitCode = EXIT_CODE_FAILURE;
  427. }
  428. leave;
  429. }
  430. if (!IsVolumeLocalNTFS( argv[argc-1][0] )) {
  431. DisplayMsg( MSG_NTFS_REQUIRED );
  432. ExitCode = EXIT_CODE_FAILURE;
  433. leave;
  434. }
  435. wcscpy( FileName, L"\\\\.\\" );
  436. wcscat( FileName, argv[argc-1] );
  437. FileHandle = CreateFile(
  438. FileName,
  439. GENERIC_READ,
  440. FILE_SHARE_READ | FILE_SHARE_WRITE,
  441. NULL,
  442. OPEN_EXISTING,
  443. FILE_ATTRIBUTE_NORMAL,
  444. NULL
  445. );
  446. if (FileHandle == INVALID_HANDLE_VALUE) {
  447. DisplayError();
  448. ExitCode = EXIT_CODE_FAILURE;
  449. leave;
  450. }
  451. nOutBufferSize = MAX_USN_DATA;
  452. lpOutBuffer = (PVOID) malloc ( nOutBufferSize );
  453. MftEnumData.StartFileReferenceNumber = My_wcstoui64( argv[0], &EndStr, 0 );
  454. if (UnsignedI64NumberCheck( MftEnumData.StartFileReferenceNumber, EndStr )) {
  455. DisplayMsg( MSG_USAGE_ENUMDATA );
  456. ExitCode = EXIT_CODE_FAILURE;
  457. leave;
  458. }
  459. MftEnumData.LowUsn = My_wcstoui64( argv[1], &EndStr, 0 );
  460. if (UnsignedI64NumberCheck( MftEnumData.LowUsn, EndStr )) {
  461. DisplayMsg( MSG_USAGE_ENUMDATA );
  462. ExitCode = EXIT_CODE_FAILURE;
  463. leave;
  464. }
  465. MftEnumData.HighUsn = My_wcstoui64( argv[2], &EndStr, 0 );
  466. if (UnsignedI64NumberCheck( MftEnumData.HighUsn, EndStr )) {
  467. DisplayMsg( MSG_USAGE_ENUMDATA );
  468. ExitCode = EXIT_CODE_FAILURE;
  469. leave;
  470. }
  471. while (TRUE) {
  472. Status = DeviceIoControl(
  473. FileHandle,
  474. FSCTL_ENUM_USN_DATA,
  475. &MftEnumData,
  476. sizeof(MFT_ENUM_DATA),
  477. lpOutBuffer,
  478. nOutBufferSize,
  479. &BytesReturned,
  480. (LPOVERLAPPED)NULL
  481. );
  482. if (!Status) {
  483. if (GetLastError() != ERROR_HANDLE_EOF) {
  484. DisplayError();
  485. ExitCode = EXIT_CODE_FAILURE;
  486. }
  487. leave;
  488. }
  489. if ( BytesReturned < sizeof( ULONGLONG ) + sizeof( USN_RECORD )) {
  490. break;
  491. }
  492. UsnRecord = (PUSN_RECORD) ((PBYTE)lpOutBuffer + sizeof( ULONGLONG ));
  493. while ((PBYTE)UsnRecord < (PBYTE)lpOutBuffer + BytesReturned) {
  494. DisplayMsg(
  495. MSG_ENUMDATA,
  496. QuadToPaddedHexText( UsnRecord->FileReferenceNumber ),
  497. QuadToPaddedHexText( UsnRecord->ParentFileReferenceNumber ),
  498. QuadToPaddedHexText( UsnRecord->Usn ),
  499. UsnRecord->SecurityId,
  500. UsnRecord->Reason,
  501. UsnRecord->FileNameLength,
  502. UsnRecord->FileNameLength / sizeof(WCHAR),
  503. UsnRecord->FileName
  504. );
  505. UsnRecord = NextUsnRecord( UsnRecord );
  506. }
  507. MftEnumData.StartFileReferenceNumber = *(PLONGLONG)lpOutBuffer;
  508. }
  509. } finally {
  510. if (FileHandle != INVALID_HANDLE_VALUE) {
  511. CloseHandle( FileHandle );
  512. }
  513. if (lpOutBuffer) {
  514. free( lpOutBuffer );
  515. }
  516. }
  517. return ExitCode;
  518. }
  519. INT
  520. ReadFileUsnData(
  521. IN INT argc,
  522. IN PWSTR argv[]
  523. )
  524. /*++
  525. Routine Description:
  526. This routine reads the usn data for the volume specified.
  527. Arguments:
  528. argc - The argument count.
  529. argv - Array of Strings of the form :
  530. ' fscutl rdusndata <pathname>'.
  531. Return Value:
  532. None
  533. --*/
  534. {
  535. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  536. WCHAR FileName[MAX_PATH];
  537. BOOL Status;
  538. DWORD BytesReturned;
  539. DWORD nOutBufferSize;
  540. PUSN_RECORD UsnRecord;
  541. PWSTR FullName;
  542. INT ExitCode = EXIT_CODE_SUCCESS;
  543. try {
  544. if (argc != 1) {
  545. DisplayMsg( MSG_USAGE_READDATA );
  546. if (argc != 0) {
  547. ExitCode = EXIT_CODE_FAILURE;
  548. }
  549. leave;
  550. }
  551. FullName = GetFullPath( argv[0] );
  552. if (!FullName) {
  553. DisplayError();
  554. ExitCode = EXIT_CODE_FAILURE;
  555. leave;
  556. }
  557. if (!IsVolumeLocalNTFS( FullName[0] )) {
  558. DisplayMsg( MSG_NTFS_REQUIRED );
  559. ExitCode = EXIT_CODE_FAILURE;
  560. leave;
  561. }
  562. wcscpy( FileName, L"\\\\.\\" );
  563. wcscat( FileName, FullName );
  564. FileHandle = CreateFile(
  565. FileName,
  566. GENERIC_READ,
  567. FILE_SHARE_READ | FILE_SHARE_WRITE,
  568. NULL,
  569. OPEN_EXISTING,
  570. FILE_ATTRIBUTE_NORMAL,
  571. NULL
  572. );
  573. if (FileHandle == INVALID_HANDLE_VALUE) {
  574. DisplayError();
  575. ExitCode = EXIT_CODE_FAILURE;
  576. leave;
  577. }
  578. nOutBufferSize = MAX_USN_DATA;
  579. UsnRecord = (PUSN_RECORD) malloc ( nOutBufferSize );
  580. Status = DeviceIoControl(
  581. FileHandle,
  582. FSCTL_READ_FILE_USN_DATA,
  583. NULL,
  584. 0,
  585. UsnRecord,
  586. nOutBufferSize,
  587. &BytesReturned,
  588. (LPOVERLAPPED)NULL
  589. );
  590. if (!Status) {
  591. DisplayError();
  592. ExitCode = EXIT_CODE_FAILURE;
  593. leave;
  594. }
  595. DisplayUsnRecord( UsnRecord );
  596. } finally {
  597. if (FileHandle != INVALID_HANDLE_VALUE) {
  598. CloseHandle( FileHandle );
  599. }
  600. if (UsnRecord) {
  601. free( UsnRecord );
  602. }
  603. free( FullName );
  604. }
  605. return ExitCode;
  606. }