// // SMAPI16.CPP - Simple MAPI implementation, 16bit Version // #include "pch.hxx" #include #include #include #include #include #include ASSERTDATA #define WriteVar2File( hf, v ) _lwrite( (hf), &(v), sizeof(v) ); #define ReadVarFromFile( hf, v ) _lread( (hf), &(v), sizeof(v) ); static const char s_cszMailMsgCmd[] = "msimn.exe /mailmsg:%s"; inline void WriteStr2File( HFILE hFile, LPCSTR cszText ) { UINT uText = ( cszText == NULL ) ? 0 : lstrlen( cszText ) + 1; _lwrite( hFile, &uText, sizeof( uText ) ); if ( uText > 0 ) _lwrite( hFile, cszText, uText ); } inline void WriteMRD2File( HFILE hFile, lpMapiRecipDesc lpMRD ) { WriteVar2File( hFile, lpMRD->ulReserved ); WriteVar2File( hFile, lpMRD->ulRecipClass ); WriteStr2File( hFile, lpMRD->lpszName ); WriteStr2File( hFile, lpMRD->lpszAddress ); WriteVar2File( hFile, lpMRD->ulEIDSize ); _lwrite( hFile, lpMRD->lpEntryID, lpMRD->ulEIDSize ); } inline LPSTR ReadStrFromFile( HFILE hFile ) { UINT uText; LPSTR szText; ReadVarFromFile( hFile, uText ); if ( uText > 0 ) { szText = (LPSTR)malloc( uText ); _lread( hFile, szText, uText ); } else szText = NULL; return( szText ); } inline lpMapiRecipDesc ReadMRDFromFile( HFILE hFile ) { lpMapiRecipDesc lpMRD = new MapiRecipDesc; ReadVarFromFile( hFile, lpMRD->ulReserved ); ReadVarFromFile( hFile, lpMRD->ulRecipClass ); lpMRD->lpszName = ReadStrFromFile( hFile ); lpMRD->lpszAddress = ReadStrFromFile( hFile ); ReadVarFromFile( hFile, lpMRD->ulEIDSize ); if ( lpMRD->ulEIDSize > 0 ) { lpMRD->lpEntryID = malloc( lpMRD->ulEIDSize ); _lread( hFile, lpMRD->lpEntryID, lpMRD->ulEIDSize ); } else lpMRD->lpEntryID = NULL; return( lpMRD ); } inline lpMapiFileDesc ReadMFDFromFile( HFILE hFile ) { lpMapiFileDesc lpMFD = new MapiFileDesc; ReadVarFromFile( hFile, lpMFD->ulReserved ); ReadVarFromFile( hFile, lpMFD->flFlags ); ReadVarFromFile( hFile, lpMFD->nPosition ); lpMFD->lpszPathName = ReadStrFromFile( hFile ); lpMFD->lpszFileName = ReadStrFromFile( hFile ); lpMFD->lpFileType = NULL; return( lpMFD ); } #define FreeMemSafe( lp ) \ if ( (lp) != NULL ) \ { \ free( lp ); \ lp = NULL; \ } inline void FreeMRDSafe( lpMapiRecipDesc &lpMRD ) { if ( lpMRD != NULL ) { FreeMemSafe( lpMRD->lpszName ); FreeMemSafe( lpMRD->lpszAddress ); FreeMemSafe( lpMRD->lpEntryID ); free( lpMRD ); lpMRD = NULL; } } inline void FreeMFDSafe( lpMapiFileDesc &lpMFD ) { if ( lpMFD != NULL ) { FreeMemSafe( lpMFD->lpszPathName ); FreeMemSafe( lpMFD->lpszFileName ); free( lpMFD ); lpMFD = NULL; } } /////////////////////////////////////////////////////////////////////// // // MAPISendMail // /////////////////////////////////////////////////////////////////////// EXTERN_C ULONG STDAPICALLTYPE MAPISENDMAIL( LHANDLE lhSession, // ignored ULONG ulUIParam, lpMapiMessage lpMessage, FLAGS flFlags, ULONG ulReserved ) { // validate parameters if ( NULL == lpMessage || IsBadReadPtr( lpMessage, sizeof( MapiMessage ) ) ) return MAPI_E_INVALID_MESSAGE; // $BUGBUG - We do not support sendmail without UI yet. This is a big // hole that we need to fix. if (!(flFlags & MAPI_DIALOG)) return MAPI_E_NOT_SUPPORTED; // Create Temporary File Storage // char szTmpDir[_MAX_PATH], szTmpFile[_MAX_PATH]; OFSTRUCT of; HFILE hTmp; if ( GetTempPath( _MAX_PATH, szTmpDir ) == 0 ) return( MAPI_E_FAILURE ); if ( GetTempFileName( szTmpDir, "msm", 0, szTmpFile ) == 0 ) return( MAPI_E_FAILURE ); hTmp = OpenFile( szTmpFile, &of, OF_CREATE | OF_WRITE ); if ( hTmp == HFILE_ERROR ) return( MAPI_E_FAILURE ); // lhSession is intentionally ignored because it is impossible to support it WriteVar2File( hTmp, lhSession ); WriteVar2File( hTmp, ulUIParam ); WriteVar2File( hTmp, flFlags ); WriteVar2File( hTmp, ulReserved ); // Write lpMapiMessage into Temporary File // int i; WriteVar2File( hTmp, lpMessage->ulReserved ); WriteStr2File( hTmp, lpMessage->lpszSubject ); WriteStr2File( hTmp, lpMessage->lpszNoteText ); WriteStr2File( hTmp, lpMessage->lpszMessageType ); WriteStr2File( hTmp, lpMessage->lpszDateReceived ); WriteStr2File( hTmp, lpMessage->lpszConversationID ); WriteVar2File( hTmp, lpMessage->flFlags ); WriteVar2File( hTmp, lpMessage->lpOriginator ); if ( lpMessage->lpOriginator != NULL ) WriteMRD2File( hTmp, lpMessage->lpOriginator ); WriteVar2File( hTmp, lpMessage->nRecipCount ); for ( i = 0; i < lpMessage->nRecipCount; i++ ) WriteMRD2File( hTmp, lpMessage->lpRecips+i ); WriteVar2File( hTmp, lpMessage->nFileCount ); for ( i = 0; i < lpMessage->nFileCount; i++ ) { lpMapiFileDesc lpMFD = lpMessage->lpFiles+i; WriteVar2File( hTmp, lpMFD->ulReserved ); WriteVar2File( hTmp, lpMFD->flFlags ); WriteVar2File( hTmp, lpMFD->nPosition ); WriteStr2File( hTmp, lpMFD->lpszPathName ); WriteStr2File( hTmp, lpMFD->lpszFileName ); Assert( lpMFD->lpFileType == NULL ); } #ifdef DEBUG WriteStr2File( hTmp, szTmpFile ); #endif if ( hTmp != NULL && hTmp != HFILE_ERROR ) _lclose( hTmp ); // Execute MSIMN.EXE // char szFmt[256], szCmd[256]; LPSTR szLastDirSep = NULL; if ( GetModuleFileName( g_hInst, szFmt, sizeof( szFmt ) ) == 0 ) return( MAPI_E_FAILURE ); for ( LPSTR szPtr = szFmt; *szPtr != '\0'; szPtr = AnsiNext( szPtr ) ) if ( *szPtr == '\\' ) szLastDirSep = szPtr; if ( szLastDirSep == NULL ) return( MAPI_E_FAILURE ); StrCpyN( szLastDirSep+1, s_cszMailMsgCmd, ARRAYSIZE(szFmt)-(szLastDirSep-szFmt)-1); wnsprintf( szCmd, ARRAYSIZE(szCmd), szFmt, szTmpFile ); return( ( WinExec( szCmd, SW_SHOW ) < 32 ) ? MAPI_E_FAILURE : SUCCESS_SUCCESS ); } HRESULT HandleMailMsg( LPSTR szCmd ) { OFSTRUCT of; HFILE hTmp; ULONG ulRet = MAPI_E_FAILURE; NCINFO nci = { 0 }; LPMIMEMESSAGE pMsg = NULL; LPSTREAM pStream = NULL; LPMIMEADDRESSTABLE pAddrTable = NULL; HRESULT hr; LPSTR szText = NULL; lpMapiRecipDesc lpMRD = NULL; lpMapiFileDesc lpMFD = NULL; ULONG ulTmp; BOOL fBody = FALSE; // Open Tmp File // LPSTR szSpace = strchr( szCmd, ' ' ); if ( szSpace != NULL ) *szSpace = '\0'; hTmp = OpenFile( szCmd, &of, OF_READ ); if ( hTmp == HFILE_ERROR ) goto error; LHANDLE lhSession; ULONG ulUIParam; FLAGS flFlags; ULONG ulReserved; ReadVarFromFile( hTmp, lhSession ); ReadVarFromFile( hTmp, ulUIParam ); ReadVarFromFile( hTmp, flFlags ); ReadVarFromFile( hTmp, ulReserved ); hr = HrCreateMessage( &pMsg ); if ( FAILED( hr ) ) goto error; nci.ntNote = ntSendNote; nci.dwFlags = NCF_SENDIMMEDIATE | NCF_MODAL; nci.pMsg = pMsg; nci.hwndOwner = (HWND)ulUIParam; ReadVarFromFile( hTmp, ulTmp ); // set the subject on the message szText = ReadStrFromFile( hTmp ); if ( szText != NULL ) { hr = MimeOleSetBodyPropA( pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_SUBJECT), NOFLAGS, szText ); if ( FAILED( hr ) ) goto error; FreeMemSafe( szText ); } // set the body on the message szText = ReadStrFromFile( hTmp ); if ( szText != NULL ) { if ( szText[0] != '\0' ) { fBody = TRUE; hr = MimeOleCreateVirtualStream( &pStream ); if ( FAILED( hr ) ) goto error; hr = pStream->Write( szText, lstrlen( szText ), NULL ); if ( FAILED( hr ) ) goto error; hr = pMsg->SetTextBody( TXT_PLAIN, IET_DECODED, NULL, pStream, NULL ); if ( FAILED( hr ) ) goto error; } FreeMemSafe( szText ); } // ignore lpMessage->lpszMessageType szText = ReadStrFromFile( hTmp ); FreeMemSafe( szText ); // ignore lpMessage->lpszDateReceived szText = ReadStrFromFile( hTmp ); FreeMemSafe( szText ); // ignore lpMessage->lpszConversationID szText = ReadStrFromFile( hTmp ); FreeMemSafe( szText ); // ignore lpMessage->flFlags ReadVarFromFile( hTmp, ulTmp ); // ignore lpMessage->lpOriginator lpMRD = ReadMRDFromFile( hTmp ); FreeMRDSafe( lpMRD ); // set the recipients on the message ReadVarFromFile( hTmp, ulTmp ); if ( ulTmp > 0 ) { hr = pMsg->GetAddressTable( &pAddrTable ); if ( FAILED( hr ) ) goto error; for ( ULONG i = 0; i < ulTmp; i++ ) { lpMRD = ReadMRDFromFile( hTmp ); hr = pAddrTable->Append( MapiRecipToMimeOle( lpMRD->ulRecipClass ), IET_DECODED, lpMRD->lpszName, lpMRD->lpszAddress, NULL ); if ( FAILED( hr ) ) goto error; FreeMRDSafe( lpMRD ); } } // set the attachments on the message ReadVarFromFile( hTmp, ulTmp ); if ( ulTmp > 0 ) { lpMFD = ReadMFDFromFile( hTmp ); // special case: no body & one .HTM file - inline the HTML if ( fBody && ulTmp == 1 && ( ( lpMFD->flFlags & ( MAPI_OLE | MAPI_OLE_STATIC ) ) == 0 ) && FIsHTMLFile( lpMFD->lpszPathName ) ) { Assert( pStream == NULL ); hr = CreateStreamOnHFile( lpMFD->lpszPathName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL, &pStream ); if ( FAILED( hr ) ) goto error; hr = pMsg->SetTextBody( TXT_HTML, IET_DECODED, NULL, pStream, NULL ); if ( FAILED( hr ) ) goto error; nci.ntNote = ntWebPage; } else { for ( ULONG i = 0; i < ulTmp; i++ ) { if ( i > 0 ) { FreeMFDSafe( lpMFD ); lpMFD = ReadMFDFromFile( hTmp ); } // $BUGBUG - should we error this out, or send anyway? if ( lpMFD->flFlags & MAPI_OLE ) continue; if ( lpMFD->lpszPathName != NULL && lpMFD->lpszPathName[0] != '\0' ) { hr = pMsg->AttachFile( lpMFD->lpszPathName, NULL, NULL ); if ( FAILED( hr ) ) goto error; } } FreeMFDSafe( lpMFD ); } } #ifdef DEBUG { LPSTR szTmpFile = ReadStrFromFile( hTmp ); free( szTmpFile ); } #endif // this is redundant, but need to close file before opening Note window if ( hTmp != NULL && hTmp != HFILE_ERROR ) { _lclose( hTmp ); hTmp = NULL; } if ( Initialize_RunDLL( TRUE ) ) { hr = HrCreateNote( &nci ); if ( SUCCEEDED( hr ) ) ulRet = SUCCESS_SUCCESS; Uninitialize_RunDLL(); } error: if ( hTmp != NULL && hTmp != HFILE_ERROR ) _lclose( hTmp ); OpenFile( szCmd, &of, OF_DELETE ); FreeMemSafe( szText ); FreeMRDSafe( lpMRD ); FreeMFDSafe( lpMFD ); if ( pMsg ) pMsg->Release(); if ( pAddrTable ) pAddrTable->Release(); if ( pStream ) pStream->Release(); if ( FAILED( ulRet ) ) AthMessageBoxW( GetDesktopWindow(), MAKEINTRESOURCEW( idsAthenaMail ), MAKEINTRESOURCEW( idsMailRundllFailed ), 0, MB_ICONEXCLAMATION | MB_OK ); return( ulRet ); }