prpage.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 35k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. #include "ctlspriv.h"
  2. #include "prshti.h"
  3. #ifdef WX86
  4. #include <wx86ofl.h>
  5. #endif
  6. #if defined(MAINWIN)  /* portable dialog templates, WINTEL FORMAT */
  7. #include <mainwin.h>
  8. #endif
  9. #ifndef WINNT
  10. // Thunk entries for 16-bit pages.
  11. typedef LPARAM HPROPSHEETPAGE16;
  12. extern BOOL WINAPI DestroyPropertySheetPage16(HPROPSHEETPAGE16 hpage);
  13. extern HWND WINAPI CreatePage16(HPROPSHEETPAGE16 hpage, HWND hwndParent);
  14. extern BOOL WINAPI _GetPageInfo16(HPROPSHEETPAGE16 hpage, LPTSTR pszCaption, int cbCaption, LPPOINT ppt, HICON FAR * phIcon, BOOL FAR * bRTL);
  15. #endif
  16. #ifndef UNICODE
  17. #define _Rstrcpyn(psz, pszW, cchMax)  _SWstrcpyn(psz, (LPCWCH)pszW, cchMax)
  18. #else
  19. #define _Rstrcpyn   lstrcpyn
  20. #endif
  21. //
  22. //  Miracle of miracles - Win95 implements lstrlenW.
  23. //
  24. #define _Rstrlen    lstrlenW
  25. #define RESCHAR WCHAR
  26. #ifndef UNICODE
  27. void _SWstrcpyn(LPSTR psz, LPCWCH pwsz, UINT cchMax)
  28. {
  29.     WideCharToMultiByte(CP_ACP, 0, pwsz, -1, psz, cchMax, NULL, NULL);
  30. }
  31. #endif
  32. #include <pshpack2.h>
  33. typedef struct                           
  34. {                                        
  35.     WORD    wDlgVer;                     
  36.     WORD    wSignature;                  
  37.     DWORD   dwHelpID;                    
  38.     DWORD   dwExStyle;                   
  39.     DWORD   dwStyle;                     
  40.     WORD    cDlgItems;
  41.     WORD    x;                           
  42.     WORD    y;                           
  43.     WORD    cx;                          
  44.     WORD    cy;                          
  45. }   DLGEXTEMPLATE, FAR *LPDLGEXTEMPLATE;
  46. #include <poppack.h> /* Resume normal packing */
  47. //
  48. //  CallPropertyPageCallback
  49. //
  50. //  Call the callback for the property page, passing it the correct lParam
  51. //  based on the character set it wants.
  52. //
  53. UINT CallPropertyPageCallback(PISP pisp, UINT uMsg)
  54. {
  55.     UINT uiResult = TRUE;           // assume success
  56.     //
  57.     //  APP COMPAT!  The MMC snapin for IIS uses a callback that
  58.     //  IGNORES THE MESSAGE NUMBER!  So you can't send it any
  59.     //  messages beyond those that shipped in Win9x Golden or
  60.     //  they will FAULT!
  61.     //
  62.     if (HASCALLBACK(pisp) &&
  63.         (pisp->_psp.dwSize > PROPSHEETPAGE_V1_SIZE ||
  64.          uMsg == PSPCB_CREATE || uMsg == PSPCB_RELEASE)) {
  65. #ifdef UNICODE
  66.         if (HASANSISHADOW(pisp))
  67.         {
  68. #ifdef WX86
  69.             if ( pisp->_pfx.dwInternalFlags & PSPI_WX86 )
  70.                 uiResult = Wx86Callback(pisp->_psp.pfnCallback, NULL, uMsg, (LPARAM) &pisp->_cpfx.pispShadow->_psp);
  71.             else
  72. #endif
  73.                 uiResult = pisp->_psp.pfnCallback(NULL, uMsg, &pisp->_cpfx.pispShadow->_psp);
  74.         } else
  75. #endif
  76.         {
  77. #ifdef WX86
  78.             if ( pisp->_pfx.dwInternalFlags & PSPI_WX86 )
  79.                 uiResult = Wx86Callback(pisp->_psp.pfnCallback, NULL, uMsg, (LPARAM) &pisp->_psp);
  80.             else
  81. #endif
  82.                 uiResult = pisp->_psp.pfnCallback(NULL, uMsg, &pisp->_psp);
  83.         }
  84.     }
  85.     return uiResult;
  86. }
  87. //
  88. //  FreePropertyPageStruct
  89. //
  90. //  Free the memory block that contains a property sheet page.
  91. //  It is the caller's responsibility to have freed all the things
  92. //  that were attached to it.
  93. //
  94. //
  95. __inline void FreePropertyPageStruct(PISP pisp)
  96. {
  97.     LocalFree(PropSheetBase(pisp));
  98. }
  99. //
  100. //  DestroyPropertySheetPage
  101. //
  102. //  Do the appropriate thing to destroy a property sheet page, whether
  103. //  this entails talking to 16-bit thunks, sending the PSPCB_RELEASE,
  104. //  or freeing the shadow page.
  105. //
  106. BOOL WINAPI DestroyPropertySheetPage(HPROPSHEETPAGE hpage)
  107. {
  108.     PISP pisp = InternalizeHPROPSHEETPAGE(hpage);
  109. #if defined(WIN32) && !defined(WINNT)
  110.     // Check if this is a proxy page for 16-bit page object.
  111.     if (pisp->_psp.dwFlags & PSP_IS16)
  112.     {
  113.         ASSERT(!HASANSISHADOW(pisp));
  114.         // Yes, call 16-bit side of DestroyPropertySheetPage();
  115.         DestroyPropertySheetPage16(pisp->_psp.lParam);
  116.         // Then, free the 16-bit DLL if we need to.
  117.         if (pisp->_psp.hInstance)
  118.         {
  119.             FreeLibrary16(pisp->_psp.hInstance);
  120.         }
  121.     }
  122.     else
  123. #endif
  124.     {
  125.         CallPropertyPageCallback(pisp, PSPCB_RELEASE);
  126.         // Do the decrement *after* calling the callback for the last time
  127.         if (HASREFPARENT(pisp))
  128.             InterlockedDecrement((LPLONG)pisp->_psp.pcRefParent);
  129. #ifdef UNICODE
  130.         if (HASANSISHADOW(pisp))
  131.         {
  132.             FreePropertyPageStrings(&pisp->_cpfx.pispShadow->_psp);
  133.             FreePropertyPageStruct(pisp->_cpfx.pispShadow);
  134.         }
  135. #endif
  136.     }
  137.     //
  138.     //  Note that FreePropertyPageStrings will try to destroy strings for
  139.     //  proxy pages, but that's okay, because the corresponding P_pszBlah
  140.     //  fields are all NULL since we never initialized them.
  141.     //
  142.     FreePropertyPageStrings(&pisp->_psp);
  143.     FreePropertyPageStruct(pisp);
  144.     return TRUE;
  145. }
  146. //
  147. // GetPageInfoEx
  148. //
  149. //  Extract information about a page into a PAGEINFOEX structure.
  150. //
  151. //  WARNING!  EVIL HORRIBLE RESTRICTION!
  152. //
  153. //  You are allowed to pass GPI_ICON only once per page.
  154. //
  155. BOOL WINAPI GetPageInfoEx(LPPROPDATA ppd, PISP pisp, PAGEINFOEX *ppi, LANGID langidMUI, DWORD flags)
  156. {
  157.     HRSRC hRes;
  158.     LPDLGTEMPLATE pDlgTemplate;
  159.     LPDLGEXTEMPLATE pDlgExTemplate;
  160.     BOOL bResult = FALSE;
  161.     HGLOBAL hDlgTemplate = 0;
  162.     BOOL bSetFont;
  163.     LPBYTE pszT;
  164.     //
  165.     // Init the output structure.
  166.     //
  167.     ZeroMemory(ppi, sizeof(*ppi));
  168. #ifdef DEBUG
  169.     //  Enforce the GPI_ICON rule.
  170.     if (flags & GPI_ICON)
  171.     {
  172.         ASSERT(!(pisp->_pfx.dwInternalFlags & PSPI_FETCHEDICON));
  173.         pisp->_pfx.dwInternalFlags |= PSPI_FETCHEDICON;
  174.     }
  175.     // For compatibility with 16-bit crap, you are only allowed to
  176.     // pass these combinations of flags.
  177.     switch (LOWORD(flags)) {
  178.     case GPI_PT | GPI_ICON | GPI_FONT | GPI_BRTL | GPI_CAPTION:
  179.         break;
  180.     case GPI_PT | GPI_ICON |            GPI_BRTL | GPI_CAPTION:
  181.         break;
  182.     case GPI_DIALOGEX:
  183.         break;
  184.     default:
  185.         ASSERT(!"Invalid flags passed to GetPageInfoEx");
  186.         break;
  187.     }
  188. #endif
  189. #ifndef WINNT
  190.     // Check if this is a proxy page for 16-bit page object.
  191.     if (pisp->_psp.dwFlags & PSP_IS16)
  192.     {
  193.         // 16-bit property sheets never support the new stuff
  194.         if (LOWORD(flags) == GPI_DIALOGEX)
  195.             return TRUE;
  196.         ASSERT(flags & GPI_ICON);
  197. #ifdef UNICODE
  198.         // Yes, call 16-bit side of GetPageInfo but we need conversion because it returns MBCS
  199.         if (_GetPageInfo16(pisp->_psp.lParam, 
  200.                            ppi->szCaption, 
  201.                            ARRAYSIZE(ppi->szCaption) * sizeof(WCHAR), 
  202.                            &ppi->pt, 
  203.                            &ppi->hIcon, 
  204.                            &ppi->bRTL))
  205.         {
  206.             LPWSTR lpCaption = ProduceWFromA(CP_ACP, (LPCSTR)ppi->szCaption);
  207.         
  208.             if (lpCaption)
  209.             {
  210.                 StrCpyNW(ppi->szCaption, lpCaption, ARRAYSIZE(ppi->szCaption));
  211.                 FreeProducedString(lpCaption);
  212.             }
  213.             return TRUE;
  214.         }
  215.         else
  216.             return FALSE;
  217. #else
  218.         // Yes, call 16-bit side of GetPageInfo
  219.         return _GetPageInfo16(pisp->_psp.lParam, 
  220.                               ppi->szCaption, 
  221.                               ARRAYSIZE(ppi->szCaption),
  222.                               &ppi->pt,
  223.                               &ppi->hIcon,
  224.                               &ppi->bRTL);
  225. #endif
  226.     }
  227. #endif
  228.     if (flags & GPI_ICON) {
  229.         if (pisp->_psp.dwFlags & PSP_USEHICON)
  230.             ppi->hIcon = pisp->_psp.P_hIcon;
  231.         else if (pisp->_psp.dwFlags & PSP_USEICONID)
  232.             ppi->hIcon = LoadImage(pisp->_psp.hInstance, pisp->_psp.P_pszIcon, IMAGE_ICON, g_cxSmIcon, g_cySmIcon, LR_DEFAULTCOLOR);
  233.     }
  234.     if (pisp->_psp.dwFlags & PSP_DLGINDIRECT)
  235.     {
  236.         pDlgTemplate = (LPDLGTEMPLATE)pisp->_psp.P_pResource;
  237.         goto UseTemplate;
  238.     }
  239.     // BUGBUG: We also need to stash away the langid that we actually found
  240.     //         so we can later determine if we have to do any ML stuff...
  241.     hRes = FindResourceExRetry(pisp->_psp.hInstance, RT_DIALOG, 
  242.                                pisp->_psp.P_pszTemplate, langidMUI);
  243.     if (hRes)
  244.     {
  245.         hDlgTemplate = LoadResource(pisp->_psp.hInstance, hRes);
  246.         if (hDlgTemplate)
  247.         {
  248.             pDlgTemplate = (LPDLGTEMPLATE)LockResource(hDlgTemplate);
  249.             if (pDlgTemplate)
  250.             {
  251. UseTemplate:
  252.                 pDlgExTemplate = (LPDLGEXTEMPLATE) pDlgTemplate;
  253.                 //
  254.                 // Get the width and the height in dialog units.
  255.                 //
  256.                 if (pDlgExTemplate->wSignature == 0xFFFF)
  257.                 {
  258.                     // DIALOGEX structure
  259.                     ppi->bDialogEx = TRUE;
  260.                     ppi->dwStyle   = pDlgExTemplate->dwStyle;
  261.                     ppi->pt.x      = pDlgExTemplate->cx;
  262.                     ppi->pt.y      = pDlgExTemplate->cy;
  263. #ifdef WINDOWS_ME
  264.                     // Get the RTL reading order for the caption
  265.                     ppi->bRTL = (((pDlgExTemplate->dwExStyle) & WS_EX_RTLREADING) || (pisp->_psp.dwFlags & PSP_RTLREADING)) ? TRUE : FALSE;
  266. #endif
  267.                     ppi->bMirrored = ((pDlgExTemplate->dwExStyle) & (RTL_MIRRORED_WINDOW)) ? TRUE : FALSE;
  268.                 }
  269.                 else
  270.                 {
  271.                     ppi->dwStyle = pDlgTemplate->style;
  272.                     ppi->pt.x    = pDlgTemplate->cx;
  273.                     ppi->pt.y    = pDlgTemplate->cy;
  274. #ifdef WINDOWS_ME
  275.                     ppi->bRTL = (pisp->_psp.dwFlags & PSP_RTLREADING) ? TRUE : FALSE;
  276. #endif
  277.                 }
  278.                 bResult = TRUE;
  279.                 if (flags & (GPI_CAPTION | GPI_FONT))
  280.                 {
  281.                     if (pisp->_psp.dwFlags & PSP_USETITLE)
  282.                     {
  283.                         if (IS_INTRESOURCE(pisp->_psp.pszTitle))
  284.                         {
  285.                             CCLoadStringExInternal(pisp->_psp.hInstance,
  286.                                                   (UINT)LOWORD(pisp->_psp.pszTitle),
  287.                                                    ppi->szCaption,
  288.                                                    ARRAYSIZE(ppi->szCaption),
  289.                                                    langidMUI);
  290.                         }
  291.                         else
  292.                         {
  293.                             // Copy pszTitle
  294.                             lstrcpyn(ppi->szCaption, pisp->_psp.pszTitle, ARRAYSIZE(ppi->szCaption));
  295.                         }
  296.                     }
  297. #if !defined(MAINWIN)
  298.                     // ML UI support for NT5
  299.                     // Grab the font face and size in point from page so that
  300.                     // we can calculate size of page in real screen pixel
  301.                     // This is for NT5 MLUI but should not be any harm for Win95
  302.                     // or even works better for the platform.
  303.                     // 1. check if the page has font specified
  304.                     if ( ppi->bDialogEx )
  305.                         bSetFont = ((pDlgExTemplate->dwStyle & DS_SETFONT) != 0);
  306.                     else
  307.                         bSetFont = ((pDlgTemplate->style & DS_SETFONT) != 0);
  308.                     // 2. Skip until after class name
  309.                     //    only if either font is set or we want title
  310.                     //
  311.                     if (bSetFont || !(pisp->_psp.dwFlags & PSP_USETITLE))
  312.                     {
  313.                         // Get the caption string from the dialog template, only
  314.                         //
  315.                         if (ppi->bDialogEx)
  316.                             pszT = (BYTE *) (pDlgExTemplate + 1);
  317.                         else
  318.                             pszT = (BYTE *) (pDlgTemplate + 1);
  319.                         // The menu name is either 0xffff followed by a word,
  320.                         // or a string.
  321.                         switch (*(LPWORD)pszT) {
  322.                         case 0xffff:
  323.                             pszT += 2 * sizeof(WORD);
  324.                             break;
  325.                         default:
  326.                             pszT += (_Rstrlen((LPTSTR)pszT) + 1) * sizeof(RESCHAR);
  327.                             break;
  328.                         }
  329.                         //
  330.                         // Now we are pointing at the class name.
  331.                         //
  332.                         pszT += (_Rstrlen((LPTSTR)pszT) + 1) * sizeof(RESCHAR);
  333.                     }
  334.                     // 3. grab the title from template if PSP_USETITLE isn't set
  335.                     //
  336.                     if (!(pisp->_psp.dwFlags & PSP_USETITLE))
  337.                         _Rstrcpyn(ppi->szCaption, (LPTSTR)pszT, ARRAYSIZE(ppi->szCaption));
  338.                     // 4. grab the point size and face name if DS_SETFONT
  339.                     //
  340.                     if (bSetFont && (flags & GPI_FONT))
  341.                     {
  342.                         // skip the title string
  343.                         pszT += (_Rstrlen((LPTSTR)pszT)+1) * sizeof(RESCHAR);
  344.                         ppi->pfd.PointSize = *((short *)pszT)++;
  345.                         if (ppi->bDialogEx)
  346.                         {
  347.                             ((short *)pszT)++; // skip weight as we always use FW_NORMAL w/ DS_3DLOOK
  348.                             ppi->pfd.bItalic  = *(BYTE *)pszT++;
  349.                             ppi->pfd.iCharset = *(BYTE *)pszT++;
  350.                         }
  351.                         else
  352.                         {
  353.                             ppi->pfd.bItalic  = FALSE;
  354.                             ppi->pfd.iCharset = DEFAULT_CHARSET;
  355.                         }
  356.                         _Rstrcpyn(ppi->pfd.szFace, (LPTSTR)pszT, ARRAYSIZE(ppi->pfd.szFace));
  357. #ifdef WINNT
  358.                         // But if this is a SHELLFONT page and the font name is "MS Shell Dlg",
  359.                         // then its font secretly gets morphed into MS Shell Dlg 2 (if
  360.                         // all the other pages agree)...  The wackiness continues...
  361.                         if (staticIsOS(OS_NT5) &&
  362.                             (ppd->fFlags & PD_SHELLFONT) &&
  363.                             IsPageInfoSHELLFONT(ppi) &&
  364.                             lstrcmpi(ppi->pfd.szFace, TEXT("MS Shell Dlg")) == 0)
  365.                         {
  366.                             _Rstrcpyn(ppi->pfd.szFace, TEXT("MS Shell Dlg 2"), ARRAYSIZE(ppi->pfd.szFace));
  367.                         }
  368. #endif
  369.                         //
  370.                         //  USER quirk #2: If the font height is 0x7FFF, then
  371.                         //  USER really uses the MessageBox font and no font
  372.                         //  information is stored in the dialog template.
  373.                         //  Win95's dialog template converter doesn't support
  374.                         //  this, so we won't either.
  375.                     }
  376. #else
  377.                     else
  378.                     {
  379.                         // Get the caption string from the dialog template, only
  380.                         //
  381.                         LPBYTE pszT;
  382.                         if (ppi->bDialogEx)
  383.                             pszT = (LPBYTE) (pDlgExTemplate + 1);
  384.                         else
  385.                             pszT = (LPBYTE) (pDlgTemplate + 1);
  386.                         // The menu name is either 0xffff followed by a word, or a string.
  387.                         //
  388.                         switch (*(LPWORD)pszT) {
  389.                         case 0xffff:
  390.                             pszT += 2 * sizeof(WORD);
  391.                             break;
  392.                         default:
  393.                             pszT += (_Rstrlen((LPTSTR)pszT) + 1) * sizeof(RESCHAR);
  394.                             break;
  395.                         }
  396.                         //
  397.                         // Now we are pointing at the class name.
  398.                         //
  399.                         pszT += (_Rstrlen((LPTSTR)pszT) + 1) * sizeof(RESCHAR);
  400.                         _Rstrcpyn(ppi->szCaption, (LPTSTR)pszT, ARRAYSIZE(ppi->szCaption));
  401.                     }
  402. #endif
  403.                 }
  404.                 if (pisp->_psp.dwFlags & PSP_DLGINDIRECT)
  405.                     return bResult;
  406.                 UnlockResource(hDlgTemplate);
  407.             }
  408.             FreeResource(hDlgTemplate);
  409.         }
  410.     }
  411.     else
  412.     {
  413.         DebugMsg(DM_ERROR, TEXT("GetPageInfo - ERROR: FindResource() failed"));
  414.     }
  415.     return bResult;
  416. }
  417. //
  418. //  Helper function that edits a dialog template in preparation for it
  419. //  becoming a property sheet page.  This has been split out because
  420. //  the legacy CreatePage function needs to do this, too.
  421. //
  422. //  Returns the place where the style was edited on success, or
  423. //  NULL if we took an exception while editing the template.
  424. //
  425. //  The old style is returned in pdwSaveStyle so it can be replaced later.
  426. //
  427. LPDWORD
  428. EditPropSheetTemplate(
  429.     LPDLGTEMPLATE pDlgTemplate,
  430.     LPDWORD pdwSaveStyle,
  431.     BOOL fFlags)                        // PD_*
  432. {
  433.     DWORD lSaveStyle;
  434.     DWORD dwNewStyle;
  435.     LPDWORD pdwStyle;
  436.     LPDLGEXTEMPLATE pDlgExTemplate = (LPDLGEXTEMPLATE) pDlgTemplate;
  437.     try {
  438.         //
  439.         // We need to save the SETFONT, LOCALEDIT, and CLIPCHILDREN
  440.         // flags.
  441.         //
  442.         if (pDlgExTemplate->wSignature == 0xFFFF)
  443.         {
  444.             pdwStyle = &pDlgExTemplate->dwStyle;
  445.         }
  446.         else
  447.         {
  448.             pdwStyle = &pDlgTemplate->style;
  449.         }
  450.         lSaveStyle = *pdwStyle;
  451.         *pdwSaveStyle = lSaveStyle;
  452.         dwNewStyle = (lSaveStyle & (DS_SHELLFONT | DS_LOCALEDIT | WS_CLIPCHILDREN))
  453.                                     | WS_CHILD | WS_TABSTOP | DS_3DLOOK | DS_CONTROL;
  454. #ifdef WINNT
  455.         // If SHELLFONT has been turned off and this page uses it, then turn
  456.         // it off.
  457.         if (!(fFlags & PD_SHELLFONT) &&
  458.             (dwNewStyle & DS_SHELLFONT) == DS_SHELLFONT)
  459.             dwNewStyle &= ~DS_FIXEDSYS;     // Leave DS_USEFONT but lose FIXEDSYS
  460. #endif
  461.         *pdwStyle = dwNewStyle;
  462.     } except (UnhandledExceptionFilter( GetExceptionInformation() )) {
  463.         return NULL;
  464.     }
  465.     __endexcept
  466.     return pdwStyle;
  467. }
  468. #ifdef UNICODE
  469. void RethunkShadowStrings(PISP pisp)
  470. {
  471.     //
  472.     //  Note:  Old code recomputed the entire UNICODE PROPSHEETHEADER
  473.     //  from the ANSI shadow at certain points, in case
  474.     //  the app edited the ANSI shadow.
  475.     //
  476.     //  So we do it too.  I need to ask Eric Flo why we did it in the
  477.     //  first place.  Note that the algorithm is buggy - if the app
  478.     //  edited any of the string fields (or any of the flags that
  479.     //  gate the string fields), we both leak the original memory
  480.     //  *and* fault when we try to free something that wasn't
  481.     //  allocated via LocalAlloc.  We preserve the bug to be compatible
  482.     //  with NT4.  (Snicker.)
  483.     //
  484.     FreePropertyPageStrings(&pisp->_psp);
  485.     hmemcpy(&pisp->_psp, &pisp->_cpfx.pispShadow->_psp,
  486.                       min(sizeof(PROPSHEETPAGE),
  487.                           pisp->_cpfx.pispShadow->_psp.dwSize));
  488.     //
  489.     //  If this copy fails, we will carry on with happy NULL strings.
  490.     //  So some strings are empty, boo-hoo.
  491.     //
  492.     EVAL(CopyPropertyPageStrings(&pisp->_psp, StrDup_AtoW));
  493. }
  494. #endif
  495. //
  496. //  This function creates a dialog box from the specified dialog template
  497. // with appropriate style flags.
  498. //
  499. HWND NEAR PASCAL _CreatePageDialog(LPPROPDATA ppd, PISP pisp, HWND hwndParent, LPDLGTEMPLATE pDlgTemplate)
  500. {
  501.     HWND hwndPage;
  502.     LPARAM lParam;
  503.     LPDWORD pdwStyle;
  504.     DWORD lSaveStyle;
  505.     DLGPROC pfnDlgProc;
  506.     pdwStyle = EditPropSheetTemplate(pDlgTemplate, &lSaveStyle, ppd->fFlags);
  507.     if (!pdwStyle)                  // error editing template
  508.         return NULL;
  509.     //
  510.     //  Thunk the Dialog proc if we were created by x86 code on RISC.
  511.     //
  512. #ifdef WX86
  513.     if (pisp->_pfx.dwInternalFlags & PSPI_WX86) {
  514.         pfnDlgProc = (DLGPROC) Wx86ThunkProc( pisp->_psp.pfnDlgProc, (PVOID) 4, TRUE );
  515.         if (pfnDlgProc == NULL)
  516.             return NULL;
  517.     }
  518.     else
  519. #endif
  520.         pfnDlgProc = pisp->_psp.pfnDlgProc;
  521.     //
  522.     //  Decide what to pass as the lParam to the CreateDialogIndirectParam.
  523.     //
  524. #ifdef UNICODE
  525.     //
  526.     // If the caller was ANSI, then use the ANSI PROPSHEETPAGE.
  527.     //
  528.     if (HASANSISHADOW(pisp))
  529.     {
  530.         lParam = (LPARAM) &pisp->_cpfx.pispShadow->_psp;
  531.     }
  532.     else if (pisp->_psp.dwFlags & PSP_SHPAGE)
  533.     {
  534.         //
  535.         //  PSP_SHPAGE is a special flag used by pre-IE5 shell32 only.
  536.         //  See prshti.h for gory details.  If we get this far, it means
  537.         //  that we need to pass the CLASSICPREFIX instead of the
  538.         //  PROPSHEETPAGE.
  539.         //
  540.         lParam = (LPARAM)&pisp->_cpfx;
  541.     }
  542.     else
  543.     {
  544.         //
  545.         //  Normal UNICODE caller gets the UNICODE PROPSHEETPAGE.
  546.         //
  547.         lParam = (LPARAM)&pisp->_psp;
  548.     }
  549. #else
  550.     //
  551.     //  ANSI caller gets the ANSI PROPSHEETHEADER (our only one).
  552.     //
  553.     lParam = (LPARAM)&pisp->_psp;
  554. #endif
  555.     //
  556.     //  All set - go create the sucker.
  557.     //
  558. #ifdef UNICODE
  559.     if (HASANSISHADOW(pisp)) {
  560.         hwndPage = CreateDialogIndirectParamA(
  561.                         pisp->_psp.hInstance,
  562.                         (LPCDLGTEMPLATE)pDlgTemplate,
  563.                         hwndParent,
  564.                         pfnDlgProc, lParam);
  565.         RethunkShadowStrings(pisp);
  566.     } else {
  567.         hwndPage = CreateDialogIndirectParam(
  568.                         pisp->_psp.hInstance,
  569.                         (LPCDLGTEMPLATE)pDlgTemplate,
  570.                         hwndParent,
  571.                         pfnDlgProc, lParam);
  572.     }
  573. #else
  574.     hwndPage = CreateDialogIndirectParam(
  575.                     pisp->_psp.hInstance,
  576.                     (LPCDLGTEMPLATE)pDlgTemplate,
  577.                     hwndParent,
  578.                     pfnDlgProc, lParam);
  579. #endif
  580.     //
  581.     //  Restore the original dialog template style.
  582.     //
  583.     try {
  584.         MwWriteDWORD((LPBYTE)pdwStyle, lSaveStyle);
  585.     } except (UnhandledExceptionFilter( GetExceptionInformation() )) {
  586.         if (hwndPage) {
  587.             DestroyWindow(hwndPage);
  588.         }
  589.         return NULL;
  590.     }
  591.     __endexcept
  592.     return hwndPage;
  593. }
  594. HWND _CreatePage(LPPROPDATA ppd, PISP pisp, HWND hwndParent, LANGID langidMUI)
  595. {
  596.     HWND hwndPage = NULL; // NULL indicates an error
  597.     if (!CallPropertyPageCallback(pisp, PSPCB_CREATE))
  598.     {
  599.         return NULL;
  600.     }
  601. #ifdef UNICODE
  602.     if (HASANSISHADOW(pisp)) {
  603.         RethunkShadowStrings(pisp);
  604.     }
  605. #endif
  606. #if defined(WIN32) && !defined(WINNT)
  607.     // Check if this is a proxy page for 16-bit page object.
  608.     if (pisp->_psp.dwFlags & PSP_IS16)
  609.     {
  610.         // Yes, call 16-bit side of CreatePage();
  611.         return CreatePage16(pisp->_psp.lParam, hwndParent);
  612.     }
  613. #endif
  614.         
  615.     if (pisp->_psp.dwFlags & PSP_DLGINDIRECT)
  616.     {
  617.         hwndPage=_CreatePageDialog(ppd, pisp, hwndParent, (LPDLGTEMPLATE)pisp->_psp.P_pResource);
  618.     }
  619.     else
  620.     {
  621.         HRSRC hRes;
  622.         hRes = FindResourceExRetry(pisp->_psp.hInstance, RT_DIALOG, 
  623.                                    pisp->_psp.P_pszTemplate, langidMUI);
  624.         if (hRes)
  625.         {
  626.             HGLOBAL hDlgTemplate;
  627.             hDlgTemplate = LoadResource(pisp->_psp.hInstance, hRes);
  628.             if (hDlgTemplate)
  629.             {
  630.                 const DLGTEMPLATE FAR * pDlgTemplate;
  631.                 pDlgTemplate = (LPDLGTEMPLATE)LockResource(hDlgTemplate);
  632.                 if (pDlgTemplate)
  633.                 {
  634.                     ULONG cbTemplate=SizeofResource(pisp->_psp.hInstance, hRes);
  635.                     LPDLGTEMPLATE pdtCopy = (LPDLGTEMPLATE)Alloc(cbTemplate);
  636.                     ASSERT(cbTemplate>=sizeof(DLGTEMPLATE));
  637.                     if (pdtCopy)
  638.                     {
  639.                         hmemcpy(pdtCopy, pDlgTemplate, cbTemplate);
  640.                         hwndPage=_CreatePageDialog(ppd, pisp, hwndParent, pdtCopy);
  641.                         Free(pdtCopy);
  642.                     }
  643.                     UnlockResource(hDlgTemplate);
  644.                 }
  645.                 FreeResource(hDlgTemplate);
  646.             }
  647.         }
  648.     }
  649.     return hwndPage;
  650. }
  651. //===========================================================================
  652. //
  653. //  Legacy crap
  654. //
  655. //  CreatePage is an internal entry point used by shell32 prior to NT5/IE5.
  656. //
  657. //  Win95's shell32 passes a PROPSHEETPAGEA.
  658. //
  659. //  WinNT's shell32 passes a CLASSICPREFIX + PROPSHEETPAGEW.
  660. //
  661. //  The kicker is that shell32 really doesn't need any property sheet page
  662. //  features.  It's just too lazy to do some dialog style editing.
  663. //
  664. //
  665. HWND WINAPI CreatePage(LPVOID hpage, HWND hwndParent)
  666. {
  667.     HWND hwndPage = NULL; // NULL indicates an error
  668.     HRSRC hrsrc;
  669.     LPPROPSHEETPAGE ppsp;
  670. #ifdef WINNT
  671.     //
  672.     //  Move from the CLASSICPREFIX to the PROPSHEETHEADER.
  673.     //
  674.     ppsp = &CONTAINING_RECORD(hpage, ISP, _cpfx)->_psp;
  675. #else
  676.     //
  677.     //  It's already a PROPSHEETHEADER.
  678.     //
  679.     ppsp = hpage;
  680. #endif
  681.     // Docfind2.c never passed these flags, so we don't need to implement them.
  682.     ASSERT(!(ppsp->dwFlags & (PSP_USECALLBACK | PSP_IS16 | PSP_DLGINDIRECT)));
  683. #ifdef WINNT
  684.     hrsrc = FindResourceW(ppsp->hInstance, ppsp->P_pszTemplate, RT_DIALOG);
  685. #else
  686.     hrsrc = FindResourceA(ppsp->hInstance, (LPSTR)ppsp->P_pszTemplate, (LPSTR)RT_DIALOG);
  687. #endif
  688.     if (hrsrc)
  689.     {
  690.         LPCDLGTEMPLATE pDlgTemplate = LoadResource(ppsp->hInstance, hrsrc);
  691.         if (pDlgTemplate)
  692.         {
  693.             //
  694.             //  Make a copy of the template so we can edit it.
  695.             //
  696.             DWORD cbTemplate = SizeofResource(ppsp->hInstance, hrsrc);
  697.             LPDLGTEMPLATE pdtCopy = (LPDLGTEMPLATE)Alloc(cbTemplate);
  698.             ASSERT(cbTemplate>=sizeof(DLGTEMPLATE));
  699.             if (pdtCopy)
  700.             {
  701.                 DWORD dwScratch;
  702.                 hmemcpy(pdtCopy, pDlgTemplate, cbTemplate);
  703.                 if (EditPropSheetTemplate(pdtCopy, &dwScratch, PD_SHELLFONT))
  704.                 {
  705. #ifdef WINNT
  706.                     hwndPage = CreateDialogIndirectParamW(
  707.                                     ppsp->hInstance,
  708.                                     pdtCopy,
  709.                                     hwndParent,
  710.                                     ppsp->pfnDlgProc, (LPARAM)hpage);
  711. #else
  712.                     hwndPage = CreateDialogIndirectParamA(
  713.                                     ppsp->hInstance,
  714.                                     pdtCopy,
  715.                                     hwndParent,
  716.                                     ppsp->pfnDlgProc, (LPARAM)hpage);
  717. #endif
  718.                 }
  719.                 Free(pdtCopy);
  720.             }
  721.         }
  722.     }
  723.     return hwndPage;
  724. }
  725. //  End of legacy crap
  726. //
  727. //===========================================================================
  728. //
  729. //  AllocPropertySheetPage
  730. //
  731. //  Allocate the memory into which we will dump a property sheet page.
  732. //
  733. //  Nothing is actually copied into the buffer.  The only thing interesting
  734. //  is that the external HPROPSHEETPAGE is set up on the assumption that
  735. //  we will not require a shadow.
  736. //
  737. //  We assume that we are allocating the memory for a non-shadow page.
  738. //
  739. PISP AllocPropertySheetPage(DWORD dwClientSize)
  740. {
  741.     PISP pisp;
  742.     LPBYTE pbAlloc;
  743.     //
  744.     //  An ISP consists of the "above" part, the "below" part, and
  745.     //  the baggage passed by the app.  Negative baggage is okay;
  746.     //  it means we have a down-level app that doesn't know about
  747.     //  pszHeaderTitle.
  748.     //
  749.     pbAlloc = LocalAlloc(LPTR, sizeof(pisp->above) + sizeof(pisp->below) +
  750.                                (dwClientSize - sizeof(PROPSHEETPAGE)));
  751.     if (!pbAlloc)
  752.         return NULL;
  753.     pisp = (PISP)(pbAlloc + sizeof(pisp->above));
  754. #ifdef UNICODE
  755.     //
  756.     // Set up the CLASSICPREFIX fields.
  757.     //
  758.     pisp->_cpfx.pispMain = pisp;
  759.     ASSERT(pisp->_cpfx.pispShadow == NULL);
  760. #endif
  761.     //
  762.     //  Assume no shadow - The app gets the PISP itself.
  763.     //
  764.     pisp->_pfx.hpage = (HPROPSHEETPAGE)pisp;
  765.     return pisp;
  766. }
  767. #ifdef UNICODE
  768. //
  769. //  Helper function during page creation.  The incoming string is really
  770. //  an ANSI string.  Thunk it to UNICODE.  Fortunately, we already have
  771. //  another helper function that does the work.
  772. //
  773. STDAPI_(LPTSTR) StrDup_AtoW(LPCTSTR ptsz)
  774. {
  775.     return ProduceWFromA(CP_ACP, (LPCSTR)ptsz);
  776. }
  777. #endif
  778. //
  779. //  CreatePropertySheetPage
  780. //
  781. //  Where HPROPSHEETPAGEs come from.
  782. //
  783. //  The fNeedShadow parameter means "The incoming LPCPROPSHEETPAGE is in the
  784. //  opposite character set from what you implement natively".
  785. //
  786. //  If we are compiling UNICODE, then fNeedShadow is TRUE if the incoming
  787. //  LPCPROPSHEETPAGE is really an ANSI property sheet page.
  788. //
  789. //  If we are compiling ANSI-only, then fNeedShadow is always FALSE because
  790. //  we don't support UNICODE in the ANSI-only version.
  791. //
  792. #ifdef UNICODE
  793. HPROPSHEETPAGE WINAPI _CreatePropertySheetPage(LPCPROPSHEETPAGE psp, BOOL fNeedShadow, BOOL fWx86)
  794. #else
  795. HPROPSHEETPAGE WINAPI CreatePropertySheetPage(LPCPROPSHEETPAGE psp)
  796. #define fNeedShadow FALSE
  797. #endif
  798. {
  799.     PISP pisp;
  800.     DWORD dwSize;
  801.     ASSERT(PROPSHEETPAGEA_V1_SIZE == PROPSHEETPAGEW_V1_SIZE);
  802.     ASSERT(sizeof(PROPSHEETPAGEA) == sizeof(PROPSHEETPAGEW));
  803.     if ((psp->dwSize < MINPROPSHEETPAGESIZE) ||
  804. #ifndef MAINWIN                                         // because of diff. in MAX_PATH 
  805.         (psp->dwSize > 4096) ||                         // or the second version     
  806. #endif
  807.         (psp->dwFlags & ~PSP_ALL))                      // bogus flag used
  808.         return NULL;
  809.     //
  810.     // The PROPSHEETPAGE structure can be larger than the
  811.     // defined size.  This allows ISV's to place private
  812.     // data at the end of the structure.  The ISP structure
  813.     // consists of some private fields and a PROPSHEETPAGE
  814.     // structure.  Calculate the size of the private fields,
  815.     // and then add in the dwSize field to determine the
  816.     // amount of memory necessary.
  817.     //
  818.     //
  819.     //  An ISP consists of the "above" part, the "below" part, and
  820.     //  the baggage passed by the app.  Negative baggage is okay;
  821.     //  it means we have a down-level app that doesn't know about
  822.     //  pszHeaderTitle.
  823.     //
  824.     //
  825.     //  If we have an "other" client, then the native side of the
  826.     //  property sheet doesn't carry any baggage.  It's just a
  827.     //  plain old PROPSHEETPAGE.
  828.     //
  829.     dwSize = fNeedShadow ? sizeof(PROPSHEETPAGE) : psp->dwSize;
  830.     pisp = AllocPropertySheetPage(dwSize);
  831.     if (pisp)
  832.     {
  833.         STRDUPPROC pfnStrDup;
  834. #ifdef WX86
  835.         //
  836.         //  We we're being called by Wx86, set the flag so we remember.
  837.         //
  838.         if ( fWx86 ) {
  839.             pisp->_pfx.dwInternalFlags |= PSPI_WX86;
  840.         }
  841. #endif
  842.         //
  843.         // Bulk copy the contents of the PROPSHEETPAGE, or
  844.         // as much of it as the app gave us.
  845.         //
  846.         hmemcpy(&pisp->_psp, psp, min(dwSize, psp->dwSize));
  847.         //
  848.         // Decide how to copy the strings
  849.         //
  850. #ifdef UNICODE
  851.         if (fNeedShadow)
  852.             pfnStrDup = StrDup_AtoW;
  853.         else
  854. #endif
  855.             pfnStrDup = StrDup;
  856.         // Now copy them
  857.         if (!CopyPropertyPageStrings(&pisp->_psp, pfnStrDup))
  858.             goto ExitStrings;
  859. #ifdef UNICODE
  860.         if (fNeedShadow)
  861.         {
  862.             PISP pispAnsi = AllocPropertySheetPage(psp->dwSize);
  863.             if (!pispAnsi)
  864.                 goto ExitShadow;
  865.             //
  866.             //  Copy the entire client PROPSHEETPAGE, including the
  867.             //  baggage.
  868.             //
  869.             hmemcpy(&pispAnsi->_psp, psp, psp->dwSize);
  870.             //
  871.             //  Hook the two copies to point to each other.
  872.             //
  873.             pisp->_cpfx.pispShadow = pispAnsi;
  874.             pispAnsi->_cpfx.pispShadow = pispAnsi;
  875.             pispAnsi->_cpfx.pispMain = pisp;
  876.             //
  877.             //  If there is a shadow, then the
  878.             //  external handle is the ANSI shadow.
  879.             //
  880.             ASSERT(pispAnsi->_pfx.hpage == (HPROPSHEETPAGE)pispAnsi);
  881.             pisp->_pfx.hpage = (HPROPSHEETPAGE)pispAnsi;
  882.             //
  883.             //  Okay, now StrDupA them strings.
  884.             //
  885.             if (!CopyPropertyPageStrings(&pispAnsi->_psp, (STRDUPPROC)StrDupA))
  886.                 goto ExitShadowStrings;
  887.         }
  888. #endif
  889.         //
  890.         // Increment the reference count to the parent object.
  891.         //
  892.         if (HASREFPARENT(pisp))
  893.             InterlockedIncrement((LPLONG)pisp->_psp.pcRefParent);
  894.         //
  895.         //  Welcome to the world.
  896.         //
  897.         CallPropertyPageCallback(pisp, PSPCB_ADDREF);
  898.         return ExternalizeHPROPSHEETPAGE(pisp);
  899.     }
  900.     else
  901.     {
  902.         return NULL;
  903.     }
  904. #ifdef UNICODE
  905. ExitShadowStrings:
  906.     FreePropertyPageStrings(&pisp->_cpfx.pispShadow->_psp);
  907.     FreePropertyPageStruct(pisp->_cpfx.pispShadow);
  908. ExitShadow:;
  909. #endif
  910. ExitStrings:
  911.     FreePropertyPageStrings(&pisp->_psp);
  912.     FreePropertyPageStruct(pisp);
  913.     return NULL;
  914. }
  915. #undef fNeedShadow
  916. #ifdef UNICODE
  917. HPROPSHEETPAGE WINAPI CreatePropertySheetPageW(LPCPROPSHEETPAGEW psp)
  918. {
  919.     BOOL fWx86 = FALSE;
  920. #ifdef WX86
  921.     fWx86 = Wx86IsCallThunked();
  922. #endif
  923.     return _CreatePropertySheetPage(psp, FALSE, fWx86);
  924. }
  925. HPROPSHEETPAGE WINAPI CreatePropertySheetPageA(LPCPROPSHEETPAGEA psp)
  926. {
  927.     BOOL fWx86 = FALSE;
  928. #ifdef WX86
  929.     fWx86 = Wx86IsCallThunked();
  930. #endif
  931.     return _CreatePropertySheetPage((LPCPROPSHEETPAGE)psp, TRUE, fWx86);
  932. }
  933. #else
  934. HPROPSHEETPAGE WINAPI CreatePropertySheetPageW(LPCPROPSHEETPAGEW psp)
  935. {
  936.     SetLastErrorEx(ERROR_CALL_NOT_IMPLEMENTED, SLE_WARNING);
  937.     return NULL;
  938. }
  939. #endif
  940. #ifdef UNICODE
  941. // HACK FOR HIJAAK 95!
  942. //
  943. // These hosebags were either stupid or evil.  Instead of creating
  944. // property sheet pages with CreatePropertySheetPage, they merely
  945. // take a pointer to a PROPSHEETPAGE structure and cast it to
  946. // HPROPSHEETPAGE.  They got away with this on Win95 because Win95's
  947. // HPROPSHEETPAGE actually was 95% identical to a PROPSHEETPAGE.
  948. // (The missing 5% causes RIPs at property sheet destruction, which
  949. // Hijaak no doubt ignored.)
  950. //
  951. // On NT and IE5, this coincidence is not true.
  952. //
  953. // So validate that what we have is really a property sheet
  954. // structure by checking if it's on the heap at the
  955. // right place.  If not, then make one.
  956. //
  957. HPROPSHEETPAGE WINAPI _Hijaak95Hack(LPPROPDATA ppd, HPROPSHEETPAGE hpage)
  958. {
  959.     if (hpage && !LocalSize(PropSheetBase(hpage))) {
  960.         // SLACKERS!  Have to call CreatePropertySheetPage for them
  961.         RIPMSG(0, "App passed HPROPSHEETPAGE not created by us; trying to cope");
  962.         hpage = _CreatePropertySheetPage((LPCPROPSHEETPAGE)hpage,
  963.                                          ppd->fFlags & PD_NEEDSHADOW,
  964.                                          ppd->fFlags & PD_WX86);
  965.     }
  966.     return hpage;
  967. }
  968. #endif
  969. #if 0
  970. extern BOOL WINAPI GetPageInfo16(HPROPSHEETPAGE16 hpage, LPTSTR pszCaption, int cbCaption, LPPOINT ppt, HICON FAR * phIcon, BOOL FAR* bRTL);
  971. extern BOOL WINAPI GetPageInfo16ME(HPROPSHEETPAGE16 hpage, LPTSTR pszCaption, int cbCaption, LPPOINT ppt, HICON FAR * phIcon, BOOL FAR* bRTL)
  972. {
  973.     return GetPageInfo16(hpage, pszCaption, cbCaption, ppt, phIcon, bRTL);
  974. }
  975. #endif