JNA 访问 NTFS USN (win32)。如何从内存对象中获取数据?

Posted

技术标签:

【中文标题】JNA 访问 NTFS USN (win32)。如何从内存对象中获取数据?【英文标题】:JNA Access NTFS USN (win32). How to get data form Memory object? 【发布时间】:2018-08-29 11:16:41 【问题描述】:

从内存中枚举 USN 数据,结果数据不正确。我不知道该怎么办

public static void main(String[] args) throws IOException 
    // get c volume handle
    WinNT.HANDLE handle = Kernel32.INSTANCE.CreateFile("\\\\.\\C:",WinNT.GENERIC_READ|WinNT.GENERIC_WRITE,
        WinNT.FILE_SHARE_READ|WinNT.FILE_SHARE_WRITE,null,WinNT.OPEN_EXISTING,0,null);

    IntByReference bytesByReturned = new IntByReference();
    // output to memory
    Memory memory = new Memory(Integer.MAX_VALUE);
    memory.clear();

    // input query args
    MFT_ENUM_DATA med = new MFT_ENUM_DATA();
    med.StartFileReferenceNumber = 0;
    med.LowUsn = 0;
    med.HighUsn = 99999999;
    med.write();

    int FSCTL_ENUM_USN_DATA = 0x000900B3;

    // access device, get usn data to memory buffer object
    boolean ok = Kernel32.INSTANCE.DeviceIoControl(handle,FSCTL_ENUM_USN_DATA, med.getPointer(),
        med.size(), memory, (int)memory.size(), bytesByReturned, null);

    if(ok) 
        // that's wrong!!! , get the wrong data!
        int RecordLength = memory.getInt(0);
        short MajorVersion = memory.getShort(4);
        short MinorVersion = memory.getShort(6);
        long FileReferenceNumber = memory.getLong(8);

        // error value
        System.out.println("RecordLength:\t"+RecordLength);
        System.out.println("MajorVersion:\t"+MajorVersion);
        System.out.println("MinorVersion:\t"+MinorVersion);
        System.out.println("FileReferenceNumber:\t"+FileReferenceNumber);
        // ...
    else 
        System.out.println("ERROR "+Kernel32.INSTANCE.GetLastError()+" "+ Kernel32Util.getLastErrorMessage());

        throw new IOException("DeviceIoControl() returned false", new Win32Exception(Kernel32.INSTANCE.GetLastError()));

    


static public class MFT_ENUM_DATA extends Structure 
    public long StartFileReferenceNumber;
    public long LowUsn;
    public long HighUsn;

    @Override
    protected List<String> getFieldOrder() 
        List<String> order = new ArrayList<>();
        order.add("StartFileReferenceNumber");
        order.add("LowUsn");
        order.add("HighUsn");
        return order;
    

我无法从内存缓冲区对象中获取结构数据,我该怎么办?

typedef struct USN_RECORD_V2 
  DWORD         RecordLength;
  WORD          MajorVersion;
  WORD          MinorVersion;
  DWORDLONG     FileReferenceNumber;
  DWORDLONG     ParentFileReferenceNumber;
  USN           Usn;
  LARGE_INTEGER TimeStamp;
  DWORD         Reason;
  DWORD         SourceInfo;
  DWORD         SecurityId;
  DWORD         FileAttributes;
  WORD          FileNameLength;
  WORD          FileNameOffset;
  WCHAR         FileName[1];
  *PUSN_RECORD_V2;

链接: - DeviceIoControl FSCTL_ENUM_USN_DATA - input MFT_ENUM_DATA_V0 Structure - output memory --> USN_RECORD_V2 Structure

从内存中获取 USN_RECORD_V2。非常感谢。

【问题讨论】:

【参考方案1】:

欢迎来到 ***!

你链接到的文档说你的这个函数的内存输出缓冲区是:

一个指向输出缓冲区的指针,它接收一个 USN 后跟零或 更多 USN_RECORD_V2 或 USN_RECORD_V3 结构。 USN 是一个 DWORDLONG 值,表示缓冲区中最后一条记录之后的 USN。

您正在尝试从偏移量 0 开始读取内存,但前 8 个字节是您可以在未来调用中使用的 USN。

您将在现有代码中添加 8 个字节以获得正确的值;然而,一个更易读的方法是映射一个Structure 与所有USN_RECORD_V2 字段及其字节值,以及read() 来自memory.share(8) 的结构。

【讨论】:

你说得对,第一次谢谢你。非常感谢

以上是关于JNA 访问 NTFS USN (win32)。如何从内存对象中获取数据?的主要内容,如果未能解决你的问题,请参考以下文章

处理 USN 期刊尺寸全箱

JMeter - Webdriver 错误:java.lang.NoClassDefFoundError: com/sun/jna/platform/win32/Kernel32

why "Everything" is so fast?

使用 JNA SetForeGroundWindow

USN日志是默认禁用的吗?

找不到com.sun.jna.platform.win32.COM.WbemcliUtil类