Too bad the whole mechanism involving TRegGroups.UnregisterModuleClasses is not documented anywhere
It is the underlying storage to support TClassFinder, which was introduced in Delphi 6, documented on-line in Delphi 2007, documented slightly in Delphi 2009, and since Delphi 2010 only one line of documentation was added (including the unchanged “instatiated”):
- Delphi 2007: [WayBack] TClassFinder Class
This is class
Classes.TClassFinder. - Delphi 2009:[WayBack] TClassFinder Class
The
TClassFinderallows the list of registered persistent classes to be retrieved. Objects instatiated from persistent classes are those that can be stored (serialised) beyond the operation of the current application. - Delphi 2010:[WayBack] Classes.TClassFinder – RAD Studio VCL Reference
TClassFinderallows registered persistent classes to be retrieved.The
TClassFinderallows the list of registered persistent classes to be retrieved. Objects instatiated from persistent classes are those that can be stored (serialised) beyond the operation of the current application.
Back to TRegGroups.UnregisterModuleClasses: it takes a HMODULE parameter and ultimately gets called through the (since Delphi 2007) on-line documented [WayBack] Classes.UnRegisterModuleClasses Function
procedure UnRegisterModuleClasses(Module: HMODULE);Call UnRegisterModuleClasses to unregister all object classes that were registered by the module with the handle specified by the Module parameter. When a class is unregistered, it can’t be loaded or saved by the component streaming system.
After unregistering a class, its name can be reused to register another object class.
To get more context about the access violation, I used both the stack trace and a debugging watch for GetModuleName(Module) (using the [WayBack] SysUtils.GetModuleName Function).
In order to see which classes were registered by what module, I set a breakpoint at in TRegGroup.AddClass (which can be called through various code paths):
procedure TRegGroup.AddClass(AClass: TPersistentClass); begin FGroupClasses.Add(AClass); end;
HModule
That gave me the class, but I also needed the HModule for a class, so I did a windows get module of currently executing code – Google Search, giving me these links, all C/C++ related:
- [WayBack] c++ – How do I get the HMODULE for the currently executing code? – Stack Overflow
I currently use the following trick (inspired from this forum):
const HMODULE GetCurrentModule() { MEMORY_BASIC_INFORMATION mbi = {0}; ::VirtualQuery( GetCurrentModule, &mbi, sizeof(mbi) ); return reinterpret_cast<HMODULE>(mbi.AllocationBase); }Is there a better way to do this that doesn’t look so hacky?
- [WayBack] Accessing the current module’s HINSTANCE from a static library | The Old New Thing
If you are using a Microsoft linker, you can take advantage of
a pseudovariable which the linker provides.EXTERN_C IMAGE_DOS_HEADER __ImageBase; #define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
The pseudovariable
__ImageBase
represents the DOS header of the module, which happens to
be what a Win32 module begins with.
In other words, it’s the base address of the module.
And the module base address is the same as itsHINSTANCE.
Here you already see some confusion: there is HINSTANCE and HMODULE. That’s a historic thing, as described by Raymond Chen in [WayBack] What is the difference between HINSTANCE and HMODULE? | The Old New Thing:
They mean the same thing today, but at one time they were quite different.
It all comes from 16-bit Windows.
In those days, a “module” represented a file on disk that had been loaded into memory, and the module “handle” was a handle to a data structure that described the parts of the file, where they come from, and where they had been loaded into memory (if at all). On the other hand an “instance” represented a “set of variables”.
One analogy that might (or might not) make sense is that a “module” is like the code for a C++ class – it describes how to construct an object, it implements the methods, it describes how the objects of the class behave. On the other hand, an “instance” is like a C++ object that belongs to that class – it describes the state of a particular instance of that object.
In C# terms, a “module” is like a “type” and an instance is like an “object”. (Except that modules don’t have things like “static members”, but it was a weak analogy anyway.)
GetModuleName
Searching for delphi “__ImageBase” – Google Search then got me [WayBack] c++ – Get DLL path at runtime – Stack Overflow with a nice Delphi related answer by [WayBack] Ian Boyd:
For Delphi users:
SysUtils.GetModuleName(hInstance); //Works; hInstance is a special global variable SysUtils.GetModuleName(0); //Fails; returns the name of the host exe process SysUtils.GetModuleName(GetModuleFilename(nil)); //Fails; returns the name of the host exe processIn case your Delphi doesn’t have SysUtils.GetModuleName, it is declared as:
...
This reassured my use of [WayBack] SysUtils.GetModuleName code was OK:
function GetModuleName(Module: HMODULE): string; var ModName: array[0..MAX_PATH] of Char; begin SetString(Result, ModName, GetModuleFileName(Module, ModName, Length(ModName))); end;
HInstance in Delphi
The example from Ian Boyd also brought back memories from long ago about the [WayBack] HInstance Variable – Delphi in a Nutshell [Book]:









