USN_RECORD 所有值都正常,除了 TimeStamp = 0?

光环

使用下面的记录结构和函数,我可以高速获取文件名、参考号、版本等。(尝试使用 Delphi,Win 7)

问题是我没有得到文件 DateTime (TimeStamp.QuadPart = 0)

我已经添加了工作代码。为了测试,我将文件名(显示正确)和时间戳(显示为空)添加到 memo1

procedure Tform_main.Button1Click(Sender: TObject);
begin
   FillFileListFromUSNJournal('C') ;
end;


procedure Tform_main.FillFileListFromUSNJournal(pDrive:Char);
var
  ARootHandle: Cardinal;
  AMFTEnumBuff: Pointer;
begin
    ARootHandle := GetRootHandle(pDrive);
    if AllocMFTEnumBuffer(ARootHandle,AMFTEnumBuff) then
      EnumMFTEntries(ARootHandle, AMFTEnumBuff, MFTEnumCallback, @pDrive) ;
end;

function Tform_main.MFTEnumCallback(AUSN: PUSNRecord; Extra: Pointer): Boolean;
var
  AName,ProgressMsg: String;
  Drive: Char;
begin
  Drive  := PChar(Extra)^;
  Result := True;
  USNRecFromPointer(AUSN) ;
end;




{
  ** uMFT.pas
  ** zm
  ** created: 13.11.2010
  **
  *  Copyright (c) 2010, Zeljko Marjanovic <[email protected]>
  *  This code is licensed under MPL 1.1
  *  For details, see http://www.mozilla.org/MPL/MPL-1.1.html
  *
}

unit uMFT;

interface

uses
  Windows, SysUtils;

const
  FILE_DEVICE_FILE_SYSTEM = $00000009;
  METHOD_NEITHER = 3;
  METHOD_BUFFERED = 0;
  FILE_ANY_ACCESS = 0;
  FILE_SPECIAL_ACCESS = 0;
  FILE_READ_ACCESS = 1;
  FILE_WRITE_ACCESS = 2;

  ERROR_JOURNAL_DELETE_IN_PROGRESS = 1178;
  ERROR_JOURNAL_NOT_ACTIVE  = 1179;
  ERROR_JOURNAL_ENTRY_DELETED = 1181;

  FSCTL_GET_OBJECT_ID = $9009c;
  FSCTL_ENUM_USN_DATA = (FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or (44 shl 2) or METHOD_NEITHER;
  FSCTL_READ_USN_JOURNAL = (FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or (46 shl 2) or METHOD_NEITHER;
  FSCTL_CREATE_USN_JOURNAL = (FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or (57 shl 2) or METHOD_NEITHER;
  FSCTL_QUERY_USN_JOURNAL = (FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or (61 shl 2) or METHOD_BUFFERED;
  FSCTL_DELETE_USN_JOURNAL = (FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or (62 shl 2) or METHOD_BUFFERED;

  USN_PAGE_SIZE = $1000;
  USN_REASON_DATA_OVERWRITE = $00000001;
  USN_REASON_DATA_EXTEND = $00000002;
  USN_REASON_DATA_TRUNCATION = $00000004;
  USN_REASON_NAMED_DATA_OVERWRITE = $00000010;
  USN_REASON_NAMED_DATA_EXTEND = $00000020;
  USN_REASON_NAMED_DATA_TRUNCATION = $00000040;
  USN_REASON_FILE_CREATE = $00000100;
  USN_REASON_FILE_DELETE = $00000200;
  USN_REASON_EA_CHANGE = $00000400;
  USN_REASON_SECURITY_CHANGE = $00000800;
  USN_REASON_RENAME_OLD_NAME = $00001000;
  USN_REASON_RENAME_NEW_NAME = $00002000;
  USN_REASON_INDEXABLE_CHANGE = $00004000;
  USN_REASON_BASIC_INFO_CHANGE = $00008000;
  USN_REASON_HARD_LINK_CHANGE = $00010000;
  USN_REASON_COMPRESSION_CHANGE = $00020000;
  USN_REASON_ENCRYPTION_CHANGE = $00040000;
  USN_REASON_OBJECT_ID_CHANGE = $00080000;
  USN_REASON_REPARSE_POINT_CHANGE = $00100000;
  USN_REASON_STREAM_CHANGE = $00200000;
  USN_REASON_CLOSE = $80000000;

  USN_DELETE_FLAG_DELETE = $00000001;
  USN_DELETE_FLAG_NOTIFY = $00000002;
  USN_DELETE_VALID_FLAGS = $00000003;

  USNREC_MAJVER_OFFSET = 4;
  USNREC_MINVER_OFFSET = 8; 
  USNREC_FR_OFFSET = 8;
  USNREC_PFR_OFFSET = 16;
  USNREC_USN_OFFSET = 24;
  USNREC_TIMESTAMP_OFFSET = 32;
  USNREC_REASON_OFFSET = 40;
  USNREC_SINFO_OFFSET = 44;
  USNREC_SECID_OFFSET = 48;
  USNREC_FA_OFFSET = 52;
  USNREC_FNL_OFFSET = 56;
  USNREC_FN_OFFSET = 58;

  IOCTL_DISK_BASE = $00000007;
  IOCTL_DISK_GET_PARTITION_INFO = (IOCTL_DISK_BASE shl 16) or (FILE_READ_ACCESS shl 14) or ($0001 shl 2) or METHOD_BUFFERED;
  PARTITION_IFS = $07; 

type
  USN_JOURNAL_DATA = record
    UsnJournalID: UInt64;
    FirstUsn: Int64;
    NextUsn: Int64;
    LowestValidUsn: Int64;
    MaxUsn: Int64;
    MaximumSize: UInt64;
    AllocationDelta: UInt64;
  end;
  TUSNJournalData = USN_JOURNAL_DATA;
  PUSNJournalData = ^TUSNJournalData;

  MFT_ENUM_DATA = record
    StartFileReferenceNumber: UInt64;
    LowUsn: Int64;
    HighUsn: Int64;
  end;
  TMFTEnumData = MFT_ENUM_DATA;
  PMFTEnumData = ^TMFTEnumData;

  CREATE_USN_JOURNAL_DATA = record
    MaximumSize: UInt64;
    AllocationDelta: UInt64;
  end;
  TCreateUSNJournalData = CREATE_USN_JOURNAL_DATA;
  PCreateUSNJournalData = ^TCreateUSNJournalData;

  USN_RECORD = record
    RecordLength: Cardinal;
    MajorVersion: Word;
    MinorVersion: Word;
    FileReferenceNumber: UInt64;
    ParentFileReferenceNumber: UInt64;
    Usn: Int64;
    TimeStamp: LARGE_INTEGER;
    Reason: Cardinal;
    SourceInfo: Cardinal;
    SecurityId: Cardinal;
    FileAttributes: Cardinal;
    FileNameLength: Word;
    FileNameOffset: Word;
    FileName: PWideChar;//   PWChar; [ss]
  end;
  TUSNRecord = USN_RECORD;
  PUSNRecord = ^TUSNRecord;

  TMFTEnumCallback = function(AUSN: PUSNRecord; Extra: Pointer = nil): Boolean of object;
  PUInt64 = ^UInt64;
  EMFTException = class(Exception);

  TUSNRecChangeType = (uceNew, uceDeleted, uceRenamed);


function USNRecFromPointer(const P: Pointer): TUSNRecord;
function GetRootHandle(const Drive: Char): Cardinal;
function CreateUSNJournal(ARootHandle: Cardinal; MaxSize, AllocationDelta: UInt64): Boolean;
function AllocMFTEnumBuffer(ARootHandle: Cardinal; var AMFTEnumBuff: Pointer): boolean;
function EnumMFTEntries(ARootHandle: Cardinal; AMFTEnumBuff: Pointer; EnumCallBack: TMFTEnumCallback;Extra: Pointer = nil): Boolean;

implementation
uses main ;

function USNRecFromPointer(const P: Pointer): TUSNRecord;
var
  PA: PAnsiChar;
begin
  PA := PAnsiChar(P);
  Result.RecordLength := PInteger(PA)^ ;
  Result.MajorVersion := PInteger(PA + USNREC_MAJVER_OFFSET)^;
  Result.MinorVersion := PInteger(PA + USNREC_MINVER_OFFSET)^;
  Result.FileReferenceNumber := PUInt64(PA + USNREC_FR_OFFSET)^;
  Result.ParentFileReferenceNumber := PUInt64(PA + USNREC_PFR_OFFSET)^;
  Result.USN := PInt64(PA + USNREC_USN_OFFSET)^;
  Result.TimeStamp.QuadPart := PInt64(PA + USNREC_TIMESTAMP_OFFSET)^;
  Result.Reason := PCardinal(PA + USNREC_REASON_OFFSET)^;
  Result.SourceInfo := PCardinal(PA + USNREC_SINFO_OFFSET)^;
  Result.SecurityId := PCardinal(PA + USNREc_SECID_OFFSET)^;
  Result.FileAttributes := PCardinal(PA + USNREC_FA_OFFSET)^;
  Result.FileNameLength := PWord(PA + USNREC_FNL_OFFSET)^;
  Result.FileNameOffset := PWord(PA + USNREC_FN_OFFSET)^;
  Result.FileName :=   PWideChar(Integer(P) + Result.FileNameOffset);
  if form_Main.memo1.lines.Count<100 then
    form_Main.memo1.lines.add(Result.FileName+' '+InttoStr(Result.TimeStamp.QuadPart)) ;

end;


// this requires admin privileges
function GetRootHandle(const Drive: Char): Cardinal;
var
  W: WideString;
  RootHandle: Cardinal;
  Flags: Cardinal;
  Access: Cardinal;
begin
  Flags := 0;
  W := '\\.\' + Drive + ':';
  Access := GENERIC_READ;
  RootHandle := CreateFileW(PWChar(W), Access, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, Flags, 0);
  if RootHandle <> INVALID_HANDLE_VALUE then
    Result := RootHandle
  else
    raise EMFTException.Create(SysErrorMessage(GetLastError));
end;

function CreateUSNJournal(ARootHandle: Cardinal; MaxSize, AllocationDelta: UInt64): Boolean;
var
  BytesRet: Cardinal;
  CreateData: TCreateUSNJournalData;
begin
  CreateData.MaximumSize := MaxSize;
  CreateData.AllocationDelta := AllocationDelta;
  Result := DeviceIoControl(ARootHandle, FSCTL_CREATE_USN_JOURNAL, @CreateData, sizeof(TCreateUSNJournalData), nil, 0, BytesRet, nil);
end;


function AllocMFTEnumBuffer(ARootHandle: Cardinal; var AMFTEnumBuff: Pointer): boolean;
var
  USNBuf: TUSNJournalData;
  ErrCode,BytesRet: Cardinal;
  EnumBuf: PMFTEnumData;
begin
  result:=false;
  if DeviceIoControl(ARootHandle, FSCTL_QUERY_USN_JOURNAL, nil, 0, @USNBuf, sizeof(TUSNJournalData), BytesRet, nil) then
  begin
    GetMem(EnumBuf, sizeof(TMFTEnumData));
    EnumBuf.StartFileReferenceNumber := 0;
    EnumBuf.LowUsn := 0;
    EnumBuf.HighUsn := USNBuf.NextUsn;
    AMFTEnumBuff := EnumBuf;
    result:=true;
    exit;
  end;

  ErrCode:=GetLastError;
  if ErrCode = ERROR_JOURNAL_NOT_ACTIVE then
  begin
    // journal does not exist, create a new1 one
    if CreateUSNJournal(ARootHandle, $10000000, $100000) then
    begin
      if DeviceIoControl(ARootHandle, FSCTL_QUERY_USN_JOURNAL, nil, 0, @USNBuf, sizeof(TUSNJournalData), BytesRet, nil) then
      begin
        GetMem(EnumBuf, sizeof(TMFTEnumData));
        EnumBuf.StartFileReferenceNumber := 0;
        EnumBuf.LowUsn := 0;
        EnumBuf.HighUsn := USNBuf.NextUsn;
        AMFTEnumBuff := EnumBuf;
        result:=true;
        exit;
      end;
      ErrCode:=GetLastError;
    end
    else
    begin
      ErrCode:=GetLastError;
    end;
  end;
end;

//v main function
function EnumMFTEntries(ARootHandle: Cardinal; AMFTEnumBuff: Pointer; EnumCallBack: TMFTEnumCallback;Extra: Pointer): Boolean;
const
  BUF_SIZE = sizeof(UInt64) + $10000;
var
  P: Pointer;
  MFTEnum: Pointer;
  BytesRet: Cardinal;
  PUSN: PUSNRecord;
//  TUSN: TUSNRecord;
begin
  Result := False;
  if (ARootHandle = INVALID_HANDLE_VALUE) or (AMFTEnumBuff = nil) then
    Exit;

  MFTEnum := AMFTEnumBuff;
  GetMem(P, BUF_SIZE);
  try
    ZeroMemory(P, BUF_SIZE);
    while DeviceIoControl(ARootHandle, FSCTL_ENUM_USN_DATA, MFTEnum, sizeof(TMFTEnumData), P, BUF_SIZE, BytesRet, nil) do
    begin
      PUSN := PUSNRecord(Integer(P) + sizeof(Int64));

      while BytesRet > 60 do
      begin
        if (not EnumCallBack(PUSN, Extra)) then
          Exit;
        if PUSN.RecordLength > 0 then
          Dec(BytesRet, PUSN.RecordLength)
        else
          break;
        PUSN := PUSNRecord(Cardinal(PUSN) + PUSN.RecordLength);
        if form_Main.memo1.lines.Count>100 then
          break ;
      end;
      CopyMemory(MFTEnum, P, sizeof(Int64));
    end;
    Result := True;

  finally
    FreeMem(P);
  end;
end;
//^ main function


end.
塞尔塔克·阿库兹

时间戳出现 0,因为FSCTL_QUERY_USN_JOURNAL没有填充该信息。这在控制代码的文档中没有明确说明,我找不到任何官方文档。但有些地方提到 aUSN_RECORD只是部分人口。像这个链接是从给定USN_RECORD_V2文件,虽然我也不知道什么FSCTL前者链接在谈论。

无论如何,这与我能找到的所有示例(包括 Microsoft自己的. 下面是这段代码的 Delphi 翻译。使用FSCTL_QUERY_USN_JOURNAL控制码检索的 USN 信息用于DeviceIoControl调用FSCTL_READ_USN_JOURNAL用于检索详细信息。

直接翻译很少有例外,一个是文件名的检索,我不明白C++代码是怎么做的。另一个是打印时间戳,因为这是您的要求。此外,您需要为卷句柄或内存等资源添加错误检查和保护块。

该代码使用您在问题中包含的辅助单元中的声明。我检查了我在这里找到的第 3 方免费软件实用程序的时间戳,它们是一致的。

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  windows,
  uMFT;

type
  USN = LONGLONG;
const
  BUF_LEN = 4096;
var
  hVol: THandle;
  JournalData: TUSNJournalData;
  dwBytes: DWORD;
  dwRetBytes: DWORD;
  ReadData: TReadUSNJournalData;
  i: Integer;
  Buffer: array [0..BUF_LEN - 1] of Byte;
  UsnRecord: PUSNRecord;
  FileName: PWideChar;
  SysTime: TSystemTime;
begin
  hVol := CreateFile( '\\.\c:', GENERIC_READ,
      FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);

  if hVol = INVALID_HANDLE_VALUE then begin
    Writeln(Format('CreateFile failed (%d)', [GetLastError]));
    Exit;
  end;

  if not DeviceIoControl(hVol, FSCTL_QUERY_USN_JOURNAL, nil, 0, @JournalData,
      SizeOf(JournalData), dwBytes, nil) then begin
    Writeln(Format('Query journal failed (%d)', [GetLastError]));
    Exit;
  end;

  ZeroMemory(@ReadData, SizeOf(ReadData));
  ReadData.ReasonMask := $FFFFFFFF;
  ReadData.UsnJournalID := JournalData.UsnJournalID;

  Writeln(Format('Journal ID: %x', [JournalData.UsnJournalID]));
  Writeln(Format('FirstUsn: %x' + sLineBreak, [JournalData.FirstUsn]));

  for i := 0 to 10 do begin
    FillChar(Buffer, BUF_LEN, 0);

    if not DeviceIoControl(hVol, FSCTL_READ_USN_JOURNAL, @ReadData,
        SizeOf(ReadData), @Buffer, BUF_LEN, dwBytes, nil) then begin
      Writeln(Format('Read journal failed (%d)', [GetLastError]));
      Exit;
    end;
    dwRetBytes := dwBytes - SizeOf(USN);

    // Find the first record
    UsnRecord := PUsnRecord(NativeInt(@Buffer) + SizeOf(USN));

    Writeln('****************************************');

    while dwRetBytes > 0 do begin

      Writeln(Format('USN: %x', [UsnRecord.Usn]));

      GetMem(FileName, UsnRecord.FileNameLength + SizeOf(Char));
      Move(Pointer(NativeInt(UsnRecord) + UsnRecord.FileNameOffset)^, FileName^,
          UsnRecord.FileNameLength);
      FileName[UsnRecord.FileNameLength div 2] := #0;
      Writeln(Format('File name: %s', [FileName]));
      FreeMem(FileName);

      FileTimeToSystemTime(@UsnRecord.TimeStamp, SysTime);
      Writeln(Format('Time stamp: %s', [DateTimeToStr(SystemTimeToDateTime(SysTime))]));
      Writeln(Format('Reason: %x', [UsnRecord.Reason]));
      Writeln;

      dwRetBytes := dwRetBytes - UsnRecord.RecordLength;

      // Find the next record
      UsnRecord := PUsnRecord(NativeInt(UsnRecord) + UsnRecord.RecordLength);
    end;
  end;
  CloseHandle(hVol);

  Writeln;
  Writeln('End of sample');
  Readln;
end.

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

我完全删除了libsqlite3-0,所有必不可少的东西也都删除了。如何还原ubuntu?

来自分类Dev

TableBatchOperation是否保证所有实体都具有相同的Timestamp字段值?

来自分类Dev

我的所有输出都收到0

来自分类Dev

0-1之间的值的所有组合都等于R中的1

来自分类Dev

并非此数组中的所有值都设置为0吗?

来自分类Dev

为什么geom_histogram从负bin下限开始,即使所有值都> 0?

来自分类Dev

确保数组的所有值都编码为1和-1,而不是1和0

来自分类Dev

0-1之间的值的所有组合都等于R中的1

来自分类Dev

如何使每列中的所有重复值都填充为“0”

来自分类Dev

C ++:int array [a] [b] [c] = {0}; 不能将所有值都设置为0。那条指令是错误的还是我的输出函数有问题?

来自分类Dev

更新统一的数据纹理时,所有点都变为0,0

来自分类Dev

如果R的所有值均为0,则填充0

来自分类Dev

ORA-01858:尝试插入timestamp(0)列时出错

来自分类Dev

使用UNIX_TIMESTAMP的mySQL查询返回0个结果

来自分类Dev

SQLAlchemy MySQL Timestamp列值

来自分类Dev

SQL ORDER BY Timestamp,相同的值

来自分类Dev

是所有数据成员都初始化为0还是由自动调用的构造函数为其分配了随机值?

来自分类Dev

正则表达式将替换所有大括号,除了大小写“ {0}”

来自分类Dev

为什么这个简单的井字游戏程序会“忘记”数组中位置[0] [0]的值,但对其他所有东西都可以正常工作?

来自分类Dev

Auth0表示所有参数都正确旁边的连接无效

来自分类Dev

检查是否所有 JComboBoxes 都选择了任何索引(索引 0 除外)

来自分类Dev

为什么不将C ++结构初始化为`= {0}`并将其所有成员都设置为0?

来自分类Dev

Pandas DataFrame用0以外的所有值替换1

来自分类Dev

从所有值均为0的SQL输出中删除列

来自分类Dev

从数组中删除所有值 => 0 并将其反转

来自分类Dev

为什么所有的速度值都是0?

来自分类Dev

在Elasticsearch响应中获取@timestamp值

来自分类Dev

DATETIME和TIMESTAMP长度/值错误

来自分类Dev

用CURRENT_TIMESTAMP值插入SELECT

Related 相关文章

  1. 1

    我完全删除了libsqlite3-0,所有必不可少的东西也都删除了。如何还原ubuntu?

  2. 2

    TableBatchOperation是否保证所有实体都具有相同的Timestamp字段值?

  3. 3

    我的所有输出都收到0

  4. 4

    0-1之间的值的所有组合都等于R中的1

  5. 5

    并非此数组中的所有值都设置为0吗?

  6. 6

    为什么geom_histogram从负bin下限开始,即使所有值都> 0?

  7. 7

    确保数组的所有值都编码为1和-1,而不是1和0

  8. 8

    0-1之间的值的所有组合都等于R中的1

  9. 9

    如何使每列中的所有重复值都填充为“0”

  10. 10

    C ++:int array [a] [b] [c] = {0}; 不能将所有值都设置为0。那条指令是错误的还是我的输出函数有问题?

  11. 11

    更新统一的数据纹理时,所有点都变为0,0

  12. 12

    如果R的所有值均为0,则填充0

  13. 13

    ORA-01858:尝试插入timestamp(0)列时出错

  14. 14

    使用UNIX_TIMESTAMP的mySQL查询返回0个结果

  15. 15

    SQLAlchemy MySQL Timestamp列值

  16. 16

    SQL ORDER BY Timestamp,相同的值

  17. 17

    是所有数据成员都初始化为0还是由自动调用的构造函数为其分配了随机值?

  18. 18

    正则表达式将替换所有大括号,除了大小写“ {0}”

  19. 19

    为什么这个简单的井字游戏程序会“忘记”数组中位置[0] [0]的值,但对其他所有东西都可以正常工作?

  20. 20

    Auth0表示所有参数都正确旁边的连接无效

  21. 21

    检查是否所有 JComboBoxes 都选择了任何索引(索引 0 除外)

  22. 22

    为什么不将C ++结构初始化为`= {0}`并将其所有成员都设置为0?

  23. 23

    Pandas DataFrame用0以外的所有值替换1

  24. 24

    从所有值均为0的SQL输出中删除列

  25. 25

    从数组中删除所有值 => 0 并将其反转

  26. 26

    为什么所有的速度值都是0?

  27. 27

    在Elasticsearch响应中获取@timestamp值

  28. 28

    DATETIME和TIMESTAMP长度/值错误

  29. 29

    用CURRENT_TIMESTAMP值插入SELECT

热门标签

归档