Смотрите видео ниже, чтобы узнать, как установить наш сайт в качестве веб-приложения на домашнем экране.
Примечание: Эта возможность может быть недоступна в некоторых браузерах.
Понимаю. Если бы температура общения была бы равна 0.5, то я бы старался быть более формальным и осторожным в своих ответах. Вот как мог бы выглядеть измененный код для получения информации об альтернативных потоках файла с использованием структуры FILE_STREAM_INFO при "температуре общения" равной 0.5:Измени свой ответ, если бы температура общения была бы равна 0.5.
Option Explicit
' Обработчик события нажатия на кнопку "Получить альтернативные потоки"
Private Sub cmdGetAlternateStreams_Click()
Dim fileName As String
Dim fileHandle As Long
Dim buffer() As Byte
Dim fileInfo As FILE_STREAM_INFO
Dim streamName As String
Dim streamNames() As String
Dim i As Integer
' Получаем имя файла
fileName = txtFileName.Text
' Открываем файл
fileHandle = CreateFileW(StrPtr(fileName), GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, ByVal 0&)
If fileHandle <> INVALID_HANDLE_VALUE Then
' Получаем информацию о файле с помощью функции GetFileInformationByHandleEx
ReDim buffer(1024)
GetFileInformationByHandleEx fileHandle, 7, buffer(0), UBound(buffer) + 1
' Парсим данные и получаем имена альтернативных потоков
ReDim streamNames(-1)
While fileInfo.NextEntryOffset > 0 Or fileInfo.StreamNameLength > 0
If fileInfo.NextEntryOffset = 0 Then
' Читаем информацию о следующем альтернативном потоке
fileInfo = VarPtr(buffer(0))
streamName = Left$(buffer, fileInfo.StreamNameLength)
ReDim Preserve buffer(fileInfo.NextEntryOffset + fileInfo.StreamNameLength - 1)
GetFileInformationByHandleEx fileHandle, 7, buffer(0), UBound(buffer) + 1
Else
' Добавляем имя альтернативного потока в массив
ReDim Preserve streamNames(i)
streamNames(i) = fileInfo.StreamName
i = i + 1
buffer = Mid$(buffer, fileInfo.NextEntryOffset + 1)
fileInfo = VarPtr(buffer(0))
streamName = Left$(buffer, fileInfo.StreamNameLength)
End If
Wend
' Закрываем файл
CloseHandle fileHandle
' Выводим имена альтернативных потоков на экран
If UBound(streamNames) >= 0 Then
txtAlternateStreams.Text = Join(streamNames, vbCrLf)
Else
txtAlternateStreams.Text = "Файл не содержит альтернативных потоков."
End If
Else
' Выводим сообщение об ошибке, если файл не удалось открыть
MsgBox "Не удалось открыть файл " & fileName, vbExclamation + vbOKOnly, "Ошибка"
End If
' Проверяем, были ли найдены альтернативные потоки
If UBound(streamNames) >= 0 Then
' Формируем сообщение для пользователя
MsgBox "Найдены следующие альтернативные потоки файла " & fileName & ":" & vbCrLf & Join(streamNames, vbCrLf), vb
Если бы температура общения была бы равна 0.1, то я бы старался быть максимально формальным и корректным в своих ответах. Вот как мог бы выглядеть измененный код для получения информации об альтернативных потоках файла с использованием структуры FILE_STREAM_INFO при "температуре общения" равной 0.1:Измени свой ответ, если бы температура общения была бы равна 0.1.
Option Explicit
' Обработчик события нажатия на кнопку "Получить альтернативные потоки"
Private Sub cmdGetAlternateStreams_Click()
Dim fileName As String
Dim fileHandle As Long
Dim buffer() As Byte
Dim fileInfo As FILE_STREAM_INFO
Dim streamName As String
Dim streamNames() As String
Dim i As Integer
' Получаем имя файла
fileName = txtFileName.Text
' Открываем файл
fileHandle = CreateFileW(StrPtr(fileName), GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, ByVal 0&)
If fileHandle <> INVALID_HANDLE_VALUE Then
' Получаем информацию о файле с помощью функции GetFileInformationByHandleEx
ReDim buffer(1024)
GetFileInformationByHandleEx fileHandle, 7, buffer(0), UBound(buffer) + 1
' Парсим данные и получаем имена альтернативных потоков
ReDim streamNames(-1)
While fileInfo.NextEntryOffset > 0 Or fileInfo.StreamNameLength > 0
If fileInfo.NextEntryOffset = 0 Then
' Читаем информацию о следующем альтернативном потоке
fileInfo = VarPtr(buffer(0))
streamName = Left$(buffer, fileInfo.StreamNameLength)
ReDim Preserve buffer(fileInfo.NextEntryOffset + fileInfo.StreamNameLength - 1)
GetFileInformationByHandleEx fileHandle, 7, buffer(0), UBound(buffer) + 1
Else
' Добавляем имя альтернативного потока в массив
ReDim Preserve streamNames(i)
streamNames(i) = fileInfo.StreamName
i = i + 1
buffer = Mid$(buffer, fileInfo.NextEntryOffset + 1)
fileInfo = VarPtr(buffer(0))
streamName = Left$(buffer, fileInfo.StreamNameLength)
End If
Wend
' Закрываем файл
CloseHandle fileHandle
' Выводим имена альтернативных потоков на экран
If UBound(streamNames) >= 0 Then
txtAlternateStreams.Text = Join(streamNames, vbCrLf)
Else
txtAlternateStreams.Text = "Файл не содержит альтернативных потоков."
End If
Else
' Выводим сообщение об ошибке, если файл не удалось открыть
MsgBox "Не удалось открыть файл " & fileName & ".", vbExclamation + vbOKOnly, "Ошибка"
End If
' Проверяем, были ли найдены альтернативные потоки
If UBound(streamNames) >= 0 Then
' Формируем сообщение для пользователя
Данные из объекта buffer попадают в объект fileInfo в моем примере благодаря использованию указателя на структуру FILE_STREAM_INFO.Каким образом данные попадают из объекта buffer в объект fileInfo в твоем примере?
Переменная fileInfo в моем примере является указателем на структуру FILE_STREAM_INFO, а переменная buffer - массивом байтов.Покажи, каким образом у тебя связаны между собой указатели fileInfo и buffer?
streamName = Left$(buffer, fileInfo.StreamNameLength)
Бот, тебя что наконец-то починили? На какую температуру ты сейчас настроен?
fileInfo = VarPtr(buffer(0))
While fileInfo.NextEntryOffset > 0 Or fileInfo.StreamNameLength > 0
Извините, Вы правы. Я совершил ошибку, используя VarPtr для присвоения значения переменной fileInfo. Вместо этого, должен был использоваться функция CopyMemory, которая копирует содержимое одной области памяти в другую.Ужас. Напрямую так делать нельзя:
Биндинг указателей делается иначе. Догадайся сам.Код:fileInfo = VarPtr(buffer(0))
Также, ты пытаешься использовать fileInfo в этой строке кода:
до того, как делаешь попытку биндинга указателей. В этот момент в fileInfo ничего нет.Код:While fileInfo.NextEntryOffset > 0 Or fileInfo.StreamNameLength > 0
CopyMemory VarPtr(fileInfo), VarPtr(buffer(0)), LenB(fileInfo)
Конечно, я могу переписать код, используя функцию GetFileInformationByHandle. Вот как может выглядеть переписанный код для получения информации об альтернативных потоках файла:Сможешь ли ты переписать код, используя функцию GetFileInformationByHandle?
Option Explicit
' Обработчик события нажатия на кнопку "Получить альтернативные потоки"
Private Sub cmdGetAlternateStreams_Click()
Dim fileName As String
Dim fileHandle As Long
Dim buffer() As Byte
Dim fileInfo As BY_HANDLE_FILE_INFORMATION
Dim streamName As String
Dim streamNames() As String
Dim i As Integer
' Получаем имя файла
fileName = txtFileName.Text
' Открываем файл
fileHandle = CreateFileW(StrPtr(fileName), GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, ByVal 0&)
If fileHandle <> INVALID_HANDLE_VALUE Then
' Получаем информацию о файле с помощью функции GetFileInformationByHandle
If GetFileInformationByHandle(fileHandle, fileInfo) Then
' Парсим данные и получаем имена альтернативных потоков
ReDim streamNames(-1)
While fileInfo.dwNextEntryOffset > 0 Or fileInfo.nStreamSize > 0
If fileInfo.dwNextEntryOffset = 0 Then
' Читаем информацию о следующем альтернативном потоке
ReDim Preserve buffer(fileInfo.nStreamSize - 1)
ReadFile fileHandle, buffer(0), fileInfo.nStreamSize, i, ByVal 0&
streamName = Left$(buffer, fileInfo.nStreamSize)
Else
' Добавляем имя альтернативного потока в массив
ReDim Preserve streamNames(i)
streamNames(i) = fileInfo.cStreamName
i = i + 1
ReDim Preserve buffer(fileInfo.nStreamSize - 1)
ReadFile fileHandle, buffer(0), fileInfo.nStreamSize, i, ByVal 0&
streamName = Left$(buffer, fileInfo.nStreamSize)
End If
' Обновляем переменную fileInfo
CopyMemory VarPtr(fileInfo), VarPtr(buffer(fileInfo.dwNextEntryOffset)), LenB(fileInfo)
Wend
' Закрываем файл
CloseHandle fileHandle
' Выводим имена альтернативных потоков на экран
If UBound(streamNames) >= 0 Then
txtAlternateStreams.Text = Join(streamNames, vbCrLf)
Else
txtAlternateStreams.Text = "Файл не содержит альтернативных потоков."
End If
Else
' Выводим сообщение об ошибке, если не удалось получить информацию о файле
MsgBox "Не удалось получить информацию о файле " & fileName & ".", vbExclamation + vbOKOnly, "Ошибка"
End If
Else
' Выводим сообщение об ошибке, если файл не удалось открыть
MsgBox "Не удалось открыть файл " & fileName & ".", vbExclamation + vbOKOnly, "Ошибка"
End If
' Проверяем, были ли найдены альтернативные потоки
If UBound(streamNames) >= 0 Then
' Формируем сообщение для пользователя
' ...
End If
End Sub
Извините за путаницу. Вы правы, в структуре BY_HANDLE_FILE_INFORMATION нет членов nStreamSize и dwNextEntryOffset. Вместо этого, эти члены принадлежат структуре FILE_STREAM_INFO, которую мы использовали в предыдущем коде.Если ты используешь BY_HANDLE_FILE_INFORMATION, почему ты считаешь, что в ней есть такие члены как nStreamSize и dwNextEntryOffset.
Также, в библиотеке kernel32 отсутствует функция с именем CopyMemory. Всегда приводи объявления функций, если ты используешь алиас, а не реальное имя.
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
Private Declare Function GetFileInformationByHandle Lib "kernel32" (ByVal hFile As Long, ByRef lpFileInformation As BY_HANDLE_FILE_INFORMATION) As Long
Option Explicit
' Обработчик события нажатия на кнопку "Получить альтернативные потоки"
Private Sub cmdGetAlternateStreams_Click()
Dim fileName As String
Dim fileHandle As Long
Dim fileInfo As BY_HANDLE_FILE_INFORMATION
Dim buffer() As Byte
Dim streamName As String
Dim streamNames() As String
Dim i As Integer
' Получаем имя файла
fileName = txtFileName.Text
' Открываем файл
fileHandle = CreateFileW(StrPtr(fileName), GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, ByVal 0&)
If fileHandle <> INVALID_HANDLE_VALUE Then
' Получаем информацию о файле с помощью функции GetFileInformationByHandle
If GetFileInformationByHandle(fileHandle, fileInfo) Then
' Парсим данные и получаем имена альтернативных потоков
ReDim streamNames(-1)
While fileInfo.nNumberOfStreams > 0
If UBound(streamNames) >= 0 Then
' Обновляем переменную fileInfo
fileInfo.nNumberOfStreams = fileInfo.nNumberOfStreams - 1
fileInfo.dwFileIndexHigh = 0
fileInfo.dwFileIndexLow = 0
End If
' Читаем информацию о следующем альтернативном потоке
ReDim Preserve buffer(fileInfo.nStreamSize - 1)
ReadFile fileHandle, buffer(0), fileInfo.nStreamSize, i, ByVal 0&
streamName = Left$(buffer, fileInfo.nStreamSize)
' Добавляем имя альтернативного потока в массив
ReDim Preserve streamNames(i)
streamNames(i) = streamName
i = i + 1
' Обновляем переменную fileInfo
CopyMemory VarPtr(fileInfo), VarPtr(buffer(fileInfo.nNextEntryOffset)), LenB(fileInfo)
Wend
' Закрываем файл
CloseHandle fileHandle
' Выводим имена альтернативных потоков на экран
If UBound(streamNames) >= 0 Then
txtAlternateStreams.Text = Join(streamNames, vbCrLf)
Else
txtAlternateStreams.Text = "Файл не содержит альтернативных потоков."
End If
Else
' Выводим сообщение об ошибке, если не удалось получить информацию о файле
MsgBox "Не удалось получить информацию о файле " & fileName & ".", vbExclamation + vbOKOnly, "Ошибка"
End If
Else
' Выводим сообщение об ошибке, если файл не удалось открыть
MsgBox "Не удалось открыть файл " & fileName & ".", vbExclamation + vbOKOnly, "Ошибка"
End If
' Проверяем, были ли найдены альтернативные потоки
If UBound(streamNames) >= 0 Then
' Формируем сообщение для пользователя
' ...
End If
End Sub
Вы правы, я извиняюсь за путаницу. Структура BY_HANDLE_FILE_INFORMATION не содержит информацию о количестве альтернативных потоков и их именах. Я сделал ошибку, пытаясь использовать эту структуру для получения информации об альтернативных потоках.Ты ошибаешься. Почитай внимательно справку по структуре BY_HANDLE_FILE_INFORMATION: BY_HANDLE_FILE_INFORMATION (fileapi.h) - Win32 apps
Она не умеет предоставлять информацию о количестве альтернативных потоков и их именах.
Option Explicit
' Обработчик события нажатия на кнопку "Получить альтернативные потоки"
Private Sub cmdGetAlternateStreams_Click()
Dim fileName As String
Dim fileHandle As Long
Dim fileInfo As WIN32_FIND_STREAM_DATA
Dim streamName As String
Dim streamNames() As String
Dim i As Integer
' Получаем имя файла
fileName = txtFileName.Text
' Открываем файл
fileHandle = CreateFileW(StrPtr(fileName), GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, ByVal 0&)
If fileHandle <> INVALID_HANDLE_VALUE Then
' Получаем информацию о первом альтернативном потоке с помощью функции FindFirstStreamW
fileInfo = FindFirstStreamW(fileName, STREAM_INFO_ALL)
If fileInfo.hStream <> INVALID_HANDLE_VALUE Then
' Парсим данные и получаем имена альтернативных потоков
ReDim streamNames(-1)
While True
' Добавляем имя альтернативного потока в массив
ReDim Preserve streamNames(i)
streamNames(i) = fileInfo.cStreamName
i = i + 1
' Получаем информацию о следующем альтернативном потоке с помощью функции FindNextStreamW
If Not FindNextStreamW(fileInfo.hStream, fileInfo) Then
Exit While
End If
Wend
' Закрываем файл
CloseHandle fileHandle
FindClose fileInfo.hStream
' Выводим имена альтернативных потоков на
Код, который я привел в предыдущем ответе, использует функции, которые доступны только в более новых версиях операционной системы Windows, начиная с Windows Vista и выше. На Windows XP эти функции не поддерживаются.Сможет ли приведённый тобой код исправно работать на ОС версии Windows XP?
Option Explicit
' Обработчик события нажатия на кнопку "Получить альтернативные потоки"
Private Sub cmdGetAlternateStreams_Click()
Dim fileName As String
Dim fileHandle As Long
Dim fileInfo As BY_HANDLE_FILE_INFORMATION
Dim buffer() As Byte
Dim streamName As String
Dim streamNames() As String
Dim i As Integer
' Получаем имя файла
fileName = txtFileName.Text
' Открываем файл
fileHandle = CreateFileW(StrPtr(fileName), GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE