625 lines
20 KiB
C++
625 lines
20 KiB
C++
|
// Copyright (C) Microsoft Corporation 1997, All Rights reserved.
|
||
|
|
||
|
#include "header.h"
|
||
|
#include "hhshell.h"
|
||
|
#include "secwin.h"
|
||
|
#include "contain.h"
|
||
|
#include "resource.h"
|
||
|
|
||
|
//Support for HH_GET_LAST_ERROR
|
||
|
#include "lasterr.h"
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#undef THIS_FILE
|
||
|
static const char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Function prototypes
|
||
|
//
|
||
|
static void FlushMessageQueue(UINT msgEnd = 0);
|
||
|
extern "C"
|
||
|
{
|
||
|
HANDLE WINAPI ShCreateHHWindow(void);
|
||
|
}
|
||
|
|
||
|
// Prototype
|
||
|
#define _CURRENT_TREAD_
|
||
|
#ifndef _CURRENT_TREAD_
|
||
|
void CALLBACK SendAsyncProc(HWND, UINT, DWORD dwData, LRESULT lResult);
|
||
|
#endif
|
||
|
|
||
|
static const char txtHHApiWindow[] = "HH_API";
|
||
|
static const char txtSharedMem[] = "hh_share";
|
||
|
static const char txtSempahore[] = "hh_semaphore";
|
||
|
|
||
|
const int CB_SHARED_MEM = 8 * 1024;
|
||
|
|
||
|
PSTR g_pszShare;
|
||
|
HANDLE g_hSharedMemory;
|
||
|
HANDLE g_hsemMemory;
|
||
|
HANDLE g_hsemNavigate = NULL;
|
||
|
HWND g_hwndApi;
|
||
|
BOOL g_fThreadCall;
|
||
|
BOOL g_fStandAlone = FALSE; // no need for threading in standalone version
|
||
|
SHORT g_tbRightMargin = 0; // magrin on the right end of the tool bar for the office animation character
|
||
|
SHORT g_tbLeftMargin = 0; // " left "
|
||
|
|
||
|
|
||
|
static HANDLE hThrd;
|
||
|
static DWORD thrdID;
|
||
|
|
||
|
extern "C"
|
||
|
HWND WINAPI HtmlHelpW(HWND hwndCaller, LPCWSTR pszFile, UINT uCommand, DWORD_PTR dwData)
|
||
|
{
|
||
|
//--- Don't display wait cursor for HH_PRETRANSLATEMESSAGE message.
|
||
|
if ( (uCommand == HH_PRETRANSLATEMESSAGE) || (uCommand == HH_PRETRANSLATEMESSAGE2) )
|
||
|
{
|
||
|
ASSERT(g_fStandAlone) ; // We have to be on same thread for this to work.
|
||
|
return xHtmlHelpW(hwndCaller, pszFile, uCommand, dwData);
|
||
|
}
|
||
|
|
||
|
if(uCommand == HH_SET_QUERYSERVICE)
|
||
|
{
|
||
|
// see if we currently have an interface, if so, release it.
|
||
|
//
|
||
|
if(g_pExternalHostServiceProvider)
|
||
|
{
|
||
|
g_pExternalHostServiceProvider->Release();
|
||
|
g_pExternalHostServiceProvider = 0;
|
||
|
}
|
||
|
|
||
|
if(dwData)
|
||
|
{
|
||
|
g_pExternalHostServiceProvider = (IServiceProvider*) dwData;
|
||
|
g_pExternalHostServiceProvider->AddRef();
|
||
|
}
|
||
|
|
||
|
return hwndCaller;
|
||
|
}
|
||
|
|
||
|
CHourGlass hourglass;
|
||
|
if (g_fStandAlone ||
|
||
|
uCommand == HH_GET_WIN_TYPE ||
|
||
|
uCommand == HH_SET_WIN_TYPE ||
|
||
|
uCommand == HH_SET_GLOBAL_PROPERTY ||
|
||
|
uCommand == HH_INITIALIZE ||
|
||
|
uCommand == HH_UNINITIALIZE)
|
||
|
{
|
||
|
return xHtmlHelpW(hwndCaller, pszFile, uCommand, dwData);
|
||
|
}
|
||
|
|
||
|
if (!g_hwndApi)
|
||
|
{
|
||
|
ShCreateHHWindow();
|
||
|
}
|
||
|
|
||
|
if(uCommand == HH_DISPLAY_TOPIC || uCommand == HH_DISPLAY_TOC || uCommand == HH_CLOSE_ALL ||
|
||
|
uCommand == HH_KEYWORD_LOOKUP || uCommand == HH_ALINK_LOOKUP)
|
||
|
{
|
||
|
WaitForNavigationComplete();
|
||
|
}
|
||
|
|
||
|
if (g_hwndApi)
|
||
|
{
|
||
|
HH_UNICODE_DATA data;
|
||
|
data.hwndCaller = hwndCaller;
|
||
|
data.pszFile = pszFile;
|
||
|
data.uCommand = uCommand;
|
||
|
data.dwData = dwData;
|
||
|
g_fThreadCall = TRUE;
|
||
|
return (HWND) SendMessage(g_hwndApi, WMP_HH_UNI_THREAD_API, (WPARAM) &data, 0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//Reset the last error.
|
||
|
if (uCommand != HH_GET_LAST_ERROR)
|
||
|
{
|
||
|
g_LastError.Reset() ;
|
||
|
}
|
||
|
return xHtmlHelpW(hwndCaller, pszFile, uCommand, dwData);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
extern "C"
|
||
|
HWND WINAPI HtmlHelpA(HWND hwndCaller, LPCSTR pszFile, UINT uCommand, DWORD_PTR dwData)
|
||
|
{
|
||
|
//--- Don't display wait cursor for HH_PRETRANSLATEMESSAGE message.
|
||
|
if ( (uCommand == HH_PRETRANSLATEMESSAGE) || (uCommand == HH_PRETRANSLATEMESSAGE2) )
|
||
|
{
|
||
|
ASSERT(g_fStandAlone) ; // We have to be on same thread for this to work.
|
||
|
return xHtmlHelpA(hwndCaller, pszFile, uCommand, dwData);
|
||
|
}
|
||
|
|
||
|
if(uCommand == HH_SET_QUERYSERVICE)
|
||
|
{
|
||
|
// see if we currently have an interface, if so, release it.
|
||
|
//
|
||
|
if(g_pExternalHostServiceProvider)
|
||
|
{
|
||
|
g_pExternalHostServiceProvider->Release();
|
||
|
g_pExternalHostServiceProvider = 0;
|
||
|
}
|
||
|
|
||
|
if(dwData)
|
||
|
{
|
||
|
g_pExternalHostServiceProvider = (IServiceProvider*) dwData;
|
||
|
g_pExternalHostServiceProvider->AddRef();
|
||
|
}
|
||
|
|
||
|
return hwndCaller;
|
||
|
}
|
||
|
|
||
|
CHourGlass hourglass;
|
||
|
if (g_fStandAlone ||
|
||
|
uCommand == HH_GET_WIN_TYPE ||
|
||
|
uCommand == HH_SET_WIN_TYPE ||
|
||
|
uCommand == HH_SET_GLOBAL_PROPERTY ||
|
||
|
uCommand == HH_INITIALIZE ||
|
||
|
uCommand == HH_UNINITIALIZE)
|
||
|
{
|
||
|
return xHtmlHelpA(hwndCaller, pszFile, uCommand, dwData);
|
||
|
}
|
||
|
|
||
|
if (!g_hwndApi)
|
||
|
{
|
||
|
ShCreateHHWindow();
|
||
|
}
|
||
|
|
||
|
if(uCommand == HH_DISPLAY_TOPIC || uCommand == HH_DISPLAY_TOC || uCommand == HH_CLOSE_ALL ||
|
||
|
uCommand == HH_KEYWORD_LOOKUP || uCommand == HH_ALINK_LOOKUP)
|
||
|
{
|
||
|
WaitForNavigationComplete();
|
||
|
}
|
||
|
|
||
|
if (g_hwndApi)
|
||
|
{
|
||
|
HH_ANSI_DATA data;
|
||
|
data.hwndCaller = /*GetDesktopWindow() ;*/ hwndCaller;
|
||
|
data.pszFile = pszFile;
|
||
|
data.uCommand = uCommand;
|
||
|
data.dwData = dwData;
|
||
|
g_fThreadCall = TRUE;
|
||
|
#ifdef _CURRENT_TREAD_
|
||
|
return (HWND) SendMessage(g_hwndApi, WMP_HH_ANSI_THREAD_API, (WPARAM) &data, 0);
|
||
|
#else
|
||
|
HWND hwndReturn = NULL;
|
||
|
BOOL b = SendMessageCallback( g_hwndApi, WMP_HH_ANSI_THREAD_API, (WPARAM) &data, 0,
|
||
|
SendAsyncProc, reinterpret_cast<DWORD>(&hwndReturn));
|
||
|
WaitForNavigationComplete() ;
|
||
|
return hwndReturn ;
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//Reset the last error.
|
||
|
if (uCommand != HH_GET_LAST_ERROR)
|
||
|
{
|
||
|
g_LastError.Reset() ;
|
||
|
}
|
||
|
|
||
|
return xHtmlHelpA(hwndCaller, pszFile, uCommand, dwData);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This window procedure is used to handle HtmlHelp API messages, and
|
||
|
* communication from individual HH windows
|
||
|
*/
|
||
|
|
||
|
static BOOL fForcedShutDown;
|
||
|
|
||
|
LRESULT WINAPI ApiWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
LRESULT result;
|
||
|
|
||
|
switch(msg) {
|
||
|
case WM_CREATE:
|
||
|
g_hwndApi = hwnd;
|
||
|
return 0;
|
||
|
|
||
|
case WMP_ANSI_API_CALL:
|
||
|
{
|
||
|
HH_ANSI_DATA* pData = (HH_ANSI_DATA*) g_pszShare;
|
||
|
HH_WINTYPE* phhWinType;
|
||
|
|
||
|
switch (pData->uCommand) {
|
||
|
case HH_GET_WIN_TYPE:
|
||
|
DBWIN("Shell HH_GET_WIN_TYPE");
|
||
|
result = (LRESULT) xHtmlHelpA(pData->hwndCaller,
|
||
|
g_pszShare + (UINT_PTR) pData->pszFile, pData->uCommand,
|
||
|
(DWORD_PTR) &phhWinType);
|
||
|
CopyMemory(pData, phhWinType, sizeof(HH_WINTYPE));
|
||
|
phhWinType = (HH_WINTYPE*) pData;
|
||
|
|
||
|
// BUGBUG: We don't copy the strings
|
||
|
|
||
|
phhWinType->pszType =
|
||
|
phhWinType->pszCaption =
|
||
|
phhWinType->pszToc =
|
||
|
phhWinType->pszIndex =
|
||
|
phhWinType->pszFile =
|
||
|
phhWinType->pszHome =
|
||
|
phhWinType->pszJump1 =
|
||
|
phhWinType->pszJump2 =
|
||
|
phhWinType->pszUrlJump1 =
|
||
|
phhWinType->pszUrlJump2 =
|
||
|
NULL;
|
||
|
|
||
|
// Note that the caller must call ReleaseSemaphore
|
||
|
|
||
|
return result;
|
||
|
|
||
|
case HH_SET_WIN_TYPE:
|
||
|
DBWIN("Shell HH_SET_WIN_TYPE");
|
||
|
phhWinType = (HH_WINTYPE*) ((PSTR) pData + pData->dwData);
|
||
|
|
||
|
// Change offsets to pointers
|
||
|
|
||
|
if (phhWinType->pszType)
|
||
|
phhWinType->pszType = (PSTR) pData + (UINT_PTR) phhWinType->pszType;
|
||
|
if (phhWinType->pszCaption)
|
||
|
phhWinType->pszCaption = (PSTR) pData + (UINT_PTR) phhWinType->pszCaption;
|
||
|
if (phhWinType->pszToc)
|
||
|
phhWinType->pszToc = (PSTR) pData + (UINT_PTR) phhWinType->pszToc;
|
||
|
if (phhWinType->pszIndex)
|
||
|
phhWinType->pszIndex = (PSTR) pData + (UINT_PTR) phhWinType->pszIndex;
|
||
|
if (phhWinType->pszFile)
|
||
|
phhWinType->pszFile = (PSTR) pData + (UINT_PTR) phhWinType->pszFile;
|
||
|
if (phhWinType->pszHome)
|
||
|
phhWinType->pszHome = (PSTR) pData + (UINT_PTR) phhWinType->pszHome;
|
||
|
if (phhWinType->pszJump1)
|
||
|
phhWinType->pszJump1 = (PSTR) pData + (UINT_PTR) phhWinType->pszJump1;
|
||
|
if (phhWinType->pszJump2)
|
||
|
phhWinType->pszJump2 = (PSTR) pData + (UINT_PTR) phhWinType->pszJump2;
|
||
|
if (phhWinType->pszUrlJump1)
|
||
|
phhWinType->pszUrlJump1 = (PSTR) pData + (UINT_PTR) phhWinType->pszUrlJump1;
|
||
|
if (phhWinType->pszUrlJump2)
|
||
|
phhWinType->pszUrlJump2 = (PSTR) pData + (UINT_PTR) phhWinType->pszUrlJump2;
|
||
|
break;
|
||
|
|
||
|
case HH_KEYWORD_LOOKUP:
|
||
|
{
|
||
|
DBWIN("Shell HH_KEYWORD_LOOKUP");
|
||
|
HH_AKLINK* phhLink = (HH_AKLINK*) pData;
|
||
|
if (phhLink->pszKeywords)
|
||
|
phhLink->pszKeywords = (PSTR) pData + (UINT_PTR) phhLink->pszKeywords;
|
||
|
if (phhLink->pszUrl)
|
||
|
phhLink->pszUrl = (PSTR) pData + (UINT_PTR) phhLink->pszUrl;
|
||
|
if (phhLink->pszMsgText)
|
||
|
phhLink->pszMsgText = (PSTR) pData + (UINT_PTR) phhLink->pszMsgText;
|
||
|
if (phhLink->pszMsgTitle)
|
||
|
phhLink->pszMsgTitle = (PSTR) pData + (UINT_PTR) phhLink->pszMsgTitle;
|
||
|
if (phhLink->pszWindow)
|
||
|
phhLink->pszWindow = (PSTR) pData + (UINT_PTR) phhLink->pszWindow;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case HH_DISPLAY_TEXT_POPUP:
|
||
|
{
|
||
|
DBWIN("Shell HH_DISPLAY_TEXT_POPUP");
|
||
|
HH_POPUP* phhSrcPop = (HH_POPUP*) pData;
|
||
|
if (phhSrcPop->pszText)
|
||
|
phhSrcPop->pszText = (PSTR) pData + (UINT_PTR) phhSrcPop->pszText;
|
||
|
if (phhSrcPop->pszFont)
|
||
|
phhSrcPop->pszFont = (PSTR) pData + (UINT_PTR) phhSrcPop->pszFont;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case HH_DISPLAY_TOPIC:
|
||
|
DBWIN("Shell HH_DISPLAY_TOPIC");
|
||
|
if (pData->dwData)
|
||
|
pData->dwData = (DWORD_PTR) ((PSTR) pData + pData->dwData);
|
||
|
break;
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
default:
|
||
|
DBWIN("Shell unsupported command");
|
||
|
break;
|
||
|
#endif
|
||
|
}
|
||
|
result = (LRESULT) xHtmlHelpA(pData->hwndCaller,
|
||
|
g_pszShare + (UINT_PTR) pData->pszFile, pData->uCommand,
|
||
|
pData->dwData);
|
||
|
ReleaseSemaphore(g_hsemMemory, 1, NULL);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
case WMP_UNICODE_API_CALL:
|
||
|
{
|
||
|
HH_UNICODE_DATA* pData = (HH_UNICODE_DATA*) g_pszShare;
|
||
|
if (pData->uCommand == HH_GET_WIN_TYPE) {
|
||
|
DBWIN("Shell UniCode command");
|
||
|
HH_WINTYPE* phhWinType;
|
||
|
result = (LRESULT) xHtmlHelpW(pData->hwndCaller, pData->pszFile, pData->uCommand,
|
||
|
(DWORD_PTR) &phhWinType);
|
||
|
CopyMemory(pData, phhWinType, sizeof(HH_WINTYPE));
|
||
|
phhWinType = (HH_WINTYPE*) pData;
|
||
|
|
||
|
// We don't copy the strings
|
||
|
|
||
|
phhWinType->pszType =
|
||
|
phhWinType->pszCaption =
|
||
|
phhWinType->pszToc =
|
||
|
phhWinType->pszIndex =
|
||
|
phhWinType->pszFile =
|
||
|
phhWinType->pszHome =
|
||
|
phhWinType->pszJump1 =
|
||
|
phhWinType->pszJump2 =
|
||
|
phhWinType->pszUrlJump1 =
|
||
|
phhWinType->pszUrlJump2 =
|
||
|
NULL;
|
||
|
|
||
|
// Note that the caller must call ReleaseSemaphore
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
#ifdef _DEBUG
|
||
|
else {
|
||
|
DBWIN("Shell unsupported UniCode command");
|
||
|
}
|
||
|
#endif
|
||
|
result = (LRESULT) xHtmlHelpW(pData->hwndCaller, pData->pszFile, pData->uCommand,
|
||
|
pData->dwData);
|
||
|
ReleaseSemaphore(g_hsemMemory, 1, NULL);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
case WMP_HH_WIN_CLOSING:
|
||
|
if (!fForcedShutDown)
|
||
|
{
|
||
|
for (int i = 0; i < g_cWindowSlots; i++) {
|
||
|
if (pahwnd[i] != NULL)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// If we get here, all our windows are closed -- time to
|
||
|
// shut down.
|
||
|
|
||
|
FlushMessageQueue();
|
||
|
DeleteAllHmData();
|
||
|
g_hwndApi = NULL;
|
||
|
PostQuitMessage(0);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Use this message to forceably shut down HH
|
||
|
|
||
|
case WMP_FORCE_HH_API_CLOSE:
|
||
|
{
|
||
|
fForcedShutDown = TRUE;
|
||
|
for (int i = 0; i < g_cWindowSlots; i++) {
|
||
|
if (pahwnd[i] != NULL)
|
||
|
SendMessage(*pahwnd[i], WM_CLOSE, 0, 0);
|
||
|
}
|
||
|
FlushMessageQueue();
|
||
|
DeleteAllHmData();
|
||
|
g_hwndApi = NULL;
|
||
|
PostQuitMessage(0);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case WMP_HH_ANSI_THREAD_API:
|
||
|
{
|
||
|
HH_ANSI_DATA* pData = (HH_ANSI_DATA*) wParam;
|
||
|
|
||
|
//Reset the last error.
|
||
|
if (pData->uCommand != HH_GET_LAST_ERROR)
|
||
|
{
|
||
|
g_LastError.Reset() ;
|
||
|
}
|
||
|
|
||
|
DBWIN("Threaded ANSI call");
|
||
|
return (LRESULT) xHtmlHelpA(pData->hwndCaller, pData->pszFile,
|
||
|
pData->uCommand, pData->dwData);
|
||
|
}
|
||
|
|
||
|
case WMP_HH_UNI_THREAD_API:
|
||
|
{
|
||
|
HH_UNICODE_DATA* pData = (HH_UNICODE_DATA*) wParam;
|
||
|
|
||
|
//Reset the last error, unless we are trying to get the last error.
|
||
|
if (pData->uCommand != HH_GET_LAST_ERROR)
|
||
|
{
|
||
|
g_LastError.Reset() ;
|
||
|
}
|
||
|
|
||
|
DBWIN("Threaded Unicode call");
|
||
|
return (LRESULT) xHtmlHelpW(pData->hwndCaller, pData->pszFile,
|
||
|
pData->uCommand, pData->dwData);
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void FlushMessageQueue(UINT msgEnd)
|
||
|
{
|
||
|
MSG msg;
|
||
|
|
||
|
while (PeekMessage(&msg, NULL, 0, msgEnd, PM_REMOVE)) {
|
||
|
TranslateMessage(&msg);
|
||
|
DispatchMessage(&msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
extern "C"
|
||
|
DWORD WINAPI HhWindowThread(LPVOID pParam)
|
||
|
{
|
||
|
#ifdef _DEBUG
|
||
|
_CrtMemState m_MemState ;
|
||
|
_CrtMemCheckpoint(&m_MemState) ;
|
||
|
#endif
|
||
|
|
||
|
static BOOL fRegistered = FALSE;
|
||
|
if (!fRegistered) {
|
||
|
fRegistered = TRUE;
|
||
|
WNDCLASS wc;
|
||
|
|
||
|
ZeroMemory(&wc, sizeof(WNDCLASS)); // clear all members
|
||
|
|
||
|
wc.lpfnWndProc = ApiWndProc;
|
||
|
wc.hInstance = _Module.GetModuleInstance();
|
||
|
wc.lpszClassName = txtHHApiWindow;
|
||
|
|
||
|
VERIFY(RegisterClass(&wc));
|
||
|
}
|
||
|
|
||
|
g_hSharedMemory = CreateFileMapping((HANDLE) -1, NULL, PAGE_READWRITE, 0,
|
||
|
CB_SHARED_MEM, txtSharedMem);
|
||
|
if (!g_hSharedMemory) {
|
||
|
hThrd = NULL;
|
||
|
if (g_hsemMemory)
|
||
|
ReleaseSemaphore(g_hsemMemory, 1, NULL);
|
||
|
return 0;
|
||
|
}
|
||
|
g_pszShare = (PSTR) MapViewOfFile(g_hSharedMemory, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
|
||
|
if (!g_hsemMemory)
|
||
|
g_hsemMemory = CreateSemaphore(NULL, 1, 9999, txtSempahore);
|
||
|
|
||
|
g_hwndApi = CreateWindow(txtHHApiWindow, "", WS_OVERLAPPED, 0, 0, 0, 0, NULL,
|
||
|
NULL, _Module.GetModuleInstance(), NULL);
|
||
|
OleInitialize(NULL);
|
||
|
ReleaseSemaphore(g_hsemMemory, 1, NULL);
|
||
|
|
||
|
AWMessagePump(g_hwndApi);
|
||
|
g_hwndApi = NULL;
|
||
|
|
||
|
if (g_hSharedMemory)
|
||
|
CloseHandle(g_hSharedMemory);
|
||
|
OleUninitialize();
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
_CrtMemDumpAllObjectsSince(&m_MemState) ;
|
||
|
#endif
|
||
|
|
||
|
// If we are launched from the shell, we should tell the shell to unload
|
||
|
// our dll.
|
||
|
|
||
|
hThrd = NULL;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
extern "C"
|
||
|
HANDLE WINAPI ShCreateHHWindow(void)
|
||
|
{
|
||
|
if (!hThrd) {
|
||
|
if (!g_hsemMemory)
|
||
|
g_hsemMemory = CreateSemaphore(NULL, 1, 9999, txtSempahore);
|
||
|
// Signal the semaphore. The thread will release it
|
||
|
#ifdef _CURRENT_TREAD_
|
||
|
WaitForSingleObject(g_hsemMemory, INFINITE);
|
||
|
#else
|
||
|
AtlWaitWithMessageLoop(g_hsemNavigate) ;
|
||
|
#endif
|
||
|
|
||
|
hThrd = CreateThread(NULL, 0, &HhWindowThread, NULL,
|
||
|
0, &thrdID);
|
||
|
SetThreadPriority(hThrd, THREAD_PRIORITY_NORMAL);
|
||
|
|
||
|
// wait for the thread to release the semaphore
|
||
|
|
||
|
#ifdef _CURRENT_TREAD_
|
||
|
WaitForSingleObject(g_hsemMemory, INFINITE);
|
||
|
#else
|
||
|
AtlWaitWithMessageLoop(g_hsemNavigate) ;
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
* Clear the signaled state now that we know the thread has
|
||
|
* created its window
|
||
|
*/
|
||
|
|
||
|
ReleaseSemaphore(g_hsemMemory, 1, NULL);
|
||
|
|
||
|
CloseHandle( hThrd );
|
||
|
}
|
||
|
return hThrd;
|
||
|
}
|
||
|
|
||
|
void WaitForNavigationComplete()
|
||
|
{
|
||
|
// Create unnamed semaphore (if it doesn't exist)
|
||
|
//
|
||
|
if (!g_hsemNavigate)
|
||
|
g_hsemNavigate = CreateSemaphore(NULL, 1, 1, NULL);
|
||
|
|
||
|
// Wait for previous navigation to reach BEFORENAVIGATE stage.
|
||
|
// Time-out after 1000ms just in case the previous navigation
|
||
|
// halted for some reason (don't want to wait here forever!).
|
||
|
//
|
||
|
#ifdef _CURRENT_TREAD_
|
||
|
DWORD dwResult = WaitForSingleObject(g_hsemNavigate, 1000);
|
||
|
#else
|
||
|
AtlWaitWithMessageLoop(g_hsemNavigate) ;
|
||
|
#endif
|
||
|
|
||
|
// if(dwResult == WAIT_TIMEOUT)
|
||
|
// MessageBox(NULL,"Wait for navigation semaphore timed out.","Notice!",MB_OK);
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
#ifndef _CURRENT_TREAD_
|
||
|
void CALLBACK SendAsyncProc(HWND, UINT, DWORD dwData, LRESULT lResult)
|
||
|
{
|
||
|
HWND* pWnd = reinterpret_cast<HWND*>(dwData) ;
|
||
|
HWND hWnd = reinterpret_cast<HWND>(lResult) ;
|
||
|
*pWnd = hWnd ;
|
||
|
}
|
||
|
#endif
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Handles pretranslating messages for HH.
|
||
|
//
|
||
|
BOOL hhPreTranslateMessage(MSG* pMsg, HWND hWndCaller /* = NULL*/ )
|
||
|
{
|
||
|
// REVIEW: Performance
|
||
|
BOOL bReturn = false ;
|
||
|
if (pMsg && IsWindow(pMsg->hwnd))
|
||
|
{
|
||
|
CHHWinType* phh;
|
||
|
|
||
|
if ( hWndCaller )
|
||
|
phh = FindHHWindowIndex(hWndCaller);
|
||
|
else
|
||
|
phh = FindHHWindowIndex(pMsg->hwnd);
|
||
|
|
||
|
if (phh && phh->m_pCIExpContainer)
|
||
|
{
|
||
|
|
||
|
unsigned uiResult = phh->m_pCIExpContainer->TranslateMessage(pMsg);
|
||
|
if ( uiResult == TAMSG_NOT_IE_ACCEL )
|
||
|
{
|
||
|
if ((pMsg->message == WM_SYSKEYDOWN) && (pMsg->wParam == VK_MENU))
|
||
|
{
|
||
|
UiStateChangeOnAlt(pMsg->hwnd) ;
|
||
|
}
|
||
|
if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_TAB))
|
||
|
{
|
||
|
UiStateChangeOnTab(pMsg->hwnd) ;
|
||
|
}
|
||
|
|
||
|
if (phh->DynamicTranslateAccelerator(pMsg))
|
||
|
{
|
||
|
bReturn = true ;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//TAMSG_TAKE_FOCUS is obsolete. Don't worry about.
|
||
|
bReturn = true ;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return bReturn ;
|
||
|
}
|