📄 sdkemsviewerruleclient.cpp
字号:
CBRH((pPicture->ValidateData()), hr);
//Convert data to string for message body
CBRH((pPicture->ToString(&pszTemp)), hr);
//Done with our picture object
SAFE_DELETE(pPicture);
//inc the base offset
if(emshi.pszUserData)
{
//Text + the picture
uBaseOffset += (_tcslen(emshi.pszUserData));
}
else
{
uBaseOffset++; //just the picture
}
uCount += chIEIDL; //point to next IEI
uObjCount++; //Increase object count
break;
}
/*
NYI...to implement, simply fill in each of the defined
classes and place code here to handle their instantiation
and use. Or define your own objects, etc.
*/
case IEI_TEXT_FORMATTING:
case IEI_PREDEFINED_SOUND:
case IEI_USERDEFINED_SOUND:
case IEI_PREDEFINED_ANIM:
case IEI_LARGE_ANIM:
case IEI_SMALL_ANIM:
case IEI_USER_PROMPT:
{
//For now, skip the object, don't update uBaseOffset or
//uObjCount, it's like it doesn't exist
uCount += chIEIDL;
if(emshi.pszUserData) //Still want the text portion
{
//[ID = IEI_TEXT_ONLY][Text Len][Text]
UINT uConv = 0;
UINT uPos = 0;
UINT uStrLen = 0;
TCHAR szConv[3] = _T("");
ASSERT(emshi.pszUserData);
uStrLen = _tcslen(emshi.pszUserData);
pszTemp = (TCHAR*)malloc(sizeof(TCHAR) * (uStrLen + 5));
ASSERT(pszTemp);
ZeroMemory(pszTemp, sizeof(TCHAR) * (_tcslen(emshi.pszUserData) + 5));
_tcscat(pszTemp, _T("FF")); //IEI_TEXT_ONLY
szConv[0] = _T('0');
uPos = (uStrLen < 0x10) ? 1 : 0;
_itot(uStrLen, &(szConv[uPos]), BASE_HEX);
_tcscat(pszTemp, szConv);
_tcscat(pszTemp, emshi.pszUserData);
uObjCount++; //Increase object count
uBaseOffset += uStrLen;
}
break;
}
default:
{
//shouldn't get any IEIs here that aren't handled
//or at least recognized
ASSERT(FALSE);
hr = E_FAIL;
goto Exit;
}
}
}
}
if(NULL == szBodyOut) //First time saving to buffer
{
//+1 for NULL +4 for Object Length
UINT uLen = _tcslen(pszTemp) + 5;
szBodyOut = (TCHAR*)malloc(sizeof(TCHAR) * (uLen));
CBRH((NULL != szBodyOut), hr);
ZeroMemory(szBodyOut, sizeof(TCHAR) * (uLen));
}
else
{
//Get size of current string, and the new one
size_t sizeold = sizeof(TCHAR)*_tcslen(szBodyOut);
size_t size = sizeof(TCHAR)*(_tcslen(pszTemp) + 5) + sizeold;
//Save the old string
TCHAR* szTemp = (TCHAR*)malloc(sizeold);
memcpy(szTemp, szBodyOut, sizeold);
//Allocate additional room for new string
TCHAR* szNewOut = (TCHAR*)realloc(szBodyOut, size);
CBRH((NULL != szNewOut), hr);
szBodyOut = szNewOut; //Save new pointer
//Clear it
memset(szBodyOut, 0x00, size);
//Copy old string, delete temp one
memcpy(szBodyOut, szTemp, sizeold);
free(szTemp);
}
//Append object length
//force this to 4 TCHARS
uLenTemp = _tcslen(pszTemp);
szBuffer[0] = _T('0');
szBuffer[1] = _T('0');
szBuffer[2] = _T('0');
uChar = (uLenTemp < 0x1000) ? 1 : 0;
uChar = (uLenTemp < 0x100) ? 2 : uChar;
uChar = (uLenTemp < 0x10) ? 3 : uChar;
_itot(uLenTemp, &(szBuffer[uChar]), BASE_HEX);
_tcscat(szBodyOut, szBuffer);
//Append object data
_tcscat(szBodyOut, pszTemp);
free(pszTemp);
pszTemp = NULL;
//Check if last SM in multipart, or just done
if((emshi.uCurrPart == emshi.uNumParts) || (!emshi.fMultiPart))
{
//allocate room for string buffer
*ppszOut = (TCHAR*)malloc(_msize(szBodyOut));
CBRH((NULL != *ppszOut), hr);
//Copy string buffer
memcpy(*ppszOut, szBodyOut, _msize(szBodyOut));
//free internal copy
free(szBodyOut);
//Write out number of objects processed
*pNumObjects = uObjCount;
//Set this so we will cleanup on exit
emshi.fMultiPart = FALSE;
}
Exit:
if(FAILED(hr) || (!emshi.fMultiPart))
{
if(pszTemp)
{
free(pszTemp);
pszTemp = NULL;
}
if(szBodyOut)
{
free(szBodyOut);
szBodyOut = NULL;
}
//reset counters
uObjCount = 0;
uBaseOffset = 0;
}
return hr;
}
/******************************************************************************
WriteEMSToBody - Write out EMS info to body of message
Params:
szEMSData[in] - String to write to body
szMessageClass[in] - Message class to set (optional)
pMsg[in] - Message we're writing to
uObjCount[in] - number of objects in data string
Returns:
Remarks:
******************************************************************************/
HRESULT WriteEMSToBody(LPCTSTR szEMSData,
LPCTSTR szMessageClass,
IMessage* pMsg,
UINT uObjCount)
{
HRESULT hr = S_OK;
int cbBody = 0;
int iCount = 0;
SPropValue rgProps[2]; //PR_MESSAGE_CLASS and PR_SUBJECT
LPSTREAM pStmBody = NULL;
DWORD cbWritten = 0;
TCHAR szBuffer[3] = _T("");
BYTE uChar = 0x00;
TCHAR* pszBody = NULL;
//Validate params, szMessageClass can be NULL, then we just don't alter it
ASSERT(NULL != szEMSData);
ASSERT(NULL != pMsg);
ASSERT(uObjCount);
if((NULL == pMsg) || (NULL == szEMSData) || (0 >= uObjCount))
{
hr = E_INVALIDARG;
goto Exit;
}
//Set message class if we have one
if(NULL != szMessageClass)
{
rgProps[iCount].ulPropTag = PR_MESSAGE_CLASS;
rgProps[iCount].Value.lpszW = const_cast<LPTSTR>(szMessageClass);
iCount++;
}
rgProps[iCount].ulPropTag = PR_SUBJECT;
rgProps[iCount].Value.lpszW = _T("SDK EMS SAMPLE");
iCount++;
//Open the body property
if(FAILED(hr = pMsg->OpenProperty(PR_BODY, NULL, 0,
MAPI_MODIFY | MAPI_CREATE, (LPUNKNOWN*)&pStmBody)))
{
goto Exit;
}
//Calculate length of body
cbBody = sizeof(TCHAR)*(_tcslen(szEMSData) + _tcslen(STR_EMSID) + 3);
pszBody = (TCHAR*)malloc(cbBody);
CBRH((NULL != pszBody), hr);
ZeroMemory(pszBody, cbBody);
//Append the GUID
_tcscat(pszBody, STR_EMSID);
//Append number of objects
szBuffer[0] = _T('0');
uChar = (uObjCount < 0x10) ? 1 : 0;
_itot(uObjCount, &(szBuffer[uChar]), BASE_HEX);
_tcscat(pszBody, szBuffer);
//Append rest of data
_tcscat(pszBody, szEMSData);
//Write string to body property
if(FAILED(hr = pStmBody->Write(pszBody, cbBody, &cbWritten)) ||
(cbWritten != (DWORD)cbBody))
{
if(hr == S_OK)
{
hr = E_FAIL;
}
goto Exit;
}
//Commit the change and finish
if(FAILED(hr = pStmBody->Commit(0)))
{
goto Exit;
}
//Set whatever props
if(FAILED(hr = pMsg->SetProps(iCount, rgProps, NULL)))
{
goto Exit;
}
Exit:
if(pszBody)
{
free(pszBody);
}
if(pStmBody)
{
pStmBody->Release();
}
return hr;
}
/******************************************************************************
CFactory::CFactory - C'TOR, called by the static method GetClassObject once
it determines the type of object the factory will create
******************************************************************************/
CFactory::CFactory(const CFactoryData* pFData) :
m_cRef(1)
{
//I'm the only one calling this so pFData shouldn't be NULL
ASSERT(pFData);
//Init the factory data info
memcpy(&m_FactoryData, pFData, sizeof(CFactoryData));
}
/******************************************************************************
CFactory::~CFactory - D'TOR, add whatever you might need here....
******************************************************************************/
CFactory::~CFactory()
{
RETAILMSG(TRUE, (_T("CFactory - destroying self.")));
}
/******************************************************************************
CFactory::QueryInterface - IUnknown implementation
Interfaces implemented:
IID_IUnknown
IID_IClassFactory
******************************************************************************/
STDMETHODIMP CFactory::QueryInterface(const IID& iid, LPVOID *ppv)
{
HRESULT hr = E_NOINTERFACE;
//Validate params
if(!ppv)
{
hr = E_INVALIDARG;
goto Exit;
}
//Check if requested interface is supported
if((IID_IUnknown == iid) || (IID_IClassFactory == iid))
{
//Yes it is
*ppv = reinterpret_cast<LPVOID>(this);
}
else
{
//No it isn't
*ppv = NULL;
}
if(*ppv)
{
//Interface was obtained so ref count
(reinterpret_cast<IUnknown*>(*ppv))->AddRef();
hr = S_OK;
}
Exit:
return hr;
}
/******************************************************************************
CFactory::AddRef - IUnknown implementation, pretty standard
******************************************************************************/
ULONG CFactory::AddRef()
{
RETAILMSG(TRUE, (_T("CFactory::AddRef->m_cRef is now %d\r\n"), m_cRef+1));
return InterlockedIncrement(&m_cRef);
}
/******************************************************************************
CFactory::Release - IUnknown implementation, pretty standard
******************************************************************************/
ULONG CFactory::Release()
{
InterlockedDecrement(&m_cRef);
RETAILMSG(TRUE, (_T("CFactory::Release->m_cRef is now %d\r\n"), m_cRef));
int nLocal = m_cRef; //make a copy in case we're destroyed
if(!m_cRef)
{
//Ref count is now 0, destroy ourselves
RETAILMSG(TRUE, (_T("CFactory::Release -> CFactory Deleted!\r\n")));
delete this;
}
return nLocal;
}
/******************************************************************************
CFactory::GetClassObject - called by DllGetClassObject, this enables us to
host muliple components using the same class factory (yippe!!)
Params:
clsid[in] - CLSID of object we're looking to create
iid[in] - id of interface we want in said object
ppv[out] - gets the class factory ready to create correct object
******************************************************************************/
HRESULT CFactory::GetClassObject(const CLSID& clsid, const IID& iid, void** ppv)
{
HRESULT hr = S_OK;
int iIndex = 0;
//Interface must be one of these
if((IID_IUnknown != iid) && (IID_IClassFactory != iid))
{
hr = E_NOINTERFACE;
goto Exit;
}
//Check listed components this dll can load and match against CLSID
for(iIndex = 0; iIndex < g_iFactoryDataEntries; iIndex++)
{
//Get data for each listed component
const CFactoryData* pFData = &g_rgFactoryData[iIndex];
//Check if requested CLSID is a match
if(pFData->IsClassID(clsid))
{
//Bingo, create a class factory for this component
*ppv = reinterpret_cast<IUnknown*>(new CFactory(pFData));
if(NULL == *ppv)
{
hr = E_OUTOFMEMORY;
}
goto Exit; //We're done either way
}
}
hr = CLASS_E_CLASSNOTAVAILABLE;
Exit:
return hr;
}
/******************************************************************************
CFactory::CreateInstance - Creates an instance of a component hosted in the
DLL. At this point we have all the info we need to create the correct one.
Params:
pUnknownOuter[in] - COM aggregation stuff, not allowed here
iid[in] - id if interface we want
ppv[out] - pointer to requested interface
******************************************************************************/
STDMETHODIMP CFactory::CreateInstance(IUnknown* pUnknownOuter,
const IID& iid, void** ppv)
{
HRESULT hr = S_OK;
IUnknown* pNewComponent = NULL;
//No aggregation
if(pUnknownOuter)
{
hr = CLASS_E_NOAGGREGATION;
goto Exit;
}
//Create the component
//m_FactoryData is initialized in the constructor, by the time CFactory is
//created it knows how to create each type of object
if(FAILED(hr = m_FactoryData.CreateInstance(pUnknownOuter, &pNewComponent)))
{
RETAILMSG(TRUE, (_T("CFactory::CreateInstance - m_FactoryData.CreateInstance failed")));
goto Exit;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -