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.

928 lines
29 KiB

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