mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
522 lines
15 KiB
522 lines
15 KiB
// Copyright (C) Microsoft Corporation 1996-1997, All Rights reserved.
|
|
|
|
// This module contains all the routines necessary for talking to hha.dll.
|
|
// This dll is installed as part of HtmlHelp Workshop, indicating that a Help
|
|
// Author is working with the HtmlHelp display.
|
|
|
|
/*
|
|
TODO: This function calls the following lines TOO many times
|
|
if (g_hmodHHA == NULL) {
|
|
if (g_fTriedHHA || !LoadHHA(NULL, _Module.GetModuleInstance())) {
|
|
|
|
this code needs to be consolidated.
|
|
|
|
|
|
*/
|
|
#include "header.h"
|
|
#include "hhctrl.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static const char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#include "strtable.h"
|
|
#include "hha_strtable.h"
|
|
#include "hhctrl.h"
|
|
#include "secwin.h"
|
|
|
|
#define DLL_VERSION 0x0018 // from hhafunc.h (help authoring dll project)
|
|
|
|
int (WINAPI *pHHA_msg)(UINT command, WPARAM wParam, LPARAM lParam);
|
|
PCSTR (STDCALL *pGetDllStringResource)(int idFormatString);
|
|
int (STDCALL *pDllMsgBox)(int idFormatString, PCSTR pszSubString, UINT nType);
|
|
static BOOL InitializeHHA(HWND hwnd, HINSTANCE hinst);
|
|
|
|
// persistent local memory class
|
|
class CDataHHA {
|
|
public:
|
|
CDataHHA::CDataHHA() { m_pszMsgBoxTitle = NULL; }
|
|
CDataHHA::~CDataHHA() { CHECK_AND_FREE( m_pszMsgBoxTitle ); }
|
|
|
|
char* GetMsgBoxTitle(void) { if( !m_pszMsgBoxTitle ) m_pszMsgBoxTitle = lcStrDup(pGetDllStringResource(IDS_AUTHOR_MSG_TITLE)); return m_pszMsgBoxTitle; }
|
|
|
|
private:
|
|
char* m_pszMsgBoxTitle;
|
|
|
|
};
|
|
|
|
static CDataHHA s_Data;
|
|
|
|
#if defined(_DEBUG)
|
|
|
|
void WINAPI CopyAssertInfo(PSTR pszDst);
|
|
|
|
void (WINAPI *pAssertErrorReport)(PCSTR pszExpression, UINT line, LPCSTR pszFile);
|
|
|
|
void AssertErrorReport(PCSTR pszExpression, UINT line, LPCSTR pszFile)
|
|
{
|
|
if (g_hmodHHA == NULL) {
|
|
if (g_fTriedHHA || !LoadHHA(NULL, _Module.GetModuleInstance())) {
|
|
HHAUnavailable:
|
|
char szMsg[MAX_PATH*2];
|
|
wsprintf(szMsg, "%s\n%s (%u)",
|
|
pszExpression, pszFile, line);
|
|
#ifdef _DEBUG
|
|
int answer = ::MessageBox(GetActiveWindow(), pszExpression, "Retry to call DebugBreak()",
|
|
MB_ABORTRETRYIGNORE);
|
|
|
|
if (answer == IDRETRY) {
|
|
DebugBreak();
|
|
return;
|
|
}
|
|
else if (answer == IDIGNORE) {
|
|
return;
|
|
}
|
|
#else
|
|
MessageBox(GetActiveWindow(), szMsg, "Assertion error",
|
|
MB_ICONEXCLAMATION);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (pAssertErrorReport == NULL) {
|
|
(FARPROC&) pAssertErrorReport =
|
|
GetProcAddress(g_hmodHHA, MAKEINTATOM(26));
|
|
if (pAssertErrorReport == NULL)
|
|
goto HHAUnavailable;
|
|
}
|
|
|
|
pAssertErrorReport(pszExpression, line, pszFile);
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: CopyAssertInfo
|
|
|
|
PURPOSE: Allows additional information to be written to the
|
|
assertion file.
|
|
|
|
PARAMETERS:
|
|
pszDst -- where to put the additional information. About 900
|
|
bytes is available.
|
|
|
|
RETURNS: void
|
|
|
|
COMMENTS: Used when hha.dll is found, and therefore hooked up to
|
|
assertion errors (HHA will call this). See InitializeHHA.
|
|
|
|
MODIFICATION DATES:
|
|
25-Feb-1997 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
void WINAPI CopyAssertInfo(PSTR pszDst)
|
|
{
|
|
*pszDst = '\0';
|
|
return;
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
const TCHAR txtRegKeySection[] = "Software\\Microsoft\\HtmlHelp Author";
|
|
const TCHAR txtRegKey[] = "location";
|
|
|
|
extern "C" HMODULE LoadHHA(HWND hwnd, HINSTANCE hinst)
|
|
{
|
|
HKEY hkey;
|
|
TCHAR szPath[MAX_PATH];
|
|
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER,
|
|
txtRegKeySection, 0, KEY_READ, &hkey) ==
|
|
ERROR_SUCCESS) {
|
|
DWORD type;
|
|
DWORD cbPath = sizeof(szPath);
|
|
LONG result = RegQueryValueEx(hkey, txtRegKey, 0, &type,
|
|
(PBYTE) szPath, &cbPath);
|
|
RegCloseKey(hkey);
|
|
if (result == ERROR_SUCCESS) {
|
|
g_hmodHHA = LoadLibrary(szPath);
|
|
if (g_hmodHHA != NULL) {
|
|
if (!InitializeHHA(hwnd, hinst)) {
|
|
FreeLibrary(g_hmodHHA);
|
|
g_hmodHHA = NULL;
|
|
g_fTriedHHA = TRUE;
|
|
return NULL;
|
|
}
|
|
return g_hmodHHA;
|
|
}
|
|
}
|
|
}
|
|
g_fTriedHHA = TRUE;
|
|
return NULL;
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: InitializeHHA
|
|
|
|
PURPOSE: Initialize the Help Authoring dll
|
|
|
|
PARAMETERS:
|
|
hwnd -- will be used as the parent of HHA.dll message boxes
|
|
|
|
RETURNS: FALSE if InitializeHHA can't be found, which means
|
|
a very corrupted HHA.dll
|
|
|
|
COMMENTS:
|
|
Call this whenever the window handle for messages boxes changes.
|
|
|
|
MODIFICATION DATES:
|
|
25-Feb-1997 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
typedef void (WINAPI* COPYASSERTINFO)(PSTR pszDst);
|
|
|
|
typedef struct {
|
|
int cb;
|
|
HINSTANCE hinstApp;
|
|
PCSTR pszErrorFile;
|
|
HWND hwndWindow;
|
|
COPYASSERTINFO CopyAssertInfo;
|
|
PCSTR pszMsgBoxTitle;
|
|
|
|
// The following will be filled in by the dll
|
|
|
|
BOOL fDBCSSystem;
|
|
LCID lcidSystem;
|
|
BOOL fDualCPU;
|
|
UINT version;
|
|
} HHA_INIT;
|
|
|
|
|
|
typedef void (WINAPI* INITIALIZEHHA)(HHA_INIT* pinit);
|
|
void (WINAPI *pInitializeHHA)(HHA_INIT* pinit);
|
|
|
|
static BOOL InitializeHHA(HWND hwnd, HINSTANCE hinst)
|
|
{
|
|
ASSERT(g_hmodHHA != NULL);
|
|
static HWND hwndLast = (HWND) -1;
|
|
|
|
if (hwnd == hwndLast)
|
|
return TRUE; // no change to window handle, so already initialized
|
|
|
|
if (pInitializeHHA == NULL) {
|
|
pInitializeHHA =
|
|
(INITIALIZEHHA) GetProcAddress(g_hmodHHA, MAKEINTATOM(78));
|
|
if (pInitializeHHA == NULL)
|
|
return FALSE;
|
|
}
|
|
|
|
(FARPROC&) pGetDllStringResource = GetProcAddress(g_hmodHHA, MAKEINTATOM(194));
|
|
|
|
HHA_INIT hwInit;
|
|
hwInit.cb = sizeof(HHA_INIT);
|
|
hwInit.hinstApp = hinst; // BUGBUG: HHA doesn't separate Resource from App. Will get English resource strings in some instances. (HINST_THIS)
|
|
#if defined(_DEBUG)
|
|
hwInit.pszErrorFile = "c:\\HtmlHelp.err";
|
|
hwInit.CopyAssertInfo = CopyAssertInfo;
|
|
#else
|
|
hwInit.pszErrorFile = "";
|
|
hwInit.CopyAssertInfo = NULL;
|
|
#endif
|
|
hwInit.pszMsgBoxTitle = s_Data.GetMsgBoxTitle();
|
|
hwInit.hwndWindow = hwnd; // parent for message boxes
|
|
hwInit.version = DLL_VERSION;
|
|
pInitializeHHA(&hwInit);
|
|
|
|
(FARPROC&) pDllMsgBox = GetProcAddress(g_hmodHHA, MAKEINTATOM(115));
|
|
(FARPROC&) pHHA_msg = GetProcAddress(g_hmodHHA, MAKEINTATOM(106));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: doAuthorMessage
|
|
|
|
PURPOSE: Use a format string from HHA.dll, format the message
|
|
with the supplied string and display it in a message box.
|
|
|
|
PARAMETERS:
|
|
idStringFormatResource -- must have been defined in HHA.dll
|
|
pszSubString
|
|
|
|
RETURNS: void
|
|
|
|
COMMENTS:
|
|
The reason for doing this is to allow for larger, more informative
|
|
strings for help authors without having to ship those strings in
|
|
a retail package where users would never see them.
|
|
|
|
MODIFICATION DATES:
|
|
25-Feb-1997 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
void doAuthorMsg(UINT idStringFormatResource, PCSTR pszSubString)
|
|
{
|
|
// Work around known stack overwrite problem in hha.dll
|
|
//
|
|
char *pszTempString = lcStrDup(pszSubString);
|
|
|
|
if(pszTempString && strlen(pszTempString) > 768)
|
|
pszTempString[768] = 0;
|
|
|
|
if (g_hmodHHA == NULL) {
|
|
if (g_fTriedHHA || !LoadHHA(NULL, _Module.GetModuleInstance()))
|
|
return; // no HHA.dll, so not a help author
|
|
}
|
|
|
|
if (pDllMsgBox == NULL) {
|
|
(FARPROC&) pDllMsgBox = GetProcAddress(g_hmodHHA, MAKEINTATOM(15));
|
|
if (pDllMsgBox == NULL)
|
|
return;
|
|
}
|
|
|
|
// Note that the resource id is in hha.dll
|
|
|
|
pDllMsgBox(idStringFormatResource, pszTempString, MB_OK);
|
|
|
|
// Track the message in HtmlHelp Workshop
|
|
if( !pszTempString || !*pszTempString )
|
|
HHA_Msg(HHA_SEND_RESID_TO_PARENT, idStringFormatResource, (LPARAM) NULL );
|
|
else
|
|
HHA_Msg(HHA_SEND_RESID_AND_STRING_TO_PARENT, idStringFormatResource,
|
|
(LPARAM) pszTempString);
|
|
}
|
|
|
|
void (WINAPI *pReportOleError)(HRESULT, PCSTR);
|
|
|
|
#ifdef _DEBUG
|
|
|
|
void doReportOleError(HRESULT hres)
|
|
{
|
|
if (g_hmodHHA == NULL) {
|
|
if (g_fTriedHHA || !LoadHHA(NULL, _Module.GetModuleInstance()))
|
|
return; // no HHA.dll, so not a help author
|
|
}
|
|
|
|
if (pReportOleError == NULL) {
|
|
(FARPROC&) pReportOleError = GetProcAddress(g_hmodHHA, MAKEINTATOM(234));
|
|
if (pReportOleError == NULL)
|
|
return;
|
|
}
|
|
pReportOleError(hres, NULL);
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
void SendStringToParent(PCSTR pszMsg)
|
|
{
|
|
#ifdef _DEBUG
|
|
OutputDebugString(pszMsg);
|
|
#endif
|
|
|
|
if (g_hmodHHA == NULL) {
|
|
if (g_fTriedHHA || !LoadHHA(NULL, _Module.GetModuleInstance()))
|
|
return; // no HHA.dll, so not a help author
|
|
}
|
|
ASSERT(pHHA_msg);
|
|
if (!pHHA_msg) {
|
|
return;
|
|
}
|
|
|
|
pHHA_msg(HHA_SEND_STRING_TO_PARENT, (WPARAM) pszMsg, 0);
|
|
}
|
|
|
|
int HHA_Msg(UINT command, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (g_hmodHHA && pHHA_msg)
|
|
return pHHA_msg(command, wParam, lParam);
|
|
|
|
if (g_hmodHHA == NULL) {
|
|
if (g_fTriedHHA || !LoadHHA(NULL, _Module.GetModuleInstance()))
|
|
return 0; // no HHA.dll, so not a help author
|
|
}
|
|
ASSERT(pHHA_msg);
|
|
if (!pHHA_msg) {
|
|
return 0;
|
|
}
|
|
|
|
return pHHA_msg(command, wParam, lParam);
|
|
}
|
|
|
|
void CHtmlHelpControl::FillGeneralInformation(HHA_GEN_INFO* pgenInfo)
|
|
{
|
|
pgenInfo->m_pszBitmap = m_pszBitmap;
|
|
// pgenInfo->m_cImages = m_cImages;
|
|
pgenInfo->pflags = m_flags;
|
|
pgenInfo->m_hfont = m_hfont;
|
|
pgenInfo->m_clrFont = m_clrFont;
|
|
pgenInfo->m_hpadding = m_hpadding;
|
|
pgenInfo->m_vpadding = m_vpadding;
|
|
pgenInfo->m_hImage = m_hImage;
|
|
pgenInfo->m_fPopupMenu = m_fPopupMenu;
|
|
pgenInfo->m_fWinHelpPopup = m_fWinHelpPopup;
|
|
|
|
/*
|
|
* A TOC image uses an imagelist, the handle for which is not
|
|
* interchangeable with a "regular" bitmap. To show what it looks like,
|
|
* we must load it as a regular bitmap. This instance of the bitmap
|
|
* will get deleted when the CHtmlHelpControl class is deleted.
|
|
*/
|
|
|
|
if (m_pszBitmap && !m_hImage) {
|
|
char szBitmap[MAX_PATH];
|
|
if (ConvertToCacheFile(m_pszBitmap, szBitmap)) {
|
|
pgenInfo->m_hImage = m_hImage =
|
|
LoadImage(_Module.GetResourceInstance(), szBitmap, IMAGE_BITMAP, 0, 0,
|
|
LR_LOADFROMFILE);
|
|
}
|
|
}
|
|
|
|
if (m_ptblItems) {
|
|
pgenInfo->cItems = m_ptblItems->CountStrings();
|
|
pgenInfo->apszItems = m_ptblItems->GetStringPointers();
|
|
}
|
|
else
|
|
pgenInfo->cItems = 0;
|
|
}
|
|
|
|
void (STDCALL *pViewEntry)(HWND hwndParent, HHA_ENTRY_APPEARANCE* pAppear);
|
|
|
|
void DisplayAuthorInfo(CInfoType *pInfoType, CSiteMap* pSiteMap, SITEMAP_ENTRY* pSiteMapEntry, HWND hwndParent, CHtmlHelpControl* phhctrl)
|
|
{
|
|
if (!pViewEntry)
|
|
(FARPROC&) pViewEntry = GetProcAddress(g_hmodHHA,
|
|
MAKEINTATOM(262));
|
|
if (!pViewEntry) {
|
|
pDllMsgBox(IDS_DLL_OUT_OF_DATE, "", MB_OK);
|
|
return;
|
|
}
|
|
HHA_ENTRY_APPEARANCE entry;
|
|
ZeroMemory(&entry, sizeof(entry));
|
|
entry.version = HHA_REQUIRED_VERSION;
|
|
entry.pSiteMap = pSiteMap;
|
|
entry.pSiteMapEntry = pSiteMapEntry;
|
|
|
|
entry.pszWindowName = pSiteMapEntry->GetWindowIndex() ?
|
|
pSiteMap->GetEntryWindow(pSiteMapEntry) : pSiteMap->GetWindowName();
|
|
entry.pszFrameName = pSiteMapEntry->GetFrameIndex() ?
|
|
pSiteMap->GetEntryFrame(pSiteMapEntry) : pSiteMap->GetFrameName();
|
|
|
|
/*
|
|
* We use a CTable so that we can free all the strings in one fell
|
|
* swoop.
|
|
*/
|
|
|
|
CTable tblData;
|
|
entry.apszUrlNames = (PCSTR*) tblData.TableMalloc(
|
|
(pSiteMapEntry->cUrls * 2) * sizeof(PCSTR));
|
|
|
|
SITE_ENTRY_URL* pUrl = pSiteMapEntry->pUrls;
|
|
for (int i = 0; i < pSiteMapEntry->cUrls; i++) {
|
|
entry.apszUrlNames[i * 2] =
|
|
pUrl->urlPrimary ?
|
|
pSiteMap->GetUrlString(pUrl->urlPrimary) : "";
|
|
entry.apszUrlNames[i * 2 + 1] =
|
|
pUrl->urlSecondary ?
|
|
pSiteMap->GetUrlString(pUrl->urlSecondary) : "";
|
|
pUrl = pSiteMap->NextUrlEntry(pUrl);
|
|
}
|
|
|
|
// Now add the type names
|
|
|
|
if (pInfoType && pInfoType->HowManyInfoTypes()) {
|
|
entry.apszTypes = (PCSTR*) tblData.TableMalloc(pInfoType->HowManyInfoTypes() * sizeof(PCSTR));
|
|
int end = pInfoType->HowManyInfoTypes();
|
|
for (int i = 0; i < end; i++)
|
|
entry.apszTypes[i] = pInfoType->GetInfoTypeName(i + 1);
|
|
entry.cTypes = end;
|
|
}
|
|
else {
|
|
entry.apszTypes = NULL;
|
|
entry.cTypes = 0;
|
|
}
|
|
|
|
if (phhctrl)
|
|
phhctrl->FillGeneralInformation(&entry.genInfo);
|
|
entry.genInfo.pszDefWindowName = pSiteMap->GetWindowName();
|
|
entry.genInfo.pszDefFrameName = pSiteMap->GetFrameName();
|
|
entry.genInfo.pszBackBitmap = pSiteMap->m_pszBackBitmap;
|
|
|
|
if (phhctrl)
|
|
phhctrl->ModalDialog(TRUE);
|
|
pViewEntry(FindTopLevelWindow(hwndParent), &entry);
|
|
if (phhctrl)
|
|
phhctrl->ModalDialog(FALSE);
|
|
}
|
|
|
|
// BUGBUG: remove when everything works!
|
|
|
|
void (STDCALL *pItDoesntWork)(void);
|
|
|
|
void ItDoesntWork()
|
|
{
|
|
if (g_hmodHHA == NULL) {
|
|
if (g_fTriedHHA || !LoadHHA(NULL, _Module.GetModuleInstance()))
|
|
return; // no HHA.dll, so not a help author
|
|
}
|
|
|
|
if (!pItDoesntWork)
|
|
(FARPROC&) pItDoesntWork = GetProcAddress(g_hmodHHA,
|
|
MAKEINTATOM(296));
|
|
if (pItDoesntWork)
|
|
pItDoesntWork();
|
|
}
|
|
|
|
BOOL IsHelpAuthor(HWND hwndCaller)
|
|
{
|
|
if (g_hmodHHA == NULL) {
|
|
if (g_fTriedHHA || !LoadHHA(hwndCaller, _Module.GetModuleInstance()))
|
|
return FALSE; // no HHA.dll, so not a help author
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void (STDCALL *pDoHhctrlVersion)(HWND hwndParent, PCSTR pszCHMVersion);
|
|
|
|
void doHhctrlVersion(HWND hwndParent, PCSTR pszCHMVersion)
|
|
{
|
|
if (!pDoHhctrlVersion)
|
|
(FARPROC&) pDoHhctrlVersion = GetProcAddress(g_hmodHHA,
|
|
MAKEINTATOM(323));
|
|
if (pDoHhctrlVersion)
|
|
pDoHhctrlVersion(hwndParent, pszCHMVersion);
|
|
}
|
|
|
|
void (STDCALL *pShowWindowType)(PHH_WINTYPE phh);
|
|
|
|
void doWindowInformation(HWND hwndParent, CHHWinType* phh)
|
|
{
|
|
if (!pShowWindowType)
|
|
(FARPROC&) pShowWindowType = GetProcAddress(g_hmodHHA,
|
|
MAKEINTATOM(380));
|
|
if (pShowWindowType) {
|
|
CStr csz("");
|
|
if (!phh->pszCustomTabs) {
|
|
for (int iTab = HHWIN_NAVTYPE_CUSTOM_FIRST; iTab < HH_MAX_TABS+1; iTab++) {
|
|
if (phh->fsWinProperties & (HHWIN_PROP_TAB_CUSTOM1 << (iTab - HH_TAB_CUSTOM_FIRST))) {
|
|
if (csz.IsNonEmpty())
|
|
csz += "\1";
|
|
csz += phh->GetExtTab(iTab - HH_TAB_CUSTOM_FIRST)->pszTabName;
|
|
csz += " -- ";
|
|
csz += phh->GetExtTab(iTab - HH_TAB_CUSTOM_FIRST)->pszProgId;
|
|
}
|
|
}
|
|
if (csz.IsNonEmpty())
|
|
csz += "\1";
|
|
phh->pszCustomTabs = csz.psz;
|
|
PSTR psz = StrChr(phh->pszCustomTabs, '\1');
|
|
while (psz) {
|
|
*psz = '\0';
|
|
psz = StrChr(psz + 1, '\1');
|
|
}
|
|
}
|
|
pShowWindowType(phh);
|
|
}
|
|
else if (pDllMsgBox)
|
|
pDllMsgBox(IDS_DLL_OUT_OF_DATE, "", MB_OK);
|
|
}
|