|
|
/*
* * REINIT.CPP * * Purpose: * RICHEDIT initialization routines * * Copyright (c) 1995-2001, 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"
#ifndef NOLINESERVICES
#include "_ols.h"
#ifndef NODELAYLOAD
#include <delayimp.h>
#endif
#endif
#include "_host.h"
#ifndef NOVERSIONINFO
#include <shlwapi.h>
#include "_version.h"
#endif
ASSERTDATA
class CTxtEdit; class CCmbBxWinHost;
extern void ReleaseTypeInfoPtrs();
static WCHAR wszClassREW[sizeof(MSFTEDIT_CLASS)/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
extern HANDLE g_hHeap;
void FreeHyphCache(void);
#ifndef NODELAYLOAD
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;) { #ifdef _WIN64
if (pui->pidd->rvaUnloadIAT) { PCImgDelayDescr pidd = pui->pidd; HMODULE* phmod = PFromRva(pidd->rvaHmod, (HMODULE *)NULL); HMODULE hmod = *phmod;
if (hmod) { // NOTE: (honwch 3/6/01) We don't need to reset pIAT since this
// routine is being called on DLL_PROCESS_DETACH. We only need to reset
// pIAT iff RE is staying around and we need to re-load this DLL again.
// The following line would crash because of a bug in BBT3.0 and delayed load.
// If RE is loaded into a different address space, pUnloadIAT is not fixed up
// correctly. (RE Bug 9292)
// OverlayIAT(pidd->pIAT, pidd->pUnloadIAT);
::FreeLibrary(hmod); *phmod = NULL; } #else
if (pui->pidd->pUnloadIAT) { PCImgDelayDescr pidd = pui->pidd; HMODULE hmod = *pidd->phmod;
if (hmod) { // NOTE: (honwch 3/6/01) We don't need to reset pIAT since this
// routine is being called on DLL_PROCESS_DETACH. We only need to reset
// pIAT iff RE is staying around and we need to re-load this DLL again.
// The following line would crash because of a bug in BBT3.0 and delayed load.
// If RE is loaded into a different address space, pUnloadIAT is not fixed up
// correctly. (RE Bug 9292)
// OverlayIAT(pidd->pIAT, pidd->pUnloadIAT);
::FreeLibrary(hmod); *pidd->phmod = NULL; } #endif
PUnloadInfo puiT = pui->puiNext; ::LocalFree(pui); pui = puiT; }
} } #endif
//CLEARTYPE test code Turn this flag on to test.
//#define CLEARTYPE_DEBUG
#ifdef CLEARTYPE_DEBUG
#include "ct_ras_win.h"
class CCustomTextOut:public ICustomTextOut { virtual BOOL WINAPI ExtTextOutW(HDC hdc, int X, int Y, UINT fuOptions, CONST RECT *lprc, LPCWSTR lpString, UINT cbCount, CONST INT *lpDx); virtual BOOL WINAPI GetCharWidthW(HDC hdc,UINT iFirstChar, UINT iLastChar, LPINT lpBuffer); virtual BOOL WINAPI NotifyCreateFont(HDC hdc); virtual void WINAPI NotifyDestroyFont(HFONT hFont); };
extern "C" HINSTANCE g_hRE; typedef HRESULT (*PFNPROC)(ICustomTextOut**); PFNPROC _pfnProc = NULL; CCustomTextOut *pCTO; HINSTANCE _hctras = NULL; EXTERN_C long g_ClearTypeNum=0; typedef BOOL (WINAPI *PFNEXTTEXTOUTW)(HDC, LONG, LONG, DWORD, CONST RECT*, PWSTR, ULONG, CONST LONG*); typedef BOOL (WINAPI *PFNGETCHARWIDTHW)(HDC, WCHAR, WCHAR, PLONG); typedef BOOL (WINAPI *PFNCREATEFONTINSTANCE)(HDC, DWORD); typedef BOOL (WINAPI *PFNDELETEFONTINSTANCE)(HFONT); PFNEXTTEXTOUTW _pfnExtTextOutW = NULL; PFNGETCHARWIDTHW _pfnGetCharWidthW = NULL; PFNCREATEFONTINSTANCE _pfnCreateFontInstance = NULL; PFNDELETEFONTINSTANCE _pfnDeleteFontInstance = NULL;
BOOL CCustomTextOut::ExtTextOutW(HDC hdc, int X, int Y, UINT fuOptions, CONST RECT *lprc, LPCWSTR lpString, UINT cbCount, CONST INT *lpDx) { return _pfnExtTextOutW(hdc, X, Y, fuOptions, lprc, (USHORT*) lpString, cbCount, (LONG*) lpDx); }
BOOL CCustomTextOut::GetCharWidthW(HDC hdc,UINT iFirstChar, UINT iLastChar, LPINT lpBuffer) { return _pfnGetCharWidthW(hdc, iFirstChar, iLastChar, (LONG*) lpBuffer); }
BOOL CCustomTextOut::NotifyCreateFont(HDC hdc) { return _pfnCreateFontInstance(hdc, 0); }
void CCustomTextOut::NotifyDestroyFont(HFONT hFont) { _pfnDeleteFontInstance(hFont); }
extern "C" void ClearTypeUnInitialize();
extern "C" HRESULT ClearTypeInitialize() { _hctras=LoadLibraryA("ctras.dll"); // check - cleartype dll is not gauranteed to be present
if (!_hctras) { ClearTypeUnInitialize(); return E_NOINTERFACE; } _pfnExtTextOutW=(PFNEXTTEXTOUTW)GetProcAddress(_hctras, "WAPI_EZCTExtTextOutW"); _pfnGetCharWidthW=(PFNGETCHARWIDTHW)GetProcAddress(_hctras, "WAPI_EZCTGetCharWidthW"); _pfnCreateFontInstance=(PFNCREATEFONTINSTANCE)GetProcAddress(_hctras, "WAPI_EZCTCreateFontInstance"); _pfnDeleteFontInstance=(PFNDELETEFONTINSTANCE)GetProcAddress(_hctras, "WAPI_EZCTDeleteFontInstance");
// check that we got these correctly
// future versions of cleartype could change this API
if(!_pfnExtTextOutW || !_pfnGetCharWidthW || !_pfnCreateFontInstance || !_pfnDeleteFontInstance) { ClearTypeUnInitialize(); return E_NOINTERFACE; }
pCTO=new CCustomTextOut; ICustomTextOut *pICTO=pCTO;
SetCustomTextOutHandlerEx(&pICTO, 0); return NOERROR; }
extern "C" void ClearTypeUnInitialize() { if(_hctras) { FreeLibrary(_hctras); _hctras = NULL; }
if(pCTO) { delete pCTO; pCTO = NULL; }
_pfnExtTextOutW = NULL; _pfnGetCharWidthW = NULL; _pfnCreateFontInstance = NULL; _pfnDeleteFontInstance = NULL; }
#endif
extern "C" {
BOOL WINAPI DllMain(HANDLE hmod, DWORD dwReason, LPVOID lpvReserved) { DebugMain ((HINSTANCE) hmod, dwReason, lpvReserved);
if(dwReason == DLL_PROCESS_DETACH) // We are unloading
{ #ifndef NOWINDOWHOSTS
DeleteDanglingHosts(); #endif
CRTFConverter::FreeFontSubInfo(); FreeFontCache(); DestroyFormatCaches(); ReleaseTypeInfoPtrs(); UninitKinsokuClassify(); FreeHyphCache();
// Release various resouces allocated during running...
#ifndef NOLINESERVICES
delete g_pols; #endif
#ifndef NOCOMPLEXSCRIPTS
delete g_pusp; g_pusp = NULL; #endif
ReleaseOutlineBitmaps();
#ifdef CLEARTYPE_DEBUG
ClearTypeUnInitialize(); #endif
if(hinstRE) { 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;
#if defined(DEBUG) && !defined(NOFULLDEBUG)
CatchLeaks(); #endif
#ifndef NODELAYLOAD
// lpvReserved is not NULL when DllMain DLL_PROCESS_DETACH is being called during process exit.
// In such case, we should not mess around with the delay loaded dll thunks
if (!lpvReserved) OurUnloadDelayLoadedDlls(); #endif
HeapDestroy(g_hHeap); DeleteCriticalSection(&g_CriticalSection); } else if(dwReason == DLL_PROCESS_ATTACH) // We have just loaded
{ #ifdef DEBUG
fInDllMain = TRUE; #endif
InitializeCriticalSection(&g_CriticalSection); #if !defined(DEBUG) && !defined(UNDER_CE)
// REVIEW (gheino) We should investigate if there is another
// way to do this on CE
DisableThreadLibraryCalls((HINSTANCE) hmod); #endif
hinstRE = (HINSTANCE) hmod;
W32 = new CW32System;
CopyMemory(wszClassREW, MSFTEDIT_CLASS, sizeof(MSFTEDIT_CLASS));
if(!RichFRegisterClass()) return FALSE;
#ifdef CLEARTYPE_DEBUG
ClearTypeInitialize(); #endif
#ifdef DEBUG
fInDllMain = FALSE; #endif
}
return TRUE; }
#ifndef NOVERSIONINFO
HRESULT CALLBACK DllGetVersion( DLLVERSIONINFO *pdvi ) { if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) return E_INVALIDARG; pdvi->dwBuildNumber = RICHEDIT_VERBUILD; pdvi->dwMajorVersion = RICHEDIT_VERMAJ; pdvi->dwMinorVersion = RICHEDIT_VERMIN; pdvi->dwPlatformID = DLLVER_PLATFORM_WINDOWS ; return NOERROR; } #endif
} // 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) { #ifndef NOWINDOWHOSTS
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) == NULL ) return FALSE; #endif // NOWINDOWHOSTS
return TRUE; }
#ifndef NOLISTCOMBOBOXES
extern "C" LRESULT CALLBACK RichListBoxWndProc(HWND, UINT, WPARAM, LPARAM); extern "C" 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)) 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)) W32->_fRegisteredXBox |= REGISTERED_COMBOBOX; }
//Set flag so we unregister the window class
return W32->_fRegisteredXBox; } #else // NOLISTCOMBOBOXES
__declspec(dllexport) BOOL WINAPI REExtendedRegisterClass(VOID) { return FALSE; } #endif // NOLISTCOMBOBOXES
#if !defined(NOLINESERVICES)
BOOL g_fNoLS = FALSE; #endif
#if !defined(NOCOMPLEXSCRIPTS)
BOOL g_fNoUniscribe = FALSE; #endif
#if !defined(NOLINESERVICES) && !defined(NOCOMPLEXSCRIPTS)
char *g_szMsgBox = NULL;
//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'); }
BOOL FIsLineServicesDll (const char *szDll) { return (*szDll == 'm' || *szDll == 'M') && (*(szDll+1) == 's' || *(szDll+1) == 'S') && (*(szDll+2) == 'l' || *(szDll+2) == 'L'); }
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 NODELAYLOAD
FARPROC WINAPI DliHook(unsigned dliNotify, PDelayLoadInfo pdli) { FARPROC fp = 0;
switch (dliNotify) { // Handy for debugging for now.
case dliNotePreGetProcAddress: if (FIsLineServicesDll(pdli->szDll)) fp = 0; break;
case dliFailLoadLib: { if (FIsUniscribeDll(pdli->szDll)) g_fNoUniscribe = TRUE; else g_fNoLS = TRUE;
fp = (FARPROC)(HMODULE)hinstRE;
CLock lock; if(!g_szMsgBox) { g_szMsgBox = (char *)PvAlloc(255, GMEM_ZEROINIT);
FormatMessageA(FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_FROM_SYSTEM, NULL, ERROR_MOD_NOT_FOUND, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char *)g_szMsgBox, 255, NULL);
CopyMemory(g_szMsgBox + lstrlenA(g_szMsgBox), " (", 3); CopyMemory(g_szMsgBox + lstrlenA(g_szMsgBox), pdli->szDll, lstrlenA(pdli->szDll) + 1); CopyMemory(g_szMsgBox + lstrlenA(g_szMsgBox), ")", 2); } } break;
case dliFailGetProc: if (FIsUniscribeDll(pdli->szDll)) fp = (FARPROC)GetUniscribeStubs(pdli->dlp.szProcName); else fp = (FARPROC)LsGetReverseLsimethodsStub; break; }
return fp; }
PfnDliHook __pfnDliFailureHook = DliHook; PfnDliHook __pfnDliNotifyHook = DliHook; #endif // NODELAYLOAD
#endif // NOLINESERVICES
|