rover Posted November 11, 2008 Share Posted November 11, 2008 an example using SetFilePointerEx to check integrity of large file copies works on files above 2gig, but not very fast. tested up to 4.5gig Move along, nothing else to see here. expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** ;#AutoIt3Wrapper_Change2CUI=y #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 ;#Obfuscator_Parameters=/striponly #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <WinAPI.au3> Opt('MustDeclareVars', 1) Global Const $INVALID_HANDLE_VALUE = 0xFFFFFFFF Global Const $FILE_BEGIN = 0 ; The starting point is zero (0) or the beginning of the file. Global Const $FILE_CURRENT = 1 ; The starting point is the current value of the file pointer. Global Const $FILE_END = 2 ; The starting point is the current end-of-file position. Global $hInFile1, $hInFile2 Global $iDLL = -1, $iPos Global $sFile_Src = FileOpenDialog("Select source file", @HomeDrive & "\", "All (*.*)", 1 + 2) Global $sFile_Copy = FileOpenDialog("Select copied file", @HomeDrive & "\", "All (*.*)", 1 + 2) ;If Not $CmdLine[0] = 2 Then Exit ;Global $sFile_Src = $CmdLine[1] ;Global $sFile_Copy = $CmdLine[2] Switch _CheckFileIntegrity($sFile_Src, $sFile_Copy, $iPos) Case 0 MsgBox(262144, "File Integrity Check", "File: " & _ $sFile_Copy & @CRLF & "Byte position: " & $iPos & @CRLF & "FAILED") Case 1 MsgBox(262144, "File Integrity Check", "File: " & _ $sFile_Copy & @CRLF & "Time: " & @extended & " Seconds" & @CRLF & "PASSED") Case - 1 MsgBox(262144, "File Integrity Check", "Error code: " & _ @error & @CRLF & "GetLastError [" & _WinAPI_GetLastError() & "] " & _WinAPI_GetLastErrorMessage()) EndSwitch Func _CheckFileIntegrity($sFileSrc, $sFileCopy, ByRef $iInt64Pos, $iBlockSize = -1) ;Author: rover ;tested with large files up to 4.5gig ;Parameters: ;$sFileSrc - Path/filename to source file ;$sFileCopy - Path/filename to copied file ;$iInt64Pos - ByRef return failed block byte position ;$iBlockSize - Block size in bytes to test (Default size 1048576 bytes) ;Return ; 0 = Fail - Error in copied file (byte position of fail returned ByRef in $iInt64Pos) ; 1 = Pass - Files identical (ByRef return in $iInt64Pos is 0) ;-1 = Error - Error in parameters - last error set (ByRef return in $iInt64Pos is -1) $iInt64Pos = -1 If (Not FileExists($sFileSrc)) Or (Not FileExists($sFileCopy)) Then Return SetError(1, _WinAPI_SetLastError(2), -1) EndIf If (Not $iBlockSize) Or ($iBlockSize = -1) Then $iBlockSize = 1024 * 1024 If FileGetSize($sFileSrc) < $iBlockSize Then MsgBox(262144, "File Integrity Check - ERROR", _ "File is smaller than block size" & @CRLF & "Src: " & _ FileGetSize($sFileSrc) & @CRLF & "Block size: " & $iBlockSize, 5) Return SetError(1, _WinAPI_SetLastError(87), -1) EndIf Local $iFlagError = 0, $iDLL = -1, $iTimer = 0, $iFlagRemain = 0 Local $tBuffer1, $tBuffer2, $pBuffer1, $pBuffer2 Local $aResult1, $aResult2, $iLastError, $iError = 6 Local $iRead1 = 0, $iRead2 = 0, $iFilePos = 0, $iCompared = 1 Local $iMaxCompare, $iBlockTotal, $iRemainder If (Not $iBlockSize) Or ($iBlockSize = -1) Then $iBlockSize = 1024 * 1024 $iMaxCompare = FileGetSize($sFileSrc) $iBlockTotal = Floor($iMaxCompare / $iBlockSize) $iRemainder = $iMaxCompare - $iBlockTotal * $iBlockSize If $iRemainder Then $iBlockTotal += 1 $iFlagRemain = 1 EndIf If IsDeclared("hInFile1") = 0 Or IsDeclared("hInFile2") = 0 Or IsDeclared("iDLL") = 0 Then ConsoleWrite("!Variables used without being declared" & @CRLF) _WinAPI_SetLastError(87) ; set last error for missing global scope variables Return SetError(2, 0, -1) EndIf ConsoleWrite("+Filesize : " & $iMaxCompare & @CRLF) ConsoleWrite("+Block size : " & $iBlockSize & @CRLF) ConsoleWrite("+Remainder block : " & $iRemainder & @CRLF) ConsoleWrite("+Number of blocks : " & $iBlockTotal & @CRLF) ConsoleWrite("+Block total : " & ($iBlockTotal * $iBlockSize) + ($iRemainder - $iBlockSize) & @CRLF) $hInFile1 = _WinAPI_CreateFile($sFileSrc, 2, 2, 6) If Not $hInFile1 Or $hInFile1 = $INVALID_HANDLE_VALUE Then Return SetError(3, 0, -1) $hInFile2 = _WinAPI_CreateFile($sFileCopy, 2, 2, 6) If Not $hInFile2 Or $hInFile2 = $INVALID_HANDLE_VALUE Then _WinAPI_CloseHandle($hInFile1) Return SetError(4, 0, -1) EndIf $iDLL = DllOpen("Kernel32.dll") If $iDLL = -1 Then If $hInFile1 And $hInFile1 <> $INVALID_HANDLE_VALUE Then _WinAPI_CloseHandle($hInFile1) If $hInFile2 And $hInFile2 <> $INVALID_HANDLE_VALUE Then _WinAPI_CloseHandle($hInFile2) $hInFile1 = "" $hInFile2 = "" _WinAPI_SetLastError(6) ; set last error for invalid handle Return SetError(5, 0, -1) EndIf $iTimer = TimerInit() Do ;Sleep(10) $aResult1 = DllCall($iDLL, "dword", "SetFilePointerEx", "hwnd", _ $hInFile1, "uint64", $iFilePos, "uint64*", 0, "dword", $FILE_BEGIN) If @error Or Not $aResult1[0] Then $iError = 6 If Not _WinAPI_GetLastError() Then _WinAPI_SetLastError(87) ExitLoop EndIf $aResult2 = DllCall($iDLL, "dword", "SetFilePointerEx", "hwnd", _ $hInFile2, "uint64", $iFilePos, "uint64*", 0, "dword", $FILE_BEGIN) If @error Or Not $aResult2[0] Then $iError = 7 If Not _WinAPI_GetLastError() Then _WinAPI_SetLastError(87) ExitLoop EndIf $tBuffer1 = DllStructCreate("ubyte [" & $iBlockSize & "]") If @error Or Not IsDllStruct($tBuffer1) Then $iError = 8 If Not _WinAPI_GetLastError() Then _WinAPI_SetLastError(87) ExitLoop EndIf $pBuffer1 = DllStructGetPtr($tBuffer1) If Not __WinAPI_ReadFile($hInFile1, $pBuffer1, $iBlockSize, $iRead1, 0, $iDLL) Then $iError = 9 ExitLoop EndIf $tBuffer2 = DllStructCreate("ubyte [" & $iBlockSize & "]") If @error Or Not IsDllStruct($tBuffer2) Then $iError = 10 If Not _WinAPI_GetLastError() Then _WinAPI_SetLastError(87) ExitLoop EndIf $pBuffer2 = DllStructGetPtr($tBuffer2) If Not __WinAPI_ReadFile($hInFile2, $pBuffer2, $iBlockSize, $iRead2, 0, $iDLL) Then $iError = 11 ExitLoop EndIf ;ConsoleWrite("- File1 pointer position: " & $aResult1[3] & @CRLF) ; debug only: consolewrites slow down loop ;ConsoleWrite(" [" & $iRead1 & "] file1 bytes read" & @CRLF) If $iRead1 <> $iRead2 Or Not $iRead1 Or Not $iRead2 Then ; compare returned size of read data to block size _WinAPI_SetLastError(87) $iError = 12 ExitLoop EndIf If DllStructGetData($tBuffer1, 1) <> DllStructGetData($tBuffer2, 1) Then $iFlagError = 1 If @error Then _WinAPI_SetLastError(87) $iError = 13 ExitLoop EndIf $tBuffer1 = "" ; clear memory $tBuffer2 = "" If $iFlagError Then ExitLoop $iFilePos += $iRead1 $iCompared += 1 If $iCompared = $iBlockTotal And $iFlagRemain Then $iBlockSize = $iRemainder Until $iCompared = ($iBlockTotal + 1) $iLastError = _WinAPI_GetLastError() If $iLastError Then ConsoleWrite("!GetLastError [" & $iLastError & "] " & _WinAPI_GetLastErrorMessage()) If $iTimer Then ConsoleWrite("-Duration in seconds: " & Round(TimerDiff($iTimer) / 1000) & @CRLF) If $iDLL <> -1 Then DllClose($iDLL) If $hInFile1 And $hInFile1 <> $INVALID_HANDLE_VALUE Then _WinAPI_CloseHandle($hInFile1) If $hInFile2 And $hInFile2 <> $INVALID_HANDLE_VALUE Then _WinAPI_CloseHandle($hInFile2) $iDLL = -1 $hInFile1 = "" $hInFile2 = "" If $iFlagError Then ConsoleWrite("!Error found in file : " & $sFileCopy & @CRLF) ConsoleWrite("!Error found in block number : " & $iCompared & @CRLF) ConsoleWrite("!Block start position : " & $aResult2[3] & @CRLF) ConsoleWrite("!Block end position : " & $aResult2[3] + $iRead1 & @CRLF) ConsoleWrite("!Block size : " & $iRead1 & @CRLF) $iInt64Pos = $aResult2[3] Return SetError(6, 0, 0) EndIf If $iCompared = ($iBlockTotal + 1) Then $iInt64Pos = 0 ConsoleWrite("-No errors found in file: " & $sFileCopy & @CRLF) Return SetError(0, Round(TimerDiff($iTimer) / 1000), 1) EndIf _WinAPI_SetLastError($iLastError) Return SetError($iError, 0, -1) EndFunc ;==>_CheckFileIntegrity Func __WinAPI_ReadFile($hFile, $pBuffer, $iToRead, ByRef $iRead, $pOverlapped = 0, $hDLL = -1) ; Modified to use dll handle and removed dllstruct code Local $aResult $iRead = 0 ; extended not set in SetError()(only to get code on one line) If Not $iToRead Then Return SetError(1, _WinAPI_SetLastError(87), False) If Not $hDLL Or $hDLL = -1 Then $hDLL = "Kernel32.dll" $aResult = DllCall($hDLL, "int", "ReadFile", "hwnd", $hFile, "ptr", _ $pBuffer, "int", $iToRead, "int*", 0, "ptr", $pOverlapped) If @error Or ($iToRead <> $aResult[4]) Then Return SetError(@error, _WinAPI_SetLastError(87), False) $iRead = $aResult[4] Return SetError(@error, 0, $aResult[0] <> 0) EndFunc ;==>__WinAPI_ReadFile ; if exiting while scanning files (tray icon menu exit etc.) this allows for handle closing Func OnAutoItExit() If _WinAPI_GetLastError() Then ConsoleWrite("!GetLastError [" & _WinAPI_GetLastError() & "] " & _WinAPI_GetLastErrorMessage()) EndIf If $iDLL <> -1 Then DllClose($iDLL) If $hInFile1 And $hInFile1 <> $INVALID_HANDLE_VALUE Then _WinAPI_CloseHandle($hInFile1) If $hInFile2 And $hInFile2 <> $INVALID_HANDLE_VALUE Then _WinAPI_CloseHandle($hInFile2) EndFunc ;==>OnAutoItExit I see fascists... Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now