当前位置:编程学习 > VB >>

关于拷贝独占文件的问题(NTFS格式已经可以,Fat32不行)

实现的功能是: 拷贝当前因为独占而造成锁定的文件
已经解决的:  如果一个文件放到NTFS分区下,使用某个程序锁定后,再使用该程序拷贝,完全没有问题
需要解决的:  如果这个文件在FAT32分区下,使用某个程序锁定后,再使用该程序拷贝,虽然可以拷贝,大小也相同,但是拷贝
的数据都是错误的,先将 代码公布如下(NTFS)的,寻求高手可以将FAT32下的功能实现

界面上放置两个文本框和一个按钮


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 Any) As Long
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Any) As Long
Private Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As Any) As Long
Private Declare Function GetSystemDirectory Lib "kernel32" Alias "GetSystemDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
Private Declare Function GetDiskFreeSpace Lib "kernel32" Alias "GetDiskFreeSpaceA" (ByVal lpRootPathName As String, lpSectorsPerCluster As Long, lpBytesPerSector As Long, lpNumberOfFreeClusters As Long, lpTotalNumberOfClusters As Long) As Long
Private Declare Function GetFileSize Lib "kernel32" (ByVal hFile As Long, lpFileSizeHigh As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Const GENERIC_READ = &H80000000
Private Const FILE_SHARE_READ = &H1
Private Const FILE_SHARE_WRITE = &H2
Private Const OPEN_EXISTING = 3
Private Const INVALID_HANDLE_VALUE = -1
Private Const GENERIC_WRITE = &H40000000
Private Const OPEN_ALWAYS = 4
Private Const FILE_READ_ATTRIBUTES = (&H80)
Private Const FSCTL_GET_RETRIEVAL_POINTERS = 589939

Private Type RETRIEVAL_POINTERS_BUFFER
    dwExtentCount As Long
    bytStartingVcn(7) As Byte '这些都可以使用LARGE_INTEGER类型代替
    bytNextVcn(7) As Byte '这些都可以使用LARGE_INTEGER类型代替
    bytLcn(7) As Byte '这些都可以使用LARGE_INTEGER类型代替
   lngTmp(255)   As Byte
End Type

Private Type LARGE_INTEGER
    LowPart As Long
    HighPart As Long
End Type

Private Sub cmdCopy_Click()
    Dim strSamPath As String
    '如果需要拷贝sam,则修改下边的
'    strSamPath = GetSystemPath & "\Config\Sam"
    strSamPath = txtSource.Text
    If CopySamFile(strSamPath, txtPath.Text) Then
        MsgBox "复制完毕!!", vbInformation, "提示"
    Else
        MsgBox "复制错误!!", vbCritical, "提示"
    End If
End Sub

'获取系统目录路径
Private Function GetSystemPath() As String
    Dim strTmp As String
    strTmp = String(260, Chr(0))
    GetSystemDirectory strTmp, 260
    strTmp = Left(strTmp, InStr(strTmp, Chr(0)) - 1)
    GetSystemPath = strTmp
End Function

Private Function GetFileClusters(ByVal strFileName As String, ByVal lngClusterSize As Long, lngClCount As Long, lngFileSize As Long) As Long()
Dim hFile As Long
    Dim lngOutSize As Long
    Dim lngBytes As Long, lngCls As Long, lngCnCount As Long, r As Long, lngCount As Long, i As Long, j As Long
    Dim lngClusters() As Long
    Dim bytInBuf(7) As Byte
    Dim objOutBuf As RETRIEVAL_POINTERS_BUFFER
    Dim bytOutBuff() As Byte
    hFile = CreateFile(strFileName, FILE_READ_ATTRIBUTES, _
                       FILE_SHARE_READ Or FILE_SHARE_WRITE Or FILE_SHARE_DELETE, _
                       ByVal 0&, OPEN_EXISTING, 0, 0)
    If hFile <> INVALID_HANDLE_VALUE Then
        lngFileSize = GetFileSize(hFile, 0)
        lngOutSize = 32 + (lngFileSize \ lngClusterSize) * 16
        Dim bytOutBuf() As Byte: ReDim bytOutBuf(lngOutSize - 1)
        If DeviceIoControl(hFile, FSCTL_GET_RETRIEVAL_POINTERS, bytInBuf(0), 8, _
        bytOutBuf(0), lngOutSize, lngBytes, ByVal 0&) Then
        CopyMemory objOutBuf, bytOutBuf(0), lngBytes
        lngClCount = (lngFileSize + lngClusterSize - 1) \ lngClusterSize

            For r = 0 To objOutBuf.dwExtentCount - 1
                CopyMemory j, objOutBuf.bytLcn(4), 4
                For i = lngClCount To 0 Step -1
                    ReDim Preserve lngClusters(0 To lngCls)
                    lngClusters(lngCls) = j
                    j = j + 1
                    lngCls = lngCls + 1
                Next
            Next
            CloseHandle hFile
            GetFileClusters = lngClusters
        End If
    End If

End Function

Private Function CopySamFile(ByVal strSamPath As String, ByVal strDestPath As String) As Boolean
        Dim lngClusterSize     As Long
        Dim lngClusters()     As Long
        Dim lngClCount     As Long, lngFileSize       As Long, lngBytes       As Long
        Dim hDrive     As Long, hFile       As Long
        Dim lngSecPerCl     As Long, lngBtPerSec       As Long, r       As Long
        Dim curTmp     As Currency
        Dim ligNo     As LARGE_INTEGER
        Dim bytBuff()     As Byte
        GetDiskFreeSpace Left(strSamPath, 2), lngSecPerCl, lngBtPerSec, ByVal 0&, ByVal 0&
        lngClusterSize = lngSecPerCl * lngBtPerSec
        On Error GoTo ErrHandle
        lngClusters = GetFileClusters(strSamPath, lngClusterSize, lngClCount, lngFileSize)
        hDrive = CreateFile("\\.\" & Left(strSamPath, 2), GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, 0, 0)
        If hDrive <> INVALID_HANDLE_VALUE Then
                hFile = CreateFile(strDestPath, GENERIC_WRITE, 0, ByVal 0, OPEN_ALWAYS, 0, 0)
                If hFile <> INVALID_HANDLE_VALUE Then
                        For r = 0 To lngClCount - 1
                                curTmp = CCur(lngClusterSize) * CCur(lngClusters(r)) / 10000              'lngClusterSize   *   lngClusters(r)
                                CopyMemory ligNo, curTmp, Len(ligNo)
                                Call SetFilePointer(hDrive, ligNo.LowPart, ligNo.HighPart, 0)
                                
                                
                                If lngFileSize < lngClusterSize Then
                                    ReDim bytBuff(lngClusterSize - 1)
                                    Call ReadFile(hDrive, bytBuff(0), lngClusterSize, lngBytes, ByVal 0&)
                                    Call WriteFile(hFile, bytBuff(0), lngFileSize, lngBytes, ByVal 0&)
                                    Exit For
                                Else
                                    ReDim bytBuff(lngClusterSize - 1)
                                End If
                                Call ReadFile(hDrive, bytBuff(0), lngClusterSize, lngBytes, ByVal 0&)
                                Call WriteFile(hFile, bytBuff(0), lngClusterSize, lngBytes, ByVal 0&)
                                lngFileSize = lngFileSize - lngBytes
                                Debug.Print ligNo.LowPart; ligNo.HighPart
                                
                                
                                
                        Next
                        End If
                CloseHandle hFile
        End If
        CloseHandle hDrive
        CopySamFile = True
        Exit Function
ErrHandle:
        If hDrive <> -1 Then CloseHandle hDrive
        If hFile <> -1 Then CloseHandle hFile
End Function

Private Sub cmdExit_Click()
    Unload Me
End Sub

--------------------编程问答-------------------- 此代码不管当前的文件是否是独占,可以用access打开一个mdb(以独占的方式),然后用这段代码再去拷贝那个已经打开的mdb文件,完全没有问题,关键是fat的分区,其实我是怀疑这个函数   GetFileClusters 中 lngOutSize = 32 + (lngFileSize \ lngClusterSize) * 16

这句代码有问题,因为Fat32和ntfs此处的参数不知道是否有用?

冰天雪地 零下60度裸奔三十里,看是否有高人予以解决!
  --------------------编程问答-------------------- 顶大侠。。
联络我把,使用在线验证 
 
 

 
这位大侠。联系上吧。 
我QQ:26404992 
 
--------------------编程问答--------------------  #14楼 得分:0回复于:2009-07-21 19:01:11或者那位大侠帮下小弟。给我加个锁上去。能控制使用权就OK。定会重谢!QQ:26404992 
 
 
对我有用[0] 丢个板砖[0] 引用 举报 管理 TOP  
 
springoldbrother
 
(springoldbrother) 

等 级: 
 #15楼 得分:0回复于:2009-07-21 19:18:29联络我把,使用在线验证 
 
 
--------------------编程问答-------------------- 学习 --------------------编程问答-------------------- 期待高手高手高高手出手,春哥保佑 --------------------编程问答-------------------- 这是以前我写的代码。
在fat32下计算磁盘偏移是有问题的
需要加上保留扇区以及fatcount等 --------------------编程问答-------------------- chenhui530,你好,这段代码是在网上搜到后修改的,请问如何修改保留扇区以及fatcount呀 --------------------编程问答-------------------- 对是修改一份c代码的,至于怎么计算其实很简单,保留扇区+FatAreaCount*2 --------------------编程问答-------------------- 请问是修改  Call SetFilePointer(hDrive, ligNo.LowPart, ligNo.HighPart, 0)
  这个函数吗? --------------------编程问答-------------------- 可否指点一下小弟,如何获取fat32 的保留扇区以及 fatareacount,偏移的时候加上这个值,指的是 setfilepointer 吗? --------------------编程问答-------------------- FDUMP version 1.0 by Armen Hakobyan, 2008

 Dumps file to another location reading its sectors directly from disk.

 FDUMP [/V] source destination

 source       Specifies the file to be dumped directly from disk.
 destination  Specifies the output file name for the dumped data.
 /V           Produce verbose output.
--------------------编程问答-------------------- 不明白 --------------------编程问答-------------------- 保留和扇区和 fat 表数,都可以计算出来,请问    保留扇区+FatAreaCount*2  是修改那个函数 --------------------编程问答-------------------- 自己再顶一下 --------------------编程问答-------------------- 我看你这代码,正准备进来说叫找陈辉这小子呢.

看来我可以匿了....... --------------------编程问答-------------------- 是呀,陈辉一直不在呀 --------------------编程问答-------------------- 不知myjian兄弟对此可有研究? --------------------编程问答-------------------- 关注

本人一直认为独占打开的access文件是无法复制的。 --------------------编程问答-------------------- 可以的,用上边的代码,如果access所在的分区是 ntfs 的话,一点问题都没有 --------------------编程问答-------------------- 我不懂这个,哈哈.

建议你开个200分的帖叫人帮你写 --------------------编程问答-------------------- ntfs 对小文件你的这个代码也会有问题的

The stream is resident in the MFT and has no clusters allocated
NTFS文件当文件很小时,文件会保存在MFT里,而不会给它分配簇来保存数据

另外一个帖子也给你回了FAT32 起始数据区计算的问题 --------------------编程问答-------------------- 好像小于512的有点问题,不过这个问题我已经处理了一下,是可以的

  Call ReadFile(hDrive, bytBuff(0), lngClusterSize, lngBytes, ByVal 0&)
  Call WriteFile(hFile, bytBuff(0), lngFileSize, lngBytes, ByVal 0&)

改了一下上边的两个函数
--------------------编程问答-------------------- 非常感谢你的回复,我再研究看看,先结贴 --------------------编程问答-------------------- curTmp = CCur(lngClusterSize) * CCur(lngClusters(r)) + (保留扇区+FatAreaCount*2) * BytesPerSector 
还有 这段代码如果分区大于2GB的话 应该也不行,GetDiskFreeSpace Left(strSamPath, 2), lngSecPerCl, lngBtPerSec, ByVal 0&, ByVal 0& 读不出SecPerCl, BtPerSec --------------------编程问答-------------------- @noface: NTFS小文件拷贝问题是如何解决的,望告知,3q
补充:VB ,  API
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,