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.

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