[FarGroup/FarManager] master: hh_compiler: add usage and diagnostic messages (ebac45c45)

0 views
Skip to first unread message

farg...@farmanager.com

unread,
Feb 19, 2026, 6:45:53 PM (7 days ago) Feb 19
to farco...@googlegroups.com
Repository : https://github.com/FarGroup/FarManager
On branch : master
Link : https://github.com/FarGroup/FarManager/commit/ebac45c45f2021e345aa0da72a122aa5cb6d7a0e

>---------------------------------------------------------------

commit ebac45c45f2021e345aa0da72a122aa5cb6d7a0e
Author: johnd0e <1838643...@users.noreply.github.com>
Date: Mon Feb 9 17:05:57 2026 +0100

hh_compiler: add usage and diagnostic messages

Also: add clear message on HHC6003

Guide user through solution of cryptic "HHC6003: Error: The file Itircl.dll has not been registered correctly."
Source: https://web.archive.org/web/20000620213107/http://mvps.org/htmlhelpcenter/itircl.htm


>---------------------------------------------------------------

ebac45c45f2021e345aa0da72a122aa5cb6d7a0e
enc/tools/hh_compiler/build.cmd | 2 +-
enc/tools/hh_compiler/hh_compiler.cpp | 130 ++++++++++++++++++++++++++++++++--
2 files changed, 125 insertions(+), 7 deletions(-)

diff --git a/enc/tools/hh_compiler/build.cmd b/enc/tools/hh_compiler/build.cmd
index 31e2afb7f..d3a0e4dd8 100644
--- a/enc/tools/hh_compiler/build.cmd
+++ b/enc/tools/hh_compiler/build.cmd
@@ -1,2 +1,2 @@
-cl /nologo /O1 /MT hh_compiler.cpp ole32.lib
+cl /nologo /O1 /MT hh_compiler.cpp ole32.lib shlwapi.lib
editbin /nologo /subsystem:console,5.0 /osversion:5.0 hh_compiler.exe
diff --git a/enc/tools/hh_compiler/hh_compiler.cpp b/enc/tools/hh_compiler/hh_compiler.cpp
index 24823bd55..a5080ecc4 100644
--- a/enc/tools/hh_compiler/hh_compiler.cpp
+++ b/enc/tools/hh_compiler/hh_compiler.cpp
@@ -1,5 +1,6 @@
#include <cstdio>
#include <windows.h>
+#include <shlwapi.h>

int CodePage;

@@ -45,7 +46,10 @@ static bool write_memory(void const** const To, const void* const From)
{
MEMORY_BASIC_INFORMATION Info;
if (!VirtualQuery(To, &Info, sizeof(Info)))
+ {
+ fprintf(stderr, "[!] VirtualQuery failed for address %p. Error: %lu\n", To, GetLastError());
return false;
+ }

DWORD Protection;

@@ -66,18 +70,30 @@ static bool write_memory(void const** const To, const void* const From)
}

if (!VirtualProtect(Info.BaseAddress, Info.RegionSize, Protection, &Protection))
+ {
+ fprintf(stderr, "[!] VirtualProtect (Unlock) failed for address %p. Error: %lu\n", Info.BaseAddress, GetLastError());
return false;
+ }

*To = From;

- return VirtualProtect(Info.BaseAddress, Info.RegionSize, Info.Protect, &Protection);
+ if (!VirtualProtect(Info.BaseAddress, Info.RegionSize, Info.Protect, &Protection))
+ {
+ fprintf(stderr, "[!] VirtualProtect (Restore) failed for address %p. Error: %lu\n", Info.BaseAddress, GetLastError());
+ return false;
+ }
+
+ return true;
}

static bool patch(HMODULE Module)
{
const auto Headers = reinterpret_cast<PIMAGE_NT_HEADERS>(PBYTE(Module) + PIMAGE_DOS_HEADER(Module)->e_lfanew);
if (Headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size <= 0)
+ {
+ fprintf(stderr, "[!] Import directory not found or empty in module %p.\n", Module);
return false;
+ }

bool AnyPatched{};

@@ -99,11 +115,26 @@ static bool patch(HMODULE Module)
const auto FunctionName = reinterpret_cast<const char*>(ImageImportByName->Name);
const auto Function = FindByName(FunctionName);

- if (Function && write_memory(reinterpret_cast<void const**>(FirstBound + i), Function))
- AnyPatched = true;
+ if (Function)
+ {
+ fprintf(stderr, "[*] Patching function: %s\n", FunctionName);
+ if (write_memory(reinterpret_cast<void const**>(FirstBound + i), Function))
+ {
+ AnyPatched = true;
+ }
+ else
+ {
+ fprintf(stderr, "[!] Failed to write memory for hook: %s\n", FunctionName);
+ }
+ }
}
}

+ if (!AnyPatched)
+ {
+ fprintf(stderr, "[!] Warning: No functions were patched. 'kernel32.dll' imports not found or target functions missing.\n");
+ }
+
return AnyPatched;
}

@@ -112,32 +143,119 @@ static int WINAPI unknown(int)
return 1;
}

+// Custom logging function for intercepting error messages
+static int LogCallback(const char* format, ...)
+{
+ va_list args;
+
+ char buffer[2048];
+ va_start(args, format);
+ int len = vsnprintf(buffer, sizeof(buffer), format, args);
+ va_end(args);
+
+ printf("%s", buffer); // original message
+
+ // "HHC6003: Error: The file Itircl.dll has not been registered correctly."
+ if (strstr(buffer, "HHC6003") && strstr(buffer, "Itircl.dll"))
+ {
+ char path[MAX_PATH] = { 0 };
+ HMODULE hHha = GetModuleHandleA("hha.dll");
+
+ if (hHha && GetModuleFileNameA(hHha, path, MAX_PATH))
+ {
+ PathRemoveFileSpecA(path);
+ PathAppendA(path, "itcc.dll");
+ }
+ else
+ {
+ strcpy_s(path, "path\\to\\itcc.dll");
+ }
+
+ fprintf(stderr,
+ "\n--------------------------------------------------------------------------------\n"
+ "RECOMMENDATION:\n"
+ "Make sure that `itcc.dll` exists and run the following command\n"
+ "with Administrator privileges:\n\n"
+ "regsvr32 \"%s\"\n",
+ path);
+
+ if (!PathFileExistsA(path))
+ {
+ fprintf(stderr,
+ "\nERROR:\n"
+ "The required file was NOT found at the expected location:\n"
+ "%s\n",
+ path);
+ }
+
+ fprintf(stderr,
+ "--------------------------------------------------------------------------------\n");
+ }
+
+ return len;
+}
+
int main(int const argc, const char* const argv[])
{
if (argc != 3)
+ {
+ fprintf(stderr, "Usage: %s <CodePage> <InputHHP>\n", argv[0]);
return 1;
+ }

CodePage = atoi(argv[1]);
+ fprintf(stderr, "[*] Target CodePage: %d\n", CodePage);

+ fprintf(stderr, "[*] Loading hha.dll...\n");
const auto HhaModule = LoadLibraryA("hha.dll");
if (!HhaModule)
+ {
+ fprintf(stderr, "[!] LoadLibraryA(\"hha.dll\") failed. Error: %lu\n"
+ "\n--------------------------------------------------------------------------------\n"
+ "RECOMMENDATION:\n"
+ "Microsoft HTML Help Workshop should be installed.\n"
+ "--------------------------------------------------------------------------------\n",
+ GetLastError());
return 1;
+ }

using CompileHHP_t = int WINAPI(const char*, int(*)(const char*, ...), int(WINAPI*)(int), DWORD);
const auto CompileHHP = reinterpret_cast<CompileHHP_t*>(GetProcAddress(HhaModule, reinterpret_cast<LPCSTR>(319)));
if (!CompileHHP)
+ {
+ fprintf(stderr, "[!] GetProcAddress(319) failed. Error: %lu\n", GetLastError());
+ FreeLibrary(HhaModule);
return 1;
+ }

if (!patch(HhaModule))
+ {
+ fprintf(stderr, "[!] Patch failed. Aborting.\n");
+ FreeLibrary(HhaModule);
return 1;
+ }

- if (!SUCCEEDED(CoInitialize({})))
+ HRESULT hr = CoInitialize({});
+ if (FAILED(hr))
+ {
+ fprintf(stderr, "[!] CoInitialize failed. HRESULT: 0x%08lX\n", hr);
+ FreeLibrary(HhaModule);
return 1;
+ }

- const auto Result = CompileHHP(argv[2], printf, unknown, 0);
+ fprintf(stderr, "[*] Starting compilation of '%s'...\n", argv[2]);
+ const auto Result = CompileHHP(argv[2], LogCallback, unknown, 0);

- CoUninitialize();
+ if (!Result)
+ {
+ fprintf(stderr, "[!] CompileHHP returned failure (0).\n");
+ }
+ else
+ {
+ fprintf(stderr, "[*] CompileHHP finished successfully.\n");
+ }

+ CoUninitialize();
FreeLibrary(HhaModule);

return Result? EXIT_SUCCESS : EXIT_FAILURE;


Reply all
Reply to author
Forward
0 new messages