阅读USN期刊会给出错误1784

时间:2018-05-03 08:10:24

标签: java jna journal usn

我想使用Java JNA库阅读Windows USN(文件系统)日志。我可以打开驱动器的句柄并查询日志信息。 但是当我尝试读取日志数据(FSCTL_READ_USN_JOURNAL)时,我收到错误1784(提供的用户缓冲区对请求的操作无效)。 Windows 7/64,JNA版本4.5.1,java 8/32。 我使用C ++尝试了同样的方法,它运行得很好。

import java.io.IOException;
import java.util.List;

import com.sun.jna.Memory;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.Kernel32Util;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.platform.win32.Winioctl;
import com.sun.jna.platform.win32.WinioctlUtil;
import com.sun.jna.ptr.IntByReference;

public class NtfsUsnJournal2
{
  public static void main(String[] args)
  {
    try
    {
      WinNT.HANDLE hDevice = openDisk('C');
      try
      {
    USN_JOURNAL_INFO_V0 journalInfo = queryJournal(hDevice);
    System.out.println(journalInfo);
    //
    Memory buffer = new Memory(4096);
    buffer.clear();
    IntByReference numBytesReturned = new IntByReference(0);
    READ_USN_JOURNAL_DATA_V0 journalData = new READ_USN_JOURNAL_DATA_V0();
    journalData.clear();
    journalData.ReasonMask = 0xFFFFFFFF;
    journalData.UsnJournalID = journalInfo.UsnJournalID;
    journalData.write();
    System.out.println(journalData);
    boolean ok = Kernel32.INSTANCE.DeviceIoControl(hDevice,
      FSCTL_READ_USN_JOURNAL, // = 590011
      journalData.getPointer(),journalData.size(),
      buffer.getPointer(0),(int)buffer.size(),
      numBytesReturned,null);
    if( !ok )
    {
      System.out.println("ERROR "+Kernel32.INSTANCE.GetLastError()+" "+Kernel32Util.getLastErrorMessage());
      return;
    }
    System.out.println(numBytesReturned.getValue());
    System.out.println(buffer.getInt(8));
      }
      finally
      {
    Kernel32.INSTANCE.CloseHandle(hDevice);
      }
    }
    catch( Exception e )
    {
      e.printStackTrace();
    }
  }

  static USN_JOURNAL_INFO_V0 queryJournal(WinNT.HANDLE hDevice) throws IOException
  {
    USN_JOURNAL_INFO_V0 journalInfo = new USN_JOURNAL_INFO_V0();
    journalInfo.clear();
    //
    IntByReference numBytesReturned = new IntByReference(0);
    boolean ok = Kernel32.INSTANCE.DeviceIoControl(hDevice,
      FSCTL_QUERY_USN_JOURNAL,null,0,
      journalInfo.getPointer(),journalInfo.size(),
      numBytesReturned,null);
    if( !ok )
    {
      throw new IOException(
    "ERROR "+Kernel32.INSTANCE.GetLastError()+": "+Kernel32Util.getLastErrorMessage());
    }
    journalInfo.read();
    return journalInfo;
  }

  static WinNT.HANDLE openDisk(char drive)
  {
    return Kernel32.INSTANCE.CreateFile("\\\\.\\"+drive+":",
      WinNT.GENERIC_READ|WinNT.GENERIC_WRITE,
      WinNT.FILE_SHARE_READ|WinNT.FILE_SHARE_WRITE,null,WinNT.OPEN_EXISTING,0,null);
  }

  static public class USN_JOURNAL_INFO_V0 extends Structure
  {
    public static final List<String> FIELDS = createFieldsOrder(
      "UsnJournalID","FirstUsn","NextUsn","LowestValidUsn","MaxUsn","MaximumSize","AllocationDelta");
    protected List<String> getFieldOrder() { return FIELDS; }
    //
    public long UsnJournalID;
    public long FirstUsn;
    public long NextUsn;
    public long LowestValidUsn;
    public long MaxUsn;
    public long MaximumSize;
    public long AllocationDelta;
  }

  static public class READ_USN_JOURNAL_DATA_V0 extends Structure
  {
    public static final List<String> FIELDS = createFieldsOrder(
      "StartUsn","ReasonMask","ReturnOnlyOnClose","Timeout","BytesToWaitFor","UsnJournalID");
    protected List<String> getFieldOrder() { return FIELDS; }
    //
    public long StartUsn;
    public int  ReasonMask;
    public int  ReturnOnlyOnClose;
    public long Timeout;
    public long BytesToWaitFor;
    public long UsnJournalID;
  }

  static final int FSCTL_QUERY_USN_JOURNAL =
    WinioctlUtil.CTL_CODE(Winioctl.FILE_DEVICE_FILE_SYSTEM, 61,
    Winioctl.METHOD_BUFFERED,Winioctl.FILE_ANY_ACCESS);

  static final int FSCTL_READ_USN_JOURNAL =
    WinioctlUtil.CTL_CODE(Winioctl.FILE_DEVICE_FILE_SYSTEM, 46,
    Winioctl.METHOD_NEITHER,Winioctl.FILE_ANY_ACCESS);
}

1 个答案:

答案 0 :(得分:0)

内存扩展了Pointer,不需要getPointer

boolean ok = Kernel32.INSTANCE.DeviceIoControl(hDevice,
         FSCTL_READ_USN_JOURNAL, // = 590011
         journalData.getPointer(),journalData.size(),
         buffer,(int)buffer.size(),
         numBytesReturned,null);