标题:使用VB访问USN journal 解决办法偿试,寻求USN (int64)结构体类型声明
取消只看楼主
q573297953
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2016-8-28
结帖率:0
已结贴  问题点数:20 回复次数:0 
使用VB访问USN journal 解决办法偿试,寻求USN (int64)结构体类型声明
Private Declare Sub PutMem1 Lib "msvbvm60" (ByVal Ptr As Long, ByVal NewVal As Byte) '向地址存1字节
Private Declare Sub PutMem2 Lib "msvbvm60" (ByVal Ptr As Long, ByVal NewVal As Integer)
Private Declare Sub PutMem4 Lib "msvbvm60" (ByVal Ptr As Long, ByVal NewVal As Long)
Private Declare Sub PutMem8 Lib "msvbvm60" (ByVal Ptr As Long, ByVal NewVal As Currency)
Private Declare Sub GetMem1 Lib "msvbvm60" (ByVal Ptr As Long, Ret As Any) '按地址取1字节
Private Declare Sub GetMem2 Lib "msvbvm60" (ByVal Ptr As Long, Ret As Any)
Private Declare Sub GetMem4 Lib "msvbvm60" (ByVal Ptr As Long, Ret As Any)
Private Declare Sub GetMem8 Lib "msvbvm60" (ByVal Ptr As Long, Ret As Any)
'****以上声明作用是用来获得USN的64位整形****

'CreateFile API声明,获得句柄用**********************
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Type SECURITY_ATTRIBUTES
        nLength As Long
        lpSecurityDescriptor As Long
        bInheritHandle As Long
End Type
Dim attr As SECURITY_ATTRIBUTES
Dim hvol As Long
Dim hFile As Long  '不声明,使用createfile容易出错
'CreateFile API声明,获得句柄用**********************

'DeviceIoControl声明,创建USN***********************
Private Declare Function DeviceIoControl Lib "kernel32" (ByVal hDevice As Long, ByVal dwIoControlCode As Long, lpInBuffer As Any, ByVal nInBufferSize As Long, lpOutBuffer As Any, ByVal nOutBufferSize As Long, lpBytesReturned As Long, lpOverlapped As OVERLAPPED) As Long
Private Type OVERLAPPED
        Internal As Long
        InternalHigh As Long
        offset As Long
        OffsetHigh As Long
        hEvent As Long
End Type

'创建USN日志64位整型,因为VB没有64位整型,这里主要是为了获得连续的2个32位内存*****
Private Type H64
  L8L As Byte '64位低8位无符号
  L8H As Byte '64位高8位无符号
  H8L As Byte '64位低8位无符号
  H8H As Byte '64位高8位无符号
  H32 As Long '64位高32位
End Type
'创建USN日志64位整型,因为VB没有64位整型,这里主要是为了获得连续的2个32位内存*****

'创建USN日志结构***********************
Private Type CREATE_USN_JOURNAL_DATA
 MaximumSize As H64 '//NTFS文件系统分配给USN日志的最大大小(字节)
 AllocationDelta As H64 '//USN日志每次创建和释放的内存字节数
End Type
'创建USN日志结构***********************

'创建USN日志数据结构*************************
Private Type USN_JOURNAL_DATA
    UsnJournalID As H64  '//USN日志ID,64-bit标识
    FirstUsn As H64  ' //第一条USN记录的位置,USN即为64位整型,相当于VB的long
    NextUsn As H64 '//下一条USN记录将要写入的位置
    LowestValidUsn As H64 ' //最小的有效的USN(FistUSN小于该值)
    MaxUsn As H64 ' //最大日志,根据最大大小算出,NextUsn比它还大,那就要清理记录。
    MaximumSize As H64 '//USN日志最大大小(按Byte算)
   AllocationDelta As H64 '//增长大小,如果增长超过MaximuSize,开始清理记录。
End Type
'创建USN日志数据结构*************************

'创建USN记录结构*******************************************************************
Private Type USN_RECORD
RecordLength As H64 '// 记录长度
MajorVersion As Long ' // 主版本
MinorVersion As Long ' // 次版本
FileReferenceNumber As H64 ' // 文件引用数
ParentFileReferenceNumber As H64 ' // 父目录引用数
USN As H64 '// USN
TimeStamp As H64 ' // 时间戳
Reason As H64 ' // 原因
SourceInfo As H64 ' // 源信息
SecurityId As H64 ' // 安全
FileAttributes As H64 '// 文件属性,改为VbFileAttribute
FileNameLength As Long ' // 文件长度
FileNameOffset As Long ' // penultimate of original version 2.0 < 文件名偏移 >

'ExtraInfo1 As Long ' // Hypothetically added in version 2.1
'ExtraInfo2 As Long ' // Hypothetically added in version 2.2
'ExtraInfo3 As Long ' // Hypothetically added in version 2.3

FileName As String ' // variable length always at the end < 文件名第一位的指针 >
End Type '记录结构
'创建USN记录结构*******************************************************************

'创建USN MFT表*************
Private Type MFT_ENUM_DATA     '卷中所有存放的数据均在该主文件表(Master File Table)中
 StartFileReferenceNumber As H64 '开始文件引用数,第一次调用必须为0
 LowUsn As H64 '最小USN,第一次调用,最好为0
 HighUsn  As H64 '最大USN
End Type  '获取数据范围
'创建USN MFT表*************

'需要使用到的各参数定义*****************************************
 Const GENERIC_READ = &H80000000
 Const GENERIC_WRITE = &H40000000 '设置windows参数,从API Viewer里查询
 Const FILE_SHARE_READ = &H1
 Const FILE_SHARE_WRITE = &H2
 Const OPEN_EXISTING = 3
 Const FILE_ATTRIBUTE_READONLY = &H1
 Const FSCTL_CREATE_USN_JOURNAL = &H900E7
 Const FSCTL_QUERY_USN_JOURNAL = &H900F4
 Const FSCTL_ENUM_USN_DATA = &H900B3
 Const FSCTL_READ_USN_DATA = &H900BB
'需要使用到的各参数定义*****************************************

Dim vlp As OVERLAPPED '异步结构
Dim out_UJD As USN_JOURNAL_DATA '输出日志结构
Dim create_UJD As CREATE_USN_JOURNAL_DATA '创建日志结构
Dim med As MFT_ENUM_DATA 'MFT表
Dim USNrecord As USN_RECORD 'USN记录
'Dim USNrecordsize As Long '定义返回缓冲数,MSDN里设置为4KB,即4096
Const USNrecordsize = 4096 '当前使用该数据时不返回记录,只好用Len(USNrecord)代替该数

Dim buffer As String * USNrecordsize
Dim feedbacksize As Long

Private Sub Command1_Click()
 '获得磁盘句柄

 hvol = CreateFile("\\.\d:", GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, attr, OPEN_EXISTING, 0, hFile)
'创建CREATE_USN_JOURNAL_DATA文件,若存在则只是打开,不禁用

 Status = DeviceIoControl(hvol, FSCTL_CREATE_USN_JOURNAL, create_UJD, Len(create_UJD), Null, 0, feedbacksize, vlp)
 '使用FSCTL_QUERY_USN_JOURNAL,查询USN文件,获得FirstUsn、NextUsn,即首个及下一个USN地址

 Status1 = DeviceIoControl(hvol, FSCTL_QUERY_USN_JOURNAL, Null, 0, out_UJD, Len(out_UJD), feedbacksize, vlp)
  
 med.StartFileReferenceNumber.L8L = 0  '首次调用须设置从0开始
 med.StartFileReferenceNumber.L8H = 0  '首次调用须设置从0开始
 med.StartFileReferenceNumber.H8L = 0  '首次调用须设置从0开始
 med.StartFileReferenceNumber.H8H = 0  '首次调用须设置从0开始
 med.StartFileReferenceNumber.H32 = 0 '首次调用须设置从0开始
 med.LowUsn.L8L = 0 '经测试发现,如果用FirstUsn有时候不正确,导致获取到不完整的数据,还是直接写0好.
 med.LowUsn.L8H = 0
 med.LowUsn.H8L = 0
 med.LowUsn.H8H = 0
 med.LowUsn.H32 = 0
 
 med.HighUsn.L8L = out_UJD.NextUsn.L8L '获取out_UJD.NextUsn的低32位,4字节
 med.HighUsn.L8H = out_UJD.NextUsn.L8H '获取out_UJD.NextUsn的高32位,4字节
 med.HighUsn.H8L = out_UJD.NextUsn.H8L '获取out_UJD.NextUsn的低32位,4字节
 med.HighUsn.H8H = out_UJD.NextUsn.H8H '获取out_UJD.NextUsn的高32位,4字节
 med.HighUsn.H32 = out_UJD.NextUsn.H32 '获取out_UJD.NextUsn的高32位,4字节
'注out_UJD.NextUsn与out_UJD.NextUsn.USNL的地址是一样的,与out_UJD.NextUsn.USNH相差4字节
 buffer = String$(USNrecordsize, "*")

上面原代码均能实现访问USN数据成功,且out_UJD.NextUsn结构体收到的数据与C++下收到的数据一致,说明上面的两步没问题。但下面的代码始终返回不了数据,实际需要下面buffer返回的数据来读取文件
  Status2 = DeviceIoControl(hvol, FSCTL_ENUM_USN_DATA, med, Len(med), buffer, USNrecordsize, feedbacksize1, vlp)

End Sub

反回不了数据,我怀疑还是USN这个类型没声明正确。查阅了好多资料,都说USN是int64(有符号64位整数)。由于VB 6.0没有且不支持64位的有符号整数,且integer是16位有符号,long是32位有符号,所以为了避免out_UJD.NextUsn低32位使用integer或long等数据类型时受符号位的影响,特意使用了四个byte来替换。实现结果是out_UJD.NextUsn结构体收到的数据与C++下收到的数据一致,但执行Status2这一句时,始终返回0,即失败。有没有高手能解决这个问题?
分数不高,权作学习探讨。个人当前也不算是新手,如果可以,可以与我作长久的学习伙伴,共同学习进步。
搜索更多相关主题的帖子: Private ByVal Long Type 创建 
2018-02-11 22:52



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-484712-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.089371 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved