/* * * 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 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