rtlmir.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 20k
Category:

Windows Kernel

Development Platform:

Visual C++

  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 "local.h"
  18. const DWORD dwNoMirrorBitmap = NOMIRRORBITMAP;
  19. const DWORD dwExStyleRTLMirrorWnd = WS_EX_LAYOUTRTL;
  20. const DWORD dwExStyleNoInheritLayout = WS_EX_NOINHERITLAYOUT; 
  21. const DWORD dwPreserveBitmap = LAYOUT_BITMAPORIENTATIONPRESERVED;
  22. /*
  23.  * Remove linkage dependecy for the RTL mirroring APIs, by retreiving
  24.  * their addresses at runtime.
  25.  */
  26. typedef DWORD (WINAPI *PFNGETLAYOUT)(HDC);                   // gdi32!GetLayout
  27. typedef DWORD (WINAPI *PFNSETLAYOUT)(HDC, DWORD);            // gdi32!SetLayout
  28. typedef BOOL  (WINAPI *PFNSETPROCESSDEFLAYOUT)(DWORD);       // user32!SetProcessDefaultLayout
  29. typedef BOOL  (WINAPI *PFNGETPROCESSDEFLAYOUT)(DWORD*);      // user32!GetProcessDefaultLayout
  30. typedef LANGID (WINAPI *PFNGETUSERDEFAULTUILANGUAGE)(void);  // kernel32!GetUserDefaultUILanguage
  31. typedef BOOL (WINAPI *PFNENUMUILANGUAGES)(UILANGUAGE_ENUMPROC, DWORD, LONG_PTR); // kernel32!EnumUILanguages
  32. typedef struct {
  33.     LANGID LangID;
  34.     BOOL   bInstalled;
  35.     } MUIINSTALLLANG, *LPMUIINSTALLLANG;
  36. #ifdef UNICODE
  37. #define ConvertHexStringToInt ConvertHexStringToIntW
  38. #else
  39. #define ConvertHexStringToInt ConvertHexStringToIntA
  40. #endif
  41. /***************************************************************************
  42. * ConvertHexStringToIntA
  43. *
  44. * Converts a hex numeric string into an integer.
  45. *
  46. * History:
  47. * 04-Feb-1998 samera    Created
  48. ***************************************************************************/
  49. BOOL ConvertHexStringToIntA( CHAR *pszHexNum , int *piNum )
  50. {
  51.     int   n=0L;
  52.     CHAR  *psz=pszHexNum;
  53.   
  54.     for(n=0 ; ; psz=CharNextA(psz))
  55.     {
  56.         if( (*psz>='0') && (*psz<='9') )
  57.             n = 0x10 * n + *psz - '0';
  58.         else
  59.         {
  60.             CHAR ch = *psz;
  61.             int n2;
  62.             if(ch >= 'a')
  63.                 ch -= 'a' - 'A';
  64.             n2 = ch - 'A' + 0xA;
  65.             if (n2 >= 0xA && n2 <= 0xF)
  66.                 n = 0x10 * n + n2;
  67.             else
  68.                 break;
  69.         }
  70.     }
  71.     /*
  72.      * Update results
  73.      */
  74.     *piNum = n;
  75.     return (psz != pszHexNum);
  76. }
  77. /***************************************************************************
  78. * ConvertHexStringToIntW
  79. *
  80. * Converts a hex numeric string into an integer.
  81. *
  82. * History:
  83. * 14-June-1998 msadek    Created
  84. ***************************************************************************/
  85. BOOL ConvertHexStringToIntW( WCHAR *pszHexNum , int *piNum )
  86. {
  87.     int   n=0L;
  88.     WCHAR  *psz=pszHexNum;
  89.   
  90.     for(n=0 ; ; psz=CharNextW(psz))
  91.     {
  92.         if( (*psz>='0') && (*psz<='9') )
  93.             n = 0x10 * n + *psz - '0';
  94.         else
  95.         {
  96.             WCHAR ch = *psz;
  97.             int n2;
  98.             if(ch >= 'a')
  99.                 ch -= 'a' - 'A';
  100.             n2 = ch - 'A' + 0xA;
  101.             if (n2 >= 0xA && n2 <= 0xF)
  102.                 n = 0x10 * n + n2;
  103.             else
  104.                 break;
  105.         }
  106.     }
  107.     /*
  108.      * Update results
  109.      */
  110.     *piNum = n;
  111.     return (psz != pszHexNum);
  112. }
  113. /***************************************************************************
  114. * IsBiDiLocalizedSystemEx
  115. *
  116. * returns TRUE if running on a lozalized BiDi (Arabic/Hebrew) NT5 or Memphis.
  117. * Should be called whenever SetProcessDefaultLayout is to be called.
  118. *
  119. * History:
  120. * 02-Feb-1998 samera    Created
  121. ***************************************************************************/
  122. BOOL IsBiDiLocalizedSystemEx( LANGID *pLangID )
  123. {
  124.     HKEY          hKey;
  125.     DWORD         dwType;
  126.     CHAR          szResourceLocale[12];
  127.     DWORD         dwSize = sizeof(szResourceLocale)/sizeof(CHAR);
  128.     int           iLCID=0L;
  129.     static BOOL   bRet = (BOOL)(DWORD)-1;
  130.     static LANGID langID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
  131.     if (bRet != (BOOL)(DWORD)-1)
  132.     {
  133.         if (bRet && pLangID)
  134.         {
  135.             *pLangID = langID;
  136.         }
  137.         return bRet;
  138.     }
  139.     bRet = FALSE;
  140.     if( staticIsOS( OS_NT5 ) )
  141.     {
  142.         /*
  143.          * Need to use NT5 detection method (Multiligual UI ID)
  144.          */
  145.         langID = Mirror_GetUserDefaultUILanguage();
  146.         if( langID )
  147.         {
  148.             WCHAR wchLCIDFontSignature[16];
  149.             iLCID = MAKELCID( langID , SORT_DEFAULT );
  150.             /*
  151.              * Let's verify this is a RTL (BiDi) locale. Since reg value is a hex string, let's
  152.              * convert to decimal value and call GetLocaleInfo afterwards.
  153.              * LOCALE_FONTSIGNATURE always gives back 16 WCHARs.
  154.              */
  155.             if( GetLocaleInfoW( iLCID , 
  156.                                 LOCALE_FONTSIGNATURE , 
  157.                                 (WCHAR *) &wchLCIDFontSignature[0] ,
  158.                                 (sizeof(wchLCIDFontSignature)/sizeof(WCHAR))) )
  159.             {
  160.       
  161.                 /* Let's verify the bits we have a BiDi UI locale */
  162.                 if(( wchLCIDFontSignature[7] & (WCHAR)0x0800) && Mirror_IsUILanguageInstalled(langID) )
  163.                 {
  164.                     bRet = TRUE;
  165.                 }
  166.             }
  167.         }
  168.     } else {
  169.         /*
  170.          * Check if BiDi-Memphis is running with Lozalized Resources (
  171.          * i.e. Arabic/Hebrew systems) -It should be enabled ofcourse-.
  172.          */
  173.         if( (staticIsOS(OS_MEMPHIS)) && (GetSystemMetrics(SM_MIDEASTENABLED)) )
  174.         {
  175.             if( RegOpenKeyExA( HKEY_CURRENT_USER , 
  176.                                "Control Panel\Desktop\ResourceLocale" , 
  177.                                0, 
  178.                                KEY_READ, &hKey) == ERROR_SUCCESS) 
  179.             {
  180.                 RegQueryValueExA( hKey , "" , 0 , &dwType , (LPBYTE)szResourceLocale , &dwSize );
  181.                 szResourceLocale[(sizeof(szResourceLocale)/sizeof(CHAR))-1] = 0;
  182.                 RegCloseKey(hKey);
  183.                 if( ConvertHexStringToIntA( szResourceLocale , &iLCID ) )
  184.                 {
  185.                     iLCID = PRIMARYLANGID(LANGIDFROMLCID(iLCID));
  186.                     if( (LANG_ARABIC == iLCID) || (LANG_HEBREW == iLCID) )
  187.                     {
  188.                         bRet = TRUE;
  189.                         langID = LANGIDFROMLCID(iLCID);
  190.                     }
  191.                 }
  192.             }
  193.         }
  194.     }
  195.     if (bRet && pLangID)
  196.     {
  197.         *pLangID = langID;
  198.     }
  199.     return bRet;
  200. }
  201. BOOL IsBiDiLocalizedSystem( void )
  202. {
  203.     return IsBiDiLocalizedSystemEx(NULL);
  204. }
  205. /***************************************************************************
  206. * IsBiDiLocalizedWin95
  207. *
  208. * returns TRUE if running on a lozalized BiDi (Arabic/Hebrew) Win95.
  209. * Needed for legacy operating system check for needed RTL UI elements
  210. * For example, DefView ListView, TreeView,...etc 
  211. * History:
  212. * 12-June-1998 a-msadek    Created
  213. ***************************************************************************/
  214. BOOL IsBiDiLocalizedWin95(BOOL bArabicOnly)
  215. {
  216.     HKEY  hKey;
  217.     DWORD dwType;
  218.     BOOL  bRet = FALSE;
  219.     CHAR  szResourceLocale[12];
  220.     DWORD dwSize = sizeof(szResourceLocale)/sizeof(CHAR);
  221.     int   iLCID=0L;
  222.          /*
  223.          * Check if BiDi-Win95 is running with Lozalized Resources (
  224.          * i.e. Arabic/Hebrew systems) -It should be enabled ofcourse-.
  225.          */
  226.         if( (staticIsOS(OS_WIN95)) && (!staticIsOS(OS_MEMPHIS)) && (GetSystemMetrics(SM_MIDEASTENABLED)) )
  227.         {
  228.             if( RegOpenKeyExA( HKEY_CURRENT_USER , 
  229.                                "Control Panel\Desktop\ResourceLocale" , 
  230.                                0, 
  231.                                KEY_READ, &hKey) == ERROR_SUCCESS) 
  232.             {
  233.                 RegQueryValueExA( hKey , "" , 0 , &dwType , (LPBYTE)szResourceLocale , &dwSize );
  234.                 szResourceLocale[(sizeof(szResourceLocale)/sizeof(CHAR))-1] = 0;
  235.                 RegCloseKey(hKey);
  236.                 if( ConvertHexStringToIntA( szResourceLocale , &iLCID ) )
  237.                 {
  238.                     iLCID = PRIMARYLANGID(LANGIDFROMLCID(iLCID));
  239.                     //
  240.                     //If bArabicOnly we will return true if it a Arabic Win95 localized. 
  241.                     //
  242.                     if( (LANG_ARABIC == iLCID) || ((LANG_HEBREW == iLCID) && !bArabicOnly ))
  243.                     {
  244.                         bRet = TRUE;
  245.                     }
  246.                 }
  247.             }
  248.         }
  249.     
  250.     return bRet;
  251. }
  252. /***************************************************************************
  253. * Mirror_IsEnabledOS
  254. *
  255. * returns TRUE if the mirroring APIs are enabled on the current OS.
  256. *
  257. * History:
  258. * 02-Feb-1998 samera    Created
  259. ***************************************************************************/
  260. BOOL Mirror_IsEnabledOS( void )
  261. {
  262.     BOOL bRet = FALSE;
  263.     if( staticIsOS(OS_NT5) )
  264.     {
  265.         bRet = TRUE;
  266.     } else if( staticIsOS(OS_MEMPHIS) && GetSystemMetrics(SM_MIDEASTENABLED)) {
  267.         bRet=TRUE;
  268.     }
  269.     return bRet;
  270. }
  271. /***************************************************************************
  272. * Mirror_GetUserDefaultUILanguage
  273. *
  274. * Reads the User UI language on NT5
  275. *
  276. * History:
  277. * 22-June-1998 samera    Created
  278. ***************************************************************************/
  279. LANGID Mirror_GetUserDefaultUILanguage( void )
  280. {
  281.     LANGID langId=0;
  282.     static PFNGETUSERDEFAULTUILANGUAGE pfnGetUserDefaultUILanguage=NULL;
  283.     if( NULL == pfnGetUserDefaultUILanguage )
  284.     {
  285.         HMODULE hmod = GetModuleHandleA("KERNEL32");
  286.         if( hmod )
  287.             pfnGetUserDefaultUILanguage = (PFNGETUSERDEFAULTUILANGUAGE)
  288.                                           GetProcAddress(hmod, "GetUserDefaultUILanguage");
  289.     }
  290.     if( pfnGetUserDefaultUILanguage )
  291.         langId = pfnGetUserDefaultUILanguage();
  292.     return langId;
  293. }
  294. /***************************************************************************
  295. * Mirror_IsUILanguageInstalled
  296. *
  297. * Verifies that the User UI language is installed on W2k
  298. *
  299. * History:
  300. * 14-June-1999 msadek    Created
  301. ***************************************************************************/
  302. BOOL Mirror_IsUILanguageInstalled( LANGID langId )
  303. {
  304.     MUIINSTALLLANG MUILangInstalled = {0};
  305.     MUILangInstalled.LangID = langId;
  306.     
  307.     static PFNENUMUILANGUAGES pfnEnumUILanguages=NULL;
  308.     if( NULL == pfnEnumUILanguages )
  309.     {
  310.         HMODULE hmod = GetModuleHandleA("KERNEL32");
  311.         if( hmod )
  312.             pfnEnumUILanguages = (PFNENUMUILANGUAGES)
  313.                                           GetProcAddress(hmod, "EnumUILanguagesW");
  314.     }
  315.     if( pfnEnumUILanguages )
  316.         pfnEnumUILanguages(Mirror_EnumUILanguagesProc, 0, (LONG_PTR)&MUILangInstalled);
  317.     return MUILangInstalled.bInstalled;
  318. }
  319. /***************************************************************************
  320. * Mirror_EnumUILanguagesProc
  321. *
  322. * Enumerates MUI installed languages on W2k
  323. * History:
  324. * 14-June-1999 msadek    Created
  325. ***************************************************************************/
  326. BOOL CALLBACK Mirror_EnumUILanguagesProc(LPTSTR lpUILanguageString, LONG_PTR lParam)
  327. {
  328.     int langID = 0;
  329.     ConvertHexStringToInt(lpUILanguageString, &langID);
  330.     if((LANGID)langID == ((LPMUIINSTALLLANG)lParam)->LangID)
  331.     {
  332.         ((LPMUIINSTALLLANG)lParam)->bInstalled = TRUE;
  333.         return FALSE;
  334.     }
  335.     return TRUE;
  336. }
  337. /***************************************************************************
  338. * Mirror_IsWindowMirroredRTL
  339. *
  340. * returns TRUE if the window is RTL mirrored
  341. *
  342. * History:
  343. * 02-Feb-1998 samera    Created
  344. ***************************************************************************/
  345. BOOL Mirror_IsWindowMirroredRTL( HWND hWnd )
  346. {
  347.     return (GetWindowLongA( hWnd , GWL_EXSTYLE ) & WS_EX_LAYOUTRTL );
  348. }
  349. /***************************************************************************
  350. * Mirror_GetLayout
  351. *
  352. * returns TRUE if the hdc is RTL mirrored
  353. *
  354. * History:
  355. * 02-Feb-1998 samera    Created
  356. ***************************************************************************/
  357. DWORD Mirror_GetLayout( HDC hdc )
  358. {
  359.     DWORD dwRet=0;
  360.     static PFNGETLAYOUT pfnGetLayout=NULL;
  361.     if( NULL == pfnGetLayout )
  362.     {
  363.         HMODULE hmod = GetModuleHandleA("GDI32");
  364.         if( hmod )
  365.             pfnGetLayout = (PFNGETLAYOUT)GetProcAddress(hmod, "GetLayout");
  366.     }
  367.     if( pfnGetLayout )
  368.         dwRet = pfnGetLayout( hdc );
  369.     return dwRet;
  370. }
  371. DWORD Mirror_IsDCMirroredRTL( HDC hdc )
  372. {
  373.     return (Mirror_GetLayout( hdc ) & LAYOUT_RTL);
  374. }
  375. /***************************************************************************
  376. * Mirror_SetLayout
  377. *
  378. * RTL Mirror the hdc
  379. *
  380. * History:
  381. * 02-Feb-1998 samera    Created
  382. ***************************************************************************/
  383. DWORD Mirror_SetLayout( HDC hdc , DWORD dwLayout )
  384. {
  385.     DWORD dwRet=0;
  386.     static PFNSETLAYOUT pfnSetLayout=NULL;
  387.     if( NULL == pfnSetLayout )
  388.     {
  389.         HMODULE hmod = GetModuleHandleA("GDI32");
  390.         if( hmod )
  391.             pfnSetLayout = (PFNSETLAYOUT)GetProcAddress(hmod, "SetLayout");
  392.     }
  393.     if( pfnSetLayout )
  394.         dwRet = pfnSetLayout( hdc , dwLayout );
  395.     return dwRet;
  396. }
  397. DWORD Mirror_MirrorDC( HDC hdc )
  398. {
  399.     return Mirror_SetLayout( hdc , LAYOUT_RTL );
  400. }
  401. /***************************************************************************
  402. * Mirror_SetProcessDefaultLayout
  403. *
  404. * Set the process-default layout.
  405. *
  406. * History:
  407. * 02-Feb-1998 samera    Created
  408. ***************************************************************************/
  409. BOOL Mirror_SetProcessDefaultLayout( DWORD dwDefaultLayout )
  410. {
  411.     BOOL bRet=0;
  412.     static PFNSETPROCESSDEFLAYOUT pfnSetProcessDefLayout=NULL;
  413.     if( NULL == pfnSetProcessDefLayout )
  414.     {
  415.         HMODULE hmod = GetModuleHandleA("USER32");
  416.         if( hmod )
  417.             pfnSetProcessDefLayout = (PFNSETPROCESSDEFLAYOUT)
  418.                                      GetProcAddress(hmod, "SetProcessDefaultLayout");
  419.     }
  420.     if( pfnSetProcessDefLayout )
  421.         bRet = pfnSetProcessDefLayout( dwDefaultLayout );
  422.     return bRet;
  423. }
  424. BOOL Mirror_MirrorProcessRTL( void )
  425. {
  426.     return Mirror_SetProcessDefaultLayout( LAYOUT_RTL );
  427. }
  428. /***************************************************************************
  429. * Mirror_GetProcessDefaultLayout
  430. *
  431. * Get the process-default layout.
  432. *
  433. * History:
  434. * 26-Feb-1998 samera    Created
  435. ***************************************************************************/
  436. BOOL Mirror_GetProcessDefaultLayout( DWORD *pdwDefaultLayout )
  437. {
  438.     BOOL bRet=0;
  439.     static PFNGETPROCESSDEFLAYOUT pfnGetProcessDefLayout=NULL;
  440.     if( NULL == pfnGetProcessDefLayout )
  441.     {
  442.         HMODULE hmod = GetModuleHandleA("USER32");
  443.         if( hmod )
  444.             pfnGetProcessDefLayout = (PFNGETPROCESSDEFLAYOUT)
  445.                                      GetProcAddress(hmod, "GetProcessDefaultLayout");
  446.     }
  447.     if( pfnGetProcessDefLayout )
  448.         bRet = pfnGetProcessDefLayout( pdwDefaultLayout );
  449.     return bRet;
  450. }
  451. BOOL Mirror_IsProcessRTL( void )
  452. {
  453.     DWORD dwDefLayout=0;
  454.     return (Mirror_GetProcessDefaultLayout(&dwDefLayout) && (dwDefLayout&LAYOUT_RTL));
  455. }
  456. ////////////////////////////////////////////////////////////////////////////
  457. // Skip_IDorString
  458. //
  459. // Skips string (or ID) and returns the next aligned WORD.
  460. ////////////////////////////////////////////////////////////////////////////
  461. PBYTE Skip_IDorString(LPBYTE pb)
  462. {
  463.     LPWORD pw = (LPWORD)pb;
  464.     if (*pw == 0xFFFF)
  465.         return (LPBYTE)(pw + 2);
  466.     while (*pw++ != 0)
  467.         ;
  468.     return (LPBYTE)pw;
  469. }
  470. ////////////////////////////////////////////////////////////////////////////
  471. // Skip_DialogHeader
  472. //
  473. // Skips the dialog header and returns the next aligned WORD. 
  474. ////////////////////////////////////////////////////////////////////////////
  475. PBYTE Skip_DialogHeader(LPDLGTEMPLATE pdt)
  476. {
  477.     LPBYTE pb;
  478.     pb = (LPBYTE)(pdt + 1);
  479.     // If there is a menu ordinal, add 4 bytes skip it. Otherwise it is a string or just a 0.
  480.     pb = Skip_IDorString(pb);
  481.     // Skip window class and window text, adjust to next word boundary.
  482.     pb = Skip_IDorString(pb);    // class
  483.     pb = Skip_IDorString(pb);    // window text
  484.     // Skip font type, size and name, adjust to next dword boundary.
  485.     if (pdt->style & DS_SETFONT)
  486.     {
  487.         pb += sizeof(WORD);
  488.         pb = Skip_IDorString(pb);
  489.     }
  490.     pb = (LPBYTE)(((ULONG_PTR)pb + 3) & ~3);    // DWORD align
  491.     return pb;
  492. }
  493. ////////////////////////////////////////////////////////////////////////////
  494. // EditBiDiDLGTemplate
  495. //
  496. // Edits a dialog template for BiDi stuff.
  497. // Optionally, skipping some controls.
  498. // Works only with DLGTEMPLATE.
  499. ////////////////////////////////////////////////////////////////////////////
  500. void EditBiDiDLGTemplate(LPDLGTEMPLATE pdt, DWORD dwFlags, PWORD pwIgnoreList, int cIgnore)
  501. {
  502.     LPBYTE pb;
  503.     UINT cItems;
  504.     if (!pdt)
  505.         return;
  506.     // we should never get an extended template
  507.     ASSERT (((LPDLGTEMPLATEEX)pdt)->wSignature != 0xFFFF);
  508.     
  509.     if(dwFlags & EBDT_NOMIRROR)
  510.     {
  511.         // Turn off the mirroring styles for the dialog.
  512.         pdt->dwExtendedStyle &= ~(WS_EX_LAYOUTRTL | WS_EX_NOINHERITLAYOUT);
  513.     }
  514.     cItems = pdt->cdit;
  515.     // skip DLGTEMPLATE part
  516.     pb = Skip_DialogHeader(pdt);
  517.     while (cItems--)
  518.     {
  519.         UINT cbCreateParams;
  520.         int i = 0;
  521.         BOOL bIgnore = FALSE;
  522.         if(pwIgnoreList && cIgnore)
  523.         {
  524.             for(i = 0;i < cIgnore; i++)
  525.             {
  526.                 if((((LPDLGITEMTEMPLATE)pb)->id == *(pwIgnoreList +i)))
  527.                 {
  528.                     bIgnore = TRUE;
  529.                 }
  530.             }
  531.         }
  532.         
  533.         if((dwFlags & EBDT_NOMIRROR) && !bIgnore)
  534.         {
  535.             // Turn off the mirroring styles for this item.
  536.             ((LPDLGITEMTEMPLATE)pb)->dwExtendedStyle &= ~(WS_EX_LAYOUTRTL | WS_EX_NOINHERITLAYOUT); 
  537.         }    
  538.         if((dwFlags & EBDT_FLIP) && !bIgnore)
  539.         {
  540.             ((LPDLGITEMTEMPLATE)pb)->x = pdt->cx - (((LPDLGITEMTEMPLATE)pb)->x + ((LPDLGITEMTEMPLATE)pb)->cx);
  541.             // BUGBUG: Should we force RTL reading order for title as well ?
  542.             // The client has the option of doining this already by PSH_RTLREADING
  543.         }
  544.         pb += sizeof(DLGITEMTEMPLATE);
  545.         // Skip the dialog control class name.
  546.         pb = Skip_IDorString(pb);
  547.         // Look at window text now.
  548.         pb = Skip_IDorString(pb);
  549.         cbCreateParams = *((LPWORD)pb);
  550.         // skip any CreateParams which include the generated size WORD.
  551.         if (cbCreateParams)
  552.             pb += cbCreateParams;
  553.         pb += sizeof(WORD);
  554.         // Point at the next dialog item. (DWORD aligned)
  555.         pb = (LPBYTE)(((ULONG_PTR)pb + 3) & ~3);
  556.         bIgnore = FALSE;
  557.     }
  558. }