As requested, I will describe the process in more detail.
I must immediately state that the resulting product has every right to crash Windows, and I am not responsible if someone hasn't closed an MS Office document or has added this thing to the startup.
I rewrote the code because the original version was intended for a specific version of Heroes 3. I borrowed a lot of code from wasm.ru, especially from
http://wasm.ru/article.php?article=apihook_1How does it work? It's simple. The prog.exe application calls the set_hook function from the syshook.dll library. This could be any application that has a Windows message processing queue.
Next, the set_hook function, located in the DLL (a requirement of MSDN for system hooks), sets a hook on WH_CBT. This could be any other system hook. Events for this hook are processed by the SysMsgProc stub function. Why like this? Because we don't need the hook itself – we need to load into the address space of all applications with windows, especially Heroes.
We could have added this DLL to the registry so that it would automatically load into all applications, but I'm not perfect and I think I made a lot of mistakes. In general, to prevent the system from crashing, it's better not to do that.
When loaded, the DLL searches for the syshook.ini file in the folder from which the process was launched. The first line of this file should contain a regular expression that matches the name of the launched file, and the second line should indicate how many times to call sleep(1) when calling IsIconic.
I won't talk about the injection mechanism here – read the article; everything is clear there.
If someone says that the main procedure of the DLL should have handled unloading correctly, I will note that I wanted the program to compile on everyone's Delphi 6, and there is an error in system.pas that prevents correct handling of load/unload events. The stack is broken.
So, how does it work? There should be a syshook.ini file in the Heroes folder (an example is attached in the archive). Run the program (prog.exe), wait 3 seconds; it should write something, then run Heroes. Do not close the program.
P.S.: It would be possible to make a simpler and less clumsy solution – to modify the Heroes executable, but this is already a creative process and individual for each specific version of Heroes.
P.P.S.: In addition to the binaries, the archive also contains the source code so that those who wish can compile it as much as they want. Open the dpr files in Delphi; I compiled it in Delphi 6, you can open and compile it in Delphi 7.
The DLL and the executable are compiled separately.
Sorry for the rambling description and poor programming style – I didn't get much sleep