Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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