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.

3640 lines
115 KiB

  1. #include "priv.h"
  2. #include "resource.h"
  3. #include "mshtmcid.h"
  4. #include <mluisupp.h>
  5. #ifndef X_IEHELPID_H_
  6. #define X_IEHELPID_H_
  7. #include "iehelpid.h"
  8. #endif
  9. #include "dhuihand.h"
  10. #define DM_DOCHOSTUIHANDLER 0
  11. #define CX_CONTEXTMENUOFFSET 2
  12. #define CY_CONTEXTMENUOFFSET 2
  13. //+------------------------------------------------------------------------
  14. //
  15. // WARNING! (greglett)
  16. //
  17. // The following defines were stolen from commdlg.h. Since SHDOCVW is
  18. // compiled with WINVER=0x0400 and these defines are WINVER=0x0500 they
  19. // needed to be copied and included here. These must be kept in sync
  20. // with the commdlg.h definitions.
  21. //
  22. // If shdocvw ever gets compiled with WINVER=0x0500 or above, then these
  23. // can be removed.
  24. //
  25. //-------------------------------------------------------------------------
  26. #define NEED_BECAUSE_COMPILED_AT_WINVER_4
  27. #ifdef NEED_BECAUSE_COMPILED_AT_WINVER_4
  28. //
  29. // Define the start page for the print dialog when using PrintDlgEx.
  30. //
  31. #define START_PAGE_GENERAL 0xffffffff
  32. //
  33. // Page Range structure for PrintDlgEx.
  34. //
  35. typedef struct tagPRINTPAGERANGE {
  36. DWORD nFromPage;
  37. DWORD nToPage;
  38. } PRINTPAGERANGE, *LPPRINTPAGERANGE;
  39. //
  40. // PrintDlgEx structure.
  41. //
  42. typedef struct tagPDEXA {
  43. DWORD lStructSize; // size of structure in bytes
  44. HWND hwndOwner; // caller's window handle
  45. HGLOBAL hDevMode; // handle to DevMode
  46. HGLOBAL hDevNames; // handle to DevNames
  47. HDC hDC; // printer DC/IC or NULL
  48. DWORD Flags; // PD_ flags
  49. DWORD Flags2; // reserved
  50. DWORD ExclusionFlags; // items to exclude from driver pages
  51. DWORD nPageRanges; // number of page ranges
  52. DWORD nMaxPageRanges; // max number of page ranges
  53. LPPRINTPAGERANGE lpPageRanges; // array of page ranges
  54. DWORD nMinPage; // min page number
  55. DWORD nMaxPage; // max page number
  56. DWORD nCopies; // number of copies
  57. HINSTANCE hInstance; // instance handle
  58. LPCSTR lpPrintTemplateName; // template name for app specific area
  59. LPUNKNOWN lpCallback; // app callback interface
  60. DWORD nPropertyPages; // number of app property pages in lphPropertyPages
  61. HPROPSHEETPAGE *lphPropertyPages; // array of app property page handles
  62. DWORD nStartPage; // start page id
  63. DWORD dwResultAction; // result action if S_OK is returned
  64. } PRINTDLGEXA, *LPPRINTDLGEXA;
  65. //
  66. // PrintDlgEx structure.
  67. //
  68. typedef struct tagPDEXW {
  69. DWORD lStructSize; // size of structure in bytes
  70. HWND hwndOwner; // caller's window handle
  71. HGLOBAL hDevMode; // handle to DevMode
  72. HGLOBAL hDevNames; // handle to DevNames
  73. HDC hDC; // printer DC/IC or NULL
  74. DWORD Flags; // PD_ flags
  75. DWORD Flags2; // reserved
  76. DWORD ExclusionFlags; // items to exclude from driver pages
  77. DWORD nPageRanges; // number of page ranges
  78. DWORD nMaxPageRanges; // max number of page ranges
  79. LPPRINTPAGERANGE lpPageRanges; // array of page ranges
  80. DWORD nMinPage; // min page number
  81. DWORD nMaxPage; // max page number
  82. DWORD nCopies; // number of copies
  83. HINSTANCE hInstance; // instance handle
  84. LPCWSTR lpPrintTemplateName; // template name for app specific area
  85. LPUNKNOWN lpCallback; // app callback interface
  86. DWORD nPropertyPages; // number of app property pages in lphPropertyPages
  87. HPROPSHEETPAGE *lphPropertyPages; // array of app property page handles
  88. DWORD nStartPage; // start page id
  89. DWORD dwResultAction; // result action if S_OK is returned
  90. } PRINTDLGEXW, *LPPRINTDLGEXW;
  91. #ifdef UNICODE
  92. typedef PRINTDLGEXW PRINTDLGEX;
  93. typedef LPPRINTDLGEXW LPPRINTDLGEX;
  94. #else
  95. typedef PRINTDLGEXA PRINTDLGEX;
  96. typedef LPPRINTDLGEXA LPPRINTDLGEX;
  97. #endif // UNICODE
  98. HRESULT APIENTRY PrintDlgExA(LPPRINTDLGEXA);
  99. HRESULT APIENTRY PrintDlgExW(LPPRINTDLGEXW);
  100. #ifdef UNICODE
  101. #define PrintDlgEx PrintDlgExW
  102. #else
  103. #define PrintDlgEx PrintDlgExA
  104. #endif // !UNICODE
  105. //
  106. // Result action ids for PrintDlgEx.
  107. //
  108. #define PD_RESULT_CANCEL 0
  109. #define PD_RESULT_PRINT 1
  110. #define PD_RESULT_APPLY 2
  111. #define PD_CURRENTPAGE 0x00400000
  112. #define PD_NOCURRENTPAGE 0x00800000
  113. #endif // NEED_BECAUSE_COMPILED_AT_WINVER_4
  114. //+------------------------------------------------------------------------
  115. //
  116. // Useful combinations of flags for IOleCommandTarget
  117. //
  118. //-------------------------------------------------------------------------
  119. #define OLECMDSTATE_DISABLED OLECMDF_SUPPORTED
  120. #define OLECMDSTATE_UP (OLECMDF_SUPPORTED | OLECMDF_ENABLED)
  121. #define OLECMDSTATE_DOWN (OLECMDF_SUPPORTED | OLECMDF_ENABLED | OLECMDF_LATCHED)
  122. #define OLECMDSTATE_NINCHED (OLECMDF_SUPPORTED | OLECMDF_ENABLED | OLECMDF_NINCHED)
  123. struct SExpandoInfo
  124. {
  125. TCHAR * name;
  126. VARTYPE type;
  127. };
  128. // Enumerations for custom expandos
  129. enum MessageEnum
  130. {
  131. MessageText,
  132. MessageCaption,
  133. MessageStyle,
  134. MessageHelpFile,
  135. MessageHelpContext
  136. };
  137. enum PagesetupEnum
  138. {
  139. PagesetupHeader,
  140. PagesetupFooter,
  141. PagesetupStruct
  142. };
  143. enum PrintEnum
  144. {
  145. PrintfRootDocumentHasFrameset,
  146. PrintfAreRatingsEnabled,
  147. PrintfPrintActiveFrame,
  148. PrintfPrintLinked,
  149. PrintfPrintSelection,
  150. PrintfPrintAsShown,
  151. PrintfShortcutTable,
  152. PrintiFontScaling,
  153. PrintpBodyActiveTarget,
  154. PrintStruct,
  155. PrintToFileOk,
  156. PrintToFileName,
  157. PrintfPrintActiveFrameEnabled,
  158. };
  159. enum PropertysheetEnum
  160. {
  161. PropertysheetPunks
  162. };
  163. //----------------------------------------------------------------------------
  164. //
  165. // Arrays describing helpcontextids for PageSetup/Print
  166. //
  167. //----------------------------------------------------------------------------
  168. static const DWORD aPrintDialogHelpIDs[] =
  169. {
  170. stc6, IDH_PRINT_CHOOSE_PRINTER,
  171. cmb4, IDH_PRINT_CHOOSE_PRINTER,
  172. psh2, IDH_PRINT_PROPERTIES,
  173. stc7, IDH_PRINT_SETUP_DETAILS,
  174. stc8, IDH_PRINT_SETUP_DETAILS,
  175. stc9, IDH_PRINT_SETUP_DETAILS,
  176. stc10, IDH_PRINT_SETUP_DETAILS,
  177. stc12, IDH_PRINT_SETUP_DETAILS,
  178. stc11, IDH_PRINT_SETUP_DETAILS,
  179. stc14, IDH_PRINT_SETUP_DETAILS,
  180. stc13, IDH_PRINT_SETUP_DETAILS,
  181. stc5, IDH_PRINT_TO_FILE,
  182. chx1, IDH_PRINT_TO_FILE,
  183. ico3, IDH_PRINT_COLLATE,
  184. chx2, IDH_PRINT_COLLATE,
  185. grp1, IDH_PRINT_RANGE,
  186. rad1, IDH_PRINT_RANGE, // all
  187. rad2, IDH_PRINT_RANGE, // selection
  188. rad3, IDH_PRINT_RANGE, // pages
  189. stc2, IDH_PRINT_RANGE,
  190. stc3, IDH_PRINT_RANGE,
  191. edt1, IDH_PRINT_RANGE,
  192. edt2, IDH_PRINT_RANGE,
  193. edt3, IDH_PRINT_COPIES,
  194. rad4, IDH_PRINT_SCREEN,
  195. rad5, IDH_PRINT_SEL_FRAME,
  196. rad6, IDH_PRINT_ALL_FRAME,
  197. IDC_LINKED, IDH_PRINT_LINKS,
  198. IDC_SHORTCUTS, IDH_PRINT_SHORTCUTS,
  199. 0, 0
  200. };
  201. static const DWORD aPageSetupDialogHelpIDs[] =
  202. {
  203. psh3, IDH_PRINT_PRINTER_SETUP,
  204. stc2, IDH_PAGE_PAPER_SIZE,
  205. cmb2, IDH_PAGE_PAPER_SIZE,
  206. stc3, IDH_PAGE_PAPER_SOURCE,
  207. cmb3, IDH_PAGE_PAPER_SOURCE,
  208. rad1, IDH_PAGE_ORIENTATION,
  209. rad2, IDH_PAGE_ORIENTATION,
  210. stc15, IDH_PAGE_MARGINS,
  211. edt4, IDH_PAGE_MARGINS,
  212. stc16, IDH_PAGE_MARGINS,
  213. edt5, IDH_PAGE_MARGINS,
  214. stc17, IDH_PAGE_MARGINS,
  215. edt6, IDH_PAGE_MARGINS,
  216. stc18, IDH_PAGE_MARGINS,
  217. edt7, IDH_PAGE_MARGINS,
  218. IDC_EDITHEADER, IDH_PAGESETUP_HEADER_LEFT,
  219. IDC_STATICHEADER, IDH_PAGESETUP_HEADER_LEFT,
  220. IDC_EDITFOOTER, IDH_PAGESETUP_HEADER_LEFT,
  221. IDC_STATICFOOTER, IDH_PAGESETUP_HEADER_LEFT,
  222. IDC_HEADERFOOTER, IDH_PAGESETUP_HEADER_LEFT,
  223. 0, 0
  224. };
  225. //+---------------------------------------------------------------------------
  226. //
  227. // Function: GetControlID
  228. //
  229. // Synopsis:
  230. //
  231. // Arguments: HWND - passed window handle of WM_CONTEXTMENU
  232. // lParam - passed coordinates (lParam) of WM_CONTEXTMENU
  233. //
  234. // Returns: int - ctrlid
  235. //
  236. //
  237. //----------------------------------------------------------------------------
  238. int GetControlID(HWND hwnd, LPARAM lParam)
  239. {
  240. int CtrlID;
  241. CtrlID = GetDlgCtrlID(hwnd);
  242. if (CtrlID==0)
  243. {
  244. POINT pt;
  245. pt.x = GET_X_LPARAM(lParam);
  246. pt.y = GET_Y_LPARAM(lParam);
  247. if (ScreenToClient(hwnd, &pt))
  248. {
  249. HWND hwndChild = ChildWindowFromPointEx(hwnd, pt, CWP_ALL);
  250. if (hwndChild)
  251. {
  252. CtrlID = GetDlgCtrlID(hwndChild);
  253. }
  254. }
  255. }
  256. return CtrlID;
  257. }
  258. //+---------------------------------------------------------------------------
  259. //
  260. // Function: GetHelpFile
  261. //
  262. // Synopsis:
  263. //
  264. // Arguments: iCtrlID - id of the control
  265. // adw - array of DWORDS, consisting of controlid,helpid pairs
  266. //
  267. // Returns: A string with the name of the helpfile
  268. //
  269. // Notes: Help topics for the print dialogs can be either in iexplore.hlp
  270. // or in windows.hlp. We key off the helpid to determine which
  271. // file to go to.
  272. //
  273. //----------------------------------------------------------------------------
  274. LPTSTR
  275. GetHelpFile(int iCtrlID, DWORD * adw)
  276. {
  277. ASSERT (adw);
  278. while (TRUE)
  279. {
  280. int ctrlid = int(*adw);
  281. int helpid = int(*(adw + 1));
  282. if (ctrlid == 0 && helpid == 0)
  283. {
  284. break;
  285. }
  286. if (ctrlid == iCtrlID)
  287. {
  288. //TraceTag((tagContextHelp, "for ctrl=%d, topic=%d", ctrlid, helpid));
  289. return (helpid < 50000) ? TEXT("windows.hlp") : TEXT("iexplore.hlp");
  290. }
  291. adw += 2;
  292. }
  293. return TEXT("windows.hlp");
  294. }
  295. GetInterfaceFromClientSite(IUnknown *pUnk, REFIID riid, void ** ppv)
  296. {
  297. HRESULT hr;
  298. IOleObject * pOleObject = NULL;
  299. IOleClientSite * pOleClientSite = NULL;
  300. if (!pUnk || !ppv)
  301. {
  302. hr = E_INVALIDARG;
  303. goto Cleanup;
  304. }
  305. *ppv = NULL;
  306. hr = pUnk->QueryInterface(IID_PPV_ARG(IOleObject, &pOleObject));
  307. if (hr)
  308. goto Cleanup;
  309. hr = pOleObject->GetClientSite(&pOleClientSite);
  310. if (pOleClientSite == NULL)
  311. {
  312. hr = E_FAIL;
  313. }
  314. if (hr)
  315. goto Cleanup;
  316. hr = pOleClientSite->QueryInterface(riid, ppv);
  317. Cleanup:
  318. ATOMICRELEASE(pOleClientSite);
  319. ATOMICRELEASE(pOleObject);
  320. return hr;
  321. }
  322. //
  323. // Get the IOleInPlaceFrame if available. If this proves useful, move this somewhere interesting.
  324. //
  325. HRESULT GetInPlaceFrameFromUnknown(IUnknown * punk, IOleInPlaceFrame ** ppOleInPlaceFrame)
  326. {
  327. IOleInPlaceSite * pOleInPlaceSite = NULL;
  328. IOleInPlaceUIWindow * pOleInPlaceUIWindow = NULL;
  329. RECT rcPos, rcClip;
  330. OLEINPLACEFRAMEINFO frameInfo = {0};
  331. HRESULT hr = GetInterfaceFromClientSite(punk, IID_PPV_ARG(IOleInPlaceSite, &pOleInPlaceSite));
  332. if (S_OK != hr)
  333. goto Cleanup;
  334. *ppOleInPlaceFrame = NULL;
  335. frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
  336. hr = pOleInPlaceSite->GetWindowContext(ppOleInPlaceFrame,
  337. &pOleInPlaceUIWindow,
  338. &rcPos,
  339. &rcClip,
  340. &frameInfo);
  341. Cleanup:
  342. ATOMICRELEASE(pOleInPlaceUIWindow);
  343. ATOMICRELEASE(pOleInPlaceSite);
  344. return hr;
  345. }
  346. HRESULT
  347. GetHwndFromUnknown(
  348. IUnknown * punk,
  349. HWND * phwnd)
  350. {
  351. HRESULT hr;
  352. IOleInPlaceFrame * pOleInPlaceFrame = NULL;
  353. ASSERT(punk);
  354. ASSERT(phwnd);
  355. if (phwnd)
  356. {
  357. *phwnd = NULL;
  358. }
  359. if (!punk || !phwnd)
  360. {
  361. hr = E_INVALIDARG;
  362. goto Cleanup;
  363. }
  364. hr = GetInPlaceFrameFromUnknown(punk, &pOleInPlaceFrame);
  365. if (S_OK != hr)
  366. goto Cleanup;
  367. hr = pOleInPlaceFrame->GetWindow(phwnd);
  368. if (S_OK != hr)
  369. goto Cleanup;
  370. Cleanup:
  371. ATOMICRELEASE(pOleInPlaceFrame);
  372. return hr;
  373. }
  374. HRESULT
  375. GetEventFromUnknown(
  376. IUnknown * punk,
  377. IHTMLEventObj ** ppEventObj)
  378. {
  379. HRESULT hr;
  380. IHTMLDocument2 * pOmDoc = NULL;
  381. IHTMLWindow2 * pOmWindow = NULL;
  382. ASSERT(punk);
  383. ASSERT(ppEventObj);
  384. if (ppEventObj)
  385. *ppEventObj = NULL;
  386. if (!punk || !ppEventObj)
  387. {
  388. hr = E_INVALIDARG;
  389. goto Cleanup;
  390. }
  391. hr = punk->QueryInterface(IID_PPV_ARG(IHTMLDocument2, &pOmDoc));
  392. if (S_OK != hr)
  393. goto Cleanup;
  394. hr = pOmDoc->get_parentWindow(&pOmWindow);
  395. if (S_OK != hr)
  396. goto Cleanup;
  397. hr = pOmWindow->get_event(ppEventObj);
  398. if (S_OK != hr)
  399. goto Cleanup;
  400. Cleanup:
  401. ATOMICRELEASE(pOmDoc);
  402. ATOMICRELEASE(pOmWindow);
  403. return hr;
  404. }
  405. //
  406. // Gets the dispids/variants from the event.
  407. //
  408. HRESULT
  409. GetParamsFromEvent(
  410. IHTMLEventObj * pEventObj,
  411. unsigned int cExpandos,
  412. DISPID aDispid[],
  413. VARIANT aVariant[],
  414. const SExpandoInfo aExpandos[])
  415. {
  416. HRESULT hr;
  417. IDispatchEx * pDispatchEx = NULL;
  418. unsigned int i;
  419. ASSERT(pEventObj);
  420. ASSERT(aVariant);
  421. ASSERT(aExpandos);
  422. // ASSERT(cExpandos >= 0); // cExpandos is an unsigned int, so this is always true
  423. // deleted "|| cExpandos < 0" from below test
  424. // since unsigned ints are never negative
  425. if (!pEventObj || !aVariant || !aExpandos)
  426. {
  427. hr = E_INVALIDARG;
  428. goto Cleanup;
  429. }
  430. for (i=0; i<cExpandos; i++)
  431. {
  432. VariantInit(aVariant+i);
  433. aDispid[i] = DISPID_UNKNOWN;
  434. }
  435. hr = pEventObj->QueryInterface(IID_PPV_ARG(IDispatchEx, &pDispatchEx));
  436. if (S_OK != hr)
  437. goto Cleanup;
  438. for (i=0; i<cExpandos; i++)
  439. {
  440. hr = pDispatchEx->GetDispID(
  441. aExpandos[i].name,
  442. fdexNameCaseSensitive,
  443. aDispid+i);
  444. if (S_OK != hr)
  445. goto Cleanup;
  446. hr = pDispatchEx->InvokeEx(
  447. aDispid[i],
  448. LOCALE_USER_DEFAULT,
  449. DISPATCH_PROPERTYGET,
  450. (DISPPARAMS *)&g_dispparamsNoArgs,
  451. aVariant+i,
  452. NULL,
  453. NULL);
  454. // Check the variant types match
  455. ASSERT( V_VT(aVariant+i) == aExpandos[i].type
  456. || V_VT(aVariant+i) == VT_EMPTY);
  457. if (S_OK != hr)
  458. goto Cleanup;
  459. }
  460. Cleanup:
  461. ATOMICRELEASE(pDispatchEx);
  462. return hr;
  463. }
  464. HRESULT
  465. PutParamToEvent(DISPID dispid, VARIANT * var, IHTMLEventObj * pEventObj)
  466. {
  467. HRESULT hr;
  468. IDispatchEx * pDispatchEx = NULL;
  469. DISPPARAMS dispparams = {var, &dispid, 1, 1};
  470. ASSERT(var);
  471. ASSERT(pEventObj);
  472. if (!var || !pEventObj)
  473. {
  474. hr = E_INVALIDARG;
  475. goto Cleanup;
  476. }
  477. hr = pEventObj->QueryInterface(IID_PPV_ARG(IDispatchEx, &pDispatchEx));
  478. if (S_OK != hr)
  479. goto Cleanup;
  480. hr = pDispatchEx->InvokeEx(
  481. dispid,
  482. LOCALE_USER_DEFAULT,
  483. DISPATCH_PROPERTYPUT,
  484. &dispparams,
  485. NULL,
  486. NULL,
  487. NULL);
  488. if (S_OK != hr)
  489. goto Cleanup;
  490. Cleanup:
  491. ATOMICRELEASE(pDispatchEx);
  492. return hr;
  493. }
  494. void PutFindText(IWebBrowser2* pwb, LPCWSTR pwszFindText)
  495. {
  496. BSTR bstrName = SysAllocString(STR_FIND_DIALOG_TEXT);
  497. if (NULL != bstrName)
  498. {
  499. VARIANT var = {VT_EMPTY};
  500. if (NULL != pwszFindText)
  501. {
  502. var.vt = VT_BSTR;
  503. var.bstrVal = SysAllocString(pwszFindText);
  504. }
  505. if ((VT_EMPTY == var.vt) || (NULL != var.bstrVal))
  506. {
  507. pwb->PutProperty(bstrName, var);
  508. }
  509. SysFreeString(var.bstrVal);
  510. SysFreeString(bstrName);
  511. }
  512. }
  513. BSTR GetFindText(IWebBrowser2* pwb)
  514. {
  515. BSTR bstrName = SysAllocString(STR_FIND_DIALOG_TEXT);
  516. VARIANT var = {0};
  517. if (bstrName)
  518. {
  519. ASSERT(pwb);
  520. pwb->GetProperty(bstrName, &var);
  521. SysFreeString(bstrName);
  522. }
  523. BSTR bstrResult;
  524. if (VT_BSTR == var.vt)
  525. {
  526. bstrResult = var.bstrVal;
  527. }
  528. else
  529. {
  530. bstrResult = NULL;
  531. VariantClear(&var);
  532. }
  533. return bstrResult;
  534. }
  535. CDocHostUIHandler::CDocHostUIHandler(void) : m_cRef(1)
  536. {
  537. DllAddRef();
  538. m_cPreviewIsUp = 0;
  539. }
  540. CDocHostUIHandler::~CDocHostUIHandler(void)
  541. {
  542. ATOMICRELEASE(_punkSite);
  543. //
  544. // We don't addref _pExternal to avoid an addref/release cycle. So, we can't release it.
  545. //
  546. // ATOMICRELEASE(_pExternal);
  547. ATOMICRELEASE(_pOptionsHolder);
  548. if (_hBrowseMenu)
  549. DestroyMenu(_hBrowseMenu);
  550. if (_hEditMenu)
  551. DestroyMenu(_hEditMenu);
  552. DllRelease();
  553. }
  554. STDMETHODIMP CDocHostUIHandler::QueryInterface(REFIID riid, PVOID *ppvObj)
  555. {
  556. static const QITAB qit[] = {
  557. QITABENT(CDocHostUIHandler, IDocHostUIHandler),
  558. QITABENT(CDocHostUIHandler, IObjectWithSite),
  559. QITABENT(CDocHostUIHandler, IOleCommandTarget),
  560. QITABENT(CDocHostUIHandler, IDispatch),
  561. { 0 },
  562. };
  563. return QISearch(this, qit, riid, ppvObj);
  564. }
  565. STDMETHODIMP_(ULONG) CDocHostUIHandler::AddRef()
  566. {
  567. return InterlockedIncrement(&m_cRef);
  568. }
  569. STDMETHODIMP_(ULONG) CDocHostUIHandler::Release()
  570. {
  571. ASSERT(0 != m_cRef);
  572. ULONG cRef = InterlockedDecrement(&m_cRef);
  573. if (0 == cRef)
  574. {
  575. delete this;
  576. }
  577. return cRef;
  578. }
  579. HRESULT CDocHostUIHandler::SetSite(IUnknown *punkSite)
  580. {
  581. ATOMICRELEASE(_punkSite);
  582. ASSERT(_punkSite == NULL); // don't lose a reference to this
  583. _punkSite = punkSite;
  584. if (_punkSite)
  585. {
  586. _punkSite->AddRef();
  587. }
  588. // Always return S_OK
  589. //
  590. return S_OK;
  591. }
  592. HRESULT CDocHostUIHandler::GetSite(REFIID riid, void **ppvSite)
  593. {
  594. if (_punkSite)
  595. return _punkSite->QueryInterface(riid, ppvSite);
  596. *ppvSite = NULL;
  597. return E_FAIL;
  598. }
  599. //==========================================================================
  600. // IDocHostUIHandler implementation
  601. //==========================================================================
  602. HRESULT CDocHostUIHandler::ShowContextMenu(DWORD dwID, POINT *ppt, IUnknown *pcmdtReserved, IDispatch *pdispReserved)
  603. {
  604. HRESULT hr = S_FALSE;
  605. HCURSOR hcursor;
  606. HMENU hMenu = NULL;
  607. VARIANT var, var1, var2;
  608. VARIANT * pvar = NULL;
  609. int iSelection = 0;
  610. HWND hwnd = NULL;
  611. IOleCommandTarget * pOleCommandTarget = NULL;
  612. IOleWindow * pOleWindow = NULL;
  613. IOleInPlaceFrame * pOleInPlaceFrame = NULL;
  614. IDocHostUIHandler * pUIHandler = NULL;
  615. MENUITEMINFO mii = {0};
  616. int i;
  617. OLECMD olecmd;
  618. UINT mf;
  619. BOOL fDeletePrint = FALSE;
  620. BOOL fDeleteSetDesktopItem = FALSE;
  621. BOOL fDeleteViewSource = FALSE;
  622. IHTMLImgElement * pImgEle = NULL;
  623. TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::ShowContextMenu called");
  624. //If restriction is set, we lie to Mshtml that context menu has been set.
  625. if (SHRestricted2W(REST_NoBrowserContextMenu, NULL, 0))
  626. return S_OK;
  627. // Do a proper QI for IOleCommandTarget
  628. //
  629. hr = pcmdtReserved->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pOleCommandTarget));
  630. if (S_OK != hr)
  631. goto Cleanup;
  632. // Check if we are in browse mode
  633. //
  634. olecmd.cmdID = IDM_BROWSEMODE;
  635. hr = pOleCommandTarget->QueryStatus(&CGID_MSHTML, 1, &olecmd, NULL);
  636. if (S_OK != hr)
  637. goto Cleanup;
  638. if (olecmd.cmdf == OLECMDSTATE_DOWN)
  639. {
  640. if (!_hBrowseMenu)
  641. _hBrowseMenu = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(IDR_BROWSE_CONTEXT_MENU));
  642. hMenu = _hBrowseMenu;
  643. }
  644. // Check if we are in edit mode
  645. else
  646. {
  647. olecmd.cmdID = IDM_EDITMODE;
  648. hr = pOleCommandTarget->QueryStatus(&CGID_MSHTML, 1, &olecmd, NULL);
  649. if (S_OK != hr)
  650. goto Cleanup;
  651. if (olecmd.cmdf == OLECMDSTATE_DOWN)
  652. {
  653. if (!_hEditMenu)
  654. _hEditMenu = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(IDR_FORM_CONTEXT_MENU));
  655. hMenu = _hEditMenu;
  656. }
  657. // Neither Browse nor Edit flags were set
  658. else
  659. {
  660. ASSERT(false);
  661. goto Cleanup;
  662. }
  663. }
  664. if (!hMenu)
  665. goto Cleanup;
  666. //
  667. // check through all the submenus and remove any sets of items which
  668. // need to be removed
  669. //
  670. fDeletePrint = SHRestricted2(REST_NoPrinting, NULL, 0);
  671. fDeleteSetDesktopItem = (WhichPlatform() != PLATFORM_INTEGRATED);
  672. fDeleteViewSource = SHRestricted2(REST_NoViewSource, NULL, 0);
  673. if (fDeletePrint || fDeleteSetDesktopItem || fDeleteViewSource)
  674. {
  675. int iSubMenuIndex;
  676. for (iSubMenuIndex = 0; iSubMenuIndex < GetMenuItemCount(hMenu); iSubMenuIndex++)
  677. {
  678. HMENU hSubMenu = GetSubMenu(hMenu, iSubMenuIndex);
  679. if (hSubMenu)
  680. {
  681. if (fDeletePrint)
  682. {
  683. DeleteMenu(hSubMenu, IDM_PRINT, MF_BYCOMMAND);
  684. }
  685. if (fDeleteSetDesktopItem)
  686. {
  687. DeleteMenu(hSubMenu, IDM_SETDESKTOPITEM, MF_BYCOMMAND);
  688. }
  689. if (fDeleteViewSource)
  690. {
  691. DeleteMenu(hSubMenu, IDM_VIEWSOURCE, MF_BYCOMMAND);
  692. }
  693. }
  694. }
  695. }
  696. // Make sure we are running mshtml debug build if we are loading debug window
  697. if (dwID == CONTEXT_MENU_DEBUG)
  698. {
  699. olecmd.cmdID = IDM_DEBUG_TRACETAGS;
  700. hr = pOleCommandTarget->QueryStatus(&CGID_MSHTML, 1, &olecmd, NULL);
  701. if (olecmd.cmdf != OLECMDSTATE_UP)
  702. goto Cleanup;
  703. }
  704. // Select the appropriate submenu based on the passed in ID
  705. hMenu = GetSubMenu(hMenu, dwID);
  706. if (!hMenu)
  707. goto Cleanup;
  708. // Loop through and QueryStatus the menu items.
  709. //
  710. for (i = 0; i < GetMenuItemCount(hMenu); i++)
  711. {
  712. olecmd.cmdID = GetMenuItemID(hMenu, i);
  713. if (olecmd.cmdID > 0)
  714. {
  715. pOleCommandTarget->QueryStatus(
  716. &CGID_MSHTML,
  717. 1,
  718. &olecmd,
  719. NULL);
  720. switch (olecmd.cmdf)
  721. {
  722. case OLECMDSTATE_UP:
  723. case OLECMDSTATE_NINCHED:
  724. mf = MF_BYCOMMAND | MF_ENABLED | MF_UNCHECKED;
  725. break;
  726. case OLECMDSTATE_DOWN:
  727. mf = MF_BYCOMMAND | MF_ENABLED | MF_CHECKED;
  728. break;
  729. case OLECMDSTATE_DISABLED:
  730. default:
  731. mf = MF_BYCOMMAND | MF_DISABLED | MF_GRAYED;
  732. break;
  733. }
  734. CheckMenuItem(hMenu, olecmd.cmdID, mf);
  735. EnableMenuItem(hMenu, olecmd.cmdID, mf);
  736. }
  737. }
  738. // Get the language submenu
  739. hr = pOleCommandTarget->Exec(&CGID_ShellDocView, SHDVID_GETMIMECSETMENU, 0, NULL, &var);
  740. if (S_OK != hr)
  741. goto Cleanup;
  742. mii.cbSize = sizeof(mii);
  743. mii.fMask = MIIM_SUBMENU;
  744. mii.hSubMenu = (HMENU) var.byref;
  745. SetMenuItemInfo(hMenu, IDM_LANGUAGE, FALSE, &mii);
  746. // Insert Context Menu
  747. V_VT(&var1) = VT_INT_PTR;
  748. V_BYREF(&var1) = hMenu;
  749. V_VT(&var2) = VT_I4;
  750. V_I4(&var2) = dwID;
  751. hr = pOleCommandTarget->Exec(&CGID_ShellDocView, SHDVID_ADDMENUEXTENSIONS, 0, &var1, &var2);
  752. if (S_OK != hr)
  753. goto Cleanup;
  754. // Get the window also.
  755. //
  756. if (SUCCEEDED(pcmdtReserved->QueryInterface(IID_PPV_ARG(IOleWindow, &pOleWindow))))
  757. {
  758. pOleWindow->GetWindow(&hwnd);
  759. }
  760. if (hwnd)
  761. {
  762. GetInterfaceFromClientSite(pcmdtReserved, IID_PPV_ARG(IDocHostUIHandler, &pUIHandler));
  763. if (pUIHandler)
  764. pUIHandler->EnableModeless(FALSE);
  765. GetInPlaceFrameFromUnknown(pcmdtReserved, &pOleInPlaceFrame);
  766. if (pOleInPlaceFrame)
  767. pOleInPlaceFrame->EnableModeless(FALSE);
  768. hcursor = SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)));
  769. // Display the menu. Pass in the HWND of our site object.
  770. //
  771. iSelection = ::TrackPopupMenu(
  772. hMenu,
  773. TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
  774. ppt->x + CX_CONTEXTMENUOFFSET,
  775. ppt->y + CY_CONTEXTMENUOFFSET,
  776. 0,
  777. hwnd,
  778. (RECT*)NULL);
  779. if (pUIHandler)
  780. pUIHandler->EnableModeless(TRUE);
  781. if (pOleInPlaceFrame)
  782. pOleInPlaceFrame->EnableModeless(TRUE);
  783. SetCursor(hcursor);
  784. }
  785. if (iSelection)
  786. {
  787. switch (iSelection)
  788. {
  789. case IDM_FOLLOWLINKN:
  790. // tell the top level browser to save its window size to the registry so
  791. // that our new window can pick it up and cascade properly
  792. IUnknown_Exec(_punkSite, &CGID_Explorer, SBCMDID_SUGGESTSAVEWINPOS, 0, NULL, NULL);
  793. // fall through
  794. case IDM_PROPERTIES:
  795. case IDM_FOLLOWLINKC:
  796. pvar = &var;
  797. V_VT(pvar) = VT_I4;
  798. V_I4(pvar) = MAKELONG(ppt->x, ppt->y);
  799. break;
  800. }
  801. pOleCommandTarget->Exec(&CGID_MSHTML, iSelection, 0, pvar, NULL);
  802. }
  803. {
  804. MENUITEMINFO mii2 = {0};
  805. mii2.cbSize = sizeof(mii);
  806. mii2.fMask = MIIM_SUBMENU;
  807. mii2.hSubMenu = NULL;
  808. SetMenuItemInfo(hMenu, IDM_LANGUAGE, FALSE, &mii2);
  809. }
  810. Cleanup:
  811. DestroyMenu(mii.hSubMenu);
  812. ATOMICRELEASE(pOleCommandTarget);
  813. ATOMICRELEASE(pOleWindow);
  814. ATOMICRELEASE(pOleInPlaceFrame);
  815. ATOMICRELEASE(pUIHandler);
  816. return hr;
  817. }
  818. HRESULT CDocHostUIHandler::GetHostInfo(DOCHOSTUIINFO *pInfo)
  819. {
  820. DWORD dwUrlEncodingDisableUTF8;
  821. DWORD dwSize = SIZEOF(dwUrlEncodingDisableUTF8);
  822. BOOL fDefault = FALSE;
  823. DWORD dwLoadf = 0;
  824. TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::GetHostInfo called");
  825. pInfo->cbSize = sizeof(DOCHOSTUIINFO);
  826. pInfo->dwFlags = DOCHOSTUIFLAG_BROWSER | DOCHOSTUIFLAG_ENABLE_INPLACE_NAVIGATION | DOCHOSTUIFLAG_IME_ENABLE_RECONVERSION;
  827. pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT; // default
  828. SHRegGetUSValue(REGSTR_PATH_INTERNET_SETTINGS,
  829. TEXT("UrlEncoding"), NULL, (LPBYTE) &dwUrlEncodingDisableUTF8, &dwSize, FALSE, (LPVOID) &fDefault, SIZEOF(fDefault));
  830. if (dwUrlEncodingDisableUTF8)
  831. pInfo->dwFlags |= DOCHOSTUIFLAG_URL_ENCODING_DISABLE_UTF8;
  832. else
  833. pInfo->dwFlags |= DOCHOSTUIFLAG_URL_ENCODING_ENABLE_UTF8;
  834. return S_OK;
  835. }
  836. HRESULT CDocHostUIHandler::ShowUI(
  837. DWORD dwID, IOleInPlaceActiveObject *pActiveObject,
  838. IOleCommandTarget *pCommandTarget, IOleInPlaceFrame *pFrame,
  839. IOleInPlaceUIWindow *pDoc)
  840. {
  841. TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::ShowUI called");
  842. // Host did not display its own UI. Trident will proceed to display its own.
  843. return S_FALSE;
  844. }
  845. HRESULT CDocHostUIHandler::HideUI(void)
  846. {
  847. TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::HideUI called");
  848. // This one is paired with ShowUI
  849. return S_FALSE;
  850. }
  851. HRESULT CDocHostUIHandler::UpdateUI(void)
  852. {
  853. TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::UpdateUI called");
  854. // LATER: Isn't this equivalent to OLECMDID_UPDATECOMMANDS?
  855. return S_FALSE;
  856. }
  857. HRESULT CDocHostUIHandler::EnableModeless(BOOL fEnable)
  858. {
  859. TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::EnableModeless called");
  860. // Called from the Trident when the equivalent member of its
  861. // IOleInPlaceActiveObject is called by the frame. We don't care
  862. // those cases.
  863. return S_OK;
  864. }
  865. HRESULT CDocHostUIHandler::OnDocWindowActivate(BOOL fActivate)
  866. {
  867. // Called from the Trident when the equivalent member of its
  868. // IOleInPlaceActiveObject is called by the frame. We don't care
  869. // those cases.
  870. return S_OK;
  871. }
  872. HRESULT CDocHostUIHandler::OnFrameWindowActivate(BOOL fActivate)
  873. {
  874. // Called from the Trident when the equivalent member of its
  875. // IOleInPlaceActiveObject is called by the frame. We don't care
  876. // those cases.
  877. return S_OK;
  878. }
  879. HRESULT CDocHostUIHandler::ResizeBorder(
  880. LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow)
  881. {
  882. // Called from the Trident when the equivalent member of its
  883. // IOleInPlaceActiveObject is called by the frame. We don't care
  884. // those cases.
  885. return S_OK;
  886. }
  887. HRESULT CDocHostUIHandler::TranslateAccelerator(
  888. LPMSG lpMsg, const GUID *pguidCmdGroup, DWORD nCmdID)
  889. {
  890. // Called from the Trident when the equivalent member of its
  891. // IOleInPlaceActiveObject is called by the frame. We don't care
  892. // those cases.
  893. return S_FALSE; // The message was not translated
  894. }
  895. HRESULT CDocHostUIHandler::GetOptionKeyPath(BSTR *pbstrKey, DWORD dw)
  896. {
  897. // Trident will default to its own user options.
  898. if (!pbstrKey)
  899. return E_POINTER;
  900. *pbstrKey = NULL;
  901. return S_FALSE;
  902. }
  903. HRESULT CDocHostUIHandler::GetDropTarget(IDropTarget *pDropTarget, IDropTarget **ppDropTarget)
  904. {
  905. TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::GetDropTarget called");
  906. return E_NOTIMPL;
  907. }
  908. HRESULT CDocHostUIHandler::GetAltExternal(IDispatch **ppDisp)
  909. {
  910. HRESULT hr = E_FAIL;
  911. IDocHostUIHandler *pDocHostUIHandler;
  912. IOleObject *pOleObject;
  913. IOleClientSite *pOleClientSite;
  914. *ppDisp = NULL;
  915. // * QI ourselves for a service provider
  916. // * QS for the top level browser's service provider
  917. // * Ask for an IOleObject
  918. // * Ask the IOleObject for an IOleClientSite
  919. // * QI the IOleClientSite for an IDocHostUIHandler
  920. // * Call GetExternal on the IDocHostUIHandler to get the IDispatch
  921. if (SUCCEEDED(IUnknown_QueryServiceForWebBrowserApp(_punkSite, IID_PPV_ARG(IOleObject, &pOleObject))))
  922. {
  923. if (SUCCEEDED(pOleObject->GetClientSite(&pOleClientSite)))
  924. {
  925. if (SUCCEEDED(pOleClientSite->QueryInterface(IID_PPV_ARG(IDocHostUIHandler, &pDocHostUIHandler))))
  926. {
  927. hr = pDocHostUIHandler->GetExternal(ppDisp);
  928. pDocHostUIHandler->Release();
  929. }
  930. pOleClientSite->Release();
  931. }
  932. pOleObject->Release();
  933. }
  934. return hr;
  935. }
  936. HRESULT CDocHostUIHandler::GetExternal(IDispatch **ppDisp)
  937. {
  938. TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::GetExternal called");
  939. HRESULT hr = S_OK;
  940. if (!ppDisp)
  941. {
  942. hr = E_INVALIDARG;
  943. goto Cleanup;
  944. }
  945. if (_pExternal)
  946. {
  947. *ppDisp = _pExternal;
  948. (*ppDisp)->AddRef();
  949. goto Cleanup;
  950. }
  951. IDispatch *psuihDisp;
  952. IDispatch *pAltExternalDisp;
  953. *ppDisp = NULL;
  954. GetAltExternal(&pAltExternalDisp);
  955. hr = CShellUIHelper_CreateInstance2((IUnknown **)&psuihDisp, IID_IDispatch, _punkSite, pAltExternalDisp);
  956. if (SUCCEEDED(hr))
  957. {
  958. *ppDisp = psuihDisp;
  959. _pExternal = *ppDisp;
  960. if (pAltExternalDisp)
  961. {
  962. // Don't hold a ref - the ShellUIHelper will do it
  963. pAltExternalDisp->Release();
  964. }
  965. }
  966. else if (pAltExternalDisp)
  967. {
  968. // Couldn't create a ShellUIHelper but we got our host's
  969. // external.
  970. *ppDisp = pAltExternalDisp;
  971. _pExternal = *ppDisp;
  972. }
  973. Cleanup:
  974. ASSERT((SUCCEEDED(hr) && (*ppDisp)) || (FAILED(hr)));
  975. return hr;
  976. }
  977. HRESULT CDocHostUIHandler::TranslateUrl(DWORD dwTranslate, OLECHAR *pchURLIn, OLECHAR **ppchURLOut)
  978. {
  979. TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::TranslateUrl called");
  980. return S_FALSE;
  981. }
  982. HRESULT CDocHostUIHandler::FilterDataObject(IDataObject *pDO, IDataObject **ppDORet)
  983. {
  984. TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::FilterDataObject called");
  985. return S_FALSE;
  986. }
  987. HRESULT CDocHostUIHandler::GetOverrideKeyPath(LPOLESTR *pchKey, DWORD dw)
  988. {
  989. TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::GetOverrideKeyPath called");
  990. return S_FALSE;
  991. }
  992. STDAPI CDocHostUIHandler_CreateInstance(IUnknown * punkOuter, IUnknown ** ppunk, LPCOBJECTINFO poi)
  993. {
  994. HRESULT hres = E_OUTOFMEMORY;
  995. CDocHostUIHandler *pis = new CDocHostUIHandler;
  996. if (pis)
  997. {
  998. *ppunk = SAFECAST(pis, IDocHostUIHandler *);
  999. hres = S_OK;
  1000. }
  1001. return hres;
  1002. }
  1003. //==========================================================================
  1004. // IOleCommandTarget implementation
  1005. //==========================================================================
  1006. HRESULT CDocHostUIHandler::QueryStatus(const GUID *pguidCmdGroup,
  1007. ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  1008. {
  1009. HRESULT hres = OLECMDERR_E_UNKNOWNGROUP;
  1010. if (IsEqualGUID(CGID_DocHostCommandHandler, *pguidCmdGroup))
  1011. {
  1012. ULONG i;
  1013. if (rgCmds == NULL)
  1014. return E_INVALIDARG;
  1015. for (i = 0 ; i < cCmds ; i++)
  1016. {
  1017. // ONLY say that we support the stuff we support in ::Exec
  1018. switch (rgCmds[i].cmdID)
  1019. {
  1020. case OLECMDID_SHOWSCRIPTERROR:
  1021. case OLECMDID_SHOWMESSAGE:
  1022. case OLECMDID_SHOWFIND:
  1023. case OLECMDID_SHOWPAGESETUP:
  1024. case OLECMDID_SHOWPRINT:
  1025. case OLECMDID_PRINTPREVIEW:
  1026. case OLECMDID_PRINT:
  1027. case OLECMDID_PROPERTIES:
  1028. case SHDVID_CLSIDTOMONIKER:
  1029. rgCmds[i].cmdf = OLECMDF_ENABLED;
  1030. break;
  1031. default:
  1032. rgCmds[i].cmdf = 0;
  1033. break;
  1034. }
  1035. }
  1036. hres = S_OK;
  1037. }
  1038. return hres;
  1039. }
  1040. HRESULT CDocHostUIHandler::Exec(const GUID *pguidCmdGroup,
  1041. DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  1042. {
  1043. if (IsEqualGUID(CGID_DocHostCommandHandler, *pguidCmdGroup))
  1044. {
  1045. switch (nCmdID)
  1046. {
  1047. case OLECMDID_SHOWSCRIPTERROR:
  1048. if (!pvarargIn || !pvarargOut)
  1049. return E_INVALIDARG;
  1050. ShowErrorDialog(pvarargIn, pvarargOut, nCmdexecopt);
  1051. return S_OK;
  1052. case OLECMDID_SHOWMESSAGE:
  1053. if (!pvarargIn || !pvarargOut)
  1054. return E_INVALIDARG;
  1055. else
  1056. return ShowMessage(pvarargIn, pvarargOut, nCmdexecopt);
  1057. case OLECMDID_SHOWFIND:
  1058. if (!pvarargIn)
  1059. return E_INVALIDARG;
  1060. ShowFindDialog(pvarargIn, pvarargOut, nCmdexecopt);
  1061. return S_OK;
  1062. case OLECMDID_SHOWPAGESETUP:
  1063. if (!pvarargIn)
  1064. return E_INVALIDARG;
  1065. else
  1066. return ShowPageSetupDialog(pvarargIn, pvarargOut, nCmdexecopt);
  1067. case IDM_TEMPLATE_PAGESETUP:
  1068. return DoTemplatePageSetup(pvarargIn);
  1069. case OLECMDID_SHOWPRINT:
  1070. if (!pvarargIn)
  1071. return E_INVALIDARG;
  1072. else
  1073. return ShowPrintDialog(pvarargIn, pvarargOut, nCmdexecopt);
  1074. case OLECMDID_PRINTPREVIEW:
  1075. if (!pvarargIn)
  1076. return E_INVALIDARG;
  1077. else
  1078. return DoTemplatePrinting(pvarargIn, pvarargOut, TRUE);
  1079. case OLECMDID_PRINT:
  1080. if (!pvarargIn)
  1081. return E_INVALIDARG;
  1082. else
  1083. return DoTemplatePrinting(pvarargIn, pvarargOut, FALSE);
  1084. case OLECMDID_REFRESH:
  1085. //if print preview is up, tell them we handled refresh
  1086. //to prevent Trident from refreshing.
  1087. if (m_cPreviewIsUp > 0)
  1088. return S_OK;
  1089. // else do default handling
  1090. break;
  1091. case OLECMDID_PROPERTIES:
  1092. if (!pvarargIn)
  1093. return E_INVALIDARG;
  1094. else
  1095. return ShowPropertysheetDialog(pvarargIn, pvarargOut, nCmdexecopt);
  1096. case SHDVID_CLSIDTOMONIKER:
  1097. if (!pvarargIn || !pvarargOut)
  1098. return E_INVALIDARG;
  1099. else
  1100. return ClsidToMoniker(pvarargIn, pvarargOut);
  1101. default:
  1102. return OLECMDERR_E_NOTSUPPORTED;
  1103. }
  1104. }
  1105. return OLECMDERR_E_UNKNOWNGROUP;
  1106. }
  1107. //+---------------------------------------------------------------------------
  1108. //
  1109. // Helper for OLECMDID_SHOWSCRIPTERROR
  1110. //
  1111. //+---------------------------------------------------------------------------
  1112. void CDocHostUIHandler::ShowErrorDialog(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD)
  1113. {
  1114. HRESULT hr;
  1115. HWND hwnd;
  1116. IHTMLEventObj * pEventObj = NULL;
  1117. IMoniker * pmk = NULL;
  1118. VARIANT varEventObj;
  1119. TCHAR szResURL[MAX_URL_STRING];
  1120. ASSERT(V_VT(pvarargIn) == VT_UNKNOWN);
  1121. hr = GetHwndFromUnknown(V_UNKNOWN(pvarargIn), &hwnd);
  1122. if (S_OK != hr)
  1123. goto Cleanup;
  1124. hr = GetEventFromUnknown(V_UNKNOWN(pvarargIn), &pEventObj);
  1125. if (S_OK != hr)
  1126. goto Cleanup;
  1127. hr = MLBuildResURLWrap(TEXT("shdoclc.dll"),
  1128. HINST_THISDLL,
  1129. ML_CROSSCODEPAGE,
  1130. TEXT("error.dlg"),
  1131. szResURL,
  1132. ARRAYSIZE(szResURL),
  1133. TEXT("shdocvw.dll"));
  1134. if (FAILED(hr))
  1135. {
  1136. goto Cleanup;
  1137. }
  1138. hr = CreateURLMoniker(NULL, szResURL, &pmk);
  1139. if (FAILED(hr))
  1140. goto Cleanup;
  1141. V_VT(&varEventObj) = VT_DISPATCH;
  1142. V_DISPATCH(&varEventObj) = pEventObj;
  1143. ShowHTMLDialog(hwnd, pmk, &varEventObj, NULL, pvarargOut);
  1144. Cleanup:
  1145. ATOMICRELEASE(pEventObj);
  1146. ATOMICRELEASE(pmk);
  1147. }
  1148. //+---------------------------------------------------------------------------
  1149. //
  1150. // Callback procedure for OLECMDID_SHOWMESSAGE dialog
  1151. //
  1152. //+---------------------------------------------------------------------------
  1153. struct MSGBOXCALLBACKINFO
  1154. {
  1155. DWORD dwHelpContext;
  1156. TCHAR * pstrHelpFile;
  1157. HWND hwnd;
  1158. };
  1159. static void CALLBACK
  1160. MessageBoxCallBack(HELPINFO *phi)
  1161. {
  1162. MSGBOXCALLBACKINFO *p = (MSGBOXCALLBACKINFO *)phi->dwContextId;
  1163. BOOL fRet;
  1164. fRet = WinHelp(
  1165. p->hwnd,
  1166. p->pstrHelpFile,
  1167. HELP_CONTEXT,
  1168. p->dwHelpContext);
  1169. THR(fRet ? S_OK : E_FAIL);
  1170. }
  1171. //+---------------------------------------------------------------------------
  1172. //
  1173. // Helper for OLECMDID_SHOWMESSAGE
  1174. //
  1175. //+---------------------------------------------------------------------------
  1176. HRESULT
  1177. CDocHostUIHandler::ShowMessage(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD)
  1178. {
  1179. // must match order of MessageEnum
  1180. static const SExpandoInfo s_aMessageExpandos[] =
  1181. {
  1182. {TEXT("messageText"), VT_BSTR},
  1183. {TEXT("messageCaption"), VT_BSTR},
  1184. {TEXT("messageStyle"), VT_UI4},
  1185. {TEXT("messageHelpFile"), VT_BSTR},
  1186. {TEXT("messageHelpContext"), VT_UI4}
  1187. };
  1188. HRESULT hr;
  1189. HWND hwnd = NULL;
  1190. MSGBOXCALLBACKINFO mcbi;
  1191. MSGBOXPARAMS mbp = {0};
  1192. LRESULT plResult = 0;
  1193. LPOLESTR lpstrText = NULL;
  1194. LPOLESTR lpstrCaption = NULL;
  1195. DWORD dwType = 0;
  1196. LPOLESTR lpstrHelpFile = NULL;
  1197. DWORD dwHelpContext = 0;
  1198. IHTMLEventObj * pEventObj = NULL;
  1199. const int cExpandos = ARRAYSIZE(s_aMessageExpandos);
  1200. DISPID aDispid[cExpandos];
  1201. VARIANT aVariant[cExpandos];
  1202. int i;
  1203. ULONG_PTR uCookie = 0;
  1204. ASSERT(pvarargIn && pvarargOut);
  1205. for (i=0; i<cExpandos; i++)
  1206. VariantInit(aVariant + i);
  1207. ASSERT(V_VT(pvarargIn) == VT_UNKNOWN);
  1208. if ((V_VT(pvarargIn) != VT_UNKNOWN) || !V_UNKNOWN(pvarargIn))
  1209. {
  1210. hr = E_INVALIDARG;
  1211. goto Cleanup;
  1212. }
  1213. GetHwndFromUnknown(V_UNKNOWN(pvarargIn), &hwnd); // hwnd can be NULL
  1214. hr = GetEventFromUnknown(V_UNKNOWN(pvarargIn), &pEventObj);
  1215. if (S_OK != hr)
  1216. goto Cleanup;
  1217. // Get parameters from event object
  1218. hr = GetParamsFromEvent(
  1219. pEventObj,
  1220. cExpandos,
  1221. aDispid,
  1222. aVariant,
  1223. s_aMessageExpandos);
  1224. if (S_OK != hr)
  1225. goto Cleanup;
  1226. // Copy values from variants
  1227. lpstrText = V_BSTR(&aVariant[MessageText]);
  1228. lpstrCaption = V_BSTR(&aVariant[MessageCaption]);
  1229. dwType = V_UI4(&aVariant[MessageStyle]);
  1230. lpstrHelpFile = V_BSTR(&aVariant[MessageHelpFile]);
  1231. dwHelpContext = V_UI4(&aVariant[MessageHelpContext]);
  1232. // Set message box callback info
  1233. mcbi.dwHelpContext = dwHelpContext;
  1234. mcbi.pstrHelpFile = lpstrHelpFile;
  1235. mcbi.hwnd = hwnd;
  1236. // Set message box params
  1237. mbp.cbSize = sizeof(mbp);
  1238. mbp.hwndOwner = hwnd; // It is okay if this is NULL
  1239. mbp.hInstance = MLGetHinst();
  1240. mbp.lpszText = lpstrText;
  1241. mbp.lpszCaption = lpstrCaption;
  1242. mbp.dwContextHelpId = (DWORD_PTR) &mcbi;
  1243. mbp.lpfnMsgBoxCallback = MessageBoxCallBack;
  1244. // mbp.dwLanguageID = ?
  1245. mbp.dwStyle = dwType;
  1246. if (dwHelpContext && lpstrHelpFile)
  1247. mbp.dwStyle |= MB_HELP;
  1248. if (mbp.hwndOwner == NULL)
  1249. mbp.dwStyle |= MB_TASKMODAL;
  1250. SHActivateContext(&uCookie);
  1251. plResult = MessageBoxIndirect(&mbp);
  1252. if (uCookie)
  1253. {
  1254. SHDeactivateContext(uCookie);
  1255. }
  1256. Cleanup:
  1257. V_VT(pvarargOut) = VT_I4;
  1258. V_I4(pvarargOut) = (LONG)plResult;
  1259. for (i=0; i<cExpandos; i++)
  1260. VariantClear(&aVariant[i]);
  1261. ATOMICRELEASE(pEventObj);
  1262. return hr;
  1263. }
  1264. BOOL CDocHostUIHandler::IsFindDialogUp(IWebBrowser2* pwb, IHTMLWindow2** ppWindow)
  1265. {
  1266. BOOL fRet = FALSE;
  1267. BSTR bstrName = SysAllocString(STR_FIND_DIALOG_NAME);
  1268. if (bstrName)
  1269. {
  1270. VARIANT var = {0};
  1271. pwb->GetProperty(bstrName, &var);
  1272. if ( (var.vt == VT_DISPATCH) && (var.pdispVal != NULL) )
  1273. {
  1274. if (ppWindow)
  1275. {
  1276. *ppWindow = (IHTMLWindow2*)var.pdispVal;
  1277. (*ppWindow)->AddRef();
  1278. }
  1279. fRet = TRUE;
  1280. }
  1281. VariantClear(&var);
  1282. SysFreeString(bstrName);
  1283. }
  1284. if (!fRet && ppWindow)
  1285. *ppWindow = NULL;
  1286. return fRet;
  1287. }
  1288. HRESULT SetFindDialogProperty(IWebBrowser2* pwb, VARIANT* pvar)
  1289. {
  1290. HRESULT hr;
  1291. BSTR bstrName = SysAllocString(STR_FIND_DIALOG_NAME);
  1292. if (bstrName)
  1293. {
  1294. hr = pwb->PutProperty(bstrName, *pvar);
  1295. SysFreeString(bstrName);
  1296. }
  1297. else
  1298. hr = E_OUTOFMEMORY;
  1299. return hr;
  1300. }
  1301. //if this fails, then we have no choice but to orphan the dialog
  1302. HRESULT SetFindDialogUp(IWebBrowser2* pwb, IHTMLWindow2* pWindow)
  1303. {
  1304. VARIANT var;
  1305. var.vt = VT_DISPATCH;
  1306. var.pdispVal = pWindow;
  1307. return SetFindDialogProperty(pwb, &var);
  1308. }
  1309. void ReleaseFindDialog(IWebBrowser2* pwb)
  1310. {
  1311. VARIANT var = {0};
  1312. SetFindDialogProperty(pwb, &var);
  1313. }
  1314. //+---------------------------------------------------------------------------
  1315. //
  1316. // Helper for OLECMDID_SHOWFIND
  1317. //
  1318. // pvarargIn - IDispatch Interface
  1319. // dwflags - bidi flag
  1320. //+---------------------------------------------------------------------------
  1321. void
  1322. CDocHostUIHandler::ShowFindDialog(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD dwflags)
  1323. {
  1324. IDispatch * pDispatch = NULL;
  1325. IHTMLOptionsHolder * pHTMLOptionsHolder = NULL;
  1326. IHTMLDocument2 * pHTMLDocument2 = NULL;
  1327. IHTMLWindow2 * pHTMLWindow2 = NULL;
  1328. IOleInPlaceFrame * pOleInPlaceFrame = NULL;
  1329. HWND hwnd = NULL;
  1330. IMoniker * pmk = NULL;
  1331. if (EVAL(V_VT(pvarargIn) == VT_DISPATCH))
  1332. {
  1333. pDispatch = V_DISPATCH(pvarargIn);
  1334. if (SUCCEEDED(pDispatch->QueryInterface(IID_PPV_ARG(IHTMLOptionsHolder, &pHTMLOptionsHolder))))
  1335. {
  1336. if (SUCCEEDED(pHTMLOptionsHolder->get_document(&pHTMLDocument2)) && pHTMLDocument2)
  1337. {
  1338. if (SUCCEEDED(pHTMLDocument2->get_parentWindow(&pHTMLWindow2)))
  1339. {
  1340. if (SUCCEEDED(GetInPlaceFrameFromUnknown(pHTMLDocument2, &pOleInPlaceFrame)))
  1341. {
  1342. if (SUCCEEDED(pOleInPlaceFrame->GetWindow(&hwnd)))
  1343. {
  1344. BOOL fInBrowser = FALSE;
  1345. IWebBrowser2 * pwb2 = NULL;
  1346. if (SUCCEEDED(IUnknown_QueryServiceForWebBrowserApp(_punkSite, IID_PPV_ARG(IWebBrowser2, &pwb2))))
  1347. {
  1348. fInBrowser = TRUE;
  1349. }
  1350. TCHAR szResURL[MAX_URL_STRING];
  1351. if (SUCCEEDED(MLBuildResURLWrap(TEXT("shdoclc.dll"),
  1352. HINST_THISDLL,
  1353. ML_CROSSCODEPAGE,
  1354. (dwflags ? TEXT("bidifind.dlg") : TEXT("find.dlg")),
  1355. szResURL,
  1356. ARRAYSIZE(szResURL),
  1357. TEXT("shdocvw.dll"))))
  1358. {
  1359. CreateURLMoniker(NULL, szResURL, &pmk);
  1360. if (fInBrowser)
  1361. {
  1362. IHTMLWindow2 *pWinOut;
  1363. if (!IsFindDialogUp(pwb2, &pWinOut))
  1364. {
  1365. ASSERT(NULL==pWinOut);
  1366. if ((NULL != pvarargIn) &&
  1367. (VT_DISPATCH == pvarargIn->vt) &&
  1368. (NULL != pvarargIn->pdispVal))
  1369. {
  1370. BSTR bstrFindText = GetFindText(pwb2);
  1371. if (bstrFindText)
  1372. {
  1373. // paranoia since we hang on to this object
  1374. // a while and there is always potential
  1375. // for mess ups below where we mean to
  1376. // release it.
  1377. ATOMICRELEASE(_pOptionsHolder);
  1378. pvarargIn->pdispVal->QueryInterface(
  1379. IID_PPV_ARG(IHTMLOptionsHolder,
  1380. &_pOptionsHolder));
  1381. if (_pOptionsHolder)
  1382. _pOptionsHolder->put_findText(bstrFindText);
  1383. SysFreeString(bstrFindText);
  1384. }
  1385. }
  1386. ShowModelessHTMLDialog(hwnd, pmk, pvarargIn, NULL, &pWinOut);
  1387. if (pWinOut)
  1388. {
  1389. //can't really handle failure here, because the dialog is already up.
  1390. BSTR bstrOnunload = SysAllocString(L"onunload");
  1391. if (bstrOnunload)
  1392. {
  1393. IHTMLWindow3 * pWin3;
  1394. if (SUCCEEDED(pWinOut->QueryInterface(IID_PPV_ARG(IHTMLWindow3, &pWin3))))
  1395. {
  1396. VARIANT_BOOL varBool;
  1397. if (SUCCEEDED(pWin3->attachEvent(bstrOnunload, (IDispatch*)this, &varBool)))
  1398. {
  1399. // on SetFindDialogUp success, the property holds the ref on pWinOut
  1400. if (FAILED(SetFindDialogUp(pwb2, pWinOut)))
  1401. {
  1402. // No way to handle the event, so detach
  1403. pWin3->detachEvent(bstrOnunload, (IDispatch*)this);
  1404. }
  1405. }
  1406. pWin3->Release();
  1407. }
  1408. SysFreeString(bstrOnunload);
  1409. }
  1410. // REVIEW: the old code leaked this ref if the property
  1411. // wasn't attached in SetFindDialogUp...
  1412. pWinOut->Release();
  1413. }
  1414. }
  1415. else
  1416. {
  1417. //since the find dialog is already up, send focus to it
  1418. pWinOut->focus();
  1419. pWinOut->Release();
  1420. }
  1421. }
  1422. else
  1423. {
  1424. //we're not in the browser, so just show it modal
  1425. ShowHTMLDialog(hwnd, pmk, pvarargIn, NULL, NULL);
  1426. }
  1427. if (pmk)
  1428. pmk->Release();
  1429. }
  1430. ATOMICRELEASE(pwb2);
  1431. }
  1432. pOleInPlaceFrame->Release();
  1433. }
  1434. pHTMLWindow2->Release();
  1435. }
  1436. pHTMLDocument2->Release();
  1437. }
  1438. pHTMLOptionsHolder->Release();
  1439. }
  1440. }
  1441. //pWinOut gets released in CDocHostUIHandler::Invoke() or CIEFrameAuto::COmWindow::ViewReleased(),
  1442. // in response to the onunload event.
  1443. if (pvarargOut)
  1444. VariantInit(pvarargOut);
  1445. }
  1446. //+---------------------------------------------------------------------------
  1447. //
  1448. // Callback procedure for OLECMDID_SHOWPAGESETUP dialog
  1449. //
  1450. //+---------------------------------------------------------------------------
  1451. struct PAGESETUPBOXCALLBACKINFO
  1452. {
  1453. TCHAR strHeader[1024];
  1454. TCHAR strFooter[1024];
  1455. };
  1456. UINT_PTR APIENTRY
  1457. PageSetupHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  1458. {
  1459. HKEY keyPageSetup = NULL;
  1460. switch (uiMsg)
  1461. {
  1462. case WM_INITDIALOG:
  1463. PAGESETUPBOXCALLBACKINFO * ppscbi;
  1464. ppscbi = (PAGESETUPBOXCALLBACKINFO *) ((PAGESETUPDLG*)lParam)->lCustData;
  1465. SetWindowLongPtr(hdlg, DWLP_USER, (LONG_PTR)ppscbi);
  1466. SendDlgItemMessage(hdlg,IDC_EDITHEADER, EM_LIMITTEXT, ARRAYSIZE(ppscbi->strHeader)-1, 0L);
  1467. SendDlgItemMessage(hdlg,IDC_EDITFOOTER, EM_LIMITTEXT, ARRAYSIZE(ppscbi->strFooter)-1, 0L);
  1468. SetDlgItemText(hdlg,IDC_EDITHEADER, ppscbi->strHeader);
  1469. SetDlgItemText(hdlg,IDC_EDITFOOTER, ppscbi->strFooter);
  1470. return TRUE;
  1471. case WM_COMMAND:
  1472. switch (GET_WM_COMMAND_ID(wParam, lParam))
  1473. {
  1474. case IDOK:
  1475. {
  1476. PAGESETUPBOXCALLBACKINFO * ppscbi;
  1477. ppscbi = (PAGESETUPBOXCALLBACKINFO *) GetWindowLongPtr(hdlg, DWLP_USER);
  1478. if (ppscbi)
  1479. {
  1480. GetDlgItemText(hdlg,IDC_EDITHEADER, ppscbi->strHeader, ARRAYSIZE(ppscbi->strHeader));
  1481. GetDlgItemText(hdlg,IDC_EDITFOOTER, ppscbi->strFooter, ARRAYSIZE(ppscbi->strFooter));
  1482. }
  1483. }
  1484. }
  1485. break;
  1486. case WM_HELP:
  1487. {
  1488. LPHELPINFO pHI = (LPHELPINFO)lParam;
  1489. if (pHI->iContextType == HELPINFO_WINDOW) // must be for a control
  1490. {
  1491. WinHelp(
  1492. (HWND)pHI->hItemHandle,
  1493. GetHelpFile(pHI->iCtrlId, (DWORD *)aPageSetupDialogHelpIDs),
  1494. HELP_WM_HELP,
  1495. (DWORD_PTR)(LPVOID) aPageSetupDialogHelpIDs);
  1496. }
  1497. break;
  1498. //return TRUE;
  1499. }
  1500. case WM_CONTEXTMENU:
  1501. {
  1502. int CtrlID = GetControlID((HWND)wParam, lParam);
  1503. WinHelp(
  1504. (HWND)wParam,
  1505. GetHelpFile(CtrlID, (DWORD *)aPageSetupDialogHelpIDs),
  1506. HELP_CONTEXTMENU,
  1507. (DWORD_PTR)(LPVOID) aPageSetupDialogHelpIDs);
  1508. break;
  1509. }
  1510. }
  1511. return FALSE;
  1512. }
  1513. //+---------------------------------------------------------------------------
  1514. //
  1515. // Helper for OLECMDID_SHOWPAGESETUP
  1516. //
  1517. // pvarargIn - holds IHTMLEventObj * for the event
  1518. //
  1519. // Returns S_FALSE if the user clicked Cancel and S_TRUE if the user
  1520. // clicked OK.
  1521. //+---------------------------------------------------------------------------
  1522. HRESULT
  1523. CDocHostUIHandler::ShowPageSetupDialog(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD)
  1524. {
  1525. // must match order of PagesetupEnum
  1526. static const SExpandoInfo s_aPagesetupExpandos[] =
  1527. {
  1528. {OLESTR("pagesetupHeader"), VT_BSTR},
  1529. {OLESTR("pagesetupFooter"), VT_BSTR},
  1530. {OLESTR("pagesetupStruct"), VT_PTR}
  1531. };
  1532. HRESULT hr = E_FAIL;
  1533. PAGESETUPDLG * ppagesetupdlg = NULL;
  1534. PAGESETUPBOXCALLBACKINFO pagesetupcbi;
  1535. IHTMLEventObj * pEventObj = NULL;
  1536. const int cExpandos = ARRAYSIZE(s_aPagesetupExpandos);
  1537. DISPID aDispid[cExpandos];
  1538. VARIANT aVariant[cExpandos];
  1539. int i;
  1540. ULONG_PTR uCookie = 0;
  1541. for (i=0; i<cExpandos; i++)
  1542. VariantInit(aVariant+i);
  1543. ASSERT(pvarargIn && (V_VT(pvarargIn) == VT_UNKNOWN));
  1544. if ((V_VT(pvarargIn) != VT_UNKNOWN) || !V_UNKNOWN(pvarargIn))
  1545. goto Cleanup;
  1546. if (V_UNKNOWN(pvarargIn)->QueryInterface(IID_PPV_ARG(IHTMLEventObj, &pEventObj)))
  1547. goto Cleanup;
  1548. // Get parameters from event object
  1549. if (GetParamsFromEvent(
  1550. pEventObj,
  1551. cExpandos,
  1552. aDispid,
  1553. aVariant,
  1554. s_aPagesetupExpandos))
  1555. goto Cleanup;
  1556. // Copy values from variants
  1557. StrCpyN(pagesetupcbi.strHeader,
  1558. V_BSTR(&aVariant[PagesetupHeader]) ? V_BSTR(&aVariant[PagesetupHeader]) : TEXT(""),
  1559. ARRAYSIZE(pagesetupcbi.strHeader));
  1560. StrCpyN(pagesetupcbi.strFooter,
  1561. V_BSTR(&aVariant[PagesetupFooter]) ? V_BSTR(&aVariant[PagesetupFooter]) : TEXT(""),
  1562. ARRAYSIZE(pagesetupcbi.strHeader));
  1563. ppagesetupdlg = (PAGESETUPDLG *)V_BYREF(&aVariant[PagesetupStruct]);
  1564. if (!ppagesetupdlg)
  1565. goto Cleanup;
  1566. // Set up custom dialog resource fields in pagesetupdlg
  1567. ppagesetupdlg->Flags |= PSD_ENABLEPAGESETUPHOOK | PSD_ENABLEPAGESETUPTEMPLATE;
  1568. ppagesetupdlg->lCustData = (LPARAM) &pagesetupcbi;
  1569. ppagesetupdlg->lpfnPageSetupHook = PageSetupHookProc;
  1570. ppagesetupdlg->hInstance = MLLoadShellLangResources();
  1571. ppagesetupdlg->lpPageSetupTemplateName = MAKEINTRESOURCE(PAGESETUPDLGORD);
  1572. // Show dialog
  1573. SHActivateContext(&uCookie);
  1574. if (!PageSetupDlg(ppagesetupdlg))
  1575. {
  1576. // treat failure as canceling
  1577. hr = S_FALSE;
  1578. goto Cleanup;
  1579. }
  1580. hr = S_OK;
  1581. // Save header/footer in event object
  1582. VARIANT var;
  1583. V_VT(&var) = VT_BSTR;
  1584. V_BSTR(&var) = SysAllocString(pagesetupcbi.strHeader ? pagesetupcbi.strHeader : TEXT(""));
  1585. if (NULL != V_BSTR(&var))
  1586. {
  1587. PutParamToEvent(aDispid[PagesetupHeader], &var, pEventObj);
  1588. VariantClear(&var);
  1589. }
  1590. V_VT(&var) = VT_BSTR;
  1591. V_BSTR(&var) = SysAllocString(pagesetupcbi.strFooter ? pagesetupcbi.strFooter : TEXT(""));
  1592. if (NULL != V_BSTR(&var))
  1593. {
  1594. PutParamToEvent(aDispid[PagesetupFooter], &var, pEventObj);
  1595. VariantClear(&var);
  1596. }
  1597. Cleanup:
  1598. if (ppagesetupdlg)
  1599. MLFreeLibrary(ppagesetupdlg->hInstance);
  1600. if (uCookie)
  1601. {
  1602. SHDeactivateContext(uCookie);
  1603. }
  1604. for (i=0; i<cExpandos; i++)
  1605. VariantClear(&aVariant[i]);
  1606. if (pvarargOut)
  1607. VariantInit(pvarargOut);
  1608. ATOMICRELEASE(pEventObj);
  1609. return hr;
  1610. }
  1611. //+---------------------------------------------------------------------------
  1612. //
  1613. // Callback procedure for OLECMDID_SHOWPRINT dialog
  1614. //
  1615. //+---------------------------------------------------------------------------
  1616. static void SetPreviewBitmap(long bitmapID, HWND hdlg);
  1617. HRESULT GetPrintFileName(HWND hwnd, TCHAR achFilePath[], int cchFilePath);
  1618. struct PRINTBOXCALLBACKINFO
  1619. {
  1620. BOOL fRootDocumentHasFrameset;
  1621. BOOL fAreRatingsEnabled;
  1622. BOOL fPrintActiveFrameEnabled;
  1623. BOOL fPrintActiveFrame;
  1624. BOOL fPrintLinked;
  1625. BOOL fPrintSelection;
  1626. BOOL fPrintAsShown;
  1627. BOOL fShortcutTable;
  1628. int iFontScaling;
  1629. IOleCommandTarget * pBodyActive;
  1630. };
  1631. // Common handling functions for both NT 5 and legacy print dialogs
  1632. void OnInitDialog( HWND hdlg, PRINTBOXCALLBACKINFO * ppcbi )
  1633. {
  1634. if (ppcbi)
  1635. {
  1636. // Three scenarioes:
  1637. // 1. Base case: Not FRAMESET, no IFRAMES. No frameoptions should be available.
  1638. // 2. FRAMESET: Obey all frameoptions. Any may be available.
  1639. // 3. IFRAME: May have selected frame available. If so, make selecetd frame & as laid out avail.
  1640. // Should the active frame be disabled?
  1641. if (!ppcbi->fPrintActiveFrameEnabled)
  1642. {
  1643. // Disable "print selected frame" radiobutton.
  1644. HWND hwndPrintActiveFrame = GetDlgItem(hdlg, rad5);
  1645. EnableWindow(hwndPrintActiveFrame, FALSE);
  1646. }
  1647. // If there is no frameset, disable "print all frames" radiobutton.
  1648. if (!ppcbi->fRootDocumentHasFrameset)
  1649. {
  1650. HWND hwndPrintAllFrames = GetDlgItem(hdlg, rad6);
  1651. EnableWindow(hwndPrintAllFrames, FALSE);
  1652. if (!ppcbi->fPrintActiveFrameEnabled)
  1653. {
  1654. // We're not a FRAMESET and don't have IFRAMEs
  1655. // Disable "print as laid out on screen" radiobutton.
  1656. HWND hwndPrintAsLaidOutOnScreen = GetDlgItem(hdlg, rad4);
  1657. EnableWindow(hwndPrintAsLaidOutOnScreen, FALSE);
  1658. SetPreviewBitmap(IDR_PRINT_PREVIEWDISABLED, hdlg);
  1659. }
  1660. }
  1661. // Setup default radio button to be checked.
  1662. // NOTE: We currently allow the template to check options that are disabled.
  1663. if (ppcbi->fPrintActiveFrame)
  1664. {
  1665. // Check "print selected frame" radiobutton.
  1666. CheckRadioButton(hdlg, rad4, rad6, rad5);
  1667. SetPreviewBitmap(IDR_PRINT_PREVIEWONEDOC, hdlg);
  1668. }
  1669. else if (ppcbi->fPrintAsShown)
  1670. {
  1671. // Check "print frames as laid out" radiobutton.
  1672. CheckRadioButton(hdlg, rad4, rad6, rad4);
  1673. SetPreviewBitmap(IDR_PRINT_PREVIEW, hdlg);
  1674. }
  1675. else
  1676. {
  1677. // Check "print all frames" radiobutton.
  1678. CheckRadioButton(hdlg, rad4, rad6, rad6);
  1679. SetPreviewBitmap(IDR_PRINT_PREVIEWALLDOCS, hdlg);
  1680. }
  1681. HWND hwndSelection = GetDlgItem(hdlg, rad2);
  1682. if (hwndSelection) EnableWindow(hwndSelection, (ppcbi->fPrintSelection));
  1683. #ifdef FONTSIZE_BOX
  1684. int i=0, cbLen=0;
  1685. //bugwin16: need to fix this.
  1686. for (i = 0; i < IDS_PRINT_FONTMAX; i++)
  1687. {
  1688. TCHAR achBuffer[128];
  1689. cbLen = MLLoadShellLangString(IDS_PRINT_FONTSCALE+i,achBuffer,127);
  1690. if (cbLen)
  1691. {
  1692. SendDlgItemMessage(hdlg, IDC_SCALING, CB_ADDSTRING, 0, (long) achBuffer);
  1693. }
  1694. }
  1695. if (i>0)
  1696. {
  1697. SendDlgItemMessage(hdlg, IDC_SCALING, CB_SETCURSEL, IDS_PRINT_FONTMAX - 1 - ppcbi->iFontScaling, 0);
  1698. }
  1699. #endif // FONTSIZE_BOX
  1700. // If ratings are enabled, don't allow recursive printing.
  1701. if (ppcbi->fAreRatingsEnabled)
  1702. {
  1703. HWND hwndPrintLinkedDocuments = GetDlgItem(hdlg, IDC_LINKED);
  1704. CheckDlgButton(hdlg, IDC_LINKED, BST_UNCHECKED);
  1705. EnableWindow(hwndPrintLinkedDocuments, FALSE);
  1706. }
  1707. }
  1708. }
  1709. void OnCommand( HWND hdlg, WPARAM wParam, LPARAM lParam )
  1710. {
  1711. PRINTBOXCALLBACKINFO * ppcbi;
  1712. ppcbi = (PRINTBOXCALLBACKINFO *)GetWindowLongPtr(hdlg, DWLP_USER);
  1713. if (!ppcbi)
  1714. {
  1715. return;
  1716. }
  1717. switch (GET_WM_COMMAND_ID(wParam, lParam))
  1718. {
  1719. case rad1: // "Print all"
  1720. case rad3: // "Print range"
  1721. case rad2: // "Print selection" (text selection)
  1722. {
  1723. // If we are printing a text selection, and we have a selected frame,
  1724. // force a print selected frame.
  1725. if (ppcbi && ppcbi->fPrintActiveFrame && ppcbi->fPrintSelection)
  1726. {
  1727. HWND hwndPrintWhatGroup = GetDlgItem(hdlg, grp3);
  1728. HWND hwndPrintActiveFrame = GetDlgItem(hdlg, rad5);
  1729. HWND hwndPrintAllFrames = GetDlgItem(hdlg, rad6);
  1730. HWND hwndPrintSelectedFrame = GetDlgItem(hdlg, rad4);
  1731. if (hwndPrintWhatGroup) EnableWindow(hwndPrintWhatGroup, LOWORD(wParam) != rad2);
  1732. if (hwndPrintActiveFrame) EnableWindow(hwndPrintActiveFrame, LOWORD(wParam) != rad2);
  1733. if (hwndPrintAllFrames) EnableWindow(hwndPrintAllFrames, ppcbi->fRootDocumentHasFrameset && LOWORD(wParam) != rad2);
  1734. if (hwndPrintSelectedFrame) EnableWindow(hwndPrintSelectedFrame, LOWORD(wParam) != rad2);
  1735. }
  1736. break;
  1737. }
  1738. case rad4:
  1739. if (HIWORD(wParam) == BN_CLICKED)
  1740. {
  1741. // now change the icon...
  1742. SetPreviewBitmap(IDR_PRINT_PREVIEW, hdlg);
  1743. HWND hwnd = GetDlgItem(hdlg, rad2);
  1744. if (hwnd) EnableWindow(hwnd, FALSE);
  1745. hwnd = GetDlgItem(hdlg, IDC_SHORTCUTS);
  1746. if (hwnd) EnableWindow(hwnd, FALSE);
  1747. hwnd = GetDlgItem(hdlg, IDC_LINKED);
  1748. if (hwnd) EnableWindow(hwnd, FALSE);
  1749. // if (ppcbi->pBodyActive);
  1750. // ppcbi->pBodyActive->Layout()->LockFocusRect(FALSE);
  1751. }
  1752. break;
  1753. case rad5:
  1754. if (HIWORD(wParam) == BN_CLICKED)
  1755. {
  1756. // now change the icon
  1757. SetPreviewBitmap(IDR_PRINT_PREVIEWONEDOC, hdlg);
  1758. HWND hwnd = GetDlgItem(hdlg, rad2);
  1759. if (hwnd) EnableWindow(hwnd, (ppcbi->fPrintSelection));
  1760. hwnd = GetDlgItem(hdlg, IDC_SHORTCUTS);
  1761. if (hwnd) EnableWindow(hwnd, TRUE);
  1762. hwnd = GetDlgItem(hdlg, IDC_LINKED);
  1763. if (hwnd) EnableWindow(hwnd, TRUE);
  1764. // if (ppcbi->pBodyActive);
  1765. // ppcbi->pBodyActive->Layout()->LockFocusRect(TRUE);
  1766. }
  1767. break;
  1768. case rad6:
  1769. if (HIWORD(wParam) == BN_CLICKED)
  1770. {
  1771. // now change the icon
  1772. SetPreviewBitmap(IDR_PRINT_PREVIEWALLDOCS, hdlg);
  1773. HWND hwnd = GetDlgItem(hdlg, rad2);
  1774. if (hwnd) EnableWindow(hwnd, FALSE);
  1775. hwnd = GetDlgItem(hdlg, IDC_SHORTCUTS);
  1776. if (hwnd) EnableWindow(hwnd, TRUE);
  1777. hwnd = GetDlgItem(hdlg, IDC_LINKED);
  1778. if (hwnd) EnableWindow(hwnd, TRUE);
  1779. // if (ppcbi->pBodyActive);
  1780. // ppcbi->pBodyActive->Layout()->LockFocusRect(FALSE);
  1781. }
  1782. break;
  1783. }
  1784. }
  1785. void OnHelp( HWND hdlg, WPARAM wParam, LPARAM lParam )
  1786. {
  1787. LPHELPINFO pHI = (LPHELPINFO)lParam;
  1788. if (pHI->iContextType == HELPINFO_WINDOW) // must be for a control
  1789. {
  1790. WinHelp(
  1791. (HWND)pHI->hItemHandle,
  1792. GetHelpFile(pHI->iCtrlId, (DWORD *) aPrintDialogHelpIDs),
  1793. HELP_WM_HELP,
  1794. (DWORD_PTR)(LPVOID) aPrintDialogHelpIDs);
  1795. }
  1796. }
  1797. void OnContextMenu( HWND hdlg, WPARAM wParam, LPARAM lParam )
  1798. {
  1799. int CtrlID = GetControlID((HWND)wParam, lParam);
  1800. WinHelp(
  1801. (HWND)wParam,
  1802. GetHelpFile(CtrlID, (DWORD *) aPrintDialogHelpIDs),
  1803. HELP_CONTEXTMENU,
  1804. (DWORD_PTR)(LPVOID) aPrintDialogHelpIDs);
  1805. }
  1806. void OnApplyOrOK( HWND hdlg, WPARAM wParam, LPARAM lParam )
  1807. {
  1808. PRINTBOXCALLBACKINFO * ppcbi = (PRINTBOXCALLBACKINFO *)GetWindowLongPtr(hdlg, DWLP_USER);
  1809. if (ppcbi)
  1810. {
  1811. ppcbi->fPrintLinked = IsDlgButtonChecked(hdlg, IDC_LINKED);
  1812. ppcbi->fPrintSelection = IsDlgButtonChecked(hdlg, rad2);
  1813. ppcbi->fPrintActiveFrame = IsDlgButtonChecked(hdlg, rad5) ||
  1814. ( ppcbi->fPrintSelection &&
  1815. ppcbi->fRootDocumentHasFrameset
  1816. );
  1817. ppcbi->fPrintAsShown = IsDlgButtonChecked(hdlg, rad4) ||
  1818. ( ppcbi->fPrintSelection &&
  1819. ppcbi->fRootDocumentHasFrameset
  1820. );
  1821. ppcbi->fShortcutTable = IsDlgButtonChecked(hdlg, IDC_SHORTCUTS);
  1822. #ifdef FONTSIZE_BOX
  1823. ppcbi->iFontScaling = IDS_PRINT_FONTMAX - 1 - SendDlgItemMessage( hdlg, IDC_SCALING, CB_GETCURSEL, 0,0 );
  1824. #endif
  1825. }
  1826. }
  1827. // This is the callback routine (and dlgproc) for the options
  1828. // page in the NT 5 print dialog.
  1829. INT_PTR APIENTRY
  1830. OptionsPageProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  1831. {
  1832. switch (uiMsg)
  1833. {
  1834. case WM_INITDIALOG:
  1835. {
  1836. PRINTBOXCALLBACKINFO * ppcbi;
  1837. ppcbi = (PRINTBOXCALLBACKINFO *) ((PROPSHEETPAGE *)lParam)->lParam;
  1838. SetWindowLongPtr(hdlg, DWLP_USER, (LONG_PTR)ppcbi);
  1839. OnInitDialog( hdlg, ppcbi );
  1840. break;
  1841. }
  1842. case WM_NOTIFY:
  1843. switch (((NMHDR FAR *)lParam)->code)
  1844. {
  1845. case PSN_APPLY:
  1846. OnApplyOrOK( hdlg, wParam, lParam );
  1847. SetWindowLongPtr (hdlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  1848. return TRUE;
  1849. break;
  1850. case PSN_KILLACTIVE:
  1851. SetWindowLongPtr (hdlg, DWLP_MSGRESULT, FALSE);
  1852. return 1;
  1853. break;
  1854. case PSN_RESET:
  1855. SetWindowLongPtr (hdlg, DWLP_MSGRESULT, FALSE);
  1856. break;
  1857. }
  1858. break;
  1859. case WM_COMMAND:
  1860. OnCommand( hdlg, wParam, lParam );
  1861. break;
  1862. case WM_HELP:
  1863. OnHelp( hdlg, wParam, lParam );
  1864. break;
  1865. case WM_CONTEXTMENU:
  1866. OnContextMenu( hdlg, wParam, lParam );
  1867. break;
  1868. }
  1869. return FALSE;
  1870. }
  1871. UINT_PTR CALLBACK
  1872. PrintHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  1873. {
  1874. switch (uiMsg)
  1875. {
  1876. case WM_INITDIALOG:
  1877. if (lParam)
  1878. {
  1879. PRINTBOXCALLBACKINFO * ppcbi;
  1880. ppcbi = (PRINTBOXCALLBACKINFO *) ((PRINTDLG*)lParam)->lCustData;
  1881. SetWindowLongPtr(hdlg, DWLP_USER, (LONG_PTR)ppcbi);
  1882. OnInitDialog( hdlg, ppcbi );
  1883. }
  1884. return TRUE;
  1885. case WM_COMMAND:
  1886. {
  1887. switch (GET_WM_COMMAND_ID(wParam, lParam))
  1888. {
  1889. case IDOK:
  1890. OnApplyOrOK( hdlg, wParam, lParam );
  1891. break;
  1892. default:
  1893. OnCommand( hdlg, wParam, lParam );
  1894. break;
  1895. }
  1896. }
  1897. break;
  1898. case WM_HELP:
  1899. OnHelp( hdlg, wParam, lParam );
  1900. break;
  1901. //return TRUE;
  1902. case WM_CONTEXTMENU:
  1903. OnContextMenu( hdlg, wParam, lParam );
  1904. break;
  1905. case WM_DESTROY:
  1906. {
  1907. PRINTBOXCALLBACKINFO * ppcbi = (PRINTBOXCALLBACKINFO *)GetWindowLongPtr(hdlg, DWLP_USER);
  1908. ASSERT(ppcbi);
  1909. break;
  1910. }
  1911. }
  1912. return FALSE;
  1913. }
  1914. void SetPreviewBitmap(long bitmapID, HWND hdlg)
  1915. {
  1916. // now change the icon...(note these bitmaps are not localized)
  1917. HBITMAP hNewBitmap = (HBITMAP) LoadImage(HINST_THISDLL, MAKEINTRESOURCE(bitmapID),
  1918. IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_LOADMAP3DCOLORS );
  1919. if (hNewBitmap)
  1920. {
  1921. HBITMAP hOldBitmap = (HBITMAP) SendDlgItemMessage(hdlg, IDC_PREVIEW, STM_SETIMAGE,
  1922. (WPARAM) IMAGE_BITMAP, (LPARAM) hNewBitmap);
  1923. if (hOldBitmap)
  1924. {
  1925. //VERIFY(DeleteObject(hOldBitmap)!=0);
  1926. int i;
  1927. i = DeleteObject(hOldBitmap);
  1928. ASSERT(i!=0);
  1929. }
  1930. }
  1931. }
  1932. //+---------------------------------------------------------------------------
  1933. //
  1934. // Helper for OLECMDID_SHOWPRINT
  1935. //
  1936. //+---------------------------------------------------------------------------
  1937. HRESULT
  1938. CDocHostUIHandler::ShowPrintDialog(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD)
  1939. {
  1940. // the following must match the order of PrintEnum
  1941. static const SExpandoInfo s_aPrintExpandos[] =
  1942. {
  1943. {OLESTR("printfRootDocumentHasFrameset"), VT_BOOL},
  1944. {OLESTR("printfAreRatingsEnabled"), VT_BOOL},
  1945. {OLESTR("printfActiveFrame"), VT_BOOL},
  1946. {OLESTR("printfLinked"), VT_BOOL},
  1947. {OLESTR("printfSelection"), VT_BOOL},
  1948. {OLESTR("printfAsShown"), VT_BOOL},
  1949. {OLESTR("printfShortcutTable"), VT_BOOL},
  1950. {OLESTR("printiFontScaling"), VT_INT},
  1951. {OLESTR("printpBodyActiveTarget"), VT_UNKNOWN},
  1952. {OLESTR("printStruct"), VT_PTR},
  1953. {OLESTR("printToFileOk"), VT_BOOL},
  1954. {OLESTR("printToFileName"), VT_BSTR},
  1955. {OLESTR("printfActiveFrameEnabled"), VT_BOOL},
  1956. };
  1957. HRESULT hr = E_FAIL;
  1958. PRINTDLG * pprintdlg = NULL;
  1959. PRINTBOXCALLBACKINFO printcbi;
  1960. IHTMLEventObj * pEventObj = NULL;
  1961. const int cExpandos = ARRAYSIZE(s_aPrintExpandos);
  1962. DISPID aDispid[cExpandos];
  1963. VARIANT aVariant[cExpandos];
  1964. int i;
  1965. DWORD dwErr = 0;
  1966. printcbi.pBodyActive = NULL;
  1967. if (!V_UNKNOWN(pvarargIn))
  1968. goto Cleanup;
  1969. if (V_UNKNOWN(pvarargIn)->QueryInterface(IID_PPV_ARG(IHTMLEventObj, &pEventObj)))
  1970. goto Cleanup;
  1971. // Get parameters from event object
  1972. if (GetParamsFromEvent(
  1973. pEventObj,
  1974. cExpandos,
  1975. aDispid,
  1976. aVariant,
  1977. s_aPrintExpandos))
  1978. goto Cleanup;
  1979. // Copy values from variants
  1980. printcbi.fRootDocumentHasFrameset = V_BOOL(&aVariant[PrintfRootDocumentHasFrameset]);
  1981. printcbi.fAreRatingsEnabled = V_BOOL(&aVariant[PrintfAreRatingsEnabled]);
  1982. printcbi.fPrintActiveFrame = V_BOOL(&aVariant[PrintfPrintActiveFrame]);
  1983. printcbi.fPrintActiveFrameEnabled = V_BOOL(&aVariant[PrintfPrintActiveFrameEnabled]);
  1984. printcbi.fPrintLinked = V_BOOL(&aVariant[PrintfPrintLinked]);
  1985. printcbi.fPrintSelection = V_BOOL(&aVariant[PrintfPrintSelection]);
  1986. printcbi.fPrintAsShown = V_BOOL(&aVariant[PrintfPrintAsShown]);
  1987. printcbi.fShortcutTable = V_BOOL(&aVariant[PrintfShortcutTable]);
  1988. printcbi.iFontScaling = V_INT(&aVariant[PrintiFontScaling]);
  1989. // If we ever get LockFocusRect, use this field to access it
  1990. // peterlee 8/7/98
  1991. /*
  1992. if (V_UNKNOWN(&aVariant[PrintpBodyActiveTarget]))
  1993. {
  1994. if (V_UNKNOWN(&aVariant[PrintpBodyActiveTarget])->QueryInterface(IID_IOleCommandTarget,
  1995. (void**)&printcbi.pBodyActive))
  1996. goto Cleanup;
  1997. }
  1998. */
  1999. pprintdlg = (PRINTDLG *)V_BYREF(&aVariant[PrintStruct]);
  2000. if (!pprintdlg)
  2001. goto Cleanup;
  2002. // Fix up requested page range so it's within bounds. The dialog will
  2003. // fail to initialize under W95 if this isn't done.
  2004. if ( pprintdlg->nFromPage < pprintdlg->nMinPage )
  2005. pprintdlg->nFromPage = pprintdlg->nMinPage;
  2006. else if ( pprintdlg->nFromPage > pprintdlg->nMaxPage )
  2007. pprintdlg->nFromPage = pprintdlg->nMaxPage;
  2008. if ( pprintdlg->nToPage < pprintdlg->nMinPage )
  2009. pprintdlg->nToPage = pprintdlg->nMinPage;
  2010. else if ( pprintdlg->nToPage > pprintdlg->nMaxPage )
  2011. pprintdlg->nToPage = pprintdlg->nMaxPage;
  2012. // Set up custom dialog resource fields in pagesetupdlg
  2013. pprintdlg->hInstance = MLLoadShellLangResources();
  2014. pprintdlg->lCustData = (LPARAM) &printcbi;
  2015. pprintdlg->lpfnPrintHook = PrintHookProc;
  2016. pprintdlg->lpPrintTemplateName = MAKEINTRESOURCE(PRINTDLGORD);
  2017. if (g_bRunOnNT5)
  2018. {
  2019. // We want to use the new PrintDlgEx in NT 5, so map all the PrintDlg
  2020. // settings to the new PrintDlgEx, get a pointer to the new function
  2021. // and then call it.
  2022. // Load the function from comdlg32 directly...
  2023. typedef HRESULT (*PFNPRINTDLGEX)(LPPRINTDLGEX pdex);
  2024. PFNPRINTDLGEX pfnPrintDlgEx = NULL;
  2025. HMODULE hComDlg32 = LoadLibrary(TEXT("comdlg32.dll"));
  2026. if (hComDlg32)
  2027. {
  2028. pfnPrintDlgEx = (PFNPRINTDLGEX)GetProcAddress(hComDlg32, "PrintDlgExW");
  2029. }
  2030. // Make sure we can call the function...
  2031. if (!pfnPrintDlgEx)
  2032. {
  2033. if (hComDlg32)
  2034. {
  2035. FreeLibrary(hComDlg32);
  2036. }
  2037. hr = E_FAIL;
  2038. goto Cleanup;
  2039. }
  2040. HPROPSHEETPAGE pages[1];
  2041. PRINTPAGERANGE ppr;
  2042. PRINTDLGEX pdex = {0};
  2043. // Copy over existing settings
  2044. pdex.lStructSize = sizeof(pdex);
  2045. pdex.hwndOwner = pprintdlg->hwndOwner;
  2046. pdex.hDevMode = pprintdlg->hDevMode;
  2047. pdex.hDevNames = pprintdlg->hDevNames;
  2048. pdex.hDC = pprintdlg->hDC;
  2049. pdex.Flags = pprintdlg->Flags;
  2050. pdex.nMinPage = pprintdlg->nMinPage;
  2051. pdex.nMaxPage = pprintdlg->nMaxPage;
  2052. pdex.nCopies = pprintdlg->nCopies;
  2053. // New settings
  2054. pdex.nStartPage = START_PAGE_GENERAL;
  2055. ppr.nFromPage = pprintdlg->nFromPage;
  2056. ppr.nToPage = pprintdlg->nToPage;
  2057. pdex.nPageRanges = 1;
  2058. pdex.nMaxPageRanges = 1;
  2059. pdex.lpPageRanges = &ppr;
  2060. // Create options page
  2061. PROPSHEETPAGE psp = {0};
  2062. psp.dwSize = sizeof(psp);
  2063. psp.dwFlags = PSP_DEFAULT;
  2064. psp.hInstance = pprintdlg->hInstance;
  2065. psp.pszTemplate = MAKEINTRESOURCE(IDD_PRINTOPTIONS);
  2066. psp.pfnDlgProc = OptionsPageProc;
  2067. psp.lParam = (LPARAM)&printcbi;
  2068. pages[0] = SHNoFusionCreatePropertySheetPageW(&psp);
  2069. if (pages[0])
  2070. {
  2071. pdex.nPropertyPages = 1;
  2072. pdex.lphPropertyPages = pages;
  2073. // Show the dialog
  2074. ULONG_PTR uCookie = 0;
  2075. SHActivateContext(&uCookie);
  2076. hr = pfnPrintDlgEx(&pdex);
  2077. if (uCookie)
  2078. {
  2079. SHDeactivateContext(uCookie);
  2080. }
  2081. if (SUCCEEDED(hr))
  2082. {
  2083. hr = S_FALSE;
  2084. if ((pdex.dwResultAction == PD_RESULT_PRINT) || (pdex.Flags & PD_RETURNDEFAULT))
  2085. {
  2086. // copy back values which might have changed
  2087. // during the call to PrintDlgEx
  2088. pprintdlg->Flags = pdex.Flags;
  2089. pprintdlg->hDevMode = pdex.hDevMode;
  2090. pprintdlg->hDevNames = pdex.hDevNames;
  2091. pprintdlg->nCopies = (WORD)pdex.nCopies;
  2092. pprintdlg->nFromPage = (WORD)ppr.nFromPage;
  2093. pprintdlg->nToPage = (WORD)ppr.nToPage;
  2094. if (pprintdlg->Flags & PD_RETURNDC)
  2095. {
  2096. pprintdlg->hDC = pdex.hDC;
  2097. }
  2098. hr = S_OK;
  2099. }
  2100. else if ((pdex.Flags & (PD_RETURNDC | PD_RETURNIC)) && pdex.hDC)
  2101. {
  2102. DeleteDC(pdex.hDC);
  2103. pdex.hDC = NULL;
  2104. }
  2105. }
  2106. else
  2107. {
  2108. hr = S_FALSE;
  2109. }
  2110. FreeLibrary(hComDlg32);
  2111. }
  2112. else
  2113. {
  2114. FreeLibrary(hComDlg32);
  2115. hr = E_OUTOFMEMORY;
  2116. goto Cleanup;
  2117. }
  2118. }
  2119. else
  2120. {
  2121. pprintdlg->Flags |= PD_ENABLEPRINTTEMPLATE | PD_ENABLEPRINTHOOK;
  2122. pprintdlg->Flags &= (~(PD_CURRENTPAGE | PD_NOCURRENTPAGE)); // Just in case, mask out the W2K only.
  2123. // Show dialog
  2124. if (!PrintDlg(pprintdlg))
  2125. {
  2126. // treat failure as canceling
  2127. dwErr = CommDlgExtendedError();
  2128. hr = S_FALSE;
  2129. goto Cleanup;
  2130. }
  2131. hr = S_OK;
  2132. }
  2133. // Write changed values to event object
  2134. VARIANT var;
  2135. V_VT(&var) = VT_BOOL;
  2136. V_BOOL(&var) = printcbi.fPrintLinked ? VARIANT_TRUE : VARIANT_FALSE;
  2137. PutParamToEvent(aDispid[PrintfPrintLinked], &var, pEventObj);
  2138. V_BOOL(&var) = printcbi.fPrintActiveFrame ? VARIANT_TRUE : VARIANT_FALSE;
  2139. PutParamToEvent(aDispid[PrintfPrintActiveFrame], &var, pEventObj);
  2140. V_BOOL(&var) = printcbi.fPrintAsShown ? VARIANT_TRUE : VARIANT_FALSE;
  2141. PutParamToEvent(aDispid[PrintfPrintAsShown], &var, pEventObj);
  2142. V_BOOL(&var) = printcbi.fShortcutTable ? VARIANT_TRUE : VARIANT_FALSE;
  2143. PutParamToEvent(aDispid[PrintfShortcutTable], &var, pEventObj);
  2144. // now pop up the fileselection dialog and save the filename...
  2145. // this is the only place where we can make this modal
  2146. BOOL fPrintToFileOk;
  2147. fPrintToFileOk = FALSE;
  2148. if ((pprintdlg->Flags & PD_PRINTTOFILE) != 0)
  2149. {
  2150. // Get the save file path from the event object
  2151. TCHAR achPrintToFileName[MAX_PATH];
  2152. StrCpyN(achPrintToFileName,
  2153. V_BSTR(&aVariant[PrintToFileName]) ? V_BSTR(&aVariant[PrintToFileName]) : TEXT(""),
  2154. ARRAYSIZE(achPrintToFileName));
  2155. if (SUCCEEDED(GetPrintFileName(pprintdlg->hwndOwner, achPrintToFileName, ARRAYSIZE(achPrintToFileName))) &&
  2156. achPrintToFileName[0])
  2157. {
  2158. fPrintToFileOk = TRUE;
  2159. V_VT(&var) = VT_BSTR;
  2160. V_BSTR(&var) = SysAllocString(achPrintToFileName);
  2161. if (NULL != V_BSTR(&var))
  2162. {
  2163. PutParamToEvent(aDispid[PrintToFileName], &var, pEventObj);
  2164. VariantClear(&var);
  2165. }
  2166. }
  2167. }
  2168. V_VT(&var) = VT_BOOL;
  2169. V_BOOL(&var) = fPrintToFileOk ? VARIANT_TRUE : VARIANT_FALSE;
  2170. PutParamToEvent(aDispid[PrintToFileOk], &var, pEventObj);
  2171. Cleanup:
  2172. if (pprintdlg)
  2173. MLFreeLibrary(pprintdlg->hInstance);
  2174. for (i=0; i<cExpandos; i++)
  2175. VariantClear(&aVariant[i]);
  2176. if (pvarargOut)
  2177. VariantInit(pvarargOut);
  2178. ATOMICRELEASE(pEventObj);
  2179. ATOMICRELEASE(printcbi.pBodyActive);
  2180. return hr;
  2181. }
  2182. //+---------------------------------------------------------------------------
  2183. //
  2184. // Callback procedure for PrintToFile Dialog
  2185. //
  2186. //+---------------------------------------------------------------------------
  2187. UINT_PTR APIENTRY PrintToFileHookProc(HWND hdlg,
  2188. UINT uiMsg,
  2189. WPARAM wParam,
  2190. LPARAM lParam)
  2191. {
  2192. switch (uiMsg)
  2193. {
  2194. case WM_INITDIALOG:
  2195. {
  2196. int cbLen;
  2197. TCHAR achOK[MAX_PATH];
  2198. // change "save" to "ok"
  2199. cbLen = MLLoadShellLangString(IDS_PRINTTOFILE_OK,achOK,ARRAYSIZE(achOK));
  2200. if (cbLen < 1)
  2201. StrCpyN(achOK, TEXT("OK"), ARRAYSIZE(achOK));
  2202. // SetDlgItemText(hdlg, IDOK, _T("OK"));
  2203. SetDlgItemText(hdlg, IDOK, achOK);
  2204. // ...and, finally force us into foreground (needed for Win95, Bug : 13368)
  2205. ::SetForegroundWindow(hdlg);
  2206. break;
  2207. }
  2208. }
  2209. return FALSE;
  2210. }
  2211. //+---------------------------------------------------------------------------
  2212. //
  2213. // Member: GetPrintFileName
  2214. //
  2215. // Synopsis: Opens up the customized save file dialog and gets
  2216. // a filename for the printoutput
  2217. // Returns:
  2218. //
  2219. //----------------------------------------------------------------------------
  2220. HRESULT GetPrintFileName(HWND hwnd, TCHAR achFilePath[], int cchFilePath)
  2221. {
  2222. int cbLen;
  2223. TCHAR achTitlePrintInto[MAX_PATH];
  2224. TCHAR achFilePrintInto[MAX_PATH];
  2225. TCHAR achPath[MAX_PATH];
  2226. HRESULT hr = E_FAIL;
  2227. OPENFILENAME openfilename = {0};
  2228. openfilename.lStructSize = sizeof(openfilename);
  2229. openfilename.hwndOwner = hwnd;
  2230. cbLen = MLLoadShellLangString(IDS_PRINTTOFILE_TITLE,achTitlePrintInto,ARRAYSIZE(achTitlePrintInto));
  2231. ASSERT (cbLen && "could not load the resource");
  2232. if (cbLen > 0)
  2233. openfilename.lpstrTitle = achTitlePrintInto;
  2234. // guarantee trailing 0 to terminate the filter string
  2235. TCHAR achFilter[MAX_PATH] = {0};
  2236. cbLen = MLLoadShellLangString(IDS_PRINTTOFILE_SPEC,achFilter,ARRAYSIZE(achFilter)-2);
  2237. ASSERT (cbLen && "could not load the resource");
  2238. if (cbLen>0)
  2239. {
  2240. for (; cbLen >= 0; cbLen--)
  2241. {
  2242. if (achFilter[cbLen]== L',')
  2243. {
  2244. achFilter[cbLen] = 0;
  2245. }
  2246. }
  2247. }
  2248. openfilename.nMaxFileTitle = openfilename.lpstrTitle ? lstrlen(openfilename.lpstrTitle) : 0;
  2249. StrCpyN(achFilePrintInto, TEXT(""), ARRAYSIZE(achFilePrintInto));
  2250. openfilename.lpstrFile = achFilePrintInto;
  2251. openfilename.nMaxFile = ARRAYSIZE(achFilePrintInto);
  2252. openfilename.Flags = OFN_NOREADONLYRETURN | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT |
  2253. OFN_ENABLEHOOK | OFN_NOCHANGEDIR;
  2254. openfilename.lpfnHook = PrintToFileHookProc;
  2255. openfilename.lpstrFilter = achFilter;
  2256. openfilename.nFilterIndex = 1;
  2257. StrCpyN(achPath, achFilePath, ARRAYSIZE(achPath));
  2258. openfilename.lpstrInitialDir = *achPath ? achPath : NULL;
  2259. if (GetSaveFileName(&openfilename))
  2260. {
  2261. StrCpyN(achFilePath, openfilename.lpstrFile, cchFilePath);
  2262. hr = S_OK;
  2263. }
  2264. if (FAILED(hr))
  2265. *achFilePath = NULL;
  2266. return hr;
  2267. }
  2268. //+---------------------------------------------------------------------------
  2269. //
  2270. // Helpers for OLECMDID_PROPERTIES
  2271. //
  2272. //+---------------------------------------------------------------------------
  2273. HRESULT
  2274. CDocHostUIHandler::ShowPropertysheetDialog(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD)
  2275. {
  2276. // must match order of PropertysheetEnum
  2277. static const SExpandoInfo s_aPropertysheetExpandos[] =
  2278. {
  2279. {OLESTR("propertysheetPunks"), VT_SAFEARRAY}
  2280. };
  2281. HRESULT hr;
  2282. HWND hwnd = NULL;
  2283. HWND hwndParent;
  2284. IUnknown * punk = NULL;
  2285. OLECMD olecmd = {0, 0};
  2286. int cUnk = 0;
  2287. IUnknown * HUGEP * apUnk = NULL;
  2288. OCPFIPARAMS ocpfiparams = {0};
  2289. CAUUID ca = { 0, 0 };
  2290. RECT rc = {0, 0, 0, 0};
  2291. RECT rcDesktop = {0, 0, 0, 0};
  2292. SIZE pixelOffset;
  2293. SIZE metricOffset = {0, 0};
  2294. IHTMLEventObj * pEventObj = NULL;
  2295. const int cExpandos = ARRAYSIZE(s_aPropertysheetExpandos);
  2296. VARIANT aVariant[cExpandos];
  2297. DISPID aDispid[cExpandos];
  2298. SAFEARRAY * psafearray = NULL;
  2299. for (int i=0; i<cExpandos; i++)
  2300. VariantInit(&aVariant[i]);
  2301. ASSERT(pvarargIn && V_VT(pvarargIn) == VT_UNKNOWN && V_UNKNOWN(pvarargIn));
  2302. if (!pvarargIn || (V_VT(pvarargIn) != VT_UNKNOWN) || !V_UNKNOWN(pvarargIn))
  2303. {
  2304. hr = E_INVALIDARG;
  2305. goto Cleanup;
  2306. }
  2307. // get the hwnd
  2308. punk = V_UNKNOWN(pvarargIn);
  2309. hr = GetHwndFromUnknown(punk, &hwnd);
  2310. if (S_OK != hr)
  2311. goto Cleanup;
  2312. // get the SafeArray expando from the event obj
  2313. hr = GetEventFromUnknown(punk, &pEventObj);
  2314. if (S_OK != hr)
  2315. goto Cleanup;
  2316. hr = GetParamsFromEvent(
  2317. pEventObj,
  2318. cExpandos,
  2319. aDispid,
  2320. aVariant,
  2321. s_aPropertysheetExpandos);
  2322. if (S_OK != hr)
  2323. goto Cleanup;
  2324. psafearray = V_ARRAY(&aVariant[PropertysheetPunks]);
  2325. // verify array dimensions
  2326. if (SafeArrayGetDim(psafearray) != 1)
  2327. {
  2328. hr = E_INVALIDARG;
  2329. goto Cleanup;
  2330. }
  2331. // get array size, adding one to 0-based size
  2332. hr = SafeArrayGetUBound(psafearray, 1, (long*)&cUnk);
  2333. if (S_OK != hr)
  2334. goto Cleanup;
  2335. cUnk++;
  2336. if (cUnk)
  2337. {
  2338. // get pointer to vector
  2339. hr = SafeArrayAccessData(psafearray, (void HUGEP* FAR*)&apUnk);
  2340. if (S_OK != hr)
  2341. goto Cleanup;
  2342. }
  2343. else
  2344. {
  2345. cUnk = 1;
  2346. apUnk = &punk;
  2347. }
  2348. // Compute pages to load
  2349. hr = THR(GetCommonPages(cUnk, apUnk, &ca));
  2350. if (S_OK != hr)
  2351. goto Cleanup;
  2352. // compute top-level parent
  2353. while (hwndParent = GetParent(hwnd))
  2354. hwnd = hwndParent;
  2355. // The dialog box is not centered on screen
  2356. // the ocpfi seems to be ignoring the x, y values in ocpfiparams
  2357. // Compute offset to center of screen
  2358. GetWindowRect(GetDesktopWindow(), &rcDesktop);
  2359. GetWindowRect(hwnd, &rc);
  2360. pixelOffset.cx = (rcDesktop.right - rcDesktop.left)/2 - rc.left;
  2361. pixelOffset.cy = (rcDesktop.bottom - rcDesktop.top)/2 - rc.top;
  2362. AtlPixelToHiMetric(&pixelOffset, &metricOffset);
  2363. ocpfiparams.cbStructSize = sizeof(ocpfiparams);
  2364. ocpfiparams.hWndOwner = hwnd;
  2365. ocpfiparams.x = metricOffset.cx;
  2366. ocpfiparams.y = metricOffset.cy;
  2367. ocpfiparams.lpszCaption = NULL;
  2368. ocpfiparams.cObjects = cUnk;
  2369. ocpfiparams.lplpUnk = apUnk;
  2370. ocpfiparams.cPages = ca.cElems;
  2371. ocpfiparams.lpPages = ca.pElems;
  2372. ocpfiparams.lcid = GetUserDefaultLCID();
  2373. ocpfiparams.dispidInitialProperty = DISPID_UNKNOWN;
  2374. // OleCreatePropertyFrameIndirect throws its own dialog on error,
  2375. // so we don't want to display that twice
  2376. ULONG_PTR uCookie = 0;
  2377. SHActivateContext(&uCookie);
  2378. THR(OleCreatePropertyFrameIndirect(&ocpfiparams));
  2379. hr = S_OK;
  2380. Cleanup:
  2381. if (uCookie)
  2382. {
  2383. SHDeactivateContext(uCookie);
  2384. }
  2385. if (ca.cElems)
  2386. CoTaskMemFree(ca.pElems);
  2387. if (psafearray && apUnk)
  2388. SafeArrayUnaccessData(psafearray);
  2389. if (pvarargOut)
  2390. VariantInit(pvarargOut);
  2391. for (i=0; i<cExpandos; i++)
  2392. VariantClear(&aVariant[i]);
  2393. ATOMICRELEASE(pEventObj);
  2394. return hr;
  2395. }
  2396. HRESULT
  2397. CDocHostUIHandler::GetCommonPages(int cUnk, IUnknown **apUnk, CAUUID *pca)
  2398. {
  2399. HRESULT hr = E_INVALIDARG;
  2400. int i;
  2401. UINT iScan, iFill, iCompare;
  2402. BOOL fFirst = TRUE;
  2403. CAUUID caCurrent;
  2404. IUnknown * pUnk;
  2405. ISpecifyPropertyPages *pSPP;
  2406. pca->cElems = 0;
  2407. pca->pElems = NULL;
  2408. for (i = 0; i < cUnk; i++)
  2409. {
  2410. pUnk = apUnk[i];
  2411. ASSERT(pUnk);
  2412. hr = THR(pUnk->QueryInterface(IID_PPV_ARG(ISpecifyPropertyPages, &pSPP)));
  2413. if (S_OK != hr)
  2414. goto Cleanup;
  2415. hr = THR(pSPP->GetPages(fFirst ? pca : &caCurrent));
  2416. ATOMICRELEASE(pSPP);
  2417. if (S_OK != hr)
  2418. goto Cleanup;
  2419. if (fFirst)
  2420. {
  2421. continue;
  2422. }
  2423. // keep only the common pages
  2424. else
  2425. {
  2426. for (iScan = 0, iFill = 0; iScan < pca->cElems; iScan++)
  2427. {
  2428. for (iCompare = 0; iCompare < caCurrent.cElems; iCompare++)
  2429. {
  2430. if (caCurrent.pElems[iCompare] == pca->pElems[iScan])
  2431. break;
  2432. }
  2433. if (iCompare != caCurrent.cElems)
  2434. {
  2435. pca->pElems[iFill++] = pca->pElems[iScan];
  2436. }
  2437. }
  2438. pca->cElems = iFill;
  2439. CoTaskMemFree(caCurrent.pElems);
  2440. }
  2441. }
  2442. Cleanup:
  2443. return hr;
  2444. }
  2445. //+---------------------------------------------------------------------------
  2446. //
  2447. // Helper for SHDVID_CLSIDTOMONIKER
  2448. //
  2449. //+---------------------------------------------------------------------------
  2450. struct HTMLPAGECACHE
  2451. {
  2452. const CLSID * pclsid;
  2453. TCHAR * ach;
  2454. };
  2455. HRESULT CDocHostUIHandler::ClsidToMoniker(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  2456. {
  2457. static const HTMLPAGECACHE s_ahtmlpagecache[] =
  2458. {
  2459. &CLSID_CAnchorBrowsePropertyPage, _T("anchrppg.ppg"),
  2460. &CLSID_CImageBrowsePropertyPage, _T("imageppg.ppg"),
  2461. &CLSID_CDocBrowsePropertyPage, _T("docppg.ppg"),
  2462. };
  2463. HRESULT hr = E_FAIL;
  2464. IMoniker * pmk = NULL;
  2465. IUnknown * pUnk = NULL;
  2466. int i;
  2467. const HTMLPAGECACHE * phtmlentry;
  2468. const CLSID * pclsid;
  2469. ASSERT(pvarargIn);
  2470. ASSERT(pvarargOut);
  2471. ASSERT(V_VT(pvarargIn) == VT_UINT_PTR && V_BYREF(pvarargIn));
  2472. if (!pvarargIn || V_VT(pvarargIn) != VT_UINT_PTR || !V_BYREF(pvarargIn))
  2473. goto Cleanup;
  2474. pclsid = (CLSID *)V_BYREF(pvarargIn);
  2475. if (!pvarargOut)
  2476. goto Cleanup;
  2477. VariantInit(pvarargOut);
  2478. // lookup the resource from the CLSID
  2479. for (i = ARRAYSIZE(s_ahtmlpagecache) - 1, phtmlentry = s_ahtmlpagecache;
  2480. i >= 0;
  2481. i--, phtmlentry++)
  2482. {
  2483. ASSERT(phtmlentry->pclsid && phtmlentry->ach);
  2484. if (IsEqualCLSID(*pclsid, *phtmlentry->pclsid))
  2485. {
  2486. // create a moniker for the dialog resource
  2487. TCHAR szResURL[MAX_URL_STRING];
  2488. hr = MLBuildResURL(TEXT("shdoclc.dll"),
  2489. HINST_THISDLL,
  2490. ML_CROSSCODEPAGE,
  2491. phtmlentry->ach,
  2492. szResURL,
  2493. ARRAYSIZE(szResURL));
  2494. if (S_OK != hr)
  2495. goto Cleanup;
  2496. hr = CreateURLMoniker(NULL, szResURL, &pmk);
  2497. if (S_OK != hr)
  2498. goto Cleanup;
  2499. break;
  2500. }
  2501. }
  2502. if (!pmk)
  2503. goto Cleanup;
  2504. // return the moniker
  2505. hr = pmk->QueryInterface(IID_PPV_ARG(IUnknown, &pUnk));
  2506. if (S_OK != hr)
  2507. goto Cleanup;
  2508. else
  2509. {
  2510. V_VT(pvarargOut) = VT_UNKNOWN;
  2511. V_UNKNOWN(pvarargOut) = pUnk;
  2512. V_UNKNOWN(pvarargOut)->AddRef();
  2513. }
  2514. Cleanup:
  2515. ATOMICRELEASE(pUnk);
  2516. ATOMICRELEASE(pmk);
  2517. return hr;
  2518. }
  2519. STDMETHODIMP CDocHostUIHandler::Invoke(
  2520. DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
  2521. VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
  2522. {
  2523. HRESULT hr = S_OK; // this function almost always succeeds! should return failure in some cases
  2524. if (pDispParams && pDispParams->cArgs>=1)
  2525. {
  2526. if (pDispParams->rgvarg[0].vt == VT_DISPATCH && pDispParams->rgvarg[0].pdispVal)
  2527. {
  2528. IHTMLEventObj *pObj=NULL;
  2529. if (SUCCEEDED(pDispParams->rgvarg[0].pdispVal->QueryInterface(IID_PPV_ARG(IHTMLEventObj, &pObj)) && pObj))
  2530. {
  2531. BSTR bstrEvent=NULL;
  2532. pObj->get_type(&bstrEvent);
  2533. if (bstrEvent)
  2534. {
  2535. ASSERT(!StrCmpCW(bstrEvent, L"unload"));
  2536. IWebBrowser2* pwb2;
  2537. hr = IUnknown_QueryServiceForWebBrowserApp(_punkSite, IID_PPV_ARG(IWebBrowser2, &pwb2));
  2538. if (SUCCEEDED(hr))
  2539. {
  2540. IHTMLWindow2* pWindow;
  2541. // we shouldn't be catching this event if the dialog is not up
  2542. if (IsFindDialogUp(pwb2, &pWindow))
  2543. {
  2544. ASSERT(pWindow);
  2545. if (_pOptionsHolder)
  2546. {
  2547. BSTR bstrFindText = NULL;
  2548. _pOptionsHolder->get_findText(&bstrFindText);
  2549. ATOMICRELEASE(_pOptionsHolder);
  2550. PutFindText(pwb2, bstrFindText);
  2551. SysFreeString(bstrFindText);
  2552. }
  2553. BSTR bstrOnunload = SysAllocString(L"onunload");
  2554. if (bstrOnunload)
  2555. {
  2556. IHTMLWindow3 * pWin3;
  2557. if (SUCCEEDED(pWindow->QueryInterface(IID_PPV_ARG(IHTMLWindow3, &pWin3))))
  2558. {
  2559. pWin3->detachEvent(bstrOnunload, (IDispatch*)this);
  2560. pWin3->Release();
  2561. }
  2562. SysFreeString(bstrOnunload);
  2563. }
  2564. pWindow->Release();
  2565. //this is the one that should release the dialog (the pWinOut from ShowFindDialog())
  2566. ReleaseFindDialog(pwb2);
  2567. }
  2568. pwb2->Release();
  2569. }
  2570. SysFreeString(bstrEvent);
  2571. }
  2572. pObj->Release();
  2573. }
  2574. }
  2575. }
  2576. return hr;
  2577. }
  2578. //------------------------------------------------------------------
  2579. //------------------------------------------------------------------
  2580. IMoniker * GetTemplateMoniker(VARIANT varUrl)
  2581. {
  2582. IMoniker * pMon = NULL;
  2583. HRESULT hr = S_OK;
  2584. if (V_VT(&varUrl) == VT_BSTR && SysStringLen(V_BSTR(&varUrl)) !=0)
  2585. {
  2586. // we have a template URL
  2587. hr = CreateURLMoniker(NULL, V_BSTR(&varUrl), &pMon);
  2588. }
  2589. else
  2590. {
  2591. TCHAR szResURL[MAX_URL_STRING];
  2592. hr = MLBuildResURLWrap(TEXT("shdoclc.dll"),
  2593. HINST_THISDLL,
  2594. ML_CROSSCODEPAGE,
  2595. TEXT("preview.dlg"),
  2596. szResURL,
  2597. ARRAYSIZE(szResURL),
  2598. TEXT("shdocvw.dll"));
  2599. if (S_OK != hr)
  2600. goto Cleanup;
  2601. hr = CreateURLMoniker(NULL, szResURL, &pMon);
  2602. }
  2603. Cleanup:
  2604. return pMon;
  2605. }
  2606. //============================================================================
  2607. //
  2608. // Printing support
  2609. //
  2610. //============================================================================
  2611. static enum {
  2612. eTemplate = 0,
  2613. eParentHWND = 1,
  2614. eHeader = 2, // keep this in ssync with the list below!
  2615. eFooter = 3,
  2616. eOutlookDoc = 4,
  2617. eFontScale = 5,
  2618. eFlags = 6,
  2619. eContent = 7,
  2620. ePrinter = 8,
  2621. eDevice = 9,
  2622. ePort = 10,
  2623. eSelectUrl = 11,
  2624. eBrowseDoc = 12,
  2625. eTempFiles = 13,
  2626. };
  2627. static const SExpandoInfo s_aPrintTemplateExpandos[] =
  2628. {
  2629. {TEXT("__IE_TemplateUrl"), VT_BSTR},
  2630. {TEXT("__IE_ParentHWND"), VT_UINT},
  2631. {TEXT("__IE_HeaderString"), VT_BSTR}, // from here down matches the
  2632. {TEXT("__IE_FooterString"), VT_BSTR}, // safeArray structure so
  2633. {TEXT("__IE_OutlookHeader"), VT_UNKNOWN}, // that we can just VariantCopy
  2634. {TEXT("__IE_BaseLineScale"), VT_INT}, // in a loop to transfer the
  2635. {TEXT("__IE_uPrintFlags"), VT_UINT}, // data.
  2636. {TEXT("__IE_ContentDocumentUrl"), VT_BSTR}, // See MSHTML: SetPrintCommandParameters()
  2637. {TEXT("__IE_PrinterCMD_Printer"), VT_BSTR},
  2638. {TEXT("__IE_PrinterCMD_Device"), VT_BSTR},
  2639. {TEXT("__IE_PrinterCMD_Port"), VT_BSTR},
  2640. {TEXT("__IE_ContentSelectionUrl"), VT_BSTR},
  2641. {TEXT("__IE_BrowseDocument"), VT_UNKNOWN},
  2642. {TEXT("__IE_TemporaryFiles"), VT_ARRAY|VT_BSTR},
  2643. };
  2644. //+--------------------------------------------------------------------------------------
  2645. //
  2646. // Helper class CPrintUnloadHandler. Used to delete tempfiles created for print[preview].
  2647. // Note that we don't delete files when we get onUnload event - at this moment
  2648. // files are still in use and can't be deleted. We use destructor - when template
  2649. // is being destructed and all files are already released, template releases
  2650. // all sinks and here we do our cleanup.
  2651. //---------------------------------------------------------------------------------------
  2652. class CPrintUnloadHandler: public IDispatch
  2653. {
  2654. CDocHostUIHandler *m_pUIHandler;
  2655. VARIANT m_vFileNameArray; //SAFEARRAY with filenames
  2656. LONG m_cRef;
  2657. IUnknown *m_punkFreeThreadedMarshaler;
  2658. bool m_fPreview;
  2659. public:
  2660. //IUnknown
  2661. STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID *ppv)
  2662. {
  2663. HRESULT hr = E_NOINTERFACE;
  2664. if (ppv == NULL)
  2665. {
  2666. return E_POINTER;
  2667. }
  2668. else if (IsEqualIID(IID_IUnknown, riid) || IsEqualIID(IID_IDispatch, riid))
  2669. {
  2670. *ppv = this;
  2671. AddRef();
  2672. hr = S_OK;
  2673. }
  2674. else if (IsEqualIID(IID_IMarshal, riid))
  2675. {
  2676. hr = m_punkFreeThreadedMarshaler->QueryInterface(riid,ppv);
  2677. }
  2678. return hr;
  2679. }
  2680. STDMETHOD_(ULONG,AddRef)(THIS)
  2681. {
  2682. return InterlockedIncrement(&m_cRef);
  2683. }
  2684. STDMETHOD_(ULONG,Release)(THIS)
  2685. {
  2686. ASSERT(0 != m_cRef);
  2687. ULONG cRef = InterlockedDecrement(&m_cRef);
  2688. if (0 == cRef)
  2689. {
  2690. delete this;
  2691. }
  2692. return cRef;
  2693. }
  2694. //IDispatch
  2695. virtual STDMETHODIMP GetTypeInfoCount(UINT* pctinfo)
  2696. { return E_NOTIMPL; };
  2697. virtual STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
  2698. { return E_NOTIMPL; };
  2699. virtual STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames,
  2700. LCID lcid, DISPID *rgDispId)
  2701. { return E_NOTIMPL; };
  2702. virtual STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid,
  2703. LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
  2704. EXCEPINFO *pExcepInfo, UINT *puArgErr)
  2705. { return S_OK; }
  2706. CPrintUnloadHandler(CDocHostUIHandler *pUIHandler, bool fPreview)
  2707. {
  2708. ASSERT(pUIHandler);
  2709. //make sure our handler doesn't go anywere..
  2710. m_pUIHandler = pUIHandler;
  2711. pUIHandler->AddRef();
  2712. m_cRef = 1;
  2713. VariantInit(&m_vFileNameArray);
  2714. //create threaded marshaler because we will be called from another thread
  2715. //which will be created for print(preview) window
  2716. CoCreateFreeThreadedMarshaler((IUnknown*)this, &m_punkFreeThreadedMarshaler);
  2717. //if preview, lock the preview gate so no more then one is possible
  2718. m_fPreview = fPreview;
  2719. if (m_fPreview)
  2720. pUIHandler->IncrementPreviewCnt();
  2721. }
  2722. ~CPrintUnloadHandler()
  2723. {
  2724. //here we delete those temp files, finally.
  2725. DeleteFiles();
  2726. if (m_fPreview)
  2727. m_pUIHandler->DecrementPreviewCnt();
  2728. if (m_pUIHandler)
  2729. m_pUIHandler->Release();
  2730. if (m_punkFreeThreadedMarshaler)
  2731. m_punkFreeThreadedMarshaler->Release();
  2732. VariantClear(&m_vFileNameArray);
  2733. }
  2734. HRESULT SetFileList(VARIANT *pvFileList)
  2735. {
  2736. if (pvFileList && (V_VT(pvFileList) == (VT_ARRAY | VT_BSTR)))
  2737. return VariantCopy(&m_vFileNameArray, pvFileList);
  2738. else
  2739. return VariantClear(&m_vFileNameArray);
  2740. }
  2741. void DeleteFiles()
  2742. {
  2743. int arrayMin, arrayMax;
  2744. if (V_VT(&m_vFileNameArray) != (VT_ARRAY | VT_BSTR))
  2745. return;
  2746. SAFEARRAY *psa = V_ARRAY(&m_vFileNameArray);
  2747. if (FAILED(SafeArrayGetLBound(psa, 1, (LONG*)&arrayMin)))
  2748. return;
  2749. if (FAILED(SafeArrayGetUBound(psa, 1, (LONG*)&arrayMax)))
  2750. return;
  2751. for (int i = arrayMin; i <= arrayMax; i++)
  2752. {
  2753. BSTR bstrName = NULL;
  2754. if (SUCCEEDED(SafeArrayGetElement(psa, (LONG*)&i, &bstrName)) && bstrName)
  2755. {
  2756. TCHAR szFileName[MAX_PATH];
  2757. SHUnicodeToTChar(bstrName, szFileName, ARRAYSIZE(szFileName));
  2758. DeleteFile(szFileName);
  2759. SysFreeString(bstrName);
  2760. }
  2761. }
  2762. }
  2763. };
  2764. #define MAX_BUF_INT (1 + 10 + 1) // -2147483647
  2765. //+--------------------------------------------------------------------------------------
  2766. //
  2767. // Member DoTemplatePrinting
  2768. //
  2769. // Synopsis : this member function deals with instantiating a print template and enabling
  2770. // the printing of a document. It deals with the logic of whether to show or hide the
  2771. // template; determining whether/and-how to bring up the print/page-setup dialogs;
  2772. // kicking off the print process rather or waiting for the template
  2773. // UI (and thus the user) to do so.
  2774. //
  2775. // Arguments :
  2776. // pvarargIn : points to an event object with a number of expandoes that define
  2777. // how this print operation should progress.
  2778. // pvarargOut : not used
  2779. // fPreview : flag indicating whether or not to actually show the template. This is true
  2780. // for preview mode, and false for normal printing
  2781. //
  2782. //---------------------------------------------------------------------------------------
  2783. HRESULT
  2784. CDocHostUIHandler::DoTemplatePrinting(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, BOOL fPreview)
  2785. {
  2786. int i;
  2787. HRESULT hr = S_OK;
  2788. VARIANT varDLGOut = {0};
  2789. const int cExpandos = ARRAYSIZE(s_aPrintTemplateExpandos);
  2790. VARIANT aVariant[cExpandos] = {0};
  2791. DISPID aDispid[cExpandos];
  2792. BSTR bstrDlgOptions = NULL;
  2793. DWORD dwDlgFlags;
  2794. IHTMLEventObj * pEventObj = NULL;
  2795. IHTMLEventObj2 * pEventObj2 = NULL;
  2796. IMoniker * pmk = NULL;
  2797. IHTMLWindow2 * pWinOut = NULL;
  2798. TCHAR achInit[512];
  2799. RECT rcClient;
  2800. HWND hwndOverlay = NULL;
  2801. HWND hwndParent = NULL;
  2802. CPrintUnloadHandler * pFinalizer = NULL;
  2803. BOOL fBlock;
  2804. // in preview mode we do not want to bring up another instance of the template
  2805. if (fPreview && (IncrementPreviewCnt() > 1))
  2806. goto Cleanup;
  2807. if (SHRestricted2(REST_NoPrinting, NULL, 0))
  2808. {
  2809. // printing functionality disabled via IEAK restriction
  2810. MLShellMessageBox(NULL, MAKEINTRESOURCE(IDS_RESTRICTED), MAKEINTRESOURCE(IDS_TITLE), MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
  2811. hr = S_FALSE;
  2812. goto Cleanup;
  2813. }
  2814. ASSERT(V_VT(pvarargIn) == VT_UNKNOWN);
  2815. if ((V_VT(pvarargIn) != VT_UNKNOWN) || !V_UNKNOWN(pvarargIn))
  2816. {
  2817. hr = E_INVALIDARG;
  2818. goto Cleanup;
  2819. }
  2820. //
  2821. // now get the expando properties that were passed in...
  2822. //
  2823. hr = V_UNKNOWN(pvarargIn)->QueryInterface(IID_PPV_ARG(IHTMLEventObj, &pEventObj));
  2824. if (S_OK != hr)
  2825. goto Cleanup;
  2826. hr = V_UNKNOWN(pvarargIn)->QueryInterface(IID_PPV_ARG(IHTMLEventObj2, &pEventObj2));
  2827. if (S_OK != hr)
  2828. goto Cleanup;
  2829. //
  2830. // Get expando parameters from event object
  2831. //
  2832. hr = GetParamsFromEvent(pEventObj,
  2833. cExpandos,
  2834. aDispid,
  2835. aVariant,
  2836. s_aPrintTemplateExpandos);
  2837. if (S_OK != hr)
  2838. goto Cleanup;
  2839. //
  2840. // Now that we have all the data, lets do the work of raising the template.
  2841. // First, Create the Moniker of the template document
  2842. //
  2843. pmk = GetTemplateMoniker(aVariant[eTemplate]);
  2844. //
  2845. // Set up the bstrDlgOptions to properly pass in the size and location
  2846. //
  2847. StrCpyN(achInit, TEXT("resizable:yes;status:no;help:no;"), ARRAYSIZE(achInit));
  2848. //
  2849. // get the top most hwnd to use as the parenting hwnd and
  2850. // to use to set the size of the preview window
  2851. //
  2852. hwndOverlay = (HWND)(void*)V_UNKNOWN(&aVariant[eParentHWND]);
  2853. while (hwndParent = GetParent(hwndOverlay))
  2854. {
  2855. hwndOverlay = hwndParent;
  2856. }
  2857. if (GetWindowRect(hwndOverlay, &rcClient))
  2858. {
  2859. TCHAR achBuf[32];
  2860. StrCatBuff(achInit, TEXT("dialogLeft:"), ARRAYSIZE(achInit));
  2861. _ltot(rcClient.left, achBuf, 10); // plenty of space in achBuf for the long value
  2862. StrCatBuff(achInit, achBuf, ARRAYSIZE(achInit));
  2863. StrCatBuff(achInit, TEXT("px;dialogTop:"), ARRAYSIZE(achInit));
  2864. _ltot(rcClient.top, achBuf, 10);
  2865. StrCatBuff(achInit, achBuf, ARRAYSIZE(achInit));
  2866. StrCatBuff(achInit, TEXT("px;dialogWidth:"), ARRAYSIZE(achInit));
  2867. _ltot(rcClient.right - rcClient.left, achBuf, 10);
  2868. StrCatBuff(achInit, achBuf, ARRAYSIZE(achInit));
  2869. StrCatBuff(achInit, TEXT("px;dialogHeight:"), ARRAYSIZE(achInit));
  2870. _ltot(rcClient.bottom - rcClient.top, achBuf, 10);
  2871. StrCatBuff(achInit, achBuf, ARRAYSIZE(achInit));
  2872. StrCatBuff(achInit, TEXT("px;"), ARRAYSIZE(achInit));
  2873. }
  2874. bstrDlgOptions = SysAllocString(achInit);
  2875. if (!bstrDlgOptions)
  2876. {
  2877. hr = E_OUTOFMEMORY;
  2878. goto Cleanup;
  2879. }
  2880. //Create a finalizer
  2881. pFinalizer = new CPrintUnloadHandler(this, fPreview);
  2882. if (pFinalizer)
  2883. {
  2884. pFinalizer->SetFileList(&aVariant[eTempFiles]);
  2885. }
  2886. //
  2887. // Bring up a modeless dialog and get the window pointer so that
  2888. // we can properly initialize the template document.
  2889. //
  2890. V_VT(&varDLGOut) = VT_UNKNOWN;
  2891. V_UNKNOWN(&varDLGOut) = NULL;
  2892. // HTMLDLG_MODELESS really means "open dialog on its own thread", which
  2893. // we want to do for both actual printing and previewing.
  2894. // Note that if we're previewing, we also flip on HTMLDLG_MODAL; this
  2895. // is by design! (see comment below).
  2896. fBlock = ((V_UINT(&aVariant[eFlags]) & PRINT_WAITFORCOMPLETION) != 0);
  2897. dwDlgFlags = HTMLDLG_PRINT_TEMPLATE;
  2898. // VERIFY if we are going to display
  2899. if (fPreview)
  2900. dwDlgFlags |= HTMLDLG_VERIFY;
  2901. // otherwise, don't display with NOUI
  2902. else
  2903. dwDlgFlags |= HTMLDLG_NOUI;
  2904. // If we are not printing synchronously, create a thread for printing.
  2905. if (!fBlock)
  2906. dwDlgFlags |= HTMLDLG_MODELESS;
  2907. // Dlg should block UI on parent
  2908. if (fPreview || fBlock)
  2909. dwDlgFlags |= HTMLDLG_MODAL;
  2910. ShowHTMLDialogEx((HWND)(void*)V_UNKNOWN(&aVariant[eParentHWND]),
  2911. pmk,
  2912. dwDlgFlags,
  2913. pvarargIn,
  2914. bstrDlgOptions,
  2915. &varDLGOut);
  2916. if (V_UNKNOWN(&varDLGOut))
  2917. {
  2918. V_UNKNOWN(&varDLGOut)->QueryInterface(IID_PPV_ARG(IHTMLWindow2, &pWinOut));
  2919. }
  2920. if (pWinOut)
  2921. {
  2922. BSTR bstrOnunload = SysAllocString(L"onunload");
  2923. //
  2924. // can't really handle failure here, because the dialog is already up.
  2925. // .. but we need to set up an onunload handler to properly ref release
  2926. //
  2927. if (bstrOnunload)
  2928. {
  2929. IHTMLWindow3 * pWin3;
  2930. if (SUCCEEDED(pWinOut->QueryInterface(IID_PPV_ARG(IHTMLWindow3, &pWin3))))
  2931. {
  2932. VARIANT_BOOL varBool;
  2933. hr = pWin3->attachEvent(bstrOnunload, (IDispatch*)pFinalizer, &varBool);
  2934. // (greglett) If this fails, we're in trouble.
  2935. // We can either delete the temp files at the end of the function (where the ATOMICRELEASE
  2936. // calls the Finalizer's destructor), or we can leak the temp files.
  2937. // We choose to delete the temp files if we were not modeless (same thread means we're now done with the files).
  2938. // Otherwise, we'd rather leak the files than not work.
  2939. // Known case: 109200.
  2940. if (S_OK != hr && !fBlock)
  2941. {
  2942. //ASSERT(FALSE && "Temp files leaked while printing!");
  2943. pFinalizer->SetFileList(NULL);
  2944. }
  2945. pWin3->Release();
  2946. }
  2947. SysFreeString(bstrOnunload);
  2948. }
  2949. pWinOut->Release();
  2950. }
  2951. Cleanup:
  2952. DecrementPreviewCnt();
  2953. VariantClear(&varDLGOut);
  2954. if (bstrDlgOptions)
  2955. SysFreeString(bstrDlgOptions);
  2956. if (pvarargOut)
  2957. VariantClear(pvarargOut);
  2958. for (i=0; i<cExpandos; i++)
  2959. VariantClear(aVariant + i);
  2960. // This will also delete temp files stored in finalizer if we did non-modeless preview (!fBlock)
  2961. ATOMICRELEASE(pFinalizer);
  2962. ATOMICRELEASE(pEventObj);
  2963. ATOMICRELEASE(pEventObj2);
  2964. ATOMICRELEASE(pmk);
  2965. return hr;
  2966. }
  2967. //+--------------------------------------------------------------------------------------
  2968. //
  2969. // Member DoTemplatePageSetup
  2970. //
  2971. // Synopsis : In template printing architecture, the page setup dialog is still raised
  2972. // by the DHUIHandler, but it may be overriden. In order to pull ALL print knowledge
  2973. // out of trident it is necessary to have trident delegate the request for pagesetup
  2974. // up to here, then we instantiate a minimal template which brings up a CTemplatePrinter
  2975. // which delegates back to the DHUIHandler to bring up the dialog itself.
  2976. //
  2977. // Although this is slightly convoluted, it is necessary in order to give the host
  2978. // complete control over the pagesetup dialog (when not raised from print preview)
  2979. // while at the same time maintaining backcompat for the registry setting that is done
  2980. // independant of the UI handling itself
  2981. //
  2982. //---------------------------------------------------------------------------------------
  2983. HRESULT
  2984. CDocHostUIHandler::DoTemplatePageSetup(VARIANTARG *pvarargIn)
  2985. {
  2986. HRESULT hr = S_OK;
  2987. TCHAR szResURL[MAX_URL_STRING];
  2988. IHTMLEventObj * pEventObj = NULL;
  2989. IMoniker * pMon = NULL;
  2990. const int cExpandos = ARRAYSIZE(s_aPrintTemplateExpandos);
  2991. VARIANT aVariant[cExpandos] = {0};
  2992. DISPID aDispid[cExpandos];
  2993. int i;
  2994. if (SHRestricted2(REST_NoPrinting, NULL, 0))
  2995. {
  2996. // printing functionality disabled via IEAK restriction
  2997. MLShellMessageBox(NULL, MAKEINTRESOURCE(IDS_RESTRICTED), MAKEINTRESOURCE(IDS_TITLE), MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
  2998. hr = S_FALSE;
  2999. goto Cleanup;
  3000. }
  3001. ASSERT(V_VT(pvarargIn) == VT_UNKNOWN);
  3002. if ((V_VT(pvarargIn) != VT_UNKNOWN) || !V_UNKNOWN(pvarargIn))
  3003. {
  3004. hr = E_INVALIDARG;
  3005. goto Cleanup;
  3006. }
  3007. //
  3008. // now get the expando properties that were passed in...
  3009. //
  3010. hr = V_UNKNOWN(pvarargIn)->QueryInterface(IID_PPV_ARG(IHTMLEventObj, &pEventObj));
  3011. if (S_OK != hr)
  3012. goto Cleanup;
  3013. //
  3014. // Get expando parameters from event object
  3015. // do we care if this fails?
  3016. hr = GetParamsFromEvent(pEventObj,
  3017. cExpandos,
  3018. aDispid,
  3019. aVariant,
  3020. s_aPrintTemplateExpandos);
  3021. // get the resource URL
  3022. hr = MLBuildResURLWrap(TEXT("shdoclc.dll"),
  3023. HINST_THISDLL,
  3024. ML_CROSSCODEPAGE,
  3025. TEXT("pstemplate.dlg"),
  3026. szResURL,
  3027. ARRAYSIZE(szResURL),
  3028. TEXT("shdocvw.dll"));
  3029. if (S_OK != hr)
  3030. goto Cleanup;
  3031. // create the moniker
  3032. hr = CreateURLMoniker(NULL, szResURL, &pMon);
  3033. if (S_OK != hr)
  3034. goto Cleanup;
  3035. // raise the template
  3036. hr = ShowHTMLDialogEx((HWND)(void*)V_UNKNOWN(&aVariant[eParentHWND]),
  3037. pMon,
  3038. HTMLDLG_MODAL | HTMLDLG_NOUI | HTMLDLG_PRINT_TEMPLATE,
  3039. pvarargIn,
  3040. NULL,
  3041. NULL);
  3042. Cleanup:
  3043. for (i=0; i<cExpandos; i++)
  3044. VariantClear(aVariant + i);
  3045. ATOMICRELEASE(pMon);
  3046. ATOMICRELEASE(pEventObj);
  3047. return hr;
  3048. }