| 网站首页 | 业界新闻 | 群组 | 交易 | 人才 | 下载频道 | 博客 | 代码贴 | 编程论坛
共有 628 人关注过本帖, 1 人收藏
标题:使用VB访问USN journal 解决办法偿试,寻求USN (int64)结构体类型声明
只看楼主 加入收藏
q573297953
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2016-8-28
结帖率:0
  已结贴   问题点数:20  回复次数:1   
使用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,即失败。有没有高手能解决这个问题?
分数不高,权作学习探讨。个人当前也不算是新手,如果可以,可以与我作长久的学习伙伴,共同学习进步。
2018-02-11 22:52
wmf2014
Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18
等 级:贵宾
威 望:156
帖 子:1717
专家分:9556
注 册:2014-12-6
  得分:20 
目前看,没有feedbacksize1变量定义。如果前面Status 、Status1都能得到正确结果的话,就要查看Status2给的变量是否正确。
百度到的DeviceIoControl说明:
BOOL DeviceIoControl(
  HANDLE hDevice,
  DWORD dwIoControlCode,
  LPVOID lpInBuffer,
  DWORD nInBufferSize,
  LPVOID lpOutBuffer,
  DWORD nOutBufferSize,
  LPDWORD lpBytesReturned,
  LPOVERLAPPED lpOverlapped
);
Parameters(参数)

hDevice (CreateFile返回的设备句柄)
[in] Handle to the device that is to perform the operation. To obtain a device handle, call the CreateFile function.
dwIoControlCode (应用程序调用驱动程序的控制命令,就是IOCTL_XXX IOCTLs )
[in] IOCTL for the operation. This value identifies the specific operation to perform and the type of device on which to perform the operation. There are no specific values defined for the dwIoControlCode parameter. However, you can define custom IOCTL_XXX IOCTLs with the CTL_CODE macro. You can then advertise these IOCTLs and an application can use these IOCTLs with DeviceIoControl to perform the driver-specific functions.
lpInBuffer (应用程序传递给驱动程序的数据缓冲区地址)
[in] Long pointer to a buffer that contains the data required to perform the operation. Set to NULL if the dwIoControlCode parameter specifies an operation that does not require input data.
nInBufferSize (应用程序传递给驱动程序的数据缓冲区大小,字节数)
[in] Size, in bytes, of the buffer pointed to by lpInBuffer.
lpOutBuffer (驱动程序返回给应用程序的数据缓冲区地址)
[out] Long pointer to a buffer that receives the output data for the operation. Set to NULL if the dwIoControlCode parameter specifies an operation that does not produce output data.
nOutBufferSize (驱动程序返回给应用程序的数据缓冲区大小,字节数)
[out] Size, in bytes, of the buffer pointed to by lpOutBuffer.
lpBytesReturned (驱动程序实际返回给应用程序的数据字节数地址)
[out] Long pointer to a variable that receives the size, in bytes, of the data stored in lpOutBuffer. The DeviceIoControl function may unnecessarily use this parameter. For example, if an operation does not produce data for lpOutBuffer and lpOutBuffer is NULL, the value of lpBytesReturned is meaningless.
lpOverlapped (重叠操作结构)
[in] Ignored; set to NULL.
Return Values(返回值)

Nonzero indicates success. Zero indicates failure. To obtain extended error information, call the GetLastError function. (非0成功,0失败)

能编个毛线衣吗?
2018-02-13 15:55







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

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