#include "pch.hxx" #include "note.h" #include "header.h" #include "envcid.h" #include "envguid.h" #include "bodyutil.h" #include "sigs.h" #include "mehost.h" #include "conman.h" #include "menuutil.h" #include "url.h" #include "fonts.h" #include "multlang.h" #include "statnery.h" #include "spell.h" #include "oleutil.h" #include "htmlhelp.h" #include "shared.h" #include "acctutil.h" #include "menures.h" #include "instance.h" #include "inetcfg.h" #include "ipab.h" #include "msgprop.h" #include "finder.h" #include "tbbands.h" #include "demand.h" #include "multiusr.h" #include #include "instance.h" #include "mapiutil.h" #include "regutil.h" #include "storecb.h" #include "receipts.h" #include "mirror.h" #include "secutil.h" #include "seclabel.h" #include "shlwapip.h" #include "mshtmcid.h" #define cxRect(rc) (rc.right - rc.left) #define cyRect(rc) (rc.bottom - rc.top) #define cyMinEdit 30 enum { MORFS_UNKNOWN = 0, MORFS_CLEARING, MORFS_SETTING, }; // Static Variables static const TCHAR c_szEditWebPage[] = "EditWebPages"; static DWORD g_dwTlsActiveNote = 0xffffffff; static HIMAGELIST g_himlToolbar = 0; static RECT g_rcLastResize = {50,30,450,450}; // default size static HACCEL g_hAccelRead = 0, g_hAccelSend = 0; //Static Functions void SetTlsGlobalActiveNote(CNote* pNote) { SideAssert(0 != TlsSetValue(g_dwTlsActiveNote, pNote)); } CNote* GetTlsGlobalActiveNote(void) { return (CNote*)TlsGetValue(g_dwTlsActiveNote); } void InitTlsActiveNote() { // Allocate a global TLS active note index g_dwTlsActiveNote = TlsAlloc(); Assert(g_dwTlsActiveNote != 0xffffffff); SideAssert(0 != TlsSetValue(g_dwTlsActiveNote, NULL)); } void DeInitTlsActiveNote() { // Free the tls index TlsFree(g_dwTlsActiveNote); g_dwTlsActiveNote = 0xffffffff; } // ************************* HRESULT CreateOENote(IUnknown *pUnkOuter, IUnknown **ppUnknown) { TraceCall("CreateOENote"); Assert(ppUnknown); *ppUnknown = NULL; // Create me CNote *pNew = new CNote(); if (NULL == pNew) return TraceResult(E_OUTOFMEMORY); // Cast to unknown *ppUnknown = SAFECAST(pNew, IOENote *); // Done return S_OK; } // ************************* BOOL Note_Init(BOOL fInit) { static BOOL fInited=FALSE; WNDCLASSW wc; DOUTL(4, "Note_Init: %d", (int)fInit); if(fInit) { if(fInited) { DOUTL(4, "Note_Init: already inited"); return TRUE; } wc.style = CS_BYTEALIGNWINDOW; wc.lpfnWndProc = CNote::ExtNoteWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = g_hInst; wc.hIcon = LoadIcon(g_hLocRes, MAKEINTRESOURCE(idiMessageAtt)); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); wc.lpszMenuName = NULL; wc.lpszClassName = c_wszNoteWndClass; if(!RegisterClassWrapW(&wc)) return FALSE; if(!FHeader_Init(TRUE)) return FALSE; fInited=TRUE; DOUTL(4, "Note_Init: success"); return TRUE; } else { // save back to registry UnregisterClassWrapW(c_wszNoteWndClass, g_hInst); if(g_himlToolbar) { ImageList_Destroy(g_himlToolbar); g_himlToolbar=0; } FHeader_Init(FALSE); fInited=FALSE; DOUTL(4, "Note_Init: deinit OK"); return TRUE; } } HRESULT _HrBlockSender(RULE_TYPE typeRule, IMimeMessage * pMsg, HWND hwnd) { HRESULT hr = S_OK; ADDRESSPROPS rSender = {0}; CHAR szRes[CCHMAX_STRINGRES]; LPSTR pszResult = NULL; // Check incoming params if ((NULL == pMsg) || (NULL == hwnd)) { hr = E_INVALIDARG; goto exit; } // Get the address to add rSender.dwProps = IAP_EMAIL; hr = pMsg->GetSender(&rSender); if (FAILED(hr)) { goto exit; } Assert(ISFLAGSET(rSender.dwProps, IAP_EMAIL)); if ((NULL == rSender.pszEmail) || ('\0' == rSender.pszEmail[0])) { goto exit; } // Add the sender to the list hr = RuleUtil_HrAddBlockSender(typeRule, rSender.pszEmail); if (FAILED(hr)) { goto exit; } // Load the template string AthLoadString(idsSenderAdded, szRes, sizeof(szRes)); // Allocate the space to hold the final string DWORD cchSize = (lstrlen(szRes) + lstrlen(rSender.pszEmail) + 1); hr = HrAlloc((VOID **) &pszResult, sizeof(*pszResult) * cchSize); if (FAILED(hr)) { goto exit; } // Build up the warning string wnsprintf(pszResult, cchSize, szRes, rSender.pszEmail); // Show the success dialog AthMessageBox(hwnd, MAKEINTRESOURCE(idsAthena), pszResult, NULL, MB_OK | MB_ICONINFORMATION); // Set the return value hr = S_OK; exit: SafeMemFree(pszResult); g_pMoleAlloc->FreeAddressProps(&rSender); if (FAILED(hr)) { AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsSenderError), NULL, MB_OK | MB_ICONERROR); } return hr; } // ************************* LRESULT CALLBACK CNote::ExtNoteWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { CNote *pNote=0; if(msg==WM_CREATE) { pNote=(CNote*)((LPCREATESTRUCT)lParam)->lpCreateParams; if(pNote && pNote->WMCreate(hwnd)) return 0; else return -1; } pNote = (CNote*)GetWndThisPtr(hwnd); if(pNote) { return pNote->WndProc(hwnd, msg, wParam, lParam); } else return DefWindowProcWrapW(hwnd, msg, wParam, lParam); } // ************************* CNote::CNote() { // Initialized in Init: // m_rHtmlOpt // m_rPlainOpt // Set before used: // m_pTabStopArray CoIncrementInit("CNote", MSOEAPI_START_SHOWERRORS, NULL, NULL); m_punkPump = NULL; m_pHdr = NULL; m_pMsg = NULL; m_pCancel = NULL; m_pstatus = NULL; m_pMsgSite = NULL; m_pPrstMime = NULL; m_pBodyObj2 = NULL; m_pCmdTargetHdr = NULL; m_pCmdTargetBody = NULL; m_pDropTargetHdr = NULL; m_pTridentDropTarget = NULL; m_pToolbarObj = NULL; m_hwnd = 0; m_hMenu = 0; m_hIcon = 0; m_hbmBack = 0; m_hCursor = 0; m_hCharset = 0; m_hTimeout = 0; m_hwndRebar = 0; m_hwndFocus = 0; m_hwndOwner = 0; m_hmenuLater = 0; m_hwndToolbar = 0; m_hmenuAccounts = 0; m_hmenuLanguage = 0; m_dwNoteAction = 0; m_dwIdentCookie = 0; m_dwNoteCreateFlags = 0; m_dwMarkOnReplyForwardState = MORFS_UNKNOWN; m_dwCBMarkType = MARK_MAX; m_OrigOperationType = SOT_INVALID; m_fHtml = TRUE; m_fMail = TRUE; m_fCBCopy = FALSE; m_fReadNote = FALSE; m_fProgress = FALSE; m_fCommitSave = TRUE; m_fTabStopsSet = FALSE; m_fCompleteMsg = FALSE; m_fHasBeenSaved = FALSE; m_fPackageImages = TRUE; m_fWindowDisabled = FALSE; m_fHeaderUIActive = FALSE; m_fOrgCmdWasDelete = FALSE; m_fUseReplyHeaders = FALSE; m_fCBDestroyWindow = FALSE; m_fBypassDropTests = FALSE; m_fOnDocReadyHandled = FALSE; m_fOriginallyWasRead = FALSE; m_fUseStationeryFonts = FALSE; m_fBodyContainsFrames = FALSE; m_fPreventConflictDlg = FALSE; m_fInternal = FALSE; m_fForceClose = FALSE; m_pLabel = NULL; if(FPresentPolicyRegInfo() && IsSMIME3Supported()) { m_fSecurityLabel = !!DwGetOption(OPT_USE_LABELS); HrGetOELabel(&m_pLabel); } else m_fSecurityLabel = FALSE; if(IsSMIME3Supported()) { m_fSecReceiptRequest = !!DwGetOption(OPT_SECREC_USE); } else m_fSecReceiptRequest = FALSE; m_ulPct = 0; m_iIndexOfBody = -1; m_cRef = 1; m_cAcctMenu = 0; m_cAcctLater = 0; m_cTabStopCount = 0; m_fStatusbarVisible = !!DwGetOption(OPT_SHOW_NOTE_STATUSBAR); m_fFormatbarVisible = !!DwGetOption(OPT_SHOW_NOTE_FMTBAR); InitializeCriticalSection(&m_csNoteState); m_nisNoteState = NIS_INIT; if (!g_hAccelRead) g_hAccelRead = LoadAccelerators(g_hLocRes, MAKEINTRESOURCE(IDA_READ_NOTE_ACCEL)); if (!g_hAccelSend) g_hAccelSend = LoadAccelerators(g_hLocRes, MAKEINTRESOURCE(IDA_SEND_NOTE_ACCEL)); ZeroMemory(&m_hlDisabled, sizeof(HWNDLIST)); m_dwRequestMDNLocked = GetLockKeyValue(c_szRequestMDNLocked); } // ************************* CNote::~CNote() { if (0 != m_hmenuLanguage) { // unload global MIME language codepage data DeinitMultiLanguage(); DestroyMenu(m_hmenuLanguage); } if (m_hMenu != NULL) DestroyMenu(m_hMenu); if (m_hIcon) DestroyIcon(m_hIcon); if (m_hbmBack) DeleteObject(m_hbmBack); // sometimes we get a setfocus in our processing of DestroyWindow // this causes a WM_ACTIVATE to the note without a corresponding // WM_DEACTIVATE. if at the time the note dies, the global note ptr // has our this ptr in it, null it out to be safe. if (this == GetTlsGlobalActiveNote()) { Assert(!(m_dwNoteCreateFlags & OENCF_MODAL)); SetTlsGlobalActiveNote(NULL); } SafeMemFree(m_pLabel); ReleaseObj(m_pMsg); ReleaseObj(m_pHdr); ReleaseObj(m_pstatus); ReleaseObj(m_pCancel); ReleaseObj(m_pMsgSite); ReleaseObj(m_punkPump); ReleaseObj(m_pPrstMime); ReleaseObj(m_pBodyObj2); ReleaseObj(m_pCmdTargetHdr); ReleaseObj(m_pCmdTargetBody); ReleaseObj(m_pDropTargetHdr); ReleaseObj(m_pTridentDropTarget); SafeRelease(m_pToolbarObj); CallbackCloseTimeout(&m_hTimeout); DeleteCriticalSection(&m_csNoteState); CoDecrementInit("CNote", NULL); } // ************************* ULONG CNote::AddRef() { return ++m_cRef; } // ************************* ULONG CNote::Release() { if (--m_cRef == 0) { delete this; return 0; } return m_cRef; } // ************************* HRESULT CNote::QueryInterface(REFIID riid, LPVOID FAR *ppvObj) { HRESULT hr; if(!ppvObj) return E_INVALIDARG; if (IsEqualIID(riid, IID_IUnknown)) *ppvObj = ((IUnknown *)(IOENote *)this); else if(IsEqualIID(riid, IID_IOENote)) *ppvObj = (IOENote *)this; else if (IsEqualIID(riid, IID_IBodyOptions)) *ppvObj = (IBodyOptions *)this; else if(IsEqualIID(riid, IID_IDropTarget)) *ppvObj = (IDropTarget *)this; else if (IsEqualIID(riid, IID_IHeaderSite)) *ppvObj = (IHeaderSite *)this; else if(IsEqualIID(riid, IID_IPersistMime)) *ppvObj = (IPersistMime *)this; else if(IsEqualIID(riid, IID_IServiceProvider)) *ppvObj = (IServiceProvider *)this; else if (IsEqualIID(riid, IID_IDockingWindowSite)) *ppvObj = (IDockingWindowSite*)this; else if (IsEqualIID(riid, IID_IIdentityChangeNotify)) *ppvObj = (IIdentityChangeNotify*)this; else if (IsEqualIID(riid, IID_IOleCommandTarget)) *ppvObj = (IOleCommandTarget*)this; else if (IsEqualIID(riid, IID_IStoreCallback)) *ppvObj = (IStoreCallback *) this; else if (IsEqualIID(riid, IID_ITimeoutCallback)) *ppvObj = (ITimeoutCallback *) this; else { *ppvObj = NULL; hr = E_NOINTERFACE; goto exit; } ((IUnknown *)*ppvObj)->AddRef(); hr = NOERROR; exit: return hr; } // ************************* HRESULT CNote::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pCmdText) { HRESULT hr = OLECMDERR_E_UNKNOWNGROUP; if (!rgCmds) return E_INVALIDARG; if (!pguidCmdGroup) return hr; // We are closing down if (!m_pMsgSite) return E_UNEXPECTED; if (m_pCmdTargetHdr) m_pCmdTargetHdr->QueryStatus(pguidCmdGroup, cCmds, rgCmds, pCmdText); if (m_pCmdTargetBody) m_pCmdTargetBody->QueryStatus(pguidCmdGroup, cCmds, rgCmds, pCmdText); MenuUtil_NewMessageIDsQueryStatus(pguidCmdGroup, cCmds, rgCmds, pCmdText, m_fMail); if (IsEqualGUID(CMDSETID_OutlookExpress, *pguidCmdGroup)) { DWORD dwStatusFlags = 0; BOOL fCompleteMsg = !!m_fCompleteMsg; BOOL fHtmlSettingsOK = m_fHtml && !m_fBodyContainsFrames; m_pMsgSite->GetStatusFlags(&dwStatusFlags); for (ULONG ul = 0; ul < cCmds; ul++) { ULONG cmdID = rgCmds[ul].cmdID; // There are certain cases that need to be overridden even if the earlier // components enabled or disabled them. They are in this switch statement. switch (cmdID) { // Until trident allows printing in edit mode, don't allow this. RAID 35635 case ID_PRINT: case ID_PRINT_NOW: rgCmds[ul].cmdf = QS_ENABLED(fCompleteMsg && m_fReadNote); continue; } if (0 != rgCmds[ul].cmdf) continue; switch (cmdID) { case ID_POPUP_LANGUAGE: rgCmds[ul].cmdf = QS_ENABLED(fCompleteMsg); break; case ID_NOTE_SAVE_AS: rgCmds[ul].cmdf = QS_ENABLED(fCompleteMsg || !m_fReadNote); break; case ID_WORK_OFFLINE: rgCmds[ul].cmdf = QS_CHECKED(g_pConMan->IsGlobalOffline()); break; case ID_CREATE_RULE_FROM_MESSAGE: case ID_BLOCK_SENDER: rgCmds[ul].cmdf = QS_ENABLED(m_fReadNote && !m_fBodyContainsFrames && (0 == (OEMSF_RULESNOTENABLED & dwStatusFlags))); break; case ID_REPLY: case ID_REPLY_ALL: rgCmds[ul].cmdf = QS_ENABLED(m_fReadNote && !m_fBodyContainsFrames && fCompleteMsg); break; case ID_REPLY_GROUP: rgCmds[ul].cmdf = QS_ENABLED(m_fReadNote && !m_fBodyContainsFrames && !m_fMail && fCompleteMsg); break; case ID_FORWARD: case ID_FORWARD_AS_ATTACH: rgCmds[ul].cmdf = QS_ENABLED(m_fReadNote && fCompleteMsg); break; case ID_UNSCRAMBLE: rgCmds[ul].cmdf = QS_ENABLED(!m_fMail && m_fReadNote); break; case ID_POPUP_FORMAT: case ID_INSERT_SIGNATURE: rgCmds[ul].cmdf = QS_ENABLED(!m_fBodyContainsFrames); break; case ID_NOTE_COPY_TO_FOLDER: rgCmds[ul].cmdf = QS_ENABLED(fCompleteMsg && (OEMSF_CAN_COPY & dwStatusFlags)); break; // Can move message if is readnote, or compose note where the message was store based. case ID_NOTE_MOVE_TO_FOLDER: rgCmds[ul].cmdf = QS_ENABLED(fCompleteMsg && (OEMSF_CAN_MOVE & dwStatusFlags) && (m_fReadNote || (OENA_COMPOSE == m_dwNoteAction))); break; case ID_NOTE_DELETE: // We should be able to delete anything that msgsite says we can delete // so long as we are a read note, or we are a drafts message. rgCmds[ul].cmdf = QS_ENABLED((OEMSF_CAN_DELETE & dwStatusFlags) && (m_fReadNote || (OENA_COMPOSE == m_dwNoteAction))); break; case ID_REDO: rgCmds[ul].cmdf = QS_ENABLED(m_fHeaderUIActive); break; case ID_SAVE: rgCmds[ul].cmdf = QS_ENABLED(fCompleteMsg && (OEMSF_CAN_SAVE & dwStatusFlags) && (m_fOnDocReadyHandled || !m_fReadNote)); break; case ID_NEXT_UNREAD_MESSAGE: case ID_NEXT_MESSAGE: rgCmds[ul].cmdf = QS_ENABLED(OEMSF_CAN_NEXT & dwStatusFlags); break; case ID_POPUP_NEXT: rgCmds[ul].cmdf = QS_ENABLED((OEMSF_CAN_PREV & dwStatusFlags) || (OEMSF_CAN_NEXT & dwStatusFlags)); break; case ID_MARK_THREAD_READ: rgCmds[ul].cmdf = QS_ENABLED(OEMSF_THREADING_ENABLED & dwStatusFlags); break; case ID_NEXT_UNREAD_THREAD: rgCmds[ul].cmdf = QS_ENABLED((OEMSF_THREADING_ENABLED & dwStatusFlags) && (OEMSF_CAN_NEXT & dwStatusFlags)); break; case ID_PREVIOUS: rgCmds[ul].cmdf = QS_ENABLED(OEMSF_CAN_PREV & dwStatusFlags); break; case ID_FORMAT_COLOR: case ID_FORMAT_COLOR1: case ID_FORMAT_COLOR2: case ID_FORMAT_COLOR3: case ID_FORMAT_COLOR4: case ID_FORMAT_COLOR5: case ID_FORMAT_COLOR6: case ID_FORMAT_COLOR7: case ID_FORMAT_COLOR8: case ID_FORMAT_COLOR9: case ID_FORMAT_COLOR10: case ID_FORMAT_COLOR11: case ID_FORMAT_COLOR12: case ID_FORMAT_COLOR13: case ID_FORMAT_COLOR14: case ID_FORMAT_COLOR15: case ID_FORMAT_COLOR16: case ID_BACK_COLOR_AUTO: case ID_FORMAT_COLORAUTO: case ID_POPUP_BACKGROUND: rgCmds[ul].cmdf = QS_ENABLED(fHtmlSettingsOK); break; case ID_FORMATTING_TOOLBAR: rgCmds[ul].cmdf = QS_ENABLECHECK((m_fHtml && !m_fBodyContainsFrames), m_fFormatbarVisible); break; case ID_SHOW_TOOLBAR: rgCmds[ul].cmdf = QS_CHECKED(m_fToolbarVisible); break; case ID_STATUS_BAR: rgCmds[ul].cmdf = QS_CHECKED(m_fStatusbarVisible); break; case ID_SEND_OBJECTS: rgCmds[ul].cmdf = QS_ENABLECHECK(fHtmlSettingsOK, m_fPackageImages); break; case ID_RICH_TEXT: rgCmds[ul].cmdf = QS_RADIOED(m_fHtml); break; case ID_PLAIN_TEXT: rgCmds[ul].cmdf = QS_RADIOED(!m_fHtml); break; case ID_FLAG_MESSAGE: rgCmds[ul].cmdf = QS_ENABLECHECK(OEMSF_CAN_MARK & dwStatusFlags, IsFlagged()); break; case ID_WATCH_THREAD: rgCmds[ul].cmdf = QS_CHECKED(IsFlagged(ARF_WATCH)); break; case ID_IGNORE_THREAD: rgCmds[ul].cmdf = QS_CHECKED(IsFlagged(ARF_IGNORE)); break; case ID_POPUP_NEW: case ID_NOTE_PROPERTIES: case ID_CLOSE: case ID_POPUP_FIND: case ID_POPUP_LANGUAGE_DEFERRED: case ID_POPUP_FONTS: case ID_ADDRESS_BOOK: case ID_POPUP_ADDRESS_BOOK: case ID_ADD_SENDER: case ID_ADD_ALL_TO: case ID_POPUP_TOOLBAR: case ID_CUSTOMIZE: // Help Menus case ID_HELP_CONTENTS: case ID_README: case ID_POPUP_MSWEB: case ID_MSWEB_FREE_STUFF: case ID_MSWEB_PRODUCT_NEWS: case ID_MSWEB_FAQ: case ID_MSWEB_SUPPORT: case ID_MSWEB_FEEDBACK: case ID_MSWEB_BEST: case ID_MSWEB_SEARCH: case ID_MSWEB_HOME: case ID_MSWEB_HOTMAIL: case ID_ABOUT: case ID_FIND_MESSAGE: case ID_FIND_PEOPLE: case ID_FIND_TEXT: case ID_SELECT_ALL: case ID_POPUP_LANGUAGE_MORE: case ID_SEND_NOW: case ID_SEND_LATER: case ID_SEND_MESSAGE: case ID_SEND_DEFAULT: rgCmds[ul].cmdf = QS_ENABLED(TRUE); break; case ID_REQUEST_READRCPT: if (m_fMail) { rgCmds[ul].cmdf = QS_CHECKFORLATCH(!m_dwRequestMDNLocked, !!(dwStatusFlags & OEMSF_MDN_REQUEST)); } else { rgCmds[ul].cmdf = QS_ENABLED(FALSE); } break; case ID_INCLUDE_LABEL: if(m_pHdr->IsHeadSigned() == S_OK) rgCmds[ul].cmdf = QS_CHECKED(m_fSecurityLabel); else rgCmds[ul].cmdf = QS_ENABLED(FALSE); break; case ID_LABEL_SETTINGS: if(m_pHdr->IsHeadSigned() == S_OK) rgCmds[ul].cmdf = QS_ENABLED(m_fSecurityLabel); else rgCmds[ul].cmdf = QS_ENABLED(FALSE); break; case ID_SEC_RECEIPT_REQUEST: if(m_pHdr->IsHeadSigned() == S_OK) rgCmds[ul].cmdf = QS_CHECKED(m_fSecReceiptRequest); else rgCmds[ul].cmdf = QS_ENABLED(FALSE); default: if ((ID_LANG_FIRST <= cmdID) && (ID_LANG_LAST >= cmdID)) { rgCmds[ul].cmdf = OLECMDF_SUPPORTED | SetMimeLanguageCheckMark(CustomGetCPFromCharset(m_hCharset, m_fReadNote), cmdID - ID_LANG_FIRST); } if (((ID_ADD_RECIPIENT_FIRST <= cmdID) && (ID_ADD_RECIPIENT_LAST >= cmdID)) || ((ID_APPLY_STATIONERY_0 <= cmdID) && (ID_APPLY_STATIONERY_NONE >= cmdID))) rgCmds[ul].cmdf = QS_ENABLED(TRUE); else if ((ID_SIGNATURE_FIRST <= cmdID) && (ID_SIGNATURE_LAST >= cmdID)) rgCmds[ul].cmdf = QS_ENABLED(!m_fBodyContainsFrames); break; } } hr = S_OK; } return hr; } // ************************* HRESULT CNote::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut) { return E_NOTIMPL; } // ************************* HRESULT CNote::ClearDirtyFlag() { m_pBodyObj2->HrSetDirtyFlag(FALSE); HeaderExecCommand(MSOEENVCMDID_DIRTY, MSOCMDEXECOPT_DODEFAULT, NULL); return S_OK; } // ************************* HRESULT CNote::IsDirty(void) { OLECMD rgCmd[] = {{MSOEENVCMDID_DIRTY, 0}}; BOOL fBodyDirty = FALSE; m_pBodyObj2->HrIsDirty(&fBodyDirty); if (fBodyDirty) return S_OK; if (m_pCmdTargetHdr) m_pCmdTargetHdr->QueryStatus(&CGID_Envelope, 1, rgCmd, NULL); return (0 != (rgCmd[0].cmdf&OLECMDF_ENABLED)) ? S_OK : S_FALSE; } // ************************* HRESULT CNote::Load(LPMIMEMESSAGE pMsg) { HRESULT hr; VARIANTARG var; IPersistMime *pPMHdr=0; BOOL fWarnUser = (OENA_WEBPAGE == m_dwNoteAction ) || (OENA_COMPOSE == m_dwNoteAction ) || (OENA_STATIONERY == m_dwNoteAction ) || (OENA_FORWARD == m_dwNoteAction); if (!m_pHdr) return E_FAIL; // OnDocumentReady will get call on the CheckForFramesets function. // Don't want that document ready to matter. Set this flag to true so // the doc ready doesn't do anything. Once the check is done, we will // set this flag to false again. m_fOnDocReadyHandled = TRUE; // If not a read note and contains frames, need to see what user wants to do if (!m_fReadNote) { hr = HrCheckForFramesets(pMsg, fWarnUser); if (FAILED(hr)) goto Exit; if (hr == S_READONLY) m_fBodyContainsFrames = TRUE; } ReplaceInterface(m_pMsg, pMsg); // The next OnDocumentReady should be run. m_fOnDocReadyHandled = FALSE; hr = m_pHdr->QueryInterface(IID_IPersistMime, (LPVOID*)&pPMHdr); if (FAILED(hr)) return hr; hr = pPMHdr->Load(pMsg); if (FAILED(hr)) goto Exit; m_pHdr->SetFlagState(IsFlagged(ARF_FLAGGED) ? MARK_MESSAGE_FLAGGED : MARK_MESSAGE_UNFLAGGED); if (IsFlagged(ARF_WATCH)) m_pHdr->SetFlagState(MARK_MESSAGE_WATCH); else if (IsFlagged(ARF_IGNORE)) m_pHdr->SetFlagState(MARK_MESSAGE_IGNORE); else m_pHdr->SetFlagState(MARK_MESSAGE_NORMALTHREAD); if (m_fCompleteMsg) hr = m_pPrstMime->Load(pMsg); CheckAndForceEncryption(); Exit: if (FAILED(hr)) // ~~~ This should eventually be an html error message m_pBodyObj2->HrUnloadAll(idsErrHtmlBodyFailedToLoad, NULL); ReleaseObj(pPMHdr); return hr; } // ************************* void CNote::CheckAndForceEncryption() { BOOL fCheck = FALSE; if(m_fSecurityLabel && m_pLabel) { DWORD dwFlags; if (SUCCEEDED(HrGetPolicyFlags(m_pLabel->pszObjIdSecurityPolicy, &dwFlags))) { if(dwFlags & SMIME_POLICY_MODULE_FORCE_ENCRYPTION) fCheck = TRUE; } } m_pHdr->ForceEncryption(&fCheck, TRUE); } // ************************* HRESULT CNote::SetCharsetUnicodeIfNeeded(IMimeMessage *pMsg) { HRESULT hr = S_OK; VARIANTARG va; PROPVARIANT Variant; int ret; HCHARSET hCharSet; UINT cpID = 0; // Call dialog only if sending a mime message // See raid 8436 or 79339 in the IE/OE 5 database. We can't send // unicode encoding unless we are a mime message. if (m_fHtml || m_rPlainOpt.fMime) { m_fPreventConflictDlg = FALSE; if (SUCCEEDED(GetCharset(&hCharSet))) { cpID = CustomGetCPFromCharset(hCharSet, FALSE); } else { pMsg->GetCharset(&hCharSet); cpID = CustomGetCPFromCharset(hCharSet, FALSE); } // Check to see if have chars that don't work in encoding va.vt = VT_UI4; va.ulVal = cpID; IF_FAILEXIT(hr = m_pCmdTargetBody->Exec(&CMDSETID_MimeEdit, MECMDID_CANENCODETEXT, 0, &va, NULL)); if (MIME_S_CHARSET_CONFLICT == hr) { // Don't let header call conflict dialog again m_fPreventConflictDlg = TRUE; ret = IntlCharsetConflictDialogBox(); if (idcSendAsUnicode == ret) { // User choose to send as Unicode (UTF8). set new charset and resnd hCharSet = GetMimeCharsetFromCodePage(CP_UTF8); ChangeCharset(hCharSet); } else if (IDOK != ret) { // return to edit mode and bail out hr = MAPI_E_USER_CANCEL; goto exit; } } } else // Since we are not mime, don't show dialog ever. m_fPreventConflictDlg = TRUE; exit: return hr; } // ************************* HRESULT CNote::Save(LPMIMEMESSAGE pMsg, DWORD dwFlags) { HRESULT hr; IPersistMime* pPersistMimeHdr=0; DWORD dwHtmlFlags = PMS_TEXT; if(!m_pHdr) IF_FAILEXIT(hr = E_FAIL); IF_FAILEXIT(hr = SetCharsetUnicodeIfNeeded(pMsg)); IF_FAILEXIT(hr = m_pHdr->QueryInterface(IID_IPersistMime, (LPVOID*)&pPersistMimeHdr)); IF_FAILEXIT(hr = pPersistMimeHdr->Save(pMsg, TRUE)); if (m_fHtml) dwHtmlFlags |= PMS_HTML; IF_FAILEXIT(hr = m_pPrstMime->Save(pMsg, dwHtmlFlags)); UpdateMsgOptions(pMsg); // During a send, don't want to commit at this time. m_fCommitSave // is set to false during a send. if (m_fCommitSave) { hr = pMsg->Commit(0); // temporary hack for #27823 if((hr == MIME_E_SECURITY_NOSIGNINGCERT) || (hr == MIME_E_SECURITY_ENCRYPTNOSENDERCERT) || (hr == MIME_E_SECURITY_CERTERROR) || (hr == MIME_E_SECURITY_NOCERT) ) // too early for this error hr = S_OK; } exit: ReleaseObj(pPersistMimeHdr); return hr; } // ************************* HRESULT CNote::InitNew(void) { return E_NOTIMPL; } // ************************* HRESULT CNote::GetClassID(CLSID *pClsID) { return NOERROR; } // ************************* HRESULT CNote::SignatureEnabled(BOOL fAuto) { int cSig; HRESULT hr; DWORD dwSigFlag; if (m_fBodyContainsFrames || m_fReadNote || (OENA_WEBPAGE == m_dwNoteAction)) return S_FALSE; if (FAILED(g_pSigMgr->GetSignatureCount(&cSig)) || (0 == cSig)) return S_FALSE; if (!fAuto) // for non-auto scenario's it's cool to insert a sig, as there is one. return S_OK; // From this point down, we are only talking about insertion upon creation if (OENCF_NOSIGNATURE & m_dwNoteCreateFlags) return S_FALSE; dwSigFlag = DwGetOption(OPT_SIGNATURE_FLAGS); // if its a sendnote: check autonew. for automatically appending the signature. We only append on a virgin sendnote or a stationery sendnote. // as if it's been saved to the store, the signature is already there. // if in a reply or forward, then check for auto-reply. switch (m_dwNoteAction) { // If it is a compose note, make sure it wasn't from the store or file system, that it doesn't have any // body parts, and that the sig flag is set case OENA_COMPOSE: { Assert(m_pMsgSite); if (m_pMsgSite) hr = (!m_fOriginallyWasRead && (S_FALSE == HrHasBodyParts(m_pMsg)) && (dwSigFlag & SIGFLAG_AUTONEW)) ? S_OK : S_FALSE; else hr = S_FALSE; break; } // For stationery, check sig flag case OENA_STATIONERY: { hr = (dwSigFlag & SIGFLAG_AUTONEW) ? S_OK : S_FALSE; break; } // Check sig flag case OENA_REPLYTOAUTHOR: case OENA_REPLYTONEWSGROUP: case OENA_REPLYALL: case OENA_FORWARD: case OENA_FORWARDBYATTACH: { hr = (dwSigFlag & SIGFLAG_AUTOREPLY) ? S_OK : S_FALSE; break; } default: AssertSz(FALSE, "Bad note action type for signature"); hr = S_FALSE; } return hr; } // ************************* HRESULT CNote::GetSignature(LPCSTR szSigID, LPDWORD pdwSigOptions, BSTR *pbstr) { HRESULT hr; IImnAccount *pAcct = NULL; GETSIGINFO si; if (m_fBodyContainsFrames) return E_NOTIMPL; hr = m_pHdr->HrGetAccountInHeader(&pAcct); if (FAILED(hr)) return hr; si.szSigID = szSigID; si.pAcct = pAcct; si.hwnd = m_hwnd; si.fHtmlOk = m_fHtml; si.fMail = m_fMail; si.uCodePage = GetACP(); hr = HrGetMailNewsSignature(&si, pdwSigOptions, pbstr); ReleaseObj(pAcct); return hr; } // ************************* HRESULT CNote::GetMarkAsReadTime(LPDWORD pdwSecs) { // Notes don't care about mark as read timers, only Views return E_NOTIMPL; } // ************************* HRESULT CNote::GetFlags(LPDWORD pdwFlags) { DWORD dwMsgSiteFlags = 0; if (!pdwFlags) return E_INVALIDARG; *pdwFlags= BOPT_FROM_NOTE; Assert(m_pMsgSite); if (m_pMsgSite) m_pMsgSite->GetStatusFlags(&dwMsgSiteFlags); // if a readnote, we can auto-inline attachments if (m_fReadNote) *pdwFlags |= BOPT_AUTOINLINE; // set HTML flag if (m_fHtml) *pdwFlags |= BOPT_HTML; else *pdwFlags |= BOPT_NOFONTTAG; if (IsReplyNote()) { // If block quote option is ON, and is HTML messages if (m_fHtml && DwGetOption(m_fMail?OPT_MAIL_MSG_HTML_INDENT_REPLY:OPT_NEWS_MSG_HTML_INDENT_REPLY)) *pdwFlags |= BOPT_BLOCKQUOTE; // Set this in all cases except where we are a reply note and the INCLUDEMSG is not set if (DwGetOption(OPT_INCLUDEMSG)) *pdwFlags |= BOPT_INCLUDEMSG; } else *pdwFlags |= BOPT_INCLUDEMSG; // If is reply or forward... if (IsReplyNote() || (OENA_FORWARD == m_dwNoteAction) || (OENA_FORWARDBYATTACH == m_dwNoteAction) ) { *pdwFlags |= BOPT_REPLYORFORWARD; // ... and spell ignore is set if(DwGetOption(OPT_SPELLIGNOREPROTECT)) *pdwFlags |= BOPT_SPELLINGOREORIGINAL; } // If not a read note, or a compose note that started as a compose note (ie one that was previously saved) if (!m_fReadNote && !m_fOriginallyWasRead) *pdwFlags |= BOPT_AUTOTEXT; if (!m_fReadNote && m_fPackageImages) *pdwFlags |= BOPT_SENDIMAGES; // ugh. OK, this is big-time sleazy. We found a security hole in SP1. To // plug this we need to at reply and forward time // mark incoming images etc as NOSEND=1 links. We do this for all messages // EXCEPT stationery or webpages if ((OENA_STATIONERY == m_dwNoteAction) || (OENA_WEBPAGE == m_dwNoteAction)) *pdwFlags |= BOPT_SENDEXTERNALS; if (m_fUseStationeryFonts) *pdwFlags |= BOPT_NOFONTTAG; if (m_fReadNote && (dwMsgSiteFlags & OEMSF_SEC_UI_ENABLED)) *pdwFlags |= BOPT_SECURITYUIENABLED; if (dwMsgSiteFlags & OEMSF_FROM_STORE) *pdwFlags |= BOPT_FROMSTORE; if (dwMsgSiteFlags & OEMSF_UNREAD) *pdwFlags |= BOPT_UNREAD; if (!m_fBodyContainsFrames && m_fUseReplyHeaders) *pdwFlags |= BOPT_USEREPLYHEADER; if (m_fMail) *pdwFlags |= BOPT_MAIL; return S_OK; } // ************************* HRESULT CNote::GetInfo(BODYOPTINFO *pBOI) { HRESULT hr = S_OK; if (m_fBodyContainsFrames) return E_NOTIMPL; if (pBOI->dwMask & BOPTF_QUOTECHAR) { pBOI->chQuote = NULL; // we allow quote char in plain-text mode only if (!m_fHtml && (IsReplyNote() || (OENA_FORWARD == m_dwNoteAction))) pBOI->chQuote =(CHAR)DwGetOption(m_fMail?OPT_MAILINDENT:OPT_NEWSINDENT); } if (pBOI->dwMask & BOPTF_REPLYTICKCOLOR) pBOI->dwReplyTickColor = DwGetOption(m_fMail?OPT_MAIL_FONTCOLOR:OPT_NEWS_FONTCOLOR); if (pBOI->dwMask & BOPTF_COMPOSEFONT) hr = HrGetComposeFontString(pBOI->rgchComposeFont, ARRAYSIZE(pBOI->rgchComposeFont), m_fMail); return hr; } HRESULT CNote::GetAccount(IImnAccount **ppAcct) { HRESULT hr = S_OK; #ifdef YST FOLDERINFO fi; FOLDERID FolderID; hr = m_pMsgSite->GetFolderID(&FolderID); if (FOLDERID_INVALID != FolderID) { hr = g_pStore->GetFolderInfo(FolderID, &fi); if (SUCCEEDED(hr)) { // Set account based upon the folder ID passed down if (FOLDER_LOCAL != fi.tyFolder) { char szAcctId[CCHMAX_ACCOUNT_NAME]; hr = GetFolderAccountId(&fi, szAcctId, ARRAYSIZE(szAcctId)); if (SUCCEEDED(hr)) hr = g_pAcctMan->FindAccount(AP_ACCOUNT_ID, szAcctId, ppAcct); } else hr = m_pMsgSite->GetCurrentAccount(ppAcct); g_pStore->FreeRecord(&fi); } } else hr = E_FAIL; #endif // 0 hr = m_pHdr->HrGetAccountInHeader(ppAcct); return(hr); } // ************************* void CNote::WMSize(int cxNote, int cyNote, BOOL fInternal) { RECT rc; int cy = 0; // assume the header autosizes itself..., unless an internal size requires we recalc... if(fInternal) { // if the size is coming from the header... figure out the current size // of the note... as cxNote and cyNote are bogus at this point... GetClientRect(m_hwnd, &rc); cxNote = cxRect(rc); cyNote = cyRect(rc); } if (m_pToolbarObj) { //Ideally we should be calling ResizeBorderDW. But HWND rebarHwnd = m_hwndRebar; m_pToolbarObj->ResizeBorderDW(&rc, (IUnknown*)(IDockingWindowSite*)this, 0); GetWindowRect(GetParent(rebarHwnd), &rc); cy += cyRect(rc); } ResizeChildren(cxNote, cyNote, cy, fInternal); } void CNote::ResizeChildren(int cxNote, int cyNote, int cy, BOOL fInternal) { int cyBottom; RECT rc; int cyStatus = 0; static int cxBorder = 0, cyBorder = 0; if(!cxBorder || !cyBorder) { cyBorder = GetSystemMetrics(SM_CYBORDER); cxBorder = GetSystemMetrics(SM_CXBORDER); } // size the header GetClientRect(m_hwnd, &rc); // remember the actual bottom cyBottom = rc.bottom; cy += 4; InflateRect(&rc, -1, -1); rc.bottom = GetRequiredHdrHeight(); rc.top = cy; rc.bottom += rc.top; if(!fInternal && m_pHdr) m_pHdr->SetRect(&rc); // WARNING: the header may resize itself during a size, due to an edit // growing cy += GetRequiredHdrHeight()+2; cy += cyBorder; if (m_pstatus) { m_pstatus->OnSize(cxNote, cyNote); m_pstatus->GetHeight(&cyStatus); } rc.top = cy; rc.bottom = cyBottom-cyBorder; // edit has a minimum size, clip if if gets too tight... rc.bottom -= cyStatus; if (m_pBodyObj2) m_pBodyObj2->HrSetSize(&rc); } // ************************* BOOL CNote::IsReplyNote() { return ((OENA_REPLYTOAUTHOR == m_dwNoteAction) || (OENA_REPLYTONEWSGROUP == m_dwNoteAction) || (OENA_REPLYALL == m_dwNoteAction)); } // ************************* HRESULT CNote::Resize(void) { WMSize(0, 0, TRUE); return S_OK; } // ************************* HRESULT CNote::UpdateTitle() { HRESULT hr; WCHAR wszTitle[cchHeaderMax+1]; Assert(m_pHdr); *wszTitle = 0x0000; hr = m_pHdr->GetTitle(wszTitle, ARRAYSIZE(wszTitle)); if(SUCCEEDED(hr)) SetWindowTextWrapW(m_hwnd, wszTitle); return hr; } // ************************* HRESULT CNote::Update(void) { m_pToolbarObj->Update(); UpdateTitle(); return S_OK; } // ************************* HRESULT CNote::OnSetFocus(HWND hwndFrom) { HWND hwndBody; // setfocus from a kid and not a body. make sure we // UIDeactivate the docobj SideAssert(m_pBodyObj2->HrGetWindow(&hwndBody)==NOERROR); if(hwndFrom != hwndBody) m_pBodyObj2->HrUIActivate(FALSE); // if focus goes to a kid, update the toolbar m_pToolbarObj->Update(); // focus is going to a kid. Enable/Disable the formatbar m_pBodyObj2->HrUpdateFormatBar(); return S_OK; } // ************************* HRESULT CNote::OnUIActivate() { m_fHeaderUIActive = TRUE; return OnSetFocus(0); } // ************************* HRESULT CNote::OnKillFocus() { m_pToolbarObj->Update(); return S_OK; } // ************************* HRESULT CNote::OnUIDeactivate(BOOL) { m_fHeaderUIActive = FALSE; return OnKillFocus(); } // ************************* HRESULT CNote::IsHTML(void) { return m_fHtml ? S_OK : S_FALSE; } HRESULT CNote::IsModal() { return (m_dwNoteCreateFlags & OENCF_MODAL) ? S_OK : S_FALSE; } // ************************* HRESULT CNote::SetHTML(BOOL fHTML) { m_fHtml = !!fHTML; return NOERROR; } #ifdef SMIME_V3 // return selected label in note // S_OK user select label // S_FALSE user uncheck using security labels HRESULT CNote::GetLabelFromNote(PSMIME_SECURITY_LABEL *pplabel) { if(m_fSecurityLabel && m_fMail) { *pplabel = m_pLabel; return S_OK; } else { *pplabel = NULL; return S_FALSE; } } HRESULT CNote::IsSecReceiptRequest(void) { if(m_fSecReceiptRequest) return(S_OK); else return(S_FALSE); } HRESULT CNote::IsForceEncryption(void) { return(m_pHdr->ForceEncryption(NULL, FALSE)); } #endif // SMIME_V3 // ************************* HRESULT CNote::SaveAttachment(void) { return m_pBodyObj2 ? m_pBodyObj2->HrSaveAttachment() : E_FAIL; } // ************************* HRESULT CNote::DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { DWORD dwEffectSave = *pdwEffect;; m_fBypassDropTests = FALSE; Assert(m_pDropTargetHdr && m_pTridentDropTarget); if (m_pHdr->HrIsDragSource() == S_OK) { m_fBypassDropTests = TRUE; // treated as drop to itself. *pdwEffect = DROPEFFECT_NONE; return S_OK; } m_pDropTargetHdr->DragEnter(pDataObj, grfKeyState, pt, pdwEffect); if (*pdwEffect == DROPEFFECT_NONE) { if (!m_fHtml) // plain text mode. If there is no text, we should not take it. { IEnumFORMATETC* pEnum = NULL; FORMATETC fetc = {0}; ULONG celtFetched = 0; BOOL fCFTEXTFound = FALSE; // see if there is CF_TEXT format if (SUCCEEDED(pDataObj->EnumFormatEtc(DATADIR_GET, &pEnum))) { pEnum->Reset(); while (S_OK == pEnum->Next(1, &fetc, &celtFetched)) { Assert(celtFetched == 1); if (fetc.cfFormat == CF_TEXT) { fCFTEXTFound = TRUE; break; } } pEnum->Release(); } if (!fCFTEXTFound) // no CF_TEXT, cannot drop in plain text mode. { *pdwEffect = DROPEFFECT_NONE; m_fBypassDropTests = TRUE; // treated as drop to itself. return S_OK; } } *pdwEffect = dwEffectSave; m_pTridentDropTarget->DragEnter(pDataObj, grfKeyState, pt, pdwEffect); } return S_OK; } // ************************* HRESULT CNote::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { DWORD dwEffectSave = *pdwEffect; if (m_fBypassDropTests) { *pdwEffect = DROPEFFECT_NONE; return S_OK; } m_pDropTargetHdr->DragOver(grfKeyState, pt, pdwEffect); if (*pdwEffect == DROPEFFECT_NONE) { *pdwEffect = dwEffectSave; m_pTridentDropTarget->DragOver(grfKeyState, pt, pdwEffect); } return S_OK; } // ************************* HRESULT CNote::DragLeave(void) { if (m_fBypassDropTests) return S_OK; m_pDropTargetHdr->DragLeave(); m_pTridentDropTarget->DragLeave(); return NOERROR; } // ************************* HRESULT CNote::Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { IDataObject *pDataObjNew = NULL; HRESULT hr = S_OK; STGMEDIUM stgmed; DWORD dwEffectSave = *pdwEffect; ZeroMemory(&stgmed, sizeof(stgmed)); if (m_fBypassDropTests) { *pdwEffect = DROPEFFECT_NONE; return NOERROR; } m_pDropTargetHdr->Drop(pDataObj, grfKeyState, pt, pdwEffect); if (*pdwEffect == DROPEFFECT_NONE) // it is Trident's drag&drop { if(!m_fHtml) { hr = m_pBodyObj2->PublicFilterDataObject(pDataObj, &pDataObjNew); if(FAILED(hr)) return E_UNEXPECTED; } else { pDataObjNew = pDataObj; pDataObj->AddRef(); } *pdwEffect = dwEffectSave; m_pTridentDropTarget->Drop(pDataObjNew, grfKeyState, pt, pdwEffect); } ReleaseObj(pDataObjNew); return hr; } // ************************* HRESULT CNote::InitWindows(RECT *prc, HWND hwndOwner) { HWND hwnd; HMENU hMenu; RECT rcCreate, rc; HCURSOR hcur; HWND hwndCapture; DWORD dwStyle = WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN; HRESULT hr = S_OK; DWORD dwExStyle = WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT | (IS_BIDI_LOCALIZED_SYSTEM() ? RTL_MIRRORED_WINDOW : 0L); WINDOWPLACEMENT wp = {0}; Assert(hwndOwner == NULL || IsWindow(hwndOwner)); m_hwndOwner = hwndOwner; hcur=SetCursor(LoadCursor(NULL, IDC_WAIT)); if(!Note_Init(TRUE)) IF_FAILEXIT(hr = E_FAIL); if(prc) CopyRect(&rcCreate, prc); else CopyRect(&rcCreate, &g_rcLastResize); m_hMenu = LoadMenu(g_hLocRes, MAKEINTRESOURCE(m_fReadNote?IDR_READ_NOTE_MENU:IDR_SEND_NOTE_MENU)); MenuUtil_ReplaceHelpMenu(m_hMenu); MenuUtil_ReplaceNewMsgMenus(m_hMenu); if (m_dwNoteCreateFlags & OENCF_MODAL) { // Check to make sure nobody has captured the mouse from us hwndCapture = GetCapture(); if (hwndCapture) SendMessage(hwndCapture, WM_CANCELMODE, 0, 0); // Let's make sure we have a real topmost owner if (m_hwndOwner) { HWND hwndParent = GetParent(m_hwndOwner); // IsChild checks the WM_CHILD bit in the window. This will only be // set with controls or subs of a window. So, a dialog's parent might be // a note, but that dialog will not be a child of the parent. // RAID 37188 while(IsChild(hwndParent, m_hwndOwner)) { m_hwndOwner = hwndParent; hwndParent = GetParent(m_hwndOwner); } // Lose the minimize box for modal notes if there is a parent dwStyle &= ~WS_MINIMIZEBOX; } } hwnd = CreateWindowExWrapW( dwExStyle, c_wszNoteWndClass, NULL, //caption set by en_change of subject dwStyle, prc?rcCreate.left:CW_USEDEFAULT, // use windows default for x and y. prc?rcCreate.top:CW_USEDEFAULT, cxRect(rcCreate), cyRect(rcCreate), m_hwndOwner, NULL, g_hInst, (LPVOID)this); IF_NULLEXIT(hwnd); if ((m_dwNoteCreateFlags & OENCF_MODAL) && (NULL != m_hwndOwner)) EnableWindow(m_hwndOwner, FALSE); if ( GetOption(OPT_MAILNOTEPOSEX, (LPVOID)&wp, sizeof(wp)) ) { wp.length = sizeof(wp); wp.showCmd = SW_HIDE; SetWindowPlacement(hwnd, &wp); } else { CenterDialog(hwnd); } exit: SetCursor(hcur); return hr; } // ************************* HRESULT CNote::Init(DWORD dwAction, DWORD dwCreateFlags, RECT *prc, HWND hwnd, INIT_MSGSITE_STRUCT *pInitStruct, IOEMsgSite *pMsgSite, IUnknown *punkPump) { HRESULT hr, tempHr = S_OK; IMimeMessage *pMsg = NULL; DWORD dwFormatFlags, dwStatusFlags = 0, dwMsgFlags = (OENA_FORWARDBYATTACH == dwAction) ? (OEGM_ORIGINAL|OEGM_AS_ATTACH) : NOFLAGS; LPSTR pszUnsent = NULL; BOOL fBool = FALSE, fOffline=FALSE; Assert((pInitStruct && !pMsgSite)|| (!pInitStruct && pMsgSite)); ReplaceInterface(m_punkPump, punkPump); // If passed in an INIT_MSGSITE_STRUCT, must convert it to a pMsgSite if (pInitStruct) { m_pMsgSite = new COEMsgSite(); if (!m_pMsgSite) { hr = E_OUTOFMEMORY; goto exit; } Assert(pInitStruct); hr = m_pMsgSite->Init(pInitStruct); if (FAILED(hr)) goto exit; } else ReplaceInterface(m_pMsgSite, pMsgSite); if(m_pMsgSite) m_pMsgSite->GetStatusFlags(&dwStatusFlags); AssertSz(m_pMsgSite, "Why don't we have a msgSite???"); m_dwNoteAction = dwAction; m_fReadNote = !!(OENA_READ == m_dwNoteAction); m_fOriginallyWasRead = m_fReadNote; m_dwNoteCreateFlags = dwCreateFlags; // The storeCallback needs to be set. m_hwnd will be reset once we have a valid handle m_hwnd = hwnd; m_pMsgSite->SetStoreCallback(this); hr = m_pMsgSite->GetMessage(&pMsg, &fBool, dwMsgFlags, &tempHr); if (FAILED(hr)) goto exit; // Raid 80277; Set default charset if(OENA_FORWARDBYATTACH == dwAction) { if (NULL == g_hDefaultCharsetForMail) ReadSendMailDefaultCharset(); pMsg->SetCharset(g_hDefaultCharsetForMail, CSET_APPLY_ALL); } m_fCompleteMsg = !!fBool; // m_f* is a bitfield fOffline = (hr == HR_S_OFFLINE); switch (m_dwNoteAction) { case OENA_REPLYTOAUTHOR: case OENA_FORWARDBYATTACH: case OENA_FORWARD: m_fMail = TRUE; break; case OENA_REPLYTONEWSGROUP: m_fMail = FALSE; case OENA_STATIONERY: case OENA_WEBPAGE: case OENA_COMPOSE: m_fMail = (0 == (m_dwNoteCreateFlags & OENCF_NEWSFIRST)); break; case OENA_REPLYALL: case OENA_READ: { DWORD dwStatusFlags = 0; hr = m_pMsgSite->GetStatusFlags(&dwStatusFlags); if (FAILED(hr)) goto exit; m_fMail = (0 == (OEMSF_BASEISNEWS & dwStatusFlags)); break; } } ProcessIncompleteAccts(hwnd); hr = ProcessICW(hwnd, m_fMail ? FOLDER_LOCAL : FOLDER_NEWS); if (FAILED(hr)) goto exit; // If this is an unsent message and is a read note, then change the type to compose. This needs // to happen after setting the m_fMail flag since we mangle the noteAction. ChangeReadToComposeIfUnsent(pMsg); if (m_fMail) { m_fPackageImages = !!DwGetOption(OPT_MAIL_SENDINLINEIMAGES); dwFormatFlags = FMT_MAIL; } else { PROPVARIANT var; IImnAccount *pAcct = NULL; TCHAR szAcctID[CCHMAX_ACCOUNT_NAME]; DWORD dw; m_fPackageImages = !!DwGetOption(OPT_NEWS_SENDINLINEIMAGES); *szAcctID = 0; dwFormatFlags = FMT_NEWS; // Bug #24267 - Check the message object for a server name before defaulting // to the default server. var.vt = VT_LPSTR; if (SUCCEEDED(pMsg->GetProp(PIDTOSTR(PID_ATT_ACCOUNTID), NOFLAGS, &var))) { StrCpyN(szAcctID, var.pszVal, ARRAYSIZE(szAcctID)); SafeMemFree(var.pszVal); } if (*szAcctID) hr = g_pAcctMan->FindAccount(AP_ACCOUNT_ID, szAcctID, &pAcct); // No account present, or the listed one no longer exists try to get the default if (!*szAcctID || (*szAcctID && FAILED(hr))) hr = m_pMsgSite->GetDefaultAccount(ACCT_NEWS, &pAcct); if ((OENA_WEBPAGE == dwAction) || (OENA_STATIONERY == dwAction)) dwFormatFlags |= FMT_FORCE_HTML; else if (SUCCEEDED(hr) && pAcct && SUCCEEDED(pAcct->GetPropDw(AP_NNTP_POST_FORMAT, &dw))) { if (dw == POST_USE_HTML) dwFormatFlags |= FMT_FORCE_HTML; else if (dw == POST_USE_PLAIN_TEXT) dwFormatFlags |= FMT_FORCE_PLAIN; else Assert(dw == POST_USE_DEFAULT); } ReleaseObj(pAcct); } GetDefaultOptInfo(&m_rHtmlOpt, &m_rPlainOpt, &fBool, dwFormatFlags); switch (m_dwNoteAction) { case OENA_FORWARDBYATTACH: m_fHtml = !!fBool; break; case OENA_COMPOSE: if (m_fOriginallyWasRead) { DWORD dwFlags = 0; pMsg->GetFlags(&dwFlags); m_fHtml = !!(dwFlags & IMF_HTML); } else m_fHtml = !!fBool; break; case OENA_STATIONERY: case OENA_WEBPAGE: case OENA_READ: m_fHtml = TRUE; // HTML is always cool in a readnote break; case OENA_REPLYTOAUTHOR: case OENA_REPLYTONEWSGROUP: case OENA_REPLYALL: case OENA_FORWARD: // when replying, if option to repect sender format is on, do so if (DwGetOption(OPT_REPLYINORIGFMT)) { DWORD dwFlags = 0; pMsg->GetFlags(&dwFlags); m_fHtml = !!(dwFlags & IMF_HTML); } else m_fHtml = !!fBool; // Bug 76570, 76575 // Set security label if(pMsg) { SECSTATE SecState; HrGetSecurityState(pMsg, &SecState, NULL); // only in case of signing message check label if(IsSigned(SecState.type)) { PCRYPT_ATTRIBUTE pattrLabel; LPBYTE pbLabel = NULL; DWORD cbLabel; PSMIME_SECURITY_LABEL plabel = NULL; IMimeSecurity2 * pSMIME3 = NULL; IMimeBody *pBody = NULL; if(pMsg->BindToObject(HBODY_ROOT, IID_IMimeBody, (void **)&pBody) == S_OK) { if(pBody->QueryInterface(IID_IMimeSecurity2, (LPVOID *) &pSMIME3) == S_OK) { // Get label attribute if(pSMIME3->GetAttribute(0, 0, SMIME_ATTRIBUTE_SET_SIGNED, 0, szOID_SMIME_Security_Label, &pattrLabel) == S_OK) { // decode label if(CryptDecodeObjectEx(X509_ASN_ENCODING, szOID_SMIME_Security_Label, pattrLabel->rgValue[0].pbData, pattrLabel->rgValue[0].cbData, CRYPT_DECODE_ALLOC_FLAG, &CryptDecodeAlloc, &plabel, &cbLabel)) { if(plabel) { m_fSecurityLabel = TRUE; SafeMemFree(m_pLabel); m_pLabel = plabel; } } } else { // Secure receipt is binary message and pMsg->GetFlags always will retutn non-HTML, but we // forward (or Replay) with our HTML screen and need to set this to HTML. if(CheckSecReceipt(pMsg) == S_OK) m_fHtml = TRUE; } SafeRelease(pSMIME3); } ReleaseObj(pBody); } } CleanupSECSTATE(&SecState); } break; } hr = InitWindows(prc, (dwCreateFlags & OENCF_MODAL) ? hwnd : 0); if (FAILED(hr)) goto exit; hr = Load(pMsg); if (FAILED(hr)) goto exit; if (FAILED(tempHr)) ShowErrorScreen(tempHr); m_fFullHeaders = (S_OK == m_pHdr->FullHeadersShowing()); if (fOffline) ShowErrorScreen(HR_E_OFFLINE); hr = InitMenusAndToolbars(); // Register with identity manager SideAssert(SUCCEEDED(hr = MU_RegisterIdentityNotifier((IUnknown *)(IOENote *)this, &m_dwIdentCookie))); exit: ReleaseObj(pMsg); if (FAILED(hr) && m_pMsgSite && !pMsgSite) m_pMsgSite->Close(); return hr; } // Will return after close if is modal, otherwise returns immediately HRESULT CNote::Show(void) { ShowWindow(m_hwnd, SW_SHOW); SetForegroundWindow(m_hwnd); if (m_dwNoteCreateFlags & OENCF_MODAL) { MSG msg; HWNDLIST hwndList; EnableThreadWindows(&hwndList, FALSE, 0, m_hwnd); while (GetMessageWrapW(&msg, NULL, 0, 0)) { // This is a member function, so don't need to wrap if (TranslateAccelerator(&msg) == S_OK) continue; ::TranslateMessage(&msg); ::DispatchMessageWrapW(&msg); } EnableThreadWindows(&hwndList, TRUE, 0, m_hwnd); } return S_OK; } // ************************* BOOL CNote::WMCreate(HWND hwnd) { LPTBBUTTON lpButtons; ULONG cBtns; HWND hwndRebar; CMimeEditDocHost *pNoteBody; DWORD dwStyle; RECT rc; VARIANTARG var; IUnknown *pUnk = NULL; REBARBANDINFO rbbi; m_hwnd = hwnd; SetWndThisPtr(hwnd, this); AddRef(); Assert(IsWindow(m_hwnd)); SetProp(hwnd, c_szOETopLevel, (HANDLE)TRUE); //Create a new bandsclass and intialize it m_pToolbarObj = new CBands(); if (!m_pToolbarObj) return FALSE; m_pToolbarObj->HrInit(0, m_hMenu, PARENT_TYPE_NOTE); m_pToolbarObj->SetSite((IOENote*)this); m_pToolbarObj->ShowDW(TRUE); m_pToolbarObj->SetFolderType(GetNoteType()); m_fToolbarVisible = m_pToolbarObj->IsToolbarVisible(); m_hwndToolbar = m_pToolbarObj->GetToolbarWnd(); m_hwndRebar = m_pToolbarObj->GetRebarWnd(); pNoteBody = new CMimeEditDocHost(MEBF_INNERCLIENTEDGE); if (!pNoteBody) return FALSE; pNoteBody->QueryInterface(IID_IBodyObj2, (LPVOID *)&m_pBodyObj2); pNoteBody->Release(); if (!m_pBodyObj2) return FALSE; m_pBodyObj2->QueryInterface(IID_IPersistMime, (LPVOID*)&m_pPrstMime); if (!m_pPrstMime) return FALSE; m_pstatus = new CStatusBar(); if (NULL == m_pstatus) return FALSE; m_pstatus->Initialize(m_hwnd, SBI_HIDE_SPOOLER | SBI_HIDE_CONNECTED | SBI_HIDE_FILTERED); m_pstatus->ShowStatus(m_fStatusbarVisible); m_pBodyObj2->HrSetStatusBar(m_pstatus); CreateInstance_Envelope(NULL, (IUnknown**)&pUnk); if (!pUnk) return FALSE; pUnk->QueryInterface(IID_IHeader, (LPVOID*)&m_pHdr); pUnk->Release(); if (!m_pHdr) return FALSE; m_pHdr->QueryInterface(IID_IDropTarget, (LPVOID*)&m_pDropTargetHdr); if (!m_pDropTargetHdr) return FALSE; m_pHdr->QueryInterface(IID_IOleCommandTarget, (LPVOID*)&m_pCmdTargetHdr); if (!m_pCmdTargetHdr) return FALSE; if (!m_fMail) HeaderExecCommand(MSOEENVCMDID_NEWS, MSOCMDEXECOPT_DODEFAULT, NULL); var.vt = VT_I4; var.lVal = m_dwNoteAction; HeaderExecCommand(MSOEENVCMDID_SETACTION, MSOCMDEXECOPT_DODEFAULT, &var); if (FAILED(m_pHdr->Init((IHeaderSite*)this, hwnd))) return FALSE; if (FAILED(InitBodyObj())) return FALSE; // Set focus in the To: line switch (m_dwNoteAction) { case OENA_COMPOSE: case OENA_FORWARD: case OENA_FORWARDBYATTACH: case OENA_WEBPAGE: case OENA_STATIONERY: m_pHdr->SetInitFocus(FALSE); break; } m_pBodyObj2->SetEventSink((IMimeEditEventSink *) this); SetForegroundWindow(m_hwnd); return TRUE; } // ************************* void CNote::InitSendAndBccBtns() { DWORD idiIcon; HICON hIconTemp = 0; Assert(m_hwnd); if (m_fMail) idiIcon = m_fReadNote?idiMsgPropSent:idiMsgPropUnSent; else idiIcon = m_fReadNote?idiArtPropPost:idiArtPropUnpost; // don't have to free HICON loaded from LoadIcon SendMessage(m_hwnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(g_hLocRes, MAKEINTRESOURCE(idiIcon))); if (m_fMail) idiIcon = m_fReadNote?idiSmallMsgPropSent:idiSmallMsgPropUnSent; else idiIcon = m_fReadNote?idiSmallArtPropPost:idiSmallArtPropUnpost; if(m_hIcon) { hIconTemp = m_hIcon; } m_hIcon = (HICON)LoadImage(g_hLocRes, MAKEINTRESOURCE(idiIcon), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0); // don't have to free HICON loaded from LoadIcon SendMessage(m_hwnd, WM_SETICON, ICON_SMALL, (LPARAM)m_hIcon); if(hIconTemp) { //Bug #101345 - (erici) ICON leaked when 'Previous' or 'Next' button clicked DestroyIcon(hIconTemp); } // If this is a news send note, then we spruce up the send button on the toolbar if ((FALSE == m_fReadNote) && (FALSE == m_fMail)) { TBBUTTONINFO tbi; ZeroMemory(&tbi, sizeof(TBBUTTONINFO)); tbi.cbSize = sizeof(TBBUTTONINFO); tbi.dwMask = TBIF_IMAGE; tbi.iImage = TBIMAGE_SEND_NEWS; SendMessage(m_hwndToolbar, TB_SETBUTTONINFO, ID_SEND_DEFAULT, (LPARAM) &tbi); } } // ************************* HRESULT CNote::HeaderExecCommand(UINT uCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn) { HRESULT hr = S_FALSE; if (uCmdID && m_pCmdTargetHdr) hr = m_pCmdTargetHdr->Exec(&CGID_Envelope, uCmdID, nCmdExecOpt, pvaIn, NULL); return hr; } // ************************* HRESULT CNote::InitBodyObj() { DWORD dwBodyStyle = MESTYLE_NOHEADER; HRESULT hr; int idsErr=0; hr = m_pBodyObj2->HrInit(m_hwnd, IBOF_TABLINKS, (IBodyOptions *)this); if (FAILED(hr)) goto fail; hr = m_pBodyObj2->QueryInterface(IID_IOleCommandTarget, (LPVOID*)&m_pCmdTargetBody); if (FAILED(hr)) goto fail; hr = m_pBodyObj2->HrShow(TRUE); if (FAILED(hr)) goto fail; // if not in html mode, don't show format bar... // we do this test here, as HrLoad could determine that a previously saved message // is indeed in html, which overrides the default setting if(!m_fHtml) m_fFormatbarVisible = FALSE; if (!m_fReadNote && !m_fBodyContainsFrames && m_fFormatbarVisible) dwBodyStyle = MESTYLE_FORMATBAR; m_pBodyObj2->HrEnableHTMLMode(m_fHtml); m_pBodyObj2->HrSetStyle(dwBodyStyle); // all is groovey return hr; fail: switch (hr) { case INET_E_UNKNOWN_PROTOCOL: idsErr = idsErrLoadProtocolBad; break; default: idsErr = idsErrNoteDeferedInit; break; } AthMessageBoxW(g_hwndInit, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErr), NULL, MB_OK); return hr; } // ************************* HRESULT CNote::InitMenusAndToolbars() { DWORD dwStatusFlags; HRESULT hr; BOOL fComposeNote, fCompleteMsg = !!m_fCompleteMsg, // m_fCompleteMsg is a bit field. fNextPrevious; HMENU hMenu = m_hMenu; m_fUseReplyHeaders = FALSE; Assert(m_pMsgSite); if (m_pMsgSite) m_pMsgSite->GetStatusFlags(&dwStatusFlags); switch (m_dwNoteAction) { case OENA_FORWARDBYATTACH: case OENA_COMPOSE: // if it's a virgin compose-note, we check the regsettings to see if they want to compose // from a stationery file. If so, we set the html stream to that file. if (m_fHtml && !(m_dwNoteCreateFlags & OENCF_NOSTATIONERY) && (OEMSF_VIRGIN & dwStatusFlags)) SetComposeStationery(); break; case OENA_STATIONERY: if (m_dwNoteCreateFlags & OENCF_USESTATIONERYFONT) m_fUseStationeryFonts = TRUE; break; case OENA_REPLYTOAUTHOR: case OENA_REPLYTONEWSGROUP: case OENA_REPLYALL: case OENA_FORWARD: m_fUseReplyHeaders = TRUE; break; } InitSendAndBccBtns(); if (m_fMail) { if (m_fReadNote || IsReplyNote()) m_pBodyObj2->HrUIActivate(TRUE); } else { if ((OENA_COMPOSE == m_dwNoteAction) && (OEMSF_VIRGIN & dwStatusFlags)) // for a sendnote in news, put focus in the subject as the to: line is filled in. bug #24720 m_pHdr->SetInitFocus(TRUE); else // else , always put focus in the BODY m_pBodyObj2->HrUIActivate(TRUE); } RECT rc; GetClientRect(m_hwnd, &rc); SendMessage(m_hwnd, WM_SIZE, SIZE_RESTORED, MAKELPARAM(rc.right, rc.bottom)); // put us into edit mode if not a readnote... hr=m_pBodyObj2->HrSetEditMode(!m_fReadNote && !m_fBodyContainsFrames); if (FAILED(hr)) goto error; if (m_fBodyContainsFrames) DisableSendNoteOnlyMenus(); // get the character set of the message being loaded if (m_pMsg) m_pMsg->GetCharset(&m_hCharset); error: return hr; } // ************************* void CNote::DisableSendNoteOnlyMenus() { } // ************************* HACCEL CNote::GetAcceleratorTable() { return (m_fReadNote ? g_hAccelRead : g_hAccelSend); } // ************************* HRESULT CNote::TranslateAccelerator(LPMSG lpmsg) { HWND hwndT, hwndFocus; if (IsMenuMessage(lpmsg) == S_OK) return S_OK; // handle the mousewheel messages for this note if ((g_msgMSWheel && (lpmsg->message == g_msgMSWheel)) || (lpmsg->message == WM_MOUSEWHEEL)) { POINT pt; HWND hwndT; pt.x = GET_X_LPARAM(lpmsg->lParam); pt.y = GET_Y_LPARAM(lpmsg->lParam); hwndT = WindowFromPoint(pt); hwndFocus = GetFocus(); if (hwndT != m_hwnd && IsChild(m_hwnd, hwndT)) SendMessage(hwndT, lpmsg->message, lpmsg->wParam, lpmsg->lParam); else if (hwndFocus != m_hwnd && IsChild(m_hwnd, hwndFocus)) SendMessage(hwndFocus, lpmsg->message, lpmsg->wParam, lpmsg->wParam); else return S_FALSE; return S_OK; } // our accelerators have higher priority. if(::TranslateAcceleratorWrapW(m_hwnd, GetAcceleratorTable(), lpmsg)) return S_OK; // see if the body want it for the docobject... if(m_pBodyObj2 && m_pBodyObj2->HrTranslateAccelerator(lpmsg)==S_OK) return S_OK; if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == VK_TAB && !(GetKeyState(VK_CONTROL) & 0x8000 )) { BOOL fGoForward = ( GetKeyState( VK_SHIFT ) & 0x8000 ) == 0; CycleThroughControls(fGoForward); return S_OK; } return S_FALSE; } // ************************* LRESULT CNote::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { LRESULT lResult; LRESULT lres; MSG Menumsg; HWND hwndActive; WINDOWPLACEMENT wp; Menumsg.hwnd = hwnd; Menumsg.message = msg; Menumsg.wParam = wParam; Menumsg.lParam = lParam; if (m_pToolbarObj && (m_pToolbarObj->TranslateMenuMessage(&Menumsg, &lres) == S_OK)) return lres; wParam = Menumsg.wParam; lParam = Menumsg.lParam; switch(msg) { case WM_ENABLE: if (!m_fInternal) { Assert (wParam || (m_hlDisabled.cHwnd == NULL && m_hlDisabled.rgHwnd == NULL)); EnableThreadWindows(&m_hlDisabled, !!wParam, ETW_OE_WINDOWS_ONLY, hwnd); g_hwndActiveModal = wParam ? NULL : hwnd; } break; case WM_OE_DESTROYNOTE: m_fForceClose = 1; SendMessage(hwnd, WM_CLOSE, 0, 0); break; case WM_OENOTE_ON_COMPLETE: _OnComplete((STOREOPERATIONTYPE)lParam, (HRESULT) wParam); break; case WM_OE_ENABLETHREADWINDOW: m_fInternal = 1; EnableWindow(hwnd, (BOOL)wParam); m_fInternal = 0; break; case WM_OE_ACTIVATETHREADWINDOW: hwndActive = GetLastActivePopup(hwnd); if (hwndActive && IsWindowEnabled(hwndActive) && IsWindowVisible(hwndActive)) ActivatePopupWindow(hwndActive); break; case NWM_GETDROPTARGET: SafeRelease(m_pTridentDropTarget); m_pTridentDropTarget = (IDropTarget*) wParam; if (m_pTridentDropTarget) m_pTridentDropTarget->AddRef(); AddRef(); return (LRESULT)(IDropTarget *) this; case WM_DESTROY: // Unregister with Identity manager if (m_dwIdentCookie != 0) { MU_UnregisterIdentityNotifier(m_dwIdentCookie); m_dwIdentCookie = 0; } wp.length = sizeof(wp); GetWindowPlacement(hwnd, &wp); SetOption(OPT_MAILNOTEPOSEX, (LPVOID)&wp, sizeof(wp), NULL, 0); RemoveProp(hwnd, c_szOETopLevel); DeinitSigPopupMenu(hwnd); if(m_pBodyObj2) { m_pBodyObj2->HrSetStatusBar(NULL); m_pBodyObj2->HrClose(); } SafeRelease(m_pTridentDropTarget); if (m_pToolbarObj) { DWORD dwReserved = 0; m_pToolbarObj->SetSite(NULL); m_pToolbarObj->CloseDW(dwReserved); } if (m_pCancel) m_pCancel->Cancel(CT_ABORT); if (m_pMsgSite) m_pMsgSite->Close(); break; case WM_NCDESTROY: DOUTL(8, "CNote::WMNCDESTROY"); WMNCDestroy(); return 0; case WM_ACTIVATEAPP: if (wParam && g_hwndActiveModal && g_hwndActiveModal != hwnd && !IsWindowEnabled(hwnd)) { // $MODAL // if we are getting activated, and are disabled then // bring our 'active' window to the top Assert (IsWindow(g_hwndActiveModal)); PostMessage(g_hwndActiveModal, WM_OE_ACTIVATETHREADWINDOW, 0, 0); } break; case WM_SYSCOMMAND: // if we're minimizing, get the control with focus, as when we get the // next WM_ACTIVATE we will already be minimized if (wParam == SC_MINIMIZE) m_hwndFocus = GetFocus(); break; case WM_ACTIVATE: if (m_pBodyObj2) m_pBodyObj2->HrFrameActivate(LOWORD(wParam) != WA_INACTIVE); break; case WM_ENDSESSION: DOUTL(2, "CNote::WM_ENDSESSION"); if (wParam) DestroyWindow(hwnd); return 0; case WM_QUERYENDSESSION: DOUTL(2, "CNote::WM_QUERYENDSESSION"); // fall thro' case WM_CLOSE: if (!m_fForceClose && !FCanClose()) return 0; // listen-up: // we have to do this EnableWindowof the modal owner in the WM_CLOSE // handler, as WM_DESTROY is too late - USER may have SetFocus to the next // active toplevel z-order window (as the note has been hidden by then) - if the // window is in another process SetFocus back to the owner will be ignored. // Also, in the places we call DestroyWindow we need to make sure we go thro' this // WM_CLOSE handler. So all calls to DestroyWindow instead call WM_OE_DESTROYNOTE // which sets an internal flag to force down the note (so we don't prompt if dirty) // and then calls WM_CLOSE, which falls thro' to DefWndProc and results in a DestroyWindow // got it? if (m_dwNoteCreateFlags & OENCF_MODAL) { // Need to enable the owner window if (NULL != m_hwndOwner) { EnableWindow(m_hwndOwner, TRUE); } } break; case WM_MEASUREITEM: if(m_pBodyObj2 && m_pBodyObj2->HrWMMeasureMenuItem(hwnd, (LPMEASUREITEMSTRUCT)lParam)==S_OK) return 0; break; case WM_DRAWITEM: if(m_pBodyObj2 && m_pBodyObj2->HrWMDrawMenuItem(hwnd, (LPDRAWITEMSTRUCT)lParam)==S_OK) return 0; break; case WM_DROPFILES: if (m_pHdr) m_pHdr->DropFiles((HDROP)wParam, FALSE); return 0; case WM_COMMAND: WMCommand( GET_WM_COMMAND_HWND(wParam, lParam), GET_WM_COMMAND_ID(wParam, lParam), GET_WM_COMMAND_CMD(wParam, lParam)); return 0; case WM_INITMENUPOPUP: return WMInitMenuPopup(hwnd, (HMENU)wParam, (UINT)LOWORD(lParam)); case WM_GETMINMAXINFO: WMGetMinMaxInfo((LPMINMAXINFO)lParam); break; case WM_MENUSELECT: if (LOWORD(wParam)>=ID_STATIONERY_RECENT_0 && LOWORD(wParam)<=ID_STATIONERY_RECENT_9) { m_pstatus->ShowSimpleText(MAKEINTRESOURCE(idsRSListGeneralHelp)); return 0; } if (LOWORD(wParam)>=ID_APPLY_STATIONERY_0 && LOWORD(wParam)<=ID_APPLY_STATIONERY_9) { m_pstatus->ShowSimpleText(MAKEINTRESOURCE(idsApplyStationeryGeneralHelp)); return 0; } if (LOWORD(wParam)>=ID_SIGNATURE_FIRST && LOWORD(wParam)<=ID_SIGNATURE_LAST) { m_pstatus->ShowSimpleText(MAKEINTRESOURCE(idsInsertSigGeneralHelp)); return 0; } if (LOWORD(wParam)>=ID_FORMAT_FIRST && LOWORD(wParam)<=ID_FORMAT_LAST) { m_pstatus->ShowSimpleText(MAKEINTRESOURCE(idsApplyFormatGeneralHelp)); return 0; } HandleMenuSelect(m_pstatus, wParam, lParam); return 0; case NWM_TESTGETDISP: case NWM_TESTGETADDR: return lTestHook(msg, wParam, lParam); case NWM_UPDATETOOLBAR: m_pToolbarObj->Update(); return 0; case NWM_PASTETOATTACHMENT: if (m_pHdr) m_pHdr->DropFiles((HDROP)wParam, (BOOL)lParam); return 0; case WM_CONTEXTMENU: break; case WM_SIZE: if(wParam==SIZE_RESTORED) // update global last-size GetWindowRect(hwnd, &g_rcLastResize); WMSize(LOWORD(lParam), HIWORD(lParam), FALSE); break; case WM_NOTIFY: WMNotify((int) wParam, (NMHDR *)lParam); break; case WM_SETCURSOR: if (!!m_fWindowDisabled) { HourGlass(); return TRUE; } break; case WM_DISPLAYCHANGE: { WINDOWPLACEMENT wp; wp.length = sizeof(wp); GetWindowPlacement(hwnd, &wp); SetWindowPlacement(hwnd, &wp); } // Drop through case WM_WININICHANGE: case WM_SYSCOLORCHANGE: case WM_QUERYNEWPALETTE: case WM_PALETTECHANGED: { HWND hwndT; // pass down to trident if (m_pBodyObj2 && m_pBodyObj2->HrGetWindow(&hwndT)==S_OK) SendMessage(hwndT, msg, wParam, lParam); if (m_pToolbarObj && m_pToolbarObj->GetWindow(&hwndT)==S_OK) SendMessage(hwndT, msg, wParam, lParam); } break; default: if (g_msgMSWheel && (msg == g_msgMSWheel)) { HWND hwndFocus = GetFocus(); if (hwndFocus != hwnd) return SendMessage(hwndFocus, msg, wParam, lParam); } break; } lResult=DefWindowProcWrapW(hwnd, msg, wParam, lParam); if (msg==WM_ACTIVATE) { // need to post-process this // save the control with the focus don't do this is we're // minimized, otherwise GetFocus()==m_hwnd if (!HIWORD(wParam)) { // if not minimized, save/restore child focus if ((LOWORD(wParam) == WA_INACTIVE)) { // if deactivating then save the focus m_hwndFocus = GetFocus(); DOUTL(4, "Focus was on 0x%x", m_hwndFocus); } else { // if activating, and not minimized then restore focus if (IsWindow(m_hwndFocus) && IsChild(hwnd, m_hwndFocus)) { DOUTL(4, "Restoring Focus to: 0x%x", m_hwndFocus); SetFocus(m_hwndFocus); } } } if (!(m_dwNoteCreateFlags & OENCF_MODAL)) SetTlsGlobalActiveNote((LOWORD(wParam)==WA_INACTIVE)?NULL:this); DOUTL(8, "CNote::WMActivate:: %x", GetTlsGlobalActiveNote()); } return lResult; } // ************************* BOOL CNote::FCanClose() { int id; HRESULT hr = S_OK; if(IsDirty()==S_FALSE) return TRUE; // TODO: set the title properly id = AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsSaveChangesMsg), NULL, MB_YESNOCANCEL|MB_ICONWARNING); if(id==IDCANCEL) return FALSE; // Note - It's the job of the subclass to display any UI that might // describe why saving failed. if (id == IDYES) hr = SaveMessage(NOFLAGS); if (FAILED(hr)) { if (E_PENDING == hr) m_fCBDestroyWindow = TRUE; return FALSE; } return TRUE; } // ************************* HRESULT CNote::SaveMessage(DWORD dwSaveFlags) { HRESULT hr; IMimeMessage *pMsg = NULL; IImnAccount *pAcct = NULL; hr = HrCreateMessage(&pMsg); if (FAILED(hr)) goto exit; hr = Save(pMsg, 0); if (SUCCEEDED(hr)) { hr = m_pHdr->HrGetAccountInHeader(&pAcct); if (FAILED(hr)) goto exit; dwSaveFlags |= OESF_UNSENT; if (m_fOriginallyWasRead && (OENA_COMPOSE == m_dwNoteAction)) dwSaveFlags |= OESF_SAVE_IN_ORIG_FOLDER; if(IsSecure(pMsg)) { if(AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsSaveSecMsgToDraft), NULL, MB_OKCANCEL) == IDCANCEL) { hr = MAPI_E_USER_CANCEL; goto exit; } else { PROPVARIANT rVariant; IMimeBody *pBody = NULL; rVariant.vt = VT_BOOL; rVariant.boolVal = TRUE; hr = pMsg->BindToObject(HBODY_ROOT, IID_IMimeBody, (void **)&pBody); if(SUCCEEDED(hr)) { pBody->SetOption(OID_NOSECURITY_ONSAVE, &rVariant); ReleaseObj(pBody); } } } m_fHasBeenSaved = TRUE; _SetPendingOp(SOT_PUT_MESSAGE); hr = m_pMsgSite->Save(pMsg, dwSaveFlags, pAcct); if (SUCCEEDED(hr)) _OnComplete(SOT_PUT_MESSAGE, S_OK); else if (hr == E_PENDING) EnableNote(FALSE); } exit: ReleaseObj(pAcct); ReleaseObj(pMsg); return hr; } // ************************* void CNote::WMNCDestroy() { if (m_dwNoteCreateFlags & OENCF_MODAL) PostQuitMessage(0); SetWndThisPtr(m_hwnd, NULL); m_hwnd=NULL; Release(); } // ************************* void CNote::ChangeReadToComposeIfUnsent(IMimeMessage *pMsg) { DWORD dwStatusFlags = 0; if (m_fReadNote && SUCCEEDED(m_pMsgSite->GetStatusFlags(&dwStatusFlags)) && (OEMSF_UNSENT & dwStatusFlags)) { m_dwNoteAction = OENA_COMPOSE; m_fReadNote = FALSE; } } // ************************* void CNote::ReloadMessageFromSite(BOOL fOriginal) { IMimeMessage *pMsg = NULL; BOOL fBool = FALSE, fTempHtml; DWORD dwBodyStyle = MESTYLE_NOHEADER, dwMsgFlags; HRESULT hr = S_OK, tempHr; if (OENA_FORWARDBYATTACH == m_dwNoteAction) dwMsgFlags = (OEGM_ORIGINAL|OEGM_AS_ATTACH); else dwMsgFlags = (fOriginal ? OEGM_ORIGINAL : NOFLAGS); hr = m_pMsgSite->GetMessage(&pMsg, &fBool, dwMsgFlags, &tempHr); if (SUCCEEDED(hr)) { // ~~~ Check what happens here if message is not downloaded and hit forward as attach DWORD dwFlags = 0; m_fCompleteMsg = !!fBool; // All notes will be read note unless unsent m_dwNoteAction = OENA_READ; m_fOriginallyWasRead = TRUE; m_fReadNote = TRUE; // Is this an unsent message and is a read note? Then should be a compose. ChangeReadToComposeIfUnsent(pMsg); // This needs to be called for the case where we load an IMAP message. In this // case we don't know if it is html or not. We won't know until after it is // downloaded. That is what is happening at this point. Before we do our // load, let's make sure that we have set m_fHtml properly. RAID 46327 if(CheckSecReceipt(pMsg) == S_OK) fTempHtml = TRUE; else { pMsg->GetFlags(&dwFlags); fTempHtml = !!(dwFlags & IMF_HTML); } // If m_fHtml was already set correctly, then don't do it again. if (fTempHtml != m_fHtml) { m_fFormatbarVisible = m_fHtml = fTempHtml; if (!m_fReadNote && !m_fBodyContainsFrames && m_fFormatbarVisible) dwBodyStyle = MESTYLE_FORMATBAR; m_pBodyObj2->HrSetStyle(dwBodyStyle); m_pBodyObj2->HrEnableHTMLMode(m_fHtml); } Load(pMsg); InitMenusAndToolbars(); pMsg->Release(); if (FAILED(tempHr)) ShowErrorScreen(tempHr); } else { if (E_FAIL == hr) m_fCBDestroyWindow = TRUE; } } // ************************* HRESULT CNote::WMCommand(HWND hwndCmd, int id, WORD wCmd) { int iRet = 0; DWORD dwFlags = 0; FOLDERID folderID = FOLDERID_INVALID; DOUTL(4, "CNote::WMCommand"); OLECMD cmd; // We can hit this via accelerators. Since accelerators don't go through // QueryStatus(), we need to make sure this should really be enabled. cmd.cmdID = id; cmd.cmdf = 0; if (FAILED(QueryStatus(&CMDSETID_OutlookExpress, 1, &cmd, NULL)) || (0 == (cmd.cmdf & OLECMDF_ENABLED))) return (S_OK); // see if any of these are for the body control, if so we're done... if(m_pBodyObj2 && SUCCEEDED(m_pBodyObj2->HrWMCommand(hwndCmd, id, wCmd))) return S_OK; // give the header a shot after the note is done if (m_pHdr && m_pHdr->WMCommand(hwndCmd, id, wCmd)==S_OK) return S_OK; // Don't handle anything that isn't a menu item or accelerator if (wCmd <= 1) { if ((id == ID_SEND_NOW) || (id >= ID_SEND_NOW_ACCOUNT_FIRST && id <= ID_SEND_NOW_ACCOUNT_LAST) || (id == ID_SEND_LATER) || (id >= ID_SEND_LATER_ACCOUNT_FIRST && id <= ID_SEND_LATER_ACCOUNT_LAST)) { HrSendMail(id); return S_OK; } if (id >= ID_LANG_FIRST && id <= ID_LANG_LAST) { SwitchLanguage(id); return S_OK; } if (id>=ID_ADD_RECIPIENT_FIRST && id<=ID_ADD_RECIPIENT_LAST) { if (m_pHdr) m_pHdr->AddRecipient(id - ID_ADD_RECIPIENT_FIRST); return S_OK; } if (id > ID_MSWEB_BASE && id < ID_MSWEB_LAST) { OnHelpGoto(m_hwnd, id); return S_OK; } // Handle all "create new note" IDs Assert(m_pMsgSite); if (m_pMsgSite) { m_pMsgSite->GetFolderID(&folderID); if (MenuUtil_HandleNewMessageIDs(id, m_hwnd, folderID, m_fMail, (m_dwNoteCreateFlags & OENCF_MODAL)?TRUE:FALSE, m_punkPump)) return S_OK; } // ONLY processing menu accelerators switch(id) { case ID_SEND_DEFAULT: HrSendMail(DwGetOption(OPT_SENDIMMEDIATE) && !g_pConMan->IsGlobalOffline() ? ID_SEND_NOW : ID_SEND_LATER); return S_OK; case ID_ABOUT: DoAboutAthena(m_hwnd, idiMail); return S_OK; case ID_SAVE: SaveMessage(NOFLAGS); return S_OK; case ID_NOTE_DELETE: { HRESULT hr; m_fOrgCmdWasDelete = TRUE; _SetPendingOp(SOT_DELETING_MESSAGES); hr = m_pMsgSite->Delete(NOFLAGS); if (SUCCEEDED(hr)) _OnComplete(SOT_DELETING_MESSAGES, S_OK); else { if (hr == E_PENDING) EnableNote(FALSE); else AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrDeleteMsg), NULL, MB_OK); } return S_OK; } case ID_NOTE_COPY_TO_FOLDER: case ID_NOTE_MOVE_TO_FOLDER: { HRESULT hr; IMimeMessage *pMsg = NULL; DWORD dwStatusFlags = 0; m_fCBCopy = (ID_NOTE_COPY_TO_FOLDER == id); m_pMsgSite->GetStatusFlags(&dwStatusFlags); if (S_OK == IsDirty() || ((OEMSF_FROM_MSG | OEMSF_VIRGIN) & dwStatusFlags)) { CommitChangesInNote(); pMsg = m_pMsg; } if(IsSecure(m_pMsg) && !m_fReadNote) { if(AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsSaveSecMsgToFolder), NULL, MB_OKCANCEL) == IDCANCEL) return S_OK; else { PROPVARIANT rVariant; IMimeBody *pBody = NULL; rVariant.vt = VT_BOOL; rVariant.boolVal = TRUE; hr = m_pMsg->BindToObject(HBODY_ROOT, IID_IMimeBody, (void **)&pBody); if(SUCCEEDED(hr)) { pBody->SetOption(OID_NOSECURITY_ONSAVE, &rVariant); ReleaseObj(pBody); } } } _SetPendingOp(SOT_COPYMOVE_MESSAGE); hr = m_pMsgSite->DoCopyMoveToFolder(m_fCBCopy, pMsg, !m_fReadNote); if (SUCCEEDED(hr)) _OnComplete(SOT_COPYMOVE_MESSAGE, S_OK); else if (E_PENDING == hr) EnableNote(FALSE); return S_OK; } case ID_NEXT_UNREAD_MESSAGE: case ID_NEXT_UNREAD_THREAD: case ID_NEXT_UNREAD_ARTICLE: dwFlags = OENF_UNREAD; if (ID_NEXT_UNREAD_THREAD == id) dwFlags |= OENF_THREAD; // Fall through case ID_PREVIOUS: case ID_NEXT_MESSAGE: { HRESULT hr; dwFlags |= (m_fMail ? OENF_SKIPMAIL : OENF_SKIPNEWS); hr = m_pMsgSite->DoNextPrev((ID_PREVIOUS != id), dwFlags); if (SUCCEEDED(hr)) { ReloadMessageFromSite(); AssertSz(!m_fCBDestroyWindow, "Shouldn't need to destroy the window..."); } #ifdef DEBUG // All DoNextPrev does is set the new message ID. Should never need to go // E_PENDING to get that information else if (E_PENDING == hr) AssertSz(FALSE, "Didn't expect to get an E_PENDING with NextPrev."); #endif else MessageBeep(MB_OK); return S_OK; } case ID_MARK_THREAD_READ: MarkMessage(MARK_MESSAGE_READ, APPLY_CHILDREN); return S_OK; case ID_NOTE_PROPERTIES: DoProperties(); return S_OK; case ID_REPLY: case ID_REPLY_GROUP: case ID_REPLY_ALL: case ID_FORWARD: case ID_FORWARD_AS_ATTACH: { DWORD dwAction = 0; RECT rc; HRESULT hr = S_OK; GetWindowRect(m_hwnd, &rc); switch (id) { case ID_REPLY: dwAction = OENA_REPLYTOAUTHOR; break; case ID_REPLY_GROUP: dwAction = OENA_REPLYTONEWSGROUP; break; case ID_REPLY_ALL: dwAction = OENA_REPLYALL; break; case ID_FORWARD: dwAction = OENA_FORWARD; break; case ID_FORWARD_AS_ATTACH: dwAction = OENA_FORWARDBYATTACH; break; default: AssertSz(dwAction, "We are about to create a note with no action."); break; }; AssertSz(m_pMsgSite, "We are about to create a note with a null m_pMsgSite."); hr = CreateAndShowNote(dwAction, m_dwNoteCreateFlags, NULL, m_hwnd, m_punkPump, &rc, m_pMsgSite); if (SUCCEEDED(hr)) { // Since the new note has this site now, I don't need to keep track of it. // More importantly, if I do, I break the new note since I will try to // close the msgsite on my destroy notification. If I haven't released it, // I would then null out items in SafeRelease(m_pMsgSite); PostMessage(m_hwnd, WM_OE_DESTROYNOTE, 0, 0); } else if (m_fReadNote && (MAPI_E_USER_CANCEL != hr)) AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrReplyForward), NULL, MB_OK); return S_OK; } case ID_HELP_CONTENTS: OEHtmlHelp(GetParent(m_hwnd), c_szMailHelpFileHTML, HH_DISPLAY_TOPIC, (DWORD_PTR) (LPCSTR) c_szCtxHelpDefault); return S_OK; case ID_README: DoReadme(m_hwnd); break; case ID_SEND_OBJECTS: m_fPackageImages = !m_fPackageImages; return S_OK; case ID_NEW_CONTACT: #if 0 Assert(g_pABInit); if (g_pABInit) g_pABInit->NewContact( m_hwnd ); #endif nyi("New contact"); return S_OK; case ID_NOTE_SAVE_AS: SaveMessageAs(); return S_OK; case ID_CHECK_NAMES: HeaderExecCommand(MSOEENVCMDID_CHECKNAMES, MSOCMDEXECOPT_PROMPTUSER, NULL); return S_OK; case ID_SELECT_RECIPIENTS: HeaderExecCommand(MSOEENVCMDID_SELECTRECIPIENTS, MSOCMDEXECOPT_DODEFAULT, NULL); return S_OK; case ID_SELECT_NEWSGROUPS: HeaderExecCommand(MSOEENVCMDID_PICKNEWSGROUPS, MSOCMDEXECOPT_DODEFAULT, NULL); return S_OK; case ID_NEWSGROUPS: HeaderExecCommand(MSOEENVCMDID_PICKNEWSGROUPS, MSOCMDEXECOPT_DODEFAULT, NULL); return S_OK; case ID_ADDRESS_BOOK: HeaderExecCommand(MSOEENVCMDID_VIEWCONTACTS, MSOCMDEXECOPT_DODEFAULT, NULL); return S_OK; case ID_CREATE_RULE_FROM_MESSAGE: { MESSAGEINFO msginfo = {0}; return HrCreateRuleFromMessage(m_hwnd, (FALSE == m_fMail) ? CRFMF_NEWS : CRFMF_MAIL, &msginfo, m_pMsg); } break; case ID_BLOCK_SENDER: { return _HrBlockSender((FALSE == m_fMail) ? RULE_TYPE_NEWS : RULE_TYPE_MAIL, m_pMsg, m_hwnd); } break; case ID_FIND_MESSAGE: DoFindMsg(FOLDERID_ROOT, FOLDER_ROOTNODE); break; case ID_FIND_PEOPLE: { TCHAR szWABExePath[MAX_PATH]; if(S_OK == HrLoadPathWABEXE(szWABExePath, sizeof(szWABExePath))) ShellExecute(NULL, "open", szWABExePath, "/find", "", SW_SHOWNORMAL); break; } case ID_OPTIONS: ShowOptions(m_hwnd, ATHENA_OPTIONS, 0, NULL); break; case ID_ACCOUNTS: { DoAccountListDialog(m_hwnd, m_fMail?ACCT_MAIL:ACCT_NEWS); break; } case ID_ADD_ALL_TO: HeaderExecCommand(MSOEENVCMDID_ADDALLONTO, MSOCMDEXECOPT_DODEFAULT, NULL); break; case ID_ADD_SENDER: if(m_fMail) { if (m_pHdr) m_pHdr->AddRecipient(-1); } else HeaderExecCommand(MSOEENVCMDID_ADDSENDER, MSOCMDEXECOPT_DODEFAULT, NULL); return S_OK; case ID_INSERT_CONTACT_INFO: HeaderExecCommand(MSOEENVCMDID_VCARD, MSOCMDEXECOPT_DODEFAULT, NULL); return S_OK; case ID_FULL_HEADERS: m_fFullHeaders = !m_fFullHeaders; if(m_pHdr) m_pHdr->ShowAdvancedHeaders(m_fFullHeaders); if (m_fMail) SetDwOption((m_fReadNote ? OPT_MAILNOTEADVREAD : OPT_MAILNOTEADVSEND), m_fFullHeaders, NULL, 0); else SetDwOption((m_fReadNote ? OPT_NEWSNOTEADVREAD : OPT_NEWSNOTEADVSEND), m_fFullHeaders, NULL, 0); return S_OK; case ID_CUT: SendMessage(GetFocus(), WM_CUT, 0, 0); return S_OK; case ID_NOTE_COPY: case ID_COPY: SendMessage(GetFocus(), WM_COPY, 0, 0); return S_OK; case ID_PASTE: SendMessage(GetFocus(), WM_PASTE, 0, 0); return S_OK; case ID_SHOW_TOOLBAR: ToggleToolbar(); return S_OK; case ID_CUSTOMIZE: SendMessage(m_hwndToolbar, TB_CUSTOMIZE, 0, 0); break; case ID_FORMATTING_TOOLBAR: ToggleFormatbar(); return S_OK; case ID_STATUS_BAR: ToggleStatusbar(); return S_OK; case ID_UNDO: Edit_Undo(GetFocus()); return S_OK; case ID_SELECT_ALL: Edit_SetSel(GetFocus(), 0, -1); return S_OK; case ID_CLOSE: SendMessage(m_hwnd, WM_CLOSE, 0, 0); return S_OK; case ID_SPELLING: if (FCheckSpellAvail() && (!m_fReadNote)) { HWND hwndFocus = GetFocus(); HRESULT hr; hr = m_pBodyObj2->HrSpellCheck(FALSE); if(FAILED(hr)) AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrSpellGenericSpell), NULL, MB_OK | MB_ICONSTOP); SetFocus(hwndFocus); } return S_OK; case ID_FORMAT_SETTINGS: FormatSettings(); return S_OK; case ID_WORK_OFFLINE: if (g_pConMan) g_pConMan->SetGlobalOffline(!g_pConMan->IsGlobalOffline(), hwndCmd); if (m_pToolbarObj) m_pToolbarObj->Update(); break; case ID_RICH_TEXT: case ID_PLAIN_TEXT: // noops if(id==ID_RICH_TEXT && m_fHtml) return S_OK; if(id==ID_PLAIN_TEXT && !m_fHtml) return S_OK; // if going to plain, warn the user he'll loose formatting... if((ID_PLAIN_TEXT == id) && (IDCANCEL == DoDontShowMeAgainDlg(m_hwnd, c_szDSHtmlToPlain, MAKEINTRESOURCE(idsAthena), MAKEINTRESOURCE(idsWarnHTMLToPlain), MB_OKCANCEL))) return S_OK; m_fHtml=!!(id==ID_RICH_TEXT); m_fFormatbarVisible=!!m_fHtml; m_pBodyObj2->HrSetStyle(m_fHtml ? MESTYLE_FORMATBAR : MESTYLE_NOHEADER); m_pBodyObj2->HrEnableHTMLMode(m_fHtml); // if going into plain-mode blow away formatting if (!m_fHtml) m_pBodyObj2->HrDowngradeToPlainText(); return S_OK; case ID_DIGITALLY_SIGN: HeaderExecCommand(MSOEENVCMDID_DIGSIGN, MSOCMDEXECOPT_DODEFAULT, NULL); return S_OK; case ID_ENCRYPT: if(m_pHdr->ForceEncryption(NULL, FALSE) == S_FALSE) HeaderExecCommand(MSOEENVCMDID_ENCRYPT, MSOCMDEXECOPT_DODEFAULT, NULL); return S_OK; case ID_INCLUDE_LABEL: m_fSecurityLabel = !m_fSecurityLabel; CheckAndForceEncryption(); return S_OK; case ID_LABEL_SETTINGS: if(m_pLabel) { if(DialogBoxParamWrapW(g_hLocRes, MAKEINTRESOURCEW(iddSelectLabel), m_hwnd, SecurityLabelsDlgProc, (LPARAM) &m_pLabel) != IDOK) return (S_FALSE); CheckAndForceEncryption(); } return S_OK; case ID_SEC_RECEIPT_REQUEST: m_fSecReceiptRequest = !m_fSecReceiptRequest; break; case ID_FLAG_MESSAGE: m_dwCBMarkType = (!IsFlagged(ARF_FLAGGED)) ? MARK_MESSAGE_FLAGGED : MARK_MESSAGE_UNFLAGGED; MarkMessage(m_dwCBMarkType, APPLY_SPECIFIED); return S_OK; case ID_WATCH_THREAD: m_dwCBMarkType = (!IsFlagged(ARF_WATCH)) ? MARK_MESSAGE_WATCH : MARK_MESSAGE_NORMALTHREAD; MarkMessage(m_dwCBMarkType, APPLY_SPECIFIED); return S_OK; case ID_IGNORE_THREAD: m_dwCBMarkType = (!IsFlagged(ARF_IGNORE)) ? MARK_MESSAGE_IGNORE : MARK_MESSAGE_NORMALTHREAD; MarkMessage(m_dwCBMarkType, APPLY_SPECIFIED); return S_OK; case ID_APPLY_STATIONERY_0: case ID_APPLY_STATIONERY_1: case ID_APPLY_STATIONERY_2: case ID_APPLY_STATIONERY_3: case ID_APPLY_STATIONERY_4: case ID_APPLY_STATIONERY_5: case ID_APPLY_STATIONERY_6: case ID_APPLY_STATIONERY_7: case ID_APPLY_STATIONERY_8: case ID_APPLY_STATIONERY_9: case ID_APPLY_STATIONERY_MORE: case ID_APPLY_STATIONERY_NONE: { AssertSz(m_fHtml, "QueryStatus should have caught this and not let this function run."); HRESULT hr; WCHAR wszBuf[INTERNET_MAX_URL_LENGTH+1]; *wszBuf = 0; switch (id) { case ID_APPLY_STATIONERY_MORE: hr = HrGetMoreStationeryFileName(m_hwnd, wszBuf); break; case ID_APPLY_STATIONERY_NONE: *wszBuf=0; hr = NOERROR; break; default: hr = HrGetStationeryFileName(id - ID_APPLY_STATIONERY_0, wszBuf); if (FAILED(hr)) { AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrStationeryNotFound), NULL, MB_OK | MB_ICONERROR); HrRemoveFromStationeryMRU(wszBuf); } break; } if(m_pBodyObj2 && SUCCEEDED(hr)) { hr = m_pBodyObj2->HrApplyStationery(wszBuf); if(SUCCEEDED(hr)) HrAddToStationeryMRU(wszBuf); } return S_OK; case IDOK: case IDCANCEL: // ignore these return S_OK; case ID_REQUEST_READRCPT: m_pMsgSite->Notify(OEMSN_TOGGLE_READRCPT_REQ); return S_OK; default: if(id>=ID_ADDROBJ_OLE_FIRST && id <=ID_ADDROBJ_OLE_LAST) { DoNoteOleVerb(id-ID_ADDROBJ_OLE_FIRST); return S_OK; } } } } if(wCmd==NHD_SIZECHANGE && id==idcNoteHdr) { DOUTL(8, "CNote::NHD_SIZECHANGE - doing note WMSize"); //header control is requesting a resize WMSize(NULL, NULL, TRUE); return S_OK; } return S_FALSE; } // ************************* BOOL CNote::IsFlagged(DWORD dwFlag) { BOOL fFlagged = FALSE; MESSAGEFLAGS dwCurrFlags = 0; Assert(m_pMsgSite); if (m_pMsgSite) { // Readnote and compose note are the only ones that can be flagged. The others might // be flagged in the store, but since we are replying or forwarding, etc, they can't // be flagged. RAID 37729 if ((m_fReadNote || (OENA_COMPOSE == m_dwNoteAction)) && SUCCEEDED(m_pMsgSite->GetMessageFlags(&dwCurrFlags))) fFlagged = (0 != (dwFlag & dwCurrFlags)); } return fFlagged; } // ************************* void CNote::DeferedLanguageMenu() { HMENU hMenu = m_hMenu; Assert (hMenu); if (!m_hmenuLanguage) { // load global MIME language codepage data InitMultiLanguage(); } else { // Charset chaching mechanism requires us to reconstruct // language menu every time DestroyMenu(m_hmenuLanguage); } m_hmenuLanguage = CreateMimeLanguageMenu(m_fMail, m_fReadNote, CustomGetCPFromCharset(m_hCharset, m_fReadNote)); } // ************************* LRESULT CNote::WMInitMenuPopup(HWND hwnd, HMENU hmenuPopup, UINT uPos) { MENUITEMINFO mii; HMENU hmenuMain; HWND hwndFocus=GetFocus(); DWORD dwFlags=0; BOOL fEnableStyleMenu = FALSE; hmenuMain = m_hMenu; mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_ID | MIIM_SUBMENU; if (hmenuMain == NULL ||!GetMenuItemInfo(hmenuMain, uPos, TRUE, &mii) || mii.hSubMenu != hmenuPopup) { if (GetMenuItemInfo(hmenuMain, ID_POPUP_LANGUAGE_DEFERRED, FALSE, &mii) && mii.hSubMenu == hmenuPopup) { mii.wID=ID_POPUP_LANGUAGE; mii.fMask = MIIM_ID; SetMenuItemInfo(hmenuMain, ID_POPUP_LANGUAGE_DEFERRED, FALSE, &mii); } mii.fMask = MIIM_ID | MIIM_SUBMENU; if (GetMenuItemInfo(hmenuMain, ID_POPUP_LANGUAGE, FALSE, &mii) && mii.hSubMenu == hmenuPopup) { DeferedLanguageMenu(); mii.fMask = MIIM_SUBMENU; mii.wID=ID_POPUP_LANGUAGE; hmenuPopup = mii.hSubMenu = m_hmenuLanguage; SetMenuItemInfo(hmenuMain, ID_POPUP_LANGUAGE, FALSE, &mii); } else return 1; } switch (mii.wID) { case ID_POPUP_FILE: case ID_POPUP_EDIT: case ID_POPUP_VIEW: break; case ID_POPUP_INSERT: InitSigPopupMenu(hmenuPopup, NULL); break; case ID_POPUP_FORMAT: { AddStationeryMenu(hmenuPopup, ID_POPUP_STATIONERY, ID_APPLY_STATIONERY_0, ID_APPLY_STATIONERY_MORE); fEnableStyleMenu = TRUE; break; } case ID_POPUP_TOOLS: if (m_fMail) { DeleteMenu(hmenuPopup, ID_SELECT_NEWSGROUPS, MF_BYCOMMAND); #ifdef SMIME_V3 if (!FPresentPolicyRegInfo()) { DeleteMenu(hmenuPopup, ID_INCLUDE_LABEL, MF_BYCOMMAND); DeleteMenu(hmenuPopup, ID_LABEL_SETTINGS, MF_BYCOMMAND); m_fSecurityLabel = FALSE; } if(!IsSMIME3Supported()) { DeleteMenu(hmenuPopup, ID_SEC_RECEIPT_REQUEST, MF_BYCOMMAND); m_fSecReceiptRequest = FALSE; } #endif } else { DeleteMenu(hmenuPopup, ID_REQUEST_READRCPT, MF_BYCOMMAND); #ifdef SMIME_V3 DeleteMenu(hmenuPopup, ID_INCLUDE_LABEL, MF_BYCOMMAND); DeleteMenu(hmenuPopup, ID_LABEL_SETTINGS, MF_BYCOMMAND); DeleteMenu(hmenuPopup, ID_SEC_RECEIPT_REQUEST, MF_BYCOMMAND); m_fSecurityLabel = FALSE; m_fSecReceiptRequest = FALSE; #endif } if (GetMenuItemInfo(hmenuPopup, ID_POPUP_ADDRESS_BOOK, FALSE, &mii)) m_pHdr->UpdateRecipientMenu(mii.hSubMenu); break; case ID_POPUP_MESSAGE: { AddStationeryMenu(hmenuPopup, ID_POPUP_NEW_MSG, ID_STATIONERY_RECENT_0, ID_STATIONERY_MORE); break; } case ID_POPUP_LANGUAGE: { if (m_pBodyObj2) m_pBodyObj2->HrOnInitMenuPopup(hmenuPopup, ID_POPUP_LANGUAGE); break; } } MenuUtil_EnablePopupMenu(hmenuPopup, this); if (fEnableStyleMenu) { if (m_pBodyObj2) m_pBodyObj2->UpdateBackAndStyleMenus(hmenuPopup); } return S_OK; } // ************************* void CNote::RemoveNewMailIcon(void) { HRESULT hr; FOLDERINFO fiFolderInfo; FOLDERID idFolder; // If a message is marked (read or deleted) and it's from the Inbox, // remove the new mail notification icon from the tray if (NULL == g_pInstance || NULL == m_pMsgSite || NULL == g_pStore) return; hr = m_pMsgSite->GetFolderID(&idFolder); if (FAILED(hr)) return; hr = g_pStore->GetFolderInfo(idFolder, &fiFolderInfo); if (SUCCEEDED(hr)) { if (FOLDER_INBOX == fiFolderInfo.tySpecial) g_pInstance->UpdateTrayIcon(TRAYICONACTION_REMOVE); g_pStore->FreeRecord(&fiFolderInfo); } } // ************************* LRESULT CNote::OnInitMenuPopup(HWND hwnd, HMENU hmenuPopup, UINT uPos, UINT wID) { return 0; } // ************************* void CNote::WMGetMinMaxInfo(LPMINMAXINFO pmmi) { MINMAXINFO mmi={0}; RECT rc; int cy; ULONG cyAttMan=0; HWND hwnd; cy=GetRequiredHdrHeight(); Assert(IsWindow(m_hwndToolbar)); if(IsWindowVisible(m_hwndToolbar)) { GetWindowRect(m_hwndToolbar, &rc); cy += cyRect(rc); } cy += GetSystemMetrics(SM_CYCAPTION); cy += GetSystemMetrics(SM_CYMENU); cy += 2*cyMinEdit; pmmi->ptMinTrackSize.x=200; //hack pmmi->ptMinTrackSize.y=cy; } // ************************* INT CNote::GetRequiredHdrHeight() { RECT rc={0}; if(m_pHdr) m_pHdr->GetRect(&rc); return cyRect(rc); } // ************************* LONG CNote::lTestHook(UINT uMsg, WPARAM wParam, LPARAM lParam) { return 0; } // ************************* void CNote::WMNotify(int idFrom, NMHDR *pnmh) { switch(pnmh->code) { case NM_SETFOCUS: if (pnmh) OnSetFocus(pnmh->hwndFrom); break; case NM_KILLFOCUS: OnKillFocus(); break; case BDN_DOWNLOADCOMPLETE: OnDocumentReady(); break; case BDN_MARKASSECURE: MarkMessage(MARK_MESSAGE_NOSECUI, APPLY_SPECIFIED); break; case TBN_DROPDOWN: OnDropDown(m_hwnd, pnmh); break; } } // ************************* void CNote::OnDocumentReady() { if (!m_fOnDocReadyHandled && m_fCompleteMsg) { HRESULT hr; DWORD dwStatusFlags; m_fOnDocReadyHandled = TRUE; m_pMsgSite->GetStatusFlags(&dwStatusFlags); // once, we've got a successfull download, we can init the attachment manager. // we can't do this before, as we have to wait until Trident has requested MHTML parts so we // can mark them as inlined. If we're in a reply or reply all then we have to remove the unused // attachments at this time if (IsReplyNote()) HrRemoveAttachments(m_pMsg, FALSE); // #62618: hack. if forwarding a multi/altern in (force) plain-text mode then the html part // shows up as an attachment // we call GetTextBody here on the html body if we're a plaintext node in forward so that // PID_ATT_RENDERED is set before we load teh attachment well if (m_dwNoteAction == OENA_FORWARD && m_fHtml == FALSE) { HBODY hBody; IStream *pstm; if (m_pMsg && !FAILED(m_pMsg->GetTextBody(TXT_HTML, IET_DECODED, &pstm, NULL))) pstm->Release(); } if (m_pHdr) { if (FAILED(m_pHdr->OnDocumentReady(m_pMsg))) AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrAttmanLoadFail), NULL, MB_OK|MB_ICONEXCLAMATION); m_pHdr->SetVCard((OEMSF_FROM_MSG|OEMSF_VIRGIN) & dwStatusFlags); } ClearDirtyFlag(); // RAID-25300 - FE-J:Athena: Newsgroup article and mail sent with charset=_autodetect // Internet Encoded and Windows Encoding are CPI_AUTODETECT { INETCSETINFO CsetInfo ; HCHARSET hCharset = NULL ; int nIdm = 0 ; // if it is a new message, check if charset equals to default charset if ((OENA_COMPOSE == m_dwNoteAction) && (OEMSF_VIRGIN & dwStatusFlags)) { // defer default charset reading until now .. if (g_hDefaultCharsetForMail==NULL) ReadSendMailDefaultCharset(); if (m_hCharset != g_hDefaultCharsetForMail ) hCharset = g_hDefaultCharsetForMail ; // get CharsetInfo from HCHARSET if ( hCharset) MimeOleGetCharsetInfo(hCharset,&CsetInfo); else MimeOleGetCharsetInfo(m_hCharset,&CsetInfo); } else // get CharsetInfo from HCHARSET MimeOleGetCharsetInfo(m_hCharset,&CsetInfo); // re-map CP_JAUTODETECT and CP_KAUTODETECT if necessary // re-map iso-2022-jp to default charset if they are in the same category if (!m_fReadNote) { hCharset = GetMimeCharsetFromCodePage(GetMapCP(CsetInfo.cpiInternet, FALSE)); } else { VARIANTARG va; va.vt = VT_BOOL; va.boolVal = VARIANT_TRUE; m_pCmdTargetBody->Exec(&CMDSETID_MimeEdit, MECMDID_TABLINKS, 0, &va, NULL); } // has a new charset defined, change it ChangeCharset(hCharset); // if user want's auto complete, enable it once we're fully loaded if (DwGetOption(OPT_USEAUTOCOMPLETE)) HeaderExecCommand(MSOEENVCMDID_AUTOCOMPLETE, MSOCMDEXECOPT_DODEFAULT, NULL); if (m_fReadNote && m_fMail && m_pMsgSite) { if(m_pMsgSite->Notify(OEMSN_PROCESS_READRCPT_REQ) != S_OK) return; } } if(DwGetOption(OPT_RTL_MSG_DIR) && ((m_dwNoteAction == OENA_FORWARDBYATTACH) || (OEMSF_VIRGIN & dwStatusFlags))) { if(FAILED(m_pCmdTargetBody->Exec(&CMDSETID_Forms3, IDM_DIRRTL, OLECMDEXECOPT_DODEFAULT, NULL, NULL))) AthMessageBoxW(g_hwndInit, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrRTLDirFailed), NULL, MB_OK); } EnterCriticalSection(&m_csNoteState); if(m_nisNoteState == NIS_INIT) m_nisNoteState = NIS_NORMAL; LeaveCriticalSection(&m_csNoteState); } } HRESULT CNote::ChangeCharset(HCHARSET hCharset) { HRESULT hr = S_OK; if (hCharset && (hCharset != m_hCharset)) { Assert(m_pBodyObj2); IF_FAILEXIT(hr = m_pBodyObj2->HrSetCharset(hCharset)); // set the new charset into the message and call HrLanguageChange to update the headers m_hCharset = hCharset; if (m_pMsg) m_pMsg->SetCharset(hCharset, CSET_APPLY_ALL); if (m_pHdr) m_pHdr->ChangeLanguage(m_pMsg); UpdateTitle(); } exit: return hr; } HRESULT CNote::GetCharset(HCHARSET *phCharset) { Assert(phCharset); *phCharset = m_hCharset; return S_OK; } // ************************* LRESULT CNote::OnDropDown(HWND hwnd, LPNMHDR lpnmh) { UINT i; HMENU hMenuPopup; RECT rc; DWORD dwCmd; TBNOTIFY *ptbn = (TBNOTIFY *)lpnmh; if (ptbn->iItem == ID_SET_PRIORITY) { hMenuPopup = LoadPopupMenu(IDR_PRIORITY_POPUP); if (hMenuPopup != NULL) { for (i = 0; i < 3; i++) CheckMenuItem(hMenuPopup, i, MF_UNCHECKED | MF_BYPOSITION); m_pHdr->GetPriority(&i); Assert(i != priNone); CheckMenuItem(hMenuPopup, 2 - i, MF_CHECKED | MF_BYPOSITION); DoToolbarDropdown(hwnd, lpnmh, hMenuPopup); DestroyMenu(hMenuPopup); } } else if (ptbn->iItem == ID_INSERT_SIGNATURE) { hMenuPopup = CreatePopupMenu(); if (hMenuPopup != NULL) { FillSignatureMenu(hMenuPopup, NULL); DoToolbarDropdown(hwnd, lpnmh, hMenuPopup); DestroyMenu(hMenuPopup); } } else if(ptbn->iItem == ID_POPUP_LANGUAGE) { DeferedLanguageMenu(); hMenuPopup = m_hmenuLanguage; if(hMenuPopup) { MenuUtil_EnablePopupMenu(hMenuPopup, this); DoToolbarDropdown(hwnd, lpnmh, hMenuPopup); } } return(TBDDRET_DEFAULT); } // ************************* void CNote::UpdateMsgOptions(LPMIMEMESSAGE pMsg) { // Store the options onto the message object SideAssert(SUCCEEDED(HrSetMailOptionsOnMessage(pMsg, &m_rHtmlOpt, &m_rPlainOpt, m_hCharset, m_fHtml))); } // ************************* HRESULT CNote::SetComposeStationery() { LPSTREAM pstm; WCHAR wszFile[MAX_PATH]; HRESULT hr=E_FAIL; HCHARSET hCharset; ENCODINGTYPE ietEncoding = IET_DECODED; BOOL fLittleEndian; AssertSz(m_fHtml, "Are you sure you want to set stationery in plain-text mode??"); if (!(m_dwNoteCreateFlags & OENCF_NOSTATIONERY) && m_pMsg && DwGetOption(m_fMail?OPT_MAIL_USESTATIONERY:OPT_NEWS_USESTATIONERY) && SUCCEEDED(GetDefaultStationeryName(m_fMail, wszFile))) { if (SUCCEEDED(hr = HrCreateBasedWebPage(wszFile, &pstm))) { if (S_OK == HrIsStreamUnicode(pstm, &fLittleEndian)) { if (SUCCEEDED(MimeOleFindCharset("utf-8", &hCharset))) { m_pMsg->SetCharset(hCharset, CSET_APPLY_ALL); } ietEncoding = IET_UNICODE; } hr = m_pMsg->SetTextBody(TXT_HTML, ietEncoding, NULL, pstm, NULL); pstm->Release(); m_fUseStationeryFonts = TRUE; } } return hr; } // ************************* HRESULT CNote::CycleThroughControls(BOOL fForward) { HRESULT hr = CheckTabStopArrays(); if (SUCCEEDED(hr)) { int index, newIndex; BOOL fFound = FALSE; HWND hCurr = GetFocus(); for (index = 0; index < m_cTabStopCount; index++) if (hCurr == m_pTabStopArray[index]) { fFound = TRUE; break; } newIndex = fFound ? GetNextIndex(index, fForward) : m_iIndexOfBody; if (newIndex == m_iIndexOfBody) m_pBodyObj2->HrUIActivate(TRUE); else SetFocus(m_pTabStopArray[newIndex]); } return hr; } // ************************* HRESULT CNote::CheckTabStopArrays() { HRESULT hr = S_OK; if (m_fTabStopsSet) return S_OK; m_fTabStopsSet = TRUE; HWND *pArray = m_pTabStopArray; int cCount = MAX_HEADER_COMP; hr = m_pHdr->GetTabStopArray(pArray, &cCount); if (FAILED(hr)) goto error; pArray += cCount; m_cTabStopCount = cCount; cCount = MAX_BODY_COMP; hr = m_pBodyObj2->GetTabStopArray(pArray, &cCount); if (FAILED(hr)) goto error; // This assumes that the first in the list returned from m_pBodyObj2-GetTabStopArray // is the Trident window handle. If that changes where it returns more than one // handle, or something else, this simple index scheme won't work m_iIndexOfBody = m_cTabStopCount; pArray += cCount; m_cTabStopCount += cCount; cCount = MAX_ATTMAN_COMP; m_cTabStopCount += cCount; return S_OK; error: m_cTabStopCount = 0; m_fTabStopsSet = FALSE; return hr; } // ************************* int CNote::GetNextIndex(int index, BOOL fForward) { LONG style; int cTotalTested = 0; BOOL fGoodHandleFound; do { if (fForward) { index++; if (index >= m_cTabStopCount) index = 0; } else { // If this is true, other asserts should have fired before now. Assert(m_cTabStopCount > 0); index--; if (index < 0) index = m_cTabStopCount - 1; } style = GetWindowLong(m_pTabStopArray[index], GWL_STYLE); cTotalTested++; fGoodHandleFound = ((0 == (style & WS_DISABLED)) && (style & WS_VISIBLE) && ((style & WS_TABSTOP) || (index == m_iIndexOfBody))); // Trident doesn't mark itself as a tabstop } while (!fGoodHandleFound && (cTotalTested < m_cTabStopCount)); if (cTotalTested >= m_cTabStopCount) index = m_iIndexOfBody; return index; } // ************************* HRESULT CreateAndShowNote(DWORD dwAction, DWORD dwCreateFlags, INIT_MSGSITE_STRUCT *pInitStruct, HWND hwnd, IUnknown *punk, RECT *prc, IOEMsgSite *pMsgSite) { HRESULT hr = S_OK; CNote *pNote = NULL; AssertSz((pMsgSite || pInitStruct), "Should have either a pInitStruct or a pMsgSite..."); // If we are coming from news, we might need to pass off this call to the smapi // client. If we reply or forward a message that was news, pass it off to smapi if ((OENCF_NEWSFIRST & dwCreateFlags) && ((OENA_REPLYTOAUTHOR == dwAction) || (OENA_FORWARD == dwAction) || (OENA_FORWARDBYATTACH == dwAction))) { // fIsDefaultMailConfiged hits the reg, only check for last result if (!FIsDefaultMailConfiged()) { IOEMsgSite *pSite = NULL; CStoreCB *pCB = NULL; //send using smapi if (pInitStruct) { pCB = new CStoreCB; if (!pCB) hr = E_OUTOFMEMORY; if (SUCCEEDED(hr)) hr = pCB->Initialize(hwnd, MAKEINTRESOURCE(idsSendingToOutbox), TRUE); if (SUCCEEDED(hr)) pSite = new COEMsgSite(); if (!pSite) hr = E_OUTOFMEMORY; if (SUCCEEDED(hr)) hr = pSite->Init(pInitStruct); if (SUCCEEDED(hr)) pSite->SetStoreCallback(pCB); } else ReplaceInterface(pSite, pMsgSite); if (pSite) { if (SUCCEEDED(hr)) { IMimeMessage *pMsg = NULL; BOOL fCompleteMsg; HRESULT hres = E_FAIL; DWORD dwMsgFlags = (OENA_FORWARDBYATTACH == dwAction) ? (OEGM_ORIGINAL|OEGM_AS_ATTACH) : NOFLAGS; hr = pSite->GetMessage(&pMsg, &fCompleteMsg, dwMsgFlags, &hres); if (E_PENDING == hr) { AssertSz((pCB && pMsgSite), "Should never get E_PENDING with pMsgSite being NULL"); pCB->Block(); pCB->Close(); hr = pSite->GetMessage(&pMsg, &fCompleteMsg, dwMsgFlags, &hres); } if (pCB) pCB->Close(); if (SUCCEEDED(hr)) { if (SUCCEEDED(hres)) hr = NewsUtil_ReFwdByMapi(hwnd, pMsg, dwAction); pMsg->Release(); } } // Don't want to close the site if it came from another note... if (!pMsgSite) pSite->Close(); pSite->Release(); } ReleaseObj(pCB); // if we succeeded, then we need to tell the creator that we // cancelled the creation through OE and went with the smapi client return (FAILED(hr) ? hr : MAPI_E_USER_CANCEL); } } //We are the default smapi client pNote = new CNote; if (pNote) hr = pNote->Init(dwAction, dwCreateFlags, prc, hwnd, pInitStruct, pMsgSite, punk); else hr = E_OUTOFMEMORY; if (SUCCEEDED(hr)) hr = pNote->Show(); ReleaseObj(pNote); if (FAILED(hr)) AthErrorMessageW(hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrNewsCantOpen), hr); return hr; } // ************************* HRESULT CNote::SaveMessageAs() { HRESULT hr=S_OK; IMimeMessage *pSecMsg=NULL; BOOL fCanbeDurt = !m_fReadNote; PROPVARIANT rVariant; IMimeBody *pBody = NULL; // Raid #25822: we can't just get the message source if it // is a secure message if (m_fReadNote/* && IsSecure(m_pMsg)*/) { // Won't care about these since the user already loaded the message BOOL fCompleteMsg = FALSE; HRESULT tempHr = S_OK; m_pMsgSite->GetMessage(&pSecMsg, &fCompleteMsg, OEGM_ORIGINAL, &tempHr); AssertSz(fCompleteMsg && SUCCEEDED(tempHr), "Shouldn't have reached this point if the load failed now."); } else { hr = CommitChangesInNote(); if (FAILED(hr)) goto error; // if a compose note, set the X-Unsent header if saving to .eml files, and save the props. MimeOleSetBodyPropA(m_pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_XUNSENT), NOFLAGS, "1"); if(IsSecure(m_pMsg)) { if(AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsSaveSecMsgToFolder), NULL, MB_OKCANCEL) == IDCANCEL) goto error; else { rVariant.vt = VT_BOOL; rVariant.boolVal = TRUE; hr = m_pMsg->BindToObject(HBODY_ROOT, IID_IMimeBody, (void **)&pBody); if(SUCCEEDED(hr)) { pBody->SetOption(OID_NOSECURITY_ONSAVE, &rVariant); ReleaseObj(pBody); } fCanbeDurt = FALSE; } } } // SaveMessageToFile displays a failure error. _SetPendingOp(SOT_PUT_MESSAGE); hr = HrSaveMessageToFile(m_hwnd, (pSecMsg ? pSecMsg : m_pMsg), m_pMsg, !m_fMail, fCanbeDurt); if (SUCCEEDED(hr)) _OnComplete(SOT_PUT_MESSAGE, S_OK); else if (E_PENDING == hr) { EnableNote(FALSE); hr = S_OK; } error: ReleaseObj(pSecMsg); return hr; } // ************************* HRESULT CNote::CommitChangesInNote() { LPMIMEMESSAGE pMsg=0; HRESULT hr=S_OK; Assert(m_pMsg); if (!m_fReadNote && !m_fBodyContainsFrames) { if (FAILED(HrCreateMessage(&pMsg))) return E_FAIL; hr = Save(pMsg, 0); if (SUCCEEDED(hr)) ReplaceInterface(m_pMsg, pMsg) pMsg->Release(); } return hr; } // ************************* void CNote::ToggleFormatbar() { m_fFormatbarVisible = !m_fFormatbarVisible; SetDwOption(OPT_SHOW_NOTE_FMTBAR, m_fFormatbarVisible, NULL, 0); m_pBodyObj2->HrSetStyle(m_fFormatbarVisible ? MESTYLE_FORMATBAR : MESTYLE_NOHEADER); } // ************************* void CNote::ToggleStatusbar() { RECT rc; m_fStatusbarVisible = !m_fStatusbarVisible; SetDwOption(OPT_SHOW_NOTE_STATUSBAR, m_fStatusbarVisible, NULL, 0); m_pstatus->ShowStatus(m_fStatusbarVisible); // cause a size GetWindowRect(m_hwnd, &rc); WMSize(rc.right-rc.left, rc.bottom-rc.top, FALSE); } // ************************* HRESULT CNote::ToggleToolbar() { RECT rc; m_fToolbarVisible = !m_fToolbarVisible; if (m_pToolbarObj) m_pToolbarObj->HideToolbar(!m_fToolbarVisible); GetWindowRect(m_hwnd, &rc); // cause a size WMSize(rc.right-rc.left, rc.bottom-rc.top, FALSE); return S_OK; } // ************************* void CNote::FormatSettings() { AssertSz(m_fReadNote, "this is broken for readnote!!!"); if (m_fHtml) FGetHTMLOptions(m_hwnd, &m_rHtmlOpt); else FGetPlainOptions(m_hwnd, &m_rPlainOpt); } // ************************* void CNote::SwitchLanguage(int idm) { HCHARSET hCharset, hOldCharset; HRESULT hr; hCharset = GetMimeCharsetFromMenuID(idm); if (!hCharset || (hCharset == m_hCharset)) return; hOldCharset = m_hCharset; // View|Language in a view does not affect the listview as in v1. It only affect the preview. // the user can change his default charset to get changes in the listview // setcharset on the body object will cause it to refresh with new fonts etc. hr = ChangeCharset(hCharset); if (FAILED(hr)) { AthMessageBoxW( m_hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW((hr == hrIncomplete)?idsViewLangMimeDBBad:idsErrViewLanguage), NULL, MB_OK|MB_ICONEXCLAMATION); goto Exit; } // here after we ask user if he wants to add this change to charset remapping list m_pMsgSite->SwitchLanguage(hOldCharset, hCharset); Exit: return; } // ************************* BOOL CNote::DoProperties() { NOMSGDATA noMsgData; MSGPROP msgProp; UINT pri; TCHAR szSubj[256]; TCHAR szLocation[1024]; LPSTR pszLocation = NULL; WCHAR wszLocation[1024]; BOOL fSucceeded; msgProp.pNoMsgData = &noMsgData; msgProp.hwndParent = m_hwnd; msgProp.type = (m_fMail ? MSGPROPTYPE_MAIL : MSGPROPTYPE_NEWS); msgProp.mpStartPage = MP_GENERAL; msgProp.szFolderName = 0; // This one needs to have special handling msgProp.pSecureMsg = NULL; msgProp.lpWabal = NULL; msgProp.szFolderName = szLocation; *szLocation = 0; m_pMsgSite->GetLocation(wszLocation, ARRAYSIZE(wszLocation)); pszLocation = PszToANSI(CP_ACP, wszLocation); StrCpyN(szLocation, pszLocation, ARRAYSIZE(szLocation)); MemFree(pszLocation); if (m_fReadNote) { msgProp.dwFlags = ARF_RECEIVED; msgProp.pMsg = m_pMsg; msgProp.fSecure = IsSecure(msgProp.pMsg); if (msgProp.fSecure) { BOOL fCompleteMsg = FALSE; HRESULT tempHr = S_OK; m_pMsgSite->GetMessage(&msgProp.pSecureMsg, &fCompleteMsg, OEGM_ORIGINAL, &tempHr); AssertSz(fCompleteMsg && SUCCEEDED(tempHr), "Shouldn't have reached this point if the load failed now."); HrGetWabalFromMsg(msgProp.pMsg, &msgProp.lpWabal); } } else { msgProp.dwFlags = ARF_UNSENT; msgProp.pMsg = NULL; } m_pHdr->GetPriority(&pri); if (pri==priLow) noMsgData.Pri=IMSG_PRI_LOW; else if (pri==priHigh) noMsgData.Pri=IMSG_PRI_HIGH; else noMsgData.Pri=IMSG_PRI_NORMAL; noMsgData.pszFrom = NULL; noMsgData.pszSent = NULL; noMsgData.ulSize = 0; noMsgData.cAttachments = 0; m_pHdr->HrGetAttachCount(&noMsgData.cAttachments); GetWindowText(m_hwnd, szSubj, sizeof(szSubj)/sizeof(TCHAR)); noMsgData.pszSubject = szSubj; msgProp.fFromListView = FALSE; fSucceeded = (S_OK == HrMsgProperties(&msgProp)); ReleaseObj(msgProp.lpWabal); ReleaseObj(msgProp.pSecureMsg); return fSucceeded; } // ************************* HRESULT CNote::HrSendMail(int id) { IImnAccount *pAccount=NULL; ULONG i; BOOL fFound=FALSE; HRESULT hr; BOOL fSendLater = (id == ID_SEND_LATER); VARIANTARG varIn; DWORD dwMsgSiteFlags=0; // Do spell check if needed if (FCheckSpellAvail() && FCheckOnSend()) { HWND hwndFocus=GetFocus(); hr=m_pBodyObj2->HrSpellCheck(TRUE); if (FAILED(hr) || hr==HR_S_SPELLCANCEL) { if (AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsSpellMsgSendOK), NULL, MB_YESNO | MB_ICONEXCLAMATION ) != IDYES) { SetFocus(hwndFocus); return E_FAIL; } } } if (!m_fMail && m_pBodyObj2) { BOOL fEmpty = FALSE; if (SUCCEEDED(m_pBodyObj2->HrIsEmpty(&fEmpty)) && fEmpty) { if (AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsNoTextInNewsPost), NULL, MB_YESNO | MB_ICONEXCLAMATION ) != IDYES) return MAPI_E_USER_CANCEL; } } // During the send, a call to the note save gets made. During // that call, IMimeMessage::Commit gets called. That is a big perf hit. // It turns out that commit will get called a second time anyway. So // set a flag to tell the save not to commit. m_fCommitSave = FALSE; hr = HeaderExecCommand(MSOEENVCMDID_SEND, fSendLater?MSOCMDEXECOPT_DODEFAULT:MSOCMDEXECOPT_DONTPROMPTUSER, NULL); m_fCommitSave = TRUE; // REVIEW: dhaws: I don't think this happens anymore. I think the send call no longer returns the conflict //RAID 8780: This message MIME_S_CHARSET_CONFLICT will get propagated to here. Now change it to an E_FAIL; if (MIME_S_CHARSET_CONFLICT == hr) hr = E_FAIL; if (FAILED(hr)) goto error; if (m_pMsgSite) m_pMsgSite->GetStatusFlags(&dwMsgSiteFlags); // If has been saved, then this note is store based in drafts and // need to delete the draft. if (((OENA_COMPOSE == m_dwNoteAction) || m_fHasBeenSaved) && !(dwMsgSiteFlags & OEMSF_FROM_FAT)) { HRESULT hr; _SetPendingOp(SOT_DELETING_MESSAGES); hr = m_pMsgSite->Delete(DELETE_MESSAGE_NOTRASHCAN | DELETE_MESSAGE_NOPROMPT); if (SUCCEEDED(hr)) { m_fCBDestroyWindow = TRUE; _OnComplete(SOT_DELETING_MESSAGES, S_OK); } else if (E_PENDING == hr) { EnableNote(FALSE); m_fCBDestroyWindow = TRUE; } else { // ~~~ Can we handle this a bit better??? AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrDeleteMsg), NULL, MB_OK); } } // If note is reply or forward, then mark the message as appropriate else if (IsReplyNote() || (OENA_FORWARD == m_dwNoteAction) || (OENA_FORWARDBYATTACH == m_dwNoteAction)) { HRESULT hr; BOOL fForwarded = (OENA_FORWARD == m_dwNoteAction) || (OENA_FORWARDBYATTACH == m_dwNoteAction); // Clear any previous flags so we don't show both, only the most recent m_dwMarkOnReplyForwardState = MORFS_CLEARING; hr = MarkMessage(fForwarded ? MARK_MESSAGE_UNREPLIED : MARK_MESSAGE_UNFORWARDED, APPLY_SPECIFIED); if (FAILED(hr) && (E_PENDING != hr)) { // Even though we have an error, we can still close the note because the send did work. PostMessage(m_hwnd, WM_OE_DESTROYNOTE, 0, 0); m_dwMarkOnReplyForwardState = MORFS_UNKNOWN; } } // Web Page and stationery else PostMessage(m_hwnd, WM_OE_DESTROYNOTE, 0, 0); error: ReleaseObj(pAccount); return hr; } // ************************* HRESULT CNote::QueryService(REFGUID guidService, REFIID riid, LPVOID *ppvObject) { if (IsEqualGUID(guidService, IID_IOEMsgSite) && IsEqualGUID(riid, IID_IOEMsgSite)) { if (!m_pMsgSite) return E_FAIL; *ppvObject = (LPVOID)m_pMsgSite; m_pMsgSite->AddRef(); return S_OK; } return E_NOINTERFACE; } // ************************* HRESULT CNote::MarkMessage(MARK_TYPE dwFlags, APPLYCHILDRENTYPE dwApplyType) { HRESULT hr; // [PaulHi] 6/8/99 We need to restore the pending operation // if the MarkMessage() call fails. STOREOPERATIONTYPE tyPrevOperation = m_OrigOperationType; _SetPendingOp(SOT_SET_MESSAGEFLAGS); hr = m_pMsgSite->MarkMessage(dwFlags, dwApplyType); if (SUCCEEDED(hr)) _OnComplete(SOT_SET_MESSAGEFLAGS, S_OK); else if (E_PENDING == hr) { EnableNote(FALSE); EnterCriticalSection(&m_csNoteState); if(m_nisNoteState == NIS_INIT) m_nisNoteState = NIS_FIXFOCUS; LeaveCriticalSection(&m_csNoteState); hr = S_OK; } else { // Restore previous operation to ensure the note window will be // re-enabled. _SetPendingOp(tyPrevOperation); } return hr; } HRESULT CNote::_SetPendingOp(STOREOPERATIONTYPE tyOperation) { m_OrigOperationType = tyOperation; return S_OK; } void CNote::EnableNote(BOOL fEnable) { Assert (IsWindow(m_hwnd)); m_fInternal = 1; if (fEnable) { if (m_fWindowDisabled) { EnableWindow(m_hwnd, TRUE); if (m_hCursor) { SetCursor(m_hCursor); m_hCursor = 0; } m_fWindowDisabled = FALSE; } } else { if (!m_fWindowDisabled) { m_fWindowDisabled = TRUE; EnableWindow(m_hwnd, FALSE); m_hCursor = HourGlass(); } } m_fInternal = 0; } // ************************* void CNote::SetStatusText(LPSTR szBuf) { if(m_pstatus) m_pstatus->SetStatusText(szBuf); } // ************************* void CNote::SetProgressPct(INT iPct) { // if (m_pstatus) // m_pstatus->SetProgressBarPos(1, iPct, FALSE); } // ************************* HRESULT CNote::GetBorderDW(IUnknown* punkSrc, LPRECT lprectBorder) { GetClientRect(m_hwnd, lprectBorder); DOUTL(4, "CNote::GetBorderDW called returning=%x,%x,%x,%x", lprectBorder->left, lprectBorder->top, lprectBorder->right, lprectBorder->bottom); return S_OK; } // ************************* HRESULT CNote::RequestBorderSpaceDW(IUnknown* punkSrc, LPCBORDERWIDTHS pborderwidths) { DOUTL(4, "CNote::ReqestBorderSpaceST pborderwidths=%x,%x,%x,%x", pborderwidths->left, pborderwidths->top, pborderwidths->right, pborderwidths->bottom); return S_OK; } // ************************* HRESULT CNote::SetBorderSpaceDW(IUnknown* punkSrc, LPCBORDERWIDTHS pborderwidths) { DOUTL(4, "CNote::SetBorderSpaceDW pborderwidths=%x,%x,%x,%x", pborderwidths->left, pborderwidths->top, pborderwidths->right, pborderwidths->bottom); RECT rcNote = {0}; GetClientRect(m_hwnd, &rcNote); //WMSize(cxRect(rcNote), cyRect(rcNote), FALSE); ResizeChildren(cxRect(rcNote), cyRect(rcNote), pborderwidths->top, FALSE); return S_OK; } // ************************* HRESULT CNote::GetWindow(HWND * lphwnd) { *lphwnd = m_hwnd; return (m_hwnd ? S_OK : E_FAIL); } // ************************* BYTE CNote::GetNoteType() { BYTE retval; if (m_fReadNote) retval = m_fMail ? MailReadNoteType : NewsReadNoteType; else retval = m_fMail ? MailSendNoteType : NewsSendNoteType; return retval; } // ************************* HRESULT CNote::IsMenuMessage(MSG *lpmsg) { Assert(m_pToolbarObj); if (m_pToolbarObj) return m_pToolbarObj->IsMenuMessage(lpmsg); else return S_FALSE; } // ************************* HRESULT CNote::EventOccurred(DWORD nCmdID, IMimeMessage *) { switch (nCmdID) { case MEHC_CMD_MARK_AS_READ: RemoveNewMailIcon(); MarkMessage(MARK_MESSAGE_READ, APPLY_SPECIFIED); break; case MEHC_CMD_CONNECT: if (g_pConMan) g_pConMan->SetGlobalOffline(FALSE); ReloadMessageFromSite(TRUE); AssertSz(!m_fCBDestroyWindow, "Shouldn't need to destroy the window..."); break; default: return S_FALSE; } return S_OK; } // ************************* HRESULT CNote::QuerySwitchIdentities() { IImnAccount *pAcct = NULL; DWORD dwServType; HRESULT hr; if (!IsWindowEnabled(m_hwnd)) { Assert(IsWindowVisible(m_hwnd)); return E_PROCESS_CANCELLED_SWITCH; } if (IsDirty() != S_FALSE) { if (FAILED(hr = m_pHdr->HrGetAccountInHeader(&pAcct))) goto fail; if (FAILED(hr = pAcct->GetServerTypes(&dwServType))) goto fail; ReleaseObj(pAcct); pAcct = NULL; SetForegroundWindow(m_hwnd); if (!!(dwServType & SRV_POP3) || !!(dwServType & SRV_NNTP)) { if (!FCanClose()) return E_USER_CANCELLED; } else { // IMAP and HTTPMail would have to remote the note, which they // can't do at this point, so fail the switch until the window is closed. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsCantSaveMsg), MAKEINTRESOURCEW(idsNoteCantSwitchIdentity), NULL, MB_OK | MB_ICONEXCLAMATION); return E_USER_CANCELLED; } } return S_OK; fail: ReleaseObj(pAcct); return E_PROCESS_CANCELLED_SWITCH; } // ************************* HRESULT CNote::SwitchIdentities() { HRESULT hr; if (IsDirty() != S_FALSE) hr = SaveMessage(OESF_FORCE_LOCAL_DRAFT); SendMessage(m_hwnd, WM_CLOSE, 0, 0); return S_OK; } // ************************* HRESULT CNote::IdentityInformationChanged(DWORD dwType) { return S_OK; } // ************************* HRESULT CNote::OnBegin(STOREOPERATIONTYPE tyOperation, STOREOPERATIONINFO *pOpInfo, IOperationCancel *pCancel) { Assert(m_pCancel == NULL); if (NULL != pCancel) { m_pCancel = pCancel; m_pCancel->AddRef(); } return(S_OK); } // ************************* void CNote::ShowErrorScreen(HRESULT hr) { switch (hr) { case IXP_E_NNTP_ARTICLE_FAILED: case STORE_E_EXPIRED: if (m_pBodyObj2) m_pBodyObj2->LoadHtmlErrorPage(c_szErrPage_Expired); break; case HR_E_USER_CANCEL_CONNECT: case HR_E_OFFLINE: if (m_pBodyObj2) m_pBodyObj2->LoadHtmlErrorPage(c_szErrPage_Offline); SetFocus(m_hwnd); break; case STG_E_MEDIUMFULL: if (m_pBodyObj2) m_pBodyObj2->LoadHtmlErrorPage(c_szErrPage_DiskFull); break; case MIME_E_SECURITY_CANTDECRYPT: if (m_pBodyObj2) m_pBodyObj2->LoadHtmlErrorPage(c_szErrPage_SMimeEncrypt); break; #ifdef SMIME_V3 case MIME_E_SECURITY_LABELACCESSDENIED: case MIME_E_SECURITY_LABELACCESSCANCELLED: case MIME_E_SECURITY_LABELCORRUPT: if (m_pBodyObj2) m_pBodyObj2->LoadHtmlErrorPage(c_szErrPage_SMimeLabel); break; #endif // SMIME_V3 case MAPI_E_USER_CANCEL: if (m_pBodyObj2) m_pBodyObj2->LoadHtmlErrorPage(c_szErrPage_DownloadCanceled); break; default: if (m_pBodyObj2) m_pBodyObj2->LoadHtmlErrorPage(c_szErrPage_GenFailure); break; } m_fCompleteMsg = FALSE; } // ************************* HRESULT CNote::OnProgress(STOREOPERATIONTYPE tyOperation, DWORD dwCurrent, DWORD dwMax, LPCSTR pszStatus) { TCHAR szRes[CCHMAX_STRINGRES], szRes2[CCHMAX_STRINGRES], szRes3[CCHMAX_STRINGRES]; MSG msg; if (m_pstatus && pszStatus) m_pstatus->SetStatusText(const_cast(pszStatus)); CallbackCloseTimeout(&m_hTimeout); switch (tyOperation) { case SOT_GET_MESSAGE: if (m_pstatus) { if (0 != dwMax) { if (!m_fProgress) { m_fProgress = TRUE; m_pstatus->ShowProgress(dwMax); } if (m_pstatus) m_pstatus->SetProgress(dwCurrent); if (!pszStatus) { AthLoadString(idsDownloadingArticle, szRes, ARRAYSIZE(szRes)); wnsprintf(szRes2, ARRAYSIZE(szRes2), szRes, (100 * dwCurrent ) / dwMax ); m_pstatus->SetStatusText(szRes2); } } else if (0 != dwCurrent) { // dwCurrent is non-zero, but no max has been specified. // This implies that dwCurrent is a byte count. AthLoadString(idsDownloadArtBytes, szRes, ARRAYSIZE(szRes)); AthFormatSizeK(dwCurrent, szRes2, ARRAYSIZE(szRes2)); wnsprintf(szRes3, ARRAYSIZE(szRes3), szRes, szRes2); m_pstatus->SetStatusText(szRes3); } } break; } return S_OK; } // ************************* HRESULT CNote::OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete, LPSTOREOPERATIONINFO pOpInfo, LPSTOREERROR pErrorInfo) { if ((SOT_PUT_MESSAGE == tyOperation) && SUCCEEDED(hrComplete) && pOpInfo && m_pMsgSite) m_pMsgSite->UpdateCallbackInfo(pOpInfo); // Close any timeout dialog, if present CallbackCloseTimeout(&m_hTimeout); if (m_pstatus) { if (m_fProgress) { m_pstatus->HideProgress(); m_fProgress = FALSE; } m_pstatus->SetStatusText(const_cast(c_szEmpty)); } if (m_pCancel != NULL) { m_pCancel->Release(); m_pCancel = NULL; } PostMessage(m_hwnd, WM_OENOTE_ON_COMPLETE, hrComplete, (DWORD)tyOperation); // This is not a very neat fix. But, at this time it is a safe fix. // Here is the reason why we can't do it any other place. // _OnComplete posts a destroy message to the note window depending on the operation. // To avoid this object from being destroyed before this function returns, the above // message is posted. Since there is no way to pass in the error info through PostMessage, // we will handle this error here. I am not handling other operation types because some // of them do get handled in _OnComplete if (tyOperation == SOT_DELETING_MESSAGES) { // Display an Error on Failures if (FAILED(hrComplete) && hrComplete != HR_E_OFFLINE) { // Call into my swanky utility CallbackDisplayError(m_hwnd, hrComplete, pErrorInfo); } } return S_OK; } // ************************* void CNote::_OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete) { BOOL fExpectedComplete = TRUE; STOREOPERATIONTYPE tyNewOp = SOT_INVALID; m_pMsgSite->OnComplete(tyOperation, hrComplete, &tyNewOp); if ((SOT_INVALID != tyNewOp) && (SOT_INVALID != m_OrigOperationType)) m_OrigOperationType = tyNewOp; if (SUCCEEDED(hrComplete)) { switch (tyOperation) { case SOT_GET_MESSAGE: switch (hrComplete) { case S_OK: ReloadMessageFromSite(); AssertSz(!m_fCBDestroyWindow, "Shouldn't need to destroy the window..."); break; case S_FALSE: // S_FALSE means the operation was canceled ShowErrorScreen(MAPI_E_USER_CANCEL); break; } break; case SOT_PUT_MESSAGE: ClearDirtyFlag(); break; case SOT_DELETING_MESSAGES: if (!m_fCBDestroyWindow && m_fOrgCmdWasDelete) ReloadMessageFromSite(TRUE); m_fOrgCmdWasDelete = FALSE; break; case SOT_COPYMOVE_MESSAGE: if (!m_fCBCopy) ReloadMessageFromSite(); break; case SOT_SET_MESSAGEFLAGS: if ((MARK_MAX != m_dwCBMarkType) && m_pHdr) { m_pHdr->SetFlagState(m_dwCBMarkType); m_dwCBMarkType = MARK_MAX; } if (MORFS_UNKNOWN != m_dwMarkOnReplyForwardState) { if (MORFS_CLEARING == m_dwMarkOnReplyForwardState) { HRESULT hr; BOOL fForwarded = (OENA_FORWARD == m_dwNoteAction) || (OENA_FORWARDBYATTACH == m_dwNoteAction); MARK_TYPE dwMarkType = (fForwarded ? MARK_MESSAGE_FORWARDED : MARK_MESSAGE_REPLIED); m_dwMarkOnReplyForwardState = MORFS_SETTING; hr = MarkMessage(dwMarkType, APPLY_SPECIFIED); if (FAILED(hr) && (E_PENDING != hr)) m_dwMarkOnReplyForwardState = MORFS_UNKNOWN; } else { PostMessage(m_hwnd, WM_OE_DESTROYNOTE, 0, 0); m_dwMarkOnReplyForwardState = MORFS_UNKNOWN; } } // Remove new mail notification icon RemoveNewMailIcon(); break; default: fExpectedComplete = FALSE; break; } } else { switch (tyOperation) { case SOT_GET_MESSAGE: ShowErrorScreen(hrComplete); break; case SOT_PUT_MESSAGE: if (FAILED(hrComplete)) { HRESULT hrTemp; // Can't save to remote server for whatever reason. Save to local Drafts instead // First, inform user of the situation, if special folders SHOULD have worked if (STORE_E_NOREMOTESPECIALFLDR != hrComplete) { AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsForceSaveToLocalDrafts), NULL, MB_OK | MB_ICONEXCLAMATION); } hrTemp = SaveMessage(OESF_FORCE_LOCAL_DRAFT); TraceError(hrTemp); } break; case SOT_SET_MESSAGEFLAGS: if (MORFS_UNKNOWN != m_dwMarkOnReplyForwardState) m_dwMarkOnReplyForwardState = MORFS_UNKNOWN; break; case SOT_DELETING_MESSAGES: m_fOrgCmdWasDelete = FALSE; break; default: fExpectedComplete = FALSE; break; } } // If the original operation was originated from the note, then // we will need to re-enable the note as well as check to see // if we need to close the window. if (tyOperation == m_OrigOperationType) { _SetPendingOp(SOT_INVALID); EnableNote(TRUE); EnterCriticalSection(&m_csNoteState); if ((tyOperation == SOT_SET_MESSAGEFLAGS) && (m_nisNoteState == NIS_FIXFOCUS)) { if(GetForegroundWindow() == m_hwnd) m_pBodyObj2->HrFrameActivate(TRUE); else m_pBodyObj2->HrGetWindow(&m_hwndFocus); m_nisNoteState = NIS_NORMAL; } LeaveCriticalSection(&m_csNoteState); if (!!m_fCBDestroyWindow) { m_fCBDestroyWindow = FALSE; PostMessage(m_hwnd, WM_OE_DESTROYNOTE, 0, 0); } } } // ************************* HRESULT CNote::OnTimeout(LPINETSERVER pServer, LPDWORD pdwTimeout, IXPTYPE ixpServerType) { // Display a timeout dialog return CallbackOnTimeout(pServer, ixpServerType, *pdwTimeout, (ITimeoutCallback *)this, &m_hTimeout); } // ************************* HRESULT CNote::CanConnect(LPCSTR pszAccountId, DWORD dwFlags) { // Call into general CanConnect Utility //return CallbackCanConnect(pszAccountId, m_hwnd, FALSE); //Always TRUE will prompt to go online if we are offline, which is what we want to do. return CallbackCanConnect(pszAccountId, m_hwnd, TRUE); } // ************************* HRESULT CNote::OnLogonPrompt(LPINETSERVER pServer, IXPTYPE ixpServerType) { // Close any timeout dialog, if present CallbackCloseTimeout(&m_hTimeout); // Call into general OnLogonPrompt Utility return CallbackOnLogonPrompt(m_hwnd, pServer, ixpServerType); } // ************************* HRESULT CNote::OnPrompt(HRESULT hrError, LPCTSTR pszText, LPCTSTR pszCaption, UINT uType, INT *piUserResponse) { // Close any timeout dialog, if present CallbackCloseTimeout(&m_hTimeout); // Call into my swanky utility return CallbackOnPrompt(m_hwnd, hrError, pszText, pszCaption, uType, piUserResponse); } // ************************* HRESULT CNote::GetParentWindow(DWORD dwReserved, HWND *phwndParent) { *phwndParent = m_hwnd; return(S_OK); } // ************************* HRESULT CNote::OnTimeoutResponse(TIMEOUTRESPONSE eResponse) { HRESULT hr = S_OK; // Call into general timeout response utility if (NULL != m_pCancel) hr = CallbackOnTimeoutResponse(eResponse, m_pCancel, &m_hTimeout); return hr; } // ************************* HRESULT CNote::CheckCharsetConflict() { return m_fPreventConflictDlg ? S_FALSE : S_OK; }