|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Запись данных об иконке в ресурсы PE файлов
Приветствую!
Все таки разобрался, как устроены ресурсы, отвечающие за иконку в PE файлах. Параллельно понял устройство и *.ico файлов, ибо это практически одно и то-же. Разница в 2 байтах заголовка сущности. Это RT_GROUP_ICON с именем `MAINICON` и один или несколько ресурсов RT_ICON с целочисленным именем, скажем от 1 до n. Сделал свой класс. Который, идеально читает как *.ico файл, так и PE. Отображает количество сущностей, данные и т.д. Идеально сохраняет в *.ico файл, с любым количеством сущностей. Хоть 1, хоть 10. Контрольная сумма совпадает полностью, с оригинальной *.ico иконкой (которую, я потом поместил в PE-Донора, при компилляции). Вот с сохранением в ресурсы PE, собственно ради чего все это и писалось, проблема. Да будь одна неладна... Иконку из одной сущности, маленького размера, взятая либо с другого PE файла, либо с иконки - записывает. Иконку из 10 сущностей, красивую, Vista Ready... Не записывает. ResourceHacker отказывается показывать RT_GROUP_ICON и RT_ICON с 6 по 10. При этом, если не записывать иконки - ресурс RT_GROUP_ICON записывается отлично, побайтно (все контрольные суммы совпадают) равен аналогичному ресурсу в PE-Доноре иконке. При этом, иконки с 1 по 5 - записываются хорошо, правда не дошли руки проверить контрольные суммы. Собственно код: Второй вариант, первый был запутанный, вызывающий общие процедуры, использующиеся при сохранении в *.ico файл, и работающие 100% в том случае. Код:
procedure TdsIconResource.SaveToResource(aFileName: WideString; aLanguage: LANGID); var mainheader: TdsIconHeader; entityheader: TdsIconEntityHeader; entityid: Word; aStream: TMemoryStream; hUpdate: THandle; i: Integer; entity: TdsIconResourceEntity; procedure SpecialWrite(const Buffer; Count: Longint); var Writed: LongInt; begin Writed:=aStream.Write(Buffer, Count); if Writed <> Count then raise Exception.Create(Format('Writed fail, %d\%d', [writed, count])); end; begin hUpdate:=BeginUpdateResourceW(PWideChar(aFileName), False); aStream:=TMemoryStream.Create; mainheader.wReserved:=0; mainheader.wType:=FType; mainheader.wCount:=FCount; SpecialWrite(mainheader, SdsIconHeader); for I := 0 to FCount - 1 do begin entity:=TdsIconResourceEntity(FEntities.Objects[i]); entityheader.bWidth:=entity.FWidth; entityheader.bHeight:=entity.FHeight; entityheader.bColorCount:=entity.FColorCount; entityheader.bReserved:=0; entityheader.wPlanes:=entity.FPlanes; entityheader.wBitCount:=entity.FBitCount; entityheader.dwBytesInRes:=entity.FData.Size; SpecialWrite(entityheader, SdsIconEntityHeader); entityid:=i+1; SpecialWrite(entityid, SizeOf(Word)); entity.FData.Position:=0; if not UpdateResourceW(hUpdate, RT_ICON, MAKEINTRESOURCE(entityid), aLanguage, entity.FData.Memory, entity.FData.Size) then raise Exception.Create('not UpdateResourceW~Icon~, '+IntToStr(GetLastError)); end; aStream.Position:=0; if not UpdateResourceW(hUpdate, RT_GROUP_ICON, 'MAINICON', aLanguage, aStream.Memory, aStream.Size) then raise Exception.Create('not UpdateResourceW~Group~, '+IntToStr(GetLastError)); if not EndUpdateResourceW(hUpdate, False) then raise Exception.Create('not EndUpdateResourceW, '+IntToStr(GetLastError)); FreeAndNil(aStream); end; В чем может быть проблема? Ошибок никаких не возникает, значит все функции возвращают истину! Есть ли какие то ограничения у BeginUpdateResource, UpdateResource, EndUpdateResource? Я ведь понимаю правильно, что можно UpdateResource - вызывать столько раз, сколько нужно? Пробовал каждый раз вызывать эту "святую троицу", так вообще - все ресурсы затерлись к чертовой бабушке! Были только иконки с 6 по 10! (Что кстати странно...) |