Тема: AHK: Патч файла
Функция FilePatch в примере ниже пишет данные в указанное место уже существующего файла (патчит его). Она принимает три аргумента: полный путь к файлу, смещение от начала файла (в байтах), по которому нужно произвести запись, и сами данные — в виде строки из шестнадцатеричных цифр. Каждый байт данных должен быть обозначен двумя цифрами — т.е. если он имеет значение 0, нужно писать его как 00, и т.д. Байты в строке можно разделять пробелами для удобства восприятия, а также строка может состоять из нескольких строчек. Возвращает функция количество реально записанных байтов.
FilePath = C:\Temp\temp.bin ; Путь к файлу.
Offset = 0x1000 ; Смещение в файле, по которому писать.
Data = ; Данные для записи. Пробелы необязательны.
(
FF FF FF FE 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 EF FF FF FF
)
Result := FilePatch(FilePath, Offset, Data)
MsgBox, Записано байтов: %Result%
; ===================== Функция записи в файл. ======================
FilePatch(SrcFile, Offset, HexString)
{
If not FileExist(SrcFile) {
MsgBox, 16, %A_ThisFunc%, Не найден файл:`n%SrcFile%
Return 0
}
FileGetSize, FileSize, %SrcFile%
If(Offset >= FileSize) {
MsgBox, 16, %A_ThisFunc%, Смещение за пределами файла.
Return 0
}
If RegExMatch(HexString, "i)0x") {
MsgBox, 16, %A_ThisFunc%,
(LTrim
Неверный формат данных: префикс "0x".
Функция не предназначена для записи чисел,
только последовательностей байтов.
)
Return 0
}
HexString := RegExReplace(HexString, "\s")
If HexString is not xDigit
{
MsgBox, 16, %A_ThisFunc%,
(LTrim
Строка данных содержит недопустимые символы.
Допустимы только 0123456789ABCDEF.
)
Return 0
}
Len := StrLen(HexString)
If Mod(Len, 2)
{
MsgBox, 16, %A_ThisFunc%,
(LTrim
В строке данных нечётное количество символов.
Каждый байт нужно обозначать двумя цифрами.
)
Return 0
}
cBytes := Len / 2
VarSetCapacity(Buf, cBytes, 0)
Pos = 1
Loop, % cBytes
{
Byte := "0x" . SubStr(HexString, Pos, 2)
Pos += 2
NumPut(Byte, Buf, A_Index - 1, "Char")
}
OPEN_EXISTING = 3
FILE_WRITE_DATA = 2
FILE_BEGIN = 0
VarSetCapacity(BytesWritten, 4, 0)
hFile := DllCall( "CreateFile", "Str", SrcFile
, "UInt", FILE_WRITE_DATA
, "UInt", 0
, "UInt", 0
, "UInt", OPEN_EXISTING
, "UInt", 0
, "UInt", 0 )
If(hFile = -1) {
MsgBox, 16, %A_ThisFunc%, Не удалось открыть файл.
Return 0
}
DllCall( "SetFilePointer", "UInt", hFile
, "UInt", Offset
, "UInt", 0
, "UInt", FILE_BEGIN )
If(A_LastError) {
DllCall( "CloseHandle", "UInt", hFile )
MsgBox, 16, %A_ThisFunc%
, Ошибка при установке указателя файла: %A_LastError%
Return 0
}
Ret := DllCall( "WriteFile", "UInt", hFile
, "UInt", &Buf
, "UInt", cBytes
, "UInt", &BytesWritten
, "UInt", 0 )
If(Ret = 0) {
DllCall( "CloseHandle", "UInt", hFile )
MsgBox, 16, %A_ThisFunc%, Не удалось записать в файл.
Return 0
}
DllCall( "CloseHandle", "UInt", hFile )
Return NumGet(BytesWritten, 0, "UInt")
}