For knowing how to find a class in a program, you first need to known. A class exist only of a Virtual Method Table (VMT), this table contains except the virtual methods also information about the class (for more information search for VMT in the Delphi help file). Including a pointer to itself at offset vmtSelfPtr, so if you search for addresses with at vmtSelfPtr a pointer back to the address it most likely is a class.
I := Code - vmtSelfPtr;
while I < Code + CodeSize do
begin
// vmtSelfPtr must point to itself.
if PPChar(I + vmtSelfPtr)^ = I then
begin
if PPChar(I + vmtParent)^ = nil then
try
// If no classParent then class can be object
if (not UsePackages) and (TClass(I).ClassName = 'TObject') then
// if class if object add it to classes.
Add(TClass(I))
except
on EAccessViolation do
end
else
// className must be in the code section.
// classParent must be in the code section or the import section (when it is imported).
if (PPChar(I + vmtClassName)^ <= Code + CodeSize) and
(PPChar(I + vmtClassName)^ >= Code) and
(((PPChar(I + vmtParent)^ <= Code + CodeSize) and
(PPChar(I + vmtParent)^ >= Code)) or
((PPChar(I + vmtParent)^ <= ImportStart + ImportSize) and
(PPChar(I + vmtParent)^ >= ImportStart))) then
// Add possible class to possible class list.
PossClasses.Add(I);
end;
Inc(I, 4);
end;
// Can't be more then 1 TObject.
if (not TPEFileClass(PEFileClass).UsePackages) and (Count > 1) then
raise EDecompilerError.Create('There can only be one TObject.');
To filter out real classes search for a class named TObject from the list of possible classes,
// If no classParent then class can be object
if TClass(I).ClassName = 'TObject' then
// if class if object add it to classes.
Add(TClass(I))
After finding TObject, search the list of possible classes with a already found class as parent,
continue this search until no new class is found.
// Add Classes to the list which parent is in the list.
repeat
Added := False;
for J := PossClasses.Count -1 downto 0 do
begin
// Try to find parent class in classList
if FindClass(TClass(PossClasses[J]).ClassParent) <> nil then
begin
// Class in class list
Add(PossClasses[J]);
PossClasses.Delete(J);
Added := True;
end;
// Try to find parent class in a other package.
for K := 0 to High(PEFiles) do
if PEFiles[K].Classes.FindClass(TClass(PossClasses[J]).ClassParent) <> nil then
begin
// Class in class list
Add(PossClasses[J]);
PossClasses.Delete(J);
Added := True;
Break;
end;
end;
until not Added;