Source code of Windows XP (NT5)
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

  1. // Copyright (C) Microsoft Corporation 1996-1997, All Rights reserved.
  2. // This module contains all the routines necessary for talking to hha.dll.
  3. // This dll is installed as part of HtmlHelp Workshop, indicating that a Help
  4. // Author is working with the HtmlHelp display.
  5. /*
  6. TODO: This function calls the following lines TOO many times
  7. if (g_hmodHHA == NULL) {
  8. if (g_fTriedHHA || !LoadHHA(NULL, _Module.GetModuleInstance())) {
  9. this code needs to be consolidated.
  10. */
  11. #include "header.h"
  12. #include "hhctrl.h"
  13. #ifdef _DEBUG
  14. #undef THIS_FILE
  15. static const char THIS_FILE[] = __FILE__;
  16. #endif
  17. #include "strtable.h"
  18. #include "hha_strtable.h"
  19. #include "hhctrl.h"
  20. #include "secwin.h"
  21. #define DLL_VERSION 0x0018 // from hhafunc.h (help authoring dll project)
  22. int (WINAPI *pHHA_msg)(UINT command, WPARAM wParam, LPARAM lParam);
  23. PCSTR (STDCALL *pGetDllStringResource)(int idFormatString);
  24. int (STDCALL *pDllMsgBox)(int idFormatString, PCSTR pszSubString, UINT nType);
  25. static BOOL InitializeHHA(HWND hwnd, HINSTANCE hinst);
  26. // persistent local memory class
  27. class CDataHHA {
  28. public:
  29. CDataHHA::CDataHHA() { m_pszMsgBoxTitle = NULL; }
  30. CDataHHA::~CDataHHA() { CHECK_AND_FREE( m_pszMsgBoxTitle ); }
  31. char* GetMsgBoxTitle(void) { if( !m_pszMsgBoxTitle ) m_pszMsgBoxTitle = lcStrDup(pGetDllStringResource(IDS_AUTHOR_MSG_TITLE)); return m_pszMsgBoxTitle; }
  32. private:
  33. char* m_pszMsgBoxTitle;
  34. };
  35. static CDataHHA s_Data;
  36. #if defined(_DEBUG)
  37. void WINAPI CopyAssertInfo(PSTR pszDst);
  38. void (WINAPI *pAssertErrorReport)(PCSTR pszExpression, UINT line, LPCSTR pszFile);
  39. void AssertErrorReport(PCSTR pszExpression, UINT line, LPCSTR pszFile)
  40. {
  41. if (g_hmodHHA == NULL) {
  42. if (g_fTriedHHA || !LoadHHA(NULL, _Module.GetModuleInstance())) {
  43. HHAUnavailable:
  44. char szMsg[MAX_PATH*2];
  45. wsprintf(szMsg, "%s\n%s (%u)",
  46. pszExpression, pszFile, line);
  47. #ifdef _DEBUG
  48. int answer = ::MessageBox(GetActiveWindow(), pszExpression, "Retry to call DebugBreak()",
  49. MB_ABORTRETRYIGNORE);
  50. if (answer == IDRETRY) {
  51. DebugBreak();
  52. return;
  53. }
  54. else if (answer == IDIGNORE) {
  55. return;
  56. }
  57. #else
  58. MessageBox(GetActiveWindow(), szMsg, "Assertion error",
  59. MB_ICONEXCLAMATION);
  60. #endif
  61. }
  62. }
  63. if (pAssertErrorReport == NULL) {
  64. (FARPROC&) pAssertErrorReport =
  65. GetProcAddress(g_hmodHHA, MAKEINTATOM(26));
  66. if (pAssertErrorReport == NULL)
  67. goto HHAUnavailable;
  68. }
  69. pAssertErrorReport(pszExpression, line, pszFile);
  70. }
  71. /***************************************************************************
  72. FUNCTION: CopyAssertInfo
  73. PURPOSE: Allows additional information to be written to the
  74. assertion file.
  75. PARAMETERS:
  76. pszDst -- where to put the additional information. About 900
  77. bytes is available.
  78. RETURNS: void
  79. COMMENTS: Used when hha.dll is found, and therefore hooked up to
  80. assertion errors (HHA will call this). See InitializeHHA.
  81. MODIFICATION DATES:
  82. 25-Feb-1997 [ralphw]
  83. ***************************************************************************/
  84. void WINAPI CopyAssertInfo(PSTR pszDst)
  85. {
  86. *pszDst = '\0';
  87. return;
  88. }
  89. #endif // _DEBUG
  90. const TCHAR txtRegKeySection[] = "Software\\Microsoft\\HtmlHelp Author";
  91. const TCHAR txtRegKey[] = "location";
  92. extern "C" HMODULE LoadHHA(HWND hwnd, HINSTANCE hinst)
  93. {
  94. HKEY hkey;
  95. TCHAR szPath[MAX_PATH];
  96. if (RegOpenKeyEx(HKEY_CURRENT_USER,
  97. txtRegKeySection, 0, KEY_READ, &hkey) ==
  98. ERROR_SUCCESS) {
  99. DWORD type;
  100. DWORD cbPath = sizeof(szPath);
  101. LONG result = RegQueryValueEx(hkey, txtRegKey, 0, &type,
  102. (PBYTE) szPath, &cbPath);
  103. RegCloseKey(hkey);
  104. if (result == ERROR_SUCCESS) {
  105. g_hmodHHA = LoadLibrary(szPath);
  106. if (g_hmodHHA != NULL) {
  107. if (!InitializeHHA(hwnd, hinst)) {
  108. FreeLibrary(g_hmodHHA);
  109. g_hmodHHA = NULL;
  110. g_fTriedHHA = TRUE;
  111. return NULL;
  112. }
  113. return g_hmodHHA;
  114. }
  115. }
  116. }
  117. g_fTriedHHA = TRUE;
  118. return NULL;
  119. }
  120. /***************************************************************************
  121. FUNCTION: InitializeHHA
  122. PURPOSE: Initialize the Help Authoring dll
  123. PARAMETERS:
  124. hwnd -- will be used as the parent of HHA.dll message boxes
  125. RETURNS: FALSE if InitializeHHA can't be found, which means
  126. a very corrupted HHA.dll
  127. COMMENTS:
  128. Call this whenever the window handle for messages boxes changes.
  129. MODIFICATION DATES:
  130. 25-Feb-1997 [ralphw]
  131. ***************************************************************************/
  132. typedef void (WINAPI* COPYASSERTINFO)(PSTR pszDst);
  133. typedef struct {
  134. int cb;
  135. HINSTANCE hinstApp;
  136. PCSTR pszErrorFile;
  137. HWND hwndWindow;
  138. COPYASSERTINFO CopyAssertInfo;
  139. PCSTR pszMsgBoxTitle;
  140. // The following will be filled in by the dll
  141. BOOL fDBCSSystem;
  142. LCID lcidSystem;
  143. BOOL fDualCPU;
  144. UINT version;
  145. } HHA_INIT;
  146. typedef void (WINAPI* INITIALIZEHHA)(HHA_INIT* pinit);
  147. void (WINAPI *pInitializeHHA)(HHA_INIT* pinit);
  148. static BOOL InitializeHHA(HWND hwnd, HINSTANCE hinst)
  149. {
  150. ASSERT(g_hmodHHA != NULL);
  151. static HWND hwndLast = (HWND) -1;
  152. if (hwnd == hwndLast)
  153. return TRUE; // no change to window handle, so already initialized
  154. if (pInitializeHHA == NULL) {
  155. pInitializeHHA =
  156. (INITIALIZEHHA) GetProcAddress(g_hmodHHA, MAKEINTATOM(78));
  157. if (pInitializeHHA == NULL)
  158. return FALSE;
  159. }
  160. (FARPROC&) pGetDllStringResource = GetProcAddress(g_hmodHHA, MAKEINTATOM(194));
  161. HHA_INIT hwInit;
  162. hwInit.cb = sizeof(HHA_INIT);
  163. hwInit.hinstApp = hinst; // BUGBUG: HHA doesn't separate Resource from App. Will get English resource strings in some instances. (HINST_THIS)
  164. #if defined(_DEBUG)
  165. hwInit.pszErrorFile = "c:\\HtmlHelp.err";
  166. hwInit.CopyAssertInfo = CopyAssertInfo;
  167. #else
  168. hwInit.pszErrorFile = "";
  169. hwInit.CopyAssertInfo = NULL;
  170. #endif
  171. hwInit.pszMsgBoxTitle = s_Data.GetMsgBoxTitle();
  172. hwInit.hwndWindow = hwnd; // parent for message boxes
  173. hwInit.version = DLL_VERSION;
  174. pInitializeHHA(&hwInit);
  175. (FARPROC&) pDllMsgBox = GetProcAddress(g_hmodHHA, MAKEINTATOM(115));
  176. (FARPROC&) pHHA_msg = GetProcAddress(g_hmodHHA, MAKEINTATOM(106));
  177. return TRUE;
  178. }
  179. /***************************************************************************
  180. FUNCTION: doAuthorMessage
  181. PURPOSE: Use a format string from HHA.dll, format the message
  182. with the supplied string and display it in a message box.
  183. PARAMETERS:
  184. idStringFormatResource -- must have been defined in HHA.dll
  185. pszSubString
  186. RETURNS: void
  187. COMMENTS:
  188. The reason for doing this is to allow for larger, more informative
  189. strings for help authors without having to ship those strings in
  190. a retail package where users would never see them.
  191. MODIFICATION DATES:
  192. 25-Feb-1997 [ralphw]
  193. ***************************************************************************/
  194. void doAuthorMsg(UINT idStringFormatResource, PCSTR pszSubString)
  195. {
  196. // Work around known stack overwrite problem in hha.dll
  197. //
  198. char *pszTempString = lcStrDup(pszSubString);
  199. if(pszTempString && strlen(pszTempString) > 768)
  200. pszTempString[768] = 0;
  201. if (g_hmodHHA == NULL) {
  202. if (g_fTriedHHA || !LoadHHA(NULL, _Module.GetModuleInstance()))
  203. return; // no HHA.dll, so not a help author
  204. }
  205. if (pDllMsgBox == NULL) {
  206. (FARPROC&) pDllMsgBox = GetProcAddress(g_hmodHHA, MAKEINTATOM(15));
  207. if (pDllMsgBox == NULL)
  208. return;
  209. }
  210. // Note that the resource id is in hha.dll
  211. pDllMsgBox(idStringFormatResource, pszTempString, MB_OK);
  212. // Track the message in HtmlHelp Workshop
  213. if( !pszTempString || !*pszTempString )
  214. HHA_Msg(HHA_SEND_RESID_TO_PARENT, idStringFormatResource, (LPARAM) NULL );
  215. else
  216. HHA_Msg(HHA_SEND_RESID_AND_STRING_TO_PARENT, idStringFormatResource,
  217. (LPARAM) pszTempString);
  218. }
  219. void (WINAPI *pReportOleError)(HRESULT, PCSTR);
  220. #ifdef _DEBUG
  221. void doReportOleError(HRESULT hres)
  222. {
  223. if (g_hmodHHA == NULL) {
  224. if (g_fTriedHHA || !LoadHHA(NULL, _Module.GetModuleInstance()))
  225. return; // no HHA.dll, so not a help author
  226. }
  227. if (pReportOleError == NULL) {
  228. (FARPROC&) pReportOleError = GetProcAddress(g_hmodHHA, MAKEINTATOM(234));
  229. if (pReportOleError == NULL)
  230. return;
  231. }
  232. pReportOleError(hres, NULL);
  233. }
  234. #endif // _DEBUG
  235. void SendStringToParent(PCSTR pszMsg)
  236. {
  237. #ifdef _DEBUG
  238. OutputDebugString(pszMsg);
  239. #endif
  240. if (g_hmodHHA == NULL) {
  241. if (g_fTriedHHA || !LoadHHA(NULL, _Module.GetModuleInstance()))
  242. return; // no HHA.dll, so not a help author
  243. }
  244. ASSERT(pHHA_msg);
  245. if (!pHHA_msg) {
  246. return;
  247. }
  248. pHHA_msg(HHA_SEND_STRING_TO_PARENT, (WPARAM) pszMsg, 0);
  249. }
  250. int HHA_Msg(UINT command, WPARAM wParam, LPARAM lParam)
  251. {
  252. if (g_hmodHHA && pHHA_msg)
  253. return pHHA_msg(command, wParam, lParam);
  254. if (g_hmodHHA == NULL) {
  255. if (g_fTriedHHA || !LoadHHA(NULL, _Module.GetModuleInstance()))
  256. return 0; // no HHA.dll, so not a help author
  257. }
  258. ASSERT(pHHA_msg);
  259. if (!pHHA_msg) {
  260. return 0;
  261. }
  262. return pHHA_msg(command, wParam, lParam);
  263. }
  264. void CHtmlHelpControl::FillGeneralInformation(HHA_GEN_INFO* pgenInfo)
  265. {
  266. pgenInfo->m_pszBitmap = m_pszBitmap;
  267. // pgenInfo->m_cImages = m_cImages;
  268. pgenInfo->pflags = m_flags;
  269. pgenInfo->m_hfont = m_hfont;
  270. pgenInfo->m_clrFont = m_clrFont;
  271. pgenInfo->m_hpadding = m_hpadding;
  272. pgenInfo->m_vpadding = m_vpadding;
  273. pgenInfo->m_hImage = m_hImage;
  274. pgenInfo->m_fPopupMenu = m_fPopupMenu;
  275. pgenInfo->m_fWinHelpPopup = m_fWinHelpPopup;
  276. /*
  277. * A TOC image uses an imagelist, the handle for which is not
  278. * interchangeable with a "regular" bitmap. To show what it looks like,
  279. * we must load it as a regular bitmap. This instance of the bitmap
  280. * will get deleted when the CHtmlHelpControl class is deleted.
  281. */
  282. if (m_pszBitmap && !m_hImage) {
  283. char szBitmap[MAX_PATH];
  284. if (ConvertToCacheFile(m_pszBitmap, szBitmap)) {
  285. pgenInfo->m_hImage = m_hImage =
  286. LoadImage(_Module.GetResourceInstance(), szBitmap, IMAGE_BITMAP, 0, 0,
  287. LR_LOADFROMFILE);
  288. }
  289. }
  290. if (m_ptblItems) {
  291. pgenInfo->cItems = m_ptblItems->CountStrings();
  292. pgenInfo->apszItems = m_ptblItems->GetStringPointers();
  293. }
  294. else
  295. pgenInfo->cItems = 0;
  296. }
  297. void (STDCALL *pViewEntry)(HWND hwndParent, HHA_ENTRY_APPEARANCE* pAppear);
  298. void DisplayAuthorInfo(CInfoType *pInfoType, CSiteMap* pSiteMap, SITEMAP_ENTRY* pSiteMapEntry, HWND hwndParent, CHtmlHelpControl* phhctrl)
  299. {
  300. if (!pViewEntry)
  301. (FARPROC&) pViewEntry = GetProcAddress(g_hmodHHA,
  302. MAKEINTATOM(262));
  303. if (!pViewEntry) {
  304. pDllMsgBox(IDS_DLL_OUT_OF_DATE, "", MB_OK);
  305. return;
  306. }
  307. HHA_ENTRY_APPEARANCE entry;
  308. ZeroMemory(&entry, sizeof(entry));
  309. entry.version = HHA_REQUIRED_VERSION;
  310. entry.pSiteMap = pSiteMap;
  311. entry.pSiteMapEntry = pSiteMapEntry;
  312. entry.pszWindowName = pSiteMapEntry->GetWindowIndex() ?
  313. pSiteMap->GetEntryWindow(pSiteMapEntry) : pSiteMap->GetWindowName();
  314. entry.pszFrameName = pSiteMapEntry->GetFrameIndex() ?
  315. pSiteMap->GetEntryFrame(pSiteMapEntry) : pSiteMap->GetFrameName();
  316. /*
  317. * We use a CTable so that we can free all the strings in one fell
  318. * swoop.
  319. */
  320. CTable tblData;
  321. entry.apszUrlNames = (PCSTR*) tblData.TableMalloc(
  322. (pSiteMapEntry->cUrls * 2) * sizeof(PCSTR));
  323. SITE_ENTRY_URL* pUrl = pSiteMapEntry->pUrls;
  324. for (int i = 0; i < pSiteMapEntry->cUrls; i++) {
  325. entry.apszUrlNames[i * 2] =
  326. pUrl->urlPrimary ?
  327. pSiteMap->GetUrlString(pUrl->urlPrimary) : "";
  328. entry.apszUrlNames[i * 2 + 1] =
  329. pUrl->urlSecondary ?
  330. pSiteMap->GetUrlString(pUrl->urlSecondary) : "";
  331. pUrl = pSiteMap->NextUrlEntry(pUrl);
  332. }
  333. // Now add the type names
  334. if (pInfoType && pInfoType->HowManyInfoTypes()) {
  335. entry.apszTypes = (PCSTR*) tblData.TableMalloc(pInfoType->HowManyInfoTypes() * sizeof(PCSTR));
  336. int end = pInfoType->HowManyInfoTypes();
  337. for (int i = 0; i < end; i++)
  338. entry.apszTypes[i] = pInfoType->GetInfoTypeName(i + 1);
  339. entry.cTypes = end;
  340. }
  341. else {
  342. entry.apszTypes = NULL;
  343. entry.cTypes = 0;
  344. }
  345. if (phhctrl)
  346. phhctrl->FillGeneralInformation(&entry.genInfo);
  347. entry.genInfo.pszDefWindowName = pSiteMap->GetWindowName();
  348. entry.genInfo.pszDefFrameName = pSiteMap->GetFrameName();
  349. entry.genInfo.pszBackBitmap = pSiteMap->m_pszBackBitmap;
  350. if (phhctrl)
  351. phhctrl->ModalDialog(TRUE);
  352. pViewEntry(FindTopLevelWindow(hwndParent), &entry);
  353. if (phhctrl)
  354. phhctrl->ModalDialog(FALSE);
  355. }
  356. // BUGBUG: remove when everything works!
  357. void (STDCALL *pItDoesntWork)(void);
  358. void ItDoesntWork()
  359. {
  360. if (g_hmodHHA == NULL) {
  361. if (g_fTriedHHA || !LoadHHA(NULL, _Module.GetModuleInstance()))
  362. return; // no HHA.dll, so not a help author
  363. }
  364. if (!pItDoesntWork)
  365. (FARPROC&) pItDoesntWork = GetProcAddress(g_hmodHHA,
  366. MAKEINTATOM(296));
  367. if (pItDoesntWork)
  368. pItDoesntWork();
  369. }
  370. BOOL IsHelpAuthor(HWND hwndCaller)
  371. {
  372. if (g_hmodHHA == NULL) {
  373. if (g_fTriedHHA || !LoadHHA(hwndCaller, _Module.GetModuleInstance()))
  374. return FALSE; // no HHA.dll, so not a help author
  375. }
  376. return TRUE;
  377. }
  378. void (STDCALL *pDoHhctrlVersion)(HWND hwndParent, PCSTR pszCHMVersion);
  379. void doHhctrlVersion(HWND hwndParent, PCSTR pszCHMVersion)
  380. {
  381. if (!pDoHhctrlVersion)
  382. (FARPROC&) pDoHhctrlVersion = GetProcAddress(g_hmodHHA,
  383. MAKEINTATOM(323));
  384. if (pDoHhctrlVersion)
  385. pDoHhctrlVersion(hwndParent, pszCHMVersion);
  386. }
  387. void (STDCALL *pShowWindowType)(PHH_WINTYPE phh);
  388. void doWindowInformation(HWND hwndParent, CHHWinType* phh)
  389. {
  390. if (!pShowWindowType)
  391. (FARPROC&) pShowWindowType = GetProcAddress(g_hmodHHA,
  392. MAKEINTATOM(380));
  393. if (pShowWindowType) {
  394. CStr csz("");
  395. if (!phh->pszCustomTabs) {
  396. for (int iTab = HHWIN_NAVTYPE_CUSTOM_FIRST; iTab < HH_MAX_TABS+1; iTab++) {
  397. if (phh->fsWinProperties & (HHWIN_PROP_TAB_CUSTOM1 << (iTab - HH_TAB_CUSTOM_FIRST))) {
  398. if (csz.IsNonEmpty())
  399. csz += "\1";
  400. csz += phh->GetExtTab(iTab - HH_TAB_CUSTOM_FIRST)->pszTabName;
  401. csz += " -- ";
  402. csz += phh->GetExtTab(iTab - HH_TAB_CUSTOM_FIRST)->pszProgId;
  403. }
  404. }
  405. if (csz.IsNonEmpty())
  406. csz += "\1";
  407. phh->pszCustomTabs = csz.psz;
  408. PSTR psz = StrChr(phh->pszCustomTabs, '\1');
  409. while (psz) {
  410. *psz = '\0';
  411. psz = StrChr(psz + 1, '\1');
  412. }
  413. }
  414. pShowWindowType(phh);
  415. }
  416. else if (pDllMsgBox)
  417. pDllMsgBox(IDS_DLL_OUT_OF_DATE, "", MB_OK);
  418. }