// This is a part of the Microsoft Foundation Classes C++ library. // Copyright (C) 1992-1998 Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Microsoft Foundation Classes Reference and related // electronic documentation provided with the library. // See these sources for detailed information regarding the // Microsoft Foundation Classes product. #include "stdafx.h" #pragma warning(disable: 4228) #include #pragma warning(default: 4228) #ifdef AFX_MAPI_SEG #pragma code_seg(AFX_MAPI_SEG) #endif #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // MAPI implementation helpers and globals AFX_STATIC_DATA BOOL _afxIsMailAvail = (BOOL)-1; // start out not determined ///////////////////////////////////////////////////////////////////////////// // _AFX_MAIL_STATE class _AFX_MAIL_STATE : public CNoTrackObject { public: HINSTANCE m_hInstMail; // handle to MAPI32.DLL virtual ~_AFX_MAIL_STATE(); }; _AFX_MAIL_STATE::~_AFX_MAIL_STATE() { if (m_hInstMail != NULL) ::FreeLibrary(m_hInstMail); } EXTERN_PROCESS_LOCAL(_AFX_MAIL_STATE, _afxMailState) ///////////////////////////////////////////////////////////////////////////// // CDocument MAPI support void CDocument::OnFileSendMail() { ASSERT_VALID(this); ASSERT(_afxIsMailAvail); // update handler always gets called first CWaitCursor wait; _AFX_MAIL_STATE* pMailState = _afxMailState; if (pMailState->m_hInstMail == NULL) pMailState->m_hInstMail = ::LoadLibraryA("MAPI32.DLL"); if (pMailState->m_hInstMail == NULL) { AfxMessageBox(AFX_IDP_FAILED_MAPI_LOAD); return; } ASSERT(pMailState->m_hInstMail != NULL); ULONG (PASCAL *lpfnSendMail)(ULONG, ULONG, MapiMessage*, FLAGS, ULONG); (FARPROC&)lpfnSendMail = GetProcAddress(pMailState->m_hInstMail, "MAPISendMail"); if (lpfnSendMail == NULL) { AfxMessageBox(AFX_IDP_INVALID_MAPI_DLL); return; } ASSERT(lpfnSendMail != NULL); TCHAR szTempName[_MAX_PATH]; TCHAR szPath[_MAX_PATH]; BOOL bRemoveTemp = FALSE; if (m_strPathName.IsEmpty() || IsModified()) { // save to temporary path VERIFY(GetTempPath(_countof(szPath), szPath) != 0); VERIFY(GetTempFileName(szPath, _T("afx"), 0, szTempName) != 0); // save it, but remember original modified flag BOOL bModified = IsModified(); BOOL bResult = DoSave(szTempName, FALSE); SetModifiedFlag(bModified); if (!bResult) { TRACE0("Warning: file save failed during File.Send Mail.\n"); return; } bRemoveTemp = TRUE; } else { // use actual file since it isn't modified lstrcpyn(szTempName, m_strPathName, _countof(szTempName)); } #ifdef _UNICODE char szTempNameA[_MAX_PATH]; _wcstombsz(szTempNameA, szTempName, _countof(szTempNameA)); #endif // build an appropriate title for the attachment TCHAR szTitle[_MAX_PATH]; if (!m_strPathName.IsEmpty()) AfxGetFileName(m_strPathName, szTitle, _countof(szTitle)); else { lstrcpyn(szTitle, m_strTitle, _countof(szTitle)); if (m_strTitle.Find('.') == -1) // no extension { // append the default suffix if there is one CString strExt; CDocTemplate* pTemplate = GetDocTemplate(); if (pTemplate != NULL && pTemplate->GetDocString(strExt, CDocTemplate::filterExt)) { lstrcat(szTitle, strExt); } } } #ifdef _UNICODE char szTitleA[_MAX_PATH]; _wcstombsz(szTitleA, szTitle, _countof(szTitleA)); #endif // prepare the file description (for the attachment) MapiFileDesc fileDesc; memset(&fileDesc, 0, sizeof(fileDesc)); fileDesc.nPosition = (ULONG)-1; #ifdef _UNICODE fileDesc.lpszPathName = szTempNameA; fileDesc.lpszFileName = szTitleA; #else fileDesc.lpszPathName = szTempName; fileDesc.lpszFileName = szTitle; #endif // prepare the message (empty with 1 attachment) MapiMessage message; memset(&message, 0, sizeof(message)); message.nFileCount = 1; message.lpFiles = &fileDesc; // prepare for modal dialog box AfxGetApp()->EnableModeless(FALSE); HWND hWndTop; CWnd* pParentWnd = CWnd::GetSafeOwner(NULL, &hWndTop); // some extra precautions are required to use MAPISendMail as it // tends to enable the parent window in between dialogs (after // the login dialog, but before the send note dialog). pParentWnd->SetCapture(); ::SetFocus(NULL); pParentWnd->m_nFlags |= WF_STAYDISABLED; int nError = lpfnSendMail(0, (ULONG)pParentWnd->GetSafeHwnd(), &message, MAPI_LOGON_UI|MAPI_DIALOG, 0); // after returning from the MAPISendMail call, the window must // be re-enabled and focus returned to the frame to undo the workaround // done before the MAPI call. ::ReleaseCapture(); pParentWnd->m_nFlags &= ~WF_STAYDISABLED; pParentWnd->EnableWindow(TRUE); ::SetActiveWindow(NULL); pParentWnd->SetActiveWindow(); pParentWnd->SetFocus(); if (hWndTop != NULL) ::EnableWindow(hWndTop, TRUE); AfxGetApp()->EnableModeless(TRUE); if (nError != SUCCESS_SUCCESS && nError != MAPI_USER_ABORT && nError != MAPI_E_LOGIN_FAILURE) { AfxMessageBox(AFX_IDP_FAILED_MAPI_SEND); } // remove temporary file, if temporary file was used if (bRemoveTemp) CFile::Remove(szTempName); } void CDocument::OnUpdateFileSendMail(CCmdUI* pCmdUI) { ASSERT_VALID(this); if (_afxIsMailAvail == (BOOL)-1) { _afxIsMailAvail = ::GetProfileInt(_T("MAIL"), _T("MAPI"), 0) != 0 && SearchPath(NULL, _T("MAPI32.DLL"), NULL, 0, NULL, NULL) != 0; } // enable the Send... menu item if available pCmdUI->Enable(_afxIsMailAvail); CMenu* pMenu = pCmdUI->m_pMenu; if (!_afxIsMailAvail && pMenu != NULL) { // remove the Send... menu and surrounding separators UINT nStateAbove = pMenu->GetMenuState(pCmdUI->m_nIndex-1, MF_BYPOSITION); UINT nStateBelow = pMenu->GetMenuState(pCmdUI->m_nIndex+1, MF_BYPOSITION); pMenu->RemoveMenu(pCmdUI->m_nIndex, MF_BYPOSITION); if (nStateAbove & nStateBelow & MF_SEPARATOR) { // a separator must be removed since the Send... is gone if (nStateAbove != (UINT)-1) pMenu->RemoveMenu(pCmdUI->m_nIndex-1, MF_BYPOSITION); else if (nStateBelow != (UINT)-1) pMenu->RemoveMenu(pCmdUI->m_nIndex, MF_BYPOSITION); } } } ///////////////////////////////////////////////////////////////////////////// // COleDocument MAPI support void COleDocument::OnFileSendMail() { ASSERT_VALID(this); ASSERT(m_bRemember); LPSTORAGE lpOrigStg = m_lpRootStg; m_lpRootStg = NULL; TRY { m_bRemember = FALSE; CDocument::OnFileSendMail(); } CATCH_ALL(e) { m_lpRootStg = lpOrigStg; m_bRemember = TRUE; THROW_LAST(); } END_CATCH_ALL m_lpRootStg = lpOrigStg; m_bRemember = TRUE; } #ifdef AFX_INIT_SEG #pragma code_seg(AFX_INIT_SEG) #endif #pragma warning(disable: 4074) #pragma init_seg(lib) PROCESS_LOCAL(_AFX_MAIL_STATE, _afxMailState) /////////////////////////////////////////////////////////////////////////////