// You can add unit Math to uses instead of using this function
function Log2(X: Extended): Extended;
asm
FLD1
FLD X
FYL2X
FWAIT
end;
type
PIconHeader = ^TIconHeader;
TIconHeader =
packed record
idReserved: Word;
// Reserved (must be 0)
idType: Word;
// Resource Type (1 for icons)
idCount: Word;
// How many images?
end;
function UpdateApplicationIconGroup(icofile: PChar; exefile: PChar; resID:PcHar; LangID:DWORD): Boolean;
type
PIconResInfoArray = ^TIconResInfoArray;
TIconResInfoArray =
packed record
idReserved: Word;
// Reserved (must be 0)
idType: Word;
// Resource Type (1 for icons)
idCount: Word;
// How many images?
idEntries:
array[0..(MaxInt
div SizeOf(GRPICONDIRENTRY))-2]
Of GRPICONDIRENTRY;
end;
TIconOffsetArray =
array[0..(MaxInt
div SizeOf(DWORD))-1]
Of DWORD;
PIconOffsetArray = ^TIconOffsetArray;
TIconResIDArray =
array[0..(MaxInt
div SizeOf(Word))-1]
Of Word;
PIconResIDArray = ^TIconResIDArray;
var
hExeInst : HMODULE;
hResInst : THANDLE;
AIconHeader : TIconHeader;
AIconResInfo : GRPICONDIRENTRY;
AIconResInfoArray : PIconResInfoArray;
AIconOffsetArray : PIconOffsetArray;
AIconResIDArray : PIconResIDArray;
i,CurResID : integer;
//AIconOrdinals : array Of Word;
hFile: THandle;
id: ICONDIR;
ide: ICONDIRENTRY;
pid: PICONDIR;
pgid: PGRPICONDIR;
uRead: DWord;
nSize: DWord;
pvFile: PByte;
hResSrc : HRSRC;
hResGlob : HGLOBAL;
pRes : Pointer;
ResSize : DWORD;
begin
result := False;
hFile := CreateFile(icofile, GENERIC_READ, FILE_SHARE_READ,
nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
FillChar(id, sizeof(id), 0);
if hFile <> INVALID_HANDLE_VALUE
then
try
ReadFile(hFile, id, sizeof(id), uRead,
nil);
finally
CloseHandle(hFile);
end;
AIconResIDArray :=
nil;
FillChar(AIconHeader, SizeOf(AIconHeader), 0);
hExeInst := LoadLibraryEx(exefile, 0, LOAD_LIBRARY_AS_DATAFILE);
If (hExeInst <> 0)
then
begin
hResSrc := FindResourceEx(hExeInst, RT_GROUP_ICON, resID, LangID);
If (hResSrc <> 0)
Then
begin
// get resource size
ResSize := SizeofResource(hInstance, hResSrc);
If (ResSize <> INVALID_FILE_SIZE)
Then
begin
hResGlob := LoadResource(hExeInst, hResSrc);
If (hResGlob <> 0)
Then
begin
pRes := LockResource(hResGlob);
If (pRes <>
nil)
Then
begin
// Collect information about old Icon group
CopyMemory(@AIconHeader, pRes, SizeOf(AIconHeader));
Inc(PChar(pRes), SizeOf(AIconHeader));
{Form1.ListBox1.Items.Add('Type: ' + IntToStr(AIconHeader.idType) + ', '
+ 'Count: ' + IntToStr(AIconHeader.idCount));}
FillChar(AIconResInfo, SizeOf(AIconResInfo), 0);
//SetLength(AIconOrdinals, AIconHeader.wCount);
If (AIconHeader.idCount < id.idCount)
then
GetMem(AIconResIDArray, id.idCount*SizeOf(Word))
else
GetMem(AIconResIDArray, AIconHeader.idCount*SizeOf(Word));
FillChar(AIconResIDArray^, AIconHeader.idCount*SizeOf(Word), 0);
for i := 1
to AIconHeader.idCount
do
begin
CopyMemory(@AIconResInfo, pRes, SizeOf(AIconResInfo));
Inc(PChar(pRes), SizeOf(AIconResInfo));
AIconResIDArray^[i-1] := AIconResInfo.nID;
//If (AIconResInfo.common.wBitCount = 0) then
// AIconResInfo.common.wBitCount := Trunc(log2(AIconResInfo.common.bColorCount));
{Form1.ListBox1.Items.Add(IntToStr(AIconResInfo.common.bWidth) + 'x' + IntToStr(AIconResInfo.common.bHeight)
+ ', ' + IntToStr(AIconResInfo.common.bColorCount + (AIconResInfo.common.bReserved * $100)) + ' colors'
//+ ', ' + IntToStr(AIconResInfo.common.bReserved) + ' bReserved'
+ ', ' + IntToStr(AIconResInfo.common.wPlanes) + ' planes'
+ ', ' + IntToStr(AIconResInfo.common.wBitCount) + ' bit'
+ ', ' + IntToStr(AIconResInfo.common.dwBytesInRes) + ' byte'
+ ', ' + 'Ordinal ' + IntToStr(AIconResInfo.nID));}
end;
// Search for unused Icon resource IDs
If (AIconHeader.idCount < id.idCount)
then
begin
i := AIconHeader.idCount;
CurResID := 1;
while (i < id.idCount)
and (CurResID < $7FFF)
do
begin
hResSrc := FindResourceEx(hExeInst, RT_ICON, MAKEINTRESOURCE(CurResID), LangID);
If not (hResSrc <> 0)
Then
begin
Inc(i);
AIconResIDArray^[i-1] := CurResID;
end;
Inc(CurResID);
end;
end;
end;
end;
end;
end;
FreeLibrary(hExeInst);
end;
If not ((AIconHeader.idCount > 0)
and (id.idCount > 0))
then
Exit;
hFile := CreateFile(icofile, GENERIC_READ, FILE_SHARE_READ,
nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if hFile <> INVALID_HANDLE_VALUE
then
try
// Read Data from new icon group in file
ReadFile(hFile, id, sizeof(id), uRead,
nil);
SetFilePointer(hFile, 0,
nil, FILE_BEGIN);
GetMem(pid, sizeof(ICONDIR)
{+ sizeof(ICONDIRENTRY)});
ReadFile(hFile, pid^, sizeof(ICONDIR)
{+ sizeof(ICONDIRENTRY)}, uRead,
nil);
GetMem(pgid, sizeof(GRPICONDIR)
{+ sizeof(GRPICONDIRENTRY)});
move(pid^, pgid^, sizeof(GRPICONDIR));
pgid^.idEntries.common := pid^.idEntries.common;
pgid^.idEntries.nID := AIconResIDArray^[0];
If (pgid^.idEntries.common.wBitCount = 0)
then
pgid^.idEntries.common.wBitCount := Trunc(Log2(pgid^.idEntries.common.bColorCount + (pgid^.idEntries.common.bReserved*$100)));
{Form1.ListBox1.Items.Add(IntToStr(uRead));}
// Write new data to EXE resources
hResInst := BeginUpdateResource(exefile, False);
// Resource deletion doesn't really work
{
for i := 1 to AIconHeader.idCount do
begin
ShowMessage(IntToStr(AIconResIDArray^[i-1]));
UpdateResource(hResInst, RT_Icon, MAKEINTRESOURCE(AIconResIDArray^[i-1]), LangID, nil, 0);
end;
}
//CopyMemory(pgid, @AIconHeader, SizeOf(TIconHeader));
//pgid^.idCount := 1;
//If (AIconHeader.idCount < pgid^.idCount) then
// pgid^.idCount := AIconHeader.idCount;
//SetFilePointer(hFile, SizeOf(TIconHeader), nil, FILE_BEGIN);
GetMem(AIconResInfoArray, SizeOf(TIconHeader)+(SizeOf(GRPICONDIRENTRY)*pgid^.idCount));
GetMem(AIconOffsetArray , SizeOf(DWORD)*pgid^.idCount);
AIconResInfoArray^.idReserved := pgid^.idReserved;
AIconResInfoArray^.idType := pgid^.idType;
AIconResInfoArray^.idCount := pgid^.idCount;
AIconResInfoArray^.idEntries[0] := pgid^.idEntries;
AIconOffsetArray^[0] := pid^.idEntries.dwImageOffset;
{Form1.ListBox1.Items.Add(IntToStr(AIconResInfoArray^.idEntries[0].common.bColorCount));}
for i := 2
to pgid^.idCount
do
begin
ReadFile(hFile,
ide, sizeof(ICONDIRENTRY), uRead,
nil);
AIconResInfoArray^.idEntries[i-1].common :=
ide.common;
AIconResInfoArray^.idEntries[i-1].nID := AIconResIDArray^[i-1];
AIconOffsetArray^[i-1] :=
ide.dwImageOffset;
{Form1.ListBox1.Items.Add(IntToStr(AIconResInfoArray^.idEntries[i-1].common.bColorCount + (AIconResInfoArray^.idEntries[i-1].common.bReserved*$100)));}
If (AIconResInfoArray^.idEntries[i-1].common.wBitCount = 0)
then
AIconResInfoArray^.idEntries[i-1].common.wBitCount := Trunc(Log2(AIconResInfoArray^.idEntries[i-1].common.bColorCount + (AIconResInfoArray^.idEntries[i-1].common.bReserved*$100)));
end;
pvFile:=
nil;
result := true;
for i := 1
to pgid^.idCount
do
begin
nSize := AIconResInfoArray^.idEntries[i-1].common.dwBytesInRes;
GetMem(pvFile, nSize);
SetFilePointer(hFile, AIconOffsetArray^[i-1],
nil, FILE_BEGIN);
ReadFile(hFile, pvFile^, nSize, uRead,
nil);
result := result
and UpdateResource(hResInst, RT_ICON, MAKEINTRESOURCE(AIconResInfoArray^.idEntries[i-1].nID), LangID, pvFile, nSize);
end;
UpdateResource(hResInst, RT_Group_Icon, resID, LangID, AIconResInfoArray, SizeOf(TIconHeader)+(SizeOf(GRPICONDIRENTRY)*pgid^.idCount));
EndUpdateResource(hResInst, False);
FreeMem(AIconOffsetArray);
FreeMem(AIconResInfoArray);
FreeMem(pvFile);
FreeMem(pgid);
FreeMem(pid);
finally
CloseHandle(hFile);
end;
If Assigned(AIconResIDArray)
then
FreeMem(AIconResIDArray);
end;