JNA 访问 NTFS USN (win32)。如何从内存对象获取数据?
JNA Access NTFS USN (win32). How to get data form Memory object?
enum 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;
link:
- DeviceIoControl FSCTL_ENUM_USN_DATA
- input MFT_ENUM_DATA_V0 Structure
- output memory --> USN_RECORD_V2 Structure
从内存中获取 USN_RECORD_V2。非常感谢。
欢迎使用 Whosebug!
您链接到的文档说此函数的内存输出缓冲区是:
A pointer to the output buffer that receives a USN followed by zero or
more USN_RECORD_V2 or USN_RECORD_V3 structures. The USN is a DWORDLONG value that represents the USN following the last record in the buffer.
您正在尝试读取从偏移量 0 开始的内存,但前 8 个字节是您可以在以后的调用中使用的 USN。
您将向现有代码添加 8 个字节以获得正确的值;然而,一种更具可读性的方法是将 Structure
映射到所有 USN_RECORD_V2
字段及其字节值,以及 read()
来自 memory.share(8)
的结构。
enum 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;
link:
- DeviceIoControl FSCTL_ENUM_USN_DATA
- input MFT_ENUM_DATA_V0 Structure
- output memory --> USN_RECORD_V2 Structure
从内存中获取 USN_RECORD_V2。非常感谢。
欢迎使用 Whosebug!
您链接到的文档说此函数的内存输出缓冲区是:
A pointer to the output buffer that receives a USN followed by zero or more USN_RECORD_V2 or USN_RECORD_V3 structures. The USN is a DWORDLONG value that represents the USN following the last record in the buffer.
您正在尝试读取从偏移量 0 开始的内存,但前 8 个字节是您可以在以后的调用中使用的 USN。
您将向现有代码添加 8 个字节以获得正确的值;然而,一种更具可读性的方法是将 Structure
映射到所有 USN_RECORD_V2
字段及其字节值,以及 read()
来自 memory.share(8)
的结构。