windows-nt/Source/XPSP1/NT/windows/richedit/re30/reinit.cpp
2020-09-26 16:20:57 +08:00

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