The Windows NT family has some nice APIs named "BeginUpdateResource",
"UpdateResource" and "EndUpdateResource". With these APIs you can change the
resources of a dll/exe file on the fly. Unfortunately the APIs are not
supported by the Windows 9x family. If you need to change resources there,
you're normally lost. Well, the Microsoft Unicode Layer for 9x promises to
add support for those APIs, but in the current state it has serious bugs.
It crashes most of the time when being used on Delphi programs/dlls.
The NT APIs aren't as reliable as you might think, either. If you use the
resource update APIs on a Delphi binary, which has TD32 debug infos in it,
the binary is totally invalid afterwards. Windows doesn't even recognize it
as a valid PE file anymore. Another disadvantage of the NT resource update
APIs is that the size of the resource section is often not adjusted, if you
remove resources. So your binary is bigger than it has to be.
To address all those problems, I've decided to build my own resource update
functions. First of all I exactly duplicated the NT APIs. Of course I didn't
duplicate the bugs. My functions work well with TD32 debug infos. Also the
resource section is always only as big as it needs to be.
Additionally to cloning the NT APIs I added some new functions. All of this
works on both the NT and the 9x family, of course. You can get an overview
of the available functions in the madRes Reference.
First of all let's have a quick look at my API clones. I duplicated the wide
version of the APIs, only. All functions of this unit only work if you open
an update handle with "BeginUpdateResourceW" first. Then you can do some
changes with the function "UpdateResourceW". Finally you can save the changes
with the "EndUpdateResourceW" function. For more detailed documentation
just look at the official Microsoft documentation. What is written there is
in the same way true for my functions:
|
function BeginUpdateResourceW (fileName : PWideChar;
delExistingRes : bool ) : dword; stdcall;
function UpdateResourceW (update : dword;
type_ : PWideChar;
name : PWideChar;
language : word;
data : pointer;
size : dword ) : bool; stdcall;
function EndUpdateResourceW (update : dword;
discard : bool ) : bool; stdcall;
procedure KillBitmapResource(exeFullPath, bmpResName: PWideChar);
var update : dword;
begin
update := BeginUpdateResourceW(exeFullPath, false);
if update <> 0 then
try
UpdateResourceW(update, PWideChar(RT_BITMAP), bmpResName, 0, nil, 0);
finally
EndUpdateResourceW(update, false);
end;
end;
|
|
The first function which I've added to the default API set is "GetResourceW".
With this function you can ask the content of a specific resource. Or you
can just ask whether it exists, ignoring the data:
|
function GetResourceW (update : dword;
type_ : PWideChar;
name : PWideChar;
language : word;
var data : pointer;
var size : dword ) : bool; stdcall;
function DoesIconGroupResourceExist(update: dword; iconGroupResName: PWideChar) : boolean;
var data : pointer;
size : dword;
begin
result := GetResourceW(update, PWideChar(RT_GROUP_ICON), iconGroupResName, data, size);
end;
|
|
The most evident thing in the resources are perhaps the icons. Of course you
can do everything you need with just the functions above. However, icons are
quite complicated. So I've added some types and functions specifically for
easy icon dealing.
|
type
TPIconGroup = ^TIconGroup;
TIconGroup = packed record
reserved : word;
type_ : word;
itemCount : word;
items : array [0..maxInt shr 4 - 1] of packed record
width : byte;
height : byte;
colors : byte;
reserved : byte;
planes : word;
bitCount : word;
imageSize : dword;
id : word;
end;
end;
TPIcoHeader = ^TIcoHeader;
TIcoHeader = packed record
reserved : word;
type_ : word;
itemCount : word;
items : array [0..maxInt shr 4 - 1] of packed record
width : byte;
height : byte;
colors : byte;
reserved : byte;
planes : word;
bitCount : word;
imageSize : dword;
offset : dword;
end;
end;
function GetIconGroupResourceW (update : dword;
name : PWideChar;
language : word;
var iconGroup : TPIconGroup) : bool; stdcall;
function SaveIconGroupResourceW (update : dword;
name : PWideChar;
language : word;
icoFile : PWideChar) : bool; stdcall;
function LoadIconGroupResourceW (update : dword;
name : PWideChar;
language : word;
icoFile : PWideChar) : bool; stdcall;
function DeleteIconGroupResourceW (update : dword;
name : PWideChar;
language : word ) : bool; stdcall;
|
|
Finally we have two bitmap resource specific functions:
|
function SaveBitmapResourceW (update : dword;
name : PWideChar;
language : word;
bmpFile : PWideChar) : bool; stdcall;
function LoadBitmapResourceW (update : dword;
name : PWideChar;
language : word;
bmpFile : PWideChar) : bool; stdcall;
|
|