#cs IMPORTANT NOTES =============== CRYPT LIBRARY ------------- This UDF initializes the Crypt library by calling _Crypt_Startup() in the _LFC_ControlBuffers function. This is done only once (the ref count is checked), however to optimize performance _Crypt_Shutdown() is NEVER called. It is advised to call _Crypt_Shutdown() when finished using this UDF. BUFFERS ------- Global buffers are created on the first call to any of the functions. These buffers will exist for the life of the script, unless a function is called with a larger buffer size, in which case the buffers will be recreated at the larger size. The buffers will never shrink. To reclaim the used memory, call the internal function _LFC_FreeBuffers(). This will free all the allocated memory and will trigger buffer recreation on the next call to any of the functions. One additional 2M static buffer is created for file hash verification. It is created once for the life of the script, when and only if hash verification is selected, and cannot be freed. See the _LFC_HashFileInternal function. SECURITY DESCRIPTORS -------------------- To properly copy all security descriptors and owner information, the script must have full admin rights and successfully get the SeSecurityPrivilege right. This means your script must include the #RequireAdmin directive on Vista+ where UAC is enabled. Access rights are checked and acquired only once. Only non-inherited descriptors are copied. Setting the owner may fail if the script does not have rights, ie trying to set the owner to SYSTEM or TrustedInstaller. #ce #include-once #include #include #include #include #include <_FileEx.au3> #region FUNCTIONS ; #FUNCTION# ==================================================================================================== ; Name...........: _LargeFileCopy ; Description....: Copy large files in such a way as to keep AutoIt GUIs responsive ; Syntax.........: _LargeFileCopy($sSrc, $sDest[, $iFlags = 0[, $iToRead = 2097152[, $iAlg = $CALG_MD5[, $sFunction = ""[, $vUserVar = Default]]]]]) ; Parameters.....: $sSrc - Source file name ; $sDest - Destination: may be a file name or directory ; $iFlags - [Optional] Combine flags with BitOR ; | 1 - Overwrite existing file ; | 2 - Create destination directory structure ; | 4 - Flush the destination file buffer before returning ; | 8 - Verify source and destination are identical via bit by bit comparison ; | 16 - Verify source and destination are identical via MD5 hash ; | 32 - Verify source and destination file size only ; | 64 - Copy source file attributes (NOT including Compression or Encryption) ; | 128 - Copy source file Creation time ; | 256 - Copy source file Last Accessed time ; | 512 - Copy source file Modified time ; |1024 - Copy source file Security Descriptors and Ownership ; |2048 - Copy source compression state ; |4096 - Copy source encryption state ; + If more than one verify flag is set, the smallest flag will take precedence ; $iToRead - [Optional] Size of the read/write buffer (Default = 2 MB) ; $iAlg - [Optional] Algorithm to use for file verification (Default = $CALG_MD5) ; + Available algorithms: $CALG_MD2, $CALG_MD4, $CALG_MD5, $CALG_SHA1 ; $sFunction - [Optional] Function to be called after each write operation (Default = "") ; + Function will be called with the following parameters: ; | 1 - Total bytes written ; | 2 - Total file size in bytes ; | 3 - Optional user variable ; $vUserVar - [Optional] User variable to pass to function (Default = Default) ; ; Return values..: Success - 1 ; Failure - 0 and sets @error ; | 1 - Failed to open source file, or source was a directory ; | 2 - Destination file exists and overwrite flag not set ; | 3 - Failed to create destination file ; | 4 - Read error during copy ; | 5 - Write error during copy ; | 6 - Verify failed ; Author.........: Erik Pilsits ; Modified.......: ; Remarks........: ; Related........: ; Link...........: ; Example........: ; =============================================================================================================== Func _LargeFileCopy($sSrc, $sDest, $iFlags = 0, $iToRead = 2097152, $iAlg = $CALG_MD5, $sFunction = "", $vUserVar = Default) ; check / fix source and dest path syntax _LFC_FixPathEx($sSrc, $sDest) ; open file for reading, fail if it doesn't exist or directory Local $hSrc = _FileEx_CreateFile($sSrc, $GENERIC_READ, $FILE_SHARE_READ, $OPEN_EXISTING, 0) If Not $hSrc Then Return SetError(1, 0, 0) ; set option flags Local $fOverwrite = (BitAND($iFlags, 1) = 1) Local $fCreate = (BitAND($iFlags, 2) = 2) Local $fFlush = (BitAND($iFlags, 4) = 4) Local $fVerify = 0 If (BitAND($iFlags, 8) = 8) Then ; bit by bit $fVerify = 1 ElseIf (BitAND($iFlags, 16) = 16) Then ; hash $fVerify = 2 ElseIf (BitAND($iFlags, 32) = 32) Then ; file size $fVerify = 3 EndIf Local $fAttr = (BitAND($iFlags, 64) = 64) Local $fTimeC = (BitAND($iFlags, 128) = 128) Local $fTimeA = (BitAND($iFlags, 256) = 256) Local $fTimeM = (BitAND($iFlags, 512) = 512) Local $fACL = (BitAND($iFlags, 1024) = 1024) Local $fCompress = (BitAND($iFlags, 2048) = 2048) Local $fEncrypt = (BitAND($iFlags, 4096) = 4096) ; check destination (this function will delete the destination file if it exists and $fOverwrite is True) _LFC_CheckDestination($sSrc, $sDest, $fOverwrite, $fCreate) If @error Then _WinAPI_CloseHandle($hSrc) Return SetError(2, 0, 0) EndIf ; check source and destination file systems and disable NTFS specific features if $fACL or $fCompress or $fEncrypt is true If ($fACL Or $fCompress Or $fEncrypt) And _ ((DriveGetFileSystem(_FileEx_PathGetRoot($sSrc)) <> "NTFS") Or (DriveGetFileSystem(_FileEx_PathGetRoot($sDest)) <> "NTFS")) Then $fACL = False $fCompress = False $fEncrypt = False EndIf ; get source attributes only if needed Local $iAttr = 0 If $fAttr Or $fCompress Or $fEncrypt Then $iAttr = _FileEx_GetAttributes($sSrc) EndIf ; ACL operations require full Admin access, ie #RequireAdmin on Vista+ ; check for proper elevation and attempt to get the SeSecurityPrivilege right Local $iSeSecurity If $fACL Then $iSeSecurity = _LFC_CheckACLAdmin() If @error Then $fACL = False EndIf ; create destination file ; check encryption / compression attributes if NTFS, they are mutually exclusive Local $hDest If $fCompress And (BitAND($iAttr, 0x800) = 0x800) Then ; FILE_ATTRIBUTE_COMPRESSED ; compression is not a settable attribute $hDest = _LFC_CreateCompressedFile($sDest) ElseIf $fEncrypt And (BitAND($iAttr, 0x4000) = 0x4000) Then ; FILE_ATTRIBUTE_ENCRYPTED ; encryption $hDest = _FileEx_CreateFile($sDest, BitOR($GENERIC_READ, $GENERIC_WRITE), 0, $CREATE_ALWAYS, 0x4000) Else ; normal file $hDest = _FileEx_CreateFile($sDest, BitOR($GENERIC_READ, $GENERIC_WRITE), 0, $CREATE_ALWAYS, 0) EndIf ; If Not $hDest Then _WinAPI_CloseHandle($hSrc) Return SetError(3, 0, 0) EndIf ; check for 0 byte source file Local $iSize = _WinAPI_GetFileSizeEx($hSrc) If $iSize = 0 Then ; nothing to copy, close handles _WinAPI_CloseHandle($hDest) _WinAPI_CloseHandle($hSrc) Else ; perform copy Local $iRead, $iWritten, $bytesRead = 0, $iTotal = 0, $mSrc = 0, $iReadError = 0, $iWriteError = 0, $iVerifyError = 0 ; allocate buffers Local $apBuffers = _LFC_CreateBuffers($iToRead) ; read buffer Local $pBuffer = $apBuffers[0] ; verify buffer Local $pvBuffer = $apBuffers[1] While $bytesRead < $iSize If $iToRead > ($iSize - $bytesRead) Then $iToRead = $iSize - $bytesRead If Not _WinAPI_ReadFile($hSrc, $pBuffer, $iToRead, $iRead) Or ($iToRead <> $iRead) Then $iReadError = 1 ExitLoop EndIf If Not _WinAPI_WriteFile($hDest, $pBuffer, $iRead, $iWritten) Or ($iRead <> $iWritten) Then $iWriteError = 1 ExitLoop EndIf If $sFunction Then $iTotal += $iToRead Call($sFunction, $iTotal, $iSize, $vUserVar) EndIf If $fVerify = 1 Then ; compare data If Not _LFC_BitCompare($hDest, $pBuffer, $pvBuffer, $iToRead) Then $iVerifyError = 1 ExitLoop EndIf ElseIf $fVerify = 2 Then ; hash source inline $mSrc = _LFC_ChunkHash($mSrc, $pBuffer, $iToRead, $iAlg) EndIf $bytesRead += $iToRead WEnd ; the FlushFileBuffers command here can take some time: ~1s for a 75MB file, ~4s for a 700MB file ; it's probably safest to enable this if you need to make sure the write buffer is empty before continuing ; the FileCopy function does NOT seem to do this based on execution time If $fFlush Then _WinAPI_FlushFileBuffers($hDest) ; check file size in verify mode 3 before closing handles If $fVerify = 3 Then If Not _LFC_SizeCompare($hSrc, $hDest) Then $iVerifyError = 1 EndIf ; close handles _WinAPI_CloseHandle($hDest) _WinAPI_CloseHandle($hSrc) If $fVerify = 2 Then ; finalize hash $mSrc = _LFC_ChunkHashFinal($mSrc) EndIf If $iReadError Then Return SetError(4, 0, 0) ElseIf $iWriteError Then Return SetError(5, 0, 0) Else If ($fVerify = 1) Or ($fVerify = 3) Then If $iVerifyError Then Return SetError(6, 0, 0) ElseIf ($fVerify = 2) Then ; hash destination and verify Local $mDest = _LFC_HashFile($sDest, $iAlg) If ($mSrc = "") Or ($mDest = "") Or ($mSrc <> $mDest) Then Return SetError(6, 0, 0) EndIf EndIf EndIf ; copy security descriptors If $fACL Then _LFC_CopyPathSD($sSrc, $sDest, $iSeSecurity) ; copy file times If $fTimeC Or $fTimeA Or $fTimeM Then Local $tC, $tA, $tM _FileEx_GetFileTime($sSrc, $tC, $tA, $tM) If Not $fTimeC Then $tC = 0 If Not $fTimeA Then $tA = 0 If Not $fTimeM Then $tM = 0 _FileEx_SetFileTime($sDest, $tC, $tA, $tM) EndIf ; copy attributes (does not affect file times) If $fAttr Then _FileEx_SetAttributes($sDest, $iAttr) Return 1 EndFunc ;==>_LargeFileCopy ; #FUNCTION# ==================================================================================================== ; Name...........: _LargeFileCopyUnbuffered ; Description....: Copy large files in such a way as to keep AutoIt GUIs responsive ; Syntax.........: _LargeFileCopyUnbuffered($sSrc, $sDest[, $iFlags = 0[, $iToRead = 2097152[, $iAlg = $CALG_MD5[, $sFunction = ""[, $vUserVar = Default]]]]]) ; Parameters.....: $sSrc - Source file name ; $sDest - Destination: may be a file name or directory ; $iFlags - [Optional] Combine flags with BitOR ; | 1 - Overwrite existing file ; | 2 - Create destination directory structure ; | 8 - Verify source and destination are identical via bit by bit comparison ; | 16 - Verify source and destination are identical via MD5 hash ; | 64 - Copy source file attributes (NOT including Compression or Encryption) ; | 128 - Copy source file Creation time ; | 256 - Copy source file Last Accessed time ; | 512 - Copy source file Modified time ; |1024 - Copy source file Security Descriptors and Ownership ; |2048 - Copy source compression state ; |4096 - Copy source encryption state ; + If more than one verify flag is set, the smallest flag will take precedence ; $iToRead - [Optional] Size of the read buffer (Default = 8 MB) ; $iAlg - [Optional] Algorithm to use for file verification (Default = $CALG_MD5) ; + Available algorithms: $CALG_MD2, $CALG_MD4, $CALG_MD5, $CALG_SHA1 ; $sFunction - [Optional] Function to be called after each write operation (Default = "") ; + Function will be called with the following parameters: ; | 1 - Total bytes written ; | 2 - Total file size in bytes ; | 3 - Optional user variable ; $vUserVar - [Optional] User variable to pass to function (Default = Default) ; ; Return values..: Success - 1 ; Failure - 0 and sets @error ; | 1 - Failed to open source file, or source was a directory ; | 2 - Destination file exists and overwrite flag not set ; | 3 - Failed to create destination file ; | 4 - Read error during copy ; | 5 - Write error during copy ; | 6 - Verify failed ; | 7 - Failed to set destination file size ; Author.........: Erik Pilsits ; Modified.......: ; Remarks........: ; Related........: ; Link...........: ; Example........: ; =============================================================================================================== Func _LargeFileCopyUnbuffered($sSrc, $sDest, $iFlags = 0, $iToRead = 2097152, $iAlg = $CALG_MD5, $sFunction = "", $vUserVar = Default) ; check / fix source and dest path syntax _LFC_FixPathEx($sSrc, $sDest) ; open file for reading, fail if it doesn't exist or directory Local $hSrc = _FileEx_CreateFile($sSrc, $GENERIC_READ, $FILE_SHARE_READ, $OPEN_EXISTING, 0) If Not $hSrc Then Return SetError(1, 0, 0) ; set option flags Local $fOverwrite = (BitAND($iFlags, 1) = 1) Local $fCreate = (BitAND($iFlags, 2) = 2) Local $fVerify = 0 If (BitAND($iFlags, 8) = 8) Then ; bit by bit $fVerify = 1 ElseIf (BitAND($iFlags, 16) = 16) Then ; hash $fVerify = 2 EndIf Local $fAttr = (BitAND($iFlags, 64) = 64) Local $fTimeC = (BitAND($iFlags, 128) = 128) Local $fTimeA = (BitAND($iFlags, 256) = 256) Local $fTimeM = (BitAND($iFlags, 512) = 512) Local $fACL = (BitAND($iFlags, 1024) = 1024) Local $fCompress = (BitAND($iFlags, 2048) = 2048) Local $fEncrypt = (BitAND($iFlags, 4096) = 4096) ; check destination _LFC_CheckDestination($sSrc, $sDest, $fOverwrite, $fCreate) If @error Then _WinAPI_CloseHandle($hSrc) Return SetError(2, 0, 0) EndIf ; check source and destination file systems and disable NTFS specific features if $fACL or $fCompress or $fEncrypt is true If ($fACL Or $fCompress Or $fEncrypt) And _ ((DriveGetFileSystem(_FileEx_PathGetRoot($sSrc)) <> "NTFS") Or (DriveGetFileSystem(_FileEx_PathGetRoot($sDest)) <> "NTFS")) Then $fACL = False $fCompress = False $fEncrypt = False EndIf ; get source attributes only if needed Local $iAttr = 0 If $fAttr Or $fCompress Or $fEncrypt Then $iAttr = _FileEx_GetAttributes($sSrc) EndIf ; ACL operations require full Admin access, ie #RequireAdmin on Vista+ ; check for proper elevation and attempt to get the SeSecurityPrivilege right Local $iSeSecurity If $fACL Then $iSeSecurity = _LFC_CheckACLAdmin() If @error Then $fACL = False EndIf ; create destination file ; check encryption / compression attributes if NTFS, they are mutually exclusive Local $hDest If $fCompress And (BitAND($iAttr, 0x800) = 0x800) Then ; FILE_ATTRIBUTE_COMPRESSED ; compression is not an attribute $hDest = _LFC_CreateCompressedFile($sDest, 0xA0000000) ElseIf $fEncrypt And (BitAND($iAttr, 0x4000) = 0x4000) Then ; FILE_ATTRIBUTE_ENCRYPTED $hDest = _FileEx_CreateFile($sDest, BitOR($GENERIC_READ, $GENERIC_WRITE), 0, $CREATE_ALWAYS, 0xA0004000) Else ; normal file ; FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH $hDest = _FileEx_CreateFile($sDest, BitOR($GENERIC_READ, $GENERIC_WRITE), 0, $CREATE_ALWAYS, 0xA0000000) EndIf ; If Not $hDest Then _WinAPI_CloseHandle($hSrc) Return SetError(3, 0, 0) EndIf ; check for 0 byte source file Local $iSize = _WinAPI_GetFileSizeEx($hSrc) If $iSize = 0 Then ; nothing to copy, close handles _WinAPI_CloseHandle($hDest) _WinAPI_CloseHandle($hSrc) Else ; get destination disk cluster size for unbuffered i/o Local $ClusterSize = _FileEx_GetDiskClusterSize($sDest) ; if error, default to 512 and hope for the best, at worst the write operation will fail later on If @error Then $ClusterSize = 512 ; perform copy Local $iRead, $iWritten, $bytesRead = 0, $iTotal = 0, $mSrc = 0, $iReadError = 0, $iWriteError = 0, $iVerifyError = 0 ; create aligned buffer $iToRead = Floor($iToRead / $ClusterSize) * $ClusterSize If $iToRead = 0 Then $iToRead = $ClusterSize Local $apBuffers = _LFC_CreateBuffers($iToRead) Local $pBuffer = $apBuffers[0] Local $pvBuffer = $apBuffers[1] Local $alignedWrite = $iToRead While $bytesRead < $iSize If $iToRead > ($iSize - $bytesRead) Then $iToRead = $iSize - $bytesRead If Not _WinAPI_ReadFile($hSrc, $pBuffer, $iToRead, $iRead) Or ($iToRead <> $iRead) Then $iReadError = 1 ExitLoop EndIf ; set aligned write size for final pass If $iRead < $alignedWrite Then $iRead = Ceiling($iRead / $ClusterSize) * $ClusterSize If Not _WinAPI_WriteFile($hDest, $pBuffer, $iRead, $iWritten) Or ($iRead <> $iWritten) Then $iWriteError = 1 ExitLoop EndIf If $sFunction Then $iTotal += $iToRead Call($sFunction, $iTotal, $iSize, $vUserVar) EndIf If $fVerify = 1 Then ; compare data, using $iRead because it must be a cluster sized block of data If Not _LFC_BitCompare($hDest, $pBuffer, $pvBuffer, $iRead) Then $iVerifyError = 1 ExitLoop EndIf ElseIf $fVerify = 2 Then ; hash source inline $mSrc = _LFC_ChunkHash($mSrc, $pBuffer, $iToRead, $iAlg) EndIf $bytesRead += $iToRead WEnd ; close handles _WinAPI_CloseHandle($hSrc) _WinAPI_CloseHandle($hDest) If $fVerify = 2 Then ; finalize hash $mSrc = _LFC_ChunkHashFinal($mSrc) EndIf ; don't bother if errors above If (Not $iReadError) And (Not $iWriteError) And (Not $iVerifyError) Then ; set correct destination file size $hDest = _FileEx_CreateFile($sDest, BitOR($GENERIC_READ, $GENERIC_WRITE), 0, $OPEN_EXISTING, 0) If $hDest Then DllCall("kernel32.dll", "bool", "SetFilePointerEx", "handle", $hDest, "int64", $iSize, "ptr", 0, "dword", 0) _WinAPI_SetEndOfFile($hDest) _WinAPI_CloseHandle($hDest) Else Return SetError(7, 0, 0) EndIf EndIf ; close dest handle _WinAPI_CloseHandle($hDest) If $iReadError Then Return SetError(4, 0, 0) ElseIf $iWriteError Then Return SetError(5, 0, 0) Else If ($fVerify = 1) Then If $iVerifyError Then Return SetError(6, 0, 0) ElseIf ($fVerify = 2) Then ; hash destination and verify Local $mDest = _LFC_HashFile($sDest, $iAlg) If ($mSrc = "") Or ($mDest = "") Or ($mSrc <> $mDest) Then Return SetError(6, 0, 0) EndIf EndIf EndIf ; copy security descriptors If $fACL Then _LFC_CopyPathSD($sSrc, $sDest, $iSeSecurity) ; copy file times If $fTimeC Or $fTimeA Or $fTimeM Then Local $tC, $tA, $tM _FileEx_GetFileTime($sSrc, $tC, $tA, $tM) If Not $fTimeC Then $tC = 0 If Not $fTimeA Then $tA = 0 If Not $fTimeM Then $tM = 0 _FileEx_SetFileTime($sDest, $tC, $tA, $tM) EndIf ; copy attributes (does not affect file times) If $fAttr Then _FileEx_SetAttributes($sDest, $iAttr) Return 1 EndFunc ;==>_LargeFileCopyUnbuffered ; #FUNCTION# ==================================================================================================== ; Name...........: _LargeRawCopy ; Description....: Copy large memory blocks to files in such a way as to keep AutoIt GUIs responsive ; Syntax.........: _LargeRawCopy($pSrc, $iSrcSize, $sDest[, $iFlags = 0[, $iToRead = 2097152[, $iAlg = $CALG_MD5[, $sFunction = ""[, $vUserVar = Default]]]]]) ; Parameters.....: $pSrc - Pointer to source raw data ; $iSrcSize - Size of raw data ; $sDest - Destination file name, must not be an existing directory ; $iFlags - [Optional] Combine flags with BitOR ; | 1 - Overwrite existing file ; | 2 - Create destination directory structure ; | 4 - Flush the destination file buffer before returning ; | 8 - Verify source and destination are identical via bit by bit comparison ; |16 - Verify source and destination are identical via MD5 hash ; |32 - Verify source and destination file size only ; + If more than one verify flag is set, the smallest flag will take precedence ; $iToRead - [Optional] Size of the read buffer (Default = 8 MB) ; $iAlg - [Optional] Algorithm to use for file verification (Default = $CALG_MD5) ; + Available algorithms: $CALG_MD2, $CALG_MD4, $CALG_MD5, $CALG_SHA1 ; $sFunction - [Optional] Function to be called after each write operation (Default = "") ; + Function will be called with the following parameters: ; | 1 - Total bytes written ; | 2 - Total file size in bytes ; | 3 - Optional user variable ; $vUserVar - [Optional] User variable to pass to function (Default = Default) ; ; Return values..: Success - 1 ; Failure - 0 and sets @error ; |-1 - $iSrcSize may not be 0 ; | 1 - $pSrc and $iSrcSize point to inaccessible memory ; | 2 - Destination is an existing directory ; | 3 - Destination file exists and overwrite flag not set ; | 4 - Failed to create destination file ; | 5 - Write error during copy ; | 6 - Verify failed ; Author.........: Erik Pilsits ; Modified.......: ; Remarks........: ; Related........: ; Link...........: ; Example........: ; =============================================================================================================== Func _LargeRawCopy($pSrc, $iSrcSize, $sDest, $iFlags = 0, $iToRead = 2097152, $iAlg = $CALG_MD5, $sFunction = "", $vUserVar = Default) ; check source size If $iSrcSize = 0 Then Return SetError(-1, 0, 0) ; check source memory, 0 = success Local $ret = DllCall("kernel32.dll", "bool", "IsBadReadPtr", "ptr", $pSrc, "uint_ptr", $iSrcSize) If $ret[0] Then Return SetError(1, 0, 0) ; check / fix dest path syntax $sDest = StringReplace($sDest, "/", "\") _LFC_FixPath($sDest) ; set option flags Local $fOverwrite = (BitAND($iFlags, 1) = 1) Local $fCreate = (BitAND($iFlags, 2) = 2) Local $fFlush = (BitAND($iFlags, 4) = 4) Local $fVerify = 0 If (BitAND($iFlags, 8) = 8) Then ; bit by bit $fVerify = 1 ElseIf (BitAND($iFlags, 16) = 16) Then ; MD5 $fVerify = 2 ElseIf (BitAND($iFlags, 32) = 32) Then ; file size $fVerify = 3 EndIf ; check destination _LFC_CheckDestination("", $sDest, $fOverwrite, $fCreate) Switch @error Case 1 ; overwrite fail Return SetError(3, 0, 0) Case 2 ; no file name Return SetError(2, 0, 0) EndSwitch ; create new file for writing, overwrite Local $hDest = _FileEx_CreateFile($sDest, BitOR($GENERIC_READ, $GENERIC_WRITE), 0, $CREATE_ALWAYS, 0) If Not $hDest Then Return SetError(4, 0, 0) ; perform copy If $iToRead > $iSrcSize Then $iToRead = $iSrcSize Local $pRead = $pSrc Local $iWritten, $bytesRead = 0, $iTotal = 0, $mSrc = 0, $iWriteError = 0, $iVerifyError = 0 ; allocate buffers Local $apBuffers = _LFC_CreateBuffers($iToRead) ; verify buffer Local $pvBuffer = $apBuffers[1] While $bytesRead < $iSrcSize If $iToRead > ($iSrcSize - $bytesRead) Then $iToRead = $iSrcSize - $bytesRead If Not _WinAPI_WriteFile($hDest, $pRead, $iToRead, $iWritten) Or ($iToRead <> $iWritten) Then $iWriteError = 1 ExitLoop EndIf If $sFunction Then $iTotal += $iToRead Call($sFunction, $iTotal, $iSrcSize, $vUserVar) EndIf If $fVerify = 1 Then ; compare data If Not _LFC_BitCompare($hDest, $pRead, $pvBuffer, $iToRead) Then $iVerifyError = 1 ExitLoop EndIf ElseIf $fVerify = 2 Then ; hash source inline $mSrc = _LFC_ChunkHash($mSrc, $pRead, $iToRead, $iAlg) EndIf ; ready next chunk $pRead += $iToRead $bytesRead += $iToRead WEnd ; the FlushFileBuffers command here can take some time: ~1s for a 75MB file, ~4s for a 700MB file ; it's probably safest to enable this if you need to make sure the write buffer is empty before continuing ; the FileCopy function does NOT seem to do this based on execution time If $fFlush Then _WinAPI_FlushFileBuffers($hDest) ; check file size in verify mode 3 before closing handles If $fVerify = 3 Then If Not _LFC_SizeCompare($iSrcSize, $hDest) Then $iVerifyError = 1 EndIf _WinAPI_CloseHandle($hDest) If $fVerify = 2 Then ; finalize hash $mSrc = _LFC_ChunkHashFinal($mSrc) EndIf If $iWriteError Then Return SetError(5, 0, 0) Else If ($fVerify = 1) Or ($fVerify = 3) Then If $iVerifyError Then Return SetError(6, 0, 0) ElseIf ($fVerify = 2) Then ; hash destination and verify Local $mDest = _LFC_HashFile($sDest, $iAlg) If ($mSrc = "") Or ($mDest = "") Or ($mSrc <> $mDest) Then Return SetError(6, 0, 0) EndIf EndIf Return 1 EndFunc ;==>_LargeRawCopy ; #FUNCTION# ==================================================================================================== ; Name...........: _LargeRawCopyUnbuffered ; Description....: Copy large memory blocks to files in such a way as to keep AutoIt GUIs responsive ; Syntax.........: _LargeRawCopyUnbuffered($pSrc, $iSrcSize, $sDest[, $iFlags = 0[, $iToRead = 2097152[, $iAlg = $CALG_MD5[, $sFunction = ""[, $vUserVar = Default]]]]]) ; Parameters.....: $pSrc - Pointer to source raw data ; $iSrcSize - Size of raw data ; $sDest - Destination file name, must not be an existing directory ; $iFlags - [Optional] Combine flags with BitOR ; | 1 - Overwrite existing file ; | 2 - Create destination directory structure ; | 8 - Verify source and destination are identical via bit by bit comparison ; |16 - Verify source and destination are identical via MD5 hash ; + If more than one verify flag is set, the smallest flag will take precedence ; $iToRead - [Optional] Size of the read buffer (Default = 8 MB) ; $iAlg - [Optional] Algorithm to use for file verification (Default = $CALG_MD5) ; + Available algorithms: $CALG_MD2, $CALG_MD4, $CALG_MD5, $CALG_SHA1 ; $sFunction - [Optional] Function to be called after each write operation (Default = "") ; + Function will be called with the following parameters: ; | 1 - Total bytes written ; | 2 - Total file size in bytes ; | 3 - Optional user variable ; $vUserVar - [Optional] User variable to pass to function (Default = Default) ; ; Return values..: Success - 1 ; Failure - 0 and sets @error ; |-1 - $iSrcSize may not be 0 ; | 1 - $pSrc and $iSrcSize point to inaccessible memory ; | 2 - Destination is an existing directory ; | 3 - Destination file exists and overwrite flag not set ; | 4 - Failed to create destination file ; | 5 - Write error during copy ; | 6 - Verify failed ; | 7 - Failed to set destination file size ; Author.........: Erik Pilsits ; Modified.......: ; Remarks........: ; Related........: ; Link...........: ; Example........: ; =============================================================================================================== Func _LargeRawCopyUnbuffered($pSrc, $iSrcSize, $sDest, $iFlags = 0, $iToRead = 2097152, $iAlg = $CALG_MD5, $sFunction = "", $vUserVar = Default) ; check source size If $iSrcSize = 0 Then Return SetError(-1, 0, 0) ; check source memory, 0 = success Local $ret = DllCall("kernel32.dll", "bool", "IsBadReadPtr", "ptr", $pSrc, "uint_ptr", $iSrcSize) If $ret[0] Then Return SetError(1, 0, 0) ; check / fix dest path syntax $sDest = StringReplace($sDest, "/", "\") _LFC_FixPath($sDest) ; set option flags Local $fOverwrite = (BitAND($iFlags, 1) = 1) Local $fCreate = (BitAND($iFlags, 2) = 2) Local $fVerify = 0 If (BitAND($iFlags, 8) = 8) Then ; bit by bit $fVerify = 1 ElseIf (BitAND($iFlags, 16) = 16) Then ; MD5 $fVerify = 2 EndIf ; check destination _LFC_CheckDestination("", $sDest, $fOverwrite, $fCreate) Switch @error Case 1 ; overwrite fail Return SetError(3, 0, 0) Case 2 ; no file name Return SetError(2, 0, 0) EndSwitch ; get destination disk cluster size for unbuffered i/o Local $ClusterSize = _FileEx_GetDiskClusterSize($sDest) ; if error, default to 512 and hope for the best, at worst the write operation will fail later on If @error Then $ClusterSize = 512 ; create new file for writing, overwrite Local $hDest = _FileEx_CreateFile($sDest, BitOR($GENERIC_READ, $GENERIC_WRITE), 0, $CREATE_ALWAYS, 0xA0000000) ; FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH If Not $hDest Then Return SetError(4, 0, 0) ; perform copy ; create aligned buffer $iToRead = Floor($iToRead / $ClusterSize) * $ClusterSize If $iToRead = 0 Then $iToRead = $ClusterSize Local $pRead = $pSrc Local $iWritten, $bytesRead = 0, $iRead = 0, $iTotal = 0, $mSrc = 0, $iWriteError = 0, $iVerifyError = 0 Local $apBuffers = _LFC_CreateBuffers($iToRead) Local $pBuffer = $apBuffers[0] Local $pvBuffer = $apBuffers[1] Local $alignedWrite = $iToRead While $bytesRead < $iSrcSize If $iToRead > ($iSrcSize - $bytesRead) Then $iToRead = $iSrcSize - $bytesRead ; copy memory to write buffer _LFC_RtlMoveMemory($pBuffer, $pRead, $iToRead) $iRead = $iToRead ; set aligned write size for final pass If $iRead < $alignedWrite Then $iRead = Ceiling($iRead / $ClusterSize) * $ClusterSize ; write data If Not _WinAPI_WriteFile($hDest, $pBuffer, $iRead, $iWritten) Or ($iRead <> $iWritten) Then $iWriteError = 1 ExitLoop EndIf If $sFunction Then $iTotal += $iToRead Call($sFunction, $iTotal, $iSrcSize, $vUserVar) EndIf If $fVerify = 1 Then ; compare data, using $iRead because it must be a cluster sized block of data If Not _LFC_BitCompare($hDest, $pBuffer, $pvBuffer, $iRead) Then $iVerifyError = 1 ExitLoop EndIf ElseIf $fVerify = 2 Then ; hash source inline $mSrc = _LFC_ChunkHash($mSrc, $pBuffer, $iToRead, $iAlg) EndIf ; ready next chunk $pRead += $iToRead $bytesRead += $iToRead WEnd ; cleanup _WinAPI_CloseHandle($hDest) If $fVerify = 2 Then ; finalize hash $mSrc = _LFC_ChunkHashFinal($mSrc) EndIf ; don't bother if errors above If (Not $iWriteError) And (Not $iVerifyError) Then ; set correct destination file size $hDest = _FileEx_CreateFile($sDest, BitOR($GENERIC_READ, $GENERIC_WRITE), 0, $OPEN_EXISTING, 0) If $hDest Then DllCall("kernel32.dll", "bool", "SetFilePointerEx", "handle", $hDest, "int64", $iSrcSize, "ptr", 0, "dword", 0) _WinAPI_SetEndOfFile($hDest) _WinAPI_CloseHandle($hDest) Else Return SetError(7, 0, 0) EndIf EndIf If $iWriteError Then Return SetError(5, 0, 0) Else If ($fVerify = 1) Then If $iVerifyError Then Return SetError(6, 0, 0) ElseIf ($fVerify = 2) Then ; hash destination and verify Local $mDest = _LFC_HashFile($sDest, $iAlg) If ($mSrc = "") Or ($mDest = "") Or ($mSrc <> $mDest) Then Return SetError(6, 0, 0) EndIf EndIf Return 1 EndFunc ;==>_LargeRawCopyUnbuffered #endregion FUNCTIONS #region INTERNAL FUNCTIONS Func _LFC_AllocBuffers(ByRef $apBuffers, $iBuffSize) Dim $apBuffers[2] = [ _ _MemVirtualAlloc(0, $iBuffSize, $MEM_COMMIT, $PAGE_READWRITE), _ _MemVirtualAlloc(0, $iBuffSize, $MEM_COMMIT, $PAGE_READWRITE) _ ] EndFunc ;==>_LFC_AllocBuffers Func _LFC_BitCompare($hDest, $pSrc, $pVerify, $iToVerify) ; if there are any errors at all, FAIL ; check memory ranges Local $ret = DllCall("kernel32.dll", "bool", "IsBadReadPtr", "ptr", $pSrc, "uint_ptr", $iToVerify) If @error Or $ret[0] Then Return SetError(1, 0, 0) $ret = DllCall("kernel32.dll", "bool", "IsBadReadPtr", "ptr", $pVerify, "uint_ptr", $iToVerify) If @error Or $ret[0] Then Return SetError(2, 0, 0) ; first move file pointer back by $iToVerify bytes $ret = DllCall("kernel32.dll", "bool", "SetFilePointerEx", "handle", $hDest, "int64", -$iToVerify, "ptr", 0, "dword", 1) ; FILE_CURRENT If @error Or (Not $ret[0]) Then Return SetError(3, 0, 0) ; read data just written to destination Local $iRead If Not _WinAPI_ReadFile($hDest, $pVerify, $iToVerify, $iRead) Or ($iRead <> $iToVerify) Then Return SetError(4, 0, 0) ; compare data= If Not _LFC_RtlCompareMemory($pSrc, $pVerify, $iToVerify) Then Return SetError(5, 0, 0) Else Return 1 EndIf EndFunc ;==>_LFC_BitCompare Func _LFC_CheckACLAdmin() Static Local $fChecked = False, $iSeSecurity = 0 ; check for admin rights and acquire SeSecurityPrivilege only once ; on successive calls, return previous value of $iSeSecurity or error If Not $fChecked Then $fChecked = True If IsAdmin() Then If _LFC_GetSESECURITYNAME() Then ; include SACL_SECURITY_INFORMATION $iSeSecurity = 0xF Else $iSeSecurity = 7 EndIf EndIf EndIf If $iSeSecurity Then Return $iSeSecurity Else Return SetError(1) EndIf EndFunc ;==>_LFC_CheckACLAdmin Func _LFC_CheckDestination($sSrc, ByRef $sDest, $fOverwrite, $fCreate) Local $iAttr = _FileEx_GetAttributes($sDest) Local $iErr = @error If ($iErr And (StringRight($sDest, 1) = "\")) Or ((Not $iErr) And (BitAND($iAttr, 0x10) = 0x10)) Then ; destination does not exist and should be a directory ; OR destination does exist and is a directory If $sSrc = "" Then ; raw copy, must provide a file name Return SetError(2) Else ; use source file name If StringRight($sDest, 1) <> "\" Then $sDest &= "\" ; add trailing \ $sDest &= StringRegExpReplace($sSrc, ".*\\", "") EndIf ElseIf $iErr And $fCreate Then ; destination does not exist and should be a file ; create destination *parent directory* _FileEx_CreateDirectory(StringRegExpReplace($sDest, "^(.*)\\.*?$", "${1}")) ElseIf Not $iErr Then ; destination exists and is a file ; check overwrite If $fOverwrite Then ; set FILE_ATTRIBUTE_NORMAL before attempting delete _FileEx_SetAttributes($sDest, 0x80) If Not FileDelete($sDest) Then Return SetError(1) Else Return SetError(1) EndIf EndIf ; else do nothing ; ie, destination is a file that doesn't exist and $fCreate is false ; if parent directory does not exist and is not created, CreateFile will fail EndFunc ;==>_LFC_CheckDestination Func _LFC_ChunkHash($hCryptHash, $pSrc, $iSize, $iAlg = $CALG_MD5) Local $aRet If $hCryptHash = 0 Then ; Create Hash object $aRet = DllCall(__Crypt_DllHandle(), "bool", "CryptCreateHash", "handle", __Crypt_Context(), "uint", $iAlg, "ptr", 0, "dword", 0, "handle*", 0) If @error Or (Not $aRet[0]) Then Return SetError(1, 0, -1) $hCryptHash = $aRet[5] ElseIf $hCryptHash = -1 Then ; previous error Return SetError(3, 0, -1) EndIf $aRet = DllCall(__Crypt_DllHandle(), "bool", "CryptHashData", "handle", $hCryptHash, "ptr", $pSrc, "dword", $iSize, "dword", $CRYPT_USERDATA) If @error Or (Not $aRet[0]) Then DllCall(__Crypt_DllHandle(), "bool", "CryptDestroyHash", "handle", $hCryptHash) Return SetError(2, 0, -1) EndIf Return $hCryptHash EndFunc ;==>_LFC_ChunkHash Func _LFC_ChunkHashFinal($hCryptHash) Local $iError, $vReturn If $hCryptHash = -1 Then ; previous error $iError = 1 $vReturn = "" $hCryptHash = 0 Else ; get hash size, in $aRet[3] Local $aRet = DllCall(__Crypt_DllHandle(), "bool", "CryptGetHashParam", "handle", $hCryptHash, "dword", $HP_HASHSIZE, "dword*", 0, "dword*", 4, "dword", 0) If @error Or (Not $aRet[0]) Then $iError = 2 $vReturn = "" Else ; get hash Local $hBuff = DllStructCreate("byte[" & $aRet[3] & "]") $aRet = DllCall(__Crypt_DllHandle(), "bool", "CryptGetHashParam", "handle", $hCryptHash, "dword", $HP_HASHVAL, "ptr", DllStructGetPtr($hBuff), "dword*", DllStructGetSize($hBuff), "dword", 0) If @error Or (Not $aRet[0]) Then $iError = 3 $vReturn = "" Else $iError = 0 $vReturn = DllStructGetData($hBuff, 1) EndIf EndIf EndIf ; Cleanup and return hash If $hCryptHash <> 0 Then DllCall(__Crypt_DllHandle(), "bool", "CryptDestroyHash", "handle", $hCryptHash) Return SetError($iError, 0, $vReturn) EndFunc ;==>_LFC_ChunkHashFinal Func _LFC_ControlBuffers($iBuffSize, $fCreate = True) Static Local $iPrevSize = 0, $apBuffers = 0 If $fCreate Then If (Not IsArray($apBuffers)) Or ($iBuffSize > $iPrevSize) Then _LFC_FreeBuffers() $iPrevSize = $iBuffSize _LFC_AllocBuffers($apBuffers, $iBuffSize) ; init crypt library, only once If Not __Crypt_RefCount() Then _Crypt_Startup() EndIf Return $apBuffers Else If IsArray($apBuffers) Then _MemVirtualFree($apBuffers[0], 0, $MEM_RELEASE) _MemVirtualFree($apBuffers[1], 0, $MEM_RELEASE) EndIf $iPrevSize = 0 $apBuffers = 0 EndIf EndFunc ;==>_LFC_ControlBuffers Func _LFC_CopyPathSD($sSrc, $sDest, $iSeSecurity) Local $pOwner, $pGroup, $pDACL, $pSACL, $pSD, $iProtect ; copy source security info _LFC_GetPathSD($sSrc, $pOwner, $pGroup, $pDACL, $pSACL, $pSD, $iProtect, $iSeSecurity) If @error Then Return SetError(1, 0, 0) ; set destination security info Local $iErr = 0 _LFC_SetPathSD($sDest, $pOwner, $pGroup, $pDACL, $pSACL, $iProtect, $iSeSecurity) If @error Then $iErr = @error DllCall("kernel32.dll", "handle", "LocalFree", "handle", $pSD) Return SetError($iErr, 0, (Not $iErr)) EndFunc ;==>_LFC_CopyPathSD Func _LFC_CreateBuffers($iBuffSize) Return _LFC_ControlBuffers($iBuffSize) EndFunc ;==>_LFC_CreateBuffers Func _LFC_CreateCompressedFile($sPath, $iFlag = 0) ;Local Const $FSCTL_SET_COMPRESSION = 0x0009C040 ;Local Const $FSCTL_GET_COMPRESSION = 0x0009003C ;Local Const $COMPRESSION_FORMAT_NONE = 0 ;Local Const $COMPRESSION_FORMAT_DEFAULT = 1 ;Local Const $COMPRESSION_FORMAT_LZNT1 = 2 ; create 0 byte file Local $hFile = _FileEx_CreateFile($sPath, BitOR($GENERIC_READ, $GENERIC_WRITE), 0, $CREATE_ALWAYS, $iFlag) If Not $hFile Then Return SetError(1, 0, 0) ; set compression state Local $aRet = DllCall("kernel32.dll", "bool", "DeviceIoControl", "handle", $hFile, "dword", 0x0009C040, "ushort*", 1, "dword", 2, _ "ptr", 0, "dword", 0, "dword*", 0, "ptr", 0) If @error Or (Not $aRet[0]) Then _WinAPI_CloseHandle($hFile) FileDelete($sPath) Return SetError(2, 0, 0) Else Return $hFile EndIf EndFunc ;==>_LFC_CreateCompressedFile Func _LFC_FixPath(ByRef $sPath) ; check for drive and make sure it ends in \ If StringRight($sPath, 1) = ":" Then $sPath &= "\" Else ; expand any relative path components ; _PathFull follows same rules as FileExists $sPath = _PathFull($sPath) EndIf EndFunc ;==>_LFC_FixPath Func _LFC_FixPathEx(ByRef $sSrc, ByRef $sDest) ; fix possible forward / $sSrc = StringReplace($sSrc, "/", "\") $sDest = StringReplace($sDest, "/", "\") ; remove trailing \'s from source only $sSrc = StringRegExpReplace($sSrc, "\\+$", "") ; convert to full paths _LFC_FixPath($sSrc) _LFC_FixPath($sDest) EndFunc ;==>_LFC_FixPathEx Func _LFC_FreeBuffers() _LFC_ControlBuffers(0, False) EndFunc ;==>_LFC_FreeBuffers Func _LFC_GetPathSD($sPath, ByRef $pOwner, ByRef $pGroup, ByRef $pDACL, ByRef $pSACL, ByRef $pSD, ByRef $iProtect, $iSeSecurity) ;Local Const $SE_FILE_OBJECT = 1 ;Local Const $OWNER_SECURITY_INFORMATION = 1 ;Local Const $GROUP_SECURITY_INFORMATION = 2 ;Local Const $DACL_SECURITY_INFORMATION = 4 ;Local Const $SACL_SECURITY_INFORMATION = 8 ; ;Local Const $SE_DACL_PROTECTED = 0x1000 ;Local Const $PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000 ;Local Const $UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000 ; ;Local Const $SE_SACL_PROTECTED = 0x2000 ;Local Const $PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000 ;Local Const $UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000 Local $aRet = DllCall("advapi32.dll", "dword", "GetNamedSecurityInfoW", "wstr", $sPath, "int", 1, "dword", $iSeSecurity, _ "ptr*", 0, "ptr*", 0, "ptr*", 0, "ptr*", 0, "ptr*", 0) If @error Or $aRet[0] Then Return SetError(1, 0, 0) $pOwner = $aRet[4] $pGroup = $aRet[5] $pDACL = $aRet[6] $pSACL = $aRet[7] $pSD = $aRet[8] $iProtect = 0 ; default no change ; query SACL, DACL protected states and set flags $aRet = DllCall("advapi32.dll", "bool", "GetSecurityDescriptorControl", "ptr", $pSD, "word*", 0, "dword*", 0) If Not @error And $aRet[0] Then If BitAND($aRet[2], 0x1000) Then ; DACL protected $iProtect = BitOR($iProtect, 0x80000000) Else ; unprotected $iProtect = BitOR($iProtect, 0x20000000) EndIf If BitAND($aRet[2], 0x2000) Then ; SACL protected $iProtect = BitOR($iProtect, 0x40000000) Else ; unprotected $iProtect = BitOR($iProtect, 0x10000000) EndIf EndIf Return 1 EndFunc ;==>_LFC_GetPathSD Func _LFC_GetSESECURITYNAME() Local $return = False Local $tagLUIDANDATTRIB = "int64 Luid;dword Attributes" Local $count = 1 Local $tagTOKENPRIVILEGES = "dword PrivilegeCount;byte LUIDandATTRIB[" & $count * 12 & "]" ; count of LUID structs * sizeof LUID struct Local $TOKEN_ADJUST_PRIVILEGES = 0x20 Local $SE_PRIVILEGE_ENABLED = 0x2 Local $curProc = DllCall("kernel32.dll", "ptr", "GetCurrentProcess") If @error Then Return False Local $call = DllCall("advapi32.dll", "int", "OpenProcessToken", "ptr", $curProc[0], "dword", $TOKEN_ADJUST_PRIVILEGES, "ptr*", 0) If (@error Or (Not $call[0])) Then Return False Local $hToken = $call[3] $call = DllCall("advapi32.dll", "int", "LookupPrivilegeValueW", "ptr", 0, "wstr", "SeSecurityPrivilege", "int64*", 0) If ((Not @error) And $call[0]) Then Local $iLuid = $call[3] Local $TP = DllStructCreate($tagTOKENPRIVILEGES) Local $LUID = DllStructCreate($tagLUIDANDATTRIB, DllStructGetPtr($TP, "LUIDandATTRIB")) DllStructSetData($TP, "PrivilegeCount", $count) DllStructSetData($LUID, "Luid", $iLuid) DllStructSetData($LUID, "Attributes", $SE_PRIVILEGE_ENABLED) $call = DllCall("advapi32.dll", "int", "AdjustTokenPrivileges", "ptr", $hToken, "int", 0, "ptr", DllStructGetPtr($TP), "dword", 0, "ptr", 0, "ptr", 0) If Not @error Then $return = ($call[0] <> 0) ; $call[0] <> 0 is success EndIf DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hToken) Return SetError(Number(Not $return), 0, $return) EndFunc ;==>_LFC_GetSESECURITYNAME Func _LFC_HashFile($sFile, $iAlg = $CALG_MD5) ; check target exists and is a file If Not FileExists($sFile) Or StringInStr(FileGetAttrib($sFile), "D") Then Return SetError(1, 0, "") Local $sHash = _LFC_HashFileInternal($sFile, $iAlg) If @error Or ($sHash = "") Then Return SetError(2, 0, "") Else Return $sHash EndIf EndFunc ;==>_LFC_HashFile Func _LFC_HashFileInternal($sFile, $iAlg = $CALG_MD5) Local $hSrc = _FileEx_CreateFile($sFile, $GENERIC_READ, $FILE_SHARE_READ, $OPEN_EXISTING, 0) If Not $hSrc Then Return SetError(1, 0, "") Local $iSize = _WinAPI_GetFileSizeEx($hSrc) Local $iRead, $iReadError = 0, $sHash = 0, $iToRead = (1024 ^ 2) * 2 ; create 2M hashing buffer only once Static Local $pBuffer = _MemVirtualAlloc(0, $iToRead, $MEM_COMMIT, $PAGE_READWRITE) Local $bytesRead = 0 While $bytesRead < $iSize If $iToRead > ($iSize - $bytesRead) Then $iToRead = $iSize - $bytesRead If Not _WinAPI_ReadFile($hSrc, $pBuffer, $iToRead, $iRead) Then $iReadError = 1 ExitLoop EndIf $sHash = _LFC_ChunkHash($sHash, $pBuffer, $iRead, $iAlg) If @error Then $iReadError = 1 ExitLoop EndIf $bytesRead += $iRead WEnd _WinAPI_CloseHandle($hSrc) $sHash = _LFC_ChunkHashFinal($sHash) If $iReadError Then Return SetError(2, 0, "") Else Return $sHash EndIf EndFunc ;==>_LFC_HashFileInternal Func _LFC_RtlCompareMemory($pSrc1, $pSrc2, $iSize) Local $ret = DllCall("ntdll.dll", "ulong_ptr", "RtlCompareMemory", "ptr", $pSrc1, "ptr", $pSrc2, "ulong_ptr", $iSize) If @error Or ($ret[0] <> $iSize) Then Return SetError(1, 0, 0) Else Return 1 EndIf EndFunc ;==>_LFC_RtlCompareMemory Func _LFC_RtlMoveMemory($pDest, $pSrc, $iSize) DllCall("ntdll.dll", "none", "RtlMoveMemory", "ptr", $pDest, "ptr", $pSrc, "ulong_ptr", $iSize) If @error Then Return SetError(1, 0, 0) Else Return 1 EndIf EndFunc ;==>_LFC_RtlMoveMemory Func _LFC_SetPathSD($sPath, $pOwner, $pGroup, $pDACL, $pSACL, $iProtect, $iSeSecurity) Local $aRet = DllCall("advapi32.dll", "dword", "SetNamedSecurityInfoW", "wstr", $sPath, "int", 1, "dword", BitOR($iProtect, $iSeSecurity), _ "ptr", $pOwner, "ptr", $pGroup, "ptr", $pDACL, "ptr", $pSACL) If @error Or $aRet[0] Then Return SetError(2, 0, 0) Return 1 EndFunc ;==>_LFC_SetPathSD Func _LFC_SizeCompare($hFile1, $hFile2) Local $iSize1 If IsPtr($hFile1) Then $iSize1 = DllCall("kernel32.dll", "bool", "GetFileSizeEx", "handle", $hFile1, "int64*", 0) If @error Or (Not $iSize1[0]) Then Return SetError(1, 0, 0) $iSize1 = $iSize1[2] Else ; for _LargeRawCopy $iSize1 = $hFile1 EndIf Local $iSize2 = DllCall("kernel32.dll", "bool", "GetFileSizeEx", "handle", $hFile2, "int64*", 0) If @error Or (Not $iSize2[0]) Then Return SetError(2, 0, 0) ; compare size If $iSize1 = $iSize2[2] Then Return 1 Else Return SetError(3, 0, 0) EndIf EndFunc ;==>_LFC_SizeCompare #endregion INTERNAL FUNCTIONS