📄 outlookextension.cpp
字号:
// OutlookExtension
// Copyright Ric Vieler, 2006
// Filter Outlook email
#include "stdafx.h"
#include <STDIO.h>
#include <WINDOWS.H>
#include <COMMCTRL.H>
#define MIDL_PASS
#include <MAPIX.H>
#include <MAPIUTIL.H>
#include <MAPIFORM.H>
#include <INITGUID.h>
#include "EXCHEXT.H"
#include "OutlookExtension.h"
// Microsoft Exchange Client Extension entry point
extern "C" _declspec(dllexport) LPEXCHEXT CALLBACK ExchEntryPoint(void);
// DLL entry point
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved )
{
return TRUE;
}
// Must provide pointer to CClientExtension for construction
CMessageEvents::CMessageEvents (LPUNKNOWN pParentInterface)
{
m_pExchExt = pParentInterface;
m_submittingMessage = false;
m_referenceCount = 0;
};
void CMessageEvents::LogContent( char* content, int contentType )
{
// Put content into one big file for this example
char buffer[ MAX_PATH ];
size_t contentLength;
FILE* sourceFile;
FILE* destinationFile;
// open the destination file - LN_LOG_FILE
strcpy( buffer, OL_LOG_FILE );
if( (destinationFile = fopen( buffer, "a+b" )) != NULL )
{
if( contentType == OL_LOG_ATTACHMENT )
{
// content is a filename
if( (sourceFile = fopen( content, "r" )) != NULL )
{
// write header
fwrite( "ATTACHMENT:\n", sizeof(char), 12, destinationFile );
// write attachment
do
{
contentLength = fread( buffer, sizeof(char), MAX_PATH, sourceFile );
if( contentLength )
{
fwrite( buffer, sizeof(char), contentLength, destinationFile );
}
} while( contentLength == MAX_PATH );
// write footer
fwrite( "\n", sizeof( char ), 1, destinationFile );
fclose( sourceFile );
}
}
else
{
// content is a string
// write header
if( contentType == OL_LOG_BODY )
{
fwrite( "BODY:\n", sizeof(char), 6, destinationFile );
}
else
{
fwrite( "DESTINATION(S):\n", sizeof(char), 16, destinationFile );
}
// write data
contentLength = strlen( content );
fwrite( content, sizeof( char ), contentLength, destinationFile );
// write footer
fwrite( "\n\n", sizeof( char ), 2, destinationFile );
}
fclose( destinationFile );
}
}
// Log message body
void CMessageEvents::LogBody( LPMESSAGE pMessage )
{
char* bodybuf = 0;
unsigned int bodysize = 0;
IStream* stream;
HRESULT hr;
// Get body of message as a stream
hr = pMessage->OpenProperty(PR_BODY,
&IID_IStream,
STGM_DIRECT | STGM_READ,
0,
(IUnknown**)&stream );
if ( !FAILED(hr) )
{
// Get size of stream
STATSTG status = { 0 };
hr = stream->Stat( &status, STATFLAG_NONAME );
if ( !FAILED(hr) )
{
// Read the stream into a local buffer
bodysize = status.cbSize.LowPart;
bodybuf = new char[ bodysize + 1 ];
ULONG count;
hr = stream->Read( bodybuf, bodysize, &count );
if ( !FAILED(hr) )
{
if ( count < bodysize)
bodysize = count;
bodybuf[bodysize] = 0;
stream->Release();
// Log the content
LogContent( bodybuf, OL_LOG_BODY );
}
}
}
}
// Log message attachments
void CMessageEvents::LogAttachments( LPMESSAGE pMessage )
{
HRESULT hr;
LPMAPITABLE pAttachmentTable;
LPATTACH pAttachment;
// Get the attachment table
hr = pMessage->GetAttachmentTable( MAPI_UNICODE, &pAttachmentTable );
if ( !FAILED(hr) )
{
SizedSPropTagArray(1,columns) = { 1, PR_ATTACH_NUM };
SRowSet* pRowSet;
hr = HrQueryAllRows( pAttachmentTable,
(SPropTagArray*)&columns,
NULL, NULL, 0, &pRowSet);
if ( !FAILED(hr) )
{
for (unsigned int row = 0; row < pRowSet->cRows; row++ )
{
if (pRowSet->aRow[row].lpProps[0].ulPropTag == PR_ATTACH_NUM )
{
// Open the attachment
hr = pMessage->OpenAttach(pRowSet->aRow[row].lpProps[0].Value.ul,
NULL,
MAPI_BEST_ACCESS,
&pAttachment );
if ( !FAILED(hr) )
{
// Get the attachment type
ULONG count;
SPropValue* property = 0;
SizedSPropTagArray(1, tag) = { 1, PR_ATTACH_METHOD };
pAttachment->GetProps((SPropTagArray*)&tag,
MAPI_UNICODE,
&count,
&property);
// Process attachment based on attachment type
if( (property[0].ulPropTag) &&
(property[0].Value.ul == ATTACH_BY_REF_ONLY ||
property[0].Value.ul == ATTACH_BY_REF_RESOLVE ||
property[0].Value.ul == ATTACH_BY_REFERENCE ))
{
// Attachment is by filename
ULONG count;
SPropValue* path = 0;
SizedSPropTagArray(2, tag) =
{ 2, { PR_ATTACH_LONG_PATHNAME,PR_ATTACH_PATHNAME } };
pAttachment->GetProps((SPropTagArray*)&tag,
MAPI_UNICODE,
&count,
&path);
if( path[0].ulPropTag == PR_ATTACH_LONG_PATHNAME )
{
LogContent( path[0].Value.LPSZ, OL_LOG_ATTACHMENT );
}
else if( path[1].ulPropTag == PR_ATTACH_PATHNAME )
{
LogContent( path[1].Value.LPSZ, OL_LOG_ATTACHMENT );
}
}
else if(property[0].ulPropTag &&
property[0].Value.ul == ATTACH_BY_VALUE)
{
// Attachment is in memory
// Convert it to a temp file
char tempFile[20];
strcpy( tempFile, OL_TEMP_LOG_FILE );
STATSTG StatInfo;
LPSTREAM pSourceStream = NULL;
LPSTREAM pDestinationStream = NULL;
hr = pAttachment->OpenProperty(PR_ATTACH_DATA_BIN,
(LPIID)&IID_IStream,
0,
MAPI_MODIFY,
(LPUNKNOWN*)&pSourceStream);
if ( !FAILED(hr) )
{
hr = OpenStreamOnFile(
MAPIAllocateBuffer,
MAPIFreeBuffer,
STGM_CREATE | STGM_READWRITE | STGM_SHARE_DENY_NONE | STGM_DELETEONRELEASE,
tempFile,
NULL,
&pDestinationStream);
if ( !FAILED(hr) )
{
// Get size of Source Stream
pSourceStream->Stat(&StatInfo, STATFLAG_NONAME);
// Write the stream to the temp file
hr = pSourceStream->CopyTo(pDestinationStream,
StatInfo.cbSize, NULL, NULL);
if ( !FAILED(hr) )
{
// Commit changes to new stream
pSourceStream->Commit(0);
// Log the attachment
LogContent( tempFile, OL_LOG_ATTACHMENT );
// Release the streams
// This should also delete the temp file
pDestinationStream->Release();
pSourceStream->Release();
}
}
}
}
// Release the attachment
pAttachment->Release();
}
}
}
FreeProws( pRowSet );
}
pAttachmentTable->Release();
}
}
// Delete a MAPI message
// Called by CMessageEvents::OnWriteComplete before returning S_OK
void CMessageEvents::DeleteMessage( LPMESSAGE pMessage )
{
HRESULT hr;
// Remove the recipients
LPMAPITABLE pRecipientTable;
hr = pMessage->GetRecipientTable( MAPI_UNICODE, &pRecipientTable );
if ( !FAILED(hr) )
{
// Need PR_ROWID for ModifyRecipients
SizedSPropTagArray(1,columns) = { 1, PR_ROWID };
SRowSet* pRowSet;
hr = HrQueryAllRows( pRecipientTable,
(SPropTagArray*)&columns,
NULL, NULL, 0, &pRowSet);
if ( !FAILED(hr) )
{
pMessage->ModifyRecipients( MODRECIP_REMOVE, (ADRLIST*)pRowSet );
FreeProws( pRowSet );
}
pRecipientTable->Release();
}
// Set PR_DELETE_AFTER_SUBMIT
ULONG count;
SPropValue* property = 0;
SizedSPropTagArray(1, tag) = { 1, PR_DELETE_AFTER_SUBMIT };
if( pMessage->GetProps((SPropTagArray*)&tag,
NULL,
&count,
&property) == S_OK )
{
if( property[0].ulPropTag == PR_DELETE_AFTER_SUBMIT )
{
property[0].Value.b = TRUE;
pMessage->SetProps( 1, property, NULL );
}
}
}
///////////////////////////////////////////////////////////////////////////////
// CMessageEvents::QueryInterface()
//
// Parameters
// riid -- Interface ID.
// ppvObj -- address of interface object pointer.
//
// Purpose
// Return interface object upon request
//
// Return Value - none
//
// Comments
// Currently the Exchange client does not call QueryInterface from any object
// except for IExchExt. This is implemented in case features are added to
// Exchange to require QueryInterface from any object. Also, as a "rule of
// OLE COM" this is the proper implementation of QueryInterface.
//
STDMETHODIMP CMessageEvents::QueryInterface(REFIID riid, LPVOID FAR * ppvObj)
{
*ppvObj = NULL;
if (riid == IID_IExchExtMessageEvents)
{
*ppvObj = (LPVOID)this;
// Increase usage count of this object
AddRef();
return S_OK;
}
if (riid == IID_IUnknown)
{
*ppvObj = (LPVOID)m_pExchExt; // return parent interface
m_pExchExt->AddRef();
return S_OK;
}
return E_NOINTERFACE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -