Source code of Windows XP (NT5)
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.

1134 lines
34 KiB

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