#include "priv.h" #include "resource.h" #include "mshtmcid.h" #include #ifndef X_IEHELPID_H_ #define X_IEHELPID_H_ #include "iehelpid.h" #endif #ifdef UNIX #ifndef X_MAINWIN_H_ #define X_MAINWIN_H_ # include #endif #endif // UNIX #include "dhuihand.h" #define DM_DOCHOSTUIHANDLER 0 #define CX_CONTEXTMENUOFFSET 2 #define CY_CONTEXTMENUOFFSET 2 //+------------------------------------------------------------------------ // // WARNING! (greglett) // // The following defines were stolen from commdlg.h. Since SHDOCVW is // compiled with WINVER=0x0400 and these defines are WINVER=0x0500 they // needed to be copied and included here. These must be kept in sync // with the commdlg.h definitions. // // If shdocvw ever gets compiled with WINVER=0x0500 or above, then these // can be removed. // //------------------------------------------------------------------------- #define NEED_BECAUSE_COMPILED_AT_WINVER_4 #ifdef NEED_BECAUSE_COMPILED_AT_WINVER_4 // // Define the start page for the print dialog when using PrintDlgEx. // #define START_PAGE_GENERAL 0xffffffff // // Page Range structure for PrintDlgEx. // typedef struct tagPRINTPAGERANGE { DWORD nFromPage; DWORD nToPage; } PRINTPAGERANGE, *LPPRINTPAGERANGE; // // PrintDlgEx structure. // typedef struct tagPDEXA { DWORD lStructSize; // size of structure in bytes HWND hwndOwner; // caller's window handle HGLOBAL hDevMode; // handle to DevMode HGLOBAL hDevNames; // handle to DevNames HDC hDC; // printer DC/IC or NULL DWORD Flags; // PD_ flags DWORD Flags2; // reserved DWORD ExclusionFlags; // items to exclude from driver pages DWORD nPageRanges; // number of page ranges DWORD nMaxPageRanges; // max number of page ranges LPPRINTPAGERANGE lpPageRanges; // array of page ranges DWORD nMinPage; // min page number DWORD nMaxPage; // max page number DWORD nCopies; // number of copies HINSTANCE hInstance; // instance handle LPCSTR lpPrintTemplateName; // template name for app specific area LPUNKNOWN lpCallback; // app callback interface DWORD nPropertyPages; // number of app property pages in lphPropertyPages HPROPSHEETPAGE *lphPropertyPages; // array of app property page handles DWORD nStartPage; // start page id DWORD dwResultAction; // result action if S_OK is returned } PRINTDLGEXA, *LPPRINTDLGEXA; // // PrintDlgEx structure. // typedef struct tagPDEXW { DWORD lStructSize; // size of structure in bytes HWND hwndOwner; // caller's window handle HGLOBAL hDevMode; // handle to DevMode HGLOBAL hDevNames; // handle to DevNames HDC hDC; // printer DC/IC or NULL DWORD Flags; // PD_ flags DWORD Flags2; // reserved DWORD ExclusionFlags; // items to exclude from driver pages DWORD nPageRanges; // number of page ranges DWORD nMaxPageRanges; // max number of page ranges LPPRINTPAGERANGE lpPageRanges; // array of page ranges DWORD nMinPage; // min page number DWORD nMaxPage; // max page number DWORD nCopies; // number of copies HINSTANCE hInstance; // instance handle LPCWSTR lpPrintTemplateName; // template name for app specific area LPUNKNOWN lpCallback; // app callback interface DWORD nPropertyPages; // number of app property pages in lphPropertyPages HPROPSHEETPAGE *lphPropertyPages; // array of app property page handles DWORD nStartPage; // start page id DWORD dwResultAction; // result action if S_OK is returned } PRINTDLGEXW, *LPPRINTDLGEXW; #ifdef UNICODE typedef PRINTDLGEXW PRINTDLGEX; typedef LPPRINTDLGEXW LPPRINTDLGEX; #else typedef PRINTDLGEXA PRINTDLGEX; typedef LPPRINTDLGEXA LPPRINTDLGEX; #endif // UNICODE HRESULT APIENTRY PrintDlgExA(LPPRINTDLGEXA); HRESULT APIENTRY PrintDlgExW(LPPRINTDLGEXW); #ifdef UNICODE #define PrintDlgEx PrintDlgExW #else #define PrintDlgEx PrintDlgExA #endif // !UNICODE // // Result action ids for PrintDlgEx. // #define PD_RESULT_CANCEL 0 #define PD_RESULT_PRINT 1 #define PD_RESULT_APPLY 2 #define PD_CURRENTPAGE 0x00400000 #define PD_NOCURRENTPAGE 0x00800000 #endif // NEED_BECAUSE_COMPILED_AT_WINVER_4 //+------------------------------------------------------------------------ // // Useful combinations of flags for IOleCommandTarget // //------------------------------------------------------------------------- #define OLECMDSTATE_DISABLED OLECMDF_SUPPORTED #define OLECMDSTATE_UP (OLECMDF_SUPPORTED | OLECMDF_ENABLED) #define OLECMDSTATE_DOWN (OLECMDF_SUPPORTED | OLECMDF_ENABLED | OLECMDF_LATCHED) #define OLECMDSTATE_NINCHED (OLECMDF_SUPPORTED | OLECMDF_ENABLED | OLECMDF_NINCHED) struct SExpandoInfo { TCHAR * name; VARTYPE type; }; // Enumerations for custom expandos enum MessageEnum { MessageText, MessageCaption, MessageStyle, MessageHelpFile, MessageHelpContext }; enum PagesetupEnum { PagesetupHeader, PagesetupFooter, PagesetupStruct }; enum PrintEnum { PrintfRootDocumentHasFrameset, PrintfAreRatingsEnabled, PrintfPrintActiveFrame, PrintfPrintLinked, PrintfPrintSelection, PrintfPrintAsShown, PrintfShortcutTable, PrintiFontScaling, PrintpBodyActiveTarget, PrintStruct, PrintToFileOk, PrintToFileName, PrintfPrintActiveFrameEnabled, }; enum PropertysheetEnum { PropertysheetPunks }; #ifdef UNIX # define ID_PRINT_R_PORTRAIT rad7 # define ID_PRINT_R_LANDSCAPE rad8 # define MAX_COMMAND_LEN 255 #endif // UNIX //---------------------------------------------------------------------------- // // Arrays describing helpcontextids for PageSetup/Print // //---------------------------------------------------------------------------- static const DWORD aPrintDialogHelpIDs[] = { stc6, IDH_PRINT_CHOOSE_PRINTER, cmb4, IDH_PRINT_CHOOSE_PRINTER, psh2, IDH_PRINT_PROPERTIES, stc7, IDH_PRINT_SETUP_DETAILS, stc8, IDH_PRINT_SETUP_DETAILS, stc9, IDH_PRINT_SETUP_DETAILS, stc10, IDH_PRINT_SETUP_DETAILS, stc12, IDH_PRINT_SETUP_DETAILS, stc11, IDH_PRINT_SETUP_DETAILS, stc14, IDH_PRINT_SETUP_DETAILS, stc13, IDH_PRINT_SETUP_DETAILS, stc5, IDH_PRINT_TO_FILE, chx1, IDH_PRINT_TO_FILE, ico3, IDH_PRINT_COLLATE, chx2, IDH_PRINT_COLLATE, grp1, IDH_PRINT_RANGE, rad1, IDH_PRINT_RANGE, // all rad2, IDH_PRINT_RANGE, // selection rad3, IDH_PRINT_RANGE, // pages stc2, IDH_PRINT_RANGE, stc3, IDH_PRINT_RANGE, edt1, IDH_PRINT_RANGE, edt2, IDH_PRINT_RANGE, edt3, IDH_PRINT_COPIES, rad4, IDH_PRINT_SCREEN, rad5, IDH_PRINT_SEL_FRAME, rad6, IDH_PRINT_ALL_FRAME, IDC_LINKED, IDH_PRINT_LINKS, IDC_SHORTCUTS, IDH_PRINT_SHORTCUTS, 0, 0 }; static const DWORD aPageSetupDialogHelpIDs[] = { psh3, IDH_PRINT_PRINTER_SETUP, stc2, IDH_PAGE_PAPER_SIZE, cmb2, IDH_PAGE_PAPER_SIZE, stc3, IDH_PAGE_PAPER_SOURCE, cmb3, IDH_PAGE_PAPER_SOURCE, rad1, IDH_PAGE_ORIENTATION, rad2, IDH_PAGE_ORIENTATION, stc15, IDH_PAGE_MARGINS, edt4, IDH_PAGE_MARGINS, stc16, IDH_PAGE_MARGINS, edt5, IDH_PAGE_MARGINS, stc17, IDH_PAGE_MARGINS, edt6, IDH_PAGE_MARGINS, stc18, IDH_PAGE_MARGINS, edt7, IDH_PAGE_MARGINS, IDC_EDITHEADER, IDH_PAGESETUP_HEADER_LEFT, IDC_STATICHEADER, IDH_PAGESETUP_HEADER_LEFT, IDC_EDITFOOTER, IDH_PAGESETUP_HEADER_LEFT, IDC_STATICFOOTER, IDH_PAGESETUP_HEADER_LEFT, IDC_HEADERFOOTER, IDH_PAGESETUP_HEADER_LEFT, 0, 0 }; //+--------------------------------------------------------------------------- // // Function: GetControlID // // Synopsis: // // Arguments: HWND - passed window handle of WM_CONTEXTMENU // lParam - passed coordinates (lParam) of WM_CONTEXTMENU // // Returns: int - ctrlid // // //---------------------------------------------------------------------------- int GetControlID(HWND hwnd, LPARAM lParam) { int CtrlID; CtrlID = GetDlgCtrlID(hwnd); if (CtrlID==0) { POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam); if (ScreenToClient(hwnd, &pt)) { HWND hwndChild = ChildWindowFromPointEx(hwnd, pt, CWP_ALL); if (hwndChild) { CtrlID = GetDlgCtrlID(hwndChild); } } } return CtrlID; } //+--------------------------------------------------------------------------- // // Function: GetHelpFile // // Synopsis: // // Arguments: iCtrlID - id of the control // adw - array of DWORDS, consisting of controlid,helpid pairs // // Returns: A string with the name of the helpfile // // Notes: Help topics for the print dialogs can be either in iexplore.hlp // or in windows.hlp. We key off the helpid to determine which // file to go to. // //---------------------------------------------------------------------------- LPTSTR GetHelpFile(int iCtrlID, DWORD * adw) { BOOL fContinue = TRUE; ASSERT (adw); while (fContinue) { int ctrlid = int(*adw); int helpid = int(*(adw + 1)); if (ctrlid == 0 && helpid == 0) { fContinue = FALSE; break; } if (ctrlid == iCtrlID) { //TraceTag((tagContextHelp, "for ctrl=%d, topic=%d", ctrlid, helpid)); return (helpid < 50000) ? TEXT("windows.hlp") : TEXT("iexplore.hlp"); } adw += 2; } return TEXT("windows.hlp"); } GetInterfaceFromClientSite(IUnknown *pUnk, REFIID riid, void ** ppv) { HRESULT hr; IOleObject * pOleObject = NULL; IOleClientSite * pOleClientSite = NULL; if (!pUnk || !ppv) { hr = E_INVALIDARG; goto Cleanup; } *ppv = NULL; hr = pUnk->QueryInterface(IID_IOleObject, (void **)&pOleObject); if (hr) goto Cleanup; hr = pOleObject->GetClientSite(&pOleClientSite); if (pOleClientSite == NULL) { hr = E_FAIL; } if (hr) goto Cleanup; hr = pOleClientSite->QueryInterface(riid, ppv); Cleanup: ATOMICRELEASE(pOleClientSite); ATOMICRELEASE(pOleObject); return hr; } // // Get the IOleInPlaceFrame if available. If this proves useful, move this somewhere interesting. // HRESULT GetInPlaceFrameFromUnknown(IUnknown * punk, IOleInPlaceFrame ** ppOleInPlaceFrame) { HRESULT hr; IOleInPlaceSite * pOleInPlaceSite = NULL; IOleInPlaceUIWindow * pOleInPlaceUIWindow = NULL; RECT rcPos, rcClip; OLEINPLACEFRAMEINFO frameInfo; hr = GetInterfaceFromClientSite(punk, IID_IOleInPlaceSite, (void**)&pOleInPlaceSite); if (hr) goto Cleanup; *ppOleInPlaceFrame = NULL; frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO); hr = pOleInPlaceSite->GetWindowContext(ppOleInPlaceFrame, &pOleInPlaceUIWindow, &rcPos, &rcClip, &frameInfo); Cleanup: ATOMICRELEASE(pOleInPlaceUIWindow); ATOMICRELEASE(pOleInPlaceSite); return hr; } HRESULT GetHwndFromUnknown( IUnknown * punk, HWND * phwnd) { HRESULT hr; IOleInPlaceFrame * pOleInPlaceFrame = NULL; ASSERT(punk); ASSERT(phwnd); if (phwnd) { *phwnd = NULL; } if (!punk || !phwnd) { hr = E_INVALIDARG; goto Cleanup; } hr = GetInPlaceFrameFromUnknown((IUnknown*)punk, &pOleInPlaceFrame); if (hr) goto Cleanup; hr = pOleInPlaceFrame->GetWindow(phwnd); if (hr) goto Cleanup; Cleanup: ATOMICRELEASE(pOleInPlaceFrame); return hr; } HRESULT GetEventFromUnknown( IUnknown * punk, IHTMLEventObj ** ppEventObj) { HRESULT hr; IHTMLDocument2 * pOmDoc = NULL; IHTMLWindow2 * pOmWindow = NULL; ASSERT(punk); ASSERT(ppEventObj); if (ppEventObj) *ppEventObj = NULL; if (!punk || !ppEventObj) { hr = E_INVALIDARG; goto Cleanup; } hr = punk->QueryInterface(IID_IHTMLDocument2, (void **) &pOmDoc); if (hr) goto Cleanup; hr = pOmDoc->get_parentWindow(&pOmWindow); if (hr) goto Cleanup; hr = pOmWindow->get_event(ppEventObj); if (hr) goto Cleanup; Cleanup: ATOMICRELEASE(pOmDoc); ATOMICRELEASE(pOmWindow); return hr; } // // Gets the dispids/variants from the event. // HRESULT GetParamsFromEvent( IHTMLEventObj * pEventObj, unsigned int cExpandos, DISPID aDispid[], VARIANT aVariant[], const SExpandoInfo aExpandos[]) { HRESULT hr; IDispatchEx * pDispatchEx = NULL; unsigned int i; ASSERT(pEventObj); ASSERT(aVariant); ASSERT(aExpandos); // ASSERT(cExpandos >= 0); // cExpandos is an unsigned int, so this is always true // deleted "|| cExpandos < 0" from below test // since unsigned ints are never negative if (!pEventObj || !aVariant || !aExpandos) { hr = E_INVALIDARG; goto Cleanup; } for (i=0; iQueryInterface(IID_IDispatchEx, (void**)&pDispatchEx); if (hr) goto Cleanup; for (i=0; iGetDispID( aExpandos[i].name, fdexNameCaseSensitive, aDispid+i); if (hr) goto Cleanup; hr = pDispatchEx->InvokeEx( aDispid[i], LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, (DISPPARAMS *)&g_dispparamsNoArgs, aVariant+i, NULL, NULL); // Check the variant types match ASSERT( V_VT(aVariant+i) == aExpandos[i].type || V_VT(aVariant+i) == VT_EMPTY); if (hr) goto Cleanup; } Cleanup: ATOMICRELEASE(pDispatchEx); return hr; } HRESULT PutParamToEvent(DISPID dispid, VARIANT * var, IHTMLEventObj * pEventObj) { HRESULT hr; IDispatchEx * pDispatchEx = NULL; DISPPARAMS dispparams = {var, &dispid, 1, 1}; ASSERT(var); ASSERT(pEventObj); if (!var || !pEventObj) { hr = E_INVALIDARG; goto Cleanup; } hr = pEventObj->QueryInterface(IID_IDispatchEx, (void**)&pDispatchEx); if (hr) goto Cleanup; hr = pDispatchEx->InvokeEx( dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL); if (hr) goto Cleanup; Cleanup: ATOMICRELEASE(pDispatchEx); return hr; } void PutFindText(IWebBrowser2* pwb, LPCWSTR pwszFindText) { BSTR bstrName = SysAllocString(STR_FIND_DIALOG_TEXT); if (NULL != bstrName) { VARIANT var = {VT_EMPTY}; if (NULL != pwszFindText) { var.vt = VT_BSTR; var.bstrVal = SysAllocString(pwszFindText); } if ((VT_EMPTY == var.vt) || (NULL != var.bstrVal)) { pwb->PutProperty(bstrName, var); } SysFreeString(var.bstrVal); SysFreeString(bstrName); } } BSTR GetFindText(IWebBrowser2* pwb) { BSTR bstrName = SysAllocString(STR_FIND_DIALOG_TEXT); VARIANT var = {0}; if (bstrName) { ASSERT(pwb); pwb->GetProperty(bstrName, &var); SysFreeString(bstrName); } BSTR bstrResult; if (VT_BSTR == var.vt) { bstrResult = var.bstrVal; } else { bstrResult = NULL; VariantClear(&var); } return bstrResult; } CDocHostUIHandler::CDocHostUIHandler(void) : m_cRef(1) { DllAddRef(); m_cPreviewIsUp = 0; } CDocHostUIHandler::~CDocHostUIHandler(void) { ATOMICRELEASE(_punkSite); // // We don't addref _pExternal to avoid an addref/release cycle. So, we can't release it. // // ATOMICRELEASE(_pExternal); ATOMICRELEASE(_pOptionsHolder); if (_hBrowseMenu) DestroyMenu(_hBrowseMenu); if (_hEditMenu) DestroyMenu(_hEditMenu); DllRelease(); } STDMETHODIMP CDocHostUIHandler::QueryInterface(REFIID riid, PVOID *ppvObj) { static const QITAB qit[] = { QITABENT(CDocHostUIHandler, IDocHostUIHandler), QITABENT(CDocHostUIHandler, IObjectWithSite), QITABENT(CDocHostUIHandler, IOleCommandTarget), QITABENT(CDocHostUIHandler, IDispatch), { 0 }, }; return QISearch(this, qit, riid, ppvObj); } STDMETHODIMP_(ULONG) CDocHostUIHandler::AddRef() { InterlockedIncrement(&m_cRef); return m_cRef; } STDMETHODIMP_(ULONG) CDocHostUIHandler::Release() { if (InterlockedDecrement(&m_cRef)) return m_cRef; delete this; return 0; } HRESULT CDocHostUIHandler::SetSite(IUnknown *punkSite) { ATOMICRELEASE(_punkSite); ASSERT(_punkSite == NULL); // don't lose a reference to this _punkSite = punkSite; if (_punkSite) { _punkSite->AddRef(); } // Always return S_OK // return S_OK; } HRESULT CDocHostUIHandler::GetSite(REFIID riid, void **ppvSite) { if (_punkSite) return _punkSite->QueryInterface(riid, ppvSite); *ppvSite = NULL; return E_FAIL; } //========================================================================== // IDocHostUIHandler implementation //========================================================================== HRESULT CDocHostUIHandler::ShowContextMenu(DWORD dwID, POINT *ppt, IUnknown *pcmdtReserved, IDispatch *pdispReserved) { HRESULT hr = S_FALSE; HCURSOR hcursor; HMENU hMenu = NULL; VARIANT var, var1, var2; VARIANT * pvar = NULL; int iSelection = 0; HWND hwnd = NULL; IOleCommandTarget * pOleCommandTarget = NULL; IOleWindow * pOleWindow = NULL; IOleInPlaceFrame * pOleInPlaceFrame = NULL; IDocHostUIHandler * pUIHandler = NULL; MENUITEMINFO mii = {0}; int i; OLECMD olecmd; UINT mf; BOOL fDeletePrint = FALSE; BOOL fDeleteSetDesktopItem = FALSE; IHTMLImgElement * pImgEle = NULL; TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::ShowContextMenu called"); //If restriction is set, we lie to Mshtml that context menu has been set. if (SHRestricted2W(REST_NoBrowserContextMenu, NULL, 0)) return S_OK; // Do a proper QI for IOleCommandTarget // hr = pcmdtReserved->QueryInterface(IID_IOleCommandTarget, (void**)&pOleCommandTarget); if (hr) goto Cleanup; // Check if we are in browse mode // olecmd.cmdID = IDM_BROWSEMODE; hr = pOleCommandTarget->QueryStatus( &CGID_MSHTML, 1, &olecmd, NULL); if (hr) goto Cleanup; if (olecmd.cmdf == OLECMDSTATE_DOWN) { if (!_hBrowseMenu) _hBrowseMenu = LoadMenu( MLGetHinst(), MAKEINTRESOURCE(IDR_BROWSE_CONTEXT_MENU)); hMenu = _hBrowseMenu; } // Check if we are in edit mode else { olecmd.cmdID = IDM_EDITMODE; hr = pOleCommandTarget->QueryStatus( &CGID_MSHTML, 1, &olecmd, NULL); if (hr) goto Cleanup; if (olecmd.cmdf == OLECMDSTATE_DOWN) { if (!_hEditMenu) _hEditMenu = LoadMenu( MLGetHinst(), MAKEINTRESOURCE(IDR_FORM_CONTEXT_MENU)); hMenu = _hEditMenu; } // Neither Browse nor Edit flags were set else { ASSERT(false); goto Cleanup; } } if (!hMenu) goto Cleanup; // // check through all the submenus and remove any sets of items which // need to be removed // fDeletePrint = SHRestricted2(REST_NoPrinting, NULL, 0); fDeleteSetDesktopItem = (WhichPlatform() != PLATFORM_INTEGRATED); if (fDeletePrint || fDeleteSetDesktopItem) { int iSubMenuIndex; for(iSubMenuIndex = 0; iSubMenuIndex < GetMenuItemCount(hMenu); iSubMenuIndex++) { HMENU hSubMenu; if(hSubMenu = GetSubMenu(hMenu, iSubMenuIndex)) { if (fDeletePrint) { DeleteMenu(hSubMenu, IDM_PRINT, MF_BYCOMMAND); } if (fDeleteSetDesktopItem) { DeleteMenu(hSubMenu, IDM_SETDESKTOPITEM, MF_BYCOMMAND); } } } } // Make sure we are running mshtml debug build if we are loading debug window if (dwID == CONTEXT_MENU_DEBUG) { olecmd.cmdID = IDM_DEBUG_TRACETAGS; hr = pOleCommandTarget->QueryStatus( &CGID_MSHTML, 1, &olecmd, NULL); if (olecmd.cmdf != OLECMDSTATE_UP) goto Cleanup; } // Select the appropriate submenu based on the passed in ID hMenu = GetSubMenu(hMenu, dwID); if (!hMenu) goto Cleanup; // Loop through and QueryStatus the menu items. // for(i = 0; i < GetMenuItemCount(hMenu); i++) { olecmd.cmdID = GetMenuItemID(hMenu, i); if (olecmd.cmdID > 0) { pOleCommandTarget->QueryStatus( &CGID_MSHTML, 1, &olecmd, NULL); switch (olecmd.cmdf) { case OLECMDSTATE_UP: case OLECMDSTATE_NINCHED: mf = MF_BYCOMMAND | MF_ENABLED | MF_UNCHECKED; break; case OLECMDSTATE_DOWN: mf = MF_BYCOMMAND | MF_ENABLED | MF_CHECKED; break; case OLECMDSTATE_DISABLED: default: mf = MF_BYCOMMAND | MF_DISABLED | MF_GRAYED; break; } CheckMenuItem(hMenu, olecmd.cmdID, mf); EnableMenuItem(hMenu, olecmd.cmdID, mf); } } // Get the language submenu hr = pOleCommandTarget->Exec(&CGID_ShellDocView, SHDVID_GETMIMECSETMENU, 0, NULL, &var); if (hr) goto Cleanup; mii.cbSize = sizeof(mii); mii.fMask = MIIM_SUBMENU; mii.hSubMenu = (HMENU) var.byref; SetMenuItemInfo(hMenu, IDM_LANGUAGE, FALSE, &mii); // Insert Context Menu V_VT(&var1) = VT_INT_PTR; V_BYREF(&var1) = hMenu; V_VT(&var2) = VT_I4; V_I4(&var2) = dwID; hr = pOleCommandTarget->Exec(&CGID_ShellDocView, SHDVID_ADDMENUEXTENSIONS, 0, &var1, &var2); if (hr) goto Cleanup; // Get the window also. // if (SUCCEEDED(pcmdtReserved->QueryInterface(IID_IOleWindow, (void**)&pOleWindow))) { pOleWindow->GetWindow(&hwnd); } if (hwnd) { GetInterfaceFromClientSite(pcmdtReserved, IID_IDocHostUIHandler, (void **)&pUIHandler); if (pUIHandler) pUIHandler->EnableModeless(FALSE); GetInPlaceFrameFromUnknown(pcmdtReserved, &pOleInPlaceFrame); if (pOleInPlaceFrame) pOleInPlaceFrame->EnableModeless(FALSE); hcursor = SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW))); // Display the menu. Pass in the HWND of our site object. // iSelection = ::TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, ppt->x + CX_CONTEXTMENUOFFSET, ppt->y + CY_CONTEXTMENUOFFSET, 0, hwnd, (RECT*)NULL); if (pUIHandler) pUIHandler->EnableModeless(TRUE); if (pOleInPlaceFrame) pOleInPlaceFrame->EnableModeless(TRUE); SetCursor(hcursor); } if (iSelection) { switch (iSelection) { case IDM_FOLLOWLINKN: // tell the top level browser to save its window size to the registry so // that our new window can pick it up and cascade properly IUnknown_Exec(_punkSite, &CGID_Explorer, SBCMDID_SUGGESTSAVEWINPOS, 0, NULL, NULL); // fall through case IDM_PROPERTIES: case IDM_FOLLOWLINKC: pvar = &var; V_VT(pvar) = VT_I4; V_I4(pvar) = MAKELONG(ppt->x, ppt->y); break; } pOleCommandTarget->Exec(&CGID_MSHTML, iSelection, 0, pvar, NULL); } { MENUITEMINFO mii2 = {0}; mii2.cbSize = sizeof(mii); mii2.fMask = MIIM_SUBMENU; mii2.hSubMenu = NULL; SetMenuItemInfo(hMenu, IDM_LANGUAGE, FALSE, &mii2); } Cleanup: DestroyMenu (mii.hSubMenu); ATOMICRELEASE(pOleCommandTarget); ATOMICRELEASE(pOleWindow); ATOMICRELEASE(pOleInPlaceFrame); ATOMICRELEASE(pUIHandler); return hr; } HRESULT CDocHostUIHandler::GetHostInfo(DOCHOSTUIINFO *pInfo) { DWORD dwUrlEncodingDisableUTF8; DWORD dwSize = SIZEOF(dwUrlEncodingDisableUTF8); BOOL fDefault = FALSE; DWORD dwLoadf = 0; TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::GetHostInfo called"); pInfo->cbSize = SIZEOF(DOCHOSTUIINFO); pInfo->dwFlags = DOCHOSTUIFLAG_BROWSER | DOCHOSTUIFLAG_ENABLE_INPLACE_NAVIGATION | DOCHOSTUIFLAG_IME_ENABLE_RECONVERSION; pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT; // default SHRegGetUSValue(REGSTR_PATH_INTERNET_SETTINGS, TEXT("UrlEncoding"), NULL, (LPBYTE) &dwUrlEncodingDisableUTF8, &dwSize, FALSE, (LPVOID) &fDefault, SIZEOF(fDefault)); if (dwUrlEncodingDisableUTF8) pInfo->dwFlags |= DOCHOSTUIFLAG_URL_ENCODING_DISABLE_UTF8; else pInfo->dwFlags |= DOCHOSTUIFLAG_URL_ENCODING_ENABLE_UTF8; return S_OK; } HRESULT CDocHostUIHandler::ShowUI( DWORD dwID, IOleInPlaceActiveObject *pActiveObject, IOleCommandTarget *pCommandTarget, IOleInPlaceFrame *pFrame, IOleInPlaceUIWindow *pDoc) { TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::ShowUI called"); // Host did not display its own UI. Trident will proceed to display its own. return S_FALSE; } HRESULT CDocHostUIHandler::HideUI(void) { TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::HideUI called"); // This one is paired with ShowUI return S_FALSE; } HRESULT CDocHostUIHandler::UpdateUI(void) { TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::UpdateUI called"); // LATER: Isn't this equivalent to OLECMDID_UPDATECOMMANDS? return S_FALSE; } HRESULT CDocHostUIHandler::EnableModeless(BOOL fEnable) { TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::EnableModeless called"); // Called from the Trident when the equivalent member of its // IOleInPlaceActiveObject is called by the frame. We don't care // those cases. return S_OK; } HRESULT CDocHostUIHandler::OnDocWindowActivate(BOOL fActivate) { // Called from the Trident when the equivalent member of its // IOleInPlaceActiveObject is called by the frame. We don't care // those cases. return S_OK; } HRESULT CDocHostUIHandler::OnFrameWindowActivate(BOOL fActivate) { // Called from the Trident when the equivalent member of its // IOleInPlaceActiveObject is called by the frame. We don't care // those cases. return S_OK; } HRESULT CDocHostUIHandler::ResizeBorder( LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow) { // Called from the Trident when the equivalent member of its // IOleInPlaceActiveObject is called by the frame. We don't care // those cases. return S_OK; } HRESULT CDocHostUIHandler::TranslateAccelerator( LPMSG lpMsg, const GUID *pguidCmdGroup, DWORD nCmdID) { // Called from the Trident when the equivalent member of its // IOleInPlaceActiveObject is called by the frame. We don't care // those cases. return S_FALSE; // The message was not translated } HRESULT CDocHostUIHandler::GetOptionKeyPath(BSTR *pbstrKey, DWORD dw) { // Trident will default to its own user options. *pbstrKey = NULL; return S_FALSE; } HRESULT CDocHostUIHandler::GetDropTarget(IDropTarget *pDropTarget, IDropTarget **ppDropTarget) { TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::GetDropTarget called"); return E_NOTIMPL; } HRESULT CDocHostUIHandler::GetAltExternal(IDispatch **ppDisp) { HRESULT hr = E_FAIL; IDocHostUIHandler *pDocHostUIHandler; IOleObject *pOleObject; IOleClientSite *pOleClientSite; *ppDisp = NULL; // * QI ourselves for a service provider // * QS for the top level browser's service provider // * Ask for an IOleObject // * Ask the IOleObject for an IOleClientSite // * QI the IOleClientSite for an IDocHostUIHandler // * Call GetExternal on the IDocHostUIHandler to get the IDispatch if (SUCCEEDED(IUnknown_QueryServiceForWebBrowserApp(_punkSite, IID_PPV_ARG(IOleObject, &pOleObject)))) { if (SUCCEEDED(pOleObject->GetClientSite(&pOleClientSite))) { if (SUCCEEDED(pOleClientSite->QueryInterface(IID_IDocHostUIHandler, (void **)&pDocHostUIHandler))) { hr = pDocHostUIHandler->GetExternal(ppDisp); pDocHostUIHandler->Release(); } pOleClientSite->Release(); } pOleObject->Release(); } return hr; } HRESULT CDocHostUIHandler::GetExternal(IDispatch **ppDisp) { TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::GetExternal called"); HRESULT hr = S_OK; if (!ppDisp) { hr = E_INVALIDARG; goto Cleanup; } if (_pExternal) { *ppDisp = _pExternal; (*ppDisp)->AddRef(); goto Cleanup; } IDispatch *psuihDisp; IDispatch *pAltExternalDisp; *ppDisp = NULL; GetAltExternal(&pAltExternalDisp); hr = CShellUIHelper_CreateInstance2((IUnknown **)&psuihDisp, IID_IDispatch, _punkSite, pAltExternalDisp); if (SUCCEEDED(hr)) { *ppDisp = psuihDisp; _pExternal = *ppDisp; if (pAltExternalDisp) { // Don't hold a ref - the ShellUIHelper will do it pAltExternalDisp->Release(); } } else if (pAltExternalDisp) { // Couldn't create a ShellUIHelper but we got our host's // external. *ppDisp = pAltExternalDisp; _pExternal = *ppDisp; } Cleanup: ASSERT((SUCCEEDED(hr) && (*ppDisp)) || (FAILED(hr))); return hr; } HRESULT CDocHostUIHandler::TranslateUrl(DWORD dwTranslate, OLECHAR *pchURLIn, OLECHAR **ppchURLOut) { TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::TranslateUrl called"); return S_FALSE; } HRESULT CDocHostUIHandler::FilterDataObject(IDataObject *pDO, IDataObject **ppDORet) { TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::FilterDataObject called"); return S_FALSE; } HRESULT CDocHostUIHandler::GetOverrideKeyPath(LPOLESTR *pchKey, DWORD dw) { TraceMsg(DM_DOCHOSTUIHANDLER, "CDOH::GetOverrideKeyPath called"); return S_FALSE; } STDAPI CDocHostUIHandler_CreateInstance(IUnknown * punkOuter, IUnknown ** ppunk, LPCOBJECTINFO poi) { HRESULT hres = E_OUTOFMEMORY; CDocHostUIHandler *pis = new CDocHostUIHandler; if (pis) { *ppunk = SAFECAST(pis, IDocHostUIHandler *); hres = S_OK; } return hres; } //========================================================================== // IOleCommandTarget implementation //========================================================================== HRESULT CDocHostUIHandler::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext) { HRESULT hres = OLECMDERR_E_UNKNOWNGROUP; if (IsEqualGUID(CGID_DocHostCommandHandler, *pguidCmdGroup)) { ULONG i; if (rgCmds == NULL) return E_INVALIDARG; for (i = 0 ; i < cCmds ; i++) { // ONLY say that we support the stuff we support in ::Exec switch (rgCmds[i].cmdID) { case OLECMDID_SHOWSCRIPTERROR: case OLECMDID_SHOWMESSAGE: case OLECMDID_SHOWFIND: case OLECMDID_SHOWPAGESETUP: case OLECMDID_SHOWPRINT: case OLECMDID_PRINTPREVIEW: case OLECMDID_PRINT: case OLECMDID_PROPERTIES: case SHDVID_CLSIDTOMONIKER: rgCmds[i].cmdf = OLECMDF_ENABLED; break; default: rgCmds[i].cmdf = 0; break; } } hres = S_OK; } return hres; } HRESULT CDocHostUIHandler::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut) { if (IsEqualGUID(CGID_DocHostCommandHandler, *pguidCmdGroup)) { switch (nCmdID) { case OLECMDID_SHOWSCRIPTERROR: if (!pvarargIn || !pvarargOut) return E_INVALIDARG; ShowErrorDialog(pvarargIn, pvarargOut, nCmdexecopt); return S_OK; case OLECMDID_SHOWMESSAGE: if (!pvarargIn || !pvarargOut) return E_INVALIDARG; else return ShowMessage(pvarargIn, pvarargOut, nCmdexecopt); case OLECMDID_SHOWFIND: if (!pvarargIn) return E_INVALIDARG; ShowFindDialog(pvarargIn, pvarargOut, nCmdexecopt); return S_OK; case OLECMDID_SHOWPAGESETUP: if (!pvarargIn) return E_INVALIDARG; else return ShowPageSetupDialog(pvarargIn, pvarargOut, nCmdexecopt); case IDM_TEMPLATE_PAGESETUP: return DoTemplatePageSetup(pvarargIn); case OLECMDID_SHOWPRINT: if (!pvarargIn) return E_INVALIDARG; else return ShowPrintDialog(pvarargIn, pvarargOut, nCmdexecopt); case OLECMDID_PRINTPREVIEW: if (!pvarargIn) return E_INVALIDARG; else return DoTemplatePrinting(pvarargIn, pvarargOut, TRUE); case OLECMDID_PRINT: if (!pvarargIn) return E_INVALIDARG; else return DoTemplatePrinting(pvarargIn, pvarargOut, FALSE); case OLECMDID_REFRESH: //if print preview is up, tell them we handled refresh //to prevent Trident from refreshing. if (m_cPreviewIsUp > 0) return S_OK; // else do default handling break; case OLECMDID_PROPERTIES: if (!pvarargIn) return E_INVALIDARG; else return ShowPropertysheetDialog(pvarargIn, pvarargOut, nCmdexecopt); case SHDVID_CLSIDTOMONIKER: if (!pvarargIn || !pvarargOut) return E_INVALIDARG; else return ClsidToMoniker(pvarargIn, pvarargOut); default: return OLECMDERR_E_NOTSUPPORTED; } } return OLECMDERR_E_UNKNOWNGROUP; } //+--------------------------------------------------------------------------- // // Helper for OLECMDID_SHOWSCRIPTERROR // //+--------------------------------------------------------------------------- void CDocHostUIHandler::ShowErrorDialog(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD) { HRESULT hr; HWND hwnd; IHTMLEventObj * pEventObj = NULL; IMoniker * pmk = NULL; VARIANT varEventObj; TCHAR szResURL[MAX_URL_STRING]; hr = GetHwndFromUnknown(V_UNKNOWN(pvarargIn), &hwnd); if (hr) goto Cleanup; hr = GetEventFromUnknown(V_UNKNOWN(pvarargIn), &pEventObj); if (hr) goto Cleanup; hr = MLBuildResURLWrap(TEXT("shdoclc.dll"), HINST_THISDLL, ML_CROSSCODEPAGE, TEXT("error.dlg"), szResURL, ARRAYSIZE(szResURL), TEXT("shdocvw.dll")); if (FAILED(hr)) { goto Cleanup; } hr = CreateURLMoniker(NULL, szResURL, &pmk); if (FAILED(hr)) goto Cleanup; V_VT(&varEventObj) = VT_DISPATCH; V_DISPATCH(&varEventObj) = pEventObj; ShowHTMLDialog(hwnd, pmk, &varEventObj, NULL, pvarargOut); Cleanup: ATOMICRELEASE(pEventObj); ATOMICRELEASE(pmk); } //+--------------------------------------------------------------------------- // // Callback procedure for OLECMDID_SHOWMESSAGE dialog // //+--------------------------------------------------------------------------- struct MSGBOXCALLBACKINFO { DWORD dwHelpContext; TCHAR * pstrHelpFile; HWND hwnd; }; static void CALLBACK MessageBoxCallBack(HELPINFO *phi) { MSGBOXCALLBACKINFO *p = (MSGBOXCALLBACKINFO *)phi->dwContextId; BOOL fRet; fRet = WinHelp( p->hwnd, p->pstrHelpFile, HELP_CONTEXT, p->dwHelpContext); THR(fRet ? S_OK : E_FAIL); } //+--------------------------------------------------------------------------- // // Helper for OLECMDID_SHOWMESSAGE // //+--------------------------------------------------------------------------- HRESULT CDocHostUIHandler::ShowMessage(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD) { // must match order of MessageEnum static const SExpandoInfo s_aMessageExpandos[] = { {TEXT("messageText"), VT_BSTR}, {TEXT("messageCaption"), VT_BSTR}, {TEXT("messageStyle"), VT_UI4}, {TEXT("messageHelpFile"), VT_BSTR}, {TEXT("messageHelpContext"), VT_UI4} }; HRESULT hr; HWND hwnd = NULL; MSGBOXPARAMS mbp; MSGBOXCALLBACKINFO mcbi; LRESULT plResult = 0; LPOLESTR lpstrText = NULL; LPOLESTR lpstrCaption = NULL; DWORD dwType = 0; LPOLESTR lpstrHelpFile = NULL; DWORD dwHelpContext = 0; IHTMLEventObj * pEventObj = NULL; const int cExpandos = ARRAYSIZE(s_aMessageExpandos); DISPID aDispid[cExpandos]; VARIANT aVariant[cExpandos]; int i; ULONG_PTR uCookie = 0; ASSERT(pvarargIn && pvarargOut); for(i=0; iGetProperty(bstrName, &var); if ( (var.vt == VT_DISPATCH) && (var.pdispVal != NULL) ) { if (ppWindow) { *ppWindow = (IHTMLWindow2*)var.pdispVal; (*ppWindow)->AddRef(); } fRet = TRUE; } VariantClear(&var); SysFreeString(bstrName); } if (!fRet && ppWindow) *ppWindow = NULL; return fRet; } HRESULT SetFindDialogProperty(IWebBrowser2* pwb, VARIANT* pvar) { HRESULT hr; BSTR bstrName = SysAllocString(STR_FIND_DIALOG_NAME); if (bstrName) { hr = pwb->PutProperty(bstrName, *pvar); SysFreeString(bstrName); } else hr = E_OUTOFMEMORY; return hr; } //if this fails, then we have no choice but to orphan the dialog HRESULT SetFindDialogUp(IWebBrowser2* pwb, IHTMLWindow2* pWindow) { VARIANT var; var.vt = VT_DISPATCH; var.pdispVal = pWindow; return SetFindDialogProperty(pwb, &var); } void ReleaseFindDialog(IWebBrowser2* pwb) { VARIANT var = {0}; SetFindDialogProperty(pwb, &var); } //+--------------------------------------------------------------------------- // // Helper for OLECMDID_SHOWFIND // // pvarargIn - IDispatch Interface // dwflags - bidi flag //+--------------------------------------------------------------------------- void CDocHostUIHandler::ShowFindDialog(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD dwflags) { IDispatch * pDispatch = NULL; IHTMLOptionsHolder * pHTMLOptionsHolder = NULL; IHTMLDocument2 * pHTMLDocument2 = NULL; IHTMLWindow2 * pHTMLWindow2 = NULL; IOleInPlaceFrame * pOleInPlaceFrame = NULL; HWND hwnd = NULL; IMoniker * pmk = NULL; if (EVAL(V_VT(pvarargIn) == VT_DISPATCH)) { pDispatch = V_DISPATCH(pvarargIn); if (SUCCEEDED(pDispatch->QueryInterface(IID_IHTMLOptionsHolder, (void**)&pHTMLOptionsHolder))) { if (SUCCEEDED(pHTMLOptionsHolder->get_document(&pHTMLDocument2)) && pHTMLDocument2) { if (SUCCEEDED(pHTMLDocument2->get_parentWindow(&pHTMLWindow2))) { if (SUCCEEDED(GetInPlaceFrameFromUnknown(pHTMLDocument2, &pOleInPlaceFrame))) { if (SUCCEEDED(pOleInPlaceFrame->GetWindow(&hwnd))) { BOOL fInBrowser = FALSE; IWebBrowser2 * pwb2 = NULL; if (SUCCEEDED(IUnknown_QueryServiceForWebBrowserApp(_punkSite, IID_PPV_ARG(IWebBrowser2, &pwb2)))) { fInBrowser = TRUE; } TCHAR szResURL[MAX_URL_STRING]; if (SUCCEEDED(MLBuildResURLWrap(TEXT("shdoclc.dll"), HINST_THISDLL, ML_CROSSCODEPAGE, (dwflags ? TEXT("bidifind.dlg") : TEXT("find.dlg")), szResURL, ARRAYSIZE(szResURL), TEXT("shdocvw.dll")))) { CreateURLMoniker(NULL, szResURL, &pmk); if (fInBrowser) { IHTMLWindow2 *pWinOut; if (!IsFindDialogUp(pwb2, &pWinOut)) { ASSERT(NULL==pWinOut); if ((NULL != pvarargIn) && (VT_DISPATCH == pvarargIn->vt) && (NULL != pvarargIn->pdispVal)) { BSTR bstrFindText = GetFindText(pwb2); if (bstrFindText) { // paranoia since we hang on to this object // a while and there is always potential // for mess ups below where we mean to // release it. ATOMICRELEASE(_pOptionsHolder); pvarargIn->pdispVal->QueryInterface( IID_IHTMLOptionsHolder, (void **)&_pOptionsHolder); if (_pOptionsHolder) _pOptionsHolder->put_findText(bstrFindText); SysFreeString(bstrFindText); } } ShowModelessHTMLDialog(hwnd, pmk, pvarargIn, NULL, &pWinOut); if (pWinOut) { //can't really handle failure here, because the dialog is already up. BSTR bstrOnunload = SysAllocString(L"onunload"); if (bstrOnunload) { IHTMLWindow3 * pWin3; if (SUCCEEDED(pWinOut->QueryInterface(IID_IHTMLWindow3, (void**)&pWin3))) { VARIANT_BOOL varBool; if (SUCCEEDED(pWin3->attachEvent(bstrOnunload, (IDispatch*)this, &varBool))) { // on SetFindDialogUp success, the property holds the ref on pWinOut if (FAILED(SetFindDialogUp(pwb2, pWinOut))) { // No way to handle the event, so detach pWin3->detachEvent(bstrOnunload, (IDispatch*)this); } } pWin3->Release(); } SysFreeString(bstrOnunload); } // REVIEW: the old code leaked this ref if the property // wasn't attached in SetFindDialogUp... pWinOut->Release(); } } else { //since the find dialog is already up, send focus to it pWinOut->focus(); pWinOut->Release(); } } else { //we're not in the browser, so just show it modal ShowHTMLDialog(hwnd, pmk, pvarargIn, NULL, NULL); } if (pmk) pmk->Release(); } ATOMICRELEASE(pwb2); } pOleInPlaceFrame->Release(); } pHTMLWindow2->Release(); } pHTMLDocument2->Release(); } pHTMLOptionsHolder->Release(); } } //pWinOut gets released in CDocHostUIHandler::Invoke() or CIEFrameAuto::COmWindow::ViewReleased(), // in response to the onunload event. if (pvarargOut) VariantInit(pvarargOut); } //+--------------------------------------------------------------------------- // // Callback procedure for OLECMDID_SHOWPAGESETUP dialog // //+--------------------------------------------------------------------------- struct PAGESETUPBOXCALLBACKINFO { TCHAR strHeader[1024]; TCHAR strFooter[1024]; }; UINT_PTR APIENTRY PageSetupHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { HKEY keyPageSetup = NULL; switch (uiMsg) { case WM_INITDIALOG: PAGESETUPBOXCALLBACKINFO * ppscbi; ppscbi = (PAGESETUPBOXCALLBACKINFO *) ((PAGESETUPDLG*)lParam)->lCustData; SetWindowLongPtr(hdlg, DWLP_USER, (LONG_PTR)ppscbi); #ifdef UNIX SendDlgItemMessage(hdlg,IDC_EDITHEADER, EM_LIMITTEXT, 1023, 0L); SendDlgItemMessage(hdlg,IDC_EDITFOOTER, EM_LIMITTEXT, 1023, 0L); #endif SetDlgItemText(hdlg,IDC_EDITHEADER, ppscbi->strHeader); SetDlgItemText(hdlg,IDC_EDITFOOTER, ppscbi->strFooter); return TRUE; case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDOK: { PAGESETUPBOXCALLBACKINFO * ppscbi; ppscbi = (PAGESETUPBOXCALLBACKINFO *) GetWindowLongPtr(hdlg, DWLP_USER); if (ppscbi) { GetDlgItemText(hdlg,IDC_EDITHEADER, ppscbi->strHeader,1024); GetDlgItemText(hdlg,IDC_EDITFOOTER, ppscbi->strFooter,1024); } } } break; case WM_HELP: { LPHELPINFO pHI; pHI = (LPHELPINFO)lParam; if (pHI->iContextType == HELPINFO_WINDOW) // must be for a control { WinHelp( (HWND)pHI->hItemHandle, GetHelpFile(pHI->iCtrlId, (DWORD *)aPageSetupDialogHelpIDs), HELP_WM_HELP, (DWORD_PTR)(LPVOID) aPageSetupDialogHelpIDs); } break; //return TRUE; } case WM_CONTEXTMENU: { int CtrlID = GetControlID((HWND)wParam, lParam); WinHelp( (HWND)wParam, GetHelpFile(CtrlID, (DWORD *)aPageSetupDialogHelpIDs), HELP_CONTEXTMENU, (DWORD_PTR)(LPVOID) aPageSetupDialogHelpIDs); break; } } return FALSE; } //+--------------------------------------------------------------------------- // // Helper for OLECMDID_SHOWPAGESETUP // // pvarargIn - holds IHTMLEventObj * for the event // // Returns S_FALSE if the user clicked Cancel and S_TRUE if the user // clicked OK. //+--------------------------------------------------------------------------- HRESULT CDocHostUIHandler::ShowPageSetupDialog(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD) { // must match order of PagesetupEnum static const SExpandoInfo s_aPagesetupExpandos[] = { {OLESTR("pagesetupHeader"), VT_BSTR}, {OLESTR("pagesetupFooter"), VT_BSTR}, {OLESTR("pagesetupStruct"), VT_PTR} }; HRESULT hr = E_FAIL; PAGESETUPDLG * ppagesetupdlg = NULL; PAGESETUPBOXCALLBACKINFO pagesetupcbi; IHTMLEventObj * pEventObj = NULL; const int cExpandos = ARRAYSIZE(s_aPagesetupExpandos); DISPID aDispid[cExpandos]; VARIANT aVariant[cExpandos]; int i; ULONG_PTR uCookie = 0; for (i=0; iQueryInterface(IID_IHTMLEventObj, (void **) &pEventObj)) goto Cleanup; // Get parameters from event object if (GetParamsFromEvent( pEventObj, cExpandos, aDispid, aVariant, s_aPagesetupExpandos)) goto Cleanup; // Copy values from variants StrCpyN((TCHAR*)pagesetupcbi.strHeader, V_BSTR(&aVariant[PagesetupHeader]) ? V_BSTR(&aVariant[PagesetupHeader]) : TEXT(""), ARRAYSIZE(pagesetupcbi.strHeader)); StrCpyN((TCHAR*)pagesetupcbi.strFooter, V_BSTR(&aVariant[PagesetupFooter]) ? V_BSTR(&aVariant[PagesetupFooter]) : TEXT(""), ARRAYSIZE(pagesetupcbi.strHeader)); ppagesetupdlg = (PAGESETUPDLG *)V_BYREF(&aVariant[PagesetupStruct]); if (!ppagesetupdlg) goto Cleanup; // Set up custom dialog resource fields in pagesetupdlg ppagesetupdlg->Flags |= PSD_ENABLEPAGESETUPHOOK | PSD_ENABLEPAGESETUPTEMPLATE; ppagesetupdlg->lCustData = (LPARAM) &pagesetupcbi; ppagesetupdlg->lpfnPageSetupHook = PageSetupHookProc; ppagesetupdlg->hInstance = MLLoadShellLangResources(); #ifdef UNIX ppagesetupdlg->lpPageSetupTemplateName = MAKEINTRESOURCE(PAGESETUPDLGORDMOTIF); #else ppagesetupdlg->lpPageSetupTemplateName = MAKEINTRESOURCE(PAGESETUPDLGORD); #endif // UNIX // Show dialog SHActivateContext(&uCookie); if (!PageSetupDlg(ppagesetupdlg)) { // treat failure as canceling hr = S_FALSE; goto Cleanup; } hr = S_OK; // Save header/footer in event object VARIANT var; V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(pagesetupcbi.strHeader ? pagesetupcbi.strHeader : TEXT("")); if (NULL != V_BSTR(&var)) { PutParamToEvent(aDispid[PagesetupHeader], &var, pEventObj); VariantClear(&var); } V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(pagesetupcbi.strFooter ? pagesetupcbi.strFooter : TEXT("")); if (NULL != V_BSTR(&var)) { PutParamToEvent(aDispid[PagesetupFooter], &var, pEventObj); VariantClear(&var); } Cleanup: if (ppagesetupdlg) MLFreeLibrary(ppagesetupdlg->hInstance); if (uCookie) { SHDeactivateContext(uCookie); } for (i=0; ifPrintActiveFrameEnabled) { // Disable "print selected frame" radiobutton. HWND hwndPrintActiveFrame = GetDlgItem(hdlg, rad5); EnableWindow(hwndPrintActiveFrame, FALSE); } // If there is no frameset, disable "print all frames" radiobutton. if (!ppcbi->fRootDocumentHasFrameset) { HWND hwndPrintAllFrames = GetDlgItem(hdlg, rad6); EnableWindow(hwndPrintAllFrames, FALSE); if (!ppcbi->fPrintActiveFrameEnabled) { // We're not a FRAMESET and don't have IFRAMEs // Disable "print as laid out on screen" radiobutton. HWND hwndPrintAsLaidOutOnScreen = GetDlgItem(hdlg, rad4); EnableWindow(hwndPrintAsLaidOutOnScreen, FALSE); SetPreviewBitmap(IDR_PRINT_PREVIEWDISABLED, hdlg); } } // Setup default radio button to be checked. // NOTE: We currently allow the template to check options that are disabled. if (ppcbi->fPrintActiveFrame) { // Check "print selected frame" radiobutton. CheckRadioButton(hdlg, rad4, rad6, rad5); SetPreviewBitmap(IDR_PRINT_PREVIEWONEDOC, hdlg); } else if (ppcbi->fPrintAsShown) { // Check "print frames as laid out" radiobutton. CheckRadioButton(hdlg, rad4, rad6, rad4); SetPreviewBitmap(IDR_PRINT_PREVIEW, hdlg); } else { // Check "print all frames" radiobutton. CheckRadioButton(hdlg, rad4, rad6, rad6); SetPreviewBitmap(IDR_PRINT_PREVIEWALLDOCS, hdlg); } HWND hwndSelection = GetDlgItem(hdlg, rad2); if (hwndSelection) EnableWindow(hwndSelection, (ppcbi->fPrintSelection)); #ifdef FONTSIZE_BOX int i=0, cbLen=0; //bugwin16: need to fix this. for (i = 0; i < IDS_PRINT_FONTMAX; i++) { TCHAR achBuffer[128]; cbLen = MLLoadShellLangString(IDS_PRINT_FONTSCALE+i,achBuffer,127); if (cbLen) { SendDlgItemMessage(hdlg, IDC_SCALING, CB_ADDSTRING, 0, (long) achBuffer); } } if (i>0) { SendDlgItemMessage(hdlg, IDC_SCALING, CB_SETCURSEL, IDS_PRINT_FONTMAX - 1 - ppcbi->iFontScaling, 0); } #endif // FONTSIZE_BOX // If ratings are enabled, don't allow recursive printing. if (ppcbi->fAreRatingsEnabled) { HWND hwndPrintLinkedDocuments = GetDlgItem(hdlg, IDC_LINKED); CheckDlgButton(hdlg, IDC_LINKED, BST_UNCHECKED); EnableWindow(hwndPrintLinkedDocuments, FALSE); } } } void OnCommand( HWND hdlg, WPARAM wParam, LPARAM lParam ) { PRINTBOXCALLBACKINFO * ppcbi; ppcbi = (PRINTBOXCALLBACKINFO *)GetWindowLongPtr(hdlg, DWLP_USER); if (!ppcbi) { return; } switch (GET_WM_COMMAND_ID(wParam, lParam)) { case rad1: // "Print all" case rad3: // "Print range" case rad2: // "Print selection" (text selection) { // If we are printing a text selection, and we have a selected frame, // force a print selected frame. if (ppcbi && ppcbi->fPrintActiveFrame && ppcbi->fPrintSelection) { HWND hwndPrintWhatGroup = GetDlgItem(hdlg, grp3); HWND hwndPrintActiveFrame = GetDlgItem(hdlg, rad5); HWND hwndPrintAllFrames = GetDlgItem(hdlg, rad6); HWND hwndPrintSelectedFrame = GetDlgItem(hdlg, rad4); if (hwndPrintWhatGroup) EnableWindow(hwndPrintWhatGroup, LOWORD(wParam) != rad2); if (hwndPrintActiveFrame) EnableWindow(hwndPrintActiveFrame, LOWORD(wParam) != rad2); if (hwndPrintAllFrames) EnableWindow(hwndPrintAllFrames, ppcbi->fRootDocumentHasFrameset && LOWORD(wParam) != rad2); if (hwndPrintSelectedFrame) EnableWindow(hwndPrintSelectedFrame, LOWORD(wParam) != rad2); } break; } case rad4: if (HIWORD(wParam) == BN_CLICKED) { // now change the icon... SetPreviewBitmap(IDR_PRINT_PREVIEW, hdlg); HWND hwnd = GetDlgItem(hdlg, rad2); if (hwnd) EnableWindow(hwnd, FALSE); hwnd = GetDlgItem(hdlg, IDC_SHORTCUTS); if (hwnd) EnableWindow(hwnd, FALSE); hwnd = GetDlgItem(hdlg, IDC_LINKED); if (hwnd) EnableWindow(hwnd, FALSE); // if(ppcbi->pBodyActive); // ppcbi->pBodyActive->Layout()->LockFocusRect(FALSE); } break; case rad5: if (HIWORD(wParam) == BN_CLICKED) { // now change the icon SetPreviewBitmap(IDR_PRINT_PREVIEWONEDOC, hdlg); HWND hwnd = GetDlgItem(hdlg, rad2); if (hwnd) EnableWindow(hwnd, (ppcbi->fPrintSelection)); hwnd = GetDlgItem(hdlg, IDC_SHORTCUTS); if (hwnd) EnableWindow(hwnd, TRUE); hwnd = GetDlgItem(hdlg, IDC_LINKED); if (hwnd) EnableWindow(hwnd, TRUE); // if(ppcbi->pBodyActive); // ppcbi->pBodyActive->Layout()->LockFocusRect(TRUE); } break; case rad6: if (HIWORD(wParam) == BN_CLICKED) { // now change the icon SetPreviewBitmap(IDR_PRINT_PREVIEWALLDOCS, hdlg); HWND hwnd = GetDlgItem(hdlg, rad2); if (hwnd) EnableWindow(hwnd, FALSE); hwnd = GetDlgItem(hdlg, IDC_SHORTCUTS); if (hwnd) EnableWindow(hwnd, TRUE); hwnd = GetDlgItem(hdlg, IDC_LINKED); if (hwnd) EnableWindow(hwnd, TRUE); // if(ppcbi->pBodyActive); // ppcbi->pBodyActive->Layout()->LockFocusRect(FALSE); } break; #ifdef UNIX case rad7: // Portrait CheckRadioButton(hdlg, ID_PRINT_R_PORTRAIT, ID_PRINT_R_LANDSCAPE, ID_PRINT_R_PORTRAIT); break; case rad8: // Landscape CheckRadioButton(hdlg, ID_PRINT_R_PORTRAIT, ID_PRINT_R_LANDSCAPE, ID_PRINT_R_LANDSCAPE); break; #endif // UNIX } } void OnHelp( HWND hdlg, WPARAM wParam, LPARAM lParam ) { LPHELPINFO pHI; pHI = (LPHELPINFO)lParam; if (pHI->iContextType == HELPINFO_WINDOW) // must be for a control { WinHelp( (HWND)pHI->hItemHandle, GetHelpFile(pHI->iCtrlId, (DWORD *) aPrintDialogHelpIDs), HELP_WM_HELP, (DWORD_PTR)(LPVOID) aPrintDialogHelpIDs); } } void OnContextMenu( HWND hdlg, WPARAM wParam, LPARAM lParam ) { int CtrlID = GetControlID((HWND)wParam, lParam); WinHelp( (HWND)wParam, GetHelpFile(CtrlID, (DWORD *) aPrintDialogHelpIDs), HELP_CONTEXTMENU, (DWORD_PTR)(LPVOID) aPrintDialogHelpIDs); } void OnApplyOrOK( HWND hdlg, WPARAM wParam, LPARAM lParam ) { #ifdef UNIX CHAR szPrinterCommand[MAX_PATH]; #endif // UNIX PRINTBOXCALLBACKINFO * ppcbi; ppcbi = (PRINTBOXCALLBACKINFO *)GetWindowLongPtr(hdlg, DWLP_USER); if (ppcbi) { ppcbi->fPrintLinked = IsDlgButtonChecked(hdlg, IDC_LINKED); ppcbi->fPrintSelection = IsDlgButtonChecked(hdlg, rad2); ppcbi->fPrintActiveFrame = IsDlgButtonChecked(hdlg, rad5) || ( ppcbi->fPrintSelection && ppcbi->fRootDocumentHasFrameset ); ppcbi->fPrintAsShown = IsDlgButtonChecked(hdlg, rad4) || ( ppcbi->fPrintSelection && ppcbi->fRootDocumentHasFrameset ); ppcbi->fShortcutTable = IsDlgButtonChecked(hdlg, IDC_SHORTCUTS); #ifdef FONTSIZE_BOX ppcbi->iFontScaling = IDS_PRINT_FONTMAX - 1 - SendDlgItemMessage( hdlg, IDC_SCALING, CB_GETCURSEL, 0,0 ); #endif #ifdef UNIX // Code to deal with orientation on print dialog if ( IsDlgButtonChecked(hdlg, ID_PRINT_R_PORTRAIT) ) { ppcbi->dmOrientation = DMORIENT_PORTRAIT; } else { ppcbi->dmOrientation = DMORIENT_LANDSCAPE; } // get user entered printer command GetDlgItemTextA(hdlg, edt4, szPrinterCommand, MAX_PATH); MwSetPrintCommand( szPrinterCommand ); #endif // UNIX } } // This is the callback routine (and dlgproc) for the options // page in the NT 5 print dialog. INT_PTR APIENTRY OptionsPageProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { switch (uiMsg) { case WM_INITDIALOG: { PRINTBOXCALLBACKINFO * ppcbi; ppcbi = (PRINTBOXCALLBACKINFO *) ((PROPSHEETPAGE *)lParam)->lParam; SetWindowLongPtr(hdlg, DWLP_USER, (LONG_PTR)ppcbi); OnInitDialog( hdlg, ppcbi ); break; } case WM_NOTIFY: switch (((NMHDR FAR *)lParam)->code) { case PSN_APPLY: OnApplyOrOK( hdlg, wParam, lParam ); SetWindowLongPtr (hdlg, DWLP_MSGRESULT, PSNRET_NOERROR); return TRUE; break; case PSN_KILLACTIVE: SetWindowLongPtr (hdlg, DWLP_MSGRESULT, FALSE); return 1; break; case PSN_RESET: SetWindowLongPtr (hdlg, DWLP_MSGRESULT, FALSE); break; } break; case WM_COMMAND: OnCommand( hdlg, wParam, lParam ); break; case WM_HELP: OnHelp( hdlg, wParam, lParam ); break; case WM_CONTEXTMENU: OnContextMenu( hdlg, wParam, lParam ); break; } return FALSE; } UINT_PTR CALLBACK PrintHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { switch (uiMsg) { case WM_INITDIALOG: if (lParam) { PRINTBOXCALLBACKINFO * ppcbi; ppcbi = (PRINTBOXCALLBACKINFO *) ((PRINTDLG*)lParam)->lCustData; SetWindowLongPtr(hdlg, DWLP_USER, (LONG_PTR)ppcbi); OnInitDialog( hdlg, ppcbi ); } return TRUE; case WM_COMMAND: { switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDOK: OnApplyOrOK( hdlg, wParam, lParam ); break; default: OnCommand( hdlg, wParam, lParam ); break; } } break; case WM_HELP: OnHelp( hdlg, wParam, lParam ); break; //return TRUE; case WM_CONTEXTMENU: OnContextMenu( hdlg, wParam, lParam ); break; case WM_DESTROY: { PRINTBOXCALLBACKINFO * ppcbi; ppcbi = (PRINTBOXCALLBACKINFO *)GetWindowLongPtr(hdlg, DWLP_USER); ASSERT(ppcbi); // if(ppcbi && ppcbi->pBodyActive); // ppcbi->pBodyActive->Layout()->LockFocusRect(FALSE); break; } } return FALSE; } void SetPreviewBitmap(long bitmapID, HWND hdlg) { // now change the icon...(note these bitmaps are not localized) HBITMAP hNewBitmap, hOldBitmap; hNewBitmap = (HBITMAP) LoadImage(HINST_THISDLL, MAKEINTRESOURCE(bitmapID), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_LOADMAP3DCOLORS ); ASSERT(hNewBitmap); if (hNewBitmap) { hOldBitmap = (HBITMAP) SendDlgItemMessage(hdlg, IDC_PREVIEW, STM_SETIMAGE, (WPARAM) IMAGE_BITMAP, (LPARAM) hNewBitmap); if (hOldBitmap) { //VERIFY(DeleteObject(hOldBitmap)!=0); int i; i = DeleteObject(hOldBitmap); ASSERT(i!=0); } } } //+--------------------------------------------------------------------------- // // Helper for OLECMDID_SHOWPRINT // //+--------------------------------------------------------------------------- HRESULT CDocHostUIHandler::ShowPrintDialog(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD) { // the following must match the order of PrintEnum static const SExpandoInfo s_aPrintExpandos[] = { {OLESTR("printfRootDocumentHasFrameset"), VT_BOOL}, {OLESTR("printfAreRatingsEnabled"), VT_BOOL}, {OLESTR("printfActiveFrame"), VT_BOOL}, {OLESTR("printfLinked"), VT_BOOL}, {OLESTR("printfSelection"), VT_BOOL}, {OLESTR("printfAsShown"), VT_BOOL}, {OLESTR("printfShortcutTable"), VT_BOOL}, {OLESTR("printiFontScaling"), VT_INT}, {OLESTR("printpBodyActiveTarget"), VT_UNKNOWN}, {OLESTR("printStruct"), VT_PTR}, {OLESTR("printToFileOk"), VT_BOOL}, {OLESTR("printToFileName"), VT_BSTR}, {OLESTR("printfActiveFrameEnabled"), VT_BOOL}, }; HRESULT hr = E_FAIL; PRINTDLG * pprintdlg = NULL; PRINTBOXCALLBACKINFO printcbi; IHTMLEventObj * pEventObj = NULL; const int cExpandos = ARRAYSIZE(s_aPrintExpandos); DISPID aDispid[cExpandos]; VARIANT aVariant[cExpandos]; int i; DWORD dwErr = 0; printcbi.pBodyActive = NULL; if (!V_UNKNOWN(pvarargIn)) goto Cleanup; if (V_UNKNOWN(pvarargIn)->QueryInterface(IID_IHTMLEventObj, (void **) &pEventObj)) goto Cleanup; // Get parameters from event object if (GetParamsFromEvent( pEventObj, cExpandos, aDispid, aVariant, s_aPrintExpandos)) goto Cleanup; // Copy values from variants printcbi.fRootDocumentHasFrameset = V_BOOL(&aVariant[PrintfRootDocumentHasFrameset]); printcbi.fAreRatingsEnabled = V_BOOL(&aVariant[PrintfAreRatingsEnabled]); printcbi.fPrintActiveFrame = V_BOOL(&aVariant[PrintfPrintActiveFrame]); printcbi.fPrintActiveFrameEnabled = V_BOOL(&aVariant[PrintfPrintActiveFrameEnabled]); printcbi.fPrintLinked = V_BOOL(&aVariant[PrintfPrintLinked]); printcbi.fPrintSelection = V_BOOL(&aVariant[PrintfPrintSelection]); printcbi.fPrintAsShown = V_BOOL(&aVariant[PrintfPrintAsShown]); printcbi.fShortcutTable = V_BOOL(&aVariant[PrintfShortcutTable]); printcbi.iFontScaling = V_INT(&aVariant[PrintiFontScaling]); // If we ever get LockFocusRect, use this field to access it // peterlee 8/7/98 /* if (V_UNKNOWN(&aVariant[PrintpBodyActiveTarget])) { if (V_UNKNOWN(&aVariant[PrintpBodyActiveTarget])->QueryInterface(IID_IOleCommandTarget, (void**)&printcbi.pBodyActive)) goto Cleanup; } */ pprintdlg = (PRINTDLG *)V_BYREF(&aVariant[PrintStruct]); if (!pprintdlg) goto Cleanup; // Fix up requested page range so it's within bounds. The dialog will // fail to initialize under W95 if this isn't done. if ( pprintdlg->nFromPage < pprintdlg->nMinPage ) pprintdlg->nFromPage = pprintdlg->nMinPage; else if ( pprintdlg->nFromPage > pprintdlg->nMaxPage ) pprintdlg->nFromPage = pprintdlg->nMaxPage; if ( pprintdlg->nToPage < pprintdlg->nMinPage ) pprintdlg->nToPage = pprintdlg->nMinPage; else if ( pprintdlg->nToPage > pprintdlg->nMaxPage ) pprintdlg->nToPage = pprintdlg->nMaxPage; // Set up custom dialog resource fields in pagesetupdlg pprintdlg->hInstance = MLLoadShellLangResources(); pprintdlg->lCustData = (LPARAM) &printcbi; pprintdlg->lpfnPrintHook = PrintHookProc; #ifdef UNIX pprintdlg->lpPrintTemplateName = MAKEINTRESOURCE(PRINTDLGORDMOTIF); pprintdlg->Flags |= PD_SHOWHELP; pprintdlg->Flags |= PD_ENABLESETUPHOOK; pprintdlg->lpfnSetupHook = PageSetupHookProc; #else pprintdlg->lpPrintTemplateName = MAKEINTRESOURCE(PRINTDLGORD); #endif // UNIX if (g_bRunOnNT5) { // We want to use the new PrintDlgEx in NT 5, so map all the PrintDlg // settings to the new PrintDlgEx, get a pointer to the new function // and then call it. // Load the function from comdlg32 directly... typedef HRESULT (*PFNPRINTDLGEX)(LPPRINTDLGEX pdex); PFNPRINTDLGEX pfnPrintDlgEx = NULL; HMODULE hComDlg32 = LoadLibrary( TEXT("comdlg32.dll") ); if (hComDlg32) { pfnPrintDlgEx = (PFNPRINTDLGEX)GetProcAddress( hComDlg32, "PrintDlgExW" ); } // Make sure we can call the function... if (!pfnPrintDlgEx) { if (hComDlg32) { FreeLibrary( hComDlg32 ); } hr = E_FAIL; goto Cleanup; } PRINTDLGEX pdex; PROPSHEETPAGE psp; HPROPSHEETPAGE pages[1]; PRINTPAGERANGE ppr; // Copy over existing settings memset( &pdex, 0, sizeof(pdex) ); pdex.lStructSize = sizeof(pdex); pdex.hwndOwner = pprintdlg->hwndOwner; pdex.hDevMode = pprintdlg->hDevMode; pdex.hDevNames = pprintdlg->hDevNames; pdex.hDC = pprintdlg->hDC; pdex.Flags = pprintdlg->Flags; pdex.nMinPage = pprintdlg->nMinPage; pdex.nMaxPage = pprintdlg->nMaxPage; pdex.nCopies = pprintdlg->nCopies; // New settings pdex.nStartPage = START_PAGE_GENERAL; ppr.nFromPage = pprintdlg->nFromPage; ppr.nToPage = pprintdlg->nToPage; pdex.nPageRanges = 1; pdex.nMaxPageRanges = 1; pdex.lpPageRanges = &ppr; // Create options page memset( &psp, 0, sizeof(psp) ); psp.dwSize = sizeof(psp); psp.dwFlags = PSP_DEFAULT; psp.hInstance = pprintdlg->hInstance; psp.pszTemplate = MAKEINTRESOURCE(IDD_PRINTOPTIONS); psp.pfnDlgProc = OptionsPageProc; psp.lParam = (LPARAM)&printcbi; pages[0] = SHNoFusionCreatePropertySheetPageW(&psp); if (pages[0]) { pdex.nPropertyPages = 1; pdex.lphPropertyPages = pages; // Show the dialog ULONG_PTR uCookie = 0; SHActivateContext(&uCookie); hr = pfnPrintDlgEx(&pdex); if (uCookie) { SHDeactivateContext(uCookie); } if (SUCCEEDED(hr)) { hr = S_FALSE; if ((pdex.dwResultAction == PD_RESULT_PRINT) || (pdex.Flags & PD_RETURNDEFAULT)) { // copy back values which might have changed // during the call to PrintDlgEx pprintdlg->Flags = pdex.Flags; pprintdlg->hDevMode = pdex.hDevMode; pprintdlg->hDevNames = pdex.hDevNames; pprintdlg->nCopies = (WORD)pdex.nCopies; pprintdlg->nFromPage = (WORD)ppr.nFromPage; pprintdlg->nToPage = (WORD)ppr.nToPage; if (pprintdlg->Flags & PD_RETURNDC) { pprintdlg->hDC = pdex.hDC; } hr = S_OK; } else if ((pdex.Flags & (PD_RETURNDC | PD_RETURNIC)) && pdex.hDC) { DeleteDC(pdex.hDC); pdex.hDC = NULL; } } else { hr = S_FALSE; } FreeLibrary( hComDlg32 ); } else { FreeLibrary( hComDlg32 ); hr = E_OUTOFMEMORY; goto Cleanup; } } else { pprintdlg->Flags |= PD_ENABLEPRINTTEMPLATE | PD_ENABLEPRINTHOOK; pprintdlg->Flags &= (~(PD_CURRENTPAGE | PD_NOCURRENTPAGE)); // Just in case, mask out the W2K only. // Show dialog if (!PrintDlg(pprintdlg)) { // treat failure as canceling dwErr = CommDlgExtendedError(); hr = S_FALSE; goto Cleanup; } hr = S_OK; } // Write changed values to event object VARIANT var; V_VT(&var) = VT_BOOL; V_BOOL(&var) = printcbi.fPrintLinked ? VARIANT_TRUE : VARIANT_FALSE; PutParamToEvent(aDispid[PrintfPrintLinked], &var, pEventObj); V_BOOL(&var) = printcbi.fPrintActiveFrame ? VARIANT_TRUE : VARIANT_FALSE; PutParamToEvent(aDispid[PrintfPrintActiveFrame], &var, pEventObj); V_BOOL(&var) = printcbi.fPrintAsShown ? VARIANT_TRUE : VARIANT_FALSE; PutParamToEvent(aDispid[PrintfPrintAsShown], &var, pEventObj); V_BOOL(&var) = printcbi.fShortcutTable ? VARIANT_TRUE : VARIANT_FALSE; PutParamToEvent(aDispid[PrintfShortcutTable], &var, pEventObj); #ifdef FONTSIZE_BOX V_VT(&var) = VT_INT; V_INT(&var) = printcbi.iFontScaling; PutParamToEvent(aDispid[PrintiFontScaling], &var, pEventObj); #endif // FONTSIZE_BOX #ifdef UNIX V_VT(&var) = VT_INT; V_INT(&var) = printcbi.dmOrientation; PutParamToEvent(aDispid[PrintdmOrientation], &var, pEventObj); #endif // UNIX // now pop up the fileselection dialog and save the filename... // this is the only place where we can make this modal BOOL fPrintToFileOk; fPrintToFileOk = FALSE; if ((pprintdlg->Flags & PD_PRINTTOFILE) != 0) { // Get the save file path from the event object TCHAR achPrintToFileName[MAX_PATH]; StrCpyN(achPrintToFileName, V_BSTR(&aVariant[PrintToFileName]) ? V_BSTR(&aVariant[PrintToFileName]) : TEXT(""), ARRAYSIZE(achPrintToFileName)); if (!GetPrintFileName(pprintdlg->hwndOwner, achPrintToFileName) && achPrintToFileName) { fPrintToFileOk = TRUE; V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(achPrintToFileName); if (NULL != V_BSTR(&var)) { PutParamToEvent(aDispid[PrintToFileName], &var, pEventObj); VariantClear(&var); } } } V_VT(&var) = VT_BOOL; V_BOOL(&var) = fPrintToFileOk ? VARIANT_TRUE : VARIANT_FALSE; PutParamToEvent(aDispid[PrintToFileOk], &var, pEventObj); Cleanup: if (pprintdlg) MLFreeLibrary(pprintdlg->hInstance); for (i=0; i 0) openfilename.lpstrTitle = achTitlePrintInto; // guarantee trailing 0 to terminate the filter string memset(achFilter, 0, sizeof(TCHAR)*MAX_PATH); cbLen = MLLoadShellLangString(IDS_PRINTTOFILE_SPEC,achFilter,MAX_PATH-2); ASSERT (cbLen && "could not load the resource"); if (cbLen>0) { for (; cbLen >= 0; cbLen--) { if (achFilter[cbLen]== L',') { achFilter[cbLen] = 0; } } } openfilename.nMaxFileTitle = openfilename.lpstrTitle ? lstrlen(openfilename.lpstrTitle) : 0; StrCpyN(achFilePrintInto, TEXT(""), ARRAYSIZE(achFilePrintInto)); openfilename.lpstrFile = achFilePrintInto; openfilename.nMaxFile = MAX_PATH; openfilename.Flags = OFN_NOREADONLYRETURN | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_ENABLEHOOK | OFN_NOCHANGEDIR; openfilename.lpfnHook = PrintToFileHookProc; openfilename.lpstrFilter = achFilter; openfilename.nFilterIndex = 1; StrCpyN(achPath, achFilePath, ARRAYSIZE(achPath)); openfilename.lpstrInitialDir = *achPath ? achPath : NULL; if (GetSaveFileName(&openfilename)) { StrCpyN(achFilePath, openfilename.lpstrFile, MAX_PATH); hr = S_OK; } if (hr) *achFilePath = NULL; return hr; } //+--------------------------------------------------------------------------- // // Helpers for OLECMDID_PROPERTIES // //+--------------------------------------------------------------------------- HRESULT CDocHostUIHandler::ShowPropertysheetDialog(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, DWORD) { // must match order of PropertysheetEnum static const SExpandoInfo s_aPropertysheetExpandos[] = { {OLESTR("propertysheetPunks"), VT_SAFEARRAY} }; HRESULT hr; HWND hwnd = NULL; HWND hwndParent; IUnknown * punk = NULL; OLECMD olecmd = {0, 0}; int cUnk = 0; IUnknown * HUGEP * apUnk = NULL; OCPFIPARAMS ocpfiparams; CAUUID ca = { 0, 0 }; RECT rc = {0, 0, 0, 0}; RECT rcDesktop = {0, 0, 0, 0}; SIZE pixelOffset; SIZE metricOffset = {0, 0}; IHTMLEventObj * pEventObj = NULL; const int cExpandos = ARRAYSIZE(s_aPropertysheetExpandos); VARIANT aVariant[cExpandos]; DISPID aDispid[cExpandos]; SAFEARRAY * psafearray = NULL; for (int i=0; icElems = 0; pca->pElems = NULL; for (i = 0; i < cUnk; i++) { pUnk = apUnk[i]; ASSERT(pUnk); hr = THR(pUnk->QueryInterface( IID_ISpecifyPropertyPages, (void **)&pSPP)); if (hr) goto Cleanup; hr = THR(pSPP->GetPages(fFirst ? pca : &caCurrent)); ATOMICRELEASE(pSPP); if (hr) goto Cleanup; if (fFirst) continue; // keep only the common pages else { for (iScan = 0, iFill = 0; iScan < pca->cElems; iScan++) { for (iCompare = 0; iCompare < caCurrent.cElems; iCompare++) { if (caCurrent.pElems[iCompare] == pca->pElems[iScan]) break; } if (iCompare != caCurrent.cElems) { pca->pElems[iFill++] = pca->pElems[iScan]; } } pca->cElems = iFill; CoTaskMemFree(caCurrent.pElems); } } Cleanup: return hr; } //+--------------------------------------------------------------------------- // // Helper for SHDVID_CLSIDTOMONIKER // //+--------------------------------------------------------------------------- struct HTMLPAGECACHE { const CLSID * pclsid; TCHAR * ach; }; HRESULT CDocHostUIHandler::ClsidToMoniker(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut) { static const HTMLPAGECACHE s_ahtmlpagecache[] = { &CLSID_CAnchorBrowsePropertyPage, _T("anchrppg.ppg"), &CLSID_CImageBrowsePropertyPage, _T("imageppg.ppg"), &CLSID_CDocBrowsePropertyPage, _T("docppg.ppg"), }; HRESULT hr = E_FAIL; IMoniker * pmk = NULL; IUnknown * pUnk = NULL; int i; const HTMLPAGECACHE * phtmlentry; const CLSID * pclsid; ASSERT(pvarargIn); ASSERT(pvarargOut); ASSERT(V_VT(pvarargIn) == VT_UINT_PTR && V_BYREF(pvarargIn)); if (!pvarargIn || V_VT(pvarargIn) != VT_UINT_PTR || !V_BYREF(pvarargIn)) goto Cleanup; pclsid = (CLSID *)V_BYREF(pvarargIn); if (!pvarargOut) goto Cleanup; VariantInit(pvarargOut); // lookup the resource from the CLSID for (i = ARRAYSIZE(s_ahtmlpagecache) - 1, phtmlentry = s_ahtmlpagecache; i >= 0; i--, phtmlentry++) { ASSERT(phtmlentry->pclsid && phtmlentry->ach); if (IsEqualCLSID(*pclsid, *phtmlentry->pclsid)) { // create a moniker for the dialog resource TCHAR szResURL[MAX_URL_STRING]; #ifndef UNIX hr = MLBuildResURL(TEXT("shdoclc.dll"), HINST_THISDLL, ML_CROSSCODEPAGE, phtmlentry->ach, szResURL, ARRAYSIZE(szResURL)); #else hr = MLBuildResURLWrap(TEXT("shdoclc.dll"), HINST_THISDLL, ML_CROSSCODEPAGE, phtmlentry->ach, szResURL, ARRAYSIZE(szResURL), TEXT("shdocvw.dll")); #endif if (hr) goto Cleanup; hr = CreateURLMoniker(NULL, szResURL, &pmk); if (hr) goto Cleanup; break; } } if (!pmk) goto Cleanup; // return the moniker hr = pmk->QueryInterface(IID_IUnknown, (void**)&pUnk); if (hr) goto Cleanup; else { V_VT(pvarargOut) = VT_UNKNOWN; V_UNKNOWN(pvarargOut) = pUnk; V_UNKNOWN(pvarargOut)->AddRef(); } Cleanup: ATOMICRELEASE(pUnk); ATOMICRELEASE(pmk); return hr; } STDMETHODIMP CDocHostUIHandler::Invoke( DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { HRESULT hr = S_OK; if (pDispParams && pDispParams->cArgs>=1) { if (pDispParams->rgvarg[0].vt == VT_DISPATCH) { IHTMLEventObj *pObj=NULL; if (SUCCEEDED(pDispParams->rgvarg[0].pdispVal->QueryInterface(IID_IHTMLEventObj, (void **)&pObj) && pObj)) { BSTR bstrEvent=NULL; pObj->get_type(&bstrEvent); if (bstrEvent) { ASSERT(!StrCmpCW(bstrEvent, L"unload")); IWebBrowser2* pwb2; hr = IUnknown_QueryServiceForWebBrowserApp(_punkSite, IID_PPV_ARG(IWebBrowser2, &pwb2)); if (SUCCEEDED(hr)) { IHTMLWindow2* pWindow; // we shouldn't be catching this event if the dialog is not up if (IsFindDialogUp(pwb2, &pWindow)) { ASSERT(pWindow); if (_pOptionsHolder) { BSTR bstrFindText = NULL; _pOptionsHolder->get_findText(&bstrFindText); ATOMICRELEASE(_pOptionsHolder); PutFindText(pwb2, bstrFindText); SysFreeString(bstrFindText); } BSTR bstrOnunload = SysAllocString(L"onunload"); if (bstrOnunload) { IHTMLWindow3 * pWin3; if (SUCCEEDED(pWindow->QueryInterface(IID_IHTMLWindow3, (void**)&pWin3))) { pWin3->detachEvent(bstrOnunload, (IDispatch*)this); pWin3->Release(); } SysFreeString(bstrOnunload); } pWindow->Release(); //this is the one that should release the dialog (the pWinOut from ShowFindDialog()) ReleaseFindDialog(pwb2); } pwb2->Release(); } SysFreeString(bstrEvent); } pObj->Release(); } } } return hr; } //------------------------------------------------------------------ //------------------------------------------------------------------ IMoniker * GetTemplateMoniker(VARIANT varUrl) { IMoniker * pMon = NULL; HRESULT hr = S_OK; if ( V_VT(&varUrl) == VT_BSTR && SysStringLen(V_BSTR(&varUrl)) !=0) { // we have a template URL hr = CreateURLMoniker(NULL, V_BSTR(&varUrl), &pMon); } else { TCHAR szResURL[MAX_URL_STRING]; hr = MLBuildResURLWrap(TEXT("shdoclc.dll"), HINST_THISDLL, ML_CROSSCODEPAGE, TEXT("preview.dlg"), szResURL, ARRAYSIZE(szResURL), TEXT("shdocvw.dll")); if (hr) goto Cleanup; hr = CreateURLMoniker(NULL, szResURL, &pMon); } if (hr) goto Cleanup; Cleanup: return pMon; } //============================================================================ // // Printing support // //============================================================================ static enum { eTemplate = 0, eParentHWND = 1, eHeader = 2, // keep this in ssync with the list below! eFooter = 3, eOutlookDoc = 4, eFontScale = 5, eFlags = 6, eContent = 7, ePrinter = 8, eDevice = 9, ePort = 10, eSelectUrl = 11, eBrowseDoc = 12, eTempFiles = 13, }; static const SExpandoInfo s_aPrintTemplateExpandos[] = { {TEXT("__IE_TemplateUrl"), VT_BSTR}, {TEXT("__IE_ParentHWND"), VT_UINT}, {TEXT("__IE_HeaderString"), VT_BSTR}, // from here down matches the {TEXT("__IE_FooterString"), VT_BSTR}, // safeArray structure so {TEXT("__IE_OutlookHeader"), VT_UNKNOWN}, // that we can just VariantCopy {TEXT("__IE_BaseLineScale"), VT_INT}, // in a loop to transfer the {TEXT("__IE_uPrintFlags"), VT_UINT}, // data. {TEXT("__IE_ContentDocumentUrl"), VT_BSTR}, // See MSHTML: SetPrintCommandParameters() {TEXT("__IE_PrinterCMD_Printer"), VT_BSTR}, {TEXT("__IE_PrinterCMD_Device"), VT_BSTR}, {TEXT("__IE_PrinterCMD_Port"), VT_BSTR}, {TEXT("__IE_ContentSelectionUrl"), VT_BSTR}, {TEXT("__IE_BrowseDocument"), VT_UNKNOWN}, {TEXT("__IE_TemporaryFiles"), VT_ARRAY|VT_BSTR}, }; //+-------------------------------------------------------------------------------------- // // Helper class CPrintUnloadHandler. Used to delete tempfiles created for print[preview]. // Note that we don't delete files when we get onUnload event - at this moment // files are still in use and can't be deleted. We use destructor - when template // is being destructed and all files are already released, template releases // all sinks and here we do our cleanup. //--------------------------------------------------------------------------------------- class CPrintUnloadHandler: public IDispatch { CDocHostUIHandler *m_pUIHandler; VARIANT m_vFileNameArray; //SAFEARRAY with filenames LONG m_cRef; IUnknown *m_punkFreeThreadedMarshaler; bool m_fPreview; public: //IUnknown STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID *ppv) { HRESULT hr = E_NOINTERFACE; if (ppv == NULL) return E_POINTER; else if(IsEqualIID(IID_IUnknown, riid) || IsEqualIID(IID_IDispatch, riid)) { *ppv = this; AddRef(); hr = S_OK; } else if(IsEqualIID(IID_IMarshal, riid)) hr = m_punkFreeThreadedMarshaler->QueryInterface(riid,ppv); return hr; } STDMETHOD_(ULONG,AddRef)(THIS) { InterlockedIncrement(&m_cRef); return m_cRef; } STDMETHOD_(ULONG,Release)(THIS) { if (InterlockedDecrement(&m_cRef)) return m_cRef; delete this; return 0; } //IDispatch virtual STDMETHODIMP GetTypeInfoCount(UINT* pctinfo) { return E_NOTIMPL; }; virtual STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) { return E_NOTIMPL; }; virtual STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) { return E_NOTIMPL; }; virtual STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { return S_OK; } CPrintUnloadHandler(CDocHostUIHandler *pUIHandler, bool fPreview) { ASSERT(pUIHandler); //make sure our handler doesn't go anywere.. m_pUIHandler = pUIHandler; pUIHandler->AddRef(); m_cRef = 1; VariantInit(&m_vFileNameArray); //create threaded marshaler because we will be called from another thread //which will be created for print(preview) window CoCreateFreeThreadedMarshaler((IUnknown*)this, &m_punkFreeThreadedMarshaler); //if preview, lock the preview gate so no more then one is possible m_fPreview = fPreview; if(m_fPreview) pUIHandler->IncrementPreviewCnt(); } ~CPrintUnloadHandler() { //here we delete those temp files, finally. DeleteFiles(); if(m_fPreview) m_pUIHandler->DecrementPreviewCnt(); if(m_pUIHandler) m_pUIHandler->Release(); if(m_punkFreeThreadedMarshaler) m_punkFreeThreadedMarshaler->Release(); VariantClear(&m_vFileNameArray); } HRESULT SetFileList(VARIANT *pvFileList) { if(pvFileList && (V_VT(pvFileList) == (VT_ARRAY | VT_BSTR))) return VariantCopy(&m_vFileNameArray, pvFileList); else return VariantClear(&m_vFileNameArray); } void DeleteFiles() { int arrayMin, arrayMax; if(V_VT(&m_vFileNameArray) != (VT_ARRAY | VT_BSTR)) return; SAFEARRAY *psa = V_ARRAY(&m_vFileNameArray); if(FAILED(SafeArrayGetLBound(psa, 1, (LONG*)&arrayMin))) return; if(FAILED(SafeArrayGetUBound(psa, 1, (LONG*)&arrayMax))) return; for ( int i = arrayMin; i <= arrayMax; i++ ) { BSTR bstrName = NULL; if(SUCCEEDED(SafeArrayGetElement(psa, (LONG*)&i, &bstrName)) && bstrName) { TCHAR szFileName[MAX_PATH]; SHUnicodeToTChar(bstrName, szFileName, MAX_PATH); DeleteFile(szFileName); SysFreeString(bstrName); } } } }; //+-------------------------------------------------------------------------------------- // // Member DoTemplatePrinting // // Synopsis : this member function deals with instantiating a print template and enabling // the printing of a document. It deals with the logic of whether to show or hide the // template; determining whether/and-how to bring up the print/page-setup dialogs; // kicking off the print process rather or waiting for the template // UI (and thus the user) to do so. // // Arguments : // pvarargIn : points to an event object with a number of expandoes that define // how this print operation should progress. // pvarargOut : not used // fPreview : flag indicating whether or not to actually show the template. This is true // for preview mode, and false for normal printing // //--------------------------------------------------------------------------------------- HRESULT CDocHostUIHandler::DoTemplatePrinting(VARIANTARG *pvarargIn, VARIANTARG *pvarargOut, BOOL fPreview) { int i; HRESULT hr = S_OK; VARIANT varDLGOut = {0}; const int cExpandos = ARRAYSIZE(s_aPrintTemplateExpandos); VARIANT aVariant[cExpandos] = {0}; DISPID aDispid[cExpandos]; BSTR bstrDlgOptions = NULL; DWORD dwDlgFlags; IHTMLEventObj * pEventObj = NULL; IHTMLEventObj2 * pEventObj2 = NULL; IMoniker * pmk = NULL; IHTMLWindow2 * pWinOut = NULL; TCHAR achInit[512]; TCHAR achBuf[32]; RECT rcClient; HWND hwndOverlay = NULL; HWND hwndParent = NULL; CPrintUnloadHandler * pFinalizer = NULL; BOOL fBlock; // in preview mode we do not want to bring up another instance of the template if (fPreview && (IncrementPreviewCnt() > 1)) goto Cleanup; if (SHRestricted2(REST_NoPrinting, NULL, 0)) { // printing functionality disabled via IEAK restriction MLShellMessageBox(NULL, MAKEINTRESOURCE(IDS_RESTRICTED), MAKEINTRESOURCE(IDS_TITLE), MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND); hr = S_FALSE; goto Cleanup; } ASSERT(V_VT(pvarargIn) == VT_UNKNOWN); if ((V_VT(pvarargIn) != VT_UNKNOWN) || !V_UNKNOWN(pvarargIn)) { hr = E_INVALIDARG; goto Cleanup; } // // now get the expando properties that were passed in... // hr = V_UNKNOWN(pvarargIn)->QueryInterface(IID_IHTMLEventObj, (void**)&pEventObj); if (hr) goto Cleanup; hr = V_UNKNOWN(pvarargIn)->QueryInterface(IID_IHTMLEventObj2, (void**)&pEventObj2); if (hr) goto Cleanup; // // Get expando parameters from event object // hr = GetParamsFromEvent(pEventObj, cExpandos, aDispid, aVariant, s_aPrintTemplateExpandos); if (hr) goto Cleanup; // // Now that we have all the data, lets do the work of raising the template. // First, Create the Moniker of the template document // pmk = GetTemplateMoniker(aVariant[eTemplate]); // // Set up the bstrDlgOptions to properly pass in the size and location // _tcscpy(achInit, _T("resizable:yes;status:no;help:no;")); // // get the top most hwnd to use as the parenting hwnd and // to use to set the size of the preview window // hwndOverlay = (HWND)(void*)V_UNKNOWN(&aVariant[eParentHWND]); while (hwndParent = GetParent(hwndOverlay)) { hwndOverlay = hwndParent; } if (GetWindowRect(hwndOverlay, &rcClient)) { _tcscat(achInit, _T("dialogLeft:")); _ltot(rcClient.left, achBuf, 10); _tcscat(achInit, achBuf); _tcscat(achInit, _T("px;dialogTop:")); _ltot(rcClient.top, achBuf, 10); _tcscat(achInit, achBuf); _tcscat(achInit, _T("px;dialogWidth:")); _ltot(rcClient.right - rcClient.left, achBuf, 10); _tcscat(achInit, achBuf); _tcscat(achInit, _T("px;dialogHeight:")); _ltot(rcClient.bottom - rcClient.top, achBuf, 10); _tcscat(achInit, achBuf); _tcscat(achInit, _T("px;")); } bstrDlgOptions = SysAllocString(achInit); if (!bstrDlgOptions) { hr = E_OUTOFMEMORY; goto Cleanup; } //Create a finalizer pFinalizer = new CPrintUnloadHandler(this, fPreview); if(pFinalizer) { pFinalizer->SetFileList(&aVariant[eTempFiles]); } // // Bring up a modeless dialog and get the window pointer so that // we can properly initialize the template document. // V_VT(&varDLGOut) = VT_UNKNOWN; V_UNKNOWN(&varDLGOut) = NULL; // HTMLDLG_MODELESS really means "open dialog on its own thread", which // we want to do for both actual printing and previewing. // Note that if we're previewing, we also flip on HTMLDLG_MODAL; this // is by design! (see comment below). fBlock = ((V_UINT(&aVariant[eFlags]) & PRINT_WAITFORCOMPLETION) != 0); dwDlgFlags = HTMLDLG_PRINT_TEMPLATE; // VERIFY if we are going to display if (fPreview) dwDlgFlags |= HTMLDLG_VERIFY; // otherwise, don't display with NOUI else dwDlgFlags |= HTMLDLG_NOUI; // If we are not printing synchronously, create a thread for printing. if (!fBlock) dwDlgFlags |= HTMLDLG_MODELESS; // Dlg should block UI on parent if (fPreview || fBlock) dwDlgFlags |= HTMLDLG_MODAL; ShowHTMLDialogEx((HWND)(void*)V_UNKNOWN(&aVariant[eParentHWND]), pmk, dwDlgFlags, pvarargIn, bstrDlgOptions, &varDLGOut); if (V_UNKNOWN(&varDLGOut)) { V_UNKNOWN(&varDLGOut)->QueryInterface(IID_IHTMLWindow2, (void**)&pWinOut); } if (pWinOut) { BSTR bstrOnunload = SysAllocString(L"onunload"); // // can't really handle failure here, because the dialog is already up. // .. but we need to set up an onunload handler to properly ref release // if (bstrOnunload) { IHTMLWindow3 * pWin3; if (SUCCEEDED(pWinOut->QueryInterface(IID_IHTMLWindow3, (void**)&pWin3))) { VARIANT_BOOL varBool; hr = pWin3->attachEvent(bstrOnunload, (IDispatch*)pFinalizer, &varBool); // (greglett) If this fails, we're in trouble. // We can either delete the temp files at the end of the function (where the ATOMICRELEASE // calls the Finalizer's destructor), or we can leak the temp files. // We choose to delete the temp files if we were not modeless (same thread means we're now done with the files). // Otherwise, we'd rather leak the files than not work. // Known case: 109200. if ( hr && !fBlock ) { //ASSERT(FALSE && "Temp files leaked while printing!"); pFinalizer->SetFileList(NULL); } pWin3->Release(); } SysFreeString(bstrOnunload); } pWinOut->Release(); } Cleanup: DecrementPreviewCnt(); VariantClear(&varDLGOut); if (bstrDlgOptions) SysFreeString(bstrDlgOptions); if (pvarargOut) VariantClear(pvarargOut); for(i=0; iQueryInterface(IID_IHTMLEventObj, (void**)&pEventObj); if (hr) goto Cleanup; // // Get expando parameters from event object // hr = GetParamsFromEvent(pEventObj, cExpandos, aDispid, aVariant, s_aPrintTemplateExpandos); // get the resource URL hr = MLBuildResURLWrap(TEXT("shdoclc.dll"), HINST_THISDLL, ML_CROSSCODEPAGE, TEXT("pstemplate.dlg"), szResURL, ARRAYSIZE(szResURL), TEXT("shdocvw.dll")); if (hr) goto Cleanup; // create the moniker hr = CreateURLMoniker(NULL, szResURL, &pMon); if (hr) goto Cleanup; // raise the template hr = ShowHTMLDialogEx((HWND)(void*)V_UNKNOWN(&aVariant[eParentHWND]), pMon, HTMLDLG_MODAL | HTMLDLG_NOUI | HTMLDLG_PRINT_TEMPLATE, pvarargIn, NULL, NULL); Cleanup: for(i=0; i