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.

1093 lines
26 KiB

  1. /*++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. fspyLog.c
  5. Abstract:
  6. This module contains functions used to retrieve and see the log records
  7. recorded by filespy.sys.
  8. // @@BEGIN_DDKSPLIT
  9. Author:
  10. Molly Brown (MollyBro) 21-Apr-1999
  11. // @@END_DDKSPLIT
  12. Environment:
  13. User mode
  14. // @@BEGIN_DDKSPLIT
  15. Revision History:
  16. // @@END_DDKSPLIT
  17. --*/
  18. #include <stdio.h>
  19. #include <windows.h>
  20. #include <stdlib.h>
  21. #include <winioctl.h>
  22. #include "ioTestLog.h"
  23. #include "ioTestLib.h"
  24. #define TIME_BUFFER_LENGTH 20
  25. #define TIME_ERROR L"time error"
  26. #define FlagOn(F,SF) ( \
  27. (((F) & (SF))) \
  28. )
  29. VOID
  30. DumpLogRecord (
  31. PLOG_RECORD pLogRecord,
  32. PLOG_CONTEXT context
  33. )
  34. {
  35. PRECORD_IRP pRecordIrp;
  36. PRECORD_FASTIO pRecordFastIo;
  37. PRECORD_FS_FILTER_OPERATION pRecordFsFilterOp;
  38. ULONG nameLength;
  39. //
  40. // Calculate the length of the name in the log record.
  41. //
  42. nameLength = pLogRecord->Length - SIZE_OF_LOG_RECORD;
  43. //
  44. // A LOG_RECORD could have Irp or FastIo data in it. This
  45. // is denoted in the low-order byte of the RecordType flag.
  46. //
  47. switch (GET_RECORD_TYPE(pLogRecord)) {
  48. case RECORD_TYPE_IRP:
  49. //
  50. // We've got an Irp record, so output this data correctly.
  51. //
  52. pRecordIrp = &(pLogRecord->Record.RecordIrp);
  53. if (context->LogToScreen) {
  54. IrpScreenDump( pLogRecord->DeviceType,
  55. pLogRecord->SequenceNumber,
  56. pLogRecord->Name,
  57. nameLength,
  58. pRecordIrp,
  59. context->VerbosityFlags);
  60. }
  61. if (context->LogToFile) {
  62. IrpFileDump( pLogRecord->DeviceType,
  63. pLogRecord->SequenceNumber,
  64. pLogRecord->Name,
  65. nameLength,
  66. pRecordIrp,
  67. context->OutputFile,
  68. context->VerbosityFlags);
  69. }
  70. break;
  71. case RECORD_TYPE_FASTIO:
  72. //
  73. // We've got a FastIo record, so output this data correctly.
  74. //
  75. pRecordFastIo = &(pLogRecord->Record.RecordFastIo);
  76. if (context->LogToScreen) {
  77. FastIoScreenDump( pLogRecord->DeviceType,
  78. pLogRecord->SequenceNumber,
  79. pLogRecord->Name,
  80. nameLength,
  81. pRecordFastIo);
  82. }
  83. if (context->LogToFile) {
  84. FastIoFileDump( pLogRecord->DeviceType,
  85. pLogRecord->SequenceNumber,
  86. pLogRecord->Name,
  87. nameLength,
  88. pRecordFastIo,
  89. context->OutputFile);
  90. }
  91. break;
  92. case RECORD_TYPE_FS_FILTER_OP:
  93. //
  94. // We've got a FsFilter operation record, so output this
  95. // data correctly.
  96. //
  97. pRecordFsFilterOp = &(pLogRecord->Record.RecordFsFilterOp);
  98. if (context->LogToScreen) {
  99. FsFilterOperationScreenDump( pLogRecord->DeviceType,
  100. pLogRecord->SequenceNumber,
  101. pLogRecord->Name,
  102. nameLength,
  103. pRecordFsFilterOp );
  104. }
  105. if (context->LogToFile) {
  106. FsFilterOperationFileDump( pLogRecord->DeviceType,
  107. pLogRecord->SequenceNumber,
  108. pLogRecord->Name,
  109. nameLength,
  110. pRecordFsFilterOp,
  111. context->OutputFile );
  112. }
  113. break;
  114. default:
  115. printf("Filmon: Unknown log record type\n");
  116. }
  117. //
  118. // The RecordType could also designate that we are out of memory
  119. // or hit our program defined memory limit, so check for these
  120. // cases.
  121. //
  122. if (pLogRecord->RecordType & RECORD_TYPE_OUT_OF_MEMORY) {
  123. if (context->LogToScreen) {
  124. printf("M %08X SYSTEM OUT OF MEMORY\n", pLogRecord->SequenceNumber);
  125. }
  126. if (context->LogToFile) {
  127. fprintf(context->OutputFile, "M:\t%u", pLogRecord->SequenceNumber);
  128. }
  129. } else if (pLogRecord->RecordType & RECORD_TYPE_EXCEED_MEMORY_ALLOWANCE) {
  130. if (context->LogToScreen) {
  131. printf("M %08X EXCEEDED MEMORY ALLOWANCE\n", pLogRecord->SequenceNumber);
  132. }
  133. if (context->LogToFile) {
  134. fprintf(context->OutputFile, "M:\t%u", pLogRecord->SequenceNumber);
  135. }
  136. }
  137. }
  138. DWORD WINAPI
  139. VerifyCurrentLogRecords (
  140. PLOG_CONTEXT Context,
  141. PEXPECTED_OPERATION ExpectedOps
  142. )
  143. {
  144. CHAR buffer[BUFFER_SIZE];
  145. DWORD bytesReturned = 0;
  146. BOOL bResult;
  147. DWORD result;
  148. PLOG_RECORD pLogRecord;
  149. BOOL askForMore = TRUE;
  150. BOOL testPassed = FALSE;
  151. ULONG currentOp = 0;
  152. #ifdef USE_DO_HINT
  153. BOOL keepVerifying = TRUE;
  154. #else
  155. BOOL seenFirstOp = FALSE;
  156. #endif /* USE_DO_HINT */
  157. while (askForMore) {
  158. //
  159. // Check to see if we should shut down
  160. //
  161. if (Context->CleaningUp) {
  162. break;
  163. }
  164. //
  165. // Request log data from filespy
  166. //
  167. bResult = DeviceIoControl( Context->Device,
  168. IOTEST_GetLog,
  169. NULL,
  170. 0,
  171. buffer,
  172. BUFFER_SIZE,
  173. &bytesReturned,
  174. NULL);
  175. if (!bResult) {
  176. result = GetLastError();
  177. printf("ERROR controlling device: 0x%x\n", result);
  178. }
  179. //
  180. // Buffer is filled with a series of LOG_RECORD structures, one
  181. // right after another. Each LOG_RECORD says how long it is, so
  182. // we know where the next LOG_RECORD begins.
  183. //
  184. pLogRecord = (PLOG_RECORD) buffer;
  185. //
  186. // Logic to write record to screen and/or file
  187. //
  188. while ((BYTE *) pLogRecord < buffer + bytesReturned) {
  189. PRECORD_IRP pRecordIrp;
  190. DumpLogRecord( pLogRecord, Context );
  191. switch (GET_RECORD_TYPE(pLogRecord)) {
  192. case RECORD_TYPE_IRP:
  193. pRecordIrp = &(pLogRecord->Record.RecordIrp);
  194. #ifdef USE_DO_HINT
  195. if (keepVerifying) {
  196. if (pRecordIrp->IrpMajor == ExpectedOps[currentOp].Op) {
  197. if(pLogRecord->DeviceType != ExpectedOps[currentOp].Device) {
  198. keepVerifying = FALSE;
  199. } else {
  200. currentOp ++;
  201. }
  202. }
  203. }
  204. #else
  205. //
  206. // If we are not using the DeviceObject hint, we expect to
  207. // see log entries from both the TOP and BOTTOM filters
  208. // for each expected operation. So that we don't have to
  209. // redefine the ExpectedOperation array, just ignore the
  210. // device in the array and check to make sure that you see
  211. // a log record for the TOP_FILTER then the BOTTOM_FILTER for
  212. // each operation in the array.
  213. //
  214. if (!seenFirstOp) {
  215. if ((pLogRecord->DeviceType == TOP_FILTER) &&
  216. (pRecordIrp->IrpMajor == ExpectedOps[currentOp].Op)) {
  217. seenFirstOp = TRUE;
  218. }
  219. } else {
  220. if ((pLogRecord->DeviceType == BOTTOM_FILTER) &&
  221. (pRecordIrp->IrpMajor == ExpectedOps[currentOp].Op)) {
  222. seenFirstOp = FALSE;
  223. currentOp ++;
  224. }
  225. }
  226. #endif /* USE_DO_HINT */
  227. break;
  228. default:
  229. //
  230. // ignore
  231. //
  232. ;
  233. }
  234. //
  235. // Move to next LOG_RECORD
  236. //
  237. pLogRecord = (PLOG_RECORD) (((BYTE *) pLogRecord) + pLogRecord->Length);
  238. }
  239. if (bytesReturned == 0) {
  240. askForMore = FALSE;
  241. }
  242. }
  243. if (ExpectedOps[currentOp].Op == IRP_MJ_MAXIMUM_FUNCTION + 1) {
  244. testPassed = TRUE;
  245. }
  246. if (testPassed) {
  247. printf( "User log verification:\tPASSED - Expected operations seen.\n" );
  248. } else {
  249. printf( "User log verification:\tFAILED - Expected operations NOT seen.\n" );
  250. }
  251. return testPassed;
  252. }
  253. DWORD WINAPI
  254. RetrieveLogRecords (
  255. LPVOID lpParameter
  256. )
  257. {
  258. PLOG_CONTEXT context = (PLOG_CONTEXT)lpParameter;
  259. CHAR buffer[BUFFER_SIZE];
  260. DWORD bytesReturned = 0;
  261. BOOL bResult;
  262. DWORD result;
  263. PLOG_RECORD pLogRecord;
  264. printf("Log: Starting up\n");
  265. while (TRUE) {
  266. //
  267. // Check to see if we should shut down
  268. //
  269. if (context->CleaningUp) {
  270. break;
  271. }
  272. //
  273. // Request log data from filespy
  274. //
  275. bResult = DeviceIoControl( context->Device,
  276. IOTEST_GetLog,
  277. NULL,
  278. 0,
  279. buffer,
  280. BUFFER_SIZE,
  281. &bytesReturned,
  282. NULL);
  283. if (!bResult) {
  284. result = GetLastError();
  285. printf("ERROR controlling device: 0x%x\n", result);
  286. }
  287. //
  288. // Buffer is filled with a series of LOG_RECORD structures, one
  289. // right after another. Each LOG_RECORD says how long it is, so
  290. // we know where the next LOG_RECORD begins.
  291. //
  292. pLogRecord = (PLOG_RECORD) buffer;
  293. //
  294. // Logic to write record to screen and/or file
  295. //
  296. while ((BYTE *) pLogRecord < buffer + bytesReturned) {
  297. DumpLogRecord( pLogRecord, context );
  298. //
  299. // Move to next LOG_RECORD
  300. //
  301. pLogRecord = (PLOG_RECORD) (((BYTE *) pLogRecord) + pLogRecord->Length);
  302. }
  303. if (bytesReturned == 0) {
  304. Sleep( 500 );
  305. }
  306. }
  307. printf("Log: Shutting down\n");
  308. ReleaseSemaphore(context->ShutDown, 1, NULL);
  309. printf("Log: All done\n");
  310. return 0;
  311. }
  312. VOID
  313. PrintIrpCode (
  314. UCHAR MajorCode,
  315. UCHAR MinorCode,
  316. ULONG FsControlCode,
  317. FILE *OutputFile,
  318. BOOLEAN PrintMajorCode
  319. )
  320. {
  321. CHAR irpMajorString[OPERATION_NAME_BUFFER_SIZE];
  322. CHAR irpMinorString[OPERATION_NAME_BUFFER_SIZE];
  323. CHAR formatBuf[OPERATION_NAME_BUFFER_SIZE*2];
  324. GetIrpName(MajorCode,MinorCode,FsControlCode,irpMajorString,irpMinorString);
  325. if (OutputFile) {
  326. sprintf(formatBuf, "%s %s", irpMajorString, irpMinorString);
  327. fprintf(OutputFile, "\t%-50s", formatBuf);
  328. } else {
  329. if (PrintMajorCode) {
  330. printf("%-31s ", irpMajorString);
  331. } else {
  332. if (irpMinorString[0] != 0) {
  333. printf(" %-35s\n",
  334. irpMinorString);
  335. }
  336. }
  337. }
  338. }
  339. VOID
  340. PrintFastIoType (
  341. FASTIO_TYPE Code,
  342. FILE *OutputFile
  343. )
  344. {
  345. CHAR outputString[OPERATION_NAME_BUFFER_SIZE];
  346. GetFastioName(Code,outputString);
  347. if (OutputFile) {
  348. fprintf(OutputFile, "%-50s", outputString);
  349. } else {
  350. printf("%-31s ", outputString);
  351. }
  352. }
  353. VOID
  354. PrintFsFilterOperation (
  355. UCHAR Operation,
  356. FILE *OutputFile
  357. )
  358. {
  359. CHAR outputString[OPERATION_NAME_BUFFER_SIZE];
  360. GetFsFilterOperationName(Operation,outputString);
  361. if (OutputFile) {
  362. fprintf( OutputFile, "%-50s", outputString );
  363. } else {
  364. printf( "%-31s ", outputString );
  365. }
  366. }
  367. ULONG
  368. FormatSystemTime (
  369. SYSTEMTIME *SystemTime,
  370. PWCHAR Buffer,
  371. ULONG BufferLength
  372. )
  373. /*++
  374. Routine Name:
  375. FormatSystemTime
  376. Routine Description:
  377. Formats the values in a SystemTime struct into the buffer
  378. passed in. The resulting string is NULL terminated. The format
  379. for the time is:
  380. hours:minutes:seconds:milliseconds
  381. Arguments:
  382. SystemTime - the struct to format
  383. Buffer - the buffer to place the formatted time in
  384. BufferLength - the size of the buffer in characters
  385. Return Value:
  386. The number of characters returned in Buffer.
  387. --*/
  388. {
  389. PWCHAR writePosition;
  390. ULONG returnLength = 0;
  391. writePosition = Buffer;
  392. if (BufferLength < TIME_BUFFER_LENGTH) {
  393. //
  394. // Buffer is too short so exit
  395. //
  396. return 0;
  397. }
  398. returnLength = swprintf( Buffer,
  399. L"%02d:%02d:%02d:%03d",
  400. SystemTime->wHour,
  401. SystemTime->wMinute,
  402. SystemTime->wSecond,
  403. SystemTime->wMilliseconds);
  404. return returnLength;
  405. }
  406. VOID
  407. IrpFileDump (
  408. IOTEST_DEVICE_TYPE DeviceType,
  409. ULONG SequenceNumber,
  410. PWCHAR Name,
  411. ULONG NameLength,
  412. PRECORD_IRP RecordIrp,
  413. FILE *File,
  414. ULONG VerbosityFlags
  415. )
  416. /*++
  417. Routine Name:
  418. IrpFileDump
  419. Routine Description:
  420. Prints a Irp log record to the specified file. The output is in a tab
  421. delimited format with the fields in the following order:
  422. SequenceNumber, OriginatingTime, CompletionTime, IrpMajor, IrpMinor,
  423. IrpFlags, NoCache, Paging I/O, Synchronous, Synchronous paging, FileName,
  424. ReturnStatus, FileName
  425. Arguments:
  426. SequenceNumber - the sequence number for this log record
  427. Name - the name of the file that this Irp relates to
  428. NameLength - the length of Name in bytes
  429. RecordIrp - the Irp record to print
  430. File - the file to print to
  431. Return Value:
  432. None.
  433. --*/
  434. {
  435. FILETIME localTime;
  436. SYSTEMTIME systemTime;
  437. WCHAR time[TIME_BUFFER_LENGTH];
  438. switch (DeviceType) {
  439. case TOP_FILTER:
  440. fprintf(File, "TOP\tI\t%08X", SequenceNumber);
  441. break;
  442. case BOTTOM_FILTER:
  443. fprintf(File, "BOT\tI\t%08X", SequenceNumber);
  444. break;
  445. default:
  446. fprintf(File, "UNK\tI\t%08X", SequenceNumber);
  447. break;
  448. }
  449. //
  450. // Convert originating time
  451. //
  452. FileTimeToLocalFileTime( (FILETIME *)&(RecordIrp->OriginatingTime), &localTime );
  453. FileTimeToSystemTime( &localTime, &systemTime );
  454. if (FormatSystemTime( &systemTime, time, TIME_BUFFER_LENGTH )) {
  455. fprintf( File, "\t%-12S", time );
  456. } else {
  457. fprintf( File, "\t%-12S", TIME_ERROR );
  458. }
  459. fprintf( File, "\t%8x.%-4x ", RecordIrp->ProcessId, RecordIrp->ThreadId );
  460. PrintIrpCode( RecordIrp->IrpMajor, RecordIrp->IrpMinor, (ULONG)(ULONG_PTR)RecordIrp->Argument3, File, TRUE );
  461. fprintf( File, "\t%08p", RecordIrp->FileObject );
  462. //
  463. // Interpret set flags
  464. //
  465. fprintf( File, "\t%08lx ", RecordIrp->IrpFlags );
  466. fprintf( File, "%s", (RecordIrp->IrpFlags & IRP_NOCACHE) ? "N":"-" );
  467. fprintf( File, "%s", (RecordIrp->IrpFlags & IRP_PAGING_IO) ? "P":"-" );
  468. fprintf( File, "%s", (RecordIrp->IrpFlags & IRP_SYNCHRONOUS_API) ? "S":"-" );
  469. fprintf( File, "%s", (RecordIrp->IrpFlags & IRP_SYNCHRONOUS_PAGING_IO) ? "Y":"-" );
  470. if (FlagOn( VerbosityFlags, FS_VF_DUMP_PARAMETERS )) {
  471. fprintf( File,
  472. "%p %p %p %p ",
  473. RecordIrp->Argument1,
  474. RecordIrp->Argument2,
  475. RecordIrp->Argument3,
  476. RecordIrp->Argument4 );
  477. if (IRP_MJ_CREATE == RecordIrp->IrpMajor) {
  478. fprintf( File, "DesiredAccess->%08lx ", RecordIrp->DesiredAccess );
  479. }
  480. }
  481. fprintf( File, "\t%.*S", NameLength/sizeof(WCHAR), Name );
  482. fprintf( File, "\n" );
  483. }
  484. VOID
  485. IrpScreenDump (
  486. IOTEST_DEVICE_TYPE DeviceType,
  487. ULONG SequenceNumber,
  488. PWCHAR Name,
  489. ULONG NameLength,
  490. PRECORD_IRP RecordIrp,
  491. ULONG VerbosityFlags
  492. )
  493. /*++
  494. Routine Name:
  495. IrpScreenDump
  496. Routine Description:
  497. Prints a Irp log record to the screen in the following order:
  498. SequenceNumber, OriginatingTime, CompletionTime, IrpMajor, IrpMinor,
  499. IrpFlags, NoCache, Paging I/O, Synchronous, Synchronous paging,
  500. FileName, ReturnStatus, FileName
  501. Arguments:
  502. SequenceNumber - the sequence number for this log record
  503. Name - the file name to which this Irp relates
  504. NameLength - the length of Name in bytes
  505. RecordIrp - the Irp record to print
  506. Return Value:
  507. None.
  508. --*/
  509. {
  510. FILETIME localTime;
  511. SYSTEMTIME systemTime;
  512. WCHAR time[TIME_BUFFER_LENGTH];
  513. switch (DeviceType) {
  514. case TOP_FILTER:
  515. printf("TOP I %08X", SequenceNumber);
  516. break;
  517. case BOTTOM_FILTER:
  518. printf("BOT I %08X", SequenceNumber);
  519. break;
  520. default:
  521. printf("UNK I %08X", SequenceNumber);
  522. break;
  523. }
  524. //
  525. // Convert originating time
  526. //
  527. FileTimeToLocalFileTime( (FILETIME *)&(RecordIrp->OriginatingTime), &localTime );
  528. FileTimeToSystemTime( &localTime, &systemTime );
  529. if (FormatSystemTime( &systemTime, time, TIME_BUFFER_LENGTH )) {
  530. printf( "%-12S ", time );
  531. } else {
  532. printf( "%-12S ", TIME_ERROR );
  533. }
  534. printf( "%8x.%-4x ", RecordIrp->ProcessId, RecordIrp->ThreadId );
  535. PrintIrpCode( RecordIrp->IrpMajor, RecordIrp->IrpMinor, (ULONG)(ULONG_PTR)RecordIrp->Argument3, NULL, TRUE );
  536. printf( "%08p ", RecordIrp->FileObject );
  537. //
  538. // Interpret set flags
  539. //
  540. printf( "%08lx ", RecordIrp->IrpFlags );
  541. printf( "%s", (RecordIrp->IrpFlags & IRP_NOCACHE) ? "N":"-" );
  542. printf( "%s", (RecordIrp->IrpFlags & IRP_PAGING_IO) ? "P":"-" );
  543. printf( "%s", (RecordIrp->IrpFlags & IRP_SYNCHRONOUS_API) ? "S":"-" );
  544. printf( "%s ", (RecordIrp->IrpFlags & IRP_SYNCHRONOUS_PAGING_IO) ? "Y":"-" );
  545. if (FlagOn( VerbosityFlags, FS_VF_DUMP_PARAMETERS )) {
  546. printf( "%p %p %p %p ",
  547. RecordIrp->Argument1,
  548. RecordIrp->Argument2,
  549. RecordIrp->Argument3,
  550. RecordIrp->Argument4 );
  551. if (IRP_MJ_CREATE == RecordIrp->IrpMajor) {
  552. printf( "DesiredAccess->%08lx ", RecordIrp->DesiredAccess );
  553. }
  554. }
  555. printf( "%.*S", NameLength/sizeof(WCHAR), Name );
  556. printf( "\n" );
  557. PrintIrpCode( RecordIrp->IrpMajor, RecordIrp->IrpMinor, (ULONG)(ULONG_PTR)RecordIrp->Argument3, NULL, FALSE );
  558. }
  559. VOID
  560. FastIoFileDump (
  561. IOTEST_DEVICE_TYPE DeviceType,
  562. ULONG SequenceNumber,
  563. PWCHAR Name,
  564. ULONG NameLength,
  565. PRECORD_FASTIO RecordFastIo,
  566. FILE *File
  567. )
  568. /*++
  569. Routine Name:
  570. FastIoFileDump
  571. Routine Description:
  572. Prints a FastIo log record to the specified file. The output is in a tab
  573. delimited format with the fields in the following order:
  574. SequenceNumber, StartTime, CompletionTime, Fast I/O Type, FileName,
  575. Length, Wait, ReturnStatus, FileName
  576. Arguments:
  577. SequenceNumber - the sequence number for this log record
  578. Name - the name of the file referenced by this Fast I/O operation
  579. NameLength - the length of name in bytes
  580. RecordFastIo - the FastIo record to print
  581. File - the file to print to
  582. Return Value:
  583. None.
  584. --*/
  585. {
  586. SYSTEMTIME systemTime;
  587. FILETIME localTime;
  588. WCHAR time[TIME_BUFFER_LENGTH];
  589. switch (DeviceType) {
  590. case TOP_FILTER:
  591. fprintf(File, "TOP\tF\t%08X", SequenceNumber);
  592. break;
  593. case BOTTOM_FILTER:
  594. fprintf(File, "BOT\tF\t%08X", SequenceNumber);
  595. break;
  596. default:
  597. fprintf(File, "UNK\tF\t%08X", SequenceNumber);
  598. break;
  599. }
  600. //
  601. // Convert start time
  602. //
  603. FileTimeToLocalFileTime( (FILETIME *)&(RecordFastIo->StartTime), &localTime );
  604. FileTimeToSystemTime( &localTime, &systemTime );
  605. if (FormatSystemTime( &systemTime, time, TIME_BUFFER_LENGTH )) {
  606. fprintf( File, "\t%-12S", time );
  607. } else {
  608. fprintf( File, "\t%-12S", TIME_ERROR );
  609. }
  610. fprintf( File, "\t%8x.%-4x ", RecordFastIo->ProcessId, RecordFastIo->ThreadId );
  611. fprintf( File, "\t" );
  612. PrintFastIoType( RecordFastIo->Type, File );
  613. fprintf( File, "\t%08p", RecordFastIo->FileObject );
  614. fprintf( File, "\t%s", (RecordFastIo->Wait)?"T":"F" );
  615. fprintf( File, "\t%08x", RecordFastIo->Length );
  616. fprintf( File, "\t%016I64x ", RecordFastIo->FileOffset );
  617. fprintf( File, "\t%.*S", NameLength/sizeof(WCHAR), Name );
  618. fprintf( File, "\n" );
  619. }
  620. VOID
  621. FastIoScreenDump (
  622. IOTEST_DEVICE_TYPE DeviceType,
  623. ULONG SequenceNumber,
  624. PWCHAR Name,
  625. ULONG NameLength,
  626. PRECORD_FASTIO RecordFastIo
  627. )
  628. /*++
  629. Routine Name:
  630. FastIoScreenDump
  631. Routine Description:
  632. Prints a FastIo log record to the screen in the following order:
  633. SequenceNumber, StartTime, CompletionTime, Fast I/O Type, FileName,
  634. Length, Wait, ReturnStatus, FileName
  635. Arguments:
  636. SequenceNumber - the sequence number for this log record
  637. Name - the name of the file referenced by this Fast I/O operation
  638. NameLength - the length of name in bytes
  639. RecordIrp - the Irp record to print
  640. Return Value:
  641. None.
  642. --*/
  643. {
  644. SYSTEMTIME systemTime;
  645. FILETIME localTime;
  646. WCHAR time[TIME_BUFFER_LENGTH];
  647. switch (DeviceType) {
  648. case TOP_FILTER:
  649. printf("TOP F %08X", SequenceNumber);
  650. break;
  651. case BOTTOM_FILTER:
  652. printf("BOT F %08X", SequenceNumber);
  653. break;
  654. default:
  655. printf("UNK F %08X", SequenceNumber);
  656. break;
  657. }
  658. //
  659. // Convert start time
  660. //
  661. FileTimeToLocalFileTime( (FILETIME *)&(RecordFastIo->StartTime), &localTime );
  662. FileTimeToSystemTime( &localTime, &systemTime );
  663. if (FormatSystemTime( &systemTime, time, TIME_BUFFER_LENGTH )) {
  664. printf( "%-12S ", time );
  665. } else {
  666. printf( "%-12S ", TIME_ERROR );
  667. }
  668. printf( "%8x.%-4x ", RecordFastIo->ProcessId, RecordFastIo->ThreadId );
  669. PrintFastIoType( RecordFastIo->Type, NULL );
  670. printf( "%08p ", RecordFastIo->FileObject );
  671. printf( "%s ", (RecordFastIo->Wait)?"T":"F" );
  672. printf( "%08x ", RecordFastIo->Length );
  673. printf( "%016I64x ", RecordFastIo->FileOffset );
  674. printf( "%.*S", NameLength/sizeof(WCHAR), Name );
  675. printf ("\n" );
  676. }
  677. VOID
  678. FsFilterOperationFileDump (
  679. IOTEST_DEVICE_TYPE DeviceType,
  680. ULONG SequenceNumber,
  681. PWCHAR Name,
  682. ULONG NameLength,
  683. PRECORD_FS_FILTER_OPERATION RecordFsFilterOp,
  684. FILE *File
  685. )
  686. /*++
  687. Routine Name:
  688. FsFilterOperationFileDump
  689. Routine Description:
  690. Prints a FsFilterOperation log record to the specified file. The output is in a tab
  691. delimited format with the fields in the following order:
  692. SequenceNumber, OriginatingTime, CompletionTime, ProcessId, ThreadId,
  693. Operation, FileObject, ReturnStatus, FileName
  694. Arguments:
  695. SequenceNumber - the sequence number for this log record
  696. Name - the name of the file that this operation relates to
  697. NameLength - the length of Name in bytes
  698. RecordFsFilterOp - the FsFilter operation record to print
  699. File - the file to print to
  700. Return Value:
  701. None.
  702. --*/
  703. {
  704. FILETIME localTime;
  705. SYSTEMTIME systemTime;
  706. WCHAR time[TIME_BUFFER_LENGTH];
  707. switch (DeviceType) {
  708. case TOP_FILTER:
  709. fprintf(File, "TOP\tO\t%08X", SequenceNumber);
  710. break;
  711. case BOTTOM_FILTER:
  712. fprintf(File, "BOT\tO\t%08X", SequenceNumber);
  713. break;
  714. default:
  715. fprintf(File, "UNK\tO\t%08X", SequenceNumber);
  716. break;
  717. }
  718. //
  719. // Convert originating time
  720. //
  721. FileTimeToLocalFileTime( (FILETIME *)&(RecordFsFilterOp->OriginatingTime), &localTime );
  722. FileTimeToSystemTime( &localTime, &systemTime );
  723. if (FormatSystemTime( &systemTime, time, TIME_BUFFER_LENGTH )) {
  724. fprintf( File, "\t%-12S", time );
  725. } else {
  726. fprintf( File, "\t%-12S", TIME_ERROR );
  727. }
  728. //
  729. // Output the process and thread id
  730. //
  731. fprintf( File, "\t%8x.%-4x ", RecordFsFilterOp->ProcessId, RecordFsFilterOp->ThreadId );
  732. //
  733. // Output the FsFilter operation parameters
  734. //
  735. PrintFsFilterOperation( RecordFsFilterOp->FsFilterOperation, File );
  736. fprintf( File, "\t%08p", RecordFsFilterOp->FileObject );
  737. fprintf( File, "\t%.*S", NameLength/sizeof(WCHAR), Name );
  738. fprintf( File, "\n" );
  739. }
  740. VOID
  741. FsFilterOperationScreenDump (
  742. IOTEST_DEVICE_TYPE DeviceType,
  743. ULONG SequenceNumber,
  744. PWCHAR Name,
  745. ULONG NameLength,
  746. PRECORD_FS_FILTER_OPERATION RecordFsFilterOp
  747. )
  748. /*++
  749. Routine Name:
  750. FsFilterOperationScreenDump
  751. Routine Description:
  752. Prints a FsFilterOperation log record to the screen in the following order:
  753. SequenceNumber, OriginatingTime, CompletionTime, ProcessId, ThreadId,
  754. Operation, FileObject, ReturnStatus, FileName
  755. Arguments:
  756. SequenceNumber - the sequence number for this log record
  757. Name - the file name to which this Irp relates
  758. NameLength - the length of name in bytes
  759. RecordFsFilterOp - the FsFilterOperation record to print
  760. Return Value:
  761. None.
  762. --*/
  763. {
  764. FILETIME localTime;
  765. SYSTEMTIME systemTime;
  766. WCHAR time[TIME_BUFFER_LENGTH];
  767. switch (DeviceType) {
  768. case TOP_FILTER:
  769. printf("TOP O %08X", SequenceNumber);
  770. break;
  771. case BOTTOM_FILTER:
  772. printf("BOT O %08X", SequenceNumber);
  773. break;
  774. default:
  775. printf("UNK O %08X", SequenceNumber);
  776. break;
  777. }
  778. //
  779. // Convert originating time
  780. //
  781. FileTimeToLocalFileTime( (FILETIME *)&(RecordFsFilterOp->OriginatingTime), &localTime );
  782. FileTimeToSystemTime( &localTime, &systemTime );
  783. if (FormatSystemTime( &systemTime, time, TIME_BUFFER_LENGTH )) {
  784. printf( "%-12S ", time );
  785. } else {
  786. printf( "%-12S ", TIME_ERROR );
  787. }
  788. printf( "%8x.%-4x ", RecordFsFilterOp->ProcessId, RecordFsFilterOp->ThreadId );
  789. PrintFsFilterOperation( RecordFsFilterOp->FsFilterOperation, NULL );
  790. //
  791. // Print FsFilter operation specific values.
  792. //
  793. printf( "%08p ", RecordFsFilterOp->FileObject );
  794. printf( "%.*S", NameLength/sizeof(WCHAR),Name );
  795. printf( "\n" );
  796. }