/*
 * Demo hhc replacement hhc_lite - www.benf.org/other/hhclite
 */
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <atlbase.h>

/*
 * 4th parameter to HHA_CompileHHP takes a structure which looks (roughly!) like this
 * You can also pass null to get no return information.
 */
struct HHAData
{
	unsigned long sizeIn;			// Size of structure.
	unsigned long unk1_1;			// ??
	unsigned long unk1_2;			// ??				
	unsigned long unk1_3;			// ??
	unsigned long nTopics;
	unsigned long nLocalLinks;
	unsigned long nGraphics;
	unsigned long nInternetLinks;
	unsigned long unk3_1;			// ??
	unsigned long unk3_2;			// ??
	unsigned long unk3_3;			// ??
	unsigned long unk3_4;			// ?? 
	char tgtname[MAX_PATH];
};

/*
 * Callback as mentioned below.  Return 1 to continue, 0 to abort.
 */
typedef int (WINAPI *HHACALLBACK)(LPCSTR);
/*
 * The export from hha.dll - takes
 * 
 * - Filename of main hhp file
 * - callback for important output
 * - callback for statusbar style output (ignorable)
 * - optional result info structure. (pass null if not needed.)
 */
typedef int (WINAPI *HHACOMPTYPE)(LPCSTR, HHACALLBACK, HHACALLBACK, HHAData *);

int WINAPI InfoFN(LPCSTR str)
{
	if (str && *str) std::cout << "L[" << str << "]\n";
	return 1; // we don't want to abort.
}

int WINAPI StatusFN(LPCSTR str)
{
	if (str && *str) std::cout << "P[" << str << "]\n";
	return 1; // we don't want to abort.
}

// RAII wrapper to unload on time.
class HM
{
	HMODULE m_m;
	HM(const HM & other);
	HM & operator=(const HM & other);
public:
	HM(HMODULE m) : m_m(m) {}
	~HM() { if (m_m != 0) FreeLibrary(m_m); }
	operator HMODULE() { return m_m; }

};

int hhc_inner(char * fname)
{
	if (!fname) 
	{
		std::cerr << "No filename given.\n";
		return 1;
	}

	HM hha(LoadLibraryEx("hha.dll", NULL, 0));
	if (0 == hha)
	{
		std::cerr << "Can't loadlibrary hha.dll.\n";
		return 1;
	}

	HHACOMPTYPE HHA_CompileHHP = (HHACOMPTYPE)GetProcAddress(hha, "HHA_CompileHHP");
	if (!HHA_CompileHHP)
	{
		std::cerr << "Can't find HHA_CompileHHP.\n";
		return 1;
	}

	HHAData info;
	info.sizeIn = sizeof(info);
	int ret = HHA_CompileHHP(fname, InfoFN, StatusFN, &info);
	if (!ret)
	{
		std::cerr << "HHA_CompileHHP failed.\n";
		return 1;
	}

	std::cout	<< "Topics         : " << info.nTopics << "\n" 
			<< "Local Links    : " << info.nLocalLinks << "\n"
			<< "Internet Links : " << info.nInternetLinks << "\n"
			<< "Graphics       : " << info.nGraphics << "\n"
			<< "Tgt filename   : " << info.tgtname << "\n";
	return 0;
}

/* 
 * NB: using COINIT_MULTITHREADED causes failure at compression time.
 */
int _tmain(int argc, _TCHAR* argv[])
{
	CoInitialize(NULL);
	int res = hhc_inner(argc >= 2 ? argv[1] : NULL);
	CoUninitialize();
	return res;
}