我正在尝试通过 NTFS 文件 ID 获取文件 HANDLE。
Memory p = new Memory(128);
Kernel32.INSTANCE.GetFileInformationByHandleEx(hFile, WinBase.FileIdInfo, p, new DWORD(p.size()));
FILE_ID_INFO fii = new FILE_ID_INFO(p);
从 FILE_ID_INFO 我可以得到 VolumeSerialNumber 和 FileId.Identifier
Kernel32.INSTANCE.CreateFile(path, FILE_READ_ATTRIBUTES, 1 | 2 | 4, null, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, null)
HANDLE OpenFileById(HANDLE hVolumeHint, Structure lpFileId, int dwDesiredAccess, int dwShareMode, SECURITY_ATTRIBUTES lpSecurityAttributes, int dwFlagsAndAttributes);
所需结构
@FieldOrder({"dwSize", "Type", "Id"})
public static class FILE_ID_DESCRIPTOR extends Structure {
public UINT dwSize;
public int Type;
public DUMMYUNIONNAME Id;
@FieldOrder({"FileId", "ObjectId", "ExtendedFileId"})
public static class DUMMYUNIONNAME extends Union {
public long FileId;
public GUID ObjectId;
public FILE_ID_128 ExtendedFileId;
public DUMMYUNIONNAME() {
super();
}
public DUMMYUNIONNAME(long Id) {
this.FileId = Id;
write();
}
}
public static UINT sizeOf()
{
return new UINT(Native.getNativeSize(FILE_ID_DESCRIPTOR.class, null));
}
public FILE_ID_DESCRIPTOR() {
super();
}
public FILE_ID_DESCRIPTOR(Pointer memory) {
super(memory);
read();
}
public FILE_ID_DESCRIPTOR(UINT dwSize, int type,
DUMMYUNIONNAME id) {
this.dwSize = dwSize;
this.Type = type;
this.Id = id;
write();
}
}
用法
FILE_ID_DESCRIPTOR fileIdDesc = new FILE_ID_DESCRIPTOR(FILE_ID_DESCRIPTOR.sizeOf(), 0, new DUMMYUNIONNAME(fii.FileId.Identifier));
HANDLE handle = Kernel32.INSTANCE.OpenFileById(hVolume, fileIdDesc, FILE_READ_ATTRIBUTES, 1 | 2 | 4, null, FILE_FLAG_BACKUP_SEMANTICS);
当我执行后 Kernel32.INSTANCE.GetLastError(); 它给了我 - 87 Invalid Parameter.
我已经更改 FILE_ID_DESCRIPTOR 以接受 long 而不是 byte[],以及其他更改 - 但每次 - 同样的错误。
类似的代码在 C# 中成功运行,但我也需要它在 Java 中运行。
请指教
你错误地初始化了你的
FILE_ID_DESCRIPTOR
值:
new FILE_ID_DESCRIPTOR(
FILE_ID_DESCRIPTOR.sizeOf(),
0,
new DUMMYUNIONNAME(fii.FileId.Identifier)
);
您将
Type
参数传递为 0,表示您想要联合中的 long FileId
。
但是当
long
的值是 16 字节数组时,您已将虚拟联合构造函数硬编码为将值分配给 8 字节 fii.FileId.Identifier
成员。
您在评论中指出:
这是你在帖子中看到的 - 是我尝试的最后一个版本。 DUMMYUNIONNAME 是结构、指针,没有 DUMMYUNIONNAME,只有 Id 等。我尝试从 4 位到 512 位 - 错误代码从未改变。
只有一个正确答案,它是 16 个字节(128 位)。但是,如果您传递 0 的
Type
,它只会读取您的 fii.FileId.Identifier
的前 8 个字节(64 位)。
您很可能想通过设置 2 的
ExtendedFileId
来设置/读取联合中的 Type
字段。
您的代码还有其他几个问题不是错误原因:
FILE_ID_INFO
时,通过为 p
提供 128 个字节来过度分配内存。您还没有显示它的映射,但它是一个 8 字节的 long
后跟一个包装 16 字节数组的结构,因此您只需要 24 个字节。sizeOf()
。 JNA 的 Structure
有一个 size()
方法可以完全满足您的要求。或者你可以只使用你的知识,在这种情况下大小总是 24.dwSize
的FILE_ID_DESCRIPTOR
场是一个DWORD
而不是一个UINT
。因为它们都是 32 位值,所以没有区别。由于 Java 没有带符号整数的概念,您不妨在这里简化并传递一个int
。Union
类,你应该完全实现它,包括覆盖联合中的 read()
以读取适当的本机值。在你的情况下,你只写它一次使用,所以你可以跳过联合的复杂性并直接分配你想要的内部字段。如果这是最大的尺寸值(FILE_ID_128
),您可以直接分配它。如果它的大小值较小(long
,那么您可以添加填充以确保整个结构大小为 24 字节)。