Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

562 lines
14 KiB

  1. /*
  2. *
  3. * REINIT.CPP
  4. *
  5. * Purpose:
  6. * RICHEDIT initialization routines
  7. *
  8. * Copyright (c) 1995-2001, Microsoft Corporation. All rights reserved.
  9. */
  10. #include "_common.h"
  11. #include "_font.h"
  12. #include "_format.h"
  13. #include "_disp.h"
  14. #include "_clasfyc.h"
  15. #include "zmouse.h"
  16. #include "_rtfconv.h"
  17. #ifndef NOLINESERVICES
  18. #include "_ols.h"
  19. #ifndef NODELAYLOAD
  20. #include <delayimp.h>
  21. #endif
  22. #endif
  23. #include "_host.h"
  24. #ifndef NOVERSIONINFO
  25. #include <shlwapi.h>
  26. #include "_version.h"
  27. #endif
  28. ASSERTDATA
  29. class CTxtEdit;
  30. class CCmbBxWinHost;
  31. extern void ReleaseTypeInfoPtrs();
  32. static WCHAR wszClassREW[sizeof(MSFTEDIT_CLASS)/sizeof(WCHAR)];
  33. static WCHAR wszClassLBW[] = LISTBOX_CLASSW;
  34. static WCHAR wszClassCBW[] = COMBOBOX_CLASSW;
  35. #define REGISTERED_LISTBOX 1
  36. #define REGISTERED_COMBOBOX 2
  37. // a critical section for multi-threading support.
  38. CRITICAL_SECTION g_CriticalSection;
  39. HINSTANCE hinstRE = 0;
  40. static BOOL RichFRegisterClass(VOID);
  41. #ifdef DEBUG
  42. BOOL fInDllMain = FALSE; // used to ensure that GDI calls are not made during
  43. // DLL_PROCESS_ATTACH
  44. #endif
  45. void FreeFontCache(); // Defined in font.cpp
  46. void ReleaseOutlineBitmaps(); // Defined in render.cpp
  47. #ifdef DEBUG
  48. void CatchLeaks(void);
  49. #endif
  50. extern HANDLE g_hHeap;
  51. void FreeHyphCache(void);
  52. #ifndef NODELAYLOAD
  53. static inline
  54. void WINAPI
  55. OverlayIAT(PImgThunkData pitdDst, PCImgThunkData pitdSrc) {
  56. memcpy(pitdDst, pitdSrc, CountOfImports(pitdDst) * sizeof IMAGE_THUNK_DATA);
  57. }
  58. void OurUnloadDelayLoadedDlls(void)
  59. {
  60. PUnloadInfo pui = __puiHead;
  61. for (;pui;)
  62. {
  63. #ifdef _WIN64
  64. if (pui->pidd->rvaUnloadIAT)
  65. {
  66. PCImgDelayDescr pidd = pui->pidd;
  67. HMODULE* phmod = PFromRva(pidd->rvaHmod, (HMODULE *)NULL);
  68. HMODULE hmod = *phmod;
  69. if (hmod)
  70. {
  71. // NOTE: (honwch 3/6/01) We don't need to reset pIAT since this
  72. // routine is being called on DLL_PROCESS_DETACH. We only need to reset
  73. // pIAT iff RE is staying around and we need to re-load this DLL again.
  74. // The following line would crash because of a bug in BBT3.0 and delayed load.
  75. // If RE is loaded into a different address space, pUnloadIAT is not fixed up
  76. // correctly. (RE Bug 9292)
  77. // OverlayIAT(pidd->pIAT, pidd->pUnloadIAT);
  78. ::FreeLibrary(hmod);
  79. *phmod = NULL;
  80. }
  81. #else
  82. if (pui->pidd->pUnloadIAT)
  83. {
  84. PCImgDelayDescr pidd = pui->pidd;
  85. HMODULE hmod = *pidd->phmod;
  86. if (hmod)
  87. {
  88. // NOTE: (honwch 3/6/01) We don't need to reset pIAT since this
  89. // routine is being called on DLL_PROCESS_DETACH. We only need to reset
  90. // pIAT iff RE is staying around and we need to re-load this DLL again.
  91. // The following line would crash because of a bug in BBT3.0 and delayed load.
  92. // If RE is loaded into a different address space, pUnloadIAT is not fixed up
  93. // correctly. (RE Bug 9292)
  94. // OverlayIAT(pidd->pIAT, pidd->pUnloadIAT);
  95. ::FreeLibrary(hmod);
  96. *pidd->phmod = NULL;
  97. }
  98. #endif
  99. PUnloadInfo puiT = pui->puiNext;
  100. ::LocalFree(pui);
  101. pui = puiT;
  102. }
  103. }
  104. }
  105. #endif
  106. //CLEARTYPE test code Turn this flag on to test.
  107. //#define CLEARTYPE_DEBUG
  108. #ifdef CLEARTYPE_DEBUG
  109. #include "ct_ras_win.h"
  110. class CCustomTextOut:public ICustomTextOut
  111. {
  112. virtual BOOL WINAPI ExtTextOutW(HDC hdc, int X, int Y, UINT fuOptions,
  113. CONST RECT *lprc, LPCWSTR lpString, UINT cbCount, CONST INT *lpDx);
  114. virtual BOOL WINAPI GetCharWidthW(HDC hdc,UINT iFirstChar, UINT iLastChar,
  115. LPINT lpBuffer);
  116. virtual BOOL WINAPI NotifyCreateFont(HDC hdc);
  117. virtual void WINAPI NotifyDestroyFont(HFONT hFont);
  118. };
  119. extern "C" HINSTANCE g_hRE;
  120. typedef HRESULT (*PFNPROC)(ICustomTextOut**);
  121. PFNPROC _pfnProc = NULL;
  122. CCustomTextOut *pCTO;
  123. HINSTANCE _hctras = NULL;
  124. EXTERN_C long g_ClearTypeNum=0;
  125. typedef BOOL (WINAPI *PFNEXTTEXTOUTW)(HDC, LONG, LONG, DWORD,
  126. CONST RECT*, PWSTR, ULONG, CONST LONG*);
  127. typedef BOOL (WINAPI *PFNGETCHARWIDTHW)(HDC, WCHAR, WCHAR, PLONG);
  128. typedef BOOL (WINAPI *PFNCREATEFONTINSTANCE)(HDC, DWORD);
  129. typedef BOOL (WINAPI *PFNDELETEFONTINSTANCE)(HFONT);
  130. PFNEXTTEXTOUTW _pfnExtTextOutW = NULL;
  131. PFNGETCHARWIDTHW _pfnGetCharWidthW = NULL;
  132. PFNCREATEFONTINSTANCE _pfnCreateFontInstance = NULL;
  133. PFNDELETEFONTINSTANCE _pfnDeleteFontInstance = NULL;
  134. BOOL CCustomTextOut::ExtTextOutW(HDC hdc, int X, int Y, UINT fuOptions,
  135. CONST RECT *lprc, LPCWSTR lpString, UINT cbCount, CONST INT *lpDx)
  136. {
  137. return _pfnExtTextOutW(hdc, X, Y, fuOptions, lprc, (USHORT*) lpString, cbCount, (LONG*) lpDx);
  138. }
  139. BOOL CCustomTextOut::GetCharWidthW(HDC hdc,UINT iFirstChar, UINT iLastChar,
  140. LPINT lpBuffer)
  141. {
  142. return _pfnGetCharWidthW(hdc, iFirstChar, iLastChar, (LONG*) lpBuffer);
  143. }
  144. BOOL CCustomTextOut::NotifyCreateFont(HDC hdc)
  145. {
  146. return _pfnCreateFontInstance(hdc, 0);
  147. }
  148. void CCustomTextOut::NotifyDestroyFont(HFONT hFont)
  149. {
  150. _pfnDeleteFontInstance(hFont);
  151. }
  152. extern "C" void ClearTypeUnInitialize();
  153. extern "C" HRESULT ClearTypeInitialize()
  154. {
  155. _hctras=LoadLibraryA("ctras.dll");
  156. // check - cleartype dll is not gauranteed to be present
  157. if (!_hctras)
  158. {
  159. ClearTypeUnInitialize();
  160. return E_NOINTERFACE;
  161. }
  162. _pfnExtTextOutW=(PFNEXTTEXTOUTW)GetProcAddress(_hctras, "WAPI_EZCTExtTextOutW");
  163. _pfnGetCharWidthW=(PFNGETCHARWIDTHW)GetProcAddress(_hctras, "WAPI_EZCTGetCharWidthW");
  164. _pfnCreateFontInstance=(PFNCREATEFONTINSTANCE)GetProcAddress(_hctras, "WAPI_EZCTCreateFontInstance");
  165. _pfnDeleteFontInstance=(PFNDELETEFONTINSTANCE)GetProcAddress(_hctras, "WAPI_EZCTDeleteFontInstance");
  166. // check that we got these correctly
  167. // future versions of cleartype could change this API
  168. if(!_pfnExtTextOutW || !_pfnGetCharWidthW || !_pfnCreateFontInstance || !_pfnDeleteFontInstance)
  169. {
  170. ClearTypeUnInitialize();
  171. return E_NOINTERFACE;
  172. }
  173. pCTO=new CCustomTextOut;
  174. ICustomTextOut *pICTO=pCTO;
  175. SetCustomTextOutHandlerEx(&pICTO, 0);
  176. return NOERROR;
  177. }
  178. extern "C" void ClearTypeUnInitialize()
  179. {
  180. if(_hctras)
  181. {
  182. FreeLibrary(_hctras);
  183. _hctras = NULL;
  184. }
  185. if(pCTO)
  186. {
  187. delete pCTO;
  188. pCTO = NULL;
  189. }
  190. _pfnExtTextOutW = NULL;
  191. _pfnGetCharWidthW = NULL;
  192. _pfnCreateFontInstance = NULL;
  193. _pfnDeleteFontInstance = NULL;
  194. }
  195. #endif
  196. extern "C"
  197. {
  198. BOOL WINAPI DllMain(HANDLE hmod, DWORD dwReason, LPVOID lpvReserved)
  199. {
  200. DebugMain ((HINSTANCE) hmod, dwReason, lpvReserved);
  201. if(dwReason == DLL_PROCESS_DETACH) // We are unloading
  202. {
  203. #ifndef NOWINDOWHOSTS
  204. DeleteDanglingHosts();
  205. #endif
  206. CRTFConverter::FreeFontSubInfo();
  207. FreeFontCache();
  208. DestroyFormatCaches();
  209. ReleaseTypeInfoPtrs();
  210. UninitKinsokuClassify();
  211. FreeHyphCache();
  212. // Release various resouces allocated during running...
  213. #ifndef NOLINESERVICES
  214. delete g_pols;
  215. #endif
  216. #ifndef NOCOMPLEXSCRIPTS
  217. delete g_pusp;
  218. g_pusp = NULL;
  219. #endif
  220. ReleaseOutlineBitmaps();
  221. #ifdef CLEARTYPE_DEBUG
  222. ClearTypeUnInitialize();
  223. #endif
  224. if(hinstRE)
  225. {
  226. W32->UnregisterClass(wszClassREW, hinstRE);
  227. if (W32->_fRegisteredXBox)
  228. {
  229. // There may be cases where these window classes
  230. // are still in memory in which case UnregisterClass
  231. // will fail. So keep track of that
  232. if (W32->UnregisterClass(wszClassLBW, hinstRE))
  233. W32->_fRegisteredXBox &= ~REGISTERED_LISTBOX;
  234. if (W32->UnregisterClass(wszClassCBW, hinstRE))
  235. W32->_fRegisteredXBox &= ~REGISTERED_COMBOBOX;
  236. }
  237. }
  238. delete W32;
  239. #if defined(DEBUG) && !defined(NOFULLDEBUG)
  240. CatchLeaks();
  241. #endif
  242. #ifndef NODELAYLOAD
  243. // lpvReserved is not NULL when DllMain DLL_PROCESS_DETACH is being called during process exit.
  244. // In such case, we should not mess around with the delay loaded dll thunks
  245. if (!lpvReserved)
  246. OurUnloadDelayLoadedDlls();
  247. #endif
  248. HeapDestroy(g_hHeap);
  249. DeleteCriticalSection(&g_CriticalSection);
  250. }
  251. else if(dwReason == DLL_PROCESS_ATTACH) // We have just loaded
  252. {
  253. #ifdef DEBUG
  254. fInDllMain = TRUE;
  255. #endif
  256. InitializeCriticalSection(&g_CriticalSection);
  257. #if !defined(DEBUG) && !defined(UNDER_CE)
  258. // REVIEW (gheino) We should investigate if there is another
  259. // way to do this on CE
  260. DisableThreadLibraryCalls((HINSTANCE) hmod);
  261. #endif
  262. hinstRE = (HINSTANCE) hmod;
  263. W32 = new CW32System;
  264. CopyMemory(wszClassREW, MSFTEDIT_CLASS, sizeof(MSFTEDIT_CLASS));
  265. if(!RichFRegisterClass())
  266. return FALSE;
  267. #ifdef CLEARTYPE_DEBUG
  268. ClearTypeInitialize();
  269. #endif
  270. #ifdef DEBUG
  271. fInDllMain = FALSE;
  272. #endif
  273. }
  274. return TRUE;
  275. }
  276. #ifndef NOVERSIONINFO
  277. HRESULT CALLBACK DllGetVersion(
  278. DLLVERSIONINFO *pdvi
  279. )
  280. {
  281. if (pdvi->cbSize != sizeof(DLLVERSIONINFO))
  282. return E_INVALIDARG;
  283. pdvi->dwBuildNumber = RICHEDIT_VERBUILD;
  284. pdvi->dwMajorVersion = RICHEDIT_VERMAJ;
  285. pdvi->dwMinorVersion = RICHEDIT_VERMIN;
  286. pdvi->dwPlatformID = DLLVER_PLATFORM_WINDOWS ;
  287. return NOERROR;
  288. }
  289. #endif
  290. } // extern "C"
  291. /*
  292. * RichFRegisterClass
  293. *
  294. * Purpose:
  295. * registers the window classes used by richedit
  296. *
  297. * Algorithm:
  298. * register two window classes, a Unicode one and an ANSI
  299. * one. This enables clients to optimize their use of
  300. * the edit control w.r.t to ANSI/Unicode data
  301. */
  302. static BOOL RichFRegisterClass(VOID)
  303. {
  304. #ifndef NOWINDOWHOSTS
  305. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "RichFRegisterClass");
  306. WNDCLASS wc;
  307. wc.style = CS_DBLCLKS | CS_GLOBALCLASS | CS_PARENTDC;
  308. wc.lpfnWndProc = RichEditWndProc;
  309. wc.cbClsExtra = 0;
  310. wc.cbWndExtra = sizeof(CTxtEdit FAR *);
  311. wc.hInstance = hinstRE;
  312. wc.hIcon = 0;
  313. wc.hCursor = 0;
  314. wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  315. wc.lpszMenuName = NULL;
  316. wc.lpszClassName = wszClassREW;
  317. if( W32->RegisterREClass(&wc) == NULL )
  318. return FALSE;
  319. #endif // NOWINDOWHOSTS
  320. return TRUE;
  321. }
  322. #ifndef NOLISTCOMBOBOXES
  323. extern "C" LRESULT CALLBACK RichListBoxWndProc(HWND, UINT, WPARAM, LPARAM);
  324. extern "C" LRESULT CALLBACK RichComboBoxWndProc(HWND, UINT, WPARAM, LPARAM);
  325. __declspec(dllexport) BOOL WINAPI REExtendedRegisterClass(VOID)
  326. {
  327. TRACEBEGIN(TRCSUBSYSHOST, TRCSCOPEINTERN, "REExtendedRegisterClass");
  328. WNDCLASS wc;
  329. if (!(W32->_fRegisteredXBox & REGISTERED_LISTBOX))
  330. {
  331. // Globally register the listbox
  332. wc.style = CS_DBLCLKS | CS_GLOBALCLASS | CS_PARENTDC;
  333. wc.lpfnWndProc = RichListBoxWndProc;
  334. wc.cbClsExtra = 0;
  335. wc.cbWndExtra = sizeof(CTxtEdit FAR *);
  336. wc.hInstance = hinstRE;
  337. wc.hIcon = 0;
  338. wc.hCursor = 0;
  339. wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  340. wc.lpszMenuName = NULL;
  341. wc.lpszClassName = wszClassLBW;
  342. if(W32->RegisterREClass(&wc))
  343. W32->_fRegisteredXBox |= REGISTERED_LISTBOX;
  344. }
  345. if (!(W32->_fRegisteredXBox & REGISTERED_COMBOBOX))
  346. {
  347. // globally register the combobox
  348. wc.style = CS_DBLCLKS | CS_GLOBALCLASS | CS_PARENTDC | CS_VREDRAW | CS_HREDRAW;
  349. wc.lpfnWndProc = RichComboBoxWndProc;
  350. wc.cbClsExtra = 0;
  351. wc.cbWndExtra = sizeof(CCmbBxWinHost FAR *);
  352. wc.hInstance = hinstRE;
  353. wc.hIcon = 0;
  354. wc.hCursor = 0;
  355. wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  356. wc.lpszMenuName = NULL;
  357. wc.lpszClassName = wszClassCBW;
  358. if(W32->RegisterREClass(&wc))
  359. W32->_fRegisteredXBox |= REGISTERED_COMBOBOX;
  360. }
  361. //Set flag so we unregister the window class
  362. return W32->_fRegisteredXBox;
  363. }
  364. #else // NOLISTCOMBOBOXES
  365. __declspec(dllexport) BOOL WINAPI REExtendedRegisterClass(VOID)
  366. {
  367. return FALSE;
  368. }
  369. #endif // NOLISTCOMBOBOXES
  370. #if !defined(NOLINESERVICES)
  371. BOOL g_fNoLS = FALSE;
  372. #endif
  373. #if !defined(NOCOMPLEXSCRIPTS)
  374. BOOL g_fNoUniscribe = FALSE;
  375. #endif
  376. #if !defined(NOLINESERVICES) && !defined(NOCOMPLEXSCRIPTS)
  377. char *g_szMsgBox = NULL;
  378. //This is a stub function which we call when we can't find LineServices.
  379. //The stub function needs to be the the first function we call in LS.
  380. LSERR WINAPI LsGetReverseLsimethodsStub(LSIMETHODS *plsim)
  381. {
  382. return lserrOutOfMemory;
  383. }
  384. //Ugly, but good enough
  385. BOOL FIsUniscribeDll (const char *szDll)
  386. {
  387. return (*szDll == 'u' || *szDll == 'U');
  388. }
  389. BOOL FIsLineServicesDll (const char *szDll)
  390. {
  391. return (*szDll == 'm' || *szDll == 'M') &&
  392. (*(szDll+1) == 's' || *(szDll+1) == 'S') &&
  393. (*(szDll+2) == 'l' || *(szDll+2) == 'L');
  394. }
  395. HRESULT WINAPI ScriptGetPropertiesStub(const SCRIPT_PROPERTIES ***ppSp,int *piNumScripts)
  396. {
  397. return E_FAIL;
  398. }
  399. const SCRIPT_LOGATTR* WINAPI ScriptString_pLogAttrStub(SCRIPT_STRING_ANALYSIS ssa)
  400. {
  401. // USP build 0175 (shipped with IE5 and Office2K) doesnt support this API.
  402. return NULL;
  403. }
  404. // Get Uniscibe's fake entry points
  405. FARPROC WINAPI GetUniscribeStubs(LPCSTR szProcName)
  406. {
  407. if (!lstrcmpiA(szProcName, "ScriptGetProperties"))
  408. return (FARPROC)ScriptGetPropertiesStub;
  409. if (!lstrcmpiA(szProcName, "ScriptString_pLogAttr"))
  410. return (FARPROC)ScriptString_pLogAttrStub;
  411. #ifdef DEBUG
  412. char szAssert[128];
  413. wsprintfA(szAssert, "Uniscribe API =%s= is missing. Fix it NOW!", szProcName);
  414. AssertSz(FALSE, szAssert);
  415. #endif
  416. return (FARPROC)ScriptGetPropertiesStub; // we're dying...
  417. }
  418. #ifndef NODELAYLOAD
  419. FARPROC WINAPI DliHook(unsigned dliNotify, PDelayLoadInfo pdli)
  420. {
  421. FARPROC fp = 0;
  422. switch (dliNotify)
  423. {
  424. // Handy for debugging for now.
  425. case dliNotePreGetProcAddress:
  426. if (FIsLineServicesDll(pdli->szDll))
  427. fp = 0;
  428. break;
  429. case dliFailLoadLib:
  430. {
  431. if (FIsUniscribeDll(pdli->szDll))
  432. g_fNoUniscribe = TRUE;
  433. else
  434. g_fNoLS = TRUE;
  435. fp = (FARPROC)(HMODULE)hinstRE;
  436. CLock lock;
  437. if(!g_szMsgBox)
  438. {
  439. g_szMsgBox = (char *)PvAlloc(255, GMEM_ZEROINIT);
  440. FormatMessageA(FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
  441. ERROR_MOD_NOT_FOUND,
  442. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  443. (char *)g_szMsgBox, 255, NULL);
  444. CopyMemory(g_szMsgBox + lstrlenA(g_szMsgBox), " (", 3);
  445. CopyMemory(g_szMsgBox + lstrlenA(g_szMsgBox), pdli->szDll, lstrlenA(pdli->szDll) + 1);
  446. CopyMemory(g_szMsgBox + lstrlenA(g_szMsgBox), ")", 2);
  447. }
  448. }
  449. break;
  450. case dliFailGetProc:
  451. if (FIsUniscribeDll(pdli->szDll))
  452. fp = (FARPROC)GetUniscribeStubs(pdli->dlp.szProcName);
  453. else
  454. fp = (FARPROC)LsGetReverseLsimethodsStub;
  455. break;
  456. }
  457. return fp;
  458. }
  459. PfnDliHook __pfnDliFailureHook = DliHook;
  460. PfnDliHook __pfnDliNotifyHook = DliHook;
  461. #endif // NODELAYLOAD
  462. #endif // NOLINESERVICES