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.

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