|
|
#include "ctlspriv.h"
#include "prshti.h"
#ifdef WX86
#include <wx86ofl.h>
#endif
#include <pshpack2.h>
typedef struct { WORD wDlgVer; WORD wSignature; DWORD dwHelpID; DWORD dwExStyle; DWORD dwStyle; WORD cDlgItems; WORD x; WORD y; WORD cx; WORD cy; } DLGEXTEMPLATE, *LPDLGEXTEMPLATE;
#include <poppack.h> /* Resume normal packing */
//
// CallPropertyPageCallback
//
// Call the callback for the property page, passing it the correct lParam
// based on the character set it wants.
//
UINT CallPropertyPageCallback(PROPDATA* ppd, PISP pisp, UINT uMsg) { UINT uiResult = TRUE; // assume success
if (HASCALLBACK(pisp) && (pisp->_psp.dwSize > PROPSHEETPAGE_V1_SIZE || uMsg == PSPCB_CREATE || uMsg == PSPCB_RELEASE)) { ULONG_PTR dwCookie = PropPageActivateContext(ppd, pisp);
if (HASANSISHADOW(pisp)) { #ifdef WX86
if ( pisp->_pfx.dwInternalFlags & PSPI_WX86 ) uiResult = Wx86Callback(pisp->_psp.pfnCallback, NULL, uMsg, (LPARAM) &pisp->_cpfx.pispShadow->_psp); else #endif
uiResult = pisp->_psp.pfnCallback(NULL, uMsg, &pisp->_cpfx.pispShadow->_psp); } else { #ifdef WX86
if ( pisp->_pfx.dwInternalFlags & PSPI_WX86 ) uiResult = Wx86Callback(pisp->_psp.pfnCallback, NULL, uMsg, (LPARAM) &pisp->_psp); else #endif
uiResult = pisp->_psp.pfnCallback(NULL, uMsg, &pisp->_psp); }
PropPageDeactivateContext(dwCookie);
} return uiResult; }
//
// FreePropertyPageStruct
//
// Free the memory block that contains a property sheet page.
// It is the caller's responsibility to have freed all the things
// that were attached to it.
//
//
__inline void FreePropertyPageStruct(PISP pisp) { LocalFree(PropSheetBase(pisp)); }
//
// DestroyPropertySheetPage
//
// Do the appropriate thing to destroy a property sheet page, whether
// this entails talking to 16-bit thunks, sending the PSPCB_RELEASE,
// or freeing the shadow page.
//
BOOL WINAPI DestroyPropertySheetPage(HPROPSHEETPAGE hpage) { PISP pisp = InternalizeHPROPSHEETPAGE(hpage);
CallPropertyPageCallback(NULL, pisp, PSPCB_RELEASE);
// Do the decrement *after* calling the callback for the last time
if (HASREFPARENT(pisp)) { ASSERT( 0 != *pisp->_psp.pcRefParent ); InterlockedDecrement((LPLONG)pisp->_psp.pcRefParent); }
if (HASANSISHADOW(pisp)) { FreePropertyPageStrings(&pisp->_cpfx.pispShadow->_psp); FreePropertyPageStruct(pisp->_cpfx.pispShadow); }
//
// Note that FreePropertyPageStrings will try to destroy strings for
// proxy pages, but that's okay, because the corresponding P_pszBlah
// fields are all NULL since we never initialized them.
//
FreePropertyPageStrings(&pisp->_psp); FreePropertyPageStruct(pisp);
return TRUE; }
//
// GetPageInfoEx
//
// Extract information about a page into a PAGEINFOEX structure.
//
// WARNING! EVIL HORRIBLE RESTRICTION!
//
// You are allowed to pass GPI_ICON only once per page.
//
BOOL WINAPI GetPageInfoEx(LPPROPDATA ppd, PISP pisp, PAGEINFOEX *ppi, LANGID langidMUI, DWORD flags) { HRSRC hRes; LPDLGTEMPLATE pDlgTemplate; LPDLGEXTEMPLATE pDlgExTemplate; BOOL bResult = FALSE; HGLOBAL hDlgTemplate = 0; BOOL bSetFont; LPBYTE pszT;
//
// Init the output structure.
//
ZeroMemory(ppi, SIZEOF(PAGEINFOEX));
#ifdef DEBUG
// Enforce the GPI_ICON rule.
if (flags & GPI_ICON) { ASSERT(!(pisp->_pfx.dwInternalFlags & PSPI_FETCHEDICON)); pisp->_pfx.dwInternalFlags |= PSPI_FETCHEDICON; }
// For compatibility with 16-bit stuff, you are only allowed to
// pass these combinations of flags.
switch (LOWORD(flags)) { case GPI_PT | GPI_ICON | GPI_FONT | GPI_BRTL | GPI_CAPTION: break; case GPI_PT | GPI_ICON | GPI_BRTL | GPI_CAPTION: break; case GPI_DIALOGEX: break; default: ASSERT(!"Invalid flags passed to GetPageInfoEx"); break; } #endif
if (flags & GPI_ICON) { if (pisp->_psp.dwFlags & PSP_USEHICON) ppi->hIcon = pisp->_psp.P_hIcon; else if (pisp->_psp.dwFlags & PSP_USEICONID) ppi->hIcon = LoadImage(pisp->_psp.hInstance, pisp->_psp.P_pszIcon, IMAGE_ICON, g_cxSmIcon, g_cySmIcon, LR_DEFAULTCOLOR); }
if (pisp->_psp.dwFlags & PSP_DLGINDIRECT) { pDlgTemplate = (LPDLGTEMPLATE)pisp->_psp.P_pResource; goto UseTemplate; }
// We also need to stash away the langid that we actually found
// so we can later determine if we have to do any ML stuff...
hRes = FindResourceExRetry(pisp->_psp.hInstance, RT_DIALOG, pisp->_psp.P_pszTemplate, langidMUI); if (hRes) { hDlgTemplate = LoadResource(pisp->_psp.hInstance, hRes); if (hDlgTemplate) { pDlgTemplate = (LPDLGTEMPLATE)LockResource(hDlgTemplate); UseTemplate: if (pDlgTemplate) { pDlgExTemplate = (LPDLGEXTEMPLATE) pDlgTemplate; //
// Get the width and the height in dialog units.
//
if (pDlgExTemplate->wSignature == 0xFFFF) { // DIALOGEX structure
ppi->bDialogEx = TRUE; ppi->dwStyle = pDlgExTemplate->dwStyle; ppi->pt.x = pDlgExTemplate->cx; ppi->pt.y = pDlgExTemplate->cy; // Get the RTL reading order for the caption
ppi->bRTL = (((pDlgExTemplate->dwExStyle) & WS_EX_RTLREADING) || (pisp->_psp.dwFlags & PSP_RTLREADING)) ? TRUE : FALSE; ppi->bMirrored = ((pDlgExTemplate->dwExStyle) & (RTL_MIRRORED_WINDOW)) ? TRUE : FALSE;
} else { ppi->dwStyle = pDlgTemplate->style; ppi->pt.x = pDlgTemplate->cx; ppi->pt.y = pDlgTemplate->cy; ppi->bRTL = (pisp->_psp.dwFlags & PSP_RTLREADING) ? TRUE : FALSE; }
bResult = TRUE;
if (flags & (GPI_CAPTION | GPI_FONT)) { if (pisp->_psp.dwFlags & PSP_USETITLE) { if (IS_INTRESOURCE(pisp->_psp.pszTitle)) { CCLoadStringExInternal(pisp->_psp.hInstance, (UINT)LOWORD(pisp->_psp.pszTitle), ppi->szCaption, ARRAYSIZE(ppi->szCaption), langidMUI); } else { // Copy pszTitle
StringCchCopy(ppi->szCaption, ARRAYSIZE(ppi->szCaption), pisp->_psp.pszTitle); } }
// ML UI support for NT5
// Grab the font face and size in point from page so that
// we can calculate size of page in real screen pixel
// This is for NT5 MLUI but should not be any harm for Win95
// or even works better for the platform.
// 1. check if the page has font specified
if ( ppi->bDialogEx ) bSetFont = ((pDlgExTemplate->dwStyle & DS_SETFONT) != 0); else bSetFont = ((pDlgTemplate->style & DS_SETFONT) != 0);
// 2. Skip until after class name
// only if either font is set or we want title
//
if (bSetFont || !(pisp->_psp.dwFlags & PSP_USETITLE)) { // Get the caption string from the dialog template, only
//
if (ppi->bDialogEx) pszT = (BYTE *) (pDlgExTemplate + 1); else pszT = (BYTE *) (pDlgTemplate + 1);
// The menu name is either 0xffff followed by a word,
// or a string.
switch (*(LPWORD)pszT) { case 0xffff: pszT += 2 * sizeof(WORD); break;
default: pszT += (lstrlenW((LPTSTR)pszT) + 1) * sizeof(WCHAR); break; } //
// Now we are pointing at the class name.
//
pszT += (lstrlenW((LPTSTR)pszT) + 1) * sizeof(WCHAR); }
// 3. grab the title from template if PSP_USETITLE isn't set
//
if (!(pisp->_psp.dwFlags & PSP_USETITLE)) { StringCchCopy(ppi->szCaption, ARRAYSIZE(ppi->szCaption), (LPTSTR)pszT); }
// 4. grab the point size and face name if DS_SETFONT
//
if (bSetFont && (flags & GPI_FONT)) { // skip the title string
pszT += (lstrlenW((LPTSTR)pszT)+1) * sizeof(WCHAR); ppi->pfd.PointSize = *((short *)pszT)++; if (ppi->bDialogEx) { ((short *)pszT)++; // skip weight as we always use FW_NORMAL w/ DS_3DLOOK
ppi->pfd.bItalic = *(BYTE *)pszT++; ppi->pfd.iCharset = *(BYTE *)pszT++; } else { ppi->pfd.bItalic = FALSE; ppi->pfd.iCharset = DEFAULT_CHARSET; }
StringCchCopy(ppi->pfd.szFace, ARRAYSIZE(ppi->pfd.szFace), (LPTSTR)pszT);
// But if this is a SHELLFONT page and the font name is "MS Shell Dlg",
// then its font secretly gets morphed into MS Shell Dlg 2 (if
// all the other pages agree)... The wackiness continues...
if (staticIsOS(OS_WIN2000ORGREATER) && (ppd->fFlags & PD_SHELLFONT) && IsPageInfoSHELLFONT(ppi) && lstrcmpi(ppi->pfd.szFace, TEXT("MS Shell Dlg")) == 0) { StringCchCopy(ppi->pfd.szFace, ARRAYSIZE(ppi->pfd.szFace), TEXT("MS Shell Dlg 2")); } //
// USER quirk #2: If the font height is 0x7FFF, then
// USER really uses the MessageBox font and no font
// information is stored in the dialog template.
// Win95's dialog template converter doesn't support
// this, so we won't either.
} }
if (pisp->_psp.dwFlags & PSP_DLGINDIRECT) return bResult;
UnlockResource(hDlgTemplate); } FreeResource(hDlgTemplate); } } else { DebugMsg(DM_ERROR, TEXT("GetPageInfo - ERROR: FindResource() failed")); } return bResult; }
//
// Helper function that edits a dialog template in preparation for it
// becoming a property sheet page. This has been split out because
// the legacy CreatePage function needs to do this, too.
//
// Returns the place where the style was edited on success, or
// NULL if we took an exception while editing the template.
//
// The old style is returned in pdwSaveStyle so it can be replaced later.
//
LPDWORD EditPropSheetTemplate( LPDLGTEMPLATE pDlgTemplate, LPDWORD pdwSaveStyle, BOOL fFlags) // PD_*
{ DWORD lSaveStyle; DWORD dwNewStyle; LPDWORD pdwStyle; LPDLGEXTEMPLATE pDlgExTemplate = (LPDLGEXTEMPLATE) pDlgTemplate;
try { //
// We need to save the SETFONT, LOCALEDIT, and CLIPCHILDREN
// flags.
//
if (pDlgExTemplate->wSignature == 0xFFFF) { pdwStyle = &pDlgExTemplate->dwStyle; } else { pdwStyle = &pDlgTemplate->style; }
lSaveStyle = *pdwStyle; *pdwSaveStyle = lSaveStyle;
dwNewStyle = (lSaveStyle & (DS_SHELLFONT | DS_LOCALEDIT | WS_CLIPCHILDREN)) | WS_CHILD | WS_TABSTOP | DS_3DLOOK | DS_CONTROL;
// If SHELLFONT has been turned off and this page uses it, then turn
// it off.
if (!(fFlags & PD_SHELLFONT) && (dwNewStyle & DS_SHELLFONT) == DS_SHELLFONT) dwNewStyle &= ~DS_FIXEDSYS; // Leave DS_USEFONT but lose FIXEDSYS
*pdwStyle = dwNewStyle;
} except (UnhandledExceptionFilter( GetExceptionInformation() )) { return NULL; } __endexcept
return pdwStyle; }
void RethunkShadowStrings(PISP pisp) { //
// Note: Old code recomputed the entire UNICODE PROPSHEETHEADER
// from the ANSI shadow at certain points, in case
// the app edited the ANSI shadow.
//
// So we do it too. I need to ask Eric Flo why we did it in the
// first place. Note that the algorithm is buggy - if the app
// edited any of the string fields (or any of the flags that
// gate the string fields), we both leak the original memory
// *and* fault when we try to free something that wasn't
// allocated via LocalAlloc. We preserve the bug to be compatible
// with NT4. (Snicker.)
//
DWORD dwSize = min(sizeof(PROPSHEETPAGE), pisp->_cpfx.pispShadow->_psp.dwSize); dwSize = min(dwSize, GETORIGINALSIZE(pisp));
FreePropertyPageStrings(&pisp->_psp); hmemcpy(&pisp->_psp, &pisp->_cpfx.pispShadow->_psp, dwSize); //
// If this copy fails, we will carry on with happy NULL strings.
// So some strings are empty, boo-hoo.
//
EVAL(CopyPropertyPageStrings(&pisp->_psp, StrDup_AtoW)); }
ULONG_PTR PropPageActivateContext(LPPROPDATA ppd, PISP pisp) { ULONG_PTR dwCookie = 0; // Activate the fusion context if available for this page.
if (pisp && pisp->_psp.dwFlags & PSP_USEFUSIONCONTEXT && pisp->_psp.dwSize > PROPSHEETPAGE_V2_SIZE && pisp->_psp.hActCtx) { ActivateActCtx(pisp->_psp.hActCtx, &dwCookie); } else if (ppd) { ActivateActCtx(ppd->hActCtxInit, &dwCookie); }
return dwCookie; }
void PropPageDeactivateContext(ULONG_PTR dw) { if (dw) DeactivateActCtx(0, dw); }
//
// This function creates a dialog box from the specified dialog template
// with appropriate style flags.
//
HWND _CreatePageDialog(LPPROPDATA ppd, PISP pisp, HWND hwndParent, LPDLGTEMPLATE pDlgTemplate) { HWND hwndPage; LPARAM lParam; LPDWORD pdwStyle; DWORD lSaveStyle; ULONG_PTR dwCookie = 0;
DLGPROC pfnDlgProc;
pdwStyle = EditPropSheetTemplate(pDlgTemplate, &lSaveStyle, ppd->fFlags);
if (!pdwStyle) // error editing template
return NULL;
//
// Thunk the Dialog proc if we were created by x86 code on RISC.
//
#ifdef WX86
if (pisp->_pfx.dwInternalFlags & PSPI_WX86) { pfnDlgProc = Wx86ThunkProc( pisp->_psp.pfnDlgProc, (PVOID) 4, TRUE );
if (pfnDlgProc == NULL) return NULL; } else #endif
pfnDlgProc = pisp->_psp.pfnDlgProc;
//
// Decide what to pass as the lParam to the CreateDialogIndirectParam.
//
//
// If the caller was ANSI, then use the ANSI PROPSHEETPAGE.
//
if (HASANSISHADOW(pisp)) { lParam = (LPARAM) &pisp->_cpfx.pispShadow->_psp; }
else if (pisp->_psp.dwFlags & PSP_SHPAGE) { //
// PSP_SHPAGE is a special flag used by pre-IE5 shell32 only.
// See prshti.h for gory details. If we get this far, it means
// that we need to pass the CLASSICPREFIX instead of the
// PROPSHEETPAGE.
//
lParam = (LPARAM)&pisp->_cpfx; } else { //
// Normal UNICODE caller gets the UNICODE PROPSHEETPAGE.
//
lParam = (LPARAM)&pisp->_psp; }
//
// All set - go create it.
//
dwCookie = PropPageActivateContext(ppd, pisp);
if (HASANSISHADOW(pisp)) { hwndPage = CreateDialogIndirectParamA( pisp->_psp.hInstance, (LPCDLGTEMPLATE)pDlgTemplate, hwndParent, pfnDlgProc, lParam); RethunkShadowStrings(pisp); } else { hwndPage = SHNoFusionCreateDialogIndirectParam( pisp->_psp.hInstance, (LPCDLGTEMPLATE)pDlgTemplate, hwndParent, pfnDlgProc, lParam); }
// Don't set the theme me style if it's a wizard page. The wizards have their own overrides that conflict
// with the theme manager
if (!((ppd->psh).dwFlags & (PSH_WIZARD | PSH_WIZARD97 | PSH_WIZARD_LITE))) { EnableThemeDialogTexture(hwndPage, ETDT_USETABTEXTURE); }
PropPageDeactivateContext(dwCookie);
//
// Restore the original dialog template style.
//
try { MwWriteDWORD((LPBYTE)pdwStyle, lSaveStyle); } except (UnhandledExceptionFilter( GetExceptionInformation() )) {
if (hwndPage) { DestroyWindow(hwndPage); } return NULL; } __endexcept
return hwndPage; }
HWND _CreatePage(LPPROPDATA ppd, PISP pisp, HWND hwndParent, LANGID langidMUI) { HWND hwndPage = NULL; // NULL indicates an error
if (!CallPropertyPageCallback(ppd, pisp, PSPCB_CREATE)) { return NULL; }
if (HASANSISHADOW(pisp)) { RethunkShadowStrings(pisp); }
if (pisp->_psp.dwFlags & PSP_DLGINDIRECT) { hwndPage=_CreatePageDialog(ppd, pisp, hwndParent, (LPDLGTEMPLATE)pisp->_psp.P_pResource); } else { HRSRC hRes; hRes = FindResourceExRetry(pisp->_psp.hInstance, RT_DIALOG, pisp->_psp.P_pszTemplate, langidMUI); if (hRes) { HGLOBAL hDlgTemplate; hDlgTemplate = LoadResource(pisp->_psp.hInstance, hRes); if (hDlgTemplate) { const DLGTEMPLATE * pDlgTemplate; pDlgTemplate = (LPDLGTEMPLATE)LockResource(hDlgTemplate); if (pDlgTemplate) { ULONG cbTemplate=SizeofResource(pisp->_psp.hInstance, hRes); LPDLGTEMPLATE pdtCopy = (LPDLGTEMPLATE)Alloc(cbTemplate);
ASSERT(cbTemplate>=sizeof(DLGTEMPLATE));
if (pdtCopy) { hmemcpy(pdtCopy, pDlgTemplate, cbTemplate); hwndPage=_CreatePageDialog(ppd, pisp, hwndParent, pdtCopy); Free(pdtCopy); }
UnlockResource(hDlgTemplate); } FreeResource(hDlgTemplate); } } }
return hwndPage; }
//===========================================================================
//
// Legacy
//
// CreatePage is an internal entry point used by shell32 prior to NT5/IE5.
//
// Win95's shell32 passes a PROPSHEETPAGEA.
//
// WinNT's shell32 passes a CLASSICPREFIX + PROPSHEETPAGEW.
//
// The kicker is that shell32 really doesn't need any property sheet page
// features. It's just too lazy to do some dialog style editing.
//
//
HWND WINAPI CreatePage(LPVOID hpage, HWND hwndParent) { HWND hwndPage = NULL; // NULL indicates an error
HRSRC hrsrc; LPPROPSHEETPAGE ppsp;
//
// Move from the CLASSICPREFIX to the PROPSHEETHEADER.
//
ppsp = &CONTAINING_RECORD(hpage, ISP, _cpfx)->_psp;
// Docfind2.c never passed these flags, so we don't need to implement them.
ASSERT(!(ppsp->dwFlags & (PSP_USECALLBACK | PSP_IS16 | PSP_DLGINDIRECT)));
hrsrc = FindResourceW(ppsp->hInstance, ppsp->P_pszTemplate, RT_DIALOG);
if (hrsrc) { LPCDLGTEMPLATE pDlgTemplate = LoadResource(ppsp->hInstance, hrsrc); if (pDlgTemplate) { //
// Make a copy of the template so we can edit it.
//
DWORD cbTemplate = SizeofResource(ppsp->hInstance, hrsrc); LPDLGTEMPLATE pdtCopy = (LPDLGTEMPLATE)Alloc(cbTemplate);
ASSERT(cbTemplate>=sizeof(DLGTEMPLATE));
if (pdtCopy) { DWORD dwScratch;
hmemcpy(pdtCopy, pDlgTemplate, cbTemplate); if (EditPropSheetTemplate(pdtCopy, &dwScratch, PD_SHELLFONT)) {
hwndPage = CreateDialogIndirectParamW( ppsp->hInstance, pdtCopy, hwndParent, ppsp->pfnDlgProc, (LPARAM)hpage); } Free(pdtCopy); } } }
return hwndPage; }
// End of legacy
//
//===========================================================================
//
// AllocPropertySheetPage
//
// Allocate the memory into which we will dump a property sheet page.
//
// Nothing is actually copied into the buffer. The only thing interesting
// is that the external HPROPSHEETPAGE is set up on the assumption that
// we will not require a shadow.
//
// We assume that we are allocating the memory for a non-shadow page.
//
PISP AllocPropertySheetPage(DWORD dwClientSize) { PISP pisp; LPBYTE pbAlloc;
//
// An ISP consists of the "above" part, the "below" part, and
// the baggage passed by the app. Negative baggage is okay;
// it means we have a down-level app that doesn't know about
// pszHeaderTitle.
//
pbAlloc = LocalAlloc(LPTR, sizeof(pisp->above) + sizeof(pisp->below) + (dwClientSize - sizeof(PROPSHEETPAGE)));
if (!pbAlloc) return NULL;
pisp = (PISP)(pbAlloc + sizeof(pisp->above));
//
// Set up the CLASSICPREFIX fields.
//
pisp->_cpfx.pispMain = pisp; ASSERT(pisp->_cpfx.pispShadow == NULL);
//
// Assume no shadow - The app gets the PISP itself.
//
pisp->_pfx.hpage = (HPROPSHEETPAGE)pisp;
return pisp; }
//
// Helper function during page creation. The incoming string is really
// an ANSI string. Thunk it to UNICODE. Fortunately, we already have
// another helper function that does the work.
//
STDAPI_(LPTSTR) StrDup_AtoW(LPCTSTR ptsz) { return ProduceWFromA(CP_ACP, (LPCSTR)ptsz); }
//
// CreatePropertySheetPage
//
// Where HPROPSHEETPAGEs come from.
//
// The fNeedShadow parameter means "The incoming LPCPROPSHEETPAGE is in the
// opposite character set from what you implement natively".
//
// If we are compiling UNICODE, then fNeedShadow is TRUE if the incoming
// LPCPROPSHEETPAGE is really an ANSI property sheet page.
//
// If we are compiling ANSI-only, then fNeedShadow is always FALSE because
// we don't support UNICODE in the ANSI-only version.
//
HPROPSHEETPAGE WINAPI _CreatePropertySheetPage(LPCPROPSHEETPAGE psp, BOOL fNeedShadow, BOOL fWx86) { PISP pisp; DWORD dwSize;
COMPILETIME_ASSERT(PROPSHEETPAGEA_V1_SIZE == PROPSHEETPAGEW_V1_SIZE); COMPILETIME_ASSERT(sizeof(PROPSHEETPAGEA) == sizeof(PROPSHEETPAGEW));
if ((psp->dwSize < MINPROPSHEETPAGESIZE) || (psp->dwSize > 4096) || // or the second version
(psp->dwFlags & ~PSP_ALL)) // bogus flag used
{ return NULL; }
//
// The PROPSHEETPAGE structure can be larger than the
// defined size. This allows ISV's to place private
// data at the end of the structure. The ISP structure
// consists of some private fields and a PROPSHEETPAGE
// structure. Calculate the size of the private fields,
// and then add in the dwSize field to determine the
// amount of memory necessary.
//
//
// An ISP consists of the "above" part, the "below" part, and
// the baggage passed by the app. Negative baggage is okay;
// it means we have a down-level app that doesn't know about
// pszHeaderTitle.
//
//
// If we have an "other" client, then the native side of the
// property sheet doesn't carry any baggage. It's just a
// plain old PROPSHEETPAGE.
//
dwSize = fNeedShadow ? sizeof(PROPSHEETPAGE) : psp->dwSize; pisp = AllocPropertySheetPage(dwSize);
if (pisp) { STRDUPPROC pfnStrDup;
#ifdef WX86
//
// We we're being called by Wx86, set the flag so we remember.
//
if ( fWx86 ) { pisp->_pfx.dwInternalFlags |= PSPI_WX86; } #endif
SETORIGINALSIZE(pisp, dwSize);
//
// Bulk copy the contents of the PROPSHEETPAGE, or
// as much of it as the app gave us.
//
hmemcpy(&pisp->_psp, psp, min(dwSize, psp->dwSize));
//
// Decide how to copy the strings
//
if (fNeedShadow) pfnStrDup = StrDup_AtoW; else pfnStrDup = StrDup;
// Now copy them
if (!CopyPropertyPageStrings(&pisp->_psp, pfnStrDup)) goto ExitStrings;
if (fNeedShadow) { PISP pispAnsi = AllocPropertySheetPage(psp->dwSize); if (!pispAnsi) goto ExitShadow;
//
// Copy the entire client PROPSHEETPAGE, including the
// baggage.
//
hmemcpy(&pispAnsi->_psp, psp, psp->dwSize);
//
// Hook the two copies to point to each other.
//
pisp->_cpfx.pispShadow = pispAnsi; pispAnsi->_cpfx.pispShadow = pispAnsi; pispAnsi->_cpfx.pispMain = pisp;
//
// If there is a shadow, then the
// external handle is the ANSI shadow.
//
ASSERT(pispAnsi->_pfx.hpage == (HPROPSHEETPAGE)pispAnsi); pisp->_pfx.hpage = (HPROPSHEETPAGE)pispAnsi;
//
// Okay, now StrDupA them strings.
//
if (!CopyPropertyPageStrings(&pispAnsi->_psp, (STRDUPPROC)StrDupA)) goto ExitShadowStrings; }
//
// Increment the reference count to the parent object.
//
if (HASREFPARENT(pisp)) InterlockedIncrement((LPLONG)pisp->_psp.pcRefParent);
//
// Welcome to the world.
//
CallPropertyPageCallback(NULL, pisp, PSPCB_ADDREF); // don't need because there is no hwnd
return ExternalizeHPROPSHEETPAGE(pisp); } else { return NULL; }
ExitShadowStrings: FreePropertyPageStrings(&pisp->_cpfx.pispShadow->_psp); FreePropertyPageStruct(pisp->_cpfx.pispShadow); ExitShadow:; ExitStrings: FreePropertyPageStrings(&pisp->_psp); FreePropertyPageStruct(pisp); return NULL; }
HPROPSHEETPAGE WINAPI CreatePropertySheetPageW(LPCPROPSHEETPAGEW psp) { BOOL fWx86 = FALSE;
#ifdef WX86
fWx86 = Wx86IsCallThunked(); #endif
return _CreatePropertySheetPage(psp, FALSE, fWx86); }
HPROPSHEETPAGE WINAPI CreatePropertySheetPageA(LPCPROPSHEETPAGEA psp) { BOOL fWx86 = FALSE;
#ifdef WX86
fWx86 = Wx86IsCallThunked(); #endif
return _CreatePropertySheetPage((LPCPROPSHEETPAGE)psp, TRUE, fWx86); }
|