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.

269 lines
6.8 KiB

  1. // File: nmhelp.cpp
  2. #include <precomp.h>
  3. #ifndef UNICODE
  4. #include <nmhelp.h>
  5. #include <htmlhelp.h>
  6. #include <strutil.h>
  7. #include <intlutil.h>
  8. extern BOOL g_fUseMLHelp;
  9. // The main NetMeeting Help file
  10. static const TCHAR s_cszWinHelpFile[] = TEXT("conf.hlp");
  11. static const TCHAR g_pszHHCtrl[] = TEXT("hhctrl.ocx");
  12. static const TCHAR g_szSHLWAPI[] = TEXT("shlwapi.dll");
  13. const LPCSTR szMLWinHelpA = (LPCSTR)395;
  14. const LPCSTR szMLHtmlHelpA = (LPCSTR)396;
  15. const LPCSTR szMLWinHelpW = (LPCSTR)397;
  16. const LPCSTR szMLHtmlHelpW = (LPCSTR)398;
  17. typedef BOOL (WINAPI * PFN_MLWinHelpA)(HWND hwndCaller, LPCSTR lpszHelp, UINT uCommand, DWORD_PTR dwData);
  18. typedef HWND (WINAPI * PFN_MLHtmlHelpA)(HWND hwndCaller, LPCSTR pszFile, UINT uCommand, DWORD_PTR dwData, DWORD dwCrossCodePage);
  19. typedef BOOL (WINAPI * PFN_MLWinHelpW)(HWND hwndCaller, LPCWSTR lpszHelp, UINT uCommand, DWORD_PTR dwData);
  20. typedef HWND (WINAPI * PFN_MLHtmlHelpW)(HWND hwndCaller, LPCWSTR pszFile, UINT uCommand, DWORD_PTR dwData, DWORD dwCrossCodePage);
  21. #ifdef UNICODE
  22. #define szMLWinHelp szMLWinHelpW
  23. #define szMLHtmlHelp szMLHtmlHelpW
  24. #define PFN_MLWinHelp PFN_MLWinHelpW
  25. #define PFN_MLHtmlHelp PFN_MLHtmlHelpW
  26. #else
  27. #define szMLWinHelp szMLWinHelpA
  28. #define szMLHtmlHelp szMLHtmlHelpA
  29. #define PFN_MLWinHelp PFN_MLWinHelpA
  30. #define PFN_MLHtmlHelp PFN_MLHtmlHelpA
  31. #endif
  32. extern "C"
  33. HWND HtmlHelpA(HWND hwndCaller, LPCSTR pszFile, UINT uCommand, DWORD_PTR dwData)
  34. {
  35. static HMODULE g_hmodHHCtrl = NULL;
  36. static HWND (WINAPI *g_pHtmlHelpA)(HWND hwndCaller, LPCSTR pszFile, UINT uCommand, DWORD_PTR dwData);
  37. if (NULL == g_hmodHHCtrl)
  38. {
  39. g_hmodHHCtrl = LoadLibrary(g_pszHHCtrl);
  40. if (NULL == g_hmodHHCtrl)
  41. {
  42. return NULL;
  43. }
  44. }
  45. #ifndef _WIN64
  46. if (NULL == g_pHtmlHelpA)
  47. {
  48. (FARPROC&)g_pHtmlHelpA = GetProcAddress(g_hmodHHCtrl, ATOM_HTMLHELP_API_ANSI);
  49. if (NULL == g_pHtmlHelpA)
  50. {
  51. return NULL;
  52. }
  53. }
  54. return g_pHtmlHelpA(hwndCaller, pszFile, uCommand, dwData);
  55. #else
  56. return NULL;
  57. #endif
  58. }
  59. /* N M W I N H E L P */
  60. /*-------------------------------------------------------------------------
  61. %%Function: NmWinHelp
  62. -------------------------------------------------------------------------*/
  63. BOOL NmWinHelp(HWND hWndMain, LPCTSTR lpszHelp, UINT uCommand, DWORD_PTR dwData)
  64. {
  65. static PFN_MLWinHelp s_pfnMLWinHelp = NULL;
  66. if (g_fUseMLHelp && (NULL == s_pfnMLWinHelp))
  67. {
  68. HINSTANCE hLib = LoadLibrary(g_szSHLWAPI);
  69. if (hLib)
  70. {
  71. s_pfnMLWinHelp = (PFN_MLWinHelp)GetProcAddress(hLib, szMLWinHelp);
  72. if (NULL == s_pfnMLWinHelp)
  73. {
  74. // must be wrong version of shlwapi.dll
  75. FreeLibrary(hLib);
  76. g_fUseMLHelp = FALSE;
  77. }
  78. }
  79. else
  80. {
  81. // cannot find shlwapi.dll
  82. g_fUseMLHelp = FALSE;
  83. }
  84. }
  85. if (NULL != s_pfnMLWinHelp)
  86. {
  87. return s_pfnMLWinHelp(hWndMain, lpszHelp, uCommand, dwData);
  88. }
  89. else
  90. {
  91. return ::WinHelp(hWndMain, lpszHelp, uCommand, dwData);
  92. }
  93. }
  94. /* N M H T M L H E L P */
  95. /*-------------------------------------------------------------------------
  96. %%Function: NmHtmlHelp
  97. -------------------------------------------------------------------------*/
  98. HWND NmHtmlHelp(HWND hwndCaller, LPCSTR pszFile, UINT uCommand, DWORD_PTR dwData)
  99. {
  100. static PFN_MLHtmlHelp s_pfnMLHtmlHelp = NULL;
  101. if (g_fUseMLHelp && (NULL == s_pfnMLHtmlHelp))
  102. {
  103. HINSTANCE hLib = LoadLibrary(g_szSHLWAPI);
  104. if (hLib)
  105. {
  106. s_pfnMLHtmlHelp = (PFN_MLHtmlHelp)GetProcAddress(hLib, szMLHtmlHelp);
  107. if (NULL == s_pfnMLHtmlHelp)
  108. {
  109. // must be wrong version of shlwapi.dll
  110. FreeLibrary(hLib);
  111. g_fUseMLHelp = FALSE;
  112. }
  113. }
  114. else
  115. {
  116. // cannot find shlwapi.dll
  117. g_fUseMLHelp = FALSE;
  118. }
  119. }
  120. if (NULL != s_pfnMLHtmlHelp)
  121. {
  122. return s_pfnMLHtmlHelp(hwndCaller, pszFile, uCommand, dwData, 0);
  123. }
  124. else
  125. {
  126. return ::HtmlHelp(hwndCaller, pszFile, uCommand, dwData);
  127. }
  128. }
  129. static const TCHAR s_cszHtmlHelpApiMarshalerWndClass[] = TEXT("NmUtil_HtmlHelpMarshalWnd");
  130. // HtmlHelp api cannot be called from multiple threads... that is, HtmlHelp must be
  131. // called from the same thread in which the DLL is loaded... This is the non-threadsafe
  132. // entry point to HtmlHelp... this must allways be called in the same thread that
  133. // InitHtmlHelpMarshaller was called....
  134. // This is the window procedure that we use to marshall calls to
  135. // HtmlHelp via calls to ShowNmHelp from arbitrary threads
  136. static LRESULT CALLBACK HtmlHelpWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  137. {
  138. switch( uMsg )
  139. {
  140. case WM_USER:
  141. {
  142. LPCTSTR lpcszHelpFile = reinterpret_cast<LPCTSTR>(lParam);
  143. NmHtmlHelp(NULL, lpcszHelpFile, HH_DISPLAY_TOPIC, 0);
  144. return(TRUE);
  145. }
  146. }
  147. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  148. }
  149. // the html help Apis are not threadsafe...
  150. // In fact, they call CoInitialize in the DLLProcessAttatch...
  151. // So essentially we are going to marshal all calls to HtmlHelp
  152. // Into the context of the first thread to call InitHtmlHelpMarshaller
  153. HRESULT InitHtmlHelpMarshaler(HINSTANCE hInst)
  154. {
  155. HRESULT hr = S_OK;
  156. WNDCLASS wc;
  157. ZeroMemory( &wc, sizeof( wc ) );
  158. wc.lpfnWndProc = HtmlHelpWndProc;
  159. wc.hInstance = hInst;
  160. wc.lpszClassName = s_cszHtmlHelpApiMarshalerWndClass;
  161. if( RegisterClass( &wc ) )
  162. {
  163. HWND hWnd = CreateWindow(s_cszHtmlHelpApiMarshalerWndClass, NULL, 0, 0, 0, 0, NULL, NULL, NULL, hInst, 0 );
  164. if( NULL == hWnd )
  165. {
  166. ERROR_OUT(("CreateWindow failed in InitHtmlHelpMarshaler"));
  167. hr = HRESULT_FROM_WIN32(GetLastError());
  168. }
  169. }
  170. else
  171. {
  172. hr = HRESULT_FROM_WIN32(GetLastError());
  173. }
  174. return hr;
  175. }
  176. VOID ShowNmHelp(LPCTSTR lpcszHtmlHelpFile)
  177. {
  178. HWND hWnd = FindWindow( s_cszHtmlHelpApiMarshalerWndClass, NULL );
  179. if( hWnd )
  180. {
  181. SendMessage( hWnd, WM_USER, 0, reinterpret_cast<LPARAM>(lpcszHtmlHelpFile) );
  182. }
  183. else
  184. {
  185. ERROR_OUT(("Could not find the Help Marshaller Window... Has InitHtmlHelpMarshaller been called yet?"));
  186. }
  187. }
  188. /* D O N M H E L P */
  189. /*-------------------------------------------------------------------------
  190. %%Function: DoNmHelp
  191. Generic routine to display the normal WinHelp information.
  192. -------------------------------------------------------------------------*/
  193. VOID DoNmHelp(HWND hwnd, UINT uCommand, DWORD_PTR dwData)
  194. {
  195. NmWinHelp(hwnd, s_cszWinHelpFile, uCommand, dwData);
  196. }
  197. // "WM_HELP" context menu handler (requires HIDC_* entry on the controls)
  198. VOID DoHelp(LPARAM lParam)
  199. {
  200. LPHELPINFO phi = (LPHELPINFO) lParam;
  201. ASSERT(phi->iContextType == HELPINFO_WINDOW);
  202. DoNmHelp((HWND) phi->hItemHandle, HELP_CONTEXTPOPUP, phi->dwContextId);
  203. }
  204. // "WM_HELP" handler (with control-to-help id map)
  205. VOID DoHelp(LPARAM lParam, const DWORD * rgId)
  206. {
  207. HWND hwnd = (HWND)(((LPHELPINFO)lParam)->hItemHandle);
  208. DoNmHelp(hwnd, HELP_WM_HELP, (DWORD_PTR) rgId);
  209. }
  210. // "WM_CONTEXTMENU" handler (with control-to-help id map)
  211. VOID DoHelpWhatsThis(WPARAM wParam, const DWORD * rgId)
  212. {
  213. HWND hwnd = (HWND)wParam;
  214. DoNmHelp(hwnd, HELP_CONTEXTMENU, (DWORD_PTR) rgId);
  215. }
  216. VOID ShutDownHelp(void)
  217. {
  218. DoNmHelp(NULL, HELP_QUIT, 0);
  219. // REVIEW: Do we shut down HTML help as well?
  220. }
  221. #endif /* UNICODE */