/* * f r n t b o d y . c p p * * Purpose: * Implementation of CFrontBody object. Derives from CBody to host the trident * control. * * History * April '97: erican - created * * Copyright (C) Microsoft Corp. 1995, 1996, 1997. */ #include #include #include #include "strconst.h" #include "xpcomm.h" #include "browser.h" #include "frntbody.h" #include #include #include #include #include #include #include #include #include "url.h" #include "bodyutil.h" #include "mimeutil.h" #include "instance.h" #include "storutil.h" #include "demand.h" #include "menures.h" #include "multiusr.h" #include "htmlhelp.h" #include "shared.h" #include "oetag.h" #include "subscr.h" #define IsBrowserMode() ( g_dwBrowserFlags & 0x07 ) CFrontBody::CFrontBody(FOLDERTYPE ftType, IAthenaBrowser *pBrowser) : CMimeEditDocHost( /*MEBF_NOSCROLL*/ 0) //$27661: turn off noscroll { if (pBrowser) { m_pBrowser = pBrowser; m_pBrowser->AddRef(); } m_phlbc = NULL; m_hwndOwner = NULL; m_pTag = 0; m_fOEFrontPage = TRUE; } CFrontBody::~CFrontBody() { if (m_pTag) { m_pTag->OnFrontPageClose(); m_pTag->Release(); m_pTag = NULL; } SafeRelease(m_pBrowser); SafeRelease(m_phlbc); } //////////////////////////////////////////////////////////////////////// // // IUnknown // //////////////////////////////////////////////////////////////////////// HRESULT CFrontBody::QueryInterface(REFIID riid, LPVOID FAR *lplpObj) { if (!lplpObj) return E_INVALIDARG; *lplpObj = NULL; if (IsEqualIID(riid, IID_IHlinkFrame)) { *lplpObj = (IHlinkFrame *)this; AddRef(); return NOERROR; } if (IsEqualIID(riid, IID_IServiceProvider)) { *lplpObj = (IServiceProvider *)this; AddRef(); return NOERROR; } if (IsEqualIID(riid, IID_IElementBehaviorFactory)) { *lplpObj = (IElementBehaviorFactory *)this; AddRef(); return NOERROR; } return CMimeEditDocHost::QueryInterface(riid, lplpObj); } ULONG CFrontBody::AddRef() { return CMimeEditDocHost::AddRef(); } ULONG CFrontBody::Release() { return CMimeEditDocHost::Release(); } //////////////////////////////////////////////////////////////////////// // // IHlinkFrame // //////////////////////////////////////////////////////////////////////// HRESULT CFrontBody::SetBrowseContext(LPHLINKBROWSECONTEXT phlbc) { ReplaceInterface(m_phlbc, phlbc); return NOERROR; } HRESULT CFrontBody::GetBrowseContext(LPHLINKBROWSECONTEXT *pphlbc) { if (pphlbc == NULL) return E_INVALIDARG; *pphlbc = m_phlbc; if (m_phlbc) m_phlbc->AddRef(); return NOERROR; } static const struct { LPCWSTR pwszCmd; UINT uCmd; } s_rgCmdLookup[] = { { L"readMail", ID_GO_INBOX }, { L"newMessage", ID_NEW_MSG_DEFAULT }, { L"readNews", ID_GO_NEWS }, { L"subscribeNews", ID_NEWSGROUPS }, { L"addrBook", ID_ADDRESS_BOOK }, { L"findAddr", ID_FIND_PEOPLE }, { L"newNewsAccount", ID_CREATE_NEWS_ACCOUNT }, { L"newMailAccount", ID_CREATE_MAIL_ACCOUNT }, { L"help", ID_HELP_CONTENTS}, { L"newNewsMessage", ID_NEW_NEWS_MESSAGE}, { L"newUser", ID_NEW_IDENTITY}, { L"switchUser", ID_SWITCH_IDENTITY}, { L"noop", ID_NOOP}, { L"findMessage", ID_FIND_MESSAGE}, { L"logoff", ID_LOGOFF_IDENTITY}, { L"manageUser", ID_MANAGE_IDENTITIES}, }; HRESULT CFrontBody::Navigate(DWORD grfHLNF, LPBC pbc, LPBINDSTATUSCALLBACK pbsc, LPHLINK phlNavigate) { HRESULT hr; LPWSTR pwszURL = NULL, pwszCmd = NULL; HINSTANCE hInst; WCHAR wsz[CCHMAX_STRINGRES], wszErr[CCHMAX_STRINGRES+INTERNET_MAX_URL_LENGTH+1]; CStringParser sp; IF_FAILEXIT(hr = phlNavigate->GetStringReference(HLINKGETREF_ABSOLUTE, &pwszURL, NULL)); if (pwszURL) { if (!StrCmpNIW(pwszURL, L"oecmd:", 6)) { pwszCmd = pwszURL + 6; for (int i = 0; i < ARRAYSIZE(s_rgCmdLookup); i++) { if (!StrCmpNIW(pwszCmd, s_rgCmdLookup[i].pwszCmd, lstrlenW(s_rgCmdLookup[i].pwszCmd))) { switch (s_rgCmdLookup[i].uCmd) { case ID_HELP_CONTENTS: { LPSTR pszCmd = NULL; pwszCmd += ARRAYSIZE(s_rgCmdLookup[i].pwszCmd); IF_NULLEXIT(pszCmd = PszToANSI(CP_ACP, pwszCmd)); sp.Init(pszCmd, lstrlen(pszCmd), 0); sp.ChParse("("); sp.ChParse(")"); OEHtmlHelp(GetTopMostParent(m_hwnd), c_szCtxHelpFileHTML, HH_DISPLAY_TOPIC, (DWORD_PTR) (sp.CchValue() ? sp.PszValue() : NULL)); MemFree(pszCmd); break; } case ID_CREATE_MAIL_ACCOUNT: case ID_CREATE_NEWS_ACCOUNT: _CreateNewAccount(s_rgCmdLookup[i].uCmd == ID_CREATE_MAIL_ACCOUNT); // handle account creation internally break; default: PostMessage(m_hwndOwner, WM_COMMAND, s_rgCmdLookup[i].uCmd, 0L); } SetStatusText(NULL); hr = S_OK; goto exit; } } AssertSz(0, "Navigation request to unknown oecmd link"); hr = E_FAIL; } else { LPSTR pszURL = NULL; TCHAR sz[CCHMAX_STRINGRES], szErr[CCHMAX_STRINGRES+INTERNET_MAX_URL_LENGTH+1]; IF_NULLEXIT(pszURL = PszToANSI(CP_ACP, pwszURL)); hInst = ShellExecute(m_hwndOwner, NULL, pszURL, NULL, NULL, SW_SHOW); if (hInst <= (HINSTANCE)HINSTANCE_ERROR) { LoadString(g_hLocRes, idsErrURLExec, sz, ARRAYSIZE(sz)); wnsprintf(szErr, ARRAYSIZE(szErr), sz, pszURL); // load title into wsz. We don't use AthMsgBox as our string maybe too long. AthMsgBox // will truncate at CCHMAX_STRINGRES. LoadString(g_hLocRes, idsAthena, sz, ARRAYSIZE(sz)); MessageBox(m_hwndOwner, szErr, sz, MB_OK); } MemFree(pszURL); } } exit: if (pwszURL) CoTaskMemFree(pwszURL); return hr; } HRESULT CFrontBody::OnNavigate(DWORD grfHLNF, LPMONIKER pmkTarget, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName, DWORD dwreserved) { return E_NOTIMPL; } HRESULT CFrontBody::UpdateHlink(ULONG uHLID, LPMONIKER pmkTarget, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName) { return E_NOTIMPL; } //////////////////////////////////////////////////////////////////////// // // IServiceProvider // //////////////////////////////////////////////////////////////////////// HRESULT CFrontBody::QueryService(REFGUID guidService, REFIID riid, LPVOID *ppvObject) { if (IsEqualGUID(guidService, IID_IHlinkFrame)) return QueryInterface(riid, ppvObject); if (IsEqualGUID(guidService, IID_IHlinkFrame)) return QueryInterface(riid, ppvObject); if (IsEqualGUID(guidService, SID_SElementBehaviorFactory)) return QueryInterface(riid, ppvObject); return E_NOINTERFACE; } //////////////////////////////////////////////////////////////////////// // // CDocHost // //////////////////////////////////////////////////////////////////////// void CFrontBody::OnDocumentReady() { URLSUB rgUrlSub[] = { { "msnlink", idsHelpMSWebHome } }; // turn on link-tabbing for the front-page if (m_pCmdTarget) { VARIANTARG va; va.vt = VT_BOOL; va.boolVal = VARIANT_TRUE; m_pCmdTarget->Exec(&CMDSETID_MimeEdit, MECMDID_TABLINKS, 0, &va, NULL); } // #42164 // we defer-show the OE-front page via script. If an IEAK person overrides this // with a custom front-page, then we show as soon as we go document ready if (!m_fOEFrontPage) HrShow(TRUE); else { // if is is the std. OE page, then replace URL's SubstituteURLs(m_pDoc, rgUrlSub, ARRAYSIZE(rgUrlSub)); } } //////////////////////////////////////////////////////////////////////// // // PUBLIC // //////////////////////////////////////////////////////////////////////// HRESULT CFrontBody::HrInit(HWND hwnd) { m_hwndOwner = hwnd; return CMimeEditDocHost::HrInit(hwnd, IBOF_TABLINKS, NULL); } HRESULT CFrontBody::HrLoadPage() { HRESULT hr = S_OK; // bobn: brianv says we have to take this out... /*if (IsBrowserMode()) { hr = HrLoadURL("res://msoeres.dll/example.eml"); m_fOEFrontPage = FALSE; g_dwBrowserFlags = 0; } else*/ { DWORD cbData; TCHAR szURL[INTERNET_MAX_URL_LENGTH + 1]; TCHAR *pszUrl; LPSTR pszUrlFree=NULL; *szURL = 0; cbData = sizeof(szURL); AthUserGetValue(NULL, c_szFrontPagePath, NULL, (LPBYTE)szURL, &cbData); if (*szURL) { pszUrl = szURL; m_fOEFrontPage = FALSE; } else { pszUrlFree = PszAllocResUrl(g_dwAthenaMode & MODE_NEWSONLY ? "frntnews.htm" : "frntpage.htm"); pszUrl = pszUrlFree; } hr = HrLoadURL(pszUrl); SafeMemFree(pszUrlFree); } return hr; } HRESULT CFrontBody::SetStatusText(LPCOLESTR pszW) { WCHAR wszRes[CCHMAX_STRINGRES]; LPWSTR pszStatusW=0; HRESULT hr; if (pszW && !StrCmpNIW(pszW, L"oecmd:", 6)) { for (int i = 0; i < ARRAYSIZE(s_rgCmdLookup); i++) { if (!StrCmpNIW(pszW+6, s_rgCmdLookup[i].pwszCmd, lstrlenW(s_rgCmdLookup[i].pwszCmd))) { *wszRes = 0; LoadStringWrapW(g_hLocRes, MH(s_rgCmdLookup[i].uCmd), wszRes, ARRAYSIZE(wszRes)); // If this fails, worse that happens is that the status text is nulled. pszStatusW = PszDupW(wszRes); pszW = pszStatusW; break; } } } hr = CMimeEditDocHost::SetStatusText(pszW); MemFree(pszStatusW); return hr; } HRESULT CFrontBody::_CreateNewAccount(BOOL fMail) { IImnAccount *pAcct=0, *pAcctDef; FOLDERID id; DWORD dwServer=0; CHAR rgch[CCHMAX_ACCOUNT_NAME]; HRESULT hr; DWORD dwPropGet, dwPropSet; // create a new account object hr = g_pAcctMan->CreateAccountObject(fMail ? ACCT_MAIL : ACCT_NEWS, &pAcct); if (FAILED(hr)) { TraceResult(hr); goto exit; } // If creating a new news account, try and use default-mail information. If creating a new mail account, try // and use default-news information (if any). We don't use def-mail for mail accounts as the front-page only shows // links for account-creation if there are 0 accounts of that type. if (g_pAcctMan->GetDefaultAccount(fMail ? ACCT_NEWS : ACCT_MAIL, &pAcctDef)==S_OK) { dwPropGet = fMail ? AP_NNTP_DISPLAY_NAME : AP_SMTP_DISPLAY_NAME; dwPropSet = fMail ? AP_SMTP_DISPLAY_NAME : AP_NNTP_DISPLAY_NAME; if (pAcctDef->GetPropSz(dwPropGet, rgch, ARRAYSIZE(rgch))==S_OK) pAcct->SetPropSz(dwPropSet, rgch); dwPropGet = fMail ? AP_NNTP_EMAIL_ADDRESS : AP_SMTP_EMAIL_ADDRESS; dwPropSet = fMail ? AP_SMTP_EMAIL_ADDRESS : AP_NNTP_EMAIL_ADDRESS; if (pAcctDef->GetPropSz(dwPropGet, rgch, ARRAYSIZE(rgch))==S_OK) pAcct->SetPropSz(dwPropSet, rgch); pAcctDef->Release(); } // show the account wizard dialog and allow the user to setup properties hr = pAcct->DoWizard(m_hwndOwner, ACCT_WIZ_MIGRATE | ACCT_WIZ_INTERNETCONNECTION | ACCT_WIZ_HTTPMAIL | ACCT_WIZ_OE); if (FAILED(hr)) { TraceResult(hr); goto exit; } // find out what servers were added hr = pAcct->GetServerTypes(&dwServer); if (FAILED(hr)) { TraceResult(hr); goto exit; } // if we added a new news or IMAP account, ask the user if they want to see the subscription dialog if ( ((dwServer & SRV_IMAP) || (dwServer & SRV_NNTP)) && IDYES == AthMessageBoxW(m_hwndOwner, MAKEINTRESOURCEW(idsAthena), dwServer & SRV_NNTP ? MAKEINTRESOURCEW(idsDisplayNewsSubDlg) : MAKEINTRESOURCEW(idsDisplayImapSubDlg), 0, MB_ICONEXCLAMATION | MB_YESNO)) { // get the account-id hr = pAcct->GetPropSz(AP_ACCOUNT_ID, rgch, ARRAYSIZE(rgch)); if (FAILED(hr)) { TraceResult(hr); goto exit; } // find the associated node in the store hr = g_pStore->FindServerId(rgch, &id); if (FAILED(hr)) { TraceResult(hr); goto exit; } //The user wants to download the list of newsgroups, so if we are offline, go online if (g_pConMan) g_pConMan->SetGlobalOffline(FALSE); // finally, show the subscription dialog DoSubscriptionDialog(m_hwndOwner, dwServer & SRV_NNTP, id); } exit: ReleaseObj(pAcct); return hr; } HRESULT CFrontBody::HrClose() { if (m_pTag) { m_pTag->OnFrontPageClose(); m_pTag->Release(); m_pTag = NULL; } SafeRelease(m_pBrowser); return CMimeEditDocHost::HrClose(); } HRESULT CFrontBody::FindBehavior(LPOLESTR pchBehavior, LPOLESTR pchBehaviorUrl, IElementBehaviorSite* pSite, IElementBehavior** ppBehavior) { HRESULT hr; if ((StrCmpIW(pchBehavior, L"APPLICATION")==0 && StrCmpIW(pchBehaviorUrl, L"#DEFAULT#APPLICATION")==0)) { if (!m_pTag) { m_pTag = new COETag(m_pBrowser, this); if (!m_pTag) return E_OUTOFMEMORY; } return m_pTag->QueryInterface(IID_IElementBehavior, (LPVOID *)ppBehavior); } return E_FAIL; } HRESULT CFrontBody::GetHostInfo( DOCHOSTUIINFO* pInfo ) { pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT; pInfo->dwFlags = DOCHOSTUIFLAG_DIV_BLOCKDEFAULT|DOCHOSTUIFLAG_OPENNEWWIN| DOCHOSTUIFLAG_NO3DBORDER|DOCHOSTUIFLAG_CODEPAGELINKEDFONTS; //This sets the flags that match the browser's encoding fGetBrowserUrlEncoding(&pInfo->dwFlags); // bobn: brianv says we have to take this out... /*if (IsBrowserMode()) pInfo->dwFlags |= DOCHOSTUIFLAG_SCROLL_NO;*/ pInfo->pchHostCss = PszDupW(L"OE\\:APPLICATION { behavior:url(#DEFAULT#APPLICATION) }"); pInfo->pchHostNS = PszDupW(L"OE"); return S_OK; }