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.

476 lines
14 KiB

  1. /****************************** Module*Header *****************************\
  2. * Module Name: rtlmir.c *
  3. * *
  4. * This module contains all the Right-To-Left (RTL) Mirroring support *
  5. * routines which are used across the whole IShell project. It abstracts *
  6. * platform-support routines of RTL mirroring (NT5 and Memphis) and removes *
  7. * linkage depedenency with the Mirroring APIs. *
  8. * *
  9. * Functions prefixed with Mirror, deal with the new Mirroring APIs *
  10. * *
  11. * *
  12. * Created: 01-Feb-1998 8:41:18 pm *
  13. * Author: Samer Arafeh [samera] *
  14. * *
  15. * Copyright (c) 1998 Microsoft Corporation *
  16. \**************************************************************************/
  17. #include "pch.hxx"
  18. #if WINVER < 0X0500
  19. #include "mirport.h"
  20. #endif
  21. #include "mirror.h"
  22. const DWORD dwNoMirrorBitmap = NOMIRRORBITMAP;
  23. const DWORD dwExStyleRTLMirrorWnd = WS_EX_LAYOUTRTL;
  24. const DWORD dwPreserveBitmap = LAYOUT_BITMAPORIENTATIONPRESERVED;
  25. /*
  26. * Remove linkage dependecy for the RTL mirroring APIs, by retreiving
  27. * their addresses at runtime.
  28. */
  29. typedef DWORD (*PFNGETLAYOUT)(HDC); // gdi32!GetLayout
  30. typedef DWORD (*PFNSETLAYOUT)(HDC, DWORD); // gdi32!SetLayout
  31. typedef BOOL (*PFNSETPROCESSDEFLAYOUT)(DWORD); // user32!SetProcessDefaultLayout
  32. typedef BOOL (*PFNGETPROCESSDEFLAYOUT)(DWORD*); // user32!GetProcessDefaultLayout
  33. typedef LANGID (*PFNGETUSERDEFAULTUILANGUAGE)(void); // kernel32!GetUserDefaultUILanguage
  34. #define OS_WINDOWS 0 // windows vs. NT
  35. #define OS_NT 1 // windows vs. NT
  36. #define OS_WIN95 2
  37. #define OS_NT4 3
  38. #define OS_NT5 4
  39. #define OS_MEMPHIS 5
  40. /*----------------------------------------------------------
  41. Purpose: Returns TRUE/FALSE if the platform is the given OS_ value.
  42. */
  43. STDAPI_(BOOL) MirLibIsOS(DWORD dwOS)
  44. {
  45. BOOL bRet;
  46. static OSVERSIONINFOA s_osvi;
  47. static BOOL s_bVersionCached = FALSE;
  48. if (!s_bVersionCached)
  49. {
  50. s_bVersionCached = TRUE;
  51. s_osvi.dwOSVersionInfoSize = sizeof(s_osvi);
  52. GetVersionExA(&s_osvi);
  53. }
  54. switch (dwOS)
  55. {
  56. case OS_WINDOWS:
  57. bRet = (VER_PLATFORM_WIN32_WINDOWS == s_osvi.dwPlatformId);
  58. break;
  59. case OS_NT:
  60. bRet = (VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId);
  61. break;
  62. case OS_WIN95:
  63. bRet = (VER_PLATFORM_WIN32_WINDOWS == s_osvi.dwPlatformId &&
  64. s_osvi.dwMajorVersion >= 4);
  65. break;
  66. case OS_MEMPHIS:
  67. bRet = (VER_PLATFORM_WIN32_WINDOWS == s_osvi.dwPlatformId &&
  68. (s_osvi.dwMajorVersion > 4 ||
  69. s_osvi.dwMajorVersion == 4 && s_osvi.dwMinorVersion >= 10));
  70. break;
  71. case OS_NT4:
  72. bRet = (VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId &&
  73. s_osvi.dwMajorVersion >= 4);
  74. break;
  75. case OS_NT5:
  76. bRet = (VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId &&
  77. s_osvi.dwMajorVersion >= 5);
  78. break;
  79. default:
  80. bRet = FALSE;
  81. break;
  82. }
  83. return bRet;
  84. }
  85. /***************************************************************************\
  86. * Mirror_GetUserDefaultUILanguage
  87. *
  88. * Reads the User UI language on NT5
  89. *
  90. * History:
  91. * 22-June-1998 samera Created
  92. \***************************************************************************/
  93. LANGID Mirror_GetUserDefaultUILanguage( void )
  94. {
  95. LANGID langId=0;
  96. static PFNGETUSERDEFAULTUILANGUAGE pfnGetUserDefaultUILanguage=NULL;
  97. if( NULL == pfnGetUserDefaultUILanguage )
  98. {
  99. HMODULE hmod = GetModuleHandleA("KERNEL32");
  100. if( hmod )
  101. pfnGetUserDefaultUILanguage = (PFNGETUSERDEFAULTUILANGUAGE)
  102. GetProcAddress(hmod, "GetUserDefaultUILanguage");
  103. }
  104. if( pfnGetUserDefaultUILanguage )
  105. langId = pfnGetUserDefaultUILanguage();
  106. return langId;
  107. }
  108. /***************************************************************************\
  109. * Mirror_EnableWindowLayoutInheritance
  110. *
  111. * returns TRUE if the window is RTL mirrored
  112. *
  113. * History:
  114. * 14-April-1998 a-msadek Created
  115. \***************************************************************************/
  116. LONG Mirror_EnableWindowLayoutInheritance( HWND hWnd )
  117. {
  118. return SetWindowLongA(hWnd, GWL_EXSTYLE, GetWindowLongA( hWnd , GWL_EXSTYLE ) & ~WS_EX_NOINHERITLAYOUT );
  119. }
  120. /***************************************************************************\
  121. * Mirror_DisableWindowLayoutInheritance
  122. *
  123. * returns TRUE if the window is RTL mirrored
  124. *
  125. * History:
  126. * 14-April-1998 a-msadek Created
  127. \***************************************************************************/
  128. LONG Mirror_DisableWindowLayoutInheritance( HWND hWnd )
  129. {
  130. return SetWindowLongA(hWnd, GWL_EXSTYLE, GetWindowLongA( hWnd , GWL_EXSTYLE ) | WS_EX_NOINHERITLAYOUT );
  131. }
  132. /***************************************************************************\
  133. * ConvertHexStringToInt
  134. *
  135. * Converts a hex numeric string into an integer.
  136. *
  137. * History:
  138. * 04-Feb-1998 samera Created
  139. \***************************************************************************/
  140. BOOL ConvertHexStringToInt( CHAR *pszHexNum , int *piNum )
  141. {
  142. int n=0L;
  143. CHAR *psz=pszHexNum;
  144. for(n=0 ; ; psz=CharNextA(psz))
  145. {
  146. if( (*psz>='0') && (*psz<='9') )
  147. n = 0x10 * n + *psz - '0';
  148. else
  149. {
  150. CHAR ch = *psz;
  151. int n2;
  152. if(ch >= 'a')
  153. ch -= 'a' - 'A';
  154. n2 = ch - 'A' + 0xA;
  155. if (n2 >= 0xA && n2 <= 0xF)
  156. n = 0x10 * n + n2;
  157. else
  158. break;
  159. }
  160. }
  161. /*
  162. * Update results
  163. */
  164. *piNum = n;
  165. return (psz != pszHexNum);
  166. }
  167. /***************************************************************************\
  168. * IsBiDiLocalizedSystem
  169. *
  170. * returns TRUE if running on a lozalized BiDi (Arabic/Hebrew) NT5 or Memphis.
  171. * Should be called whenever SetProcessDefaultLayout is to be called.
  172. *
  173. * History:
  174. * 02-Feb-1998 samera Created
  175. \***************************************************************************/
  176. BOOL IsBiDiLocalizedSystem( void )
  177. {
  178. HKEY hKey;
  179. DWORD dwType;
  180. CHAR szResourceLocale[12];
  181. DWORD dwSize = sizeof(szResourceLocale)/sizeof(CHAR);
  182. LANGID langID;
  183. int iLCID=0L;
  184. static BOOL bRet = (BOOL)(DWORD)-1;
  185. if (bRet != (BOOL)(DWORD)-1)
  186. {
  187. return bRet;
  188. }
  189. bRet = FALSE;
  190. if( MirLibIsOS( OS_NT5 ) )
  191. {
  192. /*
  193. * Need to use NT5 detection method (Multiligual UI ID)
  194. */
  195. langID = Mirror_GetUserDefaultUILanguage();
  196. if( langID )
  197. {
  198. WCHAR wchLCIDFontSignature[16];
  199. iLCID = MAKELCID( langID , SORT_DEFAULT );
  200. /*
  201. * Let's verify this is a RTL (BiDi) locale. Since reg value is a hex string, let's
  202. * convert to decimal value and call GetLocaleInfo afterwards.
  203. * LOCALE_FONTSIGNATURE always gives back 16 WCHARs.
  204. */
  205. if( GetLocaleInfoW( iLCID ,
  206. LOCALE_FONTSIGNATURE ,
  207. (WCHAR *) &wchLCIDFontSignature[0] ,
  208. (sizeof(wchLCIDFontSignature)/sizeof(WCHAR))) )
  209. {
  210. /* Let's verify the bits we have a BiDi UI locale */
  211. if( wchLCIDFontSignature[7] & (WCHAR)0x0800 )
  212. {
  213. bRet = TRUE;
  214. }
  215. }
  216. }
  217. } else {
  218. /*
  219. * Check if BiDi-Memphis is running with Lozalized Resources (
  220. * i.e. Arabic/Hebrew systems) -It should be enabled ofcourse-.
  221. */
  222. if( (MirLibIsOS(OS_MEMPHIS)) && (GetSystemMetrics(SM_MIDEASTENABLED)) )
  223. {
  224. if( RegOpenKeyExA( HKEY_CURRENT_USER ,
  225. "Control Panel\\Desktop\\ResourceLocale" ,
  226. 0,
  227. KEY_READ, &hKey) == ERROR_SUCCESS)
  228. {
  229. RegQueryValueExA( hKey , "" , 0 , &dwType , (LPBYTE)szResourceLocale , &dwSize );
  230. szResourceLocale[(sizeof(szResourceLocale)/sizeof(CHAR))-1] = 0;
  231. RegCloseKey(hKey);
  232. if( ConvertHexStringToInt( szResourceLocale , &iLCID ) )
  233. {
  234. iLCID = PRIMARYLANGID(LANGIDFROMLCID(iLCID));
  235. if( (LANG_ARABIC == iLCID) || (LANG_HEBREW == iLCID) )
  236. {
  237. bRet = TRUE;
  238. }
  239. }
  240. }
  241. }
  242. }
  243. return bRet;
  244. }
  245. /***************************************************************************\
  246. * Mirror_IsEnabledOS
  247. *
  248. * returns TRUE if the mirroring APIs are enabled on the current OS.
  249. *
  250. * History:
  251. * 02-Feb-1998 samera Created
  252. \***************************************************************************/
  253. BOOL Mirror_IsEnabledOS( void )
  254. {
  255. BOOL bRet = FALSE;
  256. if( MirLibIsOS(OS_NT5) )
  257. {
  258. bRet = TRUE;
  259. } else if( MirLibIsOS(OS_MEMPHIS) && GetSystemMetrics(SM_MIDEASTENABLED)) {
  260. bRet=TRUE;
  261. }
  262. return bRet;
  263. }
  264. /***************************************************************************\
  265. * Mirror_IsWindowMirroredRTL
  266. *
  267. * returns TRUE if the window is RTL mirrored
  268. *
  269. * History:
  270. * 02-Feb-1998 samera Created
  271. \***************************************************************************/
  272. BOOL Mirror_IsWindowMirroredRTL( HWND hWnd )
  273. {
  274. return (GetWindowLongA( hWnd , GWL_EXSTYLE ) & WS_EX_LAYOUTRTL );
  275. }
  276. /***************************************************************************\
  277. * Mirror_GetLayout
  278. *
  279. * returns TRUE if the hdc is RTL mirrored
  280. *
  281. * History:
  282. * 02-Feb-1998 samera Created
  283. \***************************************************************************/
  284. DWORD Mirror_GetLayout( HDC hdc )
  285. {
  286. DWORD dwRet=0;
  287. static PFNGETLAYOUT pfnGetLayout=NULL;
  288. if( NULL == pfnGetLayout )
  289. {
  290. HMODULE hmod = GetModuleHandleA("GDI32");
  291. if( hmod )
  292. pfnGetLayout = (PFNGETLAYOUT)GetProcAddress(hmod, "GetLayout");
  293. }
  294. if( pfnGetLayout )
  295. dwRet = pfnGetLayout( hdc );
  296. return dwRet;
  297. }
  298. DWORD Mirror_IsDCMirroredRTL( HDC hdc )
  299. {
  300. return (Mirror_GetLayout( hdc ) & LAYOUT_RTL);
  301. }
  302. /***************************************************************************\
  303. * Mirror_SetLayout
  304. *
  305. * RTL Mirror the hdc
  306. *
  307. * History:
  308. * 02-Feb-1998 samera Created
  309. \***************************************************************************/
  310. DWORD Mirror_SetLayout( HDC hdc , DWORD dwLayout )
  311. {
  312. DWORD dwRet=0;
  313. static PFNSETLAYOUT pfnSetLayout=NULL;
  314. if( NULL == pfnSetLayout )
  315. {
  316. HMODULE hmod = GetModuleHandleA("GDI32");
  317. if( hmod )
  318. pfnSetLayout = (PFNSETLAYOUT)GetProcAddress(hmod, "SetLayout");
  319. }
  320. if( pfnSetLayout )
  321. dwRet = pfnSetLayout( hdc , dwLayout );
  322. return dwRet;
  323. }
  324. DWORD Mirror_MirrorDC( HDC hdc )
  325. {
  326. return Mirror_SetLayout( hdc , LAYOUT_RTL );
  327. }
  328. /***************************************************************************\
  329. * Mirror_SetProcessDefaultLayout
  330. *
  331. * Set the process-default layout.
  332. *
  333. * History:
  334. * 02-Feb-1998 samera Created
  335. \***************************************************************************/
  336. BOOL Mirror_SetProcessDefaultLayout( DWORD dwDefaultLayout )
  337. {
  338. BOOL bRet=0;
  339. static PFNSETPROCESSDEFLAYOUT pfnSetProcessDefLayout=NULL;
  340. if( NULL == pfnSetProcessDefLayout )
  341. {
  342. HMODULE hmod = GetModuleHandleA("USER32");
  343. if( hmod )
  344. pfnSetProcessDefLayout = (PFNSETPROCESSDEFLAYOUT)
  345. GetProcAddress(hmod, "SetProcessDefaultLayout");
  346. }
  347. if( pfnSetProcessDefLayout )
  348. bRet = pfnSetProcessDefLayout( dwDefaultLayout );
  349. return bRet;
  350. }
  351. BOOL Mirror_MirrorProcessRTL( void )
  352. {
  353. return Mirror_SetProcessDefaultLayout( LAYOUT_RTL );
  354. }
  355. /***************************************************************************\
  356. * Mirror_GetProcessDefaultLayout
  357. *
  358. * Get the process-default layout.
  359. *
  360. * History:
  361. * 26-Feb-1998 samera Created
  362. \***************************************************************************/
  363. BOOL Mirror_GetProcessDefaultLayout( DWORD *pdwDefaultLayout )
  364. {
  365. BOOL bRet=0;
  366. static PFNGETPROCESSDEFLAYOUT pfnGetProcessDefLayout=NULL;
  367. if( NULL == pfnGetProcessDefLayout )
  368. {
  369. HMODULE hmod = GetModuleHandleA("USER32");
  370. if( hmod )
  371. pfnGetProcessDefLayout = (PFNGETPROCESSDEFLAYOUT)
  372. GetProcAddress(hmod, "GetProcessDefaultLayout");
  373. }
  374. if( pfnGetProcessDefLayout )
  375. bRet = pfnGetProcessDefLayout( pdwDefaultLayout );
  376. return bRet;
  377. }
  378. BOOL Mirror_IsProcessRTL( void )
  379. {
  380. DWORD dwDefLayout=0;
  381. static BOOL bRet = (BOOL)(DWORD)-1;
  382. if (bRet != (BOOL)(DWORD)-1)
  383. {
  384. return bRet;
  385. }
  386. bRet = FALSE;
  387. bRet = (Mirror_GetProcessDefaultLayout(&dwDefLayout) && (dwDefLayout&LAYOUT_RTL));
  388. return bRet;
  389. }