KaFu Posted February 12, 2013 Posted February 12, 2013 (edited) HiHo Forum ,I'm currently trying to create a working example for ReadFileScatter.http://msdn.microsoft.com/en-us/library/windows/desktop/aa365469(v=vs.85).aspxhttp://en.wikipedia.org/wiki/Vectored_I/OThe code is based on my example "Overlapped (Asynchronous) & UnBuffered ReadFile Example"What should the example do? Extract 3 * 16 KB from @AutoItExe and show it in a MsgBox(), first 16KB, 16KB from the middle of the file and the last 16KB of the file.The problem seems to be in my definition of the FILE_SEGMENT_ELEMENT structure, the function returns "998 Invalid access to memory location".typedef union _FILE_SEGMENT_ELEMENT { PVOID64 Buffer; ULONGLONG Alignment;}FILE_SEGMENT_ELEMENT, *PFILE_SEGMENT_ELEMENT;How to translate this into a tag for a DllStructCreate() call?expandcollapse popup#region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_UseX64=n #AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <StructureConstants.au3> #include <..\WinAPIEx_3.8_3380\WinAPIEx.au3> #include <Memory.au3> #include <array.au3> Global $nBytes, $hFile Global Const $ERROR_IO_INCOMPLETE = 996 ; Overlapped I/O event is not in a signaled state Global Const $ERROR_IO_PENDING = 997 ; Overlapped I/O operation is in progress Global Const $FILE_FLAG_OVERLAPPED = 0x40000000 Global Const $FILE_FLAG_NO_BUFFERING = 0x20000000 $sFile = @AutoItExe $aDrive = _WinAPI_GetDriveNumber(StringLeft($sFile, 2)) $aGeometry = _WinAPI_GetDriveGeometryEx($aDrive[1]) ; 'Bytes per Sector' = $aGeometry[4] ConsoleWrite(_WinAPI_GetLastErrorMessage() & @TAB & @error & @CRLF) ; FILE_FLAG_NO_BUFFERING ; File access sizes, including the optional file offset in the OVERLAPPED structure, if specified, ; must be for a number of bytes that is an integer multiple of the volume sector size $iBytesToRead_Total = 16384 ; 16KB per Block / 3 blocks total $iBytesToRead_Segment_Size = $aGeometry[4] $iBytesToRead_Segments = $iBytesToRead_Total / $iBytesToRead_Segment_Size ConsoleWrite("$iBytesToRead_Total " & $iBytesToRead_Total & @CRLF) ConsoleWrite("$iBytesToRead_Segment_Size " & $iBytesToRead_Segment_Size & @CRLF) ConsoleWrite("$iBytesToRead_Segments " & $iBytesToRead_Segments & @CRLF) ; The array must contain enough elements to store nNumberOfBytesToRead bytes of data, plus one element for the terminating NULL. ; For example, if there are 40 KB to be read and the page size is 4 KB, the array must have 11 elements that includes 10 for the data and one for the NULL. Local $tag_FILE_SEGMENT_ELEMENT Local $t_FILE_SEGMENT_ELEMENT_array[3] Local $p_FILE_SEGMENT_ELEMENT_array[3] For $y = 0 To 2 $tag_FILE_SEGMENT_ELEMENT = "" For $i = 1 To $iBytesToRead_Segments + 1 $tag_FILE_SEGMENT_ELEMENT &= "UINT64;ULONGLONG;" Next $t_FILE_SEGMENT_ELEMENT_array[$y] = DllStructCreate($tag_FILE_SEGMENT_ELEMENT) For $i = 0 To $iBytesToRead_Segments DllStructSetData($t_FILE_SEGMENT_ELEMENT_array[$y], ($i * 2) + 1, DllStructGetPtr(DllStructCreate("byte[" & $iBytesToRead_Segment_Size & "]", _MemVirtualAlloc(0, $iBytesToRead_Segment_Size, $MEM_COMMIT, $PAGE_READWRITE)))) Next $p_FILE_SEGMENT_ELEMENT_array[$y] = DllStructGetPtr($t_FILE_SEGMENT_ELEMENT_array[$y]) Next $iTimer = TimerInit() $hFile = _WinAPI_CreateFileEx($sFile, 3, $GENERIC_READ, 7, BitOR($FILE_ATTRIBUTE_NORMAL, $FILE_FLAG_OVERLAPPED, $FILE_FLAG_NO_BUFFERING)) $iFileGetSize = _WinAPI_GetFileSizeEx($hFile) ConsoleWrite(@CRLF & "+ Filesize " & $iFileGetSize & @CRLF & @CRLF) $iTimer_0 = TimerDiff($iTimer) ; Global Const $tagOVERLAPPED = "int Internal;int InternalHigh;int Offset;int OffsetHigh;int hEvent" $tOverlapped1 = DllStructCreate($tagOVERLAPPED) $pOverlapped1 = DllStructGetPtr($tOverlapped1) ConsoleWrite("_ReadFileScatter #1" & @TAB & _ReadFileScatter($hFile, $p_FILE_SEGMENT_ELEMENT_array[0], $iBytesToRead_Total, $pOverlapped1) & @CRLF) Func _ReadFileScatter($hFile, $FILE_SEGMENT_ELEMENT_array, $nNumberOfBytesToRead, $pOverlapped) ; ReadFileScatter ; http://msdn.microsoft.com/en-us/library/windows/desktop/aa365469(v=vs.85).aspx #cs BOOL WINAPI ReadFileScatter( _In_ HANDLE hFile, _In_ FILE_SEGMENT_ELEMENT aSegmentArray[], _In_ DWORD nNumberOfBytesToRead, _Reserved_ LPDWORD lpReserved, _Inout_ LPOVERLAPPED lpOverlapped ); #ce ConsoleWrite("_ReadFileScatter START" & @CRLF) Local $iRes = DllCall("kernel32.dll", "bool", "ReadFileScatter", "ptr", $hFile, "ptr", $FILE_SEGMENT_ELEMENT_array, "dword", $nNumberOfBytesToRead, "ptr", 0, "ptr", $pOverlapped) ConsoleWrite("_ReadFileScatter END" & @CRLF) ConsoleWrite(_WinAPI_GetLastError() & @TAB & _WinAPI_GetLastErrorMessage() & @CRLF) Return $iRes[0] EndFunc ;==>_ReadFileScatter $iTimer_1 = TimerDiff($iTimer) $sTimer_1 = _WinAPI_GetLastError() $tOverlapped2 = DllStructCreate($tagOVERLAPPED) $pOverlapped2 = DllStructGetPtr($tOverlapped2) $iOffset = Int(($iFileGetSize / 2) - ($iBytesToRead_Total / 2 + 1)) $iOffset = (Floor($iOffset / $iBytesToRead_Segment_Size)) * $iBytesToRead_Segment_Size DllStructSetData($tOverlapped2, "Offset", _WinAPI_LoDWord($iOffset)) ; Setting "Filepointer" to the middle of the file (SetFilePointer is not valid for overlapped operations) DllStructSetData($tOverlapped2, "OffsetHigh", _WinAPI_HiDWord($iOffset)) ConsoleWrite("_ReadFileScatter #2" & @TAB & _ReadFileScatter($hFile, $p_FILE_SEGMENT_ELEMENT_array[1], $iBytesToRead_Total, $pOverlapped2) & @CRLF) $iTimer_2 = TimerDiff($iTimer) $sTimer_2 = _WinAPI_GetLastError() $tOverlapped3 = DllStructCreate($tagOVERLAPPED) $pOverlapped3 = DllStructGetPtr($tOverlapped3) $iOffset = $iFileGetSize - $iBytesToRead_Total $iOffset = (Floor($iOffset / $iBytesToRead_Segment_Size)) * $iBytesToRead_Segment_Size DllStructSetData($tOverlapped3, "Offset", _WinAPI_LoDWord($iOffset)) ; Setting "Filepointer" to the end of the file (SetFilePointer is not valid for overlapped operations) DllStructSetData($tOverlapped3, "OffsetHigh", _WinAPI_HiDWord($iOffset)) ConsoleWrite("_ReadFileScatter #3" & @TAB & _ReadFileScatter($hFile, $p_FILE_SEGMENT_ELEMENT_array[2], $iBytesToRead_Total, $pOverlapped3) & @CRLF) $iTimer_3 = TimerDiff($iTimer) $sTimer_3 = _WinAPI_GetLastError() $sRes1 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped1, $nBytes) $sRes1 = $sRes1 & @TAB & $nBytes $iTimer_4 = TimerDiff($iTimer) $sTimer_4 = _WinAPI_GetLastError() $sRes2 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped2, $nBytes) $sRes2 = $sRes2 & @TAB & $nBytes $iTimer_5 = TimerDiff($iTimer) $sTimer_5 = _WinAPI_GetLastError() $sRes3 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped3, $nBytes) $sRes3 = $sRes3 & @TAB & $nBytes $iTimer_6 = TimerDiff($iTimer) $sTimer_6 = _WinAPI_GetLastError() _WinAPI_CloseHandle($hFile) $iTimer_7 = TimerDiff($iTimer) $sTimer_7 = _WinAPI_GetLastError() $sRes4 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped1, $nBytes) $sRes4 = $sRes4 & @TAB & $nBytes $sRes5 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped2, $nBytes) $sRes5 = $sRes5 & @TAB & $nBytes $sRes6 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped3, $nBytes) $sRes6 = $sRes6 & @TAB & $nBytes $iTimer = TimerInit() $t_ReadFile_Standard = _ReadFile_Standard($sFile, $iFileGetSize) ConsoleWrite("_WinAPI_CloseHandle - Before " & $sRes1 & @TAB & $sRes2 & @TAB & $sRes3 & @CRLF) ConsoleWrite("_WinAPI_CloseHandle - After " & $sRes4 & @TAB & $sRes5 & @TAB & $sRes6 & @CRLF & @CRLF) ConsoleWrite($iTimer_0 & @CRLF & $iTimer_1 & @CRLF & $iTimer_2 & @CRLF & $iTimer_3 & @CRLF & $iTimer_4 & @CRLF & $iTimer_5 & @CRLF & $iTimer_6 & @CRLF & $iTimer_7 & @CRLF & @CRLF & TimerDiff($iTimer) & @CRLF & @CRLF) ConsoleWrite($sTimer_1 & @CRLF & $sTimer_2 & @CRLF & $sTimer_3 & @CRLF & $sTimer_4 & @CRLF & $sTimer_5 & @CRLF & $sTimer_6 & @CRLF & $sTimer_7 & @CRLF) MsgBox(0, "", "ReadFileScatter" & @CRLF & StringLeft(DllStructGetData(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[0], 1), 1), 5) & StringRight(DllStructGetData(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[0], 32), 1), 5) & @CRLF _ & StringLeft(DllStructGetData(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[1], 1), 1), 5) & StringRight(DllStructGetData(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[1], 32), 1), 5) & @CRLF _ & StringLeft(DllStructGetData(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[2], 1), 1), 5) & StringRight(DllStructGetData(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[2], 32), 1), 5) & @CRLF _ & @CRLF & @CRLF & "ReadFile Standard" & @CRLF _ & StringLeft(DllStructGetData($t_ReadFile_Standard, 1), 5) & StringRight(DllStructGetData($t_ReadFile_Standard, 1), 5) & @CRLF _ & StringLeft(DllStructGetData($t_ReadFile_Standard, 2), 5) & StringRight(DllStructGetData($t_ReadFile_Standard, 2), 5) & @CRLF _ & StringLeft(DllStructGetData($t_ReadFile_Standard, 3), 5) & StringRight(DllStructGetData($t_ReadFile_Standard, 3), 5)) For $y = 0 To 2 For $i = 1 To $iBytesToRead_Segments + 1 ConsoleWrite($y & @TAB & $i & @TAB & _MemVirtualFree(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[$y], $i), 0, $MEM_RELEASE) & @CRLF) Next Next Func _ReadFile_Standard($sFile, $iFileGetSize, $iFlag = 0) Local $hFile = _WinAPI_CreateFileEx($sFile, 3, $GENERIC_READ, 7, $iFlag), $nBytes If $hFile = 0 Then Return SetError(4) ;"File was locked and could not be analyzed..." Local $tBuffer = DllStructCreate("byte[" & $iBytesToRead_Total & "];byte[" & $iBytesToRead_Total & "];byte[" & $iBytesToRead_Total & "]") _WinAPI_ReadFile($hFile, DllStructGetPtr($tBuffer, 1), $iBytesToRead_Total, $nBytes) $iOffset = Int(($iFileGetSize / 2) - ($iBytesToRead_Total / 2 + 1)) $iOffset = (Floor($iOffset / $iBytesToRead_Segment_Size)) * $iBytesToRead_Segment_Size _WinAPI_SetFilePointerEx($hFile, $iOffset) _WinAPI_ReadFile($hFile, DllStructGetPtr($tBuffer, 2), $iBytesToRead_Total, $nBytes) $iOffset = $iFileGetSize - $iBytesToRead_Total $iOffset = (Floor($iOffset / $iBytesToRead_Segment_Size)) * $iBytesToRead_Segment_Size _WinAPI_SetFilePointerEx($hFile, $iOffset) ; $iBytesToRead/2 +1 _WinAPI_ReadFile($hFile, DllStructGetPtr($tBuffer, 3), $iBytesToRead_Total, $nBytes) _WinAPI_CloseHandle($hFile) Return $tBuffer EndFunc ;==>_ReadFile_StandardBest Regards Edited March 3, 2013 by KaFu  OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2025-May-18) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16)
KaFu Posted February 12, 2013 Author Posted February 12, 2013 (edited) Well, got it working... but I don't understand why ... MSDN: "The array must contain enough elements to store nNumberOfBytesToRead bytes of data, plus one element for the terminating NULL. For example, if there are 40 KB to be read and the page size is 4 KB, the array must have 11 elements that includes 10 for the data and one for the NULL." If I would follow this, my file segment count should be something like this: $iBytesToRead_Segments = $iBytesToRead_Total / $iBytesToRead_Segment_Size + 1 But that does not work and throws and error, strangely this works fine (look at the buffer content in the console) $iBytesToRead_Segments = $iBytesToRead_Total / $iBytesToRead_Segment_Size * 2 expandcollapse popup#region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_UseX64=n #AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Array.au3> #include <StructureConstants.au3> #include <Memory.au3> #include <..\WinAPIEx_3.8_3380\WinAPIEx.au3> Global $nBytes, $hFile Global Const $ERROR_IO_INCOMPLETE = 996 ; Overlapped I/O event is not in a signaled state Global Const $ERROR_IO_PENDING = 997 ; Overlapped I/O operation is in progress Global Const $FILE_FLAG_NO_BUFFERING = 0x20000000 ; FILE_FLAG_NO_BUFFERING ; File access sizes, including the optional file offset in the OVERLAPPED structure, if specified, ; must be for a number of bytes that is an integer multiple of the volume sector size Global Const $FILE_FLAG_OVERLAPPED = 0x40000000 $sFile = @AutoItExe $iBytesToRead_Total = 16384 ; Amount of data to fetch per block in byte, 16KB per Block / 3 blocks total $aSystemInfo = _WinAPI_GetSystemInfo() $iBytesToRead_Segment_Size = $aSystemInfo[1] ; The page size and the granularity of page protection and commitment $iBytesToRead_Segments = Ceiling($iBytesToRead_Total / $iBytesToRead_Segment_Size) * 2 ; * 2 ???? ====> see next line from the documentation, a +1 would have made more sense here $iBytesToRead_Total = $iBytesToRead_Segments * $iBytesToRead_Segment_Size / 2 ; The array must contain enough elements to store nNumberOfBytesToRead bytes of data, plus one element for the terminating NULL. ; For example, if there are 40 KB to be read and the page size is 4 KB, the array must have 11 elements that includes 10 for the data and one for the NULL. ConsoleWrite("$iBytesToRead_Total " & $iBytesToRead_Total & @CRLF) ConsoleWrite("$iBytesToRead_Segment_Size " & $iBytesToRead_Segment_Size & @CRLF) ConsoleWrite("$iBytesToRead_Segments " & $iBytesToRead_Segments & @CRLF) Local $tag_FILE_SEGMENT_ELEMENT Local $t_FILE_SEGMENT_ELEMENT_array[3][$iBytesToRead_Segments + 2] Local $p_FILE_SEGMENT_ELEMENT_array[3][$iBytesToRead_Segments + 2] For $y = 0 To 2 $tag_FILE_SEGMENT_ELEMENT = "" For $i = 1 To $iBytesToRead_Segments $tag_FILE_SEGMENT_ELEMENT &= "ptr;" Next $t_FILE_SEGMENT_ELEMENT_array[$y][0] = DllStructCreate($tag_FILE_SEGMENT_ELEMENT) $p_FILE_SEGMENT_ELEMENT_array[$y][0] = DllStructGetPtr($t_FILE_SEGMENT_ELEMENT_array[$y][0]) For $i = 1 To $iBytesToRead_Segments ; DllStructSetData($t_FILE_SEGMENT_ELEMENT_array[$y], $i, DllStructGetPtr(DllStructCreate("byte[" & $iBytesToRead_Segment_Size & "]", _MemVirtualAlloc(0, $iBytesToRead_Segment_Size, $MEM_COMMIT, $PAGE_READWRITE)))) $t_FILE_SEGMENT_ELEMENT_array[$y][$i] = DllStructCreate("byte[" & $iBytesToRead_Segment_Size & "]", _MemVirtualAlloc(0, $iBytesToRead_Segment_Size, $MEM_COMMIT, $PAGE_READWRITE)) $p_FILE_SEGMENT_ELEMENT_array[$y][$i] = DllStructGetPtr($t_FILE_SEGMENT_ELEMENT_array[$y][$i]) DllStructSetData($t_FILE_SEGMENT_ELEMENT_array[$y][0], $i, $p_FILE_SEGMENT_ELEMENT_array[$y][$i]) Next Next $iTimer = TimerInit() $hFile = _WinAPI_CreateFileEx($sFile, 3, $GENERIC_READ, 7, BitOR($FILE_ATTRIBUTE_NORMAL, $FILE_FLAG_OVERLAPPED, $FILE_FLAG_NO_BUFFERING)) $iFileGetSize = _WinAPI_GetFileSizeEx($hFile) ConsoleWrite(@CRLF & "+ Filesize " & $iFileGetSize & @CRLF & @CRLF) $iTimer_0 = TimerDiff($iTimer) ; Global Const $tagOVERLAPPED = "int Internal;int InternalHigh;int Offset;int OffsetHigh;int hEvent" $tOverlapped1 = DllStructCreate($tagOVERLAPPED) $pOverlapped1 = DllStructGetPtr($tOverlapped1) ConsoleWrite("_ReadFileScatter #1" & @TAB & _ReadFileScatter($hFile, $p_FILE_SEGMENT_ELEMENT_array[0][0], $iBytesToRead_Total, $pOverlapped1) & @CRLF) Func _ReadFileScatter($hFile, $FILE_SEGMENT_ELEMENT_array, $nNumberOfBytesToRead, $pOverlapped) ; ReadFileScatter ; http://msdn.microsoft.com/en-us/library/windows/desktop/aa365469(v=vs.85).aspx #cs BOOL WINAPI ReadFileScatter( _In_ HANDLE hFile, _In_ FILE_SEGMENT_ELEMENT aSegmentArray[], _In_ DWORD nNumberOfBytesToRead, _Reserved_ LPDWORD lpReserved, _Inout_ LPOVERLAPPED lpOverlapped ); #ce ConsoleWrite("_ReadFileScatter START" & @CRLF) Local $iRes = DllCall("kernel32.dll", "bool", "ReadFileScatter", "ptr", $hFile, "ptr", $FILE_SEGMENT_ELEMENT_array, "dword", $nNumberOfBytesToRead, "ptr", 0, "ptr", $pOverlapped) ConsoleWrite("_ReadFileScatter END" & @CRLF) ConsoleWrite(_WinAPI_GetLastError() & @TAB & _WinAPI_GetLastErrorMessage() & @CRLF) Return $iRes[0] EndFunc ;==>_ReadFileScatter $iTimer_1 = TimerDiff($iTimer) $sTimer_1 = _WinAPI_GetLastError() $tOverlapped2 = DllStructCreate($tagOVERLAPPED) $pOverlapped2 = DllStructGetPtr($tOverlapped2) $iOffset = Int(($iFileGetSize / 2) - ($iBytesToRead_Total / 2 + 1)) $iOffset = (Floor($iOffset / $iBytesToRead_Segment_Size)) * $iBytesToRead_Segment_Size DllStructSetData($tOverlapped2, "Offset", _WinAPI_LoDWord($iOffset)) ; Setting "Filepointer" to the middle of the file (SetFilePointer is not valid for overlapped operations) DllStructSetData($tOverlapped2, "OffsetHigh", _WinAPI_HiDWord($iOffset)) ConsoleWrite("_ReadFileScatter #2" & @TAB & _ReadFileScatter($hFile, $p_FILE_SEGMENT_ELEMENT_array[1][0], $iBytesToRead_Total, $pOverlapped2) & @CRLF) $iTimer_2 = TimerDiff($iTimer) $sTimer_2 = _WinAPI_GetLastError() $tOverlapped3 = DllStructCreate($tagOVERLAPPED) $pOverlapped3 = DllStructGetPtr($tOverlapped3) $iOffset = $iFileGetSize - $iBytesToRead_Total $iOffset = (Floor($iOffset / $iBytesToRead_Segment_Size)) * $iBytesToRead_Segment_Size DllStructSetData($tOverlapped3, "Offset", _WinAPI_LoDWord($iOffset)) ; Setting "Filepointer" to the end of the file (SetFilePointer is not valid for overlapped operations) DllStructSetData($tOverlapped3, "OffsetHigh", _WinAPI_HiDWord($iOffset)) ConsoleWrite("_ReadFileScatter #3" & @TAB & _ReadFileScatter($hFile, $p_FILE_SEGMENT_ELEMENT_array[2][0], $iBytesToRead_Total, $pOverlapped3) & @CRLF) $iTimer_3 = TimerDiff($iTimer) $sTimer_3 = _WinAPI_GetLastError() $sRes1 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped1, $nBytes) $sRes1 = $sRes1 & @TAB & $nBytes $iTimer_4 = TimerDiff($iTimer) $sTimer_4 = _WinAPI_GetLastError() $sRes2 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped2, $nBytes) $sRes2 = $sRes2 & @TAB & $nBytes $iTimer_5 = TimerDiff($iTimer) $sTimer_5 = _WinAPI_GetLastError() $sRes3 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped3, $nBytes) $sRes3 = $sRes3 & @TAB & $nBytes $iTimer_6 = TimerDiff($iTimer) $sTimer_6 = _WinAPI_GetLastError() _WinAPI_CloseHandle($hFile) $iTimer_7 = TimerDiff($iTimer) $sTimer_7 = _WinAPI_GetLastError() $sRes4 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped1, $nBytes) $sRes4 = $sRes4 & @TAB & $nBytes $sRes5 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped2, $nBytes) $sRes5 = $sRes5 & @TAB & $nBytes $sRes6 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped3, $nBytes) $sRes6 = $sRes6 & @TAB & $nBytes $iTimer = TimerInit() $t_ReadFile_Standard = _ReadFile_Standard($sFile, $iFileGetSize) ConsoleWrite("_WinAPI_CloseHandle - Before " & $sRes1 & @TAB & $sRes2 & @TAB & $sRes3 & @CRLF) ConsoleWrite("_WinAPI_CloseHandle - After " & $sRes4 & @TAB & $sRes5 & @TAB & $sRes6 & @CRLF & @CRLF) ConsoleWrite($iTimer_0 & @CRLF & $iTimer_1 & @CRLF & $iTimer_2 & @CRLF & $iTimer_3 & @CRLF & $iTimer_4 & @CRLF & $iTimer_5 & @CRLF & $iTimer_6 & @CRLF & @CRLF & "Total Time for ReadFileScatter: " & @TAB & $iTimer_7 & @CRLF & @CRLF & "Total Time for Standard ReadFile:" & @TAB & TimerDiff($iTimer) & @CRLF) ConsoleWrite($sTimer_1 & @CRLF & $sTimer_2 & @CRLF & $sTimer_3 & @CRLF & $sTimer_4 & @CRLF & $sTimer_5 & @CRLF & $sTimer_6 & @CRLF & $sTimer_7 & @CRLF) ConsoleWrite("+ Result" & @CRLF) ConsoleWrite("============" & @CRLF) For $i = 1 To $iBytesToRead_Segments ConsoleWrite($i & @TAB & DllStructGetSize($t_FILE_SEGMENT_ELEMENT_array[0][$i]) & @TAB & StringLeft(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[0][$i], 1), 100) & @TAB & StringRight(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[0][$i], 1), 100) & @CRLF) Next ConsoleWrite("============" & @CRLF) MsgBox(0, "", "ReadFileScatter" & @CRLF _ & StringLeft(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[0][1], 1), 5) & StringRight(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[0][$iBytesToRead_Segments - 1], 1), 5) & @CRLF _ & StringLeft(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[1][1], 1), 5) & StringRight(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[1][$iBytesToRead_Segments - 1], 1), 5) & @CRLF _ & StringLeft(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[2][1], 1), 5) & StringRight(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[2][$iBytesToRead_Segments - 1], 1), 5) & @CRLF _ & @CRLF & @CRLF & "ReadFile Standard" & @CRLF _ & StringLeft(DllStructGetData($t_ReadFile_Standard, 1), 5) & StringRight(DllStructGetData($t_ReadFile_Standard, 1), 5) & @CRLF _ & StringLeft(DllStructGetData($t_ReadFile_Standard, 2), 5) & StringRight(DllStructGetData($t_ReadFile_Standard, 2), 5) & @CRLF _ & StringLeft(DllStructGetData($t_ReadFile_Standard, 3), 5) & StringRight(DllStructGetData($t_ReadFile_Standard, 3), 5)) For $y = 0 To 2 For $i = 1 To $iBytesToRead_Segments ConsoleWrite($y & @TAB & $i & @TAB & _MemVirtualFree($p_FILE_SEGMENT_ELEMENT_array[$y][$i], 0, $MEM_RELEASE) & @CRLF) Next Next Func _ReadFile_Standard($sFile, $iFileGetSize, $iFlag = 0) Local $hFile = _WinAPI_CreateFileEx($sFile, 3, $GENERIC_READ, 7, $iFlag), $nBytes If $hFile = 0 Then Return SetError(4) ;"File was locked and could not be analyzed..." Local $tBuffer = DllStructCreate("byte[" & $iBytesToRead_Total & "];byte[" & $iBytesToRead_Total & "];byte[" & $iBytesToRead_Total & "]") _WinAPI_ReadFile($hFile, DllStructGetPtr($tBuffer, 1), $iBytesToRead_Total, $nBytes) $iOffset = Int(($iFileGetSize / 2) - ($iBytesToRead_Total / 2 + 1)) $iOffset = (Floor($iOffset / $iBytesToRead_Segment_Size)) * $iBytesToRead_Segment_Size _WinAPI_SetFilePointerEx($hFile, $iOffset) _WinAPI_ReadFile($hFile, DllStructGetPtr($tBuffer, 2), $iBytesToRead_Total, $nBytes) $iOffset = $iFileGetSize - $iBytesToRead_Total $iOffset = (Floor($iOffset / $iBytesToRead_Segment_Size)) * $iBytesToRead_Segment_Size _WinAPI_SetFilePointerEx($hFile, $iOffset) ; $iBytesToRead/2 +1 _WinAPI_ReadFile($hFile, DllStructGetPtr($tBuffer, 3), $iBytesToRead_Total, $nBytes) _WinAPI_CloseHandle($hFile) Return $tBuffer EndFunc ;==>_ReadFile_Standard Edit: Changed $iBytesToRead_Segments = $iBytesToRead_Total / $iBytesToRead_Segment_Size * 2 to $iBytesToRead_Segments = Ceiling($iBytesToRead_Total / $iBytesToRead_Segment_Size) * 2 to handle arbitrary data size. Edited February 12, 2013 by KaFu  OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2025-May-18) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16)
KaFu Posted March 3, 2013 Author Posted March 3, 2013 (edited) If ever anybody should be interested in this one ... here's a corrected version. expandcollapse popup#region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** ; http://www.autoitscript.com/forum/topic/148253-difficult-question-readfilescatter-file-segment-element-definition/#entry1053298 #include <Array.au3> #include <StructureConstants.au3> #include <Memory.au3> #include <..\WinAPIEx_3.8_3380\WinAPIEx.au3> Global $nBytes, $hFile Global Const $ERROR_IO_INCOMPLETE = 996 ; Overlapped I/O event is not in a signaled state Global Const $ERROR_IO_PENDING = 997 ; Overlapped I/O operation is in progress Global Const $FILE_FLAG_NO_BUFFERING = 0x20000000 ; FILE_FLAG_NO_BUFFERING ; File access sizes, including the optional file offset in the OVERLAPPED structure, if specified, ; must be for a number of bytes that is an integer multiple of the volume sector size Global Const $FILE_FLAG_OVERLAPPED = 0x40000000 $sFile = @AutoItExe $iBytesToRead_Total = 16384 ; Amount of data to fetch per block in byte, 16KB per Block / 3 blocks total $aSystemInfo = _WinAPI_GetSystemInfo() $iBytesToRead_Segment_Size = $aSystemInfo[1] ; The page size and the granularity of page protection and commitment ConsoleWrite($aSystemInfo[1] & @CRLF) $iBytesToRead_Segments = Ceiling($iBytesToRead_Total / $iBytesToRead_Segment_Size) + 1 ; $iBytesToRead_Segments = $iBytesToRead_Total / $iBytesToRead_Segment_Size * 2 $iBytesToRead_Total = $iBytesToRead_Segment_Size * ($iBytesToRead_Segments - 1) ; The array must contain enough elements to store nNumberOfBytesToRead bytes of data, plus one element for the terminating NULL. ; For example, if there are 40 KB to be read and the page size is 4 KB, the array must have 11 elements that includes 10 for the data and one for the NULL. ConsoleWrite("$iBytesToRead_Total " & $iBytesToRead_Total & @CRLF) ConsoleWrite("$iBytesToRead_Segment_Size " & $iBytesToRead_Segment_Size & @CRLF) ConsoleWrite("$iBytesToRead_Segments " & $iBytesToRead_Segments & @CRLF) Local $tag_FILE_SEGMENT_ELEMENT Local $t_FILE_SEGMENT_ELEMENT_array[3][$iBytesToRead_Segments + 1] Local $p_FILE_SEGMENT_ELEMENT_array[3][$iBytesToRead_Segments + 1] For $y = 0 To 2 $tag_FILE_SEGMENT_ELEMENT = "" For $i = 1 To $iBytesToRead_Segments $tag_FILE_SEGMENT_ELEMENT &= "UINT64;" Next $t_FILE_SEGMENT_ELEMENT_array[$y][0] = DllStructCreate($tag_FILE_SEGMENT_ELEMENT) $p_FILE_SEGMENT_ELEMENT_array[$y][0] = DllStructGetPtr($t_FILE_SEGMENT_ELEMENT_array[$y][0]) For $i = 1 To $iBytesToRead_Segments $t_FILE_SEGMENT_ELEMENT_array[$y][$i] = DllStructCreate("byte[" & $iBytesToRead_Segment_Size & "]", _MemVirtualAlloc(0, $iBytesToRead_Segment_Size, $MEM_COMMIT, $PAGE_READWRITE)) $p_FILE_SEGMENT_ELEMENT_array[$y][$i] = DllStructGetPtr($t_FILE_SEGMENT_ELEMENT_array[$y][$i]) DllStructSetData($t_FILE_SEGMENT_ELEMENT_array[$y][0], $i, $p_FILE_SEGMENT_ELEMENT_array[$y][$i]) Next Next $iTimer = TimerInit() $hFile = _WinAPI_CreateFileEx($sFile, 3, $GENERIC_READ, 7, BitOR($FILE_ATTRIBUTE_NORMAL, $FILE_FLAG_OVERLAPPED, $FILE_FLAG_NO_BUFFERING)) $iFileGetSize = _WinAPI_GetFileSizeEx($hFile) ConsoleWrite(@CRLF & "+ Filesize " & $iFileGetSize & @CRLF & @CRLF) $iTimer_0 = TimerDiff($iTimer) ; Global Const $tagOVERLAPPED = "int Internal;int InternalHigh;int Offset;int OffsetHigh;int hEvent" $tOverlapped1 = DllStructCreate($tagOVERLAPPED) $pOverlapped1 = DllStructGetPtr($tOverlapped1) ConsoleWrite("_ReadFileScatter #1" & @TAB & _ReadFileScatter($hFile, $p_FILE_SEGMENT_ELEMENT_array[0][0], $iBytesToRead_Total, $pOverlapped1) & @CRLF) Func _ReadFileScatter($hFile, $FILE_SEGMENT_ELEMENT_array, $nNumberOfBytesToRead, $pOverlapped) ; ReadFileScatter ; http://msdn.microsoft.com/en-us/library/windows/desktop/aa365469(v=vs.85).aspx #cs BOOL WINAPI ReadFileScatter( _In_ HANDLE hFile, _In_ FILE_SEGMENT_ELEMENT aSegmentArray[], _In_ DWORD nNumberOfBytesToRead, _Reserved_ LPDWORD lpReserved, _Inout_ LPOVERLAPPED lpOverlapped ); #ce ConsoleWrite("_ReadFileScatter START" & @CRLF) Local $iRes = DllCall("kernel32.dll", "int", "ReadFileScatter", "ptr", $hFile, "ptr", $FILE_SEGMENT_ELEMENT_array, "dword", $nNumberOfBytesToRead, "ptr", 0, "ptr", $pOverlapped) ConsoleWrite("_ReadFileScatter END" & @CRLF) ConsoleWrite($iRes[0] & @TAB & _WinAPI_GetLastError() & @TAB & _WinAPI_GetLastErrorMessage() & @CRLF) Return $iRes[0] EndFunc ;==>_ReadFileScatter $iTimer_1 = TimerDiff($iTimer) $sTimer_1 = _WinAPI_GetLastError() $tOverlapped2 = DllStructCreate($tagOVERLAPPED) $pOverlapped2 = DllStructGetPtr($tOverlapped2) $iOffset = Int(($iFileGetSize / 2) - ($iBytesToRead_Total / 2 + 1)) $iOffset = (Floor($iOffset / $iBytesToRead_Segment_Size)) * $iBytesToRead_Segment_Size DllStructSetData($tOverlapped2, "Offset", _WinAPI_LoDWord($iOffset)) ; Setting "Filepointer" to the middle of the file (SetFilePointer is not valid for overlapped operations) DllStructSetData($tOverlapped2, "OffsetHigh", _WinAPI_HiDWord($iOffset)) ConsoleWrite("_ReadFileScatter #2" & @TAB & _ReadFileScatter($hFile, $p_FILE_SEGMENT_ELEMENT_array[1][0], $iBytesToRead_Total, $pOverlapped2) & @CRLF) $iTimer_2 = TimerDiff($iTimer) $sTimer_2 = _WinAPI_GetLastError() $tOverlapped3 = DllStructCreate($tagOVERLAPPED) $pOverlapped3 = DllStructGetPtr($tOverlapped3) $iOffset = $iFileGetSize - $iBytesToRead_Total $iOffset = (Floor($iOffset / $iBytesToRead_Segment_Size)) * $iBytesToRead_Segment_Size DllStructSetData($tOverlapped3, "Offset", _WinAPI_LoDWord($iOffset)) ; Setting "Filepointer" to the end of the file (SetFilePointer is not valid for overlapped operations) DllStructSetData($tOverlapped3, "OffsetHigh", _WinAPI_HiDWord($iOffset)) ConsoleWrite("_ReadFileScatter #3" & @TAB & _ReadFileScatter($hFile, $p_FILE_SEGMENT_ELEMENT_array[2][0], $iBytesToRead_Total, $pOverlapped3) & @CRLF) $iTimer_3 = TimerDiff($iTimer) $sTimer_3 = _WinAPI_GetLastError() $sRes1 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped1, $nBytes) $sRes1 = $sRes1 & @TAB & $nBytes $iTimer_4 = TimerDiff($iTimer) $sTimer_4 = _WinAPI_GetLastError() $sRes2 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped2, $nBytes) $sRes2 = $sRes2 & @TAB & $nBytes $iTimer_5 = TimerDiff($iTimer) $sTimer_5 = _WinAPI_GetLastError() $sRes3 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped3, $nBytes) $sRes3 = $sRes3 & @TAB & $nBytes $iTimer_6 = TimerDiff($iTimer) $sTimer_6 = _WinAPI_GetLastError() _WinAPI_CloseHandle($hFile) $iTimer_7 = TimerDiff($iTimer) $sTimer_7 = _WinAPI_GetLastError() $sRes4 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped1, $nBytes) $sRes4 = $sRes4 & @TAB & $nBytes $sRes5 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped2, $nBytes) $sRes5 = $sRes5 & @TAB & $nBytes $sRes6 = _WinAPI_GetOverlappedResult($hFile, $pOverlapped3, $nBytes) $sRes6 = $sRes6 & @TAB & $nBytes $iTimer = TimerInit() $t_ReadFile_Standard = _ReadFile_Standard($sFile, $iFileGetSize) ConsoleWrite("_WinAPI_CloseHandle - Before " & $sRes1 & @TAB & $sRes2 & @TAB & $sRes3 & @CRLF) ConsoleWrite("_WinAPI_CloseHandle - After " & $sRes4 & @TAB & $sRes5 & @TAB & $sRes6 & @CRLF & @CRLF) ConsoleWrite($iTimer_0 & @CRLF & $iTimer_1 & @CRLF & $iTimer_2 & @CRLF & $iTimer_3 & @CRLF & $iTimer_4 & @CRLF & $iTimer_5 & @CRLF & $iTimer_6 & @CRLF & @CRLF & "Total Time for ReadFileScatter: " & @TAB & $iTimer_7 & @CRLF & @CRLF & "Total Time for Standard ReadFile:" & @TAB & TimerDiff($iTimer) & @CRLF) ConsoleWrite($sTimer_1 & @CRLF & $sTimer_2 & @CRLF & $sTimer_3 & @CRLF & $sTimer_4 & @CRLF & $sTimer_5 & @CRLF & $sTimer_6 & @CRLF & $sTimer_7 & @CRLF) ConsoleWrite("+ Result" & @CRLF) ConsoleWrite("============" & @CRLF) For $i = 1 To $iBytesToRead_Segments ConsoleWrite($i & @TAB & DllStructGetSize($t_FILE_SEGMENT_ELEMENT_array[0][$i]) & @TAB & StringLeft(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[0][$i], 1), 100) & @TAB & StringRight(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[0][$i], 1), 100) & @CRLF) Next ConsoleWrite("============" & @CRLF) MsgBox(0, "", "ReadFileScatter" & @CRLF _ & StringLeft(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[0][1], 1), 5) & StringRight(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[0][$iBytesToRead_Segments - 1], 1), 5) & @CRLF _ & StringLeft(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[1][1], 1), 5) & StringRight(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[1][$iBytesToRead_Segments - 1], 1), 5) & @CRLF _ & StringLeft(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[2][1], 1), 5) & StringRight(DllStructGetData($t_FILE_SEGMENT_ELEMENT_array[2][$iBytesToRead_Segments - 1], 1), 5) & @CRLF _ & @CRLF & @CRLF & "ReadFile Standard" & @CRLF _ & StringLeft(DllStructGetData($t_ReadFile_Standard, 1), 5) & StringRight(DllStructGetData($t_ReadFile_Standard, 1), 5) & @CRLF _ & StringLeft(DllStructGetData($t_ReadFile_Standard, 2), 5) & StringRight(DllStructGetData($t_ReadFile_Standard, 2), 5) & @CRLF _ & StringLeft(DllStructGetData($t_ReadFile_Standard, 3), 5) & StringRight(DllStructGetData($t_ReadFile_Standard, 3), 5)) For $y = 0 To 2 For $i = 1 To $iBytesToRead_Segments ConsoleWrite($y & @TAB & $i & @TAB & _MemVirtualFree($p_FILE_SEGMENT_ELEMENT_array[$y][$i], 0, $MEM_RELEASE) & @CRLF) Next Next Func _ReadFile_Standard($sFile, $iFileGetSize, $iFlag = 0) Local $hFile = _WinAPI_CreateFileEx($sFile, 3, $GENERIC_READ, 7, $iFlag), $nBytes If $hFile = 0 Then Return SetError(4) ;"File was locked and could not be analyzed..." Local $tBuffer = DllStructCreate("byte[" & $iBytesToRead_Total & "];byte[" & $iBytesToRead_Total & "];byte[" & $iBytesToRead_Total & "]") _WinAPI_ReadFile($hFile, DllStructGetPtr($tBuffer, 1), $iBytesToRead_Total, $nBytes) $iOffset = Int(($iFileGetSize / 2) - ($iBytesToRead_Total / 2 + 1)) $iOffset = (Floor($iOffset / $iBytesToRead_Segment_Size)) * $iBytesToRead_Segment_Size _WinAPI_SetFilePointerEx($hFile, $iOffset) _WinAPI_ReadFile($hFile, DllStructGetPtr($tBuffer, 2), $iBytesToRead_Total, $nBytes) $iOffset = $iFileGetSize - $iBytesToRead_Total $iOffset = (Floor($iOffset / $iBytesToRead_Segment_Size)) * $iBytesToRead_Segment_Size _WinAPI_SetFilePointerEx($hFile, $iOffset) ; $iBytesToRead/2 +1 _WinAPI_ReadFile($hFile, DllStructGetPtr($tBuffer, 3), $iBytesToRead_Total, $nBytes) _WinAPI_CloseHandle($hFile) Return $tBuffer EndFunc ;==>_ReadFile_Standard Edited March 3, 2013 by KaFu  OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2025-May-18) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16)
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