dhuihand.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 96k
Category:

Windows Kernel

Development Platform:

Visual C++

  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. // The following defines were stolen from commdlg.h.  Since SHDOCVW is
  22. // compiled with WINVER=0x0400 and these defines are WINVER=0x0500 they
  23. // needed to be copied and included here.  These must be kept in sync
  24. // with the commdlg.h definitions.
  25. //
  26. // If shdocvw ever gets compiled with WINVER=0x0500 or above, then these
  27. // can be removed.
  28. //
  29. //-------------------------------------------------------------------------
  30. #define NEED_BECAUSE_COMPILED_AT_WINVER_4
  31. #ifdef  NEED_BECAUSE_COMPILED_AT_WINVER_4
  32. //
  33. //  Define the start page for the print dialog when using PrintDlgEx.
  34. //
  35. #define START_PAGE_GENERAL             0xffffffff
  36. //
  37. //  Page Range structure for PrintDlgEx.
  38. //
  39. typedef struct tagPRINTPAGERANGE {
  40.    DWORD  nFromPage;
  41.    DWORD  nToPage;
  42. } PRINTPAGERANGE, *LPPRINTPAGERANGE;
  43. //
  44. //  PrintDlgEx structure.
  45. //
  46. typedef struct tagPDEXA {
  47.    DWORD                 lStructSize;          // size of structure in bytes
  48.    HWND                  hwndOwner;            // caller's window handle
  49.    HGLOBAL               hDevMode;             // handle to DevMode
  50.    HGLOBAL               hDevNames;            // handle to DevNames
  51.    HDC                   hDC;                  // printer DC/IC or NULL
  52.    DWORD                 Flags;                // PD_ flags
  53.    DWORD                 Flags2;               // reserved
  54.    DWORD                 ExclusionFlags;       // items to exclude from driver pages
  55.    DWORD                 nPageRanges;          // number of page ranges
  56.    DWORD                 nMaxPageRanges;       // max number of page ranges
  57.    LPPRINTPAGERANGE      lpPageRanges;         // array of page ranges
  58.    DWORD                 nMinPage;             // min page number
  59.    DWORD                 nMaxPage;             // max page number
  60.    DWORD                 nCopies;              // number of copies
  61.    HINSTANCE             hInstance;            // instance handle
  62.    LPCSTR                lpPrintTemplateName;  // template name for app specific area
  63.    LPUNKNOWN             lpCallback;           // app callback interface
  64.    DWORD                 nPropertyPages;       // number of app property pages in lphPropertyPages
  65.    HPROPSHEETPAGE       *lphPropertyPages;     // array of app property page handles
  66.    DWORD                 nStartPage;           // start page id
  67.    DWORD                 dwResultAction;       // result action if S_OK is returned
  68. } PRINTDLGEXA, *LPPRINTDLGEXA;
  69. //
  70. //  PrintDlgEx structure.
  71. //
  72. typedef struct tagPDEXW {
  73.    DWORD                 lStructSize;          // size of structure in bytes
  74.    HWND                  hwndOwner;            // caller's window handle
  75.    HGLOBAL               hDevMode;             // handle to DevMode
  76.    HGLOBAL               hDevNames;            // handle to DevNames
  77.    HDC                   hDC;                  // printer DC/IC or NULL
  78.    DWORD                 Flags;                // PD_ flags
  79.    DWORD                 Flags2;               // reserved
  80.    DWORD                 ExclusionFlags;       // items to exclude from driver pages
  81.    DWORD                 nPageRanges;          // number of page ranges
  82.    DWORD                 nMaxPageRanges;       // max number of page ranges
  83.    LPPRINTPAGERANGE      lpPageRanges;         // array of page ranges
  84.    DWORD                 nMinPage;             // min page number
  85.    DWORD                 nMaxPage;             // max page number
  86.    DWORD                 nCopies;              // number of copies
  87.    HINSTANCE             hInstance;            // instance handle
  88.    LPCWSTR               lpPrintTemplateName;  // template name for app specific area
  89.    LPUNKNOWN             lpCallback;           // app callback interface
  90.    DWORD                 nPropertyPages;       // number of app property pages in lphPropertyPages
  91.    HPROPSHEETPAGE       *lphPropertyPages;     // array of app property page handles
  92.    DWORD                 nStartPage;           // start page id
  93.    DWORD                 dwResultAction;       // result action if S_OK is returned
  94. } PRINTDLGEXW, *LPPRINTDLGEXW;
  95. #ifdef UNICODE
  96. typedef PRINTDLGEXW PRINTDLGEX;
  97. typedef LPPRINTDLGEXW LPPRINTDLGEX;
  98. #else
  99. typedef PRINTDLGEXA PRINTDLGEX;
  100. typedef LPPRINTDLGEXA LPPRINTDLGEX;
  101. #endif // UNICODE
  102. HRESULT  APIENTRY  PrintDlgExA(LPPRINTDLGEXA);
  103. HRESULT  APIENTRY  PrintDlgExW(LPPRINTDLGEXW);
  104. #ifdef UNICODE
  105. #define PrintDlgEx  PrintDlgExW
  106. #else
  107. #define PrintDlgEx  PrintDlgExA
  108. #endif // !UNICODE
  109. //
  110. //  Result action ids for PrintDlgEx.
  111. //
  112. #define PD_RESULT_CANCEL               0
  113. #define PD_RESULT_PRINT                1
  114. #define PD_RESULT_APPLY                2
  115. #endif // NEED_BECAUSE_COMPILED_AT_WINVER_4
  116. //+------------------------------------------------------------------------
  117. //
  118. // Useful combinations of flags for IOleCommandTarget
  119. //
  120. //-------------------------------------------------------------------------
  121. #define OLECMDSTATE_DISABLED    OLECMDF_SUPPORTED
  122. #define OLECMDSTATE_UP          (OLECMDF_SUPPORTED | OLECMDF_ENABLED)
  123. #define OLECMDSTATE_DOWN        (OLECMDF_SUPPORTED | OLECMDF_ENABLED | OLECMDF_LATCHED)
  124. #define OLECMDSTATE_NINCHED     (OLECMDF_SUPPORTED | OLECMDF_ENABLED | OLECMDF_NINCHED)
  125. struct SExpandoInfo
  126. {
  127.     TCHAR * name;
  128.     VARTYPE type;
  129. };
  130. // Enumerations for custom expandos
  131. enum MessageEnum
  132. {
  133.    MessageText,
  134.    MessageCaption,
  135.    MessageStyle,
  136.    MessageHelpFile,
  137.    MessageHelpContext
  138. };
  139. enum PagesetupEnum
  140. {
  141.     PagesetupHeader,
  142.     PagesetupFooter,
  143.     PagesetupStruct
  144. };
  145. enum PrintEnum
  146. {
  147.     PrintfRootDocumentHasFrameset,
  148.     PrintfAreRatingsEnabled,
  149.     PrintfPrintActiveFrame,
  150.     PrintfPrintLinked,
  151.     PrintfPrintSelection,
  152.     PrintfPrintAsShown,
  153.     PrintfShortcutTable,
  154.     PrintiFontScaling,
  155.     PrintpBodyActiveTarget,
  156.     PrintStruct,
  157.     PrintToFileOk,
  158.     PrintToFileName
  159. #ifdef UNIX
  160.     , PrintdmOrientation
  161. #endif // UNIX
  162. };
  163. enum PropertysheetEnum
  164. {
  165.     PropertysheetPunks
  166. };
  167. #ifdef UNIX
  168. #   define ID_PRINT_R_PORTRAIT rad7
  169. #   define ID_PRINT_R_LANDSCAPE rad8
  170. #   define MAX_COMMAND_LEN   255
  171. #endif // UNIX
  172. //----------------------------------------------------------------------------
  173. //
  174. //  Arrays describing helpcontextids for PageSetup/Print
  175. //
  176. //----------------------------------------------------------------------------
  177. static const DWORD aPrintDialogHelpIDs[] =
  178. {
  179.     stc6,                       IDH_PRINT_CHOOSE_PRINTER,
  180.     cmb4,                       IDH_PRINT_CHOOSE_PRINTER,
  181.     psh2,                       IDH_PRINT_PROPERTIES,
  182.     stc7,                       IDH_PRINT_SETUP_DETAILS,
  183.     stc8,                       IDH_PRINT_SETUP_DETAILS,
  184.     stc9,                       IDH_PRINT_SETUP_DETAILS,
  185.     stc10,                      IDH_PRINT_SETUP_DETAILS,
  186.     stc12,                      IDH_PRINT_SETUP_DETAILS,
  187.     stc11,                      IDH_PRINT_SETUP_DETAILS,
  188.     stc14,                      IDH_PRINT_SETUP_DETAILS,
  189.     stc13,                      IDH_PRINT_SETUP_DETAILS,
  190.     stc5,                       IDH_PRINT_TO_FILE,
  191.     chx1,                       IDH_PRINT_TO_FILE,
  192.     ico3,                       IDH_PRINT_COLLATE,
  193.     chx2,                       IDH_PRINT_COLLATE,
  194.     grp1,                       IDH_PRINT_RANGE,
  195.     rad1,                       IDH_PRINT_RANGE,        // all
  196.     rad2,                       IDH_PRINT_RANGE,        // selection
  197.     rad3,                       IDH_PRINT_RANGE,        // pages
  198.     stc2,                       IDH_PRINT_RANGE,
  199.     stc3,                       IDH_PRINT_RANGE,
  200.     edt1,                       IDH_PRINT_RANGE,
  201.     edt2,                       IDH_PRINT_RANGE,
  202.     edt3,                       IDH_PRINT_COPIES,
  203.     rad4,                       IDH_PRINT_SCREEN,
  204.     rad5,                       IDH_PRINT_SEL_FRAME,
  205.     rad6,                       IDH_PRINT_ALL_FRAME,
  206.     IDC_LINKED,                 IDH_PRINT_LINKS,
  207.     IDC_SHORTCUTS,              IDH_PRINT_SHORTCUTS,
  208.     0,    0
  209. };
  210. static const DWORD aPageSetupDialogHelpIDs[] =
  211. {
  212.     psh3,                       IDH_PRINT_PRINTER_SETUP,
  213.     stc2,                       IDH_PAGE_PAPER_SIZE,
  214.     cmb2,                       IDH_PAGE_PAPER_SIZE,
  215.     stc3,                       IDH_PAGE_PAPER_SOURCE,
  216.     cmb3,                       IDH_PAGE_PAPER_SOURCE,
  217.     rad1,                       IDH_PAGE_ORIENTATION,
  218.     rad2,                       IDH_PAGE_ORIENTATION,
  219.     stc15,                      IDH_PAGE_MARGINS,
  220.     edt4,                       IDH_PAGE_MARGINS,
  221.     stc16,                      IDH_PAGE_MARGINS,
  222.     edt5,                       IDH_PAGE_MARGINS,
  223.     stc17,                      IDH_PAGE_MARGINS,
  224.     edt6,                       IDH_PAGE_MARGINS,
  225.     stc18,                      IDH_PAGE_MARGINS,
  226.     edt7,                       IDH_PAGE_MARGINS,
  227.     IDC_EDITHEADER,             IDH_PAGESETUP_HEADER_LEFT,
  228.     IDC_STATICHEADER,           IDH_PAGESETUP_HEADER_LEFT,
  229.     IDC_EDITFOOTER,             IDH_PAGESETUP_HEADER_LEFT,
  230.     IDC_STATICFOOTER,           IDH_PAGESETUP_HEADER_LEFT,
  231.     IDC_HEADERFOOTER,           IDH_PAGESETUP_HEADER_LEFT,
  232.     0,    0
  233. };
  234. //+---------------------------------------------------------------------------
  235. //
  236. //  Function:   GetControlID
  237. //
  238. //  Synopsis:
  239. //
  240. //  Arguments:  HWND - passed window handle of WM_CONTEXTMENU
  241. //              lParam  - passed coordinates (lParam) of WM_CONTEXTMENU
  242. //
  243. //  Returns:    int - ctrlid
  244. //
  245. //
  246. //----------------------------------------------------------------------------
  247. int GetControlID(HWND hwnd, LPARAM lParam)
  248. {
  249.     int CtrlID;
  250.     CtrlID = GetDlgCtrlID(hwnd);
  251.     if (CtrlID==0)
  252.     {
  253.         POINT pt;
  254.         pt.x = GET_X_LPARAM(lParam);
  255.         pt.y = GET_Y_LPARAM(lParam);
  256.         if (ScreenToClient(hwnd, &pt))
  257.         {
  258.             HWND  hwndChild = ChildWindowFromPointEx(hwnd, pt, CWP_ALL);
  259.             if (hwndChild)
  260.             {
  261.                 CtrlID = GetDlgCtrlID(hwndChild);
  262.             }
  263.         }
  264.     }
  265.     return CtrlID;
  266. }
  267. //+---------------------------------------------------------------------------
  268. //
  269. //  Function:   GetHelpFile
  270. //
  271. //  Synopsis:
  272. //
  273. //  Arguments:  iCtrlID - id of the control
  274. //              adw     - array of DWORDS, consisting of controlid,helpid pairs
  275. //
  276. //  Returns:    A string with the name of the helpfile
  277. //
  278. //  Notes:      Help topics for the print dialogs can be either in iexplore.hlp
  279. //              or in windows.hlp.  We key off the helpid to determine which
  280. //              file to go to.
  281. //
  282. //----------------------------------------------------------------------------
  283. LPTSTR
  284. GetHelpFile(int iCtrlID, DWORD * adw)
  285. {
  286.     BOOL fContinue = TRUE;
  287.     ASSERT (adw);
  288.     while (fContinue)
  289.     {
  290.         int ctrlid = int(*adw);
  291.         int helpid = int(*(adw + 1));
  292.         if (ctrlid == 0 && helpid == 0)
  293.         {
  294.             fContinue = FALSE;
  295.             break;
  296.         }
  297.         if (ctrlid == iCtrlID)
  298.         {
  299.             //TraceTag((tagContextHelp, "for ctrl=%d, topic=%d", ctrlid, helpid));
  300.             return (helpid < 50000) ? TEXT("windows.hlp") : TEXT("iexplore.hlp");
  301.         }
  302.         adw += 2;
  303.     }
  304.     return TEXT("windows.hlp");
  305. }
  306. GetInterfaceFromClientSite(IUnknown *pUnk, REFIID riid, void ** ppv)
  307. {
  308.     HRESULT               hr;
  309.     IOleObject          * pOleObject = NULL;
  310.     IOleClientSite      * pOleClientSite = NULL;
  311.     if (!pUnk || !ppv)
  312.     {
  313.         hr = E_INVALIDARG;
  314.         goto Cleanup;
  315.     }
  316.     *ppv = NULL;
  317.     hr = pUnk->QueryInterface(IID_IOleObject, (void **)&pOleObject);
  318.     if (hr)
  319.         goto Cleanup;
  320.     hr = pOleObject->GetClientSite(&pOleClientSite);
  321.     if (pOleClientSite == NULL)
  322.     {
  323.         hr = E_FAIL;
  324.     }
  325.     if (hr)
  326.         goto Cleanup;
  327.     hr = pOleClientSite->QueryInterface(riid, ppv);
  328. Cleanup:
  329.     ATOMICRELEASE(pOleClientSite);
  330.     ATOMICRELEASE(pOleObject);
  331.     return hr;
  332.     
  333.     
  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);
  437.     if (!pEventObj || !aVariant || !aExpandos || cExpandos < 0)
  438.     {
  439.         hr = E_INVALIDARG;
  440.         goto Cleanup;
  441.     }
  442.     for (i=0; i<cExpandos; i++)
  443.     {
  444.         VariantInit(aVariant+i);
  445.         aDispid[i] = DISPID_UNKNOWN;
  446.     }
  447.     hr = pEventObj->QueryInterface(IID_IDispatchEx, (void**)&pDispatchEx);
  448.     if (hr)
  449.         goto Cleanup;
  450.     for (i=0; i<cExpandos; i++)
  451.     {
  452.         hr = pDispatchEx->GetDispID(
  453.             aExpandos[i].name,
  454.             fdexNameCaseSensitive,
  455.             aDispid+i);
  456.         if (hr)
  457.             goto Cleanup;
  458.         hr = pDispatchEx->InvokeEx(
  459.             aDispid[i],
  460.             LOCALE_USER_DEFAULT,
  461.             DISPATCH_PROPERTYGET,
  462.             (DISPPARAMS *)&g_dispparamsNoArgs,
  463.             aVariant+i,
  464.             NULL,
  465.             NULL);
  466.         // Check the variant types match
  467.         ASSERT(V_VT(aVariant+i) == aExpandos[i].type);
  468.         if (hr)
  469.             goto Cleanup;
  470.     }
  471. Cleanup:
  472.     ATOMICRELEASE(pDispatchEx);
  473.     return hr;
  474. }
  475. HRESULT
  476. PutParamToEvent(DISPID dispid, VARIANT * var, IHTMLEventObj * pEventObj)
  477. {
  478.     HRESULT         hr;
  479.     IDispatchEx   * pDispatchEx = NULL;
  480.     DISPPARAMS      dispparams = {var, &dispid, 1, 1};
  481.     ASSERT(var);
  482.     ASSERT(pEventObj);
  483.     if (!var || !pEventObj)
  484.     {
  485.         hr = E_INVALIDARG;
  486.         goto Cleanup;
  487.     }
  488.     hr = pEventObj->QueryInterface(IID_IDispatchEx, (void**)&pDispatchEx);
  489.     if (hr)
  490.         goto Cleanup;
  491.     hr = pDispatchEx->InvokeEx(
  492.             dispid,
  493.             LOCALE_USER_DEFAULT,
  494.             DISPATCH_PROPERTYPUT,
  495.             &dispparams,
  496.             NULL,
  497.             NULL,
  498.             NULL);
  499.     if (hr)
  500.         goto Cleanup;
  501. Cleanup:
  502.     ATOMICRELEASE(pDispatchEx);
  503.     return hr;
  504. }
  505. void PutFindText(IWebBrowser2* pwb, LPCWSTR pwszFindText)
  506. {
  507.     BSTR bstrName = SysAllocString(STR_FIND_DIALOG_TEXT);
  508.     if (NULL != bstrName)
  509.     {
  510.         VARIANT var = {VT_EMPTY};
  511.         if (NULL != pwszFindText)
  512.         {
  513.             var.vt = VT_BSTR;
  514.             var.bstrVal = SysAllocString(pwszFindText);
  515.         }
  516.         if ((VT_EMPTY == var.vt) || (NULL != var.bstrVal))
  517.         {
  518.             pwb->PutProperty(bstrName, var);
  519.         }
  520.         SysFreeString(var.bstrVal);
  521.         SysFreeString(bstrName);
  522.     }
  523. }
  524. BSTR GetFindText(IWebBrowser2* pwb)
  525. {   
  526.     BSTR bstrName = SysAllocString(STR_FIND_DIALOG_TEXT);
  527.     VARIANT var = {VT_EMPTY};
  528.     if (bstrName)
  529.     {
  530.         ASSERT(pwb);
  531.         pwb->GetProperty(bstrName, &var);
  532.         SysFreeString(bstrName);
  533.     }
  534.     BSTR bstrResult; 
  535.     
  536.     if (VT_BSTR == var.vt)
  537.     {
  538.         bstrResult = var.bstrVal;
  539.     }
  540.     else
  541.     {   
  542.         bstrResult = NULL;
  543.         VariantClear(&var);
  544.     }
  545.     return bstrResult;
  546. }
  547. CDocHostUIHandler::CDocHostUIHandler(void) : m_cRef(1)
  548. {
  549.     DllAddRef();
  550. }
  551. CDocHostUIHandler::~CDocHostUIHandler(void)
  552. {
  553.     ATOMICRELEASE(_punkSite);
  554.     ATOMICRELEASE(_pExternal);
  555.     ATOMICRELEASE(_pOptionsHolder);
  556.     if (_hBrowseMenu)
  557.         DestroyMenu(_hBrowseMenu);
  558.     if (_hEditMenu)
  559.         DestroyMenu(_hEditMenu);
  560.     DllRelease();
  561. }
  562. STDMETHODIMP CDocHostUIHandler::QueryInterface(REFIID riid, PVOID *ppvObj)
  563. {
  564.     static const QITAB qit[] = {
  565.         QITABENT(CDocHostUIHandler, IDocHostUIHandler),
  566.         QITABENT(CDocHostUIHandler, IObjectWithSite),
  567.         QITABENT(CDocHostUIHandler, IOleCommandTarget),
  568.         QITABENT(CDocHostUIHandler, IDispatch),
  569.         { 0 },
  570.     };
  571.     return QISearch(this, qit, riid, ppvObj);
  572. }
  573. STDMETHODIMP_(ULONG) CDocHostUIHandler::AddRef()
  574. {
  575.     InterlockedIncrement(&m_cRef);
  576.     return m_cRef;
  577. }
  578. STDMETHODIMP_(ULONG) CDocHostUIHandler::Release()
  579. {
  580.     if (InterlockedDecrement(&m_cRef))
  581.         return m_cRef;
  582.     delete this;
  583.     return 0;
  584. }
  585. HRESULT CDocHostUIHandler::SetSite(IUnknown *punkSite)
  586. {
  587.     ATOMICRELEASE(_punkSite);
  588.     ASSERT(_punkSite == NULL);  // don't lose a reference to this
  589.     _punkSite = punkSite;
  590.     if (_punkSite)
  591.     {
  592.         _punkSite->AddRef();
  593.     }
  594.     // Always return S_OK
  595.     //
  596.     return S_OK;
  597. }
  598. HRESULT CDocHostUIHandler::GetSite(REFIID riid, void **ppvSite)
  599. {
  600.     if (_punkSite)
  601.         return _punkSite->QueryInterface(riid, ppvSite);
  602.     *ppvSite = NULL;
  603.     return E_FAIL;
  604. }
  605. //==========================================================================
  606. // IDocHostUIHandler implementation
  607. //==========================================================================
  608. HRESULT CDocHostUIHandler::ShowContextMenu(DWORD dwID, POINT *ppt, IUnknown *pcmdtReserved, IDispatch *pdispReserved)
  609. {
  610.     HRESULT                 hr = S_FALSE;
  611.     HCURSOR                 hcursor;
  612.     HMENU                   hMenu = NULL;
  613.     VARIANT                 var, var1, var2;
  614.     VARIANT               * pvar = NULL;
  615.     int                     iSelection = 0;
  616.     HWND                    hwnd = NULL;
  617.     IOleCommandTarget     * pOleCommandTarget = NULL;
  618.     IOleWindow            * pOleWindow = NULL;
  619.     IOleInPlaceFrame      * pOleInPlaceFrame = NULL;
  620.     IDocHostUIHandler     * pUIHandler = NULL;
  621.     MENUITEMINFO            mii;
  622.     int                     i;
  623.     OLECMD                  olecmd;
  624.     UINT                    mf;
  625.     TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::ShowContextMenu called");
  626.     //BUGBUG:Does anyone, other than MSHTML call this function?
  627.     //If restriction is set, we lie to Mshtml that context menu has been set. 
  628.     if (SHRestricted2W(REST_NoBrowserContextMenu, NULL, 0))
  629.         return S_OK;
  630.     // Do a proper QI for IOleCommandTarget
  631.     //
  632.     hr = pcmdtReserved->QueryInterface(IID_IOleCommandTarget, (void**)&pOleCommandTarget);
  633.     if (hr)
  634.         goto Cleanup;
  635.     // Check if we are in browse mode
  636.     //
  637.     olecmd.cmdID = IDM_BROWSEMODE;
  638.     hr = pOleCommandTarget->QueryStatus(
  639.             &CGID_MSHTML,
  640.             1,
  641.             &olecmd,
  642.             NULL);
  643.     if (hr)
  644.         goto Cleanup;
  645.     if (olecmd.cmdf == OLECMDSTATE_DOWN)
  646.     {
  647.         if (!_hBrowseMenu)
  648.             _hBrowseMenu = LoadMenu(
  649.                                 MLGetHinst(),
  650.                                 MAKEINTRESOURCE(IDR_BROWSE_CONTEXT_MENU));
  651.         hMenu = _hBrowseMenu;
  652.     }
  653.     // Check if we are in edit mode
  654.     else
  655.     {
  656.         olecmd.cmdID = IDM_EDITMODE;
  657.         hr = pOleCommandTarget->QueryStatus(
  658.                 &CGID_MSHTML,
  659.                 1,
  660.                 &olecmd,
  661.                 NULL);
  662.         if (hr)
  663.             goto Cleanup;
  664.         if (olecmd.cmdf == OLECMDSTATE_DOWN)
  665.         {
  666.             if (!_hEditMenu)
  667.                 _hEditMenu = LoadMenu(
  668.                                 MLGetHinst(),
  669.                                 MAKEINTRESOURCE(IDR_FORM_CONTEXT_MENU));
  670.             hMenu = _hEditMenu;
  671.         }
  672.         // Neither Browse nor Edit flags were set
  673.         else
  674.         {
  675.             ASSERT(false);
  676.             goto Cleanup;
  677.         }
  678.     }
  679.     if (!hMenu)
  680.         goto Cleanup;
  681.     //
  682.     // Check to see if the Integrated DESKTOP is ON
  683.     // If not, we need to delete the "Set as Desktop item" menuitem from all the
  684.     // submenus.
  685.     //
  686.     if(WhichPlatform() != PLATFORM_INTEGRATED)
  687.     {
  688.         int  iSubMenuIndex;
  689.         for(iSubMenuIndex = 0;  iSubMenuIndex < GetMenuItemCount(hMenu); iSubMenuIndex++)
  690.         {
  691.             HMENU hSubMenu;
  692.             if(hSubMenu = GetSubMenu(hMenu, iSubMenuIndex))
  693.                 DeleteMenu(hSubMenu, IDM_SETDESKTOPITEM, MF_BYCOMMAND);
  694.         }
  695.     }
  696.     // Make sure we are running mshtml debug build if we are loading debug window
  697.     if (dwID == CONTEXT_MENU_DEBUG)
  698.     {
  699.         olecmd.cmdID = IDM_DEBUG_TRACETAGS;
  700.         hr = pOleCommandTarget->QueryStatus(
  701.                 &CGID_MSHTML,
  702.                 1,
  703.                 &olecmd,
  704.                 NULL);
  705.         if (olecmd.cmdf != OLECMDSTATE_UP)
  706.             goto Cleanup;
  707.     }
  708.     // Select the appropriate submenu based on the passed in ID
  709.     hMenu = GetSubMenu(hMenu, dwID);
  710.     // Loop through and QueryStatus the menu items.
  711.     //
  712.     for(i = 0; i < GetMenuItemCount(hMenu); i++)
  713.     {
  714.         olecmd.cmdID = GetMenuItemID(hMenu, i);
  715.         if (olecmd.cmdID > 0)
  716.         {
  717.             pOleCommandTarget->QueryStatus(
  718.                     &CGID_MSHTML,
  719.                     1,
  720.                     &olecmd,
  721.                     NULL);
  722.             switch (olecmd.cmdf)
  723.             {
  724.             case OLECMDSTATE_UP:
  725.             case OLECMDSTATE_NINCHED:
  726.                 mf = MF_BYCOMMAND | MF_ENABLED | MF_UNCHECKED;
  727.                 break;
  728.             case OLECMDSTATE_DOWN:
  729.                 mf = MF_BYCOMMAND | MF_ENABLED | MF_CHECKED;
  730.                 break;
  731.             case OLECMDSTATE_DISABLED:
  732.             default:
  733.                 mf = MF_BYCOMMAND | MF_DISABLED | MF_GRAYED;
  734.                 break;
  735.             }
  736.             CheckMenuItem(hMenu, olecmd.cmdID, mf);
  737.             EnableMenuItem(hMenu, olecmd.cmdID, mf);
  738.         }
  739.     }
  740.     // Get the language submenu
  741.     hr = pOleCommandTarget->Exec(&CGID_ShellDocView, SHDVID_GETMIMECSETMENU, 0, NULL, &var);
  742.     if (hr)
  743.         goto Cleanup;
  744.     mii.cbSize = sizeof(mii);
  745.     mii.fMask  = MIIM_SUBMENU;
  746. //$ WIN64: mshtmlsrcsitebaseformmso.cxx needs to return VT_INT_PTR instead
  747. //  mii.hSubMenu = var.byref; // BUGBUG - Line should be this
  748.     mii.hSubMenu = (HMENU) LongToHandle(V_I4(&var)); 
  749.     SetMenuItemInfo(hMenu, IDM_LANGUAGE, FALSE, &mii);
  750.     // Insert Context Menu
  751. //$ WIN64: mshtmlsrcsitebaseformmso.cxx needs to accept VT_INT_PTR instead
  752. //  V_VT(&var1) = VT_INT_PTR; // BUGBUG -- Line should be this
  753. //  V_BYREF(&var1) = hMenu; // BUGBUG -- Line should be this
  754.     V_VT(&var1) = VT_I4;
  755.     V_I4(&var1) = HandleToLong(hMenu);
  756.     V_VT(&var2) = VT_I4;
  757.     V_I4(&var2) = dwID;
  758.     hr = pOleCommandTarget->Exec(&CGID_ShellDocView, SHDVID_ADDMENUEXTENSIONS, 0, &var1, &var2);
  759.     if (hr)
  760.         goto Cleanup;
  761.     // Get the window also.
  762.     //
  763.     if (SUCCEEDED(pcmdtReserved->QueryInterface(IID_IOleWindow, (void**)&pOleWindow)))
  764.     {
  765.         pOleWindow->GetWindow(&hwnd);
  766.     }
  767.     if (hwnd)
  768.     {
  769.         GetInterfaceFromClientSite(pcmdtReserved, IID_IDocHostUIHandler, (void **)&pUIHandler);
  770.         if (pUIHandler)
  771.             pUIHandler->EnableModeless(FALSE);
  772.         GetInPlaceFrameFromUnknown(pcmdtReserved, &pOleInPlaceFrame);
  773.         if (pOleInPlaceFrame)
  774.                 pOleInPlaceFrame->EnableModeless(FALSE);
  775.         hcursor = SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)));
  776.         // Display the menu.  Pass in the HWND of our site object.
  777.         //
  778.         iSelection = ::TrackPopupMenu(
  779.                         hMenu,
  780.                         TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
  781.                         ppt->x + CX_CONTEXTMENUOFFSET,
  782.                         ppt->y + CY_CONTEXTMENUOFFSET,
  783.                         0,
  784.                         hwnd,
  785.                         (RECT*)NULL);
  786.         if (pUIHandler)
  787.             pUIHandler->EnableModeless(TRUE);
  788.         if (pOleInPlaceFrame)
  789.             pOleInPlaceFrame->EnableModeless(TRUE);
  790.         SetCursor(hcursor);
  791.     }
  792.     if (iSelection)
  793.     {
  794.         switch (iSelection)
  795.         {
  796.             case IDM_FOLLOWLINKN:
  797.                 // tell the top level browser to save its window size to the registry so 
  798.                 // that our new window can pick it up and cascade properly
  799.                 IUnknown_Exec(_punkSite, &CGID_Explorer, SBCMDID_SUGGESTSAVEWINPOS, 0, NULL, NULL);
  800.                 // fall through
  801.             case IDM_PROPERTIES:
  802.             case IDM_FOLLOWLINKC:
  803.             
  804.                 pvar = &var;
  805.                 V_VT(pvar) = VT_I4;
  806.                 V_I4(pvar) = MAKELONG(ppt->x, ppt->y);
  807.                 break;
  808.         }
  809.         pOleCommandTarget->Exec(&CGID_MSHTML, iSelection, 0, pvar, NULL);
  810.     }
  811. Cleanup:
  812.     ATOMICRELEASE(pOleCommandTarget);
  813.     ATOMICRELEASE(pOleWindow);
  814.     ATOMICRELEASE(pOleInPlaceFrame);
  815.     ATOMICRELEASE(pUIHandler);
  816.     return hr;
  817. }
  818. HRESULT CDocHostUIHandler::GetHostInfo(DOCHOSTUIINFO *pInfo)
  819. {
  820.     DWORD dwUrlEncodingDisableUTF8;
  821.     DWORD dwSize = SIZEOF(dwUrlEncodingDisableUTF8);
  822.     BOOL  fDefault = FALSE;
  823.     DWORD dwLoadf = 0;
  824.     TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::GetHostInfo called");
  825.     pInfo->cbSize = SIZEOF(DOCHOSTUIINFO);
  826.     pInfo->dwFlags = DOCHOSTUIFLAG_BROWSER;
  827.     pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;     // default
  828.     SHRegGetUSValue(REGSTR_PATH_INTERNET_SETTINGS,
  829.         TEXT("UrlEncoding"), NULL, (LPBYTE) &dwUrlEncodingDisableUTF8, &dwSize, FALSE, (LPVOID) &fDefault, SIZEOF(fDefault));
  830.     if (dwUrlEncodingDisableUTF8)
  831.         pInfo->dwFlags |= DOCHOSTUIFLAG_URL_ENCODING_DISABLE_UTF8;
  832.     else
  833.         pInfo->dwFlags |= DOCHOSTUIFLAG_URL_ENCODING_ENABLE_UTF8;
  834.     return S_OK;
  835. }
  836. HRESULT CDocHostUIHandler::ShowUI(
  837.     DWORD dwID, IOleInPlaceActiveObject *pActiveObject,
  838.     IOleCommandTarget *pCommandTarget, IOleInPlaceFrame *pFrame,
  839.     IOleInPlaceUIWindow *pDoc)
  840. {
  841.     TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::ShowUI called");
  842.     // Host did not display its own UI. Trident will proceed to display its own.
  843.     return S_FALSE;
  844. }
  845. HRESULT CDocHostUIHandler::HideUI(void)
  846. {
  847.     TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::HideUI called");
  848.     // This one is paired with ShowUI
  849.     return S_FALSE;
  850. }
  851. HRESULT CDocHostUIHandler::UpdateUI(void)
  852. {
  853.     TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::UpdateUI called");
  854.     // LATER: Isn't this equivalent to OLECMDID_UPDATECOMMANDS?
  855.     return S_FALSE;
  856. }
  857. HRESULT CDocHostUIHandler::EnableModeless(BOOL fEnable)
  858. {
  859.     TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::EnableModeless called");
  860.     // Called from the Trident when the equivalent member of its
  861.     // IOleInPlaceActiveObject is called by the frame. We don't care
  862.     // those cases.
  863.     return S_OK;
  864. }
  865. HRESULT CDocHostUIHandler::OnDocWindowActivate(BOOL fActivate)
  866. {
  867.     // Called from the Trident when the equivalent member of its
  868.     // IOleInPlaceActiveObject is called by the frame. We don't care
  869.     // those cases.
  870.     return S_OK;
  871. }
  872. HRESULT CDocHostUIHandler::OnFrameWindowActivate(BOOL fActivate)
  873. {
  874.     // Called from the Trident when the equivalent member of its
  875.     // IOleInPlaceActiveObject is called by the frame. We don't care
  876.     // those cases.
  877.     return S_OK;
  878. }
  879. HRESULT CDocHostUIHandler::ResizeBorder(
  880. LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow)
  881. {
  882.     // Called from the Trident when the equivalent member of its
  883.     // IOleInPlaceActiveObject is called by the frame. We don't care
  884.     // those cases.
  885.     return S_OK;
  886. }
  887. HRESULT CDocHostUIHandler::TranslateAccelerator(
  888. LPMSG lpMsg, const GUID *pguidCmdGroup, DWORD nCmdID)
  889. {
  890.     // Called from the Trident when the equivalent member of its
  891.     // IOleInPlaceActiveObject is called by the frame. We don't care
  892.     // those cases.
  893.     return S_FALSE; // The message was not translated
  894. }
  895. HRESULT CDocHostUIHandler::GetOptionKeyPath(BSTR *pbstrKey, DWORD dw)
  896. {
  897.     // Trident will default to its own user options.
  898.     *pbstrKey = NULL;
  899.     return S_FALSE;
  900. }
  901. HRESULT CDocHostUIHandler::GetDropTarget(IDropTarget *pDropTarget, IDropTarget **ppDropTarget)
  902. {
  903.     TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::GetDropTarget called");
  904.     return E_NOTIMPL;
  905. }
  906. HRESULT CDocHostUIHandler::GetAltExternal(IDispatch **ppDisp)
  907. {
  908.     HRESULT hr = E_FAIL;
  909.     IServiceProvider  *psp;
  910.     IDocHostUIHandler *pDocHostUIHandler;
  911.     IOleObject        *pOleObject;
  912.     IOleClientSite    *pOleClientSite;
  913.     *ppDisp = NULL;
  914.     //  * QI ourselves for a service provider
  915.     //  * QS for the top level browser's service provider
  916.     //  * Ask for an IOleObject
  917.     //  * Ask the IOleObject for an IOleClientSite
  918.     //  * QI the IOleClientSite for an IDocHostUIHandler
  919.     //  * Call GetExternal on the IDocHostUIHandler to get the IDispatch
  920.     if (SUCCEEDED(IUnknown_QueryService(_punkSite,
  921.                                         SID_STopLevelBrowser,
  922.                                         IID_IServiceProvider,
  923.                                         (void **)&psp)))
  924.     {
  925.         if (SUCCEEDED(psp->QueryService(SID_SWebBrowserApp, IID_IOleObject,
  926.                                         (void **)&pOleObject)))
  927.         {
  928.             if (SUCCEEDED(pOleObject->GetClientSite(&pOleClientSite)))
  929.             {
  930.                 if (SUCCEEDED(pOleClientSite->QueryInterface(IID_IDocHostUIHandler,
  931.                                                              (void **)&pDocHostUIHandler)))
  932.                 {
  933.                     hr = pDocHostUIHandler->GetExternal(ppDisp);
  934.                     pDocHostUIHandler->Release();
  935.                 }
  936.                 pOleClientSite->Release();
  937.             }
  938.             pOleObject->Release();
  939.         }
  940.         psp->Release();
  941.     }
  942.     return hr;
  943. }
  944. HRESULT CDocHostUIHandler::GetExternal(IDispatch **ppDisp)
  945. {
  946.     TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::GetExternal called");
  947.     HRESULT hr = S_OK;
  948.     if (!ppDisp)
  949.     {
  950.         hr = E_INVALIDARG;
  951.         goto Cleanup;
  952.     }
  953.     if (_pExternal)
  954.     {
  955.         *ppDisp = _pExternal;
  956.         (*ppDisp)->AddRef();
  957.         goto Cleanup;
  958.     }
  959.     IDispatch *psuihDisp;
  960.     IDispatch *pAltExternalDisp;
  961.     *ppDisp = NULL;
  962.     GetAltExternal(&pAltExternalDisp);
  963.     hr = CShellUIHelper_CreateInstance2((IUnknown **)&psuihDisp, IID_IDispatch,
  964.                                        _punkSite, pAltExternalDisp);
  965.     if (SUCCEEDED(hr))
  966.     {
  967.         *ppDisp = psuihDisp;
  968.         _pExternal = *ppDisp;
  969.         if (pAltExternalDisp)
  970.         {
  971.             //  Don't hold a ref - the ShellUIHelper will do it
  972.             pAltExternalDisp->Release();
  973.         }
  974.     }
  975.     else if (pAltExternalDisp)
  976.     {
  977.         //  Couldn't create a ShellUIHelper but we got our host's
  978.         //  external.
  979.         *ppDisp = pAltExternalDisp;
  980.         _pExternal = *ppDisp;
  981.     }
  982. Cleanup:
  983.     ASSERT((SUCCEEDED(hr) && (*ppDisp)) || (FAILED(hr)));
  984.     return hr;
  985. }
  986. HRESULT CDocHostUIHandler::TranslateUrl(DWORD dwTranslate, OLECHAR *pchURLIn, OLECHAR **ppchURLOut)
  987. {
  988.     TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::TranslateUrl called");
  989.     return S_FALSE;
  990. }
  991. HRESULT CDocHostUIHandler::FilterDataObject(IDataObject *pDO, IDataObject **ppDORet)
  992. {
  993.     TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::FilterDataObject called");
  994.     return S_FALSE;
  995. }
  996. STDAPI CDocHostUIHandler_CreateInstance(IUnknown * punkOuter, IUnknown ** ppunk, LPCOBJECTINFO poi)
  997. {
  998.     HRESULT hres = E_OUTOFMEMORY;
  999.     CDocHostUIHandler *pis = new CDocHostUIHandler;
  1000.     if (pis)
  1001.     {
  1002.         *ppunk = SAFECAST(pis, IDocHostUIHandler *);
  1003.         hres = S_OK;
  1004.     }
  1005.     return hres;
  1006. }
  1007. //==========================================================================
  1008. // IOleCommandTarget implementation
  1009. //==========================================================================
  1010. HRESULT CDocHostUIHandler::QueryStatus(const GUID *pguidCmdGroup,
  1011.         ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  1012. {
  1013.     HRESULT hres = OLECMDERR_E_UNKNOWNGROUP;
  1014.     if (IsEqualGUID(CGID_DocHostCommandHandler, *pguidCmdGroup))
  1015.     {
  1016.         ULONG i;
  1017.         if (rgCmds == NULL)
  1018.             return E_INVALIDARG;
  1019.         for (i = 0 ; i < cCmds ; i++)
  1020.         {
  1021.             // ONLY say that we support the stuff we support in ::Exec
  1022.             switch (rgCmds[i].cmdID)
  1023.             {
  1024.             case OLECMDID_SHOWSCRIPTERROR:
  1025.             case OLECMDID_SHOWMESSAGE:
  1026.             case OLECMDID_SHOWFIND:
  1027.             case OLECMDID_SHOWPAGESETUP:
  1028.             case OLECMDID_SHOWPRINT:
  1029.             case OLECMDID_PROPERTIES:
  1030.             case SHDVID_CLSIDTOMONIKER:
  1031.                 rgCmds[i].cmdf = OLECMDF_ENABLED;
  1032.                 break;
  1033.             default:
  1034.                 rgCmds[i].cmdf = 0;
  1035.                 break;
  1036.             }
  1037.         }
  1038.         hres = S_OK;
  1039.     }
  1040.     return hres;
  1041. }
  1042. HRESULT CDocHostUIHandler::Exec(const GUID *pguidCmdGroup,
  1043.         DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  1044. {
  1045.     if (IsEqualGUID(CGID_DocHostCommandHandler, *pguidCmdGroup))
  1046.     {
  1047.         switch (nCmdID)
  1048.         {
  1049.         case OLECMDID_SHOWSCRIPTERROR:
  1050.             if (!pvarargIn || !pvarargOut)
  1051.                 return E_INVALIDARG;
  1052.             ShowErrorDialog(pvarargIn, pvarargOut, nCmdexecopt);
  1053.             return S_OK;
  1054.         case OLECMDID_SHOWMESSAGE:
  1055.             if (!pvarargIn || !pvarargOut)
  1056.                 return E_INVALIDARG;
  1057.             else
  1058.                 return ShowMessage(pvarargIn, pvarargOut, nCmdexecopt);
  1059.         case OLECMDID_SHOWFIND:
  1060.             if (!pvarargIn)
  1061.                 return E_INVALIDARG;
  1062.             ShowFindDialog(pvarargIn, pvarargOut, nCmdexecopt);
  1063.             return S_OK;
  1064.         case OLECMDID_SHOWPAGESETUP:
  1065.             if (!pvarargIn)
  1066.                 return E_INVALIDARG;
  1067.             else
  1068.                 return ShowPageSetupDialog(pvarargIn, pvarargOut, nCmdexecopt);
  1069.         case OLECMDID_SHOWPRINT:
  1070.             if (!pvarargIn)
  1071.                 return E_INVALIDARG;
  1072.             else
  1073.                 return ShowPrintDialog(pvarargIn, pvarargOut, nCmdexecopt);
  1074.         case OLECMDID_PROPERTIES:
  1075.             if (!pvarargIn)
  1076.                 return E_INVALIDARG;
  1077.             else
  1078.                 return ShowPropertysheetDialog(pvarargIn, pvarargOut, nCmdexecopt);
  1079.         case SHDVID_CLSIDTOMONIKER:
  1080.             if (!pvarargIn || !pvarargOut)
  1081.                 return E_INVALIDARG;
  1082.             else
  1083.                 return ClsidToMoniker(pvarargIn, pvarargOut);
  1084.         default:
  1085.             return OLECMDERR_E_NOTSUPPORTED;
  1086.         }
  1087.     }
  1088.     return OLECMDERR_E_UNKNOWNGROUP;
  1089. }
  1090. //+---------------------------------------------------------------------------
  1091. //
  1092. //  Helper for OLECMDID_SHOWSCRIPTERROR
  1093. //
  1094. //+---------------------------------------------------------------------------
  1095. void CDocHostUIHandler::ShowErrorDialog(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD)
  1096. {
  1097.     HRESULT hr;
  1098.     HWND hwnd;
  1099.     IHTMLEventObj * pEventObj = NULL;
  1100.     IMoniker * pmk = NULL;
  1101.     VARIANT varEventObj;
  1102.     TCHAR   szResURL[MAX_URL_STRING];
  1103.     hr = GetHwndFromUnknown(V_UNKNOWN(pvarargIn), &hwnd);
  1104.     if (hr)
  1105.         goto Cleanup;
  1106.     hr = GetEventFromUnknown(V_UNKNOWN(pvarargIn), &pEventObj);
  1107.     if (hr)
  1108.         goto Cleanup;
  1109.     hr = MLBuildResURLWrap(TEXT("shdoclc.dll"),
  1110.                            HINST_THISDLL,
  1111.                            ML_CROSSCODEPAGE,
  1112.                            TEXT("error.dlg"),
  1113.                            szResURL,
  1114.                            ARRAYSIZE(szResURL),
  1115.                            TEXT("shdocvw.dll"));
  1116.     if (FAILED(hr))
  1117.     {
  1118.         goto Cleanup;
  1119.     }
  1120.     hr = CreateURLMoniker(NULL, szResURL, &pmk);
  1121.     if (FAILED(hr))
  1122.         goto Cleanup;
  1123.     V_VT(&varEventObj) = VT_DISPATCH;
  1124.     V_DISPATCH(&varEventObj) = pEventObj;
  1125.     ShowHTMLDialog(hwnd, pmk, &varEventObj, NULL, pvarargOut);
  1126. Cleanup:
  1127.     ATOMICRELEASE(pEventObj);
  1128.     ATOMICRELEASE(pmk);
  1129. }
  1130. //+---------------------------------------------------------------------------
  1131. //
  1132. //  Callback procedure for OLECMDID_SHOWMESSAGE dialog
  1133. //
  1134. //+---------------------------------------------------------------------------
  1135. struct MSGBOXCALLBACKINFO
  1136. {
  1137.     DWORD   dwHelpContext;
  1138.     TCHAR * pstrHelpFile;
  1139.     HWND    hwnd;
  1140. };
  1141. static void CALLBACK
  1142. MessageBoxCallBack(HELPINFO *phi)
  1143. {
  1144.     MSGBOXCALLBACKINFO  *p = (MSGBOXCALLBACKINFO *)phi->dwContextId;
  1145.     BOOL                fRet;
  1146.     fRet = WinHelp(
  1147.             p->hwnd,
  1148.             p->pstrHelpFile,
  1149.             HELP_CONTEXT,
  1150.             p->dwHelpContext);
  1151.     THR(fRet ? S_OK : E_FAIL);
  1152. }
  1153. //+---------------------------------------------------------------------------
  1154. //
  1155. //  Helper for OLECMDID_SHOWMESSAGE
  1156. //
  1157. //+---------------------------------------------------------------------------
  1158. HRESULT
  1159. CDocHostUIHandler::ShowMessage(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD)
  1160. {
  1161. // must match order of MessageEnum
  1162. static const SExpandoInfo s_aMessageExpandos[] =
  1163. {
  1164.     {TEXT("messageText"),         VT_BSTR},
  1165.     {TEXT("messageCaption"),      VT_BSTR},
  1166.     {TEXT("messageStyle"),        VT_UI4},
  1167.     {TEXT("messageHelpFile"),     VT_BSTR},
  1168.     {TEXT("messageHelpContext"),  VT_UI4}
  1169. };
  1170.     HRESULT             hr;
  1171.     HWND                hwnd = NULL;
  1172.     MSGBOXPARAMS        mbp;
  1173.     MSGBOXCALLBACKINFO  mcbi;
  1174.     LRESULT             plResult = 0;
  1175.     LPOLESTR            lpstrText = NULL;
  1176.     LPOLESTR            lpstrCaption = NULL;
  1177.     DWORD               dwType = 0;
  1178.     LPOLESTR            lpstrHelpFile = NULL;
  1179.     DWORD               dwHelpContext = 0;
  1180.     IHTMLEventObj     * pEventObj = NULL;
  1181.     const int           cExpandos = ARRAYSIZE(s_aMessageExpandos);
  1182.     DISPID              aDispid[cExpandos];
  1183.     VARIANT             aVariant[cExpandos];
  1184.     int                 i;
  1185.     ASSERT(pvarargIn && pvarargOut);
  1186.     for(i=0; i<cExpandos; i++)
  1187.         VariantInit(aVariant + i);
  1188.     ASSERT(V_VT(pvarargIn) == VT_UNKNOWN);
  1189.     if ((V_VT(pvarargIn) != VT_UNKNOWN) || !V_UNKNOWN(pvarargIn))
  1190.     {
  1191.         hr = E_INVALIDARG;
  1192.         goto Cleanup;
  1193.     }
  1194.     GetHwndFromUnknown(V_UNKNOWN(pvarargIn), &hwnd);  // hwnd can be NULL
  1195.     hr = GetEventFromUnknown(V_UNKNOWN(pvarargIn), &pEventObj);
  1196.     if (hr)
  1197.         goto Cleanup;
  1198.     // Get parameters from event object
  1199.     hr = GetParamsFromEvent(
  1200.             pEventObj,
  1201.             cExpandos,
  1202.             aDispid,
  1203.             aVariant,
  1204.             s_aMessageExpandos);
  1205.     if (hr)
  1206.         goto Cleanup;
  1207.     // Copy values from variants
  1208.     lpstrText = V_BSTR(&aVariant[MessageText]);
  1209.     lpstrCaption = V_BSTR(&aVariant[MessageCaption]);
  1210.     dwType = V_UI4(&aVariant[MessageStyle]);
  1211.     lpstrHelpFile = V_BSTR(&aVariant[MessageHelpFile]);
  1212.     dwHelpContext = V_UI4(&aVariant[MessageHelpContext]);
  1213.     // Set message box callback info
  1214.     mcbi.dwHelpContext = dwHelpContext;
  1215.     mcbi.pstrHelpFile = lpstrHelpFile;
  1216.     mcbi.hwnd = hwnd;
  1217.     // Set message box params
  1218.     memset(&mbp, 0, sizeof(mbp));
  1219.     mbp.cbSize = sizeof(mbp);
  1220.     mbp.hwndOwner = hwnd;           // It is okay if this is NULL
  1221.     mbp.hInstance = MLGetHinst();
  1222.     mbp.lpszText = lpstrText;
  1223.     mbp.lpszCaption = lpstrCaption;
  1224.     mbp.dwContextHelpId = (DWORD_PTR) &mcbi;
  1225.     mbp.lpfnMsgBoxCallback = MessageBoxCallBack;
  1226.     // mbp.dwLanguageID = ?
  1227.     mbp.dwStyle = dwType;
  1228.     if (dwHelpContext && lpstrHelpFile)
  1229.         mbp.dwStyle |= MB_HELP;
  1230.     if (mbp.hwndOwner == NULL)
  1231.         mbp.dwStyle |= MB_TASKMODAL;
  1232.     plResult = MessageBoxIndirect(&mbp);
  1233. Cleanup:
  1234.     V_VT(pvarargOut) = VT_I4;
  1235.     V_I4(pvarargOut) = (LONG)plResult;
  1236.     for (i=0; i<cExpandos; i++)
  1237.         VariantClear(&aVariant[i]);
  1238.     ATOMICRELEASE(pEventObj);
  1239.     return hr;
  1240. }
  1241. BOOL CDocHostUIHandler::IsFindDialogUp(IWebBrowser2* pwb, IHTMLWindow2** ppWindow)
  1242. {
  1243.     BSTR bstrName = SysAllocString(STR_FIND_DIALOG_NAME);
  1244.     VARIANT var;
  1245.     VariantInit(&var);
  1246.     if (bstrName)
  1247.     {
  1248.         ASSERT(pwb);
  1249.         pwb->GetProperty(bstrName, &var);
  1250.         if ( (var.vt == VT_DISPATCH) && (var.pdispVal != NULL) )
  1251.         {
  1252.             //GetProperty addref's it
  1253.             var.pdispVal->Release();
  1254.         
  1255.             if (ppWindow)
  1256.                 *ppWindow = (IHTMLWindow2*)var.pdispVal;
  1257.         }
  1258.         SysFreeString(bstrName);
  1259.     }
  1260.     return ( (var.vt == VT_DISPATCH) && (var.pdispVal != NULL) );
  1261. }
  1262. //if this fails, then we have no choice but to orphan the dialog
  1263. void SetFindDialogUp(IWebBrowser2* pwb, IHTMLWindow2* pWindow)
  1264. {
  1265.     BSTR bstrName = SysAllocString(STR_FIND_DIALOG_NAME);
  1266.     if (bstrName)
  1267.     {
  1268.         ASSERT(pwb);
  1269.         VARIANT var;
  1270.         VariantInit(&var);
  1271.         var.vt = VT_DISPATCH;
  1272.         var.pdispVal = pWindow;
  1273.         pwb->PutProperty(bstrName, var);
  1274.         SysFreeString(bstrName);
  1275.     }
  1276. }
  1277. //+---------------------------------------------------------------------------
  1278. //
  1279. //  Helper for OLECMDID_SHOWFIND
  1280. //
  1281. //  pvarargIn - IDispatch Interface
  1282. //  dwflags   - bidi flag
  1283. //+---------------------------------------------------------------------------
  1284. void
  1285. CDocHostUIHandler::ShowFindDialog(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD dwflags)
  1286. {
  1287.     IDispatch             * pDispatch = NULL;
  1288.     IHTMLOptionsHolder    * pHTMLOptionsHolder = NULL;
  1289.     IHTMLDocument2        * pHTMLDocument2 = NULL;
  1290.     IHTMLWindow2          * pHTMLWindow2 = NULL;
  1291.     IOleInPlaceFrame      * pOleInPlaceFrame = NULL;
  1292.     HWND                    hwnd = NULL;
  1293.     IMoniker              * pmk = NULL;
  1294.     if (EVAL(V_VT(pvarargIn) == VT_DISPATCH))
  1295.     {
  1296.         pDispatch = V_DISPATCH(pvarargIn);
  1297.         
  1298.         if (SUCCEEDED(pDispatch->QueryInterface(IID_IHTMLOptionsHolder, (void**)&pHTMLOptionsHolder)))
  1299.         {
  1300.             if (SUCCEEDED(pHTMLOptionsHolder->get_document(&pHTMLDocument2)) && pHTMLDocument2)
  1301.             {
  1302.                 if (SUCCEEDED(pHTMLDocument2->get_parentWindow(&pHTMLWindow2)))
  1303.                 {
  1304.                     if (SUCCEEDED(GetInPlaceFrameFromUnknown(pHTMLDocument2, &pOleInPlaceFrame)))
  1305.                     {
  1306.                         if (SUCCEEDED(pOleInPlaceFrame->GetWindow(&hwnd)))
  1307.                         {
  1308.                             BOOL fInBrowser = FALSE;
  1309.                             IWebBrowser2 * pwb2 = NULL;
  1310.                             IServiceProvider * psp;
  1311.                             if (SUCCEEDED(IUnknown_QueryService(_punkSite, SID_STopLevelBrowser, IID_IServiceProvider, (LPVOID*)&psp)))
  1312.                             {
  1313.                                 if (SUCCEEDED(psp->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (LPVOID*)&pwb2)))
  1314.                                 {
  1315.                                     fInBrowser = TRUE;
  1316.                                 }
  1317.                                 psp->Release();
  1318.                             }
  1319.                             TCHAR   szResURL[MAX_URL_STRING];
  1320.                             if (SUCCEEDED(MLBuildResURLWrap(TEXT("shdoclc.dll"),
  1321.                                                             HINST_THISDLL,
  1322.                                                             ML_CROSSCODEPAGE,
  1323.                                                             (dwflags ? TEXT("bidifind.dlg") : TEXT("find.dlg")),
  1324.                                                             szResURL,
  1325.                                                             ARRAYSIZE(szResURL),
  1326.                                                             TEXT("shdocvw.dll"))))
  1327.                             {
  1328.                                 CreateURLMoniker(NULL, szResURL, &pmk);
  1329.                                 if (fInBrowser)
  1330.                                 {
  1331.                                     IHTMLWindow2 *pWinOut;
  1332.                                     if (!IsFindDialogUp(pwb2, NULL))
  1333.                                     {
  1334.                                         if ((NULL != pvarargIn) && 
  1335.                                             (VT_DISPATCH == pvarargIn->vt) &&
  1336.                                             (NULL != pvarargIn->pdispVal))
  1337.                                         {
  1338.                                             BSTR bstrFindText = GetFindText(pwb2);
  1339.                                             if (NULL != bstrFindText)
  1340.                                             {
  1341.                                                 //  paranoia since we hang on to this object
  1342.                                                 //  a while and there is always potential 
  1343.                                                 //  for screw ups below where we mean to
  1344.                                                 //  release it.
  1345.                                                 ATOMICRELEASE(_pOptionsHolder);
  1346.                                                 pvarargIn->pdispVal->QueryInterface(
  1347.                                                                      IID_IHTMLOptionsHolder,
  1348.                                                                      (void **)&_pOptionsHolder);
  1349.                                                 if (NULL != _pOptionsHolder)
  1350.                                                 {
  1351.                                                     _pOptionsHolder->put_findText(bstrFindText);
  1352.                                                 }
  1353.                                                 
  1354.                                                 SysFreeString(bstrFindText);
  1355.                                             }
  1356.                                         }
  1357.                                         ShowModelessHTMLDialog(hwnd, pmk, pvarargIn, NULL, &pWinOut);
  1358.                                         if (pWinOut)
  1359.                                         {
  1360.                                             //can't really handle failure here, because the dialog is already up.
  1361.                                             BSTR bstrOnunload = SysAllocString(L"onunload");
  1362.                                             if (bstrOnunload)
  1363.                                             {
  1364.                                                 IHTMLWindow3 * pWin3;
  1365.                                                 if (SUCCEEDED(pWinOut->QueryInterface(IID_IHTMLWindow3, (void**)&pWin3)))
  1366.                                                 {
  1367.                                                     VARIANT_BOOL varBool;
  1368.                                                     pWin3->attachEvent(bstrOnunload, (IDispatch*)this, &varBool);
  1369.                                                     pWin3->Release();
  1370.                                                 }
  1371.                                                 SysFreeString(bstrOnunload);
  1372.                                             }
  1373.                                             SetFindDialogUp(pwb2, pWinOut);
  1374.                                         }        
  1375.                                     }
  1376.                                     else
  1377.                                     {
  1378.                                         //this time, get the pointer to the window. 
  1379.                                         //note that none of this will cause an addref.
  1380.                                         EVAL(IsFindDialogUp(pwb2, &pWinOut));
  1381.                                         //since the find dialog is already up, send focus to it
  1382.                                         if (pWinOut)
  1383.                                             pWinOut->focus();
  1384.                                     }
  1385.                                 }
  1386.                                 else
  1387.                                 {
  1388.                                     //we're not in the browser, so just show it modal
  1389.                                     ShowHTMLDialog(hwnd, pmk, pvarargIn, NULL, NULL);
  1390.                                 }
  1391.                                 if (pmk)
  1392.                                     pmk->Release();
  1393.                             }
  1394.                             ATOMICRELEASE(pwb2);
  1395.                         }
  1396.                         pOleInPlaceFrame->Release();
  1397.                     }
  1398.                     pHTMLWindow2->Release();
  1399.                 }
  1400.                 pHTMLDocument2->Release();
  1401.             }
  1402.             pHTMLOptionsHolder->Release();
  1403.         }
  1404.     }
  1405.     //pWinOut gets released in CDocHostUIHandler::Invoke() or CIEFrameAuto::COmWindow::ViewReleased(),
  1406.     // in response to the onunload event.
  1407.     
  1408.     if (pvarargOut)
  1409.         VariantInit(pvarargOut);
  1410. }
  1411. //+---------------------------------------------------------------------------
  1412. //
  1413. //  Callback procedure for OLECMDID_SHOWPAGESETUP dialog
  1414. //
  1415. //+---------------------------------------------------------------------------
  1416. struct PAGESETUPBOXCALLBACKINFO
  1417. {
  1418.     TCHAR   strHeader[1024];
  1419.     TCHAR   strFooter[1024];
  1420. };
  1421. UINT_PTR APIENTRY
  1422. PageSetupHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  1423. {
  1424.     HKEY    keyPageSetup = NULL;
  1425.     switch (uiMsg)
  1426.     {
  1427.     case WM_INITDIALOG:
  1428.         PAGESETUPBOXCALLBACKINFO * ppscbi;
  1429.         ppscbi = (PAGESETUPBOXCALLBACKINFO *) ((PAGESETUPDLG*)lParam)->lCustData;
  1430.         SetWindowLongPtr(hdlg, DWLP_USER, (LONG_PTR)ppscbi);
  1431. #ifdef UNIX
  1432.         SendDlgItemMessage(hdlg,IDC_EDITHEADER, EM_LIMITTEXT, 1023, 0L);
  1433.         SendDlgItemMessage(hdlg,IDC_EDITFOOTER, EM_LIMITTEXT, 1023, 0L);
  1434. #endif
  1435.         SetDlgItemText(hdlg,IDC_EDITHEADER, ppscbi->strHeader);
  1436.         SetDlgItemText(hdlg,IDC_EDITFOOTER, ppscbi->strFooter);
  1437.         return TRUE;
  1438.     case WM_COMMAND:
  1439.         switch (GET_WM_COMMAND_ID(wParam, lParam))
  1440.         {
  1441.         case IDOK:
  1442.             {
  1443.                 PAGESETUPBOXCALLBACKINFO * ppscbi;
  1444.                 ppscbi = (PAGESETUPBOXCALLBACKINFO *) GetWindowLongPtr(hdlg, DWLP_USER);
  1445.                 if (ppscbi)
  1446.                 {
  1447.                     GetDlgItemText(hdlg,IDC_EDITHEADER, ppscbi->strHeader,1024);
  1448.                     GetDlgItemText(hdlg,IDC_EDITFOOTER, ppscbi->strFooter,1024);
  1449.                 }
  1450.             }
  1451.         }
  1452.         break;
  1453.    case WM_HELP:
  1454.     {
  1455.         LPHELPINFO pHI;
  1456.         pHI = (LPHELPINFO)lParam;
  1457.         if (pHI->iContextType == HELPINFO_WINDOW)   // must be for a control
  1458.         {
  1459.             WinHelp(
  1460.                     (HWND)pHI->hItemHandle,
  1461.                     GetHelpFile(pHI->iCtrlId, (DWORD *)aPageSetupDialogHelpIDs),
  1462.                     HELP_WM_HELP,
  1463.                     (DWORD_PTR)(LPVOID) aPageSetupDialogHelpIDs);
  1464.         }
  1465.         break;
  1466.         //return TRUE;
  1467.     }
  1468.     case WM_CONTEXTMENU:
  1469.     {
  1470.         int CtrlID = GetControlID((HWND)wParam, lParam);
  1471.         WinHelp(
  1472.                 (HWND)wParam,
  1473.                 GetHelpFile(CtrlID, (DWORD *)aPageSetupDialogHelpIDs),
  1474.                 HELP_CONTEXTMENU,
  1475.                 (DWORD_PTR)(LPVOID) aPageSetupDialogHelpIDs);
  1476.         break;
  1477.     }
  1478.     }
  1479.     return FALSE;
  1480. }
  1481. //+---------------------------------------------------------------------------
  1482. //
  1483. //  Helper for OLECMDID_SHOWPAGESETUP
  1484. //
  1485. //  pvarargIn - holds IHTMLEventObj * for the event
  1486. //
  1487. // Returns S_FALSE if the user clicked Cancel and S_TRUE if the user
  1488. // clicked OK.
  1489. //+---------------------------------------------------------------------------
  1490. HRESULT
  1491. CDocHostUIHandler::ShowPageSetupDialog(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD)
  1492. {
  1493. // must match order of PagesetupEnum
  1494. static const SExpandoInfo s_aPagesetupExpandos[] =
  1495. {
  1496.     {OLESTR("pagesetupHeader"),  VT_BSTR},
  1497.     {OLESTR("pagesetupFooter"),  VT_BSTR},
  1498.     {OLESTR("pagesetupStruct"),  VT_INT_PTR}
  1499. };
  1500.     HRESULT                         hr = E_FAIL;
  1501.     PAGESETUPDLG                  * ppagesetupdlg = NULL;
  1502.     PAGESETUPBOXCALLBACKINFO        pagesetupcbi;
  1503.     IHTMLEventObj                 * pEventObj = NULL;
  1504.     const int                       cExpandos = ARRAYSIZE(s_aPagesetupExpandos);
  1505.     DISPID                          aDispid[cExpandos];
  1506.     VARIANT                         aVariant[cExpandos];
  1507.     int                             i;
  1508.     for (i=0; i<cExpandos; i++)
  1509.         VariantInit(aVariant+i);
  1510.     ASSERT(pvarargIn && (V_VT(pvarargIn) == VT_UNKNOWN));
  1511.     if ((V_VT(pvarargIn) != VT_UNKNOWN) || !V_UNKNOWN(pvarargIn))
  1512.         goto Cleanup;
  1513.     if (V_UNKNOWN(pvarargIn)->QueryInterface(IID_IHTMLEventObj, (void **) &pEventObj))
  1514.         goto Cleanup;
  1515.     // Get parameters from event object
  1516.     if (GetParamsFromEvent(
  1517.             pEventObj,
  1518.             cExpandos,
  1519.             aDispid,
  1520.             aVariant,
  1521.             s_aPagesetupExpandos))
  1522.         goto Cleanup;
  1523.     // Copy values from variants
  1524.     StrCpyN((TCHAR*)pagesetupcbi.strHeader,
  1525.         V_BSTR(&aVariant[PagesetupHeader]) ? V_BSTR(&aVariant[PagesetupHeader]) : TEXT(""),
  1526.         ARRAYSIZE(pagesetupcbi.strHeader));
  1527.     StrCpyN((TCHAR*)pagesetupcbi.strFooter,
  1528.         V_BSTR(&aVariant[PagesetupFooter]) ? V_BSTR(&aVariant[PagesetupFooter]) : TEXT(""),
  1529.         ARRAYSIZE(pagesetupcbi.strHeader));
  1530.     ppagesetupdlg = (PAGESETUPDLG *)V_BYREF(&aVariant[PagesetupStruct]);
  1531.     if (!ppagesetupdlg)
  1532.         goto Cleanup;
  1533.     // Set up custom dialog resource fields in pagesetupdlg
  1534.     ppagesetupdlg->Flags |= PSD_ENABLEPAGESETUPHOOK | PSD_ENABLEPAGESETUPTEMPLATE;
  1535.     ppagesetupdlg->lCustData = (LPARAM) &pagesetupcbi;
  1536.     ppagesetupdlg->lpfnPageSetupHook = PageSetupHookProc;
  1537.     ppagesetupdlg->hInstance = MLLoadShellLangResources();
  1538. #ifdef UNIX
  1539.     ppagesetupdlg->lpPageSetupTemplateName = MAKEINTRESOURCE(PAGESETUPDLGORDMOTIF);
  1540. #else
  1541.     ppagesetupdlg->lpPageSetupTemplateName = MAKEINTRESOURCE(PAGESETUPDLGORD);
  1542. #endif // UNIX
  1543.     // Show dialog
  1544.     if (!PageSetupDlg(ppagesetupdlg))
  1545.     {
  1546.         // treat failure as canceling
  1547.         hr = S_FALSE;
  1548.         goto Cleanup;
  1549.     }
  1550.     hr = S_OK;
  1551.     // Save header/footer in event object
  1552.     VARIANT var;
  1553.     V_VT(&var) = VT_BSTR;
  1554.     V_BSTR(&var) = SysAllocString(pagesetupcbi.strHeader ? pagesetupcbi.strHeader : TEXT(""));
  1555.     if (NULL != V_BSTR(&var))
  1556.     {
  1557.         PutParamToEvent(aDispid[PagesetupHeader], &var, pEventObj);
  1558.         VariantClear(&var);
  1559.     }
  1560.     V_VT(&var) = VT_BSTR;
  1561.     V_BSTR(&var) = SysAllocString(pagesetupcbi.strFooter ? pagesetupcbi.strFooter : TEXT(""));
  1562.     if (NULL != V_BSTR(&var))
  1563.     {
  1564.         PutParamToEvent(aDispid[PagesetupFooter], &var, pEventObj);
  1565.         VariantClear(&var);
  1566.     }
  1567. Cleanup:
  1568.     MLFreeLibrary(ppagesetupdlg->hInstance);
  1569.     for (i=0; i<cExpandos; i++)
  1570.         VariantClear(&aVariant[i]);
  1571.     if (pvarargOut)
  1572.         VariantInit(pvarargOut);
  1573.     ATOMICRELEASE(pEventObj);
  1574.     return hr;
  1575. }
  1576. //+---------------------------------------------------------------------------
  1577. //
  1578. //  Callback procedure for OLECMDID_SHOWPRINT dialog
  1579. //
  1580. //+---------------------------------------------------------------------------
  1581. static void SetPreviewBitmap(long bitmapID, HWND hdlg);
  1582. HRESULT GetPrintFileName(HWND hwnd, TCHAR achFilePath[]);
  1583. struct PRINTBOXCALLBACKINFO
  1584. {
  1585.     BOOL    fRootDocumentHasFrameset;
  1586.     BOOL    fAreRatingsEnabled;
  1587.     BOOL    fPrintActiveFrame;
  1588.     BOOL    fPrintLinked;
  1589.     BOOL    fPrintSelection;
  1590.     BOOL    fPrintAsShown;
  1591.     BOOL    fShortcutTable;
  1592.     int     iFontScaling;
  1593.     IOleCommandTarget * pBodyActive;
  1594. #ifdef UNIX
  1595.     int     dmOrientation
  1596. #endif // UNIX
  1597. };
  1598. // Common handling functions for both NT 5 and legacy print dialogs
  1599. void OnInitDialog( HWND hdlg, PRINTBOXCALLBACKINFO * ppcbi )
  1600. {
  1601.     if (ppcbi)
  1602.     {
  1603.         // Set the frameset default depending on contents of the PRINTINFOBAG
  1604.         if (ppcbi->fPrintActiveFrame)
  1605.         {
  1606.             // Check "print selected frame" radiobutton.
  1607.             CheckRadioButton(hdlg, rad4, rad6, rad5);
  1608.             SetPreviewBitmap(IDR_PRINT_PREVIEWONEDOC, hdlg);
  1609. //           BUBUG
  1610. //           If the focus rect gets fixed, we need a way locking it
  1611. //           from shdocvw.
  1612. //             if(ppcbi->pBodyActive);
  1613. //                 ppcbi->pBodyActive->Layout()->LockFocusRect(TRUE);
  1614.         }
  1615.         else // No frame or iframe selected:
  1616.         {
  1617.             // Disable "print selected frame" radiobutton.
  1618.             HWND hwndPrintActiveFrame = GetDlgItem(hdlg, rad5);
  1619.             EnableWindow(hwndPrintActiveFrame, FALSE);
  1620.             // Check "print all frames" radiobutton.
  1621.             CheckRadioButton(hdlg, rad4, rad6, rad6);
  1622.             SetPreviewBitmap(IDR_PRINT_PREVIEWALLDOCS, hdlg);
  1623.             if (!ppcbi->fRootDocumentHasFrameset)
  1624.             {
  1625.                 HWND hwndPrintAsLaidOutOnScreen = GetDlgItem(hdlg, rad4);
  1626.                 // Since no frame or iframe is selected and we are not a frameset,
  1627.                 // disable "print as laid out on screen" radiobutton.
  1628.                 EnableWindow(hwndPrintAsLaidOutOnScreen, FALSE);
  1629.                 SetPreviewBitmap(IDR_PRINT_PREVIEWDISABLED, hdlg);
  1630.             }
  1631. //            if(ppcbi->pBodyActive);
  1632. //                ppcbi->pBodyActive->Layout()->LockFocusRect(FALSE);
  1633.         }
  1634.         HWND hwndSelection = GetDlgItem(hdlg, rad2);
  1635.         if (hwndSelection) EnableWindow(hwndSelection, (ppcbi->fPrintSelection));
  1636.         // If there is no frameset, disable "print all frames" radiobutton.
  1637.         if (!ppcbi->fRootDocumentHasFrameset)
  1638.         {
  1639.             HWND hwndPrintAllFrames = GetDlgItem(hdlg, rad6);
  1640.             EnableWindow(hwndPrintAllFrames, FALSE);
  1641.         }
  1642. #ifdef FONTSIZE_BOX
  1643.         int i=0, cbLen=0;
  1644.         //bugwin16: need to fix this.
  1645.         for (i = 0; i < IDS_PRINT_FONTMAX; i++)
  1646.         {
  1647.             TCHAR   achBuffer[128];
  1648.             cbLen = MLLoadShellLangString(IDS_PRINT_FONTSCALE+i,achBuffer,127);
  1649.             if (cbLen)
  1650.             {
  1651.                 SendDlgItemMessage(hdlg, IDC_SCALING, CB_ADDSTRING, 0, (long) achBuffer);
  1652.             }
  1653.         }
  1654.         if (i>0)
  1655.         {
  1656.             SendDlgItemMessage(hdlg, IDC_SCALING, CB_SETCURSEL, IDS_PRINT_FONTMAX - 1 - ppcbi->iFontScaling, 0);
  1657.         }
  1658. #endif // FONTSIZE_BOX
  1659.         // If ratings are enabled, don't allow recursive printing.
  1660.         if (ppcbi->fAreRatingsEnabled)
  1661.         {
  1662.             HWND hwndPrintLinkedDocuments = GetDlgItem(hdlg, IDC_LINKED);
  1663.             CheckDlgButton(hdlg, IDC_LINKED, BST_UNCHECKED);
  1664.             EnableWindow(hwndPrintLinkedDocuments, FALSE);
  1665.         }
  1666.     }
  1667. #ifdef UNIX
  1668.     {
  1669.        CHAR szPrinterCommand[MAX_PATH];
  1670.        HWND hChkBox;
  1671.        hChkBox = GetDlgItem(hdlg, IDC_LINKED);
  1672.        if (hChkBox)
  1673.            CheckDlgButton(hdlg, IDC_LINKED, FALSE);
  1674.        hChkBox = GetDlgItem(hdlg, IDC_SHORTCUTS);
  1675.        if (hChkBox)
  1676.            CheckDlgButton(hdlg, IDC_SHORTCUTS, FALSE);
  1677.        // Take off Page Setup button from Print Dialog
  1678.        hChkBox = GetDlgItem(hdlg, psh1);
  1679.        if (hChkBox)
  1680.            EnableWindow(hChkBox, TRUE);
  1681.        // Enable user to enter print command
  1682.        MwGetPrintCommand( szPrinterCommand, sizeof( szPrinterCommand ));
  1683.        SendDlgItemMessage(hdlg,edt4, EM_SETLIMITTEXT,
  1684.                           (WPARAM)MAX_COMMAND_LEN, 0);
  1685.        SetDlgItemTextA(hdlg, edt4, szPrinterCommand);
  1686.     }
  1687. #endif  // UNIX
  1688. }
  1689. void OnCommand( HWND hdlg, WPARAM wParam, LPARAM lParam )
  1690. {
  1691.     PRINTBOXCALLBACKINFO * ppcbi;
  1692.     ppcbi = (PRINTBOXCALLBACKINFO *)GetWindowLongPtr(hdlg, DWLP_USER);
  1693.     if (!ppcbi)
  1694.     {
  1695.         return;
  1696.     }
  1697.     switch (GET_WM_COMMAND_ID(wParam, lParam))
  1698.     {
  1699.     case rad1:         // "Print all"
  1700.     case rad3:         // "Print range"
  1701.     case rad2:         // "Print selection" (text selection)
  1702.       {
  1703.         // If we are printing a text selection, and we have a selected frame,
  1704.         // force a print selected frame.
  1705.         if (ppcbi && ppcbi->fPrintActiveFrame && ppcbi->fPrintSelection)
  1706.         {
  1707.             HWND hwndPrintWhatGroup = GetDlgItem(hdlg, grp3);
  1708.             HWND hwndPrintActiveFrame = GetDlgItem(hdlg, rad5);
  1709.             HWND hwndPrintAllFrames = GetDlgItem(hdlg, rad6);
  1710.             HWND hwndPrintSelectedFrame = GetDlgItem(hdlg, rad4);
  1711.             if (hwndPrintWhatGroup)     EnableWindow(hwndPrintWhatGroup, LOWORD(wParam) != rad2);
  1712.             if (hwndPrintActiveFrame)   EnableWindow(hwndPrintActiveFrame, LOWORD(wParam) != rad2);
  1713.             if (hwndPrintAllFrames)     EnableWindow(hwndPrintAllFrames, ppcbi->fRootDocumentHasFrameset && LOWORD(wParam) != rad2);
  1714.             if (hwndPrintSelectedFrame) EnableWindow(hwndPrintSelectedFrame, LOWORD(wParam) != rad2);
  1715.         }
  1716.         break;
  1717.       }
  1718.     case rad4:
  1719.         if (HIWORD(wParam) == BN_CLICKED)
  1720.         {
  1721.             // now change the icon...
  1722.             SetPreviewBitmap(IDR_PRINT_PREVIEW, hdlg);
  1723.             HWND hwnd = GetDlgItem(hdlg, rad2);
  1724.             if (hwnd) EnableWindow(hwnd, FALSE);
  1725.             hwnd = GetDlgItem(hdlg, IDC_SHORTCUTS);
  1726.             if (hwnd) EnableWindow(hwnd, FALSE);
  1727.             hwnd = GetDlgItem(hdlg, IDC_LINKED);
  1728.             if (hwnd) EnableWindow(hwnd, FALSE);
  1729.    //         if(ppcbi->pBodyActive);
  1730.    //             ppcbi->pBodyActive->Layout()->LockFocusRect(FALSE);
  1731.         }
  1732.         break;
  1733.     case rad5:
  1734.         if (HIWORD(wParam) == BN_CLICKED)
  1735.         {
  1736.             // now change the icon
  1737.             SetPreviewBitmap(IDR_PRINT_PREVIEWONEDOC, hdlg);
  1738.             HWND hwnd = GetDlgItem(hdlg, rad2);
  1739.             if (hwnd) EnableWindow(hwnd, (ppcbi->fPrintSelection));
  1740.             hwnd = GetDlgItem(hdlg, IDC_SHORTCUTS);
  1741.             if (hwnd) EnableWindow(hwnd, TRUE);
  1742.             hwnd = GetDlgItem(hdlg, IDC_LINKED);
  1743.             if (hwnd) EnableWindow(hwnd, TRUE);
  1744.    //         if(ppcbi->pBodyActive);
  1745.    //             ppcbi->pBodyActive->Layout()->LockFocusRect(TRUE);
  1746.         }
  1747.         break;
  1748.     case rad6:
  1749.         if (HIWORD(wParam) == BN_CLICKED)
  1750.         {
  1751.             // now change the icon
  1752.             SetPreviewBitmap(IDR_PRINT_PREVIEWALLDOCS, hdlg);
  1753.             HWND hwnd = GetDlgItem(hdlg, rad2);
  1754.             if (hwnd) EnableWindow(hwnd, FALSE);
  1755.             hwnd = GetDlgItem(hdlg, IDC_SHORTCUTS);
  1756.             if (hwnd) EnableWindow(hwnd, TRUE);
  1757.             hwnd = GetDlgItem(hdlg, IDC_LINKED);
  1758.             if (hwnd) EnableWindow(hwnd, TRUE);
  1759.    //         if(ppcbi->pBodyActive);
  1760.    //             ppcbi->pBodyActive->Layout()->LockFocusRect(FALSE);
  1761.         }
  1762.         break;
  1763. #ifdef UNIX
  1764.     case rad7:   // Portrait
  1765.         CheckRadioButton(hdlg, ID_PRINT_R_PORTRAIT,
  1766.                          ID_PRINT_R_LANDSCAPE, ID_PRINT_R_PORTRAIT);
  1767.         break;
  1768.     case rad8:   // Landscape
  1769.         CheckRadioButton(hdlg, ID_PRINT_R_PORTRAIT,
  1770.                          ID_PRINT_R_LANDSCAPE, ID_PRINT_R_LANDSCAPE);
  1771.         break;
  1772. #endif // UNIX
  1773.     }
  1774. }
  1775. void OnHelp( HWND hdlg, WPARAM wParam, LPARAM lParam )
  1776. {
  1777.     LPHELPINFO pHI;
  1778.     pHI = (LPHELPINFO)lParam;
  1779.     if (pHI->iContextType == HELPINFO_WINDOW)   // must be for a control
  1780.     {
  1781.         WinHelp(
  1782.                 (HWND)pHI->hItemHandle,
  1783.                 GetHelpFile(pHI->iCtrlId, (DWORD *) aPrintDialogHelpIDs),
  1784.                 HELP_WM_HELP,
  1785.                 (DWORD_PTR)(LPVOID) aPrintDialogHelpIDs);
  1786.     }
  1787. }
  1788. void OnContextMenu( HWND hdlg, WPARAM wParam, LPARAM lParam )
  1789. {
  1790.     int CtrlID = GetControlID((HWND)wParam, lParam);
  1791.     WinHelp(
  1792.             (HWND)wParam,
  1793.             GetHelpFile(CtrlID, (DWORD *) aPrintDialogHelpIDs),
  1794.             HELP_CONTEXTMENU,
  1795.             (DWORD_PTR)(LPVOID) aPrintDialogHelpIDs);
  1796. }
  1797. void OnApplyOrOK( HWND hdlg, WPARAM wParam, LPARAM lParam )
  1798. {
  1799. #ifdef UNIX
  1800.     CHAR szPrinterCommand[MAX_PATH];
  1801. #endif // UNIX
  1802.     PRINTBOXCALLBACKINFO * ppcbi;
  1803.     ppcbi = (PRINTBOXCALLBACKINFO *)GetWindowLongPtr(hdlg, DWLP_USER);
  1804.     if (ppcbi)
  1805.     {
  1806.         ppcbi->fPrintLinked      = IsDlgButtonChecked(hdlg, IDC_LINKED);
  1807.         ppcbi->fPrintSelection   = IsDlgButtonChecked(hdlg, rad2);
  1808.         ppcbi->fPrintActiveFrame = IsDlgButtonChecked(hdlg, rad5) ||
  1809.                                        ( ppcbi->fPrintSelection &&
  1810.                                          ppcbi->fRootDocumentHasFrameset
  1811.                                         );
  1812.         ppcbi->fPrintAsShown     = IsDlgButtonChecked(hdlg, rad4) ||
  1813.                                        ( ppcbi->fPrintSelection &&
  1814.                                          ppcbi->fRootDocumentHasFrameset
  1815.                                         );
  1816.         ppcbi->fShortcutTable    = IsDlgButtonChecked(hdlg, IDC_SHORTCUTS);
  1817. #ifdef FONTSIZE_BOX
  1818.         ppcbi->iFontScaling      = IDS_PRINT_FONTMAX - 1 - SendDlgItemMessage( hdlg, IDC_SCALING, CB_GETCURSEL, 0,0 );
  1819. #endif
  1820. #ifdef UNIX
  1821.         // Code to deal with orientation on print dialog
  1822.         if ( IsDlgButtonChecked(hdlg, ID_PRINT_R_PORTRAIT) )
  1823.         {
  1824.             ppcbi->dmOrientation = DMORIENT_PORTRAIT;
  1825.         }
  1826.         else
  1827.         {
  1828.             ppcbi->dmOrientation = DMORIENT_LANDSCAPE;
  1829.         }
  1830.         // get user entered printer command
  1831.         GetDlgItemTextA(hdlg, edt4, szPrinterCommand, MAX_PATH);
  1832.         MwSetPrintCommand( szPrinterCommand );
  1833. #endif // UNIX
  1834.     }
  1835. }
  1836. // This is the callback routine (and dlgproc) for the options
  1837. // page in the NT 5 print dialog.
  1838. INT_PTR APIENTRY
  1839. OptionsPageProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  1840. {
  1841.     switch (uiMsg)
  1842.     {
  1843.     case WM_INITDIALOG:
  1844.     {
  1845.         PRINTBOXCALLBACKINFO * ppcbi;
  1846.         ppcbi = (PRINTBOXCALLBACKINFO *) ((PROPSHEETPAGE *)lParam)->lParam;
  1847.         SetWindowLongPtr(hdlg, DWLP_USER, (LONG_PTR)ppcbi);
  1848.         OnInitDialog( hdlg, ppcbi );
  1849.         break;
  1850.     }
  1851.     case WM_NOTIFY:
  1852.         switch (((NMHDR FAR *)lParam)->code)
  1853.         {
  1854.         case PSN_APPLY:
  1855.             OnApplyOrOK( hdlg, wParam, lParam );
  1856.             SetWindowLongPtr (hdlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  1857.             return TRUE;
  1858.             break;
  1859.         case PSN_KILLACTIVE:
  1860.             SetWindowLongPtr (hdlg, DWLP_MSGRESULT, FALSE);
  1861.             return 1;
  1862.             break;
  1863.         case PSN_RESET:
  1864.             SetWindowLongPtr (hdlg, DWLP_MSGRESULT, FALSE);
  1865.             break;
  1866.         }
  1867.         break;
  1868.     case WM_COMMAND:
  1869.         OnCommand( hdlg, wParam, lParam );
  1870.         break;
  1871.     case WM_HELP:
  1872.         OnHelp( hdlg, wParam, lParam );
  1873.         break;
  1874.     case WM_CONTEXTMENU:
  1875.         OnContextMenu( hdlg, wParam, lParam );
  1876.         break;
  1877.     }
  1878.     return FALSE;
  1879. }
  1880. UINT_PTR CALLBACK
  1881. PrintHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  1882. {
  1883.     switch (uiMsg)
  1884.     {
  1885.     case WM_INITDIALOG:
  1886.         if (lParam)
  1887.         {
  1888.             PRINTBOXCALLBACKINFO * ppcbi;
  1889.             ppcbi = (PRINTBOXCALLBACKINFO *) ((PRINTDLG*)lParam)->lCustData;
  1890.             SetWindowLongPtr(hdlg, DWLP_USER, (LONG_PTR)ppcbi);
  1891.             OnInitDialog( hdlg, ppcbi );
  1892.         }
  1893.         return TRUE;
  1894.     case WM_COMMAND:
  1895.         {
  1896.             switch (GET_WM_COMMAND_ID(wParam, lParam))
  1897.             {
  1898.             case IDOK:
  1899.                 OnApplyOrOK( hdlg, wParam, lParam );
  1900.                 break;
  1901.             default:
  1902.                 OnCommand( hdlg, wParam, lParam );
  1903.                 break;
  1904.             }
  1905.         }
  1906.         break;
  1907.     case WM_HELP:
  1908.         OnHelp( hdlg, wParam, lParam );
  1909.         break;
  1910.         //return TRUE;
  1911.     case WM_CONTEXTMENU:
  1912.         OnContextMenu( hdlg, wParam, lParam );
  1913.         break;
  1914.     case WM_DESTROY:
  1915.     {
  1916.         PRINTBOXCALLBACKINFO * ppcbi;
  1917.         ppcbi = (PRINTBOXCALLBACKINFO *)GetWindowLongPtr(hdlg, DWLP_USER);
  1918.         ASSERT(ppcbi);
  1919.   //      if(ppcbi && ppcbi->pBodyActive);
  1920.   //          ppcbi->pBodyActive->Layout()->LockFocusRect(FALSE);
  1921.         break;
  1922.     }
  1923.     }
  1924.     return FALSE;
  1925. }
  1926. void SetPreviewBitmap(long bitmapID, HWND hdlg)
  1927. {
  1928.     // now change the icon...(note these bitmaps are not localized)
  1929.     HBITMAP hNewBitmap, hOldBitmap;
  1930.     hNewBitmap = (HBITMAP) LoadImage(HINST_THISDLL, MAKEINTRESOURCE(bitmapID),
  1931.                            IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_LOADMAP3DCOLORS );
  1932.     ASSERT(hNewBitmap);
  1933.     if (hNewBitmap)
  1934.     {
  1935.         hOldBitmap = (HBITMAP) SendDlgItemMessage(hdlg, IDC_PREVIEW, STM_SETIMAGE,
  1936.                                                   (WPARAM) IMAGE_BITMAP, (LPARAM) hNewBitmap);
  1937.         if (hOldBitmap)
  1938.         {
  1939.             //VERIFY(DeleteObject(hOldBitmap)!=0);
  1940.             int i;
  1941.             i = DeleteObject(hOldBitmap);
  1942.             ASSERT(i!=0);
  1943.         }
  1944.     }
  1945. }
  1946. //+---------------------------------------------------------------------------
  1947. //
  1948. //  Helper for OLECMDID_SHOWPRINT
  1949. //
  1950. //+---------------------------------------------------------------------------
  1951. HRESULT
  1952. CDocHostUIHandler::ShowPrintDialog(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD)
  1953. {
  1954. // the following must match the order of PrintEnum
  1955. static const SExpandoInfo s_aPrintExpandos[] =
  1956. {
  1957.     {OLESTR("printfRootDocumentHasFrameset"),   VT_BOOL},
  1958.     {OLESTR("printfAreRatingsEnabled"),         VT_BOOL},
  1959.     {OLESTR("printfActiveFrame"),               VT_BOOL},
  1960.     {OLESTR("printfLinked"),                    VT_BOOL},
  1961.     {OLESTR("printfSelection"),                 VT_BOOL},
  1962.     {OLESTR("printfAsShown"),                   VT_BOOL},
  1963.     {OLESTR("printfShortcutTable"),             VT_BOOL},
  1964.     {OLESTR("printiFontScaling"),               VT_INT},
  1965.     {OLESTR("printpBodyActiveTarget"),          VT_UNKNOWN},
  1966.     {OLESTR("printStruct"),                     VT_INT_PTR},
  1967.     {OLESTR("printToFileOk"),                   VT_BOOL},
  1968.     {OLESTR("printToFileName"),                 VT_BSTR}
  1969. #ifdef UNIX
  1970.    ,{OLESTR("printdmOrientation"),              VT_INT}
  1971. #endif // UNIX
  1972. };
  1973.     HRESULT                         hr = E_FAIL;
  1974.     PRINTDLG                      * pprintdlg = NULL;
  1975.     PRINTBOXCALLBACKINFO            printcbi;
  1976.     IHTMLEventObj                 * pEventObj = NULL;
  1977.     const int                       cExpandos = ARRAYSIZE(s_aPrintExpandos);
  1978.     DISPID                          aDispid[cExpandos];
  1979.     VARIANT                         aVariant[cExpandos];
  1980.     int                             i;
  1981.     printcbi.pBodyActive = NULL;
  1982.     if (!V_UNKNOWN(pvarargIn))
  1983.         goto Cleanup;
  1984.     if (V_UNKNOWN(pvarargIn)->QueryInterface(IID_IHTMLEventObj, (void **) &pEventObj))
  1985.         goto Cleanup;
  1986.     // Get parameters from event object
  1987.     if (GetParamsFromEvent(
  1988.             pEventObj,
  1989.             cExpandos,
  1990.             aDispid,
  1991.             aVariant,
  1992.             s_aPrintExpandos))
  1993.         goto Cleanup;
  1994.     // Copy values from variants
  1995.     printcbi.fRootDocumentHasFrameset = V_BOOL(&aVariant[PrintfRootDocumentHasFrameset]);
  1996.     printcbi.fAreRatingsEnabled = V_BOOL(&aVariant[PrintfAreRatingsEnabled]);
  1997.     printcbi.fPrintActiveFrame = V_BOOL(&aVariant[PrintfPrintActiveFrame]);
  1998.     printcbi.fPrintLinked = V_BOOL(&aVariant[PrintfPrintLinked]);
  1999.     printcbi.fPrintSelection = V_BOOL(&aVariant[PrintfPrintSelection]);
  2000.     printcbi.fPrintAsShown = V_BOOL(&aVariant[PrintfPrintAsShown]);
  2001.     printcbi.fShortcutTable = V_BOOL(&aVariant[PrintfShortcutTable]);
  2002.     printcbi.iFontScaling = V_INT(&aVariant[PrintiFontScaling]);
  2003.     // BUGBUG if we ever get LockFocusRect, use this field to access it
  2004.     // peterlee 8/7/98
  2005.     /*
  2006.     if (V_UNKNOWN(&aVariant[PrintpBodyActiveTarget]))
  2007.     {
  2008.         if (V_UNKNOWN(&aVariant[PrintpBodyActiveTarget])->QueryInterface(IID_IOleCommandTarget,
  2009.                 (void**)&printcbi.pBodyActive))
  2010.             goto Cleanup;
  2011.     }
  2012.     */
  2013.     pprintdlg = (PRINTDLG *)V_BYREF(&aVariant[PrintStruct]);
  2014.     if (!pprintdlg)
  2015.         goto Cleanup;
  2016.     // Set up custom dialog resource fields in pagesetupdlg
  2017.     pprintdlg->hInstance            = MLLoadShellLangResources();
  2018.     pprintdlg->lCustData            = (LPARAM) &printcbi;
  2019.     pprintdlg->lpfnPrintHook        = PrintHookProc;
  2020. #ifdef UNIX
  2021.     pprintdlg->lpPrintTemplateName  = MAKEINTRESOURCE(PRINTDLGORDMOTIF);
  2022.     pprintdlg->Flags |= PD_SHOWHELP;
  2023.     pprintdlg->Flags |= PD_ENABLESETUPHOOK;
  2024.     pprintdlg->lpfnSetupHook = PageSetupHookProc;
  2025. #else
  2026.     pprintdlg->lpPrintTemplateName  = MAKEINTRESOURCE(PRINTDLGORD);
  2027. #endif // UNIX
  2028.     if (g_bRunOnNT5)
  2029.     {
  2030.         // We want to use the new PrintDlgEx in NT 5, so map all the PrintDlg
  2031.         // settings to the new PrintDlgEx, get a pointer to the new function
  2032.         // and then call it.
  2033.         // Load the function from comdlg32 directly...
  2034.         typedef HRESULT (*PFNPRINTDLGEX)(LPPRINTDLGEX pdex);
  2035.         PFNPRINTDLGEX pfnPrintDlgEx = NULL;
  2036.         HMODULE hComDlg32 = LoadLibrary( TEXT("comdlg32.dll") );
  2037.         if (hComDlg32)
  2038.         {
  2039.             pfnPrintDlgEx = (PFNPRINTDLGEX)GetProcAddress( hComDlg32, "PrintDlgExW" );
  2040.         }
  2041.         // Make sure we can call the function...
  2042.         if (!pfnPrintDlgEx)
  2043.         {
  2044.             if (hComDlg32)
  2045.             {
  2046.                 FreeLibrary( hComDlg32 );
  2047.             }
  2048.             hr = E_FAIL;
  2049.             goto Cleanup;
  2050.         }
  2051.         PRINTDLGEX      pdex;
  2052.         PROPSHEETPAGE   psp;
  2053.         HPROPSHEETPAGE  pages[1];
  2054.         PRINTPAGERANGE  ppr;
  2055.         // Copy over existing settings
  2056.         memset( &pdex, 0, sizeof(pdex) );
  2057.         pdex.lStructSize = sizeof(pdex);
  2058.         pdex.hwndOwner   = pprintdlg->hwndOwner;
  2059.         pdex.hDevMode    = pprintdlg->hDevMode;
  2060.         pdex.hDevNames   = pprintdlg->hDevNames;
  2061.         pdex.hDC         = pprintdlg->hDC;
  2062.         pdex.Flags       = pprintdlg->Flags;
  2063.         pdex.nMinPage    = pprintdlg->nMinPage;
  2064.         pdex.nMaxPage    = pprintdlg->nMaxPage;
  2065.         pdex.nCopies     = pprintdlg->nCopies;
  2066.         // New settings
  2067.         pdex.nStartPage     = START_PAGE_GENERAL;
  2068.         ppr.nFromPage       = pprintdlg->nFromPage;
  2069.         ppr.nToPage         = pprintdlg->nToPage;
  2070.         pdex.nPageRanges    = 1;
  2071.         pdex.nMaxPageRanges = 1;
  2072.         pdex.lpPageRanges   = &ppr;
  2073.         // Create options page
  2074.         memset( &psp, 0, sizeof(psp) );
  2075.         psp.dwSize       = sizeof(psp);
  2076.         psp.dwFlags      = PSP_DEFAULT;
  2077.         psp.hInstance    = pprintdlg->hInstance;
  2078.         psp.pszTemplate  = MAKEINTRESOURCE(IDD_PRINTOPTIONS);
  2079.         psp.pfnDlgProc   = OptionsPageProc;
  2080.         psp.lParam       = (LPARAM)&printcbi;
  2081.         pages[0] = CreatePropertySheetPage(&psp);
  2082.         if (pages[0])
  2083.         {
  2084.             pdex.nPropertyPages = 1;
  2085.             pdex.lphPropertyPages = pages;
  2086.             // Show the dialog
  2087.             hr = pfnPrintDlgEx(&pdex);
  2088.             if (SUCCEEDED(hr))
  2089.             {
  2090.                 hr = S_FALSE;
  2091.                 if ((pdex.dwResultAction == PD_RESULT_PRINT) || (pdex.Flags & PD_RETURNDEFAULT))
  2092.                 {
  2093.                     // copy back values which might have changed
  2094.                     // during the call to PrintDlgEx
  2095.                     pprintdlg->Flags     = pdex.Flags;
  2096.                     pprintdlg->hDevMode  = pdex.hDevMode;
  2097.                     pprintdlg->hDevNames = pdex.hDevNames;
  2098.                     pprintdlg->nCopies   = (WORD)pdex.nCopies;
  2099.                     pprintdlg->nFromPage = (WORD)ppr.nFromPage;
  2100.                     pprintdlg->nToPage   = (WORD)ppr.nToPage;
  2101.                     if (pprintdlg->Flags & PD_RETURNDC)
  2102.                     {
  2103.                         pprintdlg->hDC = pdex.hDC;
  2104.                     }
  2105.                     hr = S_OK;
  2106.                 }
  2107.                 else if ((pdex.Flags & (PD_RETURNDC | PD_RETURNIC)) && pdex.hDC)
  2108.                 {
  2109.                     DeleteDC(pdex.hDC);
  2110.                     pdex.hDC = NULL;
  2111.                 }
  2112.             }
  2113.             else
  2114.             {
  2115.                 hr = S_FALSE;
  2116.             }
  2117.             FreeLibrary( hComDlg32 );
  2118.         }
  2119.         else
  2120.         {
  2121.             FreeLibrary( hComDlg32 );
  2122.             hr = E_OUTOFMEMORY;
  2123.             goto Cleanup;
  2124.         }
  2125.     }
  2126.     else
  2127.     {
  2128.         pprintdlg->Flags |= PD_ENABLEPRINTTEMPLATE | PD_ENABLEPRINTHOOK;
  2129.         // Show dialog
  2130.         if (!PrintDlg(pprintdlg))
  2131.         {
  2132.            // treat failure as canceling
  2133.             hr = S_FALSE;
  2134.             goto Cleanup;
  2135.         }
  2136.         hr = S_OK;
  2137.     }
  2138.     // Write changed values to event object
  2139.     VARIANT var;
  2140.     V_VT(&var) = VT_BOOL;
  2141.     V_BOOL(&var) = printcbi.fPrintLinked ? VARIANT_TRUE : VARIANT_FALSE;
  2142.     PutParamToEvent(aDispid[PrintfPrintLinked], &var, pEventObj);
  2143.     V_BOOL(&var) = printcbi.fPrintActiveFrame ? VARIANT_TRUE : VARIANT_FALSE;
  2144.     PutParamToEvent(aDispid[PrintfPrintActiveFrame], &var, pEventObj);
  2145.     V_BOOL(&var) = printcbi.fPrintAsShown ? VARIANT_TRUE : VARIANT_FALSE;
  2146.     PutParamToEvent(aDispid[PrintfPrintAsShown], &var, pEventObj);
  2147.     V_BOOL(&var) = printcbi.fShortcutTable ? VARIANT_TRUE : VARIANT_FALSE;
  2148.     PutParamToEvent(aDispid[PrintfShortcutTable], &var, pEventObj);
  2149. #ifdef FONTSIZE_BOX
  2150.     V_VT(&var) = VT_INT;
  2151.     V_INT(&var) = printcbi.iFontScaling;
  2152.     PutParamToEvent(aDispid[PrintiFontScaling], &var, pEventObj);
  2153. #endif // FONTSIZE_BOX
  2154. #ifdef UNIX
  2155.     V_VT(&var) = VT_INT;
  2156.     V_INT(&var) = printcbi.dmOrientation;
  2157.     PutParamToEvent(aDispid[PrintdmOrientation], &var, pEventObj);
  2158. #endif // UNIX
  2159.     // now pop up the fileselection dialog and save the filename...
  2160.     // this is the only place where we can make this modal
  2161.     BOOL fPrintToFileOk;
  2162.     fPrintToFileOk = FALSE;
  2163.     if ((pprintdlg->Flags & PD_PRINTTOFILE) != 0)
  2164.     {
  2165.         // Get the save file path from the event object
  2166.         TCHAR achPrintToFileName[MAX_PATH];
  2167.         StrCpyN(achPrintToFileName,
  2168.             V_BSTR(&aVariant[PrintToFileName]) ? V_BSTR(&aVariant[PrintToFileName]) : TEXT(""),
  2169.             ARRAYSIZE(achPrintToFileName));
  2170.         if (!GetPrintFileName(pprintdlg->hwndOwner, achPrintToFileName) &&
  2171.                 achPrintToFileName)
  2172.         {
  2173.             fPrintToFileOk = TRUE;
  2174.             V_VT(&var) = VT_BSTR;
  2175.             V_BSTR(&var) = SysAllocString(achPrintToFileName);
  2176.             if (NULL != V_BSTR(&var))
  2177.             {
  2178.                 PutParamToEvent(aDispid[PrintToFileName], &var, pEventObj);
  2179.                 VariantClear(&var);
  2180.             }
  2181.         }
  2182.     }
  2183.     V_VT(&var) = VT_BOOL;
  2184.     V_BOOL(&var) = fPrintToFileOk ? VARIANT_TRUE : VARIANT_FALSE;
  2185.     PutParamToEvent(aDispid[PrintToFileOk], &var, pEventObj);
  2186. Cleanup:
  2187.     MLFreeLibrary(pprintdlg->hInstance);
  2188.     for (i=0; i<cExpandos; i++)
  2189.         VariantClear(&aVariant[i]);
  2190.     if (pvarargOut)
  2191.         VariantInit(pvarargOut);
  2192.     ATOMICRELEASE(pEventObj);
  2193.     ATOMICRELEASE(printcbi.pBodyActive);
  2194.     return hr;
  2195. }
  2196. //+---------------------------------------------------------------------------
  2197. //
  2198. //   Callback procedure for PrintToFile Dialog
  2199. //
  2200. //+---------------------------------------------------------------------------
  2201. UINT_PTR APIENTRY PrintToFileHookProc(HWND hdlg,
  2202.                               UINT uiMsg,
  2203.                               WPARAM wParam,
  2204.                               LPARAM lParam)
  2205. {
  2206.     switch (uiMsg)
  2207.     {
  2208.         case WM_INITDIALOG:
  2209.         {
  2210.             int      cbLen;
  2211.             TCHAR    achOK[MAX_PATH];
  2212.             // change "save" to "ok"
  2213.             cbLen = MLLoadShellLangString(IDS_PRINTTOFILE_OK,achOK,MAX_PATH);
  2214.             if (cbLen < 1)
  2215.                 StrCpyN(achOK, TEXT("OK"), ARRAYSIZE(achOK));
  2216.     //        SetDlgItemText(hdlg, IDOK, _T("OK"));
  2217.             SetDlgItemText(hdlg, IDOK, achOK);
  2218.             // ...and, finally force us into foreground (needed for Win95, Bug : 13368)
  2219.             ::SetForegroundWindow(hdlg);
  2220.             break;
  2221.         }
  2222.     }
  2223.     return FALSE;
  2224. }
  2225. //+---------------------------------------------------------------------------
  2226. //
  2227. //  Member:     GetPrintFileName
  2228. //
  2229. //  Synopsis:   Opens up the customized save file dialog and gets
  2230. //              a filename for the printoutput
  2231. //  Returns:
  2232. //
  2233. //----------------------------------------------------------------------------
  2234. HRESULT GetPrintFileName(HWND hwnd, TCHAR achFilePath[])
  2235. {
  2236.     OPENFILENAME    openfilename;
  2237.     int             cbLen;
  2238.     TCHAR           achTitlePrintInto[MAX_PATH];
  2239.     TCHAR           achFilePrintInto[MAX_PATH];
  2240.     TCHAR           achFilter[MAX_PATH];
  2241.     TCHAR           achPath[MAX_PATH];
  2242.     HRESULT         hr = E_FAIL;
  2243.     memset(&openfilename,0,sizeof(openfilename));
  2244.     openfilename.lStructSize = sizeof(openfilename);
  2245.     openfilename.hwndOwner = hwnd;
  2246.     cbLen = MLLoadShellLangString(IDS_PRINTTOFILE_TITLE,achTitlePrintInto,MAX_PATH);
  2247.     ASSERT (cbLen && "could not load the resource");
  2248.     if (cbLen > 0)
  2249.         openfilename.lpstrTitle = achTitlePrintInto;
  2250.     // guarantee trailing 0 to terminate the filter string
  2251.     memset(achFilter, 0, sizeof(TCHAR)*MAX_PATH);
  2252.     cbLen = MLLoadShellLangString(IDS_PRINTTOFILE_SPEC,achFilter,MAX_PATH-2);
  2253.     ASSERT (cbLen && "could not load the resource");
  2254.     if (cbLen>0)
  2255.     {
  2256.         for (; cbLen >= 0; cbLen--)
  2257.         {
  2258.             if (achFilter[cbLen]== L',')
  2259.             {
  2260.                 achFilter[cbLen] = 0;
  2261.             }
  2262.         }
  2263.     }
  2264.     openfilename.nMaxFileTitle = lstrlen(openfilename.lpstrTitle);
  2265.     StrCpyN(achFilePrintInto, TEXT(""), ARRAYSIZE(achFilePrintInto));
  2266.     openfilename.lpstrFile = achFilePrintInto;
  2267.     openfilename.nMaxFile = MAX_PATH;
  2268.     openfilename.Flags = OFN_NOREADONLYRETURN | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT |
  2269.                         OFN_ENABLEHOOK | OFN_NOCHANGEDIR;
  2270.     openfilename.lpfnHook = PrintToFileHookProc;
  2271.     openfilename.lpstrFilter = achFilter;
  2272.     openfilename.nFilterIndex = 1;
  2273.     StrCpyN(achPath, achFilePath, ARRAYSIZE(achPath));
  2274.     openfilename.lpstrInitialDir = *achPath ? achPath : NULL;
  2275.     if (GetSaveFileName(&openfilename))
  2276.     {
  2277.         StrCpyN(achFilePath, openfilename.lpstrFile, MAX_PATH);
  2278.         hr = S_OK;
  2279.     }
  2280.     if (hr)
  2281.         *achFilePath = NULL;
  2282.     return hr;
  2283. }
  2284. //+---------------------------------------------------------------------------
  2285. //
  2286. //  Helpers for OLECMDID_PROPERTIES
  2287. //
  2288. //+---------------------------------------------------------------------------
  2289. HRESULT
  2290. CDocHostUIHandler::ShowPropertysheetDialog(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD)
  2291. {
  2292. // must match order of PropertysheetEnum
  2293. static const SExpandoInfo s_aPropertysheetExpandos[] =
  2294. {
  2295.     {OLESTR("propertysheetPunks"),  VT_SAFEARRAY}
  2296. };
  2297.     HRESULT             hr;
  2298.     HWND                hwnd = NULL;
  2299.     HWND                hwndParent;
  2300.     IUnknown          * punk = NULL;
  2301.     OLECMD              olecmd = {0, 0};
  2302.     int                 cUnk = 0;
  2303.     IUnknown * HUGEP  * apUnk = NULL;
  2304.     OCPFIPARAMS         ocpfiparams;
  2305.     CAUUID              ca = { 0, 0 };
  2306.     RECT                rc = {0, 0, 0, 0};
  2307.     RECT                rcDesktop = {0, 0, 0, 0};
  2308.     SIZE                pixelOffset;
  2309.     SIZE                metricOffset = {0, 0};
  2310.     IHTMLEventObj     * pEventObj = NULL;
  2311.     const int           cExpandos = ARRAYSIZE(s_aPropertysheetExpandos);
  2312.     VARIANT             aVariant[cExpandos];
  2313.     DISPID              aDispid[cExpandos];
  2314.     SAFEARRAY         * psafearray = NULL;
  2315.     ASSERT(pvarargIn && V_VT(pvarargIn) == VT_UNKNOWN && V_UNKNOWN(pvarargIn));
  2316.     if (!pvarargIn || (V_VT(pvarargIn) != VT_UNKNOWN) || !V_UNKNOWN(pvarargIn))
  2317.     {
  2318.         hr = E_INVALIDARG;
  2319.         goto Cleanup;
  2320.     }
  2321.     // get the hwnd
  2322.     punk = V_UNKNOWN(pvarargIn);
  2323.     hr = GetHwndFromUnknown(punk, &hwnd);
  2324.     if (hr)
  2325.         goto Cleanup;
  2326.     // get the SafeArray expando from the event obj
  2327.     hr = GetEventFromUnknown(punk, &pEventObj);
  2328.     if (hr)
  2329.         goto Cleanup;
  2330.     hr = GetParamsFromEvent(
  2331.             pEventObj,
  2332.             cExpandos,
  2333.             aDispid,
  2334.             aVariant,
  2335.             s_aPropertysheetExpandos);
  2336.     if (hr)
  2337.         goto Cleanup;
  2338.     psafearray = V_ARRAY(&aVariant[PropertysheetPunks]);
  2339.     // verify array dimensions
  2340.     if (SafeArrayGetDim(psafearray) != 1)
  2341.     {
  2342.         hr = E_INVALIDARG;
  2343.         goto Cleanup;
  2344.     }
  2345.     // get array size, adding one to 0-based size
  2346.     hr = SafeArrayGetUBound(psafearray, 1, (long*)&cUnk);
  2347.     if (hr)
  2348.         goto Cleanup;
  2349.     cUnk++;
  2350.     if (cUnk)
  2351.     {
  2352.         // get pointer to vector
  2353.         hr = SafeArrayAccessData(psafearray, (void HUGEP* FAR*)&apUnk);
  2354.         if (hr)
  2355.             goto Cleanup;
  2356.     }
  2357.     else
  2358.     {
  2359.         cUnk = 1;
  2360.         apUnk = &punk;
  2361.     }
  2362.     // Compute pages to load
  2363.     hr = THR(GetCommonPages(cUnk, apUnk, &ca));
  2364.     if (hr)
  2365.         goto Cleanup;
  2366.     //  compute top-level parent
  2367.     while ( hwndParent = GetParent(hwnd) )
  2368.         hwnd = hwndParent;
  2369.     // BUGBUG dialog box is not centered on screen
  2370.     // the ocpfi seems to be ignoring the x, y values in ocpfiparams
  2371.     // Compute offset to center of screen
  2372.     GetWindowRect(GetDesktopWindow(), &rcDesktop);
  2373.     GetWindowRect(hwnd, &rc);
  2374.     pixelOffset.cx = (rcDesktop.right - rcDesktop.left)/2 - rc.left;
  2375.     pixelOffset.cy = (rcDesktop.bottom - rcDesktop.top)/2 - rc.top;
  2376.     AtlPixelToHiMetric(&pixelOffset, &metricOffset);
  2377.     memset(&ocpfiparams, 0, sizeof(ocpfiparams));
  2378.     ocpfiparams.cbStructSize = sizeof(ocpfiparams);
  2379.     ocpfiparams.hWndOwner = hwnd;
  2380.     ocpfiparams.x = metricOffset.cx;
  2381.     ocpfiparams.y = metricOffset.cy;
  2382.     ocpfiparams.lpszCaption = NULL;
  2383.     ocpfiparams.cObjects = cUnk;
  2384.     ocpfiparams.lplpUnk = apUnk;
  2385.     ocpfiparams.cPages = ca.cElems;
  2386.     ocpfiparams.lpPages = ca.pElems;
  2387.     ocpfiparams.lcid = GetUserDefaultLCID();
  2388.     ocpfiparams.dispidInitialProperty = DISPID_UNKNOWN;
  2389.     // OleCreatePropertyFrameIndirect throws its own dialog on error,
  2390.     // so we don't want to display that twice
  2391.     THR(OleCreatePropertyFrameIndirect(&ocpfiparams));
  2392.     hr = S_OK;
  2393. Cleanup:
  2394.     if (ca.cElems)
  2395.         CoTaskMemFree(ca.pElems);
  2396.     if (psafearray && apUnk)
  2397.         SafeArrayUnaccessData(psafearray);
  2398.     if (pvarargOut)
  2399.         VariantInit(pvarargOut);
  2400.     for (int i=0; i<cExpandos; i++)
  2401.         VariantClear(&aVariant[i]);
  2402.     ATOMICRELEASE(pEventObj);
  2403.     return hr;
  2404. }
  2405. HRESULT
  2406. CDocHostUIHandler::GetCommonPages(int cUnk, IUnknown **apUnk, CAUUID *pca)
  2407. {
  2408.     HRESULT                hr;
  2409.     int                    i;
  2410.     UINT                   iScan, iFill, iCompare;
  2411.     BOOL                   fFirst = TRUE;
  2412.     CAUUID                 caCurrent;
  2413.     IUnknown *             pUnk;
  2414.     ISpecifyPropertyPages *pSPP;
  2415.     pca->cElems = 0;
  2416.     pca->pElems = NULL;
  2417.     for (i = 0; i < cUnk; i++)
  2418.     {
  2419.         pUnk = apUnk[i];
  2420.         ASSERT(pUnk);
  2421.         hr = THR(pUnk->QueryInterface(
  2422.                 IID_ISpecifyPropertyPages,
  2423.                 (void **)&pSPP));
  2424.         if (hr)
  2425.             goto Cleanup;
  2426.          hr = THR(pSPP->GetPages(fFirst ? pca : &caCurrent));
  2427.          ATOMICRELEASE(pSPP);
  2428.          if (hr)
  2429.              goto Cleanup;
  2430.          if (fFirst)
  2431.              continue;
  2432.          // keep only the common pages
  2433.          else
  2434.          {
  2435.              for (iScan = 0, iFill = 0; iScan < pca->cElems; iScan++)
  2436.              {
  2437.                  for (iCompare = 0; iCompare < caCurrent.cElems; iCompare++)
  2438.                  {
  2439.                      if (caCurrent.pElems[iCompare] == pca->pElems[iScan])
  2440.                          break;
  2441.                  }
  2442.                  if (iCompare != caCurrent.cElems)
  2443.                  {
  2444.                      pca->pElems[iFill++] = pca->pElems[iScan];
  2445.                  }
  2446.              }
  2447.              pca->cElems = iFill;
  2448.              CoTaskMemFree(caCurrent.pElems);
  2449.          }
  2450.     }
  2451. Cleanup:
  2452.     return hr;
  2453. }
  2454. //+---------------------------------------------------------------------------
  2455. //
  2456. //  Helper for SHDVID_CLSIDTOMONIKER
  2457. //
  2458. //+---------------------------------------------------------------------------
  2459. struct HTMLPAGECACHE
  2460. {
  2461.     const CLSID *   pclsid;
  2462.     TCHAR *         ach;
  2463. };
  2464. HRESULT CDocHostUIHandler::ClsidToMoniker(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  2465. {
  2466.     static const HTMLPAGECACHE s_ahtmlpagecache[] =
  2467.     {
  2468.         &CLSID_CAnchorBrowsePropertyPage,           _T("anchrppg.ppg"),
  2469.         &CLSID_CImageBrowsePropertyPage,            _T("imageppg.ppg"),
  2470.         &CLSID_CDocBrowsePropertyPage,              _T("docppg.ppg"),
  2471.     };
  2472.     HRESULT                 hr = E_FAIL;
  2473.     IMoniker              * pmk = NULL;
  2474.     IUnknown              * pUnk = NULL;
  2475.     int                     i;
  2476.     const HTMLPAGECACHE   * phtmlentry;
  2477.     const CLSID           * pclsid;
  2478.     ASSERT(pvarargIn);
  2479.     ASSERT(pvarargOut);
  2480.     ASSERT(V_VT(pvarargIn) == VT_UINT_PTR && V_BYREF(pvarargIn));
  2481.     if (!pvarargIn || V_VT(pvarargIn) != VT_UINT_PTR || !V_BYREF(pvarargIn))
  2482.         goto Cleanup;
  2483.     pclsid = (CLSID *)V_BYREF(pvarargIn);
  2484.     if (!pvarargOut)
  2485.         goto Cleanup;
  2486.     VariantInit(pvarargOut);
  2487.     // lookup the resource from the CLSID
  2488.     for (i = ARRAYSIZE(s_ahtmlpagecache) - 1, phtmlentry = s_ahtmlpagecache;
  2489.         i >= 0;
  2490.         i--, phtmlentry++)
  2491.     {
  2492.         ASSERT(phtmlentry->pclsid && phtmlentry->ach);
  2493.         if (IsEqualCLSID(*pclsid, *phtmlentry->pclsid))
  2494.         {
  2495.             // create a moniker for the dialog resource
  2496.             TCHAR szResURL[MAX_URL_STRING];
  2497. #ifndef UNIX
  2498.             // IEUNIX: BUGBUG , should call Wrap version here ???
  2499.             hr = MLBuildResURL(TEXT("shdoclc.dll"),
  2500.                        HINST_THISDLL,
  2501.                        ML_CROSSCODEPAGE,
  2502.                        phtmlentry->ach,
  2503.                        szResURL,
  2504.                        ARRAYSIZE(szResURL));
  2505. #else
  2506.             hr = MLBuildResURLWrap(TEXT("shdoclc.dll"),
  2507.                        HINST_THISDLL,
  2508.                        ML_CROSSCODEPAGE,
  2509.                        phtmlentry->ach,
  2510.                        szResURL,
  2511.                        ARRAYSIZE(szResURL),
  2512.                        TEXT("shdocvw.dll"));
  2513. #endif
  2514.             if (hr)
  2515.                 goto Cleanup;
  2516.             hr = CreateURLMoniker(NULL, szResURL, &pmk);
  2517.             if (hr)
  2518.                 goto Cleanup;
  2519.             break;
  2520.         }
  2521.     }
  2522.     if (!pmk)
  2523.         goto Cleanup;
  2524.     // return the moniker
  2525.     hr = pmk->QueryInterface(IID_IUnknown, (void**)&pUnk);
  2526.     if (hr)
  2527.         goto Cleanup;
  2528.     else
  2529.     {
  2530.         V_VT(pvarargOut) = VT_UNKNOWN;
  2531.         V_UNKNOWN(pvarargOut) = pUnk;
  2532.         V_UNKNOWN(pvarargOut)->AddRef();
  2533.     }
  2534. Cleanup:
  2535.     ATOMICRELEASE(pUnk);
  2536.     ATOMICRELEASE(pmk);
  2537.     return hr;
  2538. }
  2539. STDMETHODIMP CDocHostUIHandler::Invoke(
  2540.     DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, 
  2541.     VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
  2542. {
  2543.     HRESULT hr = S_OK;
  2544.     if (pDispParams && pDispParams->cArgs>=1)
  2545.     {
  2546.         if (pDispParams->rgvarg[0].vt == VT_DISPATCH)
  2547.         {
  2548.             IHTMLEventObj *pObj=NULL;
  2549.             if (SUCCEEDED(pDispParams->rgvarg[0].pdispVal->QueryInterface(IID_IHTMLEventObj, (void **)&pObj) && pObj))
  2550.             {
  2551.                 BSTR bstrEvent=NULL;
  2552.                 pObj->get_type(&bstrEvent);
  2553.                 if (bstrEvent)
  2554.                 {
  2555.                     ASSERT(!StrCmpCW(bstrEvent, L"unload"));
  2556.                     IServiceProvider* psp;
  2557.                     
  2558.                     hr = IUnknown_QueryService(_punkSite, SID_STopLevelBrowser, IID_IServiceProvider, (LPVOID*)&psp);
  2559.                     if (SUCCEEDED(hr))
  2560.                     {
  2561.                         IWebBrowser2* pwb2;
  2562.                     
  2563.                         hr = psp->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (LPVOID*)&pwb2);
  2564.                         if (SUCCEEDED(hr))
  2565.                         {
  2566.                             IHTMLWindow2* pWindow;
  2567.                             // we shouldn't be catching this event if the dialog is not up
  2568.                             if (EVAL(IsFindDialogUp(pwb2, &pWindow)))
  2569.                             {
  2570.                                 if (NULL != _pOptionsHolder)
  2571.                                 {
  2572.                                     BSTR bstrFindText;
  2573.                                     
  2574.                                     _pOptionsHolder->get_findText(&bstrFindText);
  2575.                                     ATOMICRELEASE(_pOptionsHolder);
  2576.                                     PutFindText(pwb2, bstrFindText);
  2577.                                     SysFreeString(bstrFindText);
  2578.                                 }
  2579.                                 
  2580.                                 ASSERT(pWindow);
  2581.                                 
  2582.                                 BSTR bstrOnunload = SysAllocString(L"onunload");
  2583.                                 if (bstrOnunload)
  2584.                                 {
  2585.                                     IHTMLWindow3 * pWin3;
  2586.                                     if (SUCCEEDED(pWindow->QueryInterface(IID_IHTMLWindow3, (void**)&pWin3)))
  2587.                                     {
  2588.                                         pWin3->detachEvent(bstrOnunload, (IDispatch*)this);
  2589.                                         pWin3->Release();
  2590.                                     }
  2591.                                     SysFreeString(bstrOnunload);
  2592.                                 }
  2593.                                  //this is the one that should release the dialog (the pWinOut from ShowFindDialog())
  2594.                                 pWindow->Release();
  2595.                                 BSTR bstrName = SysAllocString(STR_FIND_DIALOG_NAME);
  2596.                                 if (bstrName)
  2597.                                 {
  2598.                                     VARIANT var;
  2599.                                     VariantInit(&var);
  2600.                                     var.vt = VT_DISPATCH;
  2601.                                     var.pdispVal = NULL;
  2602.                                     pwb2->PutProperty(bstrName, var);
  2603.                                     SysFreeString(bstrName);
  2604.                                 }
  2605.                             }
  2606.                             pwb2->Release();
  2607.                         }
  2608.                         psp->Release();
  2609.                     }
  2610.                     SysFreeString(bstrEvent);
  2611.                 }
  2612.                 pObj->Release();
  2613.             }
  2614.         }
  2615.     }
  2616.     return hr;
  2617. }