Leaked source code of windows server 2003
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.

210 lines
4.8 KiB

  1. /*++
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. RemoveComplexScriptExtraSpace.cpp
  5. Abstract:
  6. This shim fix regression bug from Win 2K regarding complex script showing problem.
  7. ex) Reversed BiDi text.
  8. Windows XP LPK turn off the complex script handling on the text which has extra spaces.
  9. 'Cause extra character space with complex script doesn't make sense. (tarekms)
  10. This is a change from Windows 2000 and based on enabling font fallback for the FE languages.
  11. Then as bug 547349 for Office 2000, we may see BiDi text doesn't appear correctly.
  12. So far, reported problem is only for Hebrew and Arabic localized Office 2000 splash screen on .NET Server.
  13. This shim removes extra space set by SetTextCharacterExtra() for ExtTextOutW and Complex Script text.
  14. Notes:
  15. This is a general shim for the potential generic problem of LPK.DLL on Win XP & .NET Server.
  16. History:
  17. 04/18/2002 hioh Created
  18. --*/
  19. #include "precomp.h"
  20. IMPLEMENT_SHIM_BEGIN(Office9ComplexScript)
  21. #include "ShimHookMacro.h"
  22. APIHOOK_ENUM_BEGIN
  23. APIHOOK_ENUM_ENTRY(SetTextCharacterExtra)
  24. APIHOOK_ENUM_ENTRY(ExtTextOutW)
  25. APIHOOK_ENUM_END
  26. CRITICAL_SECTION g_CriticalSection; // For multi thread safe
  27. HDC g_hdc = NULL; // Remember HDC used in SetTextCharacterExtra()
  28. int g_nCharExtra = 0; // Remember extra space value set in SetTextCharacterExtra()
  29. /*++
  30. Remember HDC and extra space value.
  31. --*/
  32. int
  33. APIHOOK(SetTextCharacterExtra)(HDC hdc, int nCharExtra)
  34. {
  35. EnterCriticalSection(&g_CriticalSection);
  36. if (hdc != g_hdc)
  37. {
  38. g_hdc = hdc; // Save hdc
  39. }
  40. g_nCharExtra = nCharExtra; // Save nCharExtra
  41. LeaveCriticalSection(&g_CriticalSection);
  42. return (ORIGINAL_API(SetTextCharacterExtra)(hdc, nCharExtra));
  43. }
  44. /*++
  45. Function Description:
  46. Check if BiDi character is in the string.
  47. Arguments:
  48. IN lpString - Pointer to the string
  49. IN cbCount - Length to check
  50. Return Value:
  51. TRUE if BiDi char exist or FALSE if not
  52. History:
  53. 04/17/2002 hioh Created
  54. --*/
  55. BOOL
  56. IsBiDiString(
  57. LPCWSTR lpString,
  58. UINT cbCount
  59. )
  60. {
  61. while (0 < cbCount--)
  62. {
  63. // Check if character is in Hebrew or Arabic code range
  64. if ((0x0590 <= *lpString && *lpString <= 0x05ff) || (0x0600 <= *lpString && *lpString <= 0x06ff))
  65. {
  66. return TRUE;
  67. }
  68. lpString++;
  69. }
  70. return FALSE;
  71. }
  72. /*++
  73. Remove Extra Space when Complex Script.
  74. Revert Extra Space when removed and not Complex Script.
  75. --*/
  76. BOOL
  77. APIHOOK(ExtTextOutW)(
  78. HDC hdc,
  79. int X,
  80. int Y,
  81. UINT fuOptions,
  82. CONST RECT* lprc,
  83. LPCWSTR lpString,
  84. UINT cbCount,
  85. CONST INT* lpDx
  86. )
  87. {
  88. static HDC s_hdc = NULL;
  89. static int s_nCharExtra = 0;
  90. static BOOL s_bRemoveExtra = FALSE;
  91. // Do nothing for ETO_GLYPH_INDEX and ETO_IGNORELANGUAGE
  92. if (fuOptions & ETO_GLYPH_INDEX || fuOptions & ETO_IGNORELANGUAGE)
  93. {
  94. return (ORIGINAL_API(ExtTextOutW)(hdc, X, Y, fuOptions, lprc, lpString, cbCount, lpDx));
  95. }
  96. EnterCriticalSection(&g_CriticalSection);
  97. if (hdc == g_hdc && g_nCharExtra > 0 && hdc != s_hdc)
  98. {
  99. // New handling
  100. s_hdc = g_hdc;
  101. s_nCharExtra = g_nCharExtra;
  102. if (IsBiDiString(lpString, cbCount))
  103. {
  104. // Remove extra space
  105. ORIGINAL_API(SetTextCharacterExtra)(hdc, 0);
  106. s_bRemoveExtra = TRUE;
  107. }
  108. else
  109. {
  110. s_bRemoveExtra = FALSE;
  111. }
  112. }
  113. else if (hdc == s_hdc && s_nCharExtra > 0)
  114. {
  115. // Handled before
  116. if (IsBiDiString(lpString, cbCount))
  117. {
  118. // Remove extra space if not yet
  119. if (!s_bRemoveExtra)
  120. {
  121. ORIGINAL_API(SetTextCharacterExtra)(hdc, 0);
  122. s_bRemoveExtra = TRUE;
  123. }
  124. }
  125. else
  126. {
  127. // Revert extra space if removed
  128. if (s_bRemoveExtra)
  129. {
  130. ORIGINAL_API(SetTextCharacterExtra)(hdc, s_nCharExtra);
  131. s_bRemoveExtra = FALSE;
  132. }
  133. }
  134. }
  135. LeaveCriticalSection(&g_CriticalSection);
  136. return (ORIGINAL_API(ExtTextOutW)(hdc, X, Y, fuOptions, lprc, lpString, cbCount, lpDx));
  137. }
  138. BOOL
  139. NOTIFY_FUNCTION(
  140. DWORD fdwReason
  141. )
  142. {
  143. if (fdwReason == DLL_PROCESS_ATTACH)
  144. {
  145. return (InitializeCriticalSectionAndSpinCount(&g_CriticalSection, 0x80000000));
  146. }
  147. return TRUE;
  148. }
  149. /*++
  150. Register hooked functions
  151. --*/
  152. HOOK_BEGIN
  153. CALL_NOTIFY_FUNCTION
  154. APIHOOK_ENTRY(GDI32.DLL, SetTextCharacterExtra)
  155. APIHOOK_ENTRY(GDI32.DLL, ExtTextOutW)
  156. HOOK_END
  157. IMPLEMENT_SHIM_END