📄 sdkemsviewerruleclient.cpp
字号:
//Get the requested interface
if(FAILED(hr = pNewComponent->QueryInterface(iid, ppv)))
{
RETAILMSG(TRUE, (_T("CFactory::CreateInstance - QueryInterface failed")));
goto Exit;
}
pNewComponent->Release();
Exit:
return hr;
}
/******************************************************************************
CFactory::LockServer - COM stuff, used by client to make sure DLL isn't
unloaded while factory is in use. In our case the DLL will stay loaded as
long as tmail.exe is running, so it shouldn't be a real problem, but we
have to implement it anyway as part of the IClassFactory interface
Params:
bLock[in] - TRUE to add lock, FALSE to release lock
Returns:
S_OK - can't really fail.
******************************************************************************/
STDMETHODIMP CFactory::LockServer(BOOL bLock)
{
if(bLock)
{
g_cServerLocks++;
}
else
{
g_cServerLocks--;
}
return S_OK;
}
/******************************************************************************
CRuleClientBase::CRuleClientBase - C'TOR
******************************************************************************/
CRuleClientBase::CRuleClientBase():
m_cRef(1),
m_mrcAccess(MRC_ACCESS_NONE),
m_mrcHandled(MRC_NOT_HANDLED)
{
}
/******************************************************************************
CRuleClientBase::~CRuleClientBase - D'TOR
******************************************************************************/
CRuleClientBase::~CRuleClientBase()
{
RETAILMSG(TRUE, (_T("CRuleClientBase - Destroying self")));
}
/******************************************************************************
******************************************************************************/
HRESULT CRuleClientBase::QueryInterface(const IID& iid, void** ppobj)
{
HRESULT hr = E_NOINTERFACE;
if(!ppobj)
{
return E_INVALIDARG;
}
*ppobj = NULL;
if((IID_IUnknown == iid) || (IID_IMailRuleClient == iid))
{
*ppobj = reinterpret_cast<LPVOID>(this);
}
if (*ppobj)
{
(reinterpret_cast<IUnknown*>(*ppobj))->AddRef();
hr = S_OK;
}
return hr;
}
/******************************************************************************
******************************************************************************/
ULONG CRuleClientBase::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
/******************************************************************************
******************************************************************************/
ULONG CRuleClientBase::Release()
{
InterlockedDecrement(&m_cRef);
int nLocal = m_cRef;
if(!m_cRef)
{
delete this;
}
return nLocal;
}
/******************************************************************************
CRuleClientBase::Initialize - Derived classes need to override
******************************************************************************/
HRESULT CRuleClientBase::Initialize(IMsgStore *pMsgStore, MRCACCESS *pmaDesired)
{
UNREFERENCED_PARAMETER(pMsgStore);
UNREFERENCED_PARAMETER(pmaDesired);
return E_NOTIMPL;
}
/******************************************************************************
CRuleClientBase::ProcessMessage - Derived classes need to override
******************************************************************************/
HRESULT CRuleClientBase::ProcessMessage(IMsgStore *pMsgStore,
ULONG cbMsg,
LPENTRYID lpMsg,
ULONG cbDestFolder,
LPENTRYID lpDestFolder,
ULONG *pulEventType,
MRCHANDLED *pHandled)
{
UNREFERENCED_PARAMETER(pMsgStore);
UNREFERENCED_PARAMETER(cbMsg);
UNREFERENCED_PARAMETER(lpMsg);
UNREFERENCED_PARAMETER(cbDestFolder);
UNREFERENCED_PARAMETER(lpDestFolder);
UNREFERENCED_PARAMETER(pulEventType);
UNREFERENCED_PARAMETER(pHandled);
return E_NOTIMPL;
}
/******************************************************************************
CRuleClient_EMS::~CRuleClient_EMS - D'TOR
******************************************************************************/
CRuleClient_EMS::~CRuleClient_EMS()
{
RETAILMSG(TRUE, (_T("CRuleClient_EMS - Destroying self")));
}
/******************************************************************************
CRuleClient_EMS::CreateInstance - Each rule client in this DLL must
implement this function, it's called by CFactory to create each component
Params:
pUnknownOuter[in] - COM aggregation stuff, it will always be null or
CFactory won't even call this method, I pass it along
in case someday I want to support aggregation, and
thus would have to modify CFactory
ppNewComponent[out] - pointer to component created here
Returns:
S_OK on success, or E_OUTOFMEMORY if we can't instantiate the class
******************************************************************************/
HRESULT CRuleClient_EMS::CreateInstance(IUnknown* pUnknownOuter,
IUnknown** ppNewComponent)
{
HRESULT hr = S_OK;
UNREFERENCED_PARAMETER(pUnknownOuter);
//only CFactory is calling this, ptr* should be good
*ppNewComponent = new CRuleClient_EMS();
if(NULL == *ppNewComponent)
{
hr = E_OUTOFMEMORY;
}
return hr;
}
/******************************************************************************
CRuleClient_EMS::Initialize -
******************************************************************************/
HRESULT CRuleClient_EMS::Initialize(IMsgStore *pMsgStore,
MRCACCESS *pmaDesired)
{
UNREFERENCED_PARAMETER(pMsgStore);
RETAILMSG(TRUE, (_T("CRuleClient_EMS::Initialize")));
//Set the Access, Handled, and target string for the client
m_mrcAccess = MRC_ACCESS_WRITE;
*pmaDesired = m_mrcAccess;
return S_OK;
}
/******************************************************************************
******************************************************************************/
HRESULT CRuleClient_EMS::ProcessMessage(IMsgStore *pMsgStore,
ULONG cbMsg,
LPENTRYID lpMsg,
ULONG cbDestFolder,
LPENTRYID lpDestFolder,
ULONG *pulEventType,
MRCHANDLED *pHandled)
{
SizedSPropTagArray(2, spta) = { 2, PR_CE_EMS_HEADER_DATA, PR_SUBJECT };
HRESULT hr = S_OK;
IMessage* pMsg = NULL;
SPropValue* pspv = NULL;
ULONG cValues = 0;
MRCHANDLED mrcHandled = MRC_NOT_HANDLED;
UINT uIndex = 0;
static BOOL fProcessing = FALSE;
static EMSHEADERINFO emshi[MAX_EMS_HEADERS] = {0};
static UINT uHeaderCount = 0;
//Get the message from the entry ID
hr = pMsgStore->OpenEntry(cbMsg, lpMsg, NULL, 0, NULL, (LPUNKNOWN *) &pMsg);
if(FAILED(hr))
{
RETAILMSG(TRUE, (_T("CRuleClient_EMS - Unable to get the message!\r\n")));
goto Exit;
}
//Try to get the EMS header data
hr = pMsg->GetProps((SPropTagArray *) &spta, MAPI_UNICODE, &cValues, &pspv);
if(FAILED(hr))
{
//Failed, or it's not an EMS
RETAILMSG(TRUE, (_T("CRuleClient_EMS - Couldn't get the SM header!\r\n")));
goto Exit;
}
//Did we succeed in getting the data, or is there none to get?
//There might not be any user data, so it could be NULL
if((2 == cValues) && (NULL != pspv[0].Value.bin.lpb) && (0 != pspv[0].Value.bin.cb))
{
/*
Because the order of the incomming EMS headers can not be assured, we
have to grab each header (if multipart) then pass them in order to be
processed. If we only have one, this is easy. If we have several, we
must keep track of the headers collected, determine when we're done,
then pass the headers to the processing function. In addition, we'll
check the IDs of the parts to make sure they all match. We shouldn't
get parts of different sequences at the same time.
*/
//Insert header data into next slot
if(FAILED(ExtractEMSHeaderInfo(&(emshi[uHeaderCount]),
pspv[0].Value.bin.lpb,
pspv[0].Value.bin.cb,
pspv[1].Value.lpszW)))
{
//Massive failure, probably OOM...
hr = E_FAIL;
goto Exit;
}
fProcessing = TRUE; //got at least one...
uHeaderCount++;
if(uHeaderCount >= MAX_EMS_HEADERS)
{
//Too many headers...
hr = E_FAIL;
goto Exit;
}
/*Validate headers. This is needed in case we get a header
with a different ID. If this happens we just start over using
this header as the first in a new sequence*/
if(!ValidateHeaders(emshi, uHeaderCount))
{
//NYI...reset and store the last header as the first
//For now just fail
hr = E_FAIL;
goto Exit;
}
//Check if not done collecting parts
if((!(emshi[0].fMultiPart)) || !(emshi[0].uNumParts != (uHeaderCount)))
{
fProcessing = FALSE;
}
//Send the parts to be dealt with
if(!fProcessing)
{
TCHAR* psz = NULL;
UINT uObjCount = 0;
//Sort the headers so they get passed in order
if(1 < uHeaderCount)
{
SortHeaderInfo(emshi, uHeaderCount);
}
//Process each header
for(uIndex = 0; uIndex < uHeaderCount; uIndex++)
{
//Process each EMS
if(FAILED(ProcessEMS(emshi[uIndex], &psz, &uObjCount)))
{
//Massive error, maybe OOM...
hr = E_FAIL;
goto Exit;
}
}
//If we didn't fail above, this should be non-NULL
ASSERT(psz);
CBRH((NULL != psz), hr);
//The message class here, is used by the custom form
//later when the user opens the message for viewing
WriteEMSToBody(psz, _T("IPM.SMStext.SDKEMS"), pMsg, uObjCount);
free(psz);
}
else
{
//Still waiting for more, delete this one
DeleteMessage(pMsgStore, pMsg, cbMsg, lpMsg, cbDestFolder, lpDestFolder, pulEventType, pHandled);
}
//We get all EMS...not really the best 'real-world' solution
//but for this sample don't let any other rules have the message
mrcHandled = MRC_HANDLED_DONTCONTINUE;
}
Exit:
if(FAILED(hr) || (!fProcessing))
{
fProcessing = FALSE;
//Free header info slots we used
for(uIndex = 0; uIndex < uHeaderCount; uIndex++)
{
FREE_EMSHEADERINFO(emshi[uIndex]);
}
uHeaderCount = 0;
}
//cleanup
if(pspv)
{
MAPIFreeBuffer(pspv);
}
if(pMsg)
{
pMsg->Release();
}
*pHandled = mrcHandled;
return hr;
}
/******************************************************************************
LibMain - DLL entry point, does a whole lot o' nothing
******************************************************************************/
EXTERN_C BOOL WINAPI LibMain(HINSTANCE hinst, DWORD dwReason, LPVOID lpv)
{
UNREFERENCED_PARAMETER(lpv);
g_hInstance = hinst;
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
/******************************************************************************
DllGetClassObject - COM stuff, client will call this to get interface to
requested component. This method delegates that out to
CFactory::GetClassObject, which does a lookup of supported components and
creates the correct one.
******************************************************************************/
STDAPI DllGetClassObject(const CLSID& clsid, const IID& iid, LPVOID *ppv)
{
HRESULT hr = E_FAIL;
CFactory* pFactory = NULL;
if(FAILED(hr = CFactory::GetClassObject(clsid, iid, (void**)&pFactory)))
{
RETAILMSG(TRUE, (_T("DllGetClassObject - CFactory::GetClassObject failed")));
goto Exit;
}
// Get the requested interface
if(FAILED(hr = pFactory->QueryInterface(iid, ppv)))
{
RETAILMSG(TRUE, (_T("DllGetClassObject - QueryInterface failed")));
goto Exit;
}
pFactory->Release();
Exit:
return hr;
}
/******************************************************************************
DllCanUnloadNow - COM stuff, client calls this to see if the DLL can be
safely unloaded.
******************************************************************************/
STDAPI DllCanUnloadNow()
{
if(!g_cServerLocks)
{
//Save to unload...
return S_OK;
}
else
{
return S_FALSE;
}
}
/******************************************************************************
DllRegisterServer - COM stuff
******************************************************************************/
STDAPI DllRegisterServer()
{
return S_OK;
}
/******************************************************************************
DllUnregisterServer - COM stuff
******************************************************************************/
STDAPI DllUnregisterServer()
{
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -