396 lines
9.4 KiB
C++
396 lines
9.4 KiB
C++
/*
|
|
*
|
|
* REINIT.C
|
|
*
|
|
* Purpose:
|
|
* RICHEDIT initialization routines
|
|
*
|
|
* Copyright (c) 1995-1997, Microsoft Corporation. All rights reserved.
|
|
*/
|
|
|
|
#include "_common.h"
|
|
#include "_font.h"
|
|
#include "_format.h"
|
|
#include "_disp.h"
|
|
#include "_clasfyc.h"
|
|
#include "zmouse.h"
|
|
#include "_rtfconv.h"
|
|
#include "_ols.h"
|
|
#include "_host.h"
|
|
|
|
// The IA64 linker does not currently handle DELAYLOAD
|
|
#include <delayimp.h>
|
|
|
|
ASSERTDATA
|
|
|
|
class CTxtEdit;
|
|
class CCmbBxWinHost;
|
|
|
|
extern void ReleaseTypeInfoPtrs();
|
|
|
|
static char szClassREA[sizeof(RICHEDIT_CLASSA)];
|
|
static WCHAR wszClassREW[sizeof(RICHEDIT_CLASSW)/sizeof(WCHAR)];
|
|
|
|
static WCHAR wszClassLBW[] = LISTBOX_CLASSW;
|
|
static WCHAR wszClassCBW[] = COMBOBOX_CLASSW;
|
|
#define REGISTERED_LISTBOX 1
|
|
#define REGISTERED_COMBOBOX 2
|
|
|
|
// a critical section for multi-threading support.
|
|
CRITICAL_SECTION g_CriticalSection;
|
|
|
|
HINSTANCE hinstRE = 0;
|
|
|
|
static BOOL RichFRegisterClass(VOID);
|
|
|
|
#ifdef DEBUG
|
|
BOOL fInDllMain = FALSE; // used to ensure that GDI calls are not made during
|
|
// DLL_PROCESS_ATTACH
|
|
#endif
|
|
|
|
void FreeFontCache(); // Defined in font.cpp
|
|
void ReleaseOutlineBitmaps(); // Defined in render.cpp
|
|
|
|
#ifdef DEBUG
|
|
void CatchLeaks(void);
|
|
#endif
|
|
|
|
static inline
|
|
void WINAPI
|
|
OverlayIAT(PImgThunkData pitdDst, PCImgThunkData pitdSrc) {
|
|
memcpy(pitdDst, pitdSrc, CountOfImports(pitdDst) * sizeof IMAGE_THUNK_DATA);
|
|
}
|
|
|
|
void OurUnloadDelayLoadedDlls(void)
|
|
{
|
|
PUnloadInfo pui = __puiHead;
|
|
|
|
for (;pui;)
|
|
{
|
|
#if DELAYLOAD_VERSION >= 0x200
|
|
if (pui->pidd->rvaUnloadIAT)
|
|
{
|
|
PCImgDelayDescr pidd = pui->pidd;
|
|
HMODULE hmod = *(HMODULE *)((PCHAR)&__ImageBase + pidd->rvaHmod);
|
|
OverlayIAT((PImgThunkData) ((PCHAR)&__ImageBase + pidd->rvaIAT),
|
|
(PCImgThunkData) ((PCHAR)&__ImageBase + pidd->rvaUnloadIAT));
|
|
::FreeLibrary(hmod);
|
|
*(HMODULE *)((PCHAR)&__ImageBase+pidd->rvaHmod) = NULL;
|
|
|
|
PUnloadInfo puiT = pui->puiNext;
|
|
::LocalFree(pui);
|
|
pui = puiT;
|
|
}
|
|
#else
|
|
if (pui->pidd->pUnloadIAT)
|
|
{
|
|
PCImgDelayDescr pidd = pui->pidd;
|
|
HMODULE hmod = *pidd->phmod;
|
|
|
|
OverlayIAT(pidd->pIAT, pidd->pUnloadIAT);
|
|
::FreeLibrary(hmod);
|
|
*pidd->phmod = NULL;
|
|
|
|
PUnloadInfo puiT = pui->puiNext;
|
|
::LocalFree(pui);
|
|
pui = puiT;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
extern "C"
|
|
{
|
|
|
|
#ifdef PEGASUS
|
|
BOOL WINAPI DllMain(HANDLE hmod, DWORD dwReason, LPVOID lpvReserved)
|
|
#else
|
|
BOOL WINAPI DllMain(HMODULE hmod, DWORD dwReason, LPVOID lpvReserved)
|
|
#endif
|
|
{
|
|
DebugMain (hmod, dwReason, lpvReserved);
|
|
|
|
if(dwReason == DLL_PROCESS_DETACH) // We are unloading
|
|
{
|
|
DeleteDanglingHosts();
|
|
CRTFConverter::FreeFontSubInfo();
|
|
FreeFontCache();
|
|
DestroyFormatCaches();
|
|
ReleaseTypeInfoPtrs();
|
|
UninitKinsokuClassify();
|
|
|
|
// Release various resouces allocated during running...
|
|
delete g_pols;
|
|
delete g_pusp;
|
|
g_pusp = NULL;
|
|
|
|
ReleaseOutlineBitmaps();
|
|
|
|
if(hinstRE)
|
|
{
|
|
#ifndef PEGASUS
|
|
UnregisterClassA(szClassREA, hinstRE);
|
|
#ifdef RICHED32_BUILD
|
|
UnregisterClassA(szClassRE10A, hinstRE);
|
|
#endif
|
|
#endif
|
|
W32->UnregisterClass(wszClassREW, hinstRE);
|
|
if (W32->_fRegisteredXBox)
|
|
{
|
|
// There may be cases where these window classes
|
|
// are still in memory in which case UnregisterClass
|
|
// will fail. So keep track of that
|
|
if (W32->UnregisterClass(wszClassLBW, hinstRE))
|
|
W32->_fRegisteredXBox &= ~REGISTERED_LISTBOX;
|
|
if (W32->UnregisterClass(wszClassCBW, hinstRE))
|
|
W32->_fRegisteredXBox &= ~REGISTERED_COMBOBOX;
|
|
}
|
|
}
|
|
delete W32;
|
|
|
|
#ifdef DEBUG
|
|
CatchLeaks();
|
|
#endif
|
|
#ifndef _WIN64
|
|
OurUnloadDelayLoadedDlls();
|
|
#endif
|
|
DeleteCriticalSection(&g_CriticalSection);
|
|
}
|
|
else if(dwReason == DLL_PROCESS_ATTACH) // We have just loaded
|
|
{
|
|
#ifdef DEBUG
|
|
fInDllMain = TRUE;
|
|
#endif
|
|
InitializeCriticalSection(&g_CriticalSection);
|
|
#ifndef DEBUG
|
|
DisableThreadLibraryCalls(hmod);
|
|
#endif
|
|
#ifdef PEGASUS
|
|
hinstRE = (HINSTANCE) hmod;
|
|
#else
|
|
hinstRE = hmod;
|
|
#endif
|
|
|
|
W32 = new CW32System;
|
|
|
|
WCHAR wszFileName[_MAX_PATH];
|
|
CopyMemory(szClassREA, RICHEDIT_CLASSA, sizeof(CERICHEDIT_CLASSA));
|
|
CopyMemory(wszClassREW, RICHEDIT_CLASSW, sizeof(CERICHEDIT_CLASSW));
|
|
int iLen = W32->GetModuleFileName((HMODULE) hmod, wszFileName, _MAX_PATH);
|
|
if (iLen)
|
|
{
|
|
iLen -= sizeof("riched20.dll") - 1;
|
|
if (!lstrcmpi(&wszFileName[iLen] , TEXT("richedce.dll")))
|
|
{
|
|
// This code allows the dll to be renamed for Win CE.
|
|
Assert(sizeof(RICHEDIT_CLASSA) == sizeof(CERICHEDIT_CLASSA));
|
|
Assert(sizeof(RICHEDIT_CLASSW) == sizeof(CERICHEDIT_CLASSW));
|
|
CopyMemory(szClassREA, CERICHEDIT_CLASSA, sizeof(CERICHEDIT_CLASSA));
|
|
CopyMemory(wszClassREW, CERICHEDIT_CLASSW, sizeof(CERICHEDIT_CLASSW));
|
|
}
|
|
}
|
|
|
|
if(!RichFRegisterClass())
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
fInDllMain = FALSE;
|
|
#endif
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
} // extern "C"
|
|
|
|
/*
|
|
* RichFRegisterClass
|
|
*
|
|
* Purpose:
|
|
* registers the window classes used by richedit
|
|
*
|
|
* Algorithm:
|
|
* register two window classes, a Unicode one and an ANSI
|
|
* one. This enables clients to optimize their use of
|
|
* the edit control w.r.t to ANSI/Unicode data
|
|
*/
|
|
|
|
static BOOL RichFRegisterClass(VOID)
|
|
{
|
|
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "RichFRegisterClass");
|
|
WNDCLASS wc;
|
|
|
|
wc.style = CS_DBLCLKS | CS_GLOBALCLASS | CS_PARENTDC;
|
|
wc.lpfnWndProc = RichEditWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = sizeof(CTxtEdit FAR *);
|
|
wc.hInstance = hinstRE;
|
|
wc.hIcon = 0;
|
|
wc.hCursor = 0;
|
|
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = wszClassREW;
|
|
|
|
if( W32->RegisterREClass(&wc, szClassREA, RichEditANSIWndProc) == NULL )
|
|
{
|
|
return FALSE;
|
|
};
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* RichFRegisterClass
|
|
*
|
|
* Purpose:
|
|
* registers the window classes used by REListbox
|
|
*
|
|
* Algorithm:
|
|
* register two window classes, a Unicode one and an ANSI
|
|
* one. This enables clients to optimize their use of
|
|
* the edit control w.r.t to ANSI/Unicode data
|
|
*/
|
|
extern LRESULT CALLBACK RichListBoxWndProc(HWND, UINT, WPARAM, LPARAM);
|
|
extern LRESULT CALLBACK RichComboBoxWndProc(HWND, UINT, WPARAM, LPARAM);
|
|
__declspec(dllexport) BOOL WINAPI REExtendedRegisterClass(VOID)
|
|
{
|
|
TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "REExtendedRegisterClass");
|
|
|
|
WNDCLASS wc;
|
|
|
|
if (!(W32->_fRegisteredXBox & REGISTERED_LISTBOX))
|
|
{
|
|
// Globally register the listbox
|
|
wc.style = CS_DBLCLKS | CS_GLOBALCLASS | CS_PARENTDC;
|
|
wc.lpfnWndProc = RichListBoxWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = sizeof(CTxtEdit FAR *);
|
|
wc.hInstance = hinstRE;
|
|
wc.hIcon = 0;
|
|
wc.hCursor = 0;
|
|
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = wszClassLBW;
|
|
|
|
if(W32->RegisterREClass(&wc, NULL, NULL))
|
|
W32->_fRegisteredXBox |= REGISTERED_LISTBOX;
|
|
}
|
|
|
|
if (!(W32->_fRegisteredXBox & REGISTERED_COMBOBOX))
|
|
{
|
|
// globally register the combobox
|
|
wc.style = CS_DBLCLKS | CS_GLOBALCLASS | CS_PARENTDC | CS_VREDRAW | CS_HREDRAW;
|
|
wc.lpfnWndProc = RichComboBoxWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = sizeof(CCmbBxWinHost FAR *);
|
|
wc.hInstance = hinstRE;
|
|
wc.hIcon = 0;
|
|
wc.hCursor = 0;
|
|
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = wszClassCBW;
|
|
|
|
if(W32->RegisterREClass(&wc, NULL, NULL))
|
|
W32->_fRegisteredXBox |= REGISTERED_COMBOBOX;
|
|
}
|
|
|
|
//Set flag so we unregister the window class
|
|
return W32->_fRegisteredXBox;
|
|
}
|
|
|
|
BOOL g_fNoLS = FALSE;
|
|
BOOL g_fNoUniscribe = FALSE;
|
|
//This is a stub function which we call when we can't find LineServices.
|
|
//The stub function needs to be the the first function we call in LS.
|
|
LSERR WINAPI LsGetReverseLsimethodsStub(LSIMETHODS *plsim)
|
|
{
|
|
return lserrOutOfMemory;
|
|
}
|
|
|
|
//Ugly, but good enough
|
|
BOOL FIsUniscribeDll (const char *szDll)
|
|
{
|
|
return (*szDll == 'u' || *szDll == 'U');
|
|
}
|
|
|
|
HRESULT WINAPI ScriptGetPropertiesStub(const SCRIPT_PROPERTIES ***ppSp,int *piNumScripts)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
const SCRIPT_LOGATTR* WINAPI ScriptString_pLogAttrStub(SCRIPT_STRING_ANALYSIS ssa)
|
|
{
|
|
// USP build 0175 (shipped with IE5 and Office2K) doesnt support this API.
|
|
return NULL;
|
|
}
|
|
|
|
// Get Uniscibe's fake entry points
|
|
|
|
FARPROC WINAPI GetUniscribeStubs(LPCSTR szProcName)
|
|
{
|
|
if (!lstrcmpiA(szProcName, "ScriptGetProperties"))
|
|
return (FARPROC)ScriptGetPropertiesStub;
|
|
|
|
if (!lstrcmpiA(szProcName, "ScriptString_pLogAttr"))
|
|
return (FARPROC)ScriptString_pLogAttrStub;
|
|
|
|
#ifdef DEBUG
|
|
char szAssert[128];
|
|
|
|
wsprintfA(szAssert, "Uniscribe API =%s= is missing. Fix it NOW!", szProcName);
|
|
|
|
AssertSz(FALSE, szAssert);
|
|
#endif
|
|
|
|
return (FARPROC)ScriptGetPropertiesStub; // we're dying...
|
|
}
|
|
|
|
#ifndef _WIN64
|
|
FARPROC WINAPI DliHook(unsigned dliNotify, PDelayLoadInfo pdli)
|
|
{
|
|
FARPROC fp = 0;
|
|
|
|
switch (dliNotify)
|
|
{
|
|
case dliFailLoadLib:
|
|
{
|
|
if (FIsUniscribeDll(pdli->szDll))
|
|
g_fNoUniscribe = TRUE;
|
|
else
|
|
g_fNoLS = TRUE;
|
|
|
|
fp = (FARPROC)(HMODULE)hinstRE;
|
|
char szBuf[255];
|
|
|
|
FormatMessageA(FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
|
|
ERROR_MOD_NOT_FOUND,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
(char*)szBuf, sizeof(szBuf), NULL);
|
|
|
|
CopyMemory(szBuf + lstrlenA(szBuf), " (", 3);
|
|
CopyMemory(szBuf + lstrlenA(szBuf), pdli->szDll, lstrlenA(pdli->szDll) + 1);
|
|
CopyMemory(szBuf + lstrlenA(szBuf), ")", 2);
|
|
|
|
MessageBoxA(NULL, szBuf, NULL, MB_ICONEXCLAMATION | MB_TASKMODAL | MB_SETFOREGROUND);
|
|
}
|
|
break;
|
|
|
|
|
|
case dliFailGetProc:
|
|
if (FIsUniscribeDll(pdli->szDll))
|
|
fp = (FARPROC)GetUniscribeStubs(pdli->dlp.szProcName);
|
|
else
|
|
fp = (FARPROC)LsGetReverseLsimethodsStub;
|
|
break;
|
|
}
|
|
|
|
return fp;
|
|
}
|
|
|
|
PfnDliHook __pfnDliFailureHook = DliHook;
|
|
|
|
#endif //!_WIN64
|
|
|